pi-agent-zh 17.1.8

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 (1519) hide show
  1. package/CHANGELOG.md +14459 -0
  2. package/README.md +35 -0
  3. package/dist/CHANGELOG-vt8ene9g.md +14459 -0
  4. package/dist/cli.js +22079 -0
  5. package/dist/template-dys3vk5b.js +1671 -0
  6. package/dist/template-f8wx9vfn.css +1355 -0
  7. package/dist/template-qat058wr.html +55 -0
  8. package/dist/tool-views.generated-jdfmzwmn.js +35 -0
  9. package/examples/README.md +21 -0
  10. package/examples/custom-tools/README.md +104 -0
  11. package/examples/custom-tools/hello/index.ts +20 -0
  12. package/examples/extensions/README.md +142 -0
  13. package/examples/extensions/api-demo.ts +79 -0
  14. package/examples/extensions/chalk-logger.ts +25 -0
  15. package/examples/extensions/hello.ts +31 -0
  16. package/examples/extensions/pirate.ts +43 -0
  17. package/examples/extensions/plan-mode.ts +549 -0
  18. package/examples/extensions/reload-runtime.ts +38 -0
  19. package/examples/extensions/thinking-note.ts +13 -0
  20. package/examples/extensions/tools.ts +145 -0
  21. package/examples/extensions/with-deps/index.ts +36 -0
  22. package/examples/extensions/with-deps/package-lock.json +31 -0
  23. package/examples/extensions/with-deps/package.json +17 -0
  24. package/examples/hooks/README.md +56 -0
  25. package/examples/hooks/auto-commit-on-exit.ts +48 -0
  26. package/examples/hooks/confirm-destructive.ts +58 -0
  27. package/examples/hooks/custom-compaction.ts +115 -0
  28. package/examples/hooks/dirty-repo-guard.ts +51 -0
  29. package/examples/hooks/file-trigger.ts +40 -0
  30. package/examples/hooks/git-checkpoint.ts +52 -0
  31. package/examples/hooks/handoff.ts +149 -0
  32. package/examples/hooks/permission-gate.ts +33 -0
  33. package/examples/hooks/protected-paths.ts +29 -0
  34. package/examples/hooks/qna.ts +118 -0
  35. package/examples/hooks/status-line.ts +39 -0
  36. package/examples/sdk/01-minimal.ts +21 -0
  37. package/examples/sdk/02-custom-model.ts +49 -0
  38. package/examples/sdk/03-custom-prompt.ts +46 -0
  39. package/examples/sdk/04-skills.ts +43 -0
  40. package/examples/sdk/06-extensions.ts +82 -0
  41. package/examples/sdk/06-hooks.ts +61 -0
  42. package/examples/sdk/07-context-files.ts +35 -0
  43. package/examples/sdk/08-prompt-templates.ts +41 -0
  44. package/examples/sdk/08-slash-commands.ts +46 -0
  45. package/examples/sdk/09-api-keys-and-oauth.ts +54 -0
  46. package/examples/sdk/11-sessions.ts +47 -0
  47. package/examples/sdk/12-redis-sessions.ts +54 -0
  48. package/examples/sdk/13-sql-sessions.ts +61 -0
  49. package/examples/sdk/README.md +169 -0
  50. package/package.json +606 -0
  51. package/scripts/bench-guard.ts +71 -0
  52. package/scripts/bench-title-models.ts +332 -0
  53. package/scripts/build-binary.ts +117 -0
  54. package/scripts/bundle-dist.ts +133 -0
  55. package/scripts/compile-binary.ts +69 -0
  56. package/scripts/embed-mupdf-wasm.ts +67 -0
  57. package/scripts/format-prompts.ts +68 -0
  58. package/scripts/generate-aria-snapshot.ts +134 -0
  59. package/scripts/generate-docs-index.ts +58 -0
  60. package/scripts/generate-share-viewer.ts +34 -0
  61. package/scripts/legacy-pi-virtual-module.ts +195 -0
  62. package/scripts/measure-prompt-tokens.ts +63 -0
  63. package/scripts/omp +42 -0
  64. package/scripts/omp.ts +19 -0
  65. package/src/advisor/advise-tool.ts +216 -0
  66. package/src/advisor/config.ts +341 -0
  67. package/src/advisor/emission-guard.ts +172 -0
  68. package/src/advisor/index.ts +6 -0
  69. package/src/advisor/runtime.ts +1232 -0
  70. package/src/advisor/transcript-recorder.ts +159 -0
  71. package/src/advisor/watchdog.ts +135 -0
  72. package/src/async/index.ts +1 -0
  73. package/src/async/job-manager.ts +821 -0
  74. package/src/auto-thinking/classifier.ts +182 -0
  75. package/src/autolearn/controller.ts +152 -0
  76. package/src/autolearn/managed-skills.ts +255 -0
  77. package/src/autoresearch/command-resume.md +14 -0
  78. package/src/autoresearch/dashboard.ts +436 -0
  79. package/src/autoresearch/git.ts +331 -0
  80. package/src/autoresearch/helpers.ts +218 -0
  81. package/src/autoresearch/index.ts +541 -0
  82. package/src/autoresearch/prompt-setup.md +43 -0
  83. package/src/autoresearch/prompt.md +103 -0
  84. package/src/autoresearch/resume-message.md +10 -0
  85. package/src/autoresearch/state.ts +273 -0
  86. package/src/autoresearch/storage.ts +700 -0
  87. package/src/autoresearch/tools/init-experiment.ts +269 -0
  88. package/src/autoresearch/tools/log-experiment.ts +521 -0
  89. package/src/autoresearch/tools/run-experiment.ts +407 -0
  90. package/src/autoresearch/tools/update-notes.ts +109 -0
  91. package/src/autoresearch/types.ts +168 -0
  92. package/src/capability/context-file.ts +44 -0
  93. package/src/capability/extension-module.ts +34 -0
  94. package/src/capability/extension.ts +47 -0
  95. package/src/capability/fs.ts +117 -0
  96. package/src/capability/hook.ts +40 -0
  97. package/src/capability/index.ts +467 -0
  98. package/src/capability/instruction.ts +37 -0
  99. package/src/capability/mcp.ts +97 -0
  100. package/src/capability/prompt.ts +35 -0
  101. package/src/capability/rule-buckets.ts +66 -0
  102. package/src/capability/rule.ts +298 -0
  103. package/src/capability/settings.ts +34 -0
  104. package/src/capability/skill.ts +63 -0
  105. package/src/capability/slash-command.ts +40 -0
  106. package/src/capability/ssh.ts +41 -0
  107. package/src/capability/system-prompt.ts +34 -0
  108. package/src/capability/tool.ts +38 -0
  109. package/src/capability/types.ts +187 -0
  110. package/src/cleanse/agent.ts +226 -0
  111. package/src/cleanse/balance.ts +79 -0
  112. package/src/cleanse/checkers.ts +996 -0
  113. package/src/cleanse/index.ts +190 -0
  114. package/src/cleanse/loop.ts +51 -0
  115. package/src/cleanse/parsers.ts +726 -0
  116. package/src/cleanse/progress.ts +50 -0
  117. package/src/cleanse/prompts/assignment.md +47 -0
  118. package/src/cleanse/types.ts +72 -0
  119. package/src/cli/agents-cli.ts +138 -0
  120. package/src/cli/args.ts +420 -0
  121. package/src/cli/auth-broker-cli.ts +940 -0
  122. package/src/cli/auth-gateway-cli.ts +674 -0
  123. package/src/cli/bench-cli.ts +990 -0
  124. package/src/cli/classify-install-target.ts +76 -0
  125. package/src/cli/claude-trace-cli.ts +795 -0
  126. package/src/cli/commands/init-xdg.ts +27 -0
  127. package/src/cli/completion-gen.ts +550 -0
  128. package/src/cli/config-cli.ts +459 -0
  129. package/src/cli/dry-balance-cli.ts +864 -0
  130. package/src/cli/extension-flags.ts +48 -0
  131. package/src/cli/file-processor.ts +132 -0
  132. package/src/cli/flag-tables.ts +352 -0
  133. package/src/cli/gallery-cli.ts +272 -0
  134. package/src/cli/gallery-fixtures/agentic.ts +420 -0
  135. package/src/cli/gallery-fixtures/codeintel.ts +187 -0
  136. package/src/cli/gallery-fixtures/edit.ts +254 -0
  137. package/src/cli/gallery-fixtures/fs.ts +220 -0
  138. package/src/cli/gallery-fixtures/index.ts +40 -0
  139. package/src/cli/gallery-fixtures/interaction.ts +46 -0
  140. package/src/cli/gallery-fixtures/memory.ts +81 -0
  141. package/src/cli/gallery-fixtures/misc.ts +177 -0
  142. package/src/cli/gallery-fixtures/search.ts +135 -0
  143. package/src/cli/gallery-fixtures/shell.ts +241 -0
  144. package/src/cli/gallery-fixtures/types.ts +57 -0
  145. package/src/cli/gallery-fixtures/web.ts +158 -0
  146. package/src/cli/gallery-screenshot.ts +279 -0
  147. package/src/cli/gc-cli.ts +946 -0
  148. package/src/cli/grep-cli.ts +161 -0
  149. package/src/cli/grievances-cli.ts +256 -0
  150. package/src/cli/initial-message.ts +58 -0
  151. package/src/cli/models-cli.ts +388 -0
  152. package/src/cli/plugin-cli.ts +996 -0
  153. package/src/cli/profile-alias.ts +369 -0
  154. package/src/cli/profile-bootstrap.ts +233 -0
  155. package/src/cli/read-cli.ts +99 -0
  156. package/src/cli/session-picker.ts +93 -0
  157. package/src/cli/setup-cli.ts +320 -0
  158. package/src/cli/setup-model-picker.ts +43 -0
  159. package/src/cli/shell-cli.ts +176 -0
  160. package/src/cli/ssh-cli.ts +179 -0
  161. package/src/cli/startup-cwd.ts +58 -0
  162. package/src/cli/stats-cli.ts +229 -0
  163. package/src/cli/tiny-models-cli.ts +153 -0
  164. package/src/cli/ttsr-cli.ts +995 -0
  165. package/src/cli/update-cli.ts +1219 -0
  166. package/src/cli/usage-cli.ts +1084 -0
  167. package/src/cli/usage-error.ts +7 -0
  168. package/src/cli/web-search-cli.ts +144 -0
  169. package/src/cli/worktree-cli.ts +311 -0
  170. package/src/cli-commands.ts +166 -0
  171. package/src/cli.ts +407 -0
  172. package/src/collab/crypto.ts +63 -0
  173. package/src/collab/display-name.ts +13 -0
  174. package/src/collab/guest.ts +731 -0
  175. package/src/collab/host.ts +691 -0
  176. package/src/collab/protocol.ts +296 -0
  177. package/src/collab/relay-client.ts +282 -0
  178. package/src/collab/replication-shrink.ts +111 -0
  179. package/src/commands/acp.ts +33 -0
  180. package/src/commands/agents.ts +57 -0
  181. package/src/commands/auth-broker.ts +99 -0
  182. package/src/commands/auth-gateway.ts +69 -0
  183. package/src/commands/bench.ts +65 -0
  184. package/src/commands/cleanse.ts +45 -0
  185. package/src/commands/commit.ts +46 -0
  186. package/src/commands/complete.ts +66 -0
  187. package/src/commands/completions.ts +60 -0
  188. package/src/commands/config.ts +51 -0
  189. package/src/commands/dry-balance.ts +43 -0
  190. package/src/commands/gallery.ts +60 -0
  191. package/src/commands/gc.ts +46 -0
  192. package/src/commands/grep.ts +48 -0
  193. package/src/commands/grievances.ts +51 -0
  194. package/src/commands/install.ts +107 -0
  195. package/src/commands/join.ts +39 -0
  196. package/src/commands/launch.ts +212 -0
  197. package/src/commands/models.ts +60 -0
  198. package/src/commands/plugin.ts +78 -0
  199. package/src/commands/read.ts +38 -0
  200. package/src/commands/say.ts +145 -0
  201. package/src/commands/setup.ts +67 -0
  202. package/src/commands/shell.ts +29 -0
  203. package/src/commands/ssh.ts +60 -0
  204. package/src/commands/stats.ts +29 -0
  205. package/src/commands/tiny-models.ts +36 -0
  206. package/src/commands/token.ts +164 -0
  207. package/src/commands/ttsr.ts +125 -0
  208. package/src/commands/update.ts +33 -0
  209. package/src/commands/usage.ts +54 -0
  210. package/src/commands/web-search.ts +42 -0
  211. package/src/commands/worktree.ts +62 -0
  212. package/src/commit/agentic/agent.ts +322 -0
  213. package/src/commit/agentic/fallback.ts +96 -0
  214. package/src/commit/agentic/index.ts +382 -0
  215. package/src/commit/agentic/lock-files.ts +107 -0
  216. package/src/commit/agentic/prompts/analyze-file.md +22 -0
  217. package/src/commit/agentic/prompts/session-user.md +25 -0
  218. package/src/commit/agentic/prompts/split-confirm.md +1 -0
  219. package/src/commit/agentic/prompts/system.md +38 -0
  220. package/src/commit/agentic/state.ts +60 -0
  221. package/src/commit/agentic/tools/analyze-file.ts +148 -0
  222. package/src/commit/agentic/tools/git-file-diff.ts +191 -0
  223. package/src/commit/agentic/tools/git-hunk.ts +52 -0
  224. package/src/commit/agentic/tools/git-overview.ts +62 -0
  225. package/src/commit/agentic/tools/index.ts +54 -0
  226. package/src/commit/agentic/tools/propose-changelog.ts +147 -0
  227. package/src/commit/agentic/tools/propose-commit.ts +109 -0
  228. package/src/commit/agentic/tools/recent-commits.ts +81 -0
  229. package/src/commit/agentic/tools/schemas.ts +11 -0
  230. package/src/commit/agentic/tools/split-commit.ts +241 -0
  231. package/src/commit/agentic/topo-sort.ts +44 -0
  232. package/src/commit/agentic/trivial.ts +51 -0
  233. package/src/commit/agentic/validation.ts +183 -0
  234. package/src/commit/analysis/conventional.ts +64 -0
  235. package/src/commit/analysis/index.ts +4 -0
  236. package/src/commit/analysis/scope.ts +242 -0
  237. package/src/commit/analysis/summary.ts +107 -0
  238. package/src/commit/analysis/validation.ts +66 -0
  239. package/src/commit/changelog/detect.ts +40 -0
  240. package/src/commit/changelog/generate.ts +101 -0
  241. package/src/commit/changelog/index.ts +234 -0
  242. package/src/commit/changelog/parse.ts +44 -0
  243. package/src/commit/cli.ts +85 -0
  244. package/src/commit/git/diff.ts +148 -0
  245. package/src/commit/index.ts +5 -0
  246. package/src/commit/map-reduce/index.ts +69 -0
  247. package/src/commit/map-reduce/map-phase.ts +193 -0
  248. package/src/commit/map-reduce/reduce-phase.ts +49 -0
  249. package/src/commit/map-reduce/utils.ts +9 -0
  250. package/src/commit/message.ts +11 -0
  251. package/src/commit/model-selection.ts +95 -0
  252. package/src/commit/pipeline.ts +243 -0
  253. package/src/commit/prompts/analysis-system.md +148 -0
  254. package/src/commit/prompts/analysis-user.md +38 -0
  255. package/src/commit/prompts/changelog-system.md +50 -0
  256. package/src/commit/prompts/changelog-user.md +18 -0
  257. package/src/commit/prompts/file-observer-system.md +24 -0
  258. package/src/commit/prompts/file-observer-user.md +8 -0
  259. package/src/commit/prompts/reduce-system.md +50 -0
  260. package/src/commit/prompts/reduce-user.md +17 -0
  261. package/src/commit/prompts/summary-retry.md +3 -0
  262. package/src/commit/prompts/summary-system.md +38 -0
  263. package/src/commit/prompts/summary-user.md +13 -0
  264. package/src/commit/prompts/types-description.md +2 -0
  265. package/src/commit/shared-llm.ts +70 -0
  266. package/src/commit/types.ts +118 -0
  267. package/src/commit/utils/exclusions.ts +42 -0
  268. package/src/commit/utils.ts +58 -0
  269. package/src/config/api-key-resolver.ts +81 -0
  270. package/src/config/append-only-context-mode.ts +76 -0
  271. package/src/config/config-file.ts +347 -0
  272. package/src/config/file-lock.ts +164 -0
  273. package/src/config/inline-tool-descriptors-mode.ts +26 -0
  274. package/src/config/keybindings.ts +688 -0
  275. package/src/config/mcp-schema.json +247 -0
  276. package/src/config/model-discovery.ts +999 -0
  277. package/src/config/model-registry.ts +2725 -0
  278. package/src/config/model-resolver.ts +2068 -0
  279. package/src/config/model-roles.ts +113 -0
  280. package/src/config/models-config-schema-bundle.ts +313 -0
  281. package/src/config/models-config-schema.ts +14 -0
  282. package/src/config/models-config.ts +130 -0
  283. package/src/config/prompt-templates.ts +205 -0
  284. package/src/config/provider-globals.ts +25 -0
  285. package/src/config/resolve-config-value.ts +94 -0
  286. package/src/config/service-tier.ts +141 -0
  287. package/src/config/settings-schema.ts +5751 -0
  288. package/src/config/settings.ts +2369 -0
  289. package/src/config.ts +242 -0
  290. package/src/cursor.ts +513 -0
  291. package/src/dap/client.ts +1043 -0
  292. package/src/dap/config.ts +480 -0
  293. package/src/dap/defaults.json +212 -0
  294. package/src/dap/index.ts +4 -0
  295. package/src/dap/session.ts +1841 -0
  296. package/src/dap/types.ts +611 -0
  297. package/src/debug/index.ts +584 -0
  298. package/src/debug/log-formatting.ts +58 -0
  299. package/src/debug/log-viewer.ts +966 -0
  300. package/src/debug/profiler.ts +168 -0
  301. package/src/debug/protocol-probe.ts +267 -0
  302. package/src/debug/raw-sse-buffer.ts +421 -0
  303. package/src/debug/raw-sse.ts +312 -0
  304. package/src/debug/remote-debugger.ts +151 -0
  305. package/src/debug/report-bundle.ts +411 -0
  306. package/src/debug/system-info.ts +111 -0
  307. package/src/debug/terminal-info.ts +124 -0
  308. package/src/discovery/agents-md.ts +67 -0
  309. package/src/discovery/agents.ts +230 -0
  310. package/src/discovery/at-imports.ts +273 -0
  311. package/src/discovery/builtin-defaults.ts +39 -0
  312. package/src/discovery/builtin-rules/go-add-cleanup.md +33 -0
  313. package/src/discovery/builtin-rules/go-bench-loop.md +36 -0
  314. package/src/discovery/builtin-rules/go-exp-promoted.md +40 -0
  315. package/src/discovery/builtin-rules/go-ioutil.md +37 -0
  316. package/src/discovery/builtin-rules/go-join-hostport.md +30 -0
  317. package/src/discovery/builtin-rules/go-new-expr.md +44 -0
  318. package/src/discovery/builtin-rules/go-rand-v2.md +41 -0
  319. package/src/discovery/builtin-rules/go-range-int.md +45 -0
  320. package/src/discovery/builtin-rules/index.ts +74 -0
  321. package/src/discovery/builtin-rules/rs-box-leak.md +49 -0
  322. package/src/discovery/builtin-rules/rs-future-prelude.md +24 -0
  323. package/src/discovery/builtin-rules/rs-lazylock.md +52 -0
  324. package/src/discovery/builtin-rules/rs-match-ergonomics.md +68 -0
  325. package/src/discovery/builtin-rules/rs-parking-lot.md +45 -0
  326. package/src/discovery/builtin-rules/rs-result-type.md +20 -0
  327. package/src/discovery/builtin-rules/ts-bare-catch.md +39 -0
  328. package/src/discovery/builtin-rules/ts-import-type.md +43 -0
  329. package/src/discovery/builtin-rules/ts-no-any.md +66 -0
  330. package/src/discovery/builtin-rules/ts-no-deprecated-leftovers.md +45 -0
  331. package/src/discovery/builtin-rules/ts-no-dynamic-import.md +40 -0
  332. package/src/discovery/builtin-rules/ts-no-inline-cast-access.md +55 -0
  333. package/src/discovery/builtin-rules/ts-no-local-is-record.md +48 -0
  334. package/src/discovery/builtin-rules/ts-no-return-type.md +45 -0
  335. package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
  336. package/src/discovery/builtin-rules/ts-no-tiny-functions.md +51 -0
  337. package/src/discovery/builtin-rules/ts-promise-with-resolvers.md +66 -0
  338. package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
  339. package/src/discovery/builtin-rules/ts-set-map.md +28 -0
  340. package/src/discovery/builtin.ts +935 -0
  341. package/src/discovery/claude-plugins.ts +624 -0
  342. package/src/discovery/claude.ts +588 -0
  343. package/src/discovery/cline.ts +83 -0
  344. package/src/discovery/codex.ts +540 -0
  345. package/src/discovery/cursor.ts +220 -0
  346. package/src/discovery/gemini.ts +383 -0
  347. package/src/discovery/github.ts +337 -0
  348. package/src/discovery/helpers.ts +1159 -0
  349. package/src/discovery/index.ts +81 -0
  350. package/src/discovery/mcp-json.ts +172 -0
  351. package/src/discovery/omp-extension-roots.ts +213 -0
  352. package/src/discovery/omp-plugins.ts +387 -0
  353. package/src/discovery/opencode.ts +441 -0
  354. package/src/discovery/plugin-dir-roots.ts +28 -0
  355. package/src/discovery/ssh.ts +153 -0
  356. package/src/discovery/substitute-plugin-root.ts +77 -0
  357. package/src/discovery/vscode.ts +105 -0
  358. package/src/discovery/windsurf.ts +147 -0
  359. package/src/edit/apply-patch/index.ts +87 -0
  360. package/src/edit/apply-patch/parser.ts +174 -0
  361. package/src/edit/diff.ts +999 -0
  362. package/src/edit/file-snapshot-store.ts +148 -0
  363. package/src/edit/hashline/block-resolver.ts +33 -0
  364. package/src/edit/hashline/diff.ts +356 -0
  365. package/src/edit/hashline/execute.ts +280 -0
  366. package/src/edit/hashline/filesystem.ts +223 -0
  367. package/src/edit/hashline/index.ts +5 -0
  368. package/src/edit/hashline/noop-loop-guard.ts +99 -0
  369. package/src/edit/hashline/params.ts +12 -0
  370. package/src/edit/index.ts +676 -0
  371. package/src/edit/modes/apply-patch.lark +19 -0
  372. package/src/edit/modes/apply-patch.ts +53 -0
  373. package/src/edit/modes/patch.ts +1958 -0
  374. package/src/edit/modes/replace.ts +1137 -0
  375. package/src/edit/normalize.ts +345 -0
  376. package/src/edit/notebook.ts +242 -0
  377. package/src/edit/read-file.ts +25 -0
  378. package/src/edit/renderer.ts +998 -0
  379. package/src/edit/snapshot-details.ts +77 -0
  380. package/src/edit/streaming.ts +698 -0
  381. package/src/eval/agent-bridge.ts +224 -0
  382. package/src/eval/backend-helpers.ts +48 -0
  383. package/src/eval/backend.ts +71 -0
  384. package/src/eval/bridge-timeout.ts +62 -0
  385. package/src/eval/budget-bridge.ts +48 -0
  386. package/src/eval/completion-bridge.ts +211 -0
  387. package/src/eval/concurrency-bridge.ts +34 -0
  388. package/src/eval/executor-base.ts +504 -0
  389. package/src/eval/idle-timeout.ts +91 -0
  390. package/src/eval/index.ts +6 -0
  391. package/src/eval/jl/executor.ts +540 -0
  392. package/src/eval/jl/index.ts +54 -0
  393. package/src/eval/jl/kernel.ts +236 -0
  394. package/src/eval/jl/prelude.jl +736 -0
  395. package/src/eval/jl/prelude.ts +3 -0
  396. package/src/eval/jl/runner.jl +666 -0
  397. package/src/eval/jl/runtime.ts +118 -0
  398. package/src/eval/js/context-manager.ts +701 -0
  399. package/src/eval/js/executor.ts +175 -0
  400. package/src/eval/js/index.ts +40 -0
  401. package/src/eval/js/process-entry.ts +31 -0
  402. package/src/eval/js/shared/helpers.ts +170 -0
  403. package/src/eval/js/shared/indirect-eval.ts +30 -0
  404. package/src/eval/js/shared/local-module-loader.ts +364 -0
  405. package/src/eval/js/shared/prelude.ts +2 -0
  406. package/src/eval/js/shared/prelude.txt +294 -0
  407. package/src/eval/js/shared/rewrite-imports.ts +550 -0
  408. package/src/eval/js/shared/runtime.ts +590 -0
  409. package/src/eval/js/shared/types.ts +18 -0
  410. package/src/eval/js/tool-bridge.ts +163 -0
  411. package/src/eval/js/worker-core.ts +380 -0
  412. package/src/eval/js/worker-entry.ts +37 -0
  413. package/src/eval/js/worker-protocol.ts +47 -0
  414. package/src/eval/kernel-base.ts +569 -0
  415. package/src/eval/py/display.ts +71 -0
  416. package/src/eval/py/executor.ts +603 -0
  417. package/src/eval/py/index.ts +57 -0
  418. package/src/eval/py/kernel.ts +234 -0
  419. package/src/eval/py/prelude.py +672 -0
  420. package/src/eval/py/prelude.ts +3 -0
  421. package/src/eval/py/runner.py +1388 -0
  422. package/src/eval/py/runtime.ts +276 -0
  423. package/src/eval/py/spawn-options.ts +139 -0
  424. package/src/eval/py/tool-bridge.ts +181 -0
  425. package/src/eval/rb/executor.ts +504 -0
  426. package/src/eval/rb/index.ts +54 -0
  427. package/src/eval/rb/kernel.ts +231 -0
  428. package/src/eval/rb/prelude.rb +552 -0
  429. package/src/eval/rb/prelude.ts +3 -0
  430. package/src/eval/rb/runner.rb +581 -0
  431. package/src/eval/rb/runtime.ts +132 -0
  432. package/src/eval/runtime-env.ts +104 -0
  433. package/src/eval/session-id.ts +8 -0
  434. package/src/eval/types.ts +48 -0
  435. package/src/exa/index.ts +2 -0
  436. package/src/exa/mcp-client.ts +370 -0
  437. package/src/exa/types.ts +69 -0
  438. package/src/exec/bash-executor.ts +627 -0
  439. package/src/exec/direnv.ts +145 -0
  440. package/src/exec/exec.ts +53 -0
  441. package/src/exec/non-interactive-env.ts +118 -0
  442. package/src/export/custom-share.ts +65 -0
  443. package/src/export/html/args.ts +20 -0
  444. package/src/export/html/index.ts +313 -0
  445. package/src/export/html/share-loader.js +102 -0
  446. package/src/export/html/template.css +1355 -0
  447. package/src/export/html/template.html +55 -0
  448. package/src/export/html/template.js +1671 -0
  449. package/src/export/html/tool-views.generated.js +35 -0
  450. package/src/export/html/vendor/highlight.min.js +1213 -0
  451. package/src/export/html/vendor/marked.min.js +6 -0
  452. package/src/export/html/web-palette.ts +126 -0
  453. package/src/export/share.ts +682 -0
  454. package/src/export/ttsr.ts +590 -0
  455. package/src/extensibility/custom-commands/bundled/ci-green/index.ts +54 -0
  456. package/src/extensibility/custom-commands/bundled/review/index.ts +698 -0
  457. package/src/extensibility/custom-commands/index.ts +2 -0
  458. package/src/extensibility/custom-commands/loader.ts +242 -0
  459. package/src/extensibility/custom-commands/types.ts +119 -0
  460. package/src/extensibility/custom-tools/index.ts +7 -0
  461. package/src/extensibility/custom-tools/loader.ts +301 -0
  462. package/src/extensibility/custom-tools/types.ts +286 -0
  463. package/src/extensibility/custom-tools/wrapper.ts +50 -0
  464. package/src/extensibility/extensions/compact-handler.ts +40 -0
  465. package/src/extensibility/extensions/get-commands-handler.ts +78 -0
  466. package/src/extensibility/extensions/index.ts +16 -0
  467. package/src/extensibility/extensions/load-errors.ts +13 -0
  468. package/src/extensibility/extensions/loader.ts +624 -0
  469. package/src/extensibility/extensions/managed-timers.ts +83 -0
  470. package/src/extensibility/extensions/model-api.ts +39 -0
  471. package/src/extensibility/extensions/runner.ts +1209 -0
  472. package/src/extensibility/extensions/types.ts +1526 -0
  473. package/src/extensibility/extensions/wrapper.ts +377 -0
  474. package/src/extensibility/hooks/index.ts +6 -0
  475. package/src/extensibility/hooks/loader.ts +244 -0
  476. package/src/extensibility/hooks/runner.ts +425 -0
  477. package/src/extensibility/hooks/tool-wrapper.ts +124 -0
  478. package/src/extensibility/hooks/types.ts +612 -0
  479. package/src/extensibility/legacy-pi-ai-shim.ts +140 -0
  480. package/src/extensibility/legacy-pi-coding-agent-shim.ts +1384 -0
  481. package/src/extensibility/legacy-pi-tui-shim.ts +43 -0
  482. package/src/extensibility/plugins/bun-git-cache.ts +91 -0
  483. package/src/extensibility/plugins/doctor.ts +65 -0
  484. package/src/extensibility/plugins/git-url.ts +367 -0
  485. package/src/extensibility/plugins/index.ts +9 -0
  486. package/src/extensibility/plugins/installer.ts +201 -0
  487. package/src/extensibility/plugins/legacy-pi-compat.ts +2532 -0
  488. package/src/extensibility/plugins/legacy-pi-virtual-modules.d.ts +4 -0
  489. package/src/extensibility/plugins/loader.ts +535 -0
  490. package/src/extensibility/plugins/manager.ts +1142 -0
  491. package/src/extensibility/plugins/marketplace/cache.ts +136 -0
  492. package/src/extensibility/plugins/marketplace/fetcher.ts +316 -0
  493. package/src/extensibility/plugins/marketplace/index.ts +6 -0
  494. package/src/extensibility/plugins/marketplace/manager.ts +926 -0
  495. package/src/extensibility/plugins/marketplace/registry.ts +196 -0
  496. package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
  497. package/src/extensibility/plugins/marketplace/types.ts +192 -0
  498. package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
  499. package/src/extensibility/plugins/parser.ts +107 -0
  500. package/src/extensibility/plugins/runtime-config.ts +9 -0
  501. package/src/extensibility/plugins/types.ts +194 -0
  502. package/src/extensibility/session-handler-types.ts +21 -0
  503. package/src/extensibility/shared-events.ts +401 -0
  504. package/src/extensibility/skills.ts +511 -0
  505. package/src/extensibility/slash-commands.ts +131 -0
  506. package/src/extensibility/tool-event-input.ts +80 -0
  507. package/src/extensibility/tool-proxy.ts +28 -0
  508. package/src/extensibility/typebox.ts +958 -0
  509. package/src/extensibility/utils.ts +184 -0
  510. package/src/goals/index.ts +3 -0
  511. package/src/goals/runtime.ts +521 -0
  512. package/src/goals/state.ts +37 -0
  513. package/src/goals/tools/goal-tool.ts +251 -0
  514. package/src/hindsight/backend.ts +354 -0
  515. package/src/hindsight/bank.ts +156 -0
  516. package/src/hindsight/client.ts +680 -0
  517. package/src/hindsight/config.ts +193 -0
  518. package/src/hindsight/content.ts +266 -0
  519. package/src/hindsight/index.ts +8 -0
  520. package/src/hindsight/mental-models.ts +429 -0
  521. package/src/hindsight/seeds.json +32 -0
  522. package/src/hindsight/state.ts +550 -0
  523. package/src/hindsight/transcript.ts +71 -0
  524. package/src/index.ts +66 -0
  525. package/src/internal-urls/agent-protocol.ts +180 -0
  526. package/src/internal-urls/artifact-protocol.ts +151 -0
  527. package/src/internal-urls/docs-index.ts +102 -0
  528. package/src/internal-urls/filesystem-resource.ts +34 -0
  529. package/src/internal-urls/history-protocol.ts +198 -0
  530. package/src/internal-urls/index.ts +27 -0
  531. package/src/internal-urls/issue-pr-protocol.ts +594 -0
  532. package/src/internal-urls/json-query.ts +126 -0
  533. package/src/internal-urls/local-protocol.ts +470 -0
  534. package/src/internal-urls/mcp-protocol.ts +165 -0
  535. package/src/internal-urls/memory-protocol.ts +347 -0
  536. package/src/internal-urls/omp-protocol.ts +94 -0
  537. package/src/internal-urls/parse.ts +103 -0
  538. package/src/internal-urls/registry-helpers.ts +132 -0
  539. package/src/internal-urls/router.ts +150 -0
  540. package/src/internal-urls/rule-protocol.ts +45 -0
  541. package/src/internal-urls/skill-protocol.ts +117 -0
  542. package/src/internal-urls/ssh-protocol.ts +368 -0
  543. package/src/internal-urls/types.ts +196 -0
  544. package/src/internal-urls/vault-protocol.ts +940 -0
  545. package/src/internal-urls/xd-protocol.ts +46 -0
  546. package/src/irc/bus.ts +380 -0
  547. package/src/jsonrpc/message-framing.ts +142 -0
  548. package/src/launch/broker.ts +1134 -0
  549. package/src/launch/client.ts +350 -0
  550. package/src/launch/paths.ts +17 -0
  551. package/src/launch/presence.ts +82 -0
  552. package/src/launch/protocol.ts +396 -0
  553. package/src/launch/spawn-options.ts +17 -0
  554. package/src/launch/terminal-output.ts +46 -0
  555. package/src/lib/xai-http.ts +150 -0
  556. package/src/live/attestation.ts +91 -0
  557. package/src/live/controller.ts +517 -0
  558. package/src/live/prompts/agent-final-message.md +3 -0
  559. package/src/live/prompts/live-instructions.md +23 -0
  560. package/src/live/protocol.ts +233 -0
  561. package/src/live/transport.ts +422 -0
  562. package/src/live/visualizer.ts +214 -0
  563. package/src/live/voices.ts +18 -0
  564. package/src/lsp/client.ts +1429 -0
  565. package/src/lsp/clients/biome-client.ts +263 -0
  566. package/src/lsp/clients/index.ts +50 -0
  567. package/src/lsp/clients/lsp-linter-client.ts +85 -0
  568. package/src/lsp/clients/swiftlint-client.ts +120 -0
  569. package/src/lsp/config.ts +549 -0
  570. package/src/lsp/defaults.json +499 -0
  571. package/src/lsp/deferred-diagnostics.ts +66 -0
  572. package/src/lsp/diagnostics-ledger.ts +51 -0
  573. package/src/lsp/edits.ts +288 -0
  574. package/src/lsp/format-options.ts +119 -0
  575. package/src/lsp/index.ts +2766 -0
  576. package/src/lsp/lspmux.ts +233 -0
  577. package/src/lsp/render.ts +668 -0
  578. package/src/lsp/startup-events.ts +13 -0
  579. package/src/lsp/types.ts +453 -0
  580. package/src/lsp/utils.ts +718 -0
  581. package/src/main.ts +1647 -0
  582. package/src/markit/NOTICE +32 -0
  583. package/src/markit/converters/docx.ts +56 -0
  584. package/src/markit/converters/epub.ts +136 -0
  585. package/src/markit/converters/mammoth.d.ts +24 -0
  586. package/src/markit/converters/pdf/columns.ts +103 -0
  587. package/src/markit/converters/pdf/extract.ts +598 -0
  588. package/src/markit/converters/pdf/grid.ts +780 -0
  589. package/src/markit/converters/pdf/headers.ts +106 -0
  590. package/src/markit/converters/pdf/index.ts +146 -0
  591. package/src/markit/converters/pdf/render.ts +501 -0
  592. package/src/markit/converters/pdf/types.ts +84 -0
  593. package/src/markit/converters/pptx.ts +325 -0
  594. package/src/markit/converters/xlsx.ts +173 -0
  595. package/src/markit/index.ts +2 -0
  596. package/src/markit/registry.ts +59 -0
  597. package/src/markit/types.ts +35 -0
  598. package/src/mcp/client.ts +511 -0
  599. package/src/mcp/config-writer.ts +377 -0
  600. package/src/mcp/config.ts +381 -0
  601. package/src/mcp/index.ts +29 -0
  602. package/src/mcp/json-rpc.ts +122 -0
  603. package/src/mcp/loader.ts +125 -0
  604. package/src/mcp/manager.ts +1419 -0
  605. package/src/mcp/oauth-credentials.ts +104 -0
  606. package/src/mcp/oauth-discovery.ts +587 -0
  607. package/src/mcp/oauth-flow.ts +820 -0
  608. package/src/mcp/render.ts +214 -0
  609. package/src/mcp/smithery-auth.ts +108 -0
  610. package/src/mcp/smithery-connect.ts +154 -0
  611. package/src/mcp/smithery-registry.ts +500 -0
  612. package/src/mcp/startup-events.ts +116 -0
  613. package/src/mcp/timeout.ts +59 -0
  614. package/src/mcp/tool-bridge.ts +691 -0
  615. package/src/mcp/tool-cache.ts +117 -0
  616. package/src/mcp/transports/http.ts +523 -0
  617. package/src/mcp/transports/index.ts +7 -0
  618. package/src/mcp/transports/sse.ts +377 -0
  619. package/src/mcp/transports/stdio.ts +903 -0
  620. package/src/mcp/types.ts +437 -0
  621. package/src/memories/index.ts +1434 -0
  622. package/src/memories/storage.ts +578 -0
  623. package/src/memory-backend/index.ts +18 -0
  624. package/src/memory-backend/local-backend.ts +47 -0
  625. package/src/memory-backend/off-backend.ts +25 -0
  626. package/src/memory-backend/resolve.ts +25 -0
  627. package/src/memory-backend/runtime.ts +66 -0
  628. package/src/memory-backend/tool-names.ts +2 -0
  629. package/src/memory-backend/types.ts +166 -0
  630. package/src/mnemopi/backend.ts +629 -0
  631. package/src/mnemopi/config.ts +267 -0
  632. package/src/mnemopi/embed-client.ts +246 -0
  633. package/src/mnemopi/embed-protocol.ts +35 -0
  634. package/src/mnemopi/embed-worker.ts +114 -0
  635. package/src/mnemopi/index.ts +3 -0
  636. package/src/mnemopi/state.ts +906 -0
  637. package/src/modes/acp/acp-agent.ts +2577 -0
  638. package/src/modes/acp/acp-client-bridge.ts +154 -0
  639. package/src/modes/acp/acp-event-mapper.ts +1084 -0
  640. package/src/modes/acp/acp-mode.ts +48 -0
  641. package/src/modes/acp/index.ts +2 -0
  642. package/src/modes/acp/terminal-auth.ts +37 -0
  643. package/src/modes/components/advisor-config.ts +635 -0
  644. package/src/modes/components/advisor-message.ts +109 -0
  645. package/src/modes/components/agent-dashboard.ts +1252 -0
  646. package/src/modes/components/agent-hub.ts +648 -0
  647. package/src/modes/components/agent-transcript-viewer.ts +649 -0
  648. package/src/modes/components/ask-dialog.ts +975 -0
  649. package/src/modes/components/assistant-message.ts +972 -0
  650. package/src/modes/components/background-tan-message.ts +36 -0
  651. package/src/modes/components/bash-execution.ts +233 -0
  652. package/src/modes/components/bordered-loader.ts +41 -0
  653. package/src/modes/components/btw-panel.ts +124 -0
  654. package/src/modes/components/cache-invalidation-marker.ts +110 -0
  655. package/src/modes/components/chat-block.ts +111 -0
  656. package/src/modes/components/chat-transcript-builder.ts +495 -0
  657. package/src/modes/components/collab-prompt-message.ts +32 -0
  658. package/src/modes/components/compaction-summary-message.ts +221 -0
  659. package/src/modes/components/copy-selector.ts +218 -0
  660. package/src/modes/components/countdown-timer.ts +75 -0
  661. package/src/modes/components/custom-editor.ts +1027 -0
  662. package/src/modes/components/custom-message.ts +70 -0
  663. package/src/modes/components/diff.ts +254 -0
  664. package/src/modes/components/dynamic-border.ts +37 -0
  665. package/src/modes/components/error-banner.ts +33 -0
  666. package/src/modes/components/eval-execution.ts +169 -0
  667. package/src/modes/components/execution-shared.ts +101 -0
  668. package/src/modes/components/extensions/extension-dashboard.ts +492 -0
  669. package/src/modes/components/extensions/extension-list.ts +507 -0
  670. package/src/modes/components/extensions/index.ts +9 -0
  671. package/src/modes/components/extensions/inspector-panel.ts +321 -0
  672. package/src/modes/components/extensions/state-manager.ts +648 -0
  673. package/src/modes/components/extensions/types.ts +186 -0
  674. package/src/modes/components/footer.ts +276 -0
  675. package/src/modes/components/history-search.ts +268 -0
  676. package/src/modes/components/hook-editor.ts +213 -0
  677. package/src/modes/components/hook-input.ts +87 -0
  678. package/src/modes/components/hook-message.ts +67 -0
  679. package/src/modes/components/hook-selector.ts +691 -0
  680. package/src/modes/components/index.ts +42 -0
  681. package/src/modes/components/keybinding-hints.ts +65 -0
  682. package/src/modes/components/late-diagnostics-message.ts +60 -0
  683. package/src/modes/components/login-dialog.ts +197 -0
  684. package/src/modes/components/logout-account-selector.ts +130 -0
  685. package/src/modes/components/mcp-add-wizard.ts +1413 -0
  686. package/src/modes/components/message-frame.ts +98 -0
  687. package/src/modes/components/model-browser.ts +872 -0
  688. package/src/modes/components/model-hub.ts +2011 -0
  689. package/src/modes/components/model-picker.ts +233 -0
  690. package/src/modes/components/move-overlay.ts +293 -0
  691. package/src/modes/components/oauth-selector.ts +474 -0
  692. package/src/modes/components/omfg-panel.ts +141 -0
  693. package/src/modes/components/overlay-box.ts +109 -0
  694. package/src/modes/components/pause-screen.ts +208 -0
  695. package/src/modes/components/plan-review-overlay.ts +1226 -0
  696. package/src/modes/components/plan-toc.ts +138 -0
  697. package/src/modes/components/plugin-selector.ts +100 -0
  698. package/src/modes/components/plugin-settings.ts +745 -0
  699. package/src/modes/components/queue-mode-selector.ts +61 -0
  700. package/src/modes/components/read-tool-group.ts +678 -0
  701. package/src/modes/components/reset-usage-selector.ts +161 -0
  702. package/src/modes/components/segment-track.ts +89 -0
  703. package/src/modes/components/select-list-mouse-routing.ts +35 -0
  704. package/src/modes/components/selector-helpers.ts +129 -0
  705. package/src/modes/components/session-account-selector.ts +62 -0
  706. package/src/modes/components/session-selector.ts +1019 -0
  707. package/src/modes/components/settings-defs.ts +267 -0
  708. package/src/modes/components/settings-selector.ts +1445 -0
  709. package/src/modes/components/show-images-selector.ts +50 -0
  710. package/src/modes/components/skill-message.ts +110 -0
  711. package/src/modes/components/snapcompact-shape-preview-doc.md +14 -0
  712. package/src/modes/components/snapcompact-shape-preview.ts +192 -0
  713. package/src/modes/components/status-line/component.ts +1516 -0
  714. package/src/modes/components/status-line/context-thresholds.ts +86 -0
  715. package/src/modes/components/status-line/git-utils.ts +42 -0
  716. package/src/modes/components/status-line/index.ts +5 -0
  717. package/src/modes/components/status-line/presets.ts +106 -0
  718. package/src/modes/components/status-line/segments.ts +710 -0
  719. package/src/modes/components/status-line/separators.ts +55 -0
  720. package/src/modes/components/status-line/types.ts +159 -0
  721. package/src/modes/components/theme-selector.ts +68 -0
  722. package/src/modes/components/thinking-selector.ts +57 -0
  723. package/src/modes/components/tiny-title-download-progress.ts +90 -0
  724. package/src/modes/components/tips.txt +26 -0
  725. package/src/modes/components/todo-reminder.ts +43 -0
  726. package/src/modes/components/tool-execution.ts +1356 -0
  727. package/src/modes/components/transcript-container.ts +527 -0
  728. package/src/modes/components/tree-selector.ts +1008 -0
  729. package/src/modes/components/ttsr-notification.ts +123 -0
  730. package/src/modes/components/usage-row.ts +47 -0
  731. package/src/modes/components/user-message-selector.ts +227 -0
  732. package/src/modes/components/user-message.ts +167 -0
  733. package/src/modes/components/visual-truncate.ts +63 -0
  734. package/src/modes/components/welcome.ts +578 -0
  735. package/src/modes/controllers/btw-controller.ts +198 -0
  736. package/src/modes/controllers/command-controller-shared.ts +109 -0
  737. package/src/modes/controllers/command-controller.ts +1993 -0
  738. package/src/modes/controllers/event-controller.ts +1781 -0
  739. package/src/modes/controllers/extension-ui-controller.ts +1242 -0
  740. package/src/modes/controllers/input-controller.ts +2004 -0
  741. package/src/modes/controllers/live-command-controller.ts +260 -0
  742. package/src/modes/controllers/mcp-command-controller.ts +2403 -0
  743. package/src/modes/controllers/omfg-controller.ts +287 -0
  744. package/src/modes/controllers/omfg-rule.ts +647 -0
  745. package/src/modes/controllers/selector-controller.ts +1968 -0
  746. package/src/modes/controllers/session-focus-controller.ts +117 -0
  747. package/src/modes/controllers/ssh-command-controller.ts +385 -0
  748. package/src/modes/controllers/streaming-reveal.ts +399 -0
  749. package/src/modes/controllers/tan-command-controller.ts +229 -0
  750. package/src/modes/controllers/todo-command-controller.ts +487 -0
  751. package/src/modes/controllers/tool-args-reveal.ts +591 -0
  752. package/src/modes/data/emojis.json +1 -0
  753. package/src/modes/emoji-autocomplete.ts +285 -0
  754. package/src/modes/github-ref-autocomplete.ts +75 -0
  755. package/src/modes/gradient-highlight.ts +99 -0
  756. package/src/modes/image-references.ts +137 -0
  757. package/src/modes/index.ts +10 -0
  758. package/src/modes/interactive-mode.ts +4957 -0
  759. package/src/modes/internal-url-autocomplete.ts +158 -0
  760. package/src/modes/loop-limit.ts +192 -0
  761. package/src/modes/magic-keyword-boundary.ts +23 -0
  762. package/src/modes/magic-keywords.ts +42 -0
  763. package/src/modes/markdown-prose.ts +247 -0
  764. package/src/modes/oauth-manual-input.ts +69 -0
  765. package/src/modes/orchestrate.ts +43 -0
  766. package/src/modes/print-mode.ts +265 -0
  767. package/src/modes/prompt-action-autocomplete.ts +322 -0
  768. package/src/modes/queue-input.ts +132 -0
  769. package/src/modes/rpc/host-tools.ts +204 -0
  770. package/src/modes/rpc/host-uris.ts +235 -0
  771. package/src/modes/rpc/rpc-client.ts +1195 -0
  772. package/src/modes/rpc/rpc-frame.ts +316 -0
  773. package/src/modes/rpc/rpc-input.ts +38 -0
  774. package/src/modes/rpc/rpc-messages.ts +127 -0
  775. package/src/modes/rpc/rpc-mode.ts +1504 -0
  776. package/src/modes/rpc/rpc-subagents.ts +265 -0
  777. package/src/modes/rpc/rpc-types.ts +533 -0
  778. package/src/modes/running-subagent-badge.ts +13 -0
  779. package/src/modes/runtime-init.ts +144 -0
  780. package/src/modes/session-observer-registry.ts +218 -0
  781. package/src/modes/session-teardown.ts +82 -0
  782. package/src/modes/setup-version.ts +11 -0
  783. package/src/modes/setup-wizard/index.ts +103 -0
  784. package/src/modes/setup-wizard/lazy.ts +16 -0
  785. package/src/modes/setup-wizard/scenes/glyph.ts +103 -0
  786. package/src/modes/setup-wizard/scenes/model.ts +132 -0
  787. package/src/modes/setup-wizard/scenes/outro.ts +35 -0
  788. package/src/modes/setup-wizard/scenes/providers.ts +105 -0
  789. package/src/modes/setup-wizard/scenes/sign-in.ts +312 -0
  790. package/src/modes/setup-wizard/scenes/splash.ts +201 -0
  791. package/src/modes/setup-wizard/scenes/theme.ts +330 -0
  792. package/src/modes/setup-wizard/scenes/types.ts +65 -0
  793. package/src/modes/setup-wizard/scenes/web-search.ts +153 -0
  794. package/src/modes/setup-wizard/startup-splash.ts +107 -0
  795. package/src/modes/setup-wizard/wizard-overlay.ts +335 -0
  796. package/src/modes/shared.ts +49 -0
  797. package/src/modes/skill-command.ts +91 -0
  798. package/src/modes/theme/dark.json +95 -0
  799. package/src/modes/theme/defaults/alabaster.json +93 -0
  800. package/src/modes/theme/defaults/amethyst.json +96 -0
  801. package/src/modes/theme/defaults/anthracite.json +93 -0
  802. package/src/modes/theme/defaults/basalt.json +91 -0
  803. package/src/modes/theme/defaults/birch.json +95 -0
  804. package/src/modes/theme/defaults/dark-abyss.json +91 -0
  805. package/src/modes/theme/defaults/dark-arctic.json +104 -0
  806. package/src/modes/theme/defaults/dark-aurora.json +95 -0
  807. package/src/modes/theme/defaults/dark-catppuccin.json +107 -0
  808. package/src/modes/theme/defaults/dark-cavern.json +91 -0
  809. package/src/modes/theme/defaults/dark-copper.json +95 -0
  810. package/src/modes/theme/defaults/dark-cosmos.json +90 -0
  811. package/src/modes/theme/defaults/dark-cyberpunk.json +102 -0
  812. package/src/modes/theme/defaults/dark-dracula.json +98 -0
  813. package/src/modes/theme/defaults/dark-eclipse.json +91 -0
  814. package/src/modes/theme/defaults/dark-ember.json +95 -0
  815. package/src/modes/theme/defaults/dark-equinox.json +90 -0
  816. package/src/modes/theme/defaults/dark-forest.json +96 -0
  817. package/src/modes/theme/defaults/dark-github.json +105 -0
  818. package/src/modes/theme/defaults/dark-gruvbox.json +112 -0
  819. package/src/modes/theme/defaults/dark-lavender.json +95 -0
  820. package/src/modes/theme/defaults/dark-lunar.json +89 -0
  821. package/src/modes/theme/defaults/dark-midnight.json +95 -0
  822. package/src/modes/theme/defaults/dark-monochrome.json +94 -0
  823. package/src/modes/theme/defaults/dark-monokai.json +98 -0
  824. package/src/modes/theme/defaults/dark-nebula.json +90 -0
  825. package/src/modes/theme/defaults/dark-nord.json +97 -0
  826. package/src/modes/theme/defaults/dark-ocean.json +101 -0
  827. package/src/modes/theme/defaults/dark-one.json +100 -0
  828. package/src/modes/theme/defaults/dark-poimandres.json +143 -0
  829. package/src/modes/theme/defaults/dark-rainforest.json +91 -0
  830. package/src/modes/theme/defaults/dark-reef.json +91 -0
  831. package/src/modes/theme/defaults/dark-retro.json +92 -0
  832. package/src/modes/theme/defaults/dark-rose-pine.json +96 -0
  833. package/src/modes/theme/defaults/dark-sakura.json +95 -0
  834. package/src/modes/theme/defaults/dark-slate.json +95 -0
  835. package/src/modes/theme/defaults/dark-solarized.json +97 -0
  836. package/src/modes/theme/defaults/dark-solstice.json +90 -0
  837. package/src/modes/theme/defaults/dark-starfall.json +91 -0
  838. package/src/modes/theme/defaults/dark-sunset.json +99 -0
  839. package/src/modes/theme/defaults/dark-swamp.json +90 -0
  840. package/src/modes/theme/defaults/dark-synthwave.json +103 -0
  841. package/src/modes/theme/defaults/dark-taiga.json +91 -0
  842. package/src/modes/theme/defaults/dark-terminal.json +95 -0
  843. package/src/modes/theme/defaults/dark-tokyo-night.json +101 -0
  844. package/src/modes/theme/defaults/dark-tundra.json +91 -0
  845. package/src/modes/theme/defaults/dark-twilight.json +91 -0
  846. package/src/modes/theme/defaults/dark-volcanic.json +91 -0
  847. package/src/modes/theme/defaults/graphite.json +92 -0
  848. package/src/modes/theme/defaults/index.ts +199 -0
  849. package/src/modes/theme/defaults/light-arctic.json +107 -0
  850. package/src/modes/theme/defaults/light-aurora-day.json +91 -0
  851. package/src/modes/theme/defaults/light-canyon.json +91 -0
  852. package/src/modes/theme/defaults/light-catppuccin.json +106 -0
  853. package/src/modes/theme/defaults/light-cirrus.json +90 -0
  854. package/src/modes/theme/defaults/light-coral.json +95 -0
  855. package/src/modes/theme/defaults/light-cyberpunk.json +96 -0
  856. package/src/modes/theme/defaults/light-dawn.json +90 -0
  857. package/src/modes/theme/defaults/light-dunes.json +91 -0
  858. package/src/modes/theme/defaults/light-eucalyptus.json +95 -0
  859. package/src/modes/theme/defaults/light-forest.json +100 -0
  860. package/src/modes/theme/defaults/light-frost.json +95 -0
  861. package/src/modes/theme/defaults/light-github.json +115 -0
  862. package/src/modes/theme/defaults/light-glacier.json +91 -0
  863. package/src/modes/theme/defaults/light-gruvbox.json +108 -0
  864. package/src/modes/theme/defaults/light-haze.json +90 -0
  865. package/src/modes/theme/defaults/light-honeycomb.json +95 -0
  866. package/src/modes/theme/defaults/light-lagoon.json +91 -0
  867. package/src/modes/theme/defaults/light-lavender.json +95 -0
  868. package/src/modes/theme/defaults/light-meadow.json +91 -0
  869. package/src/modes/theme/defaults/light-mint.json +95 -0
  870. package/src/modes/theme/defaults/light-monochrome.json +101 -0
  871. package/src/modes/theme/defaults/light-ocean.json +99 -0
  872. package/src/modes/theme/defaults/light-one.json +99 -0
  873. package/src/modes/theme/defaults/light-opal.json +91 -0
  874. package/src/modes/theme/defaults/light-orchard.json +91 -0
  875. package/src/modes/theme/defaults/light-paper.json +95 -0
  876. package/src/modes/theme/defaults/light-poimandres.json +143 -0
  877. package/src/modes/theme/defaults/light-prism.json +90 -0
  878. package/src/modes/theme/defaults/light-retro.json +98 -0
  879. package/src/modes/theme/defaults/light-sand.json +95 -0
  880. package/src/modes/theme/defaults/light-savanna.json +91 -0
  881. package/src/modes/theme/defaults/light-solarized.json +102 -0
  882. package/src/modes/theme/defaults/light-soleil.json +90 -0
  883. package/src/modes/theme/defaults/light-sunset.json +99 -0
  884. package/src/modes/theme/defaults/light-synthwave.json +98 -0
  885. package/src/modes/theme/defaults/light-tokyo-night.json +111 -0
  886. package/src/modes/theme/defaults/light-wetland.json +91 -0
  887. package/src/modes/theme/defaults/light-zenith.json +89 -0
  888. package/src/modes/theme/defaults/limestone.json +94 -0
  889. package/src/modes/theme/defaults/mahogany.json +97 -0
  890. package/src/modes/theme/defaults/marble.json +93 -0
  891. package/src/modes/theme/defaults/obsidian.json +91 -0
  892. package/src/modes/theme/defaults/onyx.json +91 -0
  893. package/src/modes/theme/defaults/pearl.json +93 -0
  894. package/src/modes/theme/defaults/porcelain.json +91 -0
  895. package/src/modes/theme/defaults/quartz.json +96 -0
  896. package/src/modes/theme/defaults/sandstone.json +95 -0
  897. package/src/modes/theme/defaults/titanium.json +90 -0
  898. package/src/modes/theme/light.json +93 -0
  899. package/src/modes/theme/mermaid-cache.ts +92 -0
  900. package/src/modes/theme/shimmer.ts +305 -0
  901. package/src/modes/theme/theme-schema.json +463 -0
  902. package/src/modes/theme/theme.ts +3019 -0
  903. package/src/modes/turn-budget.ts +31 -0
  904. package/src/modes/types.ts +479 -0
  905. package/src/modes/ultrathink.ts +42 -0
  906. package/src/modes/utils/context-usage.ts +518 -0
  907. package/src/modes/utils/copy-targets.ts +378 -0
  908. package/src/modes/utils/hotkeys-markdown.ts +63 -0
  909. package/src/modes/utils/interactive-context-helpers.ts +30 -0
  910. package/src/modes/utils/keybinding-matchers.ts +86 -0
  911. package/src/modes/utils/tools-markdown.ts +31 -0
  912. package/src/modes/utils/transcript-render-helpers.ts +253 -0
  913. package/src/modes/utils/ui-helpers.ts +963 -0
  914. package/src/modes/warp-events.ts +232 -0
  915. package/src/modes/workflow.ts +49 -0
  916. package/src/plan-mode/approved-plan.ts +194 -0
  917. package/src/plan-mode/model-transition.ts +51 -0
  918. package/src/plan-mode/plan-files.ts +40 -0
  919. package/src/plan-mode/plan-handoff.ts +37 -0
  920. package/src/plan-mode/plan-protection.ts +31 -0
  921. package/src/plan-mode/state.ts +6 -0
  922. package/src/priority.json +60 -0
  923. package/src/prompts/advisor/active-repo-watchdog.md +6 -0
  924. package/src/prompts/advisor/advise-tool.md +3 -0
  925. package/src/prompts/advisor/context-files.md +8 -0
  926. package/src/prompts/advisor/system.md +98 -0
  927. package/src/prompts/agents/designer.md +74 -0
  928. package/src/prompts/agents/frontmatter.md +12 -0
  929. package/src/prompts/agents/init.md +33 -0
  930. package/src/prompts/agents/librarian.md +119 -0
  931. package/src/prompts/agents/reviewer.md +139 -0
  932. package/src/prompts/agents/scout.md +58 -0
  933. package/src/prompts/agents/task.md +17 -0
  934. package/src/prompts/bench/cache-prefix-chunk.md +1 -0
  935. package/src/prompts/bench/cache-prefix.md +3 -0
  936. package/src/prompts/bench/cache-suffix.md +1 -0
  937. package/src/prompts/bench.md +6 -0
  938. package/src/prompts/ci-green-request.md +36 -0
  939. package/src/prompts/dry-balance-bench.md +8 -0
  940. package/src/prompts/goals/goal-budget-limit.md +16 -0
  941. package/src/prompts/goals/goal-continuation.md +28 -0
  942. package/src/prompts/goals/goal-mode-active.md +23 -0
  943. package/src/prompts/goals/goal-mode-context.md +4 -0
  944. package/src/prompts/goals/goal-todo-context.md +12 -0
  945. package/src/prompts/goals/guided-goal-interview.md +43 -0
  946. package/src/prompts/memories/consolidation.md +30 -0
  947. package/src/prompts/memories/consolidation_system.md +4 -0
  948. package/src/prompts/memories/read-path.md +17 -0
  949. package/src/prompts/memories/stage_one_input.md +6 -0
  950. package/src/prompts/memories/stage_one_system.md +21 -0
  951. package/src/prompts/review-custom-request.md +21 -0
  952. package/src/prompts/review-headless-request.md +16 -0
  953. package/src/prompts/review-request.md +68 -0
  954. package/src/prompts/skills/autoload.md +8 -0
  955. package/src/prompts/skills/user-invocation.md +11 -0
  956. package/src/prompts/steering/parent-irc.md +5 -0
  957. package/src/prompts/steering/user-interjection.md +6 -0
  958. package/src/prompts/system/active-repo-context.md +4 -0
  959. package/src/prompts/system/agent-creation-architect.md +50 -0
  960. package/src/prompts/system/agent-creation-user.md +6 -0
  961. package/src/prompts/system/auto-continue.md +1 -0
  962. package/src/prompts/system/auto-thinking-difficulty-local.md +14 -0
  963. package/src/prompts/system/auto-thinking-difficulty.md +12 -0
  964. package/src/prompts/system/autolearn-guidance-learn.md +1 -0
  965. package/src/prompts/system/autolearn-guidance.md +7 -0
  966. package/src/prompts/system/autolearn-nudge-autocontinue.md +5 -0
  967. package/src/prompts/system/background-tan-dispatch.md +8 -0
  968. package/src/prompts/system/btw-user.md +8 -0
  969. package/src/prompts/system/commit-message-system.md +14 -0
  970. package/src/prompts/system/computer-safety.md +14 -0
  971. package/src/prompts/system/custom-system-prompt.md +64 -0
  972. package/src/prompts/system/eager-task.md +7 -0
  973. package/src/prompts/system/eager-todo.md +18 -0
  974. package/src/prompts/system/empty-stop-retry.md +4 -0
  975. package/src/prompts/system/gemini-tool-call-reminder.md +9 -0
  976. package/src/prompts/system/interrupted-thinking.md +7 -0
  977. package/src/prompts/system/irc-autoreply.md +6 -0
  978. package/src/prompts/system/irc-incoming.md +9 -0
  979. package/src/prompts/system/manual-continue.md +7 -0
  980. package/src/prompts/system/mcp-xdev-guidance.md +11 -0
  981. package/src/prompts/system/memory-consolidation-system.md +8 -0
  982. package/src/prompts/system/memory-extraction-system.md +26 -0
  983. package/src/prompts/system/mid-run-todo-nudge.md +3 -0
  984. package/src/prompts/system/omfg-user.md +50 -0
  985. package/src/prompts/system/orchestrate-notice.md +40 -0
  986. package/src/prompts/system/personalities/default.md +18 -0
  987. package/src/prompts/system/personalities/friendly.md +17 -0
  988. package/src/prompts/system/personalities/pragmatic.md +15 -0
  989. package/src/prompts/system/plan-mode-active.md +125 -0
  990. package/src/prompts/system/plan-mode-approved.md +22 -0
  991. package/src/prompts/system/plan-mode-compact-instructions.md +17 -0
  992. package/src/prompts/system/plan-mode-reference.md +10 -0
  993. package/src/prompts/system/plan-mode-subagent.md +33 -0
  994. package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
  995. package/src/prompts/system/plan-yolo-handoff.md +5 -0
  996. package/src/prompts/system/prewalk-checklist.md +7 -0
  997. package/src/prompts/system/prewalk-continue.md +1 -0
  998. package/src/prompts/system/prewalk-plan.md +13 -0
  999. package/src/prompts/system/project-prompt.md +61 -0
  1000. package/src/prompts/system/recap-user.md +9 -0
  1001. package/src/prompts/system/resolve-device-reminder.md +3 -0
  1002. package/src/prompts/system/rewind-report.md +6 -0
  1003. package/src/prompts/system/side-channel-no-tools.md +3 -0
  1004. package/src/prompts/system/snapcompact-context-frames-note.md +1 -0
  1005. package/src/prompts/system/snapcompact-context-stub.md +1 -0
  1006. package/src/prompts/system/snapcompact-system-frames-note.md +1 -0
  1007. package/src/prompts/system/snapcompact-system-stub.md +1 -0
  1008. package/src/prompts/system/snapcompact-toolresult-note.md +1 -0
  1009. package/src/prompts/system/speech-rewrite.md +15 -0
  1010. package/src/prompts/system/subagent-async-pending.md +6 -0
  1011. package/src/prompts/system/subagent-system-prompt.md +73 -0
  1012. package/src/prompts/system/subagent-user-prompt.md +3 -0
  1013. package/src/prompts/system/subagent-yield-reminder.md +23 -0
  1014. package/src/prompts/system/system-prompt.md +283 -0
  1015. package/src/prompts/system/tan-context-switch.md +17 -0
  1016. package/src/prompts/system/task-label.md +23 -0
  1017. package/src/prompts/system/thinking-loop-redirect.md +10 -0
  1018. package/src/prompts/system/title-marker-instruction.md +1 -0
  1019. package/src/prompts/system/title-system.md +16 -0
  1020. package/src/prompts/system/tool-call-loop-redirect.md +8 -0
  1021. package/src/prompts/system/ttsr-interrupt.md +7 -0
  1022. package/src/prompts/system/ttsr-tool-reminder.md +5 -0
  1023. package/src/prompts/system/ultrathink-notice.md +3 -0
  1024. package/src/prompts/system/unexpected-stop-classifier.md +17 -0
  1025. package/src/prompts/system/unexpected-stop-retry.md +4 -0
  1026. package/src/prompts/system/vibe-mode-active.md +26 -0
  1027. package/src/prompts/system/web-search.md +25 -0
  1028. package/src/prompts/system/workflow-notice.md +112 -0
  1029. package/src/prompts/system/xdev-mount-notice.md +20 -0
  1030. package/src/prompts/tools/apply-patch.md +65 -0
  1031. package/src/prompts/tools/ask.md +22 -0
  1032. package/src/prompts/tools/ast-edit.md +11 -0
  1033. package/src/prompts/tools/ast-grep.md +19 -0
  1034. package/src/prompts/tools/async-result.md +8 -0
  1035. package/src/prompts/tools/bash.md +25 -0
  1036. package/src/prompts/tools/browser.md +28 -0
  1037. package/src/prompts/tools/checkpoint.md +15 -0
  1038. package/src/prompts/tools/computer.md +26 -0
  1039. package/src/prompts/tools/debug.md +3 -0
  1040. package/src/prompts/tools/eval.md +45 -0
  1041. package/src/prompts/tools/github.md +22 -0
  1042. package/src/prompts/tools/glob.md +15 -0
  1043. package/src/prompts/tools/goal.md +11 -0
  1044. package/src/prompts/tools/grep.md +12 -0
  1045. package/src/prompts/tools/hub.md +34 -0
  1046. package/src/prompts/tools/image-attachment-describe-system.md +8 -0
  1047. package/src/prompts/tools/image-attachment-describe.md +10 -0
  1048. package/src/prompts/tools/image-gen.md +7 -0
  1049. package/src/prompts/tools/inspect-image-system.md +20 -0
  1050. package/src/prompts/tools/inspect-image.md +22 -0
  1051. package/src/prompts/tools/learn.md +7 -0
  1052. package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
  1053. package/src/prompts/tools/lsp.md +19 -0
  1054. package/src/prompts/tools/manage-skill.md +9 -0
  1055. package/src/prompts/tools/memory-edit.md +12 -0
  1056. package/src/prompts/tools/patch.md +57 -0
  1057. package/src/prompts/tools/read.md +27 -0
  1058. package/src/prompts/tools/recall.md +7 -0
  1059. package/src/prompts/tools/reflect.md +5 -0
  1060. package/src/prompts/tools/replace.md +29 -0
  1061. package/src/prompts/tools/retain.md +6 -0
  1062. package/src/prompts/tools/rewind.md +14 -0
  1063. package/src/prompts/tools/task-async-contract.md +1 -0
  1064. package/src/prompts/tools/task-summary.md +20 -0
  1065. package/src/prompts/tools/task.md +83 -0
  1066. package/src/prompts/tools/todo.md +42 -0
  1067. package/src/prompts/tools/vibe-kill.md +3 -0
  1068. package/src/prompts/tools/vibe-list.md +3 -0
  1069. package/src/prompts/tools/vibe-send.md +9 -0
  1070. package/src/prompts/tools/vibe-spawn.md +10 -0
  1071. package/src/prompts/tools/vibe-turn-result.md +19 -0
  1072. package/src/prompts/tools/vibe-wait.md +8 -0
  1073. package/src/prompts/tools/web-search.md +8 -0
  1074. package/src/prompts/tools/write.md +14 -0
  1075. package/src/registry/agent-lifecycle.ts +455 -0
  1076. package/src/registry/agent-registry.ts +217 -0
  1077. package/src/registry/persisted-agents.ts +98 -0
  1078. package/src/sdk.ts +3553 -0
  1079. package/src/secrets/index.ts +246 -0
  1080. package/src/secrets/obfuscator.ts +2574 -0
  1081. package/src/secrets/regex.ts +21 -0
  1082. package/src/session/acp-permission-gate.ts +165 -0
  1083. package/src/session/agent-session-events.ts +66 -0
  1084. package/src/session/agent-session-types.ts +346 -0
  1085. package/src/session/agent-session.ts +8406 -0
  1086. package/src/session/agent-storage.ts +805 -0
  1087. package/src/session/artifacts.ts +154 -0
  1088. package/src/session/async-job-delivery.ts +82 -0
  1089. package/src/session/auth-broker-config.ts +92 -0
  1090. package/src/session/auth-storage.ts +25 -0
  1091. package/src/session/bash-runner.ts +326 -0
  1092. package/src/session/blob-store.ts +295 -0
  1093. package/src/session/checkpoint-entries.ts +81 -0
  1094. package/src/session/client-bridge.ts +85 -0
  1095. package/src/session/codex-auto-reset.ts +202 -0
  1096. package/src/session/compact-modes.ts +105 -0
  1097. package/src/session/eval-runner.ts +217 -0
  1098. package/src/session/exit-diagnostics.ts +310 -0
  1099. package/src/session/history-storage.ts +327 -0
  1100. package/src/session/indexed-session-storage.ts +544 -0
  1101. package/src/session/irc-bridge.ts +203 -0
  1102. package/src/session/messages.ts +1280 -0
  1103. package/src/session/model-controls.ts +750 -0
  1104. package/src/session/prewalk.ts +257 -0
  1105. package/src/session/provider-image-budget.ts +86 -0
  1106. package/src/session/queued-messages.ts +99 -0
  1107. package/src/session/redis-session-storage.ts +257 -0
  1108. package/src/session/retry-fallback-chains.ts +455 -0
  1109. package/src/session/role-models.ts +85 -0
  1110. package/src/session/session-advisors.ts +1754 -0
  1111. package/src/session/session-context.ts +554 -0
  1112. package/src/session/session-dump-format.ts +216 -0
  1113. package/src/session/session-entries.ts +260 -0
  1114. package/src/session/session-handoff.ts +308 -0
  1115. package/src/session/session-history-format.ts +459 -0
  1116. package/src/session/session-listing.ts +715 -0
  1117. package/src/session/session-loader.ts +280 -0
  1118. package/src/session/session-maintenance.ts +2983 -0
  1119. package/src/session/session-manager.ts +2557 -0
  1120. package/src/session/session-memory.ts +222 -0
  1121. package/src/session/session-metadata.ts +53 -0
  1122. package/src/session/session-migrations.ts +78 -0
  1123. package/src/session/session-paths.ts +222 -0
  1124. package/src/session/session-persistence.ts +293 -0
  1125. package/src/session/session-provider-boundary.ts +306 -0
  1126. package/src/session/session-stats.ts +293 -0
  1127. package/src/session/session-storage.ts +734 -0
  1128. package/src/session/session-title-slot.ts +141 -0
  1129. package/src/session/session-tools.ts +1226 -0
  1130. package/src/session/session-workspace.ts +53 -0
  1131. package/src/session/settings-stream-fn.ts +74 -0
  1132. package/src/session/shake-types.ts +43 -0
  1133. package/src/session/snapcompact-inline.ts +545 -0
  1134. package/src/session/snapcompact-savings-journal.ts +113 -0
  1135. package/src/session/sql-session-storage.ts +374 -0
  1136. package/src/session/stream-guards.ts +417 -0
  1137. package/src/session/streaming-output.ts +1459 -0
  1138. package/src/session/todo-tracker.ts +380 -0
  1139. package/src/session/tool-choice-queue.ts +305 -0
  1140. package/src/session/ttsr-coordinator.ts +496 -0
  1141. package/src/session/turn-persistence.ts +142 -0
  1142. package/src/session/turn-recovery.ts +1728 -0
  1143. package/src/session/unexpected-stop-classifier.ts +132 -0
  1144. package/src/session/yield-queue.ts +183 -0
  1145. package/src/slash-commands/acp-builtins.ts +70 -0
  1146. package/src/slash-commands/available-commands.ts +105 -0
  1147. package/src/slash-commands/builtin-registry.ts +2982 -0
  1148. package/src/slash-commands/helpers/active-oauth-account.ts +80 -0
  1149. package/src/slash-commands/helpers/collab-qrcode.ts +28 -0
  1150. package/src/slash-commands/helpers/context-report.ts +66 -0
  1151. package/src/slash-commands/helpers/format.ts +46 -0
  1152. package/src/slash-commands/helpers/logout.ts +108 -0
  1153. package/src/slash-commands/helpers/marketplace-manager.ts +25 -0
  1154. package/src/slash-commands/helpers/mcp.ts +533 -0
  1155. package/src/slash-commands/helpers/parse.ts +85 -0
  1156. package/src/slash-commands/helpers/reset-usage.ts +66 -0
  1157. package/src/slash-commands/helpers/session-pin.ts +44 -0
  1158. package/src/slash-commands/helpers/ssh.ts +196 -0
  1159. package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
  1160. package/src/slash-commands/helpers/todo.ts +285 -0
  1161. package/src/slash-commands/helpers/usage-report.ts +198 -0
  1162. package/src/slash-commands/marketplace-install-parser.ts +99 -0
  1163. package/src/slash-commands/types.ts +139 -0
  1164. package/src/ssh/config-writer.ts +183 -0
  1165. package/src/ssh/connection-manager.ts +667 -0
  1166. package/src/ssh/file-transfer.ts +214 -0
  1167. package/src/ssh/sshfs-mount.ts +163 -0
  1168. package/src/ssh/utils.ts +51 -0
  1169. package/src/startup-splash.ts +19 -0
  1170. package/src/stt/asr-client.ts +401 -0
  1171. package/src/stt/asr-protocol.ts +65 -0
  1172. package/src/stt/asr-worker.ts +603 -0
  1173. package/src/stt/downloader.ts +142 -0
  1174. package/src/stt/endpointer.ts +259 -0
  1175. package/src/stt/index.ts +6 -0
  1176. package/src/stt/models.ts +150 -0
  1177. package/src/stt/sherpa-runtime.ts +71 -0
  1178. package/src/stt/stt-controller.ts +320 -0
  1179. package/src/stt/submit-trigger.ts +74 -0
  1180. package/src/subprocess/worker-client.ts +463 -0
  1181. package/src/subprocess/worker-runtime.ts +494 -0
  1182. package/src/system-prompt.ts +894 -0
  1183. package/src/task/agents.ts +168 -0
  1184. package/src/task/commands.ts +132 -0
  1185. package/src/task/discovery.ts +145 -0
  1186. package/src/task/executor.ts +3129 -0
  1187. package/src/task/index.ts +1519 -0
  1188. package/src/task/isolation-ownership.ts +106 -0
  1189. package/src/task/isolation-runner.ts +413 -0
  1190. package/src/task/label.ts +40 -0
  1191. package/src/task/name-generator.ts +1577 -0
  1192. package/src/task/omp-command.ts +26 -0
  1193. package/src/task/output-manager.ts +115 -0
  1194. package/src/task/parallel.ts +221 -0
  1195. package/src/task/persisted-revive.ts +141 -0
  1196. package/src/task/prewalk.ts +6 -0
  1197. package/src/task/prompt-policy.ts +8 -0
  1198. package/src/task/provider-concurrency.ts +100 -0
  1199. package/src/task/render.ts +1814 -0
  1200. package/src/task/renderer.ts +14 -0
  1201. package/src/task/repair-args.ts +118 -0
  1202. package/src/task/spawn-policy.ts +58 -0
  1203. package/src/task/structured-subagent.ts +649 -0
  1204. package/src/task/subprocess-tool-registry.ts +88 -0
  1205. package/src/task/types.ts +551 -0
  1206. package/src/task/worktree.ts +967 -0
  1207. package/src/task/yield-assembly.ts +198 -0
  1208. package/src/telemetry-export.ts +500 -0
  1209. package/src/thinking.ts +364 -0
  1210. package/src/tiny/device.ts +111 -0
  1211. package/src/tiny/dtype.ts +101 -0
  1212. package/src/tiny/message-preproc.ts +155 -0
  1213. package/src/tiny/models.ts +268 -0
  1214. package/src/tiny/text.ts +278 -0
  1215. package/src/tiny/title-client.ts +460 -0
  1216. package/src/tiny/title-protocol.ts +56 -0
  1217. package/src/tiny/worker.ts +354 -0
  1218. package/src/tools/acp-bridge.ts +81 -0
  1219. package/src/tools/approval.ts +245 -0
  1220. package/src/tools/ask.ts +1459 -0
  1221. package/src/tools/ast-edit.ts +718 -0
  1222. package/src/tools/ast-grep.ts +520 -0
  1223. package/src/tools/auto-generated-guard.ts +335 -0
  1224. package/src/tools/bash-interactive.ts +435 -0
  1225. package/src/tools/bash-interceptor.ts +67 -0
  1226. package/src/tools/bash-pty-selection.ts +14 -0
  1227. package/src/tools/bash-skill-urls.ts +335 -0
  1228. package/src/tools/bash.ts +1762 -0
  1229. package/src/tools/browser/aria/aria-snapshot.bundle.txt +7 -0
  1230. package/src/tools/browser/aria/aria-snapshot.ts +131 -0
  1231. package/src/tools/browser/attach.ts +194 -0
  1232. package/src/tools/browser/cmux/cmux-tab.ts +1400 -0
  1233. package/src/tools/browser/cmux/rpc.ts +206 -0
  1234. package/src/tools/browser/cmux/socket-client.ts +445 -0
  1235. package/src/tools/browser/launch.ts +788 -0
  1236. package/src/tools/browser/readable.ts +112 -0
  1237. package/src/tools/browser/registry.ts +287 -0
  1238. package/src/tools/browser/render.ts +226 -0
  1239. package/src/tools/browser/run-cancellation.ts +131 -0
  1240. package/src/tools/browser/run-output.ts +76 -0
  1241. package/src/tools/browser/tab-protocol.ts +115 -0
  1242. package/src/tools/browser/tab-supervisor.ts +1040 -0
  1243. package/src/tools/browser/tab-worker-entry.ts +29 -0
  1244. package/src/tools/browser/tab-worker.ts +1842 -0
  1245. package/src/tools/browser.ts +457 -0
  1246. package/src/tools/builtin-names.ts +66 -0
  1247. package/src/tools/checkpoint.ts +150 -0
  1248. package/src/tools/computer/exposure.ts +38 -0
  1249. package/src/tools/computer/protocol.ts +28 -0
  1250. package/src/tools/computer/supervisor.ts +306 -0
  1251. package/src/tools/computer/worker-entry.ts +34 -0
  1252. package/src/tools/computer/worker.ts +131 -0
  1253. package/src/tools/computer-renderer.ts +108 -0
  1254. package/src/tools/computer.ts +516 -0
  1255. package/src/tools/conflict-detect.ts +815 -0
  1256. package/src/tools/context.ts +46 -0
  1257. package/src/tools/debug.ts +1121 -0
  1258. package/src/tools/default-renderer.ts +139 -0
  1259. package/src/tools/essential-tools.ts +46 -0
  1260. package/src/tools/eval-backends.ts +34 -0
  1261. package/src/tools/eval-format/index.ts +24 -0
  1262. package/src/tools/eval-format/javascript.ts +952 -0
  1263. package/src/tools/eval-format/julia.ts +446 -0
  1264. package/src/tools/eval-format/python.ts +544 -0
  1265. package/src/tools/eval-format/ruby.ts +380 -0
  1266. package/src/tools/eval-render.ts +784 -0
  1267. package/src/tools/eval.ts +774 -0
  1268. package/src/tools/fetch.ts +1889 -0
  1269. package/src/tools/file-recorder.ts +35 -0
  1270. package/src/tools/fs-cache-invalidation.ts +28 -0
  1271. package/src/tools/gh-cache-invalidation.ts +175 -0
  1272. package/src/tools/gh-format.ts +12 -0
  1273. package/src/tools/gh-renderer.ts +484 -0
  1274. package/src/tools/gh.ts +3959 -0
  1275. package/src/tools/github-cache.ts +663 -0
  1276. package/src/tools/glob.ts +682 -0
  1277. package/src/tools/grep.ts +1858 -0
  1278. package/src/tools/grouped-file-output.ts +210 -0
  1279. package/src/tools/hub/index.ts +579 -0
  1280. package/src/tools/hub/jobs.ts +714 -0
  1281. package/src/tools/hub/launch.ts +579 -0
  1282. package/src/tools/hub/messaging.ts +735 -0
  1283. package/src/tools/hub/types.ts +117 -0
  1284. package/src/tools/image-gen.ts +1689 -0
  1285. package/src/tools/image-providers.ts +50 -0
  1286. package/src/tools/index.ts +691 -0
  1287. package/src/tools/inspect-image-renderer.ts +133 -0
  1288. package/src/tools/inspect-image.ts +290 -0
  1289. package/src/tools/json-tree.ts +260 -0
  1290. package/src/tools/jtd-to-json-schema.ts +219 -0
  1291. package/src/tools/jtd-to-typescript.ts +136 -0
  1292. package/src/tools/jtd-utils.ts +102 -0
  1293. package/src/tools/learn.ts +141 -0
  1294. package/src/tools/list-limit.ts +40 -0
  1295. package/src/tools/manage-skill.ts +102 -0
  1296. package/src/tools/match-line-format.ts +20 -0
  1297. package/src/tools/memory-edit.ts +61 -0
  1298. package/src/tools/memory-recall.ts +102 -0
  1299. package/src/tools/memory-reflect.ts +88 -0
  1300. package/src/tools/memory-render.ts +211 -0
  1301. package/src/tools/memory-retain.ts +89 -0
  1302. package/src/tools/output-meta.ts +845 -0
  1303. package/src/tools/output-schema-validator.ts +307 -0
  1304. package/src/tools/path-utils.ts +1381 -0
  1305. package/src/tools/plan-mode-guard.ts +155 -0
  1306. package/src/tools/puppeteer/00_stealth_tampering.txt +44 -0
  1307. package/src/tools/puppeteer/01_stealth_activity.txt +80 -0
  1308. package/src/tools/puppeteer/02_stealth_hairline.txt +57 -0
  1309. package/src/tools/puppeteer/03_stealth_botd.txt +380 -0
  1310. package/src/tools/puppeteer/04_stealth_iframe.txt +174 -0
  1311. package/src/tools/puppeteer/05_stealth_webgl.txt +233 -0
  1312. package/src/tools/puppeteer/06_stealth_screen.txt +260 -0
  1313. package/src/tools/puppeteer/07_stealth_fonts.txt +99 -0
  1314. package/src/tools/puppeteer/08_stealth_audio.txt +63 -0
  1315. package/src/tools/puppeteer/09_stealth_locale.txt +51 -0
  1316. package/src/tools/puppeteer/10_stealth_plugins.txt +212 -0
  1317. package/src/tools/puppeteer/11_stealth_hardware.txt +59 -0
  1318. package/src/tools/puppeteer/12_stealth_codecs.txt +42 -0
  1319. package/src/tools/puppeteer/13_stealth_worker.txt +235 -0
  1320. package/src/tools/read.ts +3742 -0
  1321. package/src/tools/render-utils.ts +924 -0
  1322. package/src/tools/renderers.ts +133 -0
  1323. package/src/tools/report-tool-issue.ts +568 -0
  1324. package/src/tools/resolve.ts +423 -0
  1325. package/src/tools/review.ts +103 -0
  1326. package/src/tools/shell-tokenize.ts +83 -0
  1327. package/src/tools/sqlite-reader.ts +884 -0
  1328. package/src/tools/terminal-output.ts +141 -0
  1329. package/src/tools/todo.ts +1226 -0
  1330. package/src/tools/tool-errors.ts +62 -0
  1331. package/src/tools/tool-result.ts +102 -0
  1332. package/src/tools/tool-timeouts.ts +37 -0
  1333. package/src/tools/tts.ts +266 -0
  1334. package/src/tools/vibe.ts +607 -0
  1335. package/src/tools/write.ts +1640 -0
  1336. package/src/tools/xdev.ts +508 -0
  1337. package/src/tools/yield.ts +486 -0
  1338. package/src/tts/downloader.ts +64 -0
  1339. package/src/tts/index.ts +10 -0
  1340. package/src/tts/models.ts +137 -0
  1341. package/src/tts/runtime.ts +21 -0
  1342. package/src/tts/speakable.ts +392 -0
  1343. package/src/tts/speech-enhancer.ts +206 -0
  1344. package/src/tts/streaming-player.ts +120 -0
  1345. package/src/tts/tts-client.ts +475 -0
  1346. package/src/tts/tts-protocol.ts +69 -0
  1347. package/src/tts/tts-worker.ts +434 -0
  1348. package/src/tts/vocalizer.ts +419 -0
  1349. package/src/tts/wav.ts +58 -0
  1350. package/src/tui/code-cell.ts +268 -0
  1351. package/src/tui/file-list.ts +55 -0
  1352. package/src/tui/hyperlink.ts +178 -0
  1353. package/src/tui/index.ts +13 -0
  1354. package/src/tui/output-block.ts +268 -0
  1355. package/src/tui/status-line.ts +54 -0
  1356. package/src/tui/tree-list.ts +172 -0
  1357. package/src/tui/types.ts +15 -0
  1358. package/src/tui/utils.ts +103 -0
  1359. package/src/tui/width-aware-text.ts +58 -0
  1360. package/src/utils/active-repo-context.ts +143 -0
  1361. package/src/utils/block-context.ts +312 -0
  1362. package/src/utils/changelog.ts +232 -0
  1363. package/src/utils/clipboard.ts +327 -0
  1364. package/src/utils/command-args.ts +76 -0
  1365. package/src/utils/commit-message-generator.ts +148 -0
  1366. package/src/utils/cpuprofile.ts +235 -0
  1367. package/src/utils/edit-mode.ts +61 -0
  1368. package/src/utils/enhanced-paste.ts +230 -0
  1369. package/src/utils/event-bus.ts +33 -0
  1370. package/src/utils/external-editor.ts +78 -0
  1371. package/src/utils/fetch-timeout.ts +10 -0
  1372. package/src/utils/file-display-mode.ts +44 -0
  1373. package/src/utils/file-mentions.ts +293 -0
  1374. package/src/utils/git.ts +2425 -0
  1375. package/src/utils/image-loading.ts +231 -0
  1376. package/src/utils/image-resize.ts +420 -0
  1377. package/src/utils/image-vision-fallback.ts +196 -0
  1378. package/src/utils/inspect-image-mode.ts +39 -0
  1379. package/src/utils/ipc.ts +38 -0
  1380. package/src/utils/jj.ts +416 -0
  1381. package/src/utils/lang-from-path.ts +251 -0
  1382. package/src/utils/local-date.ts +7 -0
  1383. package/src/utils/mac-file-urls.applescript +37 -0
  1384. package/src/utils/markit-cache.ts +166 -0
  1385. package/src/utils/markit.ts +223 -0
  1386. package/src/utils/mupdf-wasm-embed.ts +12 -0
  1387. package/src/utils/open.ts +126 -0
  1388. package/src/utils/profile-tree.ts +111 -0
  1389. package/src/utils/prompt-path.ts +3 -0
  1390. package/src/utils/qrcode.ts +535 -0
  1391. package/src/utils/sample-profile.ts +437 -0
  1392. package/src/utils/session-color.ts +142 -0
  1393. package/src/utils/shell-snapshot-fn-env.sh +63 -0
  1394. package/src/utils/shell-snapshot.ts +316 -0
  1395. package/src/utils/sixel.ts +69 -0
  1396. package/src/utils/thinking-display.ts +163 -0
  1397. package/src/utils/title-generator.ts +597 -0
  1398. package/src/utils/token-rate.ts +72 -0
  1399. package/src/utils/tool-choice.ts +63 -0
  1400. package/src/utils/tools-manager.ts +411 -0
  1401. package/src/utils/turndown.ts +83 -0
  1402. package/src/utils/zip.ts +1106 -0
  1403. package/src/vibe/runtime.ts +1540 -0
  1404. package/src/vibe/state.ts +4 -0
  1405. package/src/web/kagi.ts +304 -0
  1406. package/src/web/parallel.ts +354 -0
  1407. package/src/web/scrapers/artifacthub.ts +207 -0
  1408. package/src/web/scrapers/arxiv.ts +83 -0
  1409. package/src/web/scrapers/aur.ts +162 -0
  1410. package/src/web/scrapers/biorxiv.ts +133 -0
  1411. package/src/web/scrapers/bluesky.ts +262 -0
  1412. package/src/web/scrapers/brew.ts +172 -0
  1413. package/src/web/scrapers/cheatsh.ts +68 -0
  1414. package/src/web/scrapers/chocolatey.ts +196 -0
  1415. package/src/web/scrapers/choosealicense.ts +95 -0
  1416. package/src/web/scrapers/cisa-kev.ts +87 -0
  1417. package/src/web/scrapers/clojars.ts +154 -0
  1418. package/src/web/scrapers/coingecko.ts +177 -0
  1419. package/src/web/scrapers/crates-io.ts +97 -0
  1420. package/src/web/scrapers/crossref.ts +136 -0
  1421. package/src/web/scrapers/devto.ts +147 -0
  1422. package/src/web/scrapers/discogs.ts +306 -0
  1423. package/src/web/scrapers/discourse.ts +197 -0
  1424. package/src/web/scrapers/dockerhub.ts +138 -0
  1425. package/src/web/scrapers/docs-rs.ts +663 -0
  1426. package/src/web/scrapers/fdroid.ts +134 -0
  1427. package/src/web/scrapers/firefox-addons.ts +191 -0
  1428. package/src/web/scrapers/flathub.ts +223 -0
  1429. package/src/web/scrapers/github-gist.ts +58 -0
  1430. package/src/web/scrapers/github.ts +800 -0
  1431. package/src/web/scrapers/gitlab.ts +401 -0
  1432. package/src/web/scrapers/go-pkg.ts +266 -0
  1433. package/src/web/scrapers/hackage.ts +140 -0
  1434. package/src/web/scrapers/hackernews.ts +189 -0
  1435. package/src/web/scrapers/hex.ts +105 -0
  1436. package/src/web/scrapers/huggingface.ts +321 -0
  1437. package/src/web/scrapers/iacr.ts +89 -0
  1438. package/src/web/scrapers/index.ts +252 -0
  1439. package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
  1440. package/src/web/scrapers/lemmy.ts +203 -0
  1441. package/src/web/scrapers/lobsters.ts +175 -0
  1442. package/src/web/scrapers/mastodon.ts +292 -0
  1443. package/src/web/scrapers/maven.ts +138 -0
  1444. package/src/web/scrapers/mdn.ts +173 -0
  1445. package/src/web/scrapers/metacpan.ts +222 -0
  1446. package/src/web/scrapers/musicbrainz.ts +250 -0
  1447. package/src/web/scrapers/npm.ts +98 -0
  1448. package/src/web/scrapers/nuget.ts +183 -0
  1449. package/src/web/scrapers/nvd.ts +222 -0
  1450. package/src/web/scrapers/ollama.ts +239 -0
  1451. package/src/web/scrapers/open-vsx.ts +106 -0
  1452. package/src/web/scrapers/opencorporates.ts +292 -0
  1453. package/src/web/scrapers/openlibrary.ts +336 -0
  1454. package/src/web/scrapers/orcid.ts +286 -0
  1455. package/src/web/scrapers/osv.ts +176 -0
  1456. package/src/web/scrapers/packagist.ts +160 -0
  1457. package/src/web/scrapers/pub-dev.ts +143 -0
  1458. package/src/web/scrapers/pubmed.ts +211 -0
  1459. package/src/web/scrapers/pypi.ts +112 -0
  1460. package/src/web/scrapers/rawg.ts +110 -0
  1461. package/src/web/scrapers/readthedocs.ts +120 -0
  1462. package/src/web/scrapers/reddit.ts +95 -0
  1463. package/src/web/scrapers/repology.ts +251 -0
  1464. package/src/web/scrapers/rfc.ts +201 -0
  1465. package/src/web/scrapers/rubygems.ts +103 -0
  1466. package/src/web/scrapers/searchcode.ts +189 -0
  1467. package/src/web/scrapers/sec-edgar.ts +261 -0
  1468. package/src/web/scrapers/semantic-scholar.ts +171 -0
  1469. package/src/web/scrapers/snapcraft.ts +187 -0
  1470. package/src/web/scrapers/sourcegraph.ts +336 -0
  1471. package/src/web/scrapers/spdx.ts +108 -0
  1472. package/src/web/scrapers/spotify.ts +198 -0
  1473. package/src/web/scrapers/stackoverflow.ts +120 -0
  1474. package/src/web/scrapers/terraform.ts +277 -0
  1475. package/src/web/scrapers/tldr.ts +47 -0
  1476. package/src/web/scrapers/twitter.ts +94 -0
  1477. package/src/web/scrapers/types.ts +354 -0
  1478. package/src/web/scrapers/utils.ts +109 -0
  1479. package/src/web/scrapers/vimeo.ts +133 -0
  1480. package/src/web/scrapers/vscode-marketplace.ts +187 -0
  1481. package/src/web/scrapers/w3c.ts +156 -0
  1482. package/src/web/scrapers/wikidata.ts +344 -0
  1483. package/src/web/scrapers/wikipedia.ts +84 -0
  1484. package/src/web/scrapers/youtube.ts +325 -0
  1485. package/src/web/search/index.ts +376 -0
  1486. package/src/web/search/provider.ts +272 -0
  1487. package/src/web/search/providers/anthropic.ts +401 -0
  1488. package/src/web/search/providers/base.ts +110 -0
  1489. package/src/web/search/providers/brave.ts +179 -0
  1490. package/src/web/search/providers/browser-headers.ts +109 -0
  1491. package/src/web/search/providers/browser-page.ts +123 -0
  1492. package/src/web/search/providers/codex.ts +749 -0
  1493. package/src/web/search/providers/duckduckgo.ts +213 -0
  1494. package/src/web/search/providers/ecosia.ts +182 -0
  1495. package/src/web/search/providers/exa.ts +511 -0
  1496. package/src/web/search/providers/firecrawl.ts +211 -0
  1497. package/src/web/search/providers/gemini.ts +628 -0
  1498. package/src/web/search/providers/google.ts +194 -0
  1499. package/src/web/search/providers/jina.ts +134 -0
  1500. package/src/web/search/providers/kagi.ts +95 -0
  1501. package/src/web/search/providers/kimi.ts +217 -0
  1502. package/src/web/search/providers/mojeek.ts +219 -0
  1503. package/src/web/search/providers/parallel.ts +182 -0
  1504. package/src/web/search/providers/perplexity-auth.ts +142 -0
  1505. package/src/web/search/providers/perplexity.ts +994 -0
  1506. package/src/web/search/providers/public.ts +199 -0
  1507. package/src/web/search/providers/searxng.ts +461 -0
  1508. package/src/web/search/providers/startpage.ts +219 -0
  1509. package/src/web/search/providers/synthetic.ts +120 -0
  1510. package/src/web/search/providers/tavily.ts +242 -0
  1511. package/src/web/search/providers/tinyfish.ts +164 -0
  1512. package/src/web/search/providers/utils.ts +128 -0
  1513. package/src/web/search/providers/xai.ts +372 -0
  1514. package/src/web/search/providers/zai.ts +437 -0
  1515. package/src/web/search/query.ts +850 -0
  1516. package/src/web/search/render.ts +262 -0
  1517. package/src/web/search/types.ts +507 -0
  1518. package/src/web/search/utils.ts +17 -0
  1519. package/src/workspace-tree.ts +326 -0
@@ -0,0 +1,1356 @@
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
+ type NativeScrollbackLiveRegion,
12
+ Spacer,
13
+ TERMINAL,
14
+ Text,
15
+ type TUI,
16
+ } from "@oh-my-pi/pi-tui";
17
+ import { getProjectDir, logger, sanitizeText } from "@oh-my-pi/pi-utils";
18
+ import { EDIT_MODE_STRATEGIES, type EditMode, type PerFileDiffPreview } from "../../edit";
19
+ import type { Theme } from "../../modes/theme/theme";
20
+ import { getThemeEpoch, theme } from "../../modes/theme/theme";
21
+ import { BASH_DEFAULT_PREVIEW_LINES } from "../../tools/bash";
22
+ import { formatDefaultToolExecution } from "../../tools/default-renderer";
23
+ import { EVAL_DEFAULT_PREVIEW_LINES } from "../../tools/eval";
24
+ import { isWaitingPollDetails } from "../../tools/hub";
25
+ import { formatStatusIcon, replaceTabs, resolveImageOptions } from "../../tools/render-utils";
26
+ import { type FirstResultViewportRepaint, toolRenderers } from "../../tools/renderers";
27
+ import { TODO_STRIKE_TOTAL_FRAMES, type TodoToolDetails } from "../../tools/todo";
28
+ import type { XdevState } from "../../tools/xdev";
29
+ import { isFramedBlockComponent, markFramedBlockComponent, renderStatusLine, WidthAwareText } from "../../tui";
30
+ import { sanitizeWithOptionalSixelPassthrough } from "../../utils/sixel";
31
+ import { renderDiff } from "./diff";
32
+
33
+ /**
34
+ * Drop trailing removal/hunk-header lines that appear in a streaming diff
35
+ * before the matching `+added` lines have arrived. Without this, a partial
36
+ * apply_patch / hashline preview shows `-old` first and then visibly grows
37
+ * the `+new` block beneath it — the "removals first, additions catching up"
38
+ * jitter. Once the next streaming tick brings the additions in, the trailing
39
+ * block reappears alongside them.
40
+ */
41
+ function stripTrailingUnbalancedRemoval(diff: string | undefined): string | undefined {
42
+ if (!diff) return diff;
43
+ const lines = diff.split("\n");
44
+ let lastAddIdx = -1;
45
+ for (let i = lines.length - 1; i >= 0; i--) {
46
+ if (lines[i].startsWith("+")) {
47
+ lastAddIdx = i;
48
+ break;
49
+ }
50
+ }
51
+ let hasTrailingUnbalanced = false;
52
+ for (let i = lastAddIdx + 1; i < lines.length; i++) {
53
+ const line = lines[i];
54
+ if (line.startsWith("-") || line.startsWith("@@")) {
55
+ hasTrailingUnbalanced = true;
56
+ break;
57
+ }
58
+ }
59
+ if (!hasTrailingUnbalanced) return diff;
60
+ if (lastAddIdx === -1) return "";
61
+ return lines.slice(0, lastAddIdx + 1).join("\n");
62
+ }
63
+
64
+ type DisplaceableToolName = "hub" | "todo";
65
+
66
+ function isTodoToolDetails(details: unknown): details is TodoToolDetails {
67
+ return (
68
+ typeof details === "object" &&
69
+ details !== null &&
70
+ "phases" in details &&
71
+ Array.isArray((details as { phases?: unknown }).phases)
72
+ );
73
+ }
74
+
75
+ function displaceableToolName(
76
+ toolName: string,
77
+ result: { details?: unknown; isError?: boolean },
78
+ isPartial: boolean,
79
+ ): DisplaceableToolName | undefined {
80
+ if (result.isError === true) return undefined;
81
+ if (toolName === "hub" && isWaitingPollDetails(result.details)) return "hub";
82
+ if (toolName === "todo" && !isPartial && isTodoToolDetails(result.details)) return "todo";
83
+ return undefined;
84
+ }
85
+
86
+ function stabilizeStreamingPreviews(previews: PerFileDiffPreview[]): PerFileDiffPreview[] {
87
+ let changed = false;
88
+ const next = previews.map(preview => {
89
+ if (!preview.diff) return preview;
90
+ const trimmed = stripTrailingUnbalancedRemoval(preview.diff);
91
+ if (trimmed === preview.diff) return preview;
92
+ changed = true;
93
+ return { ...preview, diff: trimmed ?? "" };
94
+ });
95
+ return changed ? next : previews;
96
+ }
97
+
98
+ function isEditLikeToolName(toolName: string): boolean {
99
+ return toolName === "edit" || toolName === "apply_patch";
100
+ }
101
+
102
+ function resolveEditModeForTool(toolName: string, tool: AgentTool | undefined): EditMode | undefined {
103
+ if (toolName === "apply_patch") return "apply_patch";
104
+ if (toolName !== "edit") return undefined;
105
+ return (tool as { mode?: EditMode } | undefined)?.mode;
106
+ }
107
+
108
+ function rawTextInputFromPartialJson(partialJson: unknown): string | undefined {
109
+ if (typeof partialJson !== "string") return undefined;
110
+ if (partialJson.length === 0) return undefined;
111
+ const trimmed = partialJson.trimStart();
112
+ if (trimmed.length === 0) return undefined;
113
+ const first = trimmed[0];
114
+ // Function-tool arguments stream as JSON. Custom/free-form tools stream raw
115
+ // text in the same transport field; only the raw form is a valid fallback for
116
+ // the conventional `input` parameter.
117
+ if (first === "{" || first === '"') return undefined;
118
+ return partialJson;
119
+ }
120
+
121
+ /** Read the streamed raw-JSON buffer a tool block stashes on its args, narrowed
122
+ * rather than cast: a missing or non-string `__partialJson` yields `undefined`. */
123
+ function partialJsonOf(args: unknown): string | undefined {
124
+ if (args == null || typeof args !== "object" || !("__partialJson" in args)) return undefined;
125
+ const value = args.__partialJson;
126
+ return typeof value === "string" ? value : undefined;
127
+ }
128
+
129
+ function getArgsWithStreamedTextInput(args: unknown): unknown {
130
+ if (args == null || typeof args !== "object") return args;
131
+ const record = args as Record<string, unknown>;
132
+ if (typeof record.input === "string") return args;
133
+ const input = rawTextInputFromPartialJson(record.__partialJson);
134
+ return input === undefined ? args : { ...record, input };
135
+ }
136
+
137
+ type ToolRendererStage = "call" | "result";
138
+
139
+ class SafeToolRendererComponent implements Component {
140
+ #toolName: string;
141
+ #stage: ToolRendererStage;
142
+ #component: Component;
143
+ #fallback: () => Component | undefined;
144
+ #warned = false;
145
+ readonly wantsKeyRelease: boolean | undefined;
146
+
147
+ constructor(
148
+ toolName: string,
149
+ stage: ToolRendererStage,
150
+ component: Component,
151
+ fallback: () => Component | undefined,
152
+ ) {
153
+ this.#toolName = toolName;
154
+ this.#stage = stage;
155
+ this.#component = component;
156
+ this.#fallback = fallback;
157
+ this.wantsKeyRelease = component.wantsKeyRelease;
158
+ if (isFramedBlockComponent(component)) {
159
+ markFramedBlockComponent(this);
160
+ }
161
+ }
162
+
163
+ render(width: number): readonly string[] {
164
+ try {
165
+ return this.#component.render(width);
166
+ } catch (err) {
167
+ if (!this.#warned) {
168
+ this.#warned = true;
169
+ logger.warn("Tool renderer failed", { tool: this.#toolName, stage: this.#stage, error: String(err) });
170
+ }
171
+ return this.#fallback()?.render(width) ?? [];
172
+ }
173
+ }
174
+
175
+ handleInput(data: string): void {
176
+ const handleInput = this.#component.handleInput;
177
+ if (handleInput === undefined) return;
178
+ handleInput.call(this.#component, data);
179
+ }
180
+
181
+ invalidate(): void {
182
+ const invalidate = this.#component.invalidate;
183
+ if (invalidate === undefined) return;
184
+ invalidate.call(this.#component);
185
+ }
186
+
187
+ setIgnoreTight(ignore: boolean): void {
188
+ const setIgnoreTight = this.#component.setIgnoreTight;
189
+ if (setIgnoreTight === undefined) return;
190
+ setIgnoreTight.call(this.#component, ignore);
191
+ }
192
+
193
+ dispose(): void {
194
+ const dispose = this.#component.dispose;
195
+ if (dispose === undefined) return;
196
+ dispose.call(this.#component);
197
+ }
198
+ }
199
+ /**
200
+ * Transcript-side probe telling a block whether it is still inside the live
201
+ * (repaintable) region. Implemented by `TranscriptContainer`; injected rather
202
+ * than imported so the component stays decoupled from the transcript.
203
+ */
204
+ export interface TranscriptLiveRegionProbe {
205
+ isBlockInLiveRegion(component: Component): boolean;
206
+ }
207
+
208
+ /** Minimal TUI surface ToolExecutionComponent uses to schedule repaints and share image budget. */
209
+ export interface ToolExecutionUi {
210
+ requestRender(): void;
211
+ requestComponentRender(component: Component): void;
212
+ resetDisplay(): void;
213
+ imageBudget?: TUI["imageBudget"];
214
+ }
215
+
216
+ export interface ToolExecutionOptions {
217
+ snapshots?: SnapshotStore;
218
+ showImages?: boolean; // default: true (only used if terminal supports images)
219
+ editFuzzyThreshold?: number;
220
+ editAllowFuzzy?: boolean;
221
+ /** Live-region probe used to settle detached task progress once the block
222
+ * leaves the repaintable transcript region. */
223
+ liveRegion?: TranscriptLiveRegionProbe;
224
+ }
225
+
226
+ export interface ToolExecutionHandle extends Component {
227
+ updateArgs(args: any, toolCallId?: string): void;
228
+ updateResult(
229
+ result: {
230
+ content: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;
231
+ details?: any;
232
+ isError?: boolean;
233
+ },
234
+ isPartial?: boolean,
235
+ toolCallId?: string,
236
+ ): void;
237
+ setArgsComplete(toolCallId?: string): void;
238
+ setExpanded(expanded: boolean): void;
239
+ /** Freeze the block as final history: stop spinners and let it commit to scrollback. */
240
+ seal(): void;
241
+ }
242
+
243
+ /** Redraw live tool blocks at the spinner's glyph-advance rate. Rendering more
244
+ * often produced identical frames — the previous 30fps cadence emitted ~2.4
245
+ * paints per glyph step, and although the terminal I/O layer dedupes those, the
246
+ * compose pipeline still ran end-to-end per frame (issue #4353). Matching the
247
+ * render tick to the glyph tick halves the paints during tool execution with no
248
+ * visible change. */
249
+ export const SPINNER_RENDER_INTERVAL_MS = 80;
250
+ /** Advance the spinner glyph at its classic ~12.5fps step (mirrors `Loader`). */
251
+ export const SPINNER_GLYPH_ADVANCE_MS = 80;
252
+
253
+ /** Phase-locked spinner glyph index shared by every live tool block so parallel
254
+ * spinners advance in lockstep instead of each tracking its own start time. */
255
+ export function sharedSpinnerFrame(frameCount: number, now: number = performance.now()): number {
256
+ return frameCount > 0 ? Math.floor(now / SPINNER_GLYPH_ADVANCE_MS) % frameCount : 0;
257
+ }
258
+
259
+ // Stable per-instance counter so each tool execution's inline images get a
260
+ // graphics id that survives child re-creation (the image budget keys off it).
261
+ let toolExecutionInstanceSeq = 0;
262
+
263
+ /**
264
+ * Component that renders a tool call with its result (updateable)
265
+ */
266
+ export class ToolExecutionComponent extends Container implements NativeScrollbackLiveRegion {
267
+ #contentBox: Box; // Used for custom tools and bash visual truncation
268
+ #contentText: WidthAwareText; // Generic fallback (no custom/built-in renderer)
269
+ #multiFileBoxes: (Box | Spacer)[] = []; // Extra boxes for multi-file edit results
270
+ #imageComponents: Image[] = [];
271
+ #imageSpacers: Spacer[] = [];
272
+ readonly #instanceId = ++toolExecutionInstanceSeq;
273
+ #toolName: string;
274
+ #toolLabel: string;
275
+ #args: any;
276
+ #expanded = false;
277
+ #showImages: boolean;
278
+ #editFuzzyThreshold: number | undefined;
279
+ #editAllowFuzzy: boolean | undefined;
280
+ #snapshots?: SnapshotStore;
281
+ #isPartial = true;
282
+ #resultVersion = 0;
283
+ #lastDisplayKey: string | undefined;
284
+ // Bumped whenever a render input that #rebuildDisplay consumes but the memo
285
+ // key cannot cheaply hash changes: streamed call args, the async edit-diff
286
+ // preview, and Kitty PNG conversions. Folded into the dirty key so those
287
+ // updates are not swallowed by the memo (see #updateDisplay).
288
+ #displayInputVersion = 0;
289
+ // Set once #rebuildDisplay has populated the display. Replaces a
290
+ // #contentBox.children.length probe so the memo fast-path also covers the
291
+ // #contentText fallback path (which leaves #contentBox empty).
292
+ #displayBuilt = false;
293
+ // Number of Image children the last rebuild emitted. Only when this is > 0 does
294
+ // the memo key fold in viewport-dependent image sizing (resolveImageOptions),
295
+ // so a terminal resize re-shapes image-bearing results to rescale them without
296
+ // forcing the common image-free result to re-shape on every resize tick.
297
+ #renderedImageCount = 0;
298
+ #tool?: AgentTool;
299
+ #ui: ToolExecutionUi;
300
+ #cwd: string;
301
+ #result?: {
302
+ content: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;
303
+ isError?: boolean;
304
+ details?: any;
305
+ };
306
+ // Edit preview state
307
+ #editMode?: EditMode;
308
+ #editDiffPreview?: PerFileDiffPreview[];
309
+ #editDiffAbort?: AbortController;
310
+ #editDiffLastArgsKey?: string;
311
+ // Latest in-flight streaming diff recompute, captured so it can be awaited.
312
+ #editDiffInFlight?: Promise<void>;
313
+ /** Set when newer args arrived while a preview compute was in flight; the
314
+ * drain loop re-runs once the current compute settles, so a slow diff
315
+ * coalesces streamed ticks instead of being aborted by each one. */
316
+ #editDiffDirty = false;
317
+ // Cached converted images for Kitty protocol (which requires PNG), keyed by index
318
+ #convertedImages: Map<number, { data: string; mimeType: string }> = new Map();
319
+ // Spinner animation for partial task results
320
+ #spinnerFrame?: number;
321
+ #spinnerInterval?: NodeJS.Timeout;
322
+ // Todo write completion strikethrough reveal animation
323
+ #todoStrikeInterval?: NodeJS.Timeout;
324
+ // Track if args are still being streamed (for edit/write spinner)
325
+ #argsComplete = false;
326
+ // Sealed once the tool reaches a terminal state (result delivered, or the
327
+ // turn abandoned it without one). Drives `isTranscriptBlockFinalized`: until
328
+ // sealed the block stays in the transcript's repaintable live region so a
329
+ // late result still repaints instead of stranding the streaming preview.
330
+ #sealed = false;
331
+ // Tool result snapshots that may be superseded by a later same-tool call
332
+ // while still in the transcript live region. `hub` uses this for repeated
333
+ // all-running polls; `todo` uses it for per-turn state snapshots so only the
334
+ // latest list remains visible.
335
+ #displaceableByToolName: DisplaceableToolName | undefined;
336
+ // Probe into the owning transcript (absent outside the interactive
337
+ // transcript, e.g. in tests): whether this block is still repaintable.
338
+ #liveRegion?: TranscriptLiveRegionProbe;
339
+ // One-way latch for a detached (`async.state === "running"`) task block
340
+ // that left the transcript live region: its rows are commit-eligible
341
+ // history, so progress renders static gray and further partial snapshots are
342
+ // dropped (see #maybeFreezeBackgroundTask).
343
+ #backgroundTaskFrozen = false;
344
+ // Set on each `render()` when the last painted pending shape must be
345
+ // replayed wholesale when the first result arrives. Reset gates key off
346
+ // these so a topology-changing update that lands before the shape reaches
347
+ // the terminal never triggers a full-viewport replay (which on direct
348
+ // terminals wipes native scrollback and flashes the user's history —
349
+ // reviewer note on PR #4315).
350
+ #firstResultViewportRepaintShapePainted = false;
351
+ #partialResultShapePainted = false;
352
+ #renderState: {
353
+ spinnerFrame?: number;
354
+ expanded: boolean;
355
+ isPartial: boolean;
356
+ renderContext?: Record<string, unknown>;
357
+ } = {
358
+ expanded: false,
359
+ isPartial: true,
360
+ };
361
+
362
+ constructor(
363
+ toolName: string,
364
+ args: any,
365
+ options: ToolExecutionOptions = {},
366
+ tool: AgentTool | undefined,
367
+ ui: ToolExecutionUi,
368
+ cwd: string = getProjectDir(),
369
+ _toolCallId?: string,
370
+ ) {
371
+ super();
372
+ this.#toolName = toolName;
373
+ this.#toolLabel = tool?.label ?? toolName;
374
+ this.#showImages = options.showImages ?? true;
375
+ this.#editFuzzyThreshold = options.editFuzzyThreshold;
376
+ this.#editAllowFuzzy = options.editAllowFuzzy;
377
+ this.#snapshots = options.snapshots;
378
+ this.#liveRegion = options.liveRegion;
379
+ this.#tool = tool;
380
+ this.#ui = ui;
381
+ this.#cwd = cwd;
382
+ this.#args = args;
383
+ this.#editMode = resolveEditModeForTool(toolName, tool);
384
+
385
+ // Always create both - contentBox for custom tools/bash/tools with renderers, contentText for other built-ins.
386
+ // paddingY is 1 so background-tinted blocks (custom/extension tools and the
387
+ // generic fallback) get top/bottom breathing room. TranscriptContainer
388
+ // strips PLAIN-blank edges, so framed/minimal blocks (no bg set) drop these
389
+ // lines and keep their tight spacing — only tinted lines survive.
390
+ this.#contentBox = new Box(0, 1);
391
+ this.#contentText = new WidthAwareText(
392
+ contentWidth =>
393
+ formatDefaultToolExecution(
394
+ {
395
+ label: this.#toolLabel,
396
+ args: this.#args,
397
+ result: this.#result ? { output: this.#getTextOutput(), isError: this.#result.isError } : undefined,
398
+ options: this.#renderState,
399
+ },
400
+ contentWidth,
401
+ theme,
402
+ ),
403
+ 1,
404
+ 1,
405
+ );
406
+
407
+ // Use Box for custom tools or built-in tools that have renderers
408
+ const hasRenderer = toolName in toolRenderers;
409
+ const hasCustomRenderer = !!(tool?.renderCall || tool?.renderResult);
410
+ if (hasCustomRenderer || hasRenderer) {
411
+ this.addChild(this.#contentBox);
412
+ } else {
413
+ this.addChild(this.#contentText);
414
+ }
415
+ // Tool blocks are visually distinct cards (background-tinted or framed),
416
+ // so keep their horizontal padding even when the user enables tight layout.
417
+ this.setIgnoreTight(true);
418
+
419
+ this.#updateSpinnerAnimation();
420
+ this.#updateDisplay();
421
+ this.#schedulePreviewDiff();
422
+ }
423
+
424
+ updateArgs(args: any, _toolCallId?: string): void {
425
+ // Reference-equality short-circuit before any further work. Callers
426
+ // always allocate a new arg object on each streamed delta (see
427
+ // event-controller.ts and ui-helpers.ts), so a same-reference assignment
428
+ // signals "nothing meaningful changed" and the renderer can skip.
429
+ if (args === this.#args) return;
430
+ this.#args = args;
431
+ this.#displayInputVersion++;
432
+ this.#updateSpinnerAnimation();
433
+ this.#schedulePreviewDiff();
434
+ this.#updateDisplay();
435
+ }
436
+
437
+ /**
438
+ * Signal that args are complete (tool is about to execute).
439
+ * This triggers an immediate final diff computation for edit-like tools.
440
+ */
441
+ setArgsComplete(_toolCallId?: string): void {
442
+ this.#argsComplete = true;
443
+ this.#updateSpinnerAnimation();
444
+ this.#schedulePreviewDiff();
445
+ }
446
+
447
+ /**
448
+ * Await the streaming diff recompute kicked off by the most recent
449
+ * `updateArgs`/`setArgsComplete`. The recompute reads the file and re-runs the
450
+ * whole-file Myers diff off the render path, signalling completion only via a
451
+ * throttled `requestRender`. Tests await this to sample a *settled* preview
452
+ * deterministically instead of racing the spinner's render ticks.
453
+ */
454
+ async whenPreviewSettled(): Promise<void> {
455
+ await this.#editDiffInFlight;
456
+ }
457
+
458
+ /**
459
+ * Schedule a streaming diff preview recompute, coalescing bursts of
460
+ * `updateArgs` into one compute at a time: run the current compute to
461
+ * completion and re-run only after it settles when newer args arrived, never
462
+ * cancelling an in-flight compute on a fresh tick. The reveal controller pushes
463
+ * args ~30fps and a whole-file hashline/large-file diff can outlast a frame, so
464
+ * cancel-per-tick would starve every compute and no preview would land until
465
+ * args complete. Coalescing lets each diff land, so the preview tracks the
466
+ * stream at the rate the diffs can sustain.
467
+ */
468
+ #schedulePreviewDiff(): void {
469
+ this.#editDiffDirty = true;
470
+ if (this.#editDiffInFlight) return;
471
+ this.#editDiffInFlight = this.#drainPreviewDiff().finally(() => {
472
+ this.#editDiffInFlight = undefined;
473
+ });
474
+ }
475
+
476
+ async #drainPreviewDiff(): Promise<void> {
477
+ while (this.#editDiffDirty) {
478
+ this.#editDiffDirty = false;
479
+ await this.#computePreviewDiff();
480
+ }
481
+ }
482
+
483
+ async #computePreviewDiff(): Promise<void> {
484
+ const editMode = this.#editMode;
485
+ if (!editMode) return;
486
+ const strategy = EDIT_MODE_STRATEGIES[editMode];
487
+ if (!strategy) return;
488
+
489
+ const args = this.#args;
490
+ if (args == null || typeof args !== "object") return;
491
+
492
+ const previewArgs = getArgsWithStreamedTextInput(args);
493
+ const partialJson = partialJsonOf(previewArgs);
494
+ let effectiveArgs: unknown;
495
+ try {
496
+ effectiveArgs = strategy.extractCompleteEdits(previewArgs, partialJson);
497
+ } catch {
498
+ effectiveArgs = previewArgs;
499
+ }
500
+
501
+ // Coalesce duplicate computes for identical args. The key pairs the
502
+ // streaming flag with a content hash: the final (args-complete) pass
503
+ // computes an untrimmed diff and must run even when the payload is
504
+ // byte-identical to the last streamed chunk — only `isStreaming` differs,
505
+ // and it flips the trailing-line trim. Without the flag a single-line edit
506
+ // whose trailing payload line never gets a newline stays stuck on the
507
+ // trimmed "no changes" streaming preview and renders no diff. Hashing keeps
508
+ // the retained key tiny instead of holding the whole serialized blob.
509
+ const streamingState = this.#argsComplete ? "final" : "stream";
510
+ let argsKey: string;
511
+ try {
512
+ argsKey = `${streamingState}:${Bun.hash(JSON.stringify(effectiveArgs))}`;
513
+ } catch {
514
+ // effectiveArgs isn't JSON-serializable (exotic value in tool args).
515
+ // The raw streamed JSON is a plain string, so hash that instead of a
516
+ // timestamp — a deterministic key keeps the dedup cache working
517
+ // instead of recomputing (and re-reading the file) on every render.
518
+ argsKey = `${streamingState}:partial:${Bun.hash(partialJson ?? "")}`;
519
+ }
520
+ if (argsKey === this.#editDiffLastArgsKey) return;
521
+ this.#editDiffLastArgsKey = argsKey;
522
+
523
+ // Single-flight (the drain loop never overlaps computes), so this controller
524
+ // only ever cancels the live compute on teardown via `stopAnimation`.
525
+ const controller = new AbortController();
526
+ this.#editDiffAbort = controller;
527
+
528
+ try {
529
+ const isStreaming = !this.#argsComplete;
530
+ if (editMode === "hashline" && !this.#snapshots) return;
531
+ const previews = await strategy.computeDiffPreview(effectiveArgs, {
532
+ cwd: this.#cwd,
533
+ signal: controller.signal,
534
+ snapshots: this.#snapshots!,
535
+ fuzzyThreshold: this.#editFuzzyThreshold,
536
+ allowFuzzy: this.#editAllowFuzzy,
537
+ isStreaming,
538
+ });
539
+ if (controller.signal.aborted) return;
540
+ if (previews) {
541
+ this.#editDiffPreview = isStreaming ? stabilizeStreamingPreviews(previews) : previews;
542
+ this.#displayInputVersion++;
543
+ this.#updateDisplay();
544
+ this.#ui.requestRender();
545
+ }
546
+ } catch (err) {
547
+ if (controller.signal.aborted) return;
548
+ logger.warn("Edit preview diff failed", { tool: this.#toolName, error: String(err) });
549
+ }
550
+ }
551
+
552
+ updateResult(
553
+ result: {
554
+ content: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;
555
+ details?: any;
556
+ isError?: boolean;
557
+ },
558
+ isPartial = false,
559
+ _toolCallId?: string,
560
+ ): void {
561
+ // A detached task spawn keeps streaming progress snapshots after the
562
+ // block froze (left the transcript live region). Drop them: the rows are
563
+ // static gray history now, and repainting would rewrite rows the engine
564
+ // may already have committed to native scrollback. The terminal snapshot
565
+ // (async completed/failed → isPartial=false) still applies so a block
566
+ // that is still on screen settles on real results.
567
+ if (isPartial && this.#toolName === "task" && this.#maybeFreezeBackgroundTask()) {
568
+ return;
569
+ }
570
+ const hadNoResult = this.#result === undefined;
571
+ const wasPartialResult = this.#result !== undefined && this.#isPartial;
572
+ const firstResultRepaintShapePainted = this.#firstResultViewportRepaintShapePainted;
573
+ const partialResultPainted = this.#partialResultShapePainted;
574
+ this.#firstResultViewportRepaintShapePainted = false;
575
+ this.#partialResultShapePainted = false;
576
+ this.#result = result;
577
+ this.#resultVersion++;
578
+ this.#isPartial = isPartial;
579
+ this.#displaceableByToolName = displaceableToolName(this.#toolName, result, isPartial);
580
+ // When tool is complete, ensure args are marked complete so spinner stops
581
+ if (!isPartial) {
582
+ this.#argsComplete = true;
583
+ }
584
+ this.#updateSpinnerAnimation();
585
+ this.#updateTodoStrikeAnimation();
586
+ this.#updateDisplay();
587
+ this.#resetDisplayForResultTopologyChange(
588
+ hadNoResult && firstResultRepaintShapePainted,
589
+ wasPartialResult && partialResultPainted,
590
+ isPartial,
591
+ );
592
+ // Convert non-PNG images to PNG for Kitty protocol (async)
593
+ this.#maybeConvertImagesForKitty();
594
+ }
595
+
596
+ /**
597
+ * Get all image blocks from result content and details.images.
598
+ * Some tools (like generate_image) store images in details to avoid bloating model context.
599
+ */
600
+ #getAllImageBlocks(): Array<{ data?: string; mimeType?: string }> {
601
+ if (!this.#result) return [];
602
+ const contentImages = this.#result.content?.filter((c: any) => c.type === "image") || [];
603
+ const detailImages = this.#result.details?.images || [];
604
+ return [...contentImages, ...detailImages];
605
+ }
606
+
607
+ /**
608
+ * Convert non-PNG images to PNG for Kitty graphics protocol.
609
+ * Kitty requires PNG format (f=100), so JPEG/GIF/WebP won't display.
610
+ */
611
+ #maybeConvertImagesForKitty(): void {
612
+ // Only needed for Kitty protocol
613
+ if (TERMINAL.imageProtocol !== ImageProtocol.Kitty) return;
614
+ if (!this.#result) return;
615
+
616
+ const imageBlocks = this.#getAllImageBlocks();
617
+
618
+ for (let i = 0; i < imageBlocks.length; i++) {
619
+ const img = imageBlocks[i];
620
+ if (!img.data || !img.mimeType) continue;
621
+ // Skip if already PNG or already converted
622
+ if (img.mimeType === "image/png") continue;
623
+ if (this.#convertedImages.has(i)) continue;
624
+
625
+ // Convert async - catch errors from processing
626
+ const index = i;
627
+ new Bun.Image(Buffer.from(img.data, "base64"))
628
+ .png()
629
+ .toBase64()
630
+ .then(data => {
631
+ this.#convertedImages.set(index, { data, mimeType: "image/png" });
632
+ this.#displayInputVersion++;
633
+ this.#updateDisplay();
634
+ this.#ui.requestRender();
635
+ })
636
+ .catch(() => {
637
+ // Ignore conversion failures - display will use original image format
638
+ });
639
+ }
640
+ }
641
+
642
+ /**
643
+ * Start or stop spinner animation for live states that visibly tick.
644
+ */
645
+ #updateSpinnerAnimation(): void {
646
+ // Live partial tool blocks stay repaintable until a terminal result seals
647
+ // them. Todo snapshots and detached background tool progress are deliberate
648
+ // static exceptions because their rows can be superseded or committed to
649
+ // scrollback while later updates continue elsewhere.
650
+ const isStreamingArgs = !this.#argsComplete && (isEditLikeToolName(this.#toolName) || this.#toolName === "write");
651
+ const isBackgroundAsyncRunning =
652
+ (this.#result?.details as { async?: { state?: string } } | undefined)?.async?.state === "running";
653
+ const renderer = toolRenderers[this.#toolName] as
654
+ | {
655
+ animatedPendingPreview?: boolean | ((args: unknown) => boolean);
656
+ animatedPartialResult?: boolean | ((args: unknown) => boolean);
657
+ }
658
+ | undefined;
659
+ const pendingAnimation = renderer?.animatedPendingPreview;
660
+ const partialAnimation = renderer?.animatedPartialResult;
661
+ const pendingCallConsumesSpinner =
662
+ this.#result === undefined &&
663
+ (renderer === undefined
664
+ ? // Only the generic #formatToolExecution fallback consumes the frame;
665
+ // a custom renderCall/renderResult pair routes through the custom
666
+ // branch whose pending label is a static tool-name Text.
667
+ !this.#tool?.renderCall && !this.#tool?.renderResult
668
+ : typeof pendingAnimation === "function"
669
+ ? pendingAnimation(this.#args)
670
+ : pendingAnimation === true);
671
+ const partialResultConsumesSpinner =
672
+ this.#result !== undefined &&
673
+ (renderer === undefined
674
+ ? !this.#tool?.renderCall && !this.#tool?.renderResult
675
+ : typeof partialAnimation === "function"
676
+ ? partialAnimation(this.#args)
677
+ : partialAnimation === true);
678
+ const isLivePartialTool =
679
+ this.#isPartial &&
680
+ this.#toolName !== "todo" &&
681
+ !isBackgroundAsyncRunning &&
682
+ (pendingCallConsumesSpinner || partialResultConsumesSpinner);
683
+ const needsSpinner = isStreamingArgs || isLivePartialTool || this.#displaceableByToolName === "hub";
684
+ if (needsSpinner && !this.#spinnerInterval) {
685
+ const frameCount = theme.spinnerFrames.length;
686
+ const frame = sharedSpinnerFrame(frameCount);
687
+ this.#spinnerFrame = frame;
688
+ this.#renderState.spinnerFrame = frame;
689
+ this.#spinnerInterval = setInterval(() => {
690
+ // If a detached task interval from an older render path is still live,
691
+ // stop it the instant the block leaves the repaintable region.
692
+ if (this.#maybeFreezeBackgroundTask()) return;
693
+ const now = performance.now();
694
+ const frameCount = theme.spinnerFrames.length;
695
+ this.#spinnerFrame = sharedSpinnerFrame(frameCount, now);
696
+ this.#renderState.spinnerFrame = this.#spinnerFrame;
697
+ // Component-scoped: a spinner tick only changes this tool block, so
698
+ // the TUI reuses every other root subtree instead of walking the
699
+ // whole tree (issue #4377).
700
+ this.#ui.requestComponentRender(this);
701
+ }, SPINNER_RENDER_INTERVAL_MS);
702
+ } else if (!needsSpinner && this.#spinnerInterval) {
703
+ clearInterval(this.#spinnerInterval);
704
+ this.#spinnerInterval = undefined;
705
+ // Clear the last drawn frame so a non-live renderCall (e.g. a write whose
706
+ // args just completed) stops showing a frozen spinner glyph. Skip when a
707
+ // todo strike owns the frame — it sets its own value right after this.
708
+ if (!this.#todoStrikeInterval) {
709
+ this.#spinnerFrame = undefined;
710
+ this.#renderState.spinnerFrame = undefined;
711
+ }
712
+ }
713
+ }
714
+
715
+ /**
716
+ * Freeze a detached (`async.state === "running"`) task block once it leaves
717
+ * the transcript's live region. Past that seam its rows are commit-eligible
718
+ * native-scrollback history: repaint the progress rows static gray and drop
719
+ * further partial snapshots. One-way — blocks never re-enter the live
720
+ * region. Returns whether the block is frozen.
721
+ */
722
+ #maybeFreezeBackgroundTask(): boolean {
723
+ if (this.#backgroundTaskFrozen) return true;
724
+ if (this.#toolName !== "task" || this.#liveRegion === undefined) return false;
725
+ const asyncState = (this.#result?.details as { async?: { state?: string } } | undefined)?.async?.state;
726
+ if (asyncState !== "running") return false;
727
+ if (this.#liveRegion.isBlockInLiveRegion(this)) return false;
728
+ this.#backgroundTaskFrozen = true;
729
+ this.#updateSpinnerAnimation();
730
+ this.#updateDisplay();
731
+ this.#ui.requestRender();
732
+ return true;
733
+ }
734
+
735
+ #updateTodoStrikeAnimation(): void {
736
+ if (this.#toolName !== "todo" || this.#isPartial || this.#result?.isError) {
737
+ this.#stopTodoStrikeAnimation();
738
+ return;
739
+ }
740
+ const completedTasks = (this.#result?.details as { completedTasks?: unknown[] } | undefined)?.completedTasks;
741
+ if (!completedTasks || completedTasks.length === 0) {
742
+ this.#stopTodoStrikeAnimation();
743
+ return;
744
+ }
745
+ if (this.#todoStrikeInterval) return;
746
+
747
+ this.#spinnerFrame = 0;
748
+ this.#renderState.spinnerFrame = 0;
749
+ this.#todoStrikeInterval = setInterval(() => {
750
+ const nextFrame = (this.#spinnerFrame ?? 0) + 1;
751
+ if (nextFrame > TODO_STRIKE_TOTAL_FRAMES) {
752
+ this.#stopTodoStrikeAnimation();
753
+ } else {
754
+ this.#spinnerFrame = nextFrame;
755
+ this.#renderState.spinnerFrame = nextFrame;
756
+ }
757
+ // Component-scoped: strike animation only mutates this tool block's
758
+ // glyph, so the TUI reuses every other root subtree (issue #4377).
759
+ this.#ui.requestComponentRender(this);
760
+ }, 65);
761
+ }
762
+
763
+ #stopTodoStrikeAnimation(): void {
764
+ if (this.#todoStrikeInterval) {
765
+ clearInterval(this.#todoStrikeInterval);
766
+ this.#todoStrikeInterval = undefined;
767
+ }
768
+ if (!this.#spinnerInterval) {
769
+ this.#spinnerFrame = undefined;
770
+ this.#renderState.spinnerFrame = undefined;
771
+ }
772
+ }
773
+
774
+ /**
775
+ * Standalone harnesses may mount a tool component directly under `TUI`
776
+ * instead of inside `TranscriptContainer`. In that shape the component must
777
+ * report its own live-region seam while unfinalized, or the core renderer
778
+ * treats it like shell output and commits still-mutating preview rows to
779
+ * immutable native scrollback before the result replaces them.
780
+ */
781
+ getNativeScrollbackLiveRegionStart(): number | undefined {
782
+ return this.isTranscriptBlockFinalized() ? undefined : 0;
783
+ }
784
+
785
+ /**
786
+ * Keeps in-flight TV-wall frames out of immutable native scrollback: the
787
+ * `vibe_wait` wall and displaceable snapshots (`hub` waiting polls, `todo`
788
+ * lists). Their frames replace each other rather than append, and their
789
+ * rows mutate every spinner tick — an unpinned commit records a per-tick
790
+ * frozen snapshot AND force-seals the block (see TranscriptContainer's
791
+ * committed-snapshot seal), so the next poll stacks a new frame instead of
792
+ * displacing this one.
793
+ */
794
+ isNativeScrollbackLiveRegionPinned(): boolean {
795
+ if (this.isTranscriptBlockFinalized()) return false;
796
+ return this.#toolName === "vibe_wait" || this.#displaceableByToolName !== undefined;
797
+ }
798
+
799
+ /**
800
+ * Whether this block has reached a terminal state for transcript freezing.
801
+ * Reports `false` while it can still visually change so the
802
+ * {@link TranscriptContainer} keeps it inside the repaintable live region:
803
+ * a foreground tool awaiting its result, or one streaming partial output.
804
+ * A final (non-partial) result, a background-async tool the agent has moved
805
+ * past, or an explicit {@link seal} flips it to `true`.
806
+ */
807
+ isTranscriptBlockFinalized(): boolean {
808
+ if (this.#sealed) return true;
809
+ if (this.#result === undefined) return false;
810
+ // A displaceable snapshot stays live: its rows are kept out of native
811
+ // scrollback so a follow-up tool call can remove the block.
812
+ if (this.#displaceableByToolName) return false;
813
+ if (!this.#isPartial) return true;
814
+ // Partial result: a background async tool is accepted to freeze (the agent
815
+ // continues while it runs and would otherwise pin an unbounded live region);
816
+ // a foreground tool streaming partial output stays live until it finishes.
817
+ return (this.#result.details as { async?: { state?: string } } | undefined)?.async?.state === "running";
818
+ }
819
+
820
+ /**
821
+ * Mark the tool terminal even though no result arrived (the turn aborted or
822
+ * abandoned it) and stop animating, so it can freeze and stops pinning the
823
+ * transcript live region.
824
+ */
825
+ seal(): void {
826
+ if (this.#sealed) return;
827
+ this.#sealed = true;
828
+ this.#displaceableByToolName = undefined;
829
+ // A sealed detached task is abandoned history: settle its progress rows
830
+ // on static gray.
831
+ this.#backgroundTaskFrozen = true;
832
+ this.stopAnimation();
833
+ this.#updateDisplay();
834
+ this.#ui.requestRender();
835
+ }
836
+
837
+ /**
838
+ * Whether this block is a supersedable result snapshot that has not been
839
+ * sealed. Such a block never finalized, so none of its rows entered native
840
+ * scrollback and the whole block can be removed when a follow-up matching
841
+ * tool call supersedes it.
842
+ */
843
+ isDisplaceableBlock(): boolean {
844
+ return this.#displaceableByToolName !== undefined && !this.#sealed;
845
+ }
846
+
847
+ canBeDisplacedBy(nextToolName: string | undefined): boolean {
848
+ return (
849
+ this.#displaceableByToolName !== undefined && this.#displaceableByToolName === nextToolName && !this.#sealed
850
+ );
851
+ }
852
+
853
+ /**
854
+ * Stop spinner animation and cleanup resources.
855
+ */
856
+ stopAnimation(): void {
857
+ if (this.#spinnerInterval) {
858
+ clearInterval(this.#spinnerInterval);
859
+ this.#spinnerInterval = undefined;
860
+ this.#spinnerFrame = undefined;
861
+ this.#renderState.spinnerFrame = undefined;
862
+ }
863
+ this.#stopTodoStrikeAnimation();
864
+ this.#editDiffAbort?.abort();
865
+ this.#editDiffAbort = undefined;
866
+ // Drop any queued rerun so the drain loop exits instead of recomputing a
867
+ // preview for a torn-down block after its in-flight compute is aborted.
868
+ this.#editDiffDirty = false;
869
+ }
870
+
871
+ setExpanded(expanded: boolean): void {
872
+ this.#expanded = expanded;
873
+ this.#updateDisplay();
874
+ }
875
+
876
+ setShowImages(show: boolean): void {
877
+ this.#showImages = show;
878
+ this.#updateDisplay();
879
+ }
880
+
881
+ override invalidate(): void {
882
+ super.invalidate();
883
+ this.#updateDisplay();
884
+ }
885
+
886
+ #updateDisplay(): void {
887
+ // `TERMINAL.imageProtocol` is resolved by an async capability probe during
888
+ // TUI startup, so a result rendered before it lands must re-shape once it
889
+ // does (it gates Image children vs text fallback in #rebuildDisplay); keyed
890
+ // here for the same reason markdown.ts keys its render cache on it.
891
+ const key = `${this.#resultVersion}|${this.#expanded}|${this.#isPartial}|${this.#spinnerFrame ?? "-"}|${this.#showImages}|${getThemeEpoch()}|${this.#displayInputVersion}|${this.#backgroundTaskFrozen}|${TERMINAL.imageProtocol ?? "-"}|${this.#imageSizeKey()}`;
892
+ if (key === this.#lastDisplayKey && this.#displayBuilt) return;
893
+ this.#lastDisplayKey = key;
894
+
895
+ this.#rebuildDisplay();
896
+ this.#displayBuilt = true;
897
+ }
898
+
899
+ #rendererFlag(name: "forceResultViewportRepaintOnSettle"): boolean {
900
+ const toolValue = (this.#tool as Record<string, unknown> | undefined)?.[name];
901
+ const rendererValue = toolRenderers[this.#toolName]?.[name];
902
+ return toolValue === true || (toolValue === undefined && rendererValue === true);
903
+ }
904
+
905
+ /**
906
+ * True while the last painted pending-call shape opted into a full viewport
907
+ * repaint at the first result (`forceFirstResultViewportRepaint`) — e.g. a
908
+ * collapsed write tail window, which the first result render re-anchors
909
+ * instead of preserving. Kept as a per-paint fact so a topology-changing update that
910
+ * lands before the pending rows reach the terminal skips the reset.
911
+ */
912
+ #needsFirstResultViewportRepaintAtRender(): boolean {
913
+ if (this.#result !== undefined) return false;
914
+ const toolValue = (this.#tool as { forceFirstResultViewportRepaint?: FirstResultViewportRepaint } | undefined)
915
+ ?.forceFirstResultViewportRepaint;
916
+ const value =
917
+ toolValue !== undefined ? toolValue : toolRenderers[this.#toolName]?.forceFirstResultViewportRepaint;
918
+ if (typeof value === "function") return value(this.#args, this.#renderState);
919
+ return value === true;
920
+ }
921
+
922
+ #resetDisplayForResultTopologyChange(
923
+ firstResultAfterRepaintShapePaint: boolean,
924
+ partialResultPaintedBeforeSettle: boolean,
925
+ isPartial: boolean,
926
+ ): void {
927
+ const provisionalResultSettled =
928
+ partialResultPaintedBeforeSettle && !isPartial && this.#rendererFlag("forceResultViewportRepaintOnSettle");
929
+ if (firstResultAfterRepaintShapePaint || provisionalResultSettled) {
930
+ this.#ui.resetDisplay();
931
+ }
932
+ }
933
+
934
+ override render(width: number): readonly string[] {
935
+ const lines = super.render(width);
936
+ // Update the paint-tracking flags after `super.render(width)` — the
937
+ // override runs on every compose the parent Container performs, so a
938
+ // frame that never gets composed leaves the flags false and prevents a
939
+ // spurious `resetDisplay()`.
940
+ this.#firstResultViewportRepaintShapePainted = this.#needsFirstResultViewportRepaintAtRender();
941
+ this.#partialResultShapePainted = this.#result !== undefined && this.#isPartial;
942
+ return lines;
943
+ }
944
+
945
+ // Viewport-/settings-dependent image sizing folded into the memo key only when
946
+ // the last rebuild actually emitted images, so a terminal resize re-shapes an
947
+ // image-bearing result (to rescale it) without re-shaping every image-free
948
+ // result on each resize tick.
949
+ #imageSizeKey(): string {
950
+ if (this.#renderedImageCount === 0) return "-";
951
+ const o = resolveImageOptions();
952
+ return `${o.maxWidthCells}:${o.maxHeightCells ?? "-"}`;
953
+ }
954
+
955
+ #rebuildDisplay(): void {
956
+ // Sync shared mutable render state for component closures
957
+ this.#renderState.expanded = this.#expanded;
958
+ this.#renderState.isPartial = this.#isPartial;
959
+ this.#renderState.spinnerFrame = this.#spinnerFrame;
960
+
961
+ // Non-self-framing tools (custom/extension renderers and the generic
962
+ // fallback) get a padded, state-tinted block — built-ins that draw their
963
+ // own frame opt out below via the framed-component mark.
964
+ const stateBgKey = this.#isPartial ? "toolPendingBg" : this.#result?.isError ? "toolErrorBg" : "toolSuccessBg";
965
+ const stateBgFn = (t: string) => theme.bg(stateBgKey, t);
966
+
967
+ // Check for custom tool rendering
968
+ if (this.#tool && (this.#tool.renderCall || this.#tool.renderResult)) {
969
+ const tool = this.#tool;
970
+ const mergeCallAndResult = Boolean((tool as { mergeCallAndResult?: boolean }).mergeCallAndResult);
971
+ // Custom tools use Box for flexible component rendering
972
+ this.#contentBox.setBgFn(undefined);
973
+ this.#contentBox.clear();
974
+ // Mirror the built-in renderer branch so custom renderers (notably the
975
+ // task tool, whose live instance routes through here) receive the same
976
+ // render context — e.g. the `hasResult` flag that suppresses the task
977
+ // call preview once result lines exist.
978
+ this.#renderState.renderContext = this.#buildRenderContext();
979
+
980
+ // Render call component. The fallback label only stands in for a
981
+ // missing `renderCall`; when the call is intentionally suppressed
982
+ // (mergeCallAndResult once a result exists) we render nothing here so
983
+ // the result component isn't preceded by a redundant tool-name line.
984
+ const shouldRenderCall = !this.#result || !mergeCallAndResult;
985
+ if (shouldRenderCall) {
986
+ if (tool.renderCall) {
987
+ try {
988
+ const callArgs = this.#getCallArgsForRender();
989
+ const callComponent = tool.renderCall(callArgs, this.#renderState, theme) as Component | undefined;
990
+ if (callComponent) {
991
+ this.#contentBox.addChild(
992
+ new SafeToolRendererComponent(
993
+ this.#toolName,
994
+ "call",
995
+ callComponent,
996
+ () => new Text(theme.fg("toolTitle", theme.bold(this.#toolLabel)), 0, 0),
997
+ ),
998
+ );
999
+ }
1000
+ } catch (err) {
1001
+ logger.warn("Tool renderer failed", { tool: this.#toolName, error: String(err) });
1002
+ // Fall back to default on error
1003
+ this.#contentBox.addChild(new Text(theme.fg("toolTitle", theme.bold(this.#toolLabel)), 0, 0));
1004
+ }
1005
+ } else {
1006
+ // No custom renderCall, show tool name
1007
+ this.#contentBox.addChild(new Text(theme.fg("toolTitle", theme.bold(this.#toolLabel)), 0, 0));
1008
+ }
1009
+ }
1010
+
1011
+ // Render result component if we have a result
1012
+ if (this.#result && tool.renderResult) {
1013
+ try {
1014
+ const renderResult = tool.renderResult as (
1015
+ result: { content: Array<{ type: string; text?: string }>; details?: unknown; isError?: boolean },
1016
+ options: { expanded: boolean; isPartial: boolean; spinnerFrame?: number },
1017
+ theme: Theme,
1018
+ args?: unknown,
1019
+ ) => Component;
1020
+ const resultComponent = renderResult(
1021
+ {
1022
+ content: this.#result.content as any,
1023
+ details: this.#result.details,
1024
+ isError: this.#result.isError,
1025
+ },
1026
+ this.#renderState,
1027
+ theme,
1028
+ this.#args,
1029
+ );
1030
+ if (resultComponent) {
1031
+ this.#contentBox.addChild(
1032
+ new SafeToolRendererComponent(this.#toolName, "result", resultComponent, () => {
1033
+ const output = this.#getTextOutput();
1034
+ if (!output) return undefined;
1035
+ return new Text(theme.fg("toolOutput", replaceTabs(output)), 0, 0);
1036
+ }),
1037
+ );
1038
+ }
1039
+ } catch (err) {
1040
+ logger.warn("Tool renderer failed", { tool: this.#toolName, error: String(err) });
1041
+ // Fall back to showing raw output on error
1042
+ const output = this.#getTextOutput();
1043
+ if (output) {
1044
+ this.#contentBox.addChild(new Text(theme.fg("toolOutput", replaceTabs(output)), 0, 0));
1045
+ }
1046
+ }
1047
+ } else if (this.#result) {
1048
+ // Has result but no custom renderResult
1049
+ const output = this.#getTextOutput();
1050
+ if (output) {
1051
+ this.#contentBox.addChild(new Text(theme.fg("toolOutput", replaceTabs(output)), 0, 0));
1052
+ }
1053
+ }
1054
+ // Custom tools that draw their own frame (task) render flush; plain
1055
+ // extension renderers get the padded, state-tinted block back.
1056
+ const customFramed = this.#contentBox.children.some(isFramedBlockComponent);
1057
+ this.#contentBox.setPaddingX(customFramed ? 0 : 1);
1058
+ this.#contentBox.setBgFn(customFramed ? undefined : stateBgFn);
1059
+ } else if (this.#toolName in toolRenderers) {
1060
+ // Built-in tools with renderers
1061
+ const renderer = toolRenderers[this.#toolName];
1062
+
1063
+ // Clean up previous multi-file boxes
1064
+ for (const box of this.#multiFileBoxes) {
1065
+ this.removeChild(box);
1066
+ }
1067
+ this.#multiFileBoxes = [];
1068
+
1069
+ // Check for multi-file edit results
1070
+ const perFileResults = this.#result?.details?.perFileResults as
1071
+ | Array<{ path: string; isError?: boolean }>
1072
+ | undefined;
1073
+ if (perFileResults && perFileResults.length > 1) {
1074
+ // Multi-file: render each file as its own Box (identical to separate tool calls)
1075
+ this.#contentBox.setBgFn(undefined);
1076
+ this.#contentBox.clear();
1077
+
1078
+ const renderContext = this.#buildRenderContext();
1079
+ this.#renderState.renderContext = renderContext;
1080
+
1081
+ for (let i = 0; i < perFileResults.length; i++) {
1082
+ const fileResult = perFileResults[i];
1083
+ if (i > 0) {
1084
+ const spacer = new Spacer(1);
1085
+ this.#multiFileBoxes.push(spacer);
1086
+ this.addChild(spacer);
1087
+ }
1088
+ const fileBox = new Box(0, 0);
1089
+ try {
1090
+ const resultComponent = renderer.renderResult(
1091
+ { content: [], details: fileResult, isError: fileResult.isError },
1092
+ this.#renderState,
1093
+ theme,
1094
+ );
1095
+ if (resultComponent) {
1096
+ fileBox.addChild(
1097
+ new SafeToolRendererComponent(this.#toolName, "result", resultComponent, () => undefined),
1098
+ );
1099
+ }
1100
+ } catch (err) {
1101
+ logger.warn("Tool renderer failed", { tool: this.#toolName, error: String(err) });
1102
+ }
1103
+ this.#multiFileBoxes.push(fileBox);
1104
+ this.addChild(fileBox);
1105
+ }
1106
+
1107
+ // Show pending indicator for remaining files
1108
+ const totalFiles = this.#args?.edits
1109
+ ? new Set((this.#args.edits as any[]).map((e: any) => e?.path).filter(Boolean)).size
1110
+ : 0;
1111
+ const remaining = Math.max(0, totalFiles - perFileResults.length);
1112
+ if (remaining > 0 && this.#isPartial) {
1113
+ const pendingSpacer = new Spacer(1);
1114
+ this.#multiFileBoxes.push(pendingSpacer);
1115
+ this.addChild(pendingSpacer);
1116
+ const pendingBox = new Box(0, 0);
1117
+ const spinner =
1118
+ this.#spinnerFrame !== undefined ? formatStatusIcon("running", theme, this.#spinnerFrame) : "";
1119
+ const pendingText = renderStatusLine(
1120
+ {
1121
+ iconOverride: spinner,
1122
+ title: "Edit",
1123
+ description: theme.fg("dim", `${remaining} more file${remaining > 1 ? "s" : ""} pending…`),
1124
+ },
1125
+ theme,
1126
+ );
1127
+ pendingBox.addChild(new Text(pendingText, 0, 0));
1128
+ this.#multiFileBoxes.push(pendingBox);
1129
+ this.addChild(pendingBox);
1130
+ }
1131
+ } else {
1132
+ // Single-file or no result: standard rendering
1133
+ // Inline renderers skip background styling
1134
+ this.#contentBox.setBgFn(undefined);
1135
+ this.#contentBox.clear();
1136
+
1137
+ const renderContext = this.#buildRenderContext();
1138
+ this.#renderState.renderContext = renderContext;
1139
+
1140
+ const shouldRenderCall = !this.#result || !renderer.mergeCallAndResult;
1141
+ if (shouldRenderCall) {
1142
+ // Render call component
1143
+ try {
1144
+ const callArgs = this.#getCallArgsForRender();
1145
+ const callComponent = renderer.renderCall(callArgs, this.#renderState, theme);
1146
+ if (callComponent) {
1147
+ this.#contentBox.addChild(
1148
+ new SafeToolRendererComponent(
1149
+ this.#toolName,
1150
+ "call",
1151
+ callComponent,
1152
+ () => new Text(theme.fg("toolTitle", theme.bold(this.#toolLabel)), 0, 0),
1153
+ ),
1154
+ );
1155
+ }
1156
+ } catch (err) {
1157
+ logger.warn("Tool renderer failed", { tool: this.#toolName, error: String(err) });
1158
+ // Fall back to default on error
1159
+ this.#contentBox.addChild(new Text(theme.fg("toolTitle", theme.bold(this.#toolLabel)), 0, 0));
1160
+ }
1161
+ }
1162
+
1163
+ // Render result component if we have a result
1164
+ if (this.#result) {
1165
+ try {
1166
+ const resultComponent = renderer.renderResult(
1167
+ {
1168
+ content: this.#result.content as any,
1169
+ details: this.#result.details,
1170
+ isError: this.#result.isError,
1171
+ },
1172
+ this.#renderState,
1173
+ theme,
1174
+ this.#getCallArgsForRender(),
1175
+ );
1176
+ if (resultComponent) {
1177
+ this.#contentBox.addChild(
1178
+ new SafeToolRendererComponent(this.#toolName, "result", resultComponent, () => {
1179
+ const output = this.#getTextOutput();
1180
+ if (!output) return undefined;
1181
+ return new Text(theme.fg("toolOutput", replaceTabs(output)), 0, 0);
1182
+ }),
1183
+ );
1184
+ }
1185
+ } catch (err) {
1186
+ logger.warn("Tool renderer failed", { tool: this.#toolName, error: String(err) });
1187
+ // Fall back to showing raw output on error
1188
+ const output = this.#getTextOutput();
1189
+ if (output) {
1190
+ this.#contentBox.addChild(new Text(theme.fg("toolOutput", replaceTabs(output)), 0, 0));
1191
+ }
1192
+ }
1193
+ }
1194
+ }
1195
+ } else {
1196
+ // Generic fallback (no custom/built-in renderer). WidthAwareText
1197
+ // reformats at render time so output fills the actual terminal width
1198
+ // instead of a fixed column cap.
1199
+ this.#contentText.setCustomBgFn(stateBgFn);
1200
+ this.#contentText.invalidate();
1201
+ }
1202
+
1203
+ // Handle images (same for both custom and built-in)
1204
+ for (const img of this.#imageComponents) {
1205
+ this.removeChild(img);
1206
+ }
1207
+ this.#imageComponents = [];
1208
+ for (const spacer of this.#imageSpacers) {
1209
+ this.removeChild(spacer);
1210
+ }
1211
+ this.#imageSpacers = [];
1212
+
1213
+ if (this.#result) {
1214
+ const imageBlocks = this.#getAllImageBlocks();
1215
+
1216
+ for (let i = 0; i < imageBlocks.length; i++) {
1217
+ const img = imageBlocks[i];
1218
+ if (TERMINAL.imageProtocol && this.#showImages && img.data && img.mimeType) {
1219
+ // Use converted PNG for Kitty protocol if available
1220
+ const converted = this.#convertedImages.get(i);
1221
+ const imageData = converted?.data ?? img.data;
1222
+ const imageMimeType = converted?.mimeType ?? img.mimeType;
1223
+
1224
+ // For Kitty, skip non-PNG images that haven't been converted yet
1225
+ if (TERMINAL.imageProtocol === ImageProtocol.Kitty && imageMimeType !== "image/png") {
1226
+ continue;
1227
+ }
1228
+
1229
+ const spacer = new Spacer(1);
1230
+ this.addChild(spacer);
1231
+ this.#imageSpacers.push(spacer);
1232
+ const imageComponent = new Image(
1233
+ imageData,
1234
+ imageMimeType,
1235
+ { fallbackColor: (s: string) => theme.fg("toolOutput", s) },
1236
+ { ...resolveImageOptions(), budget: this.#ui.imageBudget, imageKey: `te${this.#instanceId}:${i}` },
1237
+ );
1238
+ this.#imageComponents.push(imageComponent);
1239
+ this.addChild(imageComponent);
1240
+ }
1241
+ }
1242
+ }
1243
+ this.#renderedImageCount = this.#imageComponents.length;
1244
+ }
1245
+
1246
+ #getCallArgsForRender(): any {
1247
+ const renderArgs = getArgsWithStreamedTextInput(this.#args);
1248
+ if (!isEditLikeToolName(this.#toolName)) {
1249
+ return renderArgs;
1250
+ }
1251
+ const previews = this.#editDiffPreview;
1252
+ if (!previews || previews.length === 0) {
1253
+ return renderArgs;
1254
+ }
1255
+ // Single-file previews feed the existing `previewDiff` channel consumed
1256
+ // by `formatStreamingDiff` in the renderer.
1257
+ const first = previews[0];
1258
+ if (!first?.diff) {
1259
+ return renderArgs;
1260
+ }
1261
+ return { ...(renderArgs as Record<string, unknown>), previewDiff: first.diff };
1262
+ }
1263
+
1264
+ /**
1265
+ * Build render context for tools that need extra state (bash, python, edit)
1266
+ */
1267
+ #buildRenderContext(): Record<string, unknown> {
1268
+ const context: Record<string, unknown> = {};
1269
+ const normalizeTimeoutSeconds = (value: unknown, maxSeconds: number): number | undefined => {
1270
+ if (typeof value !== "number" || !Number.isFinite(value)) return undefined;
1271
+ return Math.max(1, Math.min(maxSeconds, value));
1272
+ };
1273
+
1274
+ if (this.#toolName === "bash") {
1275
+ // Bash needs render context even before a result exists. The renderer uses the pending-call args
1276
+ // plus this context to keep the inline command preview visible while tool-call JSON is still streaming.
1277
+ if (this.#result) {
1278
+ // Pass raw output and expanded state - renderer handles width-aware truncation
1279
+ const output = this.#getTextOutput().trimEnd();
1280
+ context.output = output;
1281
+ }
1282
+ context.expanded = this.#expanded;
1283
+ context.previewLines = BASH_DEFAULT_PREVIEW_LINES;
1284
+ context.timeout = normalizeTimeoutSeconds(this.#args?.timeout, 3600);
1285
+ } else if (this.#toolName === "eval" && this.#result) {
1286
+ const output = this.#getTextOutput().trimEnd();
1287
+ context.output = output;
1288
+ context.expanded = this.#expanded;
1289
+ context.previewLines = EVAL_DEFAULT_PREVIEW_LINES;
1290
+ } else if (this.#toolName === "task") {
1291
+ // Once a result snapshot exists the task renderer's `renderResult`
1292
+ // draws every dispatched agent as a progress/result line, so tell
1293
+ // `renderCall` to drop its duplicate streaming preview list.
1294
+ context.hasResult = Boolean(this.#result);
1295
+ // Out of the transcript live region: progress rows render static gray
1296
+ // (see task/render.ts).
1297
+ context.frozen = this.#backgroundTaskFrozen;
1298
+ } else if (isEditLikeToolName(this.#toolName)) {
1299
+ context.editMode = this.#editMode;
1300
+ const previews = this.#editDiffPreview;
1301
+ if (previews && previews.length > 0) {
1302
+ const first = previews[0];
1303
+ if (first?.diff || first?.error) {
1304
+ context.editDiffPreview = first.error
1305
+ ? { error: first.error }
1306
+ : { diff: first.diff ?? "", firstChangedLine: first.firstChangedLine };
1307
+ }
1308
+ if (previews.length > 1) {
1309
+ context.perFileDiffPreview = previews;
1310
+ }
1311
+ }
1312
+ if (!previews?.some(preview => preview.diff)) {
1313
+ const editMode = this.#editMode;
1314
+ const strategy = editMode ? EDIT_MODE_STRATEGIES[editMode] : undefined;
1315
+ const fallback = strategy?.renderStreamingFallback(getArgsWithStreamedTextInput(this.#args), theme);
1316
+ if (fallback) context.editStreamingFallback = fallback;
1317
+ }
1318
+ context.renderDiff = renderDiff;
1319
+ } else if (this.#toolName === "write") {
1320
+ // Device-dispatch previews resolve renderers from the canonical tool map.
1321
+ const writeTool = this.#tool as { session?: { xdev?: XdevState } } | undefined;
1322
+ const xdev = writeTool?.session?.xdev;
1323
+ if (xdev) {
1324
+ context.resolveXdevMounted = (name: string) =>
1325
+ xdev.mountedNames.has(name) ? xdev.tools.get(name) : undefined;
1326
+ }
1327
+ }
1328
+
1329
+ return context;
1330
+ }
1331
+
1332
+ #getTextOutput(): string {
1333
+ if (!this.#result) return "";
1334
+
1335
+ const textBlocks = this.#result.content?.filter((c: any) => c.type === "text") || [];
1336
+ const imageBlocks = this.#getAllImageBlocks();
1337
+
1338
+ let output = textBlocks
1339
+ .map((c: any) => {
1340
+ return sanitizeWithOptionalSixelPassthrough(c.text || "", sanitizeText);
1341
+ })
1342
+ .join("\n");
1343
+
1344
+ if (imageBlocks.length > 0 && (!TERMINAL.imageProtocol || !this.#showImages)) {
1345
+ const imageIndicators = imageBlocks
1346
+ .map((img: any) => {
1347
+ const dims = img.data ? (getImageDimensions(img.data, img.mimeType) ?? undefined) : undefined;
1348
+ return imageFallback(img.mimeType, dims);
1349
+ })
1350
+ .join("\n");
1351
+ output = output ? `${output}\n${imageIndicators}` : imageIndicators;
1352
+ }
1353
+
1354
+ return output;
1355
+ }
1356
+ }