@prometheus-ai/agent 0.5.4 → 0.5.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1145) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/cli.js +25110 -0
  3. package/dist/types/async/index.d.ts +0 -1
  4. package/dist/types/async/job-manager.d.ts +33 -0
  5. package/dist/types/autolearn/controller.d.ts +25 -0
  6. package/dist/types/autolearn/managed-skills.d.ts +45 -0
  7. package/dist/types/autoresearch/state.d.ts +1 -1
  8. package/dist/types/autoresearch/tools/init-experiment.d.ts +1 -1
  9. package/dist/types/autoresearch/tools/log-experiment.d.ts +1 -1
  10. package/dist/types/autoresearch/tools/run-experiment.d.ts +1 -1
  11. package/dist/types/autoresearch/tools/update-notes.d.ts +1 -1
  12. package/dist/types/autoresearch/types.d.ts +1 -1
  13. package/dist/types/capability/context-file.d.ts +0 -13
  14. package/dist/types/capability/mcp.d.ts +1 -0
  15. package/dist/types/capability/rule-buckets.d.ts +1 -1
  16. package/dist/types/capability/rule.d.ts +6 -1
  17. package/dist/types/capability/types.d.ts +0 -4
  18. package/dist/types/cli/args.d.ts +23 -3
  19. package/dist/types/cli/bench-cli.d.ts +78 -0
  20. package/dist/types/cli/claude-trace-cli.d.ts +7 -0
  21. package/dist/types/cli/dry-balance-cli.d.ts +16 -2
  22. package/dist/types/cli/gallery-cli.d.ts +43 -0
  23. package/dist/types/cli/gallery-fixtures/agentic.d.ts +2 -0
  24. package/dist/types/cli/gallery-fixtures/codeintel.d.ts +3 -0
  25. package/dist/types/cli/gallery-fixtures/edit.d.ts +3 -0
  26. package/dist/types/cli/gallery-fixtures/fs.d.ts +2 -0
  27. package/dist/types/cli/gallery-fixtures/index.d.ts +4 -0
  28. package/dist/types/cli/gallery-fixtures/interaction.d.ts +3 -0
  29. package/dist/types/cli/gallery-fixtures/memory.d.ts +2 -0
  30. package/dist/types/cli/gallery-fixtures/misc.d.ts +3 -0
  31. package/dist/types/cli/gallery-fixtures/search.d.ts +3 -0
  32. package/dist/types/cli/gallery-fixtures/shell.d.ts +3 -0
  33. package/dist/types/cli/gallery-fixtures/types.d.ts +55 -0
  34. package/dist/types/cli/gallery-fixtures/web.d.ts +2 -0
  35. package/dist/types/cli/gallery-screenshot.d.ts +35 -0
  36. package/dist/types/cli/grievances-cli.d.ts +1 -1
  37. package/dist/types/cli/list-models.d.ts +6 -14
  38. package/dist/types/cli/models-cli.d.ts +49 -0
  39. package/dist/types/cli/session-picker.d.ts +1 -1
  40. package/dist/types/cli/setup-cli.d.ts +1 -1
  41. package/dist/types/cli/setup-model-picker.d.ts +14 -0
  42. package/dist/types/cli/startup-cwd.d.ts +2 -0
  43. package/dist/types/cli/update-cli.d.ts +13 -40
  44. package/dist/types/cli/usage-cli.d.ts +81 -0
  45. package/dist/types/cli-commands.d.ts +12 -0
  46. package/dist/types/collab/crypto.d.ts +7 -0
  47. package/dist/types/collab/guest.d.ts +37 -0
  48. package/dist/types/collab/host.d.ts +29 -0
  49. package/dist/types/collab/protocol.d.ts +119 -0
  50. package/dist/types/collab/relay-client.d.ts +22 -0
  51. package/dist/types/commands/bench.d.ts +29 -0
  52. package/dist/types/commands/gallery.d.ts +47 -0
  53. package/dist/types/commands/install.d.ts +1 -1
  54. package/dist/types/commands/join.d.ts +12 -0
  55. package/dist/types/commands/launch.d.ts +8 -4
  56. package/dist/types/commands/models.d.ts +33 -0
  57. package/dist/types/commands/read.d.ts +1 -1
  58. package/dist/types/commands/say.d.ts +24 -0
  59. package/dist/types/commands/token.d.ts +25 -0
  60. package/dist/types/commands/usage.d.ts +34 -0
  61. package/dist/types/commit/agentic/tools/analyze-file.d.ts +1 -1
  62. package/dist/types/commit/agentic/tools/git-file-diff.d.ts +1 -1
  63. package/dist/types/commit/agentic/tools/git-hunk.d.ts +1 -1
  64. package/dist/types/commit/agentic/tools/git-overview.d.ts +1 -1
  65. package/dist/types/commit/agentic/tools/propose-changelog.d.ts +1 -1
  66. package/dist/types/commit/agentic/tools/propose-commit.d.ts +1 -1
  67. package/dist/types/commit/agentic/tools/recent-commits.d.ts +1 -1
  68. package/dist/types/commit/agentic/tools/schemas.d.ts +1 -1
  69. package/dist/types/commit/agentic/tools/split-commit.d.ts +1 -1
  70. package/dist/types/commit/analysis/conventional.d.ts +2 -2
  71. package/dist/types/commit/analysis/summary.d.ts +2 -2
  72. package/dist/types/commit/changelog/generate.d.ts +3 -3
  73. package/dist/types/commit/changelog/index.d.ts +2 -2
  74. package/dist/types/commit/map-reduce/index.d.ts +3 -3
  75. package/dist/types/commit/map-reduce/map-phase.d.ts +2 -2
  76. package/dist/types/commit/map-reduce/reduce-phase.d.ts +2 -2
  77. package/dist/types/commit/model-selection.d.ts +10 -4
  78. package/dist/types/commit/shared-llm.d.ts +1 -1
  79. package/dist/types/config/api-key-resolver.d.ts +43 -0
  80. package/dist/types/config/append-only-context-mode.d.ts +2 -1
  81. package/dist/types/config/keybindings.d.ts +12 -7
  82. package/dist/types/config/model-discovery.d.ts +57 -0
  83. package/dist/types/config/model-equivalence.d.ts +1 -1
  84. package/dist/types/config/model-registry.d.ts +86 -222
  85. package/dist/types/config/model-resolver.d.ts +43 -12
  86. package/dist/types/config/model-roles.d.ts +29 -0
  87. package/dist/types/config/models-config-schema.d.ts +536 -43
  88. package/dist/types/config/models-config.d.ts +391 -0
  89. package/dist/types/config/settings-schema.d.ts +1202 -324
  90. package/dist/types/config/settings.d.ts +15 -3
  91. package/dist/types/dap/config.d.ts +14 -1
  92. package/dist/types/dap/types.d.ts +10 -0
  93. package/dist/types/debug/log-viewer.d.ts +1 -1
  94. package/dist/types/debug/raw-sse.d.ts +1 -1
  95. package/dist/types/debug/report-bundle.d.ts +3 -0
  96. package/dist/types/debug/terminal-info.d.ts +0 -1
  97. package/dist/types/discovery/at-imports.d.ts +15 -0
  98. package/dist/types/discovery/prometheus-extension-roots.d.ts +7 -7
  99. package/dist/types/edit/diff.d.ts +3 -2
  100. package/dist/types/edit/file-snapshot-store.d.ts +18 -0
  101. package/dist/types/edit/hashline/noop-loop-guard.d.ts +72 -0
  102. package/dist/types/edit/hashline/params.d.ts +1 -1
  103. package/dist/types/edit/index.d.ts +0 -1
  104. package/dist/types/edit/modes/apply-patch.d.ts +1 -1
  105. package/dist/types/edit/modes/patch.d.ts +1 -1
  106. package/dist/types/edit/modes/replace.d.ts +1 -1
  107. package/dist/types/edit/renderer.d.ts +1 -0
  108. package/dist/types/eval/__tests__/completion-bridge.test.d.ts +1 -0
  109. package/dist/types/eval/__tests__/helpers-local-roots.test.d.ts +1 -0
  110. package/dist/types/eval/__tests__/js-context-manager.test.d.ts +1 -0
  111. package/dist/types/eval/backend.d.ts +7 -2
  112. package/dist/types/eval/bridge-timeout.d.ts +1 -1
  113. package/dist/types/eval/completion-bridge.d.ts +25 -0
  114. package/dist/types/eval/idle-timeout.d.ts +1 -5
  115. package/dist/types/eval/js/context-manager.d.ts +1 -0
  116. package/dist/types/eval/js/executor.d.ts +2 -0
  117. package/dist/types/eval/js/index.d.ts +1 -1
  118. package/dist/types/eval/js/shared/helpers.d.ts +7 -1
  119. package/dist/types/eval/js/shared/rewrite-imports.d.ts +6 -6
  120. package/dist/types/eval/js/shared/runtime.d.ts +6 -1
  121. package/dist/types/eval/js/worker-protocol.d.ts +6 -0
  122. package/dist/types/eval/py/__tests__/prelude.test.d.ts +1 -0
  123. package/dist/types/eval/py/executor.d.ts +12 -0
  124. package/dist/types/eval/py/index.d.ts +1 -1
  125. package/dist/types/eval/py/kernel.d.ts +6 -1
  126. package/dist/types/eval/py/runtime.d.ts +9 -0
  127. package/dist/types/exa/index.d.ts +1 -19
  128. package/dist/types/exa/mcp-client.d.ts +10 -3
  129. package/dist/types/exa/types.d.ts +0 -83
  130. package/dist/types/exec/bash-executor.d.ts +7 -0
  131. package/dist/types/export/custom-share.d.ts +1 -2
  132. package/dist/types/export/html/index.d.ts +39 -0
  133. package/dist/types/export/html/template-js.d.ts +2 -0
  134. package/dist/types/export/share.d.ts +61 -0
  135. package/dist/types/export/ttsr.d.ts +14 -0
  136. package/dist/types/extensibility/custom-commands/types.d.ts +9 -4
  137. package/dist/types/extensibility/custom-tools/loader.d.ts +30 -4
  138. package/dist/types/extensibility/custom-tools/types.d.ts +16 -8
  139. package/dist/types/extensibility/extensions/index.d.ts +1 -1
  140. package/dist/types/extensibility/extensions/loader.d.ts +20 -1
  141. package/dist/types/extensibility/extensions/model-api.d.ts +17 -0
  142. package/dist/types/extensibility/extensions/runner.d.ts +5 -2
  143. package/dist/types/extensibility/extensions/types.d.ts +72 -11
  144. package/dist/types/extensibility/hooks/index.d.ts +2 -1
  145. package/dist/types/extensibility/hooks/loader.d.ts +1 -1
  146. package/dist/types/extensibility/hooks/types.d.ts +11 -5
  147. package/dist/types/extensibility/{legacy-pi-ai-shim.d.ts → legacy-package-ai-shim.d.ts} +2 -2
  148. package/dist/types/extensibility/plugins/{legacy-pi-compat.d.ts → legacy-package-compat.d.ts} +20 -3
  149. package/dist/types/extensibility/plugins/loader.d.ts +11 -0
  150. package/dist/types/extensibility/plugins/marketplace-auto-update.d.ts +8 -0
  151. package/dist/types/extensibility/plugins/types.d.ts +2 -2
  152. package/dist/types/extensibility/shared-events.d.ts +3 -3
  153. package/dist/types/extensibility/skills.d.ts +10 -0
  154. package/dist/types/extensibility/slash-commands.d.ts +1 -11
  155. package/dist/types/goals/guided-setup.d.ts +18 -0
  156. package/dist/types/goals/state.d.ts +1 -1
  157. package/dist/types/goals/tools/goal-tool.d.ts +1 -1
  158. package/dist/types/hindsight/mental-models.d.ts +17 -8
  159. package/dist/types/hindsight/transcript.d.ts +1 -1
  160. package/dist/types/index.d.ts +5 -0
  161. package/dist/types/internal-urls/artifact-protocol.d.ts +2 -2
  162. package/dist/types/internal-urls/history-protocol.d.ts +14 -0
  163. package/dist/types/internal-urls/index.d.ts +1 -0
  164. package/dist/types/internal-urls/local-protocol.d.ts +14 -2
  165. package/dist/types/internal-urls/types.d.ts +1 -1
  166. package/dist/types/irc/bus.d.ts +79 -0
  167. package/dist/types/lib/xai-http.d.ts +1 -1
  168. package/dist/types/lsp/client.d.ts +10 -0
  169. package/dist/types/lsp/config.d.ts +2 -2
  170. package/dist/types/lsp/edits.d.ts +9 -0
  171. package/dist/types/lsp/format-options.d.ts +32 -0
  172. package/dist/types/lsp/index.d.ts +2 -7
  173. package/dist/types/lsp/types.d.ts +13 -1
  174. package/dist/types/lsp/utils.d.ts +6 -2
  175. package/dist/types/main.d.ts +23 -8
  176. package/dist/types/mcp/json-rpc.d.ts +5 -0
  177. package/dist/types/mcp/manager.d.ts +8 -0
  178. package/dist/types/mcp/oauth-discovery.d.ts +6 -1
  179. package/dist/types/mcp/oauth-flow.d.ts +13 -3
  180. package/dist/types/mcp/startup-events.d.ts +11 -0
  181. package/dist/types/mcp/tool-bridge.d.ts +2 -0
  182. package/dist/types/mcp/transports/stdio.d.ts +13 -0
  183. package/dist/types/mcp/types.d.ts +2 -0
  184. package/dist/types/memories/index.d.ts +7 -15
  185. package/dist/types/memories/storage.d.ts +0 -10
  186. package/dist/types/memory-backend/index.d.ts +3 -1
  187. package/dist/types/memory-backend/local-backend.d.ts +4 -3
  188. package/dist/types/memory-backend/resolve.d.ts +2 -2
  189. package/dist/types/memory-backend/runtime.d.ts +4 -0
  190. package/dist/types/memory-backend/types.d.ts +67 -2
  191. package/dist/types/mnemopi/config.d.ts +31 -1
  192. package/dist/types/mnemopi/state.d.ts +40 -2
  193. package/dist/types/modes/acp/acp-agent.d.ts +1 -2
  194. package/dist/types/modes/components/agent-dashboard.d.ts +17 -1
  195. package/dist/types/modes/components/agent-hub.d.ts +82 -0
  196. package/dist/types/modes/components/assistant-message.d.ts +5 -12
  197. package/dist/types/modes/components/bash-execution.d.ts +1 -1
  198. package/dist/types/modes/components/chat-block.d.ts +64 -0
  199. package/dist/types/modes/components/collab-prompt-message.d.ts +10 -0
  200. package/dist/types/modes/components/compaction-summary-message.d.ts +25 -5
  201. package/dist/types/modes/components/copy-selector.d.ts +1 -1
  202. package/dist/types/modes/components/custom-editor.d.ts +49 -2
  203. package/dist/types/modes/components/custom-editor.test.d.ts +1 -0
  204. package/dist/types/modes/components/dynamic-border.d.ts +1 -1
  205. package/dist/types/modes/components/extensions/extension-dashboard.d.ts +1 -1
  206. package/dist/types/modes/components/extensions/extension-list.d.ts +1 -1
  207. package/dist/types/modes/components/extensions/inspector-panel.d.ts +1 -1
  208. package/dist/types/modes/components/footer.d.ts +1 -1
  209. package/dist/types/modes/components/hook-editor.d.ts +5 -0
  210. package/dist/types/modes/components/hook-input.d.ts +4 -0
  211. package/dist/types/modes/components/hook-selector.d.ts +5 -7
  212. package/dist/types/modes/components/index.d.ts +1 -0
  213. package/dist/types/modes/components/late-diagnostics-message.d.ts +20 -0
  214. package/dist/types/modes/components/logout-account-selector.d.ts +8 -0
  215. package/dist/types/modes/components/mcp-add-wizard.d.ts +2 -1
  216. package/dist/types/modes/components/model-selector.d.ts +1 -1
  217. package/dist/types/modes/components/oauth-selector.d.ts +10 -1
  218. package/dist/types/modes/components/overlay-box.d.ts +17 -0
  219. package/dist/types/modes/components/plan-review-overlay.d.ts +61 -0
  220. package/dist/types/modes/components/plan-toc.d.ts +41 -0
  221. package/dist/types/modes/components/read-tool-group.d.ts +8 -0
  222. package/dist/types/modes/components/reset-usage-selector.d.ts +12 -0
  223. package/dist/types/modes/components/segment-track.d.ts +11 -6
  224. package/dist/types/modes/components/session-selector.d.ts +18 -9
  225. package/dist/types/modes/components/settings-defs.d.ts +9 -2
  226. package/dist/types/modes/components/settings-selector.d.ts +17 -4
  227. package/dist/types/modes/components/snapcompact-shape-preview.d.ts +31 -0
  228. package/dist/types/modes/components/status-line/component.d.ts +61 -0
  229. package/dist/types/modes/components/status-line/index.d.ts +1 -0
  230. package/dist/types/modes/components/status-line/types.d.ts +47 -3
  231. package/dist/types/modes/components/tiny-title-download-progress.d.ts +1 -1
  232. package/dist/types/modes/components/tool-execution.d.ts +49 -2
  233. package/dist/types/modes/components/transcript-container.d.ts +76 -26
  234. package/dist/types/modes/components/tree-selector.d.ts +2 -2
  235. package/dist/types/modes/components/ttsr-notification.d.ts +5 -1
  236. package/dist/types/modes/components/usage-row.d.ts +3 -0
  237. package/dist/types/modes/components/user-message-selector.d.ts +1 -1
  238. package/dist/types/modes/components/user-message.d.ts +2 -1
  239. package/dist/types/modes/components/visual-truncate.d.ts +1 -1
  240. package/dist/types/modes/components/welcome.d.ts +12 -2
  241. package/dist/types/modes/controllers/command-controller.d.ts +3 -2
  242. package/dist/types/modes/controllers/event-controller.d.ts +7 -1
  243. package/dist/types/modes/controllers/extension-ui-controller.d.ts +0 -1
  244. package/dist/types/modes/controllers/input-controller.d.ts +25 -3
  245. package/dist/types/modes/controllers/mcp-command-controller.d.ts +8 -0
  246. package/dist/types/modes/controllers/selector-controller.d.ts +5 -2
  247. package/dist/types/modes/controllers/session-focus-controller.d.ts +31 -0
  248. package/dist/types/modes/controllers/streaming-reveal.d.ts +22 -0
  249. package/dist/types/modes/controllers/tan-command-controller.d.ts +6 -0
  250. package/dist/types/modes/controllers/tool-args-reveal.d.ts +43 -0
  251. package/dist/types/modes/gradient-highlight.d.ts +9 -4
  252. package/dist/types/modes/image-references.d.ts +14 -3
  253. package/dist/types/modes/index.d.ts +8 -7
  254. package/dist/types/modes/interactive-mode.d.ts +92 -16
  255. package/dist/types/modes/magic-keywords.d.ts +14 -2
  256. package/dist/types/modes/markdown-prose.d.ts +1 -1
  257. package/dist/types/modes/oauth-manual-input.d.ts +7 -0
  258. package/dist/types/modes/rpc/rpc-client.d.ts +48 -2
  259. package/dist/types/modes/rpc/rpc-mode.d.ts +67 -2
  260. package/dist/types/modes/rpc/rpc-subagents.d.ts +24 -0
  261. package/dist/types/modes/rpc/rpc-types.d.ts +113 -1
  262. package/dist/types/modes/runtime-init.d.ts +4 -0
  263. package/dist/types/modes/session-observer-registry.d.ts +9 -0
  264. package/dist/types/modes/setup-version.d.ts +11 -0
  265. package/dist/types/modes/setup-wizard/index.d.ts +7 -2
  266. package/dist/types/modes/setup-wizard/lazy.d.ts +2 -0
  267. package/dist/types/modes/setup-wizard/scenes/sign-in.d.ts +4 -1
  268. package/dist/types/modes/setup-wizard/scenes/types.d.ts +11 -2
  269. package/dist/types/modes/setup-wizard/scenes/web-search.d.ts +6 -2
  270. package/dist/types/modes/setup-wizard/wizard-overlay.d.ts +1 -1
  271. package/dist/types/modes/theme/theme.d.ts +42 -7
  272. package/dist/types/modes/types.d.ts +62 -13
  273. package/dist/types/modes/utils/context-usage.d.ts +6 -1
  274. package/dist/types/modes/utils/copy-targets.d.ts +21 -1
  275. package/dist/types/modes/utils/ui-helpers.d.ts +4 -4
  276. package/dist/types/modes/workflow.d.ts +3 -3
  277. package/dist/types/plan-mode/approved-plan.d.ts +27 -8
  278. package/dist/types/plan-mode/plan-protection.d.ts +4 -4
  279. package/dist/types/registry/agent-lifecycle.d.ts +51 -0
  280. package/dist/types/registry/agent-registry.d.ts +33 -5
  281. package/dist/types/sdk.d.ts +46 -4
  282. package/dist/types/secrets/index.d.ts +1 -1
  283. package/dist/types/secrets/obfuscator.d.ts +9 -3
  284. package/dist/types/session/agent-session.d.ts +136 -66
  285. package/dist/types/session/agent-storage.d.ts +2 -1
  286. package/dist/types/session/auth-broker-config.d.ts +4 -0
  287. package/dist/types/session/auth-storage.d.ts +1 -1
  288. package/dist/types/session/codex-auto-reset.d.ts +111 -0
  289. package/dist/types/session/indexed-session-storage.d.ts +3 -3
  290. package/dist/types/session/messages.d.ts +26 -15
  291. package/dist/types/session/session-context.d.ts +39 -0
  292. package/dist/types/session/session-entries.d.ts +159 -0
  293. package/dist/types/session/session-history-format.d.ts +12 -0
  294. package/dist/types/session/session-listing.d.ts +69 -0
  295. package/dist/types/session/session-loader.d.ts +16 -0
  296. package/dist/types/session/session-manager.d.ts +107 -440
  297. package/dist/types/session/session-migrations.d.ts +12 -0
  298. package/dist/types/session/session-paths.d.ts +25 -0
  299. package/dist/types/session/session-persistence.d.ts +8 -0
  300. package/dist/types/session/session-storage.d.ts +11 -7
  301. package/dist/types/session/snapcompact-inline.d.ts +145 -0
  302. package/dist/types/session/snapcompact-savings-journal.d.ts +46 -0
  303. package/dist/types/session/streaming-output.d.ts +46 -0
  304. package/dist/types/session/tool-choice-queue.d.ts +6 -6
  305. package/dist/types/session/yield-queue.d.ts +10 -1
  306. package/dist/types/slash-commands/acp-builtins.d.ts +16 -0
  307. package/dist/types/slash-commands/available-commands.d.ts +34 -0
  308. package/dist/types/slash-commands/builtin-registry.d.ts +10 -0
  309. package/dist/types/slash-commands/helpers/active-oauth-account.d.ts +14 -0
  310. package/dist/types/slash-commands/helpers/logout.d.ts +15 -0
  311. package/dist/types/slash-commands/helpers/reset-usage.d.ts +27 -0
  312. package/dist/types/slash-commands/helpers/stats-dashboard.d.ts +13 -0
  313. package/dist/types/slash-commands/types.d.ts +5 -9
  314. package/dist/types/ssh/connection-manager.d.ts +8 -0
  315. package/dist/types/stt/asr-client.d.ts +90 -0
  316. package/dist/types/stt/asr-protocol.d.ts +97 -0
  317. package/dist/types/stt/asr-worker.d.ts +2 -0
  318. package/dist/types/stt/downloader.d.ts +38 -0
  319. package/dist/types/stt/endpointer.d.ts +59 -0
  320. package/dist/types/stt/index.d.ts +5 -1
  321. package/dist/types/stt/models.d.ts +120 -0
  322. package/dist/types/stt/recorder.d.ts +17 -0
  323. package/dist/types/stt/stt-controller.d.ts +6 -0
  324. package/dist/types/stt/transcriber.d.ts +5 -7
  325. package/dist/types/stt/wav.d.ts +29 -0
  326. package/dist/types/system-prompt.d.ts +9 -1
  327. package/dist/types/task/commands.d.ts +1 -1
  328. package/dist/types/task/discovery.d.ts +1 -2
  329. package/dist/types/task/executor.d.ts +61 -2
  330. package/dist/types/task/index.d.ts +37 -6
  331. package/dist/types/task/output-manager.d.ts +0 -7
  332. package/dist/types/task/parallel.d.ts +2 -2
  333. package/dist/types/task/prometheus-command.d.ts +2 -2
  334. package/dist/types/task/render.d.ts +20 -7
  335. package/dist/types/task/repair-args.d.ts +8 -7
  336. package/dist/types/task/types.d.ts +109 -52
  337. package/dist/types/task/worktree.d.ts +2 -0
  338. package/dist/types/telemetry-export.d.ts +2 -2
  339. package/dist/types/thinking.d.ts +4 -0
  340. package/dist/types/tiny/models.d.ts +1 -1
  341. package/dist/types/tiny/title-client.d.ts +12 -1
  342. package/dist/types/tiny/title-protocol.d.ts +1 -0
  343. package/dist/types/tools/archive-reader.d.ts +5 -0
  344. package/dist/types/tools/ask.d.ts +6 -1
  345. package/dist/types/tools/ast-edit.d.ts +4 -1
  346. package/dist/types/tools/ast-grep.d.ts +4 -1
  347. package/dist/types/tools/bash.d.ts +5 -2
  348. package/dist/types/tools/browser/attach.d.ts +4 -4
  349. package/dist/types/tools/browser/cmux/cmux-tab.d.ts +202 -0
  350. package/dist/types/tools/browser/cmux/rpc.d.ts +70 -0
  351. package/dist/types/tools/browser/cmux/socket-client.d.ts +19 -0
  352. package/dist/types/tools/browser/registry.d.ts +17 -3
  353. package/dist/types/tools/browser/render.d.ts +2 -0
  354. package/dist/types/tools/browser/tab-protocol.d.ts +2 -0
  355. package/dist/types/tools/browser/tab-supervisor.d.ts +16 -4
  356. package/dist/types/tools/browser/tab-worker.d.ts +18 -1
  357. package/dist/types/tools/browser.d.ts +3 -1
  358. package/dist/types/tools/checkpoint.d.ts +1 -1
  359. package/dist/types/tools/conflict-detect.d.ts +16 -0
  360. package/dist/types/tools/debug.d.ts +1 -1
  361. package/dist/types/tools/eval-render.d.ts +1 -8
  362. package/dist/types/tools/eval.d.ts +9 -1
  363. package/dist/types/tools/fetch.d.ts +17 -8
  364. package/dist/types/tools/find.d.ts +1 -8
  365. package/dist/types/tools/gh-cache-invalidation.d.ts +6 -0
  366. package/dist/types/tools/gh.d.ts +4 -1
  367. package/dist/types/tools/github-cache.d.ts +19 -0
  368. package/dist/types/tools/grouped-file-output.d.ts +46 -12
  369. package/dist/types/tools/image-gen.d.ts +1 -1
  370. package/dist/types/tools/index.d.ts +89 -8
  371. package/dist/types/tools/inspect-image.d.ts +1 -1
  372. package/dist/types/tools/irc.d.ts +79 -39
  373. package/dist/types/tools/job.d.ts +8 -2
  374. package/dist/types/tools/learn.d.ts +51 -0
  375. package/dist/types/tools/manage-skill.d.ts +40 -0
  376. package/dist/types/tools/memory-edit.d.ts +2 -2
  377. package/dist/types/tools/memory-recall.d.ts +1 -1
  378. package/dist/types/tools/memory-reflect.d.ts +1 -1
  379. package/dist/types/tools/memory-render.d.ts +4 -1
  380. package/dist/types/tools/memory-retain.d.ts +1 -1
  381. package/dist/types/tools/path-utils.d.ts +17 -5
  382. package/dist/types/tools/plan-mode-guard.d.ts +18 -9
  383. package/dist/types/tools/read.d.ts +3 -2
  384. package/dist/types/tools/render-mermaid.d.ts +1 -1
  385. package/dist/types/tools/render-utils.d.ts +47 -27
  386. package/dist/types/tools/renderers.d.ts +10 -2
  387. package/dist/types/tools/report-tool-issue.d.ts +6 -1
  388. package/dist/types/tools/resolve.d.ts +1 -1
  389. package/dist/types/tools/review.d.ts +1 -1
  390. package/dist/types/tools/search-tool-bm25.d.ts +1 -1
  391. package/dist/types/tools/search.d.ts +7 -3
  392. package/dist/types/tools/sqlite-reader.d.ts +4 -0
  393. package/dist/types/tools/ssh.d.ts +2 -1
  394. package/dist/types/tools/todo.d.ts +7 -15
  395. package/dist/types/tools/tool-result.d.ts +2 -0
  396. package/dist/types/tools/tool-timeouts.d.ts +1 -1
  397. package/dist/types/tools/tts.d.ts +26 -1
  398. package/dist/types/tools/write.d.ts +6 -3
  399. package/dist/types/tools/yield.d.ts +8 -0
  400. package/dist/types/tts/downloader.d.ts +20 -0
  401. package/dist/types/tts/index.d.ts +8 -0
  402. package/dist/types/tts/models.d.ts +82 -0
  403. package/dist/types/tts/player.d.ts +32 -0
  404. package/dist/types/tts/runtime.d.ts +6 -0
  405. package/dist/types/tts/streaming-player.d.ts +41 -0
  406. package/dist/types/tts/tts-client.d.ts +93 -0
  407. package/dist/types/tts/tts-protocol.d.ts +95 -0
  408. package/dist/types/tts/tts-worker.d.ts +2 -0
  409. package/dist/types/tts/vocalizer.d.ts +41 -0
  410. package/dist/types/tts/wav.d.ts +8 -0
  411. package/dist/types/tui/code-cell.d.ts +0 -2
  412. package/dist/types/tui/hyperlink.d.ts +13 -7
  413. package/dist/types/tui/output-block.d.ts +16 -22
  414. package/dist/types/tui/status-line.d.ts +3 -0
  415. package/dist/types/utils/block-context.d.ts +35 -0
  416. package/dist/types/utils/changelog.d.ts +8 -0
  417. package/dist/types/utils/clipboard.d.ts +4 -3
  418. package/dist/types/utils/enhanced-paste.d.ts +20 -0
  419. package/dist/types/utils/file-mentions.d.ts +7 -0
  420. package/dist/types/utils/git.d.ts +22 -3
  421. package/dist/types/utils/image-loading.d.ts +30 -1
  422. package/dist/types/utils/session-color.d.ts +15 -3
  423. package/dist/types/utils/thinking-display.d.ts +17 -0
  424. package/dist/types/utils/title-generator.d.ts +3 -2
  425. package/dist/types/utils/tool-choice.d.ts +8 -0
  426. package/dist/types/utils/tools-manager.d.ts +2 -1
  427. package/dist/types/web/kagi.d.ts +2 -2
  428. package/dist/types/web/parallel.d.ts +3 -0
  429. package/dist/types/web/scrapers/github.d.ts +22 -0
  430. package/dist/types/web/scrapers/readthedocs.d.ts +3 -0
  431. package/dist/types/web/scrapers/types.d.ts +12 -0
  432. package/dist/types/web/search/index.d.ts +1 -1
  433. package/dist/types/web/search/providers/anthropic.d.ts +2 -1
  434. package/dist/types/web/search/providers/base.d.ts +2 -1
  435. package/dist/types/web/search/providers/brave.d.ts +2 -1
  436. package/dist/types/web/search/providers/codex.d.ts +2 -1
  437. package/dist/types/web/search/providers/exa.d.ts +2 -1
  438. package/dist/types/web/search/providers/gemini.d.ts +10 -6
  439. package/dist/types/web/search/providers/jina.d.ts +7 -2
  440. package/dist/types/web/search/providers/kagi.d.ts +7 -2
  441. package/dist/types/web/search/providers/kimi.d.ts +7 -2
  442. package/dist/types/web/search/providers/parallel.d.ts +2 -1
  443. package/dist/types/web/search/providers/perplexity.d.ts +10 -2
  444. package/dist/types/web/search/providers/searxng.d.ts +2 -1
  445. package/dist/types/web/search/providers/synthetic.d.ts +7 -3
  446. package/dist/types/web/search/providers/tavily.d.ts +2 -1
  447. package/dist/types/web/search/providers/zai.d.ts +2 -1
  448. package/dist/types/web/search/types.d.ts +1 -1
  449. package/examples/extensions/api-demo.ts +2 -2
  450. package/package.json +41 -15
  451. package/scripts/bench-guard.ts +71 -0
  452. package/scripts/build-binary.ts +24 -25
  453. package/scripts/bundle-dist.ts +97 -0
  454. package/scripts/generate-share-viewer.ts +34 -0
  455. package/scripts/prometheus +42 -0
  456. package/scripts/prometheus.ts +20 -0
  457. package/src/async/index.ts +0 -1
  458. package/src/async/job-manager.ts +106 -3
  459. package/src/auto-thinking/classifier.ts +2 -1
  460. package/src/autolearn/controller.ts +139 -0
  461. package/src/autolearn/managed-skills.ts +257 -0
  462. package/src/autoresearch/dashboard.ts +1 -1
  463. package/src/autoresearch/prompt-setup.md +6 -6
  464. package/src/autoresearch/prompt.md +6 -6
  465. package/src/autoresearch/state.ts +1 -1
  466. package/src/autoresearch/storage.ts +2 -1
  467. package/src/autoresearch/tools/init-experiment.ts +1 -1
  468. package/src/autoresearch/tools/log-experiment.ts +1 -1
  469. package/src/autoresearch/tools/run-experiment.ts +1 -1
  470. package/src/autoresearch/tools/update-notes.ts +1 -1
  471. package/src/autoresearch/types.ts +1 -1
  472. package/src/capability/context-file.ts +0 -14
  473. package/src/capability/fs.ts +10 -0
  474. package/src/capability/index.ts +1 -6
  475. package/src/capability/mcp.ts +1 -0
  476. package/src/capability/rule-buckets.ts +4 -2
  477. package/src/capability/rule.ts +10 -1
  478. package/src/capability/types.ts +0 -4
  479. package/src/cli/args.ts +66 -13
  480. package/src/cli/auth-broker-cli.ts +6 -7
  481. package/src/cli/auth-gateway-cli.ts +8 -9
  482. package/src/cli/bench-cli.ts +437 -0
  483. package/src/cli/claude-trace-cli.ts +28 -50
  484. package/src/cli/completion-gen.ts +28 -28
  485. package/src/cli/dry-balance-cli.ts +56 -23
  486. package/src/cli/gallery-cli.ts +231 -0
  487. package/src/cli/gallery-fixtures/agentic.ts +407 -0
  488. package/src/cli/gallery-fixtures/codeintel.ts +187 -0
  489. package/src/cli/gallery-fixtures/edit.ts +194 -0
  490. package/src/cli/gallery-fixtures/fs.ts +220 -0
  491. package/src/cli/gallery-fixtures/index.ts +40 -0
  492. package/src/cli/gallery-fixtures/interaction.ts +49 -0
  493. package/src/cli/gallery-fixtures/memory.ts +81 -0
  494. package/src/cli/gallery-fixtures/misc.ts +250 -0
  495. package/src/cli/gallery-fixtures/search.ts +213 -0
  496. package/src/cli/gallery-fixtures/shell.ts +167 -0
  497. package/src/cli/gallery-fixtures/types.ts +57 -0
  498. package/src/cli/gallery-fixtures/web.ts +158 -0
  499. package/src/cli/gallery-screenshot.ts +279 -0
  500. package/src/cli/grievances-cli.ts +1 -1
  501. package/src/cli/list-models.ts +16 -174
  502. package/src/cli/models-cli.ts +429 -0
  503. package/src/cli/session-picker.ts +2 -1
  504. package/src/cli/setup-cli.ts +148 -47
  505. package/src/cli/setup-model-picker.ts +43 -0
  506. package/src/cli/startup-cwd.ts +68 -0
  507. package/src/cli/update-cli.ts +144 -272
  508. package/src/cli/usage-cli.ts +774 -0
  509. package/src/cli-commands.ts +36 -0
  510. package/src/cli.ts +141 -32
  511. package/src/collab/crypto.ts +63 -0
  512. package/src/collab/guest.ts +451 -0
  513. package/src/collab/host.ts +565 -0
  514. package/src/collab/protocol.ts +241 -0
  515. package/src/collab/relay-client.ts +216 -0
  516. package/src/commands/bench.ts +42 -0
  517. package/src/commands/complete.ts +1 -1
  518. package/src/commands/gallery.ts +52 -0
  519. package/src/commands/install.ts +1 -1
  520. package/src/commands/join.ts +39 -0
  521. package/src/commands/launch.ts +8 -4
  522. package/src/commands/models.ts +61 -0
  523. package/src/commands/read.ts +6 -3
  524. package/src/commands/say.ts +102 -0
  525. package/src/commands/setup.ts +1 -1
  526. package/src/commands/token.ts +89 -0
  527. package/src/commands/usage.ts +43 -0
  528. package/src/commit/agentic/agent.ts +2 -1
  529. package/src/commit/agentic/tools/analyze-file.ts +42 -20
  530. package/src/commit/agentic/tools/git-file-diff.ts +1 -1
  531. package/src/commit/agentic/tools/git-hunk.ts +1 -1
  532. package/src/commit/agentic/tools/git-overview.ts +1 -1
  533. package/src/commit/agentic/tools/propose-changelog.ts +1 -1
  534. package/src/commit/agentic/tools/propose-commit.ts +1 -1
  535. package/src/commit/agentic/tools/recent-commits.ts +1 -1
  536. package/src/commit/agentic/tools/schemas.ts +1 -1
  537. package/src/commit/agentic/tools/split-commit.ts +9 -2
  538. package/src/commit/analysis/conventional.ts +2 -2
  539. package/src/commit/analysis/summary.ts +3 -3
  540. package/src/commit/changelog/generate.ts +3 -3
  541. package/src/commit/changelog/index.ts +2 -2
  542. package/src/commit/map-reduce/index.ts +3 -3
  543. package/src/commit/map-reduce/map-phase.ts +2 -2
  544. package/src/commit/map-reduce/reduce-phase.ts +2 -2
  545. package/src/commit/model-selection.ts +35 -12
  546. package/src/commit/pipeline.ts +4 -4
  547. package/src/commit/shared-llm.ts +1 -1
  548. package/src/config/api-key-resolver.ts +67 -0
  549. package/src/config/append-only-context-mode.ts +6 -12
  550. package/src/config/keybindings.ts +9 -4
  551. package/src/config/mcp-schema.json +4 -0
  552. package/src/config/model-discovery.ts +574 -0
  553. package/src/config/model-equivalence.ts +5 -4
  554. package/src/config/model-registry.ts +659 -1093
  555. package/src/config/model-resolver.ts +374 -174
  556. package/src/config/model-roles.ts +88 -0
  557. package/src/config/models-config-schema.ts +61 -9
  558. package/src/config/models-config.ts +130 -0
  559. package/src/config/settings-schema.ts +1441 -387
  560. package/src/config/settings.ts +261 -69
  561. package/src/dap/client.ts +138 -53
  562. package/src/dap/config.ts +41 -2
  563. package/src/dap/defaults.json +1 -0
  564. package/src/dap/session.ts +263 -161
  565. package/src/dap/types.ts +10 -0
  566. package/src/debug/index.ts +50 -60
  567. package/src/debug/log-viewer.ts +1 -1
  568. package/src/debug/protocol-probe.ts +1 -1
  569. package/src/debug/raw-sse-buffer.ts +7 -4
  570. package/src/debug/raw-sse.ts +1 -1
  571. package/src/debug/report-bundle.ts +9 -0
  572. package/src/debug/terminal-info.ts +0 -3
  573. package/src/discovery/agents-md.ts +25 -21
  574. package/src/discovery/agents.ts +9 -15
  575. package/src/discovery/at-imports.ts +273 -0
  576. package/src/discovery/builtin-rules/index.ts +4 -0
  577. package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
  578. package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
  579. package/src/discovery/builtin.ts +45 -23
  580. package/src/discovery/claude-plugins.ts +44 -5
  581. package/src/discovery/helpers.ts +50 -9
  582. package/src/discovery/prometheus-extension-roots.ts +10 -10
  583. package/src/discovery/prometheus-plugins.ts +10 -10
  584. package/src/edit/diff.ts +191 -4
  585. package/src/edit/file-snapshot-store.ts +34 -1
  586. package/src/edit/hashline/block-resolver.ts +20 -1
  587. package/src/edit/hashline/diff.ts +123 -2
  588. package/src/edit/hashline/execute.ts +60 -4
  589. package/src/edit/hashline/filesystem.ts +2 -1
  590. package/src/edit/hashline/noop-loop-guard.ts +99 -0
  591. package/src/edit/hashline/params.ts +1 -1
  592. package/src/edit/index.ts +47 -18
  593. package/src/edit/modes/apply-patch.ts +1 -1
  594. package/src/edit/modes/patch.ts +59 -3
  595. package/src/edit/modes/replace.ts +58 -24
  596. package/src/edit/notebook.ts +22 -2
  597. package/src/edit/renderer.ts +315 -151
  598. package/src/eval/__tests__/agent-bridge.test.ts +105 -39
  599. package/src/eval/__tests__/budget-bridge.test.ts +1 -1
  600. package/src/eval/__tests__/completion-bridge.test.ts +412 -0
  601. package/src/eval/__tests__/helpers-local-roots.test.ts +58 -0
  602. package/src/eval/__tests__/js-context-manager.test.ts +241 -0
  603. package/src/eval/__tests__/llm-bridge.test.ts +6 -4
  604. package/src/eval/__tests__/shared-executors.test.ts +34 -92
  605. package/src/eval/agent-bridge.ts +39 -23
  606. package/src/eval/backend.ts +15 -2
  607. package/src/eval/bridge-timeout.ts +1 -1
  608. package/src/eval/completion-bridge.ts +203 -0
  609. package/src/eval/idle-timeout.ts +3 -10
  610. package/src/eval/js/context-manager.ts +108 -31
  611. package/src/eval/js/executor.ts +9 -2
  612. package/src/eval/js/index.ts +7 -3
  613. package/src/eval/js/shared/helpers.ts +59 -13
  614. package/src/eval/js/shared/local-module-loader.ts +2 -2
  615. package/src/eval/js/shared/prelude.txt +167 -30
  616. package/src/eval/js/shared/rewrite-imports.ts +58 -34
  617. package/src/eval/js/shared/runtime.ts +24 -16
  618. package/src/eval/js/tool-bridge.ts +4 -0
  619. package/src/eval/js/worker-core.ts +1 -0
  620. package/src/eval/js/worker-entry.ts +6 -0
  621. package/src/eval/js/worker-protocol.ts +6 -0
  622. package/src/eval/llm-bridge.ts +2 -1
  623. package/src/eval/py/__tests__/prelude.test.ts +19 -0
  624. package/src/eval/py/executor.ts +70 -26
  625. package/src/eval/py/index.ts +13 -4
  626. package/src/eval/py/kernel.ts +48 -9
  627. package/src/eval/py/prelude.py +73 -24
  628. package/src/eval/py/runner.py +133 -28
  629. package/src/eval/py/runtime.ts +38 -1
  630. package/src/exa/index.ts +1 -26
  631. package/src/exa/mcp-client.ts +10 -10
  632. package/src/exa/types.ts +0 -97
  633. package/src/exec/bash-executor.ts +104 -7
  634. package/src/export/custom-share.ts +1 -1
  635. package/src/export/html/index.ts +119 -17
  636. package/src/export/html/share-loader.js +102 -0
  637. package/src/export/html/template-js.ts +6 -0
  638. package/src/export/html/template.css +745 -459
  639. package/src/export/html/template.css.d.ts +2 -0
  640. package/src/export/html/template.html +6 -3
  641. package/src/export/html/template.js +277 -891
  642. package/src/export/html/tool-views.generated.d.ts +2 -0
  643. package/src/export/html/tool-views.generated.js +38 -0
  644. package/src/export/share.ts +269 -0
  645. package/src/export/ttsr.ts +122 -1
  646. package/src/extensibility/custom-commands/loader.ts +7 -4
  647. package/src/extensibility/custom-commands/types.ts +9 -4
  648. package/src/extensibility/custom-tools/loader.ts +51 -23
  649. package/src/extensibility/custom-tools/types.ts +16 -8
  650. package/src/extensibility/extensions/get-commands-handler.ts +2 -1
  651. package/src/extensibility/extensions/index.ts +1 -0
  652. package/src/extensibility/extensions/loader.ts +70 -20
  653. package/src/extensibility/extensions/model-api.ts +41 -0
  654. package/src/extensibility/extensions/runner.ts +12 -2
  655. package/src/extensibility/extensions/types.ts +83 -11
  656. package/src/extensibility/extensions/wrapper.ts +41 -5
  657. package/src/extensibility/hooks/index.ts +2 -1
  658. package/src/extensibility/hooks/loader.ts +6 -3
  659. package/src/extensibility/hooks/types.ts +11 -5
  660. package/src/extensibility/{legacy-pi-ai-shim.ts → legacy-package-ai-shim.ts} +2 -2
  661. package/src/extensibility/plugins/doctor.ts +1 -2
  662. package/src/extensibility/plugins/installer.ts +2 -2
  663. package/src/extensibility/plugins/{legacy-pi-compat.ts → legacy-package-compat.ts} +165 -77
  664. package/src/extensibility/plugins/loader.ts +34 -23
  665. package/src/extensibility/plugins/manager.ts +226 -95
  666. package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
  667. package/src/extensibility/plugins/types.ts +3 -3
  668. package/src/extensibility/shared-events.ts +3 -3
  669. package/src/extensibility/skills.ts +113 -9
  670. package/src/extensibility/slash-commands.ts +1 -97
  671. package/src/goals/guided-setup.ts +133 -0
  672. package/src/goals/state.ts +1 -1
  673. package/src/goals/tools/goal-tool.ts +38 -28
  674. package/src/hindsight/bank.ts +17 -2
  675. package/src/hindsight/client.ts +27 -2
  676. package/src/hindsight/mental-models.ts +59 -12
  677. package/src/hindsight/state.ts +12 -3
  678. package/src/hindsight/transcript.ts +1 -1
  679. package/src/index.ts +5 -0
  680. package/src/internal-urls/artifact-protocol.ts +11 -2
  681. package/src/internal-urls/docs-index.generated.ts +9 -7
  682. package/src/internal-urls/history-protocol.ts +113 -0
  683. package/src/internal-urls/index.ts +1 -0
  684. package/src/internal-urls/issue-pr-protocol.ts +22 -9
  685. package/src/internal-urls/local-protocol.ts +42 -7
  686. package/src/internal-urls/memory-protocol.ts +4 -31
  687. package/src/internal-urls/router.ts +3 -1
  688. package/src/internal-urls/types.ts +1 -1
  689. package/src/irc/bus.ts +303 -0
  690. package/src/lib/xai-http.ts +3 -3
  691. package/src/lsp/client.ts +245 -104
  692. package/src/lsp/clients/biome-client.ts +101 -39
  693. package/src/lsp/clients/lsp-linter-client.ts +2 -10
  694. package/src/lsp/config.ts +15 -5
  695. package/src/lsp/defaults.json +6 -0
  696. package/src/lsp/edits.ts +143 -95
  697. package/src/lsp/format-options.ts +119 -0
  698. package/src/lsp/index.ts +233 -93
  699. package/src/lsp/render.ts +11 -35
  700. package/src/lsp/types.ts +13 -1
  701. package/src/lsp/utils.ts +31 -12
  702. package/src/main.ts +396 -216
  703. package/src/mcp/config-writer.ts +7 -3
  704. package/src/mcp/json-rpc.ts +35 -5
  705. package/src/mcp/manager.ts +31 -16
  706. package/src/mcp/oauth-discovery.ts +34 -4
  707. package/src/mcp/oauth-flow.ts +61 -8
  708. package/src/mcp/render.ts +7 -1
  709. package/src/mcp/startup-events.ts +21 -0
  710. package/src/mcp/tool-bridge.ts +2 -0
  711. package/src/mcp/transports/stdio.ts +224 -4
  712. package/src/mcp/types.ts +2 -0
  713. package/src/memories/index.ts +174 -1128
  714. package/src/memories/storage.ts +2 -41
  715. package/src/memory-backend/index.ts +14 -1
  716. package/src/memory-backend/local-backend.ts +18 -3
  717. package/src/memory-backend/off-backend.ts +9 -0
  718. package/src/memory-backend/resolve.ts +4 -6
  719. package/src/memory-backend/runtime.ts +66 -0
  720. package/src/memory-backend/types.ts +82 -2
  721. package/src/mnemopi/backend.ts +220 -28
  722. package/src/mnemopi/config.ts +138 -33
  723. package/src/mnemopi/state.ts +91 -11
  724. package/src/modes/acp/acp-agent.ts +149 -142
  725. package/src/modes/acp/acp-event-mapper.ts +5 -1
  726. package/src/modes/components/agent-dashboard.ts +17 -11
  727. package/src/modes/components/agent-hub.ts +1346 -0
  728. package/src/modes/components/assistant-message.ts +190 -80
  729. package/src/modes/components/bash-execution.ts +1 -1
  730. package/src/modes/components/btw-panel.ts +5 -1
  731. package/src/modes/components/chat-block.ts +111 -0
  732. package/src/modes/components/collab-prompt-message.ts +30 -0
  733. package/src/modes/components/compaction-summary-message.ts +168 -33
  734. package/src/modes/components/copy-selector.ts +2 -45
  735. package/src/modes/components/custom-editor.test.ts +96 -0
  736. package/src/modes/components/custom-editor.ts +405 -118
  737. package/src/modes/components/custom-message.ts +1 -3
  738. package/src/modes/components/diff.ts +13 -2
  739. package/src/modes/components/dynamic-border.ts +12 -3
  740. package/src/modes/components/execution-shared.ts +1 -2
  741. package/src/modes/components/extensions/extension-dashboard.ts +8 -5
  742. package/src/modes/components/extensions/extension-list.ts +1 -1
  743. package/src/modes/components/extensions/inspector-panel.ts +7 -3
  744. package/src/modes/components/extensions/state-manager.ts +36 -41
  745. package/src/modes/components/footer.ts +4 -2
  746. package/src/modes/components/history-search.ts +1 -1
  747. package/src/modes/components/hook-editor.ts +8 -0
  748. package/src/modes/components/hook-input.ts +8 -0
  749. package/src/modes/components/hook-message.ts +1 -3
  750. package/src/modes/components/hook-selector.ts +6 -7
  751. package/src/modes/components/index.ts +1 -0
  752. package/src/modes/components/late-diagnostics-message.ts +60 -0
  753. package/src/modes/components/login-dialog.ts +1 -1
  754. package/src/modes/components/logout-account-selector.ts +130 -0
  755. package/src/modes/components/mcp-add-wizard.ts +14 -1
  756. package/src/modes/components/model-selector.ts +177 -75
  757. package/src/modes/components/oauth-selector.ts +102 -16
  758. package/src/modes/components/overlay-box.ts +108 -0
  759. package/src/modes/components/plan-review-overlay.ts +845 -0
  760. package/src/modes/components/plan-toc.ts +138 -0
  761. package/src/modes/components/plugin-settings.ts +22 -5
  762. package/src/modes/components/read-tool-group.ts +442 -39
  763. package/src/modes/components/reset-usage-selector.ts +161 -0
  764. package/src/modes/components/segment-track.ts +44 -7
  765. package/src/modes/components/session-selector.ts +97 -37
  766. package/src/modes/components/settings-defs.ts +28 -6
  767. package/src/modes/components/settings-selector.ts +541 -93
  768. package/src/modes/components/skill-message.ts +0 -1
  769. package/src/modes/components/snapcompact-shape-preview-doc.md +11 -0
  770. package/src/modes/components/snapcompact-shape-preview.ts +193 -0
  771. package/src/modes/components/{status-line.ts → status-line/component.ts} +205 -168
  772. package/src/modes/components/status-line/index.ts +1 -0
  773. package/src/modes/components/status-line/presets.ts +3 -3
  774. package/src/modes/components/status-line/segments.ts +26 -7
  775. package/src/modes/components/status-line/types.ts +40 -9
  776. package/src/modes/components/tiny-title-download-progress.ts +1 -1
  777. package/src/modes/components/tips.txt +7 -3
  778. package/src/modes/components/todo-reminder.ts +0 -2
  779. package/src/modes/components/tool-execution.ts +236 -103
  780. package/src/modes/components/transcript-container.ts +724 -99
  781. package/src/modes/components/tree-selector.ts +19 -4
  782. package/src/modes/components/ttsr-notification.ts +72 -30
  783. package/src/modes/components/usage-row.ts +18 -0
  784. package/src/modes/components/user-message-selector.ts +1 -1
  785. package/src/modes/components/user-message.ts +28 -12
  786. package/src/modes/components/visual-truncate.ts +1 -1
  787. package/src/modes/components/welcome.ts +80 -22
  788. package/src/modes/controllers/command-controller-shared.ts +7 -6
  789. package/src/modes/controllers/command-controller.ts +210 -180
  790. package/src/modes/controllers/event-controller.ts +352 -142
  791. package/src/modes/controllers/extension-ui-controller.ts +167 -208
  792. package/src/modes/controllers/input-controller.ts +778 -162
  793. package/src/modes/controllers/mcp-command-controller.ts +232 -80
  794. package/src/modes/controllers/selector-controller.ts +284 -145
  795. package/src/modes/controllers/session-focus-controller.ts +112 -0
  796. package/src/modes/controllers/ssh-command-controller.ts +2 -2
  797. package/src/modes/controllers/streaming-reveal.ts +295 -0
  798. package/src/modes/controllers/tan-command-controller.ts +173 -0
  799. package/src/modes/controllers/tool-args-reveal.ts +174 -0
  800. package/src/modes/gradient-highlight.ts +21 -9
  801. package/src/modes/image-references.ts +33 -7
  802. package/src/modes/index.ts +8 -25
  803. package/src/modes/interactive-mode.ts +840 -186
  804. package/src/modes/magic-keywords.ts +28 -6
  805. package/src/modes/markdown-prose.ts +1 -1
  806. package/src/modes/oauth-manual-input.ts +30 -3
  807. package/src/modes/rpc/rpc-client.ts +186 -3
  808. package/src/modes/rpc/rpc-mode.ts +318 -24
  809. package/src/modes/rpc/rpc-subagents.ts +265 -0
  810. package/src/modes/rpc/rpc-types.ts +111 -2
  811. package/src/modes/runtime-init.ts +28 -3
  812. package/src/modes/session-observer-registry.ts +72 -3
  813. package/src/modes/setup-version.ts +11 -0
  814. package/src/modes/setup-wizard/index.ts +16 -4
  815. package/src/modes/setup-wizard/lazy.ts +16 -0
  816. package/src/modes/setup-wizard/scenes/glyph.ts +25 -7
  817. package/src/modes/setup-wizard/scenes/providers.ts +45 -12
  818. package/src/modes/setup-wizard/scenes/sign-in.ts +14 -13
  819. package/src/modes/setup-wizard/scenes/splash.ts +1 -1
  820. package/src/modes/setup-wizard/scenes/theme.ts +29 -2
  821. package/src/modes/setup-wizard/scenes/types.ts +11 -2
  822. package/src/modes/setup-wizard/scenes/web-search.ts +26 -9
  823. package/src/modes/setup-wizard/wizard-overlay.ts +40 -3
  824. package/src/modes/shared.ts +2 -0
  825. package/src/modes/theme/defaults/dark-poimandres.json +1 -1
  826. package/src/modes/theme/defaults/light-poimandres.json +1 -1
  827. package/src/modes/theme/shimmer.ts +20 -9
  828. package/src/modes/theme/theme-schema.json +1 -1
  829. package/src/modes/theme/theme.ts +342 -82
  830. package/src/modes/types.ts +60 -18
  831. package/src/modes/utils/context-usage.ts +88 -8
  832. package/src/modes/utils/copy-targets.ts +133 -27
  833. package/src/modes/utils/hotkeys-markdown.ts +3 -2
  834. package/src/modes/utils/ui-helpers.ts +191 -110
  835. package/src/modes/workflow.ts +10 -10
  836. package/src/plan-mode/approved-plan.ts +66 -43
  837. package/src/plan-mode/plan-protection.ts +4 -4
  838. package/src/priority.json +5 -1
  839. package/src/prompts/agents/designer.md +1 -1
  840. package/src/prompts/agents/explore.md +3 -3
  841. package/src/prompts/agents/librarian.md +2 -3
  842. package/src/prompts/agents/oracle.md +2 -2
  843. package/src/prompts/agents/plan.md +6 -6
  844. package/src/prompts/agents/reviewer.md +1 -1
  845. package/src/prompts/agents/task.md +6 -5
  846. package/src/prompts/bench.md +12 -0
  847. package/src/prompts/ci-green-request.md +5 -7
  848. package/src/prompts/goals/goal-budget-limit.md +2 -2
  849. package/src/prompts/goals/goal-continuation.md +4 -4
  850. package/src/prompts/goals/goal-mode-active.md +1 -1
  851. package/src/prompts/goals/guided-goal-interview.md +8 -0
  852. package/src/prompts/goals/guided-goal-system.md +12 -0
  853. package/src/prompts/memories/consolidation.md +2 -7
  854. package/src/prompts/memories/consolidation_system.md +4 -0
  855. package/src/prompts/memories/identity_review.md +2 -2
  856. package/src/prompts/memories/read-path.md +11 -10
  857. package/src/prompts/memories/stage_one_system.md +2 -2
  858. package/src/prompts/review-custom-request.md +1 -1
  859. package/src/prompts/system/agent-creation-architect.md +2 -2
  860. package/src/prompts/system/auto-continue.md +1 -1
  861. package/src/prompts/system/autolearn-guidance-learn.md +1 -0
  862. package/src/prompts/system/autolearn-guidance.md +7 -0
  863. package/src/prompts/system/autolearn-nudge.md +3 -0
  864. package/src/prompts/system/background-tan-dispatch.md +8 -0
  865. package/src/prompts/system/btw-user.md +2 -2
  866. package/src/prompts/system/commit-message-system.md +13 -1
  867. package/src/prompts/system/custom-system-prompt.md +1 -1
  868. package/src/prompts/system/eager-task.md +7 -0
  869. package/src/prompts/system/eager-todo.md +11 -6
  870. package/src/prompts/system/empty-stop-retry.md +4 -6
  871. package/src/prompts/system/irc-autoreply.md +6 -0
  872. package/src/prompts/system/irc-incoming.md +3 -4
  873. package/src/prompts/system/manual-continue.md +7 -0
  874. package/src/prompts/system/omfg-user.md +3 -4
  875. package/src/prompts/system/orchestrate-notice.md +10 -10
  876. package/src/prompts/system/personalities/default.md +26 -0
  877. package/src/prompts/system/personalities/friendly.md +17 -0
  878. package/src/prompts/system/personalities/pragmatic.md +15 -0
  879. package/src/prompts/system/plan-mode-active.md +70 -77
  880. package/src/prompts/system/plan-mode-approved.md +1 -1
  881. package/src/prompts/system/plan-mode-subagent.md +4 -5
  882. package/src/prompts/system/plan-mode-tool-decision-reminder.md +1 -1
  883. package/src/prompts/system/project-prompt.md +2 -2
  884. package/src/prompts/system/snapcompact-context-frames-note.md +1 -0
  885. package/src/prompts/system/snapcompact-context-stub.md +1 -0
  886. package/src/prompts/system/snapcompact-system-frames-note.md +1 -0
  887. package/src/prompts/system/snapcompact-system-stub.md +1 -0
  888. package/src/prompts/system/snapcompact-toolresult-note.md +1 -0
  889. package/src/prompts/system/subagent-system-prompt.md +7 -8
  890. package/src/prompts/system/system-prompt.md +28 -57
  891. package/src/prompts/system/tiny-title-system.md +1 -1
  892. package/src/prompts/system/title-marker-instruction.md +1 -0
  893. package/src/prompts/system/title-system-marker.md +16 -0
  894. package/src/prompts/system/title-system.md +16 -3
  895. package/src/prompts/system/ttsr-tool-reminder.md +1 -1
  896. package/src/prompts/system/workflow-notice.md +4 -4
  897. package/src/prompts/tools/ast-edit.md +1 -1
  898. package/src/prompts/tools/ast-grep.md +2 -2
  899. package/src/prompts/tools/bash.md +16 -8
  900. package/src/prompts/tools/browser.md +33 -43
  901. package/src/prompts/tools/debug.md +1 -1
  902. package/src/prompts/tools/eval.md +31 -51
  903. package/src/prompts/tools/find.md +0 -1
  904. package/src/prompts/tools/github.md +8 -7
  905. package/src/prompts/tools/goal.md +1 -1
  906. package/src/prompts/tools/image-gen.md +1 -1
  907. package/src/prompts/tools/inspect-image-system.md +1 -1
  908. package/src/prompts/tools/irc.md +39 -31
  909. package/src/prompts/tools/job.md +2 -1
  910. package/src/prompts/tools/learn.md +7 -0
  911. package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
  912. package/src/prompts/tools/lsp.md +2 -2
  913. package/src/prompts/tools/manage-skill.md +9 -0
  914. package/src/prompts/tools/memory-edit.md +1 -1
  915. package/src/prompts/tools/patch.md +2 -2
  916. package/src/prompts/tools/read.md +31 -39
  917. package/src/prompts/tools/recall.md +1 -1
  918. package/src/prompts/tools/reflect.md +1 -1
  919. package/src/prompts/tools/render-mermaid.md +2 -2
  920. package/src/prompts/tools/replace.md +4 -10
  921. package/src/prompts/tools/rewind.md +2 -2
  922. package/src/prompts/tools/search-tool-bm25.md +1 -9
  923. package/src/prompts/tools/search.md +0 -1
  924. package/src/prompts/tools/ssh.md +0 -4
  925. package/src/prompts/tools/task-summary.md +5 -16
  926. package/src/prompts/tools/task.md +47 -31
  927. package/src/prompts/tools/todo.md +6 -3
  928. package/src/registry/agent-lifecycle.ts +218 -0
  929. package/src/registry/agent-registry.ts +46 -5
  930. package/src/sdk.ts +692 -219
  931. package/src/secrets/index.ts +8 -1
  932. package/src/secrets/obfuscator.ts +40 -19
  933. package/src/session/agent-session.ts +1577 -806
  934. package/src/session/agent-storage.ts +18 -9
  935. package/src/session/auth-broker-config.ts +30 -1
  936. package/src/session/auth-storage.ts +6 -0
  937. package/src/session/codex-auto-reset.ts +202 -0
  938. package/src/session/history-storage.ts +3 -2
  939. package/src/session/indexed-session-storage.ts +7 -10
  940. package/src/session/messages.ts +59 -95
  941. package/src/session/session-context.ts +352 -0
  942. package/src/session/session-dump-format.ts +12 -3
  943. package/src/session/session-entries.ts +194 -0
  944. package/src/session/session-history-format.ts +246 -0
  945. package/src/session/session-listing.ts +588 -0
  946. package/src/session/session-loader.ts +106 -0
  947. package/src/session/session-manager.ts +1003 -2920
  948. package/src/session/session-migrations.ts +78 -0
  949. package/src/session/session-paths.ts +193 -0
  950. package/src/session/session-persistence.ts +131 -0
  951. package/src/session/session-storage.ts +91 -30
  952. package/src/session/snapcompact-inline.ts +542 -0
  953. package/src/session/snapcompact-savings-journal.ts +113 -0
  954. package/src/session/streaming-output.ts +248 -11
  955. package/src/session/tool-choice-queue.ts +23 -11
  956. package/src/session/yield-queue.ts +20 -2
  957. package/src/slash-commands/acp-builtins.ts +25 -1
  958. package/src/slash-commands/available-commands.ts +105 -0
  959. package/src/slash-commands/builtin-registry.ts +575 -49
  960. package/src/slash-commands/helpers/active-oauth-account.ts +44 -0
  961. package/src/slash-commands/helpers/context-report.ts +28 -1
  962. package/src/slash-commands/helpers/logout.ts +88 -0
  963. package/src/slash-commands/helpers/reset-usage.ts +66 -0
  964. package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
  965. package/src/slash-commands/helpers/usage-report.ts +38 -3
  966. package/src/slash-commands/types.ts +5 -9
  967. package/src/ssh/connection-manager.ts +27 -0
  968. package/src/ssh/ssh-executor.ts +60 -4
  969. package/src/stt/asr-client.ts +520 -0
  970. package/src/stt/asr-protocol.ts +65 -0
  971. package/src/stt/asr-worker.ts +790 -0
  972. package/src/stt/downloader.ts +107 -47
  973. package/src/stt/endpointer.ts +259 -0
  974. package/src/stt/index.ts +5 -1
  975. package/src/stt/models.ts +150 -0
  976. package/src/stt/recorder.ts +254 -67
  977. package/src/stt/stt-controller.ts +201 -22
  978. package/src/stt/transcriber.ts +37 -68
  979. package/src/stt/wav.ts +173 -0
  980. package/src/system-prompt.ts +52 -10
  981. package/src/task/agents.ts +3 -4
  982. package/src/task/commands.ts +3 -2
  983. package/src/task/discovery.ts +17 -24
  984. package/src/task/executor.ts +1054 -529
  985. package/src/task/index.ts +862 -757
  986. package/src/task/output-manager.ts +0 -11
  987. package/src/task/parallel.ts +3 -3
  988. package/src/task/prometheus-command.ts +2 -2
  989. package/src/task/render.ts +529 -182
  990. package/src/task/repair-args.ts +21 -9
  991. package/src/task/types.ts +144 -66
  992. package/src/task/worktree.ts +64 -56
  993. package/src/telemetry-export.ts +27 -9
  994. package/src/thinking.ts +9 -7
  995. package/src/tiny/models.ts +2 -2
  996. package/src/tiny/text.ts +5 -1
  997. package/src/tiny/title-client.ts +72 -20
  998. package/src/tiny/title-protocol.ts +1 -1
  999. package/src/tiny/worker.ts +23 -99
  1000. package/src/tool-discovery/tool-index.ts +2 -0
  1001. package/src/tools/archive-reader.ts +94 -2
  1002. package/src/tools/ask.ts +234 -177
  1003. package/src/tools/ast-edit.ts +136 -80
  1004. package/src/tools/ast-grep.ts +41 -45
  1005. package/src/tools/auto-generated-guard.ts +20 -3
  1006. package/src/tools/bash-interactive.ts +28 -8
  1007. package/src/tools/bash.ts +198 -35
  1008. package/src/tools/browser/attach.ts +26 -7
  1009. package/src/tools/browser/cmux/cmux-tab.ts +1264 -0
  1010. package/src/tools/browser/cmux/rpc.ts +156 -0
  1011. package/src/tools/browser/cmux/socket-client.ts +309 -0
  1012. package/src/tools/browser/launch.ts +11 -2
  1013. package/src/tools/browser/readable.ts +19 -2
  1014. package/src/tools/browser/registry.ts +52 -5
  1015. package/src/tools/browser/render.ts +13 -5
  1016. package/src/tools/browser/tab-protocol.ts +2 -0
  1017. package/src/tools/browser/tab-supervisor.ts +256 -34
  1018. package/src/tools/browser/tab-worker.ts +259 -91
  1019. package/src/tools/browser.ts +44 -2
  1020. package/src/tools/checkpoint.ts +1 -1
  1021. package/src/tools/conflict-detect.ts +50 -4
  1022. package/src/tools/debug.ts +27 -12
  1023. package/src/tools/eval-render.ts +32 -35
  1024. package/src/tools/eval.ts +26 -12
  1025. package/src/tools/fetch.ts +450 -99
  1026. package/src/tools/find.ts +182 -142
  1027. package/src/tools/gh-cache-invalidation.ts +255 -0
  1028. package/src/tools/gh-renderer.ts +104 -51
  1029. package/src/tools/gh.ts +232 -37
  1030. package/src/tools/github-cache.ts +97 -7
  1031. package/src/tools/grouped-file-output.ts +159 -52
  1032. package/src/tools/image-gen.ts +237 -132
  1033. package/src/tools/index.ts +147 -26
  1034. package/src/tools/inspect-image-renderer.ts +74 -45
  1035. package/src/tools/inspect-image.ts +12 -6
  1036. package/src/tools/irc.ts +626 -173
  1037. package/src/tools/job.ts +106 -29
  1038. package/src/tools/learn.ts +144 -0
  1039. package/src/tools/manage-skill.ts +104 -0
  1040. package/src/tools/memory-edit.ts +4 -4
  1041. package/src/tools/memory-recall.ts +7 -9
  1042. package/src/tools/memory-reflect.ts +5 -9
  1043. package/src/tools/memory-render.ts +23 -6
  1044. package/src/tools/memory-retain.ts +4 -4
  1045. package/src/tools/path-utils.ts +102 -48
  1046. package/src/tools/plan-mode-guard.ts +101 -40
  1047. package/src/tools/read.ts +475 -120
  1048. package/src/tools/render-mermaid.ts +1 -1
  1049. package/src/tools/render-utils.ts +132 -76
  1050. package/src/tools/renderers.ts +12 -1
  1051. package/src/tools/report-tool-issue.ts +14 -6
  1052. package/src/tools/resolve.ts +20 -3
  1053. package/src/tools/review.ts +2 -2
  1054. package/src/tools/search-tool-bm25.ts +37 -24
  1055. package/src/tools/search.ts +233 -115
  1056. package/src/tools/sqlite-reader.ts +26 -17
  1057. package/src/tools/ssh.ts +20 -14
  1058. package/src/tools/todo.ts +197 -191
  1059. package/src/tools/tool-result.ts +8 -0
  1060. package/src/tools/tool-timeouts.ts +1 -1
  1061. package/src/tools/tts.ts +205 -74
  1062. package/src/tools/write.ts +291 -155
  1063. package/src/tools/yield.ts +10 -1
  1064. package/src/tts/downloader.ts +64 -0
  1065. package/src/tts/index.ts +8 -0
  1066. package/src/tts/models.ts +137 -0
  1067. package/src/tts/player.ts +137 -0
  1068. package/src/tts/runtime.ts +21 -0
  1069. package/src/tts/streaming-player.ts +266 -0
  1070. package/src/tts/tts-client.ts +647 -0
  1071. package/src/tts/tts-protocol.ts +60 -0
  1072. package/src/tts/tts-worker.ts +505 -0
  1073. package/src/tts/vocalizer.ts +162 -0
  1074. package/src/tts/wav.ts +58 -0
  1075. package/src/tui/code-cell.ts +2 -7
  1076. package/src/tui/hyperlink.ts +40 -26
  1077. package/src/tui/output-block.ts +60 -108
  1078. package/src/tui/status-line.ts +5 -1
  1079. package/src/utils/block-context.ts +312 -0
  1080. package/src/utils/changelog.ts +27 -1
  1081. package/src/utils/clipboard.ts +91 -22
  1082. package/src/utils/commit-message-generator.ts +8 -3
  1083. package/src/utils/enhanced-paste.ts +230 -0
  1084. package/src/utils/file-mentions.ts +3 -1
  1085. package/src/utils/git.ts +315 -15
  1086. package/src/utils/image-loading.ts +65 -4
  1087. package/src/utils/session-color.ts +83 -9
  1088. package/src/utils/thinking-display.ts +37 -0
  1089. package/src/utils/title-generator.ts +73 -10
  1090. package/src/utils/tool-choice.ts +16 -0
  1091. package/src/utils/tools-manager.ts +19 -1
  1092. package/src/web/kagi.ts +28 -26
  1093. package/src/web/parallel.ts +7 -3
  1094. package/src/web/scrapers/arxiv.ts +1 -1
  1095. package/src/web/scrapers/github.ts +351 -3
  1096. package/src/web/scrapers/go-pkg.ts +1 -1
  1097. package/src/web/scrapers/iacr.ts +1 -1
  1098. package/src/web/scrapers/readthedocs.ts +1 -1
  1099. package/src/web/scrapers/twitter.ts +2 -1
  1100. package/src/web/scrapers/types.ts +87 -8
  1101. package/src/web/scrapers/wikipedia.ts +1 -1
  1102. package/src/web/scrapers/youtube.ts +9 -3
  1103. package/src/web/search/index.ts +15 -2
  1104. package/src/web/search/providers/anthropic.ts +62 -21
  1105. package/src/web/search/providers/base.ts +2 -1
  1106. package/src/web/search/providers/brave.ts +5 -2
  1107. package/src/web/search/providers/codex.ts +87 -51
  1108. package/src/web/search/providers/exa.ts +101 -10
  1109. package/src/web/search/providers/gemini.ts +49 -24
  1110. package/src/web/search/providers/jina.ts +15 -5
  1111. package/src/web/search/providers/kagi.ts +9 -2
  1112. package/src/web/search/providers/kimi.ts +45 -20
  1113. package/src/web/search/providers/parallel.ts +39 -24
  1114. package/src/web/search/providers/perplexity.ts +226 -63
  1115. package/src/web/search/providers/searxng.ts +19 -3
  1116. package/src/web/search/providers/synthetic.ts +16 -11
  1117. package/src/web/search/providers/tavily.ts +12 -9
  1118. package/src/web/search/providers/zai.ts +22 -9
  1119. package/src/web/search/render.ts +59 -64
  1120. package/src/web/search/types.ts +5 -1
  1121. package/dist/types/discovery/context-files.d.ts +0 -17
  1122. package/dist/types/exa/factory.d.ts +0 -13
  1123. package/dist/types/exa/render.d.ts +0 -19
  1124. package/dist/types/exa/researcher.d.ts +0 -9
  1125. package/dist/types/exa/search.d.ts +0 -9
  1126. package/dist/types/exa/websets.d.ts +0 -9
  1127. package/dist/types/export/html/template.generated.d.ts +0 -1
  1128. package/dist/types/modes/components/session-observer-overlay.d.ts +0 -11
  1129. package/dist/types/modes/components/status-line.d.ts +0 -77
  1130. package/dist/types/slash-commands/headless-plan.d.ts +0 -3
  1131. package/dist/types/stt/setup.d.ts +0 -18
  1132. package/scripts/generate-template.ts +0 -33
  1133. package/src/discovery/context-files.ts +0 -49
  1134. package/src/exa/factory.ts +0 -60
  1135. package/src/exa/render.ts +0 -244
  1136. package/src/exa/researcher.ts +0 -36
  1137. package/src/exa/search.ts +0 -47
  1138. package/src/exa/websets.ts +0 -248
  1139. package/src/export/html/template.generated.ts +0 -2
  1140. package/src/modes/components/session-observer-overlay.ts +0 -852
  1141. package/src/slash-commands/headless-plan.ts +0 -142
  1142. package/src/stt/setup.ts +0 -52
  1143. package/src/stt/transcribe.py +0 -70
  1144. /package/dist/types/extensibility/{legacy-pi-coding-agent-shim.d.ts → legacy-package-agent-shim.d.ts} +0 -0
  1145. /package/src/extensibility/{legacy-pi-coding-agent-shim.ts → legacy-package-agent-shim.ts} +0 -0
@@ -1,24 +1,29 @@
1
1
  import * as fs from "node:fs/promises";
2
- import type { AutocompleteProvider, SlashCommand } from "@prometheus-ai/tui";
3
- import { $env, logger, sanitizeText } from "@prometheus-ai/utils";
4
- import { getRoleInfo } from "../../config/model-registry";
2
+ import * as path from "node:path";
3
+ import type { ImageContent } from "@prometheus-ai/ai";
4
+ import { type AutocompleteProvider, matchesKey, type SlashCommand } from "@prometheus-ai/tui";
5
+ import { $env, isEnoent, logger, sanitizeText } from "@prometheus-ai/utils";
5
6
  import { isSettingsInitialized, settings } from "../../config/settings";
7
+ import { resolveLocalRoot } from "../../internal-urls";
8
+ import { AssistantMessageComponent } from "../../modes/components/assistant-message";
6
9
  import { renderSegmentTrack } from "../../modes/components/segment-track";
7
10
  import { TinyTitleDownloadProgressComponent } from "../../modes/components/tiny-title-download-progress";
8
11
  import { expandEmoticons } from "../../modes/emoji-autocomplete";
9
- import { materializeImageReferenceLinks } from "../../modes/image-references";
12
+ import { materializeImageReferenceLinks, shiftImageMarkers } from "../../modes/image-references";
10
13
  import { createPromptActionAutocompleteProvider } from "../../modes/prompt-action-autocomplete";
11
14
  import type { InteractiveModeContext } from "../../modes/types";
12
- import type { AgentSessionEvent } from "../../session/agent-session";
13
- import { SKILL_PROMPT_MESSAGE_TYPE, type SkillPromptDetails } from "../../session/messages";
15
+ import manualContinuePrompt from "../../prompts/system/manual-continue.md" with { type: "text" };
16
+ import { SKILL_PROMPT_MESSAGE_TYPE, type SkillPromptDetails, USER_INTERRUPT_LABEL } from "../../session/messages";
14
17
  import { executeBuiltinSlashCommand } from "../../slash-commands/builtin-registry";
15
18
  import { isTinyTitleLocalModelKey } from "../../tiny/models";
16
19
  import { isLowSignalTitleInput } from "../../tiny/text";
17
20
  import { tinyTitleClient } from "../../tiny/title-client";
18
21
  import type { TinyTitleProgressEvent } from "../../tiny/title-protocol";
22
+ import { shortenPath, TRUNCATE_LENGTHS, truncateToWidth } from "../../tools/render-utils";
19
23
  import { copyToClipboard, readImageFromClipboard, readTextFromClipboard } from "../../utils/clipboard";
24
+ import { EnhancedPasteController } from "../../utils/enhanced-paste";
20
25
  import { getEditorCommand, openInEditor } from "../../utils/external-editor";
21
- import { ensureSupportedImageInput } from "../../utils/image-loading";
26
+ import { ensureSupportedImageInput, ImageInputTooLargeError, loadImageInput } from "../../utils/image-loading";
22
27
  import { resizeImage } from "../../utils/image-resize";
23
28
  import { generateSessionTitle, setSessionTerminalTitle } from "../../utils/title-generator";
24
29
 
@@ -30,18 +35,76 @@ function isExpandable(obj: unknown): obj is Expandable {
30
35
  return typeof obj === "object" && obj !== null && "setExpanded" in obj && typeof obj.setExpanded === "function";
31
36
  }
32
37
 
38
+ /** Minimal contract for any component that can receive a paste payload directly. */
39
+ interface PasteTarget {
40
+ pasteText(text: string): void;
41
+ }
42
+
43
+ function hasPasteText(value: unknown): value is PasteTarget {
44
+ return typeof value === "object" && value !== null && typeof (value as PasteTarget).pasteText === "function";
45
+ }
46
+
47
+ /** Wrap pasted text in a fenced code block, using a backtick fence longer than any run of
48
+ * backticks already in the content so an embedded fence cannot terminate the block early. */
49
+ function wrapPasteInCodeBlock(content: string): string {
50
+ let longestRun = 0;
51
+ let run = 0;
52
+ for (let i = 0; i < content.length; i++) {
53
+ if (content.charCodeAt(i) === 96 /* backtick */) {
54
+ run++;
55
+ if (run > longestRun) longestRun = run;
56
+ } else {
57
+ run = 0;
58
+ }
59
+ }
60
+ const fence = "`".repeat(Math.max(3, longestRun + 1));
61
+ return `${fence}\n${content}\n${fence}`;
62
+ }
63
+
64
+ /** Wrap pasted text in `<pasted_text>` tags so the model treats it as one quoted block. */
65
+ function wrapPasteInXml(content: string): string {
66
+ return `<pasted_text>\n${content}\n</pasted_text>`;
67
+ }
68
+
33
69
  const TINY_TITLE_PROGRESS_DONE_TTL_MS = 3_000;
34
70
  // A cached model fires its file-load events in a short burst and then goes silent
35
71
  // while onnxruntime builds the session; a genuine download keeps streaming progress
36
72
  // events for seconds. Only reveal the bar once a still-incomplete event arrives after
37
73
  // this grace window, so an already-downloaded model never flashes the bar.
38
74
  const TINY_TITLE_PROGRESS_REVEAL_DELAY_MS = 1_000;
75
+ // Double-tap ← on an empty editor opens the Agent Hub (and, in a focused
76
+ // subagent view, ←← returns to the main session). The second tap must land
77
+ // inside this window. The lower bound rejects terminal-synthesized arrow-key
78
+ // bursts: "click to move cursor" / pointer features in iTerm2, WezTerm, kitty,
79
+ // and tmux emit several arrow keys in a single stdin read (sub-millisecond
80
+ // apart) on a stray click, which used to pop the hub with no key ever pressed.
81
+ // Three or more rapid taps are likewise treated as a burst, not a gesture. A
82
+ // deliberate human double-tap is always tens of milliseconds apart.
83
+ const LEFT_DOUBLE_TAP_MIN_GAP_MS = 40;
84
+ const LEFT_DOUBLE_TAP_MAX_GAP_MS = 500;
39
85
 
40
86
  export class InputController {
41
- constructor(private ctx: InteractiveModeContext) {}
87
+ constructor(
88
+ private ctx: InteractiveModeContext,
89
+ /** Injectable clipboard reads so tests can drive paste flows without a real clipboard. */
90
+ private clipboard: {
91
+ readImage: typeof readImageFromClipboard;
92
+ readText: typeof readTextFromClipboard;
93
+ } = { readImage: readImageFromClipboard, readText: readTextFromClipboard },
94
+ ) {}
95
+
96
+ #enhancedPaste?: EnhancedPasteController;
97
+ #focusedLeftTapListenerInstalled = false;
98
+ // Tap counter for the double-← gesture; reset whenever a quiet gap
99
+ // (>= LEFT_DOUBLE_TAP_MAX_GAP_MS) starts a fresh sequence. See
100
+ // #detectLeftDoubleTap.
101
+ #leftTapCount = 0;
102
+ // Sequential index for `local://attachment-N` references created by the large-paste "attach as
103
+ // file" action. Seeded from 0 and bumped past any existing attachment files in #attachPasteAsFile.
104
+ #attachmentCounter = 0;
42
105
 
43
106
  #showTinyTitleDownloadProgress(modelKey: string): void {
44
- if (!isTinyTitleLocalModelKey(modelKey) || this.ctx.isBackgrounded) return;
107
+ if (!isTinyTitleLocalModelKey(modelKey)) return;
45
108
  const component = new TinyTitleDownloadProgressComponent(modelKey);
46
109
  let added = false;
47
110
  let disposed = false;
@@ -87,11 +150,50 @@ export class InputController {
87
150
 
88
151
  setupKeyHandlers(): void {
89
152
  this.ctx.editor.setActionKeys("app.interrupt", this.ctx.keybindings.getKeys("app.interrupt"));
153
+ if (!this.#focusedLeftTapListenerInstalled) {
154
+ this.#focusedLeftTapListenerInstalled = true;
155
+ this.ctx.ui.addInputListener(data => {
156
+ if (!this.ctx.focusedAgentId) return undefined;
157
+ if (!matchesKey(data, "left")) return undefined;
158
+ if (this.ctx.editor.getText().trim()) return undefined;
159
+ this.#handleFocusedLeftTap();
160
+ return { consume: true };
161
+ });
162
+ }
90
163
  this.ctx.editor.onEscape = () => {
164
+ // Active context maintenance owns Esc: auto/manual compaction,
165
+ // handoff generation, and auto-retry backoff all advertise
166
+ // "(esc to cancel)". Dispatch on live session state instead of
167
+ // swapping onEscape handlers — interleaved start/end events used
168
+ // to clobber the single saved-handler slot (auto-compaction start
169
+ // → /compact → auto end → manual finally), leaving Esc wired to a
170
+ // stale no-op closure until restart.
171
+ const viewSession = this.ctx.viewSession;
172
+ let aborted = false;
173
+ if (viewSession.isCompacting) {
174
+ try {
175
+ viewSession.abortCompaction();
176
+ } catch {}
177
+ aborted = true;
178
+ }
179
+ if (viewSession.isGeneratingHandoff) {
180
+ try {
181
+ viewSession.abortHandoff();
182
+ } catch {}
183
+ aborted = true;
184
+ }
185
+ if (viewSession.isRetrying) {
186
+ try {
187
+ viewSession.abortRetry();
188
+ } catch {}
189
+ aborted = true;
190
+ }
191
+ if (aborted) return;
192
+
91
193
  if (this.ctx.loopModeEnabled) {
92
194
  this.ctx.pauseLoop();
93
195
  if (this.ctx.session.isStreaming) {
94
- void this.ctx.session.abort();
196
+ void this.ctx.session.abort({ reason: USER_INTERRUPT_LABEL });
95
197
  } else {
96
198
  this.ctx.cancelPendingSubmission();
97
199
  }
@@ -103,6 +205,27 @@ export class InputController {
103
205
  if (this.ctx.hasActiveOmfg() && this.ctx.handleOmfgEscape()) {
104
206
  return;
105
207
  }
208
+ if (this.ctx.focusedAgentId) {
209
+ // Esc never interrupts the focused agent's turn: clear typed text,
210
+ // else return the view to the main session. Interrupt via empty
211
+ // steer-flush submit if needed.
212
+ if (this.ctx.editor.getText().trim()) {
213
+ this.ctx.editor.setText("");
214
+ this.ctx.ui.requestRender();
215
+ } else {
216
+ void this.ctx.unfocusSession();
217
+ }
218
+ return; // double-escape backtrack (/tree, /branch) stays main-only
219
+ }
220
+ if (this.ctx.collabGuest) {
221
+ // Guest Esc: ask the host to interrupt its agent; the local replica
222
+ // session is never streaming, so the native abort path below would
223
+ // no-op.
224
+ if (this.ctx.collabGuest.state?.isStreaming || this.ctx.loadingAnimation) {
225
+ this.ctx.collabGuest.sendAbort();
226
+ }
227
+ return;
228
+ }
106
229
  if (this.ctx.loadingAnimation) {
107
230
  if (this.ctx.cancelPendingSubmission()) {
108
231
  return;
@@ -121,8 +244,13 @@ export class InputController {
121
244
  this.ctx.isPythonMode = false;
122
245
  this.ctx.updateEditorBorderColor();
123
246
  } else if (this.ctx.session.isStreaming) {
124
- void this.ctx.session.abort();
125
- } else if (!this.ctx.editor.getText().trim()) {
247
+ void this.ctx.session.abort({ reason: USER_INTERRUPT_LABEL });
248
+ } else if (this.ctx.editor.getText().trim()) {
249
+ // Esc with typed text clears the draft instead of (or before) any double-Esc action
250
+ this.ctx.editor.setText("");
251
+ this.ctx.ui.requestRender();
252
+ this.ctx.lastEscapeTime = 0;
253
+ } else {
126
254
  // Double-interrupt with empty editor triggers /tree, /branch, or nothing based on setting
127
255
  const action = settings.get("doubleEscapeAction");
128
256
  if (action !== "none") {
@@ -133,6 +261,7 @@ export class InputController {
133
261
  } else {
134
262
  this.ctx.showUserMessageSelector();
135
263
  }
264
+ this.ctx.ui.resetDisplay();
136
265
  this.ctx.lastEscapeTime = 0;
137
266
  } else {
138
267
  this.ctx.lastEscapeTime = now;
@@ -176,11 +305,13 @@ export class InputController {
176
305
  this.ctx.keybindings.getKeys("app.clipboard.pasteImage"),
177
306
  );
178
307
  this.ctx.editor.onPasteImage = () => this.handleImagePaste();
308
+ this.ctx.editor.onPasteImagePath = path => this.handleImagePathPaste(path);
179
309
  this.ctx.editor.setActionKeys(
180
310
  "app.clipboard.pasteTextRaw",
181
311
  this.ctx.keybindings.getKeys("app.clipboard.pasteTextRaw"),
182
312
  );
183
313
  this.ctx.editor.onPasteTextRaw = () => void this.handleClipboardTextRawPaste();
314
+ this.ctx.editor.onLargePaste = (text, lineCount) => this.handleLargePaste(text, lineCount);
184
315
  this.ctx.editor.setActionKeys(
185
316
  "app.clipboard.copyPrompt",
186
317
  this.ctx.keybindings.getKeys("app.clipboard.copyPrompt"),
@@ -216,13 +347,40 @@ export class InputController {
216
347
  for (const key of this.ctx.keybindings.getKeys("app.stt.toggle")) {
217
348
  this.ctx.editor.setCustomKeyHandler(key, () => void this.ctx.handleSTTToggle());
218
349
  }
350
+ // Hold the space bar to push-to-talk: the editor recognizes the auto-repeat burst, tracks
351
+ // the spam back out, and toggles STT on hold start / release. Gated on `stt.enabled` so a
352
+ // disabled STT leaves the space bar typing normally.
353
+ this.ctx.editor.sttHoldEnabled = () => settings.get("stt.enabled");
354
+ this.ctx.editor.onSpaceHoldStart = () => void this.ctx.handleSTTToggle();
355
+ this.ctx.editor.onSpaceHoldEnd = () => void this.ctx.handleSTTToggle();
219
356
  for (const key of this.ctx.keybindings.getKeys("app.clipboard.copyLine")) {
220
357
  this.ctx.editor.setCustomKeyHandler(key, () => this.handleCopyCurrentLine());
221
358
  }
222
- for (const key of this.ctx.keybindings.getKeys("app.session.observe")) {
223
- this.ctx.editor.setCustomKeyHandler(key, () => this.ctx.showSessionObserver());
359
+ const hubKeys = new Set([
360
+ ...this.ctx.keybindings.getKeys("app.agents.hub"),
361
+ ...this.ctx.keybindings.getKeys("app.session.observe"),
362
+ ]);
363
+ for (const key of hubKeys) {
364
+ this.ctx.editor.setCustomKeyHandler(key, () => this.ctx.showAgentHub());
224
365
  }
225
366
 
367
+ // Double-tap left arrow on an empty editor: opens the agent hub from the
368
+ // main session, or returns the focused subagent view to the main session.
369
+ // Focused ←← intentionally matches Esc. From the main session the gesture
370
+ // stays inert when there are no subagents (requireContent); the explicit
371
+ // hub key still opens the empty roster.
372
+ this.ctx.editor.onLeftAtStart = () => {
373
+ if (this.ctx.focusedAgentId) {
374
+ this.#handleFocusedLeftTap();
375
+ return;
376
+ }
377
+ if (this.#detectLeftDoubleTap()) {
378
+ this.ctx.showAgentHub({ requireContent: true });
379
+ }
380
+ };
381
+
382
+ this.#setupEnhancedPaste();
383
+
226
384
  this.ctx.editor.onChange = (text: string) => {
227
385
  const wasBashMode = this.ctx.isBashMode;
228
386
  const wasPythonMode = this.ctx.isPythonMode;
@@ -235,28 +393,114 @@ export class InputController {
235
393
  };
236
394
  }
237
395
 
396
+ #handleFocusedLeftTap(): void {
397
+ if (this.#detectLeftDoubleTap()) {
398
+ void this.ctx.unfocusSession();
399
+ }
400
+ }
401
+
402
+ /**
403
+ * Detect a deliberate double-← gesture, rejecting terminal-synthesized arrow
404
+ * bursts. Returns true only on the *second* tap of a fresh sequence when it
405
+ * lands a human-plausible interval after the first
406
+ * (`[LEFT_DOUBLE_TAP_MIN_GAP_MS, LEFT_DOUBLE_TAP_MAX_GAP_MS)`). Taps closer
407
+ * than the lower bound, or any third-and-later tap before a quiet gap, are a
408
+ * burst and never fire — so a stray click that makes the terminal emit a run
409
+ * of ← keys can no longer pop the Agent Hub.
410
+ */
411
+ #detectLeftDoubleTap(): boolean {
412
+ const now = Date.now();
413
+ const sinceLast = now - this.ctx.lastLeftTapTime;
414
+ this.ctx.lastLeftTapTime = now;
415
+ if (sinceLast >= LEFT_DOUBLE_TAP_MAX_GAP_MS) {
416
+ // Quiet gap: this tap starts a fresh sequence.
417
+ this.#leftTapCount = 1;
418
+ return false;
419
+ }
420
+ this.#leftTapCount += 1;
421
+ if (this.#leftTapCount === 2 && sinceLast >= LEFT_DOUBLE_TAP_MIN_GAP_MS) {
422
+ // Exactly two taps, the second a human-plausible interval after the first.
423
+ this.#leftTapCount = 0;
424
+ this.ctx.lastLeftTapTime = 0;
425
+ return true;
426
+ }
427
+ return false;
428
+ }
429
+
430
+ #setupEnhancedPaste(): void {
431
+ if (this.#enhancedPaste) return;
432
+
433
+ this.#enhancedPaste = new EnhancedPasteController({
434
+ write: data => this.ctx.ui.terminal.write(data),
435
+ pasteText: text => {
436
+ // Route enhanced-paste text to the currently focused component when it
437
+ // exposes a `pasteText` hook (modal Input prompts: OAuth API-key entry,
438
+ // Perplexity OTP, GitHub Enterprise URL, manual redirect URL). Falling
439
+ // back to the main editor would have buried the text in the detached
440
+ // editor while the modal Input had focus (#2127).
441
+ const focused = this.ctx.ui.getFocused();
442
+ const target = focused && focused !== this.ctx.editor && hasPasteText(focused) ? focused : this.ctx.editor;
443
+ target.pasteText(text);
444
+ this.ctx.ui.requestRender();
445
+ },
446
+ pasteImage: async image => {
447
+ // Images can only land in the main editor — when a modal Input is
448
+ // focused, refuse rather than dump the binary blob in a hidden buffer.
449
+ const focused = this.ctx.ui.getFocused();
450
+ if (focused && focused !== this.ctx.editor && hasPasteText(focused)) {
451
+ this.ctx.showStatus("Image paste is not supported in this prompt");
452
+ return;
453
+ }
454
+ await this.#normalizeAndInsertPastedImage(image, `Unsupported pasted image format: ${image.mimeType}`);
455
+ },
456
+ showStatus: message => this.ctx.showStatus(message),
457
+ });
458
+ this.ctx.ui.addInputListener(data => (this.#enhancedPaste?.handleInput(data) ? { consume: true } : undefined));
459
+ this.ctx.ui.addStartListener(() => this.#enhancedPaste?.enable());
460
+ }
461
+
238
462
  setupEditorSubmitHandler(): void {
239
463
  this.ctx.editor.onSubmit = async (text: string) => {
240
464
  text = text.trim();
241
465
  if ((!isSettingsInitialized() || settings.get("emojiAutocomplete")) && text) text = expandEmoticons(text);
242
466
 
243
- // Empty submit while streaming with queued messages: flush queues immediately
244
- if (!text && this.ctx.session.isStreaming && this.ctx.session.queuedMessageCount > 0) {
245
- // Abort current stream and let queued messages be processed
246
- await this.ctx.session.abort();
467
+ // Focused subagent session: the editor is a plain chat box for it.
468
+ // Everything below (continue shortcuts, slash/bash/python, loop,
469
+ // compaction queueing) is main-session-only.
470
+ if (this.ctx.focusedAgentId) {
471
+ await this.#submitToFocusedSession(text, "steer");
472
+ return;
473
+ }
474
+
475
+ // Empty submit while streaming with queued messages: abort the active
476
+ // turn and let the post-unwind drain deliver the agent-core queue.
477
+ if (!text && this.ctx.session.isStreaming) {
478
+ if (this.ctx.session.queuedMessageCount > 0) {
479
+ const aborting = this.ctx.session.abort({ reason: USER_INTERRUPT_LABEL });
480
+ await aborting;
481
+ this.ctx.updatePendingMessagesDisplay();
482
+ this.ctx.ui.requestRender();
483
+ }
247
484
  return;
248
485
  }
249
486
 
250
487
  if (!text) return;
251
488
 
252
- // Continue shortcuts: "." or "c" sends empty message (agent continues, no visible message)
489
+ // Continue shortcuts: "." or "c" resume the agent with a hidden agent-authored
490
+ // developer directive (no visible user message) instead of an empty turn, so the
491
+ // model continues the prior intent rather than second-guessing the interrupt.
253
492
  if (text === "." || text === "c") {
254
493
  if (this.ctx.onInputCallback) {
255
494
  this.ctx.editor.setText("");
256
495
  this.ctx.pendingImages = [];
257
496
  this.ctx.pendingImageLinks = [];
258
497
  this.ctx.editor.imageLinks = undefined;
259
- this.ctx.onInputCallback({ text: "", cancelled: false, started: true });
498
+ this.ctx.onInputCallback({
499
+ text: manualContinuePrompt,
500
+ cancelled: false,
501
+ started: true,
502
+ synthetic: true,
503
+ });
260
504
  }
261
505
  return;
262
506
  }
@@ -291,7 +535,6 @@ export class InputController {
291
535
  // Handle built-in slash commands
292
536
  const slashResult = await executeBuiltinSlashCommand(text, {
293
537
  ctx: this.ctx,
294
- handleBackgroundCommand: () => this.handleBackgroundCommand(),
295
538
  });
296
539
  if (slashResult === true) {
297
540
  return;
@@ -301,6 +544,37 @@ export class InputController {
301
544
  text = slashResult;
302
545
  }
303
546
 
547
+ // Collab guest: prompts execute on the host; local slash/skill/bash/
548
+ // python execution is host-only (builtins are gated inside
549
+ // executeBuiltinSlashCommand, which already consumed allowed ones).
550
+ if (this.ctx.collabGuest) {
551
+ if (text.startsWith("/")) {
552
+ this.ctx.showStatus(`${text.split(/\s+/, 1)[0]} is host-only during a collab session`);
553
+ this.ctx.editor.setText("");
554
+ return;
555
+ }
556
+ if (text.startsWith("!") || text.startsWith("$")) {
557
+ this.ctx.showStatus("Local execution is host-only during a collab session");
558
+ this.ctx.editor.setText("");
559
+ return;
560
+ }
561
+ if (this.ctx.collabGuest.readOnly) {
562
+ // Keep the typed text: the prompt was not consumed.
563
+ this.ctx.showStatus("This collab link is read-only — prompting is disabled");
564
+ return;
565
+ }
566
+ this.ctx.editor.addToHistory(text);
567
+ this.ctx.editor.setText("");
568
+ this.ctx.editor.imageLinks = undefined;
569
+ const images = inputImages && inputImages.length > 0 ? [...inputImages] : undefined;
570
+ this.ctx.pendingImages = [];
571
+ this.ctx.pendingImageLinks = [];
572
+ // No local render: the prompt comes back from the host as a
573
+ // collab-prompt event/entry and renders with the author badge.
574
+ this.ctx.collabGuest.sendPrompt(text, images);
575
+ return;
576
+ }
577
+
304
578
  // Handle skill commands (/skill:name [args]). Enter ⇒ steer (matches the
305
579
  // free-text Enter semantics applied a few lines below at the streaming
306
580
  // branch). Ctrl+Enter routes through `handleFollowUp` and dispatches the
@@ -353,11 +627,8 @@ export class InputController {
353
627
 
354
628
  // Queue input during compaction
355
629
  if (this.ctx.session.isCompacting) {
356
- if (this.ctx.pendingImages.length > 0) {
357
- this.ctx.showStatus("Compaction in progress. Retry after it completes to send images.");
358
- return;
359
- }
360
- this.ctx.queueCompactionMessage(text, "steer");
630
+ const images = inputImages && inputImages.length > 0 ? [...inputImages] : undefined;
631
+ this.ctx.queueCompactionMessage(text, "steer", images);
361
632
  return;
362
633
  }
363
634
 
@@ -403,6 +674,7 @@ export class InputController {
403
674
  this.ctx.session.sessionId,
404
675
  this.ctx.session.model,
405
676
  provider => this.ctx.session.agent.metadataForProvider(provider),
677
+ this.ctx.titleSystemPrompt,
406
678
  )
407
679
  .then(async title => {
408
680
  // Re-check: a concurrent attempt for an earlier message may have
@@ -442,11 +714,76 @@ export class InputController {
442
714
  });
443
715
 
444
716
  this.ctx.onInputCallback(submission);
717
+ } else {
718
+ // No input waiter: the main loop is between turns (post-turn
719
+ // epilogue, retry backoff, or a scheduled continue) with the agent
720
+ // momentarily idle. The editor already cleared itself on Enter, so
721
+ // falling through here would silently swallow the message. Queue it
722
+ // as a steer instead: the idle drain in #queueSteer delivers it
723
+ // immediately when the session is resumable, and a retry/continue
724
+ // run picks it up at loop start otherwise.
725
+ this.ctx.editor.imageLinks = undefined;
726
+ const images = inputImages && inputImages.length > 0 ? [...inputImages] : undefined;
727
+ this.ctx.pendingImages = [];
728
+ this.ctx.pendingImageLinks = [];
729
+ try {
730
+ await this.ctx.withLocalSubmission(text, () => this.ctx.session.steer(text, images), {
731
+ imageCount: images?.length ?? 0,
732
+ });
733
+ } catch (error) {
734
+ // Don't lose the message: hand the text and images back to the
735
+ // editor so the user can retry (e.g. steer() rejecting an
736
+ // extension command).
737
+ this.ctx.editor.setText(text);
738
+ if (images && images.length > 0) {
739
+ this.ctx.pendingImages = [...images];
740
+ this.ctx.pendingImageLinks = inputImageLinks ? [...inputImageLinks] : images.map(() => undefined);
741
+ this.ctx.editor.imageLinks = this.ctx.pendingImageLinks;
742
+ }
743
+ this.ctx.showError(error instanceof Error ? error.message : String(error));
744
+ }
745
+ this.ctx.updatePendingMessagesDisplay();
746
+ this.ctx.ui.requestRender();
445
747
  }
446
748
  this.ctx.editor.addToHistory(text);
447
749
  };
448
750
  }
449
751
 
752
+ /** Submit editor text to the focused subagent session (chat-only focus policy). */
753
+ async #submitToFocusedSession(text: string, streamingBehavior: "steer" | "followUp"): Promise<void> {
754
+ const target = this.ctx.viewSession;
755
+ if (!text) {
756
+ if (target.isStreaming && target.queuedMessageCount > 0) {
757
+ const aborting = target.abort({ reason: USER_INTERRUPT_LABEL });
758
+ await aborting;
759
+ this.ctx.updatePendingMessagesDisplay();
760
+ this.ctx.ui.requestRender();
761
+ }
762
+ return;
763
+ }
764
+ if (text.startsWith("/") || text.startsWith("!") || text.startsWith("$")) {
765
+ this.ctx.showStatus("Commands run in the main session — press ←← to return first");
766
+ return; // editor text not cleared: Editor does not auto-clear on submit
767
+ }
768
+ const images = this.ctx.pendingImages.length > 0 ? [...this.ctx.pendingImages] : undefined;
769
+ this.ctx.editor.addToHistory(text);
770
+ this.ctx.editor.setText("");
771
+ this.ctx.editor.imageLinks = undefined;
772
+ this.ctx.pendingImages = [];
773
+ this.ctx.pendingImageLinks = [];
774
+ try {
775
+ // prompt() handles idle (new turn) and streaming (queues per streamingBehavior).
776
+ await this.ctx.withLocalSubmission(text, () => target.prompt(text, { streamingBehavior, images }), {
777
+ imageCount: images?.length ?? 0,
778
+ });
779
+ } catch (error) {
780
+ this.ctx.editor.setText(text); // hand the message back, mirroring the main submit error path
781
+ this.ctx.showError(error instanceof Error ? error.message : String(error));
782
+ }
783
+ this.ctx.updatePendingMessagesDisplay();
784
+ this.ctx.ui.requestRender();
785
+ }
786
+
450
787
  handleCtrlC(): void {
451
788
  const now = Date.now();
452
789
  if (now - this.ctx.lastSigintTime < 500) {
@@ -455,6 +792,18 @@ export class InputController {
455
792
  this.ctx.clearEditor();
456
793
  this.ctx.lastSigintTime = now;
457
794
  }
795
+ // Sync-flush the session JSONL so in-flight writes survive a hard exit.
796
+ // The TUI consumes Ctrl+C as a key event in raw mode, so postmortem's
797
+ // process-level SIGINT handler never fires. The second press still
798
+ // funnels through shutdown() which awaits its own async flush — the
799
+ // sync flush here is a superset that also covers the first-press case.
800
+ try {
801
+ this.ctx.sessionManager.flushSync();
802
+ } catch (err) {
803
+ logger.warn("session-manager sync flush on Ctrl+C failed", {
804
+ error: err instanceof Error ? err.message : String(err),
805
+ });
806
+ }
458
807
  }
459
808
 
460
809
  handleCtrlD(): void {
@@ -465,17 +814,44 @@ export class InputController {
465
814
  }
466
815
 
467
816
  handleCtrlZ(): void {
468
- // Set up handler to restore TUI when resumed
469
- process.once("SIGCONT", () => {
817
+ // SIGTSTP is POSIX job-control: Windows has no equivalent and
818
+ // `process.kill(_, "SIGTSTP")` throws `TypeError: Unknown signal:
819
+ // SIGTSTP` there, taking the whole agent down via an uncaught
820
+ // exception (issue #2036). No-op on platforms that cannot suspend.
821
+ if (process.platform === "win32") {
822
+ this.ctx.showStatus("Suspend (Ctrl+Z) is not supported on this platform");
823
+ return;
824
+ }
825
+
826
+ // Capture the listener so we can detach it if the signal never
827
+ // fires; otherwise a failed suspend would leave a stale SIGCONT
828
+ // handler that fires on the next unrelated continue and tries to
829
+ // re-`start()` an already-running TUI.
830
+ const onResume = (): void => {
470
831
  this.ctx.ui.start();
471
832
  this.ctx.ui.requestRender(true);
472
- });
833
+ };
834
+ process.once("SIGCONT", onResume);
473
835
 
474
- // Stop the TUI (restore terminal to normal mode)
836
+ // Stop the TUI (restore terminal to normal mode) before sending the
837
+ // signal so the parent shell sees a sane terminal state.
475
838
  this.ctx.ui.stop();
476
839
 
477
- // Send SIGTSTP to process group (pid=0 means all processes in group)
478
- process.kill(0, "SIGTSTP");
840
+ try {
841
+ // pid=0 → entire foreground process group; the shell receives
842
+ // SIGTSTP and parks the job.
843
+ process.kill(0, "SIGTSTP");
844
+ } catch (err) {
845
+ // Either the runtime refused the signal or the kernel rejected
846
+ // it (some sandboxes block sending to pid=0). Tear the resume
847
+ // hook down and bring the TUI back so the user is not stranded
848
+ // on a frozen prompt.
849
+ process.removeListener("SIGCONT", onResume);
850
+ this.ctx.ui.start();
851
+ this.ctx.ui.requestRender(true);
852
+ const reason = err instanceof Error ? err.message : String(err);
853
+ this.ctx.showError(`Failed to suspend: ${reason}`);
854
+ }
479
855
  }
480
856
 
481
857
  handleDequeue(): void {
@@ -524,15 +900,6 @@ export class InputController {
524
900
  args: args || undefined,
525
901
  lineCount: body ? body.split("\n").length : 0,
526
902
  };
527
- // When the agent is streaming, register the compact slash-form text as
528
- // the pending-display twin BEFORE dispatching the CustomMessage. The
529
- // returned tag is embedded in details so AgentSession.#handleAgentEvent
530
- // can remove the matching display entry when the agent consumes this
531
- // message (mirrors the user-message dequeue path).
532
- if (this.ctx.session.isStreaming) {
533
- const tag = this.ctx.session.enqueueCustomMessageDisplay(text, streamingBehavior);
534
- details.__pendingDisplayTag = tag;
535
- }
536
903
  await this.ctx.session.promptCustomMessage(
537
904
  {
538
905
  customType: SKILL_PROMPT_MESSAGE_TYPE,
@@ -541,7 +908,7 @@ export class InputController {
541
908
  details,
542
909
  attribution: "user",
543
910
  },
544
- { streamingBehavior },
911
+ { streamingBehavior, queueChipText: text },
545
912
  );
546
913
  if (this.ctx.session.isStreaming) {
547
914
  this.ctx.updatePendingMessagesDisplay();
@@ -555,9 +922,15 @@ export class InputController {
555
922
 
556
923
  /** Send editor text as a follow-up message (queued behind current stream). */
557
924
  async handleFollowUp(): Promise<void> {
558
- const text = this.ctx.editor.getText().trim();
925
+ let text = this.ctx.editor.getText().trim();
559
926
  if (!text) return;
560
927
 
928
+ // Focused subagent session: follow-ups go to it; non-chat input is gated.
929
+ if (this.ctx.focusedAgentId) {
930
+ await this.#submitToFocusedSession(text, "followUp");
931
+ return;
932
+ }
933
+
561
934
  // Compaction first: while compacting, free text gets queued via
562
935
  // `queueCompactionMessage`, and `/skill:*` rides the same queue so a
563
936
  // skill typed during compaction is not lost or short-circuited through
@@ -565,10 +938,21 @@ export class InputController {
565
938
  // the queued entry is later re-parsed into a skill invocation is a
566
939
  // separate concern owned by the compaction-resume path.
567
940
  if (this.ctx.session.isCompacting) {
568
- this.ctx.queueCompactionMessage(text, "followUp");
941
+ const images = this.ctx.pendingImages.length > 0 ? [...this.ctx.pendingImages] : undefined;
942
+ this.ctx.queueCompactionMessage(text, "followUp", images);
569
943
  return;
570
944
  }
571
945
 
946
+ const slashResult = await executeBuiltinSlashCommand(text, {
947
+ ctx: this.ctx,
948
+ });
949
+ if (slashResult === true) {
950
+ return;
951
+ }
952
+ if (typeof slashResult === "string") {
953
+ text = slashResult;
954
+ }
955
+
572
956
  // Skill commands invoke through the custom-message path regardless of
573
957
  // which keybinding submitted them. Enter routes them as `steer`;
574
958
  // Ctrl+Enter (this handler) routes them as `followUp`.
@@ -576,11 +960,20 @@ export class InputController {
576
960
  return;
577
961
  }
578
962
 
963
+ // Forward any pending clipboard-pasted images alongside the queued text;
964
+ // otherwise the follow-up would drop the image (mirrors the Enter/steer path).
965
+ const images = this.ctx.pendingImages.length > 0 ? [...this.ctx.pendingImages] : undefined;
966
+
579
967
  if (this.ctx.session.isStreaming) {
580
968
  this.ctx.editor.addToHistory(text);
581
969
  this.ctx.editor.setText("");
582
- await this.ctx.withLocalSubmission(text, () =>
583
- this.ctx.session.prompt(text, { streamingBehavior: "followUp" }),
970
+ this.ctx.editor.imageLinks = undefined;
971
+ this.ctx.pendingImages = [];
972
+ this.ctx.pendingImageLinks = [];
973
+ await this.ctx.withLocalSubmission(
974
+ text,
975
+ () => this.ctx.session.prompt(text, { streamingBehavior: "followUp", images }),
976
+ { imageCount: images?.length ?? 0 },
584
977
  );
585
978
  this.ctx.updatePendingMessagesDisplay();
586
979
  this.ctx.ui.requestRender();
@@ -590,148 +983,260 @@ export class InputController {
590
983
  // Not streaming — just submit normally
591
984
  this.ctx.editor.addToHistory(text);
592
985
  this.ctx.editor.setText("");
593
- await this.ctx.withLocalSubmission(text, () => this.ctx.session.prompt(text));
986
+ this.ctx.editor.imageLinks = undefined;
987
+ this.ctx.pendingImages = [];
988
+ this.ctx.pendingImageLinks = [];
989
+ await this.ctx.withLocalSubmission(text, () => this.ctx.session.prompt(text, { images }), {
990
+ imageCount: images?.length ?? 0,
991
+ });
594
992
  }
595
993
 
596
994
  restoreQueuedMessagesToEditor(options?: { abort?: boolean; currentText?: string }): number {
597
995
  this.ctx.locallySubmittedUserSignatures.clear();
598
996
  const { steering, followUp } = this.ctx.session.clearQueue();
599
- const allQueued = [...steering, ...followUp];
997
+ // Messages typed while compacting live in `compactionQueuedMessages`, not the
998
+ // agent queue `clearQueue()` drains — but the pending bar shows the same
999
+ // "Alt+Up to edit" hint for them (ui-helpers `updatePendingMessagesDisplay`).
1000
+ // Drain them here too so the dequeue restores every message the hint
1001
+ // advertises; otherwise a skill/text queued during compaction is stranded and
1002
+ // Alt+Up reports "No queued messages to restore".
1003
+ const compactionQueued = this.ctx.compactionQueuedMessages;
1004
+ this.ctx.compactionQueuedMessages = [];
1005
+ const allQueued = [
1006
+ ...steering,
1007
+ ...compactionQueued.filter(e => e.mode === "steer").map(e => ({ text: e.text, images: e.images })),
1008
+ ...followUp,
1009
+ ...compactionQueued.filter(e => e.mode === "followUp").map(e => ({ text: e.text, images: e.images })),
1010
+ ];
600
1011
  if (allQueued.length === 0) {
601
1012
  this.ctx.updatePendingMessagesDisplay();
602
1013
  if (options?.abort) {
603
- this.ctx.session.abort();
1014
+ void this.ctx.session.abort({ reason: USER_INTERRUPT_LABEL });
604
1015
  }
605
1016
  return 0;
606
1017
  }
607
- const queuedText = allQueued.join("\n\n");
1018
+ // Image markers are positional: `[Image #N]` ↔ `pendingImages[N-1]`. Each
1019
+ // queued message numbered its markers against its own local image list
1020
+ // (1..K). Because we prepend the queued text but append the queued images
1021
+ // to `pendingImages`, any existing draft images (M of them) — plus images
1022
+ // already pulled in by earlier queued messages — shift the slot index that
1023
+ // every marker must point to. Bumping each message's markers by the
1024
+ // running offset keeps the merged text aligned with the merged
1025
+ // `pendingImages` order; draft markers stay valid because draft images
1026
+ // keep their original positions.
1027
+ const queuedImages = allQueued.flatMap(e => e.images ?? []);
1028
+ let queuedText: string;
1029
+ if (queuedImages.length > 0) {
1030
+ const parts: string[] = [];
1031
+ let imageOffset = this.ctx.pendingImages.length;
1032
+ for (const entry of allQueued) {
1033
+ parts.push(shiftImageMarkers(entry.text, imageOffset));
1034
+ if (entry.images && entry.images.length > 0) imageOffset += entry.images.length;
1035
+ }
1036
+ queuedText = parts.join("\n\n");
1037
+ } else {
1038
+ queuedText = allQueued.map(e => e.text).join("\n\n");
1039
+ }
608
1040
  const currentText = options?.currentText ?? this.ctx.editor.getText();
609
1041
  const combinedText = [queuedText, currentText].filter(t => t.trim()).join("\n\n");
610
1042
  this.ctx.editor.setText(combinedText);
1043
+ // Hand queued images back to the pending-image buffer (links are
1044
+ // re-materialized lazily; the restored text already carries the
1045
+ // renumbered `[Image #N, WxH]` markers).
1046
+ if (queuedImages.length > 0) {
1047
+ this.ctx.pendingImages.push(...queuedImages);
1048
+ this.ctx.pendingImageLinks.push(...queuedImages.map(() => undefined));
1049
+ this.ctx.editor.imageLinks = this.ctx.pendingImageLinks;
1050
+ }
611
1051
  this.ctx.updatePendingMessagesDisplay();
612
1052
  if (options?.abort) {
613
- this.ctx.session.abort();
1053
+ void this.ctx.session.abort({ reason: USER_INTERRUPT_LABEL });
614
1054
  }
615
1055
  return allQueued.length;
616
1056
  }
617
1057
 
618
- handleBackgroundCommand(): void {
619
- if (this.ctx.isBackgrounded) {
620
- this.ctx.showStatus("Background mode already enabled");
621
- return;
622
- }
623
- if (!this.ctx.session.isStreaming && this.ctx.session.queuedMessageCount === 0) {
624
- this.ctx.showWarning("Agent is idle; nothing to background");
625
- return;
626
- }
627
- if (this.ctx.hasActiveBtw()) {
628
- this.ctx.handleBtwEscape();
629
- }
630
- if (this.ctx.hasActiveOmfg()) {
631
- this.ctx.handleOmfgEscape();
632
- }
633
-
634
- this.ctx.isBackgrounded = true;
635
- const backgroundUiContext = this.ctx.createBackgroundUiContext();
636
-
637
- // Background mode disables interactive UI so tools like ask fail fast.
638
- this.ctx.setToolUIContext(backgroundUiContext, false);
639
- this.ctx.initializeHookRunner(backgroundUiContext, false);
1058
+ async #insertPendingImage(imageData: ImageContent): Promise<void> {
1059
+ const imageLink = (
1060
+ await materializeImageReferenceLinks(
1061
+ [
1062
+ {
1063
+ type: "image",
1064
+ data: imageData.data,
1065
+ mimeType: imageData.mimeType,
1066
+ },
1067
+ ],
1068
+ this.ctx.sessionManager.putBlob.bind(this.ctx.sessionManager),
1069
+ )
1070
+ )?.[0];
1071
+ this.ctx.pendingImages.push({
1072
+ type: "image",
1073
+ data: imageData.data,
1074
+ mimeType: imageData.mimeType,
1075
+ });
1076
+ this.ctx.pendingImageLinks.push(imageLink);
1077
+ this.ctx.editor.imageLinks = this.ctx.pendingImageLinks;
1078
+ const imageNum = this.ctx.pendingImages.length;
1079
+ const dims = await this.#imageDimensions(imageData);
1080
+ const label = dims ? `[Image #${imageNum}, ${dims.width}x${dims.height}]` : `[Image #${imageNum}]`;
1081
+ this.ctx.editor.insertText(`${label} `);
1082
+ this.ctx.ui.requestRender();
1083
+ }
640
1084
 
641
- if (this.ctx.loadingAnimation) {
642
- this.ctx.loadingAnimation.stop();
643
- this.ctx.loadingAnimation = undefined;
644
- }
645
- if (this.ctx.autoCompactionLoader) {
646
- this.ctx.autoCompactionLoader.stop();
647
- this.ctx.autoCompactionLoader = undefined;
648
- }
649
- if (this.ctx.retryLoader) {
650
- this.ctx.retryLoader.stop();
651
- this.ctx.retryLoader = undefined;
1085
+ /** Probe pixel dimensions for the marker label (`[Image #N, WxH]`). Returns undefined when the
1086
+ * header can't be decoded, so the caller falls back to a bare `[Image #N]`. */
1087
+ async #imageDimensions(image: ImageContent): Promise<{ width: number; height: number } | undefined> {
1088
+ try {
1089
+ const { width, height } = await new Bun.Image(Buffer.from(image.data, "base64")).metadata();
1090
+ if (width && height) return { width, height };
1091
+ } catch {
1092
+ // Unknown/corrupt header — fall back to a bare label.
652
1093
  }
653
- this.ctx.statusContainer.clear();
654
- this.ctx.statusLine.dispose();
1094
+ return undefined;
1095
+ }
655
1096
 
656
- if (this.ctx.unsubscribe) {
657
- this.ctx.unsubscribe();
1097
+ async #normalizeAndInsertPastedImage(image: ImageContent, unsupportedMessage: string): Promise<boolean> {
1098
+ let imageData = await ensureSupportedImageInput(image);
1099
+ if (!imageData) {
1100
+ this.ctx.showStatus(unsupportedMessage);
1101
+ return false;
658
1102
  }
659
- this.ctx.unsubscribe = this.ctx.session.subscribe(async (event: AgentSessionEvent) => {
660
- await this.ctx.handleBackgroundEvent(event);
661
- });
662
-
663
- // Backgrounding keeps the current process to preserve in-flight agent state.
664
- if (this.ctx.isInitialized) {
665
- this.ctx.ui.stop();
666
- this.ctx.isInitialized = false;
1103
+ if (settings.get("images.autoResize")) {
1104
+ try {
1105
+ const resized = await resizeImage({
1106
+ type: "image",
1107
+ data: imageData.data,
1108
+ mimeType: imageData.mimeType,
1109
+ });
1110
+ imageData = { type: "image", data: resized.data, mimeType: resized.mimeType };
1111
+ } catch {
1112
+ // Keep the normalized image when resize fails.
1113
+ }
667
1114
  }
1115
+ await this.#insertPendingImage(imageData);
1116
+ return true;
1117
+ }
668
1118
 
669
- process.stdout.write("Background mode enabled. Run `bg` to continue in background.\n");
670
-
671
- if (process.platform === "win32" || !process.stdout.isTTY) {
672
- process.stdout.write("Backgrounding requires POSIX job control; continuing in foreground.\n");
673
- return;
1119
+ /**
1120
+ * Win+Shift+S on Windows 11 leaves the screenshot bitmap on the clipboard
1121
+ * while the terminal pastes a transient packaged-app TempState path
1122
+ * (…\MicrosoftWindows.Client.Core_*\TempState\…) that is already gone or
1123
+ * never materialized — by the time we read it. Whenever a pasted image path
1124
+ * can't be turned into an image locally, those clipboard bytes are the real
1125
+ * payload, so prefer them before degrading to a text paste.
1126
+ *
1127
+ * Skipped over SSH: the clipboard read would hit the remote host, not the
1128
+ * terminal that holds the screenshot. Returns true when the clipboard owned
1129
+ * the outcome (image attached, or an unsupported-format status surfaced), so
1130
+ * the caller stops without emitting its own degraded diagnostic.
1131
+ */
1132
+ async #tryPasteClipboardImage(): Promise<boolean> {
1133
+ const env = process.env;
1134
+ if (env.SSH_CONNECTION || env.SSH_TTY || env.SSH_CLIENT) return false;
1135
+ try {
1136
+ const image = await this.clipboard.readImage();
1137
+ if (!image) return false;
1138
+ await this.#normalizeAndInsertPastedImage(
1139
+ { type: "image", data: image.data.toBase64(), mimeType: image.mimeType },
1140
+ `Unsupported clipboard image format: ${image.mimeType}`,
1141
+ );
1142
+ return true;
1143
+ } catch {
1144
+ return false;
674
1145
  }
1146
+ }
675
1147
 
676
- process.kill(0, "SIGTSTP");
1148
+ async handleImagePathPaste(path: string): Promise<void> {
1149
+ try {
1150
+ const image = await loadImageInput({
1151
+ path,
1152
+ cwd: this.ctx.sessionManager.getCwd(),
1153
+ autoResize: false,
1154
+ });
1155
+ if (!image) {
1156
+ // Path resolved but is not a readable image (e.g. a zero-byte or
1157
+ // locked transient screenshot file). Prefer the clipboard bytes.
1158
+ if (await this.#tryPasteClipboardImage()) return;
1159
+ this.ctx.editor.pasteText(path);
1160
+ this.ctx.ui.requestRender();
1161
+ this.ctx.showStatus("Pasted path is not a supported image");
1162
+ return;
1163
+ }
1164
+ await this.#normalizeAndInsertPastedImage(
1165
+ { type: "image", data: image.data, mimeType: image.mimeType },
1166
+ `Unsupported pasted image format: ${image.mimeType}`,
1167
+ );
1168
+ } catch (error) {
1169
+ if (error instanceof ImageInputTooLargeError) {
1170
+ this.ctx.editor.pasteText(path);
1171
+ this.ctx.ui.requestRender();
1172
+ this.ctx.showStatus(error.message);
1173
+ return;
1174
+ }
1175
+ if (isEnoent(error)) {
1176
+ // #2375: the bracketed paste forwarded by a local terminal carries a
1177
+ // path on the *local* filesystem. The bytes may still be on the
1178
+ // clipboard (Win+Shift+S), so try those before giving up.
1179
+ if (await this.#tryPasteClipboardImage()) return;
1180
+ // Over SSH the clipboard lives on the remote host, so the path is
1181
+ // genuinely unreachable; pasting it as text would look like the
1182
+ // image was attached when nothing was sent. Surface an SSH-aware
1183
+ // diagnostic instead. The pasted path is untrusted terminal input —
1184
+ // strip control/ANSI/newlines, collapse home to `~`, and bound the
1185
+ // displayed length before splicing it into the status string.
1186
+ const env = process.env;
1187
+ const overSsh = Boolean(env.SSH_CONNECTION || env.SSH_TTY || env.SSH_CLIENT);
1188
+ const displayPath = truncateToWidth(
1189
+ shortenPath(
1190
+ sanitizeText(path)
1191
+ .replace(/[\r\n\t]+/g, " ")
1192
+ .trim(),
1193
+ ),
1194
+ TRUNCATE_LENGTHS.CONTENT,
1195
+ );
1196
+ this.ctx.showStatus(
1197
+ overSsh
1198
+ ? `Image not found at ${displayPath}. Over SSH this path is local to your terminal — paste the image directly (clipboard image-paste shortcut) to send its bytes.`
1199
+ : `Image not found at ${displayPath}`,
1200
+ );
1201
+ return;
1202
+ }
1203
+ if (await this.#tryPasteClipboardImage()) return;
1204
+ this.ctx.editor.pasteText(path);
1205
+ this.ctx.ui.requestRender();
1206
+ this.ctx.showStatus("Failed to read pasted image path");
1207
+ }
677
1208
  }
678
1209
 
679
1210
  async handleImagePaste(): Promise<boolean> {
680
1211
  try {
681
- const image = await readImageFromClipboard();
682
- if (image) {
683
- const base64Data = image.data.toBase64();
684
- let imageData = await ensureSupportedImageInput({
685
- type: "image",
686
- data: base64Data,
687
- mimeType: image.mimeType,
688
- });
689
- if (!imageData) {
690
- this.ctx.showStatus(`Unsupported clipboard image format: ${image.mimeType}`);
1212
+ const image = await this.clipboard.readImage();
1213
+ if (!image) {
1214
+ // Smart paste (#1628): no image on the clipboard — fall back to
1215
+ // pasting its text so the same chord covers both payload kinds.
1216
+ // Hosts that pre-empt the terminal's own paste (VS Code's
1217
+ // integrated terminal, Win+V clipboard history) deliver only
1218
+ // this keypress, so a miss here must not dead-end.
1219
+ const text = await this.clipboard.readText();
1220
+ if (!text) {
1221
+ this.ctx.showStatus("Clipboard is empty");
691
1222
  return false;
692
1223
  }
693
- if (settings.get("images.autoResize")) {
694
- try {
695
- const resized = await resizeImage({
696
- type: "image",
697
- data: imageData.data,
698
- mimeType: imageData.mimeType,
699
- });
700
- imageData = { type: "image", data: resized.data, mimeType: resized.mimeType };
701
- } catch {
702
- // Keep the normalized image when resize fails.
703
- }
704
- }
705
-
706
- const imageLink = (
707
- await materializeImageReferenceLinks(
708
- [
709
- {
710
- type: "image",
711
- data: imageData.data,
712
- mimeType: imageData.mimeType,
713
- },
714
- ],
715
- this.ctx.sessionManager.putBlob.bind(this.ctx.sessionManager),
716
- )
717
- )?.[0];
718
- this.ctx.pendingImages.push({
719
- type: "image",
720
- data: imageData.data,
721
- mimeType: imageData.mimeType,
722
- });
723
- this.ctx.pendingImageLinks.push(imageLink);
724
- this.ctx.editor.imageLinks = this.ctx.pendingImageLinks;
725
- // Insert placeholder at cursor like Claude does
726
- const imageNum = this.ctx.pendingImages.length;
727
- const placeholder = `[Image #${imageNum}]`;
728
- this.ctx.editor.insertText(`${placeholder} `);
1224
+ // Route to the focused component when it accepts pastes (modal
1225
+ // Input prompts), matching the enhanced-paste text path (#2127).
1226
+ const focused = this.ctx.ui.getFocused();
1227
+ const target = focused && focused !== this.ctx.editor && hasPasteText(focused) ? focused : this.ctx.editor;
1228
+ target.pasteText(text);
729
1229
  this.ctx.ui.requestRender();
730
1230
  return true;
731
1231
  }
732
- // No image in clipboard - show hint
733
- this.ctx.showStatus("No image in clipboard (use terminal paste for text)");
734
- return false;
1232
+ return await this.#normalizeAndInsertPastedImage(
1233
+ {
1234
+ type: "image",
1235
+ data: image.data.toBase64(),
1236
+ mimeType: image.mimeType,
1237
+ },
1238
+ `Unsupported clipboard image format: ${image.mimeType}`,
1239
+ );
735
1240
  } catch {
736
1241
  this.ctx.showStatus("Failed to read clipboard");
737
1242
  return false;
@@ -740,10 +1245,11 @@ export class InputController {
740
1245
 
741
1246
  async handleClipboardTextRawPaste(): Promise<void> {
742
1247
  try {
743
- const text = await readTextFromClipboard();
1248
+ const text = await this.clipboard.readText();
744
1249
  if (text) {
745
1250
  this.ctx.editor.insertText(text);
746
1251
  this.ctx.ui.requestRender();
1252
+ } else {
747
1253
  this.ctx.showStatus("No text in clipboard to paste raw");
748
1254
  }
749
1255
  } catch {
@@ -751,6 +1257,97 @@ export class InputController {
751
1257
  }
752
1258
  }
753
1259
 
1260
+ /**
1261
+ * Editor `onLargePaste` hook: gate a marker-sized paste behind the large-paste menu. Returns
1262
+ * `true` to intercept (the editor skips its default `[Paste]` marker) once the paste reaches the
1263
+ * configured `paste.largeMenuThreshold` line count; otherwise `false` for default collapse-to-marker
1264
+ * behavior. The async menu is fired and forgotten — the editor only needs the synchronous verdict.
1265
+ */
1266
+ handleLargePaste(text: string, lineCount: number): boolean {
1267
+ const threshold = this.ctx.settings.get("paste.largeMenuThreshold");
1268
+ if (!(threshold > 0) || lineCount < threshold) return false;
1269
+ void this.presentLargePasteMenu(text, lineCount);
1270
+ return true;
1271
+ }
1272
+
1273
+ /**
1274
+ * Present the large-paste menu and apply the chosen action: wrap in a code block or in XML tags
1275
+ * (both collapse to a `[Paste]` marker that expands on submit), or save the text to a file and
1276
+ * reference its path so the agent can `read` it on demand. Cancelling (Esc) falls back to the
1277
+ * default inline paste marker, so the pasted content is never lost.
1278
+ */
1279
+ async presentLargePasteMenu(text: string, lineCount: number): Promise<void> {
1280
+ const CODE_BLOCK = "Wrap in a code block";
1281
+ const XML = "Wrap in XML tags";
1282
+ const FILE = "Attach as a file";
1283
+
1284
+ let choice: string | undefined;
1285
+ try {
1286
+ choice = await this.ctx.showHookSelector(
1287
+ `Pasted ${lineCount} lines`,
1288
+ [
1289
+ { label: CODE_BLOCK, description: "Fence the text in a ``` block, collapsed to a marker" },
1290
+ { label: XML, description: "Wrap the text in <pasted_text> tags, collapsed to a marker" },
1291
+ { label: FILE, description: "Save the text to a file and reference its path" },
1292
+ ],
1293
+ { helpText: "Esc to paste inline" },
1294
+ );
1295
+ } catch (error) {
1296
+ logger.warn("large-paste menu failed", { error: error instanceof Error ? error.message : String(error) });
1297
+ choice = undefined;
1298
+ }
1299
+
1300
+ switch (choice) {
1301
+ case CODE_BLOCK:
1302
+ this.ctx.editor.insertPaste(wrapPasteInCodeBlock(text));
1303
+ break;
1304
+ case XML:
1305
+ this.ctx.editor.insertPaste(wrapPasteInXml(text));
1306
+ break;
1307
+ case FILE:
1308
+ await this.#attachPasteAsFile(text, lineCount);
1309
+ break;
1310
+ default:
1311
+ // Esc / cancel: keep the original behavior — collapse to an inline paste marker.
1312
+ this.ctx.editor.insertPaste(text);
1313
+ break;
1314
+ }
1315
+ this.ctx.ui.requestRender();
1316
+ }
1317
+
1318
+ /**
1319
+ * Save a large paste to the session's `local://` store and insert a clean `local://attachment-N`
1320
+ * reference into the editor so the agent can `read` it on demand — instead of inlining the text or
1321
+ * leaking a raw temp path. Falls back to an inline paste marker when the write fails, so the
1322
+ * content is never lost.
1323
+ */
1324
+ async #attachPasteAsFile(text: string, lineCount: number): Promise<void> {
1325
+ try {
1326
+ // Mirror the exact mapping the read tool's local:// resolver uses so a later
1327
+ // `read local://attachment-N` lands on the file written here.
1328
+ const localRoot = resolveLocalRoot({
1329
+ getArtifactsDir: () => this.ctx.sessionManager.getArtifactsDir(),
1330
+ getSessionId: () => this.ctx.sessionManager.getSessionId(),
1331
+ });
1332
+ let name: string;
1333
+ let filePath: string;
1334
+ do {
1335
+ this.#attachmentCounter++;
1336
+ name = `attachment-${this.#attachmentCounter}`;
1337
+ filePath = path.join(localRoot, name);
1338
+ } while (await Bun.file(filePath).exists());
1339
+ await Bun.write(filePath, text);
1340
+ this.ctx.editor.insertText(`local://${name} `);
1341
+ this.ctx.showStatus(`Saved ${lineCount} pasted lines to local://${name}`);
1342
+ } catch (error) {
1343
+ logger.warn("failed to save large paste to file", {
1344
+ error: error instanceof Error ? error.message : String(error),
1345
+ });
1346
+ this.ctx.editor.insertPaste(text);
1347
+ this.ctx.showError("Failed to save paste to a file — pasted inline instead");
1348
+ }
1349
+ }
1350
+
754
1351
  createAutocompleteProvider(commands: SlashCommand[], basePath: string): AutocompleteProvider {
755
1352
  return createPromptActionAutocompleteProvider({
756
1353
  commands,
@@ -802,6 +1399,10 @@ export class InputController {
802
1399
  }
803
1400
 
804
1401
  cycleThinkingLevel(): void {
1402
+ if (this.ctx.focusedAgentId) {
1403
+ this.ctx.showStatus("Model/thinking apply to the main session — press ←← to return first");
1404
+ return;
1405
+ }
805
1406
  const newLevel = this.ctx.session.cycleThinkingLevel();
806
1407
  if (newLevel === undefined) {
807
1408
  this.ctx.showStatus("Current model does not support thinking");
@@ -812,6 +1413,10 @@ export class InputController {
812
1413
  }
813
1414
 
814
1415
  async cycleRoleModel(direction: "forward" | "backward" = "forward"): Promise<void> {
1416
+ if (this.ctx.focusedAgentId) {
1417
+ this.ctx.showStatus("Model/thinking apply to the main session — press ←← to return first");
1418
+ return;
1419
+ }
815
1420
  try {
816
1421
  const cycleOrder = settings.get("cycleOrder");
817
1422
  const result = await this.ctx.session.cycleRoleModels(cycleOrder, direction);
@@ -824,12 +1429,14 @@ export class InputController {
824
1429
  this.ctx.updateEditorBorderColor();
825
1430
  // The status line already reports the resolved model + thinking level, so
826
1431
  // the cycle status is just a status-line-style chip track (active role
827
- // filled), matching the plan-approval model slider.
1432
+ // filled), matching the plan-approval model slider. It renders into its
1433
+ // own anchored container above the editor (cleared+rebuilt each cycle),
1434
+ // so it updates in place instead of stacking duplicates in the scrollback.
828
1435
  const track = renderSegmentTrack(
829
- cycleOrder.map(role => ({ label: role, color: getRoleInfo(role, settings).color })),
1436
+ cycleOrder.map(role => ({ label: role })),
830
1437
  cycleOrder.indexOf(result.role),
831
1438
  );
832
- this.ctx.showStatus(track, { dim: false });
1439
+ this.ctx.showModelCycleTrack(track);
833
1440
  } catch (error) {
834
1441
  this.ctx.showError(error instanceof Error ? error.message : String(error));
835
1442
  }
@@ -846,23 +1453,32 @@ export class InputController {
846
1453
  child.setExpanded(expanded);
847
1454
  }
848
1455
  }
849
- this.ctx.ui.requestRender(false, { allowUnknownViewportMutation: true });
1456
+ // Toggling expansion mutates every block, but on ED3-risk terminals the
1457
+ // transcript freezes a snapshot of each block once it scrolls past the live
1458
+ // region (committed native scrollback is immutable there). A plain repaint
1459
+ // replays those stale snapshots, so the toggle appears to do nothing above
1460
+ // the live block. resetDisplay() invalidates the snapshots and forces a
1461
+ // full clear + replay — the keyboard-accessible resize-reset equivalent —
1462
+ // which is the only path that re-emits the whole transcript at its new
1463
+ // heights.
1464
+ this.ctx.ui.resetDisplay();
850
1465
  }
851
1466
 
852
1467
  toggleThinkingBlockVisibility(): void {
853
1468
  this.ctx.hideThinkingBlock = !this.ctx.hideThinkingBlock;
854
- settings.set("hideThinkingBlock", this.ctx.hideThinkingBlock);
1469
+ this.ctx.settings.set("hideThinkingBlock", this.ctx.hideThinkingBlock);
855
1470
  this.ctx.session.agent.hideThinkingSummary = this.ctx.hideThinkingBlock;
856
1471
 
857
- // Rebuild chat from session messages
858
- this.ctx.chatContainer.clear();
859
- this.ctx.rebuildChatFromMessages();
1472
+ for (const child of this.ctx.chatContainer.children) {
1473
+ if (child instanceof AssistantMessageComponent) {
1474
+ child.setHideThinkingBlock(this.ctx.hideThinkingBlock);
1475
+ child.invalidate();
1476
+ }
1477
+ }
860
1478
 
861
- // If streaming, re-add the streaming component with updated visibility and re-render
862
1479
  if (this.ctx.streamingComponent && this.ctx.streamingMessage) {
863
1480
  this.ctx.streamingComponent.setHideThinkingBlock(this.ctx.hideThinkingBlock);
864
1481
  this.ctx.streamingComponent.updateContent(this.ctx.streamingMessage);
865
- this.ctx.chatContainer.addChild(this.ctx.streamingComponent);
866
1482
  }
867
1483
 
868
1484
  this.ctx.showStatus(`Thinking blocks: ${this.ctx.hideThinkingBlock ? "hidden" : "visible"}`);