@prometheus-ai/agent 0.5.3 → 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 (1160) hide show
  1. package/CHANGELOG.md +39 -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/gateway-cli.d.ts +4 -0
  37. package/dist/types/cli/grievances-cli.d.ts +1 -1
  38. package/dist/types/cli/list-models.d.ts +6 -14
  39. package/dist/types/cli/models-cli.d.ts +49 -0
  40. package/dist/types/cli/session-picker.d.ts +1 -1
  41. package/dist/types/cli/setup-cli.d.ts +1 -1
  42. package/dist/types/cli/setup-model-picker.d.ts +14 -0
  43. package/dist/types/cli/startup-cwd.d.ts +2 -0
  44. package/dist/types/cli/update-cli.d.ts +13 -40
  45. package/dist/types/cli/usage-cli.d.ts +81 -0
  46. package/dist/types/cli-commands.d.ts +12 -0
  47. package/dist/types/collab/crypto.d.ts +7 -0
  48. package/dist/types/collab/guest.d.ts +37 -0
  49. package/dist/types/collab/host.d.ts +29 -0
  50. package/dist/types/collab/protocol.d.ts +119 -0
  51. package/dist/types/collab/relay-client.d.ts +22 -0
  52. package/dist/types/commands/bench.d.ts +29 -0
  53. package/dist/types/commands/gallery.d.ts +47 -0
  54. package/dist/types/commands/gateway.d.ts +3 -0
  55. package/dist/types/commands/install.d.ts +1 -1
  56. package/dist/types/commands/join.d.ts +12 -0
  57. package/dist/types/commands/launch.d.ts +8 -4
  58. package/dist/types/commands/models.d.ts +33 -0
  59. package/dist/types/commands/read.d.ts +1 -1
  60. package/dist/types/commands/say.d.ts +24 -0
  61. package/dist/types/commands/token.d.ts +25 -0
  62. package/dist/types/commands/usage.d.ts +34 -0
  63. package/dist/types/commit/agentic/tools/analyze-file.d.ts +1 -1
  64. package/dist/types/commit/agentic/tools/git-file-diff.d.ts +1 -1
  65. package/dist/types/commit/agentic/tools/git-hunk.d.ts +1 -1
  66. package/dist/types/commit/agentic/tools/git-overview.d.ts +1 -1
  67. package/dist/types/commit/agentic/tools/propose-changelog.d.ts +1 -1
  68. package/dist/types/commit/agentic/tools/propose-commit.d.ts +1 -1
  69. package/dist/types/commit/agentic/tools/recent-commits.d.ts +1 -1
  70. package/dist/types/commit/agentic/tools/schemas.d.ts +1 -1
  71. package/dist/types/commit/agentic/tools/split-commit.d.ts +1 -1
  72. package/dist/types/commit/analysis/conventional.d.ts +2 -2
  73. package/dist/types/commit/analysis/summary.d.ts +2 -2
  74. package/dist/types/commit/changelog/generate.d.ts +3 -3
  75. package/dist/types/commit/changelog/index.d.ts +2 -2
  76. package/dist/types/commit/map-reduce/index.d.ts +3 -3
  77. package/dist/types/commit/map-reduce/map-phase.d.ts +2 -2
  78. package/dist/types/commit/map-reduce/reduce-phase.d.ts +2 -2
  79. package/dist/types/commit/model-selection.d.ts +10 -4
  80. package/dist/types/commit/shared-llm.d.ts +1 -1
  81. package/dist/types/config/api-key-resolver.d.ts +43 -0
  82. package/dist/types/config/append-only-context-mode.d.ts +2 -1
  83. package/dist/types/config/keybindings.d.ts +12 -7
  84. package/dist/types/config/model-discovery.d.ts +57 -0
  85. package/dist/types/config/model-equivalence.d.ts +1 -1
  86. package/dist/types/config/model-registry.d.ts +86 -222
  87. package/dist/types/config/model-resolver.d.ts +43 -12
  88. package/dist/types/config/model-roles.d.ts +29 -0
  89. package/dist/types/config/models-config-schema.d.ts +536 -43
  90. package/dist/types/config/models-config.d.ts +391 -0
  91. package/dist/types/config/settings-schema.d.ts +1211 -324
  92. package/dist/types/config/settings.d.ts +15 -3
  93. package/dist/types/dap/config.d.ts +14 -1
  94. package/dist/types/dap/types.d.ts +10 -0
  95. package/dist/types/debug/log-viewer.d.ts +1 -1
  96. package/dist/types/debug/raw-sse.d.ts +1 -1
  97. package/dist/types/debug/report-bundle.d.ts +3 -0
  98. package/dist/types/debug/terminal-info.d.ts +0 -1
  99. package/dist/types/discovery/at-imports.d.ts +15 -0
  100. package/dist/types/discovery/prometheus-extension-roots.d.ts +7 -7
  101. package/dist/types/edit/diff.d.ts +3 -2
  102. package/dist/types/edit/file-snapshot-store.d.ts +18 -0
  103. package/dist/types/edit/hashline/noop-loop-guard.d.ts +72 -0
  104. package/dist/types/edit/hashline/params.d.ts +1 -1
  105. package/dist/types/edit/index.d.ts +0 -1
  106. package/dist/types/edit/modes/apply-patch.d.ts +1 -1
  107. package/dist/types/edit/modes/patch.d.ts +1 -1
  108. package/dist/types/edit/modes/replace.d.ts +1 -1
  109. package/dist/types/edit/renderer.d.ts +1 -0
  110. package/dist/types/eval/__tests__/completion-bridge.test.d.ts +1 -0
  111. package/dist/types/eval/__tests__/helpers-local-roots.test.d.ts +1 -0
  112. package/dist/types/eval/__tests__/js-context-manager.test.d.ts +1 -0
  113. package/dist/types/eval/backend.d.ts +7 -2
  114. package/dist/types/eval/bridge-timeout.d.ts +1 -1
  115. package/dist/types/eval/completion-bridge.d.ts +25 -0
  116. package/dist/types/eval/idle-timeout.d.ts +1 -5
  117. package/dist/types/eval/js/context-manager.d.ts +1 -0
  118. package/dist/types/eval/js/executor.d.ts +2 -0
  119. package/dist/types/eval/js/index.d.ts +1 -1
  120. package/dist/types/eval/js/shared/helpers.d.ts +7 -1
  121. package/dist/types/eval/js/shared/rewrite-imports.d.ts +6 -6
  122. package/dist/types/eval/js/shared/runtime.d.ts +6 -1
  123. package/dist/types/eval/js/worker-protocol.d.ts +6 -0
  124. package/dist/types/eval/py/__tests__/prelude.test.d.ts +1 -0
  125. package/dist/types/eval/py/executor.d.ts +12 -0
  126. package/dist/types/eval/py/index.d.ts +1 -1
  127. package/dist/types/eval/py/kernel.d.ts +6 -1
  128. package/dist/types/eval/py/runtime.d.ts +9 -0
  129. package/dist/types/exa/index.d.ts +1 -19
  130. package/dist/types/exa/mcp-client.d.ts +10 -3
  131. package/dist/types/exa/types.d.ts +0 -83
  132. package/dist/types/exec/bash-executor.d.ts +7 -0
  133. package/dist/types/export/custom-share.d.ts +1 -2
  134. package/dist/types/export/html/index.d.ts +39 -0
  135. package/dist/types/export/html/template-js.d.ts +2 -0
  136. package/dist/types/export/share.d.ts +61 -0
  137. package/dist/types/export/ttsr.d.ts +14 -0
  138. package/dist/types/extensibility/custom-commands/types.d.ts +9 -4
  139. package/dist/types/extensibility/custom-tools/loader.d.ts +30 -4
  140. package/dist/types/extensibility/custom-tools/types.d.ts +16 -8
  141. package/dist/types/extensibility/extensions/index.d.ts +1 -1
  142. package/dist/types/extensibility/extensions/loader.d.ts +20 -1
  143. package/dist/types/extensibility/extensions/model-api.d.ts +17 -0
  144. package/dist/types/extensibility/extensions/runner.d.ts +5 -2
  145. package/dist/types/extensibility/extensions/types.d.ts +72 -11
  146. package/dist/types/extensibility/hooks/index.d.ts +2 -1
  147. package/dist/types/extensibility/hooks/loader.d.ts +1 -1
  148. package/dist/types/extensibility/hooks/types.d.ts +11 -5
  149. package/dist/types/extensibility/{legacy-pi-ai-shim.d.ts → legacy-package-ai-shim.d.ts} +2 -2
  150. package/dist/types/extensibility/plugins/{legacy-pi-compat.d.ts → legacy-package-compat.d.ts} +20 -3
  151. package/dist/types/extensibility/plugins/loader.d.ts +11 -0
  152. package/dist/types/extensibility/plugins/marketplace-auto-update.d.ts +8 -0
  153. package/dist/types/extensibility/plugins/types.d.ts +2 -2
  154. package/dist/types/extensibility/shared-events.d.ts +3 -3
  155. package/dist/types/extensibility/skills.d.ts +10 -0
  156. package/dist/types/extensibility/slash-commands.d.ts +1 -11
  157. package/dist/types/gateway/adapters/telegram/access.d.ts +4 -1
  158. package/dist/types/gateway/adapters/telegram/setup-api.d.ts +1 -1
  159. package/dist/types/gateway/adapters/telegram/webhook.d.ts +1 -1
  160. package/dist/types/gateway/types.d.ts +1 -1
  161. package/dist/types/goals/guided-setup.d.ts +18 -0
  162. package/dist/types/goals/state.d.ts +1 -1
  163. package/dist/types/goals/tools/goal-tool.d.ts +1 -1
  164. package/dist/types/hindsight/mental-models.d.ts +17 -8
  165. package/dist/types/hindsight/transcript.d.ts +1 -1
  166. package/dist/types/index.d.ts +5 -0
  167. package/dist/types/internal-urls/artifact-protocol.d.ts +2 -2
  168. package/dist/types/internal-urls/history-protocol.d.ts +14 -0
  169. package/dist/types/internal-urls/index.d.ts +1 -0
  170. package/dist/types/internal-urls/local-protocol.d.ts +14 -2
  171. package/dist/types/internal-urls/types.d.ts +1 -1
  172. package/dist/types/irc/bus.d.ts +79 -0
  173. package/dist/types/lib/xai-http.d.ts +1 -1
  174. package/dist/types/lsp/client.d.ts +10 -0
  175. package/dist/types/lsp/config.d.ts +2 -2
  176. package/dist/types/lsp/edits.d.ts +9 -0
  177. package/dist/types/lsp/format-options.d.ts +32 -0
  178. package/dist/types/lsp/index.d.ts +2 -7
  179. package/dist/types/lsp/types.d.ts +13 -1
  180. package/dist/types/lsp/utils.d.ts +6 -2
  181. package/dist/types/main.d.ts +23 -8
  182. package/dist/types/mcp/json-rpc.d.ts +5 -0
  183. package/dist/types/mcp/manager.d.ts +8 -0
  184. package/dist/types/mcp/oauth-discovery.d.ts +6 -1
  185. package/dist/types/mcp/oauth-flow.d.ts +13 -3
  186. package/dist/types/mcp/startup-events.d.ts +11 -0
  187. package/dist/types/mcp/tool-bridge.d.ts +2 -0
  188. package/dist/types/mcp/transports/stdio.d.ts +13 -0
  189. package/dist/types/mcp/types.d.ts +2 -0
  190. package/dist/types/memories/index.d.ts +7 -15
  191. package/dist/types/memories/storage.d.ts +0 -10
  192. package/dist/types/memory-backend/index.d.ts +3 -1
  193. package/dist/types/memory-backend/local-backend.d.ts +4 -3
  194. package/dist/types/memory-backend/resolve.d.ts +2 -2
  195. package/dist/types/memory-backend/runtime.d.ts +4 -0
  196. package/dist/types/memory-backend/types.d.ts +67 -2
  197. package/dist/types/mnemopi/config.d.ts +31 -1
  198. package/dist/types/mnemopi/state.d.ts +40 -2
  199. package/dist/types/modes/acp/acp-agent.d.ts +1 -2
  200. package/dist/types/modes/components/agent-dashboard.d.ts +17 -1
  201. package/dist/types/modes/components/agent-hub.d.ts +82 -0
  202. package/dist/types/modes/components/assistant-message.d.ts +5 -12
  203. package/dist/types/modes/components/bash-execution.d.ts +1 -1
  204. package/dist/types/modes/components/chat-block.d.ts +64 -0
  205. package/dist/types/modes/components/collab-prompt-message.d.ts +10 -0
  206. package/dist/types/modes/components/compaction-summary-message.d.ts +25 -5
  207. package/dist/types/modes/components/copy-selector.d.ts +1 -1
  208. package/dist/types/modes/components/custom-editor.d.ts +49 -2
  209. package/dist/types/modes/components/custom-editor.test.d.ts +1 -0
  210. package/dist/types/modes/components/dynamic-border.d.ts +1 -1
  211. package/dist/types/modes/components/extensions/extension-dashboard.d.ts +1 -1
  212. package/dist/types/modes/components/extensions/extension-list.d.ts +1 -1
  213. package/dist/types/modes/components/extensions/inspector-panel.d.ts +1 -1
  214. package/dist/types/modes/components/footer.d.ts +1 -1
  215. package/dist/types/modes/components/hook-editor.d.ts +5 -0
  216. package/dist/types/modes/components/hook-input.d.ts +4 -0
  217. package/dist/types/modes/components/hook-selector.d.ts +5 -7
  218. package/dist/types/modes/components/index.d.ts +1 -0
  219. package/dist/types/modes/components/late-diagnostics-message.d.ts +20 -0
  220. package/dist/types/modes/components/logout-account-selector.d.ts +8 -0
  221. package/dist/types/modes/components/mcp-add-wizard.d.ts +2 -1
  222. package/dist/types/modes/components/model-selector.d.ts +1 -1
  223. package/dist/types/modes/components/oauth-selector.d.ts +10 -1
  224. package/dist/types/modes/components/overlay-box.d.ts +17 -0
  225. package/dist/types/modes/components/plan-review-overlay.d.ts +61 -0
  226. package/dist/types/modes/components/plan-toc.d.ts +41 -0
  227. package/dist/types/modes/components/read-tool-group.d.ts +8 -0
  228. package/dist/types/modes/components/reset-usage-selector.d.ts +12 -0
  229. package/dist/types/modes/components/segment-track.d.ts +11 -6
  230. package/dist/types/modes/components/session-selector.d.ts +18 -9
  231. package/dist/types/modes/components/settings-defs.d.ts +9 -2
  232. package/dist/types/modes/components/settings-selector.d.ts +17 -4
  233. package/dist/types/modes/components/snapcompact-shape-preview.d.ts +31 -0
  234. package/dist/types/modes/components/status-line/component.d.ts +61 -0
  235. package/dist/types/modes/components/status-line/index.d.ts +1 -0
  236. package/dist/types/modes/components/status-line/types.d.ts +47 -3
  237. package/dist/types/modes/components/tiny-title-download-progress.d.ts +1 -1
  238. package/dist/types/modes/components/tool-execution.d.ts +49 -2
  239. package/dist/types/modes/components/transcript-container.d.ts +76 -26
  240. package/dist/types/modes/components/tree-selector.d.ts +2 -2
  241. package/dist/types/modes/components/ttsr-notification.d.ts +5 -1
  242. package/dist/types/modes/components/usage-row.d.ts +3 -0
  243. package/dist/types/modes/components/user-message-selector.d.ts +1 -1
  244. package/dist/types/modes/components/user-message.d.ts +2 -1
  245. package/dist/types/modes/components/visual-truncate.d.ts +1 -1
  246. package/dist/types/modes/components/welcome.d.ts +12 -2
  247. package/dist/types/modes/controllers/command-controller.d.ts +3 -2
  248. package/dist/types/modes/controllers/event-controller.d.ts +7 -1
  249. package/dist/types/modes/controllers/extension-ui-controller.d.ts +0 -1
  250. package/dist/types/modes/controllers/input-controller.d.ts +25 -3
  251. package/dist/types/modes/controllers/mcp-command-controller.d.ts +8 -0
  252. package/dist/types/modes/controllers/selector-controller.d.ts +5 -2
  253. package/dist/types/modes/controllers/session-focus-controller.d.ts +31 -0
  254. package/dist/types/modes/controllers/streaming-reveal.d.ts +22 -0
  255. package/dist/types/modes/controllers/tan-command-controller.d.ts +6 -0
  256. package/dist/types/modes/controllers/tool-args-reveal.d.ts +43 -0
  257. package/dist/types/modes/gradient-highlight.d.ts +9 -4
  258. package/dist/types/modes/image-references.d.ts +14 -3
  259. package/dist/types/modes/index.d.ts +8 -7
  260. package/dist/types/modes/interactive-mode.d.ts +92 -16
  261. package/dist/types/modes/magic-keywords.d.ts +14 -2
  262. package/dist/types/modes/markdown-prose.d.ts +1 -1
  263. package/dist/types/modes/oauth-manual-input.d.ts +7 -0
  264. package/dist/types/modes/rpc/rpc-client.d.ts +48 -2
  265. package/dist/types/modes/rpc/rpc-mode.d.ts +67 -2
  266. package/dist/types/modes/rpc/rpc-subagents.d.ts +24 -0
  267. package/dist/types/modes/rpc/rpc-types.d.ts +113 -1
  268. package/dist/types/modes/runtime-init.d.ts +4 -0
  269. package/dist/types/modes/session-observer-registry.d.ts +9 -0
  270. package/dist/types/modes/setup-version.d.ts +11 -0
  271. package/dist/types/modes/setup-wizard/index.d.ts +7 -2
  272. package/dist/types/modes/setup-wizard/lazy.d.ts +2 -0
  273. package/dist/types/modes/setup-wizard/scenes/sign-in.d.ts +4 -1
  274. package/dist/types/modes/setup-wizard/scenes/types.d.ts +11 -2
  275. package/dist/types/modes/setup-wizard/scenes/web-search.d.ts +6 -2
  276. package/dist/types/modes/setup-wizard/wizard-overlay.d.ts +1 -1
  277. package/dist/types/modes/theme/theme.d.ts +42 -7
  278. package/dist/types/modes/types.d.ts +62 -13
  279. package/dist/types/modes/utils/context-usage.d.ts +6 -1
  280. package/dist/types/modes/utils/copy-targets.d.ts +21 -1
  281. package/dist/types/modes/utils/ui-helpers.d.ts +4 -4
  282. package/dist/types/modes/workflow.d.ts +3 -3
  283. package/dist/types/plan-mode/approved-plan.d.ts +27 -8
  284. package/dist/types/plan-mode/plan-protection.d.ts +4 -4
  285. package/dist/types/registry/agent-lifecycle.d.ts +51 -0
  286. package/dist/types/registry/agent-registry.d.ts +33 -5
  287. package/dist/types/sdk.d.ts +46 -4
  288. package/dist/types/secrets/index.d.ts +1 -1
  289. package/dist/types/secrets/obfuscator.d.ts +9 -3
  290. package/dist/types/session/agent-session.d.ts +136 -66
  291. package/dist/types/session/agent-storage.d.ts +2 -1
  292. package/dist/types/session/auth-broker-config.d.ts +4 -0
  293. package/dist/types/session/auth-storage.d.ts +1 -1
  294. package/dist/types/session/codex-auto-reset.d.ts +111 -0
  295. package/dist/types/session/indexed-session-storage.d.ts +3 -3
  296. package/dist/types/session/messages.d.ts +26 -15
  297. package/dist/types/session/session-context.d.ts +39 -0
  298. package/dist/types/session/session-entries.d.ts +159 -0
  299. package/dist/types/session/session-history-format.d.ts +12 -0
  300. package/dist/types/session/session-listing.d.ts +69 -0
  301. package/dist/types/session/session-loader.d.ts +16 -0
  302. package/dist/types/session/session-manager.d.ts +107 -440
  303. package/dist/types/session/session-migrations.d.ts +12 -0
  304. package/dist/types/session/session-paths.d.ts +25 -0
  305. package/dist/types/session/session-persistence.d.ts +8 -0
  306. package/dist/types/session/session-storage.d.ts +11 -7
  307. package/dist/types/session/snapcompact-inline.d.ts +145 -0
  308. package/dist/types/session/snapcompact-savings-journal.d.ts +46 -0
  309. package/dist/types/session/streaming-output.d.ts +46 -0
  310. package/dist/types/session/tool-choice-queue.d.ts +6 -6
  311. package/dist/types/session/yield-queue.d.ts +10 -1
  312. package/dist/types/slash-commands/acp-builtins.d.ts +16 -0
  313. package/dist/types/slash-commands/available-commands.d.ts +34 -0
  314. package/dist/types/slash-commands/builtin-registry.d.ts +10 -0
  315. package/dist/types/slash-commands/helpers/active-oauth-account.d.ts +14 -0
  316. package/dist/types/slash-commands/helpers/logout.d.ts +15 -0
  317. package/dist/types/slash-commands/helpers/reset-usage.d.ts +27 -0
  318. package/dist/types/slash-commands/helpers/stats-dashboard.d.ts +13 -0
  319. package/dist/types/slash-commands/types.d.ts +5 -9
  320. package/dist/types/ssh/connection-manager.d.ts +8 -0
  321. package/dist/types/stt/asr-client.d.ts +90 -0
  322. package/dist/types/stt/asr-protocol.d.ts +97 -0
  323. package/dist/types/stt/asr-worker.d.ts +2 -0
  324. package/dist/types/stt/downloader.d.ts +38 -0
  325. package/dist/types/stt/endpointer.d.ts +59 -0
  326. package/dist/types/stt/index.d.ts +5 -1
  327. package/dist/types/stt/models.d.ts +120 -0
  328. package/dist/types/stt/recorder.d.ts +17 -0
  329. package/dist/types/stt/stt-controller.d.ts +6 -0
  330. package/dist/types/stt/transcriber.d.ts +5 -7
  331. package/dist/types/stt/wav.d.ts +29 -0
  332. package/dist/types/system-prompt.d.ts +9 -1
  333. package/dist/types/task/commands.d.ts +1 -1
  334. package/dist/types/task/discovery.d.ts +1 -2
  335. package/dist/types/task/executor.d.ts +61 -2
  336. package/dist/types/task/index.d.ts +37 -6
  337. package/dist/types/task/output-manager.d.ts +0 -7
  338. package/dist/types/task/parallel.d.ts +2 -2
  339. package/dist/types/task/prometheus-command.d.ts +2 -2
  340. package/dist/types/task/render.d.ts +20 -7
  341. package/dist/types/task/repair-args.d.ts +8 -7
  342. package/dist/types/task/types.d.ts +109 -52
  343. package/dist/types/task/worktree.d.ts +2 -0
  344. package/dist/types/telemetry-export.d.ts +2 -2
  345. package/dist/types/thinking.d.ts +4 -0
  346. package/dist/types/tiny/models.d.ts +1 -1
  347. package/dist/types/tiny/title-client.d.ts +12 -1
  348. package/dist/types/tiny/title-protocol.d.ts +1 -0
  349. package/dist/types/tools/archive-reader.d.ts +5 -0
  350. package/dist/types/tools/ask.d.ts +6 -1
  351. package/dist/types/tools/ast-edit.d.ts +4 -1
  352. package/dist/types/tools/ast-grep.d.ts +4 -1
  353. package/dist/types/tools/bash.d.ts +5 -2
  354. package/dist/types/tools/browser/attach.d.ts +4 -4
  355. package/dist/types/tools/browser/cmux/cmux-tab.d.ts +202 -0
  356. package/dist/types/tools/browser/cmux/rpc.d.ts +70 -0
  357. package/dist/types/tools/browser/cmux/socket-client.d.ts +19 -0
  358. package/dist/types/tools/browser/registry.d.ts +17 -3
  359. package/dist/types/tools/browser/render.d.ts +2 -0
  360. package/dist/types/tools/browser/tab-protocol.d.ts +2 -0
  361. package/dist/types/tools/browser/tab-supervisor.d.ts +16 -4
  362. package/dist/types/tools/browser/tab-worker.d.ts +18 -1
  363. package/dist/types/tools/browser.d.ts +3 -1
  364. package/dist/types/tools/checkpoint.d.ts +1 -1
  365. package/dist/types/tools/conflict-detect.d.ts +16 -0
  366. package/dist/types/tools/debug.d.ts +1 -1
  367. package/dist/types/tools/eval-render.d.ts +1 -8
  368. package/dist/types/tools/eval.d.ts +9 -1
  369. package/dist/types/tools/fetch.d.ts +17 -8
  370. package/dist/types/tools/find.d.ts +1 -8
  371. package/dist/types/tools/gh-cache-invalidation.d.ts +6 -0
  372. package/dist/types/tools/gh.d.ts +4 -1
  373. package/dist/types/tools/github-cache.d.ts +19 -0
  374. package/dist/types/tools/grouped-file-output.d.ts +46 -12
  375. package/dist/types/tools/image-gen.d.ts +1 -1
  376. package/dist/types/tools/index.d.ts +89 -8
  377. package/dist/types/tools/inspect-image.d.ts +1 -1
  378. package/dist/types/tools/irc.d.ts +79 -39
  379. package/dist/types/tools/job.d.ts +8 -2
  380. package/dist/types/tools/learn.d.ts +51 -0
  381. package/dist/types/tools/manage-skill.d.ts +40 -0
  382. package/dist/types/tools/memory-edit.d.ts +2 -2
  383. package/dist/types/tools/memory-recall.d.ts +1 -1
  384. package/dist/types/tools/memory-reflect.d.ts +1 -1
  385. package/dist/types/tools/memory-render.d.ts +4 -1
  386. package/dist/types/tools/memory-retain.d.ts +1 -1
  387. package/dist/types/tools/path-utils.d.ts +17 -5
  388. package/dist/types/tools/plan-mode-guard.d.ts +18 -9
  389. package/dist/types/tools/read.d.ts +3 -2
  390. package/dist/types/tools/render-mermaid.d.ts +1 -1
  391. package/dist/types/tools/render-utils.d.ts +47 -27
  392. package/dist/types/tools/renderers.d.ts +10 -2
  393. package/dist/types/tools/report-tool-issue.d.ts +6 -1
  394. package/dist/types/tools/resolve.d.ts +1 -1
  395. package/dist/types/tools/review.d.ts +1 -1
  396. package/dist/types/tools/search-tool-bm25.d.ts +1 -1
  397. package/dist/types/tools/search.d.ts +7 -3
  398. package/dist/types/tools/sqlite-reader.d.ts +4 -0
  399. package/dist/types/tools/ssh.d.ts +2 -1
  400. package/dist/types/tools/todo.d.ts +7 -15
  401. package/dist/types/tools/tool-result.d.ts +2 -0
  402. package/dist/types/tools/tool-timeouts.d.ts +1 -1
  403. package/dist/types/tools/tts.d.ts +26 -1
  404. package/dist/types/tools/write.d.ts +6 -3
  405. package/dist/types/tools/yield.d.ts +8 -0
  406. package/dist/types/tts/downloader.d.ts +20 -0
  407. package/dist/types/tts/index.d.ts +8 -0
  408. package/dist/types/tts/models.d.ts +82 -0
  409. package/dist/types/tts/player.d.ts +32 -0
  410. package/dist/types/tts/runtime.d.ts +6 -0
  411. package/dist/types/tts/streaming-player.d.ts +41 -0
  412. package/dist/types/tts/tts-client.d.ts +93 -0
  413. package/dist/types/tts/tts-protocol.d.ts +95 -0
  414. package/dist/types/tts/tts-worker.d.ts +2 -0
  415. package/dist/types/tts/vocalizer.d.ts +41 -0
  416. package/dist/types/tts/wav.d.ts +8 -0
  417. package/dist/types/tui/code-cell.d.ts +0 -2
  418. package/dist/types/tui/hyperlink.d.ts +13 -7
  419. package/dist/types/tui/output-block.d.ts +16 -22
  420. package/dist/types/tui/status-line.d.ts +3 -0
  421. package/dist/types/utils/block-context.d.ts +35 -0
  422. package/dist/types/utils/changelog.d.ts +8 -0
  423. package/dist/types/utils/clipboard.d.ts +4 -3
  424. package/dist/types/utils/enhanced-paste.d.ts +20 -0
  425. package/dist/types/utils/file-mentions.d.ts +7 -0
  426. package/dist/types/utils/git.d.ts +22 -3
  427. package/dist/types/utils/image-loading.d.ts +30 -1
  428. package/dist/types/utils/session-color.d.ts +15 -3
  429. package/dist/types/utils/thinking-display.d.ts +17 -0
  430. package/dist/types/utils/title-generator.d.ts +3 -2
  431. package/dist/types/utils/tool-choice.d.ts +8 -0
  432. package/dist/types/utils/tools-manager.d.ts +2 -1
  433. package/dist/types/web/kagi.d.ts +2 -2
  434. package/dist/types/web/parallel.d.ts +3 -0
  435. package/dist/types/web/scrapers/github.d.ts +22 -0
  436. package/dist/types/web/scrapers/readthedocs.d.ts +3 -0
  437. package/dist/types/web/scrapers/types.d.ts +12 -0
  438. package/dist/types/web/search/index.d.ts +1 -1
  439. package/dist/types/web/search/providers/anthropic.d.ts +2 -1
  440. package/dist/types/web/search/providers/base.d.ts +2 -1
  441. package/dist/types/web/search/providers/brave.d.ts +2 -1
  442. package/dist/types/web/search/providers/codex.d.ts +2 -1
  443. package/dist/types/web/search/providers/exa.d.ts +2 -1
  444. package/dist/types/web/search/providers/gemini.d.ts +10 -6
  445. package/dist/types/web/search/providers/jina.d.ts +7 -2
  446. package/dist/types/web/search/providers/kagi.d.ts +7 -2
  447. package/dist/types/web/search/providers/kimi.d.ts +7 -2
  448. package/dist/types/web/search/providers/parallel.d.ts +2 -1
  449. package/dist/types/web/search/providers/perplexity.d.ts +10 -2
  450. package/dist/types/web/search/providers/searxng.d.ts +2 -1
  451. package/dist/types/web/search/providers/synthetic.d.ts +7 -3
  452. package/dist/types/web/search/providers/tavily.d.ts +2 -1
  453. package/dist/types/web/search/providers/zai.d.ts +2 -1
  454. package/dist/types/web/search/types.d.ts +1 -1
  455. package/examples/extensions/api-demo.ts +2 -2
  456. package/package.json +41 -15
  457. package/scripts/bench-guard.ts +71 -0
  458. package/scripts/build-binary.ts +24 -25
  459. package/scripts/bundle-dist.ts +97 -0
  460. package/scripts/generate-share-viewer.ts +34 -0
  461. package/scripts/prometheus +42 -0
  462. package/scripts/prometheus.ts +20 -0
  463. package/src/async/index.ts +0 -1
  464. package/src/async/job-manager.ts +106 -3
  465. package/src/auto-thinking/classifier.ts +2 -1
  466. package/src/autolearn/controller.ts +139 -0
  467. package/src/autolearn/managed-skills.ts +257 -0
  468. package/src/autoresearch/dashboard.ts +1 -1
  469. package/src/autoresearch/prompt-setup.md +6 -6
  470. package/src/autoresearch/prompt.md +6 -6
  471. package/src/autoresearch/state.ts +1 -1
  472. package/src/autoresearch/storage.ts +2 -1
  473. package/src/autoresearch/tools/init-experiment.ts +1 -1
  474. package/src/autoresearch/tools/log-experiment.ts +1 -1
  475. package/src/autoresearch/tools/run-experiment.ts +1 -1
  476. package/src/autoresearch/tools/update-notes.ts +1 -1
  477. package/src/autoresearch/types.ts +1 -1
  478. package/src/capability/context-file.ts +0 -14
  479. package/src/capability/fs.ts +10 -0
  480. package/src/capability/index.ts +1 -6
  481. package/src/capability/mcp.ts +1 -0
  482. package/src/capability/rule-buckets.ts +4 -2
  483. package/src/capability/rule.ts +10 -1
  484. package/src/capability/types.ts +0 -4
  485. package/src/cli/args.ts +66 -13
  486. package/src/cli/auth-broker-cli.ts +6 -7
  487. package/src/cli/auth-gateway-cli.ts +8 -9
  488. package/src/cli/bench-cli.ts +437 -0
  489. package/src/cli/claude-trace-cli.ts +28 -50
  490. package/src/cli/completion-gen.ts +28 -28
  491. package/src/cli/dry-balance-cli.ts +56 -23
  492. package/src/cli/gallery-cli.ts +231 -0
  493. package/src/cli/gallery-fixtures/agentic.ts +407 -0
  494. package/src/cli/gallery-fixtures/codeintel.ts +187 -0
  495. package/src/cli/gallery-fixtures/edit.ts +194 -0
  496. package/src/cli/gallery-fixtures/fs.ts +220 -0
  497. package/src/cli/gallery-fixtures/index.ts +40 -0
  498. package/src/cli/gallery-fixtures/interaction.ts +49 -0
  499. package/src/cli/gallery-fixtures/memory.ts +81 -0
  500. package/src/cli/gallery-fixtures/misc.ts +250 -0
  501. package/src/cli/gallery-fixtures/search.ts +213 -0
  502. package/src/cli/gallery-fixtures/shell.ts +167 -0
  503. package/src/cli/gallery-fixtures/types.ts +57 -0
  504. package/src/cli/gallery-fixtures/web.ts +158 -0
  505. package/src/cli/gallery-screenshot.ts +279 -0
  506. package/src/cli/gateway-cli.ts +32 -2
  507. package/src/cli/grievances-cli.ts +1 -1
  508. package/src/cli/list-models.ts +16 -174
  509. package/src/cli/models-cli.ts +429 -0
  510. package/src/cli/session-picker.ts +2 -1
  511. package/src/cli/setup-cli.ts +148 -47
  512. package/src/cli/setup-model-picker.ts +43 -0
  513. package/src/cli/startup-cwd.ts +68 -0
  514. package/src/cli/update-cli.ts +144 -272
  515. package/src/cli/usage-cli.ts +774 -0
  516. package/src/cli-commands.ts +36 -0
  517. package/src/cli.ts +141 -32
  518. package/src/collab/crypto.ts +63 -0
  519. package/src/collab/guest.ts +451 -0
  520. package/src/collab/host.ts +565 -0
  521. package/src/collab/protocol.ts +241 -0
  522. package/src/collab/relay-client.ts +216 -0
  523. package/src/commands/bench.ts +42 -0
  524. package/src/commands/complete.ts +1 -1
  525. package/src/commands/gallery.ts +52 -0
  526. package/src/commands/gateway.ts +4 -0
  527. package/src/commands/install.ts +1 -1
  528. package/src/commands/join.ts +39 -0
  529. package/src/commands/launch.ts +8 -4
  530. package/src/commands/models.ts +61 -0
  531. package/src/commands/read.ts +6 -3
  532. package/src/commands/say.ts +102 -0
  533. package/src/commands/setup.ts +1 -1
  534. package/src/commands/token.ts +89 -0
  535. package/src/commands/usage.ts +43 -0
  536. package/src/commit/agentic/agent.ts +2 -1
  537. package/src/commit/agentic/tools/analyze-file.ts +42 -20
  538. package/src/commit/agentic/tools/git-file-diff.ts +1 -1
  539. package/src/commit/agentic/tools/git-hunk.ts +1 -1
  540. package/src/commit/agentic/tools/git-overview.ts +1 -1
  541. package/src/commit/agentic/tools/propose-changelog.ts +1 -1
  542. package/src/commit/agentic/tools/propose-commit.ts +1 -1
  543. package/src/commit/agentic/tools/recent-commits.ts +1 -1
  544. package/src/commit/agentic/tools/schemas.ts +1 -1
  545. package/src/commit/agentic/tools/split-commit.ts +9 -2
  546. package/src/commit/analysis/conventional.ts +2 -2
  547. package/src/commit/analysis/summary.ts +3 -3
  548. package/src/commit/changelog/generate.ts +3 -3
  549. package/src/commit/changelog/index.ts +2 -2
  550. package/src/commit/map-reduce/index.ts +3 -3
  551. package/src/commit/map-reduce/map-phase.ts +2 -2
  552. package/src/commit/map-reduce/reduce-phase.ts +2 -2
  553. package/src/commit/model-selection.ts +35 -12
  554. package/src/commit/pipeline.ts +4 -4
  555. package/src/commit/shared-llm.ts +1 -1
  556. package/src/config/api-key-resolver.ts +67 -0
  557. package/src/config/append-only-context-mode.ts +6 -12
  558. package/src/config/keybindings.ts +9 -4
  559. package/src/config/mcp-schema.json +4 -0
  560. package/src/config/model-discovery.ts +574 -0
  561. package/src/config/model-equivalence.ts +5 -4
  562. package/src/config/model-registry.ts +659 -1093
  563. package/src/config/model-resolver.ts +374 -174
  564. package/src/config/model-roles.ts +88 -0
  565. package/src/config/models-config-schema.ts +61 -9
  566. package/src/config/models-config.ts +130 -0
  567. package/src/config/settings-schema.ts +1445 -382
  568. package/src/config/settings.ts +261 -69
  569. package/src/dap/client.ts +138 -53
  570. package/src/dap/config.ts +41 -2
  571. package/src/dap/defaults.json +1 -0
  572. package/src/dap/session.ts +263 -161
  573. package/src/dap/types.ts +10 -0
  574. package/src/debug/index.ts +50 -60
  575. package/src/debug/log-viewer.ts +1 -1
  576. package/src/debug/protocol-probe.ts +1 -1
  577. package/src/debug/raw-sse-buffer.ts +7 -4
  578. package/src/debug/raw-sse.ts +1 -1
  579. package/src/debug/report-bundle.ts +9 -0
  580. package/src/debug/terminal-info.ts +0 -3
  581. package/src/discovery/agents-md.ts +25 -21
  582. package/src/discovery/agents.ts +9 -15
  583. package/src/discovery/at-imports.ts +273 -0
  584. package/src/discovery/builtin-rules/index.ts +4 -0
  585. package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
  586. package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
  587. package/src/discovery/builtin.ts +45 -23
  588. package/src/discovery/claude-plugins.ts +44 -5
  589. package/src/discovery/helpers.ts +50 -9
  590. package/src/discovery/prometheus-extension-roots.ts +10 -10
  591. package/src/discovery/prometheus-plugins.ts +10 -10
  592. package/src/edit/diff.ts +191 -4
  593. package/src/edit/file-snapshot-store.ts +34 -1
  594. package/src/edit/hashline/block-resolver.ts +20 -1
  595. package/src/edit/hashline/diff.ts +123 -2
  596. package/src/edit/hashline/execute.ts +60 -4
  597. package/src/edit/hashline/filesystem.ts +2 -1
  598. package/src/edit/hashline/noop-loop-guard.ts +99 -0
  599. package/src/edit/hashline/params.ts +1 -1
  600. package/src/edit/index.ts +47 -18
  601. package/src/edit/modes/apply-patch.ts +1 -1
  602. package/src/edit/modes/patch.ts +59 -3
  603. package/src/edit/modes/replace.ts +58 -24
  604. package/src/edit/notebook.ts +22 -2
  605. package/src/edit/renderer.ts +315 -151
  606. package/src/eval/__tests__/agent-bridge.test.ts +105 -39
  607. package/src/eval/__tests__/budget-bridge.test.ts +1 -1
  608. package/src/eval/__tests__/completion-bridge.test.ts +412 -0
  609. package/src/eval/__tests__/helpers-local-roots.test.ts +58 -0
  610. package/src/eval/__tests__/js-context-manager.test.ts +241 -0
  611. package/src/eval/__tests__/llm-bridge.test.ts +6 -4
  612. package/src/eval/__tests__/shared-executors.test.ts +34 -92
  613. package/src/eval/agent-bridge.ts +39 -23
  614. package/src/eval/backend.ts +15 -2
  615. package/src/eval/bridge-timeout.ts +1 -1
  616. package/src/eval/completion-bridge.ts +203 -0
  617. package/src/eval/idle-timeout.ts +3 -10
  618. package/src/eval/js/context-manager.ts +108 -31
  619. package/src/eval/js/executor.ts +9 -2
  620. package/src/eval/js/index.ts +7 -3
  621. package/src/eval/js/shared/helpers.ts +59 -13
  622. package/src/eval/js/shared/local-module-loader.ts +2 -2
  623. package/src/eval/js/shared/prelude.txt +167 -30
  624. package/src/eval/js/shared/rewrite-imports.ts +58 -34
  625. package/src/eval/js/shared/runtime.ts +24 -16
  626. package/src/eval/js/tool-bridge.ts +4 -0
  627. package/src/eval/js/worker-core.ts +1 -0
  628. package/src/eval/js/worker-entry.ts +6 -0
  629. package/src/eval/js/worker-protocol.ts +6 -0
  630. package/src/eval/llm-bridge.ts +2 -1
  631. package/src/eval/py/__tests__/prelude.test.ts +19 -0
  632. package/src/eval/py/executor.ts +70 -26
  633. package/src/eval/py/index.ts +13 -4
  634. package/src/eval/py/kernel.ts +48 -9
  635. package/src/eval/py/prelude.py +73 -24
  636. package/src/eval/py/runner.py +133 -28
  637. package/src/eval/py/runtime.ts +38 -1
  638. package/src/exa/index.ts +1 -26
  639. package/src/exa/mcp-client.ts +10 -10
  640. package/src/exa/types.ts +0 -97
  641. package/src/exec/bash-executor.ts +104 -7
  642. package/src/export/custom-share.ts +1 -1
  643. package/src/export/html/index.ts +119 -17
  644. package/src/export/html/share-loader.js +102 -0
  645. package/src/export/html/template-js.ts +6 -0
  646. package/src/export/html/template.css +745 -459
  647. package/src/export/html/template.css.d.ts +2 -0
  648. package/src/export/html/template.html +6 -3
  649. package/src/export/html/template.js +277 -891
  650. package/src/export/html/tool-views.generated.d.ts +2 -0
  651. package/src/export/html/tool-views.generated.js +38 -0
  652. package/src/export/share.ts +269 -0
  653. package/src/export/ttsr.ts +122 -1
  654. package/src/extensibility/custom-commands/loader.ts +7 -4
  655. package/src/extensibility/custom-commands/types.ts +9 -4
  656. package/src/extensibility/custom-tools/loader.ts +51 -23
  657. package/src/extensibility/custom-tools/types.ts +16 -8
  658. package/src/extensibility/extensions/get-commands-handler.ts +2 -1
  659. package/src/extensibility/extensions/index.ts +1 -0
  660. package/src/extensibility/extensions/loader.ts +70 -20
  661. package/src/extensibility/extensions/model-api.ts +41 -0
  662. package/src/extensibility/extensions/runner.ts +12 -2
  663. package/src/extensibility/extensions/types.ts +83 -11
  664. package/src/extensibility/extensions/wrapper.ts +41 -5
  665. package/src/extensibility/hooks/index.ts +2 -1
  666. package/src/extensibility/hooks/loader.ts +6 -3
  667. package/src/extensibility/hooks/types.ts +11 -5
  668. package/src/extensibility/{legacy-pi-ai-shim.ts → legacy-package-ai-shim.ts} +2 -2
  669. package/src/extensibility/plugins/doctor.ts +1 -2
  670. package/src/extensibility/plugins/installer.ts +2 -2
  671. package/src/extensibility/plugins/{legacy-pi-compat.ts → legacy-package-compat.ts} +165 -77
  672. package/src/extensibility/plugins/loader.ts +34 -23
  673. package/src/extensibility/plugins/manager.ts +226 -95
  674. package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
  675. package/src/extensibility/plugins/types.ts +3 -3
  676. package/src/extensibility/shared-events.ts +3 -3
  677. package/src/extensibility/skills.ts +113 -9
  678. package/src/extensibility/slash-commands.ts +1 -97
  679. package/src/gateway/adapters/telegram/access.ts +39 -4
  680. package/src/gateway/adapters/telegram/normalize.ts +16 -1
  681. package/src/gateway/adapters/telegram/setup-api.ts +7 -1
  682. package/src/gateway/adapters/telegram/webhook.ts +26 -5
  683. package/src/gateway/context.ts +9 -1
  684. package/src/gateway/types.ts +1 -1
  685. package/src/goals/guided-setup.ts +133 -0
  686. package/src/goals/state.ts +1 -1
  687. package/src/goals/tools/goal-tool.ts +38 -28
  688. package/src/hindsight/bank.ts +17 -2
  689. package/src/hindsight/client.ts +27 -2
  690. package/src/hindsight/mental-models.ts +59 -12
  691. package/src/hindsight/state.ts +12 -3
  692. package/src/hindsight/transcript.ts +1 -1
  693. package/src/index.ts +5 -0
  694. package/src/internal-urls/artifact-protocol.ts +11 -2
  695. package/src/internal-urls/docs-index.generated.ts +11 -9
  696. package/src/internal-urls/history-protocol.ts +113 -0
  697. package/src/internal-urls/index.ts +1 -0
  698. package/src/internal-urls/issue-pr-protocol.ts +22 -9
  699. package/src/internal-urls/local-protocol.ts +42 -7
  700. package/src/internal-urls/memory-protocol.ts +4 -31
  701. package/src/internal-urls/router.ts +3 -1
  702. package/src/internal-urls/types.ts +1 -1
  703. package/src/irc/bus.ts +303 -0
  704. package/src/lib/xai-http.ts +3 -3
  705. package/src/lsp/client.ts +245 -104
  706. package/src/lsp/clients/biome-client.ts +101 -39
  707. package/src/lsp/clients/lsp-linter-client.ts +2 -10
  708. package/src/lsp/config.ts +15 -5
  709. package/src/lsp/defaults.json +6 -0
  710. package/src/lsp/edits.ts +143 -95
  711. package/src/lsp/format-options.ts +119 -0
  712. package/src/lsp/index.ts +233 -93
  713. package/src/lsp/render.ts +11 -35
  714. package/src/lsp/types.ts +13 -1
  715. package/src/lsp/utils.ts +31 -12
  716. package/src/main.ts +396 -216
  717. package/src/mcp/config-writer.ts +7 -3
  718. package/src/mcp/json-rpc.ts +35 -5
  719. package/src/mcp/manager.ts +31 -16
  720. package/src/mcp/oauth-discovery.ts +34 -4
  721. package/src/mcp/oauth-flow.ts +61 -8
  722. package/src/mcp/render.ts +7 -1
  723. package/src/mcp/startup-events.ts +21 -0
  724. package/src/mcp/tool-bridge.ts +2 -0
  725. package/src/mcp/transports/stdio.ts +224 -4
  726. package/src/mcp/types.ts +2 -0
  727. package/src/memories/index.ts +174 -1128
  728. package/src/memories/storage.ts +2 -41
  729. package/src/memory-backend/index.ts +14 -1
  730. package/src/memory-backend/local-backend.ts +18 -3
  731. package/src/memory-backend/off-backend.ts +9 -0
  732. package/src/memory-backend/resolve.ts +4 -6
  733. package/src/memory-backend/runtime.ts +66 -0
  734. package/src/memory-backend/types.ts +82 -2
  735. package/src/mnemopi/backend.ts +220 -28
  736. package/src/mnemopi/config.ts +138 -33
  737. package/src/mnemopi/state.ts +91 -11
  738. package/src/modes/acp/acp-agent.ts +149 -142
  739. package/src/modes/acp/acp-event-mapper.ts +5 -1
  740. package/src/modes/components/agent-dashboard.ts +17 -11
  741. package/src/modes/components/agent-hub.ts +1346 -0
  742. package/src/modes/components/assistant-message.ts +190 -80
  743. package/src/modes/components/bash-execution.ts +1 -1
  744. package/src/modes/components/btw-panel.ts +5 -1
  745. package/src/modes/components/chat-block.ts +111 -0
  746. package/src/modes/components/collab-prompt-message.ts +30 -0
  747. package/src/modes/components/compaction-summary-message.ts +168 -33
  748. package/src/modes/components/copy-selector.ts +2 -45
  749. package/src/modes/components/custom-editor.test.ts +96 -0
  750. package/src/modes/components/custom-editor.ts +405 -118
  751. package/src/modes/components/custom-message.ts +1 -3
  752. package/src/modes/components/diff.ts +13 -2
  753. package/src/modes/components/dynamic-border.ts +12 -3
  754. package/src/modes/components/execution-shared.ts +1 -2
  755. package/src/modes/components/extensions/extension-dashboard.ts +8 -5
  756. package/src/modes/components/extensions/extension-list.ts +1 -1
  757. package/src/modes/components/extensions/inspector-panel.ts +7 -3
  758. package/src/modes/components/extensions/state-manager.ts +36 -41
  759. package/src/modes/components/footer.ts +4 -2
  760. package/src/modes/components/history-search.ts +1 -1
  761. package/src/modes/components/hook-editor.ts +8 -0
  762. package/src/modes/components/hook-input.ts +8 -0
  763. package/src/modes/components/hook-message.ts +1 -3
  764. package/src/modes/components/hook-selector.ts +6 -7
  765. package/src/modes/components/index.ts +1 -0
  766. package/src/modes/components/late-diagnostics-message.ts +60 -0
  767. package/src/modes/components/login-dialog.ts +1 -1
  768. package/src/modes/components/logout-account-selector.ts +130 -0
  769. package/src/modes/components/mcp-add-wizard.ts +14 -1
  770. package/src/modes/components/model-selector.ts +177 -75
  771. package/src/modes/components/oauth-selector.ts +102 -16
  772. package/src/modes/components/overlay-box.ts +108 -0
  773. package/src/modes/components/plan-review-overlay.ts +845 -0
  774. package/src/modes/components/plan-toc.ts +138 -0
  775. package/src/modes/components/plugin-settings.ts +22 -5
  776. package/src/modes/components/read-tool-group.ts +442 -39
  777. package/src/modes/components/reset-usage-selector.ts +161 -0
  778. package/src/modes/components/segment-track.ts +44 -7
  779. package/src/modes/components/session-selector.ts +97 -37
  780. package/src/modes/components/settings-defs.ts +28 -6
  781. package/src/modes/components/settings-selector.ts +541 -93
  782. package/src/modes/components/skill-message.ts +0 -1
  783. package/src/modes/components/snapcompact-shape-preview-doc.md +11 -0
  784. package/src/modes/components/snapcompact-shape-preview.ts +193 -0
  785. package/src/modes/components/{status-line.ts → status-line/component.ts} +205 -168
  786. package/src/modes/components/status-line/index.ts +1 -0
  787. package/src/modes/components/status-line/presets.ts +3 -3
  788. package/src/modes/components/status-line/segments.ts +26 -7
  789. package/src/modes/components/status-line/types.ts +40 -9
  790. package/src/modes/components/tiny-title-download-progress.ts +1 -1
  791. package/src/modes/components/tips.txt +7 -3
  792. package/src/modes/components/todo-reminder.ts +0 -2
  793. package/src/modes/components/tool-execution.ts +236 -103
  794. package/src/modes/components/transcript-container.ts +724 -99
  795. package/src/modes/components/tree-selector.ts +19 -4
  796. package/src/modes/components/ttsr-notification.ts +72 -30
  797. package/src/modes/components/usage-row.ts +18 -0
  798. package/src/modes/components/user-message-selector.ts +1 -1
  799. package/src/modes/components/user-message.ts +28 -12
  800. package/src/modes/components/visual-truncate.ts +1 -1
  801. package/src/modes/components/welcome.ts +80 -22
  802. package/src/modes/controllers/command-controller-shared.ts +7 -6
  803. package/src/modes/controllers/command-controller.ts +210 -180
  804. package/src/modes/controllers/event-controller.ts +352 -142
  805. package/src/modes/controllers/extension-ui-controller.ts +167 -208
  806. package/src/modes/controllers/input-controller.ts +778 -162
  807. package/src/modes/controllers/mcp-command-controller.ts +232 -80
  808. package/src/modes/controllers/selector-controller.ts +284 -145
  809. package/src/modes/controllers/session-focus-controller.ts +112 -0
  810. package/src/modes/controllers/ssh-command-controller.ts +2 -2
  811. package/src/modes/controllers/streaming-reveal.ts +295 -0
  812. package/src/modes/controllers/tan-command-controller.ts +173 -0
  813. package/src/modes/controllers/tool-args-reveal.ts +174 -0
  814. package/src/modes/gradient-highlight.ts +21 -9
  815. package/src/modes/image-references.ts +33 -7
  816. package/src/modes/index.ts +8 -25
  817. package/src/modes/interactive-mode.ts +840 -186
  818. package/src/modes/magic-keywords.ts +28 -6
  819. package/src/modes/markdown-prose.ts +1 -1
  820. package/src/modes/oauth-manual-input.ts +30 -3
  821. package/src/modes/rpc/rpc-client.ts +186 -3
  822. package/src/modes/rpc/rpc-mode.ts +318 -24
  823. package/src/modes/rpc/rpc-subagents.ts +265 -0
  824. package/src/modes/rpc/rpc-types.ts +111 -2
  825. package/src/modes/runtime-init.ts +28 -3
  826. package/src/modes/session-observer-registry.ts +72 -3
  827. package/src/modes/setup-version.ts +11 -0
  828. package/src/modes/setup-wizard/index.ts +16 -4
  829. package/src/modes/setup-wizard/lazy.ts +16 -0
  830. package/src/modes/setup-wizard/scenes/glyph.ts +25 -7
  831. package/src/modes/setup-wizard/scenes/providers.ts +45 -12
  832. package/src/modes/setup-wizard/scenes/sign-in.ts +14 -13
  833. package/src/modes/setup-wizard/scenes/splash.ts +1 -1
  834. package/src/modes/setup-wizard/scenes/telegram.ts +77 -22
  835. package/src/modes/setup-wizard/scenes/theme.ts +29 -2
  836. package/src/modes/setup-wizard/scenes/types.ts +11 -2
  837. package/src/modes/setup-wizard/scenes/web-search.ts +26 -9
  838. package/src/modes/setup-wizard/wizard-overlay.ts +40 -3
  839. package/src/modes/shared.ts +2 -0
  840. package/src/modes/theme/defaults/dark-poimandres.json +1 -1
  841. package/src/modes/theme/defaults/light-poimandres.json +1 -1
  842. package/src/modes/theme/shimmer.ts +20 -9
  843. package/src/modes/theme/theme-schema.json +1 -1
  844. package/src/modes/theme/theme.ts +342 -82
  845. package/src/modes/types.ts +60 -18
  846. package/src/modes/utils/context-usage.ts +88 -8
  847. package/src/modes/utils/copy-targets.ts +133 -27
  848. package/src/modes/utils/hotkeys-markdown.ts +3 -2
  849. package/src/modes/utils/ui-helpers.ts +191 -110
  850. package/src/modes/workflow.ts +10 -10
  851. package/src/plan-mode/approved-plan.ts +66 -43
  852. package/src/plan-mode/plan-protection.ts +4 -4
  853. package/src/priority.json +5 -1
  854. package/src/prompts/agents/designer.md +1 -1
  855. package/src/prompts/agents/explore.md +3 -3
  856. package/src/prompts/agents/librarian.md +2 -3
  857. package/src/prompts/agents/oracle.md +2 -2
  858. package/src/prompts/agents/plan.md +6 -6
  859. package/src/prompts/agents/reviewer.md +1 -1
  860. package/src/prompts/agents/task.md +6 -5
  861. package/src/prompts/bench.md +12 -0
  862. package/src/prompts/ci-green-request.md +5 -7
  863. package/src/prompts/goals/goal-budget-limit.md +2 -2
  864. package/src/prompts/goals/goal-continuation.md +4 -4
  865. package/src/prompts/goals/goal-mode-active.md +1 -1
  866. package/src/prompts/goals/guided-goal-interview.md +8 -0
  867. package/src/prompts/goals/guided-goal-system.md +12 -0
  868. package/src/prompts/memories/consolidation.md +2 -7
  869. package/src/prompts/memories/consolidation_system.md +4 -0
  870. package/src/prompts/memories/identity_review.md +2 -2
  871. package/src/prompts/memories/read-path.md +11 -10
  872. package/src/prompts/memories/stage_one_system.md +2 -2
  873. package/src/prompts/review-custom-request.md +1 -1
  874. package/src/prompts/system/agent-creation-architect.md +2 -2
  875. package/src/prompts/system/auto-continue.md +1 -1
  876. package/src/prompts/system/autolearn-guidance-learn.md +1 -0
  877. package/src/prompts/system/autolearn-guidance.md +7 -0
  878. package/src/prompts/system/autolearn-nudge.md +3 -0
  879. package/src/prompts/system/background-tan-dispatch.md +8 -0
  880. package/src/prompts/system/btw-user.md +2 -2
  881. package/src/prompts/system/commit-message-system.md +13 -1
  882. package/src/prompts/system/custom-system-prompt.md +1 -1
  883. package/src/prompts/system/eager-task.md +7 -0
  884. package/src/prompts/system/eager-todo.md +11 -6
  885. package/src/prompts/system/empty-stop-retry.md +4 -6
  886. package/src/prompts/system/irc-autoreply.md +6 -0
  887. package/src/prompts/system/irc-incoming.md +3 -4
  888. package/src/prompts/system/manual-continue.md +7 -0
  889. package/src/prompts/system/omfg-user.md +3 -4
  890. package/src/prompts/system/orchestrate-notice.md +10 -10
  891. package/src/prompts/system/personalities/default.md +26 -0
  892. package/src/prompts/system/personalities/friendly.md +17 -0
  893. package/src/prompts/system/personalities/pragmatic.md +15 -0
  894. package/src/prompts/system/plan-mode-active.md +70 -77
  895. package/src/prompts/system/plan-mode-approved.md +1 -1
  896. package/src/prompts/system/plan-mode-subagent.md +4 -5
  897. package/src/prompts/system/plan-mode-tool-decision-reminder.md +1 -1
  898. package/src/prompts/system/project-prompt.md +2 -2
  899. package/src/prompts/system/snapcompact-context-frames-note.md +1 -0
  900. package/src/prompts/system/snapcompact-context-stub.md +1 -0
  901. package/src/prompts/system/snapcompact-system-frames-note.md +1 -0
  902. package/src/prompts/system/snapcompact-system-stub.md +1 -0
  903. package/src/prompts/system/snapcompact-toolresult-note.md +1 -0
  904. package/src/prompts/system/subagent-system-prompt.md +7 -8
  905. package/src/prompts/system/system-prompt.md +28 -57
  906. package/src/prompts/system/tiny-title-system.md +1 -1
  907. package/src/prompts/system/title-marker-instruction.md +1 -0
  908. package/src/prompts/system/title-system-marker.md +16 -0
  909. package/src/prompts/system/title-system.md +16 -3
  910. package/src/prompts/system/ttsr-tool-reminder.md +1 -1
  911. package/src/prompts/system/workflow-notice.md +4 -4
  912. package/src/prompts/tools/ast-edit.md +1 -1
  913. package/src/prompts/tools/ast-grep.md +2 -2
  914. package/src/prompts/tools/bash.md +16 -8
  915. package/src/prompts/tools/browser.md +33 -43
  916. package/src/prompts/tools/debug.md +1 -1
  917. package/src/prompts/tools/eval.md +31 -51
  918. package/src/prompts/tools/find.md +0 -1
  919. package/src/prompts/tools/github.md +8 -7
  920. package/src/prompts/tools/goal.md +1 -1
  921. package/src/prompts/tools/image-gen.md +1 -1
  922. package/src/prompts/tools/inspect-image-system.md +1 -1
  923. package/src/prompts/tools/irc.md +39 -31
  924. package/src/prompts/tools/job.md +2 -1
  925. package/src/prompts/tools/learn.md +7 -0
  926. package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
  927. package/src/prompts/tools/lsp.md +2 -2
  928. package/src/prompts/tools/manage-skill.md +9 -0
  929. package/src/prompts/tools/memory-edit.md +1 -1
  930. package/src/prompts/tools/patch.md +2 -2
  931. package/src/prompts/tools/read.md +31 -39
  932. package/src/prompts/tools/recall.md +1 -1
  933. package/src/prompts/tools/reflect.md +1 -1
  934. package/src/prompts/tools/render-mermaid.md +2 -2
  935. package/src/prompts/tools/replace.md +4 -10
  936. package/src/prompts/tools/rewind.md +2 -2
  937. package/src/prompts/tools/search-tool-bm25.md +1 -9
  938. package/src/prompts/tools/search.md +0 -1
  939. package/src/prompts/tools/ssh.md +0 -4
  940. package/src/prompts/tools/task-summary.md +5 -16
  941. package/src/prompts/tools/task.md +47 -31
  942. package/src/prompts/tools/todo.md +6 -3
  943. package/src/registry/agent-lifecycle.ts +218 -0
  944. package/src/registry/agent-registry.ts +46 -5
  945. package/src/sdk.ts +692 -219
  946. package/src/secrets/index.ts +8 -1
  947. package/src/secrets/obfuscator.ts +40 -19
  948. package/src/session/agent-session.ts +1577 -806
  949. package/src/session/agent-storage.ts +18 -9
  950. package/src/session/auth-broker-config.ts +30 -1
  951. package/src/session/auth-storage.ts +6 -0
  952. package/src/session/codex-auto-reset.ts +202 -0
  953. package/src/session/history-storage.ts +3 -2
  954. package/src/session/indexed-session-storage.ts +7 -10
  955. package/src/session/messages.ts +59 -95
  956. package/src/session/session-context.ts +352 -0
  957. package/src/session/session-dump-format.ts +12 -3
  958. package/src/session/session-entries.ts +194 -0
  959. package/src/session/session-history-format.ts +246 -0
  960. package/src/session/session-listing.ts +588 -0
  961. package/src/session/session-loader.ts +106 -0
  962. package/src/session/session-manager.ts +1003 -2920
  963. package/src/session/session-migrations.ts +78 -0
  964. package/src/session/session-paths.ts +193 -0
  965. package/src/session/session-persistence.ts +131 -0
  966. package/src/session/session-storage.ts +91 -30
  967. package/src/session/snapcompact-inline.ts +542 -0
  968. package/src/session/snapcompact-savings-journal.ts +113 -0
  969. package/src/session/streaming-output.ts +248 -11
  970. package/src/session/tool-choice-queue.ts +23 -11
  971. package/src/session/yield-queue.ts +20 -2
  972. package/src/slash-commands/acp-builtins.ts +25 -1
  973. package/src/slash-commands/available-commands.ts +105 -0
  974. package/src/slash-commands/builtin-registry.ts +575 -49
  975. package/src/slash-commands/helpers/active-oauth-account.ts +44 -0
  976. package/src/slash-commands/helpers/context-report.ts +28 -1
  977. package/src/slash-commands/helpers/logout.ts +88 -0
  978. package/src/slash-commands/helpers/reset-usage.ts +66 -0
  979. package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
  980. package/src/slash-commands/helpers/usage-report.ts +38 -3
  981. package/src/slash-commands/types.ts +5 -9
  982. package/src/ssh/connection-manager.ts +27 -0
  983. package/src/ssh/ssh-executor.ts +60 -4
  984. package/src/stt/asr-client.ts +520 -0
  985. package/src/stt/asr-protocol.ts +65 -0
  986. package/src/stt/asr-worker.ts +790 -0
  987. package/src/stt/downloader.ts +107 -47
  988. package/src/stt/endpointer.ts +259 -0
  989. package/src/stt/index.ts +5 -1
  990. package/src/stt/models.ts +150 -0
  991. package/src/stt/recorder.ts +254 -67
  992. package/src/stt/stt-controller.ts +201 -22
  993. package/src/stt/transcriber.ts +37 -68
  994. package/src/stt/wav.ts +173 -0
  995. package/src/system-prompt.ts +52 -10
  996. package/src/task/agents.ts +3 -4
  997. package/src/task/commands.ts +3 -2
  998. package/src/task/discovery.ts +17 -24
  999. package/src/task/executor.ts +1054 -529
  1000. package/src/task/index.ts +862 -757
  1001. package/src/task/output-manager.ts +0 -11
  1002. package/src/task/parallel.ts +3 -3
  1003. package/src/task/prometheus-command.ts +2 -2
  1004. package/src/task/render.ts +529 -182
  1005. package/src/task/repair-args.ts +21 -9
  1006. package/src/task/types.ts +144 -66
  1007. package/src/task/worktree.ts +64 -56
  1008. package/src/telemetry-export.ts +27 -9
  1009. package/src/thinking.ts +9 -7
  1010. package/src/tiny/models.ts +2 -2
  1011. package/src/tiny/text.ts +5 -1
  1012. package/src/tiny/title-client.ts +72 -20
  1013. package/src/tiny/title-protocol.ts +1 -1
  1014. package/src/tiny/worker.ts +23 -99
  1015. package/src/tool-discovery/tool-index.ts +2 -0
  1016. package/src/tools/archive-reader.ts +94 -2
  1017. package/src/tools/ask.ts +234 -177
  1018. package/src/tools/ast-edit.ts +136 -80
  1019. package/src/tools/ast-grep.ts +41 -45
  1020. package/src/tools/auto-generated-guard.ts +20 -3
  1021. package/src/tools/bash-interactive.ts +28 -8
  1022. package/src/tools/bash.ts +198 -35
  1023. package/src/tools/browser/attach.ts +26 -7
  1024. package/src/tools/browser/cmux/cmux-tab.ts +1264 -0
  1025. package/src/tools/browser/cmux/rpc.ts +156 -0
  1026. package/src/tools/browser/cmux/socket-client.ts +309 -0
  1027. package/src/tools/browser/launch.ts +11 -2
  1028. package/src/tools/browser/readable.ts +19 -2
  1029. package/src/tools/browser/registry.ts +52 -5
  1030. package/src/tools/browser/render.ts +13 -5
  1031. package/src/tools/browser/tab-protocol.ts +2 -0
  1032. package/src/tools/browser/tab-supervisor.ts +256 -34
  1033. package/src/tools/browser/tab-worker.ts +259 -91
  1034. package/src/tools/browser.ts +44 -2
  1035. package/src/tools/checkpoint.ts +1 -1
  1036. package/src/tools/conflict-detect.ts +50 -4
  1037. package/src/tools/debug.ts +27 -12
  1038. package/src/tools/eval-render.ts +32 -35
  1039. package/src/tools/eval.ts +26 -12
  1040. package/src/tools/fetch.ts +450 -99
  1041. package/src/tools/find.ts +182 -142
  1042. package/src/tools/gh-cache-invalidation.ts +255 -0
  1043. package/src/tools/gh-renderer.ts +104 -51
  1044. package/src/tools/gh.ts +232 -37
  1045. package/src/tools/github-cache.ts +97 -7
  1046. package/src/tools/grouped-file-output.ts +159 -52
  1047. package/src/tools/image-gen.ts +237 -132
  1048. package/src/tools/index.ts +147 -26
  1049. package/src/tools/inspect-image-renderer.ts +74 -45
  1050. package/src/tools/inspect-image.ts +12 -6
  1051. package/src/tools/irc.ts +626 -173
  1052. package/src/tools/job.ts +106 -29
  1053. package/src/tools/learn.ts +144 -0
  1054. package/src/tools/manage-skill.ts +104 -0
  1055. package/src/tools/memory-edit.ts +4 -4
  1056. package/src/tools/memory-recall.ts +7 -9
  1057. package/src/tools/memory-reflect.ts +5 -9
  1058. package/src/tools/memory-render.ts +23 -6
  1059. package/src/tools/memory-retain.ts +4 -4
  1060. package/src/tools/path-utils.ts +102 -48
  1061. package/src/tools/plan-mode-guard.ts +101 -40
  1062. package/src/tools/read.ts +475 -120
  1063. package/src/tools/render-mermaid.ts +1 -1
  1064. package/src/tools/render-utils.ts +132 -76
  1065. package/src/tools/renderers.ts +12 -1
  1066. package/src/tools/report-tool-issue.ts +14 -6
  1067. package/src/tools/resolve.ts +20 -3
  1068. package/src/tools/review.ts +2 -2
  1069. package/src/tools/search-tool-bm25.ts +37 -24
  1070. package/src/tools/search.ts +233 -115
  1071. package/src/tools/sqlite-reader.ts +26 -17
  1072. package/src/tools/ssh.ts +20 -14
  1073. package/src/tools/todo.ts +197 -191
  1074. package/src/tools/tool-result.ts +8 -0
  1075. package/src/tools/tool-timeouts.ts +1 -1
  1076. package/src/tools/tts.ts +205 -74
  1077. package/src/tools/write.ts +291 -155
  1078. package/src/tools/yield.ts +10 -1
  1079. package/src/tts/downloader.ts +64 -0
  1080. package/src/tts/index.ts +8 -0
  1081. package/src/tts/models.ts +137 -0
  1082. package/src/tts/player.ts +137 -0
  1083. package/src/tts/runtime.ts +21 -0
  1084. package/src/tts/streaming-player.ts +266 -0
  1085. package/src/tts/tts-client.ts +647 -0
  1086. package/src/tts/tts-protocol.ts +60 -0
  1087. package/src/tts/tts-worker.ts +505 -0
  1088. package/src/tts/vocalizer.ts +162 -0
  1089. package/src/tts/wav.ts +58 -0
  1090. package/src/tui/code-cell.ts +2 -7
  1091. package/src/tui/hyperlink.ts +40 -26
  1092. package/src/tui/output-block.ts +60 -108
  1093. package/src/tui/status-line.ts +5 -1
  1094. package/src/utils/block-context.ts +312 -0
  1095. package/src/utils/changelog.ts +27 -1
  1096. package/src/utils/clipboard.ts +91 -22
  1097. package/src/utils/commit-message-generator.ts +8 -3
  1098. package/src/utils/enhanced-paste.ts +230 -0
  1099. package/src/utils/file-mentions.ts +3 -1
  1100. package/src/utils/git.ts +315 -15
  1101. package/src/utils/image-loading.ts +65 -4
  1102. package/src/utils/session-color.ts +83 -9
  1103. package/src/utils/thinking-display.ts +37 -0
  1104. package/src/utils/title-generator.ts +73 -10
  1105. package/src/utils/tool-choice.ts +16 -0
  1106. package/src/utils/tools-manager.ts +19 -1
  1107. package/src/web/kagi.ts +28 -26
  1108. package/src/web/parallel.ts +7 -3
  1109. package/src/web/scrapers/arxiv.ts +1 -1
  1110. package/src/web/scrapers/github.ts +351 -3
  1111. package/src/web/scrapers/go-pkg.ts +1 -1
  1112. package/src/web/scrapers/iacr.ts +1 -1
  1113. package/src/web/scrapers/readthedocs.ts +1 -1
  1114. package/src/web/scrapers/twitter.ts +2 -1
  1115. package/src/web/scrapers/types.ts +87 -8
  1116. package/src/web/scrapers/wikipedia.ts +1 -1
  1117. package/src/web/scrapers/youtube.ts +9 -3
  1118. package/src/web/search/index.ts +15 -2
  1119. package/src/web/search/providers/anthropic.ts +62 -21
  1120. package/src/web/search/providers/base.ts +2 -1
  1121. package/src/web/search/providers/brave.ts +5 -2
  1122. package/src/web/search/providers/codex.ts +87 -51
  1123. package/src/web/search/providers/exa.ts +101 -10
  1124. package/src/web/search/providers/gemini.ts +49 -24
  1125. package/src/web/search/providers/jina.ts +15 -5
  1126. package/src/web/search/providers/kagi.ts +9 -2
  1127. package/src/web/search/providers/kimi.ts +45 -20
  1128. package/src/web/search/providers/parallel.ts +39 -24
  1129. package/src/web/search/providers/perplexity.ts +226 -63
  1130. package/src/web/search/providers/searxng.ts +19 -3
  1131. package/src/web/search/providers/synthetic.ts +16 -11
  1132. package/src/web/search/providers/tavily.ts +12 -9
  1133. package/src/web/search/providers/zai.ts +22 -9
  1134. package/src/web/search/render.ts +59 -64
  1135. package/src/web/search/types.ts +5 -1
  1136. package/dist/types/discovery/context-files.d.ts +0 -17
  1137. package/dist/types/exa/factory.d.ts +0 -13
  1138. package/dist/types/exa/render.d.ts +0 -19
  1139. package/dist/types/exa/researcher.d.ts +0 -9
  1140. package/dist/types/exa/search.d.ts +0 -9
  1141. package/dist/types/exa/websets.d.ts +0 -9
  1142. package/dist/types/export/html/template.generated.d.ts +0 -1
  1143. package/dist/types/modes/components/session-observer-overlay.d.ts +0 -11
  1144. package/dist/types/modes/components/status-line.d.ts +0 -77
  1145. package/dist/types/slash-commands/headless-plan.d.ts +0 -3
  1146. package/dist/types/stt/setup.d.ts +0 -18
  1147. package/scripts/generate-template.ts +0 -33
  1148. package/src/discovery/context-files.ts +0 -49
  1149. package/src/exa/factory.ts +0 -60
  1150. package/src/exa/render.ts +0 -244
  1151. package/src/exa/researcher.ts +0 -36
  1152. package/src/exa/search.ts +0 -47
  1153. package/src/exa/websets.ts +0 -248
  1154. package/src/export/html/template.generated.ts +0 -2
  1155. package/src/modes/components/session-observer-overlay.ts +0 -852
  1156. package/src/slash-commands/headless-plan.ts +0 -142
  1157. package/src/stt/setup.ts +0 -52
  1158. package/src/stt/transcribe.py +0 -70
  1159. /package/dist/types/extensibility/{legacy-pi-coding-agent-shim.d.ts → legacy-package-agent-shim.d.ts} +0 -0
  1160. /package/src/extensibility/{legacy-pi-coding-agent-shim.ts → legacy-package-agent-shim.ts} +0 -0
@@ -7,12 +7,15 @@
7
7
  import path from "node:path";
8
8
  import type { AgentEvent, AgentIdentity, AgentTelemetryConfig, ThinkingLevel } from "@prometheus-ai/agent-core";
9
9
  import { recordHandoff, resolveTelemetry } from "@prometheus-ai/agent-core";
10
- import { logger, prompt, untilAborted } from "@prometheus-ai/utils";
10
+ import type { Usage } from "@prometheus-ai/ai";
11
+ import { logger, popLoopPhase, prompt, pushLoopPhase, untilAborted } from "@prometheus-ai/utils";
12
+ import type { Rule } from "../capability/rule";
11
13
  import { ModelRegistry } from "../config/model-registry";
12
14
  import { resolveModelOverrideWithAuthFallback } from "../config/model-resolver";
13
15
  import type { PromptTemplate } from "../config/prompt-templates";
14
16
  import { Settings } from "../config/settings";
15
17
  import { SETTINGS_SCHEMA, type SettingPath } from "../config/settings-schema";
18
+ import type { ToolPathWithSource } from "../extensibility/custom-tools";
16
19
  import type { CustomTool } from "../extensibility/custom-tools/types";
17
20
  import { runExtensionCompact, runExtensionSetModel } from "../extensibility/extensions/compact-handler";
18
21
  import { getSessionSlashCommands } from "../extensibility/extensions/get-commands-handler";
@@ -24,8 +27,9 @@ import type { MCPManager } from "../mcp/manager";
24
27
  import type { MnemopiSessionState } from "../mnemopi/state";
25
28
  import subagentSystemPromptTemplate from "../prompts/system/subagent-system-prompt.md" with { type: "text" };
26
29
  import submitReminderTemplate from "../prompts/system/subagent-yield-reminder.md" with { type: "text" };
30
+ import { AgentLifecycleManager } from "../registry/agent-lifecycle";
27
31
  import { AgentRegistry } from "../registry/agent-registry";
28
- import { createAgentSession, discoverAuthStorage } from "../sdk";
32
+ import { type CreateAgentSessionOptions, createAgentSession, discoverAuthStorage } from "../sdk";
29
33
  import type { AgentSession, AgentSessionEvent } from "../session/agent-session";
30
34
  import type { ArtifactManager } from "../session/artifacts";
31
35
  import type { AuthStorage } from "../session/auth-storage";
@@ -33,8 +37,13 @@ import { SKILL_PROMPT_MESSAGE_TYPE } from "../session/messages";
33
37
  import { SessionManager } from "../session/session-manager";
34
38
  import { truncateTail } from "../session/streaming-output";
35
39
  import type { ContextFileEntry } from "../tools";
40
+ import { isIrcEnabled } from "../tools/irc";
36
41
  import { normalizeSchema } from "../tools/jtd-to-json-schema";
37
- import { buildOutputValidator, summarizeValidationFailure } from "../tools/output-schema-validator";
42
+ import {
43
+ buildOutputValidator,
44
+ type OutputValidator,
45
+ summarizeValidationFailure,
46
+ } from "../tools/output-schema-validator";
38
47
 
39
48
  import { type ReportFindingDetails, toReviewFinding } from "../tools/review";
40
49
  import { ToolAbortError } from "../tools/tool-errors";
@@ -47,7 +56,9 @@ import {
47
56
  type AgentProgress,
48
57
  MAX_OUTPUT_BYTES,
49
58
  MAX_OUTPUT_LINES,
59
+ oneLineLabel,
50
60
  type ReviewFinding,
61
+ resolveSubagentDisplayName,
51
62
  type SingleResult,
52
63
  TASK_SUBAGENT_EVENT_CHANNEL,
53
64
  TASK_SUBAGENT_LIFECYCLE_CHANNEL,
@@ -57,6 +68,30 @@ import {
57
68
 
58
69
  const MCP_CALL_TIMEOUT_MS = 60_000;
59
70
 
71
+ /**
72
+ * Soft per-agent request budgets (assistant requests per run). When a subagent
73
+ * crosses its budget it receives ONE steering notice asking it to wrap up; at
74
+ * 1.5x the budget the run is aborted gracefully so partial output is salvaged.
75
+ * The `default` key applies to agents without an explicit entry and can be
76
+ * overridden via the `task.softRequestBudget` setting (0 disables the guard).
77
+ */
78
+ export const SOFT_REQUEST_BUDGET: Record<string, number> = {
79
+ explore: 40,
80
+ quick_task: 40,
81
+ default: 90,
82
+ };
83
+
84
+ /** Steering notice injected once when a subagent crosses its soft request budget. */
85
+ export function buildBudgetNotice(requests: number): string {
86
+ return `[budget notice] You have used ${requests} requests in this run. Wrap up now: finish the current step and yield your final report.`;
87
+ }
88
+
89
+ /** Flatten whitespace and clip salvage text for the cancelled-child summary line. */
90
+ function formatSalvageSnippet(text: string, maxLength = 500): string {
91
+ const flattened = text.replace(/\s+/g, " ").trim();
92
+ return flattened.length > maxLength ? `${flattened.slice(0, maxLength - 1)}…` : flattened;
93
+ }
94
+
60
95
  /** Agent event types to forward for progress tracking. */
61
96
  const agentEventTypes = new Set<AgentEvent["type"]>([
62
97
  "agent_start",
@@ -88,9 +123,16 @@ function normalizeModelPatterns(value: string | string[] | undefined): string[]
88
123
  function renderIrcPeerRoster(selfId: string): string {
89
124
  const peers = AgentRegistry.global()
90
125
  .list()
91
- .filter(ref => ref.id !== selfId && (ref.status === "running" || ref.status === "idle"));
92
- if (peers.length === 0) return "- (no other live agents)";
93
- return peers.map(peer => `- \`${peer.id}\` — ${peer.displayName} (${peer.kind}, ${peer.status})`).join("\n");
126
+ .filter(ref => ref.id !== selfId && ref.status !== "aborted");
127
+ if (peers.length === 0) return "- (no other agents)";
128
+ const lines = peers.map(
129
+ peer =>
130
+ `- \`${peer.id}\` — ${peer.displayName} (${peer.kind}, ${peer.status})${peer.activity ? `: ${peer.activity}` : ""}`,
131
+ );
132
+ if (peers.some(peer => peer.status === "idle" || peer.status === "parked")) {
133
+ lines.push("Idle/parked peers are not gone: messaging them wakes (or revives) them.");
134
+ }
135
+ return lines.join("\n");
94
136
  }
95
137
 
96
138
  function withAbortTimeout<T>(promise: Promise<T>, timeoutMs: number, signal?: AbortSignal): Promise<T> {
@@ -146,6 +188,7 @@ export interface ExecutorOptions {
146
188
  agent: AgentDefinition;
147
189
  task: string;
148
190
  assignment?: string;
191
+ /** Shared background from the task call (`task.batch`), rendered into the subagent's system prompt. */
149
192
  context?: string;
150
193
  /**
151
194
  * The session's active overall plan, handed off so subagents spawned during
@@ -154,8 +197,18 @@ export interface ExecutorOptions {
154
197
  */
155
198
  planReference?: { path: string; content: string };
156
199
  description?: string;
200
+ /** Specialist role/expertise for this spawn; drives the system-prompt preamble, display name, and telemetry identity. */
201
+ role?: string;
157
202
  index: number;
158
203
  id: string;
204
+ parentToolCallId?: string;
205
+ /**
206
+ * Spawn runs as a detached background job (parent turn not blocked on it).
207
+ * Rides the subagent lifecycle/progress payloads so HUD-style surfaces can
208
+ * skip spawns the transcript already renders inline. See
209
+ * {@link SubagentLifecyclePayload.detached}.
210
+ */
211
+ detached?: boolean;
159
212
  modelOverride?: string | string[];
160
213
  /**
161
214
  * Active model selector of the parent session, used as an auth-aware fallback
@@ -166,19 +219,38 @@ export interface ExecutorOptions {
166
219
  outputSchema?: unknown;
167
220
  /** Parent task recursion depth (0 = top-level, 1 = first child, etc.) */
168
221
  taskDepth?: number;
222
+ /**
223
+ * Override the `task.maxRuntimeMs` wall-clock cap for this run. When provided
224
+ * it wins over the settings value; `0` disables the per-subagent wall-clock
225
+ * limit entirely. Used by the eval `agent()` bridge, whose parent cell
226
+ * watchdog is already suspended for the call's duration.
227
+ */
228
+ maxRuntimeMs?: number;
169
229
  enableLsp?: boolean;
170
230
  signal?: AbortSignal;
171
231
  onProgress?: (progress: AgentProgress) => void;
172
232
  sessionFile?: string | null;
173
233
  persistArtifacts?: boolean;
174
234
  artifactsDir?: string;
175
- /** Path to parent conversation context file */
176
- contextFile?: string;
177
235
  eventBus?: EventBus;
178
236
  contextFiles?: ContextFileEntry[];
179
237
  skills?: Skill[];
180
238
  promptTemplates?: PromptTemplate[];
181
239
  workspaceTree?: WorkspaceTree;
240
+ /** Parent-discovered rules, forwarded to skip rule discovery in the subagent. */
241
+ rules?: Rule[];
242
+ /**
243
+ * Parent's discovered extension source paths. Forwarded to skip the
244
+ * extension FS scan in the subagent; the subagent then re-binds each
245
+ * extension against its own `ExtensionAPI` (cwd, eventBus, runtime).
246
+ */
247
+ preloadedExtensionPaths?: string[];
248
+ /**
249
+ * Parent's discovered custom-tool source paths. Forwarded to skip the
250
+ * `.prometheus/tools/` FS scan in the subagent; the subagent then re-binds each
251
+ * tool against its own `CustomToolAPI` (cwd, exec, pushPendingAction, UI).
252
+ */
253
+ preloadedCustomToolPaths?: ToolPathWithSource[];
182
254
  mcpManager?: MCPManager;
183
255
  authStorage?: AuthStorage;
184
256
  modelRegistry?: ModelRegistry;
@@ -249,21 +321,40 @@ function extractCompletionData(parsed: unknown): unknown {
249
321
  return parsed;
250
322
  }
251
323
 
252
- function normalizeCompleteData(data: unknown, reportFindings?: ReviewFinding[]): unknown {
253
- let normalized = parseStringifiedJson(data ?? null);
324
+ /**
325
+ * Resolve the final yielded payload, optionally splicing collected
326
+ * `report_finding` entries into a top-level `findings` array.
327
+ *
328
+ * Injection is suppressed when an active validator would reject the augmented
329
+ * payload (e.g. a caller-supplied schema with `additionalProperties: false`
330
+ * that does not declare `findings`). That keeps the in-tool yield validator
331
+ * (which only sees the raw, pre-injection data) in lockstep with this
332
+ * post-mortem validator — honoring the "accepted in-tool ⇒ accepted
333
+ * post-mortem" guarantee documented in `output-schema-validator.ts`. The
334
+ * dropped findings are still preserved verbatim in the agent's progress
335
+ * stream and JSONL artifact, so no information is lost when injection is
336
+ * suppressed.
337
+ */
338
+ function normalizeCompleteData(
339
+ data: unknown,
340
+ reportFindings: ReviewFinding[] | undefined,
341
+ validator: OutputValidator | undefined,
342
+ ): unknown {
343
+ const normalized = parseStringifiedJson(data ?? null);
254
344
  if (
255
- Array.isArray(reportFindings) &&
256
- reportFindings.length > 0 &&
257
- normalized &&
258
- typeof normalized === "object" &&
259
- !Array.isArray(normalized)
345
+ !Array.isArray(reportFindings) ||
346
+ reportFindings.length === 0 ||
347
+ !normalized ||
348
+ typeof normalized !== "object" ||
349
+ Array.isArray(normalized)
260
350
  ) {
261
- const record = normalized as Record<string, unknown>;
262
- if (!("findings" in record)) {
263
- normalized = { ...record, findings: reportFindings };
264
- }
351
+ return normalized;
265
352
  }
266
- return normalized;
353
+ const record = normalized as Record<string, unknown>;
354
+ if ("findings" in record) return normalized;
355
+ const injected = { ...record, findings: reportFindings };
356
+ if (validator && !validator.validate(injected).success) return normalized;
357
+ return injected;
267
358
  }
268
359
 
269
360
  function resolveFallbackCompletion(rawOutput: string, outputSchema: unknown): { data: unknown } | null {
@@ -281,6 +372,15 @@ export interface YieldItem {
281
372
  data?: unknown;
282
373
  status?: "success" | "aborted";
283
374
  error?: string;
375
+ /**
376
+ * Set by the in-tool yield validator when it exhausted its retry budget
377
+ * (MAX_SCHEMA_RETRIES) and accepted a schema-invalid payload anyway.
378
+ * `finalizeSubprocessOutput` honors this by serializing the payload and
379
+ * surfacing a stderr warning, instead of re-emitting `schema_violation`
380
+ * — which would silently swap the subagent's "accepted" view for a
381
+ * different, opaque error blob in the parent's view of the result.
382
+ */
383
+ schemaOverridden?: boolean;
284
384
  }
285
385
 
286
386
  interface FinalizeSubprocessOutputArgs {
@@ -301,7 +401,8 @@ interface FinalizeSubprocessOutputResult {
301
401
  abortedViaYield: boolean;
302
402
  hasYield: boolean;
303
403
  }
304
-
404
+ export const SUBAGENT_WARNING_SCHEMA_OVERRIDDEN =
405
+ "SYSTEM WARNING: Subagent exhausted schema-retry budget; result was accepted despite failing the output schema.";
305
406
  export const SUBAGENT_WARNING_NULL_YIELD = "SYSTEM WARNING: Subagent called yield with null data.";
306
407
  export const SUBAGENT_WARNING_MISSING_YIELD =
307
408
  "SYSTEM WARNING: Subagent exited without calling yield tool after 3 reminders.";
@@ -353,30 +454,32 @@ export function finalizeSubprocessOutput(args: FinalizeSubprocessOutputArgs): Fi
353
454
  if (submitData === null || submitData === undefined) {
354
455
  rawOutput = rawOutput ? `${SUBAGENT_WARNING_NULL_YIELD}\n\n${rawOutput}` : SUBAGENT_WARNING_NULL_YIELD;
355
456
  } else {
356
- const completeData = normalizeCompleteData(submitData, reportFindings);
357
457
  const { validator, error: schemaError } = buildOutputValidator(outputSchema);
358
- if (schemaError) {
359
- rawOutput = `{"error":"schema_violation","message":"invalid output schema: ${schemaError.replace(/"/g, '\\"')}"}`;
360
- stderr = `schema_violation: invalid output schema: ${schemaError}`;
361
- exitCode = 1;
458
+ const overridden = lastYield?.schemaOverridden === true;
459
+ const completeData = normalizeCompleteData(submitData, reportFindings, validator);
460
+ const result =
461
+ schemaError || overridden
462
+ ? { success: true as const }
463
+ : (validator?.validate(completeData) ?? { success: true as const });
464
+ if (!result.success) {
465
+ const summary = summarizeValidationFailure(result, completeData, validator?.requiredFields ?? []);
466
+ const outcome = buildSchemaViolationOutcome(summary, completeData);
467
+ rawOutput = outcome.rawOutput;
468
+ stderr = outcome.stderr;
469
+ exitCode = outcome.exitCode;
362
470
  } else {
363
- const result = validator?.validate(completeData) ?? { success: true as const };
364
- if (!result.success) {
365
- const summary = summarizeValidationFailure(result, completeData, validator?.requiredFields ?? []);
366
- const outcome = buildSchemaViolationOutcome(summary, completeData);
367
- rawOutput = outcome.rawOutput;
368
- stderr = outcome.stderr;
369
- exitCode = outcome.exitCode;
370
- } else {
371
- try {
372
- rawOutput = JSON.stringify(completeData, null, 2) ?? "null";
373
- } catch (err) {
374
- const errorMessage = err instanceof Error ? err.message : String(err);
375
- rawOutput = `{"error":"Failed to serialize yield data: ${errorMessage}"}`;
376
- }
377
- exitCode = 0;
378
- stderr = "";
471
+ try {
472
+ rawOutput = JSON.stringify(completeData, null, 2) ?? "null";
473
+ } catch (err) {
474
+ const errorMessage = err instanceof Error ? err.message : String(err);
475
+ rawOutput = `{"error":"Failed to serialize yield data: ${errorMessage}"}`;
379
476
  }
477
+ exitCode = 0;
478
+ stderr = overridden
479
+ ? SUBAGENT_WARNING_SCHEMA_OVERRIDDEN
480
+ : schemaError
481
+ ? `invalid output schema: ${schemaError}`
482
+ : "";
380
483
  }
381
484
  }
382
485
  }
@@ -386,8 +489,8 @@ export function finalizeSubprocessOutput(args: FinalizeSubprocessOutputArgs): Fi
386
489
  const hasOutputSchema = normalizedSchema !== undefined && !schemaError;
387
490
  const fallback = allowFallback ? resolveFallbackCompletion(rawOutput, outputSchema) : null;
388
491
  if (fallback) {
389
- const completeData = normalizeCompleteData(fallback.data, reportFindings);
390
492
  const { validator } = buildOutputValidator(outputSchema);
493
+ const completeData = normalizeCompleteData(fallback.data, reportFindings, validator);
391
494
  const result = validator?.validate(completeData) ?? { success: true as const };
392
495
  if (!result.success) {
393
496
  const summary = summarizeValidationFailure(result, completeData, validator?.requiredFields ?? []);
@@ -481,7 +584,7 @@ function getUsageTokens(usage: unknown): number {
481
584
  /**
482
585
  * Create proxy tools that reuse the parent's MCP connections.
483
586
  */
484
- function createMCPProxyTools(mcpManager: MCPManager): CustomTool[] {
587
+ export function createMCPProxyTools(mcpManager: MCPManager): CustomTool[] {
485
588
  return mcpManager.getTools().map(tool => {
486
589
  const mcpTool = tool as { mcpToolName?: string; mcpServerName?: string };
487
590
  return {
@@ -531,7 +634,10 @@ function createMCPProxyTools(mcpManager: MCPManager): CustomTool[] {
531
634
  });
532
635
  }
533
636
 
534
- function createSubagentSettings(baseSettings: Settings, overrides?: Partial<Record<SettingPath, unknown>>): Settings {
637
+ export function createSubagentSettings(
638
+ baseSettings: Settings,
639
+ overrides?: Partial<Record<SettingPath, unknown>>,
640
+ ): Settings {
535
641
  const snapshot: Partial<Record<SettingPath, unknown>> = {};
536
642
  for (const key of Object.keys(SETTINGS_SCHEMA) as SettingPath[]) {
537
643
  snapshot[key] = baseSettings.get(key);
@@ -549,28 +655,68 @@ function createSubagentSettings(baseSettings: Settings, overrides?: Partial<Reco
549
655
  });
550
656
  }
551
657
 
658
+ type AbortReason = "signal" | "terminate" | "timeout" | "budget";
659
+
660
+ /** Inputs for the run monitor driving one subagent assignment. */
661
+ interface RunMonitorArgs {
662
+ index: number;
663
+ id: string;
664
+ agent: AgentDefinition;
665
+ task: string;
666
+ assignment?: string;
667
+ description?: string;
668
+ modelOverride?: string | string[];
669
+ signal?: AbortSignal;
670
+ onProgress?: (progress: AgentProgress) => void;
671
+ eventBus?: EventBus;
672
+ parentToolCallId?: string;
673
+ detached?: boolean;
674
+ sessionFile?: string;
675
+ /** Soft assistant-request budget; 0 disables the guard. */
676
+ softRequestBudget: number;
677
+ /** Wall-clock cap in ms; 0 disables the timer. */
678
+ maxRuntimeMs: number;
679
+ }
680
+
552
681
  /**
553
- * Run a single agent in-process.
682
+ * The run-monitoring core of {@link runSubprocess}: progress tracking, event
683
+ * processing, abort/budget machinery, usage accumulation, and output capture
684
+ * for one assignment run.
554
685
  */
555
- export async function runSubprocess(options: ExecutorOptions): Promise<SingleResult> {
556
- const {
557
- cwd,
558
- agent,
559
- task,
560
- assignment,
561
- index,
562
- id,
563
- worktree,
564
- modelOverride,
565
- thinkingLevel,
566
- outputSchema,
567
- enableLsp,
568
- signal,
569
- onProgress,
570
- } = options;
686
+ interface SubagentRunMonitor {
687
+ readonly progress: AgentProgress;
688
+ /** Fires when the run was asked to stop (caller signal, timeout, budget, terminate). */
689
+ readonly abortSignal: AbortSignal;
690
+ readonly accumulatedUsage: Usage;
691
+ hasUsage(): boolean;
692
+ yieldCalled(): boolean;
693
+ runtimeLimitExceeded(): boolean;
694
+ /** True when the abort carries a precise external reason (signal / wall-clock / budget). */
695
+ hasExplicitAbortReason(): boolean;
696
+ /** Whether the (attempted) abort counts as a cancelled run rather than an internal failure. */
697
+ isAbortedRun(): boolean;
698
+ requestAbort(reason: AbortReason): void;
699
+ resolveSignalAbortReason(): string;
700
+ resolveAbortReasonText(): string;
701
+ setActiveSession(session: AgentSession | null): void;
702
+ /** Return and clear the active session reference. */
703
+ takeActiveSession(): AgentSession | null;
704
+ /** Subscribe the monitor to a session's events. Returns the unsubscribe function. */
705
+ attach(session: AgentSession): () => void;
706
+ /** Best-effort capture of the last assistant text for cancelled-run salvage. */
707
+ captureSalvage(session: AgentSession): void;
708
+ lastAssistantSalvageText(): string | undefined;
709
+ /** Final raw output: end-of-run assistant text when available, else accumulated chunks. */
710
+ rawOutput(): string;
711
+ scheduleProgress(flush?: boolean): void;
712
+ /** Stop processing events and clear listeners/timers. Call once the run settled. */
713
+ finish(): void;
714
+ }
715
+
716
+ function createSubagentRunMonitor(args: RunMonitorArgs): SubagentRunMonitor {
717
+ const { index, id, agent, task, assignment, signal, onProgress, softRequestBudget, maxRuntimeMs } = args;
571
718
  const startTime = Date.now();
572
719
 
573
- // Initialize progress
574
720
  const progress: AgentProgress = {
575
721
  index,
576
722
  id,
@@ -579,106 +725,23 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
579
725
  status: "running",
580
726
  task,
581
727
  assignment,
582
- description: options.description,
728
+ description: args.description,
583
729
  lastIntent: undefined,
584
730
  recentTools: [],
585
731
  recentOutput: [],
586
732
  toolCount: 0,
733
+ requests: 0,
587
734
  tokens: 0,
588
735
  cost: 0,
589
736
  durationMs: 0,
590
- modelOverride,
737
+ modelOverride: args.modelOverride,
591
738
  };
592
739
 
593
- // Check if already aborted
594
- if (signal?.aborted) {
595
- return {
596
- index,
597
- id,
598
- agent: agent.name,
599
- agentSource: agent.source,
600
- task,
601
- assignment,
602
- description: options.description,
603
- exitCode: 1,
604
- output: "",
605
- stderr: "Cancelled before start",
606
- truncated: false,
607
- durationMs: 0,
608
- tokens: 0,
609
- modelOverride,
610
- error: "Cancelled before start",
611
- aborted: true,
612
- abortReason: "Cancelled before start",
613
- };
614
- }
615
-
616
- // Set up artifact paths and write input file upfront if artifacts dir provided
617
- let subtaskSessionFile: string | undefined;
618
- if (options.artifactsDir) {
619
- subtaskSessionFile = path.join(options.artifactsDir, `${id}.jsonl`);
620
- }
621
-
622
- const settings = options.settings ?? Settings.isolated();
623
- const subagentSettings = createSubagentSettings(
624
- settings,
625
- agent.readSummarize === false ? { "read.summarize.enabled": false } : undefined,
626
- );
627
- const maxRecursionDepth = settings.get("task.maxRecursionDepth") ?? 2;
628
- const maxRuntimeMs = Math.max(0, Math.trunc(Number(settings.get("task.maxRuntimeMs") ?? 0) || 0));
629
- const parentDepth = options.taskDepth ?? 0;
630
- const childDepth = parentDepth + 1;
631
- const atMaxDepth = maxRecursionDepth >= 0 && childDepth >= maxRecursionDepth;
632
-
633
- // Add tools if specified
634
- let toolNames: string[] | undefined;
635
- if (agent.tools && agent.tools.length > 0) {
636
- toolNames = agent.tools;
637
- // Auto-include task tool if spawns defined but task not in tools
638
- if (agent.spawns !== undefined && !toolNames.includes("task") && !atMaxDepth) {
639
- toolNames = [...toolNames, "task"];
640
- }
641
- }
642
-
643
- if (atMaxDepth && toolNames?.includes("task")) {
644
- toolNames = toolNames.filter(name => name !== "task");
645
- }
646
- // IRC is always available; the COOP prompt section advertises it, so a restricted
647
- // whitelist must still carry `irc` for the subagent to actually use it.
648
- if (toolNames && !toolNames.includes("irc")) {
649
- toolNames = [...toolNames, "irc"];
650
- }
651
- if (toolNames?.includes("exec")) {
652
- const allowEvalPy = settings.get("eval.py") ?? true;
653
- const allowEvalJs = settings.get("eval.js") ?? true;
654
- const expanded = toolNames.filter(name => name !== "exec");
655
- if (allowEvalPy || allowEvalJs) expanded.push("eval");
656
- expanded.push("bash");
657
- toolNames = Array.from(new Set(expanded));
658
- }
659
-
660
- const modelPatterns = normalizeModelPatterns(modelOverride ?? agent.model);
661
- const sessionFile = subtaskSessionFile ?? null;
662
- const spawnsEnv = atMaxDepth
663
- ? ""
664
- : agent.spawns === undefined
665
- ? ""
666
- : agent.spawns === "*"
667
- ? "*"
668
- : agent.spawns.join(",");
669
-
670
- const lspEnabled = enableLsp ?? true;
671
- const ircEnabled = subagentSettings.get("irc.enabled") === true;
672
- const contextFileForPrompt = ircEnabled ? undefined : options.contextFile;
673
- const skipPythonPreflight = Array.isArray(toolNames) && !toolNames.includes("eval");
674
-
675
740
  const outputChunks: string[] = [];
676
741
  const finalOutputChunks: string[] = [];
677
742
  const RECENT_OUTPUT_TAIL_BYTES = 8 * 1024;
678
743
  let recentOutputTail = "";
679
- let stderr = "";
680
744
  let resolved = false;
681
- type AbortReason = "signal" | "terminate" | "timeout";
682
745
  let abortSent = false;
683
746
  let abortReason: AbortReason | undefined;
684
747
  let runtimeLimitExceeded = false;
@@ -687,11 +750,10 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
687
750
  const abortController = new AbortController();
688
751
  const abortSignal = abortController.signal;
689
752
  let activeSession: AgentSession | null = null;
690
- let unsubscribe: (() => void) | null = null;
691
753
  let yieldCalled = false;
692
754
 
693
755
  // Accumulate usage incrementally from message_end events (no memory for streaming events)
694
- const accumulatedUsage = {
756
+ const accumulatedUsage: Usage = {
695
757
  input: 0,
696
758
  output: 0,
697
759
  cacheRead: 0,
@@ -700,11 +762,17 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
700
762
  cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
701
763
  };
702
764
  let hasUsage = false;
765
+ let budgetSteerSent = false;
766
+ let budgetLimitExceeded = false;
767
+ let lastAssistantSalvageText: string | undefined;
703
768
 
704
769
  const requestAbort = (reason: AbortReason) => {
705
770
  if (reason === "timeout") {
706
771
  runtimeLimitExceeded = true;
707
772
  }
773
+ if (reason === "budget") {
774
+ budgetLimitExceeded = true;
775
+ }
708
776
  if (abortSent) {
709
777
  if (reason === "signal" && abortReason !== "signal" && abortReason !== "timeout") {
710
778
  abortReason = "signal";
@@ -721,11 +789,14 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
721
789
  };
722
790
 
723
791
  // Handle abort signal
724
- const onAbort = () => {
725
- if (!resolved) requestAbort("signal");
726
- };
727
792
  if (signal) {
728
- signal.addEventListener("abort", onAbort, { once: true, signal: listenerSignal });
793
+ signal.addEventListener(
794
+ "abort",
795
+ () => {
796
+ if (!resolved) requestAbort("signal");
797
+ },
798
+ { once: true, signal: listenerSignal },
799
+ );
729
800
  }
730
801
 
731
802
  // Wall-clock hard limit. Defense-in-depth for the case where a provider stream
@@ -761,6 +832,9 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
761
832
  if (runtimeLimitExceeded) {
762
833
  return `Subagent runtime limit exceeded (task.maxRuntimeMs=${maxRuntimeMs})`;
763
834
  }
835
+ if (budgetLimitExceeded) {
836
+ return `Soft request budget exceeded (${progress.requests} requests; budget ${softRequestBudget})`;
837
+ }
764
838
  return resolveSignalAbortReason();
765
839
  };
766
840
  const PROGRESS_COALESCE_MS = 150;
@@ -770,15 +844,20 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
770
844
  const emitProgressNow = () => {
771
845
  progress.durationMs = Date.now() - startTime;
772
846
  onProgress?.({ ...progress });
773
- if (options.eventBus) {
774
- options.eventBus.emit(TASK_SUBAGENT_PROGRESS_CHANNEL, {
847
+ const activityGist =
848
+ progress.lastIntent ?? (progress.currentTool ? `running ${progress.currentTool}` : undefined);
849
+ if (activityGist) AgentRegistry.global().setActivity(id, activityGist);
850
+ if (args.eventBus) {
851
+ args.eventBus.emit(TASK_SUBAGENT_PROGRESS_CHANNEL, {
775
852
  index,
776
853
  agent: agent.name,
777
854
  agentSource: agent.source,
778
855
  task,
856
+ parentToolCallId: args.parentToolCallId,
857
+ detached: args.detached,
779
858
  assignment,
780
859
  progress: { ...progress },
781
- sessionFile: subtaskSessionFile,
860
+ sessionFile: args.sessionFile,
782
861
  });
783
862
  }
784
863
  lastProgressEmitMs = Date.now();
@@ -858,20 +937,16 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
858
937
  progress.recentOutput = [];
859
938
  };
860
939
 
940
+ const emitSubagentEvent = (event: AgentSessionEvent) => {
941
+ if (!args.eventBus) return;
942
+ args.eventBus.emit(TASK_SUBAGENT_EVENT_CHANNEL, {
943
+ id,
944
+ event,
945
+ });
946
+ };
947
+
861
948
  const processEvent = (event: AgentEvent) => {
862
949
  if (resolved) return;
863
-
864
- if (options.eventBus) {
865
- options.eventBus.emit(TASK_SUBAGENT_EVENT_CHANNEL, {
866
- index,
867
- agent: agent.name,
868
- agentSource: agent.source,
869
- task,
870
- assignment,
871
- event,
872
- });
873
- }
874
-
875
950
  const now = Date.now();
876
951
  let flushProgress = false;
877
952
 
@@ -1016,6 +1091,26 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1016
1091
  case "message_end": {
1017
1092
  // Extract text from assistant and toolResult messages (not user prompts)
1018
1093
  const role = event.message?.role;
1094
+ if (role === "assistant") {
1095
+ progress.requests += 1;
1096
+ if (softRequestBudget > 0 && !abortSent) {
1097
+ if (progress.requests >= softRequestBudget * 1.5) {
1098
+ requestAbort("budget");
1099
+ } else if (!budgetSteerSent && progress.requests >= softRequestBudget) {
1100
+ budgetSteerSent = true;
1101
+ const steerSession = activeSession;
1102
+ if (steerSession) {
1103
+ void steerSession
1104
+ .sendUserMessage(buildBudgetNotice(progress.requests), { deliverAs: "steer" })
1105
+ .catch(err => {
1106
+ logger.warn("Subagent budget steer failed", {
1107
+ error: err instanceof Error ? err.message : String(err),
1108
+ });
1109
+ });
1110
+ }
1111
+ }
1112
+ }
1113
+ }
1019
1114
  if (role === "assistant") {
1020
1115
  const messageContent =
1021
1116
  getMessageContent(event.message) || (event as AgentEvent & { content?: unknown }).content;
@@ -1085,98 +1180,653 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1085
1180
  scheduleProgress(flushProgress);
1086
1181
  };
1087
1182
 
1088
- const runSubagent = async (): Promise<{
1089
- exitCode: number;
1090
- error?: string;
1091
- aborted?: boolean;
1092
- abortReason?: string;
1093
- durationMs: number;
1094
- }> => {
1095
- const sessionAbortController = new AbortController();
1096
- let exitCode = 0;
1097
- let error: string | undefined;
1098
- let aborted = false;
1099
- let abortReasonText: string | undefined;
1100
- const checkAbort = () => {
1101
- if (abortSignal.aborted) {
1102
- aborted = abortReason === "signal" || runtimeLimitExceeded || abortReason === undefined;
1103
- if (aborted) {
1104
- abortReasonText ??= resolveAbortReasonText();
1183
+ const attach = (session: AgentSession): (() => void) =>
1184
+ session.subscribe(event => {
1185
+ emitSubagentEvent(event);
1186
+ if (event.type === "auto_retry_start") {
1187
+ progress.retryState = {
1188
+ attempt: event.attempt,
1189
+ maxAttempts: event.maxAttempts,
1190
+ delayMs: event.delayMs,
1191
+ errorMessage: event.errorMessage,
1192
+ startedAtMs: Date.now(),
1193
+ };
1194
+ progress.retryFailure = undefined;
1195
+ scheduleProgress(true);
1196
+ return;
1197
+ }
1198
+ if (event.type === "auto_retry_end") {
1199
+ const attempt = progress.retryState?.attempt ?? event.attempt;
1200
+ progress.retryState = undefined;
1201
+ if (!event.success) {
1202
+ progress.retryFailure = {
1203
+ attempt,
1204
+ errorMessage: event.finalError ?? "Auto-retry failed",
1205
+ };
1105
1206
  }
1106
- exitCode = 1;
1107
- throw new ToolAbortError();
1207
+ scheduleProgress(true);
1208
+ return;
1108
1209
  }
1109
- };
1110
- const awaitAbortable = async <T>(promise: Promise<T>): Promise<T> => {
1111
- checkAbort();
1112
- const { promise: abortPromise, reject } = Promise.withResolvers<never>();
1113
- const onAbort = () => {
1210
+ if (isAgentEvent(event)) {
1211
+ // Breadcrumb the synchronous subagent event handling so the loop
1212
+ // watchdog can attribute any block to this in-process subagent.
1213
+ pushLoopPhase(`subagent:${id}`);
1114
1214
  try {
1115
- checkAbort();
1215
+ processEvent(event);
1116
1216
  } catch (err) {
1117
- reject(err);
1217
+ logger.error("Subagent event processing failed", {
1218
+ error: err instanceof Error ? err.message : String(err),
1219
+ });
1220
+ requestAbort("terminate");
1221
+ } finally {
1222
+ popLoopPhase();
1118
1223
  }
1119
- };
1120
- abortSignal.addEventListener("abort", onAbort, { once: true });
1121
- try {
1122
- return await Promise.race([promise, abortPromise]);
1123
- } finally {
1124
- abortSignal.removeEventListener("abort", onAbort);
1125
1224
  }
1126
- };
1225
+ });
1127
1226
 
1227
+ const captureSalvage = (session: AgentSession): void => {
1228
+ // Best-effort salvage: capture the last assistant text so
1229
+ // cancelled/aborted children can surface "last activity" instead of
1230
+ // "(no output)".
1128
1231
  try {
1129
- checkAbort();
1130
- // Pin authStorage to modelRegistry.authStorage — mirrors the createAgentSession invariant.
1131
- const registryFromParent = options.modelRegistry !== undefined;
1132
- const modelRegistry =
1133
- options.modelRegistry ??
1134
- new ModelRegistry(options.authStorage ?? (await awaitAbortable(discoverAuthStorage())));
1135
- const authStorage = modelRegistry.authStorage;
1136
- if (options.authStorage && options.authStorage !== authStorage) {
1137
- throw new Error(
1138
- "options.authStorage and options.modelRegistry.authStorage must be the same instance when both are provided",
1139
- );
1140
- }
1141
- checkAbort();
1142
- if (!registryFromParent) {
1143
- await awaitAbortable(modelRegistry.refresh());
1144
- } else {
1145
- logger.debug("runSubagent: reusing parent modelRegistry; skipping refresh");
1232
+ const lastContent = session.getLastAssistantMessage()?.content;
1233
+ if (Array.isArray(lastContent)) {
1234
+ const text = lastContent
1235
+ .map(block => (block.type === "text" && typeof block.text === "string" ? block.text : ""))
1236
+ .filter(Boolean)
1237
+ .join("\n");
1238
+ if (text.trim()) {
1239
+ lastAssistantSalvageText = text;
1240
+ }
1146
1241
  }
1147
- checkAbort();
1242
+ } catch {
1243
+ // Salvage is best-effort; partial sessions may not implement it
1244
+ }
1245
+ };
1148
1246
 
1149
- const {
1150
- model,
1151
- thinkingLevel: resolvedThinkingLevel,
1152
- explicitThinkingLevel,
1153
- authFallbackUsed,
1154
- } = await awaitAbortable(
1155
- resolveModelOverrideWithAuthFallback(
1156
- modelPatterns,
1157
- options.parentActiveModelPattern,
1158
- modelRegistry,
1159
- settings,
1160
- ),
1161
- );
1162
- if (authFallbackUsed && model) {
1163
- logger.warn("Subagent model has no working credentials; falling back to parent session model", {
1164
- requested: modelPatterns,
1165
- parentModel: options.parentActiveModelPattern,
1166
- resolvedProvider: model.provider,
1167
- resolvedModel: model.id,
1168
- });
1169
- }
1170
- if (model?.contextWindow && model.contextWindow > 0) {
1171
- progress.contextWindow = model.contextWindow;
1247
+ return {
1248
+ progress,
1249
+ abortSignal,
1250
+ accumulatedUsage,
1251
+ hasUsage: () => hasUsage,
1252
+ yieldCalled: () => yieldCalled,
1253
+ runtimeLimitExceeded: () => runtimeLimitExceeded,
1254
+ hasExplicitAbortReason: () => abortReason === "signal" || runtimeLimitExceeded || budgetLimitExceeded,
1255
+ isAbortedRun: () =>
1256
+ abortReason === "signal" || runtimeLimitExceeded || budgetLimitExceeded || abortReason === undefined,
1257
+ requestAbort,
1258
+ resolveSignalAbortReason,
1259
+ resolveAbortReasonText,
1260
+ setActiveSession: session => {
1261
+ activeSession = session;
1262
+ },
1263
+ takeActiveSession: () => {
1264
+ const session = activeSession;
1265
+ activeSession = null;
1266
+ return session;
1267
+ },
1268
+ attach,
1269
+ captureSalvage,
1270
+ lastAssistantSalvageText: () => lastAssistantSalvageText,
1271
+ rawOutput: () => (finalOutputChunks.length > 0 ? finalOutputChunks.join("") : outputChunks.join("")),
1272
+ scheduleProgress,
1273
+ finish: () => {
1274
+ resolved = true;
1275
+ listenerController.abort();
1276
+ if (runtimeTimeoutId !== undefined) {
1277
+ clearTimeout(runtimeTimeoutId);
1278
+ runtimeTimeoutId = undefined;
1172
1279
  }
1173
- if (model) {
1174
- progress.resolvedModel = explicitThinkingLevel
1175
- ? `${model.provider}/${model.id}:${resolvedThinkingLevel}`
1176
- : `${model.provider}/${model.id}`;
1280
+ if (progressTimeoutId) {
1281
+ clearTimeout(progressTimeoutId);
1282
+ progressTimeoutId = null;
1177
1283
  }
1178
- const effectiveThinkingLevel = explicitThinkingLevel
1179
- ? resolvedThinkingLevel
1284
+ },
1285
+ };
1286
+ }
1287
+
1288
+ interface DriveOutcome {
1289
+ exitCode: number;
1290
+ error?: string;
1291
+ aborted: boolean;
1292
+ abortReasonText?: string;
1293
+ }
1294
+
1295
+ const MAX_YIELD_RETRIES = 3;
1296
+
1297
+ /**
1298
+ * Drive one assignment through a live session: send the prompt, wait for idle,
1299
+ * remind the agent to `yield` (up to {@link MAX_YIELD_RETRIES} times), then
1300
+ * classify the terminal assistant state.
1301
+ */
1302
+ async function driveSessionToYield(
1303
+ session: AgentSession,
1304
+ monitor: SubagentRunMonitor,
1305
+ task: string,
1306
+ ): Promise<DriveOutcome> {
1307
+ const abortSignal = monitor.abortSignal;
1308
+ let exitCode = 0;
1309
+ let error: string | undefined;
1310
+ let aborted = false;
1311
+ let abortReasonText: string | undefined;
1312
+ const checkAbort = () => {
1313
+ if (abortSignal.aborted) {
1314
+ aborted = monitor.isAbortedRun();
1315
+ if (aborted) {
1316
+ abortReasonText ??= monitor.resolveAbortReasonText();
1317
+ }
1318
+ exitCode = 1;
1319
+ throw new ToolAbortError();
1320
+ }
1321
+ };
1322
+ const awaitAbortable = async <T>(promise: Promise<T>): Promise<T> => {
1323
+ checkAbort();
1324
+ const { promise: abortPromise, reject } = Promise.withResolvers<never>();
1325
+ const onAbort = () => {
1326
+ try {
1327
+ checkAbort();
1328
+ } catch (err) {
1329
+ reject(err);
1330
+ }
1331
+ };
1332
+ abortSignal.addEventListener("abort", onAbort, { once: true });
1333
+ try {
1334
+ return await Promise.race([promise, abortPromise]);
1335
+ } finally {
1336
+ abortSignal.removeEventListener("abort", onAbort);
1337
+ }
1338
+ };
1339
+
1340
+ try {
1341
+ await awaitAbortable(session.prompt(task, { attribution: "agent" }));
1342
+ await awaitAbortable(session.waitForIdle());
1343
+
1344
+ const reminderToolChoice = buildNamedToolChoice("yield", session.model);
1345
+
1346
+ let retryCount = 0;
1347
+ while (!monitor.yieldCalled() && retryCount < MAX_YIELD_RETRIES && !abortSignal.aborted) {
1348
+ // Skip reminders when the model returned a terminal error (e.g.
1349
+ // rate-limit cap hit, auth failure). Re-prompting would just
1350
+ // hit the same wall, multiplying the failure noise without
1351
+ // any chance of producing a yield.
1352
+ const lastBeforeReminder = session.getLastAssistantMessage();
1353
+ if (lastBeforeReminder?.stopReason === "error") break;
1354
+ try {
1355
+ retryCount++;
1356
+ const reminder = prompt.render(submitReminderTemplate, {
1357
+ retryCount,
1358
+ maxRetries: MAX_YIELD_RETRIES,
1359
+ });
1360
+
1361
+ const isFinalRetry = retryCount >= MAX_YIELD_RETRIES;
1362
+ await awaitAbortable(
1363
+ session.prompt(reminder, {
1364
+ attribution: "agent",
1365
+ synthetic: true,
1366
+ ...(isFinalRetry && reminderToolChoice ? { toolChoice: reminderToolChoice } : {}),
1367
+ }),
1368
+ );
1369
+ await awaitAbortable(session.waitForIdle());
1370
+ } catch (err) {
1371
+ if (abortSignal.aborted || err instanceof ToolAbortError) {
1372
+ // Benign control-flow exit — user cancel (^C) or compaction aborting
1373
+ // pending operations both surface here as ToolAbortError. The outer
1374
+ // catch and finally already mark the run aborted; logging at ERROR
1375
+ // would spam operator dashboards with non-failures.
1376
+ logger.debug("Subagent prompt aborted");
1377
+ } else {
1378
+ logger.error("Subagent prompt failed", {
1379
+ error: err instanceof Error ? err.message : String(err),
1380
+ });
1381
+ }
1382
+ }
1383
+ }
1384
+
1385
+ await awaitAbortable(session.waitForIdle());
1386
+
1387
+ const lastAssistant = session.getLastAssistantMessage();
1388
+ if (lastAssistant) {
1389
+ if (lastAssistant.stopReason === "aborted") {
1390
+ aborted = monitor.isAbortedRun();
1391
+ if (aborted) {
1392
+ // A real caller signal or the wall-clock timer carries a precise
1393
+ // reason (signal.reason / "runtime limit exceeded"). An internal
1394
+ // turn abort does NOT — prefer the assistant message's own
1395
+ // errorMessage ("Request was aborted" or a specific stream error)
1396
+ // over the misleading "Cancelled by caller".
1397
+ abortReasonText ??= monitor.hasExplicitAbortReason()
1398
+ ? monitor.resolveAbortReasonText()
1399
+ : lastAssistant.errorMessage?.trim() || monitor.resolveAbortReasonText();
1400
+ }
1401
+ exitCode = 1;
1402
+ } else if (lastAssistant.stopReason === "error") {
1403
+ exitCode = 1;
1404
+ error ??= lastAssistant.errorMessage || "Subagent failed";
1405
+ }
1406
+ }
1407
+ } catch (err) {
1408
+ exitCode = 1;
1409
+ if (!abortSignal.aborted) {
1410
+ error = err instanceof Error ? err.stack || err.message : String(err);
1411
+ }
1412
+ } finally {
1413
+ if (abortSignal.aborted) {
1414
+ aborted = monitor.isAbortedRun();
1415
+ if (aborted) {
1416
+ abortReasonText ??= monitor.resolveAbortReasonText();
1417
+ }
1418
+ if (exitCode === 0) exitCode = 1;
1419
+ }
1420
+ }
1421
+
1422
+ return { exitCode, error, aborted, abortReasonText };
1423
+ }
1424
+
1425
+ interface FinalizeRunArgs {
1426
+ monitor: SubagentRunMonitor;
1427
+ done: { exitCode: number; error?: string; aborted?: boolean; abortReason?: string; durationMs: number };
1428
+ index: number;
1429
+ id: string;
1430
+ agent: AgentDefinition;
1431
+ task: string;
1432
+ assignment?: string;
1433
+ description?: string;
1434
+ modelOverride?: string | string[];
1435
+ outputSchema?: unknown;
1436
+ signal?: AbortSignal;
1437
+ artifactsDir?: string;
1438
+ eventBus?: EventBus;
1439
+ parentToolCallId?: string;
1440
+ detached?: boolean;
1441
+ sessionFile?: string;
1442
+ startTime: number;
1443
+ }
1444
+
1445
+ /**
1446
+ * Turn a settled run into a {@link SingleResult}: resolve the yield payload via
1447
+ * {@link finalizeSubprocessOutput}, salvage cancelled-run output, write the
1448
+ * `<id>.md` output artifact, flush final progress, and emit the lifecycle end
1449
+ * event.
1450
+ */
1451
+ async function finalizeRunResult(args: FinalizeRunArgs): Promise<SingleResult> {
1452
+ const { monitor, done, index, id, agent, task, assignment, signal, modelOverride } = args;
1453
+ const progress = monitor.progress;
1454
+ let exitCode = done.exitCode;
1455
+ let stderr = done.error ?? "";
1456
+
1457
+ // Use final output if available, otherwise accumulated output
1458
+ let rawOutput = monitor.rawOutput();
1459
+ const yieldItems = progress.extractedToolData?.yield as YieldItem[] | undefined;
1460
+ const reportFindingDetails = progress.extractedToolData?.report_finding as ReportFindingDetails[] | undefined;
1461
+ const reportFindings: ReviewFinding[] | undefined = reportFindingDetails?.map(toReviewFinding);
1462
+ // Breadcrumb the synchronous yield-payload shaping (O(rawOutput)) so a block
1463
+ // here is attributed to this subagent rather than logged as "unknown".
1464
+ pushLoopPhase(`subagent:${id}`);
1465
+ let finalized: FinalizeSubprocessOutputResult;
1466
+ try {
1467
+ finalized = finalizeSubprocessOutput({
1468
+ rawOutput,
1469
+ exitCode,
1470
+ stderr,
1471
+ doneAborted: Boolean(done.aborted),
1472
+ signalAborted: Boolean(signal?.aborted),
1473
+ yieldItems,
1474
+ reportFindings,
1475
+ outputSchema: args.outputSchema,
1476
+ });
1477
+ } finally {
1478
+ popLoopPhase();
1479
+ }
1480
+ rawOutput = finalized.rawOutput;
1481
+ exitCode = finalized.exitCode;
1482
+ stderr = finalized.stderr;
1483
+ // Salvage for cancelled/aborted children that produced no completed output:
1484
+ // surface the last assistant text + stats instead of "(no output)" so the
1485
+ // parent doesn't redo work the child already finished.
1486
+ const salvageText = monitor.lastAssistantSalvageText();
1487
+ if (
1488
+ (done.aborted || signal?.aborted || monitor.runtimeLimitExceeded()) &&
1489
+ !rawOutput.trim() &&
1490
+ salvageText !== undefined
1491
+ ) {
1492
+ rawOutput = `[cancelled after ${progress.requests} req, ${progress.tokens} tok — last activity: "${formatSalvageSnippet(salvageText)}"]`;
1493
+ }
1494
+ const lastYield = yieldItems?.[yieldItems.length - 1];
1495
+ const yieldAbortReason = lastYield?.status === "aborted" ? lastYield.error || "Subagent aborted task" : undefined;
1496
+ const { abortedViaYield, hasYield } = finalized;
1497
+ const { content: truncatedOutput, truncated } = truncateTail(rawOutput, {
1498
+ maxBytes: MAX_OUTPUT_BYTES,
1499
+ maxLines: MAX_OUTPUT_LINES,
1500
+ });
1501
+
1502
+ // Write output artifact (input and jsonl already written in real-time)
1503
+ // Compute output metadata for agent:// URL integration
1504
+ let outputMeta: { lineCount: number; charCount: number } | undefined;
1505
+ let outputPath: string | undefined;
1506
+ if (args.artifactsDir) {
1507
+ outputPath = path.join(args.artifactsDir, `${id}.md`);
1508
+ try {
1509
+ await Bun.write(outputPath, rawOutput);
1510
+ outputMeta = {
1511
+ lineCount: rawOutput.split("\n").length,
1512
+ charCount: rawOutput.length,
1513
+ };
1514
+ } catch {
1515
+ // Non-fatal
1516
+ }
1517
+ }
1518
+
1519
+ // Update final progress. A wall-clock timeout always wins: if the runtime
1520
+ // limit fired we report aborted/failed regardless of whether a yield landed
1521
+ // while we were tearing the session down. The yield data is still surfaced
1522
+ // to the caller via `progress.extractedToolData`, but the exit status must
1523
+ // reflect the timeout so on-call doesn't mistake a stuck run for success.
1524
+ const runtimeLimitExceeded = monitor.runtimeLimitExceeded();
1525
+ if (runtimeLimitExceeded && exitCode === 0) {
1526
+ exitCode = 1;
1527
+ }
1528
+ const wasAborted =
1529
+ runtimeLimitExceeded || abortedViaYield || (!hasYield && (done.aborted || signal?.aborted || false));
1530
+ const finalAbortReason = wasAborted
1531
+ ? runtimeLimitExceeded
1532
+ ? monitor.resolveAbortReasonText()
1533
+ : abortedViaYield
1534
+ ? yieldAbortReason
1535
+ : (done.abortReason ??
1536
+ (signal?.aborted ? monitor.resolveSignalAbortReason() : monitor.resolveAbortReasonText()))
1537
+ : undefined;
1538
+ progress.status = wasAborted ? "aborted" : exitCode === 0 ? "completed" : "failed";
1539
+ monitor.scheduleProgress(true);
1540
+
1541
+ // Emit lifecycle end event after finalization so yield status is reflected
1542
+ if (args.eventBus) {
1543
+ args.eventBus.emit(TASK_SUBAGENT_LIFECYCLE_CHANNEL, {
1544
+ id,
1545
+ agent: agent.name,
1546
+ parentToolCallId: args.parentToolCallId,
1547
+ detached: args.detached,
1548
+ agentSource: agent.source,
1549
+ description: args.description,
1550
+ status: progress.status as "completed" | "failed" | "aborted",
1551
+ sessionFile: args.sessionFile,
1552
+ index,
1553
+ });
1554
+ }
1555
+
1556
+ return {
1557
+ index,
1558
+ id,
1559
+ agent: agent.name,
1560
+ agentSource: agent.source,
1561
+ task,
1562
+ assignment,
1563
+ description: args.description,
1564
+ lastIntent: progress.lastIntent,
1565
+ exitCode,
1566
+ output: truncatedOutput,
1567
+ stderr,
1568
+ truncated: Boolean(truncated),
1569
+ durationMs: Date.now() - args.startTime,
1570
+ tokens: progress.tokens,
1571
+ requests: progress.requests,
1572
+ contextTokens: progress.contextTokens,
1573
+ contextWindow: progress.contextWindow,
1574
+ modelOverride,
1575
+ resolvedModel: progress.resolvedModel,
1576
+ error: exitCode !== 0 && stderr ? stderr : undefined,
1577
+ aborted: wasAborted,
1578
+ abortReason: finalAbortReason,
1579
+ usage: monitor.hasUsage() ? monitor.accumulatedUsage : undefined,
1580
+ outputPath,
1581
+ extractedToolData: progress.extractedToolData,
1582
+ retryFailure: progress.retryFailure,
1583
+ outputMeta,
1584
+ };
1585
+ }
1586
+
1587
+ /**
1588
+ * Run a single agent in-process.
1589
+ */
1590
+ export async function runSubprocess(options: ExecutorOptions): Promise<SingleResult> {
1591
+ const {
1592
+ cwd,
1593
+ agent,
1594
+ task,
1595
+ assignment,
1596
+ index,
1597
+ id,
1598
+ worktree,
1599
+ modelOverride,
1600
+ thinkingLevel,
1601
+ outputSchema,
1602
+ enableLsp,
1603
+ signal,
1604
+ onProgress,
1605
+ } = options;
1606
+ const startTime = Date.now();
1607
+
1608
+ // Check if already aborted
1609
+ if (signal?.aborted) {
1610
+ return {
1611
+ index,
1612
+ id,
1613
+ agent: agent.name,
1614
+ agentSource: agent.source,
1615
+ task,
1616
+ assignment,
1617
+ description: options.description,
1618
+ exitCode: 1,
1619
+ output: "",
1620
+ stderr: "Cancelled before start",
1621
+ truncated: false,
1622
+ durationMs: 0,
1623
+ tokens: 0,
1624
+ requests: 0,
1625
+ modelOverride,
1626
+ error: "Cancelled before start",
1627
+ aborted: true,
1628
+ abortReason: "Cancelled before start",
1629
+ };
1630
+ }
1631
+
1632
+ // Set up artifact paths and write input file upfront if artifacts dir provided
1633
+ let subtaskSessionFile: string | undefined;
1634
+ if (options.artifactsDir) {
1635
+ subtaskSessionFile = path.join(options.artifactsDir, `${id}.jsonl`);
1636
+ }
1637
+
1638
+ const settings = options.settings ?? Settings.isolated();
1639
+ const subagentSettings = createSubagentSettings(
1640
+ settings,
1641
+ agent.readSummarize === false ? { "read.summarize.enabled": false } : undefined,
1642
+ );
1643
+ const maxRecursionDepth = settings.get("task.maxRecursionDepth") ?? 2;
1644
+ // Tailored specialist identity for this spawn. `subagentRole` is the full
1645
+ // (trimmed) role text fed to the system-prompt preamble; `subagentDisplayName`
1646
+ // is the label-normalized form the registry/roster show, falling back to the
1647
+ // agent type name when no role was given.
1648
+ const subagentRole = options.role?.trim() || undefined;
1649
+ const subagentDisplayName = resolveSubagentDisplayName(options.role, agent.name);
1650
+ const maxRuntimeMs = Math.max(
1651
+ 0,
1652
+ Math.trunc(Number(options.maxRuntimeMs ?? settings.get("task.maxRuntimeMs") ?? 0) || 0),
1653
+ );
1654
+ // TTL before an adopted idle subagent is parked by the lifecycle manager.
1655
+ // <= 0 disables parking (the session stays live until process teardown).
1656
+ const agentIdleTtlMs = Math.trunc(Number(settings.get("task.agentIdleTtlMs") ?? 420_000) || 0);
1657
+ const configuredDefaultBudget = Math.max(
1658
+ 0,
1659
+ Math.trunc(Number(settings.get("task.softRequestBudget") ?? SOFT_REQUEST_BUDGET.default) || 0),
1660
+ );
1661
+ const softRequestBudget =
1662
+ configuredDefaultBudget === 0 ? 0 : (SOFT_REQUEST_BUDGET[agent.name] ?? configuredDefaultBudget);
1663
+ const parentDepth = options.taskDepth ?? 0;
1664
+ const childDepth = parentDepth + 1;
1665
+ const atMaxDepth = maxRecursionDepth >= 0 && childDepth >= maxRecursionDepth;
1666
+
1667
+ // Add tools if specified
1668
+ let toolNames: string[] | undefined;
1669
+ if (agent.tools && agent.tools.length > 0) {
1670
+ toolNames = agent.tools;
1671
+ // Auto-include task tool if spawns defined but task not in tools
1672
+ if (agent.spawns !== undefined && !toolNames.includes("task") && !atMaxDepth) {
1673
+ toolNames = [...toolNames, "task"];
1674
+ }
1675
+ }
1676
+
1677
+ if (atMaxDepth && toolNames?.includes("task")) {
1678
+ toolNames = toolNames.filter(name => name !== "task");
1679
+ }
1680
+ // IRC is always available; the COOP prompt section advertises it, so a restricted
1681
+ // whitelist must still carry `irc` for the subagent to actually use it.
1682
+ if (toolNames && !toolNames.includes("irc")) {
1683
+ toolNames = [...toolNames, "irc"];
1684
+ }
1685
+ if (toolNames?.includes("exec")) {
1686
+ const allowEvalPy = settings.get("eval.py") ?? true;
1687
+ const allowEvalJs = settings.get("eval.js") ?? true;
1688
+ const expanded = toolNames.filter(name => name !== "exec");
1689
+ if (allowEvalPy || allowEvalJs) expanded.push("eval");
1690
+ expanded.push("bash");
1691
+ toolNames = Array.from(new Set(expanded));
1692
+ }
1693
+
1694
+ const modelPatterns = normalizeModelPatterns(modelOverride ?? agent.model);
1695
+ const sessionFile = subtaskSessionFile ?? null;
1696
+ const spawnsEnv = atMaxDepth
1697
+ ? ""
1698
+ : agent.spawns === undefined
1699
+ ? ""
1700
+ : agent.spawns === "*"
1701
+ ? "*"
1702
+ : agent.spawns.join(",");
1703
+
1704
+ const lspEnabled = enableLsp ?? true;
1705
+ const ircEnabled = isIrcEnabled(subagentSettings, childDepth);
1706
+ const skipPythonPreflight = Array.isArray(toolNames) && !toolNames.includes("eval");
1707
+
1708
+ const monitor = createSubagentRunMonitor({
1709
+ index,
1710
+ id,
1711
+ agent,
1712
+ task,
1713
+ assignment,
1714
+ description: options.description,
1715
+ modelOverride,
1716
+ signal,
1717
+ onProgress,
1718
+ eventBus: options.eventBus,
1719
+ parentToolCallId: options.parentToolCallId,
1720
+ detached: options.detached,
1721
+ sessionFile: subtaskSessionFile,
1722
+ softRequestBudget,
1723
+ maxRuntimeMs,
1724
+ });
1725
+ const progress = monitor.progress;
1726
+ let unsubscribe: (() => void) | null = null;
1727
+ let reviveSession: (() => Promise<AgentSession>) | null = null;
1728
+ // Adopted (kept-alive) subagents flip registry status from session events on
1729
+ // later turns: revive/wake → running, turn drained → idle. The subscription
1730
+ // intentionally survives this run; a disposed session emits nothing, so it
1731
+ // needs no teardown.
1732
+ const installRegistryStatusSync = (target: AgentSession): void => {
1733
+ target.subscribe(event => {
1734
+ if (event.type === "agent_start") {
1735
+ AgentRegistry.global().setStatus(id, "running");
1736
+ } else if (event.type === "agent_end") {
1737
+ AgentRegistry.global().setStatus(id, "idle");
1738
+ }
1739
+ });
1740
+ };
1741
+
1742
+ const runSubagent = async (): Promise<{
1743
+ exitCode: number;
1744
+ error?: string;
1745
+ aborted?: boolean;
1746
+ abortReason?: string;
1747
+ durationMs: number;
1748
+ }> => {
1749
+ const sessionAbortController = new AbortController();
1750
+ const abortSignal = monitor.abortSignal;
1751
+ let exitCode = 0;
1752
+ let error: string | undefined;
1753
+ let aborted = false;
1754
+ let abortReasonText: string | undefined;
1755
+ const checkAbort = () => {
1756
+ if (abortSignal.aborted) {
1757
+ throw new ToolAbortError();
1758
+ }
1759
+ };
1760
+ const awaitAbortable = async <T>(promise: Promise<T>): Promise<T> => {
1761
+ checkAbort();
1762
+ const { promise: abortPromise, reject } = Promise.withResolvers<never>();
1763
+ const onAbort = () => {
1764
+ try {
1765
+ checkAbort();
1766
+ } catch (err) {
1767
+ reject(err);
1768
+ }
1769
+ };
1770
+ abortSignal.addEventListener("abort", onAbort, { once: true });
1771
+ try {
1772
+ return await Promise.race([promise, abortPromise]);
1773
+ } finally {
1774
+ abortSignal.removeEventListener("abort", onAbort);
1775
+ }
1776
+ };
1777
+
1778
+ try {
1779
+ checkAbort();
1780
+ // Pin authStorage to modelRegistry.authStorage — mirrors the createAgentSession invariant.
1781
+ const registryFromParent = options.modelRegistry !== undefined;
1782
+ const modelRegistry =
1783
+ options.modelRegistry ??
1784
+ new ModelRegistry(options.authStorage ?? (await awaitAbortable(discoverAuthStorage())));
1785
+ const authStorage = modelRegistry.authStorage;
1786
+ if (options.authStorage && options.authStorage !== authStorage) {
1787
+ throw new Error(
1788
+ "options.authStorage and options.modelRegistry.authStorage must be the same instance when both are provided",
1789
+ );
1790
+ }
1791
+ checkAbort();
1792
+ if (!registryFromParent) {
1793
+ await awaitAbortable(modelRegistry.refresh());
1794
+ } else {
1795
+ logger.debug("runSubagent: reusing parent modelRegistry; skipping refresh");
1796
+ }
1797
+ checkAbort();
1798
+
1799
+ const {
1800
+ model,
1801
+ thinkingLevel: resolvedThinkingLevel,
1802
+ explicitThinkingLevel,
1803
+ authFallbackUsed,
1804
+ } = await awaitAbortable(
1805
+ resolveModelOverrideWithAuthFallback(
1806
+ modelPatterns,
1807
+ options.parentActiveModelPattern,
1808
+ modelRegistry,
1809
+ settings,
1810
+ ),
1811
+ );
1812
+ if (authFallbackUsed && model) {
1813
+ logger.warn("Subagent model has no working credentials; falling back to parent session model", {
1814
+ requested: modelPatterns,
1815
+ parentModel: options.parentActiveModelPattern,
1816
+ resolvedProvider: model.provider,
1817
+ resolvedModel: model.id,
1818
+ });
1819
+ }
1820
+ if (model?.contextWindow && model.contextWindow > 0) {
1821
+ progress.contextWindow = model.contextWindow;
1822
+ }
1823
+ if (model) {
1824
+ progress.resolvedModel = explicitThinkingLevel
1825
+ ? `${model.provider}/${model.id}:${resolvedThinkingLevel}`
1826
+ : `${model.provider}/${model.id}`;
1827
+ }
1828
+ const effectiveThinkingLevel = explicitThinkingLevel
1829
+ ? resolvedThinkingLevel
1180
1830
  : (thinkingLevel ?? resolvedThinkingLevel);
1181
1831
 
1182
1832
  const sessionManager = sessionFile
@@ -1195,7 +1845,11 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1195
1845
  // carry the subagent's own agent identity, and use the subagent's
1196
1846
  // own session id for `gen_ai.conversation.id`.
1197
1847
  const subagentAgentIdentity: AgentIdentity | undefined = options.parentTelemetry
1198
- ? { id, name: agent.name, description: agent.description }
1848
+ ? {
1849
+ id,
1850
+ name: subagentDisplayName,
1851
+ description: subagentRole ? oneLineLabel(subagentRole) : agent.description,
1852
+ }
1199
1853
  : undefined;
1200
1854
  const subagentTelemetry: AgentTelemetryConfig | undefined =
1201
1855
  options.parentTelemetry && subagentAgentIdentity
@@ -1221,64 +1875,99 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1221
1875
 
1222
1876
  const { normalized: normalizedOutputSchema } = normalizeSchema(outputSchema);
1223
1877
 
1224
- const { session } = await awaitAbortable(
1225
- createAgentSession({
1226
- cwd: worktree ?? cwd,
1227
- authStorage,
1228
- modelRegistry,
1229
- settings: subagentSettings,
1230
- model,
1231
- thinkingLevel: effectiveThinkingLevel,
1232
- toolNames,
1233
- outputSchema,
1234
- requireYieldTool: true,
1235
- contextFiles: options.contextFiles,
1236
- skills: options.skills,
1237
- promptTemplates: options.promptTemplates,
1238
- workspaceTree: options.workspaceTree,
1239
- systemPrompt: defaultPrompt => {
1240
- const subagentPrompt = prompt.render(subagentSystemPromptTemplate, {
1241
- agent: agent.systemPrompt,
1242
- context: options.context?.trim() ?? "",
1243
- planReference: options.planReference?.content ?? "",
1244
- planReferencePath: options.planReference?.path ?? "",
1245
- worktree: worktree ?? "",
1246
- outputSchema: normalizedOutputSchema,
1247
- contextFile: contextFileForPrompt,
1248
- ircPeers: ircEnabled ? renderIrcPeerRoster(id) : "",
1249
- ircSelfId: ircEnabled ? id : "",
1250
- });
1251
- return defaultPrompt.length === 0
1252
- ? [subagentPrompt]
1253
- : [...defaultPrompt.slice(0, -1), subagentPrompt, defaultPrompt[defaultPrompt.length - 1]];
1254
- },
1255
- sessionManager,
1256
- hasUI: false,
1257
- spawns: spawnsEnv,
1258
- taskDepth: childDepth,
1259
- parentHindsightSessionState: options.parentHindsightSessionState,
1260
- parentMnemopiSessionState: options.parentMnemopiSessionState,
1261
- parentTaskPrefix: id,
1262
- agentId: id,
1263
- agentDisplayName: agent.name,
1264
- enableLsp: lspEnabled,
1265
- skipPythonPreflight,
1266
- enableMCP,
1267
- mcpManager: options.mcpManager,
1268
- customTools: mcpProxyTools.length > 0 ? mcpProxyTools : undefined,
1269
- localProtocolOptions: options.localProtocolOptions,
1270
- telemetry: subagentTelemetry,
1271
- parentEvalSessionId: options.parentEvalSessionId,
1272
- }),
1273
- );
1878
+ // Captured by the lifecycle reviver: rebuilding an equivalent session from
1879
+ // the same JSONL file re-invokes createAgentSession with the exact options
1880
+ // of the original run (same agent id, tools, model, system prompt,
1881
+ // artifacts dir) — only the SessionManager differs.
1882
+ const buildSubagentSessionOptions = (sessionManagerForRun: SessionManager): CreateAgentSessionOptions => ({
1883
+ cwd: worktree ?? cwd,
1884
+ authStorage,
1885
+ modelRegistry,
1886
+ settings: subagentSettings,
1887
+ model,
1888
+ thinkingLevel: effectiveThinkingLevel,
1889
+ toolNames,
1890
+ outputSchema,
1891
+ requireYieldTool: true,
1892
+ contextFiles: options.contextFiles,
1893
+ skills: options.skills,
1894
+ promptTemplates: options.promptTemplates,
1895
+ workspaceTree: options.workspaceTree,
1896
+ rules: options.rules,
1897
+ preloadedExtensionPaths: options.preloadedExtensionPaths,
1898
+ preloadedCustomToolPaths: options.preloadedCustomToolPaths,
1899
+ systemPrompt: defaultPrompt => {
1900
+ const subagentPrompt = prompt.render(subagentSystemPromptTemplate, {
1901
+ agent: agent.systemPrompt,
1902
+ role: subagentRole ? oneLineLabel(subagentRole) : "",
1903
+ context: options.context?.trim() ?? "",
1904
+ planReference: options.planReference?.content ?? "",
1905
+ planReferencePath: options.planReference?.path ?? "",
1906
+ worktree: worktree ?? "",
1907
+ outputSchema: normalizedOutputSchema,
1908
+ ircPeers: ircEnabled ? renderIrcPeerRoster(id) : "",
1909
+ ircSelfId: ircEnabled ? id : "",
1910
+ });
1911
+ return defaultPrompt.length === 0
1912
+ ? [subagentPrompt]
1913
+ : [...defaultPrompt.slice(0, -1), subagentPrompt, defaultPrompt[defaultPrompt.length - 1]];
1914
+ },
1915
+ sessionManager: sessionManagerForRun,
1916
+ hasUI: false,
1917
+ spawns: spawnsEnv,
1918
+ taskDepth: childDepth,
1919
+ parentHindsightSessionState: options.parentHindsightSessionState,
1920
+ parentMnemopiSessionState: options.parentMnemopiSessionState,
1921
+ parentTaskPrefix: id,
1922
+ agentId: id,
1923
+ agentDisplayName: subagentDisplayName,
1924
+ enableLsp: lspEnabled,
1925
+ skipPythonPreflight,
1926
+ enableMCP,
1927
+ mcpManager: options.mcpManager,
1928
+ customTools: mcpProxyTools.length > 0 ? mcpProxyTools : undefined,
1929
+ localProtocolOptions: options.localProtocolOptions,
1930
+ telemetry: subagentTelemetry,
1931
+ parentEvalSessionId: options.parentEvalSessionId,
1932
+ });
1274
1933
 
1275
- activeSession = session;
1934
+ const sessionPromise = createAgentSession(buildSubagentSessionOptions(sessionManager));
1935
+ let session: AgentSession;
1936
+ try {
1937
+ ({ session } = await awaitAbortable(sessionPromise));
1938
+ } catch (err) {
1939
+ // Abort raced session startup. The session may still resolve later
1940
+ // holding live LSP/MCP child processes — dispose it when it does so
1941
+ // a cancelled subagent cannot leak them.
1942
+ void sessionPromise.then(created => created.session.dispose()).catch(() => {});
1943
+ throw err;
1944
+ }
1945
+
1946
+ monitor.setActiveSession(session);
1947
+ installRegistryStatusSync(session);
1948
+ if (sessionFile !== null && worktree === undefined) {
1949
+ // Lifecycle reviver: park closed the JSONL writer, so reopening takes
1950
+ // the single-writer lock cleanly and restores the full message history
1951
+ // (createAgentSession → agent.replaceMessages). Isolated runs are not
1952
+ // resumable (worktree is merged + cleaned) and never get a reviver.
1953
+ reviveSession = async () => {
1954
+ const reopened = await SessionManager.open(sessionFile);
1955
+ if (options.parentArtifactManager) {
1956
+ reopened.adoptArtifactManager(options.parentArtifactManager);
1957
+ }
1958
+ const { session: revived } = await createAgentSession(buildSubagentSessionOptions(reopened));
1959
+ installRegistryStatusSync(revived);
1960
+ return revived;
1961
+ };
1962
+ }
1276
1963
 
1277
1964
  // Emit lifecycle start event
1278
1965
  if (options.eventBus) {
1279
1966
  options.eventBus.emit(TASK_SUBAGENT_LIFECYCLE_CHANNEL, {
1280
1967
  id,
1281
1968
  agent: agent.name,
1969
+ parentToolCallId: options.parentToolCallId,
1970
+ detached: options.detached,
1282
1971
  agentSource: agent.source,
1283
1972
  description: options.description,
1284
1973
  status: "started",
@@ -1316,16 +2005,19 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1316
2005
  }
1317
2006
 
1318
2007
  const extensionRunner = session.extensionRunner;
1319
- const pendingExtensionMessages: Promise<void>[] = [];
2008
+ const pendingExtensionMessages: Promise<unknown>[] = [];
1320
2009
  if (extensionRunner) {
1321
2010
  extensionRunner.initialize(
1322
2011
  {
1323
2012
  sendMessage: (message, options) => {
1324
- const sendPromise = session.sendCustomMessage(message, options).catch(e => {
1325
- logger.error("Extension sendMessage failed", {
1326
- error: e instanceof Error ? e.message : String(e),
2013
+ const sendPromise = session
2014
+ .sendCustomMessage(message, options)
2015
+ .then(() => undefined)
2016
+ .catch(e => {
2017
+ logger.error("Extension sendMessage failed", {
2018
+ error: e instanceof Error ? e.message : String(e),
2019
+ });
1327
2020
  });
1328
- });
1329
2021
  pendingExtensionMessages.push(sendPromise);
1330
2022
  },
1331
2023
  sendUserMessage: (content, options) => {
@@ -1375,43 +2067,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1375
2067
  }
1376
2068
  }
1377
2069
 
1378
- const MAX_YIELD_RETRIES = 3;
1379
- unsubscribe = session.subscribe(event => {
1380
- if (event.type === "auto_retry_start") {
1381
- progress.retryState = {
1382
- attempt: event.attempt,
1383
- maxAttempts: event.maxAttempts,
1384
- delayMs: event.delayMs,
1385
- errorMessage: event.errorMessage,
1386
- startedAtMs: Date.now(),
1387
- };
1388
- progress.retryFailure = undefined;
1389
- scheduleProgress(true);
1390
- return;
1391
- }
1392
- if (event.type === "auto_retry_end") {
1393
- const attempt = progress.retryState?.attempt ?? event.attempt;
1394
- progress.retryState = undefined;
1395
- if (!event.success) {
1396
- progress.retryFailure = {
1397
- attempt,
1398
- errorMessage: event.finalError ?? "Auto-retry failed",
1399
- };
1400
- }
1401
- scheduleProgress(true);
1402
- return;
1403
- }
1404
- if (isAgentEvent(event)) {
1405
- try {
1406
- processEvent(event);
1407
- } catch (err) {
1408
- logger.error("Subagent event processing failed", {
1409
- error: err instanceof Error ? err.message : String(err),
1410
- });
1411
- requestAbort("terminate");
1412
- }
1413
- }
1414
- });
2070
+ unsubscribe = monitor.attach(session);
1415
2071
 
1416
2072
  checkAbort();
1417
2073
  // Autoload skills via sendCustomMessage (same mechanic as /skill:<name>)
@@ -1429,69 +2085,12 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1429
2085
  );
1430
2086
  }
1431
2087
  }
1432
- await awaitAbortable(session.prompt(task, { attribution: "agent" }));
1433
- await awaitAbortable(session.waitForIdle());
1434
-
1435
- const reminderToolChoice = buildNamedToolChoice("yield", session.model);
1436
-
1437
- let retryCount = 0;
1438
- while (!yieldCalled && retryCount < MAX_YIELD_RETRIES && !abortSignal.aborted) {
1439
- // Skip reminders when the model returned a terminal error (e.g.
1440
- // rate-limit cap hit, auth failure). Re-prompting would just
1441
- // hit the same wall, multiplying the failure noise without
1442
- // any chance of producing a yield.
1443
- const lastBeforeReminder = session.getLastAssistantMessage();
1444
- if (lastBeforeReminder?.stopReason === "error") break;
1445
- try {
1446
- retryCount++;
1447
- const reminder = prompt.render(submitReminderTemplate, {
1448
- retryCount,
1449
- maxRetries: MAX_YIELD_RETRIES,
1450
- });
1451
-
1452
- const isFinalRetry = retryCount >= MAX_YIELD_RETRIES;
1453
- await awaitAbortable(
1454
- session.prompt(reminder, {
1455
- attribution: "agent",
1456
- ...(isFinalRetry && reminderToolChoice ? { toolChoice: reminderToolChoice } : {}),
1457
- }),
1458
- );
1459
- await awaitAbortable(session.waitForIdle());
1460
- } catch (err) {
1461
- if (abortSignal.aborted || err instanceof ToolAbortError) {
1462
- // Benign control-flow exit — user cancel (^C) or compaction aborting
1463
- // pending operations both surface here as ToolAbortError. The outer
1464
- // catch and finally already mark the run aborted; logging at ERROR
1465
- // would spam operator dashboards with non-failures.
1466
- logger.debug("Subagent prompt aborted", {
1467
- reason: abortReason ?? "signal",
1468
- });
1469
- } else {
1470
- logger.error("Subagent prompt failed", {
1471
- error: err instanceof Error ? err.message : String(err),
1472
- });
1473
- }
1474
- }
1475
- }
1476
-
1477
- await awaitAbortable(session.waitForIdle());
1478
- if (!yieldCalled && !abortSignal.aborted) {
1479
- exitCode = 0;
1480
- }
1481
2088
 
1482
- const lastAssistant = session.getLastAssistantMessage();
1483
- if (lastAssistant) {
1484
- if (lastAssistant.stopReason === "aborted") {
1485
- aborted = abortReason === "signal" || runtimeLimitExceeded || abortReason === undefined;
1486
- if (aborted) {
1487
- abortReasonText ??= resolveAbortReasonText();
1488
- }
1489
- exitCode = 1;
1490
- } else if (lastAssistant.stopReason === "error") {
1491
- exitCode = 1;
1492
- error ??= lastAssistant.errorMessage || "Subagent failed";
1493
- }
1494
- }
2089
+ const outcome = await driveSessionToYield(session, monitor, task);
2090
+ exitCode = outcome.exitCode;
2091
+ error = outcome.error;
2092
+ aborted = outcome.aborted;
2093
+ abortReasonText = outcome.abortReasonText;
1495
2094
  } catch (err) {
1496
2095
  exitCode = 1;
1497
2096
  if (!abortSignal.aborted) {
@@ -1499,9 +2098,9 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1499
2098
  }
1500
2099
  } finally {
1501
2100
  if (abortSignal.aborted) {
1502
- aborted = abortReason === "signal" || runtimeLimitExceeded || abortReason === undefined;
2101
+ aborted = monitor.isAbortedRun();
1503
2102
  if (aborted) {
1504
- abortReasonText ??= resolveAbortReasonText();
2103
+ abortReasonText ??= monitor.resolveAbortReasonText();
1505
2104
  }
1506
2105
  if (exitCode === 0) exitCode = 1;
1507
2106
  }
@@ -1514,13 +2113,39 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1514
2113
  }
1515
2114
  unsubscribe = null;
1516
2115
  }
1517
- if (activeSession) {
1518
- const session = activeSession;
1519
- activeSession = null;
1520
- try {
1521
- await untilAborted(AbortSignal.timeout(5000), () => session.dispose());
1522
- } catch {
1523
- // Ignore cleanup errors
2116
+ const session = monitor.takeActiveSession();
2117
+ if (session) {
2118
+ monitor.captureSalvage(session);
2119
+ const registry = AgentRegistry.global();
2120
+ if (aborted) {
2121
+ // Hard abort (caller signal / wall-clock / budget): terminal teardown.
2122
+ registry.setStatus(id, "aborted");
2123
+ try {
2124
+ await untilAborted(AbortSignal.timeout(5000), () => session.dispose());
2125
+ } catch {
2126
+ // Ignore cleanup errors
2127
+ }
2128
+ } else if (worktree !== undefined) {
2129
+ // Isolated run: the worktree is merged + cleaned after the run, so
2130
+ // the session is not resumable. Park the ref WITHOUT adopting — the
2131
+ // transcript stays reachable (history://), but ensureLive will throw.
2132
+ // Status must flip to "parked" before dispose so the sdk dispose
2133
+ // wrapper skips unregister.
2134
+ registry.setStatus(id, "parked");
2135
+ try {
2136
+ await untilAborted(AbortSignal.timeout(5000), () => session.dispose());
2137
+ } catch {
2138
+ // Ignore cleanup errors
2139
+ }
2140
+ registry.detachSession(id);
2141
+ } else {
2142
+ // Keep-alive: finished and failed subagents both stay interrogable.
2143
+ // The lifecycle manager owns idle-TTL parking + revival from here on.
2144
+ registry.setStatus(id, "idle");
2145
+ AgentLifecycleManager.global().adopt(id, {
2146
+ idleTtlMs: agentIdleTtlMs,
2147
+ revive: reviveSession ?? undefined,
2148
+ });
1524
2149
  }
1525
2150
  }
1526
2151
  }
@@ -1535,125 +2160,25 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1535
2160
  };
1536
2161
 
1537
2162
  const done = await runSubagent();
1538
- resolved = true;
1539
- listenerController.abort();
1540
- if (runtimeTimeoutId !== undefined) {
1541
- clearTimeout(runtimeTimeoutId);
1542
- runtimeTimeoutId = undefined;
1543
- }
1544
-
1545
- if (progressTimeoutId) {
1546
- clearTimeout(progressTimeoutId);
1547
- progressTimeoutId = null;
1548
- }
1549
-
1550
- let exitCode = done.exitCode;
1551
- if (done.error) {
1552
- stderr = done.error;
1553
- }
1554
-
1555
- // Use final output if available, otherwise accumulated output
1556
- let rawOutput = finalOutputChunks.length > 0 ? finalOutputChunks.join("") : outputChunks.join("");
1557
- const yieldItems = progress.extractedToolData?.yield as YieldItem[] | undefined;
1558
- const reportFindingDetails = progress.extractedToolData?.report_finding as ReportFindingDetails[] | undefined;
1559
- const reportFindings: ReviewFinding[] | undefined = reportFindingDetails?.map(toReviewFinding);
1560
- const finalized = finalizeSubprocessOutput({
1561
- rawOutput,
1562
- exitCode,
1563
- stderr,
1564
- doneAborted: Boolean(done.aborted),
1565
- signalAborted: Boolean(signal?.aborted),
1566
- yieldItems,
1567
- reportFindings,
1568
- outputSchema,
1569
- });
1570
- rawOutput = finalized.rawOutput;
1571
- exitCode = finalized.exitCode;
1572
- stderr = finalized.stderr;
1573
- const lastYield = yieldItems?.[yieldItems.length - 1];
1574
- const yieldAbortReason = lastYield?.status === "aborted" ? lastYield.error || "Subagent aborted task" : undefined;
1575
- const { abortedViaYield, hasYield } = finalized;
1576
- const { content: truncatedOutput, truncated } = truncateTail(rawOutput, {
1577
- maxBytes: MAX_OUTPUT_BYTES,
1578
- maxLines: MAX_OUTPUT_LINES,
1579
- });
1580
-
1581
- // Write output artifact (input and jsonl already written in real-time)
1582
- // Compute output metadata for agent:// URL integration
1583
- let outputMeta: { lineCount: number; charCount: number } | undefined;
1584
- let outputPath: string | undefined;
1585
- if (options.artifactsDir) {
1586
- outputPath = path.join(options.artifactsDir, `${id}.md`);
1587
- try {
1588
- await Bun.write(outputPath, rawOutput);
1589
- outputMeta = {
1590
- lineCount: rawOutput.split("\n").length,
1591
- charCount: rawOutput.length,
1592
- };
1593
- } catch {
1594
- // Non-fatal
1595
- }
1596
- }
1597
-
1598
- // Update final progress. A wall-clock timeout always wins: if the runtime
1599
- // limit fired we report aborted/failed regardless of whether a yield landed
1600
- // while we were tearing the session down. The yield data is still surfaced
1601
- // to the caller via `progress.extractedToolData`, but the exit status must
1602
- // reflect the timeout so on-call doesn't mistake a stuck run for success.
1603
- if (runtimeLimitExceeded && exitCode === 0) {
1604
- exitCode = 1;
1605
- }
1606
- const wasAborted =
1607
- runtimeLimitExceeded || abortedViaYield || (!hasYield && (done.aborted || signal?.aborted || false));
1608
- const finalAbortReason = wasAborted
1609
- ? runtimeLimitExceeded
1610
- ? resolveAbortReasonText()
1611
- : abortedViaYield
1612
- ? yieldAbortReason
1613
- : (done.abortReason ?? (signal?.aborted ? resolveSignalAbortReason() : resolveAbortReasonText()))
1614
- : undefined;
1615
- progress.status = wasAborted ? "aborted" : exitCode === 0 ? "completed" : "failed";
1616
- scheduleProgress(true);
2163
+ monitor.finish();
1617
2164
 
1618
- // Emit lifecycle end event after finalization so yield status is reflected
1619
- if (options.eventBus) {
1620
- options.eventBus.emit(TASK_SUBAGENT_LIFECYCLE_CHANNEL, {
1621
- id,
1622
- agent: agent.name,
1623
- agentSource: agent.source,
1624
- description: options.description,
1625
- status: progress.status as "completed" | "failed" | "aborted",
1626
- sessionFile: subtaskSessionFile,
1627
- index,
1628
- });
1629
- }
1630
-
1631
- return {
2165
+ return finalizeRunResult({
2166
+ monitor,
2167
+ done,
1632
2168
  index,
1633
2169
  id,
1634
- agent: agent.name,
1635
- agentSource: agent.source,
2170
+ agent,
1636
2171
  task,
1637
2172
  assignment,
1638
2173
  description: options.description,
1639
- lastIntent: progress.lastIntent,
1640
- exitCode,
1641
- output: truncatedOutput,
1642
- stderr,
1643
- truncated: Boolean(truncated),
1644
- durationMs: Date.now() - startTime,
1645
- tokens: progress.tokens,
1646
- contextTokens: progress.contextTokens,
1647
- contextWindow: progress.contextWindow,
1648
2174
  modelOverride,
1649
- resolvedModel: progress.resolvedModel,
1650
- error: exitCode !== 0 && stderr ? stderr : undefined,
1651
- aborted: wasAborted,
1652
- abortReason: finalAbortReason,
1653
- usage: hasUsage ? accumulatedUsage : undefined,
1654
- outputPath,
1655
- extractedToolData: progress.extractedToolData,
1656
- retryFailure: progress.retryFailure,
1657
- outputMeta,
1658
- };
2175
+ outputSchema,
2176
+ signal,
2177
+ artifactsDir: options.artifactsDir,
2178
+ eventBus: options.eventBus,
2179
+ parentToolCallId: options.parentToolCallId,
2180
+ detached: options.detached,
2181
+ sessionFile: subtaskSessionFile,
2182
+ startTime,
2183
+ });
1659
2184
  }