@greppleai/grip 0.1.5 → 0.1.6

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 (565) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +1 -1
  3. package/dist/bun/cli.d.ts.map +1 -1
  4. package/dist/bun/cli.js.map +1 -1
  5. package/dist/bun/embedded-assets.d.ts.map +1 -1
  6. package/dist/bun/embedded-assets.js.map +1 -1
  7. package/dist/bun/register-bedrock.d.ts.map +1 -1
  8. package/dist/bun/restore-sandbox-env.d.ts.map +1 -1
  9. package/dist/bun/restore-sandbox-env.js.map +1 -1
  10. package/dist/cli/args.d.ts.map +1 -1
  11. package/dist/cli/args.js.map +1 -1
  12. package/dist/cli/config-selector.d.ts.map +1 -1
  13. package/dist/cli/config-selector.js.map +1 -1
  14. package/dist/cli/file-processor.d.ts.map +1 -1
  15. package/dist/cli/file-processor.js.map +1 -1
  16. package/dist/cli/initial-message.d.ts +1 -1
  17. package/dist/cli/initial-message.d.ts.map +1 -1
  18. package/dist/cli/initial-message.js.map +1 -1
  19. package/dist/cli/list-models.d.ts.map +1 -1
  20. package/dist/cli/list-models.js.map +1 -1
  21. package/dist/cli/session-picker.d.ts.map +1 -1
  22. package/dist/cli/session-picker.js.map +1 -1
  23. package/dist/cli.d.ts.map +1 -1
  24. package/dist/cli.js.map +1 -1
  25. package/dist/config.d.ts.map +1 -1
  26. package/dist/config.js.map +1 -1
  27. package/dist/core/agent-session.d.ts +27 -0
  28. package/dist/core/agent-session.d.ts.map +1 -1
  29. package/dist/core/agent-session.js +117 -152
  30. package/dist/core/agent-session.js.map +1 -1
  31. package/dist/core/auth-guidance.d.ts.map +1 -1
  32. package/dist/core/auth-guidance.js.map +1 -1
  33. package/dist/core/auth-storage.d.ts +4 -0
  34. package/dist/core/auth-storage.d.ts.map +1 -1
  35. package/dist/core/auth-storage.js +3 -10
  36. package/dist/core/auth-storage.js.map +1 -1
  37. package/dist/core/bash-executor.d.ts.map +1 -1
  38. package/dist/core/bash-executor.js +19 -23
  39. package/dist/core/bash-executor.js.map +1 -1
  40. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  41. package/dist/core/compaction/branch-summarization.js.map +1 -1
  42. package/dist/core/compaction/compaction.d.ts.map +1 -1
  43. package/dist/core/compaction/compaction.js.map +1 -1
  44. package/dist/core/compaction/compression-detection-ledger.d.ts.map +1 -1
  45. package/dist/core/compaction/compression-detection-ledger.js.map +1 -1
  46. package/dist/core/compaction/compression-detector.d.ts +1 -0
  47. package/dist/core/compaction/compression-detector.d.ts.map +1 -1
  48. package/dist/core/compaction/compression-detector.js +10 -21
  49. package/dist/core/compaction/compression-detector.js.map +1 -1
  50. package/dist/core/compaction/compression-economics.d.ts.map +1 -1
  51. package/dist/core/compaction/compression-economics.js.map +1 -1
  52. package/dist/core/compaction/utils.d.ts.map +1 -1
  53. package/dist/core/compaction/utils.js.map +1 -1
  54. package/dist/core/defaults.d.ts.map +1 -1
  55. package/dist/core/diagnostics.d.ts.map +1 -1
  56. package/dist/core/event-bus.d.ts.map +1 -1
  57. package/dist/core/event-bus.js.map +1 -1
  58. package/dist/core/exec.d.ts.map +1 -1
  59. package/dist/core/exec.js.map +1 -1
  60. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
  61. package/dist/core/export-html/ansi-to-html.js.map +1 -1
  62. package/dist/core/export-html/index.d.ts.map +1 -1
  63. package/dist/core/export-html/index.js.map +1 -1
  64. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  65. package/dist/core/export-html/tool-renderer.js.map +1 -1
  66. package/dist/core/extensions/loader.d.ts.map +1 -1
  67. package/dist/core/extensions/loader.js.map +1 -1
  68. package/dist/core/extensions/runner.d.ts.map +1 -1
  69. package/dist/core/extensions/runner.js +18 -30
  70. package/dist/core/extensions/runner.js.map +1 -1
  71. package/dist/core/extensions/types.d.ts.map +1 -1
  72. package/dist/core/extensions/types.js.map +1 -1
  73. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  74. package/dist/core/extensions/wrapper.js.map +1 -1
  75. package/dist/core/footer-data-provider.d.ts.map +1 -1
  76. package/dist/core/footer-data-provider.js +15 -16
  77. package/dist/core/footer-data-provider.js.map +1 -1
  78. package/dist/core/grip-agent.d.ts.map +1 -1
  79. package/dist/core/grip-agent.js +7 -21
  80. package/dist/core/grip-agent.js.map +1 -1
  81. package/dist/core/grip-manifest.d.ts.map +1 -1
  82. package/dist/core/grip-manifest.js.map +1 -1
  83. package/dist/core/hooks/aggregate.d.ts.map +1 -1
  84. package/dist/core/hooks/aggregate.js.map +1 -1
  85. package/dist/core/hooks/config.d.ts.map +1 -1
  86. package/dist/core/hooks/config.js.map +1 -1
  87. package/dist/core/hooks/executor.d.ts.map +1 -1
  88. package/dist/core/hooks/executor.js.map +1 -1
  89. package/dist/core/hooks/index.d.ts.map +1 -1
  90. package/dist/core/hooks/index.js.map +1 -1
  91. package/dist/core/hooks/matcher.d.ts.map +1 -1
  92. package/dist/core/hooks/matcher.js.map +1 -1
  93. package/dist/core/hooks/trust-store.d.ts.map +1 -1
  94. package/dist/core/hooks/trust-store.js +0 -3
  95. package/dist/core/hooks/trust-store.js.map +1 -1
  96. package/dist/core/hooks/types.d.ts.map +1 -1
  97. package/dist/core/hooks/types.js.map +1 -1
  98. package/dist/core/http-dispatcher.d.ts.map +1 -1
  99. package/dist/core/http-dispatcher.js.map +1 -1
  100. package/dist/core/instruction-resource-loader.d.ts.map +1 -1
  101. package/dist/core/instruction-resource-loader.js +0 -3
  102. package/dist/core/instruction-resource-loader.js.map +1 -1
  103. package/dist/core/keybindings.d.ts.map +1 -1
  104. package/dist/core/keybindings.js +0 -1
  105. package/dist/core/keybindings.js.map +1 -1
  106. package/dist/core/lsp/abort.d.ts.map +1 -1
  107. package/dist/core/lsp/abort.js.map +1 -1
  108. package/dist/core/lsp/client.d.ts.map +1 -1
  109. package/dist/core/lsp/client.js +8 -22
  110. package/dist/core/lsp/client.js.map +1 -1
  111. package/dist/core/lsp/config-loader.d.ts.map +1 -1
  112. package/dist/core/lsp/config-loader.js.map +1 -1
  113. package/dist/core/lsp/config.d.ts.map +1 -1
  114. package/dist/core/lsp/config.js.map +1 -1
  115. package/dist/core/lsp/diagnostics.d.ts.map +1 -1
  116. package/dist/core/lsp/diagnostics.js.map +1 -1
  117. package/dist/core/lsp/file-sync.d.ts.map +1 -1
  118. package/dist/core/lsp/file-sync.js +7 -9
  119. package/dist/core/lsp/file-sync.js.map +1 -1
  120. package/dist/core/lsp/integration.d.ts.map +1 -1
  121. package/dist/core/lsp/integration.js.map +1 -1
  122. package/dist/core/lsp/language-map.d.ts.map +1 -1
  123. package/dist/core/lsp/language-map.js +2 -7
  124. package/dist/core/lsp/language-map.js.map +1 -1
  125. package/dist/core/lsp/manager.d.ts.map +1 -1
  126. package/dist/core/lsp/manager.js +18 -29
  127. package/dist/core/lsp/manager.js.map +1 -1
  128. package/dist/core/lsp/navigation.d.ts.map +1 -1
  129. package/dist/core/lsp/navigation.js.map +1 -1
  130. package/dist/core/lsp/portable-path.d.ts.map +1 -1
  131. package/dist/core/lsp/portable-path.js.map +1 -1
  132. package/dist/core/lsp/refactor.d.ts.map +1 -1
  133. package/dist/core/lsp/refactor.js.map +1 -1
  134. package/dist/core/lsp/transport.d.ts.map +1 -1
  135. package/dist/core/lsp/transport.js.map +1 -1
  136. package/dist/core/messages.d.ts.map +1 -1
  137. package/dist/core/messages.js.map +1 -1
  138. package/dist/core/model-registry.d.ts.map +1 -1
  139. package/dist/core/model-registry.js +5 -7
  140. package/dist/core/model-registry.js.map +1 -1
  141. package/dist/core/model-resolver.d.ts.map +1 -1
  142. package/dist/core/model-resolver.js.map +1 -1
  143. package/dist/core/output-guard.d.ts.map +1 -1
  144. package/dist/core/output-guard.js.map +1 -1
  145. package/dist/core/package-manager.d.ts.map +1 -1
  146. package/dist/core/package-manager.js +0 -6
  147. package/dist/core/package-manager.js.map +1 -1
  148. package/dist/core/prompt-templates.d.ts.map +1 -1
  149. package/dist/core/prompt-templates.js.map +1 -1
  150. package/dist/core/provider-display-names.d.ts.map +1 -1
  151. package/dist/core/remote-workspace-protocol/contract.d.ts.map +1 -1
  152. package/dist/core/remote-workspace-protocol/contract.js +4 -2
  153. package/dist/core/remote-workspace-protocol/contract.js.map +1 -1
  154. package/dist/core/remote-workspace-protocol/guest-shared-client.d.ts.map +1 -1
  155. package/dist/core/remote-workspace-protocol/guest-shared-client.js +1 -5
  156. package/dist/core/remote-workspace-protocol/guest-shared-client.js.map +1 -1
  157. package/dist/core/remote-workspace-protocol/guest-shared-outbound-scheduler.d.ts.map +1 -1
  158. package/dist/core/remote-workspace-protocol/guest-shared-outbound-scheduler.js +5 -10
  159. package/dist/core/remote-workspace-protocol/guest-shared-outbound-scheduler.js.map +1 -1
  160. package/dist/core/remote-workspace-protocol/guest-shared-uplink.d.ts.map +1 -1
  161. package/dist/core/remote-workspace-protocol/guest-shared-uplink.js +2 -9
  162. package/dist/core/remote-workspace-protocol/guest-shared-uplink.js.map +1 -1
  163. package/dist/core/remote-workspace-protocol/lima-owner-directory.d.ts.map +1 -1
  164. package/dist/core/remote-workspace-protocol/lima-owner-directory.js.map +1 -1
  165. package/dist/core/remote-workspace-protocol/lima-owner-lock.d.ts.map +1 -1
  166. package/dist/core/remote-workspace-protocol/lima-owner-lock.js.map +1 -1
  167. package/dist/core/remote-workspace-protocol/session.d.ts.map +1 -1
  168. package/dist/core/remote-workspace-protocol/session.js +27 -65
  169. package/dist/core/remote-workspace-protocol/session.js.map +1 -1
  170. package/dist/core/remote-workspace-protocol/shared-transport.d.ts.map +1 -1
  171. package/dist/core/remote-workspace-protocol/shared-transport.js.map +1 -1
  172. package/dist/core/resolve-config-value.d.ts.map +1 -1
  173. package/dist/core/resolve-config-value.js.map +1 -1
  174. package/dist/core/resource-loader.d.ts.map +1 -1
  175. package/dist/core/resource-loader.js +0 -48
  176. package/dist/core/resource-loader.js.map +1 -1
  177. package/dist/core/rules.d.ts.map +1 -1
  178. package/dist/core/rules.js.map +1 -1
  179. package/dist/core/sandbox/command.d.ts.map +1 -1
  180. package/dist/core/sandbox/command.js.map +1 -1
  181. package/dist/core/sandbox/config.d.ts.map +1 -1
  182. package/dist/core/sandbox/config.js.map +1 -1
  183. package/dist/core/sandbox/lima-guest-binary.d.ts.map +1 -1
  184. package/dist/core/sandbox/lima-guest-binary.js.map +1 -1
  185. package/dist/core/sandbox/lima.d.ts +2 -0
  186. package/dist/core/sandbox/lima.d.ts.map +1 -1
  187. package/dist/core/sandbox/lima.js +3 -9
  188. package/dist/core/sandbox/lima.js.map +1 -1
  189. package/dist/core/sandbox/shared-lima-roots.d.ts.map +1 -1
  190. package/dist/core/sandbox/shared-lima-roots.js.map +1 -1
  191. package/dist/core/sandbox/update-shared-guest-binary.d.ts.map +1 -1
  192. package/dist/core/sandbox/update-shared-guest-binary.js.map +1 -1
  193. package/dist/core/session/constants.d.ts.map +1 -1
  194. package/dist/core/session/context-metadata.d.ts.map +1 -1
  195. package/dist/core/session/context-metadata.js.map +1 -1
  196. package/dist/core/session/context.d.ts.map +1 -1
  197. package/dist/core/session/context.js.map +1 -1
  198. package/dist/core/session/ids.d.ts.map +1 -1
  199. package/dist/core/session/ids.js.map +1 -1
  200. package/dist/core/session/in-memory-session-manager.d.ts.map +1 -1
  201. package/dist/core/session/in-memory-session-manager.js +0 -1
  202. package/dist/core/session/in-memory-session-manager.js.map +1 -1
  203. package/dist/core/session/in-memory-session.d.ts.map +1 -1
  204. package/dist/core/session/in-memory-session.js.map +1 -1
  205. package/dist/core/session/jsonl-errors.d.ts.map +1 -1
  206. package/dist/core/session/jsonl-errors.js +0 -11
  207. package/dist/core/session/jsonl-errors.js.map +1 -1
  208. package/dist/core/session/jsonl-helpers.d.ts.map +1 -1
  209. package/dist/core/session/jsonl-helpers.js.map +1 -1
  210. package/dist/core/session/local-session-manager.d.ts.map +1 -1
  211. package/dist/core/session/local-session-manager.js +4 -6
  212. package/dist/core/session/local-session-manager.js.map +1 -1
  213. package/dist/core/session/local-session.d.ts.map +1 -1
  214. package/dist/core/session/local-session.js.map +1 -1
  215. package/dist/core/session/migrations.d.ts.map +1 -1
  216. package/dist/core/session/migrations.js.map +1 -1
  217. package/dist/core/session/remote-session-client.d.ts.map +1 -1
  218. package/dist/core/session/remote-session-client.js +0 -6
  219. package/dist/core/session/remote-session-client.js.map +1 -1
  220. package/dist/core/session/remote-session-manager.d.ts.map +1 -1
  221. package/dist/core/session/remote-session-manager.js +0 -3
  222. package/dist/core/session/remote-session-manager.js.map +1 -1
  223. package/dist/core/session/remote-session.d.ts.map +1 -1
  224. package/dist/core/session/remote-session.js +0 -1
  225. package/dist/core/session/remote-session.js.map +1 -1
  226. package/dist/core/session/session-manager.d.ts.map +1 -1
  227. package/dist/core/session/session.d.ts.map +1 -1
  228. package/dist/core/session/session.js +1 -5
  229. package/dist/core/session/session.js.map +1 -1
  230. package/dist/core/session/stores/in-memory-session-store.d.ts.map +1 -1
  231. package/dist/core/session/stores/in-memory-session-store.js +7 -6
  232. package/dist/core/session/stores/in-memory-session-store.js.map +1 -1
  233. package/dist/core/session/stores/jsonl-session-store.d.ts.map +1 -1
  234. package/dist/core/session/stores/jsonl-session-store.js +6 -14
  235. package/dist/core/session/stores/jsonl-session-store.js.map +1 -1
  236. package/dist/core/session/stores/remote-session-store.d.ts.map +1 -1
  237. package/dist/core/session/stores/remote-session-store.js +3 -8
  238. package/dist/core/session/stores/remote-session-store.js.map +1 -1
  239. package/dist/core/session/stores/session-store.d.ts.map +1 -1
  240. package/dist/core/session/types.d.ts.map +1 -1
  241. package/dist/core/session/usage-ledger.d.ts.map +1 -1
  242. package/dist/core/session/usage-ledger.js.map +1 -1
  243. package/dist/core/session-cwd.d.ts.map +1 -1
  244. package/dist/core/session-cwd.js +0 -1
  245. package/dist/core/session-cwd.js.map +1 -1
  246. package/dist/core/settings-manager.d.ts.map +1 -1
  247. package/dist/core/settings-manager.js +9 -17
  248. package/dist/core/settings-manager.js.map +1 -1
  249. package/dist/core/skills.d.ts.map +1 -1
  250. package/dist/core/skills.js.map +1 -1
  251. package/dist/core/slash-commands.d.ts.map +1 -1
  252. package/dist/core/source-info.d.ts.map +1 -1
  253. package/dist/core/source-info.js.map +1 -1
  254. package/dist/core/system-prompt.d.ts.map +1 -1
  255. package/dist/core/system-prompt.js.map +1 -1
  256. package/dist/core/telemetry.d.ts.map +1 -1
  257. package/dist/core/telemetry.js.map +1 -1
  258. package/dist/core/timings.d.ts.map +1 -1
  259. package/dist/core/timings.js.map +1 -1
  260. package/dist/core/tools/bash.d.ts.map +1 -1
  261. package/dist/core/tools/bash.js +8 -5
  262. package/dist/core/tools/bash.js.map +1 -1
  263. package/dist/core/tools/compress-context.d.ts.map +1 -1
  264. package/dist/core/tools/compress-context.js.map +1 -1
  265. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  266. package/dist/core/tools/edit-diff.js.map +1 -1
  267. package/dist/core/tools/edit.d.ts.map +1 -1
  268. package/dist/core/tools/edit.js.map +1 -1
  269. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  270. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  271. package/dist/core/tools/find.d.ts.map +1 -1
  272. package/dist/core/tools/find.js.map +1 -1
  273. package/dist/core/tools/grep.d.ts.map +1 -1
  274. package/dist/core/tools/grep.js.map +1 -1
  275. package/dist/core/tools/hash-store.d.ts.map +1 -1
  276. package/dist/core/tools/hash-store.js.map +1 -1
  277. package/dist/core/tools/hashline/apply.d.ts.map +1 -1
  278. package/dist/core/tools/hashline/apply.js.map +1 -1
  279. package/dist/core/tools/hashline/hash.d.ts.map +1 -1
  280. package/dist/core/tools/hashline/hash.js.map +1 -1
  281. package/dist/core/tools/hashline/parse.d.ts.map +1 -1
  282. package/dist/core/tools/hashline/parse.js.map +1 -1
  283. package/dist/core/tools/hashline/resolve.d.ts.map +1 -1
  284. package/dist/core/tools/hashline/resolve.js.map +1 -1
  285. package/dist/core/tools/hashline-utils.d.ts.map +1 -1
  286. package/dist/core/tools/hashline-utils.js.map +1 -1
  287. package/dist/core/tools/index.d.ts.map +1 -1
  288. package/dist/core/tools/index.js.map +1 -1
  289. package/dist/core/tools/ls.d.ts.map +1 -1
  290. package/dist/core/tools/ls.js.map +1 -1
  291. package/dist/core/tools/operations.d.ts +5 -0
  292. package/dist/core/tools/operations.d.ts.map +1 -1
  293. package/dist/core/tools/operations.js +26 -24
  294. package/dist/core/tools/operations.js.map +1 -1
  295. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  296. package/dist/core/tools/output-accumulator.js +12 -18
  297. package/dist/core/tools/output-accumulator.js.map +1 -1
  298. package/dist/core/tools/path-utils.d.ts.map +1 -1
  299. package/dist/core/tools/path-utils.js.map +1 -1
  300. package/dist/core/tools/read.d.ts.map +1 -1
  301. package/dist/core/tools/read.js.map +1 -1
  302. package/dist/core/tools/render-utils.d.ts.map +1 -1
  303. package/dist/core/tools/render-utils.js.map +1 -1
  304. package/dist/core/tools/replace-diff.d.ts.map +1 -1
  305. package/dist/core/tools/replace-diff.js.map +1 -1
  306. package/dist/core/tools/replace-normalize.d.ts.map +1 -1
  307. package/dist/core/tools/replace-normalize.js.map +1 -1
  308. package/dist/core/tools/replace-render.d.ts +1 -1
  309. package/dist/core/tools/replace-render.d.ts.map +1 -1
  310. package/dist/core/tools/replace-render.js.map +1 -1
  311. package/dist/core/tools/runtime.d.ts.map +1 -1
  312. package/dist/core/tools/runtime.js.map +1 -1
  313. package/dist/core/tools/session-history.d.ts.map +1 -1
  314. package/dist/core/tools/session-history.js.map +1 -1
  315. package/dist/core/tools/subagent-agents.d.ts.map +1 -1
  316. package/dist/core/tools/subagent-agents.js.map +1 -1
  317. package/dist/core/tools/subagent.d.ts.map +1 -1
  318. package/dist/core/tools/subagent.js.map +1 -1
  319. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  320. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  321. package/dist/core/tools/truncate.d.ts.map +1 -1
  322. package/dist/core/tools/truncate.js.map +1 -1
  323. package/dist/core/tools/websearch.d.ts.map +1 -1
  324. package/dist/core/tools/websearch.js.map +1 -1
  325. package/dist/core/tools/workspace-tool-host.d.ts +1 -0
  326. package/dist/core/tools/workspace-tool-host.d.ts.map +1 -1
  327. package/dist/core/tools/workspace-tool-host.js +36 -22
  328. package/dist/core/tools/workspace-tool-host.js.map +1 -1
  329. package/dist/core/tools/write.d.ts.map +1 -1
  330. package/dist/core/tools/write.js +0 -1
  331. package/dist/core/tools/write.js.map +1 -1
  332. package/dist/core/workspace-identity.d.ts.map +1 -1
  333. package/dist/daemon/activity-budget.d.ts.map +1 -1
  334. package/dist/daemon/activity-budget.js +2 -3
  335. package/dist/daemon/activity-budget.js.map +1 -1
  336. package/dist/daemon/command.d.ts.map +1 -1
  337. package/dist/daemon/command.js.map +1 -1
  338. package/dist/daemon/config.d.ts +2 -0
  339. package/dist/daemon/config.d.ts.map +1 -1
  340. package/dist/daemon/config.js +4 -0
  341. package/dist/daemon/config.js.map +1 -1
  342. package/dist/daemon/help.d.ts.map +1 -1
  343. package/dist/daemon/help.js +4 -3
  344. package/dist/daemon/help.js.map +1 -1
  345. package/dist/daemon/lsp-config.d.ts.map +1 -1
  346. package/dist/daemon/lsp-config.js.map +1 -1
  347. package/dist/daemon/outbound-budget.d.ts.map +1 -1
  348. package/dist/daemon/outbound-budget.js +2 -4
  349. package/dist/daemon/outbound-budget.js.map +1 -1
  350. package/dist/daemon/security.d.ts.map +1 -1
  351. package/dist/daemon/security.js.map +1 -1
  352. package/dist/daemon/server.d.ts.map +1 -1
  353. package/dist/daemon/server.js.map +1 -1
  354. package/dist/daemon/shared-connection.d.ts.map +1 -1
  355. package/dist/daemon/shared-connection.js +10 -15
  356. package/dist/daemon/shared-connection.js.map +1 -1
  357. package/dist/daemon/shared-revision.d.ts.map +1 -1
  358. package/dist/daemon/shared-revision.js +2 -1
  359. package/dist/daemon/shared-revision.js.map +1 -1
  360. package/dist/daemon/shared-roots.d.ts.map +1 -1
  361. package/dist/daemon/shared-roots.js +0 -1
  362. package/dist/daemon/shared-roots.js.map +1 -1
  363. package/dist/daemon/workspace-runtime.d.ts +2 -0
  364. package/dist/daemon/workspace-runtime.d.ts.map +1 -1
  365. package/dist/daemon/workspace-runtime.js +43 -15
  366. package/dist/daemon/workspace-runtime.js.map +1 -1
  367. package/dist/index.d.ts.map +1 -1
  368. package/dist/main.d.ts.map +1 -1
  369. package/dist/main.js.map +1 -1
  370. package/dist/migrations.d.ts.map +1 -1
  371. package/dist/migrations.js.map +1 -1
  372. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  373. package/dist/modes/interactive/components/assistant-message.js +3 -10
  374. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  375. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  376. package/dist/modes/interactive/components/bash-execution.js +4 -9
  377. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  378. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  379. package/dist/modes/interactive/components/bordered-loader.js +0 -3
  380. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  381. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  382. package/dist/modes/interactive/components/branch-summary-message.js +1 -3
  383. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  384. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  385. package/dist/modes/interactive/components/compaction-summary-message.js +1 -3
  386. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  387. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  388. package/dist/modes/interactive/components/config-selector.js +6 -16
  389. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  390. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  391. package/dist/modes/interactive/components/countdown-timer.js +0 -5
  392. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  393. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  394. package/dist/modes/interactive/components/custom-editor.js +1 -8
  395. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  396. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  397. package/dist/modes/interactive/components/custom-message.js +1 -6
  398. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  399. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  400. package/dist/modes/interactive/components/diff.js.map +1 -1
  401. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  402. package/dist/modes/interactive/components/dynamic-border.js +0 -1
  403. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  404. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  405. package/dist/modes/interactive/components/extension-editor.js +1 -7
  406. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  407. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  408. package/dist/modes/interactive/components/extension-input.js +2 -8
  409. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  410. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  411. package/dist/modes/interactive/components/extension-selector.js +1 -9
  412. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  413. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  414. package/dist/modes/interactive/components/footer.js +1 -3
  415. package/dist/modes/interactive/components/footer.js.map +1 -1
  416. package/dist/modes/interactive/components/hook-execution.d.ts.map +1 -1
  417. package/dist/modes/interactive/components/hook-execution.js +2 -5
  418. package/dist/modes/interactive/components/hook-execution.js.map +1 -1
  419. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  420. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  421. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  422. package/dist/modes/interactive/components/login-dialog.js +3 -9
  423. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  424. package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -1
  425. package/dist/modes/interactive/components/markdown-transform.js.map +1 -1
  426. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
  427. package/dist/modes/interactive/components/mermaid.js.map +1 -1
  428. package/dist/modes/interactive/components/message-card.d.ts.map +1 -1
  429. package/dist/modes/interactive/components/message-card.js +0 -1
  430. package/dist/modes/interactive/components/message-card.js.map +1 -1
  431. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  432. package/dist/modes/interactive/components/model-selector.js +13 -28
  433. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  434. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  435. package/dist/modes/interactive/components/oauth-selector.js +3 -12
  436. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  437. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  438. package/dist/modes/interactive/components/scoped-models-selector.js +9 -13
  439. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  440. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  441. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  442. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  443. package/dist/modes/interactive/components/session-selector.js +33 -58
  444. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  445. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  446. package/dist/modes/interactive/components/settings-selector.js +0 -4
  447. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  448. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  449. package/dist/modes/interactive/components/show-images-selector.js +0 -1
  450. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  451. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  452. package/dist/modes/interactive/components/skill-invocation-message.js +1 -3
  453. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  454. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  455. package/dist/modes/interactive/components/theme-selector.js +0 -2
  456. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  457. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  458. package/dist/modes/interactive/components/thinking-selector.js +0 -1
  459. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  460. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  461. package/dist/modes/interactive/components/tool-execution.js +9 -24
  462. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  463. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  464. package/dist/modes/interactive/components/tree-selector.js +18 -34
  465. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  466. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  467. package/dist/modes/interactive/components/user-message-selector.js +3 -6
  468. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  469. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  470. package/dist/modes/interactive/components/user-message.js +0 -4
  471. package/dist/modes/interactive/components/user-message.js.map +1 -1
  472. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  473. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  474. package/dist/modes/interactive/interactive-mode.d.ts +14 -0
  475. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  476. package/dist/modes/interactive/interactive-mode.js +159 -135
  477. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  478. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  479. package/dist/modes/interactive/theme/theme.js +0 -7
  480. package/dist/modes/interactive/theme/theme.js.map +1 -1
  481. package/dist/modes/json-event.d.ts.map +1 -1
  482. package/dist/modes/json-event.js.map +1 -1
  483. package/dist/modes/print-mode.d.ts.map +1 -1
  484. package/dist/modes/print-mode.js.map +1 -1
  485. package/dist/modes/rpc/jsonl.d.ts.map +1 -1
  486. package/dist/modes/rpc/jsonl.js.map +1 -1
  487. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  488. package/dist/modes/rpc/rpc-client.js +10 -11
  489. package/dist/modes/rpc/rpc-client.js.map +1 -1
  490. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  491. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  492. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  493. package/dist/package-manager-cli.d.ts.map +1 -1
  494. package/dist/package-manager-cli.js.map +1 -1
  495. package/dist/utils/ansi.d.ts.map +1 -1
  496. package/dist/utils/ansi.js.map +1 -1
  497. package/dist/utils/changelog.d.ts.map +1 -1
  498. package/dist/utils/changelog.js.map +1 -1
  499. package/dist/utils/child-process.d.ts.map +1 -1
  500. package/dist/utils/child-process.js.map +1 -1
  501. package/dist/utils/clipboard-image.d.ts.map +1 -1
  502. package/dist/utils/clipboard-image.js.map +1 -1
  503. package/dist/utils/clipboard-native.d.ts.map +1 -1
  504. package/dist/utils/clipboard-native.js.map +1 -1
  505. package/dist/utils/clipboard.d.ts.map +1 -1
  506. package/dist/utils/clipboard.js.map +1 -1
  507. package/dist/utils/deprecation.d.ts.map +1 -1
  508. package/dist/utils/deprecation.js.map +1 -1
  509. package/dist/utils/directory-completions.d.ts.map +1 -1
  510. package/dist/utils/directory-completions.js.map +1 -1
  511. package/dist/utils/exif-orientation.d.ts.map +1 -1
  512. package/dist/utils/exif-orientation.js.map +1 -1
  513. package/dist/utils/frontmatter.d.ts.map +1 -1
  514. package/dist/utils/frontmatter.js.map +1 -1
  515. package/dist/utils/fs-watch.d.ts.map +1 -1
  516. package/dist/utils/fs-watch.js.map +1 -1
  517. package/dist/utils/git.d.ts.map +1 -1
  518. package/dist/utils/git.js.map +1 -1
  519. package/dist/utils/grip-user-agent.d.ts.map +1 -1
  520. package/dist/utils/grip-user-agent.js.map +1 -1
  521. package/dist/utils/html.d.ts.map +1 -1
  522. package/dist/utils/html.js.map +1 -1
  523. package/dist/utils/image-convert.d.ts.map +1 -1
  524. package/dist/utils/image-convert.js.map +1 -1
  525. package/dist/utils/image-process.d.ts.map +1 -1
  526. package/dist/utils/image-process.js.map +1 -1
  527. package/dist/utils/image-resize-core.d.ts.map +1 -1
  528. package/dist/utils/image-resize-core.js.map +1 -1
  529. package/dist/utils/image-resize-worker.d.ts.map +1 -1
  530. package/dist/utils/image-resize-worker.js.map +1 -1
  531. package/dist/utils/image-resize.d.ts.map +1 -1
  532. package/dist/utils/image-resize.js.map +1 -1
  533. package/dist/utils/json.d.ts.map +1 -1
  534. package/dist/utils/json.js.map +1 -1
  535. package/dist/utils/mime.d.ts.map +1 -1
  536. package/dist/utils/mime.js.map +1 -1
  537. package/dist/utils/open-browser.d.ts.map +1 -1
  538. package/dist/utils/open-browser.js.map +1 -1
  539. package/dist/utils/paths.d.ts.map +1 -1
  540. package/dist/utils/paths.js.map +1 -1
  541. package/dist/utils/photon.d.ts.map +1 -1
  542. package/dist/utils/photon.js +10 -5
  543. package/dist/utils/photon.js.map +1 -1
  544. package/dist/utils/shell.d.ts.map +1 -1
  545. package/dist/utils/shell.js.map +1 -1
  546. package/dist/utils/sleep.d.ts.map +1 -1
  547. package/dist/utils/sleep.js.map +1 -1
  548. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  549. package/dist/utils/syntax-highlight.js +1 -1
  550. package/dist/utils/syntax-highlight.js.map +1 -1
  551. package/dist/utils/tools-manager.d.ts.map +1 -1
  552. package/dist/utils/tools-manager.js.map +1 -1
  553. package/dist/utils/version-check.d.ts.map +1 -1
  554. package/dist/utils/version-check.js.map +1 -1
  555. package/dist/utils/windows-self-update.d.ts.map +1 -1
  556. package/dist/utils/windows-self-update.js.map +1 -1
  557. package/docs/sandbox.md +6 -0
  558. package/docs/sessions.md +1 -1
  559. package/docs/usage.md +2 -1
  560. package/examples/extensions/custom-provider-anthropic/package.json +2 -2
  561. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  562. package/examples/extensions/sandbox/package.json +2 -2
  563. package/examples/extensions/with-deps/package.json +1 -1
  564. package/npm-shrinkwrap.json +601 -833
  565. package/package.json +20 -21
@@ -1 +1 @@
1
- {"version":3,"file":"tool-definition-wrapper.d.ts","sourceRoot":"","sources":["../../../src/core/tools/tool-definition-wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE/E,oEAAoE;AACpE,wBAAgB,kBAAkB,CAAC,QAAQ,GAAG,OAAO,EACpD,UAAU,EAAE,cAAc,CAAC,GAAG,EAAE,QAAQ,CAAC,EACzC,UAAU,CAAC,EAAE,MAAM,gBAAgB,GACjC,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,CAW1B;AAED,0EAA0E;AAC1E,wBAAgB,mBAAmB,CAClC,WAAW,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EACvC,UAAU,CAAC,EAAE,MAAM,gBAAgB,GACjC,SAAS,CAAC,GAAG,CAAC,EAAE,CAElB;AAED;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,CAUpG","sourcesContent":["import type { AgentTool } from \"@greppleai/grip-agent-core\";\nimport type { ExtensionContext, ToolDefinition } from \"../extensions/types.ts\";\n\n/** Wrap a ToolDefinition into an AgentTool for the core runtime. */\nexport function wrapToolDefinition<TDetails = unknown>(\n\tdefinition: ToolDefinition<any, TDetails>,\n\tctxFactory?: () => ExtensionContext,\n): AgentTool<any, TDetails> {\n\treturn {\n\t\tname: definition.name,\n\t\tlabel: definition.label,\n\t\tdescription: definition.description,\n\t\tparameters: definition.parameters,\n\t\tprepareArguments: definition.prepareArguments,\n\t\texecutionMode: definition.executionMode,\n\t\texecute: (toolCallId, params, signal, onUpdate, ctx?: ExtensionContext) =>\n\t\t\tdefinition.execute(toolCallId, params, signal, onUpdate, ctx ?? (ctxFactory?.() as ExtensionContext)),\n\t};\n}\n\n/** Wrap multiple ToolDefinitions into AgentTools for the core runtime. */\nexport function wrapToolDefinitions(\n\tdefinitions: ToolDefinition<any, any>[],\n\tctxFactory?: () => ExtensionContext,\n): AgentTool<any>[] {\n\treturn definitions.map((definition) => wrapToolDefinition(definition, ctxFactory));\n}\n\n/**\n * Synthesize a minimal ToolDefinition from an AgentTool.\n *\n * This keeps AgentSession's internal registry definition-first even when a caller\n * provides plain AgentTool overrides that do not include prompt metadata or renderers.\n */\nexport function createToolDefinitionFromAgentTool(tool: AgentTool<any>): ToolDefinition<any, unknown> {\n\treturn {\n\t\tname: tool.name,\n\t\tlabel: tool.label,\n\t\tdescription: tool.description,\n\t\tparameters: tool.parameters as any,\n\t\tprepareArguments: tool.prepareArguments,\n\t\texecutionMode: tool.executionMode,\n\t\texecute: async (toolCallId, params, signal, onUpdate) => tool.execute(toolCallId, params, signal, onUpdate),\n\t};\n}\n"]}
1
+ {"version":3,"file":"tool-definition-wrapper.d.ts","sourceRoot":"","sources":["../../../src/core/tools/tool-definition-wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE/E,oEAAoE;AACpE,wBAAgB,kBAAkB,CAAC,QAAQ,GAAG,OAAO,EACpD,UAAU,EAAE,cAAc,CAAC,GAAG,EAAE,QAAQ,CAAC,EACzC,UAAU,CAAC,EAAE,MAAM,gBAAgB,GACjC,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,CAW1B;AAED,0EAA0E;AAC1E,wBAAgB,mBAAmB,CAClC,WAAW,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EACvC,UAAU,CAAC,EAAE,MAAM,gBAAgB,GACjC,SAAS,CAAC,GAAG,CAAC,EAAE,CAElB;AAED;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,CAUpG"}
@@ -1 +1 @@
1
- {"version":3,"file":"tool-definition-wrapper.js","sourceRoot":"","sources":["../../../src/core/tools/tool-definition-wrapper.ts"],"names":[],"mappings":"AAGA,oEAAoE;AACpE,MAAM,UAAU,kBAAkB,CACjC,UAAyC,EACzC,UAAmC,EACR;IAC3B,OAAO;QACN,IAAI,EAAE,UAAU,CAAC,IAAI;QACrB,KAAK,EAAE,UAAU,CAAC,KAAK;QACvB,WAAW,EAAE,UAAU,CAAC,WAAW;QACnC,UAAU,EAAE,UAAU,CAAC,UAAU;QACjC,gBAAgB,EAAE,UAAU,CAAC,gBAAgB;QAC7C,aAAa,EAAE,UAAU,CAAC,aAAa;QACvC,OAAO,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAsB,EAAE,EAAE,CACzE,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAK,UAAU,EAAE,EAAuB,CAAC;KACtG,CAAC;AAAA,CACF;AAED,0EAA0E;AAC1E,MAAM,UAAU,mBAAmB,CAClC,WAAuC,EACvC,UAAmC,EAChB;IACnB,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;AAAA,CACnF;AAED;;;;;GAKG;AACH,MAAM,UAAU,iCAAiC,CAAC,IAAoB,EAAgC;IACrG,OAAO;QACN,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,UAAU,EAAE,IAAI,CAAC,UAAiB;QAClC,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;QACvC,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC;KAC3G,CAAC;AAAA,CACF","sourcesContent":["import type { AgentTool } from \"@greppleai/grip-agent-core\";\nimport type { ExtensionContext, ToolDefinition } from \"../extensions/types.ts\";\n\n/** Wrap a ToolDefinition into an AgentTool for the core runtime. */\nexport function wrapToolDefinition<TDetails = unknown>(\n\tdefinition: ToolDefinition<any, TDetails>,\n\tctxFactory?: () => ExtensionContext,\n): AgentTool<any, TDetails> {\n\treturn {\n\t\tname: definition.name,\n\t\tlabel: definition.label,\n\t\tdescription: definition.description,\n\t\tparameters: definition.parameters,\n\t\tprepareArguments: definition.prepareArguments,\n\t\texecutionMode: definition.executionMode,\n\t\texecute: (toolCallId, params, signal, onUpdate, ctx?: ExtensionContext) =>\n\t\t\tdefinition.execute(toolCallId, params, signal, onUpdate, ctx ?? (ctxFactory?.() as ExtensionContext)),\n\t};\n}\n\n/** Wrap multiple ToolDefinitions into AgentTools for the core runtime. */\nexport function wrapToolDefinitions(\n\tdefinitions: ToolDefinition<any, any>[],\n\tctxFactory?: () => ExtensionContext,\n): AgentTool<any>[] {\n\treturn definitions.map((definition) => wrapToolDefinition(definition, ctxFactory));\n}\n\n/**\n * Synthesize a minimal ToolDefinition from an AgentTool.\n *\n * This keeps AgentSession's internal registry definition-first even when a caller\n * provides plain AgentTool overrides that do not include prompt metadata or renderers.\n */\nexport function createToolDefinitionFromAgentTool(tool: AgentTool<any>): ToolDefinition<any, unknown> {\n\treturn {\n\t\tname: tool.name,\n\t\tlabel: tool.label,\n\t\tdescription: tool.description,\n\t\tparameters: tool.parameters as any,\n\t\tprepareArguments: tool.prepareArguments,\n\t\texecutionMode: tool.executionMode,\n\t\texecute: async (toolCallId, params, signal, onUpdate) => tool.execute(toolCallId, params, signal, onUpdate),\n\t};\n}\n"]}
1
+ {"version":3,"file":"tool-definition-wrapper.js","sourceRoot":"","sources":["../../../src/core/tools/tool-definition-wrapper.ts"],"names":[],"mappings":"AAGA,oEAAoE;AACpE,MAAM,UAAU,kBAAkB,CACjC,UAAyC,EACzC,UAAmC;IAEnC,OAAO;QACN,IAAI,EAAE,UAAU,CAAC,IAAI;QACrB,KAAK,EAAE,UAAU,CAAC,KAAK;QACvB,WAAW,EAAE,UAAU,CAAC,WAAW;QACnC,UAAU,EAAE,UAAU,CAAC,UAAU;QACjC,gBAAgB,EAAE,UAAU,CAAC,gBAAgB;QAC7C,aAAa,EAAE,UAAU,CAAC,aAAa;QACvC,OAAO,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAsB,EAAE,EAAE,CACzE,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAK,UAAU,EAAE,EAAuB,CAAC;KACtG,CAAC;AACH,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,mBAAmB,CAClC,WAAuC,EACvC,UAAmC;IAEnC,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;AACpF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iCAAiC,CAAC,IAAoB;IACrE,OAAO;QACN,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,UAAU,EAAE,IAAI,CAAC,UAAiB;QAClC,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;QACvC,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC;KAC3G,CAAC;AACH,CAAC","sourcesContent":["import type { AgentTool } from \"@greppleai/grip-agent-core\";\nimport type { ExtensionContext, ToolDefinition } from \"../extensions/types.ts\";\n\n/** Wrap a ToolDefinition into an AgentTool for the core runtime. */\nexport function wrapToolDefinition<TDetails = unknown>(\n\tdefinition: ToolDefinition<any, TDetails>,\n\tctxFactory?: () => ExtensionContext,\n): AgentTool<any, TDetails> {\n\treturn {\n\t\tname: definition.name,\n\t\tlabel: definition.label,\n\t\tdescription: definition.description,\n\t\tparameters: definition.parameters,\n\t\tprepareArguments: definition.prepareArguments,\n\t\texecutionMode: definition.executionMode,\n\t\texecute: (toolCallId, params, signal, onUpdate, ctx?: ExtensionContext) =>\n\t\t\tdefinition.execute(toolCallId, params, signal, onUpdate, ctx ?? (ctxFactory?.() as ExtensionContext)),\n\t};\n}\n\n/** Wrap multiple ToolDefinitions into AgentTools for the core runtime. */\nexport function wrapToolDefinitions(\n\tdefinitions: ToolDefinition<any, any>[],\n\tctxFactory?: () => ExtensionContext,\n): AgentTool<any>[] {\n\treturn definitions.map((definition) => wrapToolDefinition(definition, ctxFactory));\n}\n\n/**\n * Synthesize a minimal ToolDefinition from an AgentTool.\n *\n * This keeps AgentSession's internal registry definition-first even when a caller\n * provides plain AgentTool overrides that do not include prompt metadata or renderers.\n */\nexport function createToolDefinitionFromAgentTool(tool: AgentTool<any>): ToolDefinition<any, unknown> {\n\treturn {\n\t\tname: tool.name,\n\t\tlabel: tool.label,\n\t\tdescription: tool.description,\n\t\tparameters: tool.parameters as any,\n\t\tprepareArguments: tool.prepareArguments,\n\t\texecutionMode: tool.executionMode,\n\t\texecute: async (toolCallId, params, signal, onUpdate) => tool.execute(toolCallId, params, signal, onUpdate),\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"truncate.d.ts","sourceRoot":"","sources":["../../../src/core/tools/truncate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAE5G,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;AACpD,eAAO,MAAM,iBAAiB,OAAO,CAAC;AACtC,eAAO,MAAM,iBAAiB,QAAY,CAAC;AAC3C,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAaxC;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQhD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,gBAAgB,CAkF/F;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,gBAAgB,CAyE/F;AAuBD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAA6B,GAAG,oBAAoB,CAKxG","sourcesContent":["/**\n * Shared truncation utilities for tool outputs.\n *\n * Truncation is based on two independent limits - whichever is hit first wins:\n * - Line limit (default: 2000 lines)\n * - Byte limit (default: 50KB)\n *\n * Never returns partial lines (except bash tail truncation edge case).\n */\n\nimport type { LineTruncationResult, TruncationOptions, TruncationResult } from \"@greppleai/grip-agent-core\";\n\nexport type { TruncationOptions, TruncationResult };\nexport const DEFAULT_MAX_LINES = 2000;\nexport const DEFAULT_MAX_BYTES = 50 * 1024; // 50KB\nexport const GREP_MAX_LINE_LENGTH = 500; // Max chars per grep match line\n\nfunction splitLinesForCounting(content: string): string[] {\n\tif (content.length === 0) {\n\t\treturn [];\n\t}\n\tconst lines = content.split(\"\\n\");\n\tif (content.endsWith(\"\\n\")) {\n\t\tlines.pop();\n\t}\n\treturn lines;\n}\n\n/**\n * Format bytes as human-readable size.\n */\nexport function formatSize(bytes: number): string {\n\tif (bytes < 1024) {\n\t\treturn `${bytes}B`;\n\t} else if (bytes < 1024 * 1024) {\n\t\treturn `${(bytes / 1024).toFixed(1)}KB`;\n\t} else {\n\t\treturn `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n\t}\n}\n\n/**\n * Truncate content from the head (keep first N lines/bytes).\n * Suitable for file reads where you want to see the beginning.\n *\n * Never returns partial lines. If first line exceeds byte limit,\n * returns empty content with firstLineExceedsLimit=true.\n */\nexport function truncateHead(content: string, options: TruncationOptions = {}): TruncationResult {\n\tconst maxLines = options.maxLines ?? DEFAULT_MAX_LINES;\n\tconst maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;\n\n\tconst totalBytes = Buffer.byteLength(content, \"utf-8\");\n\tconst lines = splitLinesForCounting(content);\n\tconst totalLines = lines.length;\n\n\t// Check if no truncation needed\n\tif (totalLines <= maxLines && totalBytes <= maxBytes) {\n\t\treturn {\n\t\t\tcontent,\n\t\t\ttruncated: false,\n\t\t\ttruncatedBy: null,\n\t\t\ttotalLines,\n\t\t\ttotalBytes,\n\t\t\toutputLines: totalLines,\n\t\t\toutputBytes: totalBytes,\n\t\t\tlastLinePartial: false,\n\t\t\tfirstLineExceedsLimit: false,\n\t\t\tmaxLines,\n\t\t\tmaxBytes,\n\t\t};\n\t}\n\n\t// Check if first line alone exceeds byte limit\n\tconst firstLineBytes = Buffer.byteLength(lines[0], \"utf-8\");\n\tif (firstLineBytes > maxBytes) {\n\t\treturn {\n\t\t\tcontent: \"\",\n\t\t\ttruncated: true,\n\t\t\ttruncatedBy: \"bytes\",\n\t\t\ttotalLines,\n\t\t\ttotalBytes,\n\t\t\toutputLines: 0,\n\t\t\toutputBytes: 0,\n\t\t\tlastLinePartial: false,\n\t\t\tfirstLineExceedsLimit: true,\n\t\t\tmaxLines,\n\t\t\tmaxBytes,\n\t\t};\n\t}\n\n\t// Collect complete lines that fit\n\tconst outputLinesArr: string[] = [];\n\tlet outputBytesCount = 0;\n\tlet truncatedBy: \"lines\" | \"bytes\" = \"lines\";\n\n\tfor (let i = 0; i < lines.length && i < maxLines; i++) {\n\t\tconst line = lines[i];\n\t\tconst lineBytes = Buffer.byteLength(line, \"utf-8\") + (i > 0 ? 1 : 0); // +1 for newline\n\n\t\tif (outputBytesCount + lineBytes > maxBytes) {\n\t\t\ttruncatedBy = \"bytes\";\n\t\t\tbreak;\n\t\t}\n\n\t\toutputLinesArr.push(line);\n\t\toutputBytesCount += lineBytes;\n\t}\n\n\t// If we exited due to line limit\n\tif (outputLinesArr.length >= maxLines && outputBytesCount <= maxBytes) {\n\t\ttruncatedBy = \"lines\";\n\t}\n\n\tconst outputContent = outputLinesArr.join(\"\\n\");\n\tconst finalOutputBytes = Buffer.byteLength(outputContent, \"utf-8\");\n\n\treturn {\n\t\tcontent: outputContent,\n\t\ttruncated: true,\n\t\ttruncatedBy,\n\t\ttotalLines,\n\t\ttotalBytes,\n\t\toutputLines: outputLinesArr.length,\n\t\toutputBytes: finalOutputBytes,\n\t\tlastLinePartial: false,\n\t\tfirstLineExceedsLimit: false,\n\t\tmaxLines,\n\t\tmaxBytes,\n\t};\n}\n\n/**\n * Truncate content from the tail (keep last N lines/bytes).\n * Suitable for bash output where you want to see the end (errors, final results).\n *\n * May return partial first line if the last line of original content exceeds byte limit.\n */\nexport function truncateTail(content: string, options: TruncationOptions = {}): TruncationResult {\n\tconst maxLines = options.maxLines ?? DEFAULT_MAX_LINES;\n\tconst maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;\n\n\tconst totalBytes = Buffer.byteLength(content, \"utf-8\");\n\tconst lines = splitLinesForCounting(content);\n\tconst totalLines = lines.length;\n\n\t// Check if no truncation needed\n\tif (totalLines <= maxLines && totalBytes <= maxBytes) {\n\t\treturn {\n\t\t\tcontent,\n\t\t\ttruncated: false,\n\t\t\ttruncatedBy: null,\n\t\t\ttotalLines,\n\t\t\ttotalBytes,\n\t\t\toutputLines: totalLines,\n\t\t\toutputBytes: totalBytes,\n\t\t\tlastLinePartial: false,\n\t\t\tfirstLineExceedsLimit: false,\n\t\t\tmaxLines,\n\t\t\tmaxBytes,\n\t\t};\n\t}\n\n\t// Work backwards from the end\n\tconst outputLinesArr: string[] = [];\n\tlet outputBytesCount = 0;\n\tlet truncatedBy: \"lines\" | \"bytes\" = \"lines\";\n\tlet lastLinePartial = false;\n\n\tfor (let i = lines.length - 1; i >= 0 && outputLinesArr.length < maxLines; i--) {\n\t\tconst line = lines[i];\n\t\tconst lineBytes = Buffer.byteLength(line, \"utf-8\") + (outputLinesArr.length > 0 ? 1 : 0); // +1 for newline\n\n\t\tif (outputBytesCount + lineBytes > maxBytes) {\n\t\t\ttruncatedBy = \"bytes\";\n\t\t\t// Edge case: if we haven't added ANY lines yet and this line exceeds maxBytes,\n\t\t\t// take the end of the line (partial)\n\t\t\tif (outputLinesArr.length === 0) {\n\t\t\t\tconst truncatedLine = truncateStringToBytesFromEnd(line, maxBytes);\n\t\t\t\toutputLinesArr.unshift(truncatedLine);\n\t\t\t\toutputBytesCount = Buffer.byteLength(truncatedLine, \"utf-8\");\n\t\t\t\tlastLinePartial = true;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\toutputLinesArr.unshift(line);\n\t\toutputBytesCount += lineBytes;\n\t}\n\n\t// If we exited due to line limit\n\tif (outputLinesArr.length >= maxLines && outputBytesCount <= maxBytes) {\n\t\ttruncatedBy = \"lines\";\n\t}\n\n\tconst outputContent = outputLinesArr.join(\"\\n\");\n\tconst finalOutputBytes = Buffer.byteLength(outputContent, \"utf-8\");\n\n\treturn {\n\t\tcontent: outputContent,\n\t\ttruncated: true,\n\t\ttruncatedBy,\n\t\ttotalLines,\n\t\ttotalBytes,\n\t\toutputLines: outputLinesArr.length,\n\t\toutputBytes: finalOutputBytes,\n\t\tlastLinePartial,\n\t\tfirstLineExceedsLimit: false,\n\t\tmaxLines,\n\t\tmaxBytes,\n\t};\n}\n\n/**\n * Truncate a string to fit within a byte limit (from the end).\n * Handles multi-byte UTF-8 characters correctly.\n */\nfunction truncateStringToBytesFromEnd(str: string, maxBytes: number): string {\n\tconst buf = Buffer.from(str, \"utf-8\");\n\tif (buf.length <= maxBytes) {\n\t\treturn str;\n\t}\n\n\t// Start from the end, skip maxBytes back\n\tlet start = buf.length - maxBytes;\n\n\t// Find a valid UTF-8 boundary (start of a character)\n\twhile (start < buf.length && (buf[start] & 0xc0) === 0x80) {\n\t\tstart++;\n\t}\n\n\treturn buf.slice(start).toString(\"utf-8\");\n}\n\n/**\n * Truncate a single line to max characters, adding [truncated] suffix.\n * Used for grep match lines.\n */\nexport function truncateLine(line: string, maxChars: number = GREP_MAX_LINE_LENGTH): LineTruncationResult {\n\tif (line.length <= maxChars) {\n\t\treturn { text: line, wasTruncated: false };\n\t}\n\treturn { text: `${line.slice(0, maxChars)}... [truncated]`, wasTruncated: true };\n}\n"]}
1
+ {"version":3,"file":"truncate.d.ts","sourceRoot":"","sources":["../../../src/core/tools/truncate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAE5G,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;AACpD,eAAO,MAAM,iBAAiB,OAAO,CAAC;AACtC,eAAO,MAAM,iBAAiB,QAAY,CAAC;AAC3C,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAaxC;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQhD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,gBAAgB,CAkF/F;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,gBAAgB,CAyE/F;AAuBD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAA6B,GAAG,oBAAoB,CAKxG"}
@@ -1 +1 @@
1
- {"version":3,"file":"truncate.js","sourceRoot":"","sources":["../../../src/core/tools/truncate.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared truncation utilities for tool outputs.\n *\n * Truncation is based on two independent limits - whichever is hit first wins:\n * - Line limit (default: 2000 lines)\n * - Byte limit (default: 50KB)\n *\n * Never returns partial lines (except bash tail truncation edge case).\n */\n\nimport type { LineTruncationResult, TruncationOptions, TruncationResult } from \"@greppleai/grip-agent-core\";\n\nexport type { TruncationOptions, TruncationResult };\nexport const DEFAULT_MAX_LINES = 2000;\nexport const DEFAULT_MAX_BYTES = 50 * 1024; // 50KB\nexport const GREP_MAX_LINE_LENGTH = 500; // Max chars per grep match line\n\nfunction splitLinesForCounting(content: string): string[] {\n\tif (content.length === 0) {\n\t\treturn [];\n\t}\n\tconst lines = content.split(\"\\n\");\n\tif (content.endsWith(\"\\n\")) {\n\t\tlines.pop();\n\t}\n\treturn lines;\n}\n\n/**\n * Format bytes as human-readable size.\n */\nexport function formatSize(bytes: number): string {\n\tif (bytes < 1024) {\n\t\treturn `${bytes}B`;\n\t} else if (bytes < 1024 * 1024) {\n\t\treturn `${(bytes / 1024).toFixed(1)}KB`;\n\t} else {\n\t\treturn `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n\t}\n}\n\n/**\n * Truncate content from the head (keep first N lines/bytes).\n * Suitable for file reads where you want to see the beginning.\n *\n * Never returns partial lines. If first line exceeds byte limit,\n * returns empty content with firstLineExceedsLimit=true.\n */\nexport function truncateHead(content: string, options: TruncationOptions = {}): TruncationResult {\n\tconst maxLines = options.maxLines ?? DEFAULT_MAX_LINES;\n\tconst maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;\n\n\tconst totalBytes = Buffer.byteLength(content, \"utf-8\");\n\tconst lines = splitLinesForCounting(content);\n\tconst totalLines = lines.length;\n\n\t// Check if no truncation needed\n\tif (totalLines <= maxLines && totalBytes <= maxBytes) {\n\t\treturn {\n\t\t\tcontent,\n\t\t\ttruncated: false,\n\t\t\ttruncatedBy: null,\n\t\t\ttotalLines,\n\t\t\ttotalBytes,\n\t\t\toutputLines: totalLines,\n\t\t\toutputBytes: totalBytes,\n\t\t\tlastLinePartial: false,\n\t\t\tfirstLineExceedsLimit: false,\n\t\t\tmaxLines,\n\t\t\tmaxBytes,\n\t\t};\n\t}\n\n\t// Check if first line alone exceeds byte limit\n\tconst firstLineBytes = Buffer.byteLength(lines[0], \"utf-8\");\n\tif (firstLineBytes > maxBytes) {\n\t\treturn {\n\t\t\tcontent: \"\",\n\t\t\ttruncated: true,\n\t\t\ttruncatedBy: \"bytes\",\n\t\t\ttotalLines,\n\t\t\ttotalBytes,\n\t\t\toutputLines: 0,\n\t\t\toutputBytes: 0,\n\t\t\tlastLinePartial: false,\n\t\t\tfirstLineExceedsLimit: true,\n\t\t\tmaxLines,\n\t\t\tmaxBytes,\n\t\t};\n\t}\n\n\t// Collect complete lines that fit\n\tconst outputLinesArr: string[] = [];\n\tlet outputBytesCount = 0;\n\tlet truncatedBy: \"lines\" | \"bytes\" = \"lines\";\n\n\tfor (let i = 0; i < lines.length && i < maxLines; i++) {\n\t\tconst line = lines[i];\n\t\tconst lineBytes = Buffer.byteLength(line, \"utf-8\") + (i > 0 ? 1 : 0); // +1 for newline\n\n\t\tif (outputBytesCount + lineBytes > maxBytes) {\n\t\t\ttruncatedBy = \"bytes\";\n\t\t\tbreak;\n\t\t}\n\n\t\toutputLinesArr.push(line);\n\t\toutputBytesCount += lineBytes;\n\t}\n\n\t// If we exited due to line limit\n\tif (outputLinesArr.length >= maxLines && outputBytesCount <= maxBytes) {\n\t\ttruncatedBy = \"lines\";\n\t}\n\n\tconst outputContent = outputLinesArr.join(\"\\n\");\n\tconst finalOutputBytes = Buffer.byteLength(outputContent, \"utf-8\");\n\n\treturn {\n\t\tcontent: outputContent,\n\t\ttruncated: true,\n\t\ttruncatedBy,\n\t\ttotalLines,\n\t\ttotalBytes,\n\t\toutputLines: outputLinesArr.length,\n\t\toutputBytes: finalOutputBytes,\n\t\tlastLinePartial: false,\n\t\tfirstLineExceedsLimit: false,\n\t\tmaxLines,\n\t\tmaxBytes,\n\t};\n}\n\n/**\n * Truncate content from the tail (keep last N lines/bytes).\n * Suitable for bash output where you want to see the end (errors, final results).\n *\n * May return partial first line if the last line of original content exceeds byte limit.\n */\nexport function truncateTail(content: string, options: TruncationOptions = {}): TruncationResult {\n\tconst maxLines = options.maxLines ?? DEFAULT_MAX_LINES;\n\tconst maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;\n\n\tconst totalBytes = Buffer.byteLength(content, \"utf-8\");\n\tconst lines = splitLinesForCounting(content);\n\tconst totalLines = lines.length;\n\n\t// Check if no truncation needed\n\tif (totalLines <= maxLines && totalBytes <= maxBytes) {\n\t\treturn {\n\t\t\tcontent,\n\t\t\ttruncated: false,\n\t\t\ttruncatedBy: null,\n\t\t\ttotalLines,\n\t\t\ttotalBytes,\n\t\t\toutputLines: totalLines,\n\t\t\toutputBytes: totalBytes,\n\t\t\tlastLinePartial: false,\n\t\t\tfirstLineExceedsLimit: false,\n\t\t\tmaxLines,\n\t\t\tmaxBytes,\n\t\t};\n\t}\n\n\t// Work backwards from the end\n\tconst outputLinesArr: string[] = [];\n\tlet outputBytesCount = 0;\n\tlet truncatedBy: \"lines\" | \"bytes\" = \"lines\";\n\tlet lastLinePartial = false;\n\n\tfor (let i = lines.length - 1; i >= 0 && outputLinesArr.length < maxLines; i--) {\n\t\tconst line = lines[i];\n\t\tconst lineBytes = Buffer.byteLength(line, \"utf-8\") + (outputLinesArr.length > 0 ? 1 : 0); // +1 for newline\n\n\t\tif (outputBytesCount + lineBytes > maxBytes) {\n\t\t\ttruncatedBy = \"bytes\";\n\t\t\t// Edge case: if we haven't added ANY lines yet and this line exceeds maxBytes,\n\t\t\t// take the end of the line (partial)\n\t\t\tif (outputLinesArr.length === 0) {\n\t\t\t\tconst truncatedLine = truncateStringToBytesFromEnd(line, maxBytes);\n\t\t\t\toutputLinesArr.unshift(truncatedLine);\n\t\t\t\toutputBytesCount = Buffer.byteLength(truncatedLine, \"utf-8\");\n\t\t\t\tlastLinePartial = true;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\toutputLinesArr.unshift(line);\n\t\toutputBytesCount += lineBytes;\n\t}\n\n\t// If we exited due to line limit\n\tif (outputLinesArr.length >= maxLines && outputBytesCount <= maxBytes) {\n\t\ttruncatedBy = \"lines\";\n\t}\n\n\tconst outputContent = outputLinesArr.join(\"\\n\");\n\tconst finalOutputBytes = Buffer.byteLength(outputContent, \"utf-8\");\n\n\treturn {\n\t\tcontent: outputContent,\n\t\ttruncated: true,\n\t\ttruncatedBy,\n\t\ttotalLines,\n\t\ttotalBytes,\n\t\toutputLines: outputLinesArr.length,\n\t\toutputBytes: finalOutputBytes,\n\t\tlastLinePartial,\n\t\tfirstLineExceedsLimit: false,\n\t\tmaxLines,\n\t\tmaxBytes,\n\t};\n}\n\n/**\n * Truncate a string to fit within a byte limit (from the end).\n * Handles multi-byte UTF-8 characters correctly.\n */\nfunction truncateStringToBytesFromEnd(str: string, maxBytes: number): string {\n\tconst buf = Buffer.from(str, \"utf-8\");\n\tif (buf.length <= maxBytes) {\n\t\treturn str;\n\t}\n\n\t// Start from the end, skip maxBytes back\n\tlet start = buf.length - maxBytes;\n\n\t// Find a valid UTF-8 boundary (start of a character)\n\twhile (start < buf.length && (buf[start] & 0xc0) === 0x80) {\n\t\tstart++;\n\t}\n\n\treturn buf.slice(start).toString(\"utf-8\");\n}\n\n/**\n * Truncate a single line to max characters, adding [truncated] suffix.\n * Used for grep match lines.\n */\nexport function truncateLine(line: string, maxChars: number = GREP_MAX_LINE_LENGTH): LineTruncationResult {\n\tif (line.length <= maxChars) {\n\t\treturn { text: line, wasTruncated: false };\n\t}\n\treturn { text: `${line.slice(0, maxChars)}... [truncated]`, wasTruncated: true };\n}\n"]}
1
+ {"version":3,"file":"truncate.js","sourceRoot":"","sources":["../../../src/core/tools/truncate.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared truncation utilities for tool outputs.\n *\n * Truncation is based on two independent limits - whichever is hit first wins:\n * - Line limit (default: 2000 lines)\n * - Byte limit (default: 50KB)\n *\n * Never returns partial lines (except bash tail truncation edge case).\n */\n\nimport type { LineTruncationResult, TruncationOptions, TruncationResult } from \"@greppleai/grip-agent-core\";\n\nexport type { TruncationOptions, TruncationResult };\nexport const DEFAULT_MAX_LINES = 2000;\nexport const DEFAULT_MAX_BYTES = 50 * 1024; // 50KB\nexport const GREP_MAX_LINE_LENGTH = 500; // Max chars per grep match line\n\nfunction splitLinesForCounting(content: string): string[] {\n\tif (content.length === 0) {\n\t\treturn [];\n\t}\n\tconst lines = content.split(\"\\n\");\n\tif (content.endsWith(\"\\n\")) {\n\t\tlines.pop();\n\t}\n\treturn lines;\n}\n\n/**\n * Format bytes as human-readable size.\n */\nexport function formatSize(bytes: number): string {\n\tif (bytes < 1024) {\n\t\treturn `${bytes}B`;\n\t} else if (bytes < 1024 * 1024) {\n\t\treturn `${(bytes / 1024).toFixed(1)}KB`;\n\t} else {\n\t\treturn `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n\t}\n}\n\n/**\n * Truncate content from the head (keep first N lines/bytes).\n * Suitable for file reads where you want to see the beginning.\n *\n * Never returns partial lines. If first line exceeds byte limit,\n * returns empty content with firstLineExceedsLimit=true.\n */\nexport function truncateHead(content: string, options: TruncationOptions = {}): TruncationResult {\n\tconst maxLines = options.maxLines ?? DEFAULT_MAX_LINES;\n\tconst maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;\n\n\tconst totalBytes = Buffer.byteLength(content, \"utf-8\");\n\tconst lines = splitLinesForCounting(content);\n\tconst totalLines = lines.length;\n\n\t// Check if no truncation needed\n\tif (totalLines <= maxLines && totalBytes <= maxBytes) {\n\t\treturn {\n\t\t\tcontent,\n\t\t\ttruncated: false,\n\t\t\ttruncatedBy: null,\n\t\t\ttotalLines,\n\t\t\ttotalBytes,\n\t\t\toutputLines: totalLines,\n\t\t\toutputBytes: totalBytes,\n\t\t\tlastLinePartial: false,\n\t\t\tfirstLineExceedsLimit: false,\n\t\t\tmaxLines,\n\t\t\tmaxBytes,\n\t\t};\n\t}\n\n\t// Check if first line alone exceeds byte limit\n\tconst firstLineBytes = Buffer.byteLength(lines[0], \"utf-8\");\n\tif (firstLineBytes > maxBytes) {\n\t\treturn {\n\t\t\tcontent: \"\",\n\t\t\ttruncated: true,\n\t\t\ttruncatedBy: \"bytes\",\n\t\t\ttotalLines,\n\t\t\ttotalBytes,\n\t\t\toutputLines: 0,\n\t\t\toutputBytes: 0,\n\t\t\tlastLinePartial: false,\n\t\t\tfirstLineExceedsLimit: true,\n\t\t\tmaxLines,\n\t\t\tmaxBytes,\n\t\t};\n\t}\n\n\t// Collect complete lines that fit\n\tconst outputLinesArr: string[] = [];\n\tlet outputBytesCount = 0;\n\tlet truncatedBy: \"lines\" | \"bytes\" = \"lines\";\n\n\tfor (let i = 0; i < lines.length && i < maxLines; i++) {\n\t\tconst line = lines[i];\n\t\tconst lineBytes = Buffer.byteLength(line, \"utf-8\") + (i > 0 ? 1 : 0); // +1 for newline\n\n\t\tif (outputBytesCount + lineBytes > maxBytes) {\n\t\t\ttruncatedBy = \"bytes\";\n\t\t\tbreak;\n\t\t}\n\n\t\toutputLinesArr.push(line);\n\t\toutputBytesCount += lineBytes;\n\t}\n\n\t// If we exited due to line limit\n\tif (outputLinesArr.length >= maxLines && outputBytesCount <= maxBytes) {\n\t\ttruncatedBy = \"lines\";\n\t}\n\n\tconst outputContent = outputLinesArr.join(\"\\n\");\n\tconst finalOutputBytes = Buffer.byteLength(outputContent, \"utf-8\");\n\n\treturn {\n\t\tcontent: outputContent,\n\t\ttruncated: true,\n\t\ttruncatedBy,\n\t\ttotalLines,\n\t\ttotalBytes,\n\t\toutputLines: outputLinesArr.length,\n\t\toutputBytes: finalOutputBytes,\n\t\tlastLinePartial: false,\n\t\tfirstLineExceedsLimit: false,\n\t\tmaxLines,\n\t\tmaxBytes,\n\t};\n}\n\n/**\n * Truncate content from the tail (keep last N lines/bytes).\n * Suitable for bash output where you want to see the end (errors, final results).\n *\n * May return partial first line if the last line of original content exceeds byte limit.\n */\nexport function truncateTail(content: string, options: TruncationOptions = {}): TruncationResult {\n\tconst maxLines = options.maxLines ?? DEFAULT_MAX_LINES;\n\tconst maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;\n\n\tconst totalBytes = Buffer.byteLength(content, \"utf-8\");\n\tconst lines = splitLinesForCounting(content);\n\tconst totalLines = lines.length;\n\n\t// Check if no truncation needed\n\tif (totalLines <= maxLines && totalBytes <= maxBytes) {\n\t\treturn {\n\t\t\tcontent,\n\t\t\ttruncated: false,\n\t\t\ttruncatedBy: null,\n\t\t\ttotalLines,\n\t\t\ttotalBytes,\n\t\t\toutputLines: totalLines,\n\t\t\toutputBytes: totalBytes,\n\t\t\tlastLinePartial: false,\n\t\t\tfirstLineExceedsLimit: false,\n\t\t\tmaxLines,\n\t\t\tmaxBytes,\n\t\t};\n\t}\n\n\t// Work backwards from the end\n\tconst outputLinesArr: string[] = [];\n\tlet outputBytesCount = 0;\n\tlet truncatedBy: \"lines\" | \"bytes\" = \"lines\";\n\tlet lastLinePartial = false;\n\n\tfor (let i = lines.length - 1; i >= 0 && outputLinesArr.length < maxLines; i--) {\n\t\tconst line = lines[i];\n\t\tconst lineBytes = Buffer.byteLength(line, \"utf-8\") + (outputLinesArr.length > 0 ? 1 : 0); // +1 for newline\n\n\t\tif (outputBytesCount + lineBytes > maxBytes) {\n\t\t\ttruncatedBy = \"bytes\";\n\t\t\t// Edge case: if we haven't added ANY lines yet and this line exceeds maxBytes,\n\t\t\t// take the end of the line (partial)\n\t\t\tif (outputLinesArr.length === 0) {\n\t\t\t\tconst truncatedLine = truncateStringToBytesFromEnd(line, maxBytes);\n\t\t\t\toutputLinesArr.unshift(truncatedLine);\n\t\t\t\toutputBytesCount = Buffer.byteLength(truncatedLine, \"utf-8\");\n\t\t\t\tlastLinePartial = true;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\toutputLinesArr.unshift(line);\n\t\toutputBytesCount += lineBytes;\n\t}\n\n\t// If we exited due to line limit\n\tif (outputLinesArr.length >= maxLines && outputBytesCount <= maxBytes) {\n\t\ttruncatedBy = \"lines\";\n\t}\n\n\tconst outputContent = outputLinesArr.join(\"\\n\");\n\tconst finalOutputBytes = Buffer.byteLength(outputContent, \"utf-8\");\n\n\treturn {\n\t\tcontent: outputContent,\n\t\ttruncated: true,\n\t\ttruncatedBy,\n\t\ttotalLines,\n\t\ttotalBytes,\n\t\toutputLines: outputLinesArr.length,\n\t\toutputBytes: finalOutputBytes,\n\t\tlastLinePartial,\n\t\tfirstLineExceedsLimit: false,\n\t\tmaxLines,\n\t\tmaxBytes,\n\t};\n}\n\n/**\n * Truncate a string to fit within a byte limit (from the end).\n * Handles multi-byte UTF-8 characters correctly.\n */\nfunction truncateStringToBytesFromEnd(str: string, maxBytes: number): string {\n\tconst buf = Buffer.from(str, \"utf-8\");\n\tif (buf.length <= maxBytes) {\n\t\treturn str;\n\t}\n\n\t// Start from the end, skip maxBytes back\n\tlet start = buf.length - maxBytes;\n\n\t// Find a valid UTF-8 boundary (start of a character)\n\twhile (start < buf.length && (buf[start] & 0xc0) === 0x80) {\n\t\tstart++;\n\t}\n\n\treturn buf.slice(start).toString(\"utf-8\");\n}\n\n/**\n * Truncate a single line to max characters, adding [truncated] suffix.\n * Used for grep match lines.\n */\nexport function truncateLine(line: string, maxChars: number = GREP_MAX_LINE_LENGTH): LineTruncationResult {\n\tif (line.length <= maxChars) {\n\t\treturn { text: line, wasTruncated: false };\n\t}\n\treturn { text: `${line.slice(0, maxChars)}... [truncated]`, wasTruncated: true };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"websearch.d.ts","sourceRoot":"","sources":["../../../src/core/tools/websearch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAE5D,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,wBAAwB,CAAC;AAatF,MAAM,MAAM,iBAAiB,GAC1B,YAAY,GACZ,2BAA2B,GAC3B,OAAO,GACP,cAAc,GACd,WAAW,GACX,kBAAkB,CAAC;AAEtB,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,QAAA,MAAM,eAAe;;;EAKnB,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,eAAe,CAAC,CAAC;AAEhE,MAAM,MAAM,eAAe,GAAG,2BAA2B,GAAG,cAAc,GAAG,kBAAkB,CAAC;AAEhG,MAAM,WAAW,mBAAmB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,MAAM,EAAE,eAAe,CAAC;CACxB;AAoCD,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,oBAAoB,GAAG,SAAS,CA2B1F;AAmDD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,mBAAmB,EAAE,CAoB3F;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,mBAAmB,EAAE,CAqB5F;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,mBAAmB,EAAE,CAsBhG;AAoKD,wBAAgB,6BAA6B,CAC5C,OAAO,CAAC,EAAE,oBAAoB,GAC5B,cAAc,CAAC,OAAO,eAAe,EAAE,oBAAoB,CAAC,CAiD9D;AAED,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC,OAAO,eAAe,CAAC,CAErG","sourcesContent":["import type { AgentTool } from \"@greppleai/grip-agent-core\";\nimport { Text } from \"@greppleai/grip-tui\";\nimport { type Static, Type } from \"typebox\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport { getTextOutput, invalidArgText, str, type ToolTextOutputContent } from \"./render-utils.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\ninterface RenderTheme {\n\tbold(value: string): string;\n\tfg(role: string, value: string): string;\n}\n\nconst DEFAULT_LIMIT = 8;\nconst MAX_LIMIT = 20;\nconst REQUEST_TIMEOUT_MS = 10_000;\n\nexport type WebsearchProvider =\n\t| \"duckduckgo\"\n\t| \"duckduckgo-instant-answer\"\n\t| \"brave\"\n\t| \"brave-search\"\n\t| \"firecrawl\"\n\t| \"firecrawl-search\";\n\nexport interface WebsearchToolOptions {\n\tprovider?: WebsearchProvider;\n\tapiKey?: string;\n\tbaseUrl?: string;\n}\n\nconst websearchSchema = Type.Object({\n\tquery: Type.String({ description: \"Search query\" }),\n\tlimit: Type.Optional(\n\t\tType.Number({ description: `Maximum number of links to return (default ${DEFAULT_LIMIT}, max ${MAX_LIMIT})` }),\n\t),\n});\n\nexport type WebsearchToolInput = Static<typeof websearchSchema>;\n\nexport type WebsearchSource = \"duckduckgo-instant-answer\" | \"brave-search\" | \"firecrawl-search\";\n\nexport interface WebsearchResultItem {\n\ttitle: string;\n\turl: string;\n\tsnippet?: string;\n}\n\nexport interface WebsearchToolDetails {\n\tquery: string;\n\tresults: WebsearchResultItem[];\n\tsource: WebsearchSource;\n}\n\ninterface WebsearchCallArguments {\n\tquery?: string;\n\tlimit?: number;\n}\n\ninterface WebsearchRenderResult {\n\tcontent: ToolTextOutputContent[];\n\tdetails?: WebsearchToolDetails;\n}\n\ninterface DuckDuckGoTopic {\n\tFirstURL?: unknown;\n\tText?: unknown;\n\tName?: unknown;\n\tTopics?: unknown;\n}\n\ninterface BraveSearchResult {\n\ttitle?: unknown;\n\turl?: unknown;\n\tdescription?: unknown;\n}\n\ninterface FirecrawlSearchResult {\n\ttitle?: unknown;\n\turl?: unknown;\n\tdescription?: unknown;\n\tmarkdown?: unknown;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nexport function parseWebsearchToolOptions(value: unknown): WebsearchToolOptions | undefined {\n\tif (value === undefined) return undefined;\n\tif (!isRecord(value)) throw new Error(\"tools.websearch must be an object\");\n\tconst options: WebsearchToolOptions = {};\n\n\tconst provider = asString(value.provider);\n\tif (provider !== undefined) {\n\t\tif (\n\t\t\tprovider !== \"duckduckgo\" &&\n\t\t\tprovider !== \"duckduckgo-instant-answer\" &&\n\t\t\tprovider !== \"brave\" &&\n\t\t\tprovider !== \"brave-search\" &&\n\t\t\tprovider !== \"firecrawl\" &&\n\t\t\tprovider !== \"firecrawl-search\"\n\t\t) {\n\t\t\tthrow new Error(`Invalid tools.websearch.provider: ${provider}`);\n\t\t}\n\t\toptions.provider = provider;\n\t}\n\n\tconst apiKey = asString(value.apiKey);\n\tif (apiKey !== undefined) options.apiKey = apiKey;\n\n\tconst baseUrl = asString(value.baseUrl);\n\tif (baseUrl !== undefined) options.baseUrl = baseUrl;\n\n\treturn options;\n}\n\nfunction asString(value: unknown): string | undefined {\n\treturn typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nfunction stripHtml(value: string): string {\n\treturn value\n\t\t.replace(/<[^>]*>/g, \"\")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n}\n\nfunction titleFromText(text: string): string {\n\tconst separator = text.indexOf(\" - \");\n\treturn (separator > 0 ? text.slice(0, separator) : text).trim();\n}\n\nfunction pushResult(results: WebsearchResultItem[], seen: Set<string>, item: WebsearchResultItem): void {\n\tconst url = item.url.trim();\n\tif (!url || seen.has(url)) return;\n\tseen.add(url);\n\tresults.push({ ...item, url });\n}\n\nfunction collectRelatedTopics(value: unknown, results: WebsearchResultItem[], seen: Set<string>, limit: number): void {\n\tif (results.length >= limit) return;\n\tif (!Array.isArray(value)) return;\n\n\tfor (const entry of value) {\n\t\tif (results.length >= limit) return;\n\t\tif (!isRecord(entry)) continue;\n\t\tconst topic = entry as DuckDuckGoTopic;\n\t\tconst nestedTopics = topic.Topics;\n\t\tif (Array.isArray(nestedTopics)) {\n\t\t\tcollectRelatedTopics(nestedTopics, results, seen, limit);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst url = asString(topic.FirstURL);\n\t\tconst rawText = asString(topic.Text) ?? asString(topic.Name);\n\t\tif (!url || !rawText) continue;\n\t\tconst text = stripHtml(rawText);\n\t\tpushResult(results, seen, {\n\t\t\ttitle: titleFromText(text),\n\t\t\turl,\n\t\t\tsnippet: text,\n\t\t});\n\t}\n}\n\nexport function parseDuckDuckGoResponse(data: unknown, limit: number): WebsearchResultItem[] {\n\tconst results: WebsearchResultItem[] = [];\n\tconst seen = new Set<string>();\n\tif (!isRecord(data)) return results;\n\n\tconst heading = asString(data.Heading);\n\tconst abstractUrl = asString(data.AbstractURL);\n\tconst abstractText = asString(data.AbstractText) ?? asString(data.Abstract);\n\tif (abstractUrl && (heading || abstractText)) {\n\t\tpushResult(results, seen, {\n\t\t\ttitle: heading ?? titleFromText(stripHtml(abstractText ?? abstractUrl)),\n\t\t\turl: abstractUrl,\n\t\t\tsnippet: abstractText ? stripHtml(abstractText) : undefined,\n\t\t});\n\t}\n\n\tcollectRelatedTopics(data.RelatedTopics, results, seen, limit);\n\tcollectRelatedTopics(data.Results, results, seen, limit);\n\n\treturn results.slice(0, limit);\n}\n\nexport function parseBraveSearchResponse(data: unknown, limit: number): WebsearchResultItem[] {\n\tconst results: WebsearchResultItem[] = [];\n\tconst seen = new Set<string>();\n\tif (!isRecord(data) || !isRecord(data.web) || !Array.isArray(data.web.results)) return results;\n\n\tfor (const entry of data.web.results) {\n\t\tif (results.length >= limit) break;\n\t\tif (!isRecord(entry)) continue;\n\t\tconst item = entry as BraveSearchResult;\n\t\tconst title = asString(item.title);\n\t\tconst url = asString(item.url);\n\t\tif (!title || !url) continue;\n\t\tconst description = asString(item.description);\n\t\tpushResult(results, seen, {\n\t\t\ttitle: stripHtml(title),\n\t\t\turl,\n\t\t\tsnippet: description ? stripHtml(description) : undefined,\n\t\t});\n\t}\n\n\treturn results;\n}\n\nexport function parseFirecrawlSearchResponse(data: unknown, limit: number): WebsearchResultItem[] {\n\tconst results: WebsearchResultItem[] = [];\n\tconst seen = new Set<string>();\n\tif (!isRecord(data) || !isRecord(data.data) || !Array.isArray(data.data.web)) return results;\n\n\tfor (const entry of data.data.web) {\n\t\tif (results.length >= limit) break;\n\t\tif (!isRecord(entry)) continue;\n\t\tconst item = entry as FirecrawlSearchResult;\n\t\tconst title = asString(item.title);\n\t\tconst url = asString(item.url);\n\t\tif (!title || !url) continue;\n\t\tconst description = asString(item.description);\n\t\tconst markdown = asString(item.markdown);\n\t\tpushResult(results, seen, {\n\t\t\ttitle: stripHtml(title),\n\t\t\turl,\n\t\t\tsnippet: description ? stripHtml(description) : markdown ? stripHtml(markdown).slice(0, 500) : undefined,\n\t\t});\n\t}\n\n\treturn results;\n}\n\nfunction formatSourceName(source: WebsearchSource): string {\n\tswitch (source) {\n\t\tcase \"brave-search\":\n\t\t\treturn \"Brave Search\";\n\t\tcase \"firecrawl-search\":\n\t\t\treturn \"Firecrawl\";\n\t\tcase \"duckduckgo-instant-answer\":\n\t\t\treturn \"DuckDuckGo\";\n\t}\n}\n\nfunction formatResults(query: string, results: WebsearchResultItem[], source: WebsearchSource): string {\n\tif (results.length === 0) {\n\t\treturn `No ${formatSourceName(source)} links found for: ${query}`;\n\t}\n\treturn results\n\t\t.map((result, index) => {\n\t\t\tconst lines = [`${index + 1}. ${result.title}`, ` ${result.url}`];\n\t\t\tif (result.snippet) lines.push(` ${result.snippet}`);\n\t\t\treturn lines.join(\"\\n\");\n\t\t})\n\t\t.join(\"\\n\\n\");\n}\n\nfunction resolveLimit(limit: number | undefined): number {\n\tif (limit === undefined) return DEFAULT_LIMIT;\n\tif (!Number.isFinite(limit) || limit <= 0) return DEFAULT_LIMIT;\n\treturn Math.min(MAX_LIMIT, Math.floor(limit));\n}\n\nfunction formatWebsearchCall(args: WebsearchCallArguments | undefined, theme: RenderTheme): string {\n\tconst query = str(args?.query);\n\tconst invalidArg = invalidArgText(theme);\n\tlet text = `${theme.fg(\"toolTitle\", theme.bold(\"websearch\"))} ${query === null ? invalidArg : theme.fg(\"accent\", query)}`;\n\tif (args?.limit !== undefined) text += theme.fg(\"toolOutput\", ` (limit ${args.limit})`);\n\treturn text;\n}\n\nfunction formatWebsearchResult(\n\tresult: WebsearchRenderResult,\n\toptions: ToolRenderResultOptions,\n\ttheme: RenderTheme,\n\tshowImages: boolean,\n): string {\n\tconst output = getTextOutput(result, showImages).trim();\n\tif (!output) return \"\";\n\tconst lines = output.split(\"\\n\");\n\tconst maxLines = options.expanded ? lines.length : 24;\n\tconst displayed = lines.slice(0, maxLines).map((line) => theme.fg(\"toolOutput\", line));\n\tconst remaining = lines.length - maxLines;\n\treturn remaining > 0\n\t\t? `${displayed.join(\"\\n\")}\\n${theme.fg(\"muted\", `... (${remaining} more lines)`)}`\n\t\t: displayed.join(\"\\n\");\n}\nfunction resolveWebsearchProvider(options?: WebsearchToolOptions): WebsearchSource {\n\tconst configured =\n\t\toptions?.provider?.trim().toLowerCase() ?? process.env.GRIP_WEBSEARCH_PROVIDER?.trim().toLowerCase();\n\tif (!configured) {\n\t\tif (process.env.GRIP_WEBSEARCH_FIRECRAWL_API_KEY || process.env.FIRECRAWL_API_KEY) return \"firecrawl-search\";\n\t\tif (options?.apiKey || process.env.GRIP_WEBSEARCH_BRAVE_API_KEY || process.env.BRAVE_SEARCH_API_KEY)\n\t\t\treturn \"brave-search\";\n\t}\n\tif (!configured || configured === \"duckduckgo\" || configured === \"duckduckgo-instant-answer\") {\n\t\treturn \"duckduckgo-instant-answer\";\n\t}\n\tif (configured === \"brave\" || configured === \"brave-search\") return \"brave-search\";\n\tif (configured === \"firecrawl\" || configured === \"firecrawl-search\") return \"firecrawl-search\";\n\tthrow new Error(`Unsupported websearch provider: ${configured}`);\n}\n\nfunction resolveBraveApiKey(options?: WebsearchToolOptions): string {\n\tconst key = options?.apiKey ?? process.env.GRIP_WEBSEARCH_BRAVE_API_KEY ?? process.env.BRAVE_SEARCH_API_KEY;\n\tif (!key?.trim()) {\n\t\tthrow new Error(\n\t\t\t\"Brave websearch requires tools.websearch.apiKey, GRIP_WEBSEARCH_BRAVE_API_KEY, or BRAVE_SEARCH_API_KEY\",\n\t\t);\n\t}\n\treturn key.trim();\n}\n\nfunction resolveFirecrawlApiKey(options?: WebsearchToolOptions): string {\n\tconst key = options?.apiKey ?? process.env.GRIP_WEBSEARCH_FIRECRAWL_API_KEY ?? process.env.FIRECRAWL_API_KEY;\n\tif (!key?.trim()) {\n\t\tthrow new Error(\n\t\t\t\"Firecrawl websearch requires tools.websearch.apiKey, GRIP_WEBSEARCH_FIRECRAWL_API_KEY, or FIRECRAWL_API_KEY\",\n\t\t);\n\t}\n\treturn key.trim();\n}\n\nasync function fetchDuckDuckGoResults(\n\tquery: string,\n\tlimit: number,\n\tsignal: AbortSignal,\n): Promise<WebsearchResultItem[]> {\n\tconst url = new URL(\"https://api.duckduckgo.com/\");\n\turl.searchParams.set(\"q\", query);\n\turl.searchParams.set(\"format\", \"json\");\n\turl.searchParams.set(\"no_html\", \"1\");\n\turl.searchParams.set(\"skip_disambig\", \"1\");\n\n\tconst response = await fetch(url, {\n\t\theaders: { accept: \"application/json\", \"user-agent\": \"grip-coding-agent\" },\n\t\tsignal,\n\t});\n\tif (!response.ok) {\n\t\tthrow new Error(`DuckDuckGo request failed: ${response.status} ${response.statusText}`);\n\t}\n\treturn parseDuckDuckGoResponse((await response.json()) as unknown, limit);\n}\n\nasync function fetchBraveResults(\n\tquery: string,\n\tlimit: number,\n\tsignal: AbortSignal,\n\toptions?: WebsearchToolOptions,\n): Promise<WebsearchResultItem[]> {\n\tconst url = new URL(\n\t\toptions?.baseUrl ?? process.env.GRIP_WEBSEARCH_BRAVE_BASE_URL ?? \"https://api.search.brave.com/res/v1/web/search\",\n\t);\n\turl.searchParams.set(\"q\", query);\n\turl.searchParams.set(\"count\", String(limit));\n\n\tconst response = await fetch(url, {\n\t\theaders: {\n\t\t\taccept: \"application/json\",\n\t\t\t\"user-agent\": \"grip-coding-agent\",\n\t\t\t\"x-subscription-token\": resolveBraveApiKey(options),\n\t\t},\n\t\tsignal,\n\t});\n\tif (!response.ok) {\n\t\tthrow new Error(`Brave Search request failed: ${response.status} ${response.statusText}`);\n\t}\n\treturn parseBraveSearchResponse((await response.json()) as unknown, limit);\n}\n\nasync function fetchFirecrawlResults(\n\tquery: string,\n\tlimit: number,\n\tsignal: AbortSignal,\n\toptions?: WebsearchToolOptions,\n): Promise<WebsearchResultItem[]> {\n\tconst url = new URL(\n\t\toptions?.baseUrl ?? process.env.GRIP_WEBSEARCH_FIRECRAWL_BASE_URL ?? \"https://api.firecrawl.dev/v2/search\",\n\t);\n\tconst response = await fetch(url, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\taccept: \"application/json\",\n\t\t\t\"content-type\": \"application/json\",\n\t\t\t\"user-agent\": \"grip-coding-agent\",\n\t\t\tauthorization: `Bearer ${resolveFirecrawlApiKey(options)}`,\n\t\t},\n\t\tbody: JSON.stringify({ query, limit, sources: [{ type: \"web\" }] }),\n\t\tsignal,\n\t});\n\tif (!response.ok) {\n\t\tthrow new Error(`Firecrawl Search request failed: ${response.status} ${response.statusText}`);\n\t}\n\treturn parseFirecrawlSearchResponse((await response.json()) as unknown, limit);\n}\nexport function createWebsearchToolDefinition(\n\toptions?: WebsearchToolOptions,\n): ToolDefinition<typeof websearchSchema, WebsearchToolDetails> {\n\treturn {\n\t\tname: \"websearch\",\n\t\tlabel: \"websearch\",\n\t\tdescription:\n\t\t\t\"Search the web for relevant links using DuckDuckGo by default, or Brave Search/Firecrawl when configured. Returns titles, URLs, and snippets when available.\",\n\t\tpromptSnippet: \"Search the web for relevant links\",\n\t\tparameters: websearchSchema,\n\t\tasync execute(_toolCallId, { query, limit }: WebsearchToolInput, signal?: AbortSignal) {\n\t\t\tconst trimmedQuery = query.trim();\n\t\t\tif (!trimmedQuery) throw new Error(\"query is required\");\n\n\t\t\tconst effectiveLimit = resolveLimit(limit);\n\t\t\tconst controller = new AbortController();\n\t\t\tconst timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n\t\t\tconst onAbort = () => controller.abort();\n\t\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\ttry {\n\t\t\t\tconst source = resolveWebsearchProvider(options);\n\t\t\t\tconst results = await (async () => {\n\t\t\t\t\tswitch (source) {\n\t\t\t\t\t\tcase \"brave-search\":\n\t\t\t\t\t\t\treturn fetchBraveResults(trimmedQuery, effectiveLimit, controller.signal, options);\n\t\t\t\t\t\tcase \"firecrawl-search\":\n\t\t\t\t\t\t\treturn fetchFirecrawlResults(trimmedQuery, effectiveLimit, controller.signal, options);\n\t\t\t\t\t\tcase \"duckduckgo-instant-answer\":\n\t\t\t\t\t\t\treturn fetchDuckDuckGoResults(trimmedQuery, effectiveLimit, controller.signal);\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: formatResults(trimmedQuery, results, source) }],\n\t\t\t\t\tdetails: { query: trimmedQuery, results, source },\n\t\t\t\t};\n\t\t\t} finally {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t}\n\t\t},\n\t\trenderCall(args, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatWebsearchCall(args as WebsearchCallArguments | undefined, theme));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatWebsearchResult(result as WebsearchRenderResult, options, theme, context.showImages));\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createWebsearchTool(options?: WebsearchToolOptions): AgentTool<typeof websearchSchema> {\n\treturn wrapToolDefinition(createWebsearchToolDefinition(options));\n}\n"]}
1
+ {"version":3,"file":"websearch.d.ts","sourceRoot":"","sources":["../../../src/core/tools/websearch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAE5D,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,wBAAwB,CAAC;AAatF,MAAM,MAAM,iBAAiB,GAC1B,YAAY,GACZ,2BAA2B,GAC3B,OAAO,GACP,cAAc,GACd,WAAW,GACX,kBAAkB,CAAC;AAEtB,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,QAAA,MAAM,eAAe;;;EAKnB,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,eAAe,CAAC,CAAC;AAEhE,MAAM,MAAM,eAAe,GAAG,2BAA2B,GAAG,cAAc,GAAG,kBAAkB,CAAC;AAEhG,MAAM,WAAW,mBAAmB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,MAAM,EAAE,eAAe,CAAC;CACxB;AAoCD,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,oBAAoB,GAAG,SAAS,CA2B1F;AAmDD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,mBAAmB,EAAE,CAoB3F;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,mBAAmB,EAAE,CAqB5F;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,mBAAmB,EAAE,CAsBhG;AAoKD,wBAAgB,6BAA6B,CAC5C,OAAO,CAAC,EAAE,oBAAoB,GAC5B,cAAc,CAAC,OAAO,eAAe,EAAE,oBAAoB,CAAC,CAiD9D;AAED,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC,OAAO,eAAe,CAAC,CAErG"}
@@ -1 +1 @@
1
- {"version":3,"file":"websearch.js","sourceRoot":"","sources":["../../../src/core/tools/websearch.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@greppleai/grip-agent-core\";\nimport { Text } from \"@greppleai/grip-tui\";\nimport { type Static, Type } from \"typebox\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport { getTextOutput, invalidArgText, str, type ToolTextOutputContent } from \"./render-utils.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\ninterface RenderTheme {\n\tbold(value: string): string;\n\tfg(role: string, value: string): string;\n}\n\nconst DEFAULT_LIMIT = 8;\nconst MAX_LIMIT = 20;\nconst REQUEST_TIMEOUT_MS = 10_000;\n\nexport type WebsearchProvider =\n\t| \"duckduckgo\"\n\t| \"duckduckgo-instant-answer\"\n\t| \"brave\"\n\t| \"brave-search\"\n\t| \"firecrawl\"\n\t| \"firecrawl-search\";\n\nexport interface WebsearchToolOptions {\n\tprovider?: WebsearchProvider;\n\tapiKey?: string;\n\tbaseUrl?: string;\n}\n\nconst websearchSchema = Type.Object({\n\tquery: Type.String({ description: \"Search query\" }),\n\tlimit: Type.Optional(\n\t\tType.Number({ description: `Maximum number of links to return (default ${DEFAULT_LIMIT}, max ${MAX_LIMIT})` }),\n\t),\n});\n\nexport type WebsearchToolInput = Static<typeof websearchSchema>;\n\nexport type WebsearchSource = \"duckduckgo-instant-answer\" | \"brave-search\" | \"firecrawl-search\";\n\nexport interface WebsearchResultItem {\n\ttitle: string;\n\turl: string;\n\tsnippet?: string;\n}\n\nexport interface WebsearchToolDetails {\n\tquery: string;\n\tresults: WebsearchResultItem[];\n\tsource: WebsearchSource;\n}\n\ninterface WebsearchCallArguments {\n\tquery?: string;\n\tlimit?: number;\n}\n\ninterface WebsearchRenderResult {\n\tcontent: ToolTextOutputContent[];\n\tdetails?: WebsearchToolDetails;\n}\n\ninterface DuckDuckGoTopic {\n\tFirstURL?: unknown;\n\tText?: unknown;\n\tName?: unknown;\n\tTopics?: unknown;\n}\n\ninterface BraveSearchResult {\n\ttitle?: unknown;\n\turl?: unknown;\n\tdescription?: unknown;\n}\n\ninterface FirecrawlSearchResult {\n\ttitle?: unknown;\n\turl?: unknown;\n\tdescription?: unknown;\n\tmarkdown?: unknown;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nexport function parseWebsearchToolOptions(value: unknown): WebsearchToolOptions | undefined {\n\tif (value === undefined) return undefined;\n\tif (!isRecord(value)) throw new Error(\"tools.websearch must be an object\");\n\tconst options: WebsearchToolOptions = {};\n\n\tconst provider = asString(value.provider);\n\tif (provider !== undefined) {\n\t\tif (\n\t\t\tprovider !== \"duckduckgo\" &&\n\t\t\tprovider !== \"duckduckgo-instant-answer\" &&\n\t\t\tprovider !== \"brave\" &&\n\t\t\tprovider !== \"brave-search\" &&\n\t\t\tprovider !== \"firecrawl\" &&\n\t\t\tprovider !== \"firecrawl-search\"\n\t\t) {\n\t\t\tthrow new Error(`Invalid tools.websearch.provider: ${provider}`);\n\t\t}\n\t\toptions.provider = provider;\n\t}\n\n\tconst apiKey = asString(value.apiKey);\n\tif (apiKey !== undefined) options.apiKey = apiKey;\n\n\tconst baseUrl = asString(value.baseUrl);\n\tif (baseUrl !== undefined) options.baseUrl = baseUrl;\n\n\treturn options;\n}\n\nfunction asString(value: unknown): string | undefined {\n\treturn typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nfunction stripHtml(value: string): string {\n\treturn value\n\t\t.replace(/<[^>]*>/g, \"\")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n}\n\nfunction titleFromText(text: string): string {\n\tconst separator = text.indexOf(\" - \");\n\treturn (separator > 0 ? text.slice(0, separator) : text).trim();\n}\n\nfunction pushResult(results: WebsearchResultItem[], seen: Set<string>, item: WebsearchResultItem): void {\n\tconst url = item.url.trim();\n\tif (!url || seen.has(url)) return;\n\tseen.add(url);\n\tresults.push({ ...item, url });\n}\n\nfunction collectRelatedTopics(value: unknown, results: WebsearchResultItem[], seen: Set<string>, limit: number): void {\n\tif (results.length >= limit) return;\n\tif (!Array.isArray(value)) return;\n\n\tfor (const entry of value) {\n\t\tif (results.length >= limit) return;\n\t\tif (!isRecord(entry)) continue;\n\t\tconst topic = entry as DuckDuckGoTopic;\n\t\tconst nestedTopics = topic.Topics;\n\t\tif (Array.isArray(nestedTopics)) {\n\t\t\tcollectRelatedTopics(nestedTopics, results, seen, limit);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst url = asString(topic.FirstURL);\n\t\tconst rawText = asString(topic.Text) ?? asString(topic.Name);\n\t\tif (!url || !rawText) continue;\n\t\tconst text = stripHtml(rawText);\n\t\tpushResult(results, seen, {\n\t\t\ttitle: titleFromText(text),\n\t\t\turl,\n\t\t\tsnippet: text,\n\t\t});\n\t}\n}\n\nexport function parseDuckDuckGoResponse(data: unknown, limit: number): WebsearchResultItem[] {\n\tconst results: WebsearchResultItem[] = [];\n\tconst seen = new Set<string>();\n\tif (!isRecord(data)) return results;\n\n\tconst heading = asString(data.Heading);\n\tconst abstractUrl = asString(data.AbstractURL);\n\tconst abstractText = asString(data.AbstractText) ?? asString(data.Abstract);\n\tif (abstractUrl && (heading || abstractText)) {\n\t\tpushResult(results, seen, {\n\t\t\ttitle: heading ?? titleFromText(stripHtml(abstractText ?? abstractUrl)),\n\t\t\turl: abstractUrl,\n\t\t\tsnippet: abstractText ? stripHtml(abstractText) : undefined,\n\t\t});\n\t}\n\n\tcollectRelatedTopics(data.RelatedTopics, results, seen, limit);\n\tcollectRelatedTopics(data.Results, results, seen, limit);\n\n\treturn results.slice(0, limit);\n}\n\nexport function parseBraveSearchResponse(data: unknown, limit: number): WebsearchResultItem[] {\n\tconst results: WebsearchResultItem[] = [];\n\tconst seen = new Set<string>();\n\tif (!isRecord(data) || !isRecord(data.web) || !Array.isArray(data.web.results)) return results;\n\n\tfor (const entry of data.web.results) {\n\t\tif (results.length >= limit) break;\n\t\tif (!isRecord(entry)) continue;\n\t\tconst item = entry as BraveSearchResult;\n\t\tconst title = asString(item.title);\n\t\tconst url = asString(item.url);\n\t\tif (!title || !url) continue;\n\t\tconst description = asString(item.description);\n\t\tpushResult(results, seen, {\n\t\t\ttitle: stripHtml(title),\n\t\t\turl,\n\t\t\tsnippet: description ? stripHtml(description) : undefined,\n\t\t});\n\t}\n\n\treturn results;\n}\n\nexport function parseFirecrawlSearchResponse(data: unknown, limit: number): WebsearchResultItem[] {\n\tconst results: WebsearchResultItem[] = [];\n\tconst seen = new Set<string>();\n\tif (!isRecord(data) || !isRecord(data.data) || !Array.isArray(data.data.web)) return results;\n\n\tfor (const entry of data.data.web) {\n\t\tif (results.length >= limit) break;\n\t\tif (!isRecord(entry)) continue;\n\t\tconst item = entry as FirecrawlSearchResult;\n\t\tconst title = asString(item.title);\n\t\tconst url = asString(item.url);\n\t\tif (!title || !url) continue;\n\t\tconst description = asString(item.description);\n\t\tconst markdown = asString(item.markdown);\n\t\tpushResult(results, seen, {\n\t\t\ttitle: stripHtml(title),\n\t\t\turl,\n\t\t\tsnippet: description ? stripHtml(description) : markdown ? stripHtml(markdown).slice(0, 500) : undefined,\n\t\t});\n\t}\n\n\treturn results;\n}\n\nfunction formatSourceName(source: WebsearchSource): string {\n\tswitch (source) {\n\t\tcase \"brave-search\":\n\t\t\treturn \"Brave Search\";\n\t\tcase \"firecrawl-search\":\n\t\t\treturn \"Firecrawl\";\n\t\tcase \"duckduckgo-instant-answer\":\n\t\t\treturn \"DuckDuckGo\";\n\t}\n}\n\nfunction formatResults(query: string, results: WebsearchResultItem[], source: WebsearchSource): string {\n\tif (results.length === 0) {\n\t\treturn `No ${formatSourceName(source)} links found for: ${query}`;\n\t}\n\treturn results\n\t\t.map((result, index) => {\n\t\t\tconst lines = [`${index + 1}. ${result.title}`, ` ${result.url}`];\n\t\t\tif (result.snippet) lines.push(` ${result.snippet}`);\n\t\t\treturn lines.join(\"\\n\");\n\t\t})\n\t\t.join(\"\\n\\n\");\n}\n\nfunction resolveLimit(limit: number | undefined): number {\n\tif (limit === undefined) return DEFAULT_LIMIT;\n\tif (!Number.isFinite(limit) || limit <= 0) return DEFAULT_LIMIT;\n\treturn Math.min(MAX_LIMIT, Math.floor(limit));\n}\n\nfunction formatWebsearchCall(args: WebsearchCallArguments | undefined, theme: RenderTheme): string {\n\tconst query = str(args?.query);\n\tconst invalidArg = invalidArgText(theme);\n\tlet text = `${theme.fg(\"toolTitle\", theme.bold(\"websearch\"))} ${query === null ? invalidArg : theme.fg(\"accent\", query)}`;\n\tif (args?.limit !== undefined) text += theme.fg(\"toolOutput\", ` (limit ${args.limit})`);\n\treturn text;\n}\n\nfunction formatWebsearchResult(\n\tresult: WebsearchRenderResult,\n\toptions: ToolRenderResultOptions,\n\ttheme: RenderTheme,\n\tshowImages: boolean,\n): string {\n\tconst output = getTextOutput(result, showImages).trim();\n\tif (!output) return \"\";\n\tconst lines = output.split(\"\\n\");\n\tconst maxLines = options.expanded ? lines.length : 24;\n\tconst displayed = lines.slice(0, maxLines).map((line) => theme.fg(\"toolOutput\", line));\n\tconst remaining = lines.length - maxLines;\n\treturn remaining > 0\n\t\t? `${displayed.join(\"\\n\")}\\n${theme.fg(\"muted\", `... (${remaining} more lines)`)}`\n\t\t: displayed.join(\"\\n\");\n}\nfunction resolveWebsearchProvider(options?: WebsearchToolOptions): WebsearchSource {\n\tconst configured =\n\t\toptions?.provider?.trim().toLowerCase() ?? process.env.GRIP_WEBSEARCH_PROVIDER?.trim().toLowerCase();\n\tif (!configured) {\n\t\tif (process.env.GRIP_WEBSEARCH_FIRECRAWL_API_KEY || process.env.FIRECRAWL_API_KEY) return \"firecrawl-search\";\n\t\tif (options?.apiKey || process.env.GRIP_WEBSEARCH_BRAVE_API_KEY || process.env.BRAVE_SEARCH_API_KEY)\n\t\t\treturn \"brave-search\";\n\t}\n\tif (!configured || configured === \"duckduckgo\" || configured === \"duckduckgo-instant-answer\") {\n\t\treturn \"duckduckgo-instant-answer\";\n\t}\n\tif (configured === \"brave\" || configured === \"brave-search\") return \"brave-search\";\n\tif (configured === \"firecrawl\" || configured === \"firecrawl-search\") return \"firecrawl-search\";\n\tthrow new Error(`Unsupported websearch provider: ${configured}`);\n}\n\nfunction resolveBraveApiKey(options?: WebsearchToolOptions): string {\n\tconst key = options?.apiKey ?? process.env.GRIP_WEBSEARCH_BRAVE_API_KEY ?? process.env.BRAVE_SEARCH_API_KEY;\n\tif (!key?.trim()) {\n\t\tthrow new Error(\n\t\t\t\"Brave websearch requires tools.websearch.apiKey, GRIP_WEBSEARCH_BRAVE_API_KEY, or BRAVE_SEARCH_API_KEY\",\n\t\t);\n\t}\n\treturn key.trim();\n}\n\nfunction resolveFirecrawlApiKey(options?: WebsearchToolOptions): string {\n\tconst key = options?.apiKey ?? process.env.GRIP_WEBSEARCH_FIRECRAWL_API_KEY ?? process.env.FIRECRAWL_API_KEY;\n\tif (!key?.trim()) {\n\t\tthrow new Error(\n\t\t\t\"Firecrawl websearch requires tools.websearch.apiKey, GRIP_WEBSEARCH_FIRECRAWL_API_KEY, or FIRECRAWL_API_KEY\",\n\t\t);\n\t}\n\treturn key.trim();\n}\n\nasync function fetchDuckDuckGoResults(\n\tquery: string,\n\tlimit: number,\n\tsignal: AbortSignal,\n): Promise<WebsearchResultItem[]> {\n\tconst url = new URL(\"https://api.duckduckgo.com/\");\n\turl.searchParams.set(\"q\", query);\n\turl.searchParams.set(\"format\", \"json\");\n\turl.searchParams.set(\"no_html\", \"1\");\n\turl.searchParams.set(\"skip_disambig\", \"1\");\n\n\tconst response = await fetch(url, {\n\t\theaders: { accept: \"application/json\", \"user-agent\": \"grip-coding-agent\" },\n\t\tsignal,\n\t});\n\tif (!response.ok) {\n\t\tthrow new Error(`DuckDuckGo request failed: ${response.status} ${response.statusText}`);\n\t}\n\treturn parseDuckDuckGoResponse((await response.json()) as unknown, limit);\n}\n\nasync function fetchBraveResults(\n\tquery: string,\n\tlimit: number,\n\tsignal: AbortSignal,\n\toptions?: WebsearchToolOptions,\n): Promise<WebsearchResultItem[]> {\n\tconst url = new URL(\n\t\toptions?.baseUrl ?? process.env.GRIP_WEBSEARCH_BRAVE_BASE_URL ?? \"https://api.search.brave.com/res/v1/web/search\",\n\t);\n\turl.searchParams.set(\"q\", query);\n\turl.searchParams.set(\"count\", String(limit));\n\n\tconst response = await fetch(url, {\n\t\theaders: {\n\t\t\taccept: \"application/json\",\n\t\t\t\"user-agent\": \"grip-coding-agent\",\n\t\t\t\"x-subscription-token\": resolveBraveApiKey(options),\n\t\t},\n\t\tsignal,\n\t});\n\tif (!response.ok) {\n\t\tthrow new Error(`Brave Search request failed: ${response.status} ${response.statusText}`);\n\t}\n\treturn parseBraveSearchResponse((await response.json()) as unknown, limit);\n}\n\nasync function fetchFirecrawlResults(\n\tquery: string,\n\tlimit: number,\n\tsignal: AbortSignal,\n\toptions?: WebsearchToolOptions,\n): Promise<WebsearchResultItem[]> {\n\tconst url = new URL(\n\t\toptions?.baseUrl ?? process.env.GRIP_WEBSEARCH_FIRECRAWL_BASE_URL ?? \"https://api.firecrawl.dev/v2/search\",\n\t);\n\tconst response = await fetch(url, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\taccept: \"application/json\",\n\t\t\t\"content-type\": \"application/json\",\n\t\t\t\"user-agent\": \"grip-coding-agent\",\n\t\t\tauthorization: `Bearer ${resolveFirecrawlApiKey(options)}`,\n\t\t},\n\t\tbody: JSON.stringify({ query, limit, sources: [{ type: \"web\" }] }),\n\t\tsignal,\n\t});\n\tif (!response.ok) {\n\t\tthrow new Error(`Firecrawl Search request failed: ${response.status} ${response.statusText}`);\n\t}\n\treturn parseFirecrawlSearchResponse((await response.json()) as unknown, limit);\n}\nexport function createWebsearchToolDefinition(\n\toptions?: WebsearchToolOptions,\n): ToolDefinition<typeof websearchSchema, WebsearchToolDetails> {\n\treturn {\n\t\tname: \"websearch\",\n\t\tlabel: \"websearch\",\n\t\tdescription:\n\t\t\t\"Search the web for relevant links using DuckDuckGo by default, or Brave Search/Firecrawl when configured. Returns titles, URLs, and snippets when available.\",\n\t\tpromptSnippet: \"Search the web for relevant links\",\n\t\tparameters: websearchSchema,\n\t\tasync execute(_toolCallId, { query, limit }: WebsearchToolInput, signal?: AbortSignal) {\n\t\t\tconst trimmedQuery = query.trim();\n\t\t\tif (!trimmedQuery) throw new Error(\"query is required\");\n\n\t\t\tconst effectiveLimit = resolveLimit(limit);\n\t\t\tconst controller = new AbortController();\n\t\t\tconst timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n\t\t\tconst onAbort = () => controller.abort();\n\t\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\ttry {\n\t\t\t\tconst source = resolveWebsearchProvider(options);\n\t\t\t\tconst results = await (async () => {\n\t\t\t\t\tswitch (source) {\n\t\t\t\t\t\tcase \"brave-search\":\n\t\t\t\t\t\t\treturn fetchBraveResults(trimmedQuery, effectiveLimit, controller.signal, options);\n\t\t\t\t\t\tcase \"firecrawl-search\":\n\t\t\t\t\t\t\treturn fetchFirecrawlResults(trimmedQuery, effectiveLimit, controller.signal, options);\n\t\t\t\t\t\tcase \"duckduckgo-instant-answer\":\n\t\t\t\t\t\t\treturn fetchDuckDuckGoResults(trimmedQuery, effectiveLimit, controller.signal);\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: formatResults(trimmedQuery, results, source) }],\n\t\t\t\t\tdetails: { query: trimmedQuery, results, source },\n\t\t\t\t};\n\t\t\t} finally {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t}\n\t\t},\n\t\trenderCall(args, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatWebsearchCall(args as WebsearchCallArguments | undefined, theme));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatWebsearchResult(result as WebsearchRenderResult, options, theme, context.showImages));\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createWebsearchTool(options?: WebsearchToolOptions): AgentTool<typeof websearchSchema> {\n\treturn wrapToolDefinition(createWebsearchToolDefinition(options));\n}\n"]}
1
+ {"version":3,"file":"websearch.js","sourceRoot":"","sources":["../../../src/core/tools/websearch.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@greppleai/grip-agent-core\";\nimport { Text } from \"@greppleai/grip-tui\";\nimport { type Static, Type } from \"typebox\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport { getTextOutput, invalidArgText, str, type ToolTextOutputContent } from \"./render-utils.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\ninterface RenderTheme {\n\tbold(value: string): string;\n\tfg(role: string, value: string): string;\n}\n\nconst DEFAULT_LIMIT = 8;\nconst MAX_LIMIT = 20;\nconst REQUEST_TIMEOUT_MS = 10_000;\n\nexport type WebsearchProvider =\n\t| \"duckduckgo\"\n\t| \"duckduckgo-instant-answer\"\n\t| \"brave\"\n\t| \"brave-search\"\n\t| \"firecrawl\"\n\t| \"firecrawl-search\";\n\nexport interface WebsearchToolOptions {\n\tprovider?: WebsearchProvider;\n\tapiKey?: string;\n\tbaseUrl?: string;\n}\n\nconst websearchSchema = Type.Object({\n\tquery: Type.String({ description: \"Search query\" }),\n\tlimit: Type.Optional(\n\t\tType.Number({ description: `Maximum number of links to return (default ${DEFAULT_LIMIT}, max ${MAX_LIMIT})` }),\n\t),\n});\n\nexport type WebsearchToolInput = Static<typeof websearchSchema>;\n\nexport type WebsearchSource = \"duckduckgo-instant-answer\" | \"brave-search\" | \"firecrawl-search\";\n\nexport interface WebsearchResultItem {\n\ttitle: string;\n\turl: string;\n\tsnippet?: string;\n}\n\nexport interface WebsearchToolDetails {\n\tquery: string;\n\tresults: WebsearchResultItem[];\n\tsource: WebsearchSource;\n}\n\ninterface WebsearchCallArguments {\n\tquery?: string;\n\tlimit?: number;\n}\n\ninterface WebsearchRenderResult {\n\tcontent: ToolTextOutputContent[];\n\tdetails?: WebsearchToolDetails;\n}\n\ninterface DuckDuckGoTopic {\n\tFirstURL?: unknown;\n\tText?: unknown;\n\tName?: unknown;\n\tTopics?: unknown;\n}\n\ninterface BraveSearchResult {\n\ttitle?: unknown;\n\turl?: unknown;\n\tdescription?: unknown;\n}\n\ninterface FirecrawlSearchResult {\n\ttitle?: unknown;\n\turl?: unknown;\n\tdescription?: unknown;\n\tmarkdown?: unknown;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nexport function parseWebsearchToolOptions(value: unknown): WebsearchToolOptions | undefined {\n\tif (value === undefined) return undefined;\n\tif (!isRecord(value)) throw new Error(\"tools.websearch must be an object\");\n\tconst options: WebsearchToolOptions = {};\n\n\tconst provider = asString(value.provider);\n\tif (provider !== undefined) {\n\t\tif (\n\t\t\tprovider !== \"duckduckgo\" &&\n\t\t\tprovider !== \"duckduckgo-instant-answer\" &&\n\t\t\tprovider !== \"brave\" &&\n\t\t\tprovider !== \"brave-search\" &&\n\t\t\tprovider !== \"firecrawl\" &&\n\t\t\tprovider !== \"firecrawl-search\"\n\t\t) {\n\t\t\tthrow new Error(`Invalid tools.websearch.provider: ${provider}`);\n\t\t}\n\t\toptions.provider = provider;\n\t}\n\n\tconst apiKey = asString(value.apiKey);\n\tif (apiKey !== undefined) options.apiKey = apiKey;\n\n\tconst baseUrl = asString(value.baseUrl);\n\tif (baseUrl !== undefined) options.baseUrl = baseUrl;\n\n\treturn options;\n}\n\nfunction asString(value: unknown): string | undefined {\n\treturn typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nfunction stripHtml(value: string): string {\n\treturn value\n\t\t.replace(/<[^>]*>/g, \"\")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n}\n\nfunction titleFromText(text: string): string {\n\tconst separator = text.indexOf(\" - \");\n\treturn (separator > 0 ? text.slice(0, separator) : text).trim();\n}\n\nfunction pushResult(results: WebsearchResultItem[], seen: Set<string>, item: WebsearchResultItem): void {\n\tconst url = item.url.trim();\n\tif (!url || seen.has(url)) return;\n\tseen.add(url);\n\tresults.push({ ...item, url });\n}\n\nfunction collectRelatedTopics(value: unknown, results: WebsearchResultItem[], seen: Set<string>, limit: number): void {\n\tif (results.length >= limit) return;\n\tif (!Array.isArray(value)) return;\n\n\tfor (const entry of value) {\n\t\tif (results.length >= limit) return;\n\t\tif (!isRecord(entry)) continue;\n\t\tconst topic = entry as DuckDuckGoTopic;\n\t\tconst nestedTopics = topic.Topics;\n\t\tif (Array.isArray(nestedTopics)) {\n\t\t\tcollectRelatedTopics(nestedTopics, results, seen, limit);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst url = asString(topic.FirstURL);\n\t\tconst rawText = asString(topic.Text) ?? asString(topic.Name);\n\t\tif (!url || !rawText) continue;\n\t\tconst text = stripHtml(rawText);\n\t\tpushResult(results, seen, {\n\t\t\ttitle: titleFromText(text),\n\t\t\turl,\n\t\t\tsnippet: text,\n\t\t});\n\t}\n}\n\nexport function parseDuckDuckGoResponse(data: unknown, limit: number): WebsearchResultItem[] {\n\tconst results: WebsearchResultItem[] = [];\n\tconst seen = new Set<string>();\n\tif (!isRecord(data)) return results;\n\n\tconst heading = asString(data.Heading);\n\tconst abstractUrl = asString(data.AbstractURL);\n\tconst abstractText = asString(data.AbstractText) ?? asString(data.Abstract);\n\tif (abstractUrl && (heading || abstractText)) {\n\t\tpushResult(results, seen, {\n\t\t\ttitle: heading ?? titleFromText(stripHtml(abstractText ?? abstractUrl)),\n\t\t\turl: abstractUrl,\n\t\t\tsnippet: abstractText ? stripHtml(abstractText) : undefined,\n\t\t});\n\t}\n\n\tcollectRelatedTopics(data.RelatedTopics, results, seen, limit);\n\tcollectRelatedTopics(data.Results, results, seen, limit);\n\n\treturn results.slice(0, limit);\n}\n\nexport function parseBraveSearchResponse(data: unknown, limit: number): WebsearchResultItem[] {\n\tconst results: WebsearchResultItem[] = [];\n\tconst seen = new Set<string>();\n\tif (!isRecord(data) || !isRecord(data.web) || !Array.isArray(data.web.results)) return results;\n\n\tfor (const entry of data.web.results) {\n\t\tif (results.length >= limit) break;\n\t\tif (!isRecord(entry)) continue;\n\t\tconst item = entry as BraveSearchResult;\n\t\tconst title = asString(item.title);\n\t\tconst url = asString(item.url);\n\t\tif (!title || !url) continue;\n\t\tconst description = asString(item.description);\n\t\tpushResult(results, seen, {\n\t\t\ttitle: stripHtml(title),\n\t\t\turl,\n\t\t\tsnippet: description ? stripHtml(description) : undefined,\n\t\t});\n\t}\n\n\treturn results;\n}\n\nexport function parseFirecrawlSearchResponse(data: unknown, limit: number): WebsearchResultItem[] {\n\tconst results: WebsearchResultItem[] = [];\n\tconst seen = new Set<string>();\n\tif (!isRecord(data) || !isRecord(data.data) || !Array.isArray(data.data.web)) return results;\n\n\tfor (const entry of data.data.web) {\n\t\tif (results.length >= limit) break;\n\t\tif (!isRecord(entry)) continue;\n\t\tconst item = entry as FirecrawlSearchResult;\n\t\tconst title = asString(item.title);\n\t\tconst url = asString(item.url);\n\t\tif (!title || !url) continue;\n\t\tconst description = asString(item.description);\n\t\tconst markdown = asString(item.markdown);\n\t\tpushResult(results, seen, {\n\t\t\ttitle: stripHtml(title),\n\t\t\turl,\n\t\t\tsnippet: description ? stripHtml(description) : markdown ? stripHtml(markdown).slice(0, 500) : undefined,\n\t\t});\n\t}\n\n\treturn results;\n}\n\nfunction formatSourceName(source: WebsearchSource): string {\n\tswitch (source) {\n\t\tcase \"brave-search\":\n\t\t\treturn \"Brave Search\";\n\t\tcase \"firecrawl-search\":\n\t\t\treturn \"Firecrawl\";\n\t\tcase \"duckduckgo-instant-answer\":\n\t\t\treturn \"DuckDuckGo\";\n\t}\n}\n\nfunction formatResults(query: string, results: WebsearchResultItem[], source: WebsearchSource): string {\n\tif (results.length === 0) {\n\t\treturn `No ${formatSourceName(source)} links found for: ${query}`;\n\t}\n\treturn results\n\t\t.map((result, index) => {\n\t\t\tconst lines = [`${index + 1}. ${result.title}`, ` ${result.url}`];\n\t\t\tif (result.snippet) lines.push(` ${result.snippet}`);\n\t\t\treturn lines.join(\"\\n\");\n\t\t})\n\t\t.join(\"\\n\\n\");\n}\n\nfunction resolveLimit(limit: number | undefined): number {\n\tif (limit === undefined) return DEFAULT_LIMIT;\n\tif (!Number.isFinite(limit) || limit <= 0) return DEFAULT_LIMIT;\n\treturn Math.min(MAX_LIMIT, Math.floor(limit));\n}\n\nfunction formatWebsearchCall(args: WebsearchCallArguments | undefined, theme: RenderTheme): string {\n\tconst query = str(args?.query);\n\tconst invalidArg = invalidArgText(theme);\n\tlet text = `${theme.fg(\"toolTitle\", theme.bold(\"websearch\"))} ${query === null ? invalidArg : theme.fg(\"accent\", query)}`;\n\tif (args?.limit !== undefined) text += theme.fg(\"toolOutput\", ` (limit ${args.limit})`);\n\treturn text;\n}\n\nfunction formatWebsearchResult(\n\tresult: WebsearchRenderResult,\n\toptions: ToolRenderResultOptions,\n\ttheme: RenderTheme,\n\tshowImages: boolean,\n): string {\n\tconst output = getTextOutput(result, showImages).trim();\n\tif (!output) return \"\";\n\tconst lines = output.split(\"\\n\");\n\tconst maxLines = options.expanded ? lines.length : 24;\n\tconst displayed = lines.slice(0, maxLines).map((line) => theme.fg(\"toolOutput\", line));\n\tconst remaining = lines.length - maxLines;\n\treturn remaining > 0\n\t\t? `${displayed.join(\"\\n\")}\\n${theme.fg(\"muted\", `... (${remaining} more lines)`)}`\n\t\t: displayed.join(\"\\n\");\n}\nfunction resolveWebsearchProvider(options?: WebsearchToolOptions): WebsearchSource {\n\tconst configured =\n\t\toptions?.provider?.trim().toLowerCase() ?? process.env.GRIP_WEBSEARCH_PROVIDER?.trim().toLowerCase();\n\tif (!configured) {\n\t\tif (process.env.GRIP_WEBSEARCH_FIRECRAWL_API_KEY || process.env.FIRECRAWL_API_KEY) return \"firecrawl-search\";\n\t\tif (options?.apiKey || process.env.GRIP_WEBSEARCH_BRAVE_API_KEY || process.env.BRAVE_SEARCH_API_KEY)\n\t\t\treturn \"brave-search\";\n\t}\n\tif (!configured || configured === \"duckduckgo\" || configured === \"duckduckgo-instant-answer\") {\n\t\treturn \"duckduckgo-instant-answer\";\n\t}\n\tif (configured === \"brave\" || configured === \"brave-search\") return \"brave-search\";\n\tif (configured === \"firecrawl\" || configured === \"firecrawl-search\") return \"firecrawl-search\";\n\tthrow new Error(`Unsupported websearch provider: ${configured}`);\n}\n\nfunction resolveBraveApiKey(options?: WebsearchToolOptions): string {\n\tconst key = options?.apiKey ?? process.env.GRIP_WEBSEARCH_BRAVE_API_KEY ?? process.env.BRAVE_SEARCH_API_KEY;\n\tif (!key?.trim()) {\n\t\tthrow new Error(\n\t\t\t\"Brave websearch requires tools.websearch.apiKey, GRIP_WEBSEARCH_BRAVE_API_KEY, or BRAVE_SEARCH_API_KEY\",\n\t\t);\n\t}\n\treturn key.trim();\n}\n\nfunction resolveFirecrawlApiKey(options?: WebsearchToolOptions): string {\n\tconst key = options?.apiKey ?? process.env.GRIP_WEBSEARCH_FIRECRAWL_API_KEY ?? process.env.FIRECRAWL_API_KEY;\n\tif (!key?.trim()) {\n\t\tthrow new Error(\n\t\t\t\"Firecrawl websearch requires tools.websearch.apiKey, GRIP_WEBSEARCH_FIRECRAWL_API_KEY, or FIRECRAWL_API_KEY\",\n\t\t);\n\t}\n\treturn key.trim();\n}\n\nasync function fetchDuckDuckGoResults(\n\tquery: string,\n\tlimit: number,\n\tsignal: AbortSignal,\n): Promise<WebsearchResultItem[]> {\n\tconst url = new URL(\"https://api.duckduckgo.com/\");\n\turl.searchParams.set(\"q\", query);\n\turl.searchParams.set(\"format\", \"json\");\n\turl.searchParams.set(\"no_html\", \"1\");\n\turl.searchParams.set(\"skip_disambig\", \"1\");\n\n\tconst response = await fetch(url, {\n\t\theaders: { accept: \"application/json\", \"user-agent\": \"grip-coding-agent\" },\n\t\tsignal,\n\t});\n\tif (!response.ok) {\n\t\tthrow new Error(`DuckDuckGo request failed: ${response.status} ${response.statusText}`);\n\t}\n\treturn parseDuckDuckGoResponse((await response.json()) as unknown, limit);\n}\n\nasync function fetchBraveResults(\n\tquery: string,\n\tlimit: number,\n\tsignal: AbortSignal,\n\toptions?: WebsearchToolOptions,\n): Promise<WebsearchResultItem[]> {\n\tconst url = new URL(\n\t\toptions?.baseUrl ?? process.env.GRIP_WEBSEARCH_BRAVE_BASE_URL ?? \"https://api.search.brave.com/res/v1/web/search\",\n\t);\n\turl.searchParams.set(\"q\", query);\n\turl.searchParams.set(\"count\", String(limit));\n\n\tconst response = await fetch(url, {\n\t\theaders: {\n\t\t\taccept: \"application/json\",\n\t\t\t\"user-agent\": \"grip-coding-agent\",\n\t\t\t\"x-subscription-token\": resolveBraveApiKey(options),\n\t\t},\n\t\tsignal,\n\t});\n\tif (!response.ok) {\n\t\tthrow new Error(`Brave Search request failed: ${response.status} ${response.statusText}`);\n\t}\n\treturn parseBraveSearchResponse((await response.json()) as unknown, limit);\n}\n\nasync function fetchFirecrawlResults(\n\tquery: string,\n\tlimit: number,\n\tsignal: AbortSignal,\n\toptions?: WebsearchToolOptions,\n): Promise<WebsearchResultItem[]> {\n\tconst url = new URL(\n\t\toptions?.baseUrl ?? process.env.GRIP_WEBSEARCH_FIRECRAWL_BASE_URL ?? \"https://api.firecrawl.dev/v2/search\",\n\t);\n\tconst response = await fetch(url, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\taccept: \"application/json\",\n\t\t\t\"content-type\": \"application/json\",\n\t\t\t\"user-agent\": \"grip-coding-agent\",\n\t\t\tauthorization: `Bearer ${resolveFirecrawlApiKey(options)}`,\n\t\t},\n\t\tbody: JSON.stringify({ query, limit, sources: [{ type: \"web\" }] }),\n\t\tsignal,\n\t});\n\tif (!response.ok) {\n\t\tthrow new Error(`Firecrawl Search request failed: ${response.status} ${response.statusText}`);\n\t}\n\treturn parseFirecrawlSearchResponse((await response.json()) as unknown, limit);\n}\nexport function createWebsearchToolDefinition(\n\toptions?: WebsearchToolOptions,\n): ToolDefinition<typeof websearchSchema, WebsearchToolDetails> {\n\treturn {\n\t\tname: \"websearch\",\n\t\tlabel: \"websearch\",\n\t\tdescription:\n\t\t\t\"Search the web for relevant links using DuckDuckGo by default, or Brave Search/Firecrawl when configured. Returns titles, URLs, and snippets when available.\",\n\t\tpromptSnippet: \"Search the web for relevant links\",\n\t\tparameters: websearchSchema,\n\t\tasync execute(_toolCallId, { query, limit }: WebsearchToolInput, signal?: AbortSignal) {\n\t\t\tconst trimmedQuery = query.trim();\n\t\t\tif (!trimmedQuery) throw new Error(\"query is required\");\n\n\t\t\tconst effectiveLimit = resolveLimit(limit);\n\t\t\tconst controller = new AbortController();\n\t\t\tconst timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n\t\t\tconst onAbort = () => controller.abort();\n\t\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\ttry {\n\t\t\t\tconst source = resolveWebsearchProvider(options);\n\t\t\t\tconst results = await (async () => {\n\t\t\t\t\tswitch (source) {\n\t\t\t\t\t\tcase \"brave-search\":\n\t\t\t\t\t\t\treturn fetchBraveResults(trimmedQuery, effectiveLimit, controller.signal, options);\n\t\t\t\t\t\tcase \"firecrawl-search\":\n\t\t\t\t\t\t\treturn fetchFirecrawlResults(trimmedQuery, effectiveLimit, controller.signal, options);\n\t\t\t\t\t\tcase \"duckduckgo-instant-answer\":\n\t\t\t\t\t\t\treturn fetchDuckDuckGoResults(trimmedQuery, effectiveLimit, controller.signal);\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: formatResults(trimmedQuery, results, source) }],\n\t\t\t\t\tdetails: { query: trimmedQuery, results, source },\n\t\t\t\t};\n\t\t\t} finally {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t}\n\t\t},\n\t\trenderCall(args, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatWebsearchCall(args as WebsearchCallArguments | undefined, theme));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatWebsearchResult(result as WebsearchRenderResult, options, theme, context.showImages));\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createWebsearchTool(options?: WebsearchToolOptions): AgentTool<typeof websearchSchema> {\n\treturn wrapToolDefinition(createWebsearchToolDefinition(options));\n}\n"]}
@@ -87,6 +87,7 @@ export declare class WorkspaceToolHost {
87
87
  dispose(): Promise<void>;
88
88
  private registerConfiguredTools;
89
89
  private selectWorkspaceExecution;
90
+ private createScopedToolDefinition;
90
91
  private resolveLocalDefinition;
91
92
  private startRemoteExecution;
92
93
  private startLocalExecution;
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-tool-host.d.ts","sourceRoot":"","sources":["../../../src/core/tools/workspace-tool-host.ts"],"names":[],"mappings":"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","sourcesContent":["import { isAbsolute } from \"node:path\";\nimport type { AgentTool, AgentToolResult, AgentToolUpdateCallback } from \"@greppleai/grip-agent-core\";\nimport { validateToolArguments } from \"@greppleai/grip-ai\";\nimport type { Static, TSchema } from \"typebox\";\nimport type { ExtensionContext, ToolDefinition } from \"../extensions/types.ts\";\nimport {\n\ttype BashToolDefinition,\n\ttype BashToolOptions,\n\tcreateBashToolDefinition,\n\tgetBashSessionEnvironment,\n} from \"./bash.ts\";\nimport { createEditToolDefinition, type EditToolDefinition, type EditToolOptions } from \"./edit.ts\";\nimport { createFindToolDefinition, type FindToolDefinition, type FindToolOptions } from \"./find.ts\";\nimport { createGrepToolDefinition, type GrepToolDefinition, type GrepToolOptions } from \"./grep.ts\";\nimport { createLsToolDefinition, type LsToolDefinition, type LsToolOptions } from \"./ls.ts\";\nimport { LocalToolOperations, type ToolOperations, type WorkspaceToolExecutionOptions } from \"./operations.ts\";\nimport { resolveToCwd } from \"./path-utils.ts\";\nimport {\n\tcreateReadToolDefinition,\n\ttype ReadToolDefinition,\n\ttype ReadToolOperations,\n\ttype ReadToolOptions,\n} from \"./read.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { createWriteToolDefinition, type WriteToolDefinition, type WriteToolOptions } from \"./write.ts\";\n\nexport const WORKSPACE_TOOL_NAMES = Object.freeze([\"read\", \"bash\", \"edit\", \"write\", \"grep\", \"find\", \"ls\"] as const);\nconst WORKSPACE_TOOL_NAME_SET = new Set<string>(WORKSPACE_TOOL_NAMES);\nexport type WorkspaceToolName = (typeof WORKSPACE_TOOL_NAMES)[number];\nexport type WorkspaceToolDefinition =\n\t| ReadToolDefinition\n\t| BashToolDefinition\n\t| EditToolDefinition\n\t| WriteToolDefinition\n\t| GrepToolDefinition\n\t| FindToolDefinition\n\t| LsToolDefinition;\n\n// Heterogeneous tool registries erase per-tool schema/detail types at the lookup boundary.\ntype AnyAgentTool = AgentTool<any, any>;\ntype AnyToolDefinition = ToolDefinition<any, any, any>;\n\nexport interface WorkspaceToolOptions {\n\tread?: ReadToolOptions;\n\tbash?: BashToolOptions;\n\twrite?: WriteToolOptions;\n\tedit?: EditToolOptions;\n\tgrep?: GrepToolOptions;\n\tfind?: FindToolOptions;\n\tls?: LsToolOptions;\n}\n\nexport interface WorkspaceToolHostOptions {\n\tcwd: string;\n\toperations?: ToolOperations;\n\ttools?: WorkspaceToolOptions;\n\t/** Closed tool allowlist. Defaults to all canonical workspace tools. */\n\ttoolNames?: readonly WorkspaceToolName[];\n\tshellPath?: string;\n\t/** Dispose a caller-provided operations backend with the host. Defaults to false. */\n\townsOperations?: boolean;\n\t/** Maximum time to await cancellation before continuing disposal. Defaults to 5 seconds. */\n\tdisposeTimeoutMs?: number;\n\t/** Called after a negotiated remote catalog refresh has completed. */\n\tonCatalogChanged?: () => void | Promise<void>;\n\t/** Additional canonical service definitions, such as daemon-owned LSP tools. */\n\tadditionalDefinitions?: readonly AnyToolDefinition[];\n}\n\nexport interface WorkspaceToolCatalogEntry {\n\tname: string;\n\tlabel: string;\n\tdescription: string;\n\tparameters: TSchema;\n\texecutionMode: AnyToolDefinition[\"executionMode\"];\n}\n\nexport interface WorkspaceToolInvocation {\n\ttoolCallId: string;\n\targuments: unknown;\n\tsignal?: AbortSignal;\n\tonUpdate?: AgentToolUpdateCallback<unknown>;\n\texecutionOptions?: WorkspaceToolExecutionOptions;\n}\n\ninterface WorkspaceExecutionSelection {\n\texecuteRemotely: boolean;\n\treadOperations: ReadToolOperations | undefined;\n}\n\ninterface HostedToolExecution<TParams extends TSchema, TDetails> {\n\tname: string;\n\ttoolCallId: string;\n\tparams: Static<TParams>;\n\tsignal: AbortSignal;\n\tonUpdate: AgentToolUpdateCallback<TDetails> | undefined;\n\tcontext: ExtensionContext;\n\texecutionOptions: WorkspaceToolExecutionOptions | undefined;\n}\n\nfunction cloneObjectGraph<T>(value: T, seen = new Map<object, object>()): T {\n\tif (typeof value !== \"object\" || value === null) return value;\n\tconst existing = seen.get(value);\n\tif (existing) return existing as T;\n\tconst clone: object = Array.isArray(value) ? [] : Object.create(Object.getPrototypeOf(value));\n\tseen.set(value, clone);\n\tfor (const key of Reflect.ownKeys(value)) {\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(value, key);\n\t\tif (!descriptor) continue;\n\t\tif (\"value\" in descriptor) descriptor.value = cloneObjectGraph(descriptor.value, seen);\n\t\tObject.defineProperty(clone, key, descriptor);\n\t}\n\treturn clone as T;\n}\n\nfunction freezeObjectGraph(value: unknown, seen = new Set<object>()): void {\n\tif ((typeof value !== \"object\" && typeof value !== \"function\") || value === null || seen.has(value)) return;\n\tseen.add(value);\n\tfor (const key of Reflect.ownKeys(value)) {\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(value, key);\n\t\tif (descriptor && \"value\" in descriptor) freezeObjectGraph(descriptor.value, seen);\n\t}\n\tObject.freeze(value);\n}\n\nfunction validateDisposeTimeout(value: number | undefined): number {\n\tconst resolved = value ?? 5000;\n\tif (!Number.isSafeInteger(resolved) || resolved < 1 || resolved > 60_000) {\n\t\tthrow new Error(\"disposeTimeoutMs must be an integer from 1 through 60000\");\n\t}\n\treturn resolved;\n}\n\nfunction createRemoteExecutionOptions(toolOptions: WorkspaceToolOptions | undefined): WorkspaceToolExecutionOptions {\n\treturn Object.freeze({\n\t\t...(toolOptions?.read?.autoResizeImages === undefined\n\t\t\t? {}\n\t\t\t: { imageAutoResize: toolOptions.read.autoResizeImages }),\n\t\t...(toolOptions?.bash?.commandPrefix === undefined ? {} : { shellCommandPrefix: toolOptions.bash.commandPrefix }),\n\t});\n}\n\n/**\n * Canonical workspace-scoped tool construction and execution without an AgentSession.\n *\n * This host deliberately excludes subagents, session lifecycle tools, extensions, LSP,\n * models, prompts, conversation state, persistence, and UI. Caller-provided operations\n * are borrowed unless ownsOperations is explicitly enabled.\n */\nexport class WorkspaceToolHost {\n\treadonly operations: ToolOperations;\n\n\tprivate readonly definitions = new Map<string, AnyToolDefinition>();\n\tprivate readonly rawDefinitions = new Map<string, AnyToolDefinition>();\n\tprivate readonly remoteToolNames = new Set<string>();\n\tprivate readonly tools = new Map<string, AnyAgentTool>();\n\tprivate readonly ownsOperations: boolean;\n\tprivate readonly toolOptions: WorkspaceToolOptions | undefined;\n\tprivate readonly remoteExecutionOptions: WorkspaceToolExecutionOptions;\n\tprivate unsubscribeCatalog: (() => void) | undefined;\n\tprivate readonly disposeTimeoutMs: number;\n\tprivate readonly disposeController = new AbortController();\n\tprivate readonly activeInvocations = new Set<Promise<unknown>>();\n\tprivate disposePromise: Promise<void> | undefined;\n\tprivate disposed = false;\n\n\tconstructor(options: WorkspaceToolHostOptions) {\n\t\tif (options.operations && options.cwd !== options.operations.cwd) {\n\t\t\tthrow new Error(`Workspace host cwd ${options.cwd} does not match operations cwd ${options.operations.cwd}`);\n\t\t}\n\t\tthis.operations = options.operations ?? new LocalToolOperations(options.cwd, { shellPath: options.shellPath });\n\t\tthis.ownsOperations = options.operations ? options.ownsOperations === true : true;\n\t\tthis.toolOptions = options.tools;\n\t\tthis.remoteExecutionOptions = createRemoteExecutionOptions(options.tools);\n\t\tthis.disposeTimeoutMs = validateDisposeTimeout(options.disposeTimeoutMs);\n\t\tconst enabledNames = new Set(options.toolNames ?? WORKSPACE_TOOL_NAMES);\n\t\tfor (const name of enabledNames) {\n\t\t\tif (!WORKSPACE_TOOL_NAME_SET.has(name)) throw new Error(`Unknown workspace tool: ${name}`);\n\t\t}\n\t\tthis.registerConfiguredTools(enabledNames);\n\t\tthis.registerAdditionalDefinitions(options.additionalDefinitions ?? []);\n\t\tthis.unsubscribeCatalog = options.onCatalogChanged\n\t\t\t? this.operations.onWorkspaceToolCatalogChanged?.(options.onCatalogChanged)\n\t\t\t: undefined;\n\t}\n\n\tgetDefinitions(): ReadonlyMap<string, AnyToolDefinition> {\n\t\treturn new Map(this.definitions);\n\t}\n\n\tgetDefinition(name: string): AnyToolDefinition | undefined {\n\t\treturn this.definitions.get(name);\n\t}\n\n\tgetCatalog(): WorkspaceToolCatalogEntry[] {\n\t\treturn [...this.definitions.entries()].map(([name, definition]) => ({\n\t\t\tname,\n\t\t\tlabel: definition.label,\n\t\t\tdescription: definition.description,\n\t\t\tparameters: structuredClone(definition.parameters),\n\t\t\texecutionMode: definition.executionMode,\n\t\t}));\n\t}\n\n\tprepareArguments(name: string, rawArguments: unknown): unknown {\n\t\tif (this.disposed) throw new Error(\"Workspace tool host is disposed\");\n\t\tconst tool = this.requireTool(name);\n\t\treturn tool.prepareArguments ? tool.prepareArguments(rawArguments) : rawArguments;\n\t}\n\n\tasync execute(name: string, invocation: WorkspaceToolInvocation): Promise<AgentToolResult<unknown>> {\n\t\tconst preparedArguments = this.prepareArguments(name, invocation.arguments);\n\t\treturn await this.executePrepared(name, { ...invocation, arguments: preparedArguments });\n\t}\n\n\tvalidatePreparedArguments(name: string, argumentsValue: unknown): boolean {\n\t\tconst tool = this.tools.get(name);\n\t\tif (!tool || this.disposed) return false;\n\t\ttry {\n\t\t\tvalidateToolArguments(tool, {\n\t\t\t\ttype: \"toolCall\",\n\t\t\t\tid: \"validate\",\n\t\t\t\tname: tool.name,\n\t\t\t\targuments: argumentsValue as Record<string, unknown>,\n\t\t\t});\n\t\t\treturn true;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tasync executePrepared(name: string, invocation: WorkspaceToolInvocation): Promise<AgentToolResult<unknown>> {\n\t\tif (this.disposed) throw new Error(\"Workspace tool host is disposed\");\n\t\tconst tool = this.requireTool(name);\n\t\tconst params = validateToolArguments(tool, {\n\t\t\ttype: \"toolCall\",\n\t\t\tid: invocation.toolCallId,\n\t\t\tname: tool.name,\n\t\t\targuments: invocation.arguments as Record<string, unknown>,\n\t\t});\n\t\treturn await this.runDefinition(\n\t\t\tname,\n\t\t\tinvocation.toolCallId,\n\t\t\tparams,\n\t\t\tinvocation.signal,\n\t\t\tinvocation.onUpdate,\n\t\t\tundefined as unknown as ExtensionContext,\n\t\t\tinvocation.executionOptions,\n\t\t);\n\t}\n\n\tdetachCatalogListener(): void {\n\t\tthis.unsubscribeCatalog?.();\n\t\tthis.unsubscribeCatalog = undefined;\n\t}\n\n\twaitForIdle(timeoutMs = this.disposeTimeoutMs): Promise<boolean> {\n\t\tif (this.activeInvocations.size === 0) return Promise.resolve(true);\n\t\treturn new Promise((resolve) => {\n\t\t\tlet settled = false;\n\t\t\tconst finish = (value: boolean) => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tresolve(value);\n\t\t\t};\n\t\t\tconst timer = setTimeout(() => finish(false), timeoutMs);\n\t\t\ttimer.unref?.();\n\t\t\tvoid Promise.allSettled([...this.activeInvocations]).then(() => finish(true));\n\t\t});\n\t}\n\n\tdispose(): Promise<void> {\n\t\tthis.disposed = true;\n\t\tthis.disposePromise ??= this.disposeHost();\n\t\treturn this.disposePromise;\n\t}\n\n\tprivate registerConfiguredTools(enabledNames: ReadonlySet<WorkspaceToolName>): void {\n\t\tconst toolOptions = this.toolOptions;\n\t\tif (enabledNames.has(\"read\")) this.register(\"read\", createReadToolDefinition(this.operations, toolOptions?.read));\n\t\tif (enabledNames.has(\"bash\")) this.register(\"bash\", createBashToolDefinition(this.operations, toolOptions?.bash));\n\t\tif (enabledNames.has(\"edit\")) this.register(\"edit\", createEditToolDefinition(this.operations, toolOptions?.edit));\n\t\tif (enabledNames.has(\"write\"))\n\t\t\tthis.register(\"write\", createWriteToolDefinition(this.operations, toolOptions?.write));\n\t\tif (enabledNames.has(\"grep\")) this.register(\"grep\", createGrepToolDefinition(this.operations, toolOptions?.grep));\n\t\tif (enabledNames.has(\"find\")) this.register(\"find\", createFindToolDefinition(this.operations, toolOptions?.find));\n\t\tif (enabledNames.has(\"ls\")) this.register(\"ls\", createLsToolDefinition(this.operations, toolOptions?.ls));\n\t}\n\tprivate selectWorkspaceExecution(name: string, params: unknown): WorkspaceExecutionSelection {\n\t\tconst executeRemotely = this.remoteToolNames.has(name);\n\t\tconst operationsForPath = this.toolOptions?.read?.operationsForPath;\n\t\tif (!executeRemotely || name !== \"read\" || !operationsForPath) {\n\t\t\treturn { executeRemotely, readOperations: undefined };\n\t\t}\n\t\tconst readPath = (params as { path?: unknown }).path;\n\t\tif (typeof readPath !== \"string\" || !isAbsolute(readPath)) {\n\t\t\treturn { executeRemotely, readOperations: undefined };\n\t\t}\n\t\tconst absolutePath = resolveToCwd(readPath, this.operations.cwd);\n\t\tconst readOperations = operationsForPath(absolutePath);\n\t\treturn { executeRemotely: !readOperations, readOperations };\n\t}\n\n\tprivate resolveLocalDefinition<TParams extends TSchema, TDetails>(\n\t\trequest: HostedToolExecution<TParams, TDetails>,\n\t\tdefinition: ToolDefinition<TParams, TDetails>,\n\t\treadOperations: ReadToolOperations | undefined,\n\t): ToolDefinition<TParams, TDetails> {\n\t\tif (request.name === \"read\" && (readOperations || request.executionOptions?.imageAutoResize !== undefined)) {\n\t\t\treturn createReadToolDefinition(this.operations, {\n\t\t\t\t...this.toolOptions?.read,\n\t\t\t\t...(request.executionOptions?.imageAutoResize === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: { autoResizeImages: request.executionOptions.imageAutoResize }),\n\t\t\t\t...(readOperations ? { operationsForPath: () => readOperations } : {}),\n\t\t\t}) as unknown as ToolDefinition<TParams, TDetails>;\n\t\t}\n\t\tif (\n\t\t\trequest.name === \"bash\" &&\n\t\t\t(request.executionOptions?.shellCommandPrefix !== undefined ||\n\t\t\t\trequest.executionOptions?.sessionEnvironment !== undefined)\n\t\t) {\n\t\t\tconst sessionEnvironment = request.executionOptions.sessionEnvironment;\n\t\t\tconst configuredSpawnHook = this.toolOptions?.bash?.spawnHook;\n\t\t\treturn createBashToolDefinition(this.operations, {\n\t\t\t\t...this.toolOptions?.bash,\n\t\t\t\tcommandPrefix: request.executionOptions.shellCommandPrefix,\n\t\t\t\texposeSessionEnvironment: false,\n\t\t\t\tspawnHook: sessionEnvironment\n\t\t\t\t\t? (spawnContext) => {\n\t\t\t\t\t\t\tconst resolved = configuredSpawnHook?.(spawnContext) ?? spawnContext;\n\t\t\t\t\t\t\treturn { ...resolved, env: { ...resolved.env, ...sessionEnvironment } };\n\t\t\t\t\t\t}\n\t\t\t\t\t: configuredSpawnHook,\n\t\t\t}) as unknown as ToolDefinition<TParams, TDetails>;\n\t\t}\n\t\treturn definition;\n\t}\n\n\tprivate startRemoteExecution<TParams extends TSchema, TDetails>(\n\t\trequest: HostedToolExecution<TParams, TDetails>,\n\t): Promise<AgentToolResult<TDetails>> {\n\t\tif (!this.operations.executeWorkspaceTool) {\n\t\t\tthrow new Error(`Remote workspace executor is unavailable: ${request.name}`);\n\t\t}\n\t\treturn Promise.resolve().then(\n\t\t\tasync () =>\n\t\t\t\t(await this.operations.executeWorkspaceTool!(request.name, {\n\t\t\t\t\ttoolCallId: request.toolCallId,\n\t\t\t\t\targuments: request.params,\n\t\t\t\t\tsignal: request.signal,\n\t\t\t\t\tonUpdate: request.onUpdate as AgentToolUpdateCallback<unknown> | undefined,\n\t\t\t\t\texecutionOptions: request.executionOptions ?? this.remoteExecutionOptions,\n\t\t\t\t})) as AgentToolResult<TDetails>,\n\t\t);\n\t}\n\n\tprivate startLocalExecution<TParams extends TSchema, TDetails>(\n\t\trequest: HostedToolExecution<TParams, TDetails>,\n\t\tdefinition: ToolDefinition<TParams, TDetails>,\n\t): Promise<AgentToolResult<TDetails>> {\n\t\treturn Promise.resolve().then(() =>\n\t\t\tdefinition.execute(request.toolCallId, request.params, request.signal, request.onUpdate, request.context),\n\t\t);\n\t}\n\n\tprivate trackExecution<TDetails>(execution: Promise<AgentToolResult<TDetails>>): Promise<AgentToolResult<TDetails>> {\n\t\tthis.activeInvocations.add(execution);\n\t\tvoid execution.then(\n\t\t\t() => this.activeInvocations.delete(execution),\n\t\t\t() => this.activeInvocations.delete(execution),\n\t\t);\n\t\treturn execution;\n\t}\n\n\tprivate registerAdditionalDefinitions(definitions: readonly AnyToolDefinition[]): void {\n\t\tfor (const definition of definitions) {\n\t\t\tif (this.definitions.has(definition.name)) throw new Error(`Duplicate hosted tool: ${definition.name}`);\n\t\t\tthis.register(definition.name, definition);\n\t\t}\n\t}\n\n\tprivate register<TParams extends TSchema, TDetails, TState>(\n\t\tname: string,\n\t\tdefinition: ToolDefinition<TParams, TDetails, TState>,\n\t): void {\n\t\tconst canonicalDefinition: ToolDefinition<TParams, TDetails, TState> = {\n\t\t\t...definition,\n\t\t\tparameters: cloneObjectGraph(definition.parameters),\n\t\t};\n\t\tfreezeObjectGraph(canonicalDefinition);\n\t\tconst execute: ToolDefinition<TParams, TDetails, TState>[\"execute\"] = (\n\t\t\ttoolCallId,\n\t\t\tparams,\n\t\t\tsignal,\n\t\t\tonUpdate,\n\t\t\tcontext,\n\t\t) => this.runDefinition<TParams, TDetails>(name, toolCallId, params, signal, onUpdate, context, undefined);\n\t\tconst execution = this.operations.resolveWorkspaceToolExecution?.(name, canonicalDefinition.parameters);\n\t\tif (execution === \"unavailable\") return;\n\t\tif (execution === \"remote\") this.remoteToolNames.add(name);\n\t\tconst hostedDefinition: ToolDefinition<TParams, TDetails, TState> = Object.freeze({\n\t\t\t...canonicalDefinition,\n\t\t\texecute,\n\t\t});\n\t\tthis.rawDefinitions.set(name, canonicalDefinition);\n\t\tthis.definitions.set(name, hostedDefinition as unknown as WorkspaceToolDefinition);\n\t\tthis.tools.set(name, wrapToolDefinition(canonicalDefinition));\n\t}\n\n\tprivate async runDefinition<TParams extends TSchema, TDetails>(\n\t\tname: string,\n\t\ttoolCallId: string,\n\t\tparams: Static<TParams>,\n\t\tsignal: AbortSignal | undefined,\n\t\tonUpdate: AgentToolUpdateCallback<TDetails> | undefined,\n\t\tcontext: ExtensionContext,\n\t\texecutionOptions: WorkspaceToolExecutionOptions | undefined,\n\t): Promise<AgentToolResult<TDetails>> {\n\t\tif (this.disposed) throw new Error(\"Workspace tool host is disposed\");\n\t\tconst definition = this.requireRawDefinition(name) as ToolDefinition<TParams, TDetails>;\n\t\tconst combinedSignal = signal\n\t\t\t? AbortSignal.any([signal, this.disposeController.signal])\n\t\t\t: this.disposeController.signal;\n\t\tif (combinedSignal.aborted) throw new Error(\"Operation aborted\");\n\t\tconst selection = this.selectWorkspaceExecution(name, params);\n\t\tconst resolvedExecutionOptions = executionOptions ?? this.remoteExecutionOptions;\n\t\tconst request: HostedToolExecution<TParams, TDetails> = {\n\t\t\tname,\n\t\t\ttoolCallId,\n\t\t\tparams,\n\t\t\tsignal: combinedSignal,\n\t\t\tonUpdate,\n\t\t\tcontext,\n\t\t\texecutionOptions:\n\t\t\t\tname === \"bash\" && context && this.toolOptions?.bash?.exposeSessionEnvironment !== false\n\t\t\t\t\t? { ...resolvedExecutionOptions, sessionEnvironment: getBashSessionEnvironment(context) }\n\t\t\t\t\t: executionOptions,\n\t\t};\n\t\tconst execution = selection.executeRemotely\n\t\t\t? this.startRemoteExecution(request)\n\t\t\t: this.startLocalExecution(\n\t\t\t\t\trequest,\n\t\t\t\t\tthis.resolveLocalDefinition(request, definition, selection.readOperations),\n\t\t\t\t);\n\t\treturn await this.trackExecution(execution);\n\t}\n\n\tprivate async disposeHost(): Promise<void> {\n\t\tthis.detachCatalogListener();\n\t\tthis.disposeController.abort();\n\t\tlet timer: NodeJS.Timeout | undefined;\n\t\ttry {\n\t\t\tawait Promise.race([\n\t\t\t\tPromise.allSettled([...this.activeInvocations]),\n\t\t\t\tnew Promise<void>((resolve) => {\n\t\t\t\t\ttimer = setTimeout(resolve, this.disposeTimeoutMs);\n\t\t\t\t\ttimer.unref?.();\n\t\t\t\t}),\n\t\t\t]);\n\t\t} finally {\n\t\t\tif (timer) clearTimeout(timer);\n\t\t}\n\t\tif (this.ownsOperations) await this.operations.dispose?.();\n\t}\n\n\tprivate requireRawDefinition(name: string): AnyToolDefinition {\n\t\tconst definition = this.rawDefinitions.get(name);\n\t\tif (!definition) throw new Error(`Unknown or non-workspace tool: ${name}`);\n\t\treturn definition;\n\t}\n\n\tprivate requireTool(name: string): AnyAgentTool {\n\t\tconst tool = this.tools.get(name);\n\t\tif (!tool) throw new Error(`Unknown or non-workspace tool: ${name}`);\n\t\treturn tool;\n\t}\n}\n"]}
1
+ {"version":3,"file":"workspace-tool-host.d.ts","sourceRoot":"","sources":["../../../src/core/tools/workspace-tool-host.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,7 @@ import { createEditToolDefinition } from "./edit.js";
5
5
  import { createFindToolDefinition } from "./find.js";
6
6
  import { createGrepToolDefinition } from "./grep.js";
7
7
  import { createLsToolDefinition } from "./ls.js";
8
- import { LocalToolOperations } from "./operations.js";
8
+ import { borrowToolOperations, LocalToolOperations, } from "./operations.js";
9
9
  import { resolveToCwd } from "./path-utils.js";
10
10
  import { createReadToolDefinition, } from "./read.js";
11
11
  import { wrapToolDefinition } from "./tool-definition-wrapper.js";
@@ -64,21 +64,14 @@ function createRemoteExecutionOptions(toolOptions) {
64
64
  * are borrowed unless ownsOperations is explicitly enabled.
65
65
  */
66
66
  export class WorkspaceToolHost {
67
- operations;
68
- definitions = new Map();
69
- rawDefinitions = new Map();
70
- remoteToolNames = new Set();
71
- tools = new Map();
72
- ownsOperations;
73
- toolOptions;
74
- remoteExecutionOptions;
75
- unsubscribeCatalog;
76
- disposeTimeoutMs;
77
- disposeController = new AbortController();
78
- activeInvocations = new Set();
79
- disposePromise;
80
- disposed = false;
81
67
  constructor(options) {
68
+ this.definitions = new Map();
69
+ this.rawDefinitions = new Map();
70
+ this.remoteToolNames = new Set();
71
+ this.tools = new Map();
72
+ this.disposeController = new AbortController();
73
+ this.activeInvocations = new Set();
74
+ this.disposed = false;
82
75
  if (options.operations && options.cwd !== options.operations.cwd) {
83
76
  throw new Error(`Workspace host cwd ${options.cwd} does not match operations cwd ${options.operations.cwd}`);
84
77
  }
@@ -209,9 +202,29 @@ export class WorkspaceToolHost {
209
202
  const readOperations = operationsForPath(absolutePath);
210
203
  return { executeRemotely: !readOperations, readOperations };
211
204
  }
205
+ createScopedToolDefinition(name, operations, cwd) {
206
+ if (!cwd)
207
+ return undefined;
208
+ const factories = {
209
+ edit: () => createEditToolDefinition(operations, this.toolOptions?.edit),
210
+ write: () => createWriteToolDefinition(operations, this.toolOptions?.write),
211
+ grep: () => createGrepToolDefinition(operations, this.toolOptions?.grep),
212
+ find: () => createFindToolDefinition(operations, this.toolOptions?.find),
213
+ ls: () => createLsToolDefinition(operations, this.toolOptions?.ls),
214
+ };
215
+ return factories[name]?.();
216
+ }
212
217
  resolveLocalDefinition(request, definition, readOperations) {
213
- if (request.name === "read" && (readOperations || request.executionOptions?.imageAutoResize !== undefined)) {
214
- return createReadToolDefinition(this.operations, {
218
+ const cwd = request.executionOptions?.cwd;
219
+ // Bind only this invocation's cwd; never mutate the shared daemon host or its mount root.
220
+ const operations = cwd
221
+ ? new Proxy(borrowToolOperations(this.operations), {
222
+ get: (target, property, receiver) => property === "cwd" ? cwd : Reflect.get(target, property, receiver),
223
+ })
224
+ : this.operations;
225
+ if (request.name === "read" &&
226
+ (cwd || readOperations || request.executionOptions?.imageAutoResize !== undefined)) {
227
+ return createReadToolDefinition(operations, {
215
228
  ...this.toolOptions?.read,
216
229
  ...(request.executionOptions?.imageAutoResize === undefined
217
230
  ? {}
@@ -220,13 +233,14 @@ export class WorkspaceToolHost {
220
233
  });
221
234
  }
222
235
  if (request.name === "bash" &&
223
- (request.executionOptions?.shellCommandPrefix !== undefined ||
236
+ (cwd ||
237
+ request.executionOptions?.shellCommandPrefix !== undefined ||
224
238
  request.executionOptions?.sessionEnvironment !== undefined)) {
225
- const sessionEnvironment = request.executionOptions.sessionEnvironment;
239
+ const sessionEnvironment = request.executionOptions?.sessionEnvironment;
226
240
  const configuredSpawnHook = this.toolOptions?.bash?.spawnHook;
227
- return createBashToolDefinition(this.operations, {
241
+ return createBashToolDefinition(operations, {
228
242
  ...this.toolOptions?.bash,
229
- commandPrefix: request.executionOptions.shellCommandPrefix,
243
+ commandPrefix: request.executionOptions?.shellCommandPrefix,
230
244
  exposeSessionEnvironment: false,
231
245
  spawnHook: sessionEnvironment
232
246
  ? (spawnContext) => {
@@ -236,7 +250,7 @@ export class WorkspaceToolHost {
236
250
  : configuredSpawnHook,
237
251
  });
238
252
  }
239
- return definition;
253
+ return (this.createScopedToolDefinition(request.name, operations, cwd) ?? definition);
240
254
  }
241
255
  startRemoteExecution(request) {
242
256
  if (!this.operations.executeWorkspaceTool) {