glob.ts 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. import { z } from "zod"
  2. import path from "path"
  3. import { Tool } from "./tool"
  4. import { App } from "../app/app"
  5. import DESCRIPTION from "./glob.txt"
  6. export const GlobTool = Tool.define({
  7. id: "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. const app = App.info()
  20. let search = params.path ?? app.path.cwd
  21. search = path.isAbsolute(search)
  22. ? search
  23. : path.resolve(app.path.cwd, search)
  24. const limit = 100
  25. const glob = new Bun.Glob(params.pattern)
  26. const files = []
  27. let truncated = false
  28. for await (const file of glob.scan({ cwd: search, dot: true })) {
  29. if (files.length >= limit) {
  30. truncated = true
  31. break
  32. }
  33. const full = path.resolve(search, file)
  34. const stats = await Bun.file(full)
  35. .stat()
  36. .then((x) => x.mtime.getTime())
  37. .catch(() => 0)
  38. files.push({
  39. path: full,
  40. mtime: stats,
  41. })
  42. }
  43. files.sort((a, b) => b.mtime - a.mtime)
  44. const output = []
  45. if (files.length === 0) output.push("No files found")
  46. if (files.length > 0) {
  47. output.push(...files.map((f) => f.path))
  48. if (truncated) {
  49. output.push("")
  50. output.push(
  51. "(Results are truncated. Consider using a more specific path or pattern.)",
  52. )
  53. }
  54. }
  55. return {
  56. metadata: {
  57. count: files.length,
  58. truncated,
  59. title: path.relative(app.path.root, search),
  60. },
  61. output: output.join("\n"),
  62. }
  63. },
  64. })