cloudaxe-opencode/packages/opencode/src/tool/glob.ts

67 lines
1.9 KiB
TypeScript
Raw Normal View History

2025-05-31 18:41:00 +00:00
import { z } from "zod"
2025-06-04 17:12:13 +00:00
import path from "path"
2025-05-31 18:41:00 +00:00
import { Tool } from "./tool"
import { App } from "../app/app"
2025-06-04 17:12:13 +00:00
import DESCRIPTION from "./glob.txt"
import { Ripgrep } from "../file/ripgrep"
2025-05-21 14:30:39 +00:00
export const GlobTool = Tool.define("glob", {
2025-05-21 14:30:39 +00:00
description: DESCRIPTION,
parameters: z.object({
pattern: z.string().describe("The glob pattern to match files against"),
path: z
.string()
2025-06-17 15:27:07 +00:00
.optional()
2025-05-21 14:30:39 +00:00
.describe(
2025-06-04 17:12:13 +00:00
`The directory to search in. If not specified, the current working directory will be used. IMPORTANT: Omit this field to use the default directory. DO NOT enter "undefined" or "null" - simply omit it for the default behavior. Must be a valid directory path if provided.`,
2025-06-10 00:24:18 +00:00
),
2025-05-21 14:30:39 +00:00
}),
async execute(params) {
const app = App.info()
2025-06-04 17:12:13 +00:00
let search = params.path ?? app.path.cwd
search = path.isAbsolute(search) ? search : path.resolve(app.path.cwd, search)
2025-06-04 17:12:13 +00:00
2025-05-31 18:41:00 +00:00
const limit = 100
const files = []
let truncated = false
2025-06-23 21:37:32 +00:00
for (const file of await Ripgrep.files({
cwd: search,
2025-07-08 22:14:24 +00:00
glob: [params.pattern],
2025-06-23 21:37:32 +00:00
})) {
2025-05-21 14:30:39 +00:00
if (files.length >= limit) {
2025-05-31 18:41:00 +00:00
truncated = true
break
2025-05-21 14:30:39 +00:00
}
2025-06-04 17:12:13 +00:00
const full = path.resolve(search, file)
const stats = await Bun.file(full)
2025-05-21 14:30:39 +00:00
.stat()
.then((x) => x.mtime.getTime())
2025-05-31 18:41:00 +00:00
.catch(() => 0)
2025-05-21 14:30:39 +00:00
files.push({
2025-06-04 17:12:13 +00:00
path: full,
2025-05-21 14:30:39 +00:00
mtime: stats,
2025-05-31 18:41:00 +00:00
})
2025-05-21 14:30:39 +00:00
}
2025-05-31 18:41:00 +00:00
files.sort((a, b) => b.mtime - a.mtime)
2025-05-21 14:30:39 +00:00
2025-05-31 18:41:00 +00:00
const output = []
if (files.length === 0) output.push("No files found")
2025-05-21 14:30:39 +00:00
if (files.length > 0) {
2025-05-31 18:41:00 +00:00
output.push(...files.map((f) => f.path))
2025-05-21 14:30:39 +00:00
if (truncated) {
2025-05-31 18:41:00 +00:00
output.push("")
output.push("(Results are truncated. Consider using a more specific path or pattern.)")
2025-05-21 14:30:39 +00:00
}
}
return {
title: path.relative(app.path.root, search),
2025-05-21 14:30:39 +00:00
metadata: {
count: files.length,
truncated,
},
output: output.join("\n"),
2025-05-31 18:41:00 +00:00
}
2025-05-21 14:30:39 +00:00
},
2025-05-31 18:41:00 +00:00
})