grep.test.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import { describe, expect } from "bun:test"
  2. import path from "path"
  3. import { Effect, Layer } from "effect"
  4. import { GrepTool } from "../../src/tool/grep"
  5. import { provideInstance, provideTmpdirInstance } from "../fixture/fixture"
  6. import { SessionID, MessageID } from "../../src/session/schema"
  7. import * as CrossSpawnSpawner from "../../src/effect/cross-spawn-spawner"
  8. import { Truncate } from "../../src/tool/truncate"
  9. import { Agent } from "../../src/agent/agent"
  10. import { Ripgrep } from "../../src/file/ripgrep"
  11. import { AppFileSystem } from "../../src/filesystem"
  12. import { testEffect } from "../lib/effect"
  13. const it = testEffect(
  14. Layer.mergeAll(
  15. CrossSpawnSpawner.defaultLayer,
  16. AppFileSystem.defaultLayer,
  17. Ripgrep.defaultLayer,
  18. Truncate.defaultLayer,
  19. Agent.defaultLayer,
  20. ),
  21. )
  22. const ctx = {
  23. sessionID: SessionID.make("ses_test"),
  24. messageID: MessageID.make(""),
  25. callID: "",
  26. agent: "code", // kilocode_change
  27. abort: AbortSignal.any([]),
  28. messages: [],
  29. metadata: () => Effect.void,
  30. ask: () => Effect.void,
  31. }
  32. const root = path.join(__dirname, "../..")
  33. describe("tool.grep", () => {
  34. it.live("basic search", () =>
  35. Effect.gen(function* () {
  36. const info = yield* GrepTool
  37. const grep = yield* info.init()
  38. const result = yield* provideInstance(root)(
  39. grep.execute(
  40. {
  41. pattern: "export",
  42. path: path.join(root, "src/tool"),
  43. include: "*.ts",
  44. },
  45. ctx,
  46. ),
  47. )
  48. expect(result.metadata.matches).toBeGreaterThan(0)
  49. expect(result.output).toContain("Found")
  50. }),
  51. )
  52. it.live("no matches returns correct output", () =>
  53. provideTmpdirInstance((dir) =>
  54. Effect.gen(function* () {
  55. yield* Effect.promise(() => Bun.write(path.join(dir, "test.txt"), "hello world"))
  56. const info = yield* GrepTool
  57. const grep = yield* info.init()
  58. const result = yield* grep.execute(
  59. {
  60. pattern: "xyznonexistentpatternxyz123",
  61. path: dir,
  62. },
  63. ctx,
  64. )
  65. expect(result.metadata.matches).toBe(0)
  66. expect(result.output).toBe("No files found")
  67. }),
  68. ),
  69. )
  70. it.live("finds matches in tmp instance", () =>
  71. provideTmpdirInstance((dir) =>
  72. Effect.gen(function* () {
  73. yield* Effect.promise(() => Bun.write(path.join(dir, "test.txt"), "line1\nline2\nline3"))
  74. const info = yield* GrepTool
  75. const grep = yield* info.init()
  76. const result = yield* grep.execute(
  77. {
  78. pattern: "line",
  79. path: dir,
  80. },
  81. ctx,
  82. )
  83. expect(result.metadata.matches).toBeGreaterThan(0)
  84. }),
  85. ),
  86. )
  87. it.live("supports exact file paths", () =>
  88. provideTmpdirInstance((dir) =>
  89. Effect.gen(function* () {
  90. const file = path.join(dir, "test.txt")
  91. yield* Effect.promise(() => Bun.write(file, "line1\nline2\nline3"))
  92. const info = yield* GrepTool
  93. const grep = yield* info.init()
  94. const result = yield* grep.execute(
  95. {
  96. pattern: "line2",
  97. path: file,
  98. },
  99. ctx,
  100. )
  101. expect(result.metadata.matches).toBe(1)
  102. expect(result.output).toContain(file)
  103. expect(result.output).toContain("Line 2: line2")
  104. }),
  105. ),
  106. )
  107. })