@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
@@ -1,202 +1,71 @@
1
- import type { AgentEndEvent, AgentStartEvent, ExtensionAPI, ExtensionCommandContext, ExtensionContext, ExtensionHandler, MessageRenderer, ModelSelectEvent, RegisteredCommand, SessionShutdownEvent, SessionStartEvent, ToolDefinition, ToolExecutionEndEvent, ToolExecutionStartEvent, TurnEndEvent, TurnStartEvent } from "@bastani/atomic";
1
+ import { APP_NAME, getEnvValue, type ExtensionAPI, type ExtensionContext, type SessionStartEvent, type ToolDefinition, type ToolExecutionStartEvent } from "@bastani/atomic";
2
2
  import { Text } from "@earendil-works/pi-tui";
3
3
  import { Type } from "typebox";
4
4
  import { renderIntercomToolResult } from "./result-renderers.js";
5
-
6
- type CapturedCommand = Omit<RegisteredCommand, "name" | "sourceInfo">;
7
- type CapturedShortcut = Parameters<ExtensionAPI["registerShortcut"]>[1];
8
- type EventHandler = Parameters<ExtensionAPI["events"]["on"]>[1];
9
- type EventPayload = Parameters<EventHandler>[0];
10
- type ToolRenderResultArgs = Parameters<NonNullable<ToolDefinition["renderResult"]>>;
11
-
12
- type ForwardedEventMap = {
13
- session_start: SessionStartEvent;
14
- session_shutdown: SessionShutdownEvent;
15
- turn_start: TurnStartEvent;
16
- turn_end: TurnEndEvent;
17
- agent_start: AgentStartEvent;
18
- agent_end: AgentEndEvent;
19
- tool_execution_start: ToolExecutionStartEvent;
20
- tool_execution_end: ToolExecutionEndEvent;
21
- model_select: ModelSelectEvent;
22
- };
23
-
24
- type LazyLifecycleEvent = keyof ForwardedEventMap;
25
- type ForwardedHandler<K extends LazyLifecycleEvent> = ExtensionHandler<ForwardedEventMap[K]>;
26
- type ForwardedHandlerMap = { [K in LazyLifecycleEvent]: ForwardedHandler<K>[] };
27
- type AnyForwardedHandler = { [K in LazyLifecycleEvent]: ForwardedHandler<K> }[LazyLifecycleEvent];
28
-
29
- type CapturedHeavy = {
30
- tools: Map<string, ToolDefinition>;
31
- commands: Map<string, CapturedCommand>;
32
- handlers: ForwardedHandlerMap;
33
- shortcuts: Map<string, CapturedShortcut>;
34
- eventHandlers: Map<string, EventHandler[]>;
35
- };
36
-
37
- type LifecycleSnapshot<K extends LazyLifecycleEvent> = {
5
+ import { loadConfig } from "./config.js";
6
+ import { executeHeavyTool, runHeavyCommand, type HeavyHandle } from "./lazy-tool-execution.js";
7
+ import { assertCurrentLifecycleLease, createLifecycleLease, retainSettledLifecycleCleanup, retireLifecycleLease, SerializedLifecycleForwarder, type LifecycleLease } from "./lifecycle-lease.js";
8
+ import { rejectLazyResultRelay } from "./lazy-subagent-ack.js";
9
+ import {
10
+ createForwardedHandlerMap,
11
+ createHeavyProxy,
12
+ dispatchEventHandlers,
13
+ dispatchHandlers,
14
+ type CapturedHeavy,
15
+ type ForwardedEventMap,
16
+ type HeavyRuntimeReadiness,
17
+ type ToolRenderResultArgs,
18
+ } from "./lazy-heavy-proxy.js";
19
+
20
+ type LifecycleSnapshot<K extends keyof ForwardedEventMap> = {
38
21
  event: ForwardedEventMap[K];
39
22
  ctx: ExtensionContext;
40
23
  };
41
-
42
- type SessionSnapshot = LifecycleSnapshot<"session_start"> & {
43
- generation: number;
44
- };
45
-
24
+ type ShutdownSnapshot = LifecycleSnapshot<"session_shutdown"> & { generation: number };
25
+ type IntercomLease = LifecycleLease<ShutdownSnapshot>;
26
+ type SessionSnapshot = LifecycleSnapshot<"session_start"> & { generation: number; lease: IntercomLease };
27
+ type IntercomHeavyHandle = HeavyHandle<CapturedHeavy>;
28
+ type HeavyAttempt = { lease: IntercomLease; promise: Promise<IntercomHeavyHandle> };
29
+ type ReplayAttempt = { lease: IntercomLease; heavy: CapturedHeavy; promise: Promise<void> };
46
30
  type ActiveLifecycleState = {
47
31
  turnStart: LifecycleSnapshot<"turn_start"> | null;
48
32
  agentStart: LifecycleSnapshot<"agent_start"> | null;
49
33
  activeTools: Map<string, LifecycleSnapshot<"tool_execution_start">>;
50
34
  modelSelect: LifecycleSnapshot<"model_select"> | null;
51
35
  };
52
- const SUBAGENT_CONTROL_INTERCOM_EVENT = "subagent:control-intercom";
53
- const SUBAGENT_RESULT_INTERCOM_EVENT = "subagent:result-intercom";
54
-
55
- function hasSubagentIntercomEnv(): boolean {
56
- return Object.keys(process.env).some((key) => key.endsWith("_SUBAGENT_ORCHESTRATOR_TARGET"));
36
+ interface LightweightIntercomOptions {
37
+ importHeavy?: () => Promise<{ default: (pi: ExtensionAPI) => void | HeavyRuntimeReadiness | Promise<void | HeavyRuntimeReadiness> }>;
38
+ isEnabled?: () => boolean;
57
39
  }
58
40
 
59
- function createSyntheticSessionStartEvent(): SessionStartEvent {
60
- return { type: "session_start", reason: "startup" };
61
- }
41
+ const MANAGEMENT_ONLY_SUBAGENT_ACTIONS = new Set(["list", "get", "create", "update", "delete", "status", "interrupt", "doctor"]);
62
42
 
63
- function createForwardedHandlerMap(): ForwardedHandlerMap {
64
- return {
65
- session_start: [],
66
- session_shutdown: [],
67
- turn_start: [],
68
- turn_end: [],
69
- agent_start: [],
70
- agent_end: [],
71
- tool_execution_start: [],
72
- tool_execution_end: [],
73
- model_select: [],
74
- };
43
+ function isInteractiveForegroundSubagentStart(event: ToolExecutionStartEvent, ctx: ExtensionContext): boolean {
44
+ if (!ctx.hasUI || event.toolName !== "subagent") return false;
45
+ if (!event.args || typeof event.args !== "object" || Array.isArray(event.args)) return true;
46
+ const args = event.args as { action?: unknown; async?: unknown };
47
+ const action = typeof args.action === "string" ? args.action.trim() : "";
48
+ if (action && MANAGEMENT_ONLY_SUBAGENT_ACTIONS.has(action)) return false;
49
+ return args.async !== true;
75
50
  }
76
51
 
77
- function addHandler<K extends LazyLifecycleEvent>(captured: CapturedHeavy, event: K, handler: ForwardedHandler<K>): void {
78
- captured.handlers[event].push(handler);
79
- }
80
52
 
81
- function captureForwardedHandler(captured: CapturedHeavy, event: "session_start", handler: ForwardedHandler<"session_start">): void;
82
- function captureForwardedHandler(captured: CapturedHeavy, event: "session_shutdown", handler: ForwardedHandler<"session_shutdown">): void;
83
- function captureForwardedHandler(captured: CapturedHeavy, event: "turn_start", handler: ForwardedHandler<"turn_start">): void;
84
- function captureForwardedHandler(captured: CapturedHeavy, event: "turn_end", handler: ForwardedHandler<"turn_end">): void;
85
- function captureForwardedHandler(captured: CapturedHeavy, event: "agent_start", handler: ForwardedHandler<"agent_start">): void;
86
- function captureForwardedHandler(captured: CapturedHeavy, event: "agent_end", handler: ForwardedHandler<"agent_end">): void;
87
- function captureForwardedHandler(captured: CapturedHeavy, event: "tool_execution_start", handler: ForwardedHandler<"tool_execution_start">): void;
88
- function captureForwardedHandler(captured: CapturedHeavy, event: "tool_execution_end", handler: ForwardedHandler<"tool_execution_end">): void;
89
- function captureForwardedHandler(captured: CapturedHeavy, event: "model_select", handler: ForwardedHandler<"model_select">): void;
90
- function captureForwardedHandler(captured: CapturedHeavy, event: LazyLifecycleEvent, handler: AnyForwardedHandler): void;
91
- function captureForwardedHandler(captured: CapturedHeavy, event: LazyLifecycleEvent, handler: AnyForwardedHandler): void {
92
- switch (event) {
93
- case "session_start":
94
- addHandler(captured, event, handler as ForwardedHandler<"session_start">);
95
- return;
96
- case "session_shutdown":
97
- addHandler(captured, event, handler as ForwardedHandler<"session_shutdown">);
98
- return;
99
- case "turn_start":
100
- addHandler(captured, event, handler as ForwardedHandler<"turn_start">);
101
- return;
102
- case "turn_end":
103
- addHandler(captured, event, handler as ForwardedHandler<"turn_end">);
104
- return;
105
- case "agent_start":
106
- addHandler(captured, event, handler as ForwardedHandler<"agent_start">);
107
- return;
108
- case "agent_end":
109
- addHandler(captured, event, handler as ForwardedHandler<"agent_end">);
110
- return;
111
- case "tool_execution_start":
112
- addHandler(captured, event, handler as ForwardedHandler<"tool_execution_start">);
113
- return;
114
- case "tool_execution_end":
115
- addHandler(captured, event, handler as ForwardedHandler<"tool_execution_end">);
116
- return;
117
- case "model_select":
118
- addHandler(captured, event, handler as ForwardedHandler<"model_select">);
119
- }
120
- }
121
-
122
- function addEventHandler(captured: CapturedHeavy, event: string, handler: EventHandler): void {
123
- const handlers = captured.eventHandlers.get(event) ?? [];
124
- handlers.push(handler);
125
- captured.eventHandlers.set(event, handlers);
126
- }
127
-
128
- async function dispatchHandlers<K extends LazyLifecycleEvent>(captured: CapturedHeavy, eventName: K, event: ForwardedEventMap[K], ctx: ExtensionContext): Promise<void> {
129
- for (const handler of captured.handlers[eventName]) {
130
- await handler(event, ctx);
131
- }
132
- }
53
+ const SUBAGENT_CONTROL_INTERCOM_EVENT = "subagent:control-intercom";
54
+ const SUBAGENT_RESULT_INTERCOM_EVENT = "subagent:result-intercom";
133
55
 
134
- async function dispatchEventHandlers(captured: CapturedHeavy, eventName: string, payload: EventPayload): Promise<void> {
135
- for (const handler of captured.eventHandlers.get(eventName) ?? []) {
136
- await handler(payload);
137
- }
138
- }
56
+ const SUBAGENT_ENV_PREFIX = `${APP_NAME.toUpperCase()}_SUBAGENT_`;
139
57
 
140
- function createHeavyProxy(pi: ExtensionAPI, captured: CapturedHeavy): ExtensionAPI {
141
- return new Proxy(pi, {
142
- get(target, prop, receiver) {
143
- if (prop === "registerTool") {
144
- return (tool: ToolDefinition) => captured.tools.set(tool.name, tool);
145
- }
146
- if (prop === "registerCommand") {
147
- return (name: string, options: CapturedCommand) => captured.commands.set(name, options);
148
- }
149
- if (prop === "on") {
150
- return (event: LazyLifecycleEvent, handler: AnyForwardedHandler) => {
151
- captureForwardedHandler(captured, event, handler);
152
- };
153
- }
154
- if (prop === "registerShortcut") {
155
- return (shortcut: string, options: CapturedShortcut) => {
156
- captured.shortcuts.set(shortcut, options);
157
- };
158
- }
159
- if (prop === "registerMessageRenderer") {
160
- return (customType: string, renderer: MessageRenderer) => pi.registerMessageRenderer(customType, renderer);
161
- }
162
- if (prop === "events") {
163
- return new Proxy(pi.events, {
164
- get(eventTarget, eventProp, eventReceiver) {
165
- if (eventProp === "on") {
166
- return (event: string, handler: EventHandler) => {
167
- addEventHandler(captured, event, handler);
168
- return () => {
169
- const handlers = captured.eventHandlers.get(event) ?? [];
170
- captured.eventHandlers.set(event, handlers.filter((candidate) => candidate !== handler));
171
- };
172
- };
173
- }
174
- return Reflect.get(eventTarget, eventProp, eventReceiver);
175
- },
176
- });
177
- }
178
- return Reflect.get(target, prop, receiver);
179
- },
180
- }) as ExtensionAPI;
58
+ function readSubagentEnv(name: string): string | undefined {
59
+ const value = getEnvValue(`${SUBAGENT_ENV_PREFIX}${name}`)?.trim();
60
+ return value || undefined;
181
61
  }
182
62
 
183
- async function executeHeavyTool(
184
- loadHeavy: (ctx?: ExtensionContext) => Promise<CapturedHeavy>,
185
- name: string,
186
- args: Parameters<NonNullable<ToolDefinition["execute"]>>,
187
- ): Promise<Awaited<ReturnType<NonNullable<ToolDefinition["execute"]>>>> {
188
- const ctx = args[4];
189
- const heavy = await loadHeavy(ctx);
190
- const tool = heavy.tools.get(name);
191
- if (!tool?.execute) throw new Error(`Intercom tool implementation not found: ${name}`);
192
- return await tool.execute(...args) as Awaited<ReturnType<NonNullable<ToolDefinition["execute"]>>>;
63
+ function hasSubagentIntercomEnv(): boolean {
64
+ return readSubagentEnv("ORCHESTRATOR_TARGET") !== undefined;
193
65
  }
194
66
 
195
- async function runHeavyCommand(loadHeavy: (ctx?: ExtensionContext) => Promise<CapturedHeavy>, args: string | undefined, ctx: ExtensionCommandContext): Promise<void> {
196
- const heavy = await loadHeavy(ctx);
197
- const command = heavy.commands.get("intercom");
198
- if (!command) throw new Error("Intercom command implementation not found");
199
- await command.handler(args ?? "", ctx);
67
+ function createSyntheticSessionStartEvent(): SessionStartEvent {
68
+ return { type: "session_start", reason: "startup" };
200
69
  }
201
70
 
202
71
  function renderHeavyToolResult(loadedHeavy: CapturedHeavy | null, name: string, args: ToolRenderResultArgs): ReturnType<NonNullable<ToolDefinition["renderResult"]>> {
@@ -204,159 +73,307 @@ function renderHeavyToolResult(loadedHeavy: CapturedHeavy | null, name: string,
204
73
  if (renderer) return renderer(...args);
205
74
  return renderIntercomToolResult(name, args);
206
75
  }
207
-
208
- export default function intercom(pi: ExtensionAPI) {
209
- let heavyPromise: Promise<CapturedHeavy> | null = null;
210
- let loadedHeavy: CapturedHeavy | null = null;
76
+ export default function intercom(pi: ExtensionAPI, options: LightweightIntercomOptions = {}) {
77
+ const enabled = options.isEnabled?.() ?? loadConfig().enabled;
78
+ const delegatedSession = hasSubagentIntercomEnv();
79
+ const delegatedSessionName = readSubagentEnv("INTERCOM_SESSION_NAME");
80
+ let heavyAttempt: HeavyAttempt | null = null;
81
+ let loadedHeavy: IntercomHeavyHandle | null = null;
211
82
  let sessionSnapshot: SessionSnapshot | null = null;
212
83
  let lifecycleGeneration = 0;
84
+ let nextLeaseId = 1;
85
+ let activeLease = createLifecycleLease<ShutdownSnapshot>(nextLeaseId++);
213
86
  let replayedGeneration = 0;
87
+ let replayAttempt: ReplayAttempt | null = null;
88
+ const lifecycleForward = new SerializedLifecycleForwarder();
89
+ const invalidatedMessage = "Intercom initialization was invalidated by session shutdown";
214
90
  const activeLifecycle: ActiveLifecycleState = {
215
91
  turnStart: null,
216
92
  agentStart: null,
217
93
  activeTools: new Map(),
218
94
  modelSelect: null,
219
95
  };
220
-
221
- async function replaySessionStart(heavy: CapturedHeavy): Promise<void> {
222
- if (!sessionSnapshot || replayedGeneration === sessionSnapshot.generation) return;
223
- replayedGeneration = sessionSnapshot.generation;
224
- await dispatchHandlers(heavy, "session_start", sessionSnapshot.event, sessionSnapshot.ctx);
225
- if (activeLifecycle.turnStart) {
226
- await dispatchHandlers(heavy, "turn_start", activeLifecycle.turnStart.event, activeLifecycle.turnStart.ctx);
227
- }
228
- if (activeLifecycle.modelSelect) {
229
- await dispatchHandlers(heavy, "model_select", activeLifecycle.modelSelect.event, activeLifecycle.modelSelect.ctx);
230
- }
231
- if (activeLifecycle.agentStart) {
232
- await dispatchHandlers(heavy, "agent_start", activeLifecycle.agentStart.event, activeLifecycle.agentStart.ctx);
233
- }
234
- for (const activeTool of activeLifecycle.activeTools.values()) {
235
- await dispatchHandlers(heavy, "tool_execution_start", activeTool.event, activeTool.ctx);
96
+ function assertLease(lease: IntercomLease): void {
97
+ assertCurrentLifecycleLease(activeLease, lease, invalidatedMessage);
98
+ }
99
+ function createHandle(heavy: CapturedHeavy, lease: IntercomLease): IntercomHeavyHandle {
100
+ return { heavy, assertCurrent: () => assertLease(lease) };
101
+ }
102
+ async function waitForPriorCleanup(lease: IntercomLease): Promise<void> {
103
+ await lease.priorCleanup;
104
+ assertLease(lease);
105
+ }
106
+ function isReplaySnapshotCurrent(snapshot: SessionSnapshot, lease: IntercomLease): boolean {
107
+ assertLease(lease);
108
+ return sessionSnapshot === snapshot;
109
+ }
110
+ async function replaySessionStart(heavy: CapturedHeavy, lease: IntercomLease, onReplay?: (ctx: ExtensionContext) => void): Promise<void> {
111
+ for (;;) {
112
+ assertLease(lease);
113
+ const snapshot = sessionSnapshot;
114
+ if (!snapshot || snapshot.lease !== lease || replayedGeneration === snapshot.generation) return;
115
+ const active = {
116
+ turnStart: activeLifecycle.turnStart,
117
+ modelSelect: activeLifecycle.modelSelect,
118
+ agentStart: activeLifecycle.agentStart,
119
+ activeTools: [...activeLifecycle.activeTools.values()],
120
+ };
121
+ onReplay?.(snapshot.ctx);
122
+ await dispatchHandlers(heavy, "session_start", snapshot.event, snapshot.ctx);
123
+ if (!isReplaySnapshotCurrent(snapshot, lease)) continue;
124
+ if (active.turnStart) await dispatchHandlers(heavy, "turn_start", active.turnStart.event, active.turnStart.ctx);
125
+ if (!isReplaySnapshotCurrent(snapshot, lease)) continue;
126
+ if (active.modelSelect) await dispatchHandlers(heavy, "model_select", active.modelSelect.event, active.modelSelect.ctx);
127
+ if (!isReplaySnapshotCurrent(snapshot, lease)) continue;
128
+ if (active.agentStart) await dispatchHandlers(heavy, "agent_start", active.agentStart.event, active.agentStart.ctx);
129
+ if (!isReplaySnapshotCurrent(snapshot, lease)) continue;
130
+ for (const activeTool of active.activeTools) {
131
+ await dispatchHandlers(heavy, "tool_execution_start", activeTool.event, activeTool.ctx);
132
+ if (!isReplaySnapshotCurrent(snapshot, lease)) break;
133
+ }
134
+ if (!isReplaySnapshotCurrent(snapshot, lease)) continue;
135
+ replayedGeneration = snapshot.generation;
136
+ return;
236
137
  }
237
138
  }
238
-
239
- async function loadHeavy(ctx?: ExtensionContext): Promise<CapturedHeavy> {
240
- if (!heavyPromise) {
241
- heavyPromise = (async () => {
242
- const captured: CapturedHeavy = {
243
- tools: new Map(),
244
- commands: new Map(),
245
- handlers: createForwardedHandlerMap(),
246
- shortcuts: new Map(),
247
- eventHandlers: new Map(),
248
- };
249
- const mod = await import("./index-heavy.js");
250
- await mod.default(createHeavyProxy(pi, captured));
251
- loadedHeavy = captured;
139
+ async function ensureSessionStartReplayed(heavy: CapturedHeavy, lease: IntercomLease, onReplay?: (ctx: ExtensionContext) => void): Promise<void> {
140
+ await waitForPriorCleanup(lease);
141
+ const snapshot = sessionSnapshot;
142
+ if (!snapshot || snapshot.lease !== lease || replayedGeneration === snapshot.generation) return;
143
+ const existing = replayAttempt;
144
+ if (existing?.lease === lease && existing.heavy === heavy) return existing.promise;
145
+ let promise: Promise<void>;
146
+ promise = lifecycleForward.enqueue(() => replaySessionStart(heavy, lease, onReplay)).finally(() => {
147
+ if (replayAttempt?.promise === promise) replayAttempt = null;
148
+ });
149
+ replayAttempt = { lease, heavy, promise };
150
+ await promise;
151
+ }
152
+ async function loadHeavy(ctx?: ExtensionContext): Promise<IntercomHeavyHandle> {
153
+ const lease = activeLease;
154
+ if (lease.retired) throw new Error("Intercom initialization unavailable: no active session");
155
+ await waitForPriorCleanup(lease);
156
+ const existing = heavyAttempt;
157
+ if (existing?.lease === lease) {
158
+ const handle = await existing.promise;
159
+ assertLease(lease);
160
+ if (!sessionSnapshot && ctx) {
161
+ sessionSnapshot = { event: createSyntheticSessionStartEvent(), ctx, generation: ++lifecycleGeneration, lease };
162
+ }
163
+ await ensureSessionStartReplayed(handle.heavy, lease);
164
+ assertLease(lease);
165
+ return handle;
166
+ }
167
+ let promise: Promise<IntercomHeavyHandle>;
168
+ promise = (async (): Promise<IntercomHeavyHandle> => {
169
+ const captured: CapturedHeavy = {
170
+ tools: new Map(), commands: new Map(), handlers: createForwardedHandlerMap(),
171
+ shortcuts: new Map(), eventHandlers: new Map(),
172
+ };
173
+ let replayCtx: ExtensionContext | null = null;
174
+ let cleaned = false;
175
+ const cleanupCandidate = async (): Promise<void> => {
176
+ const shutdown = lease.shutdown;
177
+ const cleanupCtx = shutdown?.ctx ?? replayCtx;
178
+ if (!cleanupCtx || cleaned) return;
179
+ cleaned = true;
180
+ const event = shutdown?.event ?? { type: "session_shutdown", reason: "quit" };
181
+ try {
182
+ await dispatchHandlers(captured, "session_shutdown", event, cleanupCtx);
183
+ } catch (cleanupError) {
184
+ console.error("Intercom failed to clean rejected lazy candidate:", cleanupError);
185
+ }
186
+ };
187
+ try {
188
+ const mod = await (options.importHeavy?.() ?? import("./index-heavy.js"));
189
+ assertLease(lease);
190
+ const runtimeReadiness = await mod.default(createHeavyProxy(pi, captured));
191
+ if (runtimeReadiness) captured.runtimeReadiness = runtimeReadiness;
192
+ assertLease(lease);
252
193
  if (!sessionSnapshot && ctx) {
253
- sessionSnapshot = { event: createSyntheticSessionStartEvent(), ctx, generation: ++lifecycleGeneration };
194
+ sessionSnapshot = { event: createSyntheticSessionStartEvent(), ctx, generation: ++lifecycleGeneration, lease };
254
195
  }
255
- await replaySessionStart(captured);
256
- return captured;
257
- })();
258
- }
259
- const heavy = await heavyPromise;
260
- if (!sessionSnapshot && ctx) {
261
- sessionSnapshot = { event: createSyntheticSessionStartEvent(), ctx, generation: ++lifecycleGeneration };
262
- await replaySessionStart(heavy);
196
+ await ensureSessionStartReplayed(captured, lease, (replayContext) => { replayCtx = replayContext; });
197
+ assertLease(lease);
198
+ const handle = createHandle(captured, lease);
199
+ loadedHeavy = handle;
200
+ return handle;
201
+ } catch (error) {
202
+ await cleanupCandidate();
203
+ throw error;
204
+ }
205
+ })();
206
+ heavyAttempt = { lease, promise };
207
+ void promise.then(
208
+ () => undefined,
209
+ (error: unknown) => {
210
+ if (heavyAttempt?.promise === promise) heavyAttempt = null;
211
+ const message = error instanceof Error ? error.message : String(error);
212
+ console.error(`Intercom heavy initialization failed; a later call will retry: ${message}`, error);
213
+ },
214
+ );
215
+ return promise;
216
+ }
217
+ async function registerAutomatically(ctx: ExtensionContext, phase: string, foreground = false): Promise<boolean> {
218
+ try {
219
+ const handle = await loadHeavy(ctx);
220
+ const readiness = handle.heavy.runtimeReadiness;
221
+ if (!readiness) throw new Error("Intercom heavy runtime did not expose broker readiness");
222
+ if (readiness.enabled) {
223
+ if (foreground) await readiness.awaitForegroundBrokerReady();
224
+ else await readiness.awaitAutomaticBrokerReady();
225
+ }
226
+ handle.assertCurrent();
227
+ return readiness.enabled;
228
+ } catch (error) {
229
+ const message = error instanceof Error ? error.message : String(error);
230
+ console.error(`Intercom ${phase} failed; session will continue and a later call may retry: ${message}`, error);
231
+ return false;
263
232
  }
264
- return heavy;
265
233
  }
266
-
267
234
  pi.on("session_start", async (event, ctx) => {
235
+ if (delegatedSessionName && typeof pi.setSessionName === "function") pi.setSessionName(delegatedSessionName);
236
+ if (activeLease.retired) activeLease = createLifecycleLease<ShutdownSnapshot>(nextLeaseId++, activeLease.cleanupBarrier);
237
+ const lease = activeLease;
238
+ await waitForPriorCleanup(lease);
239
+ if (sessionSnapshot) {
240
+ activeLifecycle.turnStart = null;
241
+ activeLifecycle.agentStart = null;
242
+ activeLifecycle.activeTools.clear();
243
+ activeLifecycle.modelSelect = null;
244
+ }
268
245
  const generation = ++lifecycleGeneration;
269
- sessionSnapshot = { event, ctx, generation };
246
+ sessionSnapshot = { event, ctx, generation, lease };
270
247
  if (loadedHeavy) {
271
- replayedGeneration = generation;
272
- await dispatchHandlers(loadedHeavy, "session_start", event, ctx);
248
+ await ensureSessionStartReplayed(loadedHeavy.heavy, lease);
249
+ return;
273
250
  }
251
+ if (!enabled || (!ctx.hasUI && !delegatedSession)) return;
252
+ if (delegatedSession) await registerAutomatically(ctx, "bridged child automatic registration");
274
253
  });
275
-
276
254
  pi.on("session_shutdown", async (event, ctx) => {
277
- ++lifecycleGeneration;
255
+ const lease = activeLease;
256
+ const generation = ++lifecycleGeneration;
257
+ retireLifecycleLease(lease, { event, ctx, generation });
258
+ const retiredHeavy = loadedHeavy?.heavy ?? null;
259
+ const retiredAttempt = heavyAttempt?.lease === lease ? heavyAttempt.promise : null;
260
+ const retiredReplay = replayAttempt?.lease === lease ? replayAttempt.promise : null;
261
+ sessionSnapshot = null;
262
+ heavyAttempt = null;
263
+ loadedHeavy = null;
264
+ replayAttempt = null;
265
+ replayedGeneration = generation;
278
266
  activeLifecycle.turnStart = null;
279
267
  activeLifecycle.agentStart = null;
280
268
  activeLifecycle.activeTools.clear();
281
269
  activeLifecycle.modelSelect = null;
282
- if (loadedHeavy) {
283
- await dispatchHandlers(loadedHeavy, "session_shutdown", event, ctx);
270
+ const publishedCleanup = retiredHeavy
271
+ ? lifecycleForward.enqueue(() => dispatchHandlers(retiredHeavy, "session_shutdown", event, ctx))
272
+ : Promise.resolve();
273
+ const retainedCleanup = retainSettledLifecycleCleanup(lease, [publishedCleanup, retiredAttempt, retiredReplay, lifecycleForward.settled]);
274
+ try {
275
+ await publishedCleanup;
276
+ } finally {
277
+ await retainedCleanup;
284
278
  }
285
- sessionSnapshot = null;
286
- replayedGeneration = lifecycleGeneration;
287
279
  });
288
-
289
280
  pi.on("turn_start", async (event, ctx) => {
281
+ if (activeLease.retired) return;
290
282
  activeLifecycle.turnStart = { event, ctx };
291
- if (loadedHeavy) await dispatchHandlers(loadedHeavy, "turn_start", event, ctx);
283
+ const heavy = loadedHeavy?.heavy;
284
+ if (heavy) await lifecycleForward.enqueue(() => dispatchHandlers(heavy, "turn_start", event, ctx));
292
285
  });
293
-
294
286
  pi.on("turn_end", async (event, ctx) => {
287
+ if (activeLease.retired) return;
295
288
  activeLifecycle.turnStart = null;
296
289
  activeLifecycle.agentStart = null;
297
290
  activeLifecycle.activeTools.clear();
298
- if (loadedHeavy) await dispatchHandlers(loadedHeavy, "turn_end", event, ctx);
291
+ const heavy = loadedHeavy?.heavy;
292
+ if (heavy) await lifecycleForward.enqueue(() => dispatchHandlers(heavy, "turn_end", event, ctx));
299
293
  });
300
-
301
294
  pi.on("agent_start", async (event, ctx) => {
295
+ if (activeLease.retired) return;
302
296
  activeLifecycle.agentStart = { event, ctx };
303
297
  activeLifecycle.activeTools.clear();
304
- if (loadedHeavy) await dispatchHandlers(loadedHeavy, "agent_start", event, ctx);
298
+ const heavy = loadedHeavy?.heavy;
299
+ if (heavy) await lifecycleForward.enqueue(() => dispatchHandlers(heavy, "agent_start", event, ctx));
305
300
  });
306
-
307
301
  pi.on("agent_end", async (event, ctx) => {
302
+ if (activeLease.retired) return;
308
303
  activeLifecycle.agentStart = null;
309
304
  activeLifecycle.activeTools.clear();
310
- if (loadedHeavy) await dispatchHandlers(loadedHeavy, "agent_end", event, ctx);
305
+ const heavy = loadedHeavy?.heavy;
306
+ if (heavy) await lifecycleForward.enqueue(() => dispatchHandlers(heavy, "agent_end", event, ctx));
311
307
  });
312
-
313
308
  pi.on("tool_execution_start", async (event, ctx) => {
314
- activeLifecycle.activeTools.set(event.toolCallId, { event, ctx });
315
- if (loadedHeavy) await dispatchHandlers(loadedHeavy, "tool_execution_start", event, ctx);
309
+ if (activeLease.retired) return;
310
+ const lease = activeLease;
311
+ const toolSnapshot: LifecycleSnapshot<"tool_execution_start"> = { event, ctx };
312
+ activeLifecycle.activeTools.set(event.toolCallId, toolSnapshot);
313
+ if (isInteractiveForegroundSubagentStart(event, ctx) && enabled) {
314
+ const session = sessionSnapshot;
315
+ const warmHeavy = loadedHeavy?.heavy ?? null;
316
+ const warmReplayComplete = warmHeavy !== null
317
+ && session?.lease === lease
318
+ && replayedGeneration === session.generation;
319
+ // Successful readiness gates launch; optional Intercom failures degrade
320
+ // without preventing the subagent tool itself from executing.
321
+ await registerAutomatically(ctx, "foreground parent warmup", true);
322
+ if (warmReplayComplete
323
+ && activeLease === lease
324
+ && !lease.retired
325
+ && sessionSnapshot === session
326
+ && activeLifecycle.activeTools.get(event.toolCallId) === toolSnapshot
327
+ && loadedHeavy?.heavy === warmHeavy) {
328
+ await lifecycleForward.enqueue(() => dispatchHandlers(warmHeavy, "tool_execution_start", event, ctx));
329
+ }
330
+ return; // Cold initialization replay owns this active tool's delivery.
331
+ }
332
+ const heavy = loadedHeavy?.heavy;
333
+ if (heavy) await lifecycleForward.enqueue(() => dispatchHandlers(heavy, "tool_execution_start", event, ctx));
316
334
  });
317
-
318
335
  pi.on("tool_execution_end", async (event, ctx) => {
336
+ if (activeLease.retired) return;
319
337
  activeLifecycle.activeTools.delete(event.toolCallId);
320
- if (loadedHeavy) await dispatchHandlers(loadedHeavy, "tool_execution_end", event, ctx);
338
+ const heavy = loadedHeavy?.heavy;
339
+ if (heavy) await lifecycleForward.enqueue(() => dispatchHandlers(heavy, "tool_execution_end", event, ctx));
321
340
  });
322
-
323
341
  pi.on("model_select", async (event, ctx) => {
342
+ if (activeLease.retired) return;
324
343
  activeLifecycle.modelSelect = { event, ctx };
325
- if (loadedHeavy) await dispatchHandlers(loadedHeavy, "model_select", event, ctx);
344
+ const heavy = loadedHeavy?.heavy;
345
+ if (heavy) await lifecycleForward.enqueue(() => dispatchHandlers(heavy, "model_select", event, ctx));
326
346
  });
327
-
328
347
  pi.registerShortcut("alt+m", {
329
348
  description: "Open session intercom overlay",
330
349
  handler: async (ctx) => {
331
- const heavy = await loadHeavy(ctx);
332
- const handler = heavy.shortcuts.get("alt+m")?.handler;
350
+ const handle = await loadHeavy(ctx);
351
+ handle.assertCurrent();
352
+ const handler = handle.heavy.shortcuts.get("alt+m")?.handler;
333
353
  if (!handler) throw new Error("Intercom shortcut implementation not found: alt+m");
334
354
  await handler(ctx);
355
+ handle.assertCurrent();
335
356
  },
336
357
  });
337
-
338
358
  for (const eventName of [SUBAGENT_CONTROL_INTERCOM_EVENT, SUBAGENT_RESULT_INTERCOM_EVENT] as const) {
339
359
  pi.events.on(eventName, (payload) => {
340
- void loadHeavy().then((heavy) => dispatchEventHandlers(heavy, eventName, payload)).catch((error) => {
360
+ void loadHeavy().then(async (handle) => {
361
+ handle.assertCurrent();
362
+ await dispatchEventHandlers(handle.heavy, eventName, payload);
363
+ handle.assertCurrent();
364
+ }).catch((error) => {
365
+ rejectLazyResultRelay(pi, eventName, payload, error);
341
366
  console.error(`Intercom event relay failed (${eventName}):`, error);
342
367
  });
343
368
  });
344
369
  }
345
-
346
- if (hasSubagentIntercomEnv()) {
347
- pi.on("session_start", (_event, ctx) => {
348
- void loadHeavy(ctx).catch((error) => {
349
- console.error("Intercom initialization failed:", error);
350
- });
351
- });
352
- }
353
-
370
+ // Bridged children are registered synchronously by the primary session-start
371
+ // handler, before their first agent turn can send or receive intercom messages.
354
372
  pi.registerTool({
355
373
  name: "intercom",
356
374
  label: "Intercom",
357
375
  description: `Send a message to another local agent session running on this machine.
358
376
  Use this to communicate findings, request help, or coordinate work with other sessions.
359
-
360
377
  Usage:
361
378
  intercom({ action: "list" }) → List active sessions
362
379
  intercom({ action: "send", to: "session-name", message: "..." }) → Send message
@@ -378,14 +395,13 @@ Usage:
378
395
  replyTo: Type.Optional(Type.String({ description: "Message ID to reply to (for threading or responding to an 'ask')" })),
379
396
  }),
380
397
  execute: (...args) => executeHeavyTool(loadHeavy, "intercom", args),
381
- renderResult: (...args) => renderHeavyToolResult(loadedHeavy, "intercom", args),
398
+ renderResult: (...args) => renderHeavyToolResult(loadedHeavy?.heavy ?? null, "intercom", args),
382
399
  renderCall(args, theme) {
383
400
  const input = args as { action?: string; to?: string; message?: string };
384
401
  const target = input.to ? ` ${input.to}` : "";
385
402
  return new Text(theme.fg("toolTitle", theme.bold(`intercom ${input.action ?? ""}`)) + theme.fg("accent", target), 0, 0);
386
403
  },
387
404
  });
388
-
389
405
  if (hasSubagentIntercomEnv()) {
390
406
  pi.registerTool({
391
407
  name: "contact_supervisor",
@@ -419,7 +435,7 @@ Usage:
419
435
  }, { description: "Structured interview request for reason='interview_request'" })),
420
436
  }),
421
437
  execute: (...args) => executeHeavyTool(loadHeavy, "contact_supervisor", args),
422
- renderResult: (...args) => renderHeavyToolResult(loadedHeavy, "contact_supervisor", args),
438
+ renderResult: (...args) => renderHeavyToolResult(loadedHeavy?.heavy ?? null, "contact_supervisor", args),
423
439
  renderCall(args, theme) {
424
440
  const input = args as { reason?: string; message?: string; interview?: { title?: string } };
425
441
  const reason = input.reason ?? "contact";