@bastani/atomic 0.9.5-alpha.9 → 0.9.5

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 (377) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/README.md +2 -2
  3. package/dist/builtin/cursor/CHANGELOG.md +12 -0
  4. package/dist/builtin/cursor/package.json +3 -3
  5. package/dist/builtin/cursor/src/model-mapper.ts +6 -3
  6. package/dist/builtin/intercom/CHANGELOG.md +37 -0
  7. package/dist/builtin/intercom/README.md +4 -2
  8. package/dist/builtin/intercom/broker/broker.ts +6 -114
  9. package/dist/builtin/intercom/broker/client.ts +29 -54
  10. package/dist/builtin/intercom/broker/delivered-message-cache.ts +44 -0
  11. package/dist/builtin/intercom/broker/pending-send-registry.ts +142 -0
  12. package/dist/builtin/intercom/broker/send-handler.ts +106 -0
  13. package/dist/builtin/intercom/broker/send-signature.ts +37 -0
  14. package/dist/builtin/intercom/foreground-detach-handoff.ts +136 -0
  15. package/dist/builtin/intercom/index-heavy.ts +49 -53
  16. package/dist/builtin/intercom/index.ts +278 -262
  17. package/dist/builtin/intercom/lazy-heavy-proxy.ts +114 -0
  18. package/dist/builtin/intercom/lazy-subagent-ack.ts +20 -0
  19. package/dist/builtin/intercom/lazy-tool-execution.ts +39 -0
  20. package/dist/builtin/intercom/lifecycle-lease.ts +51 -0
  21. package/dist/builtin/intercom/lifecycle.ts +37 -20
  22. package/dist/builtin/intercom/package.json +3 -6
  23. package/dist/builtin/intercom/reply-routing.ts +17 -0
  24. package/dist/builtin/intercom/subagent-relay.ts +58 -12
  25. package/dist/builtin/intercom/types.ts +3 -3
  26. package/dist/builtin/mcp/CHANGELOG.md +27 -0
  27. package/dist/builtin/mcp/OAUTH.md +1 -0
  28. package/dist/builtin/mcp/README.md +4 -0
  29. package/dist/builtin/mcp/apps-cancellation.ts +32 -0
  30. package/dist/builtin/mcp/call-tool-result.ts +9 -0
  31. package/dist/builtin/mcp/caller-wait.ts +50 -0
  32. package/dist/builtin/mcp/command-registration.ts +82 -0
  33. package/dist/builtin/mcp/direct-tool-executor.ts +279 -0
  34. package/dist/builtin/mcp/direct-tools.ts +6 -239
  35. package/dist/builtin/mcp/host-html-template.ts +4 -2
  36. package/dist/builtin/mcp/index.ts +258 -250
  37. package/dist/builtin/mcp/init.ts +96 -87
  38. package/dist/builtin/mcp/mcp-auth-flow.ts +247 -237
  39. package/dist/builtin/mcp/mcp-callback-server.ts +89 -68
  40. package/dist/builtin/mcp/mcp-oauth-provider.ts +23 -1
  41. package/dist/builtin/mcp/metadata-hydration.ts +21 -6
  42. package/dist/builtin/mcp/package.json +3 -3
  43. package/dist/builtin/mcp/proxy-auth.ts +4 -4
  44. package/dist/builtin/mcp/proxy-call.ts +111 -40
  45. package/dist/builtin/mcp/proxy-connect.ts +35 -15
  46. package/dist/builtin/mcp/proxy-info-modes.ts +49 -19
  47. package/dist/builtin/mcp/proxy-modes.ts +3 -3
  48. package/dist/builtin/mcp/session-cleanup-barrier.ts +43 -0
  49. package/dist/builtin/mcp/state-lease.ts +12 -0
  50. package/dist/builtin/mcp/ui-server.ts +8 -8
  51. package/dist/builtin/mcp/ui-session.ts +9 -18
  52. package/dist/builtin/subagents/CHANGELOG.md +66 -0
  53. package/dist/builtin/subagents/README.md +30 -29
  54. package/dist/builtin/subagents/agents/code-simplifier.md +2 -2
  55. package/dist/builtin/subagents/agents/codebase-analyzer.md +2 -2
  56. package/dist/builtin/subagents/agents/codebase-locator.md +2 -2
  57. package/dist/builtin/subagents/agents/codebase-online-researcher.md +2 -2
  58. package/dist/builtin/subagents/agents/codebase-pattern-finder.md +2 -2
  59. package/dist/builtin/subagents/agents/codebase-research-analyzer.md +2 -2
  60. package/dist/builtin/subagents/agents/codebase-research-locator.md +2 -2
  61. package/dist/builtin/subagents/agents/debugger.md +2 -2
  62. package/dist/builtin/subagents/agents/worker.md +2 -2
  63. package/dist/builtin/subagents/package.json +5 -5
  64. package/dist/builtin/subagents/prompts/review-loop.md +1 -1
  65. package/dist/builtin/subagents/skills/subagent/SKILL.md +37 -36
  66. package/dist/builtin/subagents/src/extension/api-lifecycle.ts +64 -0
  67. package/dist/builtin/subagents/src/extension/fanout-child.ts +44 -51
  68. package/dist/builtin/subagents/src/extension/index.ts +287 -307
  69. package/dist/builtin/subagents/src/extension/prompt-guidance.ts +7 -10
  70. package/dist/builtin/subagents/src/extension/schemas.ts +22 -5
  71. package/dist/builtin/subagents/src/extension/tool-description.ts +29 -0
  72. package/dist/builtin/subagents/src/intercom/intercom-bridge.ts +13 -2
  73. package/dist/builtin/subagents/src/intercom/result-intercom.ts +4 -4
  74. package/dist/builtin/subagents/src/runs/background/async-event-journal.ts +106 -0
  75. package/dist/builtin/subagents/src/runs/background/async-execution-common.ts +3 -2
  76. package/dist/builtin/subagents/src/runs/background/async-execution-single.ts +13 -2
  77. package/dist/builtin/subagents/src/runs/background/async-execution-types.ts +3 -0
  78. package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +1 -1
  79. package/dist/builtin/subagents/src/runs/background/completion-claims.ts +189 -0
  80. package/dist/builtin/subagents/src/runs/background/completion-dedupe.ts +44 -7
  81. package/dist/builtin/subagents/src/runs/background/completion-notification.ts +34 -0
  82. package/dist/builtin/subagents/src/runs/background/notify.ts +72 -22
  83. package/dist/builtin/subagents/src/runs/background/result-delivery-processor.ts +232 -0
  84. package/dist/builtin/subagents/src/runs/background/result-file-claims.ts +151 -0
  85. package/dist/builtin/subagents/src/runs/background/result-quarantine.ts +72 -0
  86. package/dist/builtin/subagents/src/runs/background/result-retry-scheduler.ts +48 -0
  87. package/dist/builtin/subagents/src/runs/background/result-status.ts +81 -0
  88. package/dist/builtin/subagents/src/runs/background/result-watcher-data.ts +59 -0
  89. package/dist/builtin/subagents/src/runs/background/result-watcher.ts +172 -238
  90. package/dist/builtin/subagents/src/runs/background/run-id-resolver.ts +3 -2
  91. package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +73 -14
  92. package/dist/builtin/subagents/src/runs/background/subagent-runner-streaming.ts +17 -13
  93. package/dist/builtin/subagents/src/runs/background/top-level-async.ts +1 -2
  94. package/dist/builtin/subagents/src/runs/foreground/chain-execution-dynamic-step.ts +1 -0
  95. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-runner.ts +1 -0
  96. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-step.ts +1 -0
  97. package/dist/builtin/subagents/src/runs/foreground/chain-execution-sequential-step.ts +7 -9
  98. package/dist/builtin/subagents/src/runs/foreground/chain-execution-types.ts +3 -13
  99. package/dist/builtin/subagents/src/runs/foreground/chain-execution.ts +2 -15
  100. package/dist/builtin/subagents/src/runs/foreground/execution-attempt-finalize.ts +2 -2
  101. package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +53 -44
  102. package/dist/builtin/subagents/src/runs/foreground/execution-detach-reservations.ts +48 -0
  103. package/dist/builtin/subagents/src/runs/foreground/execution-detach-route.ts +17 -0
  104. package/dist/builtin/subagents/src/runs/foreground/execution-run-sync.ts +39 -26
  105. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +3 -1
  106. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-chain.ts +3 -51
  107. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-context.ts +6 -11
  108. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-input.ts +11 -2
  109. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +2 -0
  110. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel.ts +5 -112
  111. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-resume.ts +2 -0
  112. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +68 -118
  113. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-status.ts +79 -7
  114. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-types.ts +2 -2
  115. package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +3 -0
  116. package/dist/builtin/subagents/src/runs/shared/pi-args.ts +2 -2
  117. package/dist/builtin/subagents/src/runs/shared/pi-spawn.ts +27 -11
  118. package/dist/builtin/subagents/src/shared/artifacts.ts +22 -11
  119. package/dist/builtin/subagents/src/shared/event-jsonl-writer.ts +294 -0
  120. package/dist/builtin/subagents/src/shared/exclusive-file-publication.ts +44 -0
  121. package/dist/builtin/subagents/src/shared/jsonl-writer.ts +1 -0
  122. package/dist/builtin/subagents/src/shared/model-info.ts +2 -2
  123. package/dist/builtin/subagents/src/shared/settings.ts +20 -10
  124. package/dist/builtin/subagents/src/shared/types-async.ts +3 -1
  125. package/dist/builtin/subagents/src/shared/types-config.ts +2 -0
  126. package/dist/builtin/subagents/src/shared/types-runtime.ts +3 -2
  127. package/dist/builtin/subagents/src/slash/slash-commands.ts +9 -12
  128. package/dist/builtin/subagents/src/slash/slash-live-state.ts +63 -32
  129. package/dist/builtin/subagents/src/tui/render-result.ts +7 -0
  130. package/dist/builtin/subagents/src/tui/render-stable-output.ts +1 -0
  131. package/dist/builtin/subagents/src/tui/render-widget.ts +128 -89
  132. package/dist/builtin/web-access/CHANGELOG.md +28 -0
  133. package/dist/builtin/web-access/README.md +4 -0
  134. package/dist/builtin/web-access/content-tools.ts +8 -3
  135. package/dist/builtin/web-access/index-heavy.ts +1 -1
  136. package/dist/builtin/web-access/index.ts +190 -46
  137. package/dist/builtin/web-access/lifecycle-lease.ts +38 -0
  138. package/dist/builtin/web-access/package.json +2 -2
  139. package/dist/builtin/web-access/result-renderers.ts +1 -1
  140. package/dist/builtin/web-access/summary-review.ts +1 -1
  141. package/dist/builtin/web-access/web-search-activity.ts +1 -1
  142. package/dist/builtin/web-access/web-search-return.ts +7 -0
  143. package/dist/builtin/web-access/web-search-summary.ts +1 -1
  144. package/dist/builtin/web-access/web-search-tool.ts +4 -2
  145. package/dist/builtin/workflows/CHANGELOG.md +68 -0
  146. package/dist/builtin/workflows/README.md +4 -4
  147. package/dist/builtin/workflows/builtin/deep-research-codebase-utils.ts +27 -4
  148. package/dist/builtin/workflows/builtin/goal-runner.ts +47 -26
  149. package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +10 -0
  150. package/dist/builtin/workflows/builtin/ralph-core.ts +9 -9
  151. package/dist/builtin/workflows/builtin/ralph-models.ts +71 -36
  152. package/dist/builtin/workflows/builtin/ralph-runner.ts +20 -31
  153. package/dist/builtin/workflows/package.json +2 -2
  154. package/dist/builtin/workflows/src/durable/stage-primitive.ts +2 -1
  155. package/dist/builtin/workflows/src/engine/primitives/task.ts +2 -1
  156. package/dist/builtin/workflows/src/extension/workflow-prompts.ts +17 -22
  157. package/dist/builtin/workflows/src/extension/workflow-schema.ts +15 -2
  158. package/dist/builtin/workflows/src/runs/foreground/executor-hil.ts +1 -2
  159. package/dist/builtin/workflows/src/runs/shared/model-fallback-candidates.ts +1 -1
  160. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +2 -2
  161. package/dist/builtin/workflows/src/shared/authoring-contract-stage.ts +2 -2
  162. package/dist/builtin/workflows/src/shared/resume-continuation.ts +2 -0
  163. package/dist/builtin/workflows/src/tui/stage-chat-view-archive-history.ts +1 -23
  164. package/dist/builtin/workflows/src/tui/stage-chat-view-footer-status.ts +54 -9
  165. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +5 -2
  166. package/dist/cli/args.d.ts.map +1 -1
  167. package/dist/cli/args.js +2 -2
  168. package/dist/cli/args.js.map +1 -1
  169. package/dist/core/agent-session-events.d.ts.map +1 -1
  170. package/dist/core/agent-session-events.js +2 -1
  171. package/dist/core/agent-session-events.js.map +1 -1
  172. package/dist/core/agent-session-message-queue.d.ts.map +1 -1
  173. package/dist/core/agent-session-message-queue.js +1 -1
  174. package/dist/core/agent-session-message-queue.js.map +1 -1
  175. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  176. package/dist/core/agent-session-prompt.js +1 -1
  177. package/dist/core/agent-session-prompt.js.map +1 -1
  178. package/dist/core/agent-session-retry.d.ts.map +1 -1
  179. package/dist/core/agent-session-retry.js +1 -1
  180. package/dist/core/agent-session-retry.js.map +1 -1
  181. package/dist/core/agent-session-services.d.ts.map +1 -1
  182. package/dist/core/agent-session-services.js +3 -2
  183. package/dist/core/agent-session-services.js.map +1 -1
  184. package/dist/core/agent-session-types.d.ts.map +1 -1
  185. package/dist/core/agent-session-types.js +1 -1
  186. package/dist/core/agent-session-types.js.map +1 -1
  187. package/dist/core/anthropic-thinking-guard.d.ts +5 -5
  188. package/dist/core/anthropic-thinking-guard.d.ts.map +1 -1
  189. package/dist/core/anthropic-thinking-guard.js +42 -32
  190. package/dist/core/anthropic-thinking-guard.js.map +1 -1
  191. package/dist/core/atomic-guide-command.d.ts.map +1 -1
  192. package/dist/core/atomic-guide-command.js +15 -15
  193. package/dist/core/atomic-guide-command.js.map +1 -1
  194. package/dist/core/auth-storage.d.ts.map +1 -1
  195. package/dist/core/auth-storage.js +14 -9
  196. package/dist/core/auth-storage.js.map +1 -1
  197. package/dist/core/compaction/compaction.d.ts +2 -0
  198. package/dist/core/compaction/compaction.d.ts.map +1 -1
  199. package/dist/core/compaction/compaction.js +79 -46
  200. package/dist/core/compaction/compaction.js.map +1 -1
  201. package/dist/core/compaction/context-assistant-turns.d.ts +42 -0
  202. package/dist/core/compaction/context-assistant-turns.d.ts.map +1 -0
  203. package/dist/core/compaction/context-assistant-turns.js +87 -0
  204. package/dist/core/compaction/context-assistant-turns.js.map +1 -0
  205. package/dist/core/compaction/context-compaction-critical.d.ts +1 -1
  206. package/dist/core/compaction/context-compaction-critical.d.ts.map +1 -1
  207. package/dist/core/compaction/context-compaction-critical.js +2 -2
  208. package/dist/core/compaction/context-compaction-critical.js.map +1 -1
  209. package/dist/core/compaction/context-compaction-eviction-alternates.d.ts +18 -0
  210. package/dist/core/compaction/context-compaction-eviction-alternates.d.ts.map +1 -0
  211. package/dist/core/compaction/context-compaction-eviction-alternates.js +186 -0
  212. package/dist/core/compaction/context-compaction-eviction-alternates.js.map +1 -0
  213. package/dist/core/compaction/context-compaction-eviction.d.ts +10 -2
  214. package/dist/core/compaction/context-compaction-eviction.d.ts.map +1 -1
  215. package/dist/core/compaction/context-compaction-eviction.js +196 -146
  216. package/dist/core/compaction/context-compaction-eviction.js.map +1 -1
  217. package/dist/core/compaction/context-compaction-prompt.d.ts.map +1 -1
  218. package/dist/core/compaction/context-compaction-prompt.js +1 -1
  219. package/dist/core/compaction/context-compaction-prompt.js.map +1 -1
  220. package/dist/core/compaction/context-compaction-types.d.ts +2 -0
  221. package/dist/core/compaction/context-compaction-types.d.ts.map +1 -1
  222. package/dist/core/compaction/context-compaction-types.js.map +1 -1
  223. package/dist/core/compaction/context-deletion-application.d.ts +5 -4
  224. package/dist/core/compaction/context-deletion-application.d.ts.map +1 -1
  225. package/dist/core/compaction/context-deletion-application.js +17 -15
  226. package/dist/core/compaction/context-deletion-application.js.map +1 -1
  227. package/dist/core/compaction/context-deletion-store.d.ts.map +1 -1
  228. package/dist/core/compaction/context-deletion-store.js +1 -1
  229. package/dist/core/compaction/context-deletion-store.js.map +1 -1
  230. package/dist/core/compaction/context-deletion-targets.d.ts +2 -1
  231. package/dist/core/compaction/context-deletion-targets.d.ts.map +1 -1
  232. package/dist/core/compaction/context-deletion-targets.js +36 -31
  233. package/dist/core/compaction/context-deletion-targets.js.map +1 -1
  234. package/dist/core/compaction/context-deletion-tool-helpers.d.ts.map +1 -1
  235. package/dist/core/compaction/context-deletion-tool-helpers.js +116 -43
  236. package/dist/core/compaction/context-deletion-tool-helpers.js.map +1 -1
  237. package/dist/core/compaction/context-transcript-analysis.d.ts +1 -2
  238. package/dist/core/compaction/context-transcript-analysis.d.ts.map +1 -1
  239. package/dist/core/compaction/context-transcript-analysis.js +33 -37
  240. package/dist/core/compaction/context-transcript-analysis.js.map +1 -1
  241. package/dist/core/copilot-model-synthesis.d.ts.map +1 -1
  242. package/dist/core/copilot-model-synthesis.js +3 -1
  243. package/dist/core/copilot-model-synthesis.js.map +1 -1
  244. package/dist/core/extensions/provider-types.d.ts +2 -7
  245. package/dist/core/extensions/provider-types.d.ts.map +1 -1
  246. package/dist/core/extensions/provider-types.js.map +1 -1
  247. package/dist/core/messages.d.ts +9 -0
  248. package/dist/core/messages.d.ts.map +1 -1
  249. package/dist/core/messages.js +100 -18
  250. package/dist/core/messages.js.map +1 -1
  251. package/dist/core/model-registry-builtins.d.ts.map +1 -1
  252. package/dist/core/model-registry-builtins.js +5 -0
  253. package/dist/core/model-registry-builtins.js.map +1 -1
  254. package/dist/core/model-registry-custom-loader.d.ts.map +1 -1
  255. package/dist/core/model-registry-custom-loader.js +49 -8
  256. package/dist/core/model-registry-custom-loader.js.map +1 -1
  257. package/dist/core/model-registry-dynamic.d.ts.map +1 -1
  258. package/dist/core/model-registry-dynamic.js +11 -5
  259. package/dist/core/model-registry-dynamic.js.map +1 -1
  260. package/dist/core/model-registry-loader.d.ts.map +1 -1
  261. package/dist/core/model-registry-loader.js +8 -0
  262. package/dist/core/model-registry-loader.js.map +1 -1
  263. package/dist/core/model-registry-schemas.d.ts +93 -8
  264. package/dist/core/model-registry-schemas.d.ts.map +1 -1
  265. package/dist/core/model-registry-schemas.js +24 -12
  266. package/dist/core/model-registry-schemas.js.map +1 -1
  267. package/dist/core/model-registry-types.d.ts +7 -6
  268. package/dist/core/model-registry-types.d.ts.map +1 -1
  269. package/dist/core/model-registry-types.js.map +1 -1
  270. package/dist/core/model-registry.d.ts +5 -0
  271. package/dist/core/model-registry.d.ts.map +1 -1
  272. package/dist/core/model-registry.js +23 -0
  273. package/dist/core/model-registry.js.map +1 -1
  274. package/dist/core/model-resolver-cli.d.ts.map +1 -1
  275. package/dist/core/model-resolver-cli.js +33 -5
  276. package/dist/core/model-resolver-cli.js.map +1 -1
  277. package/dist/core/model-resolver-initial.d.ts +6 -1
  278. package/dist/core/model-resolver-initial.d.ts.map +1 -1
  279. package/dist/core/model-resolver-initial.js +12 -7
  280. package/dist/core/model-resolver-initial.js.map +1 -1
  281. package/dist/core/model-resolver.d.ts +1 -1
  282. package/dist/core/model-resolver.d.ts.map +1 -1
  283. package/dist/core/model-resolver.js +1 -1
  284. package/dist/core/model-resolver.js.map +1 -1
  285. package/dist/core/resource-loader-context-files.d.ts +1 -0
  286. package/dist/core/resource-loader-context-files.d.ts.map +1 -1
  287. package/dist/core/resource-loader-context-files.js +13 -10
  288. package/dist/core/resource-loader-context-files.js.map +1 -1
  289. package/dist/core/sdk.d.ts.map +1 -1
  290. package/dist/core/sdk.js +2 -2
  291. package/dist/core/sdk.js.map +1 -1
  292. package/dist/core/session-entry-normalization.d.ts +7 -0
  293. package/dist/core/session-entry-normalization.d.ts.map +1 -0
  294. package/dist/core/session-entry-normalization.js +14 -0
  295. package/dist/core/session-entry-normalization.js.map +1 -0
  296. package/dist/core/session-manager-core.d.ts.map +1 -1
  297. package/dist/core/session-manager-core.js +1 -0
  298. package/dist/core/session-manager-core.js.map +1 -1
  299. package/dist/core/session-manager-history.d.ts +2 -2
  300. package/dist/core/session-manager-history.d.ts.map +1 -1
  301. package/dist/core/session-manager-history.js +127 -108
  302. package/dist/core/session-manager-history.js.map +1 -1
  303. package/dist/core/settings-manager-basic-accessors.d.ts +2 -2
  304. package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
  305. package/dist/core/settings-manager-basic-accessors.js.map +1 -1
  306. package/dist/core/settings-types.d.ts +1 -1
  307. package/dist/core/settings-types.d.ts.map +1 -1
  308. package/dist/core/settings-types.js.map +1 -1
  309. package/dist/core/tools/bash.d.ts.map +1 -1
  310. package/dist/core/tools/bash.js +11 -8
  311. package/dist/core/tools/bash.js.map +1 -1
  312. package/dist/main-session.d.ts.map +1 -1
  313. package/dist/main-session.js +1 -0
  314. package/dist/main-session.js.map +1 -1
  315. package/dist/modes/interactive/components/settings-selector-options.d.ts.map +1 -1
  316. package/dist/modes/interactive/components/settings-selector-options.js +3 -1
  317. package/dist/modes/interactive/components/settings-selector-options.js.map +1 -1
  318. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  319. package/dist/modes/interactive/components/thinking-selector.js +2 -1
  320. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  321. package/dist/modes/interactive/interactive-agent-events.d.ts.map +1 -1
  322. package/dist/modes/interactive/interactive-agent-events.js +2 -1
  323. package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
  324. package/dist/modes/interactive/interactive-child-ordering.d.ts +7 -0
  325. package/dist/modes/interactive/interactive-child-ordering.d.ts.map +1 -0
  326. package/dist/modes/interactive/interactive-child-ordering.js +26 -0
  327. package/dist/modes/interactive/interactive-child-ordering.js.map +1 -0
  328. package/dist/modes/interactive/interactive-deferred-startup.d.ts.map +1 -1
  329. package/dist/modes/interactive/interactive-deferred-startup.js +2 -2
  330. package/dist/modes/interactive/interactive-deferred-startup.js.map +1 -1
  331. package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -1
  332. package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
  333. package/dist/modes/interactive/interactive-mode-deps.js +1 -1
  334. package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
  335. package/dist/modes/interactive/interactive-model-routing.d.ts.map +1 -1
  336. package/dist/modes/interactive/interactive-model-routing.js +8 -3
  337. package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
  338. package/dist/modes/interactive/theme/theme-class.d.ts +1 -1
  339. package/dist/modes/interactive/theme/theme-class.d.ts.map +1 -1
  340. package/dist/modes/interactive/theme/theme-class.js +2 -0
  341. package/dist/modes/interactive/theme/theme-class.js.map +1 -1
  342. package/dist/utils/clipboard-image.d.ts.map +1 -1
  343. package/dist/utils/clipboard-image.js +3 -0
  344. package/dist/utils/clipboard-image.js.map +1 -1
  345. package/docs/changelog.mdx +19 -0
  346. package/docs/compaction.md +55 -48
  347. package/docs/custom-provider.md +18 -5
  348. package/docs/extensions.md +7 -3
  349. package/docs/models.md +69 -10
  350. package/docs/providers.md +1 -1
  351. package/docs/quickstart.md +11 -7
  352. package/docs/rpc.md +2 -2
  353. package/docs/sdk.md +1 -1
  354. package/docs/settings.md +3 -3
  355. package/docs/subagents.md +36 -5
  356. package/docs/tools.md +1 -1
  357. package/docs/usage.md +4 -2
  358. package/docs/workflows.md +26 -43
  359. package/examples/extensions/preset.ts +2 -2
  360. package/examples/extensions/subagent/README.md +2 -2
  361. package/examples/extensions/subagent/index.ts +1 -2
  362. package/examples/extensions/subagent/schemas.ts +4 -1
  363. package/examples/sdk/12-full-control.ts +1 -1
  364. package/npm-shrinkwrap.json +48 -51
  365. package/package.json +7 -7
  366. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-behavior.ts +0 -75
  367. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-component.ts +0 -202
  368. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-edit.ts +0 -97
  369. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-editor.ts +0 -160
  370. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-frame.ts +0 -72
  371. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-render-modes.ts +0 -161
  372. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-render-selectors.ts +0 -203
  373. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-selectors.ts +0 -234
  374. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-state.ts +0 -103
  375. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-types.ts +0 -29
  376. package/dist/builtin/subagents/src/runs/foreground/chain-clarify.ts +0 -9
  377. package/dist/builtin/subagents/src/runs/foreground/chain-execution-clarify.ts +0 -117
@@ -17,16 +17,18 @@ import { registerSlashCommands } from "../slash/slash-commands.ts";
17
17
  import { registerPromptTemplateDelegationBridge } from "../slash/prompt-template-bridge.ts";
18
18
  import { registerSlashSubagentBridge } from "../slash/slash-bridge.ts";
19
19
  import { clearSlashSnapshots, getSlashRenderableSnapshot, resolveSlashMessageDetails, restoreSlashFinalSnapshots, type SlashMessageDetails } from "../slash/slash-live-state.ts";
20
- import { inspectSubagentStatus } from "../runs/background/run-status.ts";
21
20
  import registerSubagentNotify, { type SubagentNotifyDetails } from "../runs/background/notify.ts";
22
21
  import { SUBAGENT_CHILD_ENV, SUBAGENT_FANOUT_CHILD_ENV } from "../runs/shared/pi-args.ts";
23
22
  import registerFanoutChildSubagentExtension from "./fanout-child.ts";
24
23
  import { formatDuration, shortenPath } from "../shared/formatters.ts";
25
24
  import { loadConfig } from "./config.ts";
26
25
  import { DEFAULT_PROMPT_GUIDANCE } from "./prompt-guidance.ts";
27
- import { type Details, type SubagentState, ASYNC_DIR, DEFAULT_ARTIFACT_CONFIG, RESULTS_DIR, SLASH_RESULT_TYPE, SUBAGENT_ASYNC_COMPLETE_EVENT, SUBAGENT_ASYNC_STARTED_EVENT, SUBAGENT_CONTROL_EVENT, WIDGET_KEY } from "../shared/types.ts";
26
+ import { SUBAGENT_TOOL_DESCRIPTION } from "./tool-description.ts";
27
+ export { SUBAGENT_TOOL_DESCRIPTION } from "./tool-description.ts";
28
+ import { type Details, type SubagentState, ASYNC_DIR, DEFAULT_ARTIFACT_CONFIG, RESULTS_DIR, SLASH_RESULT_TYPE, SUBAGENT_ASYNC_COMPLETE_EVENT, SUBAGENT_ASYNC_STARTED_EVENT, SUBAGENT_CONTROL_EVENT } from "../shared/types.ts";
28
29
  import { clearPendingForegroundControlNotices, formatSubagentControlNotice, handleSubagentControlNotice, SUBAGENT_CONTROL_MESSAGE_TYPE, type SubagentControlMessageDetails } from "./control-notices.ts";
29
30
  import { createSubagentStartupMaintenance } from "./startup-maintenance.ts";
31
+ import { beginApiLifecycle, getApiScopedSet } from "./api-lifecycle.ts";
30
32
  export { loadConfig } from "./config.ts";
31
33
  function getSubagentSessionRoot(parentSessionFile: string | null): string {
32
34
  if (parentSessionFile) {
@@ -60,9 +62,6 @@ function isSlashResultRunning(result: { details?: Details }): boolean {
60
62
  function isSlashResultError(result: { details?: Details }): boolean {
61
63
  return result.details?.results.some((entry) => entry.exitCode !== 0 && entry.progress?.status !== "running") || false;
62
64
  }
63
- function isStaleExtensionContextError(error: unknown): boolean {
64
- return error instanceof Error && error.message.includes("Extension context no longer active");
65
- }
66
65
  type SubagentToolRenderState = SubagentResultRenderState;
67
66
  function rebuildSlashResultContainer(
68
67
  container: Container,
@@ -81,13 +80,14 @@ function createSlashResultComponent(
81
80
  details: SlashMessageDetails,
82
81
  options: { expanded: boolean },
83
82
  theme: ExtensionContext["ui"]["theme"],
83
+ owner: ExtensionAPI,
84
84
  ): Container {
85
85
  const container = new Container();
86
86
  let lastVersion = -1;
87
87
  let lastSnapshotNow = 0;
88
88
  let pulseFrame = 0;
89
89
  container.render = (width: number): string[] => {
90
- const snapshot = getSlashRenderableSnapshot(details);
90
+ const snapshot = getSlashRenderableSnapshot(details, owner);
91
91
  if (snapshot.version !== lastVersion) {
92
92
  lastVersion = snapshot.version;
93
93
  lastSnapshotNow = Date.now();
@@ -153,329 +153,309 @@ class SubagentControlNoticeComponent implements Component {
153
153
  return lines;
154
154
  }
155
155
  }
156
+
156
157
  export default function registerSubagentExtension(pi: ExtensionAPI): void {
157
158
  if (getEnvValue(SUBAGENT_CHILD_ENV) === "1") {
158
159
  if (getEnvValue(SUBAGENT_FANOUT_CHILD_ENV) === "1") registerFanoutChildSubagentExtension(pi);
159
160
  return;
160
161
  }
161
- const globalStore = globalThis as Record<string, unknown>;
162
- const runtimeCleanupStoreKey = "__piSubagentRuntimeCleanup";
163
- const previousRuntimeCleanup = globalStore[runtimeCleanupStoreKey];
164
- if (typeof previousRuntimeCleanup === "function") {
165
- try {
166
- previousRuntimeCleanup();
167
- } catch {
168
- }
169
- }
170
- ensureAccessibleDir(RESULTS_DIR);
171
- ensureAccessibleDir(ASYNC_DIR);
172
- const config = loadConfig();
173
- const asyncByDefault = config.asyncByDefault === true;
174
- const tempArtifactsDir = getArtifactsDir(null);
175
- const state: SubagentState = {
176
- baseCwd: "",
177
- currentSessionId: null,
178
- asyncJobs: new Map(),
179
- subagentInProgress: false,
180
- foregroundRuns: new Map(),
181
- foregroundControls: new Map(),
182
- lastForegroundControlId: null,
183
- pendingForegroundControlNotices: new Map(),
184
- cleanupTimers: new Map(),
185
- lastUiContext: null,
186
- poller: null,
187
- completionSeen: new Map(),
188
- watcher: null,
189
- watcherRestartTimer: null,
190
- resultFileCoalescer: {
191
- schedule: () => false,
192
- clear: () => {},
193
- },
194
- };
195
- const maintenance = createSubagentStartupMaintenance(pi, state, {
196
- resultsDir: RESULTS_DIR,
197
- artifactCleanupDays: DEFAULT_ARTIFACT_CONFIG.cleanupDays,
198
- resultTtlMs: 10 * 60 * 1000,
199
- });
200
- maintenance.scheduleStartupCleanup();
201
- maintenance.startResultWatcherDeferred();
202
- maintenance.primeExistingResultsDeferred();
203
- const runtimeCleanup = () => {
204
- maintenance.stop();
205
- stopWidgetAnimation();
206
- stopResultAnimations();
207
- clearPendingForegroundControlNotices(state);
208
- if (state.poller) {
209
- clearInterval(state.poller);
210
- state.poller = null;
211
- }
212
- };
213
- globalStore[runtimeCleanupStoreKey] = runtimeCleanup;
214
- const { ensurePoller, handleStarted, handleComplete, resetJobs, hydrateActiveJobs } = createAsyncJobTracker(pi, state, ASYNC_DIR);
215
- const executor = createSubagentExecutor({
216
- pi,
217
- state,
218
- config,
219
- asyncByDefault,
220
- tempArtifactsDir,
221
- getSubagentSessionRoot,
222
- expandTilde,
223
- discoverAgents,
224
- });
225
- pi.registerMessageRenderer<SlashMessageDetails>(SLASH_RESULT_TYPE, (message, options, theme) => {
226
- const details = resolveSlashMessageDetails(message.details);
227
- if (!details) return undefined;
228
- return createSlashResultComponent(details, options, theme);
229
- });
230
- pi.registerMessageRenderer<SubagentNotifyDetails>("subagent-notify", (message, options, theme) => {
231
- const content = typeof message.content === "string" ? message.content : "";
232
- const details = (message.details as SubagentNotifyDetails | undefined) ?? parseSubagentNotifyContent(content);
233
- if (!details) return new Text(content, 0, 0);
234
- const icon = details.status === "completed"
235
- ? theme.fg("success", "✓")
236
- : details.status === "paused"
237
- ? theme.fg("warning", "")
238
- : theme.fg("error", "✗");
239
- const parts: string[] = [];
240
- if (details.taskInfo) parts.push(details.taskInfo);
241
- if (details.durationMs !== undefined) parts.push(formatDuration(details.durationMs));
242
- let text = `${icon} ${theme.bold(details.agent)} ${theme.fg("dim", details.status)}`;
243
- if (parts.length > 0) text += ` ${theme.fg("dim", "·")} ${parts.map((part) => theme.fg("dim", part)).join(` ${theme.fg("dim", "·")} `)}`;
244
- const trimmedPreview = details.resultPreview.trim();
245
- const previewLines = options.expanded
246
- ? trimmedPreview.split("\n").filter((line) => line.trim())
247
- : [trimmedPreview.split("\n", 1)[0] ?? ""].filter((line) => line.trim());
248
- for (const line of previewLines.length > 0 ? previewLines : ["(no output)"]) {
249
- text += `\n ${theme.fg("dim", `⎿ ${line}`)}`;
250
- }
251
- if (!options.expanded && trimmedPreview.includes("\n")) {
252
- text += `\n ${theme.fg("dim", "ctrl+o full notification")}`;
253
- }
254
- if (details.sessionLabel && details.sessionValue) {
255
- text += `\n ${theme.fg("muted", `${details.sessionLabel}: ${shortenPath(details.sessionValue)}`)}`;
256
- }
257
- return new Text(text, 0, 0);
258
- });
259
- pi.registerMessageRenderer<SubagentControlMessageDetails>(SUBAGENT_CONTROL_MESSAGE_TYPE, (message, _options, theme) => {
260
- const details = message.details as SubagentControlMessageDetails | undefined;
261
- if (!details?.event) return undefined;
262
- const content = typeof message.content === "string" ? message.content : undefined;
263
- return new SubagentControlNoticeComponent({ ...details, noticeText: formatSubagentControlNotice(details, content) }, theme);
264
- });
265
- const executeSubagentCollapsed = (id: string, params: SubagentParamsLike, signal: AbortSignal, onUpdate: ((result: AgentToolResult<Details>) => void) | undefined, ctx: ExtensionContext) => {
266
- if (ctx.hasUI) {
267
- state.lastUiContext = ctx;
268
- ctx.ui.setToolsExpanded(false);
269
- }
270
- return executor.execute(id, params, signal, onUpdate, ctx);
271
- };
272
- const slashBridge = registerSlashSubagentBridge({
273
- events: pi.events,
274
- getContext: () => state.lastUiContext,
275
- execute: (id, params, signal, onUpdate, ctx) =>
276
- executeSubagentCollapsed(id, params, signal, onUpdate, ctx),
277
- });
278
- const promptTemplateBridge = registerPromptTemplateDelegationBridge({
279
- events: pi.events,
280
- getContext: () => state.lastUiContext,
281
- execute: async (requestId, request, signal, ctx, onUpdate) => {
282
- if (request.tasks && request.tasks.length > 0) {
162
+ const lifecycle = beginApiLifecycle(pi);
163
+ const registrationFailureCleanups: Array<() => void> = [];
164
+ let runtimeCleanupInstalled = false;
165
+ try {
166
+ ensureAccessibleDir(RESULTS_DIR);
167
+ ensureAccessibleDir(ASYNC_DIR);
168
+ const config = loadConfig();
169
+ const asyncByDefault = config.asyncByDefault === true;
170
+ const tempArtifactsDir = getArtifactsDir(null);
171
+ const state: SubagentState = {
172
+ baseCwd: "",
173
+ currentSessionId: null,
174
+ asyncJobs: new Map(),
175
+ subagentInProgress: false,
176
+ foregroundRuns: new Map(),
177
+ foregroundControls: new Map(),
178
+ lastForegroundControlId: null,
179
+ pendingForegroundControlNotices: new Map(),
180
+ cleanupTimers: new Map(),
181
+ lastUiContext: null,
182
+ poller: null,
183
+ completionSeen: new Map(),
184
+ watcher: null,
185
+ watcherRestartTimer: null,
186
+ resultFileCoalescer: {
187
+ schedule: () => false,
188
+ clear: () => {},
189
+ },
190
+ };
191
+ const maintenance = createSubagentStartupMaintenance(pi, state, {
192
+ resultsDir: RESULTS_DIR,
193
+ artifactCleanupDays: DEFAULT_ARTIFACT_CONFIG.cleanupDays,
194
+ resultTtlMs: 10 * 60 * 1000,
195
+ });
196
+ maintenance.scheduleStartupCleanup();
197
+ registrationFailureCleanups.push(() => maintenance.stop());
198
+ maintenance.startResultWatcherDeferred();
199
+ maintenance.primeExistingResultsDeferred();
200
+ const { ensurePoller, handleStarted, handleComplete, resetJobs, hydrateActiveJobs } = createAsyncJobTracker(pi, state, ASYNC_DIR);
201
+ const executor = createSubagentExecutor({
202
+ pi,
203
+ state,
204
+ config,
205
+ asyncByDefault,
206
+ tempArtifactsDir,
207
+ getSubagentSessionRoot,
208
+ expandTilde,
209
+ discoverAgents,
210
+ });
211
+ pi.registerMessageRenderer<SlashMessageDetails>(SLASH_RESULT_TYPE, (message, options, theme) => {
212
+ const details = resolveSlashMessageDetails(message.details);
213
+ if (!details) return undefined;
214
+ return createSlashResultComponent(details, options, theme, pi);
215
+ });
216
+ pi.registerMessageRenderer<SubagentNotifyDetails>("subagent-notify", (message, options, theme) => {
217
+ const content = typeof message.content === "string" ? message.content : "";
218
+ const details = (message.details as SubagentNotifyDetails | undefined) ?? parseSubagentNotifyContent(content);
219
+ if (!details) return new Text(content, 0, 0);
220
+ const icon = details.status === "completed"
221
+ ? theme.fg("success", "✓")
222
+ : details.status === "paused"
223
+ ? theme.fg("warning", "■")
224
+ : theme.fg("error", "✗");
225
+ const parts: string[] = [];
226
+ if (details.taskInfo) parts.push(details.taskInfo);
227
+ if (details.durationMs !== undefined) parts.push(formatDuration(details.durationMs));
228
+ let text = `${icon} ${theme.bold(details.agent)} ${theme.fg("dim", details.status)}`;
229
+ if (parts.length > 0) text += ` ${theme.fg("dim", "·")} ${parts.map((part) => theme.fg("dim", part)).join(` ${theme.fg("dim", "·")} `)}`;
230
+ const trimmedPreview = details.resultPreview.trim();
231
+ const previewLines = options.expanded
232
+ ? trimmedPreview.split("\n").filter((line) => line.trim())
233
+ : [trimmedPreview.split("\n", 1)[0] ?? ""].filter((line) => line.trim());
234
+ for (const line of previewLines.length > 0 ? previewLines : ["(no output)"]) {
235
+ text += `\n ${theme.fg("dim", `⎿ ${line}`)}`;
236
+ }
237
+ if (!options.expanded && trimmedPreview.includes("\n")) {
238
+ text += `\n ${theme.fg("dim", "ctrl+o full notification")}`;
239
+ }
240
+ if (details.sessionLabel && details.sessionValue) {
241
+ text += `\n ${theme.fg("muted", `${details.sessionLabel}: ${shortenPath(details.sessionValue)}`)}`;
242
+ }
243
+ return new Text(text, 0, 0);
244
+ });
245
+ pi.registerMessageRenderer<SubagentControlMessageDetails>(SUBAGENT_CONTROL_MESSAGE_TYPE, (message, _options, theme) => {
246
+ const details = message.details as SubagentControlMessageDetails | undefined;
247
+ if (!details?.event) return undefined;
248
+ const content = typeof message.content === "string" ? message.content : undefined;
249
+ return new SubagentControlNoticeComponent({ ...details, noticeText: formatSubagentControlNotice(details, content) }, theme);
250
+ });
251
+ const executeSubagentCollapsed = (id: string, params: SubagentParamsLike, signal: AbortSignal, onUpdate: ((result: AgentToolResult<Details>) => void) | undefined, ctx: ExtensionContext) => {
252
+ if (ctx.hasUI) {
253
+ state.lastUiContext = ctx;
254
+ ctx.ui.setToolsExpanded(false);
255
+ }
256
+ return executor.execute(id, params, signal, onUpdate, ctx);
257
+ };
258
+ const slashBridge = registerSlashSubagentBridge({
259
+ events: pi.events,
260
+ getContext: () => state.lastUiContext,
261
+ execute: (id, params, signal, onUpdate, ctx) =>
262
+ executeSubagentCollapsed(id, params, signal, onUpdate, ctx),
263
+ });
264
+ registrationFailureCleanups.push(() => {
265
+ slashBridge.cancelAll();
266
+ slashBridge.dispose();
267
+ });
268
+ const promptTemplateBridge = registerPromptTemplateDelegationBridge({
269
+ events: pi.events,
270
+ getContext: () => state.lastUiContext,
271
+ execute: async (requestId, request, signal, ctx, onUpdate) => {
272
+ if (request.tasks && request.tasks.length > 0) {
273
+ return executeSubagentCollapsed(
274
+ requestId,
275
+ {
276
+ tasks: request.tasks,
277
+ context: request.context,
278
+ cwd: request.cwd,
279
+ worktree: request.worktree,
280
+ async: false,
281
+ },
282
+ signal,
283
+ onUpdate,
284
+ ctx,
285
+ );
286
+ }
283
287
  return executeSubagentCollapsed(
284
288
  requestId,
285
289
  {
286
- tasks: request.tasks,
290
+ agent: request.agent,
291
+ task: request.task,
287
292
  context: request.context,
288
293
  cwd: request.cwd,
289
- worktree: request.worktree,
294
+ model: request.model,
290
295
  async: false,
291
- clarify: false,
292
296
  },
293
297
  signal,
294
298
  onUpdate,
295
299
  ctx,
296
300
  );
297
- }
298
- return executeSubagentCollapsed(
299
- requestId,
300
- {
301
- agent: request.agent,
302
- task: request.task,
303
- context: request.context,
304
- cwd: request.cwd,
305
- model: request.model,
306
- async: false,
307
- clarify: false,
308
- },
309
- signal,
310
- onUpdate,
311
- ctx,
312
- );
313
- },
314
- });
315
- function effectiveParallelTaskCount(tasks: Array<{ count?: unknown }> | undefined): number {
316
- if (!tasks || tasks.length === 0) return 0;
317
- return tasks.reduce((total, task) => {
318
- const count = typeof task.count === "number" && Number.isInteger(task.count) && task.count >= 1 ? task.count : 1;
319
- return total + count;
320
- }, 0);
321
- }
322
- const tool: ToolDefinition<typeof SubagentParams, Details, SubagentToolRenderState> = {
323
- name: "subagent",
324
- label: "Subagent",
325
- description: `Delegate to subagents or manage agent definitions.
326
- EXECUTION (use exactly ONE mode):
327
- • Before executing, use { action: "list" } to inspect configured agents/chains. Only execute agents listed as executable/non-disabled.
328
- SINGLE: { agent, task? } - one task; omit task for self-contained agents
329
- CHAIN: { chain: [{agent:"agent-a"}, {parallel:[{agent:"agent-b",count:3}]}] } - sequential pipeline with optional parallel fan-out
330
- PARALLEL: { tasks: [{agent,task,count?,output?,reads?,progress?}, ...], concurrency?: number, worktree?: true } - concurrent execution (worktree: isolate each task in a git worktree)
331
- Optional context: { context: "fresh" | "fork" } (default: if any requested agent has defaultContext: "fork", the whole invocation uses fork; otherwise "fresh"; inspect agent defaults via { action: "list" })
332
- CHAIN TEMPLATE VARIABLES (use in task strings):
333
- {task} - The original task/request from the user
334
- • {previous} - Text response from the previous step (empty for first step)
335
- • {chain_dir} - Shared directory for chain files (e.g., <tmpdir>/${APP_NAME}-subagents-<scope>/chain-runs/abc123/)
336
- Example: { chain: [{agent:"agent-a", task:"Analyze {task}"}, {agent:"agent-b", task:"Plan based on {previous}"}] }
337
- MANAGEMENT (use action field, omit agent/task/chain/tasks):
338
- { action: "list" } - discover executable agents/chains
339
- { action: "get", agent: "name" } - full detail; packaged agents use dotted runtime names like "package.agent"
340
- • { action: "create", config: { name: "custom-agent", package: "code-analysis", systemPrompt, systemPromptMode, inheritProjectContext, inheritSkills, defaultContext, ... } }
341
- • { action: "update", agent: "code-analysis.custom-agent", config: { package: "analysis", ... } } - merge
342
- • { action: "delete", agent: "code-analysis.custom-agent" }
343
- • Use chainName for chain operations; packaged chains also use dotted runtime names
344
- CONTROL:
345
- • { action: "status", id: "..." } - inspect an async/background run by id or prefix
346
- • { action: "interrupt", id?: "..." } - soft-interrupt the current child turn and leave the run paused
347
- • { action: "resume", id: "...", message: "...", index?: 0 } - follow up with a live async child or revive a completed async/foreground child from its session
348
- DIAGNOSTICS:
349
- • { action: "doctor" } - read-only report for runtime paths, discovery, sessions, and intercom`,
350
- parameters: SubagentParams,
351
- promptGuidelines: DEFAULT_PROMPT_GUIDANCE,
352
- execute(id, params, signal, onUpdate, ctx) {
353
- return executeSubagentCollapsed(id, params, signal, onUpdate, ctx);
354
- },
355
- renderCall(args, theme) {
356
- if (args.action) {
357
- const target = args.agent || args.chainName || "";
358
- return new Text(
359
- `${theme.fg("toolTitle", theme.bold("subagent "))}${args.action}${target ? ` ${theme.fg("accent", target)}` : ""}`,
360
- 0, 0,
361
- );
362
- }
363
- const isParallel = (args.tasks?.length ?? 0) > 0;
364
- const parallelCount = effectiveParallelTaskCount(args.tasks as Array<{ count?: unknown }> | undefined);
365
- const asyncLabel = args.async === true && args.clarify !== true && !isParallel ? theme.fg("warning", " [async]") : "";
366
- if (args.chain?.length)
367
- return new Text(
368
- `${theme.fg("toolTitle", theme.bold("subagent "))}chain (${args.chain.length})${asyncLabel}`,
369
- 0,
370
- 0,
371
- );
372
- if (isParallel)
301
+ },
302
+ });
303
+ registrationFailureCleanups.push(() => {
304
+ promptTemplateBridge.cancelAll();
305
+ promptTemplateBridge.dispose();
306
+ });
307
+ function effectiveParallelTaskCount(tasks: Array<{ count?: unknown }> | undefined): number {
308
+ if (!tasks || tasks.length === 0) return 0;
309
+ return tasks.reduce((total, task) => {
310
+ const count = typeof task.count === "number" && Number.isInteger(task.count) && task.count >= 1 ? task.count : 1;
311
+ return total + count;
312
+ }, 0);
313
+ }
314
+ const tool: ToolDefinition<typeof SubagentParams, Details, SubagentToolRenderState> = {
315
+ name: "subagent",
316
+ label: "Subagent",
317
+ description: SUBAGENT_TOOL_DESCRIPTION,
318
+ parameters: SubagentParams,
319
+ promptGuidelines: DEFAULT_PROMPT_GUIDANCE,
320
+ execute(id, params, signal, onUpdate, ctx) {
321
+ const executionSignal = signal ?? ctx.signal ?? new AbortController().signal;
322
+ return executeSubagentCollapsed(id, params as SubagentParamsLike, executionSignal, onUpdate, ctx);
323
+ },
324
+ renderCall(args, theme) {
325
+ if (args.action) {
326
+ const target = args.agent || args.chainName || "";
327
+ return new Text(
328
+ `${theme.fg("toolTitle", theme.bold("subagent "))}${args.action}${target ? ` ${theme.fg("accent", target)}` : ""}`,
329
+ 0, 0,
330
+ );
331
+ }
332
+ const isParallel = (args.tasks?.length ?? 0) > 0;
333
+ const parallelCount = effectiveParallelTaskCount(args.tasks as Array<{ count?: unknown }> | undefined);
334
+ const asyncLabel = args.async === true ? theme.fg("warning", " [async]") : "";
335
+ if (args.chain?.length)
336
+ return new Text(
337
+ `${theme.fg("toolTitle", theme.bold("subagent "))}chain (${args.chain.length})${asyncLabel}`,
338
+ 0,
339
+ 0,
340
+ );
341
+ if (isParallel)
342
+ return new Text(
343
+ `${theme.fg("toolTitle", theme.bold("subagent "))}parallel (${parallelCount})${asyncLabel}`,
344
+ 0,
345
+ 0,
346
+ );
373
347
  return new Text(
374
- `${theme.fg("toolTitle", theme.bold("subagent "))}parallel (${parallelCount})`,
348
+ `${theme.fg("toolTitle", theme.bold("subagent "))}${theme.fg("accent", args.agent || "?")}${asyncLabel}`,
375
349
  0,
376
350
  0,
377
351
  );
378
- return new Text(
379
- `${theme.fg("toolTitle", theme.bold("subagent "))}${theme.fg("accent", args.agent || "?")}${asyncLabel}`,
380
- 0,
381
- 0,
382
- );
383
- },
384
- renderResult(result, options, theme, context) {
385
- return renderLiveSubagentResult(result, options, theme, context);
386
- },
387
- };
388
- pi.registerTool(tool);
389
- registerSlashCommands(pi, state);
390
- const eventUnsubscribeStoreKey = "__piSubagentEventUnsubscribes";
391
- const controlNoticeSeenStoreKey = "__piSubagentVisibleControlNotices";
392
- const previousEventUnsubscribes = globalStore[eventUnsubscribeStoreKey];
393
- if (Array.isArray(previousEventUnsubscribes)) {
394
- for (const unsubscribe of previousEventUnsubscribes) {
395
- if (typeof unsubscribe !== "function") continue;
396
- try {
397
- unsubscribe();
398
- } catch {
399
- }
352
+ },
353
+ renderResult(result, options, theme, context) {
354
+ return renderLiveSubagentResult(result, options, theme, context);
355
+ },
356
+ };
357
+ pi.registerTool(tool);
358
+ registerSlashCommands(pi, state);
359
+ const notifyCleanup = registerSubagentNotify(pi);
360
+ registrationFailureCleanups.push(notifyCleanup);
361
+ const visibleControlNotices = getApiScopedSet(pi, "__piSubagentVisibleControlNoticesByApi");
362
+ const startedEventHandler = (payload: unknown) => {
363
+ if (lifecycle.isCurrent()) handleStarted(payload);
364
+ };
365
+ const completeEventHandler = (payload: unknown) => {
366
+ if (lifecycle.isCurrent()) handleComplete(payload);
367
+ };
368
+ const controlEventHandler = (payload: unknown) => {
369
+ if (!lifecycle.isCurrent()) return;
370
+ handleSubagentControlNotice({
371
+ pi,
372
+ state,
373
+ visibleControlNotices,
374
+ details: payload as SubagentControlMessageDetails,
375
+ });
376
+ };
377
+ const eventUnsubscribes: Array<() => void> = [];
378
+ for (const [event, handler] of [
379
+ [SUBAGENT_ASYNC_STARTED_EVENT, startedEventHandler],
380
+ [SUBAGENT_ASYNC_COMPLETE_EVENT, completeEventHandler],
381
+ [SUBAGENT_CONTROL_EVENT, controlEventHandler],
382
+ ] as const) {
383
+ const unsubscribe = pi.events.on(event, handler);
384
+ eventUnsubscribes.push(unsubscribe);
385
+ registrationFailureCleanups.push(unsubscribe);
400
386
  }
401
- }
402
- registerSubagentNotify(pi);
403
- const existingVisibleControlNotices = globalStore[controlNoticeSeenStoreKey];
404
- const visibleControlNotices = existingVisibleControlNotices instanceof Set ? existingVisibleControlNotices as Set<string> : new Set<string>();
405
- globalStore[controlNoticeSeenStoreKey] = visibleControlNotices;
406
- const controlEventHandler = (payload: unknown) => {
407
- handleSubagentControlNotice({
408
- pi,
409
- state,
410
- visibleControlNotices,
411
- details: payload as SubagentControlMessageDetails,
412
- });
413
- };
414
- const eventUnsubscribes = [
415
- pi.events.on(SUBAGENT_ASYNC_STARTED_EVENT, handleStarted),
416
- pi.events.on(SUBAGENT_ASYNC_COMPLETE_EVENT, handleComplete),
417
- pi.events.on(SUBAGENT_CONTROL_EVENT, controlEventHandler),
418
- ];
419
- globalStore[eventUnsubscribeStoreKey] = eventUnsubscribes;
420
- pi.on("tool_result", (event, ctx) => {
421
- if (event.toolName !== "subagent") return;
422
- if (!ctx.hasUI) return;
423
- state.lastUiContext = ctx;
424
- hydrateActiveJobs(ctx);
425
- if (state.asyncJobs.size > 0) ensurePoller();
426
- });
427
- const cleanupSessionArtifacts = (ctx: ExtensionContext) => {
428
- maintenance.cleanupSessionArtifactsDeferred(ctx);
429
- };
430
- const resetSessionState = (ctx: ExtensionContext) => {
431
- state.baseCwd = ctx.cwd;
432
- state.currentSessionId = resolveCurrentSessionId(ctx.sessionManager);
433
- state.lastUiContext = ctx;
434
- cleanupSessionArtifacts(ctx);
435
- clearPendingForegroundControlNotices(state);
436
- resetJobs(ctx);
437
- hydrateActiveJobs(ctx);
438
- restoreSlashFinalSnapshots(ctx.sessionManager.getEntries());
439
- maintenance.primeExistingResultsDeferred();
440
- };
441
- pi.on("session_start", (_event, ctx) => {
442
- resetSessionState(ctx);
443
- });
444
- pi.on("session_shutdown", () => {
445
- for (const unsubscribe of eventUnsubscribes) {
446
- try {
447
- unsubscribe();
448
- } catch {
387
+ let cleaned = false;
388
+ const runtimeCleanup = () => {
389
+ if (cleaned) return;
390
+ cleaned = true;
391
+ const cleanupSteps: Array<() => void> = [
392
+ ...eventUnsubscribes,
393
+ notifyCleanup,
394
+ () => maintenance.stop(),
395
+ () => stopWidgetAnimation(undefined, pi),
396
+ () => stopResultAnimations(),
397
+ () => {
398
+ if (state.poller) clearInterval(state.poller);
399
+ state.poller = null;
400
+ },
401
+ () => clearPendingForegroundControlNotices(state),
402
+ ...Array.from(state.cleanupTimers.values(), (timer) => () => clearTimeout(timer)),
403
+ () => state.cleanupTimers.clear(),
404
+ () => state.asyncJobs.clear(),
405
+ () => clearSlashSnapshots(pi),
406
+ () => slashBridge.cancelAll(),
407
+ () => slashBridge.dispose(),
408
+ () => promptTemplateBridge.cancelAll(),
409
+ () => promptTemplateBridge.dispose(),
410
+ ];
411
+ for (const cleanup of cleanupSteps) {
412
+ try {
413
+ cleanup();
414
+ } catch {
415
+ // Cleanup is exhaustive and best effort so later owned resources release.
416
+ }
449
417
  }
450
- }
451
- if (globalStore[eventUnsubscribeStoreKey] === eventUnsubscribes) {
452
- delete globalStore[eventUnsubscribeStoreKey];
453
- }
454
- maintenance.stop();
455
- stopWidgetAnimation();
456
- stopResultAnimations();
457
- if (state.poller) clearInterval(state.poller);
458
- state.poller = null;
459
- clearPendingForegroundControlNotices(state);
460
- for (const timer of state.cleanupTimers.values()) {
461
- clearTimeout(timer);
462
- }
463
- state.cleanupTimers.clear();
464
- state.asyncJobs.clear();
465
- clearSlashSnapshots();
466
- slashBridge.cancelAll();
467
- slashBridge.dispose();
468
- promptTemplateBridge.cancelAll();
469
- promptTemplateBridge.dispose();
470
- if (globalStore[runtimeCleanupStoreKey] === runtimeCleanup) {
471
- delete globalStore[runtimeCleanupStoreKey];
472
- }
473
- try {
474
- if (state.lastUiContext?.hasUI) {
475
- state.lastUiContext.ui.setWidget(WIDGET_KEY, undefined);
418
+ };
419
+ lifecycle.setCleanup(runtimeCleanup);
420
+ runtimeCleanupInstalled = true;
421
+ pi.on("tool_result", (event, ctx) => {
422
+ if (!lifecycle.isCurrent() || event.toolName !== "subagent") return;
423
+ if (!ctx.hasUI) return;
424
+ state.lastUiContext = ctx;
425
+ hydrateActiveJobs(ctx);
426
+ if (state.asyncJobs.size > 0) ensurePoller();
427
+ });
428
+ const cleanupSessionArtifacts = (ctx: ExtensionContext) => {
429
+ maintenance.cleanupSessionArtifactsDeferred(ctx);
430
+ };
431
+ const resetSessionState = (ctx: ExtensionContext) => {
432
+ state.baseCwd = ctx.cwd;
433
+ state.currentSessionId = resolveCurrentSessionId(ctx.sessionManager);
434
+ state.lastUiContext = ctx;
435
+ cleanupSessionArtifacts(ctx);
436
+ clearPendingForegroundControlNotices(state);
437
+ resetJobs(ctx);
438
+ hydrateActiveJobs(ctx);
439
+ restoreSlashFinalSnapshots(ctx.sessionManager.getEntries(), pi);
440
+ maintenance.primeExistingResultsDeferred();
441
+ };
442
+ pi.on("session_start", (_event, ctx) => {
443
+ if (lifecycle.isCurrent()) resetSessionState(ctx);
444
+ });
445
+ pi.on("session_shutdown", () => {
446
+ lifecycle.dispose();
447
+ });
448
+ } catch (error) {
449
+ if (!runtimeCleanupInstalled) {
450
+ for (const cleanup of registrationFailureCleanups.reverse()) {
451
+ try {
452
+ cleanup();
453
+ } catch {
454
+ // Continue releasing partial-registration resources.
455
+ }
476
456
  }
477
- } catch (error) {
478
- if (!isStaleExtensionContextError(error)) throw error;
479
457
  }
480
- });
458
+ lifecycle.dispose();
459
+ throw error;
460
+ }
481
461
  }