@prestyj/cli 5.11.0 → 5.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (366) hide show
  1. package/assets/skills/compliance-guard/SKILL.md +251 -0
  2. package/assets/skills/compliance-guard/references/artifacts.md +186 -0
  3. package/assets/skills/compliance-guard/references/eu-uk.md +151 -0
  4. package/assets/skills/compliance-guard/references/exposure-triage.md +161 -0
  5. package/assets/skills/compliance-guard/references/lawsuit-vectors.md +141 -0
  6. package/assets/skills/compliance-guard/references/provenance.md +42 -0
  7. package/assets/skills/compliance-guard/references/sector-gates.md +173 -0
  8. package/assets/skills/compliance-guard/references/security-baseline.md +130 -0
  9. package/assets/skills/compliance-guard/references/trigger-map.md +163 -0
  10. package/assets/skills/compliance-guard/references/us.md +164 -0
  11. package/dist/app-sidecar-auth-broadcast.test.js +69 -3
  12. package/dist/app-sidecar-auth-broadcast.test.js.map +1 -1
  13. package/dist/app-sidecar-sessions.test.js +1 -1
  14. package/dist/app-sidecar.js +119 -45
  15. package/dist/app-sidecar.js.map +1 -1
  16. package/dist/chat-agents/jiwa.test.js +1 -1
  17. package/dist/cli/auth.d.ts.map +1 -1
  18. package/dist/cli/auth.js +33 -36
  19. package/dist/cli/auth.js.map +1 -1
  20. package/dist/cli.d.ts.map +1 -1
  21. package/dist/cli.js +12 -1
  22. package/dist/cli.js.map +1 -1
  23. package/dist/config.d.ts +16 -5
  24. package/dist/config.d.ts.map +1 -1
  25. package/dist/config.js +35 -76
  26. package/dist/config.js.map +1 -1
  27. package/dist/config.test.js +20 -12
  28. package/dist/config.test.js.map +1 -1
  29. package/dist/core/agent-session-checkpoint-flush.test.js +2 -2
  30. package/dist/core/agent-session-crash-durability.test.js +3 -3
  31. package/dist/core/agent-session-model-switch.test.js +1 -1
  32. package/dist/core/agent-session-process-gate.test.js +7 -1
  33. package/dist/core/agent-session-process-gate.test.js.map +1 -1
  34. package/dist/core/agent-session-review-coverage.test.js +1 -1
  35. package/dist/core/agent-session-tool-tiers.test.d.ts +2 -0
  36. package/dist/core/agent-session-tool-tiers.test.d.ts.map +1 -0
  37. package/dist/core/agent-session-tool-tiers.test.js +138 -0
  38. package/dist/core/agent-session-tool-tiers.test.js.map +1 -0
  39. package/dist/core/agent-session.d.ts +43 -3
  40. package/dist/core/agent-session.d.ts.map +1 -1
  41. package/dist/core/agent-session.js +142 -31
  42. package/dist/core/agent-session.js.map +1 -1
  43. package/dist/core/agents.d.ts +29 -1
  44. package/dist/core/agents.d.ts.map +1 -1
  45. package/dist/core/agents.js +47 -97
  46. package/dist/core/agents.js.map +1 -1
  47. package/dist/core/agents.test.js +87 -7
  48. package/dist/core/agents.test.js.map +1 -1
  49. package/dist/core/api-benchmark.d.ts +3 -3
  50. package/dist/core/api-benchmark.js +7 -7
  51. package/dist/core/auth-providers.d.ts +37 -1
  52. package/dist/core/auth-providers.d.ts.map +1 -1
  53. package/dist/core/auth-providers.js +83 -3
  54. package/dist/core/auth-providers.js.map +1 -1
  55. package/dist/core/auto-update.test.js +1 -1
  56. package/dist/core/autopilot-gate.d.ts +2 -2
  57. package/dist/core/autopilot-gate.js +1 -1
  58. package/dist/core/bash-spawn-benchmark.js +6 -6
  59. package/dist/core/bundled-agents.d.ts +3 -0
  60. package/dist/core/bundled-agents.d.ts.map +1 -0
  61. package/dist/core/bundled-agents.js +252 -0
  62. package/dist/core/bundled-agents.js.map +1 -0
  63. package/dist/core/cache-warm-benchmark.d.ts +2 -2
  64. package/dist/core/cache-warm-benchmark.js +5 -5
  65. package/dist/core/code-retrieval-chunkers.d.ts +27 -0
  66. package/dist/core/code-retrieval-chunkers.d.ts.map +1 -0
  67. package/dist/core/code-retrieval-chunkers.js +264 -0
  68. package/dist/core/code-retrieval-chunkers.js.map +1 -0
  69. package/dist/core/code-retrieval-chunkers.test.d.ts +2 -0
  70. package/dist/core/code-retrieval-chunkers.test.d.ts.map +1 -0
  71. package/dist/core/code-retrieval-chunkers.test.js +203 -0
  72. package/dist/core/code-retrieval-chunkers.test.js.map +1 -0
  73. package/dist/core/code-retrieval.d.ts +6 -0
  74. package/dist/core/code-retrieval.d.ts.map +1 -1
  75. package/dist/core/code-retrieval.js +38 -1
  76. package/dist/core/code-retrieval.js.map +1 -1
  77. package/dist/core/encode-cwd.test.js +1 -1
  78. package/dist/core/extensions/plugin-bundles.js +2 -2
  79. package/dist/core/extensions/plugin-bundles.js.map +1 -1
  80. package/dist/core/extensions/plugin-bundles.test.js +2 -2
  81. package/dist/core/extensions/plugin-bundles.test.js.map +1 -1
  82. package/dist/core/fast-apply-benchmark.d.ts +2 -2
  83. package/dist/core/fast-apply-benchmark.js +6 -6
  84. package/dist/core/foreign-session-import.test.js +1 -1
  85. package/dist/core/goal-lifecycle-smoke.test.js +2 -2
  86. package/dist/core/goal-store.js +1 -1
  87. package/dist/core/goal-store.test.js +2 -2
  88. package/dist/core/goal-verifier.test.js +2 -2
  89. package/dist/core/goal-worker-dev-server-lifecycle.test.js +1 -1
  90. package/dist/core/goal-worker.test.js +2 -2
  91. package/dist/core/hashline-edit-benchmark.d.ts +2 -2
  92. package/dist/core/hashline-edit-benchmark.js +7 -7
  93. package/dist/core/local-endpoint-store.test.js +1 -1
  94. package/dist/core/logger.d.ts +1 -1
  95. package/dist/core/logger.js +2 -2
  96. package/dist/core/logger.js.map +1 -1
  97. package/dist/core/lsp/client-navigation.test.d.ts +2 -0
  98. package/dist/core/lsp/client-navigation.test.d.ts.map +1 -0
  99. package/dist/core/lsp/client-navigation.test.js +135 -0
  100. package/dist/core/lsp/client-navigation.test.js.map +1 -0
  101. package/dist/core/lsp/client.d.ts +69 -0
  102. package/dist/core/lsp/client.d.ts.map +1 -1
  103. package/dist/core/lsp/client.js +151 -2
  104. package/dist/core/lsp/client.js.map +1 -1
  105. package/dist/core/lsp/integration.test.js +2 -2
  106. package/dist/core/lsp/manager-navigation.test.d.ts +2 -0
  107. package/dist/core/lsp/manager-navigation.test.d.ts.map +1 -0
  108. package/dist/core/lsp/manager-navigation.test.js +121 -0
  109. package/dist/core/lsp/manager-navigation.test.js.map +1 -0
  110. package/dist/core/lsp/manager.d.ts +35 -1
  111. package/dist/core/lsp/manager.d.ts.map +1 -1
  112. package/dist/core/lsp/manager.js +92 -0
  113. package/dist/core/lsp/manager.js.map +1 -1
  114. package/dist/core/lsp/servers.test.js +1 -1
  115. package/dist/core/lsp/windows.test.js +4 -4
  116. package/dist/core/mcp/catalog-cache.test.js +1 -1
  117. package/dist/core/mcp/client-session-recovery.test.js +1 -1
  118. package/dist/core/mcp/client.d.ts.map +1 -1
  119. package/dist/core/mcp/client.js +2 -10
  120. package/dist/core/mcp/client.js.map +1 -1
  121. package/dist/core/mcp/content.d.ts +19 -0
  122. package/dist/core/mcp/content.d.ts.map +1 -0
  123. package/dist/core/mcp/content.js +172 -0
  124. package/dist/core/mcp/content.js.map +1 -0
  125. package/dist/core/mcp/content.test.d.ts +2 -0
  126. package/dist/core/mcp/content.test.d.ts.map +1 -0
  127. package/dist/core/mcp/content.test.js +135 -0
  128. package/dist/core/mcp/content.test.js.map +1 -0
  129. package/dist/core/mcp/deferred-catalog.d.ts +1 -1
  130. package/dist/core/mcp/deferred-catalog.js +1 -1
  131. package/dist/core/mcp/elicitation.test.js +1 -1
  132. package/dist/core/mcp/legacy-negotiation.test.js +2 -2
  133. package/dist/core/mcp/oauth-store.test.js +2 -2
  134. package/dist/core/mcp/resolve-stdio.test.js +5 -5
  135. package/dist/core/mcp/shared-pool.test.js +5 -5
  136. package/dist/core/mcp/store.test.js +5 -5
  137. package/dist/core/mcp/when-connected.test.js +2 -2
  138. package/dist/core/nolan-model.test.js +1 -1
  139. package/dist/core/nolan-prompt.js +5 -5
  140. package/dist/core/oauth/xai.d.ts +2 -0
  141. package/dist/core/oauth/xai.d.ts.map +1 -0
  142. package/dist/core/oauth/xai.js +4 -0
  143. package/dist/core/oauth/xai.js.map +1 -0
  144. package/dist/core/persistent-shell.js +1 -1
  145. package/dist/core/persistent-shell.test.js +6 -6
  146. package/dist/core/process-manager-dev-server-repro.test.js +51 -12
  147. package/dist/core/process-manager-dev-server-repro.test.js.map +1 -1
  148. package/dist/core/process-manager-notifications.test.js +24 -14
  149. package/dist/core/process-manager-notifications.test.js.map +1 -1
  150. package/dist/core/process-manager.d.ts +22 -0
  151. package/dist/core/process-manager.d.ts.map +1 -1
  152. package/dist/core/process-manager.js +58 -2
  153. package/dist/core/process-manager.js.map +1 -1
  154. package/dist/core/progress/git-xp.test.js +2 -2
  155. package/dist/core/progress/ranks.d.ts +14 -3
  156. package/dist/core/progress/ranks.d.ts.map +1 -1
  157. package/dist/core/progress/ranks.js +181 -12
  158. package/dist/core/progress/ranks.js.map +1 -1
  159. package/dist/core/progress/ranks.test.js +48 -7
  160. package/dist/core/progress/ranks.test.js.map +1 -1
  161. package/dist/core/progress/rebuild.test.js +1 -1
  162. package/dist/core/progress/store.test.js +1 -1
  163. package/dist/core/progress/types.d.ts +2 -1
  164. package/dist/core/progress/types.d.ts.map +1 -1
  165. package/dist/core/project-discovery.d.ts.map +1 -1
  166. package/dist/core/project-discovery.js +62 -48
  167. package/dist/core/project-discovery.js.map +1 -1
  168. package/dist/core/project-discovery.test.js +10 -10
  169. package/dist/core/prompt-commands.js +3 -3
  170. package/dist/core/radio.d.ts +1 -1
  171. package/dist/core/radio.d.ts.map +1 -1
  172. package/dist/core/radio.js +90 -6
  173. package/dist/core/radio.js.map +1 -1
  174. package/dist/core/radio.test.js +15 -2
  175. package/dist/core/radio.test.js.map +1 -1
  176. package/dist/core/run-journal.test.js +2 -2
  177. package/dist/core/sandbox.test.js +6 -6
  178. package/dist/core/semantic-search-benchmark.d.ts +2 -2
  179. package/dist/core/semantic-search-benchmark.js +5 -5
  180. package/dist/core/session-compaction.test.js +1 -1
  181. package/dist/core/session-manager.d.ts.map +1 -1
  182. package/dist/core/session-manager.js +83 -67
  183. package/dist/core/session-manager.js.map +1 -1
  184. package/dist/core/session-manager.test.js +7 -7
  185. package/dist/core/session-storage-fd-leak.test.d.ts +2 -0
  186. package/dist/core/session-storage-fd-leak.test.d.ts.map +1 -0
  187. package/dist/core/session-storage-fd-leak.test.js +116 -0
  188. package/dist/core/session-storage-fd-leak.test.js.map +1 -0
  189. package/dist/core/session-storage.d.ts +22 -2
  190. package/dist/core/session-storage.d.ts.map +1 -1
  191. package/dist/core/session-storage.js +33 -6
  192. package/dist/core/session-storage.js.map +1 -1
  193. package/dist/core/session-storage.test.js +2 -2
  194. package/dist/core/settings-manager.d.ts +2 -0
  195. package/dist/core/settings-manager.d.ts.map +1 -1
  196. package/dist/core/settings-manager.js +10 -1
  197. package/dist/core/settings-manager.js.map +1 -1
  198. package/dist/core/shell-path.js +1 -1
  199. package/dist/core/shell.d.ts +1 -1
  200. package/dist/core/shell.js +2 -2
  201. package/dist/core/shell.test.js +2 -2
  202. package/dist/core/shutdown.d.ts +71 -0
  203. package/dist/core/shutdown.d.ts.map +1 -0
  204. package/dist/core/shutdown.js +144 -0
  205. package/dist/core/shutdown.js.map +1 -0
  206. package/dist/core/shutdown.test.d.ts +2 -0
  207. package/dist/core/shutdown.test.d.ts.map +1 -0
  208. package/dist/core/shutdown.test.js +160 -0
  209. package/dist/core/shutdown.test.js.map +1 -0
  210. package/dist/core/sidecar-error-reporter.js +1 -1
  211. package/dist/core/sidecar-error-reporter.test.js +2 -2
  212. package/dist/core/skills-routing.test.js +96 -0
  213. package/dist/core/skills-routing.test.js.map +1 -1
  214. package/dist/core/skills.d.ts.map +1 -1
  215. package/dist/core/skills.js +3 -0
  216. package/dist/core/skills.js.map +1 -1
  217. package/dist/core/subagent-manager.d.ts +9 -0
  218. package/dist/core/subagent-manager.d.ts.map +1 -1
  219. package/dist/core/subagent-manager.js +45 -12
  220. package/dist/core/subagent-manager.js.map +1 -1
  221. package/dist/core/subagent-manager.test.js +14 -8
  222. package/dist/core/subagent-manager.test.js.map +1 -1
  223. package/dist/core/subagent-store.test.js +3 -3
  224. package/dist/core/task-store.js +1 -1
  225. package/dist/index.js +1 -1
  226. package/dist/index.js.map +1 -1
  227. package/dist/modes/acp-mode.js +2 -2
  228. package/dist/modes/acp-mode.test.js +4 -4
  229. package/dist/modes/agent-home-mode.d.ts.map +1 -1
  230. package/dist/modes/agent-home-mode.js +15 -11
  231. package/dist/modes/agent-home-mode.js.map +1 -1
  232. package/dist/modes/json-mode.d.ts +9 -1
  233. package/dist/modes/json-mode.d.ts.map +1 -1
  234. package/dist/modes/json-mode.js +3 -1
  235. package/dist/modes/json-mode.js.map +1 -1
  236. package/dist/modes/serve-mode.d.ts +1 -1
  237. package/dist/modes/serve-mode.d.ts.map +1 -1
  238. package/dist/modes/serve-mode.js +14 -9
  239. package/dist/modes/serve-mode.js.map +1 -1
  240. package/dist/modes/subagent-worker-mode.d.ts +5 -0
  241. package/dist/modes/subagent-worker-mode.d.ts.map +1 -1
  242. package/dist/modes/subagent-worker-mode.js.map +1 -1
  243. package/dist/session.test.js +1 -1
  244. package/dist/system-prompt.d.ts +37 -1
  245. package/dist/system-prompt.d.ts.map +1 -1
  246. package/dist/system-prompt.js +123 -11
  247. package/dist/system-prompt.js.map +1 -1
  248. package/dist/system-prompt.test.js +90 -11
  249. package/dist/system-prompt.test.js.map +1 -1
  250. package/dist/system-prompt.tiering.test.d.ts +2 -0
  251. package/dist/system-prompt.tiering.test.d.ts.map +1 -0
  252. package/dist/system-prompt.tiering.test.js +105 -0
  253. package/dist/system-prompt.tiering.test.js.map +1 -0
  254. package/dist/tools/code-nav.d.ts +30 -0
  255. package/dist/tools/code-nav.d.ts.map +1 -0
  256. package/dist/tools/code-nav.js +320 -0
  257. package/dist/tools/code-nav.js.map +1 -0
  258. package/dist/tools/code-nav.test.d.ts +2 -0
  259. package/dist/tools/code-nav.test.d.ts.map +1 -0
  260. package/dist/tools/code-nav.test.js +136 -0
  261. package/dist/tools/code-nav.test.js.map +1 -0
  262. package/dist/tools/edit.test.js +1 -1
  263. package/dist/tools/generate-image.d.ts +1 -1
  264. package/dist/tools/goals.d.ts +2 -2
  265. package/dist/tools/goals.test.js +2 -2
  266. package/dist/tools/grep-parity.test.d.ts +2 -0
  267. package/dist/tools/grep-parity.test.d.ts.map +1 -0
  268. package/dist/tools/grep-parity.test.js +92 -0
  269. package/dist/tools/grep-parity.test.js.map +1 -0
  270. package/dist/tools/grep-recall.test.d.ts +2 -0
  271. package/dist/tools/grep-recall.test.d.ts.map +1 -0
  272. package/dist/tools/grep-recall.test.js +114 -0
  273. package/dist/tools/grep-recall.test.js.map +1 -0
  274. package/dist/tools/grep-spawn.test.d.ts +2 -0
  275. package/dist/tools/grep-spawn.test.d.ts.map +1 -0
  276. package/dist/tools/grep-spawn.test.js +66 -0
  277. package/dist/tools/grep-spawn.test.js.map +1 -0
  278. package/dist/tools/grep.d.ts +13 -3
  279. package/dist/tools/grep.d.ts.map +1 -1
  280. package/dist/tools/grep.js +340 -40
  281. package/dist/tools/grep.js.map +1 -1
  282. package/dist/tools/grep.test.js +17 -14
  283. package/dist/tools/grep.test.js.map +1 -1
  284. package/dist/tools/index.d.ts +7 -0
  285. package/dist/tools/index.d.ts.map +1 -1
  286. package/dist/tools/index.js +8 -1
  287. package/dist/tools/index.js.map +1 -1
  288. package/dist/tools/plan-mode.test.js +1 -1
  289. package/dist/tools/prompt-hints.d.ts +9 -0
  290. package/dist/tools/prompt-hints.d.ts.map +1 -1
  291. package/dist/tools/prompt-hints.js +61 -8
  292. package/dist/tools/prompt-hints.js.map +1 -1
  293. package/dist/tools/safe-env.js +1 -1
  294. package/dist/tools/search-code.d.ts.map +1 -1
  295. package/dist/tools/search-code.js +7 -6
  296. package/dist/tools/search-code.js.map +1 -1
  297. package/dist/tools/search-code.test.js +8 -2
  298. package/dist/tools/search-code.test.js.map +1 -1
  299. package/dist/tools/skill.js +2 -1
  300. package/dist/tools/skill.js.map +1 -1
  301. package/dist/tools/subagent-control.d.ts.map +1 -1
  302. package/dist/tools/subagent-control.js +20 -5
  303. package/dist/tools/subagent-control.js.map +1 -1
  304. package/dist/tools/subagent-control.test.js +34 -1
  305. package/dist/tools/subagent-control.test.js.map +1 -1
  306. package/dist/tools/subagent-shared.d.ts +20 -1
  307. package/dist/tools/subagent-shared.d.ts.map +1 -1
  308. package/dist/tools/subagent-shared.js +34 -7
  309. package/dist/tools/subagent-shared.js.map +1 -1
  310. package/dist/tools/subagent-shared.test.js +43 -9
  311. package/dist/tools/subagent-shared.test.js.map +1 -1
  312. package/dist/tools/subagent.d.ts.map +1 -1
  313. package/dist/tools/subagent.js +11 -8
  314. package/dist/tools/subagent.js.map +1 -1
  315. package/dist/tools/subagent.test.js +3 -0
  316. package/dist/tools/subagent.test.js.map +1 -1
  317. package/dist/tools/task-send.test.js +19 -10
  318. package/dist/tools/task-send.test.js.map +1 -1
  319. package/dist/tools/tool-search.d.ts.map +1 -1
  320. package/dist/tools/tool-search.js +2 -1
  321. package/dist/tools/tool-search.js.map +1 -1
  322. package/dist/tools/tool-tiers.d.ts +42 -0
  323. package/dist/tools/tool-tiers.d.ts.map +1 -0
  324. package/dist/tools/tool-tiers.js +78 -0
  325. package/dist/tools/tool-tiers.js.map +1 -0
  326. package/dist/tools/tool-tiers.test.d.ts +2 -0
  327. package/dist/tools/tool-tiers.test.d.ts.map +1 -0
  328. package/dist/tools/tool-tiers.test.js +48 -0
  329. package/dist/tools/tool-tiers.test.js.map +1 -0
  330. package/dist/tools/write.test.js +1 -1
  331. package/dist/ui/App.js.map +1 -1
  332. package/dist/ui/components/Banner.d.ts.map +1 -1
  333. package/dist/ui/components/Banner.js +24 -16
  334. package/dist/ui/components/Banner.js.map +1 -1
  335. package/dist/ui/components/ToolExecution.js +42 -34
  336. package/dist/ui/components/ToolExecution.js.map +1 -1
  337. package/dist/ui/components/force-color.d.ts +2 -0
  338. package/dist/ui/components/force-color.d.ts.map +1 -0
  339. package/dist/ui/components/force-color.js +11 -0
  340. package/dist/ui/components/force-color.js.map +1 -0
  341. package/dist/ui/components/themed-output.test.d.ts +2 -0
  342. package/dist/ui/components/themed-output.test.d.ts.map +1 -0
  343. package/dist/ui/components/themed-output.test.js +111 -0
  344. package/dist/ui/components/themed-output.test.js.map +1 -0
  345. package/dist/ui/error-item.d.ts +1 -1
  346. package/dist/ui/error-item.js +3 -3
  347. package/dist/ui/error-item.js.map +1 -1
  348. package/dist/ui/hooks/useAgentLoop.d.ts +3 -0
  349. package/dist/ui/hooks/useAgentLoop.d.ts.map +1 -1
  350. package/dist/ui/hooks/useAgentLoop.js +27 -2
  351. package/dist/ui/hooks/useAgentLoop.js.map +1 -1
  352. package/dist/ui/login.js +1 -1
  353. package/dist/ui/login.js.map +1 -1
  354. package/dist/ui/render.d.ts +1 -1
  355. package/dist/ui/render.js +6 -6
  356. package/dist/ui/theme/dark-ansi.json +6 -0
  357. package/dist/ui/theme/dark-daltonized.json +6 -0
  358. package/dist/ui/theme/dark.json +6 -0
  359. package/dist/ui/theme/light-ansi.json +6 -0
  360. package/dist/ui/theme/light-daltonized.json +6 -0
  361. package/dist/ui/theme/light.json +6 -0
  362. package/dist/ui/theme/theme.d.ts +6 -0
  363. package/dist/ui/theme/theme.d.ts.map +1 -1
  364. package/dist/ui/tui-terminal-recorder.test.js +1 -1
  365. package/dist/utils/git.test.js +3 -3
  366. package/package.json +4 -4
@@ -0,0 +1,92 @@
1
+ import { beforeAll, describe, expect, it } from "vitest";
2
+ import fs from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { createGrepTool, detectExternalScanner } from "./grep.js";
6
+ function context() {
7
+ return { signal: new AbortController().signal, toolCallId: "test" };
8
+ }
9
+ /**
10
+ * One fixture covering the inputs where two regex engines and two file walkers
11
+ * are most likely to disagree: dot-directories, ignored paths, non-ASCII text,
12
+ * CRLF endings, a line past the truncation cap, and a binary blob.
13
+ */
14
+ async function makeFixture() {
15
+ const dir = await fs.mkdtemp(path.join(os.tmpdir(), "ez-grep-parity-"));
16
+ const files = {
17
+ ".gitignore": "ignored/\n*.min.js\n",
18
+ ".github/workflows/ci.yml": "name: ci\njobs:\n build:\n runs-on: ubuntu-latest\n",
19
+ "src/alpha.ts": "export const alpha = 1;\nconst TOKEN = 'alpha';\n// alpha again\n",
20
+ "src/beta.ts": "export function beta() {\n return 'ALPHA';\n}\n",
21
+ // A nested ignore file must NOT take effect: only the search root's
22
+ // .gitignore applies, on both scanner paths.
23
+ "src/nested/.gitignore": "deep/\n",
24
+ "src/nested/deep/gamma.ts": "// alpha in a deep file\nexport const gamma = 2;\n",
25
+ "src/unicode.ts": "const caf\u00e9 = '\u00e9l\u00e8ve \u2014 alpha';\nconst \u65e5\u672c = 'alpha \u6f22\u5b57';\n",
26
+ "src/crlf.ts": "const a = 1;\r\nconst alpha = 2;\r\nconst c = 3;\r\n",
27
+ "src/long.ts": `const long = "${"alpha ".repeat(120)}";\n`,
28
+ "ignored/hidden.ts": "export const alpha = 'should not be searched';\n",
29
+ "vendor/bundle.min.js": "var alpha=1;\n",
30
+ "docs/notes.md": "Alpha, beta and gamma.\n",
31
+ };
32
+ for (const [rel, content] of Object.entries(files)) {
33
+ const abs = path.join(dir, rel);
34
+ await fs.mkdir(path.dirname(abs), { recursive: true });
35
+ await fs.writeFile(abs, content);
36
+ }
37
+ await fs
38
+ .writeFile(path.join(dir, "assets", "blob.bin"), Buffer.from([0, 1, 2, 97, 108, 112, 104, 97, 0, 3]))
39
+ .catch(async () => {
40
+ await fs.mkdir(path.join(dir, "assets"), { recursive: true });
41
+ await fs.writeFile(path.join(dir, "assets", "blob.bin"), Buffer.from([0, 1, 2, 97, 108, 112, 104, 97, 0, 3]));
42
+ });
43
+ return dir;
44
+ }
45
+ const queries = [
46
+ { label: "literal", args: { pattern: "alpha", max_results: 200 } },
47
+ {
48
+ label: "case-insensitive",
49
+ args: { pattern: "alpha", case_insensitive: true, max_results: 200 },
50
+ },
51
+ { label: "inline (?i) flag", args: { pattern: "(?i)ALPHA", max_results: 200 } },
52
+ { label: "anchored", args: { pattern: "^export ", max_results: 200 } },
53
+ { label: "character class", args: { pattern: "const [a-z]+ =", max_results: 200 } },
54
+ { label: "include filter", args: { pattern: "alpha", include: "*.ts", max_results: 200 } },
55
+ { label: "unicode literal", args: { pattern: "\u6f22\u5b57", max_results: 200 } },
56
+ { label: "result cap", args: { pattern: "alpha", max_results: 3 } },
57
+ { label: "no matches", args: { pattern: "zzz-not-present-zzz", max_results: 200 } },
58
+ ];
59
+ let externalAvailable = false;
60
+ beforeAll(async () => {
61
+ externalAvailable = (await detectExternalScanner()) !== undefined;
62
+ });
63
+ describe("grep scanner parity", () => {
64
+ it.each(queries)("returns identical output for $label", async ({ args }) => {
65
+ if (!externalAvailable) {
66
+ // `rg` is optional. Skipping loudly beats a silently green run.
67
+ console.warn("skipping grep parity: the external scanner `rg` is not on PATH");
68
+ return;
69
+ }
70
+ const dir = await makeFixture();
71
+ const inProcess = await createGrepTool(dir, undefined, {
72
+ useExternalScanner: () => false,
73
+ }).execute(args, context());
74
+ const external = await createGrepTool(dir, undefined, {
75
+ useExternalScanner: () => true,
76
+ }).execute(args, context());
77
+ expect(String(external)).toBe(String(inProcess));
78
+ });
79
+ it("falls back in-process for lookahead, which the external engine cannot run", async () => {
80
+ const dir = await makeFixture();
81
+ const args = { pattern: "alpha(?= again)", max_results: 200 };
82
+ const forced = await createGrepTool(dir, undefined, {
83
+ useExternalScanner: () => true,
84
+ }).execute(args, context());
85
+ const reference = await createGrepTool(dir, undefined, {
86
+ useExternalScanner: () => false,
87
+ }).execute(args, context());
88
+ expect(String(forced)).toBe(String(reference));
89
+ expect(String(forced)).toContain("alpha again");
90
+ });
91
+ });
92
+ //# sourceMappingURL=grep-parity.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep-parity.test.js","sourceRoot":"","sources":["../../src/tools/grep-parity.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=grep-recall.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep-recall.test.d.ts","sourceRoot":"","sources":["../../src/tools/grep-recall.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,114 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import fs from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import readline from "node:readline";
6
+ import { createReadStream } from "node:fs";
7
+ import { createGrepTool } from "./grep.js";
8
+ function context() {
9
+ return { signal: new AbortController().signal, toolCallId: "test" };
10
+ }
11
+ async function makeFixture(files) {
12
+ const dir = await fs.mkdtemp(path.join(os.tmpdir(), "ez-grep-recall-"));
13
+ for (const [rel, content] of Object.entries(files)) {
14
+ const abs = path.join(dir, rel);
15
+ await fs.mkdir(path.dirname(abs), { recursive: true });
16
+ await fs.writeFile(abs, content);
17
+ }
18
+ return dir;
19
+ }
20
+ /** Both scanner paths, so recall is asserted for whichever one a host uses. */
21
+ const scanners = [
22
+ { label: "in-process", useExternalScanner: () => false },
23
+ { label: "external", useExternalScanner: () => true },
24
+ ];
25
+ describe.each(scanners)("grep recall ($label)", ({ useExternalScanner }) => {
26
+ const grep = (dir) => createGrepTool(dir, undefined, { useExternalScanner });
27
+ it("searches dot-directories", async () => {
28
+ const dir = await makeFixture({
29
+ ".github/workflows/ci.yml": "jobs:\n build:\n runs-on: ubuntu-latest\n",
30
+ "README.md": "no jobs here\n",
31
+ });
32
+ const result = await grep(dir).execute({ pattern: "runs-on" }, context());
33
+ expect(result).toContain(path.join(".github", "workflows", "ci.yml") + ":3:");
34
+ });
35
+ it("skips files matched by .gitignore", async () => {
36
+ const dir = await makeFixture({
37
+ ".gitignore": "dist/\n*.log\n",
38
+ "src/app.ts": "export const marker = 1;\n",
39
+ "dist/app.js": "export const marker = 1;\n",
40
+ "debug.log": "marker\n",
41
+ });
42
+ const result = await grep(dir).execute({ pattern: "marker" }, context());
43
+ expect(result).toContain(path.join("src", "app.ts") + ":1:");
44
+ expect(result).not.toContain("dist");
45
+ expect(result).not.toContain("debug.log");
46
+ });
47
+ it("still searches an ignored directory when it is the explicit path", async () => {
48
+ const dir = await makeFixture({
49
+ ".gitignore": "dist/\n",
50
+ "dist/app.js": "export const marker = 1;\n",
51
+ });
52
+ const result = await grep(dir).execute({ pattern: "marker", path: "dist" }, context());
53
+ expect(result).toContain("app.js:1:");
54
+ });
55
+ it("never scans node_modules or .git", async () => {
56
+ const dir = await makeFixture({
57
+ "node_modules/dep/index.js": "marker\n",
58
+ ".git/COMMIT_EDITMSG": "marker\n",
59
+ "src/keep.ts": "marker\n",
60
+ });
61
+ const result = await grep(dir).execute({ pattern: "marker" }, context());
62
+ expect(result).toContain(path.join("src", "keep.ts") + ":1:");
63
+ expect(result).not.toContain("node_modules");
64
+ expect(result).not.toContain(".git");
65
+ });
66
+ });
67
+ describe("grep scan ordering", () => {
68
+ it("matches a sequential scan over the same candidate list", async () => {
69
+ const files = {};
70
+ // Enough files to fill several scan waves, with matches spread across them.
71
+ for (let i = 0; i < 50; i++) {
72
+ files[`pkg${String(i).padStart(2, "0")}/mod.ts`] =
73
+ `line one\nconst marker${i} = ${i};\nmarker tail\n`;
74
+ }
75
+ const dir = await makeFixture(files);
76
+ const parallel = await createGrepTool(dir, undefined, {
77
+ useExternalScanner: () => false,
78
+ }).execute({ pattern: "marker", max_results: 500 }, context());
79
+ const expected = await sequentialScan(dir, /marker/g);
80
+ expect(String(parallel).split("\n\n")[0]).toBe(expected.join("\n"));
81
+ });
82
+ });
83
+ /**
84
+ * Reference implementation: one file at a time, candidates in sorted order.
85
+ *
86
+ * fast-glob always yields POSIX-separated paths, while the tool reports
87
+ * `path.relative` output — native separators, so backslashes on Windows.
88
+ * Normalizing here keeps this test about ORDER and CONTENT; asserting the raw
89
+ * glob strings instead silently made it a path-format test that only failed on
90
+ * Windows.
91
+ */
92
+ async function sequentialScan(dir, regex) {
93
+ const fg = await import("fast-glob");
94
+ const entries = (await fg.default("**/*", { cwd: dir, dot: true, onlyFiles: true, suppressErrors: true }))
95
+ .sort()
96
+ .map((entry) => path.normalize(entry));
97
+ const results = [];
98
+ for (const entry of entries) {
99
+ const rl = readline.createInterface({
100
+ input: createReadStream(path.join(dir, entry), "utf-8"),
101
+ crlfDelay: Infinity,
102
+ });
103
+ let lineNum = 0;
104
+ for await (const line of rl) {
105
+ lineNum++;
106
+ regex.lastIndex = 0;
107
+ if (regex.test(line))
108
+ results.push(`${entry}:${lineNum}:${line}`);
109
+ }
110
+ rl.close();
111
+ }
112
+ return results;
113
+ }
114
+ //# sourceMappingURL=grep-recall.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep-recall.test.js","sourceRoot":"","sources":["../../src/tools/grep-recall.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=grep-spawn.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep-spawn.test.d.ts","sourceRoot":"","sources":["../../src/tools/grep-spawn.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,66 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import fs from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ const spawnMock = vi.hoisted(() => vi.fn());
6
+ // Importing `spawn` from the mocked module would hand back the mock itself, so
7
+ // delegating to it recurses. Capture the genuine implementation inside the mock
8
+ // factory instead.
9
+ const actualSpawn = vi.hoisted(() => ({ fn: undefined }));
10
+ vi.mock("node:child_process", async () => {
11
+ const actual = await vi.importActual("node:child_process");
12
+ actualSpawn.fn = actual.spawn;
13
+ return { ...actual, spawn: spawnMock };
14
+ });
15
+ const { createGrepTool, detectExternalScanner, resetExternalScannerProbe } = await import("./grep.js");
16
+ function context() {
17
+ return { signal: new AbortController().signal, toolCallId: "test" };
18
+ }
19
+ let tmpDir;
20
+ beforeEach(async () => {
21
+ tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "ez-grep-spawn-"));
22
+ await fs.writeFile(path.join(tmpDir, "a.ts"), "const marker = 1;\n");
23
+ resetExternalScannerProbe();
24
+ spawnMock.mockReset();
25
+ // Delegate to the genuine spawn so the tool behaves normally; we only assert
26
+ // the options it was handed.
27
+ spawnMock.mockImplementation((...args) => actualSpawn.fn(...args));
28
+ });
29
+ afterEach(async () => {
30
+ resetExternalScannerProbe();
31
+ await fs.rm(tmpDir, { recursive: true, force: true });
32
+ });
33
+ describe("grep external scanner spawn options", () => {
34
+ it("hides the console window when probing for the scanner", async () => {
35
+ await detectExternalScanner();
36
+ expect(spawnMock).toHaveBeenCalledWith("rg", ["--version"], expect.objectContaining({ windowsHide: true }));
37
+ });
38
+ it("hides the console window when running a search", async () => {
39
+ const tool = createGrepTool(tmpDir, undefined, { useExternalScanner: () => true });
40
+ await tool.execute({ pattern: "marker" }, context());
41
+ const searchCall = spawnMock.mock.calls.find((call) => Array.isArray(call[1]) && !call[1].includes("--version"));
42
+ // `rg` is optional. When it is absent the in-process path legitimately
43
+ // never spawns — but assert that is the actual reason, so this test can
44
+ // never pass merely because the search silently failed to run.
45
+ if (!searchCall) {
46
+ expect(await detectExternalScanner()).toBeUndefined();
47
+ return;
48
+ }
49
+ expect(searchCall[2]).toEqual(expect.objectContaining({ windowsHide: true }));
50
+ expect(searchCall[2]).toEqual(expect.objectContaining({ cwd: tmpDir }));
51
+ });
52
+ it("never spawns a scan once the budget is already spent", async () => {
53
+ const tool = createGrepTool(tmpDir, undefined, {
54
+ useExternalScanner: () => true,
55
+ deadlineMs: 0,
56
+ });
57
+ const result = String(await tool.execute({ pattern: "marker" }, context()));
58
+ // The child's budget is floored at 1ms, so spawning here would race the
59
+ // scanner: whenever the child won, an expired budget still returned real
60
+ // matches — and only sometimes, which is how it slipped through as a flake.
61
+ expect(spawnMock).not.toHaveBeenCalled();
62
+ expect(result).toContain("No matches found.");
63
+ expect(result).not.toContain("a.ts:1:");
64
+ });
65
+ });
66
+ //# sourceMappingURL=grep-spawn.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep-spawn.test.js","sourceRoot":"","sources":["../../src/tools/grep-spawn.test.ts"],"names":[],"mappings":"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"}
@@ -8,8 +8,18 @@ declare const GrepParams: z.ZodObject<{
8
8
  max_results: z.ZodOptional<z.ZodNumber>;
9
9
  case_insensitive: z.ZodOptional<z.ZodBoolean>;
10
10
  }, z.core.$strip>;
11
- export declare function createGrepTool(cwd: string, ops?: ToolOperations,
12
- /** Wall-clock budget for one call. Overridable so tests can trip it without a 5s wait. */
13
- deadlineMs?: number): AgentTool<typeof GrepParams>;
11
+ export interface GrepToolOptions {
12
+ /** Wall-clock budget for one call. Overridable so tests can trip it without a 5s wait. */
13
+ deadlineMs?: number;
14
+ /**
15
+ * Whether the external `rg` scanner may be used when it is on PATH. Read
16
+ * lazily so a settings change takes effect without rebuilding the toolset.
17
+ */
18
+ useExternalScanner?: () => boolean;
19
+ }
20
+ export declare function createGrepTool(cwd: string, ops?: ToolOperations, options?: GrepToolOptions): AgentTool<typeof GrepParams>;
21
+ export declare function detectExternalScanner(): Promise<string | undefined>;
22
+ /** Test seam: forget the cached probe result. */
23
+ export declare function resetExternalScannerProbe(): void;
14
24
  export {};
15
25
  //# sourceMappingURL=grep.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"grep.d.ts","sourceRoot":"","sources":["../../src/tools/grep.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAIhD,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEvE,QAAA,MAAM,UAAU;;;;;;iBAWd,CAAC;AAiHH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,GAAG,GAAE,cAAgC;AACrC,0FAA0F;AAC1F,UAAU,GAAE,MAAyB,GACpC,SAAS,CAAC,OAAO,UAAU,CAAC,CA+F9B"}
1
+ {"version":3,"file":"grep.d.ts","sourceRoot":"","sources":["../../src/tools/grep.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAIhD,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEvE,QAAA,MAAM,UAAU;;;;;;iBAcd,CAAC;AA0HH,MAAM,WAAW,eAAe;IAC9B,0FAA0F;IAC1F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,OAAO,CAAC;CACpC;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,GAAG,GAAE,cAAgC,EACrC,OAAO,GAAE,eAAoB,GAC5B,SAAS,CAAC,OAAO,UAAU,CAAC,CA4F9B;AA6JD,wBAAgB,qBAAqB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAgBnE;AAED,iDAAiD;AACjD,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD"}