glob.ts 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. import z from "zod"
  2. import path from "path"
  3. import { Tool } from "./tool"
  4. import DESCRIPTION from "./glob.txt"
  5. import { Ripgrep } from "../file/ripgrep"
  6. import { Instance } from "../project/instance"
  7. export const GlobTool = Tool.define("glob", {
  8. description: DESCRIPTION,
  9. parameters: z.object({
  10. pattern: z.string().describe("The glob pattern to match files against"),
  11. path: z
  12. .string()
  13. .optional()
  14. .describe(
  15. `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.`,
  16. ),
  17. }),
  18. async execute(params) {
  19. let search = params.path ?? Instance.directory
  20. search = path.isAbsolute(search) ? search : path.resolve(Instance.directory, search)
  21. const limit = 100
  22. const files = []
  23. let truncated = false
  24. for await (const file of Ripgrep.files({
  25. cwd: search,
  26. glob: [params.pattern],
  27. })) {
  28. if (files.length >= limit) {
  29. truncated = true
  30. break
  31. }
  32. const full = path.resolve(search, file)
  33. const stats = await Bun.file(full)
  34. .stat()
  35. .then((x) => x.mtime.getTime())
  36. .catch(() => 0)
  37. files.push({
  38. path: full,
  39. mtime: stats,
  40. })
  41. }
  42. files.sort((a, b) => b.mtime - a.mtime)
  43. const output = []
  44. if (files.length === 0) output.push("No files found")
  45. if (files.length > 0) {
  46. output.push(...files.map((f) => f.path))
  47. if (truncated) {
  48. output.push("")
  49. output.push("(Results are truncated. Consider using a more specific path or pattern.)")
  50. }
  51. }
  52. return {
  53. title: path.relative(Instance.worktree, search),
  54. metadata: {
  55. count: files.length,
  56. truncated,
  57. },
  58. output: output.join("\n"),
  59. }
  60. },
  61. })