@oh-my-pi/pi-coding-agent 15.10.10 → 15.10.12

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 (415) hide show
  1. package/CHANGELOG.md +142 -7
  2. package/dist/cli.js +23108 -0
  3. package/dist/tokenizers.linux-x64-gnu-xcjh3jwk.node +0 -0
  4. package/dist/types/async/job-manager.d.ts +18 -0
  5. package/dist/types/cli/args.d.ts +2 -1
  6. package/dist/types/cli/dry-balance-cli.d.ts +1 -1
  7. package/dist/types/cli/gallery-cli.d.ts +1 -1
  8. package/dist/types/cli/gallery-fixtures/types.d.ts +1 -1
  9. package/dist/types/cli/usage-cli.d.ts +72 -0
  10. package/dist/types/cli-commands.d.ts +12 -0
  11. package/dist/types/commands/launch.d.ts +5 -1
  12. package/dist/types/commands/read.d.ts +1 -1
  13. package/dist/types/commands/usage.d.ts +25 -0
  14. package/dist/types/config/api-key-resolver.d.ts +3 -0
  15. package/dist/types/config/append-only-context-mode.d.ts +2 -1
  16. package/dist/types/config/model-discovery.d.ts +55 -0
  17. package/dist/types/config/model-registry.d.ts +8 -219
  18. package/dist/types/config/model-resolver.d.ts +34 -10
  19. package/dist/types/config/model-roles.d.ts +28 -0
  20. package/dist/types/config/models-config-schema.d.ts +523 -42
  21. package/dist/types/config/models-config.d.ts +385 -0
  22. package/dist/types/config/settings-schema.d.ts +41 -8
  23. package/dist/types/config/settings.d.ts +8 -1
  24. package/dist/types/debug/log-viewer.d.ts +1 -1
  25. package/dist/types/debug/raw-sse.d.ts +1 -1
  26. package/dist/types/edit/hashline/noop-loop-guard.d.ts +72 -0
  27. package/dist/types/eval/backend.d.ts +0 -2
  28. package/dist/types/eval/idle-timeout.d.ts +0 -4
  29. package/dist/types/eval/js/shared/rewrite-imports.d.ts +6 -6
  30. package/dist/types/eval/py/executor.d.ts +5 -0
  31. package/dist/types/eval/py/kernel.d.ts +6 -1
  32. package/dist/types/eval/py/runtime.d.ts +9 -0
  33. package/dist/types/exec/bash-executor.d.ts +2 -0
  34. package/dist/types/export/html/template.generated.d.ts +1 -1
  35. package/dist/types/extensibility/extensions/runner.d.ts +3 -2
  36. package/dist/types/extensibility/extensions/types.d.ts +6 -3
  37. package/dist/types/hindsight/mental-models.d.ts +17 -8
  38. package/dist/types/internal-urls/artifact-protocol.d.ts +2 -2
  39. package/dist/types/internal-urls/types.d.ts +1 -1
  40. package/dist/types/lsp/edits.d.ts +9 -0
  41. package/dist/types/lsp/index.d.ts +2 -2
  42. package/dist/types/lsp/types.d.ts +2 -0
  43. package/dist/types/lsp/utils.d.ts +3 -0
  44. package/dist/types/mcp/json-rpc.d.ts +5 -0
  45. package/dist/types/memory-backend/index.d.ts +1 -0
  46. package/dist/types/memory-backend/runtime.d.ts +4 -0
  47. package/dist/types/memory-backend/types.d.ts +66 -1
  48. package/dist/types/mnemopi/state.d.ts +11 -1
  49. package/dist/types/modes/components/agent-dashboard.d.ts +1 -1
  50. package/dist/types/modes/components/assistant-message.d.ts +3 -1
  51. package/dist/types/modes/components/bash-execution.d.ts +1 -1
  52. package/dist/types/modes/components/copy-selector.d.ts +1 -1
  53. package/dist/types/modes/components/dynamic-border.d.ts +1 -1
  54. package/dist/types/modes/components/extensions/extension-dashboard.d.ts +1 -1
  55. package/dist/types/modes/components/extensions/extension-list.d.ts +1 -1
  56. package/dist/types/modes/components/extensions/inspector-panel.d.ts +1 -1
  57. package/dist/types/modes/components/footer.d.ts +1 -1
  58. package/dist/types/modes/components/hook-editor.d.ts +5 -0
  59. package/dist/types/modes/components/hook-input.d.ts +4 -0
  60. package/dist/types/modes/components/hook-selector.d.ts +1 -1
  61. package/dist/types/modes/components/model-selector.d.ts +1 -1
  62. package/dist/types/modes/components/plan-review-overlay.d.ts +1 -1
  63. package/dist/types/modes/components/session-observer-overlay.d.ts +1 -1
  64. package/dist/types/modes/components/session-selector.d.ts +1 -1
  65. package/dist/types/modes/components/status-line/component.d.ts +1 -1
  66. package/dist/types/modes/components/tiny-title-download-progress.d.ts +1 -1
  67. package/dist/types/modes/components/transcript-container.d.ts +25 -6
  68. package/dist/types/modes/components/tree-selector.d.ts +1 -1
  69. package/dist/types/modes/components/user-message-selector.d.ts +1 -1
  70. package/dist/types/modes/components/user-message.d.ts +2 -1
  71. package/dist/types/modes/components/visual-truncate.d.ts +1 -1
  72. package/dist/types/modes/components/welcome.d.ts +19 -3
  73. package/dist/types/modes/controllers/mcp-command-controller.d.ts +1 -1
  74. package/dist/types/modes/controllers/streaming-reveal.d.ts +1 -1
  75. package/dist/types/modes/index.d.ts +3 -3
  76. package/dist/types/modes/interactive-mode.d.ts +8 -3
  77. package/dist/types/modes/oauth-manual-input.d.ts +7 -0
  78. package/dist/types/modes/rpc/rpc-client.d.ts +39 -2
  79. package/dist/types/modes/rpc/rpc-mode.d.ts +31 -2
  80. package/dist/types/modes/rpc/rpc-subagents.d.ts +24 -0
  81. package/dist/types/modes/rpc/rpc-types.d.ts +75 -1
  82. package/dist/types/modes/setup-wizard/index.d.ts +5 -1
  83. package/dist/types/modes/setup-wizard/lazy.d.ts +2 -0
  84. package/dist/types/modes/setup-wizard/scenes/sign-in.d.ts +1 -1
  85. package/dist/types/modes/setup-wizard/scenes/types.d.ts +1 -1
  86. package/dist/types/modes/setup-wizard/scenes/web-search.d.ts +1 -1
  87. package/dist/types/modes/setup-wizard/wizard-overlay.d.ts +1 -1
  88. package/dist/types/modes/types.d.ts +4 -1
  89. package/dist/types/secrets/index.d.ts +1 -1
  90. package/dist/types/secrets/obfuscator.d.ts +8 -2
  91. package/dist/types/session/agent-session.d.ts +15 -3
  92. package/dist/types/session/auth-broker-config.d.ts +4 -0
  93. package/dist/types/session/session-manager.d.ts +1 -1
  94. package/dist/types/session/streaming-output.d.ts +23 -0
  95. package/dist/types/slash-commands/acp-builtins.d.ts +16 -0
  96. package/dist/types/slash-commands/builtin-registry.d.ts +1 -0
  97. package/dist/types/slash-commands/helpers/stats-dashboard.d.ts +13 -0
  98. package/dist/types/slash-commands/types.d.ts +1 -1
  99. package/dist/types/ssh/connection-manager.d.ts +8 -0
  100. package/dist/types/system-prompt.d.ts +2 -0
  101. package/dist/types/task/executor.d.ts +1 -0
  102. package/dist/types/task/index.d.ts +2 -2
  103. package/dist/types/task/parallel.d.ts +2 -2
  104. package/dist/types/task/types.d.ts +8 -0
  105. package/dist/types/task/worktree.d.ts +2 -0
  106. package/dist/types/thinking.d.ts +4 -0
  107. package/dist/types/tiny/title-client.d.ts +11 -0
  108. package/dist/types/tiny/title-protocol.d.ts +1 -0
  109. package/dist/types/tools/ask.d.ts +4 -0
  110. package/dist/types/tools/conflict-detect.d.ts +16 -0
  111. package/dist/types/tools/github-cache.d.ts +7 -0
  112. package/dist/types/tools/index.d.ts +6 -0
  113. package/dist/types/tools/sqlite-reader.d.ts +3 -0
  114. package/dist/types/tui/output-block.d.ts +3 -3
  115. package/dist/types/utils/changelog.d.ts +8 -0
  116. package/dist/types/utils/git.d.ts +15 -2
  117. package/dist/types/utils/title-generator.d.ts +3 -2
  118. package/dist/types/web/scrapers/readthedocs.d.ts +3 -0
  119. package/dist/types/web/scrapers/types.d.ts +12 -0
  120. package/dist/types/web/search/providers/codex.d.ts +1 -1
  121. package/dist/types/web/search/providers/gemini.d.ts +1 -1
  122. package/examples/extensions/tools.ts +5 -4
  123. package/package.json +14 -11
  124. package/scripts/build-binary.ts +18 -23
  125. package/scripts/bundle-dist.ts +81 -0
  126. package/scripts/{dev-launch → omp} +1 -1
  127. package/scripts/{dev-launch-preload.ts → omp.ts} +1 -1
  128. package/src/async/job-manager.ts +57 -3
  129. package/src/auto-thinking/classifier.ts +1 -0
  130. package/src/autoresearch/dashboard.ts +1 -1
  131. package/src/autoresearch/prompt-setup.md +6 -6
  132. package/src/autoresearch/prompt.md +6 -6
  133. package/src/capability/fs.ts +10 -0
  134. package/src/cli/args.ts +4 -1
  135. package/src/cli/auth-gateway-cli.ts +1 -3
  136. package/src/cli/dry-balance-cli.ts +1 -1
  137. package/src/cli/gallery-cli.ts +1 -1
  138. package/src/cli/gallery-fixtures/fs.ts +1 -1
  139. package/src/cli/gallery-fixtures/types.ts +5 -1
  140. package/src/cli/list-models.ts +2 -1
  141. package/src/cli/usage-cli.ts +603 -0
  142. package/src/cli-commands.ts +30 -0
  143. package/src/cli.ts +76 -13
  144. package/src/commands/complete.ts +1 -1
  145. package/src/commands/launch.ts +5 -1
  146. package/src/commands/read.ts +6 -3
  147. package/src/commands/usage.ts +35 -0
  148. package/src/commit/agentic/agent.ts +1 -1
  149. package/src/commit/model-selection.ts +4 -3
  150. package/src/config/api-key-resolver.ts +8 -6
  151. package/src/config/append-only-context-mode.ts +6 -12
  152. package/src/config/model-discovery.ts +554 -0
  153. package/src/config/model-registry.ts +320 -1041
  154. package/src/config/model-resolver.ts +173 -156
  155. package/src/config/model-roles.ts +74 -0
  156. package/src/config/models-config-schema.ts +57 -8
  157. package/src/config/models-config.ts +129 -0
  158. package/src/config/settings-schema.ts +61 -19
  159. package/src/config/settings.ts +98 -4
  160. package/src/dap/client.ts +124 -37
  161. package/src/dap/session.ts +259 -158
  162. package/src/debug/log-viewer.ts +1 -1
  163. package/src/debug/raw-sse.ts +1 -1
  164. package/src/edit/diff.ts +47 -3
  165. package/src/edit/hashline/block-resolver.ts +20 -1
  166. package/src/edit/hashline/diff.ts +36 -1
  167. package/src/edit/hashline/execute.ts +47 -4
  168. package/src/edit/hashline/noop-loop-guard.ts +99 -0
  169. package/src/edit/index.ts +16 -1
  170. package/src/edit/modes/patch.ts +52 -0
  171. package/src/edit/modes/replace.ts +56 -22
  172. package/src/edit/notebook.ts +22 -2
  173. package/src/edit/renderer.ts +36 -10
  174. package/src/eval/__tests__/completion-bridge.test.ts +1 -1
  175. package/src/eval/backend.ts +0 -2
  176. package/src/eval/completion-bridge.ts +3 -1
  177. package/src/eval/idle-timeout.ts +2 -9
  178. package/src/eval/js/context-manager.ts +6 -8
  179. package/src/eval/js/executor.ts +6 -2
  180. package/src/eval/js/index.ts +0 -2
  181. package/src/eval/js/shared/helpers.ts +5 -6
  182. package/src/eval/js/shared/local-module-loader.ts +1 -1
  183. package/src/eval/js/shared/prelude.txt +62 -1
  184. package/src/eval/js/shared/rewrite-imports.ts +40 -22
  185. package/src/eval/js/shared/runtime.ts +1 -1
  186. package/src/eval/py/executor.ts +29 -7
  187. package/src/eval/py/index.ts +6 -3
  188. package/src/eval/py/kernel.ts +43 -4
  189. package/src/eval/py/runner.py +107 -3
  190. package/src/eval/py/runtime.ts +37 -0
  191. package/src/exec/bash-executor.ts +85 -4
  192. package/src/export/html/template.generated.ts +1 -1
  193. package/src/export/html/template.js +3 -1
  194. package/src/extensibility/extensions/get-commands-handler.ts +2 -1
  195. package/src/extensibility/extensions/runner.ts +6 -1
  196. package/src/extensibility/extensions/types.ts +6 -2
  197. package/src/extensibility/plugins/legacy-pi-compat.ts +20 -3
  198. package/src/hindsight/bank.ts +17 -2
  199. package/src/hindsight/mental-models.ts +59 -12
  200. package/src/hindsight/state.ts +6 -1
  201. package/src/internal-urls/artifact-protocol.ts +11 -2
  202. package/src/internal-urls/docs-index.generated.ts +11 -11
  203. package/src/internal-urls/issue-pr-protocol.ts +12 -5
  204. package/src/internal-urls/router.ts +1 -1
  205. package/src/internal-urls/types.ts +1 -1
  206. package/src/lib/xai-http.ts +1 -1
  207. package/src/lsp/client.ts +118 -38
  208. package/src/lsp/clients/biome-client.ts +101 -39
  209. package/src/lsp/edits.ts +143 -95
  210. package/src/lsp/index.ts +31 -22
  211. package/src/lsp/render.ts +1 -1
  212. package/src/lsp/types.ts +2 -0
  213. package/src/lsp/utils.ts +28 -10
  214. package/src/main.ts +183 -23
  215. package/src/mcp/json-rpc.ts +35 -5
  216. package/src/mcp/transports/stdio.ts +7 -1
  217. package/src/memories/index.ts +4 -1
  218. package/src/memory-backend/index.ts +1 -0
  219. package/src/memory-backend/local-backend.ts +9 -0
  220. package/src/memory-backend/off-backend.ts +9 -0
  221. package/src/memory-backend/runtime.ts +66 -0
  222. package/src/memory-backend/types.ts +81 -1
  223. package/src/mnemopi/backend.ts +176 -7
  224. package/src/mnemopi/state.ts +38 -2
  225. package/src/modes/acp/acp-agent.ts +119 -11
  226. package/src/modes/components/agent-dashboard.ts +10 -7
  227. package/src/modes/components/assistant-message.ts +32 -28
  228. package/src/modes/components/bash-execution.ts +1 -1
  229. package/src/modes/components/copy-selector.ts +1 -1
  230. package/src/modes/components/diff.ts +13 -2
  231. package/src/modes/components/dynamic-border.ts +12 -3
  232. package/src/modes/components/extensions/extension-dashboard.ts +8 -5
  233. package/src/modes/components/extensions/extension-list.ts +1 -1
  234. package/src/modes/components/extensions/inspector-panel.ts +1 -1
  235. package/src/modes/components/footer.ts +4 -2
  236. package/src/modes/components/history-search.ts +1 -1
  237. package/src/modes/components/hook-editor.ts +8 -0
  238. package/src/modes/components/hook-input.ts +8 -0
  239. package/src/modes/components/hook-selector.ts +2 -2
  240. package/src/modes/components/model-selector.ts +4 -2
  241. package/src/modes/components/plan-review-overlay.ts +1 -1
  242. package/src/modes/components/session-observer-overlay.ts +2 -2
  243. package/src/modes/components/session-selector.ts +1 -1
  244. package/src/modes/components/settings-selector.ts +5 -1
  245. package/src/modes/components/status-line/component.ts +119 -35
  246. package/src/modes/components/tiny-title-download-progress.ts +1 -1
  247. package/src/modes/components/transcript-container.ts +258 -53
  248. package/src/modes/components/tree-selector.ts +3 -3
  249. package/src/modes/components/user-message-selector.ts +1 -1
  250. package/src/modes/components/user-message.ts +17 -5
  251. package/src/modes/components/visual-truncate.ts +1 -1
  252. package/src/modes/components/welcome.ts +108 -26
  253. package/src/modes/controllers/command-controller.ts +11 -4
  254. package/src/modes/controllers/event-controller.ts +73 -4
  255. package/src/modes/controllers/input-controller.ts +2 -1
  256. package/src/modes/controllers/mcp-command-controller.ts +39 -4
  257. package/src/modes/controllers/selector-controller.ts +1 -1
  258. package/src/modes/controllers/streaming-reveal.ts +85 -18
  259. package/src/modes/index.ts +3 -21
  260. package/src/modes/interactive-mode.ts +42 -18
  261. package/src/modes/oauth-manual-input.ts +30 -3
  262. package/src/modes/rpc/rpc-client.ts +154 -3
  263. package/src/modes/rpc/rpc-mode.ts +97 -12
  264. package/src/modes/rpc/rpc-subagents.ts +265 -0
  265. package/src/modes/rpc/rpc-types.ts +81 -1
  266. package/src/modes/setup-wizard/index.ts +12 -2
  267. package/src/modes/setup-wizard/lazy.ts +16 -0
  268. package/src/modes/setup-wizard/scenes/glyph.ts +1 -1
  269. package/src/modes/setup-wizard/scenes/providers.ts +1 -1
  270. package/src/modes/setup-wizard/scenes/sign-in.ts +1 -1
  271. package/src/modes/setup-wizard/scenes/theme.ts +1 -1
  272. package/src/modes/setup-wizard/scenes/types.ts +1 -1
  273. package/src/modes/setup-wizard/scenes/web-search.ts +1 -1
  274. package/src/modes/setup-wizard/wizard-overlay.ts +1 -1
  275. package/src/modes/types.ts +4 -1
  276. package/src/prompts/agents/explore.md +2 -2
  277. package/src/prompts/agents/librarian.md +1 -2
  278. package/src/prompts/agents/oracle.md +1 -1
  279. package/src/prompts/agents/plan.md +5 -5
  280. package/src/prompts/agents/task.md +5 -5
  281. package/src/prompts/ci-green-request.md +5 -7
  282. package/src/prompts/goals/goal-budget-limit.md +2 -2
  283. package/src/prompts/goals/goal-continuation.md +4 -4
  284. package/src/prompts/goals/goal-mode-active.md +1 -1
  285. package/src/prompts/memories/read-path.md +1 -1
  286. package/src/prompts/memories/stage_one_system.md +2 -2
  287. package/src/prompts/review-custom-request.md +1 -1
  288. package/src/prompts/system/agent-creation-architect.md +2 -2
  289. package/src/prompts/system/auto-continue.md +1 -1
  290. package/src/prompts/system/background-tan-dispatch.md +1 -1
  291. package/src/prompts/system/btw-user.md +2 -2
  292. package/src/prompts/system/commit-message-system.md +13 -1
  293. package/src/prompts/system/custom-system-prompt.md +1 -1
  294. package/src/prompts/system/eager-todo.md +2 -2
  295. package/src/prompts/system/irc-incoming.md +1 -1
  296. package/src/prompts/system/manual-continue.md +1 -1
  297. package/src/prompts/system/omfg-user.md +3 -4
  298. package/src/prompts/system/orchestrate-notice.md +9 -9
  299. package/src/prompts/system/plan-mode-active.md +4 -4
  300. package/src/prompts/system/plan-mode-subagent.md +4 -5
  301. package/src/prompts/system/plan-mode-tool-decision-reminder.md +1 -1
  302. package/src/prompts/system/project-prompt.md +2 -2
  303. package/src/prompts/system/subagent-system-prompt.md +4 -4
  304. package/src/prompts/system/system-prompt.md +13 -24
  305. package/src/prompts/system/title-system.md +2 -2
  306. package/src/prompts/system/ttsr-tool-reminder.md +1 -1
  307. package/src/prompts/system/workflow-notice.md +1 -1
  308. package/src/prompts/tools/ast-edit.md +1 -1
  309. package/src/prompts/tools/ast-grep.md +2 -2
  310. package/src/prompts/tools/bash.md +5 -7
  311. package/src/prompts/tools/browser.md +7 -7
  312. package/src/prompts/tools/debug.md +1 -1
  313. package/src/prompts/tools/eval.md +3 -3
  314. package/src/prompts/tools/find.md +0 -1
  315. package/src/prompts/tools/github.md +8 -7
  316. package/src/prompts/tools/goal.md +1 -1
  317. package/src/prompts/tools/image-gen.md +1 -1
  318. package/src/prompts/tools/inspect-image-system.md +1 -1
  319. package/src/prompts/tools/irc.md +15 -15
  320. package/src/prompts/tools/lsp.md +2 -2
  321. package/src/prompts/tools/patch.md +2 -2
  322. package/src/prompts/tools/read.md +3 -4
  323. package/src/prompts/tools/recall.md +1 -1
  324. package/src/prompts/tools/reflect.md +1 -1
  325. package/src/prompts/tools/render-mermaid.md +2 -2
  326. package/src/prompts/tools/replace.md +4 -10
  327. package/src/prompts/tools/rewind.md +2 -2
  328. package/src/prompts/tools/search-tool-bm25.md +1 -9
  329. package/src/prompts/tools/search.md +0 -1
  330. package/src/prompts/tools/ssh.md +0 -4
  331. package/src/prompts/tools/task.md +2 -3
  332. package/src/prompts/tools/todo.md +1 -1
  333. package/src/sdk.ts +31 -11
  334. package/src/secrets/index.ts +8 -1
  335. package/src/secrets/obfuscator.ts +39 -18
  336. package/src/session/agent-session.ts +223 -64
  337. package/src/session/auth-broker-config.ts +30 -1
  338. package/src/session/session-manager.ts +2 -2
  339. package/src/session/streaming-output.ts +188 -11
  340. package/src/slash-commands/acp-builtins.ts +24 -0
  341. package/src/slash-commands/builtin-registry.ts +40 -0
  342. package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
  343. package/src/slash-commands/types.ts +1 -1
  344. package/src/ssh/connection-manager.ts +27 -0
  345. package/src/system-prompt.ts +14 -0
  346. package/src/task/commands.ts +2 -1
  347. package/src/task/executor.ts +74 -65
  348. package/src/task/index.ts +146 -68
  349. package/src/task/parallel.ts +3 -3
  350. package/src/task/render.ts +20 -5
  351. package/src/task/types.ts +9 -0
  352. package/src/task/worktree.ts +64 -56
  353. package/src/thinking.ts +9 -1
  354. package/src/tiny/title-client.ts +60 -16
  355. package/src/tiny/title-protocol.ts +1 -1
  356. package/src/tiny/worker.ts +6 -4
  357. package/src/tools/archive-reader.ts +30 -2
  358. package/src/tools/ask.ts +104 -21
  359. package/src/tools/ast-edit.ts +25 -5
  360. package/src/tools/auto-generated-guard.ts +20 -3
  361. package/src/tools/bash-interactive.ts +27 -7
  362. package/src/tools/bash.ts +100 -18
  363. package/src/tools/browser/launch.ts +11 -2
  364. package/src/tools/browser/readable.ts +19 -2
  365. package/src/tools/browser/registry.ts +4 -1
  366. package/src/tools/browser/render.ts +2 -2
  367. package/src/tools/browser/tab-supervisor.ts +55 -16
  368. package/src/tools/conflict-detect.ts +50 -4
  369. package/src/tools/debug.ts +1 -1
  370. package/src/tools/eval-render.ts +5 -5
  371. package/src/tools/eval.ts +0 -2
  372. package/src/tools/fetch.ts +33 -10
  373. package/src/tools/gh-cache-invalidation.ts +63 -8
  374. package/src/tools/gh-renderer.ts +1 -1
  375. package/src/tools/gh.ts +172 -29
  376. package/src/tools/github-cache.ts +70 -6
  377. package/src/tools/image-gen.ts +14 -13
  378. package/src/tools/index.ts +13 -1
  379. package/src/tools/inspect-image.ts +1 -0
  380. package/src/tools/irc.ts +5 -1
  381. package/src/tools/job.ts +1 -1
  382. package/src/tools/read.ts +202 -61
  383. package/src/tools/render-utils.ts +3 -3
  384. package/src/tools/resolve.ts +1 -1
  385. package/src/tools/search.ts +92 -29
  386. package/src/tools/sqlite-reader.ts +17 -5
  387. package/src/tools/ssh.ts +8 -8
  388. package/src/tools/todo.ts +38 -8
  389. package/src/tools/write.ts +118 -18
  390. package/src/tui/output-block.ts +4 -4
  391. package/src/utils/changelog.ts +27 -1
  392. package/src/utils/commit-message-generator.ts +1 -0
  393. package/src/utils/file-mentions.ts +2 -1
  394. package/src/utils/git.ts +267 -13
  395. package/src/utils/title-generator.ts +24 -5
  396. package/src/web/scrapers/arxiv.ts +1 -1
  397. package/src/web/scrapers/go-pkg.ts +1 -1
  398. package/src/web/scrapers/iacr.ts +1 -1
  399. package/src/web/scrapers/readthedocs.ts +1 -1
  400. package/src/web/scrapers/twitter.ts +2 -1
  401. package/src/web/scrapers/types.ts +87 -8
  402. package/src/web/scrapers/wikipedia.ts +1 -1
  403. package/src/web/scrapers/youtube.ts +6 -1
  404. package/src/web/search/index.ts +1 -1
  405. package/src/web/search/providers/codex.ts +2 -1
  406. package/src/web/search/providers/gemini.ts +2 -3
  407. package/src/web/search/render.ts +8 -6
  408. package/dist/types/config/model-equivalence.d.ts +0 -24
  409. package/dist/types/config/model-id-affixes.d.ts +0 -12
  410. package/dist/types/config/model-provider-priority.d.ts +0 -1
  411. package/dist/types/exec/idle-timeout-watchdog.d.ts +0 -18
  412. package/src/config/model-equivalence.ts +0 -875
  413. package/src/config/model-id-affixes.ts +0 -81
  414. package/src/config/model-provider-priority.ts +0 -56
  415. package/src/exec/idle-timeout-watchdog.ts +0 -126
@@ -21,9 +21,11 @@ import {
21
21
  } from "../../extensibility/extensions";
22
22
  import { type Theme, theme } from "../../modes/theme/theme";
23
23
  import type { AgentSession } from "../../session/agent-session";
24
+ import type { EventBus } from "../../utils/event-bus";
24
25
  import { initializeExtensions } from "../runtime-init";
25
26
  import { isRpcHostToolResult, isRpcHostToolUpdate, RpcHostToolBridge } from "./host-tools";
26
27
  import { isRpcHostUriResult, RpcHostUriBridge } from "./host-uris";
28
+ import { RpcSubagentRegistry, readRpcSubagentTranscript } from "./rpc-subagents";
27
29
  import type {
28
30
  RpcCommand,
29
31
  RpcExtensionUIRequest,
@@ -35,6 +37,7 @@ import type {
35
37
  RpcHostUriRequest,
36
38
  RpcResponse,
37
39
  RpcSessionState,
40
+ RpcSubagentSubscriptionLevel,
38
41
  } from "./rpc-types";
39
42
 
40
43
  // Re-export types for consumers
@@ -56,6 +59,47 @@ type RpcOutput = (
56
59
  | object,
57
60
  ) => void;
58
61
 
62
+ export type RpcSessionChangeCommand = Extract<
63
+ RpcCommand,
64
+ { type: "new_session" } | { type: "switch_session" } | { type: "branch" }
65
+ >;
66
+
67
+ export type RpcSessionChangeResult =
68
+ | { type: "new_session"; data: { cancelled: boolean } }
69
+ | { type: "switch_session"; data: { cancelled: boolean } }
70
+ | { type: "branch"; data: { text: string; cancelled: boolean } };
71
+
72
+ export type RpcSessionChangeSession = Pick<AgentSession, "newSession" | "switchSession" | "branch">;
73
+ export type RpcSubagentResetRegistry = Pick<RpcSubagentRegistry, "clear">;
74
+
75
+ export async function handleRpcSessionChange(
76
+ session: RpcSessionChangeSession,
77
+ command: RpcSessionChangeCommand,
78
+ subagentRegistry?: RpcSubagentResetRegistry,
79
+ ): Promise<RpcSessionChangeResult> {
80
+ switch (command.type) {
81
+ case "new_session": {
82
+ const options = command.parentSession ? { parentSession: command.parentSession } : undefined;
83
+ const cancelled = !(await session.newSession(options));
84
+ if (!cancelled) subagentRegistry?.clear();
85
+ return { type: "new_session", data: { cancelled } };
86
+ }
87
+
88
+ case "switch_session": {
89
+ const cancelled = !(await session.switchSession(command.sessionPath));
90
+ if (!cancelled) subagentRegistry?.clear();
91
+ return { type: "switch_session", data: { cancelled } };
92
+ }
93
+
94
+ case "branch": {
95
+ const result = await session.branch(command.entryId);
96
+ if (!result.cancelled) subagentRegistry?.clear();
97
+ return { type: "branch", data: { text: result.selectedText, cancelled: result.cancelled } };
98
+ }
99
+ }
100
+ throw new Error("Unsupported RPC session change command");
101
+ }
102
+
59
103
  function normalizeHostToolDefinitions(tools: RpcHostToolDefinition[]): RpcHostToolDefinition[] {
60
104
  return tools.map((tool, index) => {
61
105
  const name = typeof tool.name === "string" ? tool.name.trim() : "";
@@ -99,6 +143,10 @@ function shouldEmitRpcTitles(): boolean {
99
143
  return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
100
144
  }
101
145
 
146
+ function isSubagentSubscriptionLevel(value: unknown): value is RpcSubagentSubscriptionLevel {
147
+ return value === "off" || value === "progress" || value === "events";
148
+ }
149
+
102
150
  export function requestRpcEditor(
103
151
  pendingRequests: Map<string, PendingExtensionRequest>,
104
152
  output: RpcOutput,
@@ -169,6 +217,7 @@ export function requestRpcEditor(
169
217
  export async function runRpcMode(
170
218
  session: AgentSession,
171
219
  setToolUIContext?: (uiContext: ExtensionUIContext, hasUI: boolean) => void,
220
+ eventBus?: EventBus,
172
221
  ): Promise<never> {
173
222
  // Signal to RPC clients that the server is ready to accept commands
174
223
  // Suppress terminal notifications: they write \x07 (BEL) or OSC sequences directly to
@@ -201,6 +250,7 @@ export async function runRpcMode(
201
250
  const pendingExtensionRequests = new Map<string, PendingExtensionRequest>();
202
251
  const hostToolBridge = new RpcHostToolBridge(output);
203
252
  const hostUriBridge = new RpcHostUriBridge(output);
253
+ const subagentRegistry = eventBus ? new RpcSubagentRegistry(eventBus, output) : undefined;
204
254
 
205
255
  // Shutdown request flag (wrapped in object to allow mutation with const)
206
256
  const shutdownState = { requested: false };
@@ -507,9 +557,8 @@ export async function runRpcMode(
507
557
  }
508
558
 
509
559
  case "new_session": {
510
- const options = command.parentSession ? { parentSession: command.parentSession } : undefined;
511
- const cancelled = !(await session.newSession(options));
512
- return success(id, "new_session", { cancelled });
560
+ const result = await handleRpcSessionChange(session, command, subagentRegistry);
561
+ return success(id, result.type, result.data);
513
562
  }
514
563
 
515
564
  // =================================================================
@@ -564,6 +613,44 @@ export async function runRpcMode(
564
613
  }
565
614
  }
566
615
 
616
+ case "set_subagent_subscription": {
617
+ if (!subagentRegistry) {
618
+ return error(id, "set_subagent_subscription", "Subagent event bus is unavailable");
619
+ }
620
+ if (!isSubagentSubscriptionLevel(command.level)) {
621
+ return error(
622
+ id,
623
+ "set_subagent_subscription",
624
+ `Invalid subagent subscription level: ${String(command.level)}`,
625
+ );
626
+ }
627
+ subagentRegistry.setSubscriptionLevel(command.level);
628
+ return success(id, "set_subagent_subscription", { level: subagentRegistry.getSubscriptionLevel() });
629
+ }
630
+
631
+ case "get_subagents": {
632
+ if (!subagentRegistry) {
633
+ return error(id, "get_subagents", "Subagent event bus is unavailable");
634
+ }
635
+ return success(id, "get_subagents", { subagents: subagentRegistry.getSubagents() });
636
+ }
637
+
638
+ case "get_subagent_messages": {
639
+ if (!subagentRegistry) {
640
+ return error(id, "get_subagent_messages", "Subagent event bus is unavailable");
641
+ }
642
+ try {
643
+ if (command.fromByte !== undefined && !Number.isFinite(command.fromByte)) {
644
+ return error(id, "get_subagent_messages", "fromByte must be a finite number");
645
+ }
646
+ const sessionFile = subagentRegistry.resolveSessionFile(command);
647
+ const transcript = await readRpcSubagentTranscript(sessionFile, command.fromByte);
648
+ return success(id, "get_subagent_messages", transcript);
649
+ } catch (err) {
650
+ return error(id, "get_subagent_messages", err instanceof Error ? err.message : String(err));
651
+ }
652
+ }
653
+
567
654
  // =================================================================
568
655
  // Model
569
656
  // =================================================================
@@ -683,14 +770,10 @@ export async function runRpcMode(
683
770
  return success(id, "export_html", { path });
684
771
  }
685
772
 
686
- case "switch_session": {
687
- const cancelled = !(await session.switchSession(command.sessionPath));
688
- return success(id, "switch_session", { cancelled });
689
- }
690
-
773
+ case "switch_session":
691
774
  case "branch": {
692
- const result = await session.branch(command.entryId);
693
- return success(id, "branch", { text: result.selectedText, cancelled: result.cancelled });
775
+ const result = await handleRpcSessionChange(session, command, subagentRegistry);
776
+ return success(id, result.type, result.data);
694
777
  }
695
778
 
696
779
  case "get_branch_messages": {
@@ -850,13 +933,15 @@ export async function runRpcMode(
850
933
 
851
934
  // Check for deferred shutdown request (idle between commands)
852
935
  await checkShutdownRequested();
853
- } catch (e: any) {
854
- output(error(undefined, "parse", `Failed to parse command: ${e.message}`));
936
+ } catch (e: unknown) {
937
+ const message = e instanceof Error ? e.message : String(e);
938
+ output(error(undefined, "parse", `Failed to parse command: ${message}`));
855
939
  }
856
940
  }
857
941
 
858
942
  // stdin closed — RPC client is gone, exit cleanly
859
943
  hostToolBridge.rejectAllPending("RPC client disconnected before host tool execution completed");
860
944
  hostUriBridge.clear("RPC client disconnected before host URI request completed");
945
+ subagentRegistry?.dispose();
861
946
  process.exit(0);
862
947
  }
@@ -0,0 +1,265 @@
1
+ import * as fs from "node:fs/promises";
2
+ import { isEnoent } from "@oh-my-pi/pi-utils";
3
+ import type { FileEntry, SessionMessageEntry } from "../../session/session-manager";
4
+ import { parseSessionEntries } from "../../session/session-manager";
5
+ import {
6
+ type AgentProgress,
7
+ type SubagentEventPayload,
8
+ type SubagentLifecyclePayload,
9
+ type SubagentProgressPayload,
10
+ TASK_SUBAGENT_EVENT_CHANNEL,
11
+ TASK_SUBAGENT_LIFECYCLE_CHANNEL,
12
+ TASK_SUBAGENT_PROGRESS_CHANNEL,
13
+ } from "../../task";
14
+ import type { EventBus } from "../../utils/event-bus";
15
+ import type {
16
+ RpcSubagentEventFrame,
17
+ RpcSubagentFrame,
18
+ RpcSubagentMessagesResult,
19
+ RpcSubagentSnapshot,
20
+ RpcSubagentSubscriptionLevel,
21
+ } from "./rpc-types";
22
+
23
+ export interface RpcSubagentTranscriptSelector {
24
+ subagentId?: string;
25
+ sessionFile?: string;
26
+ fromByte?: number;
27
+ }
28
+
29
+ type RpcSubagentOutput = (frame: RpcSubagentFrame) => void;
30
+
31
+ const MAX_RETAINED_TRANSCRIPT_REFERENCES = 256;
32
+
33
+ function isSessionMessageEntry(entry: FileEntry): entry is SessionMessageEntry {
34
+ return entry.type === "message";
35
+ }
36
+
37
+ function statusFromLifecycle(status: SubagentLifecyclePayload["status"]): AgentProgress["status"] {
38
+ return status === "started" ? "running" : status;
39
+ }
40
+
41
+ function isTerminalLifecycleStatus(status: SubagentLifecyclePayload["status"]): boolean {
42
+ return status !== "started";
43
+ }
44
+
45
+ function hasSameOwner(
46
+ payload: Pick<SubagentLifecyclePayload | SubagentProgressPayload, "parentToolCallId" | "sessionFile">,
47
+ snapshot: RpcSubagentSnapshot,
48
+ ): boolean {
49
+ if (payload.parentToolCallId !== undefined && snapshot.parentToolCallId !== undefined) {
50
+ return payload.parentToolCallId === snapshot.parentToolCallId;
51
+ }
52
+ if (payload.sessionFile !== undefined && snapshot.sessionFile !== undefined) {
53
+ return payload.sessionFile === snapshot.sessionFile;
54
+ }
55
+ return true;
56
+ }
57
+
58
+ function addPruned(set: Set<string>, value: string, maxSize: number): void {
59
+ set.delete(value);
60
+ set.add(value);
61
+ while (set.size > maxSize) {
62
+ const oldest = set.keys().next();
63
+ if (oldest.done) break;
64
+ set.delete(oldest.value);
65
+ }
66
+ }
67
+
68
+ export async function readRpcSubagentTranscript(sessionFile: string, fromByte = 0): Promise<RpcSubagentMessagesResult> {
69
+ let startByte = Number.isFinite(fromByte) ? Math.max(0, Math.trunc(fromByte)) : 0;
70
+ const file = Bun.file(sessionFile);
71
+ let size: number;
72
+ try {
73
+ ({ size } = await fs.stat(sessionFile));
74
+ } catch (err) {
75
+ if (!isEnoent(err)) throw err;
76
+ return {
77
+ sessionFile,
78
+ fromByte: startByte,
79
+ nextByte: startByte,
80
+ reset: false,
81
+ entries: [],
82
+ messages: [],
83
+ };
84
+ }
85
+ let reset = false;
86
+ if (startByte > size) {
87
+ startByte = 0;
88
+ reset = true;
89
+ }
90
+
91
+ const text = startByte >= size ? "" : await file.slice(startByte).text();
92
+ const lastNewline = text.lastIndexOf("\n");
93
+ const completeText = lastNewline >= 0 ? text.slice(0, lastNewline + 1) : "";
94
+ const entries = completeText.length > 0 ? parseSessionEntries(completeText) : [];
95
+ const nextByte = startByte + Buffer.byteLength(completeText, "utf8");
96
+
97
+ return {
98
+ sessionFile,
99
+ fromByte: startByte,
100
+ nextByte,
101
+ reset,
102
+ entries,
103
+ messages: entries.filter(isSessionMessageEntry).map(entry => entry.message),
104
+ };
105
+ }
106
+
107
+ export class RpcSubagentRegistry {
108
+ #subagents = new Map<string, RpcSubagentSnapshot>();
109
+ #transcriptSessionFilesBySubagentId = new Map<string, string>();
110
+ #staleSubagentIds = new Set<string>();
111
+ #unsubscribers: Array<() => void> = [];
112
+ #output: RpcSubagentOutput;
113
+ #subscriptionLevel: RpcSubagentSubscriptionLevel = "off";
114
+
115
+ constructor(eventBus: EventBus, output: RpcSubagentOutput) {
116
+ this.#output = output;
117
+ this.#unsubscribers.push(
118
+ eventBus.on(TASK_SUBAGENT_LIFECYCLE_CHANNEL, data => {
119
+ this.handleLifecycle(data as SubagentLifecyclePayload);
120
+ }),
121
+ eventBus.on(TASK_SUBAGENT_PROGRESS_CHANNEL, data => {
122
+ this.handleProgress(data as SubagentProgressPayload);
123
+ }),
124
+ eventBus.on(TASK_SUBAGENT_EVENT_CHANNEL, data => {
125
+ this.handleEvent(data as SubagentEventPayload);
126
+ }),
127
+ );
128
+ }
129
+
130
+ dispose(): void {
131
+ for (const unsubscribe of this.#unsubscribers) unsubscribe();
132
+ this.#unsubscribers = [];
133
+ this.#subagents.clear();
134
+ this.#transcriptSessionFilesBySubagentId.clear();
135
+ this.#staleSubagentIds.clear();
136
+ }
137
+
138
+ clear(): void {
139
+ for (const subagentId of this.#subagents.keys()) {
140
+ addPruned(this.#staleSubagentIds, subagentId, MAX_RETAINED_TRANSCRIPT_REFERENCES);
141
+ }
142
+ for (const subagentId of this.#transcriptSessionFilesBySubagentId.keys()) {
143
+ addPruned(this.#staleSubagentIds, subagentId, MAX_RETAINED_TRANSCRIPT_REFERENCES);
144
+ }
145
+ this.#subagents.clear();
146
+ this.#transcriptSessionFilesBySubagentId.clear();
147
+ }
148
+
149
+ setSubscriptionLevel(level: RpcSubagentSubscriptionLevel): void {
150
+ this.#subscriptionLevel = level;
151
+ }
152
+
153
+ getSubscriptionLevel(): RpcSubagentSubscriptionLevel {
154
+ return this.#subscriptionLevel;
155
+ }
156
+
157
+ getSubagents(): RpcSubagentSnapshot[] {
158
+ return [...this.#subagents.values()].sort((a, b) => a.index - b.index || a.id.localeCompare(b.id));
159
+ }
160
+
161
+ #rememberTranscriptSession(subagentId: string, sessionFile: string | undefined): void {
162
+ if (!sessionFile) return;
163
+ this.#transcriptSessionFilesBySubagentId.delete(subagentId);
164
+ this.#transcriptSessionFilesBySubagentId.set(subagentId, sessionFile);
165
+ while (this.#transcriptSessionFilesBySubagentId.size > MAX_RETAINED_TRANSCRIPT_REFERENCES) {
166
+ const oldest = this.#transcriptSessionFilesBySubagentId.keys().next();
167
+ if (oldest.done) break;
168
+ this.#transcriptSessionFilesBySubagentId.delete(oldest.value);
169
+ }
170
+ }
171
+
172
+ #hasTranscriptSessionFile(sessionFile: string): boolean {
173
+ for (const snapshot of this.#subagents.values()) {
174
+ if (snapshot.sessionFile === sessionFile) return true;
175
+ }
176
+ for (const transcriptSessionFile of this.#transcriptSessionFilesBySubagentId.values()) {
177
+ if (transcriptSessionFile === sessionFile) return true;
178
+ }
179
+ return false;
180
+ }
181
+
182
+ handleLifecycle(payload: SubagentLifecyclePayload): void {
183
+ const existing = this.#subagents.get(payload.id);
184
+ if (existing && !hasSameOwner(payload, existing)) return;
185
+ if (!existing && payload.status !== "started") return;
186
+ if (payload.status === "started") {
187
+ this.#staleSubagentIds.delete(payload.id);
188
+ }
189
+ const sessionFile = payload.sessionFile ?? existing?.sessionFile;
190
+ const snapshot: RpcSubagentSnapshot = {
191
+ id: payload.id,
192
+ index: payload.index,
193
+ agent: payload.agent,
194
+ agentSource: payload.agentSource,
195
+ description: payload.description ?? existing?.description,
196
+ status: statusFromLifecycle(payload.status),
197
+ task: existing?.task,
198
+ assignment: existing?.assignment,
199
+ sessionFile,
200
+ parentToolCallId: payload.parentToolCallId ?? existing?.parentToolCallId,
201
+ lastUpdate: Date.now(),
202
+ progress: existing?.progress,
203
+ };
204
+ this.#rememberTranscriptSession(payload.id, sessionFile);
205
+ if (isTerminalLifecycleStatus(payload.status)) {
206
+ this.#subagents.delete(payload.id);
207
+ } else {
208
+ this.#subagents.set(payload.id, snapshot);
209
+ }
210
+ if (this.#subscriptionLevel !== "off") {
211
+ this.#output({ type: "subagent_lifecycle", payload });
212
+ }
213
+ }
214
+
215
+ handleProgress(payload: SubagentProgressPayload): void {
216
+ const progress = payload.progress;
217
+ if (this.#staleSubagentIds.has(progress.id)) return;
218
+ const existing = this.#subagents.get(progress.id);
219
+ if (!existing) return;
220
+ if (!hasSameOwner(payload, existing)) return;
221
+ const sessionFile = payload.sessionFile ?? existing?.sessionFile;
222
+ this.#rememberTranscriptSession(progress.id, sessionFile);
223
+ this.#subagents.set(progress.id, {
224
+ id: progress.id,
225
+ index: payload.index,
226
+ agent: payload.agent,
227
+ agentSource: payload.agentSource,
228
+ description: progress.description ?? existing?.description,
229
+ status: progress.status,
230
+ task: payload.task,
231
+ assignment: payload.assignment,
232
+ sessionFile,
233
+ lastUpdate: Date.now(),
234
+ parentToolCallId: payload.parentToolCallId ?? existing?.parentToolCallId,
235
+ progress,
236
+ });
237
+ if (this.#subscriptionLevel !== "off") {
238
+ this.#output({ type: "subagent_progress", payload });
239
+ }
240
+ }
241
+
242
+ handleEvent(payload: SubagentEventPayload): void {
243
+ if (this.#staleSubagentIds.has(payload.id)) return;
244
+ if (this.#subscriptionLevel !== "events") return;
245
+ this.#output({ type: "subagent_event", payload } satisfies RpcSubagentEventFrame);
246
+ }
247
+
248
+ resolveSessionFile(selector: RpcSubagentTranscriptSelector): string {
249
+ if (selector.subagentId) {
250
+ const snapshot = this.#subagents.get(selector.subagentId);
251
+ const sessionFile = snapshot?.sessionFile ?? this.#transcriptSessionFilesBySubagentId.get(selector.subagentId);
252
+ if (!sessionFile) {
253
+ throw new Error(`Unknown subagent or session file unavailable: ${selector.subagentId}`);
254
+ }
255
+ return sessionFile;
256
+ }
257
+
258
+ if (selector.sessionFile) {
259
+ if (this.#hasTranscriptSessionFile(selector.sessionFile)) return selector.sessionFile;
260
+ throw new Error("Unknown subagent session file");
261
+ }
262
+
263
+ throw new Error("get_subagent_messages requires subagentId or sessionFile");
264
+ }
265
+ }
@@ -9,7 +9,14 @@ import type { CompactionResult } from "@oh-my-pi/pi-agent-core/compaction";
9
9
  import type { Effort, ImageContent, Model } from "@oh-my-pi/pi-ai";
10
10
  import type { BashResult } from "../../exec/bash-executor";
11
11
  import type { ContextUsage } from "../../extensibility/extensions/types";
12
- import type { SessionStats } from "../../session/agent-session";
12
+ import type { AgentSessionEvent, SessionStats } from "../../session/agent-session";
13
+ import type { FileEntry } from "../../session/session-manager";
14
+ import type {
15
+ AgentProgress,
16
+ SubagentEventPayload,
17
+ SubagentLifecyclePayload,
18
+ SubagentProgressPayload,
19
+ } from "../../task";
13
20
  import type { TodoPhase } from "../../tools/todo";
14
21
 
15
22
  // ============================================================================
@@ -30,6 +37,9 @@ export type RpcCommand =
30
37
  | { id?: string; type: "set_todos"; phases: TodoPhase[] }
31
38
  | { id?: string; type: "set_host_tools"; tools: RpcHostToolDefinition[] }
32
39
  | { id?: string; type: "set_host_uri_schemes"; schemes: RpcHostUriSchemeDefinition[] }
40
+ | { id?: string; type: "set_subagent_subscription"; level: RpcSubagentSubscriptionLevel }
41
+ | { id?: string; type: "get_subagents" }
42
+ | { id?: string; type: "get_subagent_messages"; subagentId?: string; sessionFile?: string; fromByte?: number }
33
43
 
34
44
  // Model
35
45
  | { id?: string; type: "set_model"; provider: string; modelId: string }
@@ -104,6 +114,32 @@ export interface RpcHandoffResult {
104
114
  savedPath?: string;
105
115
  }
106
116
 
117
+ export type RpcSubagentSubscriptionLevel = "off" | "progress" | "events";
118
+
119
+ export interface RpcSubagentSnapshot {
120
+ id: string;
121
+ index: number;
122
+ agent: string;
123
+ agentSource: AgentProgress["agentSource"];
124
+ description?: string;
125
+ status: AgentProgress["status"];
126
+ task?: string;
127
+ assignment?: string;
128
+ sessionFile?: string;
129
+ lastUpdate: number;
130
+ progress?: AgentProgress;
131
+ parentToolCallId?: string;
132
+ }
133
+
134
+ export interface RpcSubagentMessagesResult {
135
+ sessionFile: string;
136
+ fromByte: number;
137
+ nextByte: number;
138
+ reset: boolean;
139
+ entries: FileEntry[];
140
+ messages: AgentMessage[];
141
+ }
142
+
107
143
  // ============================================================================
108
144
  // RPC Responses (stdout)
109
145
  // ============================================================================
@@ -123,6 +159,27 @@ export type RpcResponse =
123
159
  | { id?: string; type: "response"; command: "set_todos"; success: true; data: { todoPhases: TodoPhase[] } }
124
160
  | { id?: string; type: "response"; command: "set_host_tools"; success: true; data: { toolNames: string[] } }
125
161
  | { id?: string; type: "response"; command: "set_host_uri_schemes"; success: true; data: { schemes: string[] } }
162
+ | {
163
+ id?: string;
164
+ type: "response";
165
+ command: "set_subagent_subscription";
166
+ success: true;
167
+ data: { level: RpcSubagentSubscriptionLevel };
168
+ }
169
+ | {
170
+ id?: string;
171
+ type: "response";
172
+ command: "get_subagents";
173
+ success: true;
174
+ data: { subagents: RpcSubagentSnapshot[] };
175
+ }
176
+ | {
177
+ id?: string;
178
+ type: "response";
179
+ command: "get_subagent_messages";
180
+ success: true;
181
+ data: RpcSubagentMessagesResult;
182
+ }
126
183
 
127
184
  // Model
128
185
  | {
@@ -212,6 +269,29 @@ export type RpcResponse =
212
269
  // Error response (any command can fail)
213
270
  | { id?: string; type: "response"; command: string; success: false; error: string };
214
271
 
272
+ // ============================================================================
273
+ // Subagent Events (stdout)
274
+ // ============================================================================
275
+
276
+ export interface RpcSubagentLifecycleFrame {
277
+ type: "subagent_lifecycle";
278
+ payload: SubagentLifecyclePayload;
279
+ }
280
+
281
+ export interface RpcSubagentProgressFrame {
282
+ type: "subagent_progress";
283
+ payload: SubagentProgressPayload;
284
+ }
285
+
286
+ export interface RpcSubagentEventFrame {
287
+ type: "subagent_event";
288
+ payload: SubagentEventPayload;
289
+ }
290
+
291
+ export type RpcSubagentFrame = RpcSubagentLifecycleFrame | RpcSubagentProgressFrame | RpcSubagentEventFrame;
292
+
293
+ export type RpcSessionEventFrame = AgentSessionEvent | RpcSubagentFrame;
294
+
215
295
  // ============================================================================
216
296
  // Extension UI Events (stdout)
217
297
  // ============================================================================
@@ -65,9 +65,15 @@ export async function markSetupWizardComplete(
65
65
  await settings.flush();
66
66
  }
67
67
 
68
+ export interface RunSetupWizardOptions {
69
+ markComplete?: boolean;
70
+ playWelcomeIntro?: boolean;
71
+ }
72
+
68
73
  export async function runSetupWizard(
69
74
  ctx: InteractiveModeContext,
70
75
  scenes: readonly SetupScene[] = ALL_SCENES,
76
+ options: RunSetupWizardOptions = {},
71
77
  ): Promise<void> {
72
78
  if (scenes.length === 0) return;
73
79
  const component = new SetupWizardComponent(ctx, scenes);
@@ -79,11 +85,15 @@ export async function runSetupWizard(
79
85
  });
80
86
  try {
81
87
  await component.run();
82
- await markSetupWizardComplete(ctx.settings);
88
+ if (options.markComplete !== false) {
89
+ await markSetupWizardComplete(ctx.settings);
90
+ }
83
91
  } finally {
84
92
  component.dispose();
85
93
  ctx.ui.setFocus(component);
86
94
  overlay.hide();
87
95
  }
88
- ctx.playWelcomeIntro();
96
+ if (options.playWelcomeIntro !== false) {
97
+ ctx.playWelcomeIntro();
98
+ }
89
99
  }
@@ -0,0 +1,16 @@
1
+ import type { InteractiveModeContext } from "../types";
2
+
3
+ export async function runProviderSetupWizard(ctx: InteractiveModeContext): Promise<void> {
4
+ // Keep the full setup wizard behind the existing cold-start boundary; a static
5
+ // import here would load provider/OAuth/search/theme setup deps on every TUI startup.
6
+ const { ALL_SCENES, runSetupWizard } = await import("./index");
7
+ const providersScene = ALL_SCENES.find(scene => scene.id === "providers");
8
+ if (!providersScene) {
9
+ ctx.showError("Provider setup is unavailable.");
10
+ return;
11
+ }
12
+ await runSetupWizard(ctx, [providersScene], {
13
+ markComplete: false,
14
+ playWelcomeIntro: false,
15
+ });
16
+ }
@@ -60,7 +60,7 @@ class GlyphSceneController implements SetupSceneController {
60
60
  this.#selectList.handleInput(data);
61
61
  }
62
62
 
63
- render(width: number): string[] {
63
+ render(width: number): readonly string[] {
64
64
  return [
65
65
  theme.fg("muted", "If a row shows boxes, tofu, or misaligned icons, pick another."),
66
66
  "",
@@ -52,7 +52,7 @@ class ProvidersSceneController implements SetupSceneController {
52
52
  tab.handleInput(data);
53
53
  }
54
54
 
55
- render(width: number): string[] {
55
+ render(width: number): readonly string[] {
56
56
  return [...this.#tabBar.render(width), "", ...this.#activeTab().render(width)];
57
57
  }
58
58
 
@@ -68,7 +68,7 @@ export class SignInTab implements SetupTab {
68
68
  this.#selector.handleInput(data);
69
69
  }
70
70
 
71
- render(width: number): string[] {
71
+ render(width: number): readonly string[] {
72
72
  const lines: string[] = [];
73
73
  if (this.#loggingInProvider) {
74
74
  lines.push(theme.bold(`Signing in to ${this.#loggingInProvider}`));
@@ -117,7 +117,7 @@ class ThemeSceneController implements SetupSceneController {
117
117
  this.#selectList.handleInput(data);
118
118
  }
119
119
 
120
- render(width: number): string[] {
120
+ render(width: number): readonly string[] {
121
121
  const lines = [
122
122
  theme.fg("muted", "Theme changes preview live. Nothing is saved until you press Enter."),
123
123
  this.#mode === "all"
@@ -31,7 +31,7 @@ export interface SetupTab {
31
31
  * login). The parent scene MUST NOT switch tabs or finish while modal.
32
32
  */
33
33
  readonly modal: boolean;
34
- render(width: number): string[];
34
+ render(width: number): readonly string[];
35
35
  handleInput(data: string): void;
36
36
  invalidate(): void;
37
37
  /** Called when the tab becomes active (including initial mount). */
@@ -63,7 +63,7 @@ export class WebSearchTab implements SetupTab {
63
63
  this.#disposed = true;
64
64
  }
65
65
 
66
- render(width: number): string[] {
66
+ render(width: number): readonly string[] {
67
67
  const lines = [
68
68
  theme.fg("muted", "Choose the provider the web_search tool should prefer."),
69
69
  "",
@@ -116,7 +116,7 @@ export class SetupWizardComponent implements Component {
116
116
  this.#activeScene?.handleInput?.(data);
117
117
  }
118
118
 
119
- render(width: number): string[] {
119
+ render(width: number): readonly string[] {
120
120
  const safeWidth = Math.max(1, width);
121
121
  const height = Math.max(1, this.ctx.ui.terminal.rows);
122
122
  let lines: string[];