@sns-myagent/cli 0.2.0

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