@kr78/pi-coding-agent 17.2.10

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 (1593) hide show
  1. package/CHANGELOG.md +14861 -0
  2. package/README.md +35 -0
  3. package/dist/CHANGELOG-chtdxh1z.md +14861 -0
  4. package/dist/cli.js +20483 -0
  5. package/dist/template-c2hyaytt.js +1653 -0
  6. package/dist/template-f8wx9vfn.css +1355 -0
  7. package/dist/template-qat058wr.html +55 -0
  8. package/dist/tool-views.generated-jdfmzwmn.js +35 -0
  9. package/examples/README.md +21 -0
  10. package/examples/custom-tools/README.md +104 -0
  11. package/examples/custom-tools/hello/index.ts +20 -0
  12. package/examples/extensions/README.md +142 -0
  13. package/examples/extensions/api-demo.ts +78 -0
  14. package/examples/extensions/chalk-logger.ts +25 -0
  15. package/examples/extensions/hello.ts +31 -0
  16. package/examples/extensions/pirate.ts +43 -0
  17. package/examples/extensions/plan-mode.ts +549 -0
  18. package/examples/extensions/reload-runtime.ts +38 -0
  19. package/examples/extensions/thinking-note.ts +13 -0
  20. package/examples/extensions/tools.ts +145 -0
  21. package/examples/extensions/with-deps/index.ts +36 -0
  22. package/examples/extensions/with-deps/package-lock.json +31 -0
  23. package/examples/extensions/with-deps/package.json +17 -0
  24. package/examples/hooks/README.md +56 -0
  25. package/examples/hooks/auto-commit-on-exit.ts +48 -0
  26. package/examples/hooks/confirm-destructive.ts +58 -0
  27. package/examples/hooks/custom-compaction.ts +115 -0
  28. package/examples/hooks/dirty-repo-guard.ts +51 -0
  29. package/examples/hooks/file-trigger.ts +40 -0
  30. package/examples/hooks/git-checkpoint.ts +52 -0
  31. package/examples/hooks/handoff.ts +149 -0
  32. package/examples/hooks/permission-gate.ts +33 -0
  33. package/examples/hooks/protected-paths.ts +29 -0
  34. package/examples/hooks/qna.ts +118 -0
  35. package/examples/hooks/status-line.ts +39 -0
  36. package/examples/sdk/01-minimal.ts +21 -0
  37. package/examples/sdk/02-custom-model.ts +49 -0
  38. package/examples/sdk/03-custom-prompt.ts +46 -0
  39. package/examples/sdk/04-skills.ts +43 -0
  40. package/examples/sdk/06-extensions.ts +82 -0
  41. package/examples/sdk/06-hooks.ts +61 -0
  42. package/examples/sdk/07-context-files.ts +35 -0
  43. package/examples/sdk/08-prompt-templates.ts +41 -0
  44. package/examples/sdk/08-slash-commands.ts +46 -0
  45. package/examples/sdk/09-api-keys-and-oauth.ts +54 -0
  46. package/examples/sdk/11-sessions.ts +47 -0
  47. package/examples/sdk/12-redis-sessions.ts +54 -0
  48. package/examples/sdk/13-sql-sessions.ts +61 -0
  49. package/examples/sdk/README.md +169 -0
  50. package/package.json +587 -0
  51. package/scripts/bench-guard.ts +71 -0
  52. package/scripts/bench-title-models.ts +332 -0
  53. package/scripts/build-binary.ts +117 -0
  54. package/scripts/bundle-dist.ts +123 -0
  55. package/scripts/compile-binary.ts +69 -0
  56. package/scripts/embed-mupdf-wasm.ts +67 -0
  57. package/scripts/format-prompts.ts +68 -0
  58. package/scripts/generate-aria-snapshot.ts +134 -0
  59. package/scripts/generate-docs-index.ts +58 -0
  60. package/scripts/generate-share-viewer.ts +34 -0
  61. package/scripts/legacy-pi-virtual-module.ts +205 -0
  62. package/scripts/measure-prompt-tokens.ts +63 -0
  63. package/scripts/omp +51 -0
  64. package/scripts/omp.ts +19 -0
  65. package/scripts/security-compare.ts +40 -0
  66. package/src/advisor/advise-tool.ts +234 -0
  67. package/src/advisor/config.ts +341 -0
  68. package/src/advisor/emission-guard.ts +172 -0
  69. package/src/advisor/index.ts +6 -0
  70. package/src/advisor/runtime.ts +1412 -0
  71. package/src/advisor/transcript-recorder.ts +215 -0
  72. package/src/advisor/watchdog.ts +135 -0
  73. package/src/async/index.ts +1 -0
  74. package/src/async/job-manager.ts +847 -0
  75. package/src/auto-thinking/classifier.ts +220 -0
  76. package/src/autolearn/controller.ts +152 -0
  77. package/src/autolearn/managed-skills.ts +255 -0
  78. package/src/autoresearch/command-resume.md +14 -0
  79. package/src/autoresearch/dashboard.ts +436 -0
  80. package/src/autoresearch/git.ts +331 -0
  81. package/src/autoresearch/helpers.ts +218 -0
  82. package/src/autoresearch/index.ts +541 -0
  83. package/src/autoresearch/prompt-setup.md +43 -0
  84. package/src/autoresearch/prompt.md +103 -0
  85. package/src/autoresearch/resume-message.md +10 -0
  86. package/src/autoresearch/state.ts +273 -0
  87. package/src/autoresearch/storage.ts +700 -0
  88. package/src/autoresearch/tools/init-experiment.ts +268 -0
  89. package/src/autoresearch/tools/log-experiment.ts +520 -0
  90. package/src/autoresearch/tools/run-experiment.ts +407 -0
  91. package/src/autoresearch/tools/update-notes.ts +109 -0
  92. package/src/autoresearch/types.ts +168 -0
  93. package/src/capability/context-file.ts +44 -0
  94. package/src/capability/extension-module.ts +34 -0
  95. package/src/capability/extension.ts +47 -0
  96. package/src/capability/fs.ts +117 -0
  97. package/src/capability/hook.ts +40 -0
  98. package/src/capability/index.ts +467 -0
  99. package/src/capability/instruction.ts +37 -0
  100. package/src/capability/mcp.ts +115 -0
  101. package/src/capability/prompt.ts +35 -0
  102. package/src/capability/rule-buckets.ts +66 -0
  103. package/src/capability/rule.ts +298 -0
  104. package/src/capability/settings.ts +34 -0
  105. package/src/capability/skill.ts +69 -0
  106. package/src/capability/slash-command.ts +40 -0
  107. package/src/capability/ssh.ts +41 -0
  108. package/src/capability/system-prompt.ts +34 -0
  109. package/src/capability/tool.ts +38 -0
  110. package/src/capability/types.ts +187 -0
  111. package/src/cleanse/agent.ts +226 -0
  112. package/src/cleanse/balance.ts +79 -0
  113. package/src/cleanse/checkers.ts +996 -0
  114. package/src/cleanse/index.ts +190 -0
  115. package/src/cleanse/loop.ts +51 -0
  116. package/src/cleanse/parsers.ts +726 -0
  117. package/src/cleanse/progress.ts +50 -0
  118. package/src/cleanse/prompts/assignment.md +47 -0
  119. package/src/cleanse/types.ts +72 -0
  120. package/src/cli/agents-cli.ts +138 -0
  121. package/src/cli/args.ts +368 -0
  122. package/src/cli/auth-broker-cli.ts +940 -0
  123. package/src/cli/auth-gateway-cli.ts +674 -0
  124. package/src/cli/bench-cli.ts +990 -0
  125. package/src/cli/browser-relay-cli.ts +119 -0
  126. package/src/cli/classify-install-target.ts +76 -0
  127. package/src/cli/claude-trace-cli.ts +795 -0
  128. package/src/cli/command-help.ts +107 -0
  129. package/src/cli/commands/init-xdg.ts +27 -0
  130. package/src/cli/completion-gen.ts +550 -0
  131. package/src/cli/config-cli.ts +459 -0
  132. package/src/cli/dry-balance-cli.ts +864 -0
  133. package/src/cli/extension-flags.ts +48 -0
  134. package/src/cli/file-processor.ts +132 -0
  135. package/src/cli/flag-tables.ts +367 -0
  136. package/src/cli/gallery-cli.ts +272 -0
  137. package/src/cli/gallery-fixtures/agentic.ts +420 -0
  138. package/src/cli/gallery-fixtures/codeintel.ts +187 -0
  139. package/src/cli/gallery-fixtures/edit.ts +254 -0
  140. package/src/cli/gallery-fixtures/fs.ts +245 -0
  141. package/src/cli/gallery-fixtures/index.ts +40 -0
  142. package/src/cli/gallery-fixtures/interaction.ts +46 -0
  143. package/src/cli/gallery-fixtures/memory.ts +81 -0
  144. package/src/cli/gallery-fixtures/misc.ts +177 -0
  145. package/src/cli/gallery-fixtures/search.ts +135 -0
  146. package/src/cli/gallery-fixtures/shell.ts +241 -0
  147. package/src/cli/gallery-fixtures/types.ts +57 -0
  148. package/src/cli/gallery-fixtures/web.ts +158 -0
  149. package/src/cli/gallery-screenshot.ts +279 -0
  150. package/src/cli/gc-cli.ts +1566 -0
  151. package/src/cli/grep-cli.ts +161 -0
  152. package/src/cli/grievances-cli.ts +256 -0
  153. package/src/cli/help-extra.ts +89 -0
  154. package/src/cli/initial-message.ts +58 -0
  155. package/src/cli/models-cli.ts +385 -0
  156. package/src/cli/plugin-cli.ts +996 -0
  157. package/src/cli/profile-alias.ts +369 -0
  158. package/src/cli/profile-bootstrap.ts +233 -0
  159. package/src/cli/read-cli.ts +99 -0
  160. package/src/cli/session-picker.ts +110 -0
  161. package/src/cli/setup-cli.ts +312 -0
  162. package/src/cli/setup-model-picker.ts +43 -0
  163. package/src/cli/shell-cli.ts +176 -0
  164. package/src/cli/ssh-cli.ts +179 -0
  165. package/src/cli/startup-cwd.ts +58 -0
  166. package/src/cli/stats-cli.ts +229 -0
  167. package/src/cli/thinking-levels.ts +7 -0
  168. package/src/cli/tiny-models-cli.ts +153 -0
  169. package/src/cli/ttsr-cli.ts +1013 -0
  170. package/src/cli/update-cli.ts +1184 -0
  171. package/src/cli/usage-cli.ts +1084 -0
  172. package/src/cli/usage-error.ts +7 -0
  173. package/src/cli/web-search-cli.ts +144 -0
  174. package/src/cli/worktree-cli.ts +311 -0
  175. package/src/cli-commands.ts +308 -0
  176. package/src/cli.ts +428 -0
  177. package/src/collab/crypto.ts +63 -0
  178. package/src/collab/display-name.ts +13 -0
  179. package/src/collab/guest.ts +764 -0
  180. package/src/collab/host.ts +692 -0
  181. package/src/collab/protocol.ts +296 -0
  182. package/src/collab/relay-client.ts +282 -0
  183. package/src/collab/replication-shrink.ts +111 -0
  184. package/src/commands/acp.ts +35 -0
  185. package/src/commands/agents.ts +58 -0
  186. package/src/commands/auth-broker.ts +100 -0
  187. package/src/commands/auth-gateway.ts +70 -0
  188. package/src/commands/bench.ts +64 -0
  189. package/src/commands/browser-relay.ts +53 -0
  190. package/src/commands/cleanse.ts +45 -0
  191. package/src/commands/commit.ts +47 -0
  192. package/src/commands/complete.ts +67 -0
  193. package/src/commands/completions.ts +61 -0
  194. package/src/commands/config.ts +52 -0
  195. package/src/commands/dry-balance.ts +43 -0
  196. package/src/commands/gallery.ts +61 -0
  197. package/src/commands/gc.ts +47 -0
  198. package/src/commands/grep.ts +49 -0
  199. package/src/commands/grievances.ts +52 -0
  200. package/src/commands/install.ts +107 -0
  201. package/src/commands/join.ts +40 -0
  202. package/src/commands/launch-help.ts +116 -0
  203. package/src/commands/launch.ts +34 -0
  204. package/src/commands/models.ts +61 -0
  205. package/src/commands/plugin.ts +79 -0
  206. package/src/commands/read.ts +39 -0
  207. package/src/commands/say.ts +146 -0
  208. package/src/commands/setup.ts +68 -0
  209. package/src/commands/share.ts +71 -0
  210. package/src/commands/shell.ts +30 -0
  211. package/src/commands/ssh.ts +61 -0
  212. package/src/commands/stats.ts +30 -0
  213. package/src/commands/tiny-models.ts +36 -0
  214. package/src/commands/token.ts +164 -0
  215. package/src/commands/ttsr.ts +125 -0
  216. package/src/commands/update.ts +34 -0
  217. package/src/commands/usage.ts +55 -0
  218. package/src/commands/web-search.ts +43 -0
  219. package/src/commands/worktree.ts +63 -0
  220. package/src/commit/agentic/agent.ts +322 -0
  221. package/src/commit/agentic/fallback.ts +96 -0
  222. package/src/commit/agentic/index.ts +383 -0
  223. package/src/commit/agentic/lock-files.ts +107 -0
  224. package/src/commit/agentic/prompts/analyze-file.md +22 -0
  225. package/src/commit/agentic/prompts/session-user.md +25 -0
  226. package/src/commit/agentic/prompts/split-confirm.md +1 -0
  227. package/src/commit/agentic/prompts/system.md +38 -0
  228. package/src/commit/agentic/state.ts +60 -0
  229. package/src/commit/agentic/tools/analyze-file.ts +148 -0
  230. package/src/commit/agentic/tools/git-file-diff.ts +191 -0
  231. package/src/commit/agentic/tools/git-hunk.ts +52 -0
  232. package/src/commit/agentic/tools/git-overview.ts +62 -0
  233. package/src/commit/agentic/tools/index.ts +54 -0
  234. package/src/commit/agentic/tools/propose-changelog.ts +147 -0
  235. package/src/commit/agentic/tools/propose-commit.ts +109 -0
  236. package/src/commit/agentic/tools/recent-commits.ts +81 -0
  237. package/src/commit/agentic/tools/schemas.ts +11 -0
  238. package/src/commit/agentic/tools/split-commit.ts +241 -0
  239. package/src/commit/agentic/topo-sort.ts +44 -0
  240. package/src/commit/agentic/trivial.ts +51 -0
  241. package/src/commit/agentic/validation.ts +183 -0
  242. package/src/commit/analysis/conventional.ts +64 -0
  243. package/src/commit/analysis/index.ts +4 -0
  244. package/src/commit/analysis/scope.ts +242 -0
  245. package/src/commit/analysis/summary.ts +107 -0
  246. package/src/commit/analysis/validation.ts +66 -0
  247. package/src/commit/changelog/detect.ts +40 -0
  248. package/src/commit/changelog/generate.ts +101 -0
  249. package/src/commit/changelog/index.ts +234 -0
  250. package/src/commit/changelog/parse.ts +44 -0
  251. package/src/commit/cli.ts +85 -0
  252. package/src/commit/git/diff.ts +148 -0
  253. package/src/commit/index.ts +5 -0
  254. package/src/commit/map-reduce/index.ts +69 -0
  255. package/src/commit/map-reduce/map-phase.ts +193 -0
  256. package/src/commit/map-reduce/reduce-phase.ts +49 -0
  257. package/src/commit/map-reduce/utils.ts +9 -0
  258. package/src/commit/message.ts +11 -0
  259. package/src/commit/model-selection.ts +95 -0
  260. package/src/commit/pipeline.ts +244 -0
  261. package/src/commit/prompts/analysis-system.md +148 -0
  262. package/src/commit/prompts/analysis-user.md +38 -0
  263. package/src/commit/prompts/changelog-system.md +50 -0
  264. package/src/commit/prompts/changelog-user.md +18 -0
  265. package/src/commit/prompts/file-observer-system.md +24 -0
  266. package/src/commit/prompts/file-observer-user.md +8 -0
  267. package/src/commit/prompts/reduce-system.md +50 -0
  268. package/src/commit/prompts/reduce-user.md +17 -0
  269. package/src/commit/prompts/summary-retry.md +3 -0
  270. package/src/commit/prompts/summary-system.md +38 -0
  271. package/src/commit/prompts/summary-user.md +13 -0
  272. package/src/commit/prompts/types-description.md +2 -0
  273. package/src/commit/shared-llm.ts +70 -0
  274. package/src/commit/types.ts +118 -0
  275. package/src/commit/utils/exclusions.ts +42 -0
  276. package/src/commit/utils.ts +58 -0
  277. package/src/config/api-key-resolver.ts +81 -0
  278. package/src/config/append-only-context-mode.ts +76 -0
  279. package/src/config/config-file.ts +347 -0
  280. package/src/config/inline-tool-descriptors-mode.ts +26 -0
  281. package/src/config/keybindings.ts +703 -0
  282. package/src/config/mcp-schema.json +252 -0
  283. package/src/config/model-discovery.ts +1077 -0
  284. package/src/config/model-registry.ts +2822 -0
  285. package/src/config/model-resolver.ts +2115 -0
  286. package/src/config/model-roles.ts +113 -0
  287. package/src/config/models-config-schema-bundle.ts +315 -0
  288. package/src/config/models-config-schema.ts +14 -0
  289. package/src/config/models-config.ts +130 -0
  290. package/src/config/prompt-templates.ts +205 -0
  291. package/src/config/provider-globals.ts +25 -0
  292. package/src/config/resolve-config-value.ts +95 -0
  293. package/src/config/service-tier.ts +146 -0
  294. package/src/config/settings-schema.ts +5887 -0
  295. package/src/config/settings.ts +2394 -0
  296. package/src/config.ts +242 -0
  297. package/src/cursor-bridge-tools.ts +81 -0
  298. package/src/cursor.ts +960 -0
  299. package/src/dap/client.ts +1043 -0
  300. package/src/dap/config.ts +480 -0
  301. package/src/dap/defaults.json +212 -0
  302. package/src/dap/index.ts +4 -0
  303. package/src/dap/session.ts +1841 -0
  304. package/src/dap/types.ts +611 -0
  305. package/src/debug/index.ts +584 -0
  306. package/src/debug/log-formatting.ts +58 -0
  307. package/src/debug/log-viewer.ts +966 -0
  308. package/src/debug/profiler.ts +168 -0
  309. package/src/debug/protocol-probe.ts +267 -0
  310. package/src/debug/raw-sse-buffer.ts +421 -0
  311. package/src/debug/raw-sse.ts +312 -0
  312. package/src/debug/remote-debugger.ts +151 -0
  313. package/src/debug/report-bundle.ts +411 -0
  314. package/src/debug/system-info.ts +111 -0
  315. package/src/debug/terminal-info.ts +124 -0
  316. package/src/discovery/agent-plugin-format.ts +551 -0
  317. package/src/discovery/agent-plugins.ts +341 -0
  318. package/src/discovery/agents-md.ts +67 -0
  319. package/src/discovery/agents.ts +300 -0
  320. package/src/discovery/at-imports.ts +273 -0
  321. package/src/discovery/builtin-defaults.ts +39 -0
  322. package/src/discovery/builtin-rules/go-add-cleanup.md +33 -0
  323. package/src/discovery/builtin-rules/go-bench-loop.md +36 -0
  324. package/src/discovery/builtin-rules/go-exp-promoted.md +40 -0
  325. package/src/discovery/builtin-rules/go-ioutil.md +37 -0
  326. package/src/discovery/builtin-rules/go-join-hostport.md +30 -0
  327. package/src/discovery/builtin-rules/go-new-expr.md +44 -0
  328. package/src/discovery/builtin-rules/go-rand-v2.md +41 -0
  329. package/src/discovery/builtin-rules/go-range-int.md +45 -0
  330. package/src/discovery/builtin-rules/index.ts +74 -0
  331. package/src/discovery/builtin-rules/rs-box-leak.md +49 -0
  332. package/src/discovery/builtin-rules/rs-future-prelude.md +24 -0
  333. package/src/discovery/builtin-rules/rs-lazylock.md +52 -0
  334. package/src/discovery/builtin-rules/rs-match-ergonomics.md +68 -0
  335. package/src/discovery/builtin-rules/rs-parking-lot.md +45 -0
  336. package/src/discovery/builtin-rules/rs-result-type.md +20 -0
  337. package/src/discovery/builtin-rules/ts-bare-catch.md +39 -0
  338. package/src/discovery/builtin-rules/ts-import-type.md +43 -0
  339. package/src/discovery/builtin-rules/ts-no-any.md +66 -0
  340. package/src/discovery/builtin-rules/ts-no-deprecated-leftovers.md +45 -0
  341. package/src/discovery/builtin-rules/ts-no-dynamic-import.md +40 -0
  342. package/src/discovery/builtin-rules/ts-no-inline-cast-access.md +56 -0
  343. package/src/discovery/builtin-rules/ts-no-local-is-record.md +48 -0
  344. package/src/discovery/builtin-rules/ts-no-return-type.md +45 -0
  345. package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
  346. package/src/discovery/builtin-rules/ts-no-tiny-functions.md +51 -0
  347. package/src/discovery/builtin-rules/ts-promise-with-resolvers.md +66 -0
  348. package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
  349. package/src/discovery/builtin-rules/ts-set-map.md +28 -0
  350. package/src/discovery/builtin.ts +945 -0
  351. package/src/discovery/claude-plugins.ts +640 -0
  352. package/src/discovery/claude.ts +591 -0
  353. package/src/discovery/cline.ts +83 -0
  354. package/src/discovery/codex.ts +553 -0
  355. package/src/discovery/contained-path.ts +78 -0
  356. package/src/discovery/cursor.ts +223 -0
  357. package/src/discovery/gemini.ts +386 -0
  358. package/src/discovery/github.ts +337 -0
  359. package/src/discovery/helpers.ts +1183 -0
  360. package/src/discovery/index.ts +82 -0
  361. package/src/discovery/mcp-json.ts +182 -0
  362. package/src/discovery/omp-extension-roots.ts +272 -0
  363. package/src/discovery/omp-plugins.ts +409 -0
  364. package/src/discovery/opencode.ts +441 -0
  365. package/src/discovery/plugin-dir-roots.ts +28 -0
  366. package/src/discovery/ssh.ts +153 -0
  367. package/src/discovery/substitute-plugin-root.ts +77 -0
  368. package/src/discovery/vscode.ts +106 -0
  369. package/src/discovery/windsurf.ts +149 -0
  370. package/src/edit/apply-patch/index.ts +87 -0
  371. package/src/edit/apply-patch/parser.ts +174 -0
  372. package/src/edit/diff.ts +1008 -0
  373. package/src/edit/edit-clipboard.ts +23 -0
  374. package/src/edit/file-snapshot-store.ts +148 -0
  375. package/src/edit/hashline/block-resolver.ts +33 -0
  376. package/src/edit/hashline/diff.ts +402 -0
  377. package/src/edit/hashline/execute.ts +313 -0
  378. package/src/edit/hashline/filesystem.ts +247 -0
  379. package/src/edit/hashline/index.ts +5 -0
  380. package/src/edit/hashline/noop-loop-guard.ts +99 -0
  381. package/src/edit/hashline/params.ts +12 -0
  382. package/src/edit/index.ts +699 -0
  383. package/src/edit/modes/apply-patch.lark +19 -0
  384. package/src/edit/modes/apply-patch.ts +53 -0
  385. package/src/edit/modes/patch.ts +1958 -0
  386. package/src/edit/modes/replace.ts +1191 -0
  387. package/src/edit/normalize.ts +345 -0
  388. package/src/edit/notebook.ts +242 -0
  389. package/src/edit/read-file.ts +25 -0
  390. package/src/edit/renderer.ts +998 -0
  391. package/src/edit/snapshot-details.ts +77 -0
  392. package/src/edit/streaming.ts +710 -0
  393. package/src/eval/agent-bridge.ts +224 -0
  394. package/src/eval/backend-helpers.ts +48 -0
  395. package/src/eval/backend.ts +71 -0
  396. package/src/eval/bridge-timeout.ts +65 -0
  397. package/src/eval/budget-bridge.ts +48 -0
  398. package/src/eval/completion-bridge.ts +212 -0
  399. package/src/eval/concurrency-bridge.ts +34 -0
  400. package/src/eval/executor-base.ts +562 -0
  401. package/src/eval/idle-timeout.ts +91 -0
  402. package/src/eval/index.ts +6 -0
  403. package/src/eval/jl/executor.ts +551 -0
  404. package/src/eval/jl/index.ts +54 -0
  405. package/src/eval/jl/kernel.ts +236 -0
  406. package/src/eval/jl/prelude.jl +736 -0
  407. package/src/eval/jl/prelude.ts +3 -0
  408. package/src/eval/jl/runner.jl +666 -0
  409. package/src/eval/jl/runtime.ts +118 -0
  410. package/src/eval/js/context-manager.ts +872 -0
  411. package/src/eval/js/executor.ts +178 -0
  412. package/src/eval/js/index.ts +41 -0
  413. package/src/eval/js/process-entry.ts +31 -0
  414. package/src/eval/js/shared/helpers.ts +170 -0
  415. package/src/eval/js/shared/indirect-eval.ts +30 -0
  416. package/src/eval/js/shared/local-module-loader.ts +364 -0
  417. package/src/eval/js/shared/prelude.ts +2 -0
  418. package/src/eval/js/shared/prelude.txt +294 -0
  419. package/src/eval/js/shared/rewrite-imports.ts +550 -0
  420. package/src/eval/js/shared/runtime.ts +590 -0
  421. package/src/eval/js/shared/types.ts +18 -0
  422. package/src/eval/js/tool-bridge.ts +163 -0
  423. package/src/eval/js/worker-core.ts +380 -0
  424. package/src/eval/js/worker-entry.ts +37 -0
  425. package/src/eval/js/worker-protocol.ts +47 -0
  426. package/src/eval/kernel-base.ts +569 -0
  427. package/src/eval/py/display.ts +71 -0
  428. package/src/eval/py/executor.ts +643 -0
  429. package/src/eval/py/index.ts +57 -0
  430. package/src/eval/py/kernel.ts +235 -0
  431. package/src/eval/py/prelude.py +673 -0
  432. package/src/eval/py/prelude.ts +3 -0
  433. package/src/eval/py/runner.py +1425 -0
  434. package/src/eval/py/runtime.ts +276 -0
  435. package/src/eval/py/spawn-options.ts +134 -0
  436. package/src/eval/py/tool-bridge.ts +201 -0
  437. package/src/eval/rb/executor.ts +511 -0
  438. package/src/eval/rb/index.ts +54 -0
  439. package/src/eval/rb/kernel.ts +231 -0
  440. package/src/eval/rb/prelude.rb +551 -0
  441. package/src/eval/rb/prelude.ts +3 -0
  442. package/src/eval/rb/runner.rb +581 -0
  443. package/src/eval/rb/runtime.ts +132 -0
  444. package/src/eval/runtime-env.ts +104 -0
  445. package/src/eval/session-id.ts +8 -0
  446. package/src/eval/types.ts +48 -0
  447. package/src/exa/index.ts +2 -0
  448. package/src/exa/mcp-client.ts +370 -0
  449. package/src/exa/types.ts +69 -0
  450. package/src/exec/bash-executor.ts +627 -0
  451. package/src/exec/direnv.ts +145 -0
  452. package/src/exec/exec.ts +53 -0
  453. package/src/exec/non-interactive-env.ts +118 -0
  454. package/src/export/custom-share.ts +65 -0
  455. package/src/export/html/args.ts +20 -0
  456. package/src/export/html/index.ts +320 -0
  457. package/src/export/html/share-loader.js +102 -0
  458. package/src/export/html/template.css +1355 -0
  459. package/src/export/html/template.html +55 -0
  460. package/src/export/html/template.js +1653 -0
  461. package/src/export/html/tool-views.generated.js +35 -0
  462. package/src/export/html/vendor/highlight.min.js +1213 -0
  463. package/src/export/html/vendor/marked.min.js +6 -0
  464. package/src/export/html/web-palette.ts +126 -0
  465. package/src/export/share.ts +686 -0
  466. package/src/export/ttsr.ts +590 -0
  467. package/src/extensibility/custom-commands/bundled/ci-green/index.ts +54 -0
  468. package/src/extensibility/custom-commands/bundled/review/index.ts +698 -0
  469. package/src/extensibility/custom-commands/index.ts +2 -0
  470. package/src/extensibility/custom-commands/loader.ts +242 -0
  471. package/src/extensibility/custom-commands/types.ts +119 -0
  472. package/src/extensibility/custom-tools/index.ts +7 -0
  473. package/src/extensibility/custom-tools/loader.ts +301 -0
  474. package/src/extensibility/custom-tools/types.ts +287 -0
  475. package/src/extensibility/custom-tools/wrapper.ts +50 -0
  476. package/src/extensibility/extensions/compact-handler.ts +40 -0
  477. package/src/extensibility/extensions/get-commands-handler.ts +78 -0
  478. package/src/extensibility/extensions/index.ts +16 -0
  479. package/src/extensibility/extensions/load-errors.ts +13 -0
  480. package/src/extensibility/extensions/loader.ts +663 -0
  481. package/src/extensibility/extensions/managed-timers.ts +83 -0
  482. package/src/extensibility/extensions/model-api.ts +39 -0
  483. package/src/extensibility/extensions/runner.ts +1396 -0
  484. package/src/extensibility/extensions/types.ts +1603 -0
  485. package/src/extensibility/extensions/wrapper.ts +395 -0
  486. package/src/extensibility/hooks/index.ts +6 -0
  487. package/src/extensibility/hooks/loader.ts +243 -0
  488. package/src/extensibility/hooks/runner.ts +425 -0
  489. package/src/extensibility/hooks/tool-wrapper.ts +124 -0
  490. package/src/extensibility/hooks/types.ts +612 -0
  491. package/src/extensibility/legacy-pi-ai-shim.ts +161 -0
  492. package/src/extensibility/legacy-pi-coding-agent-shim.ts +1460 -0
  493. package/src/extensibility/legacy-pi-tui-shim.ts +43 -0
  494. package/src/extensibility/legacy-typebox.ts +101 -0
  495. package/src/extensibility/plugins/bun-git-cache.ts +91 -0
  496. package/src/extensibility/plugins/doctor.ts +65 -0
  497. package/src/extensibility/plugins/git-url.ts +367 -0
  498. package/src/extensibility/plugins/index.ts +9 -0
  499. package/src/extensibility/plugins/installer.ts +201 -0
  500. package/src/extensibility/plugins/legacy-pi-compat.ts +2643 -0
  501. package/src/extensibility/plugins/legacy-pi-virtual-modules.d.ts +4 -0
  502. package/src/extensibility/plugins/loader.ts +535 -0
  503. package/src/extensibility/plugins/manager.ts +1142 -0
  504. package/src/extensibility/plugins/marketplace/cache.ts +136 -0
  505. package/src/extensibility/plugins/marketplace/fetcher.ts +316 -0
  506. package/src/extensibility/plugins/marketplace/index.ts +6 -0
  507. package/src/extensibility/plugins/marketplace/manager.ts +927 -0
  508. package/src/extensibility/plugins/marketplace/registry.ts +192 -0
  509. package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
  510. package/src/extensibility/plugins/marketplace/types.ts +192 -0
  511. package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
  512. package/src/extensibility/plugins/parser.ts +107 -0
  513. package/src/extensibility/plugins/runtime-config.ts +9 -0
  514. package/src/extensibility/plugins/types.ts +194 -0
  515. package/src/extensibility/session-handler-types.ts +21 -0
  516. package/src/extensibility/shared-events.ts +401 -0
  517. package/src/extensibility/skills.ts +531 -0
  518. package/src/extensibility/slash-commands.ts +131 -0
  519. package/src/extensibility/tool-event-input.ts +80 -0
  520. package/src/extensibility/tool-proxy.ts +28 -0
  521. package/src/extensibility/utils.ts +192 -0
  522. package/src/goals/index.ts +3 -0
  523. package/src/goals/runtime.ts +521 -0
  524. package/src/goals/state.ts +37 -0
  525. package/src/goals/tools/goal-tool.ts +251 -0
  526. package/src/hindsight/backend.ts +354 -0
  527. package/src/hindsight/bank.ts +156 -0
  528. package/src/hindsight/client.ts +680 -0
  529. package/src/hindsight/config.ts +193 -0
  530. package/src/hindsight/content.ts +266 -0
  531. package/src/hindsight/index.ts +8 -0
  532. package/src/hindsight/mental-models.ts +429 -0
  533. package/src/hindsight/seeds.json +32 -0
  534. package/src/hindsight/state.ts +530 -0
  535. package/src/hindsight/transcript.ts +71 -0
  536. package/src/index.ts +66 -0
  537. package/src/internal-urls/agent-protocol.ts +180 -0
  538. package/src/internal-urls/artifact-protocol.ts +151 -0
  539. package/src/internal-urls/docs-index.ts +102 -0
  540. package/src/internal-urls/filesystem-resource.ts +34 -0
  541. package/src/internal-urls/history-protocol.ts +198 -0
  542. package/src/internal-urls/index.ts +28 -0
  543. package/src/internal-urls/issue-pr-protocol.ts +594 -0
  544. package/src/internal-urls/json-query.ts +126 -0
  545. package/src/internal-urls/local-protocol.ts +471 -0
  546. package/src/internal-urls/mcp-protocol.ts +168 -0
  547. package/src/internal-urls/memory-protocol.ts +380 -0
  548. package/src/internal-urls/omp-protocol.ts +94 -0
  549. package/src/internal-urls/parse.ts +103 -0
  550. package/src/internal-urls/registry-helpers.ts +132 -0
  551. package/src/internal-urls/router.ts +153 -0
  552. package/src/internal-urls/rule-protocol.ts +45 -0
  553. package/src/internal-urls/security-protocol.ts +261 -0
  554. package/src/internal-urls/skill-protocol.ts +131 -0
  555. package/src/internal-urls/ssh-protocol.ts +368 -0
  556. package/src/internal-urls/types.ts +196 -0
  557. package/src/internal-urls/vault-protocol.ts +940 -0
  558. package/src/internal-urls/xd-protocol.ts +46 -0
  559. package/src/irc/bus.ts +380 -0
  560. package/src/jsonrpc/message-framing.ts +142 -0
  561. package/src/launch/broker.ts +1368 -0
  562. package/src/launch/client.ts +521 -0
  563. package/src/launch/ensure.ts +73 -0
  564. package/src/launch/paths.ts +14 -0
  565. package/src/launch/presence.ts +82 -0
  566. package/src/launch/protocol.ts +448 -0
  567. package/src/launch/spawn-options.ts +17 -0
  568. package/src/launch/terminal-output-worker-client.ts +53 -0
  569. package/src/launch/terminal-output-worker-protocol.ts +11 -0
  570. package/src/launch/terminal-output-worker.ts +23 -0
  571. package/src/launch/terminal-output.ts +46 -0
  572. package/src/lib/xai-http.ts +150 -0
  573. package/src/live/attestation.ts +91 -0
  574. package/src/live/controller.ts +517 -0
  575. package/src/live/prompts/agent-final-message.md +3 -0
  576. package/src/live/prompts/live-instructions.md +23 -0
  577. package/src/live/protocol.ts +233 -0
  578. package/src/live/transport.ts +422 -0
  579. package/src/live/visualizer.ts +221 -0
  580. package/src/live/voices.ts +18 -0
  581. package/src/lsp/client.ts +1465 -0
  582. package/src/lsp/clients/biome-client.ts +263 -0
  583. package/src/lsp/clients/index.ts +50 -0
  584. package/src/lsp/clients/lsp-linter-client.ts +85 -0
  585. package/src/lsp/clients/swiftlint-client.ts +120 -0
  586. package/src/lsp/config.ts +549 -0
  587. package/src/lsp/defaults.json +499 -0
  588. package/src/lsp/deferred-diagnostics.ts +66 -0
  589. package/src/lsp/diagnostics-ledger.ts +51 -0
  590. package/src/lsp/edits.ts +288 -0
  591. package/src/lsp/format-options.ts +119 -0
  592. package/src/lsp/index.ts +2821 -0
  593. package/src/lsp/lspmux.ts +233 -0
  594. package/src/lsp/mux/daemon.ts +348 -0
  595. package/src/lsp/mux/protocol.ts +96 -0
  596. package/src/lsp/mux/server.ts +797 -0
  597. package/src/lsp/render.ts +668 -0
  598. package/src/lsp/startup-events.ts +13 -0
  599. package/src/lsp/types.ts +479 -0
  600. package/src/lsp/utils.ts +747 -0
  601. package/src/main.ts +1799 -0
  602. package/src/markit/NOTICE +32 -0
  603. package/src/markit/converters/docx.ts +56 -0
  604. package/src/markit/converters/epub.ts +136 -0
  605. package/src/markit/converters/pdf/columns.ts +103 -0
  606. package/src/markit/converters/pdf/extract.ts +598 -0
  607. package/src/markit/converters/pdf/grid.ts +780 -0
  608. package/src/markit/converters/pdf/headers.ts +106 -0
  609. package/src/markit/converters/pdf/index.ts +146 -0
  610. package/src/markit/converters/pdf/render.ts +501 -0
  611. package/src/markit/converters/pdf/types.ts +84 -0
  612. package/src/markit/converters/pptx.ts +325 -0
  613. package/src/markit/converters/xlsx.ts +173 -0
  614. package/src/markit/index.ts +2 -0
  615. package/src/markit/registry.ts +59 -0
  616. package/src/markit/types.ts +35 -0
  617. package/src/mcp/client.ts +511 -0
  618. package/src/mcp/config-writer.ts +377 -0
  619. package/src/mcp/config.ts +385 -0
  620. package/src/mcp/index.ts +29 -0
  621. package/src/mcp/json-rpc.ts +122 -0
  622. package/src/mcp/loader.ts +125 -0
  623. package/src/mcp/manager.ts +1524 -0
  624. package/src/mcp/oauth-credentials.ts +104 -0
  625. package/src/mcp/oauth-discovery.ts +587 -0
  626. package/src/mcp/oauth-flow.ts +830 -0
  627. package/src/mcp/render.ts +214 -0
  628. package/src/mcp/request-id.ts +24 -0
  629. package/src/mcp/smithery-auth.ts +108 -0
  630. package/src/mcp/smithery-connect.ts +154 -0
  631. package/src/mcp/smithery-registry.ts +500 -0
  632. package/src/mcp/startup-events.ts +116 -0
  633. package/src/mcp/timeout.ts +59 -0
  634. package/src/mcp/tool-bridge.ts +691 -0
  635. package/src/mcp/tool-cache.ts +117 -0
  636. package/src/mcp/transports/header-policy.ts +95 -0
  637. package/src/mcp/transports/http.ts +508 -0
  638. package/src/mcp/transports/index.ts +7 -0
  639. package/src/mcp/transports/sse.ts +372 -0
  640. package/src/mcp/transports/stdio.ts +905 -0
  641. package/src/mcp/types.ts +467 -0
  642. package/src/memories/index.ts +1434 -0
  643. package/src/memories/storage.ts +578 -0
  644. package/src/memory-backend/index.ts +19 -0
  645. package/src/memory-backend/local-backend.ts +47 -0
  646. package/src/memory-backend/messages.ts +19 -0
  647. package/src/memory-backend/off-backend.ts +25 -0
  648. package/src/memory-backend/resolve.ts +25 -0
  649. package/src/memory-backend/runtime.ts +66 -0
  650. package/src/memory-backend/tool-names.ts +2 -0
  651. package/src/memory-backend/types.ts +166 -0
  652. package/src/mnemopi/backend.ts +629 -0
  653. package/src/mnemopi/config.ts +267 -0
  654. package/src/mnemopi/embed-client.ts +293 -0
  655. package/src/mnemopi/embed-protocol.ts +35 -0
  656. package/src/mnemopi/embed-worker.ts +114 -0
  657. package/src/mnemopi/index.ts +3 -0
  658. package/src/mnemopi/state.ts +940 -0
  659. package/src/modes/acp/acp-agent.ts +2595 -0
  660. package/src/modes/acp/acp-client-bridge.ts +154 -0
  661. package/src/modes/acp/acp-event-mapper.ts +1084 -0
  662. package/src/modes/acp/acp-mode.ts +48 -0
  663. package/src/modes/acp/index.ts +2 -0
  664. package/src/modes/acp/terminal-auth.ts +37 -0
  665. package/src/modes/components/advisor-config.ts +635 -0
  666. package/src/modes/components/advisor-message.ts +109 -0
  667. package/src/modes/components/agent-dashboard.ts +1252 -0
  668. package/src/modes/components/agent-hub-projection.ts +248 -0
  669. package/src/modes/components/agent-hub-renderer.ts +194 -0
  670. package/src/modes/components/agent-hub.ts +1126 -0
  671. package/src/modes/components/agent-transcript-viewer.ts +647 -0
  672. package/src/modes/components/ask-dialog.ts +1017 -0
  673. package/src/modes/components/assistant-message.ts +978 -0
  674. package/src/modes/components/background-tan-message.ts +36 -0
  675. package/src/modes/components/bash-execution.ts +233 -0
  676. package/src/modes/components/bordered-loader.ts +41 -0
  677. package/src/modes/components/btw-panel.ts +161 -0
  678. package/src/modes/components/cache-invalidation-marker.ts +110 -0
  679. package/src/modes/components/chat-block.ts +111 -0
  680. package/src/modes/components/chat-transcript-builder.ts +518 -0
  681. package/src/modes/components/codex-reset-fireworks.ts +369 -0
  682. package/src/modes/components/collab-prompt-message.ts +32 -0
  683. package/src/modes/components/compaction-summary-message.ts +221 -0
  684. package/src/modes/components/copy-selector.ts +218 -0
  685. package/src/modes/components/countdown-timer.ts +75 -0
  686. package/src/modes/components/custom-editor.ts +1036 -0
  687. package/src/modes/components/custom-message.ts +70 -0
  688. package/src/modes/components/diff.ts +254 -0
  689. package/src/modes/components/dynamic-border.ts +37 -0
  690. package/src/modes/components/error-banner.ts +33 -0
  691. package/src/modes/components/eval-execution.ts +169 -0
  692. package/src/modes/components/execution-shared.ts +101 -0
  693. package/src/modes/components/extensions/extension-dashboard.ts +492 -0
  694. package/src/modes/components/extensions/extension-list.ts +507 -0
  695. package/src/modes/components/extensions/index.ts +9 -0
  696. package/src/modes/components/extensions/inspector-panel.ts +326 -0
  697. package/src/modes/components/extensions/state-manager.ts +648 -0
  698. package/src/modes/components/extensions/types.ts +186 -0
  699. package/src/modes/components/footer.ts +274 -0
  700. package/src/modes/components/history-search.ts +268 -0
  701. package/src/modes/components/hook-editor.ts +213 -0
  702. package/src/modes/components/hook-input.ts +87 -0
  703. package/src/modes/components/hook-message.ts +67 -0
  704. package/src/modes/components/hook-selector.ts +691 -0
  705. package/src/modes/components/index.ts +42 -0
  706. package/src/modes/components/keybinding-hints.ts +56 -0
  707. package/src/modes/components/late-diagnostics-message.ts +60 -0
  708. package/src/modes/components/login-dialog.ts +197 -0
  709. package/src/modes/components/logout-account-selector.ts +130 -0
  710. package/src/modes/components/mcp-add-wizard.ts +1413 -0
  711. package/src/modes/components/message-frame.ts +98 -0
  712. package/src/modes/components/model-browser.ts +888 -0
  713. package/src/modes/components/model-hub.ts +2014 -0
  714. package/src/modes/components/model-picker.ts +237 -0
  715. package/src/modes/components/move-overlay.ts +293 -0
  716. package/src/modes/components/oauth-selector.ts +474 -0
  717. package/src/modes/components/omfg-panel.ts +141 -0
  718. package/src/modes/components/overlay-box.ts +109 -0
  719. package/src/modes/components/pause-screen.ts +208 -0
  720. package/src/modes/components/plan-review-overlay.ts +1226 -0
  721. package/src/modes/components/plan-toc.ts +138 -0
  722. package/src/modes/components/plugin-selector.ts +100 -0
  723. package/src/modes/components/plugin-settings.ts +745 -0
  724. package/src/modes/components/queue-mode-selector.ts +61 -0
  725. package/src/modes/components/read-tool-group.ts +856 -0
  726. package/src/modes/components/reset-usage-selector.ts +161 -0
  727. package/src/modes/components/segment-track.ts +89 -0
  728. package/src/modes/components/select-list-mouse-routing.ts +35 -0
  729. package/src/modes/components/selector-helpers.ts +129 -0
  730. package/src/modes/components/session-account-selector.ts +62 -0
  731. package/src/modes/components/session-selector.ts +1035 -0
  732. package/src/modes/components/settings-defs.ts +267 -0
  733. package/src/modes/components/settings-selector.ts +1445 -0
  734. package/src/modes/components/show-images-selector.ts +50 -0
  735. package/src/modes/components/skill-message.ts +110 -0
  736. package/src/modes/components/snapcompact-shape-preview-doc.md +14 -0
  737. package/src/modes/components/snapcompact-shape-preview.ts +192 -0
  738. package/src/modes/components/status-line/component.ts +1843 -0
  739. package/src/modes/components/status-line/context-thresholds.ts +86 -0
  740. package/src/modes/components/status-line/git-utils.ts +42 -0
  741. package/src/modes/components/status-line/index.ts +5 -0
  742. package/src/modes/components/status-line/presets.ts +106 -0
  743. package/src/modes/components/status-line/segments.ts +710 -0
  744. package/src/modes/components/status-line/separators.ts +55 -0
  745. package/src/modes/components/status-line/types.ts +159 -0
  746. package/src/modes/components/stripped-tool-calls-placeholder.ts +35 -0
  747. package/src/modes/components/theme-selector.ts +68 -0
  748. package/src/modes/components/thinking-selector.ts +57 -0
  749. package/src/modes/components/tiny-title-download-progress.ts +90 -0
  750. package/src/modes/components/tips.txt +26 -0
  751. package/src/modes/components/todo-reminder.ts +43 -0
  752. package/src/modes/components/tool-execution.ts +1467 -0
  753. package/src/modes/components/transcript-container.ts +527 -0
  754. package/src/modes/components/tree-selector.ts +1006 -0
  755. package/src/modes/components/ttsr-notification.ts +123 -0
  756. package/src/modes/components/usage-row.ts +52 -0
  757. package/src/modes/components/user-message-selector.ts +227 -0
  758. package/src/modes/components/user-message.ts +167 -0
  759. package/src/modes/components/visual-truncate.ts +63 -0
  760. package/src/modes/components/welcome.ts +578 -0
  761. package/src/modes/controllers/btw-controller.ts +246 -0
  762. package/src/modes/controllers/command-controller-shared.ts +109 -0
  763. package/src/modes/controllers/command-controller.ts +2024 -0
  764. package/src/modes/controllers/event-controller.ts +2173 -0
  765. package/src/modes/controllers/extension-ui-controller.ts +1243 -0
  766. package/src/modes/controllers/input-controller.ts +2037 -0
  767. package/src/modes/controllers/live-command-controller.ts +261 -0
  768. package/src/modes/controllers/mcp-command-controller.ts +2552 -0
  769. package/src/modes/controllers/omfg-controller.ts +287 -0
  770. package/src/modes/controllers/omfg-rule.ts +647 -0
  771. package/src/modes/controllers/selector-controller.ts +2058 -0
  772. package/src/modes/controllers/session-focus-controller.ts +117 -0
  773. package/src/modes/controllers/ssh-command-controller.ts +385 -0
  774. package/src/modes/controllers/streaming-reveal.ts +399 -0
  775. package/src/modes/controllers/tan-command-controller.ts +243 -0
  776. package/src/modes/controllers/todo-command-controller.ts +487 -0
  777. package/src/modes/controllers/tool-args-reveal.ts +591 -0
  778. package/src/modes/data/emojis.json +1 -0
  779. package/src/modes/emoji-autocomplete.ts +285 -0
  780. package/src/modes/github-ref-autocomplete.ts +75 -0
  781. package/src/modes/gradient-highlight.ts +99 -0
  782. package/src/modes/image-references.ts +137 -0
  783. package/src/modes/index.ts +10 -0
  784. package/src/modes/interactive-mode.ts +5055 -0
  785. package/src/modes/internal-url-autocomplete.ts +158 -0
  786. package/src/modes/loop-limit.ts +192 -0
  787. package/src/modes/magic-keyword-boundary.ts +23 -0
  788. package/src/modes/magic-keywords.ts +42 -0
  789. package/src/modes/markdown-prose.ts +247 -0
  790. package/src/modes/oauth-manual-input.ts +69 -0
  791. package/src/modes/orchestrate.ts +43 -0
  792. package/src/modes/print-mode.ts +282 -0
  793. package/src/modes/prompt-action-autocomplete.ts +322 -0
  794. package/src/modes/queue-input.ts +132 -0
  795. package/src/modes/rpc/host-tools.ts +204 -0
  796. package/src/modes/rpc/host-uris.ts +241 -0
  797. package/src/modes/rpc/rpc-client.ts +1213 -0
  798. package/src/modes/rpc/rpc-frame.ts +316 -0
  799. package/src/modes/rpc/rpc-input.ts +38 -0
  800. package/src/modes/rpc/rpc-messages.ts +127 -0
  801. package/src/modes/rpc/rpc-mode.ts +1519 -0
  802. package/src/modes/rpc/rpc-subagents.ts +265 -0
  803. package/src/modes/rpc/rpc-types.ts +544 -0
  804. package/src/modes/running-subagent-badge.ts +13 -0
  805. package/src/modes/runtime-init.ts +144 -0
  806. package/src/modes/session-observer-registry.ts +223 -0
  807. package/src/modes/session-teardown.ts +82 -0
  808. package/src/modes/setup-version.ts +11 -0
  809. package/src/modes/setup-wizard/index.ts +103 -0
  810. package/src/modes/setup-wizard/lazy.ts +16 -0
  811. package/src/modes/setup-wizard/scenes/glyph.ts +103 -0
  812. package/src/modes/setup-wizard/scenes/model.ts +132 -0
  813. package/src/modes/setup-wizard/scenes/outro.ts +35 -0
  814. package/src/modes/setup-wizard/scenes/providers.ts +105 -0
  815. package/src/modes/setup-wizard/scenes/sign-in.ts +312 -0
  816. package/src/modes/setup-wizard/scenes/splash.ts +201 -0
  817. package/src/modes/setup-wizard/scenes/theme.ts +330 -0
  818. package/src/modes/setup-wizard/scenes/types.ts +65 -0
  819. package/src/modes/setup-wizard/scenes/web-search.ts +153 -0
  820. package/src/modes/setup-wizard/startup-splash.ts +107 -0
  821. package/src/modes/setup-wizard/wizard-overlay.ts +335 -0
  822. package/src/modes/shared.ts +49 -0
  823. package/src/modes/skill-command.ts +91 -0
  824. package/src/modes/theme/dark.json +95 -0
  825. package/src/modes/theme/defaults/alabaster.json +93 -0
  826. package/src/modes/theme/defaults/amethyst.json +96 -0
  827. package/src/modes/theme/defaults/anthracite.json +93 -0
  828. package/src/modes/theme/defaults/basalt.json +91 -0
  829. package/src/modes/theme/defaults/birch.json +95 -0
  830. package/src/modes/theme/defaults/dark-abyss.json +91 -0
  831. package/src/modes/theme/defaults/dark-arctic.json +104 -0
  832. package/src/modes/theme/defaults/dark-aurora.json +95 -0
  833. package/src/modes/theme/defaults/dark-catppuccin.json +107 -0
  834. package/src/modes/theme/defaults/dark-cavern.json +91 -0
  835. package/src/modes/theme/defaults/dark-copper.json +95 -0
  836. package/src/modes/theme/defaults/dark-cosmos.json +90 -0
  837. package/src/modes/theme/defaults/dark-cyberpunk.json +102 -0
  838. package/src/modes/theme/defaults/dark-dracula.json +98 -0
  839. package/src/modes/theme/defaults/dark-eclipse.json +91 -0
  840. package/src/modes/theme/defaults/dark-ember.json +95 -0
  841. package/src/modes/theme/defaults/dark-equinox.json +90 -0
  842. package/src/modes/theme/defaults/dark-forest.json +96 -0
  843. package/src/modes/theme/defaults/dark-github.json +105 -0
  844. package/src/modes/theme/defaults/dark-gruvbox.json +112 -0
  845. package/src/modes/theme/defaults/dark-lavender.json +95 -0
  846. package/src/modes/theme/defaults/dark-lunar.json +89 -0
  847. package/src/modes/theme/defaults/dark-midnight.json +95 -0
  848. package/src/modes/theme/defaults/dark-monochrome.json +94 -0
  849. package/src/modes/theme/defaults/dark-monokai.json +98 -0
  850. package/src/modes/theme/defaults/dark-nebula.json +90 -0
  851. package/src/modes/theme/defaults/dark-nord.json +97 -0
  852. package/src/modes/theme/defaults/dark-ocean.json +101 -0
  853. package/src/modes/theme/defaults/dark-one.json +100 -0
  854. package/src/modes/theme/defaults/dark-poimandres.json +143 -0
  855. package/src/modes/theme/defaults/dark-rainforest.json +91 -0
  856. package/src/modes/theme/defaults/dark-reef.json +91 -0
  857. package/src/modes/theme/defaults/dark-retro.json +92 -0
  858. package/src/modes/theme/defaults/dark-rose-pine.json +96 -0
  859. package/src/modes/theme/defaults/dark-sakura.json +95 -0
  860. package/src/modes/theme/defaults/dark-slate.json +95 -0
  861. package/src/modes/theme/defaults/dark-solarized.json +97 -0
  862. package/src/modes/theme/defaults/dark-solstice.json +90 -0
  863. package/src/modes/theme/defaults/dark-starfall.json +91 -0
  864. package/src/modes/theme/defaults/dark-sunset.json +99 -0
  865. package/src/modes/theme/defaults/dark-swamp.json +90 -0
  866. package/src/modes/theme/defaults/dark-synthwave.json +103 -0
  867. package/src/modes/theme/defaults/dark-taiga.json +91 -0
  868. package/src/modes/theme/defaults/dark-terminal.json +95 -0
  869. package/src/modes/theme/defaults/dark-tokyo-night.json +101 -0
  870. package/src/modes/theme/defaults/dark-tundra.json +91 -0
  871. package/src/modes/theme/defaults/dark-twilight.json +91 -0
  872. package/src/modes/theme/defaults/dark-volcanic.json +91 -0
  873. package/src/modes/theme/defaults/graphite.json +92 -0
  874. package/src/modes/theme/defaults/index.ts +199 -0
  875. package/src/modes/theme/defaults/light-arctic.json +107 -0
  876. package/src/modes/theme/defaults/light-aurora-day.json +91 -0
  877. package/src/modes/theme/defaults/light-canyon.json +91 -0
  878. package/src/modes/theme/defaults/light-catppuccin.json +106 -0
  879. package/src/modes/theme/defaults/light-cirrus.json +90 -0
  880. package/src/modes/theme/defaults/light-coral.json +95 -0
  881. package/src/modes/theme/defaults/light-cyberpunk.json +96 -0
  882. package/src/modes/theme/defaults/light-dawn.json +90 -0
  883. package/src/modes/theme/defaults/light-dunes.json +91 -0
  884. package/src/modes/theme/defaults/light-eucalyptus.json +95 -0
  885. package/src/modes/theme/defaults/light-forest.json +100 -0
  886. package/src/modes/theme/defaults/light-frost.json +95 -0
  887. package/src/modes/theme/defaults/light-github.json +115 -0
  888. package/src/modes/theme/defaults/light-glacier.json +91 -0
  889. package/src/modes/theme/defaults/light-gruvbox.json +108 -0
  890. package/src/modes/theme/defaults/light-haze.json +90 -0
  891. package/src/modes/theme/defaults/light-honeycomb.json +95 -0
  892. package/src/modes/theme/defaults/light-lagoon.json +91 -0
  893. package/src/modes/theme/defaults/light-lavender.json +95 -0
  894. package/src/modes/theme/defaults/light-meadow.json +91 -0
  895. package/src/modes/theme/defaults/light-mint.json +95 -0
  896. package/src/modes/theme/defaults/light-monochrome.json +101 -0
  897. package/src/modes/theme/defaults/light-ocean.json +99 -0
  898. package/src/modes/theme/defaults/light-one.json +99 -0
  899. package/src/modes/theme/defaults/light-opal.json +91 -0
  900. package/src/modes/theme/defaults/light-orchard.json +91 -0
  901. package/src/modes/theme/defaults/light-paper.json +95 -0
  902. package/src/modes/theme/defaults/light-poimandres.json +143 -0
  903. package/src/modes/theme/defaults/light-prism.json +90 -0
  904. package/src/modes/theme/defaults/light-retro.json +98 -0
  905. package/src/modes/theme/defaults/light-sand.json +95 -0
  906. package/src/modes/theme/defaults/light-savanna.json +91 -0
  907. package/src/modes/theme/defaults/light-solarized.json +102 -0
  908. package/src/modes/theme/defaults/light-soleil.json +90 -0
  909. package/src/modes/theme/defaults/light-sunset.json +99 -0
  910. package/src/modes/theme/defaults/light-synthwave.json +98 -0
  911. package/src/modes/theme/defaults/light-tokyo-night.json +111 -0
  912. package/src/modes/theme/defaults/light-wetland.json +91 -0
  913. package/src/modes/theme/defaults/light-zenith.json +89 -0
  914. package/src/modes/theme/defaults/limestone.json +94 -0
  915. package/src/modes/theme/defaults/mahogany.json +97 -0
  916. package/src/modes/theme/defaults/marble.json +93 -0
  917. package/src/modes/theme/defaults/obsidian.json +91 -0
  918. package/src/modes/theme/defaults/onyx.json +91 -0
  919. package/src/modes/theme/defaults/pearl.json +93 -0
  920. package/src/modes/theme/defaults/porcelain.json +91 -0
  921. package/src/modes/theme/defaults/quartz.json +96 -0
  922. package/src/modes/theme/defaults/sandstone.json +95 -0
  923. package/src/modes/theme/defaults/titanium.json +90 -0
  924. package/src/modes/theme/light.json +93 -0
  925. package/src/modes/theme/mermaid-cache.ts +92 -0
  926. package/src/modes/theme/shimmer.ts +305 -0
  927. package/src/modes/theme/theme-schema.json +463 -0
  928. package/src/modes/theme/theme.ts +3171 -0
  929. package/src/modes/turn-budget.ts +31 -0
  930. package/src/modes/types.ts +494 -0
  931. package/src/modes/ultrathink.ts +42 -0
  932. package/src/modes/utils/context-usage.ts +518 -0
  933. package/src/modes/utils/copy-targets.ts +378 -0
  934. package/src/modes/utils/hotkeys-markdown.ts +65 -0
  935. package/src/modes/utils/interactive-context-helpers.ts +31 -0
  936. package/src/modes/utils/keybinding-matchers.ts +86 -0
  937. package/src/modes/utils/tools-markdown.ts +31 -0
  938. package/src/modes/utils/transcript-render-helpers.ts +253 -0
  939. package/src/modes/utils/ui-helpers.ts +976 -0
  940. package/src/modes/warp-events.ts +232 -0
  941. package/src/modes/workflow.ts +55 -0
  942. package/src/plan-mode/approved-plan.ts +194 -0
  943. package/src/plan-mode/model-transition.ts +51 -0
  944. package/src/plan-mode/plan-files.ts +40 -0
  945. package/src/plan-mode/plan-handoff.ts +37 -0
  946. package/src/plan-mode/plan-protection.ts +31 -0
  947. package/src/plan-mode/state.ts +6 -0
  948. package/src/priority.json +60 -0
  949. package/src/prompts/advisor/active-repo-watchdog.md +6 -0
  950. package/src/prompts/advisor/advise-tool.md +3 -0
  951. package/src/prompts/advisor/context-files.md +8 -0
  952. package/src/prompts/advisor/system.md +98 -0
  953. package/src/prompts/agents/designer.md +74 -0
  954. package/src/prompts/agents/frontmatter.md +12 -0
  955. package/src/prompts/agents/init.md +33 -0
  956. package/src/prompts/agents/librarian.md +119 -0
  957. package/src/prompts/agents/reviewer.md +139 -0
  958. package/src/prompts/agents/scout.md +58 -0
  959. package/src/prompts/agents/security-reviewer.md +75 -0
  960. package/src/prompts/agents/task.md +17 -0
  961. package/src/prompts/bench/cache-prefix-chunk.md +1 -0
  962. package/src/prompts/bench/cache-prefix.md +3 -0
  963. package/src/prompts/bench/cache-suffix.md +1 -0
  964. package/src/prompts/bench.md +6 -0
  965. package/src/prompts/ci-green-request.md +36 -0
  966. package/src/prompts/dry-balance-bench.md +8 -0
  967. package/src/prompts/goals/goal-budget-limit.md +16 -0
  968. package/src/prompts/goals/goal-continuation.md +28 -0
  969. package/src/prompts/goals/goal-mode-active.md +23 -0
  970. package/src/prompts/goals/goal-mode-context.md +4 -0
  971. package/src/prompts/goals/goal-todo-context.md +12 -0
  972. package/src/prompts/goals/guided-goal-interview.md +43 -0
  973. package/src/prompts/memories/consolidation.md +30 -0
  974. package/src/prompts/memories/consolidation_system.md +4 -0
  975. package/src/prompts/memories/read-path.md +17 -0
  976. package/src/prompts/memories/stage_one_input.md +6 -0
  977. package/src/prompts/memories/stage_one_system.md +21 -0
  978. package/src/prompts/review-custom-request.md +21 -0
  979. package/src/prompts/review-headless-request.md +16 -0
  980. package/src/prompts/review-request.md +68 -0
  981. package/src/prompts/security/scan-coordinator.md +7 -0
  982. package/src/prompts/security/scan-request.md +21 -0
  983. package/src/prompts/security/validate-request.md +8 -0
  984. package/src/prompts/session/launch-completion.md +1 -0
  985. package/src/prompts/skills/autoload.md +8 -0
  986. package/src/prompts/skills/user-invocation.md +11 -0
  987. package/src/prompts/steering/parent-irc.md +5 -0
  988. package/src/prompts/steering/user-interjection.md +6 -0
  989. package/src/prompts/system/active-repo-context.md +4 -0
  990. package/src/prompts/system/agent-creation-architect.md +50 -0
  991. package/src/prompts/system/agent-creation-user.md +6 -0
  992. package/src/prompts/system/auto-continue.md +1 -0
  993. package/src/prompts/system/auto-thinking-difficulty-local.md +14 -0
  994. package/src/prompts/system/auto-thinking-difficulty.md +14 -0
  995. package/src/prompts/system/autolearn-guidance-learn.md +1 -0
  996. package/src/prompts/system/autolearn-guidance.md +7 -0
  997. package/src/prompts/system/autolearn-nudge-autocontinue.md +5 -0
  998. package/src/prompts/system/background-tan-dispatch.md +8 -0
  999. package/src/prompts/system/btw-user.md +8 -0
  1000. package/src/prompts/system/commit-message-system.md +14 -0
  1001. package/src/prompts/system/computer-safety.md +14 -0
  1002. package/src/prompts/system/custom-system-prompt.md +64 -0
  1003. package/src/prompts/system/eager-task.md +7 -0
  1004. package/src/prompts/system/eager-todo.md +18 -0
  1005. package/src/prompts/system/empty-stop-retry.md +4 -0
  1006. package/src/prompts/system/gemini-tool-call-reminder.md +9 -0
  1007. package/src/prompts/system/interrupted-thinking.md +7 -0
  1008. package/src/prompts/system/irc-autoreply.md +6 -0
  1009. package/src/prompts/system/irc-incoming.md +9 -0
  1010. package/src/prompts/system/manual-continue.md +7 -0
  1011. package/src/prompts/system/mcp-xdev-guidance.md +11 -0
  1012. package/src/prompts/system/memory-consolidation-system.md +8 -0
  1013. package/src/prompts/system/memory-extraction-system.md +26 -0
  1014. package/src/prompts/system/mid-run-todo-nudge.md +3 -0
  1015. package/src/prompts/system/omfg-user.md +50 -0
  1016. package/src/prompts/system/orchestrate-notice.md +40 -0
  1017. package/src/prompts/system/personalities/default.md +18 -0
  1018. package/src/prompts/system/personalities/friendly.md +17 -0
  1019. package/src/prompts/system/personalities/pragmatic.md +15 -0
  1020. package/src/prompts/system/plan-mode-active.md +125 -0
  1021. package/src/prompts/system/plan-mode-approved.md +22 -0
  1022. package/src/prompts/system/plan-mode-compact-instructions.md +17 -0
  1023. package/src/prompts/system/plan-mode-reference.md +10 -0
  1024. package/src/prompts/system/plan-mode-subagent.md +33 -0
  1025. package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
  1026. package/src/prompts/system/plan-yolo-handoff.md +5 -0
  1027. package/src/prompts/system/prewalk-checklist.md +7 -0
  1028. package/src/prompts/system/prewalk-continue.md +1 -0
  1029. package/src/prompts/system/prewalk-plan.md +13 -0
  1030. package/src/prompts/system/project-prompt.md +61 -0
  1031. package/src/prompts/system/recap-user.md +9 -0
  1032. package/src/prompts/system/resolve-device-reminder.md +3 -0
  1033. package/src/prompts/system/rewind-report.md +6 -0
  1034. package/src/prompts/system/side-channel-no-tools.md +3 -0
  1035. package/src/prompts/system/snapcompact-context-frames-note.md +1 -0
  1036. package/src/prompts/system/snapcompact-context-stub.md +1 -0
  1037. package/src/prompts/system/snapcompact-system-frames-note.md +1 -0
  1038. package/src/prompts/system/snapcompact-system-stub.md +1 -0
  1039. package/src/prompts/system/snapcompact-toolresult-note.md +1 -0
  1040. package/src/prompts/system/speech-rewrite.md +15 -0
  1041. package/src/prompts/system/subagent-async-pending.md +6 -0
  1042. package/src/prompts/system/subagent-system-prompt.md +73 -0
  1043. package/src/prompts/system/subagent-user-prompt.md +3 -0
  1044. package/src/prompts/system/subagent-yield-reminder.md +23 -0
  1045. package/src/prompts/system/system-prompt.md +263 -0
  1046. package/src/prompts/system/tan-context-switch.md +17 -0
  1047. package/src/prompts/system/task-label.md +23 -0
  1048. package/src/prompts/system/thinking-loop-redirect.md +10 -0
  1049. package/src/prompts/system/title-marker-instruction.md +1 -0
  1050. package/src/prompts/system/title-system.md +16 -0
  1051. package/src/prompts/system/tool-call-loop-redirect.md +8 -0
  1052. package/src/prompts/system/ttsr-interrupt.md +7 -0
  1053. package/src/prompts/system/ttsr-tool-reminder.md +5 -0
  1054. package/src/prompts/system/ultrathink-notice.md +3 -0
  1055. package/src/prompts/system/unexpected-stop-classifier.md +17 -0
  1056. package/src/prompts/system/unexpected-stop-retry.md +4 -0
  1057. package/src/prompts/system/vibe-mode-active.md +26 -0
  1058. package/src/prompts/system/web-search.md +25 -0
  1059. package/src/prompts/system/workflow-notice.md +112 -0
  1060. package/src/prompts/system/xdev-mount-notice.md +20 -0
  1061. package/src/prompts/tools/apply-patch.md +65 -0
  1062. package/src/prompts/tools/ask.md +22 -0
  1063. package/src/prompts/tools/ast-edit.md +11 -0
  1064. package/src/prompts/tools/ast-grep.md +19 -0
  1065. package/src/prompts/tools/async-result.md +8 -0
  1066. package/src/prompts/tools/bash.md +23 -0
  1067. package/src/prompts/tools/browser.md +29 -0
  1068. package/src/prompts/tools/checkpoint.md +15 -0
  1069. package/src/prompts/tools/computer.md +26 -0
  1070. package/src/prompts/tools/debug.md +3 -0
  1071. package/src/prompts/tools/eval.md +45 -0
  1072. package/src/prompts/tools/github.md +22 -0
  1073. package/src/prompts/tools/glob.md +16 -0
  1074. package/src/prompts/tools/goal.md +11 -0
  1075. package/src/prompts/tools/grep.md +13 -0
  1076. package/src/prompts/tools/hub.md +34 -0
  1077. package/src/prompts/tools/image-attachment-describe-system.md +8 -0
  1078. package/src/prompts/tools/image-attachment-describe.md +10 -0
  1079. package/src/prompts/tools/image-gen.md +7 -0
  1080. package/src/prompts/tools/inspect-image-system.md +20 -0
  1081. package/src/prompts/tools/inspect-image.md +22 -0
  1082. package/src/prompts/tools/learn.md +7 -0
  1083. package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
  1084. package/src/prompts/tools/lsp.md +19 -0
  1085. package/src/prompts/tools/manage-skill.md +9 -0
  1086. package/src/prompts/tools/memory-edit.md +12 -0
  1087. package/src/prompts/tools/patch.md +57 -0
  1088. package/src/prompts/tools/read.md +27 -0
  1089. package/src/prompts/tools/recall.md +7 -0
  1090. package/src/prompts/tools/reflect.md +5 -0
  1091. package/src/prompts/tools/replace.md +30 -0
  1092. package/src/prompts/tools/retain.md +6 -0
  1093. package/src/prompts/tools/rewind.md +14 -0
  1094. package/src/prompts/tools/security-publish.md +1 -0
  1095. package/src/prompts/tools/security-scan.md +1 -0
  1096. package/src/prompts/tools/task-async-contract.md +1 -0
  1097. package/src/prompts/tools/task-summary.md +20 -0
  1098. package/src/prompts/tools/task.md +83 -0
  1099. package/src/prompts/tools/todo.md +42 -0
  1100. package/src/prompts/tools/vibe-kill.md +3 -0
  1101. package/src/prompts/tools/vibe-list.md +3 -0
  1102. package/src/prompts/tools/vibe-send.md +9 -0
  1103. package/src/prompts/tools/vibe-spawn.md +10 -0
  1104. package/src/prompts/tools/vibe-turn-result.md +19 -0
  1105. package/src/prompts/tools/vibe-wait.md +8 -0
  1106. package/src/prompts/tools/web-search.md +8 -0
  1107. package/src/prompts/tools/write.md +14 -0
  1108. package/src/registry/agent-lifecycle.ts +505 -0
  1109. package/src/registry/agent-registry.ts +287 -0
  1110. package/src/registry/persisted-agents.ts +423 -0
  1111. package/src/sdk.ts +3820 -0
  1112. package/src/secrets/index.ts +375 -0
  1113. package/src/secrets/obfuscator.ts +2629 -0
  1114. package/src/secrets/regex.ts +21 -0
  1115. package/src/security/auth.ts +98 -0
  1116. package/src/security/cloud.ts +686 -0
  1117. package/src/security/comparison.ts +255 -0
  1118. package/src/security/contracts/ids.ts +111 -0
  1119. package/src/security/contracts/index.ts +4 -0
  1120. package/src/security/contracts/schemas.ts +219 -0
  1121. package/src/security/contracts/types.ts +254 -0
  1122. package/src/security/contracts/validation.ts +69 -0
  1123. package/src/security/coordinator.ts +708 -0
  1124. package/src/security/importers/codex-security.ts +387 -0
  1125. package/src/security/importers/index.ts +2 -0
  1126. package/src/security/importers/sarif.ts +357 -0
  1127. package/src/security/index.ts +13 -0
  1128. package/src/security/preflight.ts +405 -0
  1129. package/src/security/provenance.ts +106 -0
  1130. package/src/security/publication.ts +326 -0
  1131. package/src/security/remediation.ts +93 -0
  1132. package/src/security/resource-output.ts +50 -0
  1133. package/src/security/sarif.ts +78 -0
  1134. package/src/security/store.ts +430 -0
  1135. package/src/session/acp-permission-gate.ts +165 -0
  1136. package/src/session/agent-session-events.ts +67 -0
  1137. package/src/session/agent-session-types.ts +407 -0
  1138. package/src/session/agent-session.ts +9000 -0
  1139. package/src/session/agent-storage.ts +807 -0
  1140. package/src/session/artifacts.ts +154 -0
  1141. package/src/session/async-job-delivery.ts +82 -0
  1142. package/src/session/auth-broker-config.ts +92 -0
  1143. package/src/session/auth-storage.ts +25 -0
  1144. package/src/session/bash-runner.ts +326 -0
  1145. package/src/session/blob-store.ts +295 -0
  1146. package/src/session/checkpoint-entries.ts +81 -0
  1147. package/src/session/claude-session-store.ts +426 -0
  1148. package/src/session/client-bridge.ts +85 -0
  1149. package/src/session/codex-auto-reset.ts +673 -0
  1150. package/src/session/codex-session-store.ts +673 -0
  1151. package/src/session/compact-modes.ts +105 -0
  1152. package/src/session/credential-pin.ts +93 -0
  1153. package/src/session/eval-runner.ts +219 -0
  1154. package/src/session/exit-diagnostics.ts +310 -0
  1155. package/src/session/foreign-session-import.ts +52 -0
  1156. package/src/session/foreign-session-jsonl.ts +29 -0
  1157. package/src/session/foreign-session-store.ts +26 -0
  1158. package/src/session/history-storage.ts +329 -0
  1159. package/src/session/indexed-session-storage.ts +553 -0
  1160. package/src/session/irc-bridge.ts +203 -0
  1161. package/src/session/launch-completion.ts +37 -0
  1162. package/src/session/messages.ts +1304 -0
  1163. package/src/session/model-controls.ts +757 -0
  1164. package/src/session/prewalk.ts +279 -0
  1165. package/src/session/provider-image-budget.ts +86 -0
  1166. package/src/session/queued-messages.ts +99 -0
  1167. package/src/session/redis-session-storage.ts +257 -0
  1168. package/src/session/retry-fallback-chains.ts +455 -0
  1169. package/src/session/role-models.ts +85 -0
  1170. package/src/session/session-advisors.ts +1896 -0
  1171. package/src/session/session-context.ts +584 -0
  1172. package/src/session/session-dump-format.ts +216 -0
  1173. package/src/session/session-entries.ts +306 -0
  1174. package/src/session/session-handoff.ts +325 -0
  1175. package/src/session/session-history-format.ts +459 -0
  1176. package/src/session/session-listing.ts +715 -0
  1177. package/src/session/session-loader.ts +362 -0
  1178. package/src/session/session-maintenance.ts +3115 -0
  1179. package/src/session/session-manager.ts +2747 -0
  1180. package/src/session/session-memory.ts +222 -0
  1181. package/src/session/session-metadata.ts +53 -0
  1182. package/src/session/session-migrations.ts +78 -0
  1183. package/src/session/session-paths.ts +280 -0
  1184. package/src/session/session-persistence.ts +293 -0
  1185. package/src/session/session-provider-boundary.ts +306 -0
  1186. package/src/session/session-stats.ts +349 -0
  1187. package/src/session/session-storage.ts +774 -0
  1188. package/src/session/session-title-slot.ts +141 -0
  1189. package/src/session/session-tools.ts +1385 -0
  1190. package/src/session/session-workspace.ts +53 -0
  1191. package/src/session/settings-stream-fn.ts +79 -0
  1192. package/src/session/shake-types.ts +43 -0
  1193. package/src/session/snapcompact-inline.ts +545 -0
  1194. package/src/session/snapcompact-savings-journal.ts +113 -0
  1195. package/src/session/sql-session-storage.ts +374 -0
  1196. package/src/session/stream-guards.ts +417 -0
  1197. package/src/session/streaming-output.ts +1459 -0
  1198. package/src/session/todo-tracker.ts +380 -0
  1199. package/src/session/tool-choice-queue.ts +305 -0
  1200. package/src/session/ttsr-coordinator.ts +496 -0
  1201. package/src/session/turn-persistence.ts +142 -0
  1202. package/src/session/turn-recovery.ts +2005 -0
  1203. package/src/session/unexpected-stop-classifier.ts +141 -0
  1204. package/src/session/yield-queue.ts +288 -0
  1205. package/src/slash-commands/acp-builtins.ts +70 -0
  1206. package/src/slash-commands/available-commands.ts +105 -0
  1207. package/src/slash-commands/builtin-registry.ts +3149 -0
  1208. package/src/slash-commands/helpers/active-oauth-account.ts +80 -0
  1209. package/src/slash-commands/helpers/collab-qrcode.ts +28 -0
  1210. package/src/slash-commands/helpers/context-report.ts +66 -0
  1211. package/src/slash-commands/helpers/format.ts +46 -0
  1212. package/src/slash-commands/helpers/logout.ts +108 -0
  1213. package/src/slash-commands/helpers/marketplace-manager.ts +25 -0
  1214. package/src/slash-commands/helpers/mcp.ts +533 -0
  1215. package/src/slash-commands/helpers/parse.ts +85 -0
  1216. package/src/slash-commands/helpers/reset-usage.ts +68 -0
  1217. package/src/slash-commands/helpers/security.ts +451 -0
  1218. package/src/slash-commands/helpers/session-pin.ts +44 -0
  1219. package/src/slash-commands/helpers/ssh.ts +196 -0
  1220. package/src/slash-commands/helpers/stats-dashboard.ts +86 -0
  1221. package/src/slash-commands/helpers/todo.ts +285 -0
  1222. package/src/slash-commands/helpers/usage-report.ts +198 -0
  1223. package/src/slash-commands/marketplace-install-parser.ts +99 -0
  1224. package/src/slash-commands/types.ts +139 -0
  1225. package/src/ssh/config-writer.ts +183 -0
  1226. package/src/ssh/connection-manager.ts +667 -0
  1227. package/src/ssh/file-transfer.ts +214 -0
  1228. package/src/ssh/sshfs-mount.ts +163 -0
  1229. package/src/ssh/utils.ts +51 -0
  1230. package/src/startup-splash.ts +19 -0
  1231. package/src/stt/asr-client.ts +401 -0
  1232. package/src/stt/asr-protocol.ts +65 -0
  1233. package/src/stt/asr-worker.ts +603 -0
  1234. package/src/stt/downloader.ts +142 -0
  1235. package/src/stt/endpointer.ts +259 -0
  1236. package/src/stt/index.ts +6 -0
  1237. package/src/stt/models.ts +150 -0
  1238. package/src/stt/sherpa-runtime.ts +71 -0
  1239. package/src/stt/stt-controller.ts +320 -0
  1240. package/src/stt/submit-trigger.ts +74 -0
  1241. package/src/subprocess/worker-client.ts +463 -0
  1242. package/src/subprocess/worker-runtime.ts +494 -0
  1243. package/src/system-prompt.ts +921 -0
  1244. package/src/task/agents.ts +170 -0
  1245. package/src/task/commands.ts +132 -0
  1246. package/src/task/discovery.ts +145 -0
  1247. package/src/task/executor.ts +3431 -0
  1248. package/src/task/index.ts +1515 -0
  1249. package/src/task/isolation-ownership.ts +106 -0
  1250. package/src/task/isolation-runner.ts +444 -0
  1251. package/src/task/label.ts +40 -0
  1252. package/src/task/name-generator.ts +1577 -0
  1253. package/src/task/omp-command.ts +26 -0
  1254. package/src/task/output-manager.ts +115 -0
  1255. package/src/task/parallel.ts +221 -0
  1256. package/src/task/persisted-revive.ts +173 -0
  1257. package/src/task/prewalk.ts +6 -0
  1258. package/src/task/prompt-policy.ts +8 -0
  1259. package/src/task/provider-concurrency.ts +100 -0
  1260. package/src/task/read-only-policy.ts +27 -0
  1261. package/src/task/render.ts +1830 -0
  1262. package/src/task/renderer.ts +14 -0
  1263. package/src/task/repair-args.ts +118 -0
  1264. package/src/task/spawn-policy.ts +72 -0
  1265. package/src/task/structured-subagent.ts +676 -0
  1266. package/src/task/subprocess-tool-registry.ts +88 -0
  1267. package/src/task/types.ts +555 -0
  1268. package/src/task/worktree.ts +967 -0
  1269. package/src/task/yield-assembly.ts +198 -0
  1270. package/src/telemetry-export.ts +504 -0
  1271. package/src/thinking.ts +377 -0
  1272. package/src/tiny/device.ts +111 -0
  1273. package/src/tiny/dtype.ts +101 -0
  1274. package/src/tiny/message-preproc.ts +155 -0
  1275. package/src/tiny/models.ts +268 -0
  1276. package/src/tiny/text.ts +290 -0
  1277. package/src/tiny/title-client.ts +460 -0
  1278. package/src/tiny/title-protocol.ts +56 -0
  1279. package/src/tiny/worker.ts +354 -0
  1280. package/src/tools/acp-bridge.ts +125 -0
  1281. package/src/tools/approval.ts +245 -0
  1282. package/src/tools/ask.ts +1459 -0
  1283. package/src/tools/ast-edit.ts +718 -0
  1284. package/src/tools/ast-grep.ts +526 -0
  1285. package/src/tools/auto-generated-guard.ts +335 -0
  1286. package/src/tools/bash-interactive.ts +435 -0
  1287. package/src/tools/bash-interceptor.ts +148 -0
  1288. package/src/tools/bash-pty-selection.ts +14 -0
  1289. package/src/tools/bash-skill-urls.ts +350 -0
  1290. package/src/tools/bash.ts +1826 -0
  1291. package/src/tools/browser/aria/aria-snapshot.bundle.txt +7 -0
  1292. package/src/tools/browser/aria/aria-snapshot.ts +131 -0
  1293. package/src/tools/browser/attach.ts +219 -0
  1294. package/src/tools/browser/cmux/cmux-tab.ts +1531 -0
  1295. package/src/tools/browser/cmux/rpc.ts +200 -0
  1296. package/src/tools/browser/cmux/socket-client.ts +445 -0
  1297. package/src/tools/browser/launch.ts +939 -0
  1298. package/src/tools/browser/readable.ts +112 -0
  1299. package/src/tools/browser/registry.ts +447 -0
  1300. package/src/tools/browser/relay/bridge.ts +945 -0
  1301. package/src/tools/browser/relay/daemon.ts +117 -0
  1302. package/src/tools/browser/relay/extension-assets/background.js.txt +242 -0
  1303. package/src/tools/browser/relay/extension-assets/manifest.json.txt +14 -0
  1304. package/src/tools/browser/relay/extension-assets/options.html.txt +53 -0
  1305. package/src/tools/browser/relay/extension-assets/options.js.txt +23 -0
  1306. package/src/tools/browser/relay/kind.ts +41 -0
  1307. package/src/tools/browser/relay/protocol.ts +54 -0
  1308. package/src/tools/browser/relay/server.ts +141 -0
  1309. package/src/tools/browser/render.ts +229 -0
  1310. package/src/tools/browser/run-output.ts +76 -0
  1311. package/src/tools/browser/shared-daemon.ts +139 -0
  1312. package/src/tools/browser/tab-protocol.ts +123 -0
  1313. package/src/tools/browser/tab-supervisor.ts +1077 -0
  1314. package/src/tools/browser/tab-worker-entry.ts +29 -0
  1315. package/src/tools/browser/tab-worker.ts +1982 -0
  1316. package/src/tools/browser.ts +487 -0
  1317. package/src/tools/builtin-names.ts +67 -0
  1318. package/src/tools/checkpoint.ts +137 -0
  1319. package/src/tools/computer/exposure.ts +14 -0
  1320. package/src/tools/computer/protocol.ts +69 -0
  1321. package/src/tools/computer/supervisor.ts +409 -0
  1322. package/src/tools/computer/worker-entry.ts +39 -0
  1323. package/src/tools/computer/worker.ts +745 -0
  1324. package/src/tools/computer-renderer.ts +147 -0
  1325. package/src/tools/computer.ts +222 -0
  1326. package/src/tools/conflict-detect.ts +815 -0
  1327. package/src/tools/context.ts +49 -0
  1328. package/src/tools/debug.ts +1121 -0
  1329. package/src/tools/default-renderer.ts +154 -0
  1330. package/src/tools/essential-tools.ts +46 -0
  1331. package/src/tools/eval-backends.ts +34 -0
  1332. package/src/tools/eval-format/index.ts +24 -0
  1333. package/src/tools/eval-format/javascript.ts +952 -0
  1334. package/src/tools/eval-format/julia.ts +446 -0
  1335. package/src/tools/eval-format/python.ts +544 -0
  1336. package/src/tools/eval-format/ruby.ts +380 -0
  1337. package/src/tools/eval-render.ts +784 -0
  1338. package/src/tools/eval.ts +774 -0
  1339. package/src/tools/fetch.ts +1889 -0
  1340. package/src/tools/file-recorder.ts +35 -0
  1341. package/src/tools/fs-cache-invalidation.ts +28 -0
  1342. package/src/tools/gh-cache-invalidation.ts +175 -0
  1343. package/src/tools/gh-format.ts +12 -0
  1344. package/src/tools/gh-renderer.ts +484 -0
  1345. package/src/tools/gh.ts +3958 -0
  1346. package/src/tools/github-cache.ts +663 -0
  1347. package/src/tools/glob.ts +691 -0
  1348. package/src/tools/grep.ts +1920 -0
  1349. package/src/tools/grouped-file-output.ts +210 -0
  1350. package/src/tools/hub/index.ts +579 -0
  1351. package/src/tools/hub/jobs.ts +714 -0
  1352. package/src/tools/hub/launch.ts +690 -0
  1353. package/src/tools/hub/messaging.ts +735 -0
  1354. package/src/tools/hub/types.ts +117 -0
  1355. package/src/tools/image-gen.ts +1689 -0
  1356. package/src/tools/image-providers.ts +50 -0
  1357. package/src/tools/index.ts +736 -0
  1358. package/src/tools/inspect-image-renderer.ts +133 -0
  1359. package/src/tools/inspect-image.ts +316 -0
  1360. package/src/tools/json-tree.ts +260 -0
  1361. package/src/tools/jtd-to-json-schema.ts +219 -0
  1362. package/src/tools/jtd-to-typescript.ts +136 -0
  1363. package/src/tools/jtd-utils.ts +102 -0
  1364. package/src/tools/learn.ts +141 -0
  1365. package/src/tools/list-limit.ts +40 -0
  1366. package/src/tools/manage-skill.ts +102 -0
  1367. package/src/tools/match-line-format.ts +20 -0
  1368. package/src/tools/memory-edit.ts +61 -0
  1369. package/src/tools/memory-recall.ts +102 -0
  1370. package/src/tools/memory-reflect.ts +88 -0
  1371. package/src/tools/memory-render.ts +211 -0
  1372. package/src/tools/memory-retain.ts +89 -0
  1373. package/src/tools/output-meta.ts +860 -0
  1374. package/src/tools/output-schema-validator.ts +307 -0
  1375. package/src/tools/path-utils.ts +1489 -0
  1376. package/src/tools/plan-mode-guard.ts +155 -0
  1377. package/src/tools/puppeteer/00_stealth_tampering.txt +44 -0
  1378. package/src/tools/puppeteer/01_stealth_activity.txt +80 -0
  1379. package/src/tools/puppeteer/02_stealth_hairline.txt +57 -0
  1380. package/src/tools/puppeteer/03_stealth_botd.txt +380 -0
  1381. package/src/tools/puppeteer/04_stealth_iframe.txt +174 -0
  1382. package/src/tools/puppeteer/05_stealth_webgl.txt +233 -0
  1383. package/src/tools/puppeteer/06_stealth_screen.txt +260 -0
  1384. package/src/tools/puppeteer/07_stealth_fonts.txt +99 -0
  1385. package/src/tools/puppeteer/08_stealth_audio.txt +63 -0
  1386. package/src/tools/puppeteer/09_stealth_locale.txt +51 -0
  1387. package/src/tools/puppeteer/10_stealth_plugins.txt +212 -0
  1388. package/src/tools/puppeteer/11_stealth_hardware.txt +59 -0
  1389. package/src/tools/puppeteer/12_stealth_codecs.txt +42 -0
  1390. package/src/tools/puppeteer/13_stealth_worker.txt +235 -0
  1391. package/src/tools/read.ts +3762 -0
  1392. package/src/tools/render-utils.ts +926 -0
  1393. package/src/tools/renderers.ts +133 -0
  1394. package/src/tools/report-tool-issue.ts +568 -0
  1395. package/src/tools/resolve.ts +423 -0
  1396. package/src/tools/review.ts +103 -0
  1397. package/src/tools/run-scope.ts +417 -0
  1398. package/src/tools/security-scan.ts +287 -0
  1399. package/src/tools/shell-tokenize.ts +213 -0
  1400. package/src/tools/sqlite-reader.ts +884 -0
  1401. package/src/tools/terminal-output.ts +141 -0
  1402. package/src/tools/todo.ts +1226 -0
  1403. package/src/tools/tool-errors.ts +62 -0
  1404. package/src/tools/tool-result.ts +102 -0
  1405. package/src/tools/tool-timeouts.ts +38 -0
  1406. package/src/tools/tts.ts +266 -0
  1407. package/src/tools/vibe.ts +608 -0
  1408. package/src/tools/write.ts +1646 -0
  1409. package/src/tools/xdev.ts +560 -0
  1410. package/src/tools/yield.ts +486 -0
  1411. package/src/tts/downloader.ts +64 -0
  1412. package/src/tts/index.ts +10 -0
  1413. package/src/tts/models.ts +137 -0
  1414. package/src/tts/runtime.ts +21 -0
  1415. package/src/tts/speakable.ts +392 -0
  1416. package/src/tts/speech-enhancer.ts +206 -0
  1417. package/src/tts/streaming-player.ts +120 -0
  1418. package/src/tts/tts-client.ts +475 -0
  1419. package/src/tts/tts-protocol.ts +69 -0
  1420. package/src/tts/tts-worker.ts +434 -0
  1421. package/src/tts/vocalizer.ts +419 -0
  1422. package/src/tts/wav.ts +58 -0
  1423. package/src/tui/code-cell.ts +268 -0
  1424. package/src/tui/file-list.ts +55 -0
  1425. package/src/tui/hyperlink.ts +178 -0
  1426. package/src/tui/index.ts +13 -0
  1427. package/src/tui/output-block.ts +268 -0
  1428. package/src/tui/status-line.ts +54 -0
  1429. package/src/tui/tree-list.ts +172 -0
  1430. package/src/tui/types.ts +15 -0
  1431. package/src/tui/utils.ts +103 -0
  1432. package/src/tui/width-aware-text.ts +58 -0
  1433. package/src/utils/active-repo-context.ts +143 -0
  1434. package/src/utils/block-context.ts +312 -0
  1435. package/src/utils/changelog.ts +373 -0
  1436. package/src/utils/clipboard.ts +361 -0
  1437. package/src/utils/command-args.ts +74 -0
  1438. package/src/utils/commit-message-generator.ts +148 -0
  1439. package/src/utils/cpuprofile.ts +235 -0
  1440. package/src/utils/edit-mode.ts +61 -0
  1441. package/src/utils/enhanced-paste.ts +230 -0
  1442. package/src/utils/event-bus.ts +33 -0
  1443. package/src/utils/external-editor.ts +80 -0
  1444. package/src/utils/fetch-timeout.ts +10 -0
  1445. package/src/utils/file-display-mode.ts +44 -0
  1446. package/src/utils/file-mentions.ts +293 -0
  1447. package/src/utils/git.ts +2472 -0
  1448. package/src/utils/image-loading.ts +236 -0
  1449. package/src/utils/image-resize.ts +420 -0
  1450. package/src/utils/image-vision-fallback.ts +196 -0
  1451. package/src/utils/inspect-image-mode.ts +39 -0
  1452. package/src/utils/ipc.ts +38 -0
  1453. package/src/utils/jj.ts +422 -0
  1454. package/src/utils/lang-from-path.ts +251 -0
  1455. package/src/utils/late-cleanup.ts +17 -0
  1456. package/src/utils/local-date.ts +7 -0
  1457. package/src/utils/mac-file-urls.applescript +37 -0
  1458. package/src/utils/markit-cache.ts +166 -0
  1459. package/src/utils/markit.ts +223 -0
  1460. package/src/utils/mupdf-wasm-embed.ts +12 -0
  1461. package/src/utils/open.ts +126 -0
  1462. package/src/utils/profile-tree.ts +111 -0
  1463. package/src/utils/prompt-path.ts +3 -0
  1464. package/src/utils/qrcode.ts +535 -0
  1465. package/src/utils/sample-profile.ts +437 -0
  1466. package/src/utils/session-color.ts +142 -0
  1467. package/src/utils/shell-snapshot-fn-env.sh +63 -0
  1468. package/src/utils/shell-snapshot.ts +326 -0
  1469. package/src/utils/sixel.ts +69 -0
  1470. package/src/utils/thinking-display.ts +163 -0
  1471. package/src/utils/title-generator.ts +597 -0
  1472. package/src/utils/token-rate.ts +72 -0
  1473. package/src/utils/tool-choice.ts +50 -0
  1474. package/src/utils/tools-manager.ts +411 -0
  1475. package/src/utils/turndown.ts +82 -0
  1476. package/src/utils/zip.ts +1106 -0
  1477. package/src/vibe/runtime.ts +1684 -0
  1478. package/src/vibe/state.ts +4 -0
  1479. package/src/web/kagi.ts +305 -0
  1480. package/src/web/parallel.ts +354 -0
  1481. package/src/web/scrapers/artifacthub.ts +207 -0
  1482. package/src/web/scrapers/arxiv.ts +83 -0
  1483. package/src/web/scrapers/aur.ts +162 -0
  1484. package/src/web/scrapers/biorxiv.ts +133 -0
  1485. package/src/web/scrapers/bluesky.ts +262 -0
  1486. package/src/web/scrapers/brew.ts +172 -0
  1487. package/src/web/scrapers/cheatsh.ts +68 -0
  1488. package/src/web/scrapers/chocolatey.ts +196 -0
  1489. package/src/web/scrapers/choosealicense.ts +95 -0
  1490. package/src/web/scrapers/cisa-kev.ts +87 -0
  1491. package/src/web/scrapers/clojars.ts +154 -0
  1492. package/src/web/scrapers/coingecko.ts +177 -0
  1493. package/src/web/scrapers/crates-io.ts +97 -0
  1494. package/src/web/scrapers/crossref.ts +136 -0
  1495. package/src/web/scrapers/devto.ts +147 -0
  1496. package/src/web/scrapers/discogs.ts +306 -0
  1497. package/src/web/scrapers/discourse.ts +197 -0
  1498. package/src/web/scrapers/dockerhub.ts +138 -0
  1499. package/src/web/scrapers/docs-rs.ts +663 -0
  1500. package/src/web/scrapers/fdroid.ts +134 -0
  1501. package/src/web/scrapers/firefox-addons.ts +191 -0
  1502. package/src/web/scrapers/flathub.ts +223 -0
  1503. package/src/web/scrapers/github-gist.ts +58 -0
  1504. package/src/web/scrapers/github.ts +800 -0
  1505. package/src/web/scrapers/gitlab.ts +401 -0
  1506. package/src/web/scrapers/go-pkg.ts +266 -0
  1507. package/src/web/scrapers/hackage.ts +129 -0
  1508. package/src/web/scrapers/hackernews.ts +189 -0
  1509. package/src/web/scrapers/hex.ts +105 -0
  1510. package/src/web/scrapers/huggingface.ts +321 -0
  1511. package/src/web/scrapers/iacr.ts +89 -0
  1512. package/src/web/scrapers/index.ts +252 -0
  1513. package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
  1514. package/src/web/scrapers/lemmy.ts +203 -0
  1515. package/src/web/scrapers/lobsters.ts +175 -0
  1516. package/src/web/scrapers/mastodon.ts +292 -0
  1517. package/src/web/scrapers/maven.ts +138 -0
  1518. package/src/web/scrapers/mdn.ts +173 -0
  1519. package/src/web/scrapers/metacpan.ts +222 -0
  1520. package/src/web/scrapers/musicbrainz.ts +250 -0
  1521. package/src/web/scrapers/npm.ts +98 -0
  1522. package/src/web/scrapers/nuget.ts +183 -0
  1523. package/src/web/scrapers/nvd.ts +222 -0
  1524. package/src/web/scrapers/ollama.ts +239 -0
  1525. package/src/web/scrapers/open-vsx.ts +106 -0
  1526. package/src/web/scrapers/opencorporates.ts +292 -0
  1527. package/src/web/scrapers/openlibrary.ts +336 -0
  1528. package/src/web/scrapers/orcid.ts +286 -0
  1529. package/src/web/scrapers/osv.ts +176 -0
  1530. package/src/web/scrapers/packagist.ts +160 -0
  1531. package/src/web/scrapers/pub-dev.ts +143 -0
  1532. package/src/web/scrapers/pubmed.ts +211 -0
  1533. package/src/web/scrapers/pypi.ts +112 -0
  1534. package/src/web/scrapers/rawg.ts +110 -0
  1535. package/src/web/scrapers/readthedocs.ts +121 -0
  1536. package/src/web/scrapers/reddit.ts +95 -0
  1537. package/src/web/scrapers/repology.ts +251 -0
  1538. package/src/web/scrapers/rfc.ts +201 -0
  1539. package/src/web/scrapers/rubygems.ts +103 -0
  1540. package/src/web/scrapers/searchcode.ts +189 -0
  1541. package/src/web/scrapers/sec-edgar.ts +261 -0
  1542. package/src/web/scrapers/semantic-scholar.ts +171 -0
  1543. package/src/web/scrapers/snapcraft.ts +187 -0
  1544. package/src/web/scrapers/sourcegraph.ts +336 -0
  1545. package/src/web/scrapers/spdx.ts +108 -0
  1546. package/src/web/scrapers/spotify.ts +198 -0
  1547. package/src/web/scrapers/stackoverflow.ts +120 -0
  1548. package/src/web/scrapers/terraform.ts +277 -0
  1549. package/src/web/scrapers/tldr.ts +47 -0
  1550. package/src/web/scrapers/twitter.ts +94 -0
  1551. package/src/web/scrapers/types.ts +354 -0
  1552. package/src/web/scrapers/utils.ts +109 -0
  1553. package/src/web/scrapers/vimeo.ts +133 -0
  1554. package/src/web/scrapers/vscode-marketplace.ts +187 -0
  1555. package/src/web/scrapers/w3c.ts +156 -0
  1556. package/src/web/scrapers/wikidata.ts +344 -0
  1557. package/src/web/scrapers/wikipedia.ts +84 -0
  1558. package/src/web/scrapers/youtube.ts +325 -0
  1559. package/src/web/search/index.ts +393 -0
  1560. package/src/web/search/provider.ts +272 -0
  1561. package/src/web/search/providers/anthropic.ts +406 -0
  1562. package/src/web/search/providers/base.ts +112 -0
  1563. package/src/web/search/providers/brave.ts +181 -0
  1564. package/src/web/search/providers/browser-headers.ts +82 -0
  1565. package/src/web/search/providers/browser-page.ts +125 -0
  1566. package/src/web/search/providers/codex.ts +788 -0
  1567. package/src/web/search/providers/duckduckgo.ts +382 -0
  1568. package/src/web/search/providers/ecosia.ts +183 -0
  1569. package/src/web/search/providers/exa.ts +513 -0
  1570. package/src/web/search/providers/firecrawl.ts +213 -0
  1571. package/src/web/search/providers/gemini.ts +634 -0
  1572. package/src/web/search/providers/google.ts +195 -0
  1573. package/src/web/search/providers/jina.ts +144 -0
  1574. package/src/web/search/providers/kagi.ts +98 -0
  1575. package/src/web/search/providers/kimi.ts +221 -0
  1576. package/src/web/search/providers/mojeek.ts +220 -0
  1577. package/src/web/search/providers/parallel.ts +186 -0
  1578. package/src/web/search/providers/perplexity-auth.ts +142 -0
  1579. package/src/web/search/providers/perplexity.ts +997 -0
  1580. package/src/web/search/providers/public.ts +199 -0
  1581. package/src/web/search/providers/searxng.ts +467 -0
  1582. package/src/web/search/providers/startpage.ts +225 -0
  1583. package/src/web/search/providers/synthetic.ts +126 -0
  1584. package/src/web/search/providers/tavily.ts +244 -0
  1585. package/src/web/search/providers/tinyfish.ts +166 -0
  1586. package/src/web/search/providers/utils.ts +130 -0
  1587. package/src/web/search/providers/xai.ts +372 -0
  1588. package/src/web/search/providers/zai.ts +452 -0
  1589. package/src/web/search/query.ts +850 -0
  1590. package/src/web/search/render.ts +262 -0
  1591. package/src/web/search/types.ts +518 -0
  1592. package/src/web/search/utils.ts +17 -0
  1593. package/src/workspace-tree.ts +326 -0
@@ -0,0 +1,1826 @@
1
+ import * as fs from "node:fs";
2
+ import { type } from "@oh-my-pi/omptype";
3
+ import type {
4
+ AgentTool,
5
+ AgentToolContext,
6
+ AgentToolResult,
7
+ AgentToolUpdateCallback,
8
+ ToolApprovalDecision,
9
+ } from "@oh-my-pi/pi-agent-core";
10
+ import type { Component } from "@oh-my-pi/pi-tui";
11
+ import { ImageProtocol, TERMINAL } from "@oh-my-pi/pi-tui";
12
+ import { getProjectDir, isEnoent, logger, prompt } from "@oh-my-pi/pi-utils";
13
+ import type { Settings } from "../config/settings";
14
+ import { applyDirenvPreflight, type BashResult, executeBash } from "../exec/bash-executor";
15
+ import type { RenderResultOptions } from "../extensibility/custom-tools/types";
16
+ import { InternalUrlRouter } from "../internal-urls";
17
+ import { truncateToVisualLines } from "../modes/components/visual-truncate";
18
+ import { highlightCode, type Theme } from "../modes/theme/theme";
19
+ import bashDescription from "../prompts/tools/bash.md" with { type: "text" };
20
+ import type {
21
+ ClientBridgeTerminalExitStatus,
22
+ ClientBridgeTerminalHandle,
23
+ ClientBridgeTerminalOutput,
24
+ } from "../session/client-bridge";
25
+ import { DEFAULT_MAX_BYTES, enforceInlineByteCap, streamTailUpdates, TailBuffer } from "../session/streaming-output";
26
+ import { renderStatusLine } from "../tui";
27
+ import { CachedOutputBlock, markFramedBlockComponent, outputBlockContentWidth } from "../tui/output-block";
28
+ import { getSixelLineMask } from "../utils/sixel";
29
+ import type { ToolSession } from ".";
30
+ import { truncateForPrompt } from "./approval";
31
+ import { type BashInteractiveResult, runInteractiveBashPty } from "./bash-interactive";
32
+ import { checkBashInterception } from "./bash-interceptor";
33
+ import { canUseInteractiveBashPty } from "./bash-pty-selection";
34
+ import { expandInternalUrls, type InternalUrlExpansionOptions } from "./bash-skill-urls";
35
+ import { resolveEvalBackends } from "./eval-backends";
36
+ import { invalidateGithubCacheForBashCommand } from "./gh-cache-invalidation";
37
+ import {
38
+ formatStyledTruncationWarning,
39
+ type OutputMeta,
40
+ resolveInlineByteCapBudget,
41
+ stripOutputNotice,
42
+ stripRawOutputArtifactNotice,
43
+ } from "./output-meta";
44
+ import { resolveToCwd } from "./path-utils";
45
+ import {
46
+ capPreviewLines,
47
+ DEFAULT_TERMINAL_PREVIEW_LINES,
48
+ formatToolWorkingDirectory,
49
+ previewWindowRows,
50
+ replaceTabs,
51
+ } from "./render-utils";
52
+ import { tokenizeShellSegments } from "./shell-tokenize";
53
+ import { ToolAbortError, ToolError } from "./tool-errors";
54
+ import { toolResult } from "./tool-result";
55
+ import { clampTimeout, TOOL_TIMEOUTS } from "./tool-timeouts";
56
+
57
+ export const BASH_DEFAULT_PREVIEW_LINES = DEFAULT_TERMINAL_PREVIEW_LINES;
58
+
59
+ const BASH_ENV_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
60
+ const DEFAULT_AUTO_BACKGROUND_THRESHOLD_MS = 60_000;
61
+ const BASH_APPROVAL_SHELL_CONTROL_CHARS: Record<string, true> = {
62
+ "\n": true,
63
+ "\r": true,
64
+ ";": true,
65
+ "&": true,
66
+ "|": true,
67
+ "<": true,
68
+ ">": true,
69
+ "`": true,
70
+ $: true,
71
+ "(": true,
72
+ ")": true,
73
+ };
74
+ const BASH_APPROVAL_REINTERPRETED_ARGUMENT_RE = /(?:^|[ \t])(?:-[^-]*[ce]|--(?:command|eval))(?:[= \t]|$)/u;
75
+
76
+ function hasBashApprovalShellControl(command: string): boolean {
77
+ let quote: "'" | '"' | undefined;
78
+ let hasReinterpretableShellControl = false;
79
+ for (let i = 0; i < command.length; i++) {
80
+ const ch = command[i];
81
+ if (quote === "'") {
82
+ if (ch === "'") {
83
+ quote = undefined;
84
+ } else if (Object.hasOwn(BASH_APPROVAL_SHELL_CONTROL_CHARS, ch)) {
85
+ hasReinterpretableShellControl = true;
86
+ }
87
+ continue;
88
+ }
89
+ if (ch === "\\") {
90
+ const escaped = command[i + 1];
91
+ if (escaped && Object.hasOwn(BASH_APPROVAL_SHELL_CONTROL_CHARS, escaped)) {
92
+ hasReinterpretableShellControl = true;
93
+ }
94
+ i++;
95
+ continue;
96
+ }
97
+ if (quote === '"') {
98
+ if (ch === '"') {
99
+ quote = undefined;
100
+ continue;
101
+ }
102
+ // Expansion is active inside double quotes even in the original line.
103
+ if (ch === "`" || ch === "$") return true;
104
+ // Other control characters are literal here but become executable if a
105
+ // `-c`/`-e` option reinterprets the argument through another shell.
106
+ if (Object.hasOwn(BASH_APPROVAL_SHELL_CONTROL_CHARS, ch)) hasReinterpretableShellControl = true;
107
+ continue;
108
+ }
109
+ if (ch === "'" || ch === '"') {
110
+ quote = ch;
111
+ continue;
112
+ }
113
+ if (Object.hasOwn(BASH_APPROVAL_SHELL_CONTROL_CHARS, ch)) return true;
114
+ }
115
+ // Options such as `git -c alias.x='!...'` and `sh -c "..."` reinterpret
116
+ // otherwise literal quoted or escaped arguments as executable code.
117
+ return hasReinterpretableShellControl && BASH_APPROVAL_REINTERPRETED_ARGUMENT_RE.test(command);
118
+ }
119
+
120
+ const BASH_PATTERN_APPROVAL_VALUES = new Set(["allow", "deny", "prompt"]);
121
+
122
+ /**
123
+ * Shape a shell command line for an ACP-conformant `terminal/create` request.
124
+ *
125
+ * ACP's `command` field is documented as the executable and `args` as its
126
+ * argv tail (see https://agentclientprotocol.com/protocol/v1/terminals), so a
127
+ * spec-conformant client `spawn(command, args)`s them directly — no implicit
128
+ * shell. A raw `bash` tool line ("git status && echo x | head") therefore has
129
+ * to be wrapped in an explicit shell invocation, otherwise the client tries
130
+ * to spawn the whole line as argv[0] and fails with `ENOENT` for anything
131
+ * containing a space, pipe, `&&`, redirect, or `$(...)`.
132
+ *
133
+ * The wrap reuses the same shell binary + args the local `bash-executor` would
134
+ * pick via `settings.getShellConfig()` — Git Bash / `bash.exe` on Windows
135
+ * (`cmd.exe /c` as the last-resort fallback when no bash exists on the host),
136
+ * `$SHELL` (bash/zsh) with the `sh` fallback on POSIX — so the ACP path
137
+ * preserves `bash` tool semantics (`$VAR`, `$(...)`, `source`, POSIX quoting,
138
+ * `-l`) wherever a POSIX shell is available. The agent host's shell path is
139
+ * used as a proxy for the client's, matching the near-universal ACP
140
+ * deployment shape of an editor spawning omp as a co-hosted subprocess.
141
+ */
142
+ export function wrapShellLineForClientTerminal(
143
+ line: string,
144
+ shellConfig: { shell: string; args: string[]; prefix?: string | undefined },
145
+ ): { command: string; args: string[] } {
146
+ const finalLine = shellConfig.prefix ? `${shellConfig.prefix} ${line}` : line;
147
+ return { command: shellConfig.shell, args: [...shellConfig.args, finalLine] };
148
+ }
149
+
150
+ /**
151
+ * Mirrors pi-shell's `uutils_env_disabled` gate for `PI_DISABLE_UUTILS_BUILTINS`:
152
+ * session shell env first, then process env; truthy = present and not "", "0",
153
+ * or "false". Controls whether the prompt advertises the in-process builtins.
154
+ */
155
+ function shellBuiltinsDisabled(settings: Settings): boolean {
156
+ const raw = settings.getShellConfig().env?.PI_DISABLE_UUTILS_BUILTINS ?? Bun.env.PI_DISABLE_UUTILS_BUILTINS;
157
+ return !!raw && raw !== "0" && raw.toLowerCase() !== "false";
158
+ }
159
+
160
+ /**
161
+ * Bash patterns flagged as safety critical for approval policy.
162
+ *
163
+ * Kept intentionally tight — the cost of a false negative is data loss or a compromised host,
164
+ * while false positives remain actionable through user policy control.
165
+ * New patterns should target shapes that are virtually never legitimate in automation.
166
+ */
167
+ export const CRITICAL_BASH_PATTERNS = [
168
+ // Recursive destruction.
169
+ /\brm\s+-[a-z]*[rRfF][a-z]*\s+\//i, // rm -rf /, rm -fr /, rm -r /, rm -f /…
170
+ /\bsudo\s+rm\b/i, // any `sudo rm`.
171
+ /\bchmod\s+-R\s+[0-7]+\s+\//i, // `chmod -R 777 /`.
172
+ /\bchmod\s+-R\s+[ugoa+\-=rwxXst,]+\s+\//, // `chmod -R u+x /`, `chmod -R u+rwx,o+w /etc` (symbolic mode, root target).
173
+ /\bchown\s+-R\s+\S+\s+\//i, // `chown -R user /`.
174
+
175
+ // Fork bomb (a few common spacings).
176
+ /:\(\)\s*\{\s*:\s*\|\s*:/i,
177
+
178
+ // Disk / filesystem destruction.
179
+ />\s*\/dev\/sd[a-z]/i, // write to disk device.
180
+ /\bmkfs(\.|\b)/i, // format filesystem.
181
+ /\bdd\s+if=.+of=\/dev\//i, // dd to a device.
182
+ /\bshred\s+\/dev\//i,
183
+ /\bcryptsetup\b/i,
184
+
185
+ // System-config destruction.
186
+ />\s*\/etc\/(?:passwd|shadow|sudoers)\b/i,
187
+ /\btee\s+(?:-a\s+)?\/etc\/(?:passwd|shadow|sudoers)\b/i, // `tee /etc/passwd`, `tee -a /etc/sudoers`.
188
+
189
+ // Remote-fetch-then-execute (curl/wget piped to a shell or process-subbed).
190
+ /\b(?:curl|wget|fetch)\b[^|]*\|\s*(?:bash|sh|zsh|fish)\b/i,
191
+ // Process-sub variants — `bash <(curl …)`, `source <(curl …)`, `. <(curl …)`. `.` and `source` are
192
+ // anchored to a command boundary so `find . -name` and similar don't false-positive.
193
+ /(?:^|[\s;&|(])(?:bash|sh|zsh|source|\.)\s+<\(\s*(?:curl|wget|fetch)\b/i,
194
+ // `eval "$(curl …)"` / `eval $(curl …)` / `eval \`curl …\``.
195
+ /\beval\s+["'`]?\$\(\s*(?:curl|wget|fetch)\b|\beval\s+`\s*(?:curl|wget|fetch)\b/i,
196
+
197
+ // Process/host control.
198
+ /\bkill\s+-9\s+1\b/, // kill PID 1.
199
+ // Process/host control — must sit at command position so `npm run reboot-tests`
200
+ // or `echo 'shutdown the queue'` don't false-positive.
201
+ /(?:^|[\s;&|(])(?:shutdown|poweroff|reboot|halt)(?:\s|$|[;|&])/i,
202
+ /(?:^|[\s;&|(])init\s+0\b/i,
203
+
204
+ // Network-shell exfil.
205
+ /\bnc\b[^|;]*\s-[a-zA-Z]*[ec][a-zA-Z]*\s/i, // `nc -e` / `nc -c`.
206
+ ] as const;
207
+
208
+ type BashPatternApproval = "allow" | "deny" | "prompt";
209
+
210
+ interface BashApprovalPatternRule {
211
+ match: string;
212
+ approval: BashPatternApproval;
213
+ }
214
+
215
+ function normalizeBashApprovalPattern(value: string): string {
216
+ return value.trim().replace(/\s+/gu, " ");
217
+ }
218
+
219
+ function bashApprovalPatternToRegExp(pattern: string): RegExp {
220
+ const escaped = normalizeBashApprovalPattern(pattern)
221
+ .split("*")
222
+ .map(part => part.replace(/[\\^$+?.()|[\]{}]/gu, "\\$&"))
223
+ .join(".*");
224
+ return new RegExp(`^${escaped}$`, "u");
225
+ }
226
+
227
+ function normalizeBashPatternApproval(value: unknown): BashPatternApproval | undefined {
228
+ if (typeof value !== "string") return undefined;
229
+ const normalized = value.trim().toLowerCase();
230
+ return BASH_PATTERN_APPROVAL_VALUES.has(normalized) ? (normalized as BashPatternApproval) : undefined;
231
+ }
232
+
233
+ function getBashApprovalPatternRules(value: unknown): BashApprovalPatternRule[] {
234
+ if (!Array.isArray(value)) return [];
235
+ return value
236
+ .map(item => {
237
+ if (!item || typeof item !== "object" || Array.isArray(item)) return undefined;
238
+ const record = item as Record<string, unknown>;
239
+ if (typeof record.match !== "string") return undefined;
240
+ const match = normalizeBashApprovalPattern(record.match);
241
+ const approval = normalizeBashPatternApproval(record.approval);
242
+ return match.length > 0 && approval ? { match, approval } : undefined;
243
+ })
244
+ .filter((rule): rule is BashApprovalPatternRule => !!rule);
245
+ }
246
+
247
+ function commandMatchesBashApprovalPattern(command: string, pattern: string): boolean {
248
+ const normalizedCommand = normalizeBashApprovalPattern(command);
249
+ if (normalizedCommand.length === 0) return false;
250
+ return bashApprovalPatternToRegExp(pattern).test(normalizedCommand);
251
+ }
252
+
253
+ // `deny`/`prompt` rules are matched per segment so a dangerous command buried in
254
+ // a compound line (`cd x && rm -rf /`, `sleep 1 & rm -rf /`) is still caught.
255
+ // Reuse the shared shell tokenizer so segmentation stays in one place and honors
256
+ // every command boundary (`;`, `&&`, `||`, `|`, `&`, subshells, newlines).
257
+ function bashCommandSegments(command: string): string[] {
258
+ return tokenizeShellSegments(command)
259
+ .map(segment => segment.join(" "))
260
+ .filter(segment => segment.length > 0);
261
+ }
262
+
263
+ // `deny`/`prompt` matching: the rule fires when its glob matches the whole
264
+ // command or any single segment of a compound command.
265
+ function commandSegmentMatchesBashApprovalPattern(command: string, pattern: string): boolean {
266
+ const regex = bashApprovalPatternToRegExp(pattern);
267
+ const normalizedCommand = normalizeBashApprovalPattern(command);
268
+ if (normalizedCommand.length === 0) return false;
269
+ if (regex.test(normalizedCommand)) return true;
270
+ return bashCommandSegments(command).some(segment => regex.test(segment));
271
+ }
272
+
273
+ // A rule "applies" to a command under approval-specific semantics: `allow` must
274
+ // vouch for the ENTIRE command and never rides a compound line (shell control
275
+ // syntax could smuggle an unsafe segment past a narrow allow), while `deny` and
276
+ // `prompt` fire on any matching segment so they mean what they appear to.
277
+ function bashApprovalRuleMatches(command: string, rule: BashApprovalPatternRule): boolean {
278
+ if (rule.approval === "allow") {
279
+ if (hasBashApprovalShellControl(command)) return false;
280
+ return commandMatchesBashApprovalPattern(command, rule.match);
281
+ }
282
+ return commandSegmentMatchesBashApprovalPattern(command, rule.match);
283
+ }
284
+
285
+ function findBashApprovalPatternRule(
286
+ command: string,
287
+ rules: readonly BashApprovalPatternRule[],
288
+ ): BashApprovalPatternRule | undefined {
289
+ return rules.find(rule => bashApprovalRuleMatches(command, rule));
290
+ }
291
+
292
+ async function saveBashOriginalArtifact(session: ToolSession, originalText: string): Promise<string | undefined> {
293
+ try {
294
+ const alloc = await session.allocateOutputArtifact?.("bash-original");
295
+ if (!alloc?.path || !alloc.id) return undefined;
296
+ await Bun.write(alloc.path, originalText);
297
+ return alloc.id;
298
+ } catch {
299
+ return undefined;
300
+ }
301
+ }
302
+
303
+ const BASH_TIMEOUT_DESCRIPTION = `timeout in seconds; 0 disables the command deadline; nonzero values are clamped to ${TOOL_TIMEOUTS.bash.min}-${TOOL_TIMEOUTS.bash.max}`;
304
+
305
+ const bashSchemaBase = type({
306
+ command: type("string").describe("command to execute"),
307
+ "env?": type({ "[string]": "string" }).describe("extra env vars"),
308
+ "timeout?": type("number").describe(BASH_TIMEOUT_DESCRIPTION),
309
+ "cwd?": type("string").describe("working directory"),
310
+ "pty?": type("boolean").describe("run in pty mode"),
311
+ });
312
+
313
+ const bashSchemaWithAsync = type({
314
+ command: "string",
315
+ "env?": { "[string]": "string" },
316
+ "timeout?": type("number").describe(BASH_TIMEOUT_DESCRIPTION),
317
+ "cwd?": "string",
318
+ "pty?": "boolean",
319
+ "async?": type("boolean").describe("run in background"),
320
+ });
321
+
322
+ type BashToolSchema = typeof bashSchemaBase | typeof bashSchemaWithAsync;
323
+
324
+ export interface BashToolInput {
325
+ command: string;
326
+ env?: Record<string, string>;
327
+ timeout?: number;
328
+ cwd?: string;
329
+
330
+ async?: boolean;
331
+ pty?: boolean;
332
+ }
333
+
334
+ export interface BashToolDetails {
335
+ meta?: OutputMeta;
336
+ timeoutSeconds?: number;
337
+ requestedTimeoutSeconds?: number;
338
+ timeoutDisabled?: boolean;
339
+ wallTimeMs?: number;
340
+ /** Exit code of a command that ran to completion but failed (non-zero). */
341
+ exitCode?: number;
342
+ /** True when the command was killed by its timeout deadline (not a failure). */
343
+ timedOut?: boolean;
344
+ terminalId?: string;
345
+ async?: {
346
+ state: "running" | "completed" | "failed";
347
+ jobId: string;
348
+ type: "bash";
349
+ };
350
+ }
351
+
352
+ export interface BashToolOptions {}
353
+
354
+ type ManagedBashJobCompletion =
355
+ | {
356
+ kind: "completed";
357
+ result: AgentToolResult<BashToolDetails>;
358
+ }
359
+ | {
360
+ kind: "failed";
361
+ error: unknown;
362
+ };
363
+
364
+ interface ManagedBashJobHandle {
365
+ jobId: string;
366
+ completion: Promise<ManagedBashJobCompletion>;
367
+ getLatestText: () => string;
368
+ stopUpdates: () => void;
369
+ }
370
+
371
+ function normalizeResultOutput(result: BashResult | BashInteractiveResult): string {
372
+ return result.output || "";
373
+ }
374
+
375
+ function normalizeBashEnv(env: Record<string, string> | undefined): Record<string, string> | undefined {
376
+ if (!env || Object.keys(env).length === 0) return undefined;
377
+ const normalized: Record<string, string> = {};
378
+ for (const [key, value] of Object.entries(env)) {
379
+ if (!BASH_ENV_NAME_PATTERN.test(key)) {
380
+ throw new ToolError(`Invalid bash env name: ${key}`);
381
+ }
382
+ normalized[key] = value;
383
+ }
384
+ return normalized;
385
+ }
386
+
387
+ function escapeBashEnvValueForDisplay(value: unknown): string {
388
+ return String(value)
389
+ .replaceAll("\\", "\\\\")
390
+ .replaceAll("\n", "\\n")
391
+ .replaceAll("\r", "\\r")
392
+ .replaceAll("\t", "\\t")
393
+ .replaceAll('"', '\\"')
394
+ .replaceAll("$", "\\$")
395
+ .replaceAll("`", "\\`");
396
+ }
397
+
398
+ function formatBashEnvAssignments(env: Record<string, unknown> | undefined): string {
399
+ if (!env || Object.keys(env).length === 0) return "";
400
+ return Object.entries(env)
401
+ .sort(([a], [b]) => a.localeCompare(b))
402
+ .map(([key, value]) => `${key}="${escapeBashEnvValueForDisplay(value)}"`)
403
+ .join(" ");
404
+ }
405
+
406
+ function unescapePartialJsonString(value: string): string {
407
+ let output = "";
408
+ for (let index = 0; index < value.length; index += 1) {
409
+ const char = value[index];
410
+ if (char !== "\\") {
411
+ output += char;
412
+ continue;
413
+ }
414
+ const next = value[index + 1];
415
+ if (!next) {
416
+ output += "\\";
417
+ break;
418
+ }
419
+ index += 1;
420
+ switch (next) {
421
+ case '"':
422
+ output += '"';
423
+ break;
424
+ case "\\":
425
+ output += "\\";
426
+ break;
427
+ case "/":
428
+ output += "/";
429
+ break;
430
+ case "b":
431
+ output += "\b";
432
+ break;
433
+ case "f":
434
+ output += "\f";
435
+ break;
436
+ case "n":
437
+ output += "\n";
438
+ break;
439
+ case "r":
440
+ output += "\r";
441
+ break;
442
+ case "t":
443
+ output += "\t";
444
+ break;
445
+ case "u": {
446
+ const hex = value.slice(index + 1, index + 5);
447
+ if (/^[0-9a-fA-F]{4}$/u.test(hex)) {
448
+ output += String.fromCharCode(Number.parseInt(hex, 16));
449
+ index += 4;
450
+ } else {
451
+ output += "\\u";
452
+ }
453
+ break;
454
+ }
455
+ default:
456
+ output += next;
457
+ }
458
+ }
459
+ return output;
460
+ }
461
+
462
+ function extractPartialBashEnv(partialJson: string | undefined): Record<string, string> | undefined {
463
+ if (!partialJson) return undefined;
464
+ const envStart = partialJson.search(/"env"\s*:\s*\{/u);
465
+ if (envStart === -1) return undefined;
466
+ const objectStart = partialJson.indexOf("{", envStart);
467
+ if (objectStart === -1) return undefined;
468
+ const envBody = partialJson.slice(objectStart + 1);
469
+ const env: Record<string, string> = {};
470
+ const matcher = /"([A-Za-z_][A-Za-z0-9_]*)"\s*:\s*"((?:\\.|[^"\\])*)(?:"|$)/gu;
471
+ for (const match of envBody.matchAll(matcher)) {
472
+ env[match[1]!] = unescapePartialJsonString(match[2]!);
473
+ }
474
+ return Object.keys(env).length > 0 ? env : undefined;
475
+ }
476
+
477
+ function formatTimeoutClampNotice(
478
+ requestedTimeoutSec: number,
479
+ effectiveTimeoutSec: number,
480
+ maxTimeout: number,
481
+ ): string | undefined {
482
+ if (requestedTimeoutSec === effectiveTimeoutSec) return undefined;
483
+ const cappedByGlobal = maxTimeout > 0 && effectiveTimeoutSec === maxTimeout && maxTimeout < TOOL_TIMEOUTS.bash.max;
484
+ const limit = cappedByGlobal
485
+ ? `global tools.maxTimeout ceiling ${maxTimeout}s`
486
+ : `allowed range ${TOOL_TIMEOUTS.bash.min}-${TOOL_TIMEOUTS.bash.max}s`;
487
+ return `Timeout clamped to ${effectiveTimeoutSec}s (requested ${requestedTimeoutSec}s; ${limit}).`;
488
+ }
489
+
490
+ function formatWallTimeSeconds(wallTimeMs: number): string {
491
+ return (wallTimeMs / 1000).toFixed(2);
492
+ }
493
+
494
+ function formatWallTimeNotice(wallTimeMs: number): string {
495
+ return `Wall time: ${formatWallTimeSeconds(wallTimeMs)} seconds`;
496
+ }
497
+
498
+ function formatExitCodeNotice(exitCode: number): string {
499
+ return `Command exited with code ${exitCode}`;
500
+ }
501
+
502
+ function formatBackgroundNotice(jobId: string): string {
503
+ return `Backgrounded as job ${jobId}; result will be delivered automatically.`;
504
+ }
505
+
506
+ /**
507
+ * Strip the trailing occurrence of `notice` (plus a single surrounding newline
508
+ * on each side) so the TUI can echo the value via a styled footer label
509
+ * instead of repeating it verbatim in the output pane. The notice is
510
+ * reconstructed from the same value the result was tagged with, so a literal
511
+ * sub-string match never strips a coincidental in-output token — only the
512
+ * exact line we appended in #buildCompletedResult.
513
+ */
514
+ function stripTrailingNotice(text: string, notice: string): string {
515
+ const idx = text.lastIndexOf(notice);
516
+ if (idx === -1) return text;
517
+ let start = idx;
518
+ let end = idx + notice.length;
519
+ if (text[start - 1] === "\n") start -= 1;
520
+ if (text[end] === "\n") end += 1;
521
+ return (text.slice(0, start) + text.slice(end)).trimEnd();
522
+ }
523
+
524
+ function stripWallTimeNotice(text: string, wallTimeMs: number | undefined): string {
525
+ if (wallTimeMs === undefined) return text;
526
+ return stripTrailingNotice(text, formatWallTimeNotice(wallTimeMs));
527
+ }
528
+
529
+ function stripExitCodeNotice(text: string, exitCode: number | undefined): string {
530
+ if (exitCode === undefined) return text;
531
+ return stripTrailingNotice(text, formatExitCodeNotice(exitCode));
532
+ }
533
+
534
+ function stripBackgroundNotice(text: string, async: BashToolDetails["async"] | undefined): string {
535
+ if (async?.state !== "running") return text;
536
+ return stripTrailingNotice(text, formatBackgroundNotice(async.jobId));
537
+ }
538
+
539
+ /**
540
+ * Bash tool implementation.
541
+ *
542
+ * Executes bash commands with optional timeout and working directory.
543
+ */
544
+ export class BashTool implements AgentTool<typeof bashSchemaBase | typeof bashSchemaWithAsync, BashToolDetails> {
545
+ readonly name = "bash";
546
+ readonly approval = (args: unknown): ToolApprovalDecision => {
547
+ const rawCommand = (args as Partial<BashToolInput>).command;
548
+ const command = typeof rawCommand === "string" ? rawCommand : "";
549
+ const patternRules = getBashApprovalPatternRules(this.session.settings.get("bash.patterns"));
550
+ const patternRule = findBashApprovalPatternRule(command, patternRules);
551
+ if (patternRule?.approval === "deny") {
552
+ return {
553
+ tier: "exec",
554
+ override: true,
555
+ policy: "deny",
556
+ reason: `Blocked by bash pattern: ${patternRule.match}`,
557
+ };
558
+ }
559
+ if (command !== "" && CRITICAL_BASH_PATTERNS.some(pattern => pattern.test(command))) {
560
+ return { tier: "exec", override: true, reason: "Critical pattern detected" };
561
+ }
562
+ if (patternRule?.approval === "allow") return { tier: "write", policy: "allow" };
563
+ if (patternRule?.approval === "prompt") {
564
+ return {
565
+ tier: "exec",
566
+ override: true,
567
+ policy: "prompt",
568
+ reason: `Prompt required by bash pattern: ${patternRule.match}`,
569
+ };
570
+ }
571
+ return "exec";
572
+ };
573
+ readonly formatApprovalDetails = (args: unknown): string[] => {
574
+ const rawCommand = (args as Partial<BashToolInput>).command;
575
+ const command = typeof rawCommand === "string" ? rawCommand : "(missing)";
576
+ return [`Command: ${truncateForPrompt(command)}`];
577
+ };
578
+ readonly label = "Bash";
579
+ readonly loadMode = "essential";
580
+ get description(): string {
581
+ const evalBackends = resolveEvalBackends(this.session);
582
+ const isToolActive = (name: string, fallback: boolean): boolean => this.session.isToolActive?.(name) ?? fallback;
583
+ return prompt.render(bashDescription, {
584
+ asyncEnabled: this.#asyncEnabled,
585
+ autoBackgroundEnabled: this.#autoBackgroundEnabled,
586
+ autoBackgroundThresholdSeconds: Math.max(0, Math.floor(this.#autoBackgroundThresholdMs / 1000)),
587
+ hasAstGrep: isToolActive("ast_grep", this.session.settings.get("astGrep.enabled")),
588
+ hasAstEdit: isToolActive("ast_edit", this.session.settings.get("astEdit.enabled")),
589
+ hasGrep: isToolActive("grep", this.session.settings.get("grep.enabled")),
590
+ hasGlob: isToolActive("glob", this.session.settings.get("glob.enabled")),
591
+ hasRead: isToolActive("read", true),
592
+ hasLaunch: isToolActive("hub", this.session.settings.get("launch.enabled")),
593
+ hasEval: isToolActive(
594
+ "eval",
595
+ evalBackends.python || evalBackends.js || evalBackends.ruby || evalBackends.julia,
596
+ ),
597
+ hasShellBuiltins: !shellBuiltinsDisabled(this.session.settings),
598
+ isWindows: process.platform === "win32",
599
+ });
600
+ }
601
+ readonly parameters: BashToolSchema;
602
+ // Non-pty calls run alongside each other (the executor isolates overlapping
603
+ // runs on the same shell session); pty takes over the terminal UI and must
604
+ // run alone.
605
+ readonly concurrency = (args: Partial<BashToolInput>): "shared" | "exclusive" =>
606
+ args.pty === true ? "exclusive" : "shared";
607
+ readonly strict = true;
608
+ readonly #asyncEnabled: boolean;
609
+ readonly #autoBackgroundEnabled: boolean;
610
+ readonly #autoBackgroundThresholdMs: number;
611
+
612
+ constructor(private readonly session: ToolSession) {
613
+ this.#asyncEnabled = this.session.settings.get("async.enabled");
614
+ this.#autoBackgroundEnabled = this.session.settings.get("bash.autoBackground.enabled");
615
+ this.#autoBackgroundThresholdMs = Math.max(
616
+ 0,
617
+ Math.floor(
618
+ this.session.settings.get("bash.autoBackground.thresholdMs") ?? DEFAULT_AUTO_BACKGROUND_THRESHOLD_MS,
619
+ ),
620
+ );
621
+ this.parameters = this.#asyncEnabled ? bashSchemaWithAsync : bashSchemaBase;
622
+ }
623
+
624
+ #formatResultOutput(result: BashResult | BashInteractiveResult): string {
625
+ const outputText = normalizeResultOutput(result);
626
+ return outputText || "(no output)";
627
+ }
628
+
629
+ /**
630
+ * Throw for outcomes that are *not* a completed command: user aborts and a
631
+ * missing exit status. Timeouts are handled separately by
632
+ * #buildCompletedResult, which returns a non-throwing error result with
633
+ * details.timedOut=true so the renderer can show a warning border. The
634
+ * foreground and bridge callers plus the async job manager rely on these
635
+ * throwing so cancellations surface as aborts and jobs are recorded as
636
+ * failed. A definite non-zero exit is a completed command that failed;
637
+ * #buildCompletedResult surfaces it as an error *result* (carrying
638
+ * execution details) rather than a throw.
639
+ */
640
+ #throwIfUnfinished(
641
+ result: BashResult | BashInteractiveResult,
642
+ timeoutSec: number | undefined,
643
+ outputText: string,
644
+ ): void {
645
+ if (result.cancelled) {
646
+ // Local executor output already carries a leading `[Command cancelled]`
647
+ // notice from the sink; PTY/bridge output does not, so annotate only
648
+ // the latter.
649
+ const out = normalizeResultOutput(result);
650
+ const annotated = out.startsWith("[Command cancelled]") ? out : out ? `${out}\n\n[Command aborted]` : out;
651
+ throw new ToolError(annotated || "Command aborted");
652
+ }
653
+ if (result.timedOut === true) {
654
+ const out = normalizeResultOutput(result);
655
+ const message =
656
+ timeoutSec === undefined ? "Command timed out" : `Command timed out after ${timeoutSec} seconds`;
657
+ throw new ToolError(out ? `${out}\n\n[${message}]` : message);
658
+ }
659
+ if (result.exitCode === undefined) {
660
+ throw new ToolError(`${outputText}\n\nCommand failed: missing exit status`);
661
+ }
662
+ }
663
+
664
+ async #buildCompletedResult(
665
+ result: BashResult | BashInteractiveResult,
666
+ timeoutSec: number | undefined,
667
+ options: {
668
+ requestedTimeoutSec?: number;
669
+ notices?: readonly string[];
670
+ terminalId?: string;
671
+ wallTimeMs?: number;
672
+ } = {},
673
+ ): Promise<AgentToolResult<BashToolDetails>> {
674
+ const exitCode = result.exitCode;
675
+ const failedExit = exitCode !== undefined && exitCode !== 0;
676
+
677
+ const outputLines = [this.#formatResultOutput(result)];
678
+ const notices: string[] = [];
679
+ if (options.wallTimeMs !== undefined) {
680
+ notices.push(formatWallTimeNotice(options.wallTimeMs));
681
+ }
682
+ if (options.notices) {
683
+ for (const notice of options.notices) {
684
+ if (notice) notices.push(notice);
685
+ }
686
+ }
687
+ if (notices.length > 0) outputLines.push("", ...notices);
688
+ if (failedExit) outputLines.push("", formatExitCodeNotice(exitCode));
689
+ const outputText = outputLines.join("\n");
690
+
691
+ // Timeouts are not failures — the command ran its course. Return an error
692
+ // result (isError=true for the model) but flag timedOut so the renderer
693
+ // uses a warning border instead of error red. Both interactive and
694
+ // non-interactive results carry an explicit `timedOut` field from the
695
+ // executor/PTY layer.
696
+ const isTimeout = result.timedOut === true;
697
+
698
+ const details: BashToolDetails = {};
699
+ if (timeoutSec === undefined) {
700
+ details.timeoutDisabled = true;
701
+ } else {
702
+ details.timeoutSeconds = timeoutSec;
703
+ }
704
+ if (options.requestedTimeoutSec !== undefined && options.requestedTimeoutSec !== timeoutSec) {
705
+ details.requestedTimeoutSeconds = options.requestedTimeoutSec;
706
+ }
707
+ if (options.terminalId !== undefined) {
708
+ details.terminalId = options.terminalId;
709
+ }
710
+ if (options.wallTimeMs !== undefined) {
711
+ details.wallTimeMs = options.wallTimeMs;
712
+ }
713
+ if (failedExit) {
714
+ details.exitCode = exitCode;
715
+ }
716
+
717
+ // Final-defense inline cap config, shared by the timeout and normal
718
+ // completion paths. The sink already bounds inline bodies to the spill
719
+ // threshold, so with the notice slack this only fires on paths that
720
+ // bypass the sink (client-bridge terminals, minimizer misses). When the
721
+ // sink spilled, its artifact already holds the full raw stream — reuse
722
+ // that id instead of saving a second (already-truncated) copy, so the
723
+ // `[raw output: artifact://N]` footer and the truncation notice agree.
724
+ const inlineCap = {
725
+ maxBytes: resolveInlineByteCapBudget(this.session.settings),
726
+ saveArtifact: (full: string) => result.artifactId ?? saveBashOriginalArtifact(this.session, full),
727
+ };
728
+
729
+ if (isTimeout) {
730
+ details.timedOut = true;
731
+ const message =
732
+ timeoutSec === undefined ? "Command timed out" : `Command timed out after ${timeoutSec} seconds`;
733
+ // executeBash has already emitted this leading sink notice. PTY output
734
+ // has not, so provide the LLM-facing annotation exactly once.
735
+ if (!normalizeResultOutput(result).startsWith(`[${message}]\n`)) {
736
+ outputLines.push("", `[${message}]`);
737
+ }
738
+ const timeoutOutputText = await enforceInlineByteCap(outputLines.join("\n"), inlineCap);
739
+ return toolResult(details)
740
+ .text(timeoutOutputText)
741
+ .truncationFromSummary(result, { direction: "tail" })
742
+ .error()
743
+ .done();
744
+ }
745
+
746
+ // Non-timeout cancellations and missing exit status still propagate as thrown errors.
747
+ this.#throwIfUnfinished(result, timeoutSec, outputText);
748
+
749
+ // No-op for already-bounded output; see `inlineCap` above.
750
+ const cappedOutputText = await enforceInlineByteCap(outputText, inlineCap);
751
+
752
+ const resultBuilder = toolResult(details)
753
+ .text(cappedOutputText)
754
+ .truncationFromSummary(result, { direction: "tail" });
755
+ if (failedExit) resultBuilder.error();
756
+ return resultBuilder.done();
757
+ }
758
+
759
+ #buildBackgroundStartResult(
760
+ jobId: string,
761
+ previewText: string,
762
+ timeoutSec: number | undefined,
763
+ options: { requestedTimeoutSec?: number; notices?: readonly string[] } = {},
764
+ ): AgentToolResult<BashToolDetails> {
765
+ const details: BashToolDetails = {
766
+ async: { state: "running", jobId, type: "bash" },
767
+ };
768
+ if (timeoutSec === undefined) {
769
+ details.timeoutDisabled = true;
770
+ } else {
771
+ details.timeoutSeconds = timeoutSec;
772
+ }
773
+ if (options.requestedTimeoutSec !== undefined && options.requestedTimeoutSec !== timeoutSec) {
774
+ details.requestedTimeoutSeconds = options.requestedTimeoutSec;
775
+ }
776
+ const lines: string[] = [];
777
+ const trimmedPreview = previewText.trimEnd();
778
+ if (trimmedPreview.length > 0) {
779
+ lines.push(trimmedPreview, "");
780
+ }
781
+ if (options.notices?.length) {
782
+ lines.push(...options.notices, "");
783
+ }
784
+ lines.push(formatBackgroundNotice(jobId));
785
+ return {
786
+ content: [{ type: "text", text: lines.join("\n") }],
787
+ details,
788
+ };
789
+ }
790
+
791
+ #extractTextResult(result: AgentToolResult<BashToolDetails>): string {
792
+ return result.content.find(block => block.type === "text")?.text ?? "";
793
+ }
794
+
795
+ #startManagedBashJob(options: {
796
+ command: string;
797
+ commandCwd: string;
798
+ timeoutMs: number | undefined;
799
+ timeoutSec: number | undefined;
800
+ requestedTimeoutSec?: number;
801
+ notices?: readonly string[];
802
+
803
+ resolvedEnv?: Record<string, string>;
804
+ onUpdate?: AgentToolUpdateCallback<BashToolDetails>;
805
+ forwardUpdates: boolean;
806
+ }): ManagedBashJobHandle {
807
+ const manager = this.session.asyncJobManager;
808
+ if (!manager) {
809
+ throw new ToolError("Background job manager unavailable for this session.");
810
+ }
811
+
812
+ const label = options.command.length > 120 ? `${options.command.slice(0, 117)}...` : options.command;
813
+ let latestText = "";
814
+ let forwardUpdates = options.forwardUpdates;
815
+ const completion = Promise.withResolvers<ManagedBashJobCompletion>();
816
+
817
+ const jobId = manager.register(
818
+ "bash",
819
+ label,
820
+ async ({ jobId, signal: runSignal, reportProgress }) => {
821
+ const { path: artifactPath, id: artifactId } = (await this.session.allocateOutputArtifact?.("bash")) ?? {};
822
+ const tailBuffer = new TailBuffer(DEFAULT_MAX_BYTES);
823
+ const wallTimeStart = performance.now();
824
+ try {
825
+ const result = await executeBash(options.command, {
826
+ cwd: options.commandCwd,
827
+ sessionKey: `${this.session.getSessionId?.() ?? ""}:async:${jobId}`,
828
+ timeout: options.timeoutMs ?? 0,
829
+ signal: runSignal,
830
+ env: options.resolvedEnv,
831
+ artifactPath,
832
+ artifactId,
833
+ onChunk: chunk => {
834
+ tailBuffer.append(chunk);
835
+ latestText = tailBuffer.text();
836
+ void reportProgress(latestText, { async: { state: "running", jobId, type: "bash" } });
837
+ },
838
+ onMinimizedSave: originalText => saveBashOriginalArtifact(this.session, originalText),
839
+ });
840
+ const wallTimeMs = performance.now() - wallTimeStart;
841
+ const finalResult = await this.#buildCompletedResult(result, options.timeoutSec, {
842
+ requestedTimeoutSec: options.requestedTimeoutSec,
843
+ notices: options.notices ?? [],
844
+ wallTimeMs,
845
+ });
846
+ const finalText = this.#extractTextResult(finalResult);
847
+ latestText = finalText;
848
+ // Hand the detailed result to the foreground auto-background
849
+ // waiter (which renders it, footer included) before deciding
850
+ // the job's terminal state.
851
+ completion.resolve({ kind: "completed", result: finalResult });
852
+ if (finalResult.isError === true) {
853
+ // A non-zero exit is a completed command that failed. Re-enter
854
+ // the failure path so the job manager records it as failed and
855
+ // delivers the error text, matching prior throw-based behavior.
856
+ throw new ToolError(finalText);
857
+ }
858
+ await reportProgress(finalText, { async: { state: "completed", jobId, type: "bash" } });
859
+ return finalText;
860
+ } catch (error) {
861
+ const message = error instanceof Error ? error.message : String(error);
862
+ latestText = message;
863
+ completion.resolve({ kind: "failed", error });
864
+ await reportProgress(message, { async: { state: "failed", jobId, type: "bash" } });
865
+ throw error;
866
+ }
867
+ },
868
+ {
869
+ ownerId: this.session.getAgentId?.() ?? undefined,
870
+ onProgress: async text => {
871
+ latestText = text;
872
+ if (!forwardUpdates) return;
873
+ await options.onUpdate?.({
874
+ content: [{ type: "text", text }],
875
+ details: {},
876
+ });
877
+ },
878
+ },
879
+ );
880
+
881
+ return {
882
+ jobId,
883
+ completion: completion.promise,
884
+ getLatestText: () => latestText,
885
+ stopUpdates: () => {
886
+ forwardUpdates = false;
887
+ },
888
+ };
889
+ }
890
+
891
+ async #waitForManagedBashJob(
892
+ job: ManagedBashJobHandle,
893
+ thresholdMs: number,
894
+ signal?: AbortSignal,
895
+ steeringSignal?: AbortSignal,
896
+ ): Promise<ManagedBashJobCompletion | { kind: "running" } | { kind: "steer" } | { kind: "aborted" }> {
897
+ if (signal?.aborted) {
898
+ return { kind: "aborted" };
899
+ }
900
+ if (steeringSignal?.aborted) {
901
+ return { kind: "steer" };
902
+ }
903
+
904
+ // Cancellable threshold: a bare Bun.sleep(thresholdMs) leaves a live, ref'd
905
+ // timer for the full threshold after the command finishes (or abort/steer)
906
+ // wins the race first — delaying SDK/headless shutdown and accumulating
907
+ // timers under fast command rates. Settle a withResolvers promise from
908
+ // setTimeout so the finally can clear it regardless of which waiter wins.
909
+ const { promise: thresholdPromise, resolve: resolveThreshold } = Promise.withResolvers<{
910
+ kind: "running";
911
+ }>();
912
+ const thresholdTimer = setTimeout(() => resolveThreshold({ kind: "running" }), thresholdMs);
913
+ const waiters: Array<
914
+ Promise<ManagedBashJobCompletion | { kind: "running" } | { kind: "steer" } | { kind: "aborted" }>
915
+ > = [job.completion, thresholdPromise];
916
+
917
+ const { promise: abortedPromise, resolve: resolveAborted } = Promise.withResolvers<{ kind: "aborted" }>();
918
+ const onAbort = () => resolveAborted({ kind: "aborted" });
919
+ const { promise: steerPromise, resolve: resolveSteer } = Promise.withResolvers<{ kind: "steer" }>();
920
+ const onSteer = () => resolveSteer({ kind: "steer" });
921
+ if (signal) {
922
+ signal.addEventListener("abort", onAbort, { once: true });
923
+ waiters.push(abortedPromise);
924
+ }
925
+ if (steeringSignal) {
926
+ steeringSignal.addEventListener("abort", onSteer, { once: true });
927
+ waiters.push(steerPromise);
928
+ }
929
+ try {
930
+ return await Promise.race(waiters);
931
+ } finally {
932
+ clearTimeout(thresholdTimer);
933
+ signal?.removeEventListener("abort", onAbort);
934
+ steeringSignal?.removeEventListener("abort", onSteer);
935
+ }
936
+ }
937
+
938
+ #resolveAutoBackgroundWaitMs(timeoutMs: number | undefined): number {
939
+ if (this.#autoBackgroundThresholdMs <= 0) return 0;
940
+ if (timeoutMs === undefined) return this.#autoBackgroundThresholdMs;
941
+ const timeoutBufferMs = 1_000;
942
+ return Math.max(0, Math.min(this.#autoBackgroundThresholdMs, timeoutMs - timeoutBufferMs));
943
+ }
944
+
945
+ async execute(
946
+ _toolCallId: string,
947
+ {
948
+ command: rawCommand,
949
+ env: rawEnv,
950
+ timeout: rawTimeout = 300,
951
+ cwd,
952
+
953
+ async: asyncRequested = false,
954
+ pty = false,
955
+ }: BashToolInput,
956
+ signal?: AbortSignal,
957
+ onUpdate?: AgentToolUpdateCallback<BashToolDetails>,
958
+ ctx?: AgentToolContext,
959
+ ): Promise<AgentToolResult<BashToolDetails>> {
960
+ let command = rawCommand;
961
+ const env = normalizeBashEnv(rawEnv);
962
+
963
+ // Extract leading `cd <path> && ...` into cwd when the model ignores the cwd parameter.
964
+ // Constrained to a single line so a `&&` that sits on a later line of a multiline
965
+ // script can't pull the entire script into the "cwd" capture.
966
+ if (!cwd) {
967
+ const cdMatch = command.match(/^cd[ \t]+((?:[^&\\\n\r]|\\.)+?)[ \t]*&&[ \t]*/);
968
+ // Skip extraction when the path needs shell expansion ($VAR, $(...),
969
+ // backticks) — resolveToCwd only expands `~`, so routing those through
970
+ // cwd would reject commands the shell itself handles fine.
971
+ if (cdMatch && !/[$`(]/.test(cdMatch[1])) {
972
+ cwd = cdMatch[1].trim().replace(/^["']|["']$/g, "");
973
+ command = command.slice(cdMatch[0].length);
974
+ }
975
+ }
976
+ if (asyncRequested && !this.#asyncEnabled) {
977
+ throw new ToolError("Async bash execution is disabled. Enable async.enabled to use async mode.");
978
+ }
979
+
980
+ // Check both the original command and the cwd-normalized command so
981
+ // leading `cd ... &&` wrappers do not hide either shell-navigation rules
982
+ // or the dedicated-tool command that follows the directory change.
983
+ if (this.session.settings.get("bashInterceptor.enabled")) {
984
+ const rules = this.session.settings.getBashInterceptorRules();
985
+ const commandsToCheck = rawCommand === command ? [command] : [rawCommand, command];
986
+ for (const commandToCheck of commandsToCheck) {
987
+ const interception = checkBashInterception(commandToCheck, ctx?.toolNames ?? [], rules, rawCommand);
988
+ if (interception.block) {
989
+ throw new ToolError(interception.message ?? "Command blocked");
990
+ }
991
+ }
992
+ }
993
+
994
+ const internalUrlOptions: InternalUrlExpansionOptions = {
995
+ skills: this.session.skills ?? [],
996
+ internalRouter: InternalUrlRouter.instance(),
997
+ cwd: this.session.cwd,
998
+ localOptions: {
999
+ getArtifactsDir: this.session.getArtifactsDir,
1000
+ getSessionId: this.session.getSessionId,
1001
+ },
1002
+ };
1003
+ command = await expandInternalUrls(command, { ...internalUrlOptions, ensureLocalParentDirs: true });
1004
+ const resolvedEnv = env
1005
+ ? Object.fromEntries(
1006
+ await Promise.all(
1007
+ Object.entries(env).map(async ([key, value]) => [
1008
+ key,
1009
+ await expandInternalUrls(value, {
1010
+ ...internalUrlOptions,
1011
+ ensureLocalParentDirs: true,
1012
+ noEscape: true,
1013
+ }),
1014
+ ]),
1015
+ ),
1016
+ )
1017
+ : undefined;
1018
+
1019
+ // Resolve protocol URLs (skill://, agent://, etc.) in extracted cwd.
1020
+ if (cwd?.includes("://") || cwd?.includes("local:/")) {
1021
+ cwd = await expandInternalUrls(cwd, { ...internalUrlOptions, noEscape: true });
1022
+ }
1023
+
1024
+ // Best-effort cache invalidation: drop github-cache rows for any issue/PR
1025
+ // number touched by a mutating `gh` subcommand inside this bash call so
1026
+ // subsequent issue:// / pr:// reads pick up the post-mutation state
1027
+ // instead of the cached pre-mutation snapshot.
1028
+ invalidateGithubCacheForBashCommand(command);
1029
+
1030
+ const commandCwd = cwd ? resolveToCwd(cwd, this.session.cwd) : this.session.cwd;
1031
+ let cwdStat: fs.Stats;
1032
+ try {
1033
+ cwdStat = await fs.promises.stat(commandCwd);
1034
+ } catch (err) {
1035
+ if (isEnoent(err)) {
1036
+ throw new ToolError(`Working directory does not exist: ${commandCwd}`);
1037
+ }
1038
+ throw err;
1039
+ }
1040
+ if (!cwdStat.isDirectory()) {
1041
+ throw new ToolError(`Working directory is not a directory: ${commandCwd}`);
1042
+ }
1043
+
1044
+ // A timeout of 0 is an explicit long-running-command contract: the user
1045
+ // must still cancel the call or job, but OMP does not impose a deadline.
1046
+ const requestedTimeoutSec = rawTimeout;
1047
+ const timeoutDisabled = requestedTimeoutSec === 0;
1048
+ const maxTimeout = this.session.settings.get("tools.maxTimeout");
1049
+ const timeoutSec = timeoutDisabled ? undefined : clampTimeout("bash", requestedTimeoutSec, maxTimeout);
1050
+ const timeoutMs = timeoutSec === undefined ? undefined : timeoutSec * 1000;
1051
+ const pendingNotices: string[] = [];
1052
+ if (timeoutSec !== undefined) {
1053
+ const timeoutClampNotice = formatTimeoutClampNotice(requestedTimeoutSec, timeoutSec, maxTimeout);
1054
+ if (timeoutClampNotice) pendingNotices.push(timeoutClampNotice);
1055
+ }
1056
+
1057
+ if (asyncRequested) {
1058
+ if (!this.session.asyncJobManager) {
1059
+ throw new ToolError("Async job manager unavailable for this session.");
1060
+ }
1061
+ const job = this.#startManagedBashJob({
1062
+ command,
1063
+ commandCwd,
1064
+ timeoutMs,
1065
+ timeoutSec,
1066
+ requestedTimeoutSec,
1067
+ notices: pendingNotices,
1068
+
1069
+ resolvedEnv,
1070
+ onUpdate,
1071
+ forwardUpdates: false,
1072
+ });
1073
+ return this.#buildBackgroundStartResult(job.jobId, "", timeoutSec, {
1074
+ requestedTimeoutSec,
1075
+ notices: pendingNotices,
1076
+ });
1077
+ }
1078
+
1079
+ // The client-bridge terminal provides a live terminal card in the editor;
1080
+ // when available it wins over auto-backgrounding (both are opt-in, and
1081
+ // auto-background would otherwise silently disable the terminal route).
1082
+ const clientBridge = this.session.getClientBridge?.();
1083
+ const bridgeTerminalAvailable = Boolean(
1084
+ clientBridge?.capabilities.terminal && clientBridge.createTerminal && !pty,
1085
+ );
1086
+
1087
+ const autoBgManager = this.session.asyncJobManager;
1088
+ // At the running-job cap, fall through to direct foreground execution
1089
+ // instead of failing every bash call until a slot frees up.
1090
+ if (
1091
+ this.#autoBackgroundEnabled &&
1092
+ !pty &&
1093
+ !bridgeTerminalAvailable &&
1094
+ autoBgManager &&
1095
+ !autoBgManager.atCapacity
1096
+ ) {
1097
+ const autoBackgroundWaitMs = this.#resolveAutoBackgroundWaitMs(timeoutMs);
1098
+ const startBackgrounded = autoBackgroundWaitMs === 0;
1099
+ const job = this.#startManagedBashJob({
1100
+ command,
1101
+ commandCwd,
1102
+ timeoutMs,
1103
+ timeoutSec,
1104
+ requestedTimeoutSec,
1105
+ notices: pendingNotices,
1106
+
1107
+ resolvedEnv,
1108
+ onUpdate,
1109
+ forwardUpdates: !startBackgrounded,
1110
+ });
1111
+ if (startBackgrounded) {
1112
+ return this.#buildBackgroundStartResult(job.jobId, "", timeoutSec, {
1113
+ requestedTimeoutSec,
1114
+ notices: pendingNotices,
1115
+ });
1116
+ }
1117
+ // Suppress the completion delivery up front so a job finishing while we
1118
+ // foreground-wait cannot also be injected by the delivery loop. Lifted
1119
+ // via resumeDeliveries() if we end up backgrounding after all.
1120
+ autoBgManager.acknowledgeDeliveries([job.jobId]);
1121
+ const waitResult = await this.#waitForManagedBashJob(
1122
+ job,
1123
+ autoBackgroundWaitMs,
1124
+ signal,
1125
+ ctx?.toolCall?.steeringSignal,
1126
+ );
1127
+ if (waitResult.kind === "completed") {
1128
+ return waitResult.result;
1129
+ }
1130
+ if (waitResult.kind === "failed") {
1131
+ throw waitResult.error;
1132
+ }
1133
+ if (waitResult.kind === "aborted") {
1134
+ autoBgManager.cancel(job.jobId);
1135
+ throw new ToolAbortError(job.getLatestText() || "Command aborted");
1136
+ }
1137
+ job.stopUpdates();
1138
+ autoBgManager.resumeDeliveries([job.jobId]);
1139
+ // "steer": a queued user/peer message arrived mid-wait — background
1140
+ // the command (it keeps running) so the message injects promptly.
1141
+ const notices =
1142
+ waitResult.kind === "steer"
1143
+ ? [...pendingNotices, "Backgrounded early to handle an incoming message; the command keeps running."]
1144
+ : pendingNotices;
1145
+ return this.#buildBackgroundStartResult(job.jobId, job.getLatestText(), timeoutSec, {
1146
+ requestedTimeoutSec,
1147
+ notices,
1148
+ });
1149
+ }
1150
+
1151
+ // Fold direnv/devenv env into (command, env) ONCE for the two backends
1152
+ // that bypass `executeBash` — the ACP client terminal and the PTY. The
1153
+ // `executeBash` branch below is intentionally excluded: it runs its own
1154
+ // preflight internally, so routing the pre-applied command there too
1155
+ // would double-apply the unset prefix and re-merge the env. No
1156
+ // `commandPrefix` here: ACP applies the shell prefix via
1157
+ // `wrapShellLineForClientTerminal`, and the PTY path never wrapped one.
1158
+ // `callerTimeoutMs` clamps the direnv load to a positive command timeout
1159
+ // (the backend's own timeout is installed only after this await), matching
1160
+ // the executeBash branch so a cold `.envrc` can't outlast a short call.
1161
+ const backendPreflight =
1162
+ (clientBridge?.capabilities.terminal && clientBridge.createTerminal && !pty) ||
1163
+ canUseInteractiveBashPty(pty, ctx)
1164
+ ? await applyDirenvPreflight(command, commandCwd, {
1165
+ callerEnv: resolvedEnv,
1166
+ signal,
1167
+ timeoutMs: this.session.settings.get("bash.direnvLoadTimeoutMs"),
1168
+ callerTimeoutMs: timeoutMs,
1169
+ direnvSetting: this.session.settings.get("bash.direnv"),
1170
+ })
1171
+ : undefined;
1172
+
1173
+ // Route through the client terminal when the client advertises the terminal capability.
1174
+ // Skip when pty=true (PTY needs the local terminal UI).
1175
+ if (clientBridge?.capabilities.terminal && clientBridge.createTerminal && !pty) {
1176
+ // Invariant (ACP terminal bridge): createTerminal has no signal in its
1177
+ // contract; allocation cannot be cancelled retroactively. Guard before
1178
+ // allocation. Shared timeout helper / pure AbortSignal fusion rejected:
1179
+ // we need explicit kill-before-read ordering and distinct abort vs
1180
+ // timeout result shapes. Per-route race retained for testability.
1181
+ if (signal?.aborted) {
1182
+ throw new ToolAbortError("Command aborted");
1183
+ }
1184
+
1185
+ const bridgeWallTimeStart = performance.now();
1186
+ const killGraceMs = 1000;
1187
+ const outputSnapshotGraceMs = 2000;
1188
+ // Cancellable timeout: a bare Bun.sleep(timeoutMs) would leave a live,
1189
+ // ref'd timer for the full command timeout after fast completions —
1190
+ // accumulating timers and delaying process shutdown in SDK/headless use.
1191
+ // `timeoutMs` is optional (#4642): without one, no timer is armed and
1192
+ // the promise simply never resolves.
1193
+ const { promise: timeoutPromise, resolve: resolveTimeout } = Promise.withResolvers<{
1194
+ kind: "timeout";
1195
+ }>();
1196
+ const timeoutTimer = timeoutMs ? setTimeout(() => resolveTimeout({ kind: "timeout" }), timeoutMs) : undefined;
1197
+ const { promise: abortedP, resolve: resolveAborted } = Promise.withResolvers<void>();
1198
+ let handle: ClientBridgeTerminalHandle | undefined;
1199
+ let killStarted = false;
1200
+ const fireKill = (): Promise<void> => {
1201
+ if (killStarted) return Promise.resolve();
1202
+ const currentHandle = handle;
1203
+ if (!currentHandle) return Promise.resolve();
1204
+ killStarted = true;
1205
+ return currentHandle.kill().catch((error: unknown) => {
1206
+ logger.warn("ACP terminal kill failed", { terminalId: currentHandle.terminalId, error });
1207
+ });
1208
+ };
1209
+ const cleanupLateCreate = (createP: Promise<ClientBridgeTerminalHandle>): void => {
1210
+ void createP
1211
+ .then(async lateHandle => {
1212
+ try {
1213
+ await lateHandle.kill();
1214
+ } catch (error) {
1215
+ logger.warn("ACP terminal kill failed", { terminalId: lateHandle.terminalId, error });
1216
+ }
1217
+ try {
1218
+ await lateHandle.release();
1219
+ } catch (error) {
1220
+ logger.warn("ACP terminal release failed", { terminalId: lateHandle.terminalId, error });
1221
+ }
1222
+ })
1223
+ .catch((error: unknown) => {
1224
+ logger.warn("ACP terminal create failed after cancellation", { error });
1225
+ });
1226
+ };
1227
+ const onAbortSignal = () => {
1228
+ resolveAborted();
1229
+ void fireKill();
1230
+ };
1231
+ signal?.addEventListener("abort", onAbortSignal, { once: true });
1232
+
1233
+ try {
1234
+ // direnv-transformed command (carries any `unset -v` prefix) + merged
1235
+ // env; falls back to the raw command/env when direnv is off/absent.
1236
+ const bridgeCommand = backendPreflight?.command ?? command;
1237
+ const bridgeEnv = backendPreflight?.env ?? resolvedEnv;
1238
+ const shellSpawn = wrapShellLineForClientTerminal(bridgeCommand, this.session.settings.getShellConfig());
1239
+ const createP = clientBridge.createTerminal({
1240
+ command: shellSpawn.command,
1241
+ args: shellSpawn.args,
1242
+ cwd: commandCwd,
1243
+ env: bridgeEnv
1244
+ ? Object.entries(bridgeEnv).map(([name, value]) => ({ name, value: value as string }))
1245
+ : undefined,
1246
+ outputByteLimit: DEFAULT_MAX_BYTES,
1247
+ });
1248
+ const createRaced = await Promise.race([
1249
+ createP.then(createdHandle => ({ kind: "created" as const, handle: createdHandle })),
1250
+ timeoutPromise,
1251
+ abortedP.then(() => ({ kind: "aborted" as const })),
1252
+ ]);
1253
+ if (createRaced.kind === "aborted" || signal?.aborted) {
1254
+ cleanupLateCreate(createP);
1255
+ throw new ToolAbortError("Command aborted");
1256
+ }
1257
+ if (createRaced.kind === "timeout") {
1258
+ cleanupLateCreate(createP);
1259
+ const timedOutResult: BashInteractiveResult = {
1260
+ output: "",
1261
+ exitCode: undefined,
1262
+ cancelled: false,
1263
+ timedOut: true,
1264
+ truncated: false,
1265
+ totalLines: 0,
1266
+ totalBytes: 0,
1267
+ outputLines: 0,
1268
+ outputBytes: 0,
1269
+ };
1270
+ this.#throwIfUnfinished(timedOutResult, timeoutSec, this.#formatResultOutput(timedOutResult));
1271
+ throw new ToolError("Command timed out");
1272
+ }
1273
+
1274
+ handle = createRaced.handle;
1275
+
1276
+ // Emit partial update so the editor can embed the live terminal card.
1277
+ onUpdate?.({ content: [], details: { terminalId: handle.terminalId } });
1278
+
1279
+ const exitPromise = handle.waitForExit();
1280
+ let exitStatus!: ClientBridgeTerminalExitStatus;
1281
+
1282
+ type BridgeRaceResult =
1283
+ | { kind: "exit"; status: ClientBridgeTerminalExitStatus }
1284
+ | { kind: "poll" }
1285
+ | { kind: "timeout" }
1286
+ | { kind: "aborted" };
1287
+
1288
+ const exitRacer = exitPromise.then(status => ({ kind: "exit" as const, status }));
1289
+ const abortRacer = abortedP.then(() => ({ kind: "aborted" as const }));
1290
+ const abortPollRacer = abortedP.then(() => undefined as ClientBridgeTerminalOutput | undefined);
1291
+ const timeoutPollRacer = timeoutPromise.then(() => undefined as ClientBridgeTerminalOutput | undefined);
1292
+ let lastPolledOutput: ClientBridgeTerminalOutput = { output: "", truncated: false };
1293
+
1294
+ // Poll until the process exits, times out, or the caller aborts.
1295
+ for (;;) {
1296
+ const racers: Array<Promise<BridgeRaceResult>> = [
1297
+ exitRacer,
1298
+ timeoutPromise,
1299
+ Bun.sleep(250).then(() => ({ kind: "poll" as const })),
1300
+ ];
1301
+ if (signal) {
1302
+ racers.push(abortRacer);
1303
+ }
1304
+ const raced = await Promise.race(racers);
1305
+
1306
+ if (raced.kind === "aborted" || signal?.aborted) {
1307
+ await Promise.race([fireKill(), Bun.sleep(killGraceMs)]);
1308
+ throw new ToolAbortError("Command aborted");
1309
+ }
1310
+
1311
+ if (raced.kind === "timeout") {
1312
+ // Kill before reading final output so a slow `terminal/output`
1313
+ // RPC cannot let a timed-out command keep running past the
1314
+ // enforced timeout. The handle stays valid post-kill so the
1315
+ // buffered output is still readable.
1316
+ await Promise.race([fireKill(), Bun.sleep(killGraceMs)]);
1317
+ let current = lastPolledOutput;
1318
+ try {
1319
+ current = await Promise.race([
1320
+ handle.currentOutput(),
1321
+ Bun.sleep(outputSnapshotGraceMs).then(() => lastPolledOutput),
1322
+ ]);
1323
+ } catch (error) {
1324
+ logger.warn("ACP terminal final output read failed", {
1325
+ terminalId: handle.terminalId,
1326
+ error,
1327
+ });
1328
+ }
1329
+ const timedOutResult: BashInteractiveResult = {
1330
+ output: current.output,
1331
+ exitCode: undefined,
1332
+ cancelled: false,
1333
+ timedOut: true,
1334
+ truncated: current.truncated,
1335
+ totalLines: current.output.length > 0 ? current.output.split("\n").length : 0,
1336
+ totalBytes: current.output.length,
1337
+ outputLines: current.output.length > 0 ? current.output.split("\n").length : 0,
1338
+ outputBytes: current.output.length,
1339
+ };
1340
+ this.#throwIfUnfinished(timedOutResult, timeoutSec, this.#formatResultOutput(timedOutResult));
1341
+ throw new ToolError("Command timed out");
1342
+ }
1343
+
1344
+ if (raced.kind === "exit") {
1345
+ exitStatus = raced.status;
1346
+ break;
1347
+ }
1348
+
1349
+ // Poll tick: push current output so agent-loop transcript stays consistent.
1350
+ // Race the read against abort/timeout so a stuck `terminal/output` RPC does
1351
+ // not delay cancellation or let the command outlive its deadline.
1352
+ const pollOutput = await Promise.race([handle.currentOutput(), abortPollRacer, timeoutPollRacer]);
1353
+ if (pollOutput === undefined) {
1354
+ // Abort or timeout fired during the poll-tick read; let the next loop
1355
+ // iteration exit via the matching abort/timeout branch.
1356
+ continue;
1357
+ }
1358
+ lastPolledOutput = pollOutput;
1359
+ onUpdate?.({
1360
+ content: [{ type: "text", text: pollOutput.output }],
1361
+ details: { terminalId: handle.terminalId },
1362
+ });
1363
+ }
1364
+
1365
+ // Fetch final output; the terminal is released in the outer finally.
1366
+ let finalOutput = lastPolledOutput;
1367
+ try {
1368
+ finalOutput = await Promise.race([
1369
+ handle.currentOutput(),
1370
+ Bun.sleep(outputSnapshotGraceMs).then(() => lastPolledOutput),
1371
+ ]);
1372
+ } catch (error) {
1373
+ logger.warn("ACP terminal final output read failed", {
1374
+ terminalId: handle.terminalId,
1375
+ error,
1376
+ });
1377
+ }
1378
+
1379
+ // Map exit status: null exitCode with a signal → treat as signal kill (137).
1380
+ const rawExitCode = exitStatus.exitCode;
1381
+ const exitCode: number | undefined =
1382
+ rawExitCode != null ? rawExitCode : exitStatus.signal ? 137 : undefined;
1383
+
1384
+ const outputText = finalOutput.output;
1385
+ const outputByteLen = outputText.length;
1386
+ const outputLineCount = outputText.length > 0 ? outputText.split("\n").length : 0;
1387
+
1388
+ const bridgeResult: BashResult = {
1389
+ output: outputText,
1390
+ exitCode,
1391
+ cancelled: false,
1392
+ truncated: finalOutput.truncated,
1393
+ totalLines: outputLineCount,
1394
+ totalBytes: outputByteLen,
1395
+ outputLines: outputLineCount,
1396
+ outputBytes: outputByteLen,
1397
+ };
1398
+
1399
+ const bridgeNotices: string[] = [];
1400
+ if (finalOutput.truncated) bridgeNotices.push("(output truncated)");
1401
+ for (const notice of pendingNotices) bridgeNotices.push(notice);
1402
+
1403
+ return this.#buildCompletedResult(bridgeResult, timeoutSec, {
1404
+ requestedTimeoutSec,
1405
+ notices: bridgeNotices,
1406
+ terminalId: handle.terminalId,
1407
+ wallTimeMs: performance.now() - bridgeWallTimeStart,
1408
+ });
1409
+ } finally {
1410
+ clearTimeout(timeoutTimer);
1411
+ signal?.removeEventListener("abort", onAbortSignal);
1412
+ if (handle) {
1413
+ const releaseHandle = handle;
1414
+ // Bound release like kill/output: a hung `terminal/release` RPC must not
1415
+ // keep the tool pending after the result is already decided.
1416
+ await Promise.race([
1417
+ releaseHandle.release().catch((error: unknown) => {
1418
+ logger.warn("ACP terminal release failed", { terminalId: releaseHandle.terminalId, error });
1419
+ }),
1420
+ Bun.sleep(killGraceMs),
1421
+ ]);
1422
+ }
1423
+ }
1424
+ }
1425
+
1426
+ // Track output for streaming updates (tail only)
1427
+ const tailBuffer = new TailBuffer(DEFAULT_MAX_BYTES);
1428
+
1429
+ // Allocate artifact for truncated output storage
1430
+ const { path: artifactPath, id: artifactId } = (await this.session.allocateOutputArtifact?.("bash")) ?? {};
1431
+
1432
+ const interactiveUi = canUseInteractiveBashPty(pty, ctx) ? ctx?.ui : undefined;
1433
+ if (pty && !interactiveUi) {
1434
+ pendingNotices.push("pty requested but unavailable in this environment; ran without a terminal");
1435
+ }
1436
+ const wallTimeStart = performance.now();
1437
+ const result: BashResult | BashInteractiveResult = interactiveUi
1438
+ ? await runInteractiveBashPty(interactiveUi, {
1439
+ // PTY bypasses executeBash, so feed it the direnv-transformed
1440
+ // command + merged env (backendPreflight is defined whenever this
1441
+ // branch runs, since both gate on canUseInteractiveBashPty).
1442
+ command: backendPreflight?.command ?? command,
1443
+ cwd: commandCwd,
1444
+ timeoutMs,
1445
+ signal,
1446
+ env: backendPreflight?.env ?? resolvedEnv,
1447
+ artifactPath,
1448
+ artifactId,
1449
+ })
1450
+ : // executeBash runs its OWN direnv preflight internally — pass the RAW
1451
+ // command + resolvedEnv here so the unset prefix / env merge is not
1452
+ // applied twice.
1453
+ await executeBash(command, {
1454
+ cwd: commandCwd,
1455
+ sessionKey: this.session.getSessionId?.() ?? undefined,
1456
+ timeout: timeoutMs ?? 0,
1457
+ signal,
1458
+ env: resolvedEnv,
1459
+ artifactPath,
1460
+ artifactId,
1461
+ onChunk: streamTailUpdates(tailBuffer, onUpdate),
1462
+ onMinimizedSave: originalText => saveBashOriginalArtifact(this.session, originalText),
1463
+ });
1464
+ const wallTimeMs = performance.now() - wallTimeStart;
1465
+ if (result.cancelled) {
1466
+ // A cancelled result is either a timeout (the command's deadline fired)
1467
+ // or a user/system abort. Timeouts are handled by #buildCompletedResult
1468
+ // which returns a non-throwing error result with details.timedOut=true
1469
+ // so the renderer can show a warning border instead of error red.
1470
+ // Both interactive and non-interactive results carry an explicit
1471
+ // `timedOut` field from the executor/PTY layer.
1472
+ const isTimeout = result.timedOut === true;
1473
+ if (!isTimeout) {
1474
+ const out = normalizeResultOutput(result);
1475
+ // The local executor already prepends `[Command cancelled]`; PTY
1476
+ // output does not, so preserve one cancellation notice in either case.
1477
+ const message = out.startsWith("[Command cancelled]")
1478
+ ? out
1479
+ : out
1480
+ ? `${out}\n\n[Command aborted]`
1481
+ : "Command aborted";
1482
+ if (signal?.aborted) {
1483
+ throw new ToolAbortError(message);
1484
+ }
1485
+ throw new ToolError(message);
1486
+ }
1487
+ }
1488
+ return this.#buildCompletedResult(result, timeoutSec, {
1489
+ requestedTimeoutSec,
1490
+ notices: pendingNotices,
1491
+ wallTimeMs,
1492
+ });
1493
+ }
1494
+ }
1495
+
1496
+ // =============================================================================
1497
+ // TUI Renderer
1498
+ // =============================================================================
1499
+ export interface BashRenderArgs {
1500
+ command?: string;
1501
+ env?: Record<string, unknown>;
1502
+ timeout?: number;
1503
+ cwd?: string;
1504
+ __partialJson?: string;
1505
+ [key: string]: unknown;
1506
+ }
1507
+
1508
+ export interface BashRenderContext {
1509
+ /** Raw output text */
1510
+ output?: string;
1511
+ /** Whether output came from artifact storage */
1512
+ isFullOutput?: boolean;
1513
+ /** Whether output is expanded */
1514
+ expanded?: boolean;
1515
+ /** Number of preview lines when collapsed */
1516
+ previewLines?: number;
1517
+ /** Timeout in seconds */
1518
+ timeout?: number;
1519
+ }
1520
+
1521
+ export interface ShellRendererConfig<TArgs> {
1522
+ resolveTitle: (args: TArgs | undefined, options: RenderResultOptions) => string;
1523
+ resolveCommand?: (args: TArgs | undefined) => string | undefined;
1524
+ resolveCwd?: (args: TArgs | undefined) => string | undefined;
1525
+ resolveEnv?: (args: TArgs | undefined) => Record<string, unknown> | undefined;
1526
+ showHeader?: boolean;
1527
+ }
1528
+
1529
+ function getPartialJson<TArgs>(args: TArgs | undefined): string | undefined {
1530
+ if (!args || typeof args !== "object" || !("__partialJson" in args)) return undefined;
1531
+ const value = (args as { __partialJson?: unknown }).__partialJson;
1532
+ return typeof value === "string" ? value : undefined;
1533
+ }
1534
+
1535
+ export function getBashEnvForDisplay(args: BashRenderArgs): Record<string, unknown> | undefined {
1536
+ // The parsed args don't always mirror the exact current stream prefix, so recover
1537
+ // env from the raw JSON buffer to surface `NAME="..." cmd` in the preview as it
1538
+ // streams rather than only once the args object finishes.
1539
+ const partialEnv = extractPartialBashEnv(args.__partialJson);
1540
+ if (partialEnv && args.env) return { ...partialEnv, ...args.env };
1541
+ return args.env ?? partialEnv;
1542
+ }
1543
+
1544
+ /**
1545
+ * Returns the bash command formatted for the result body: the dim `$ cd … &&`
1546
+ * prefix joined with syntax-highlighted command lines. The prefix is applied
1547
+ * only to the first line so multi-line commands display cleanly — terminals
1548
+ * reset SGR state at line boundaries, which made the previous single-string
1549
+ * `theme.fg("dim", ...)` form render only the first line as dim.
1550
+ */
1551
+ export function formatBashCommandLines(args: BashRenderArgs, uiTheme: Theme): string[] {
1552
+ const command = replaceTabs(args.command || "…");
1553
+ const cwd = getProjectDir();
1554
+ const displayWorkdir = formatToolWorkingDirectory(args.cwd, cwd);
1555
+ const envAssignments = formatBashEnvAssignments(getBashEnvForDisplay(args));
1556
+ const prefixParts = ["$"];
1557
+ if (displayWorkdir) prefixParts.push(`cd ${displayWorkdir} &&`);
1558
+ if (envAssignments) prefixParts.push(envAssignments);
1559
+ const prefix = uiTheme.fg("dim", `${prefixParts.join(" ")} `);
1560
+ const highlightedLines = highlightCode(command, "bash");
1561
+ if (highlightedLines.length === 0) return [prefix.trimEnd()];
1562
+ return highlightedLines.map((line, i) => (i === 0 ? `${prefix}${line}` : line));
1563
+ }
1564
+
1565
+ function toBashRenderArgs<TArgs>(args: TArgs | undefined, config: ShellRendererConfig<TArgs>): BashRenderArgs {
1566
+ return {
1567
+ command: config.resolveCommand?.(args),
1568
+ cwd: config.resolveCwd?.(args),
1569
+ env: config.resolveEnv?.(args),
1570
+ __partialJson: getPartialJson(args),
1571
+ };
1572
+ }
1573
+
1574
+ export function createShellRenderer<TArgs>(config: ShellRendererConfig<TArgs>) {
1575
+ return {
1576
+ renderCall(args: TArgs, options: RenderResultOptions, uiTheme: Theme): Component {
1577
+ const renderArgs = toBashRenderArgs(args, config);
1578
+ const cmdLines = formatBashCommandLines(renderArgs, uiTheme);
1579
+ const outputBlock = new CachedOutputBlock();
1580
+ return markFramedBlockComponent({
1581
+ render: (width: number): readonly string[] => {
1582
+ const header =
1583
+ config.showHeader === false
1584
+ ? undefined
1585
+ : renderStatusLine(
1586
+ {
1587
+ icon: options.spinnerFrame !== undefined ? "running" : "pending",
1588
+ spinnerFrame: options.spinnerFrame,
1589
+ title: config.resolveTitle(args, options),
1590
+ },
1591
+ uiTheme,
1592
+ );
1593
+ return outputBlock.render(
1594
+ {
1595
+ header,
1596
+ state: options.spinnerFrame !== undefined ? "running" : "pending",
1597
+ sections: [{ lines: capPreviewLines(cmdLines, uiTheme, { expanded: options.expanded }) }],
1598
+ width,
1599
+ },
1600
+ uiTheme,
1601
+ );
1602
+ },
1603
+ invalidate: () => {
1604
+ outputBlock.invalidate();
1605
+ },
1606
+ });
1607
+ },
1608
+
1609
+ renderResult(
1610
+ result: {
1611
+ content: Array<{ type: string; text?: string }>;
1612
+ details?: BashToolDetails;
1613
+ isError?: boolean;
1614
+ },
1615
+ options: RenderResultOptions & { renderContext?: BashRenderContext },
1616
+ uiTheme: Theme,
1617
+ args?: TArgs,
1618
+ ): Component {
1619
+ const renderArgs = toBashRenderArgs(args, config);
1620
+ const cmdLines = args ? formatBashCommandLines(renderArgs, uiTheme) : undefined;
1621
+ const isError = result.isError === true;
1622
+ const isPartial = options.isPartial === true;
1623
+ const success = !isPartial && !isError;
1624
+ const details = result.details;
1625
+ const isTimeout = details?.timedOut === true;
1626
+ const header =
1627
+ config.showHeader === false
1628
+ ? undefined
1629
+ : renderStatusLine(
1630
+ success
1631
+ ? {
1632
+ iconOverride: uiTheme.styledSymbol("tool.bash", "accent"),
1633
+ title: config.resolveTitle(args, options),
1634
+ }
1635
+ : {
1636
+ icon: isPartial ? "pending" : isTimeout ? "warning" : "error",
1637
+ title: config.resolveTitle(args, options),
1638
+ },
1639
+ uiTheme,
1640
+ );
1641
+ const outputBlock = new CachedOutputBlock();
1642
+
1643
+ // Per-instance cache for the expensive inner lines computation. Mirrors
1644
+ // the eval-renderer pattern (`eval-render.ts:709-752`): without this,
1645
+ // every TUI repaint (one per keystroke when a long transcript is on
1646
+ // screen) re-runs `split` / `replaceTabs` / `truncateToVisualLines` over
1647
+ // the whole stored output for every bash row in scrollback. With a
1648
+ // 50KB-tail bash result times hundreds of rows, that re-rendering is
1649
+ // what pinned the main thread in issue #2081 and made keystrokes feel
1650
+ // like the CPU was at 100%. The cache key includes every render input
1651
+ // that materially affects the produced lines.
1652
+ let cachedWidth: number | undefined;
1653
+ let cachedPreviewLines: number | undefined;
1654
+ let cachedExpanded: boolean | undefined;
1655
+ let cachedRawOutput: string | undefined;
1656
+ let cachedIsPartial: boolean | undefined;
1657
+ let cachedLines: readonly string[] | undefined;
1658
+ let cachedPreviewWindow: number | undefined;
1659
+
1660
+ return markFramedBlockComponent({
1661
+ render: (width: number): readonly string[] => {
1662
+ // REACTIVE: read mutable options at render time
1663
+ const { renderContext } = options;
1664
+ const expanded = renderContext?.expanded ?? options.expanded;
1665
+ const previewLines = renderContext?.previewLines ?? BASH_DEFAULT_PREVIEW_LINES;
1666
+
1667
+ // Get output from context (preferred) or fall back to result content.
1668
+ // Strip the LLM-facing notice appended by wrappedExecute so we don't
1669
+ // double-print it alongside the styled warning line below.
1670
+ const rawOutput = renderContext?.output ?? result.content?.find(c => c.type === "text")?.text ?? "";
1671
+
1672
+ const isPartial = options.isPartial === true;
1673
+ const previewWindow = previewWindowRows();
1674
+
1675
+ if (
1676
+ cachedLines !== undefined &&
1677
+ cachedWidth === width &&
1678
+ cachedPreviewLines === previewLines &&
1679
+ cachedExpanded === expanded &&
1680
+ cachedRawOutput === rawOutput &&
1681
+ cachedIsPartial === isPartial &&
1682
+ cachedPreviewWindow === previewWindow
1683
+ ) {
1684
+ return cachedLines;
1685
+ }
1686
+ const withoutBackground = stripBackgroundNotice(rawOutput, details?.async);
1687
+ const strippedOutput = stripOutputNotice(withoutBackground, details?.meta);
1688
+ const withoutExit = stripExitCodeNotice(strippedOutput, details?.exitCode);
1689
+ const withoutWall = stripWallTimeNotice(withoutExit, details?.wallTimeMs);
1690
+ const rawOutputArtifact = stripRawOutputArtifactNotice(withoutWall);
1691
+ const output = rawOutputArtifact.text;
1692
+ const displayOutput = output.trimEnd();
1693
+ const showingFullOutput = expanded && renderContext?.isFullOutput === true;
1694
+
1695
+ // Build truncation warning
1696
+ const timeoutDisabled = details?.timeoutDisabled === true || renderContext?.timeout === 0;
1697
+ const timeoutSeconds = timeoutDisabled ? undefined : (details?.timeoutSeconds ?? renderContext?.timeout);
1698
+ const requestedTimeoutSeconds = details?.requestedTimeoutSeconds;
1699
+ const wallTimeMs = details?.wallTimeMs;
1700
+ const statsParts: string[] = [];
1701
+ if (details?.async?.state === "running") {
1702
+ statsParts.push(`Backgrounded: ${details.async.jobId}`);
1703
+ }
1704
+ if (wallTimeMs !== undefined) {
1705
+ statsParts.push(`Wall: ${formatWallTimeSeconds(wallTimeMs)}s`);
1706
+ }
1707
+ if (timeoutDisabled) {
1708
+ statsParts.push("Timeout: disabled");
1709
+ }
1710
+ if (typeof timeoutSeconds === "number") {
1711
+ statsParts.push(
1712
+ requestedTimeoutSeconds !== undefined && requestedTimeoutSeconds !== timeoutSeconds
1713
+ ? `Timeout: ${timeoutSeconds}s (requested ${requestedTimeoutSeconds}s clamped)`
1714
+ : `Timeout: ${timeoutSeconds}s`,
1715
+ );
1716
+ }
1717
+ if (rawOutputArtifact.artifactId) {
1718
+ statsParts.push(`Artifact: ${rawOutputArtifact.artifactId}`);
1719
+ }
1720
+ if (isError && typeof details?.exitCode === "number") {
1721
+ statsParts.push(`Exit: ${details.exitCode}`);
1722
+ }
1723
+ const timeoutLine =
1724
+ statsParts.length > 0
1725
+ ? uiTheme.fg(
1726
+ "dim",
1727
+ `${uiTheme.format.bracketLeft}${statsParts.join(" | ")}${uiTheme.format.bracketRight}`,
1728
+ )
1729
+ : undefined;
1730
+ let warningLine: string | undefined;
1731
+ if (details?.meta?.truncation && !showingFullOutput) {
1732
+ warningLine = formatStyledTruncationWarning(details.meta, uiTheme) ?? undefined;
1733
+ }
1734
+
1735
+ const outputLines: string[] = [];
1736
+ const hasOutput = displayOutput.trim().length > 0;
1737
+ const rawOutputLines = displayOutput.split("\n");
1738
+ const sixelLineMask =
1739
+ TERMINAL.imageProtocol === ImageProtocol.Sixel ? getSixelLineMask(rawOutputLines) : undefined;
1740
+ const hasSixelOutput = sixelLineMask?.some(Boolean) ?? false;
1741
+ if (hasOutput) {
1742
+ if (hasSixelOutput) {
1743
+ outputLines.push(
1744
+ ...rawOutputLines.map((line, index) =>
1745
+ sixelLineMask?.[index] ? line : uiTheme.fg("toolOutput", replaceTabs(line)),
1746
+ ),
1747
+ );
1748
+ } else if (expanded) {
1749
+ outputLines.push(...rawOutputLines.map(line => uiTheme.fg("toolOutput", replaceTabs(line))));
1750
+ } else {
1751
+ const styledOutput = rawOutputLines
1752
+ .map(line => uiTheme.fg("toolOutput", replaceTabs(line)))
1753
+ .join("\n");
1754
+ const textContent = styledOutput;
1755
+ // Cap the collapsed/streaming output to a viewport-sized tail and
1756
+ // measure it at the box's INNER width. Otherwise a growing tail
1757
+ // window scrolls its (mutating) rows above the live-region window
1758
+ // and the engine re-commits a fresh snapshot every frame —
1759
+ // spraying duplicate "… ctrl+o to expand" banners into native
1760
+ // scrollback (the box never overflows the viewport now).
1761
+ const previewBudget = Math.min(previewLines, previewWindow);
1762
+ const result = truncateToVisualLines(textContent, previewBudget, outputBlockContentWidth(width));
1763
+ if (result.skippedCount > 0) {
1764
+ outputLines.push(
1765
+ uiTheme.fg(
1766
+ "dim",
1767
+ `… (${result.skippedCount} earlier lines, showing ${result.visualLines.length} of ${result.skippedCount + result.visualLines.length}) (ctrl+o to expand)`,
1768
+ ),
1769
+ );
1770
+ }
1771
+ outputLines.push(...result.visualLines);
1772
+ }
1773
+ }
1774
+ if (timeoutLine) outputLines.push(timeoutLine);
1775
+ if (warningLine) outputLines.push(warningLine);
1776
+
1777
+ const framed = outputBlock.render(
1778
+ {
1779
+ header,
1780
+ state: isPartial ? "pending" : isError ? (isTimeout ? "warning" : "error") : "success",
1781
+ sections: [
1782
+ {
1783
+ // Viewport-sized tail window in every state — streaming and final
1784
+ // render identically; only ctrl+o uncaps.
1785
+ lines: capPreviewLines(cmdLines ?? [], uiTheme, { expanded }),
1786
+ },
1787
+ { label: uiTheme.fg("toolTitle", "Output"), lines: outputLines },
1788
+ ],
1789
+ width,
1790
+ },
1791
+ uiTheme,
1792
+ );
1793
+
1794
+ cachedWidth = width;
1795
+ cachedPreviewLines = previewLines;
1796
+ cachedExpanded = expanded;
1797
+ cachedRawOutput = rawOutput;
1798
+ cachedIsPartial = isPartial;
1799
+ cachedPreviewWindow = previewWindow;
1800
+ cachedLines = framed;
1801
+ return framed;
1802
+ },
1803
+ invalidate: () => {
1804
+ outputBlock.invalidate();
1805
+ cachedLines = undefined;
1806
+ cachedWidth = undefined;
1807
+ cachedPreviewLines = undefined;
1808
+ cachedExpanded = undefined;
1809
+ cachedRawOutput = undefined;
1810
+ cachedIsPartial = undefined;
1811
+ cachedPreviewWindow = undefined;
1812
+ },
1813
+ });
1814
+ },
1815
+ mergeCallAndResult: true,
1816
+ inline: true,
1817
+ };
1818
+ }
1819
+
1820
+ export const bashToolRenderer = createShellRenderer<BashRenderArgs>({
1821
+ resolveTitle: () => "Bash",
1822
+ resolveCommand: args => args?.command,
1823
+ resolveCwd: args => args?.cwd,
1824
+ resolveEnv: args => args?.env,
1825
+ showHeader: false,
1826
+ });