@oh-my-pi/pi-coding-agent 7.0.0 → 8.0.1

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 (503) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/README.md +1 -1
  3. package/docs/hooks.md +2 -2
  4. package/docs/sdk.md +1 -1
  5. package/package.json +12 -11
  6. package/scripts/format-prompts.ts +143 -0
  7. package/scripts/generate-template.ts +1 -1
  8. package/src/cli/args.ts +3 -3
  9. package/src/cli/config-cli.ts +4 -4
  10. package/src/cli/file-processor.ts +3 -3
  11. package/src/cli/list-models.ts +2 -2
  12. package/src/cli/plugin-cli.ts +3 -3
  13. package/src/cli/session-picker.ts +2 -2
  14. package/src/cli/setup-cli.ts +2 -2
  15. package/src/cli/stats-cli.ts +1 -1
  16. package/src/cli/update-cli.ts +2 -2
  17. package/src/{core → config}/keybindings.ts +1 -1
  18. package/src/{core → config}/model-registry.ts +1 -1
  19. package/src/{core → config}/model-resolver.ts +3 -3
  20. package/src/{core → config}/prompt-templates.ts +2 -2
  21. package/src/{core → config}/settings-manager.ts +6 -6
  22. package/src/{core/cursor/exec-bridge.ts → cursor.ts} +4 -4
  23. package/src/discovery/agents-md.ts +4 -4
  24. package/src/discovery/builtin.ts +17 -17
  25. package/src/discovery/claude.ts +12 -12
  26. package/src/discovery/cline.ts +6 -6
  27. package/src/discovery/codex.ts +21 -21
  28. package/src/discovery/cursor.ts +9 -9
  29. package/src/discovery/gemini.ts +9 -9
  30. package/src/discovery/github.ts +6 -6
  31. package/src/discovery/helpers.ts +4 -4
  32. package/src/discovery/index.ts +16 -16
  33. package/src/discovery/mcp-json.ts +4 -4
  34. package/src/discovery/ssh.ts +4 -4
  35. package/src/discovery/vscode.ts +4 -4
  36. package/src/discovery/windsurf.ts +6 -6
  37. package/src/{core/tools/exa → exa}/company.ts +2 -3
  38. package/src/{core/tools/exa → exa}/index.ts +2 -2
  39. package/src/{core/tools/exa → exa}/linkedin.ts +2 -3
  40. package/src/{core/tools/exa → exa}/mcp-client.ts +2 -2
  41. package/src/{core/tools/exa → exa}/render.ts +3 -3
  42. package/src/{core/tools/exa → exa}/researcher.ts +1 -1
  43. package/src/{core/tools/exa → exa}/search.ts +2 -10
  44. package/src/{core/tools/exa → exa}/websets.ts +1 -1
  45. package/src/{core → exec}/bash-executor.ts +22 -6
  46. package/src/{core → export}/custom-share.ts +1 -1
  47. package/src/{core/export-html → export/html}/index.ts +3 -3
  48. package/src/{core → export}/ttsr.ts +2 -2
  49. package/src/{core → extensibility}/custom-commands/bundled/review/index.ts +4 -4
  50. package/src/{core → extensibility}/custom-commands/loader.ts +3 -3
  51. package/src/{core → extensibility}/custom-commands/types.ts +1 -1
  52. package/src/{core → extensibility}/custom-tools/loader.ts +9 -9
  53. package/src/{core → extensibility}/custom-tools/types.ts +6 -6
  54. package/src/{core → extensibility}/custom-tools/wrapper.ts +1 -1
  55. package/src/{core → extensibility}/extensions/loader.ts +8 -8
  56. package/src/{core → extensibility}/extensions/runner.ts +3 -3
  57. package/src/{core → extensibility}/extensions/types.ts +15 -15
  58. package/src/{core → extensibility}/extensions/wrapper.ts +1 -1
  59. package/src/{core → extensibility}/hooks/index.ts +1 -1
  60. package/src/{core → extensibility}/hooks/loader.ts +7 -7
  61. package/src/{core → extensibility}/hooks/runner.ts +4 -4
  62. package/src/{core → extensibility}/hooks/types.ts +9 -9
  63. package/src/{core → extensibility}/plugins/doctor.ts +1 -1
  64. package/src/{core → extensibility}/plugins/installer.ts +2 -3
  65. package/src/{core → extensibility}/plugins/paths.ts +1 -1
  66. package/src/{core → extensibility}/skills.ts +8 -48
  67. package/src/{core → extensibility}/slash-commands.ts +6 -6
  68. package/src/index.ts +127 -128
  69. package/src/internal-urls/agent-protocol.ts +126 -0
  70. package/src/internal-urls/artifact-protocol.ts +93 -0
  71. package/src/internal-urls/index.ts +28 -0
  72. package/src/internal-urls/json-query.ts +126 -0
  73. package/src/internal-urls/router.ts +69 -0
  74. package/src/internal-urls/rule-protocol.ts +56 -0
  75. package/src/internal-urls/skill-protocol.ts +112 -0
  76. package/src/internal-urls/types.ts +48 -0
  77. package/src/{core/python-executor.ts → ipy/executor.ts} +51 -11
  78. package/src/{core/python-gateway-coordinator.ts → ipy/gateway-coordinator.ts} +41 -325
  79. package/src/{core/python-kernel.ts → ipy/kernel.ts} +38 -10
  80. package/src/ipy/prelude.ts +3 -0
  81. package/src/{core/tools/lsp → lsp}/client.ts +7 -6
  82. package/src/{core/tools/lsp → lsp}/clients/biome-client.ts +1 -1
  83. package/src/{core/tools/lsp → lsp}/clients/index.ts +1 -1
  84. package/src/{core/tools/lsp → lsp}/clients/lsp-linter-client.ts +4 -4
  85. package/src/{core/tools/lsp → lsp}/config.ts +1 -1
  86. package/src/{core/tools/lsp → lsp}/index.ts +16 -15
  87. package/src/{core/tools/lsp → lsp}/render.ts +2 -2
  88. package/src/{core/tools/lsp → lsp}/types.ts +14 -16
  89. package/src/{core/tools/lsp → lsp}/utils.ts +1 -1
  90. package/src/main.ts +12 -12
  91. package/src/{core/mcp → mcp}/config.ts +8 -8
  92. package/src/{core/mcp → mcp}/loader.ts +5 -6
  93. package/src/{core/mcp → mcp}/manager.ts +2 -2
  94. package/src/{core/mcp → mcp}/tool-bridge.ts +35 -6
  95. package/src/{core/mcp → mcp}/tool-cache.ts +1 -1
  96. package/src/{core/mcp → mcp}/transports/http.ts +7 -1
  97. package/src/{core/mcp → mcp}/transports/stdio.ts +1 -1
  98. package/src/{core/mcp → mcp}/types.ts +1 -1
  99. package/src/migrations.ts +2 -2
  100. package/src/modes/{interactive/components → components}/armin.ts +1 -1
  101. package/src/modes/{interactive/components → components}/assistant-message.ts +1 -1
  102. package/src/modes/{interactive/components → components}/bash-execution.ts +37 -29
  103. package/src/modes/{interactive/components → components}/bordered-loader.ts +1 -1
  104. package/src/modes/{interactive/components → components}/branch-summary-message.ts +2 -2
  105. package/src/modes/{interactive/components → components}/compaction-summary-message.ts +2 -2
  106. package/src/modes/{interactive/components → components}/custom-message.ts +3 -3
  107. package/src/modes/{interactive/components → components}/diff.ts +1 -1
  108. package/src/modes/{interactive/components → components}/dynamic-border.ts +1 -1
  109. package/src/modes/{interactive/components → components}/extensions/extension-dashboard.ts +3 -3
  110. package/src/modes/{interactive/components → components}/extensions/extension-list.ts +2 -2
  111. package/src/modes/{interactive/components → components}/extensions/inspector-panel.ts +1 -1
  112. package/src/modes/{interactive/components → components}/extensions/state-manager.ts +11 -17
  113. package/src/modes/{interactive/components → components}/extensions/types.ts +1 -1
  114. package/src/modes/{interactive/components → components}/footer.ts +3 -3
  115. package/src/modes/{interactive/components → components}/history-search.ts +2 -2
  116. package/src/modes/{interactive/components → components}/hook-editor.ts +1 -1
  117. package/src/modes/{interactive/components → components}/hook-input.ts +1 -1
  118. package/src/modes/{interactive/components → components}/hook-message.ts +3 -3
  119. package/src/modes/{interactive/components → components}/hook-selector.ts +1 -1
  120. package/src/modes/{interactive/components → components}/keybinding-hints.ts +2 -2
  121. package/src/modes/{interactive/components → components}/login-dialog.ts +1 -1
  122. package/src/modes/{interactive/components → components}/model-selector.ts +5 -5
  123. package/src/modes/{interactive/components → components}/oauth-selector.ts +2 -2
  124. package/src/modes/{interactive/components → components}/plugin-settings.ts +3 -3
  125. package/src/modes/{interactive/components → components}/python-execution.ts +35 -24
  126. package/src/modes/{interactive/components → components}/queue-mode-selector.ts +1 -1
  127. package/src/modes/{interactive/components → components}/read-tool-group.ts +2 -2
  128. package/src/modes/{interactive/components → components}/session-selector.ts +3 -3
  129. package/src/modes/{interactive/components → components}/settings-defs.ts +2 -2
  130. package/src/modes/{interactive/components → components}/settings-selector.ts +2 -2
  131. package/src/modes/{interactive/components → components}/show-images-selector.ts +1 -1
  132. package/src/modes/{interactive/components → components}/status-line/segments.ts +2 -2
  133. package/src/modes/{interactive/components → components}/status-line/separators.ts +1 -1
  134. package/src/modes/{interactive/components → components}/status-line/types.ts +2 -2
  135. package/src/modes/{interactive/components → components}/status-line-segment-editor.ts +2 -2
  136. package/src/modes/{interactive/components → components}/status-line.ts +3 -3
  137. package/src/modes/{interactive/components → components}/theme-selector.ts +1 -1
  138. package/src/modes/{interactive/components → components}/thinking-selector.ts +1 -1
  139. package/src/modes/{interactive/components → components}/todo-display.ts +3 -4
  140. package/src/modes/{interactive/components → components}/todo-reminder.ts +2 -2
  141. package/src/modes/{interactive/components → components}/tool-execution.ts +8 -8
  142. package/src/modes/{interactive/components → components}/tree-selector.ts +3 -3
  143. package/src/modes/{interactive/components → components}/ttsr-notification.ts +2 -2
  144. package/src/modes/{interactive/components → components}/user-message-selector.ts +1 -1
  145. package/src/modes/{interactive/components → components}/user-message.ts +1 -1
  146. package/src/modes/{interactive/components → components}/welcome.ts +2 -2
  147. package/src/modes/{interactive/controllers → controllers}/command-controller.ts +32 -30
  148. package/src/modes/{interactive/controllers → controllers}/event-controller.ts +9 -9
  149. package/src/modes/{interactive/controllers → controllers}/extension-ui-controller.ts +8 -8
  150. package/src/modes/{interactive/controllers → controllers}/input-controller.ts +6 -6
  151. package/src/modes/{interactive/controllers → controllers}/selector-controller.ts +16 -16
  152. package/src/modes/index.ts +1 -1
  153. package/src/modes/{interactive/interactive-mode.ts → interactive-mode.ts} +14 -14
  154. package/src/modes/print-mode.ts +1 -1
  155. package/src/modes/rpc/rpc-client.ts +3 -3
  156. package/src/modes/rpc/rpc-mode.ts +3 -3
  157. package/src/modes/rpc/rpc-types.ts +3 -3
  158. package/src/modes/{interactive/theme → theme}/theme.ts +1 -1
  159. package/src/modes/{interactive/types.ts → types.ts} +8 -9
  160. package/src/modes/{interactive/utils → utils}/ui-helpers.ts +20 -27
  161. package/src/{core/tools/patch → patch}/applicator.ts +1 -1
  162. package/src/{core/tools/patch → patch}/diff.ts +1 -1
  163. package/src/{core/tools/patch → patch}/index.ts +31 -36
  164. package/src/{core/tools/patch → patch}/shared.ts +9 -6
  165. package/src/prompts/agents/explore.md +83 -46
  166. package/src/prompts/agents/init.md +9 -4
  167. package/src/prompts/agents/plan.md +8 -7
  168. package/src/prompts/agents/reviewer.md +36 -18
  169. package/src/prompts/agents/task.md +4 -4
  170. package/src/prompts/compaction/branch-summary-preamble.md +0 -1
  171. package/src/prompts/review-request.md +0 -1
  172. package/src/prompts/system/custom-system-prompt.md +2 -14
  173. package/src/prompts/system/file-operations.md +0 -2
  174. package/src/prompts/system/system-prompt.md +147 -138
  175. package/src/prompts/system/web-search.md +26 -0
  176. package/src/prompts/tools/ask.md +31 -24
  177. package/src/prompts/tools/bash.md +20 -17
  178. package/src/prompts/tools/calculator.md +9 -5
  179. package/src/prompts/tools/fetch.md +16 -0
  180. package/src/prompts/tools/find.md +15 -5
  181. package/src/prompts/tools/gemini-image.md +21 -6
  182. package/src/prompts/tools/grep.md +28 -12
  183. package/src/prompts/tools/lsp.md +35 -14
  184. package/src/prompts/tools/patch.md +39 -41
  185. package/src/prompts/tools/python.md +59 -76
  186. package/src/prompts/tools/read.md +23 -22
  187. package/src/prompts/tools/replace.md +19 -12
  188. package/src/prompts/tools/ssh.md +21 -28
  189. package/src/prompts/tools/task.md +54 -44
  190. package/src/prompts/tools/todo-write.md +52 -163
  191. package/src/prompts/tools/web-search.md +16 -9
  192. package/src/prompts/tools/write.md +13 -2
  193. package/src/{core/sdk.ts → sdk.ts} +65 -34
  194. package/src/{core → session}/agent-session.ts +45 -37
  195. package/src/{core → session}/agent-storage.ts +2 -2
  196. package/src/session/artifacts.ts +110 -0
  197. package/src/{core → session}/auth-storage.ts +1 -1
  198. package/src/{core → session}/compaction/branch-summarization.ts +5 -5
  199. package/src/{core → session}/compaction/compaction.ts +6 -6
  200. package/src/{core → session}/compaction/utils.ts +3 -3
  201. package/src/{core → session}/history-storage.ts +1 -1
  202. package/src/{core → session}/messages.ts +6 -8
  203. package/src/{core → session}/session-manager.ts +2 -2
  204. package/src/{core → session}/storage-migration.ts +2 -2
  205. package/src/session/streaming-output.ts +177 -0
  206. package/src/{core/ssh → ssh}/connection-manager.ts +1 -1
  207. package/src/{core/ssh → ssh}/ssh-executor.ts +19 -4
  208. package/src/{core/ssh → ssh}/sshfs-mount.ts +1 -1
  209. package/src/{core/system-prompt.ts → system-prompt.ts} +8 -37
  210. package/src/{core/tools/task → task}/agents.ts +8 -8
  211. package/src/{core/tools/task → task}/commands.ts +5 -6
  212. package/src/{core/tools/task → task}/discovery.ts +3 -3
  213. package/src/{core/tools/task → task}/executor.ts +34 -44
  214. package/src/{core/tools/task → task}/index.ts +206 -50
  215. package/src/{core/tools/task → task}/render.ts +80 -23
  216. package/src/{core/tools/task → task}/subprocess-tool-registry.ts +1 -1
  217. package/src/task/template.ts +47 -0
  218. package/src/{core/tools/task → task}/types.ts +19 -27
  219. package/src/{core/tools/task → task}/worker-protocol.ts +8 -4
  220. package/src/{core/tools/task → task}/worker.ts +34 -29
  221. package/src/task/worktree.ts +166 -0
  222. package/src/{core/tools → tools}/ask.ts +13 -21
  223. package/src/{core/tools → tools}/bash-interceptor.ts +1 -1
  224. package/src/{core/tools → tools}/bash.ts +61 -63
  225. package/src/{core/tools → tools}/calculator.ts +4 -4
  226. package/src/{core/tools → tools}/complete.ts +1 -1
  227. package/src/{core/tools → tools}/context.ts +2 -2
  228. package/src/{core/tools/web-fetch.ts → tools/fetch.ts} +97 -76
  229. package/src/{core/tools → tools}/find.ts +80 -104
  230. package/src/{core/tools → tools}/gemini-image.ts +420 -29
  231. package/src/{core/tools → tools}/grep.ts +155 -164
  232. package/src/{core/tools → tools}/index.ts +63 -56
  233. package/src/tools/list-limit.ts +40 -0
  234. package/src/{core/tools → tools}/ls.ts +44 -35
  235. package/src/{core/tools → tools}/notebook.ts +3 -3
  236. package/src/tools/output-meta.ts +443 -0
  237. package/src/tools/output-utils.ts +63 -0
  238. package/src/{core/tools → tools}/python.ts +105 -89
  239. package/src/tools/read.ts +882 -0
  240. package/src/{core/tools → tools}/render-utils.ts +1 -1
  241. package/src/{core/tools → tools}/renderers.ts +8 -10
  242. package/src/{core/tools → tools}/review.ts +2 -2
  243. package/src/{core/tools → tools}/ssh.ts +56 -59
  244. package/src/{core/tools → tools}/todo-write.ts +12 -23
  245. package/src/tools/tool-errors.ts +95 -0
  246. package/src/tools/tool-result.ts +92 -0
  247. package/src/{core/tools → tools}/truncate.ts +2 -2
  248. package/src/{core/tools → tools}/write.ts +15 -13
  249. package/src/utils/changelog.ts +1 -1
  250. package/src/{core → utils}/file-mentions.ts +4 -4
  251. package/src/utils/image-convert.ts +1 -1
  252. package/src/utils/image-resize.ts +1 -1
  253. package/src/utils/shell.ts +1 -1
  254. package/src/{core → utils}/title-generator.ts +4 -4
  255. package/src/utils/tools-manager.ts +1 -1
  256. package/src/{core/tools/web-scrapers → web/scrapers}/choosealicense.ts +1 -1
  257. package/src/{core/tools/web-scrapers → web/scrapers}/twitter.ts +3 -2
  258. package/src/{core/tools/web-scrapers → web/scrapers}/types.ts +4 -2
  259. package/src/{core/tools/web-scrapers → web/scrapers}/utils.ts +1 -1
  260. package/src/{core/tools/web-scrapers → web/scrapers}/youtube.ts +14 -13
  261. package/src/{core/tools/web-search → web/search}/auth.ts +4 -4
  262. package/src/{core/tools/web-search → web/search}/index.ts +22 -71
  263. package/src/{core/tools/web-search → web/search}/providers/anthropic.ts +7 -10
  264. package/src/{core/tools/web-search → web/search}/providers/exa.ts +2 -2
  265. package/src/{core/tools/web-search → web/search}/providers/perplexity.ts +4 -16
  266. package/src/{core/tools/web-search → web/search}/render.ts +3 -3
  267. package/tsconfig.json +25 -0
  268. package/scripts/migrate-sessions.sh +0 -93
  269. package/src/core/index.ts +0 -56
  270. package/src/core/python-prelude.ts +0 -3
  271. package/src/core/ssh-executor.ts +0 -5
  272. package/src/core/streaming-output.ts +0 -115
  273. package/src/core/tools/output.ts +0 -519
  274. package/src/core/tools/read.ts +0 -717
  275. package/src/core/tools/task/template.ts +0 -37
  276. package/src/prompts/tools/output.md +0 -47
  277. package/src/prompts/tools/web-fetch.md +0 -9
  278. package/src/vendor/photon/photon_rs_bg.wasm.b64.js +0 -1
  279. /package/src/{core/tools/exa → exa}/types.ts +0 -0
  280. /package/src/{core → exec}/exec.ts +0 -0
  281. /package/src/{core/export-html → export/html}/template.css +0 -0
  282. /package/src/{core/export-html → export/html}/template.generated.ts +0 -0
  283. /package/src/{core/export-html → export/html}/template.html +0 -0
  284. /package/src/{core/export-html → export/html}/template.js +0 -0
  285. /package/src/{core/export-html → export/html}/template.macro.ts +0 -0
  286. /package/src/{core/export-html → export/html}/vendor/highlight.min.js +0 -0
  287. /package/src/{core/export-html → export/html}/vendor/marked.min.js +0 -0
  288. /package/src/{core → extensibility}/custom-commands/index.ts +0 -0
  289. /package/src/{core → extensibility}/custom-tools/index.ts +0 -0
  290. /package/src/{core → extensibility}/extensions/index.ts +0 -0
  291. /package/src/{core → extensibility}/hooks/tool-wrapper.ts +0 -0
  292. /package/src/{core → extensibility}/plugins/index.ts +0 -0
  293. /package/src/{core → extensibility}/plugins/loader.ts +0 -0
  294. /package/src/{core → extensibility}/plugins/manager.ts +0 -0
  295. /package/src/{core → extensibility}/plugins/parser.ts +0 -0
  296. /package/src/{core → extensibility}/plugins/types.ts +0 -0
  297. /package/src/{core/python-modules.ts → ipy/modules.ts} +0 -0
  298. /package/src/{core/python-prelude.py → ipy/prelude.py} +0 -0
  299. /package/src/{core/tools/lsp → lsp}/defaults.json +0 -0
  300. /package/src/{core/tools/lsp → lsp}/edits.ts +0 -0
  301. /package/src/{core/tools/lsp → lsp}/lspmux.ts +0 -0
  302. /package/src/{core/tools/lsp → lsp}/rust-analyzer.ts +0 -0
  303. /package/src/{core/mcp → mcp}/client.ts +0 -0
  304. /package/src/{core/mcp → mcp}/index.ts +0 -0
  305. /package/src/{core/mcp → mcp}/json-rpc.ts +0 -0
  306. /package/src/{core/mcp → mcp}/transports/index.ts +0 -0
  307. /package/src/modes/{interactive/components → components}/countdown-timer.ts +0 -0
  308. /package/src/modes/{interactive/components → components}/custom-editor.ts +0 -0
  309. /package/src/modes/{interactive/components → components}/extensions/index.ts +0 -0
  310. /package/src/modes/{interactive/components → components}/index.ts +0 -0
  311. /package/src/modes/{interactive/components → components}/status-line/index.ts +0 -0
  312. /package/src/modes/{interactive/components → components}/status-line/presets.ts +0 -0
  313. /package/src/modes/{interactive/components → components}/visual-truncate.ts +0 -0
  314. /package/src/modes/{interactive/theme → theme}/dark.json +0 -0
  315. /package/src/modes/{interactive/theme → theme}/defaults/alabaster.json +0 -0
  316. /package/src/modes/{interactive/theme → theme}/defaults/amethyst.json +0 -0
  317. /package/src/modes/{interactive/theme → theme}/defaults/anthracite.json +0 -0
  318. /package/src/modes/{interactive/theme → theme}/defaults/basalt.json +0 -0
  319. /package/src/modes/{interactive/theme → theme}/defaults/birch.json +0 -0
  320. /package/src/modes/{interactive/theme → theme}/defaults/dark-abyss.json +0 -0
  321. /package/src/modes/{interactive/theme → theme}/defaults/dark-arctic.json +0 -0
  322. /package/src/modes/{interactive/theme → theme}/defaults/dark-aurora.json +0 -0
  323. /package/src/modes/{interactive/theme → theme}/defaults/dark-catppuccin.json +0 -0
  324. /package/src/modes/{interactive/theme → theme}/defaults/dark-cavern.json +0 -0
  325. /package/src/modes/{interactive/theme → theme}/defaults/dark-copper.json +0 -0
  326. /package/src/modes/{interactive/theme → theme}/defaults/dark-cosmos.json +0 -0
  327. /package/src/modes/{interactive/theme → theme}/defaults/dark-cyberpunk.json +0 -0
  328. /package/src/modes/{interactive/theme → theme}/defaults/dark-dracula.json +0 -0
  329. /package/src/modes/{interactive/theme → theme}/defaults/dark-eclipse.json +0 -0
  330. /package/src/modes/{interactive/theme → theme}/defaults/dark-ember.json +0 -0
  331. /package/src/modes/{interactive/theme → theme}/defaults/dark-equinox.json +0 -0
  332. /package/src/modes/{interactive/theme → theme}/defaults/dark-forest.json +0 -0
  333. /package/src/modes/{interactive/theme → theme}/defaults/dark-github.json +0 -0
  334. /package/src/modes/{interactive/theme → theme}/defaults/dark-gruvbox.json +0 -0
  335. /package/src/modes/{interactive/theme → theme}/defaults/dark-lavender.json +0 -0
  336. /package/src/modes/{interactive/theme → theme}/defaults/dark-lunar.json +0 -0
  337. /package/src/modes/{interactive/theme → theme}/defaults/dark-midnight.json +0 -0
  338. /package/src/modes/{interactive/theme → theme}/defaults/dark-monochrome.json +0 -0
  339. /package/src/modes/{interactive/theme → theme}/defaults/dark-monokai.json +0 -0
  340. /package/src/modes/{interactive/theme → theme}/defaults/dark-nebula.json +0 -0
  341. /package/src/modes/{interactive/theme → theme}/defaults/dark-nord.json +0 -0
  342. /package/src/modes/{interactive/theme → theme}/defaults/dark-ocean.json +0 -0
  343. /package/src/modes/{interactive/theme → theme}/defaults/dark-one.json +0 -0
  344. /package/src/modes/{interactive/theme → theme}/defaults/dark-rainforest.json +0 -0
  345. /package/src/modes/{interactive/theme → theme}/defaults/dark-reef.json +0 -0
  346. /package/src/modes/{interactive/theme → theme}/defaults/dark-retro.json +0 -0
  347. /package/src/modes/{interactive/theme → theme}/defaults/dark-rose-pine.json +0 -0
  348. /package/src/modes/{interactive/theme → theme}/defaults/dark-sakura.json +0 -0
  349. /package/src/modes/{interactive/theme → theme}/defaults/dark-slate.json +0 -0
  350. /package/src/modes/{interactive/theme → theme}/defaults/dark-solarized.json +0 -0
  351. /package/src/modes/{interactive/theme → theme}/defaults/dark-solstice.json +0 -0
  352. /package/src/modes/{interactive/theme → theme}/defaults/dark-starfall.json +0 -0
  353. /package/src/modes/{interactive/theme → theme}/defaults/dark-sunset.json +0 -0
  354. /package/src/modes/{interactive/theme → theme}/defaults/dark-swamp.json +0 -0
  355. /package/src/modes/{interactive/theme → theme}/defaults/dark-synthwave.json +0 -0
  356. /package/src/modes/{interactive/theme → theme}/defaults/dark-taiga.json +0 -0
  357. /package/src/modes/{interactive/theme → theme}/defaults/dark-terminal.json +0 -0
  358. /package/src/modes/{interactive/theme → theme}/defaults/dark-tokyo-night.json +0 -0
  359. /package/src/modes/{interactive/theme → theme}/defaults/dark-tundra.json +0 -0
  360. /package/src/modes/{interactive/theme → theme}/defaults/dark-twilight.json +0 -0
  361. /package/src/modes/{interactive/theme → theme}/defaults/dark-volcanic.json +0 -0
  362. /package/src/modes/{interactive/theme → theme}/defaults/graphite.json +0 -0
  363. /package/src/modes/{interactive/theme → theme}/defaults/index.ts +0 -0
  364. /package/src/modes/{interactive/theme → theme}/defaults/light-arctic.json +0 -0
  365. /package/src/modes/{interactive/theme → theme}/defaults/light-aurora-day.json +0 -0
  366. /package/src/modes/{interactive/theme → theme}/defaults/light-canyon.json +0 -0
  367. /package/src/modes/{interactive/theme → theme}/defaults/light-catppuccin.json +0 -0
  368. /package/src/modes/{interactive/theme → theme}/defaults/light-cirrus.json +0 -0
  369. /package/src/modes/{interactive/theme → theme}/defaults/light-coral.json +0 -0
  370. /package/src/modes/{interactive/theme → theme}/defaults/light-cyberpunk.json +0 -0
  371. /package/src/modes/{interactive/theme → theme}/defaults/light-dawn.json +0 -0
  372. /package/src/modes/{interactive/theme → theme}/defaults/light-dunes.json +0 -0
  373. /package/src/modes/{interactive/theme → theme}/defaults/light-eucalyptus.json +0 -0
  374. /package/src/modes/{interactive/theme → theme}/defaults/light-forest.json +0 -0
  375. /package/src/modes/{interactive/theme → theme}/defaults/light-frost.json +0 -0
  376. /package/src/modes/{interactive/theme → theme}/defaults/light-github.json +0 -0
  377. /package/src/modes/{interactive/theme → theme}/defaults/light-glacier.json +0 -0
  378. /package/src/modes/{interactive/theme → theme}/defaults/light-gruvbox.json +0 -0
  379. /package/src/modes/{interactive/theme → theme}/defaults/light-haze.json +0 -0
  380. /package/src/modes/{interactive/theme → theme}/defaults/light-honeycomb.json +0 -0
  381. /package/src/modes/{interactive/theme → theme}/defaults/light-lagoon.json +0 -0
  382. /package/src/modes/{interactive/theme → theme}/defaults/light-lavender.json +0 -0
  383. /package/src/modes/{interactive/theme → theme}/defaults/light-meadow.json +0 -0
  384. /package/src/modes/{interactive/theme → theme}/defaults/light-mint.json +0 -0
  385. /package/src/modes/{interactive/theme → theme}/defaults/light-monochrome.json +0 -0
  386. /package/src/modes/{interactive/theme → theme}/defaults/light-ocean.json +0 -0
  387. /package/src/modes/{interactive/theme → theme}/defaults/light-one.json +0 -0
  388. /package/src/modes/{interactive/theme → theme}/defaults/light-opal.json +0 -0
  389. /package/src/modes/{interactive/theme → theme}/defaults/light-orchard.json +0 -0
  390. /package/src/modes/{interactive/theme → theme}/defaults/light-paper.json +0 -0
  391. /package/src/modes/{interactive/theme → theme}/defaults/light-prism.json +0 -0
  392. /package/src/modes/{interactive/theme → theme}/defaults/light-retro.json +0 -0
  393. /package/src/modes/{interactive/theme → theme}/defaults/light-sand.json +0 -0
  394. /package/src/modes/{interactive/theme → theme}/defaults/light-savanna.json +0 -0
  395. /package/src/modes/{interactive/theme → theme}/defaults/light-solarized.json +0 -0
  396. /package/src/modes/{interactive/theme → theme}/defaults/light-soleil.json +0 -0
  397. /package/src/modes/{interactive/theme → theme}/defaults/light-sunset.json +0 -0
  398. /package/src/modes/{interactive/theme → theme}/defaults/light-synthwave.json +0 -0
  399. /package/src/modes/{interactive/theme → theme}/defaults/light-tokyo-night.json +0 -0
  400. /package/src/modes/{interactive/theme → theme}/defaults/light-wetland.json +0 -0
  401. /package/src/modes/{interactive/theme → theme}/defaults/light-zenith.json +0 -0
  402. /package/src/modes/{interactive/theme → theme}/defaults/limestone.json +0 -0
  403. /package/src/modes/{interactive/theme → theme}/defaults/mahogany.json +0 -0
  404. /package/src/modes/{interactive/theme → theme}/defaults/marble.json +0 -0
  405. /package/src/modes/{interactive/theme → theme}/defaults/obsidian.json +0 -0
  406. /package/src/modes/{interactive/theme → theme}/defaults/onyx.json +0 -0
  407. /package/src/modes/{interactive/theme → theme}/defaults/pearl.json +0 -0
  408. /package/src/modes/{interactive/theme → theme}/defaults/porcelain.json +0 -0
  409. /package/src/modes/{interactive/theme → theme}/defaults/quartz.json +0 -0
  410. /package/src/modes/{interactive/theme → theme}/defaults/sandstone.json +0 -0
  411. /package/src/modes/{interactive/theme → theme}/defaults/titanium.json +0 -0
  412. /package/src/modes/{interactive/theme → theme}/light.json +0 -0
  413. /package/src/modes/{interactive/theme → theme}/theme-schema.json +0 -0
  414. /package/src/{core/tools/patch → patch}/fuzzy.ts +0 -0
  415. /package/src/{core/tools/patch → patch}/normalize.ts +0 -0
  416. /package/src/{core/tools/patch → patch}/normative.ts +0 -0
  417. /package/src/{core/tools/patch → patch}/parser.ts +0 -0
  418. /package/src/{core/tools/patch → patch}/types.ts +0 -0
  419. /package/src/{core → session}/compaction/index.ts +0 -0
  420. /package/src/{core → session}/session-storage.ts +0 -0
  421. /package/src/{core/tools/task → task}/name-generator.ts +0 -0
  422. /package/src/{core/tools/task → task}/omp-command.ts +0 -0
  423. /package/src/{core/tools/task → task}/parallel.ts +0 -0
  424. /package/src/{core/tools → tools}/jtd-to-json-schema.ts +0 -0
  425. /package/src/{core/tools → tools}/path-utils.ts +0 -0
  426. /package/src/{core → utils}/event-bus.ts +0 -0
  427. /package/src/{core → utils}/frontmatter.ts +0 -0
  428. /package/src/{core → utils}/terminal-notify.ts +0 -0
  429. /package/src/{core → utils}/timings.ts +0 -0
  430. /package/src/{core → utils}/utils.ts +0 -0
  431. /package/src/{core/tools/web-scrapers → web/scrapers}/artifacthub.ts +0 -0
  432. /package/src/{core/tools/web-scrapers → web/scrapers}/arxiv.ts +0 -0
  433. /package/src/{core/tools/web-scrapers → web/scrapers}/aur.ts +0 -0
  434. /package/src/{core/tools/web-scrapers → web/scrapers}/biorxiv.ts +0 -0
  435. /package/src/{core/tools/web-scrapers → web/scrapers}/bluesky.ts +0 -0
  436. /package/src/{core/tools/web-scrapers → web/scrapers}/brew.ts +0 -0
  437. /package/src/{core/tools/web-scrapers → web/scrapers}/cheatsh.ts +0 -0
  438. /package/src/{core/tools/web-scrapers → web/scrapers}/chocolatey.ts +0 -0
  439. /package/src/{core/tools/web-scrapers → web/scrapers}/cisa-kev.ts +0 -0
  440. /package/src/{core/tools/web-scrapers → web/scrapers}/clojars.ts +0 -0
  441. /package/src/{core/tools/web-scrapers → web/scrapers}/coingecko.ts +0 -0
  442. /package/src/{core/tools/web-scrapers → web/scrapers}/crates-io.ts +0 -0
  443. /package/src/{core/tools/web-scrapers → web/scrapers}/crossref.ts +0 -0
  444. /package/src/{core/tools/web-scrapers → web/scrapers}/devto.ts +0 -0
  445. /package/src/{core/tools/web-scrapers → web/scrapers}/discogs.ts +0 -0
  446. /package/src/{core/tools/web-scrapers → web/scrapers}/discourse.ts +0 -0
  447. /package/src/{core/tools/web-scrapers → web/scrapers}/dockerhub.ts +0 -0
  448. /package/src/{core/tools/web-scrapers → web/scrapers}/fdroid.ts +0 -0
  449. /package/src/{core/tools/web-scrapers → web/scrapers}/firefox-addons.ts +0 -0
  450. /package/src/{core/tools/web-scrapers → web/scrapers}/flathub.ts +0 -0
  451. /package/src/{core/tools/web-scrapers → web/scrapers}/github-gist.ts +0 -0
  452. /package/src/{core/tools/web-scrapers → web/scrapers}/github.ts +0 -0
  453. /package/src/{core/tools/web-scrapers → web/scrapers}/gitlab.ts +0 -0
  454. /package/src/{core/tools/web-scrapers → web/scrapers}/go-pkg.ts +0 -0
  455. /package/src/{core/tools/web-scrapers → web/scrapers}/hackage.ts +0 -0
  456. /package/src/{core/tools/web-scrapers → web/scrapers}/hackernews.ts +0 -0
  457. /package/src/{core/tools/web-scrapers → web/scrapers}/hex.ts +0 -0
  458. /package/src/{core/tools/web-scrapers → web/scrapers}/huggingface.ts +0 -0
  459. /package/src/{core/tools/web-scrapers → web/scrapers}/iacr.ts +0 -0
  460. /package/src/{core/tools/web-scrapers → web/scrapers}/index.ts +0 -0
  461. /package/src/{core/tools/web-scrapers → web/scrapers}/jetbrains-marketplace.ts +0 -0
  462. /package/src/{core/tools/web-scrapers → web/scrapers}/lemmy.ts +0 -0
  463. /package/src/{core/tools/web-scrapers → web/scrapers}/lobsters.ts +0 -0
  464. /package/src/{core/tools/web-scrapers → web/scrapers}/mastodon.ts +0 -0
  465. /package/src/{core/tools/web-scrapers → web/scrapers}/maven.ts +0 -0
  466. /package/src/{core/tools/web-scrapers → web/scrapers}/mdn.ts +0 -0
  467. /package/src/{core/tools/web-scrapers → web/scrapers}/metacpan.ts +0 -0
  468. /package/src/{core/tools/web-scrapers → web/scrapers}/musicbrainz.ts +0 -0
  469. /package/src/{core/tools/web-scrapers → web/scrapers}/npm.ts +0 -0
  470. /package/src/{core/tools/web-scrapers → web/scrapers}/nuget.ts +0 -0
  471. /package/src/{core/tools/web-scrapers → web/scrapers}/nvd.ts +0 -0
  472. /package/src/{core/tools/web-scrapers → web/scrapers}/ollama.ts +0 -0
  473. /package/src/{core/tools/web-scrapers → web/scrapers}/open-vsx.ts +0 -0
  474. /package/src/{core/tools/web-scrapers → web/scrapers}/opencorporates.ts +0 -0
  475. /package/src/{core/tools/web-scrapers → web/scrapers}/openlibrary.ts +0 -0
  476. /package/src/{core/tools/web-scrapers → web/scrapers}/orcid.ts +0 -0
  477. /package/src/{core/tools/web-scrapers → web/scrapers}/osv.ts +0 -0
  478. /package/src/{core/tools/web-scrapers → web/scrapers}/packagist.ts +0 -0
  479. /package/src/{core/tools/web-scrapers → web/scrapers}/pub-dev.ts +0 -0
  480. /package/src/{core/tools/web-scrapers → web/scrapers}/pubmed.ts +0 -0
  481. /package/src/{core/tools/web-scrapers → web/scrapers}/pypi.ts +0 -0
  482. /package/src/{core/tools/web-scrapers → web/scrapers}/rawg.ts +0 -0
  483. /package/src/{core/tools/web-scrapers → web/scrapers}/readthedocs.ts +0 -0
  484. /package/src/{core/tools/web-scrapers → web/scrapers}/reddit.ts +0 -0
  485. /package/src/{core/tools/web-scrapers → web/scrapers}/repology.ts +0 -0
  486. /package/src/{core/tools/web-scrapers → web/scrapers}/rfc.ts +0 -0
  487. /package/src/{core/tools/web-scrapers → web/scrapers}/rubygems.ts +0 -0
  488. /package/src/{core/tools/web-scrapers → web/scrapers}/searchcode.ts +0 -0
  489. /package/src/{core/tools/web-scrapers → web/scrapers}/sec-edgar.ts +0 -0
  490. /package/src/{core/tools/web-scrapers → web/scrapers}/semantic-scholar.ts +0 -0
  491. /package/src/{core/tools/web-scrapers → web/scrapers}/snapcraft.ts +0 -0
  492. /package/src/{core/tools/web-scrapers → web/scrapers}/sourcegraph.ts +0 -0
  493. /package/src/{core/tools/web-scrapers → web/scrapers}/spdx.ts +0 -0
  494. /package/src/{core/tools/web-scrapers → web/scrapers}/spotify.ts +0 -0
  495. /package/src/{core/tools/web-scrapers → web/scrapers}/stackoverflow.ts +0 -0
  496. /package/src/{core/tools/web-scrapers → web/scrapers}/terraform.ts +0 -0
  497. /package/src/{core/tools/web-scrapers → web/scrapers}/tldr.ts +0 -0
  498. /package/src/{core/tools/web-scrapers → web/scrapers}/vimeo.ts +0 -0
  499. /package/src/{core/tools/web-scrapers → web/scrapers}/vscode-marketplace.ts +0 -0
  500. /package/src/{core/tools/web-scrapers → web/scrapers}/w3c.ts +0 -0
  501. /package/src/{core/tools/web-scrapers → web/scrapers}/wikidata.ts +0 -0
  502. /package/src/{core/tools/web-scrapers → web/scrapers}/wikipedia.ts +0 -0
  503. /package/src/{core/tools/web-search → web/search}/types.ts +0 -0
@@ -6,53 +6,39 @@ import { Text } from "@oh-my-pi/pi-tui";
6
6
  import { ptree, readLines } from "@oh-my-pi/pi-utils";
7
7
  import { Type } from "@sinclair/typebox";
8
8
  import { $ } from "bun";
9
- import { getLanguageFromPath, type Theme } from "../../modes/interactive/theme/theme";
10
- import grepDescription from "../../prompts/tools/grep.md" with { type: "text" };
11
- import { ensureTool } from "../../utils/tools-manager";
12
- import type { RenderResultOptions } from "../custom-tools/types";
13
- import { renderPromptTemplate } from "../prompt-templates";
14
- import { untilAborted } from "../utils";
9
+ import { renderPromptTemplate } from "$c/config/prompt-templates";
10
+ import type { RenderResultOptions } from "$c/extensibility/custom-tools/types";
11
+ import { getLanguageFromPath, type Theme } from "$c/modes/theme/theme";
12
+ import grepDescription from "$c/prompts/tools/grep.md" with { type: "text" };
13
+ import type { OutputMeta } from "$c/tools/output-meta";
14
+ import { ToolAbortError, ToolError } from "$c/tools/tool-errors";
15
+ import { ensureTool } from "$c/utils/tools-manager";
16
+ import { untilAborted } from "$c/utils/utils";
15
17
  import type { ToolSession } from "./index";
18
+ import { applyListLimit } from "./list-limit";
16
19
  import { resolveToCwd } from "./path-utils";
17
20
  import { PREVIEW_LIMITS, ToolUIKit } from "./render-utils";
18
- import {
19
- DEFAULT_MAX_BYTES,
20
- DEFAULT_MAX_COLUMN,
21
- formatSize,
22
- type TruncationResult,
23
- truncateHead,
24
- truncateLine,
25
- } from "./truncate";
21
+ import { toolResult } from "./tool-result";
22
+ import { DEFAULT_MAX_COLUMN, type TruncationResult, truncateHead, truncateLine } from "./truncate";
26
23
 
27
24
  const grepSchema = Type.Object({
28
- pattern: Type.String({ description: "Search pattern (regex or literal string)" }),
29
- path: Type.Optional(Type.String({ description: "Directory or file to search (default: current directory)" })),
30
- glob: Type.Optional(Type.String({ description: "Filter files by glob pattern, e.g. '*.ts' or '**/*.spec.ts'" })),
31
- type: Type.Optional(Type.String({ description: "File type filter (e.g., 'ts', 'rust', 'py')" })),
32
- ignoreCase: Type.Optional(
33
- Type.Boolean({ description: "Force case-insensitive search (default: false, uses smart-case otherwise)" }),
34
- ),
35
- caseSensitive: Type.Optional(
36
- Type.Boolean({ description: "Force case-sensitive search (default: false, disables smart-case)" }),
37
- ),
38
- literal: Type.Optional(
39
- Type.Boolean({ description: "Treat pattern as literal string instead of regex (default: false)" }),
40
- ),
41
- multiline: Type.Optional(
42
- Type.Boolean({ description: "Enable multiline matching for cross-line patterns (default: false)" }),
43
- ),
44
- context: Type.Optional(
45
- Type.Number({ description: "Number of lines to show before and after each match (default: 0)" }),
46
- ),
47
- limit: Type.Optional(Type.Number({ description: "Maximum number of matches to return (default: 100)" })),
48
- outputMode: Type.Optional(
25
+ pattern: Type.String({ description: "Search pattern (regex)" }),
26
+ path: Type.Optional(Type.String({ description: "Directory or file to search (default: cwd)" })),
27
+ glob: Type.Optional(Type.String({ description: "Glob filter, e.g. '*.ts', '**/*.spec.ts'" })),
28
+ type: Type.Optional(Type.String({ description: "File type filter, e.g. 'ts', 'py', 'rust'" })),
29
+ ignore_case: Type.Optional(Type.Boolean({ description: "Force case-insensitive (default: smart-case)" })),
30
+ case_sensitive: Type.Optional(Type.Boolean({ description: "Force case-sensitive (default: smart-case)" })),
31
+ literal: Type.Optional(Type.Boolean({ description: "Treat pattern as literal, not regex (default: false)" })),
32
+ multiline: Type.Optional(Type.Boolean({ description: "Match across line boundaries (default: false)" })),
33
+ context: Type.Optional(Type.Number({ description: "Lines of context before/after match (default: 0)" })),
34
+ limit: Type.Optional(Type.Number({ description: "Max matches to return (default: 100)" })),
35
+ output_mode: Type.Optional(
49
36
  StringEnum(["content", "files_with_matches", "count"], {
50
- description:
51
- "Output mode: 'content' shows matching lines, 'files_with_matches' shows only file paths, 'count' shows match counts per file (default: 'content')",
37
+ description: "Output format (default: content)",
52
38
  }),
53
39
  ),
54
- headLimit: Type.Optional(Type.Number({ description: "Limit output to first N results (default: unlimited)" })),
55
- offset: Type.Optional(Type.Number({ description: "Skip first N results before applying headLimit (default: 0)" })),
40
+ head_limit: Type.Optional(Type.Number({ description: "Truncate output to first N results" })),
41
+ offset: Type.Optional(Type.Number({ description: "Skip first N results (default: 0)" })),
56
42
  });
57
43
 
58
44
  const DEFAULT_LIMIT = 100;
@@ -62,6 +48,7 @@ export interface GrepToolDetails {
62
48
  matchLimitReached?: number;
63
49
  headLimitReached?: number;
64
50
  linesTruncated?: boolean;
51
+ meta?: OutputMeta;
65
52
  // Fields for TUI rendering
66
53
  scopePath?: string;
67
54
  matchCount?: number;
@@ -99,14 +86,14 @@ interface GrepParams {
99
86
  path?: string;
100
87
  glob?: string;
101
88
  type?: string;
102
- ignoreCase?: boolean;
103
- caseSensitive?: boolean;
89
+ ignore_case?: boolean;
90
+ case_sensitive?: boolean;
104
91
  literal?: boolean;
105
92
  multiline?: boolean;
106
93
  context?: number;
107
94
  limit?: number;
108
- outputMode?: "content" | "files_with_matches" | "count";
109
- headLimit?: number;
95
+ output_mode?: "content" | "files_with_matches" | "count";
96
+ head_limit?: number;
110
97
  offset?: number;
111
98
  }
112
99
 
@@ -165,14 +152,14 @@ export class GrepTool implements AgentTool<typeof grepSchema, GrepToolDetails> {
165
152
  path: searchDir,
166
153
  glob,
167
154
  type,
168
- ignoreCase,
169
- caseSensitive,
155
+ ignore_case,
156
+ case_sensitive,
170
157
  literal,
171
158
  multiline,
172
159
  context,
173
160
  limit,
174
- outputMode,
175
- headLimit,
161
+ output_mode,
162
+ head_limit,
176
163
  offset,
177
164
  } = params;
178
165
 
@@ -189,7 +176,7 @@ export class GrepTool implements AgentTool<typeof grepSchema, GrepToolDetails> {
189
176
 
190
177
  const rgPath = await this.rgPath;
191
178
  if (!rgPath) {
192
- throw new Error("ripgrep (rg) is not available and could not be downloaded");
179
+ throw new ToolError("ripgrep (rg) is not available and could not be downloaded");
193
180
  }
194
181
 
195
182
  const searchPath = resolveToCwd(searchDir || ".", this.session.cwd);
@@ -202,13 +189,12 @@ export class GrepTool implements AgentTool<typeof grepSchema, GrepToolDetails> {
202
189
  try {
203
190
  isDirectory = await this.ops.isDirectory(searchPath);
204
191
  } catch {
205
- throw new Error(`Path not found: ${searchPath}`);
192
+ throw new ToolError(`Path not found: ${searchPath}`);
206
193
  }
207
194
  const contextValue = context && context > 0 ? context : 0;
208
195
  const effectiveLimit = Math.max(1, limit ?? DEFAULT_LIMIT);
209
- const effectiveOutputMode = outputMode ?? "content";
196
+ const effectiveOutputMode = output_mode ?? "content";
210
197
  const effectiveOffset = offset && offset > 0 ? offset : 0;
211
- const hasHeadLimit = headLimit !== undefined && headLimit > 0;
212
198
 
213
199
  const formatPath = (filePath: string): string => {
214
200
  if (isDirectory) {
@@ -248,9 +234,9 @@ export class GrepTool implements AgentTool<typeof grepSchema, GrepToolDetails> {
248
234
  args.push("--json", "--line-number", "--color=never", "--hidden");
249
235
  }
250
236
 
251
- if (caseSensitive) {
237
+ if (case_sensitive) {
252
238
  args.push("--case-sensitive");
253
- } else if (ignoreCase) {
239
+ } else if (ignore_case) {
254
240
  args.push("--ignore-case");
255
241
  } else {
256
242
  args.push("--smart-case");
@@ -310,7 +296,7 @@ export class GrepTool implements AgentTool<typeof grepSchema, GrepToolDetails> {
310
296
  const exitCode = child.exitCode ?? 0;
311
297
  if (exitCode !== 0 && exitCode !== 1) {
312
298
  const errorMsg = child.peekStderr().trim() || `ripgrep exited with code ${exitCode}`;
313
- throw new Error(errorMsg);
299
+ throw new ToolError(errorMsg);
314
300
  }
315
301
 
316
302
  const lines = stdout
@@ -319,27 +305,25 @@ export class GrepTool implements AgentTool<typeof grepSchema, GrepToolDetails> {
319
305
  .filter((line) => line.length > 0);
320
306
 
321
307
  if (lines.length === 0) {
322
- return {
323
- content: [{ type: "text", text: "No matches found" }],
324
- details: {
325
- scopePath,
326
- matchCount: 0,
327
- fileCount: 0,
328
- files: [],
329
- mode: effectiveOutputMode,
330
- truncated: false,
331
- },
308
+ const details: GrepToolDetails = {
309
+ scopePath,
310
+ matchCount: 0,
311
+ fileCount: 0,
312
+ files: [],
313
+ mode: effectiveOutputMode,
314
+ truncated: false,
332
315
  };
316
+ return toolResult(details).text("No matches found").done();
333
317
  }
334
318
 
335
- // Apply offset and headLimit
336
- let processedLines = lines;
337
- if (effectiveOffset > 0) {
338
- processedLines = processedLines.slice(effectiveOffset);
339
- }
340
- if (hasHeadLimit) {
341
- processedLines = processedLines.slice(0, headLimit);
342
- }
319
+ const offsetLines = effectiveOffset > 0 ? lines.slice(effectiveOffset) : lines;
320
+ const listLimit = applyListLimit(offsetLines, {
321
+ limit: effectiveLimit,
322
+ headLimit: head_limit,
323
+ limitType: "result",
324
+ });
325
+ const processedLines = listLimit.items;
326
+ const limitMeta = listLimit.meta;
343
327
 
344
328
  let simpleMatchCount = 0;
345
329
  let fileCount = 0;
@@ -382,7 +366,7 @@ export class GrepTool implements AgentTool<typeof grepSchema, GrepToolDetails> {
382
366
  fileCount = simpleFiles.size;
383
367
  }
384
368
 
385
- const truncatedByHeadLimit = hasHeadLimit && processedLines.length < lines.length;
369
+ const truncatedByLimit = Boolean(limitMeta.resultLimit || limitMeta.headLimit);
386
370
 
387
371
  // For count mode, format as "path:count"
388
372
  if (effectiveOutputMode === "count") {
@@ -393,39 +377,47 @@ export class GrepTool implements AgentTool<typeof grepSchema, GrepToolDetails> {
393
377
  return `${relative}:${count}`;
394
378
  });
395
379
  const output = formatted.join("\n");
396
- return {
397
- content: [{ type: "text", text: output }],
398
- details: {
399
- scopePath,
400
- matchCount: simpleMatchCount,
401
- fileCount,
402
- files: simpleFileList,
403
- fileMatches: simpleFileList.map((path) => ({
404
- path,
405
- count: simpleFileMatchCounts.get(path) ?? 0,
406
- })),
407
- mode: effectiveOutputMode,
408
- truncated: truncatedByHeadLimit,
409
- headLimitReached: truncatedByHeadLimit ? headLimit : undefined,
410
- },
380
+ const details: GrepToolDetails = {
381
+ scopePath,
382
+ matchCount: simpleMatchCount,
383
+ fileCount,
384
+ files: simpleFileList,
385
+ fileMatches: simpleFileList.map((path) => ({
386
+ path,
387
+ count: simpleFileMatchCounts.get(path) ?? 0,
388
+ })),
389
+ mode: effectiveOutputMode,
390
+ truncated: truncatedByLimit,
391
+ headLimitReached: limitMeta.headLimit?.reached,
411
392
  };
393
+ return toolResult(details)
394
+ .text(output)
395
+ .limits({
396
+ resultLimit: limitMeta.resultLimit?.reached,
397
+ headLimit: limitMeta.headLimit?.reached,
398
+ })
399
+ .done();
412
400
  }
413
401
 
414
402
  // For files_with_matches, format paths
415
403
  const formatted = processedLines.map((line) => formatPath(line));
416
404
  const output = formatted.join("\n");
417
- return {
418
- content: [{ type: "text", text: output }],
419
- details: {
420
- scopePath,
421
- matchCount: simpleMatchCount,
422
- fileCount,
423
- files: simpleFileList,
424
- mode: effectiveOutputMode,
425
- truncated: truncatedByHeadLimit,
426
- headLimitReached: truncatedByHeadLimit ? headLimit : undefined,
427
- },
405
+ const details: GrepToolDetails = {
406
+ scopePath,
407
+ matchCount: simpleMatchCount,
408
+ fileCount,
409
+ files: simpleFileList,
410
+ mode: effectiveOutputMode,
411
+ truncated: truncatedByLimit,
412
+ headLimitReached: limitMeta.headLimit?.reached,
428
413
  };
414
+ return toolResult(details)
415
+ .text(output)
416
+ .limits({
417
+ resultLimit: limitMeta.resultLimit?.reached,
418
+ headLimit: limitMeta.headLimit?.reached,
419
+ })
420
+ .done();
429
421
  }
430
422
 
431
423
  // Content mode - existing JSON processing
@@ -499,7 +491,7 @@ export class GrepTool implements AgentTool<typeof grepSchema, GrepToolDetails> {
499
491
  }
500
492
  } catch (err) {
501
493
  if (err instanceof ptree.Exception && err.aborted) {
502
- throw new Error("Operation aborted");
494
+ throw new ToolAbortError();
503
495
  }
504
496
  // Stream may close early if we killed due to limit - that's ok
505
497
  if (!killedDueToLimit) {
@@ -513,12 +505,12 @@ export class GrepTool implements AgentTool<typeof grepSchema, GrepToolDetails> {
513
505
  } catch (err) {
514
506
  if (err instanceof ptree.Exception) {
515
507
  if (err.aborted) {
516
- throw new Error("Operation aborted");
508
+ throw new ToolAbortError();
517
509
  }
518
510
  // Non-zero exit is ok if we killed due to limit or exit code 1 (no matches)
519
511
  if (!killedDueToLimit && err.exitCode !== 1) {
520
512
  const errorMsg = child.peekStderr().trim() || `ripgrep exited with code ${err.exitCode}`;
521
- throw new Error(errorMsg);
513
+ throw new ToolError(errorMsg);
522
514
  }
523
515
  } else {
524
516
  throw err;
@@ -526,34 +518,29 @@ export class GrepTool implements AgentTool<typeof grepSchema, GrepToolDetails> {
526
518
  }
527
519
 
528
520
  if (matchCount === 0) {
529
- return {
530
- content: [{ type: "text", text: "No matches found" }],
531
- details: {
532
- scopePath,
533
- matchCount: 0,
534
- fileCount: 0,
535
- files: [],
536
- mode: effectiveOutputMode,
537
- truncated: false,
538
- },
521
+ const details: GrepToolDetails = {
522
+ scopePath,
523
+ matchCount: 0,
524
+ fileCount: 0,
525
+ files: [],
526
+ mode: effectiveOutputMode,
527
+ truncated: false,
539
528
  };
529
+ return toolResult(details).text("No matches found").done();
540
530
  }
541
531
 
542
- // Apply offset and headLimit to output lines
543
- let processedLines = outputLines;
544
- if (effectiveOffset > 0) {
545
- processedLines = processedLines.slice(effectiveOffset);
546
- }
547
- if (hasHeadLimit) {
548
- processedLines = processedLines.slice(0, headLimit);
549
- }
532
+ // Apply offset and head_limit to output lines
533
+ let processedLines = effectiveOffset > 0 ? outputLines.slice(effectiveOffset) : outputLines;
534
+ const listLimit = applyListLimit(processedLines, { headLimit: head_limit });
535
+ processedLines = listLimit.items;
536
+ const limitMeta = listLimit.meta;
550
537
 
551
538
  // Apply byte truncation (no line limit since we already have match limit)
552
539
  const rawOutput = processedLines.join("\n");
553
540
  const truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });
554
541
 
555
- let output = truncation.content;
556
- const truncatedByHeadLimit = hasHeadLimit && processedLines.length < outputLines.length;
542
+ const output = truncation.content;
543
+ const truncated = Boolean(matchLimitReached || truncation.truncated || limitMeta.headLimit || linesTruncated);
557
544
  const details: GrepToolDetails = {
558
545
  scopePath,
559
546
  matchCount,
@@ -564,38 +551,27 @@ export class GrepTool implements AgentTool<typeof grepSchema, GrepToolDetails> {
564
551
  count: fileMatchCounts.get(path) ?? 0,
565
552
  })),
566
553
  mode: effectiveOutputMode,
567
- truncated: matchLimitReached || truncation.truncated || truncatedByHeadLimit,
568
- headLimitReached: truncatedByHeadLimit ? headLimit : undefined,
554
+ truncated,
555
+ headLimitReached: limitMeta.headLimit?.reached,
569
556
  };
570
557
 
571
- // Build notices
572
- const notices: string[] = [];
573
-
574
- if (matchLimitReached) {
575
- notices.push(
576
- `${effectiveLimit} matches limit reached. Use limit=${effectiveLimit * 2} for more, or refine pattern`,
577
- );
578
- details.matchLimitReached = effectiveLimit;
579
- }
580
-
558
+ // Keep TUI compatibility fields
559
+ if (matchLimitReached) details.matchLimitReached = effectiveLimit;
560
+ if (truncation.truncated) details.truncation = truncation;
561
+ if (linesTruncated) details.linesTruncated = true;
562
+
563
+ const resultBuilder = toolResult(details)
564
+ .text(output)
565
+ .limits({
566
+ matchLimit: matchLimitReached ? effectiveLimit : undefined,
567
+ headLimit: limitMeta.headLimit?.reached,
568
+ columnMax: linesTruncated ? DEFAULT_MAX_COLUMN : undefined,
569
+ });
581
570
  if (truncation.truncated) {
582
- notices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);
583
- details.truncation = truncation;
584
- }
585
-
586
- if (linesTruncated) {
587
- notices.push(`Some lines truncated to ${DEFAULT_MAX_COLUMN} chars. Use read tool to see full lines`);
588
- details.linesTruncated = true;
571
+ resultBuilder.truncation(truncation, { direction: "head" });
589
572
  }
590
573
 
591
- if (notices.length > 0) {
592
- output += `\n\n[${notices.join(". ")}]`;
593
- }
594
-
595
- return {
596
- content: [{ type: "text", text: output }],
597
- details,
598
- };
574
+ return resultBuilder.done();
599
575
  });
600
576
  }
601
577
  }
@@ -609,13 +585,13 @@ interface GrepRenderArgs {
609
585
  path?: string;
610
586
  glob?: string;
611
587
  type?: string;
612
- ignoreCase?: boolean;
613
- caseSensitive?: boolean;
588
+ ignore_case?: boolean;
589
+ case_sensitive?: boolean;
614
590
  literal?: boolean;
615
591
  multiline?: boolean;
616
592
  context?: number;
617
593
  limit?: number;
618
- outputMode?: string;
594
+ output_mode?: string;
619
595
  }
620
596
 
621
597
  const COLLAPSED_LIST_LIMIT = PREVIEW_LIMITS.COLLAPSED_ITEMS;
@@ -632,10 +608,10 @@ export const grepToolRenderer = {
632
608
  if (args.path) meta.push(`in ${args.path}`);
633
609
  if (args.glob) meta.push(`glob:${args.glob}`);
634
610
  if (args.type) meta.push(`type:${args.type}`);
635
- if (args.outputMode && args.outputMode !== "files_with_matches") meta.push(`mode:${args.outputMode}`);
636
- if (args.caseSensitive) {
611
+ if (args.output_mode && args.output_mode !== "files_with_matches") meta.push(`mode:${args.output_mode}`);
612
+ if (args.case_sensitive) {
637
613
  meta.push("case:sensitive");
638
- } else if (args.ignoreCase) {
614
+ } else if (args.ignore_case) {
639
615
  meta.push("case:insensitive");
640
616
  }
641
617
  if (args.literal) meta.push("literal");
@@ -696,7 +672,16 @@ export const grepToolRenderer = {
696
672
  const matchCount = details?.matchCount ?? 0;
697
673
  const fileCount = details?.fileCount ?? 0;
698
674
  const mode = details?.mode ?? "files_with_matches";
699
- const truncated = details?.truncated ?? details?.truncation?.truncated ?? false;
675
+ const truncation = details?.meta?.truncation;
676
+ const limits = details?.meta?.limits;
677
+ const truncated = Boolean(
678
+ details?.truncated ||
679
+ truncation ||
680
+ limits?.matchLimit ||
681
+ limits?.resultLimit ||
682
+ limits?.headLimit ||
683
+ limits?.columnTruncated,
684
+ );
700
685
  const files = details?.files ?? [];
701
686
 
702
687
  if (matchCount === 0) {
@@ -721,17 +706,23 @@ export const grepToolRenderer = {
721
706
  let text = ` ${icon} ${uiTheme.fg("dim", summaryText)}${ui.truncationSuffix(truncated)}${scopeLabel}${expandHint}`;
722
707
 
723
708
  const truncationReasons: string[] = [];
724
- if (details?.matchLimitReached) {
725
- truncationReasons.push(`limit ${details.matchLimitReached} matches`);
709
+ if (limits?.matchLimit) {
710
+ truncationReasons.push(`limit ${limits.matchLimit.reached} matches`);
711
+ }
712
+ if (limits?.resultLimit) {
713
+ truncationReasons.push(`limit ${limits.resultLimit.reached} results`);
714
+ }
715
+ if (limits?.headLimit) {
716
+ truncationReasons.push(`head limit ${limits.headLimit.reached}`);
726
717
  }
727
- if (details?.headLimitReached) {
728
- truncationReasons.push(`head limit ${details.headLimitReached}`);
718
+ if (truncation) {
719
+ truncationReasons.push(truncation.truncatedBy === "lines" ? "line limit" : "size limit");
729
720
  }
730
- if (details?.truncation?.truncated) {
731
- truncationReasons.push("size limit");
721
+ if (limits?.columnTruncated) {
722
+ truncationReasons.push(`line length ${limits.columnTruncated.maxColumn}`);
732
723
  }
733
- if (details?.linesTruncated) {
734
- truncationReasons.push("line length");
724
+ if (truncation?.artifactId) {
725
+ truncationReasons.push(`full output: artifact://${truncation.artifactId}`);
735
726
  }
736
727
 
737
728
  const hasTruncation = truncationReasons.length > 0;