@wahack/pi-coding-agent 15.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1152) hide show
  1. package/CHANGELOG.md +10031 -0
  2. package/README.md +36 -0
  3. package/examples/README.md +21 -0
  4. package/examples/custom-tools/README.md +104 -0
  5. package/examples/custom-tools/hello/index.ts +20 -0
  6. package/examples/extensions/README.md +142 -0
  7. package/examples/extensions/api-demo.ts +79 -0
  8. package/examples/extensions/chalk-logger.ts +25 -0
  9. package/examples/extensions/hello.ts +31 -0
  10. package/examples/extensions/pirate.ts +43 -0
  11. package/examples/extensions/plan-mode.ts +549 -0
  12. package/examples/extensions/reload-runtime.ts +38 -0
  13. package/examples/extensions/thinking-note.ts +13 -0
  14. package/examples/extensions/tools.ts +145 -0
  15. package/examples/extensions/with-deps/index.ts +36 -0
  16. package/examples/extensions/with-deps/package-lock.json +31 -0
  17. package/examples/extensions/with-deps/package.json +17 -0
  18. package/examples/hooks/README.md +56 -0
  19. package/examples/hooks/auto-commit-on-exit.ts +48 -0
  20. package/examples/hooks/confirm-destructive.ts +58 -0
  21. package/examples/hooks/custom-compaction.ts +115 -0
  22. package/examples/hooks/dirty-repo-guard.ts +51 -0
  23. package/examples/hooks/file-trigger.ts +40 -0
  24. package/examples/hooks/git-checkpoint.ts +52 -0
  25. package/examples/hooks/handoff.ts +149 -0
  26. package/examples/hooks/permission-gate.ts +33 -0
  27. package/examples/hooks/protected-paths.ts +29 -0
  28. package/examples/hooks/qna.ts +118 -0
  29. package/examples/hooks/status-line.ts +39 -0
  30. package/examples/sdk/01-minimal.ts +21 -0
  31. package/examples/sdk/02-custom-model.ts +49 -0
  32. package/examples/sdk/03-custom-prompt.ts +46 -0
  33. package/examples/sdk/04-skills.ts +43 -0
  34. package/examples/sdk/06-extensions.ts +82 -0
  35. package/examples/sdk/06-hooks.ts +61 -0
  36. package/examples/sdk/07-context-files.ts +35 -0
  37. package/examples/sdk/08-prompt-templates.ts +41 -0
  38. package/examples/sdk/08-slash-commands.ts +46 -0
  39. package/examples/sdk/09-api-keys-and-oauth.ts +54 -0
  40. package/examples/sdk/11-sessions.ts +47 -0
  41. package/examples/sdk/12-redis-sessions.ts +54 -0
  42. package/examples/sdk/13-sql-sessions.ts +61 -0
  43. package/examples/sdk/README.md +172 -0
  44. package/package.json +554 -0
  45. package/scripts/build-binary.ts +100 -0
  46. package/scripts/bundle-dist.ts +90 -0
  47. package/scripts/format-prompts.ts +68 -0
  48. package/scripts/generate-docs-index.ts +40 -0
  49. package/scripts/generate-template.ts +33 -0
  50. package/scripts/omp +42 -0
  51. package/scripts/omp.ts +19 -0
  52. package/src/async/index.ts +1 -0
  53. package/src/async/job-manager.ts +625 -0
  54. package/src/auto-thinking/classifier.ts +185 -0
  55. package/src/autoresearch/command-resume.md +14 -0
  56. package/src/autoresearch/dashboard.ts +436 -0
  57. package/src/autoresearch/git.ts +319 -0
  58. package/src/autoresearch/helpers.ts +218 -0
  59. package/src/autoresearch/index.ts +536 -0
  60. package/src/autoresearch/prompt-setup.md +43 -0
  61. package/src/autoresearch/prompt.md +103 -0
  62. package/src/autoresearch/resume-message.md +10 -0
  63. package/src/autoresearch/state.ts +273 -0
  64. package/src/autoresearch/storage.ts +699 -0
  65. package/src/autoresearch/tools/init-experiment.ts +272 -0
  66. package/src/autoresearch/tools/log-experiment.ts +524 -0
  67. package/src/autoresearch/tools/run-experiment.ts +407 -0
  68. package/src/autoresearch/tools/update-notes.ts +109 -0
  69. package/src/autoresearch/types.ts +168 -0
  70. package/src/bun-imports.d.ts +28 -0
  71. package/src/capability/context-file.ts +44 -0
  72. package/src/capability/extension-module.ts +34 -0
  73. package/src/capability/extension.ts +47 -0
  74. package/src/capability/fs.ts +117 -0
  75. package/src/capability/hook.ts +40 -0
  76. package/src/capability/index.ts +436 -0
  77. package/src/capability/instruction.ts +37 -0
  78. package/src/capability/mcp.ts +74 -0
  79. package/src/capability/prompt.ts +35 -0
  80. package/src/capability/rule-buckets.ts +66 -0
  81. package/src/capability/rule.ts +261 -0
  82. package/src/capability/settings.ts +34 -0
  83. package/src/capability/skill.ts +63 -0
  84. package/src/capability/slash-command.ts +40 -0
  85. package/src/capability/ssh.ts +41 -0
  86. package/src/capability/system-prompt.ts +34 -0
  87. package/src/capability/tool.ts +38 -0
  88. package/src/capability/types.ts +168 -0
  89. package/src/cli/agents-cli.ts +138 -0
  90. package/src/cli/args.ts +340 -0
  91. package/src/cli/auth-broker-cli.ts +895 -0
  92. package/src/cli/auth-gateway-cli.ts +611 -0
  93. package/src/cli/classify-install-target.ts +76 -0
  94. package/src/cli/claude-trace-cli.ts +795 -0
  95. package/src/cli/commands/init-xdg.ts +27 -0
  96. package/src/cli/completion-gen.ts +550 -0
  97. package/src/cli/config-cli.ts +418 -0
  98. package/src/cli/dry-balance-cli.ts +856 -0
  99. package/src/cli/extension-flags.ts +48 -0
  100. package/src/cli/file-processor.ts +133 -0
  101. package/src/cli/gallery-cli.ts +230 -0
  102. package/src/cli/gallery-fixtures/agentic.ts +407 -0
  103. package/src/cli/gallery-fixtures/codeintel.ts +187 -0
  104. package/src/cli/gallery-fixtures/edit.ts +194 -0
  105. package/src/cli/gallery-fixtures/fs.ts +220 -0
  106. package/src/cli/gallery-fixtures/index.ts +40 -0
  107. package/src/cli/gallery-fixtures/interaction.ts +49 -0
  108. package/src/cli/gallery-fixtures/memory.ts +81 -0
  109. package/src/cli/gallery-fixtures/misc.ts +250 -0
  110. package/src/cli/gallery-fixtures/search.ts +213 -0
  111. package/src/cli/gallery-fixtures/shell.ts +167 -0
  112. package/src/cli/gallery-fixtures/types.ts +57 -0
  113. package/src/cli/gallery-fixtures/web.ts +158 -0
  114. package/src/cli/gallery-screenshot.ts +279 -0
  115. package/src/cli/grep-cli.ts +160 -0
  116. package/src/cli/grievances-cli.ts +256 -0
  117. package/src/cli/initial-message.ts +58 -0
  118. package/src/cli/list-models.ts +194 -0
  119. package/src/cli/plugin-cli.ts +996 -0
  120. package/src/cli/read-cli.ts +57 -0
  121. package/src/cli/session-picker.ts +79 -0
  122. package/src/cli/setup-cli.ts +231 -0
  123. package/src/cli/shell-cli.ts +176 -0
  124. package/src/cli/ssh-cli.ts +179 -0
  125. package/src/cli/startup-cwd.ts +68 -0
  126. package/src/cli/stats-cli.ts +238 -0
  127. package/src/cli/tiny-models-cli.ts +127 -0
  128. package/src/cli/update-cli.ts +611 -0
  129. package/src/cli/usage-cli.ts +603 -0
  130. package/src/cli/web-search-cli.ts +132 -0
  131. package/src/cli/worktree-cli.ts +291 -0
  132. package/src/cli-commands.ts +79 -0
  133. package/src/cli.ts +200 -0
  134. package/src/commands/acp.ts +24 -0
  135. package/src/commands/agents.ts +57 -0
  136. package/src/commands/auth-broker.ts +99 -0
  137. package/src/commands/auth-gateway.ts +69 -0
  138. package/src/commands/commit.ts +46 -0
  139. package/src/commands/complete.ts +66 -0
  140. package/src/commands/completions.ts +60 -0
  141. package/src/commands/config.ts +51 -0
  142. package/src/commands/dry-balance.ts +43 -0
  143. package/src/commands/gallery.ts +52 -0
  144. package/src/commands/grep.ts +48 -0
  145. package/src/commands/grievances.ts +51 -0
  146. package/src/commands/install.ts +107 -0
  147. package/src/commands/launch.ts +169 -0
  148. package/src/commands/plugin.ts +78 -0
  149. package/src/commands/read.ts +38 -0
  150. package/src/commands/setup.ts +67 -0
  151. package/src/commands/shell.ts +29 -0
  152. package/src/commands/ssh.ts +60 -0
  153. package/src/commands/stats.ts +29 -0
  154. package/src/commands/tiny-models.ts +36 -0
  155. package/src/commands/update.ts +21 -0
  156. package/src/commands/usage.ts +35 -0
  157. package/src/commands/web-search.ts +42 -0
  158. package/src/commands/worktree.ts +56 -0
  159. package/src/commit/agentic/agent.ts +317 -0
  160. package/src/commit/agentic/fallback.ts +96 -0
  161. package/src/commit/agentic/index.ts +355 -0
  162. package/src/commit/agentic/prompts/analyze-file.md +22 -0
  163. package/src/commit/agentic/prompts/session-user.md +25 -0
  164. package/src/commit/agentic/prompts/split-confirm.md +1 -0
  165. package/src/commit/agentic/prompts/system.md +38 -0
  166. package/src/commit/agentic/state.ts +60 -0
  167. package/src/commit/agentic/tools/analyze-file.ts +146 -0
  168. package/src/commit/agentic/tools/git-file-diff.ts +191 -0
  169. package/src/commit/agentic/tools/git-hunk.ts +50 -0
  170. package/src/commit/agentic/tools/git-overview.ts +81 -0
  171. package/src/commit/agentic/tools/index.ts +54 -0
  172. package/src/commit/agentic/tools/propose-changelog.ts +144 -0
  173. package/src/commit/agentic/tools/propose-commit.ts +109 -0
  174. package/src/commit/agentic/tools/recent-commits.ts +81 -0
  175. package/src/commit/agentic/tools/schemas.ts +23 -0
  176. package/src/commit/agentic/tools/split-commit.ts +245 -0
  177. package/src/commit/agentic/topo-sort.ts +44 -0
  178. package/src/commit/agentic/trivial.ts +51 -0
  179. package/src/commit/agentic/validation.ts +183 -0
  180. package/src/commit/analysis/conventional.ts +64 -0
  181. package/src/commit/analysis/index.ts +4 -0
  182. package/src/commit/analysis/scope.ts +242 -0
  183. package/src/commit/analysis/summary.ts +105 -0
  184. package/src/commit/analysis/validation.ts +66 -0
  185. package/src/commit/changelog/detect.ts +40 -0
  186. package/src/commit/changelog/generate.ts +97 -0
  187. package/src/commit/changelog/index.ts +234 -0
  188. package/src/commit/changelog/parse.ts +44 -0
  189. package/src/commit/cli.ts +85 -0
  190. package/src/commit/git/diff.ts +148 -0
  191. package/src/commit/index.ts +5 -0
  192. package/src/commit/map-reduce/index.ts +69 -0
  193. package/src/commit/map-reduce/map-phase.ts +193 -0
  194. package/src/commit/map-reduce/reduce-phase.ts +49 -0
  195. package/src/commit/map-reduce/utils.ts +9 -0
  196. package/src/commit/message.ts +11 -0
  197. package/src/commit/model-selection.ts +92 -0
  198. package/src/commit/pipeline.ts +243 -0
  199. package/src/commit/prompts/analysis-system.md +148 -0
  200. package/src/commit/prompts/analysis-user.md +38 -0
  201. package/src/commit/prompts/changelog-system.md +50 -0
  202. package/src/commit/prompts/changelog-user.md +18 -0
  203. package/src/commit/prompts/file-observer-system.md +24 -0
  204. package/src/commit/prompts/file-observer-user.md +8 -0
  205. package/src/commit/prompts/reduce-system.md +50 -0
  206. package/src/commit/prompts/reduce-user.md +17 -0
  207. package/src/commit/prompts/summary-retry.md +3 -0
  208. package/src/commit/prompts/summary-system.md +38 -0
  209. package/src/commit/prompts/summary-user.md +13 -0
  210. package/src/commit/prompts/types-description.md +2 -0
  211. package/src/commit/shared-llm.ts +77 -0
  212. package/src/commit/types.ts +118 -0
  213. package/src/commit/utils/exclusions.ts +42 -0
  214. package/src/commit/utils.ts +58 -0
  215. package/src/config/api-key-resolver.ts +60 -0
  216. package/src/config/append-only-context-mode.ts +31 -0
  217. package/src/config/config-file.ts +317 -0
  218. package/src/config/file-lock.ts +164 -0
  219. package/src/config/keybindings.ts +628 -0
  220. package/src/config/mcp-schema.json +230 -0
  221. package/src/config/model-discovery.ts +554 -0
  222. package/src/config/model-registry.ts +2090 -0
  223. package/src/config/model-resolver.ts +1502 -0
  224. package/src/config/model-roles.ts +74 -0
  225. package/src/config/models-config-schema.ts +226 -0
  226. package/src/config/models-config.ts +129 -0
  227. package/src/config/prompt-templates.ts +185 -0
  228. package/src/config/resolve-config-value.ts +94 -0
  229. package/src/config/settings-schema.ts +3530 -0
  230. package/src/config/settings.ts +1178 -0
  231. package/src/config.ts +242 -0
  232. package/src/cursor.ts +340 -0
  233. package/src/dap/client.ts +760 -0
  234. package/src/dap/config.ts +189 -0
  235. package/src/dap/defaults.json +212 -0
  236. package/src/dap/index.ts +4 -0
  237. package/src/dap/session.ts +1441 -0
  238. package/src/dap/types.ts +610 -0
  239. package/src/debug/index.ts +515 -0
  240. package/src/debug/log-formatting.ts +58 -0
  241. package/src/debug/log-viewer.ts +908 -0
  242. package/src/debug/profiler.ts +162 -0
  243. package/src/debug/protocol-probe.ts +267 -0
  244. package/src/debug/raw-sse-buffer.ts +273 -0
  245. package/src/debug/raw-sse.ts +292 -0
  246. package/src/debug/report-bundle.ts +374 -0
  247. package/src/debug/system-info.ts +111 -0
  248. package/src/debug/terminal-info.ts +124 -0
  249. package/src/discovery/agents-md.ts +67 -0
  250. package/src/discovery/agents.ts +230 -0
  251. package/src/discovery/at-imports.ts +273 -0
  252. package/src/discovery/builtin-defaults.ts +39 -0
  253. package/src/discovery/builtin-rules/index.ts +54 -0
  254. package/src/discovery/builtin-rules/rs-box-leak.md +48 -0
  255. package/src/discovery/builtin-rules/rs-future-prelude.md +23 -0
  256. package/src/discovery/builtin-rules/rs-lazylock.md +51 -0
  257. package/src/discovery/builtin-rules/rs-match-ergonomics.md +67 -0
  258. package/src/discovery/builtin-rules/rs-parking-lot.md +44 -0
  259. package/src/discovery/builtin-rules/rs-result-type.md +19 -0
  260. package/src/discovery/builtin-rules/ts-bare-catch.md +38 -0
  261. package/src/discovery/builtin-rules/ts-import-type.md +42 -0
  262. package/src/discovery/builtin-rules/ts-no-any.md +56 -0
  263. package/src/discovery/builtin-rules/ts-no-deprecated-leftovers.md +44 -0
  264. package/src/discovery/builtin-rules/ts-no-dynamic-import.md +39 -0
  265. package/src/discovery/builtin-rules/ts-no-return-type.md +45 -0
  266. package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
  267. package/src/discovery/builtin-rules/ts-no-tiny-functions.md +51 -0
  268. package/src/discovery/builtin-rules/ts-promise-with-resolvers.md +65 -0
  269. package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
  270. package/src/discovery/builtin-rules/ts-set-map.md +28 -0
  271. package/src/discovery/builtin.ts +906 -0
  272. package/src/discovery/claude-plugins.ts +386 -0
  273. package/src/discovery/claude.ts +584 -0
  274. package/src/discovery/cline.ts +83 -0
  275. package/src/discovery/codex.ts +522 -0
  276. package/src/discovery/cursor.ts +220 -0
  277. package/src/discovery/gemini.ts +383 -0
  278. package/src/discovery/github.ts +154 -0
  279. package/src/discovery/helpers.ts +1016 -0
  280. package/src/discovery/index.ts +81 -0
  281. package/src/discovery/mcp-json.ts +171 -0
  282. package/src/discovery/omp-extension-roots.ts +190 -0
  283. package/src/discovery/omp-plugins.ts +383 -0
  284. package/src/discovery/opencode.ts +398 -0
  285. package/src/discovery/plugin-dir-roots.ts +28 -0
  286. package/src/discovery/ssh.ts +153 -0
  287. package/src/discovery/substitute-plugin-root.ts +29 -0
  288. package/src/discovery/vscode.ts +105 -0
  289. package/src/discovery/windsurf.ts +147 -0
  290. package/src/edit/apply-patch/index.ts +87 -0
  291. package/src/edit/apply-patch/parser.ts +174 -0
  292. package/src/edit/diff.ts +999 -0
  293. package/src/edit/file-snapshot-store.ts +91 -0
  294. package/src/edit/hashline/block-resolver.ts +33 -0
  295. package/src/edit/hashline/diff.ts +290 -0
  296. package/src/edit/hashline/execute.ts +242 -0
  297. package/src/edit/hashline/filesystem.ts +130 -0
  298. package/src/edit/hashline/index.ts +5 -0
  299. package/src/edit/hashline/noop-loop-guard.ts +99 -0
  300. package/src/edit/hashline/params.ts +18 -0
  301. package/src/edit/index.ts +571 -0
  302. package/src/edit/modes/apply-patch.lark +19 -0
  303. package/src/edit/modes/apply-patch.ts +53 -0
  304. package/src/edit/modes/patch.ts +1891 -0
  305. package/src/edit/modes/replace.ts +1137 -0
  306. package/src/edit/normalize.ts +345 -0
  307. package/src/edit/notebook.ts +242 -0
  308. package/src/edit/read-file.ts +25 -0
  309. package/src/edit/renderer.ts +769 -0
  310. package/src/edit/streaming.ts +517 -0
  311. package/src/eval/__tests__/agent-bridge.test.ts +708 -0
  312. package/src/eval/__tests__/bridge-timeout.test.ts +64 -0
  313. package/src/eval/__tests__/budget-bridge.test.ts +69 -0
  314. package/src/eval/__tests__/completion-bridge.test.ts +412 -0
  315. package/src/eval/__tests__/helpers-local-roots.test.ts +58 -0
  316. package/src/eval/__tests__/idle-timeout.test.ts +80 -0
  317. package/src/eval/__tests__/js-context-manager.test.ts +241 -0
  318. package/src/eval/__tests__/kernel-spawn.test.ts +103 -0
  319. package/src/eval/agent-bridge.ts +319 -0
  320. package/src/eval/backend.ts +71 -0
  321. package/src/eval/bridge-timeout.ts +44 -0
  322. package/src/eval/budget-bridge.ts +48 -0
  323. package/src/eval/completion-bridge.ts +207 -0
  324. package/src/eval/concurrency-bridge.ts +34 -0
  325. package/src/eval/idle-timeout.ts +91 -0
  326. package/src/eval/index.ts +4 -0
  327. package/src/eval/js/context-manager.ts +502 -0
  328. package/src/eval/js/executor.ts +173 -0
  329. package/src/eval/js/index.ts +51 -0
  330. package/src/eval/js/shared/helpers.ts +283 -0
  331. package/src/eval/js/shared/indirect-eval.ts +30 -0
  332. package/src/eval/js/shared/local-module-loader.ts +342 -0
  333. package/src/eval/js/shared/prelude.ts +2 -0
  334. package/src/eval/js/shared/prelude.txt +246 -0
  335. package/src/eval/js/shared/rewrite-imports.ts +532 -0
  336. package/src/eval/js/shared/runtime.ts +352 -0
  337. package/src/eval/js/shared/types.ts +18 -0
  338. package/src/eval/js/tool-bridge.ts +162 -0
  339. package/src/eval/js/worker-core.ts +132 -0
  340. package/src/eval/js/worker-entry.ts +30 -0
  341. package/src/eval/js/worker-protocol.ts +47 -0
  342. package/src/eval/py/__tests__/prelude.test.ts +19 -0
  343. package/src/eval/py/display.ts +71 -0
  344. package/src/eval/py/executor.ts +742 -0
  345. package/src/eval/py/index.ts +68 -0
  346. package/src/eval/py/kernel.ts +748 -0
  347. package/src/eval/py/prelude.py +658 -0
  348. package/src/eval/py/prelude.ts +3 -0
  349. package/src/eval/py/runner.py +1133 -0
  350. package/src/eval/py/runtime.ts +276 -0
  351. package/src/eval/py/spawn-options.ts +126 -0
  352. package/src/eval/py/tool-bridge.ts +182 -0
  353. package/src/eval/session-id.ts +8 -0
  354. package/src/eval/types.ts +48 -0
  355. package/src/exa/index.ts +2 -0
  356. package/src/exa/mcp-client.ts +370 -0
  357. package/src/exa/types.ts +69 -0
  358. package/src/exec/bash-executor.ts +419 -0
  359. package/src/exec/exec.ts +53 -0
  360. package/src/exec/non-interactive-env.ts +48 -0
  361. package/src/export/custom-share.ts +65 -0
  362. package/src/export/html/index.ts +164 -0
  363. package/src/export/html/template.css +1051 -0
  364. package/src/export/html/template.generated.ts +2 -0
  365. package/src/export/html/template.html +46 -0
  366. package/src/export/html/template.js +2271 -0
  367. package/src/export/html/template.macro.ts +25 -0
  368. package/src/export/html/vendor/highlight.min.js +1213 -0
  369. package/src/export/html/vendor/marked.min.js +6 -0
  370. package/src/export/ttsr.ts +583 -0
  371. package/src/extensibility/custom-commands/bundled/ci-green/index.ts +54 -0
  372. package/src/extensibility/custom-commands/bundled/review/index.ts +489 -0
  373. package/src/extensibility/custom-commands/index.ts +2 -0
  374. package/src/extensibility/custom-commands/loader.ts +238 -0
  375. package/src/extensibility/custom-commands/types.ts +113 -0
  376. package/src/extensibility/custom-tools/index.ts +7 -0
  377. package/src/extensibility/custom-tools/loader.ts +269 -0
  378. package/src/extensibility/custom-tools/types.ts +270 -0
  379. package/src/extensibility/custom-tools/wrapper.ts +47 -0
  380. package/src/extensibility/extensions/compact-handler.ts +40 -0
  381. package/src/extensibility/extensions/get-commands-handler.ts +78 -0
  382. package/src/extensibility/extensions/index.ts +16 -0
  383. package/src/extensibility/extensions/loader.ts +572 -0
  384. package/src/extensibility/extensions/runner.ts +922 -0
  385. package/src/extensibility/extensions/types.ts +1322 -0
  386. package/src/extensibility/extensions/wrapper.ts +223 -0
  387. package/src/extensibility/hooks/index.ts +5 -0
  388. package/src/extensibility/hooks/loader.ts +257 -0
  389. package/src/extensibility/hooks/runner.ts +425 -0
  390. package/src/extensibility/hooks/tool-wrapper.ts +107 -0
  391. package/src/extensibility/hooks/types.ts +606 -0
  392. package/src/extensibility/legacy-pi-ai-shim.ts +24 -0
  393. package/src/extensibility/legacy-pi-coding-agent-shim.ts +15 -0
  394. package/src/extensibility/plugins/doctor.ts +65 -0
  395. package/src/extensibility/plugins/git-url.ts +367 -0
  396. package/src/extensibility/plugins/index.ts +9 -0
  397. package/src/extensibility/plugins/installer.ts +192 -0
  398. package/src/extensibility/plugins/legacy-pi-compat.ts +682 -0
  399. package/src/extensibility/plugins/loader.ts +313 -0
  400. package/src/extensibility/plugins/manager.ts +827 -0
  401. package/src/extensibility/plugins/marketplace/cache.ts +136 -0
  402. package/src/extensibility/plugins/marketplace/fetcher.ts +317 -0
  403. package/src/extensibility/plugins/marketplace/index.ts +6 -0
  404. package/src/extensibility/plugins/marketplace/manager.ts +770 -0
  405. package/src/extensibility/plugins/marketplace/registry.ts +196 -0
  406. package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
  407. package/src/extensibility/plugins/marketplace/types.ts +191 -0
  408. package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
  409. package/src/extensibility/plugins/parser.ts +105 -0
  410. package/src/extensibility/plugins/types.ts +194 -0
  411. package/src/extensibility/shared-events.ts +343 -0
  412. package/src/extensibility/skills.ts +312 -0
  413. package/src/extensibility/slash-commands.ts +227 -0
  414. package/src/extensibility/tool-proxy.ts +25 -0
  415. package/src/extensibility/typebox.ts +418 -0
  416. package/src/extensibility/utils.ts +44 -0
  417. package/src/goals/index.ts +3 -0
  418. package/src/goals/runtime.ts +528 -0
  419. package/src/goals/state.ts +37 -0
  420. package/src/goals/tools/goal-tool.ts +251 -0
  421. package/src/hindsight/backend.ts +354 -0
  422. package/src/hindsight/bank.ts +156 -0
  423. package/src/hindsight/client.ts +598 -0
  424. package/src/hindsight/config.ts +175 -0
  425. package/src/hindsight/content.ts +210 -0
  426. package/src/hindsight/index.ts +8 -0
  427. package/src/hindsight/mental-models.ts +429 -0
  428. package/src/hindsight/seeds.json +32 -0
  429. package/src/hindsight/state.ts +488 -0
  430. package/src/hindsight/transcript.ts +71 -0
  431. package/src/index.ts +59 -0
  432. package/src/internal-urls/agent-protocol.ts +146 -0
  433. package/src/internal-urls/artifact-protocol.ts +107 -0
  434. package/src/internal-urls/docs-index.generated.ts +106 -0
  435. package/src/internal-urls/history-protocol.ts +113 -0
  436. package/src/internal-urls/index.ts +25 -0
  437. package/src/internal-urls/issue-pr-protocol.ts +584 -0
  438. package/src/internal-urls/json-query.ts +126 -0
  439. package/src/internal-urls/local-protocol.ts +287 -0
  440. package/src/internal-urls/mcp-protocol.ts +151 -0
  441. package/src/internal-urls/memory-protocol.ts +169 -0
  442. package/src/internal-urls/omp-protocol.ts +93 -0
  443. package/src/internal-urls/parse.ts +72 -0
  444. package/src/internal-urls/registry-helpers.ts +25 -0
  445. package/src/internal-urls/router.ts +105 -0
  446. package/src/internal-urls/rule-protocol.ts +45 -0
  447. package/src/internal-urls/skill-protocol.ts +96 -0
  448. package/src/internal-urls/types.ts +152 -0
  449. package/src/internal-urls/vault-protocol.ts +936 -0
  450. package/src/irc/bus.ts +292 -0
  451. package/src/lib/xai-http.ts +124 -0
  452. package/src/lsp/client.ts +1193 -0
  453. package/src/lsp/clients/biome-client.ts +264 -0
  454. package/src/lsp/clients/index.ts +50 -0
  455. package/src/lsp/clients/lsp-linter-client.ts +93 -0
  456. package/src/lsp/clients/swiftlint-client.ts +120 -0
  457. package/src/lsp/config.ts +502 -0
  458. package/src/lsp/defaults.json +493 -0
  459. package/src/lsp/diagnostics-ledger.ts +51 -0
  460. package/src/lsp/edits.ts +267 -0
  461. package/src/lsp/index.ts +2477 -0
  462. package/src/lsp/lspmux.ts +233 -0
  463. package/src/lsp/render.ts +694 -0
  464. package/src/lsp/startup-events.ts +13 -0
  465. package/src/lsp/types.ts +455 -0
  466. package/src/lsp/utils.ts +718 -0
  467. package/src/main.ts +1325 -0
  468. package/src/mcp/client.ts +484 -0
  469. package/src/mcp/config-writer.ts +225 -0
  470. package/src/mcp/config.ts +365 -0
  471. package/src/mcp/index.ts +29 -0
  472. package/src/mcp/json-rpc.ts +122 -0
  473. package/src/mcp/loader.ts +124 -0
  474. package/src/mcp/manager.ts +1275 -0
  475. package/src/mcp/oauth-discovery.ts +442 -0
  476. package/src/mcp/oauth-flow.ts +442 -0
  477. package/src/mcp/render.ts +132 -0
  478. package/src/mcp/smithery-auth.ts +104 -0
  479. package/src/mcp/smithery-connect.ts +145 -0
  480. package/src/mcp/smithery-registry.ts +477 -0
  481. package/src/mcp/timeout.ts +59 -0
  482. package/src/mcp/tool-bridge.ts +426 -0
  483. package/src/mcp/tool-cache.ts +117 -0
  484. package/src/mcp/transports/http.ts +519 -0
  485. package/src/mcp/transports/index.ts +6 -0
  486. package/src/mcp/transports/stdio.ts +528 -0
  487. package/src/mcp/types.ts +423 -0
  488. package/src/memories/index.ts +1150 -0
  489. package/src/memories/storage.ts +577 -0
  490. package/src/memory-backend/index.ts +18 -0
  491. package/src/memory-backend/local-backend.ts +39 -0
  492. package/src/memory-backend/off-backend.ts +25 -0
  493. package/src/memory-backend/resolve.ts +25 -0
  494. package/src/memory-backend/runtime.ts +66 -0
  495. package/src/memory-backend/types.ts +166 -0
  496. package/src/mnemopi/backend.ts +547 -0
  497. package/src/mnemopi/config.ts +160 -0
  498. package/src/mnemopi/index.ts +3 -0
  499. package/src/mnemopi/state.ts +584 -0
  500. package/src/modes/acp/acp-agent.ts +2407 -0
  501. package/src/modes/acp/acp-client-bridge.ts +154 -0
  502. package/src/modes/acp/acp-event-mapper.ts +929 -0
  503. package/src/modes/acp/acp-mode.ts +23 -0
  504. package/src/modes/acp/index.ts +2 -0
  505. package/src/modes/acp/terminal-auth.ts +37 -0
  506. package/src/modes/components/agent-dashboard.ts +1206 -0
  507. package/src/modes/components/agent-hub.ts +1071 -0
  508. package/src/modes/components/assistant-message.ts +307 -0
  509. package/src/modes/components/bash-execution.ts +220 -0
  510. package/src/modes/components/bordered-loader.ts +41 -0
  511. package/src/modes/components/branch-summary-message.ts +45 -0
  512. package/src/modes/components/btw-panel.ts +104 -0
  513. package/src/modes/components/chat-block.ts +111 -0
  514. package/src/modes/components/compaction-summary-message.ts +87 -0
  515. package/src/modes/components/copy-selector.ts +206 -0
  516. package/src/modes/components/countdown-timer.ts +75 -0
  517. package/src/modes/components/custom-editor.ts +398 -0
  518. package/src/modes/components/custom-message.ts +63 -0
  519. package/src/modes/components/diff.ts +277 -0
  520. package/src/modes/components/dynamic-border.ts +34 -0
  521. package/src/modes/components/error-banner.ts +33 -0
  522. package/src/modes/components/eval-execution.ts +158 -0
  523. package/src/modes/components/execution-shared.ts +101 -0
  524. package/src/modes/components/extensions/extension-dashboard.ts +399 -0
  525. package/src/modes/components/extensions/extension-list.ts +502 -0
  526. package/src/modes/components/extensions/index.ts +9 -0
  527. package/src/modes/components/extensions/inspector-panel.ts +317 -0
  528. package/src/modes/components/extensions/state-manager.ts +627 -0
  529. package/src/modes/components/extensions/types.ts +186 -0
  530. package/src/modes/components/footer.ts +274 -0
  531. package/src/modes/components/history-search.ts +280 -0
  532. package/src/modes/components/hook-editor.ts +167 -0
  533. package/src/modes/components/hook-input.ts +87 -0
  534. package/src/modes/components/hook-message.ts +66 -0
  535. package/src/modes/components/hook-selector.ts +660 -0
  536. package/src/modes/components/index.ts +38 -0
  537. package/src/modes/components/keybinding-hints.ts +65 -0
  538. package/src/modes/components/late-diagnostics-message.ts +60 -0
  539. package/src/modes/components/login-dialog.ts +164 -0
  540. package/src/modes/components/mcp-add-wizard.ts +1340 -0
  541. package/src/modes/components/message-frame.ts +88 -0
  542. package/src/modes/components/model-selector.ts +1271 -0
  543. package/src/modes/components/oauth-selector.ts +368 -0
  544. package/src/modes/components/omfg-panel.ts +141 -0
  545. package/src/modes/components/overlay-box.ts +108 -0
  546. package/src/modes/components/plan-review-overlay.ts +820 -0
  547. package/src/modes/components/plan-toc.ts +138 -0
  548. package/src/modes/components/plugin-selector.ts +95 -0
  549. package/src/modes/components/plugin-settings.ts +722 -0
  550. package/src/modes/components/queue-mode-selector.ts +56 -0
  551. package/src/modes/components/read-tool-group.ts +670 -0
  552. package/src/modes/components/segment-track.ts +52 -0
  553. package/src/modes/components/session-selector.ts +625 -0
  554. package/src/modes/components/settings-defs.ts +189 -0
  555. package/src/modes/components/settings-selector.ts +651 -0
  556. package/src/modes/components/show-images-selector.ts +45 -0
  557. package/src/modes/components/skill-message.ts +89 -0
  558. package/src/modes/components/status-line/component.ts +869 -0
  559. package/src/modes/components/status-line/context-thresholds.ts +79 -0
  560. package/src/modes/components/status-line/git-utils.ts +42 -0
  561. package/src/modes/components/status-line/index.ts +5 -0
  562. package/src/modes/components/status-line/presets.ts +106 -0
  563. package/src/modes/components/status-line/segments.ts +584 -0
  564. package/src/modes/components/status-line/separators.ts +55 -0
  565. package/src/modes/components/status-line/token-rate.ts +66 -0
  566. package/src/modes/components/status-line/types.ts +108 -0
  567. package/src/modes/components/theme-selector.ts +63 -0
  568. package/src/modes/components/thinking-selector.ts +52 -0
  569. package/src/modes/components/tiny-title-download-progress.ts +90 -0
  570. package/src/modes/components/tips.txt +19 -0
  571. package/src/modes/components/todo-reminder.ts +38 -0
  572. package/src/modes/components/tool-execution.ts +1024 -0
  573. package/src/modes/components/transcript-container.ts +608 -0
  574. package/src/modes/components/tree-selector.ts +978 -0
  575. package/src/modes/components/ttsr-notification.ts +122 -0
  576. package/src/modes/components/user-message-selector.ts +227 -0
  577. package/src/modes/components/user-message.ts +66 -0
  578. package/src/modes/components/visual-truncate.ts +63 -0
  579. package/src/modes/components/welcome.ts +493 -0
  580. package/src/modes/controllers/btw-controller.ts +105 -0
  581. package/src/modes/controllers/command-controller-shared.ts +109 -0
  582. package/src/modes/controllers/command-controller.ts +1566 -0
  583. package/src/modes/controllers/event-controller.ts +1054 -0
  584. package/src/modes/controllers/extension-ui-controller.ts +886 -0
  585. package/src/modes/controllers/input-controller.ts +1073 -0
  586. package/src/modes/controllers/mcp-command-controller.ts +2017 -0
  587. package/src/modes/controllers/omfg-controller.ts +283 -0
  588. package/src/modes/controllers/omfg-rule.ts +647 -0
  589. package/src/modes/controllers/selector-controller.ts +1108 -0
  590. package/src/modes/controllers/ssh-command-controller.ts +384 -0
  591. package/src/modes/controllers/streaming-reveal.ts +279 -0
  592. package/src/modes/controllers/tan-command-controller.ts +173 -0
  593. package/src/modes/controllers/todo-command-controller.ts +485 -0
  594. package/src/modes/data/emojis.json +1 -0
  595. package/src/modes/emoji-autocomplete.ts +285 -0
  596. package/src/modes/gradient-highlight.ts +87 -0
  597. package/src/modes/image-references.ts +117 -0
  598. package/src/modes/index.ts +17 -0
  599. package/src/modes/interactive-mode.ts +3370 -0
  600. package/src/modes/internal-url-autocomplete.ts +143 -0
  601. package/src/modes/loop-limit.ts +140 -0
  602. package/src/modes/magic-keywords.ts +20 -0
  603. package/src/modes/markdown-prose.ts +247 -0
  604. package/src/modes/oauth-manual-input.ts +69 -0
  605. package/src/modes/orchestrate.ts +42 -0
  606. package/src/modes/print-mode.ts +126 -0
  607. package/src/modes/prompt-action-autocomplete.ts +260 -0
  608. package/src/modes/rpc/host-tools.ts +186 -0
  609. package/src/modes/rpc/host-uris.ts +235 -0
  610. package/src/modes/rpc/rpc-client.ts +963 -0
  611. package/src/modes/rpc/rpc-mode.ts +947 -0
  612. package/src/modes/rpc/rpc-subagents.ts +265 -0
  613. package/src/modes/rpc/rpc-types.ts +458 -0
  614. package/src/modes/runtime-init.ts +116 -0
  615. package/src/modes/session-observer-registry.ts +146 -0
  616. package/src/modes/setup-version.ts +11 -0
  617. package/src/modes/setup-wizard/index.ts +99 -0
  618. package/src/modes/setup-wizard/lazy.ts +16 -0
  619. package/src/modes/setup-wizard/scenes/glyph.ts +96 -0
  620. package/src/modes/setup-wizard/scenes/outro.ts +35 -0
  621. package/src/modes/setup-wizard/scenes/providers.ts +69 -0
  622. package/src/modes/setup-wizard/scenes/sign-in.ts +205 -0
  623. package/src/modes/setup-wizard/scenes/splash.ts +201 -0
  624. package/src/modes/setup-wizard/scenes/theme.ts +299 -0
  625. package/src/modes/setup-wizard/scenes/types.ts +48 -0
  626. package/src/modes/setup-wizard/scenes/web-search.ts +129 -0
  627. package/src/modes/setup-wizard/wizard-overlay.ts +275 -0
  628. package/src/modes/shared.ts +47 -0
  629. package/src/modes/theme/dark.json +95 -0
  630. package/src/modes/theme/defaults/alabaster.json +93 -0
  631. package/src/modes/theme/defaults/amethyst.json +96 -0
  632. package/src/modes/theme/defaults/anthracite.json +93 -0
  633. package/src/modes/theme/defaults/basalt.json +91 -0
  634. package/src/modes/theme/defaults/birch.json +95 -0
  635. package/src/modes/theme/defaults/dark-abyss.json +91 -0
  636. package/src/modes/theme/defaults/dark-arctic.json +104 -0
  637. package/src/modes/theme/defaults/dark-aurora.json +95 -0
  638. package/src/modes/theme/defaults/dark-catppuccin.json +107 -0
  639. package/src/modes/theme/defaults/dark-cavern.json +91 -0
  640. package/src/modes/theme/defaults/dark-copper.json +95 -0
  641. package/src/modes/theme/defaults/dark-cosmos.json +90 -0
  642. package/src/modes/theme/defaults/dark-cyberpunk.json +102 -0
  643. package/src/modes/theme/defaults/dark-dracula.json +98 -0
  644. package/src/modes/theme/defaults/dark-eclipse.json +91 -0
  645. package/src/modes/theme/defaults/dark-ember.json +95 -0
  646. package/src/modes/theme/defaults/dark-equinox.json +90 -0
  647. package/src/modes/theme/defaults/dark-forest.json +96 -0
  648. package/src/modes/theme/defaults/dark-github.json +105 -0
  649. package/src/modes/theme/defaults/dark-gruvbox.json +112 -0
  650. package/src/modes/theme/defaults/dark-lavender.json +95 -0
  651. package/src/modes/theme/defaults/dark-lunar.json +89 -0
  652. package/src/modes/theme/defaults/dark-midnight.json +95 -0
  653. package/src/modes/theme/defaults/dark-monochrome.json +94 -0
  654. package/src/modes/theme/defaults/dark-monokai.json +98 -0
  655. package/src/modes/theme/defaults/dark-nebula.json +90 -0
  656. package/src/modes/theme/defaults/dark-nord.json +97 -0
  657. package/src/modes/theme/defaults/dark-ocean.json +101 -0
  658. package/src/modes/theme/defaults/dark-one.json +100 -0
  659. package/src/modes/theme/defaults/dark-poimandres.json +142 -0
  660. package/src/modes/theme/defaults/dark-rainforest.json +91 -0
  661. package/src/modes/theme/defaults/dark-reef.json +91 -0
  662. package/src/modes/theme/defaults/dark-retro.json +92 -0
  663. package/src/modes/theme/defaults/dark-rose-pine.json +96 -0
  664. package/src/modes/theme/defaults/dark-sakura.json +95 -0
  665. package/src/modes/theme/defaults/dark-slate.json +95 -0
  666. package/src/modes/theme/defaults/dark-solarized.json +97 -0
  667. package/src/modes/theme/defaults/dark-solstice.json +90 -0
  668. package/src/modes/theme/defaults/dark-starfall.json +91 -0
  669. package/src/modes/theme/defaults/dark-sunset.json +99 -0
  670. package/src/modes/theme/defaults/dark-swamp.json +90 -0
  671. package/src/modes/theme/defaults/dark-synthwave.json +103 -0
  672. package/src/modes/theme/defaults/dark-taiga.json +91 -0
  673. package/src/modes/theme/defaults/dark-terminal.json +95 -0
  674. package/src/modes/theme/defaults/dark-tokyo-night.json +101 -0
  675. package/src/modes/theme/defaults/dark-tundra.json +91 -0
  676. package/src/modes/theme/defaults/dark-twilight.json +91 -0
  677. package/src/modes/theme/defaults/dark-volcanic.json +91 -0
  678. package/src/modes/theme/defaults/graphite.json +92 -0
  679. package/src/modes/theme/defaults/index.ts +199 -0
  680. package/src/modes/theme/defaults/light-arctic.json +107 -0
  681. package/src/modes/theme/defaults/light-aurora-day.json +91 -0
  682. package/src/modes/theme/defaults/light-canyon.json +91 -0
  683. package/src/modes/theme/defaults/light-catppuccin.json +106 -0
  684. package/src/modes/theme/defaults/light-cirrus.json +90 -0
  685. package/src/modes/theme/defaults/light-coral.json +95 -0
  686. package/src/modes/theme/defaults/light-cyberpunk.json +96 -0
  687. package/src/modes/theme/defaults/light-dawn.json +90 -0
  688. package/src/modes/theme/defaults/light-dunes.json +91 -0
  689. package/src/modes/theme/defaults/light-eucalyptus.json +95 -0
  690. package/src/modes/theme/defaults/light-forest.json +100 -0
  691. package/src/modes/theme/defaults/light-frost.json +95 -0
  692. package/src/modes/theme/defaults/light-github.json +115 -0
  693. package/src/modes/theme/defaults/light-glacier.json +91 -0
  694. package/src/modes/theme/defaults/light-gruvbox.json +108 -0
  695. package/src/modes/theme/defaults/light-haze.json +90 -0
  696. package/src/modes/theme/defaults/light-honeycomb.json +95 -0
  697. package/src/modes/theme/defaults/light-lagoon.json +91 -0
  698. package/src/modes/theme/defaults/light-lavender.json +95 -0
  699. package/src/modes/theme/defaults/light-meadow.json +91 -0
  700. package/src/modes/theme/defaults/light-mint.json +95 -0
  701. package/src/modes/theme/defaults/light-monochrome.json +101 -0
  702. package/src/modes/theme/defaults/light-ocean.json +99 -0
  703. package/src/modes/theme/defaults/light-one.json +99 -0
  704. package/src/modes/theme/defaults/light-opal.json +91 -0
  705. package/src/modes/theme/defaults/light-orchard.json +91 -0
  706. package/src/modes/theme/defaults/light-paper.json +95 -0
  707. package/src/modes/theme/defaults/light-poimandres.json +142 -0
  708. package/src/modes/theme/defaults/light-prism.json +90 -0
  709. package/src/modes/theme/defaults/light-retro.json +98 -0
  710. package/src/modes/theme/defaults/light-sand.json +95 -0
  711. package/src/modes/theme/defaults/light-savanna.json +91 -0
  712. package/src/modes/theme/defaults/light-solarized.json +102 -0
  713. package/src/modes/theme/defaults/light-soleil.json +90 -0
  714. package/src/modes/theme/defaults/light-sunset.json +99 -0
  715. package/src/modes/theme/defaults/light-synthwave.json +98 -0
  716. package/src/modes/theme/defaults/light-tokyo-night.json +111 -0
  717. package/src/modes/theme/defaults/light-wetland.json +91 -0
  718. package/src/modes/theme/defaults/light-zenith.json +89 -0
  719. package/src/modes/theme/defaults/limestone.json +94 -0
  720. package/src/modes/theme/defaults/mahogany.json +97 -0
  721. package/src/modes/theme/defaults/marble.json +93 -0
  722. package/src/modes/theme/defaults/obsidian.json +91 -0
  723. package/src/modes/theme/defaults/onyx.json +91 -0
  724. package/src/modes/theme/defaults/pearl.json +93 -0
  725. package/src/modes/theme/defaults/porcelain.json +91 -0
  726. package/src/modes/theme/defaults/quartz.json +96 -0
  727. package/src/modes/theme/defaults/sandstone.json +95 -0
  728. package/src/modes/theme/defaults/titanium.json +90 -0
  729. package/src/modes/theme/light.json +93 -0
  730. package/src/modes/theme/mermaid-cache.ts +29 -0
  731. package/src/modes/theme/shimmer.ts +235 -0
  732. package/src/modes/theme/theme-schema.json +459 -0
  733. package/src/modes/theme/theme.ts +2676 -0
  734. package/src/modes/turn-budget.ts +31 -0
  735. package/src/modes/types.ts +359 -0
  736. package/src/modes/ultrathink.ts +41 -0
  737. package/src/modes/utils/context-usage.ts +339 -0
  738. package/src/modes/utils/copy-targets.ts +360 -0
  739. package/src/modes/utils/hotkeys-markdown.ts +61 -0
  740. package/src/modes/utils/keybinding-matchers.ts +51 -0
  741. package/src/modes/utils/tools-markdown.ts +27 -0
  742. package/src/modes/utils/ui-helpers.ts +801 -0
  743. package/src/modes/workflow.ts +42 -0
  744. package/src/plan-mode/approved-plan.ts +186 -0
  745. package/src/plan-mode/plan-handoff.ts +37 -0
  746. package/src/plan-mode/plan-protection.ts +31 -0
  747. package/src/plan-mode/state.ts +6 -0
  748. package/src/priority.json +41 -0
  749. package/src/prompts/agents/designer.md +66 -0
  750. package/src/prompts/agents/explore.md +58 -0
  751. package/src/prompts/agents/frontmatter.md +11 -0
  752. package/src/prompts/agents/init.md +33 -0
  753. package/src/prompts/agents/librarian.md +119 -0
  754. package/src/prompts/agents/oracle.md +55 -0
  755. package/src/prompts/agents/plan.md +48 -0
  756. package/src/prompts/agents/reviewer.md +140 -0
  757. package/src/prompts/agents/task.md +16 -0
  758. package/src/prompts/ci-green-request.md +36 -0
  759. package/src/prompts/dry-balance-bench.md +8 -0
  760. package/src/prompts/goals/goal-budget-limit.md +16 -0
  761. package/src/prompts/goals/goal-continuation.md +28 -0
  762. package/src/prompts/goals/goal-mode-active.md +23 -0
  763. package/src/prompts/memories/consolidation.md +30 -0
  764. package/src/prompts/memories/read-path.md +11 -0
  765. package/src/prompts/memories/stage_one_input.md +6 -0
  766. package/src/prompts/memories/stage_one_system.md +21 -0
  767. package/src/prompts/review-custom-request.md +22 -0
  768. package/src/prompts/review-headless-request.md +16 -0
  769. package/src/prompts/review-request.md +69 -0
  770. package/src/prompts/steering/user-interjection.md +10 -0
  771. package/src/prompts/system/agent-creation-architect.md +50 -0
  772. package/src/prompts/system/agent-creation-user.md +6 -0
  773. package/src/prompts/system/auto-continue.md +1 -0
  774. package/src/prompts/system/auto-thinking-difficulty-local.md +14 -0
  775. package/src/prompts/system/auto-thinking-difficulty.md +12 -0
  776. package/src/prompts/system/background-tan-dispatch.md +8 -0
  777. package/src/prompts/system/btw-user.md +8 -0
  778. package/src/prompts/system/commit-message-system.md +14 -0
  779. package/src/prompts/system/custom-system-prompt.md +64 -0
  780. package/src/prompts/system/eager-todo.md +13 -0
  781. package/src/prompts/system/empty-stop-retry.md +6 -0
  782. package/src/prompts/system/irc-incoming.md +7 -0
  783. package/src/prompts/system/manual-continue.md +7 -0
  784. package/src/prompts/system/memory-consolidation-system.md +8 -0
  785. package/src/prompts/system/memory-extraction-system.md +26 -0
  786. package/src/prompts/system/omfg-user.md +50 -0
  787. package/src/prompts/system/orchestrate-notice.md +40 -0
  788. package/src/prompts/system/plan-mode-active.md +109 -0
  789. package/src/prompts/system/plan-mode-approved.md +25 -0
  790. package/src/prompts/system/plan-mode-compact-instructions.md +16 -0
  791. package/src/prompts/system/plan-mode-reference.md +11 -0
  792. package/src/prompts/system/plan-mode-subagent.md +33 -0
  793. package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
  794. package/src/prompts/system/project-prompt.md +52 -0
  795. package/src/prompts/system/subagent-system-prompt.md +64 -0
  796. package/src/prompts/system/subagent-user-prompt.md +3 -0
  797. package/src/prompts/system/subagent-yield-reminder.md +12 -0
  798. package/src/prompts/system/system-prompt.md +258 -0
  799. package/src/prompts/system/tiny-title-system.md +8 -0
  800. package/src/prompts/system/title-system.md +16 -0
  801. package/src/prompts/system/ttsr-interrupt.md +7 -0
  802. package/src/prompts/system/ttsr-tool-reminder.md +5 -0
  803. package/src/prompts/system/ultrathink-notice.md +3 -0
  804. package/src/prompts/system/web-search.md +25 -0
  805. package/src/prompts/system/workflow-notice.md +70 -0
  806. package/src/prompts/tools/apply-patch.md +65 -0
  807. package/src/prompts/tools/ask.md +30 -0
  808. package/src/prompts/tools/ast-edit.md +39 -0
  809. package/src/prompts/tools/ast-grep.md +42 -0
  810. package/src/prompts/tools/async-result.md +8 -0
  811. package/src/prompts/tools/bash.md +46 -0
  812. package/src/prompts/tools/browser.md +73 -0
  813. package/src/prompts/tools/checkpoint.md +16 -0
  814. package/src/prompts/tools/debug.md +34 -0
  815. package/src/prompts/tools/eval.md +92 -0
  816. package/src/prompts/tools/find.md +36 -0
  817. package/src/prompts/tools/github.md +21 -0
  818. package/src/prompts/tools/goal.md +18 -0
  819. package/src/prompts/tools/image-gen.md +7 -0
  820. package/src/prompts/tools/inspect-image-system.md +20 -0
  821. package/src/prompts/tools/inspect-image.md +32 -0
  822. package/src/prompts/tools/irc.md +59 -0
  823. package/src/prompts/tools/job.md +19 -0
  824. package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
  825. package/src/prompts/tools/lsp.md +42 -0
  826. package/src/prompts/tools/memory-edit.md +8 -0
  827. package/src/prompts/tools/patch.md +70 -0
  828. package/src/prompts/tools/read.md +84 -0
  829. package/src/prompts/tools/recall.md +5 -0
  830. package/src/prompts/tools/reflect.md +5 -0
  831. package/src/prompts/tools/render-mermaid.md +9 -0
  832. package/src/prompts/tools/replace.md +30 -0
  833. package/src/prompts/tools/resolve.md +9 -0
  834. package/src/prompts/tools/retain.md +6 -0
  835. package/src/prompts/tools/rewind.md +13 -0
  836. package/src/prompts/tools/search-tool-bm25.md +32 -0
  837. package/src/prompts/tools/search.md +24 -0
  838. package/src/prompts/tools/ssh.md +31 -0
  839. package/src/prompts/tools/task-summary.md +17 -0
  840. package/src/prompts/tools/task.md +88 -0
  841. package/src/prompts/tools/todo.md +62 -0
  842. package/src/prompts/tools/web-search.md +10 -0
  843. package/src/prompts/tools/write.md +14 -0
  844. package/src/registry/agent-lifecycle.ts +218 -0
  845. package/src/registry/agent-registry.ts +151 -0
  846. package/src/sdk.ts +2558 -0
  847. package/src/secrets/index.ts +123 -0
  848. package/src/secrets/obfuscator.ts +298 -0
  849. package/src/secrets/regex.ts +21 -0
  850. package/src/session/agent-session.ts +10121 -0
  851. package/src/session/agent-storage.ts +455 -0
  852. package/src/session/artifacts.ts +135 -0
  853. package/src/session/auth-broker-config.ts +131 -0
  854. package/src/session/auth-storage.ts +29 -0
  855. package/src/session/blob-store.ts +255 -0
  856. package/src/session/client-bridge.ts +85 -0
  857. package/src/session/history-storage.ts +348 -0
  858. package/src/session/indexed-session-storage.ts +430 -0
  859. package/src/session/messages.ts +541 -0
  860. package/src/session/redis-session-storage.ts +170 -0
  861. package/src/session/session-dump-format.ts +209 -0
  862. package/src/session/session-history-format.ts +246 -0
  863. package/src/session/session-manager.ts +3676 -0
  864. package/src/session/session-storage.ts +529 -0
  865. package/src/session/shake-types.ts +43 -0
  866. package/src/session/sql-session-storage.ts +314 -0
  867. package/src/session/streaming-output.ts +1330 -0
  868. package/src/session/tool-choice-queue.ts +213 -0
  869. package/src/session/yield-queue.ts +173 -0
  870. package/src/slash-commands/acp-builtins.ts +70 -0
  871. package/src/slash-commands/builtin-registry.ts +1798 -0
  872. package/src/slash-commands/helpers/context-report.ts +39 -0
  873. package/src/slash-commands/helpers/format.ts +46 -0
  874. package/src/slash-commands/helpers/marketplace-manager.ts +25 -0
  875. package/src/slash-commands/helpers/mcp.ts +532 -0
  876. package/src/slash-commands/helpers/parse.ts +85 -0
  877. package/src/slash-commands/helpers/ssh.ts +195 -0
  878. package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
  879. package/src/slash-commands/helpers/todo.ts +279 -0
  880. package/src/slash-commands/helpers/usage-report.ts +95 -0
  881. package/src/slash-commands/marketplace-install-parser.ts +99 -0
  882. package/src/slash-commands/types.ts +135 -0
  883. package/src/ssh/config-writer.ts +183 -0
  884. package/src/ssh/connection-manager.ts +509 -0
  885. package/src/ssh/ssh-executor.ts +189 -0
  886. package/src/ssh/sshfs-mount.ts +140 -0
  887. package/src/ssh/utils.ts +8 -0
  888. package/src/stt/downloader.ts +71 -0
  889. package/src/stt/index.ts +3 -0
  890. package/src/stt/recorder.ts +351 -0
  891. package/src/stt/setup.ts +52 -0
  892. package/src/stt/stt-controller.ts +160 -0
  893. package/src/stt/transcribe.py +70 -0
  894. package/src/stt/transcriber.ts +91 -0
  895. package/src/stubs/natives/index.ts +814 -0
  896. package/src/stubs/natives/package.json +7 -0
  897. package/src/stubs/tui/index.ts +282 -0
  898. package/src/stubs/tui/package.json +7 -0
  899. package/src/system-prompt.ts +611 -0
  900. package/src/task/agents.ts +167 -0
  901. package/src/task/commands.ts +132 -0
  902. package/src/task/discovery.ts +122 -0
  903. package/src/task/executor.ts +2133 -0
  904. package/src/task/index.ts +1419 -0
  905. package/src/task/name-generator.ts +1577 -0
  906. package/src/task/omp-command.ts +26 -0
  907. package/src/task/output-manager.ts +88 -0
  908. package/src/task/parallel.ts +116 -0
  909. package/src/task/render.ts +1381 -0
  910. package/src/task/repair-args.ts +129 -0
  911. package/src/task/subprocess-tool-registry.ts +88 -0
  912. package/src/task/types.ts +336 -0
  913. package/src/task/worktree.ts +514 -0
  914. package/src/telemetry-export.ts +144 -0
  915. package/src/thinking.ts +167 -0
  916. package/src/tiny/compiled-runtime.ts +179 -0
  917. package/src/tiny/device.ts +111 -0
  918. package/src/tiny/dtype.ts +101 -0
  919. package/src/tiny/models.ts +242 -0
  920. package/src/tiny/text.ts +165 -0
  921. package/src/tiny/title-client.ts +543 -0
  922. package/src/tiny/title-protocol.ts +56 -0
  923. package/src/tiny/worker.ts +568 -0
  924. package/src/tool-discovery/mode.ts +24 -0
  925. package/src/tool-discovery/tool-index.ts +256 -0
  926. package/src/tools/approval.ts +189 -0
  927. package/src/tools/archive-reader.ts +721 -0
  928. package/src/tools/ask.ts +928 -0
  929. package/src/tools/ast-edit.ts +642 -0
  930. package/src/tools/ast-grep.ts +452 -0
  931. package/src/tools/auto-generated-guard.ts +322 -0
  932. package/src/tools/bash-command-fixup.ts +37 -0
  933. package/src/tools/bash-interactive.ts +408 -0
  934. package/src/tools/bash-interceptor.ts +67 -0
  935. package/src/tools/bash-pty-selection.ts +14 -0
  936. package/src/tools/bash-skill-urls.ts +248 -0
  937. package/src/tools/bash.ts +1386 -0
  938. package/src/tools/browser/attach.ts +175 -0
  939. package/src/tools/browser/launch.ts +660 -0
  940. package/src/tools/browser/readable.ts +112 -0
  941. package/src/tools/browser/registry.ts +197 -0
  942. package/src/tools/browser/render.ts +216 -0
  943. package/src/tools/browser/tab-protocol.ts +105 -0
  944. package/src/tools/browser/tab-supervisor.ts +628 -0
  945. package/src/tools/browser/tab-worker-entry.ts +21 -0
  946. package/src/tools/browser/tab-worker.ts +1226 -0
  947. package/src/tools/browser.ts +343 -0
  948. package/src/tools/checkpoint.ts +136 -0
  949. package/src/tools/conflict-detect.ts +718 -0
  950. package/src/tools/context.ts +39 -0
  951. package/src/tools/debug.ts +1067 -0
  952. package/src/tools/eval-backends.ts +27 -0
  953. package/src/tools/eval-render.ts +752 -0
  954. package/src/tools/eval.ts +577 -0
  955. package/src/tools/fetch.ts +1926 -0
  956. package/src/tools/file-recorder.ts +35 -0
  957. package/src/tools/find.ts +609 -0
  958. package/src/tools/fs-cache-invalidation.ts +28 -0
  959. package/src/tools/gh-cache-invalidation.ts +255 -0
  960. package/src/tools/gh-format.ts +12 -0
  961. package/src/tools/gh-renderer.ts +481 -0
  962. package/src/tools/gh.ts +3720 -0
  963. package/src/tools/github-cache.ts +637 -0
  964. package/src/tools/grouped-file-output.ts +210 -0
  965. package/src/tools/image-gen.ts +1517 -0
  966. package/src/tools/index.ts +599 -0
  967. package/src/tools/inspect-image-renderer.ts +132 -0
  968. package/src/tools/inspect-image.ts +174 -0
  969. package/src/tools/irc.ts +723 -0
  970. package/src/tools/job.ts +557 -0
  971. package/src/tools/json-tree.ts +243 -0
  972. package/src/tools/jtd-to-json-schema.ts +219 -0
  973. package/src/tools/jtd-to-typescript.ts +136 -0
  974. package/src/tools/jtd-utils.ts +102 -0
  975. package/src/tools/list-limit.ts +40 -0
  976. package/src/tools/match-line-format.ts +20 -0
  977. package/src/tools/memory-edit.ts +59 -0
  978. package/src/tools/memory-recall.ts +100 -0
  979. package/src/tools/memory-reflect.ts +88 -0
  980. package/src/tools/memory-render.ts +202 -0
  981. package/src/tools/memory-retain.ts +91 -0
  982. package/src/tools/output-meta.ts +754 -0
  983. package/src/tools/output-schema-validator.ts +132 -0
  984. package/src/tools/path-utils.ts +1054 -0
  985. package/src/tools/plan-mode-guard.ts +108 -0
  986. package/src/tools/puppeteer/00_stealth_tampering.txt +63 -0
  987. package/src/tools/puppeteer/01_stealth_activity.txt +20 -0
  988. package/src/tools/puppeteer/02_stealth_hairline.txt +11 -0
  989. package/src/tools/puppeteer/03_stealth_botd.txt +384 -0
  990. package/src/tools/puppeteer/04_stealth_iframe.txt +81 -0
  991. package/src/tools/puppeteer/05_stealth_webgl.txt +75 -0
  992. package/src/tools/puppeteer/06_stealth_screen.txt +72 -0
  993. package/src/tools/puppeteer/07_stealth_fonts.txt +97 -0
  994. package/src/tools/puppeteer/08_stealth_audio.txt +51 -0
  995. package/src/tools/puppeteer/09_stealth_locale.txt +46 -0
  996. package/src/tools/puppeteer/10_stealth_plugins.txt +206 -0
  997. package/src/tools/puppeteer/11_stealth_hardware.txt +8 -0
  998. package/src/tools/puppeteer/12_stealth_codecs.txt +40 -0
  999. package/src/tools/puppeteer/13_stealth_worker.txt +74 -0
  1000. package/src/tools/read.ts +2929 -0
  1001. package/src/tools/render-mermaid.ts +69 -0
  1002. package/src/tools/render-utils.ts +838 -0
  1003. package/src/tools/renderers.ts +77 -0
  1004. package/src/tools/report-tool-issue.ts +534 -0
  1005. package/src/tools/resolve.ts +276 -0
  1006. package/src/tools/review.ts +253 -0
  1007. package/src/tools/search-tool-bm25.ts +351 -0
  1008. package/src/tools/search.ts +1580 -0
  1009. package/src/tools/sqlite-reader.ts +828 -0
  1010. package/src/tools/ssh.ts +349 -0
  1011. package/src/tools/todo.ts +982 -0
  1012. package/src/tools/tool-errors.ts +62 -0
  1013. package/src/tools/tool-result.ts +94 -0
  1014. package/src/tools/tool-timeouts.ts +30 -0
  1015. package/src/tools/tts.ts +133 -0
  1016. package/src/tools/write.ts +1217 -0
  1017. package/src/tools/yield.ts +269 -0
  1018. package/src/tui/code-cell.ts +216 -0
  1019. package/src/tui/file-list.ts +55 -0
  1020. package/src/tui/hyperlink.ts +175 -0
  1021. package/src/tui/index.ts +12 -0
  1022. package/src/tui/output-block.ts +240 -0
  1023. package/src/tui/status-line.ts +54 -0
  1024. package/src/tui/tree-list.ts +84 -0
  1025. package/src/tui/types.ts +15 -0
  1026. package/src/tui/utils.ts +103 -0
  1027. package/src/utils/block-context.ts +312 -0
  1028. package/src/utils/changelog.ts +132 -0
  1029. package/src/utils/clipboard.ts +193 -0
  1030. package/src/utils/command-args.ts +76 -0
  1031. package/src/utils/commit-message-generator.ts +151 -0
  1032. package/src/utils/edit-mode.ts +41 -0
  1033. package/src/utils/enhanced-paste.ts +230 -0
  1034. package/src/utils/event-bus.ts +33 -0
  1035. package/src/utils/external-editor.ts +65 -0
  1036. package/src/utils/file-display-mode.ts +45 -0
  1037. package/src/utils/file-mentions.ts +281 -0
  1038. package/src/utils/git.ts +1833 -0
  1039. package/src/utils/image-loading.ts +132 -0
  1040. package/src/utils/image-resize.ts +309 -0
  1041. package/src/utils/jj.ts +248 -0
  1042. package/src/utils/lang-from-path.ts +239 -0
  1043. package/src/utils/markit.ts +89 -0
  1044. package/src/utils/open.ts +55 -0
  1045. package/src/utils/session-color.ts +68 -0
  1046. package/src/utils/shell-snapshot.ts +187 -0
  1047. package/src/utils/sixel.ts +69 -0
  1048. package/src/utils/title-generator.ts +373 -0
  1049. package/src/utils/tool-choice.ts +33 -0
  1050. package/src/utils/tools-manager.ts +363 -0
  1051. package/src/web/kagi.ts +305 -0
  1052. package/src/web/parallel.ts +353 -0
  1053. package/src/web/scrapers/artifacthub.ts +207 -0
  1054. package/src/web/scrapers/arxiv.ts +83 -0
  1055. package/src/web/scrapers/aur.ts +162 -0
  1056. package/src/web/scrapers/biorxiv.ts +133 -0
  1057. package/src/web/scrapers/bluesky.ts +262 -0
  1058. package/src/web/scrapers/brew.ts +172 -0
  1059. package/src/web/scrapers/cheatsh.ts +68 -0
  1060. package/src/web/scrapers/chocolatey.ts +196 -0
  1061. package/src/web/scrapers/choosealicense.ts +95 -0
  1062. package/src/web/scrapers/cisa-kev.ts +87 -0
  1063. package/src/web/scrapers/clojars.ts +154 -0
  1064. package/src/web/scrapers/coingecko.ts +177 -0
  1065. package/src/web/scrapers/crates-io.ts +97 -0
  1066. package/src/web/scrapers/crossref.ts +136 -0
  1067. package/src/web/scrapers/devto.ts +147 -0
  1068. package/src/web/scrapers/discogs.ts +306 -0
  1069. package/src/web/scrapers/discourse.ts +197 -0
  1070. package/src/web/scrapers/dockerhub.ts +138 -0
  1071. package/src/web/scrapers/docs-rs.ts +653 -0
  1072. package/src/web/scrapers/fdroid.ts +134 -0
  1073. package/src/web/scrapers/firefox-addons.ts +191 -0
  1074. package/src/web/scrapers/flathub.ts +223 -0
  1075. package/src/web/scrapers/github-gist.ts +58 -0
  1076. package/src/web/scrapers/github.ts +704 -0
  1077. package/src/web/scrapers/gitlab.ts +401 -0
  1078. package/src/web/scrapers/go-pkg.ts +266 -0
  1079. package/src/web/scrapers/hackage.ts +140 -0
  1080. package/src/web/scrapers/hackernews.ts +189 -0
  1081. package/src/web/scrapers/hex.ts +105 -0
  1082. package/src/web/scrapers/huggingface.ts +321 -0
  1083. package/src/web/scrapers/iacr.ts +89 -0
  1084. package/src/web/scrapers/index.ts +252 -0
  1085. package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
  1086. package/src/web/scrapers/lemmy.ts +203 -0
  1087. package/src/web/scrapers/lobsters.ts +175 -0
  1088. package/src/web/scrapers/mastodon.ts +292 -0
  1089. package/src/web/scrapers/maven.ts +138 -0
  1090. package/src/web/scrapers/mdn.ts +173 -0
  1091. package/src/web/scrapers/metacpan.ts +222 -0
  1092. package/src/web/scrapers/musicbrainz.ts +250 -0
  1093. package/src/web/scrapers/npm.ts +98 -0
  1094. package/src/web/scrapers/nuget.ts +183 -0
  1095. package/src/web/scrapers/nvd.ts +222 -0
  1096. package/src/web/scrapers/ollama.ts +239 -0
  1097. package/src/web/scrapers/open-vsx.ts +106 -0
  1098. package/src/web/scrapers/opencorporates.ts +292 -0
  1099. package/src/web/scrapers/openlibrary.ts +336 -0
  1100. package/src/web/scrapers/orcid.ts +286 -0
  1101. package/src/web/scrapers/osv.ts +176 -0
  1102. package/src/web/scrapers/packagist.ts +160 -0
  1103. package/src/web/scrapers/pub-dev.ts +143 -0
  1104. package/src/web/scrapers/pubmed.ts +211 -0
  1105. package/src/web/scrapers/pypi.ts +112 -0
  1106. package/src/web/scrapers/rawg.ts +110 -0
  1107. package/src/web/scrapers/readthedocs.ts +120 -0
  1108. package/src/web/scrapers/reddit.ts +95 -0
  1109. package/src/web/scrapers/repology.ts +251 -0
  1110. package/src/web/scrapers/rfc.ts +201 -0
  1111. package/src/web/scrapers/rubygems.ts +103 -0
  1112. package/src/web/scrapers/searchcode.ts +189 -0
  1113. package/src/web/scrapers/sec-edgar.ts +261 -0
  1114. package/src/web/scrapers/semantic-scholar.ts +171 -0
  1115. package/src/web/scrapers/snapcraft.ts +187 -0
  1116. package/src/web/scrapers/sourcegraph.ts +336 -0
  1117. package/src/web/scrapers/spdx.ts +108 -0
  1118. package/src/web/scrapers/spotify.ts +198 -0
  1119. package/src/web/scrapers/stackoverflow.ts +120 -0
  1120. package/src/web/scrapers/terraform.ts +277 -0
  1121. package/src/web/scrapers/tldr.ts +47 -0
  1122. package/src/web/scrapers/twitter.ts +94 -0
  1123. package/src/web/scrapers/types.ts +397 -0
  1124. package/src/web/scrapers/utils.ts +109 -0
  1125. package/src/web/scrapers/vimeo.ts +133 -0
  1126. package/src/web/scrapers/vscode-marketplace.ts +187 -0
  1127. package/src/web/scrapers/w3c.ts +156 -0
  1128. package/src/web/scrapers/wikidata.ts +344 -0
  1129. package/src/web/scrapers/wikipedia.ts +84 -0
  1130. package/src/web/scrapers/youtube.ts +325 -0
  1131. package/src/web/search/index.ts +292 -0
  1132. package/src/web/search/provider.ts +157 -0
  1133. package/src/web/search/providers/anthropic.ts +318 -0
  1134. package/src/web/search/providers/base.ts +89 -0
  1135. package/src/web/search/providers/brave.ts +152 -0
  1136. package/src/web/search/providers/codex.ts +591 -0
  1137. package/src/web/search/providers/exa.ts +400 -0
  1138. package/src/web/search/providers/gemini.ts +460 -0
  1139. package/src/web/search/providers/jina.ts +111 -0
  1140. package/src/web/search/providers/kagi.ts +86 -0
  1141. package/src/web/search/providers/kimi.ts +196 -0
  1142. package/src/web/search/providers/parallel.ts +225 -0
  1143. package/src/web/search/providers/perplexity.ts +730 -0
  1144. package/src/web/search/providers/searxng.ts +313 -0
  1145. package/src/web/search/providers/synthetic.ts +114 -0
  1146. package/src/web/search/providers/tavily.ts +176 -0
  1147. package/src/web/search/providers/utils.ts +128 -0
  1148. package/src/web/search/providers/zai.ts +333 -0
  1149. package/src/web/search/render.ts +262 -0
  1150. package/src/web/search/types.ts +482 -0
  1151. package/src/web/search/utils.ts +17 -0
  1152. package/src/workspace-tree.ts +286 -0
@@ -0,0 +1,1024 @@
1
+ import type { SnapshotStore } from "@oh-my-pi/hashline";
2
+ import type { AgentTool } from "@oh-my-pi/pi-agent-core";
3
+ import {
4
+ Box,
5
+ type Component,
6
+ Container,
7
+ getImageDimensions,
8
+ Image,
9
+ ImageProtocol,
10
+ imageFallback,
11
+ Spacer,
12
+ TERMINAL,
13
+ Text,
14
+ type TUI,
15
+ } from './stubs/tui/index.ts';
16
+ import { getProjectDir, logger, sanitizeText } from "@oh-my-pi/pi-utils";
17
+ import { EDIT_MODE_STRATEGIES, type EditMode, type PerFileDiffPreview } from "../../edit";
18
+ import type { Theme } from "../../modes/theme/theme";
19
+ import { theme } from "../../modes/theme/theme";
20
+ import { BASH_DEFAULT_PREVIEW_LINES } from "../../tools/bash";
21
+ import { EVAL_DEFAULT_PREVIEW_LINES } from "../../tools/eval";
22
+ import { isWaitingPollDetails } from "../../tools/job";
23
+ import {
24
+ formatArgsInline,
25
+ JSON_TREE_MAX_DEPTH_COLLAPSED,
26
+ JSON_TREE_MAX_DEPTH_EXPANDED,
27
+ JSON_TREE_MAX_LINES_COLLAPSED,
28
+ JSON_TREE_MAX_LINES_EXPANDED,
29
+ JSON_TREE_SCALAR_LEN_COLLAPSED,
30
+ JSON_TREE_SCALAR_LEN_EXPANDED,
31
+ renderJsonTreeLines,
32
+ } from "../../tools/json-tree";
33
+ import { formatExpandHint, replaceTabs, resolveImageOptions, truncateToWidth } from "../../tools/render-utils";
34
+ import { toolRenderers } from "../../tools/renderers";
35
+ import { TODO_STRIKE_TOTAL_FRAMES } from "../../tools/todo";
36
+ import { isFramedBlockComponent, renderStatusLine } from "../../tui";
37
+ import { sanitizeWithOptionalSixelPassthrough } from "../../utils/sixel";
38
+ import { renderDiff } from "./diff";
39
+
40
+ /**
41
+ * Drop trailing removal/hunk-header lines that appear in a streaming diff
42
+ * before the matching `+added` lines have arrived. Without this, a partial
43
+ * apply_patch / hashline preview shows `-old` first and then visibly grows
44
+ * the `+new` block beneath it — the "removals first, additions catching up"
45
+ * jitter. Once the next streaming tick brings the additions in, the trailing
46
+ * block reappears alongside them.
47
+ */
48
+ function stripTrailingUnbalancedRemoval(diff: string | undefined): string | undefined {
49
+ if (!diff) return diff;
50
+ const lines = diff.split("\n");
51
+ let lastAddIdx = -1;
52
+ for (let i = lines.length - 1; i >= 0; i--) {
53
+ if (lines[i].startsWith("+")) {
54
+ lastAddIdx = i;
55
+ break;
56
+ }
57
+ }
58
+ let hasTrailingUnbalanced = false;
59
+ for (let i = lastAddIdx + 1; i < lines.length; i++) {
60
+ const line = lines[i];
61
+ if (line.startsWith("-") || line.startsWith("@@")) {
62
+ hasTrailingUnbalanced = true;
63
+ break;
64
+ }
65
+ }
66
+ if (!hasTrailingUnbalanced) return diff;
67
+ if (lastAddIdx === -1) return "";
68
+ return lines.slice(0, lastAddIdx + 1).join("\n");
69
+ }
70
+
71
+ function stabilizeStreamingPreviews(previews: PerFileDiffPreview[]): PerFileDiffPreview[] {
72
+ let changed = false;
73
+ const next = previews.map(preview => {
74
+ if (!preview.diff) return preview;
75
+ const trimmed = stripTrailingUnbalancedRemoval(preview.diff);
76
+ if (trimmed === preview.diff) return preview;
77
+ changed = true;
78
+ return { ...preview, diff: trimmed ?? "" };
79
+ });
80
+ return changed ? next : previews;
81
+ }
82
+
83
+ function isEditLikeToolName(toolName: string): boolean {
84
+ return toolName === "edit" || toolName === "apply_patch";
85
+ }
86
+
87
+ function resolveEditModeForTool(toolName: string, tool: AgentTool | undefined): EditMode | undefined {
88
+ if (toolName === "apply_patch") return "apply_patch";
89
+ if (toolName !== "edit") return undefined;
90
+ return (tool as { mode?: EditMode } | undefined)?.mode;
91
+ }
92
+
93
+ function rawTextInputFromPartialJson(partialJson: unknown): string | undefined {
94
+ if (typeof partialJson !== "string") return undefined;
95
+ if (partialJson.length === 0) return undefined;
96
+ const trimmed = partialJson.trimStart();
97
+ if (trimmed.length === 0) return undefined;
98
+ const first = trimmed[0];
99
+ // Function-tool arguments stream as JSON. Custom/free-form tools stream raw
100
+ // text in the same transport field; only the raw form is a valid fallback for
101
+ // the conventional `input` parameter.
102
+ if (first === "{" || first === '"') return undefined;
103
+ return partialJson;
104
+ }
105
+
106
+ function getArgsWithStreamedTextInput(args: unknown): unknown {
107
+ if (args == null || typeof args !== "object") return args;
108
+ const record = args as Record<string, unknown>;
109
+ if (typeof record.input === "string") return args;
110
+ const input = rawTextInputFromPartialJson(record.__partialJson);
111
+ return input === undefined ? args : { ...record, input };
112
+ }
113
+
114
+ export interface ToolExecutionOptions {
115
+ snapshots?: SnapshotStore;
116
+ showImages?: boolean; // default: true (only used if terminal supports images)
117
+ editFuzzyThreshold?: number;
118
+ editAllowFuzzy?: boolean;
119
+ }
120
+
121
+ export interface ToolExecutionHandle {
122
+ updateArgs(args: any, toolCallId?: string): void;
123
+ updateResult(
124
+ result: {
125
+ content: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;
126
+ details?: any;
127
+ isError?: boolean;
128
+ },
129
+ isPartial?: boolean,
130
+ toolCallId?: string,
131
+ ): void;
132
+ setArgsComplete(toolCallId?: string): void;
133
+ setExpanded(expanded: boolean): void;
134
+ }
135
+
136
+ /** Drive pending-tool redraws at 30fps so the running `task` row's shimmered
137
+ * subagent name stays smooth without spending twice the frame budget. The TUI
138
+ * throttles at the same cadence, and static frames diff to a no-op redraw at
139
+ * ~zero cost. */
140
+ const SPINNER_RENDER_INTERVAL_MS = 1000 / 30;
141
+ /** Advance the spinner glyph at its classic ~12.5fps step, decoupled from the
142
+ * render cadence (mirrors `Loader`). */
143
+ const SPINNER_GLYPH_ADVANCE_MS = 80;
144
+
145
+ // Stable per-instance counter so each tool execution's inline images get a
146
+ // graphics id that survives child re-creation (the image budget keys off it).
147
+ let toolExecutionInstanceSeq = 0;
148
+
149
+ /**
150
+ * Component that renders a tool call with its result (updateable)
151
+ */
152
+ export class ToolExecutionComponent extends Container {
153
+ #contentBox: Box; // Used for custom tools and bash visual truncation
154
+ #contentText: Text; // For built-in tools (with its own padding/bg)
155
+ #multiFileBoxes: (Box | Spacer)[] = []; // Extra boxes for multi-file edit results
156
+ #imageComponents: Image[] = [];
157
+ #imageSpacers: Spacer[] = [];
158
+ readonly #instanceId = ++toolExecutionInstanceSeq;
159
+ #toolName: string;
160
+ #toolLabel: string;
161
+ #args: any;
162
+ #expanded = false;
163
+ #showImages: boolean;
164
+ #editFuzzyThreshold: number | undefined;
165
+ #editAllowFuzzy: boolean | undefined;
166
+ #snapshots?: SnapshotStore;
167
+ #isPartial = true;
168
+ #tool?: AgentTool;
169
+ #ui: TUI;
170
+ #cwd: string;
171
+ #result?: {
172
+ content: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;
173
+ isError?: boolean;
174
+ details?: any;
175
+ };
176
+ // Edit preview state
177
+ #editMode?: EditMode;
178
+ #editDiffPreview?: PerFileDiffPreview[];
179
+ #editDiffAbort?: AbortController;
180
+ #editDiffLastArgsKey?: string;
181
+ // Latest in-flight streaming diff recompute, captured so it can be awaited.
182
+ #editDiffInFlight?: Promise<void>;
183
+ // Cached converted images for Kitty protocol (which requires PNG), keyed by index
184
+ #convertedImages: Map<number, { data: string; mimeType: string }> = new Map();
185
+ // Spinner animation for partial task results
186
+ #spinnerFrame?: number;
187
+ #spinnerInterval?: NodeJS.Timeout;
188
+ #lastSpinnerAdvanceAt = 0;
189
+ // Todo write completion strikethrough reveal animation
190
+ #todoStrikeInterval?: NodeJS.Timeout;
191
+ // Track if args are still being streamed (for edit/write spinner)
192
+ #argsComplete = false;
193
+ // Sealed once the tool reaches a terminal state (result delivered, or the
194
+ // turn abandoned it without one). Drives `isTranscriptBlockFinalized`: until
195
+ // sealed the block stays in the transcript's repaintable live region so a
196
+ // late result still repaints instead of stranding the streaming preview.
197
+ #sealed = false;
198
+ // A `job` poll result whose watched jobs are all still running. Such a
199
+ // block never finalizes (stays in the transcript live region) so a
200
+ // follow-up `job` call can displace it instead of stacking another
201
+ // "waiting on N jobs" frame. Cleared by `seal()`.
202
+ #displaceable = false;
203
+ #renderState: {
204
+ spinnerFrame?: number;
205
+ expanded: boolean;
206
+ isPartial: boolean;
207
+ renderContext?: Record<string, unknown>;
208
+ } = {
209
+ expanded: false,
210
+ isPartial: true,
211
+ };
212
+
213
+ constructor(
214
+ toolName: string,
215
+ args: any,
216
+ options: ToolExecutionOptions = {},
217
+ tool: AgentTool | undefined,
218
+ ui: TUI,
219
+ cwd: string = getProjectDir(),
220
+ _toolCallId?: string,
221
+ ) {
222
+ super();
223
+ this.#toolName = toolName;
224
+ this.#toolLabel = tool?.label ?? toolName;
225
+ this.#showImages = options.showImages ?? true;
226
+ this.#editFuzzyThreshold = options.editFuzzyThreshold;
227
+ this.#editAllowFuzzy = options.editAllowFuzzy;
228
+ this.#snapshots = options.snapshots;
229
+ this.#tool = tool;
230
+ this.#ui = ui;
231
+ this.#cwd = cwd;
232
+ this.#args = args;
233
+
234
+ // Always create both - contentBox for custom tools/bash/tools with renderers, contentText for other built-ins.
235
+ // paddingY is 1 so background-tinted blocks (custom/extension tools and the
236
+ // generic fallback) get top/bottom breathing room. TranscriptContainer
237
+ // strips PLAIN-blank edges, so framed/minimal blocks (no bg set) drop these
238
+ // lines and keep their tight spacing — only tinted lines survive.
239
+ this.#contentBox = new Box(0, 1);
240
+ this.#contentText = new Text("", 1, 1);
241
+
242
+ // Use Box for custom tools or built-in tools that have renderers
243
+ const hasRenderer = toolName in toolRenderers;
244
+ const hasCustomRenderer = !!(tool?.renderCall || tool?.renderResult);
245
+ if (hasCustomRenderer || hasRenderer) {
246
+ this.addChild(this.#contentBox);
247
+ } else {
248
+ this.addChild(this.#contentText);
249
+ }
250
+
251
+ this.#editMode = resolveEditModeForTool(toolName, tool);
252
+
253
+ this.#updateDisplay();
254
+ this.#editDiffInFlight = this.#runPreviewDiff();
255
+ }
256
+
257
+ updateArgs(args: any, _toolCallId?: string): void {
258
+ // Reference-equality short-circuit before any further work. Callers
259
+ // always allocate a new arg object on each streamed delta (see
260
+ // event-controller.ts and ui-helpers.ts), so a same-reference assignment
261
+ // signals "nothing meaningful changed" and the renderer can skip.
262
+ if (args === this.#args) return;
263
+ this.#args = args;
264
+ this.#updateSpinnerAnimation();
265
+ this.#editDiffInFlight = this.#runPreviewDiff();
266
+ this.#updateDisplay();
267
+ }
268
+
269
+ /**
270
+ * Signal that args are complete (tool is about to execute).
271
+ * This triggers an immediate final diff computation for edit-like tools.
272
+ */
273
+ setArgsComplete(_toolCallId?: string): void {
274
+ this.#argsComplete = true;
275
+ this.#updateSpinnerAnimation();
276
+ this.#editDiffInFlight = this.#runPreviewDiff();
277
+ }
278
+
279
+ /**
280
+ * Await the streaming diff recompute kicked off by the most recent
281
+ * `updateArgs`/`setArgsComplete`. The recompute reads the file and re-runs the
282
+ * whole-file Myers diff off the render path, signalling completion only via a
283
+ * throttled `requestRender`. Tests await this to sample a *settled* preview
284
+ * deterministically instead of racing the spinner's render ticks.
285
+ */
286
+ async whenPreviewSettled(): Promise<void> {
287
+ await this.#editDiffInFlight;
288
+ }
289
+
290
+ async #runPreviewDiff(): Promise<void> {
291
+ const editMode = this.#editMode;
292
+ if (!editMode) return;
293
+ const strategy = EDIT_MODE_STRATEGIES[editMode];
294
+ if (!strategy) return;
295
+
296
+ const args = this.#args;
297
+ if (args == null || typeof args !== "object") return;
298
+
299
+ const previewArgs = getArgsWithStreamedTextInput(args);
300
+ const partialJson = (previewArgs as { __partialJson?: string }).__partialJson;
301
+ let effectiveArgs: unknown;
302
+ try {
303
+ effectiveArgs = strategy.extractCompleteEdits(previewArgs, partialJson);
304
+ } catch {
305
+ effectiveArgs = previewArgs;
306
+ }
307
+
308
+ // Coalesce duplicate computes for identical args. The key pairs the
309
+ // streaming flag with a content hash: the final (args-complete) pass
310
+ // computes an untrimmed diff and must run even when the payload is
311
+ // byte-identical to the last streamed chunk — only `isStreaming` differs,
312
+ // and it flips the trailing-line trim. Without the flag a single-line edit
313
+ // whose trailing payload line never gets a newline stays stuck on the
314
+ // trimmed "no changes" streaming preview and renders no diff. Hashing keeps
315
+ // the retained key tiny instead of holding the whole serialized blob.
316
+ const streamingState = this.#argsComplete ? "final" : "stream";
317
+ let argsKey: string;
318
+ try {
319
+ argsKey = `${streamingState}:${Bun.hash(JSON.stringify(effectiveArgs))}`;
320
+ } catch {
321
+ // effectiveArgs isn't JSON-serializable (exotic value in tool args).
322
+ // The raw streamed JSON is a plain string, so hash that instead of a
323
+ // timestamp — a deterministic key keeps the dedup cache working
324
+ // instead of recomputing (and re-reading the file) on every render.
325
+ argsKey = `${streamingState}:partial:${Bun.hash(partialJson ?? "")}`;
326
+ }
327
+ if (argsKey === this.#editDiffLastArgsKey) return;
328
+ this.#editDiffLastArgsKey = argsKey;
329
+
330
+ this.#editDiffAbort?.abort();
331
+ const controller = new AbortController();
332
+ this.#editDiffAbort = controller;
333
+
334
+ try {
335
+ const isStreaming = !this.#argsComplete;
336
+ if (editMode === "hashline" && !this.#snapshots) return;
337
+ const previews = await strategy.computeDiffPreview(effectiveArgs, {
338
+ cwd: this.#cwd,
339
+ signal: controller.signal,
340
+ snapshots: this.#snapshots!,
341
+ fuzzyThreshold: this.#editFuzzyThreshold,
342
+ allowFuzzy: this.#editAllowFuzzy,
343
+ isStreaming,
344
+ });
345
+ if (controller.signal.aborted) return;
346
+ if (previews) {
347
+ this.#editDiffPreview = isStreaming ? stabilizeStreamingPreviews(previews) : previews;
348
+ this.#updateDisplay();
349
+ this.#ui.requestRender();
350
+ }
351
+ } catch (err) {
352
+ if (controller.signal.aborted) return;
353
+ logger.warn("Edit preview diff failed", { tool: this.#toolName, error: String(err) });
354
+ }
355
+ }
356
+
357
+ updateResult(
358
+ result: {
359
+ content: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;
360
+ details?: any;
361
+ isError?: boolean;
362
+ },
363
+ isPartial = false,
364
+ _toolCallId?: string,
365
+ ): void {
366
+ this.#result = result;
367
+ this.#isPartial = isPartial;
368
+ // A `job` poll that found every watched job still running is transient
369
+ // "still waiting" chrome; keep the block displaceable so the next `job`
370
+ // call replaces it instead of stacking another waiting frame (see the
371
+ // event controller's displaceable-poll bookkeeping).
372
+ this.#displaceable = this.#toolName === "job" && result.isError !== true && isWaitingPollDetails(result.details);
373
+ // When tool is complete, ensure args are marked complete so spinner stops
374
+ if (!isPartial) {
375
+ this.#argsComplete = true;
376
+ }
377
+ this.#updateSpinnerAnimation();
378
+ this.#updateTodoStrikeAnimation();
379
+ this.#updateDisplay();
380
+ // Convert non-PNG images to PNG for Kitty protocol (async)
381
+ this.#maybeConvertImagesForKitty();
382
+ }
383
+
384
+ /**
385
+ * Get all image blocks from result content and details.images.
386
+ * Some tools (like generate_image) store images in details to avoid bloating model context.
387
+ */
388
+ #getAllImageBlocks(): Array<{ data?: string; mimeType?: string }> {
389
+ if (!this.#result) return [];
390
+ const contentImages = this.#result.content?.filter((c: any) => c.type === "image") || [];
391
+ const detailImages = this.#result.details?.images || [];
392
+ return [...contentImages, ...detailImages];
393
+ }
394
+
395
+ /**
396
+ * Convert non-PNG images to PNG for Kitty graphics protocol.
397
+ * Kitty requires PNG format (f=100), so JPEG/GIF/WebP won't display.
398
+ */
399
+ #maybeConvertImagesForKitty(): void {
400
+ // Only needed for Kitty protocol
401
+ if (TERMINAL.imageProtocol !== ImageProtocol.Kitty) return;
402
+ if (!this.#result) return;
403
+
404
+ const imageBlocks = this.#getAllImageBlocks();
405
+
406
+ for (let i = 0; i < imageBlocks.length; i++) {
407
+ const img = imageBlocks[i];
408
+ if (!img.data || !img.mimeType) continue;
409
+ // Skip if already PNG or already converted
410
+ if (img.mimeType === "image/png") continue;
411
+ if (this.#convertedImages.has(i)) continue;
412
+
413
+ // Convert async - catch errors from processing
414
+ const index = i;
415
+ new Bun.Image(Buffer.from(img.data, "base64"))
416
+ .png()
417
+ .toBase64()
418
+ .then(data => {
419
+ this.#convertedImages.set(index, { data, mimeType: "image/png" });
420
+ this.#updateDisplay();
421
+ this.#ui.requestRender();
422
+ })
423
+ .catch(() => {
424
+ // Ignore conversion failures - display will use original image format
425
+ });
426
+ }
427
+ }
428
+
429
+ /**
430
+ * Start or stop spinner animation based on whether this is a partial task result.
431
+ */
432
+ #updateSpinnerAnimation(): void {
433
+ // Spinner for: task tool with partial result, or edit/write while args streaming
434
+ const isStreamingArgs = !this.#argsComplete && (isEditLikeToolName(this.#toolName) || this.#toolName === "write");
435
+ const isBackgroundAsyncRunning =
436
+ (this.#result?.details as { async?: { state?: string } } | undefined)?.async?.state === "running";
437
+ const isBackgroundAsyncTask = this.#toolName === "task" && isBackgroundAsyncRunning;
438
+ const isPartialTask = this.#isPartial && this.#toolName === "task" && !isBackgroundAsyncTask;
439
+ // A displaceable waiting poll keeps its spinner ticking: it reads as one
440
+ // persistent live poll, and the changing leading glyph keeps the
441
+ // transcript's stable-prefix ratchet from committing rows of a block
442
+ // that a follow-up `job` call may remove.
443
+ const needsSpinner = isStreamingArgs || isPartialTask || this.isDisplaceableBlock();
444
+ if (needsSpinner && !this.#spinnerInterval) {
445
+ const now = performance.now();
446
+ const frameCount = theme.spinnerFrames.length;
447
+ this.#lastSpinnerAdvanceAt = now;
448
+ if (frameCount > 0 && this.#spinnerFrame === undefined) {
449
+ this.#spinnerFrame = 0;
450
+ this.#renderState.spinnerFrame = 0;
451
+ }
452
+ this.#spinnerInterval = setInterval(() => {
453
+ const now = performance.now();
454
+ const frameCount = theme.spinnerFrames.length;
455
+ // Redraw at 30fps for a smooth `task` name shimmer, but keep the spinner
456
+ // glyph phase-locked to its classic ~12.5fps cadence. Advancing the
457
+ // anchor by elapsed frames instead of resetting to `now` avoids the
458
+ // 30fps timer quantizing the glyph down to one step every three ticks.
459
+ if (frameCount > 0) {
460
+ const elapsed = now - this.#lastSpinnerAdvanceAt;
461
+ if (elapsed >= SPINNER_GLYPH_ADVANCE_MS) {
462
+ const steps = Math.floor(elapsed / SPINNER_GLYPH_ADVANCE_MS);
463
+ this.#spinnerFrame = ((this.#spinnerFrame ?? 0) + steps) % frameCount;
464
+ this.#renderState.spinnerFrame = this.#spinnerFrame;
465
+ this.#lastSpinnerAdvanceAt += steps * SPINNER_GLYPH_ADVANCE_MS;
466
+ }
467
+ }
468
+ this.#ui.requestRender();
469
+ }, SPINNER_RENDER_INTERVAL_MS);
470
+ } else if (!needsSpinner && this.#spinnerInterval) {
471
+ clearInterval(this.#spinnerInterval);
472
+ this.#spinnerInterval = undefined;
473
+ // Clear the last drawn frame so a non-live renderCall (e.g. a write whose
474
+ // args just completed) stops showing a frozen spinner glyph. Skip when a
475
+ // todo strike owns the frame — it sets its own value right after this.
476
+ if (!this.#todoStrikeInterval) {
477
+ this.#spinnerFrame = undefined;
478
+ this.#renderState.spinnerFrame = undefined;
479
+ }
480
+ }
481
+ }
482
+
483
+ #updateTodoStrikeAnimation(): void {
484
+ if (this.#toolName !== "todo" || this.#isPartial || this.#result?.isError) {
485
+ this.#stopTodoStrikeAnimation();
486
+ return;
487
+ }
488
+ const completedTasks = (this.#result?.details as { completedTasks?: unknown[] } | undefined)?.completedTasks;
489
+ if (!completedTasks || completedTasks.length === 0) {
490
+ this.#stopTodoStrikeAnimation();
491
+ return;
492
+ }
493
+ if (this.#todoStrikeInterval) return;
494
+
495
+ this.#spinnerFrame = 0;
496
+ this.#renderState.spinnerFrame = 0;
497
+ this.#todoStrikeInterval = setInterval(() => {
498
+ const nextFrame = (this.#spinnerFrame ?? 0) + 1;
499
+ if (nextFrame > TODO_STRIKE_TOTAL_FRAMES) {
500
+ this.#stopTodoStrikeAnimation();
501
+ } else {
502
+ this.#spinnerFrame = nextFrame;
503
+ this.#renderState.spinnerFrame = nextFrame;
504
+ }
505
+ this.#ui.requestRender();
506
+ }, 65);
507
+ }
508
+
509
+ #stopTodoStrikeAnimation(): void {
510
+ if (this.#todoStrikeInterval) {
511
+ clearInterval(this.#todoStrikeInterval);
512
+ this.#todoStrikeInterval = undefined;
513
+ }
514
+ if (!this.#spinnerInterval) {
515
+ this.#spinnerFrame = undefined;
516
+ this.#renderState.spinnerFrame = undefined;
517
+ }
518
+ }
519
+
520
+ /**
521
+ * Whether this block has reached a terminal state for transcript freezing.
522
+ * Reports `false` while it can still visually change so the
523
+ * {@link TranscriptContainer} keeps it inside the repaintable live region:
524
+ * a foreground tool awaiting its result, or one streaming partial output.
525
+ * A final (non-partial) result, a background-async tool the agent has moved
526
+ * past, or an explicit {@link seal} flips it to `true`.
527
+ */
528
+ isTranscriptBlockFinalized(): boolean {
529
+ if (this.#sealed) return true;
530
+ if (this.#result === undefined) return false;
531
+ // A displaceable waiting poll stays live: its rows are kept out of
532
+ // native scrollback so a follow-up `job` call can remove the block.
533
+ if (this.#displaceable) return false;
534
+ if (!this.#isPartial) return true;
535
+ // Partial result: a background async tool is accepted to freeze (the agent
536
+ // continues while it runs and would otherwise pin an unbounded live region);
537
+ // a foreground tool streaming partial output stays live until it finishes.
538
+ return (this.#result.details as { async?: { state?: string } } | undefined)?.async?.state === "running";
539
+ }
540
+
541
+ /**
542
+ * Mark the tool terminal even though no result arrived (the turn aborted or
543
+ * abandoned it) and stop animating, so it can freeze and stops pinning the
544
+ * transcript live region.
545
+ */
546
+ seal(): void {
547
+ if (this.#sealed) return;
548
+ this.#sealed = true;
549
+ this.#displaceable = false;
550
+ this.stopAnimation();
551
+ this.#updateDisplay();
552
+ this.#ui.requestRender();
553
+ }
554
+
555
+ /**
556
+ * Whether this block is a waiting `job` poll (every watched job still
557
+ * running) that has not been sealed. Such a block never finalized, so none
558
+ * of its rows entered native scrollback (the ticking spinner keeps the
559
+ * stable-prefix ratchet at zero) and the whole block can be removed when a
560
+ * follow-up `job` call supersedes it.
561
+ */
562
+ isDisplaceableBlock(): boolean {
563
+ return this.#displaceable && !this.#sealed;
564
+ }
565
+
566
+ /**
567
+ * Stop spinner animation and cleanup resources.
568
+ */
569
+ stopAnimation(): void {
570
+ if (this.#spinnerInterval) {
571
+ clearInterval(this.#spinnerInterval);
572
+ this.#spinnerInterval = undefined;
573
+ this.#spinnerFrame = undefined;
574
+ this.#renderState.spinnerFrame = undefined;
575
+ }
576
+ this.#stopTodoStrikeAnimation();
577
+ this.#editDiffAbort?.abort();
578
+ this.#editDiffAbort = undefined;
579
+ }
580
+
581
+ setExpanded(expanded: boolean): void {
582
+ this.#expanded = expanded;
583
+ this.#updateDisplay();
584
+ }
585
+
586
+ setShowImages(show: boolean): void {
587
+ this.#showImages = show;
588
+ this.#updateDisplay();
589
+ }
590
+
591
+ override invalidate(): void {
592
+ super.invalidate();
593
+ this.#updateDisplay();
594
+ }
595
+
596
+ #updateDisplay(): void {
597
+ // Sync shared mutable render state for component closures
598
+ this.#renderState.expanded = this.#expanded;
599
+ this.#renderState.isPartial = this.#isPartial;
600
+ this.#renderState.spinnerFrame = this.#spinnerFrame;
601
+
602
+ // Non-self-framing tools (custom/extension renderers and the generic
603
+ // fallback) get a padded, state-tinted block — built-ins that draw their
604
+ // own frame opt out below via the framed-component mark.
605
+ const stateBgKey = this.#isPartial ? "toolPendingBg" : this.#result?.isError ? "toolErrorBg" : "toolSuccessBg";
606
+ const stateBgFn = (t: string) => theme.bg(stateBgKey, t);
607
+
608
+ // Check for custom tool rendering
609
+ if (this.#tool && (this.#tool.renderCall || this.#tool.renderResult)) {
610
+ const tool = this.#tool;
611
+ const mergeCallAndResult = Boolean((tool as { mergeCallAndResult?: boolean }).mergeCallAndResult);
612
+ // Custom tools use Box for flexible component rendering
613
+ this.#contentBox.setBgFn(undefined);
614
+ this.#contentBox.clear();
615
+ // Mirror the built-in renderer branch so custom renderers (notably the
616
+ // task tool, whose live instance routes through here) receive the same
617
+ // render context — e.g. the `hasResult` flag that suppresses the task
618
+ // call preview once result lines exist.
619
+ this.#renderState.renderContext = this.#buildRenderContext();
620
+
621
+ // Render call component. The fallback label only stands in for a
622
+ // missing `renderCall`; when the call is intentionally suppressed
623
+ // (mergeCallAndResult once a result exists) we render nothing here so
624
+ // the result component isn't preceded by a redundant tool-name line.
625
+ const shouldRenderCall = !this.#result || !mergeCallAndResult;
626
+ if (shouldRenderCall) {
627
+ if (tool.renderCall) {
628
+ try {
629
+ const callComponent = tool.renderCall(this.#getCallArgsForRender(), this.#renderState, theme);
630
+ if (callComponent) this.#contentBox.addChild(callComponent as Component);
631
+ } catch (err) {
632
+ logger.warn("Tool renderer failed", { tool: this.#toolName, error: String(err) });
633
+ // Fall back to default on error
634
+ this.#contentBox.addChild(new Text(theme.fg("toolTitle", theme.bold(this.#toolLabel)), 0, 0));
635
+ }
636
+ } else {
637
+ // No custom renderCall, show tool name
638
+ this.#contentBox.addChild(new Text(theme.fg("toolTitle", theme.bold(this.#toolLabel)), 0, 0));
639
+ }
640
+ }
641
+
642
+ // Render result component if we have a result
643
+ if (this.#result && tool.renderResult) {
644
+ try {
645
+ const renderResult = tool.renderResult as (
646
+ result: { content: Array<{ type: string; text?: string }>; details?: unknown; isError?: boolean },
647
+ options: { expanded: boolean; isPartial: boolean; spinnerFrame?: number },
648
+ theme: Theme,
649
+ args?: unknown,
650
+ ) => Component;
651
+ const resultComponent = renderResult(
652
+ {
653
+ content: this.#result.content as any,
654
+ details: this.#result.details,
655
+ isError: this.#result.isError,
656
+ },
657
+ this.#renderState,
658
+ theme,
659
+ this.#args,
660
+ );
661
+ if (resultComponent) this.#contentBox.addChild(resultComponent);
662
+ } catch (err) {
663
+ logger.warn("Tool renderer failed", { tool: this.#toolName, error: String(err) });
664
+ // Fall back to showing raw output on error
665
+ const output = this.#getTextOutput();
666
+ if (output) {
667
+ this.#contentBox.addChild(new Text(theme.fg("toolOutput", replaceTabs(output)), 0, 0));
668
+ }
669
+ }
670
+ } else if (this.#result) {
671
+ // Has result but no custom renderResult
672
+ const output = this.#getTextOutput();
673
+ if (output) {
674
+ this.#contentBox.addChild(new Text(theme.fg("toolOutput", replaceTabs(output)), 0, 0));
675
+ }
676
+ }
677
+ // Custom tools that draw their own frame (task) render flush; plain
678
+ // extension renderers get the padded, state-tinted block back.
679
+ const customFramed = this.#contentBox.children.some(isFramedBlockComponent);
680
+ this.#contentBox.setPaddingX(customFramed ? 0 : 1);
681
+ this.#contentBox.setBgFn(customFramed ? undefined : stateBgFn);
682
+ } else if (this.#toolName in toolRenderers) {
683
+ // Built-in tools with renderers
684
+ const renderer = toolRenderers[this.#toolName];
685
+
686
+ // Clean up previous multi-file boxes
687
+ for (const box of this.#multiFileBoxes) {
688
+ this.removeChild(box);
689
+ }
690
+ this.#multiFileBoxes = [];
691
+
692
+ // Check for multi-file edit results
693
+ const perFileResults = this.#result?.details?.perFileResults as
694
+ | Array<{ path: string; isError?: boolean }>
695
+ | undefined;
696
+ if (perFileResults && perFileResults.length > 1) {
697
+ // Multi-file: render each file as its own Box (identical to separate tool calls)
698
+ this.#contentBox.setBgFn(undefined);
699
+ this.#contentBox.clear();
700
+
701
+ const renderContext = this.#buildRenderContext();
702
+ this.#renderState.renderContext = renderContext;
703
+
704
+ for (let i = 0; i < perFileResults.length; i++) {
705
+ const fileResult = perFileResults[i];
706
+ if (i > 0) {
707
+ const spacer = new Spacer(1);
708
+ this.#multiFileBoxes.push(spacer);
709
+ this.addChild(spacer);
710
+ }
711
+ const fileBox = new Box(0, 0);
712
+ try {
713
+ const resultComponent = renderer.renderResult(
714
+ { content: [], details: fileResult, isError: fileResult.isError },
715
+ this.#renderState,
716
+ theme,
717
+ );
718
+ if (resultComponent) fileBox.addChild(resultComponent);
719
+ } catch (err) {
720
+ logger.warn("Tool renderer failed", { tool: this.#toolName, error: String(err) });
721
+ }
722
+ this.#multiFileBoxes.push(fileBox);
723
+ this.addChild(fileBox);
724
+ }
725
+
726
+ // Show pending indicator for remaining files
727
+ const totalFiles = this.#args?.edits
728
+ ? new Set((this.#args.edits as any[]).map((e: any) => e?.path).filter(Boolean)).size
729
+ : 0;
730
+ const remaining = Math.max(0, totalFiles - perFileResults.length);
731
+ if (remaining > 0 && this.#isPartial) {
732
+ const pendingSpacer = new Spacer(1);
733
+ this.#multiFileBoxes.push(pendingSpacer);
734
+ this.addChild(pendingSpacer);
735
+ const pendingBox = new Box(0, 0);
736
+ const pendingText = renderStatusLine(
737
+ {
738
+ icon: "pending",
739
+ title: "Edit",
740
+ description: theme.fg("dim", `${remaining} more file${remaining > 1 ? "s" : ""} pending…`),
741
+ },
742
+ theme,
743
+ );
744
+ pendingBox.addChild(new Text(pendingText, 0, 0));
745
+ this.#multiFileBoxes.push(pendingBox);
746
+ this.addChild(pendingBox);
747
+ }
748
+ } else {
749
+ // Single-file or no result: standard rendering
750
+ // Inline renderers skip background styling
751
+ this.#contentBox.setBgFn(undefined);
752
+ this.#contentBox.clear();
753
+
754
+ const renderContext = this.#buildRenderContext();
755
+ this.#renderState.renderContext = renderContext;
756
+
757
+ const shouldRenderCall = !this.#result || !renderer.mergeCallAndResult;
758
+ if (shouldRenderCall) {
759
+ // Render call component
760
+ try {
761
+ const callComponent = renderer.renderCall(this.#getCallArgsForRender(), this.#renderState, theme);
762
+ if (callComponent) this.#contentBox.addChild(callComponent);
763
+ } catch (err) {
764
+ logger.warn("Tool renderer failed", { tool: this.#toolName, error: String(err) });
765
+ // Fall back to default on error
766
+ this.#contentBox.addChild(new Text(theme.fg("toolTitle", theme.bold(this.#toolLabel)), 0, 0));
767
+ }
768
+ }
769
+
770
+ // Render result component if we have a result
771
+ if (this.#result) {
772
+ try {
773
+ const resultComponent = renderer.renderResult(
774
+ {
775
+ content: this.#result.content as any,
776
+ details: this.#result.details,
777
+ isError: this.#result.isError,
778
+ },
779
+ this.#renderState,
780
+ theme,
781
+ this.#getCallArgsForRender(),
782
+ );
783
+ if (resultComponent) this.#contentBox.addChild(resultComponent);
784
+ } catch (err) {
785
+ logger.warn("Tool renderer failed", { tool: this.#toolName, error: String(err) });
786
+ // Fall back to showing raw output on error
787
+ const output = this.#getTextOutput();
788
+ if (output) {
789
+ this.#contentBox.addChild(new Text(theme.fg("toolOutput", replaceTabs(output)), 0, 0));
790
+ }
791
+ }
792
+ }
793
+ }
794
+ } else {
795
+ // Other built-in tools: use Text directly with caching
796
+ this.#contentText.setCustomBgFn(stateBgFn);
797
+ this.#contentText.setText(this.#formatToolExecution());
798
+ }
799
+
800
+ // Handle images (same for both custom and built-in)
801
+ for (const img of this.#imageComponents) {
802
+ this.removeChild(img);
803
+ }
804
+ this.#imageComponents = [];
805
+ for (const spacer of this.#imageSpacers) {
806
+ this.removeChild(spacer);
807
+ }
808
+ this.#imageSpacers = [];
809
+
810
+ if (this.#result) {
811
+ const imageBlocks = this.#getAllImageBlocks();
812
+
813
+ for (let i = 0; i < imageBlocks.length; i++) {
814
+ const img = imageBlocks[i];
815
+ if (TERMINAL.imageProtocol && this.#showImages && img.data && img.mimeType) {
816
+ // Use converted PNG for Kitty protocol if available
817
+ const converted = this.#convertedImages.get(i);
818
+ const imageData = converted?.data ?? img.data;
819
+ const imageMimeType = converted?.mimeType ?? img.mimeType;
820
+
821
+ // For Kitty, skip non-PNG images that haven't been converted yet
822
+ if (TERMINAL.imageProtocol === ImageProtocol.Kitty && imageMimeType !== "image/png") {
823
+ continue;
824
+ }
825
+
826
+ const spacer = new Spacer(1);
827
+ this.addChild(spacer);
828
+ this.#imageSpacers.push(spacer);
829
+ const imageComponent = new Image(
830
+ imageData,
831
+ imageMimeType,
832
+ { fallbackColor: (s: string) => theme.fg("toolOutput", s) },
833
+ { ...resolveImageOptions(), budget: this.#ui.imageBudget, imageKey: `te${this.#instanceId}:${i}` },
834
+ );
835
+ this.#imageComponents.push(imageComponent);
836
+ this.addChild(imageComponent);
837
+ }
838
+ }
839
+ }
840
+ }
841
+
842
+ #getCallArgsForRender(): any {
843
+ const renderArgs = getArgsWithStreamedTextInput(this.#args);
844
+ if (!isEditLikeToolName(this.#toolName)) {
845
+ return renderArgs;
846
+ }
847
+ const previews = this.#editDiffPreview;
848
+ if (!previews || previews.length === 0) {
849
+ return renderArgs;
850
+ }
851
+ // Single-file previews feed the existing `previewDiff` channel consumed
852
+ // by `formatStreamingDiff` in the renderer.
853
+ const first = previews[0];
854
+ if (!first?.diff) {
855
+ return renderArgs;
856
+ }
857
+ return { ...(renderArgs as Record<string, unknown>), previewDiff: first.diff };
858
+ }
859
+
860
+ /**
861
+ * Build render context for tools that need extra state (bash, python, edit)
862
+ */
863
+ #buildRenderContext(): Record<string, unknown> {
864
+ const context: Record<string, unknown> = {};
865
+ const normalizeTimeoutSeconds = (value: unknown, maxSeconds: number): number | undefined => {
866
+ if (typeof value !== "number" || !Number.isFinite(value)) return undefined;
867
+ return Math.max(1, Math.min(maxSeconds, value));
868
+ };
869
+
870
+ if (this.#toolName === "bash") {
871
+ // Bash needs render context even before a result exists. The renderer uses the pending-call args
872
+ // plus this context to keep the inline command preview visible while tool-call JSON is still streaming.
873
+ if (this.#result) {
874
+ // Pass raw output and expanded state - renderer handles width-aware truncation
875
+ const output = this.#getTextOutput().trimEnd();
876
+ context.output = output;
877
+ }
878
+ context.expanded = this.#expanded;
879
+ context.previewLines = BASH_DEFAULT_PREVIEW_LINES;
880
+ context.timeout = normalizeTimeoutSeconds(this.#args?.timeout, 3600);
881
+ } else if (this.#toolName === "eval" && this.#result) {
882
+ const output = this.#getTextOutput().trimEnd();
883
+ context.output = output;
884
+ context.expanded = this.#expanded;
885
+ context.previewLines = EVAL_DEFAULT_PREVIEW_LINES;
886
+ } else if (this.#toolName === "task") {
887
+ // Once a result snapshot exists the task renderer's `renderResult`
888
+ // draws every dispatched agent as a progress/result line, so tell
889
+ // `renderCall` to drop its duplicate streaming preview list.
890
+ context.hasResult = Boolean(this.#result);
891
+ } else if (isEditLikeToolName(this.#toolName)) {
892
+ context.editMode = this.#editMode;
893
+ const previews = this.#editDiffPreview;
894
+ if (previews && previews.length > 0) {
895
+ const first = previews[0];
896
+ if (first?.diff || first?.error) {
897
+ context.editDiffPreview = first.error
898
+ ? { error: first.error }
899
+ : { diff: first.diff ?? "", firstChangedLine: first.firstChangedLine };
900
+ }
901
+ if (previews.length > 1) {
902
+ context.perFileDiffPreview = previews;
903
+ }
904
+ }
905
+ if (!previews?.some(preview => preview.diff)) {
906
+ const editMode = this.#editMode;
907
+ const strategy = editMode ? EDIT_MODE_STRATEGIES[editMode] : undefined;
908
+ const fallback = strategy?.renderStreamingFallback(getArgsWithStreamedTextInput(this.#args), theme);
909
+ if (fallback) context.editStreamingFallback = fallback;
910
+ }
911
+ context.renderDiff = renderDiff;
912
+ }
913
+
914
+ return context;
915
+ }
916
+
917
+ #getTextOutput(): string {
918
+ if (!this.#result) return "";
919
+
920
+ const textBlocks = this.#result.content?.filter((c: any) => c.type === "text") || [];
921
+ const imageBlocks = this.#getAllImageBlocks();
922
+
923
+ let output = textBlocks
924
+ .map((c: any) => {
925
+ return sanitizeWithOptionalSixelPassthrough(c.text || "", sanitizeText);
926
+ })
927
+ .join("\n");
928
+
929
+ if (imageBlocks.length > 0 && (!TERMINAL.imageProtocol || !this.#showImages)) {
930
+ const imageIndicators = imageBlocks
931
+ .map((img: any) => {
932
+ const dims = img.data ? (getImageDimensions(img.data, img.mimeType) ?? undefined) : undefined;
933
+ return imageFallback(img.mimeType, dims);
934
+ })
935
+ .join("\n");
936
+ output = output ? `${output}\n${imageIndicators}` : imageIndicators;
937
+ }
938
+
939
+ return output;
940
+ }
941
+
942
+ /**
943
+ * Format a generic tool execution (fallback for tools without custom renderers)
944
+ */
945
+ #formatToolExecution(): string {
946
+ const lines: string[] = [];
947
+ const icon = this.#isPartial ? "pending" : this.#result?.isError ? "error" : "done";
948
+ lines.push(renderStatusLine({ icon, title: this.#toolLabel }, theme));
949
+
950
+ const argsObject = this.#args && typeof this.#args === "object" ? (this.#args as Record<string, unknown>) : null;
951
+ if (!this.#expanded && argsObject && Object.keys(argsObject).length > 0) {
952
+ const preview = formatArgsInline(argsObject, 70);
953
+ if (preview) {
954
+ lines.push(` ${theme.fg("dim", theme.tree.last)} ${theme.fg("dim", preview)}`);
955
+ }
956
+ }
957
+
958
+ if (this.#expanded && this.#args !== undefined) {
959
+ lines.push("");
960
+ lines.push(theme.fg("dim", "Args"));
961
+ const tree = renderJsonTreeLines(
962
+ this.#args,
963
+ theme,
964
+ JSON_TREE_MAX_DEPTH_EXPANDED,
965
+ JSON_TREE_MAX_LINES_EXPANDED,
966
+ JSON_TREE_SCALAR_LEN_EXPANDED,
967
+ );
968
+ lines.push(...tree.lines);
969
+ if (tree.truncated) {
970
+ lines.push(theme.fg("dim", "…"));
971
+ }
972
+ lines.push("");
973
+ }
974
+
975
+ if (!this.#result) {
976
+ return lines.join("\n");
977
+ }
978
+
979
+ const textContent = this.#getTextOutput().trimEnd();
980
+ if (!textContent) {
981
+ lines.push(theme.fg("dim", "(no output)"));
982
+ return lines.join("\n");
983
+ }
984
+
985
+ if (textContent.startsWith("{") || textContent.startsWith("[")) {
986
+ try {
987
+ const parsed = JSON.parse(textContent);
988
+ const maxDepth = this.#expanded ? JSON_TREE_MAX_DEPTH_EXPANDED : JSON_TREE_MAX_DEPTH_COLLAPSED;
989
+ const maxLines = this.#expanded ? JSON_TREE_MAX_LINES_EXPANDED : JSON_TREE_MAX_LINES_COLLAPSED;
990
+ const maxScalarLen = this.#expanded ? JSON_TREE_SCALAR_LEN_EXPANDED : JSON_TREE_SCALAR_LEN_COLLAPSED;
991
+ const tree = renderJsonTreeLines(parsed, theme, maxDepth, maxLines, maxScalarLen);
992
+
993
+ if (tree.lines.length > 0) {
994
+ lines.push(...tree.lines);
995
+ if (!this.#expanded) {
996
+ lines.push(formatExpandHint(theme, this.#expanded, true));
997
+ } else if (tree.truncated) {
998
+ lines.push(theme.fg("dim", "…"));
999
+ }
1000
+ return lines.join("\n");
1001
+ }
1002
+ } catch {
1003
+ // Fall through to raw output
1004
+ }
1005
+ }
1006
+
1007
+ const outputLines = textContent.split("\n");
1008
+ const maxOutputLines = this.#expanded ? 12 : 4;
1009
+ const displayLines = outputLines.slice(0, maxOutputLines);
1010
+
1011
+ for (const line of displayLines) {
1012
+ lines.push(theme.fg("toolOutput", truncateToWidth(replaceTabs(line), 80)));
1013
+ }
1014
+
1015
+ if (outputLines.length > maxOutputLines) {
1016
+ const remaining = outputLines.length - maxOutputLines;
1017
+ lines.push(`${theme.fg("dim", `… ${remaining} more lines`)} ${formatExpandHint(theme, this.#expanded, true)}`);
1018
+ } else if (!this.#expanded) {
1019
+ lines.push(formatExpandHint(theme, this.#expanded, true));
1020
+ }
1021
+
1022
+ return lines.join("\n");
1023
+ }
1024
+ }