@bastani/atomic 0.9.5-alpha.8 → 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 (530) hide show
  1. package/CHANGELOG.md +122 -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 +38 -0
  27. package/dist/builtin/mcp/OAUTH.md +1 -0
  28. package/dist/builtin/mcp/README.md +10 -6
  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 +40 -255
  35. package/dist/builtin/mcp/host-html-template.ts +4 -2
  36. package/dist/builtin/mcp/index.ts +274 -239
  37. package/dist/builtin/mcp/init.ts +96 -126
  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 +52 -0
  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 +106 -23
  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/startup-warmup.ts +98 -0
  50. package/dist/builtin/mcp/state-lease.ts +12 -0
  51. package/dist/builtin/mcp/tool-result-renderer.ts +3 -3
  52. package/dist/builtin/mcp/ui-server.ts +8 -8
  53. package/dist/builtin/mcp/ui-session.ts +9 -18
  54. package/dist/builtin/subagents/CHANGELOG.md +78 -0
  55. package/dist/builtin/subagents/README.md +30 -29
  56. package/dist/builtin/subagents/agents/code-simplifier.md +2 -2
  57. package/dist/builtin/subagents/agents/codebase-analyzer.md +2 -2
  58. package/dist/builtin/subagents/agents/codebase-locator.md +2 -2
  59. package/dist/builtin/subagents/agents/codebase-online-researcher.md +2 -2
  60. package/dist/builtin/subagents/agents/codebase-pattern-finder.md +2 -2
  61. package/dist/builtin/subagents/agents/codebase-research-analyzer.md +2 -2
  62. package/dist/builtin/subagents/agents/codebase-research-locator.md +2 -2
  63. package/dist/builtin/subagents/agents/debugger.md +2 -2
  64. package/dist/builtin/subagents/agents/worker.md +2 -2
  65. package/dist/builtin/subagents/package.json +5 -5
  66. package/dist/builtin/subagents/prompts/review-loop.md +1 -1
  67. package/dist/builtin/subagents/skills/subagent/SKILL.md +37 -36
  68. package/dist/builtin/subagents/src/extension/api-lifecycle.ts +64 -0
  69. package/dist/builtin/subagents/src/extension/fanout-child.ts +44 -51
  70. package/dist/builtin/subagents/src/extension/index.ts +289 -320
  71. package/dist/builtin/subagents/src/extension/prompt-guidance.ts +7 -10
  72. package/dist/builtin/subagents/src/extension/schemas.ts +22 -5
  73. package/dist/builtin/subagents/src/extension/startup-maintenance.ts +89 -0
  74. package/dist/builtin/subagents/src/extension/tool-description.ts +29 -0
  75. package/dist/builtin/subagents/src/intercom/intercom-bridge.ts +13 -2
  76. package/dist/builtin/subagents/src/intercom/result-intercom.ts +4 -4
  77. package/dist/builtin/subagents/src/runs/background/async-event-journal.ts +106 -0
  78. package/dist/builtin/subagents/src/runs/background/async-execution-common.ts +26 -20
  79. package/dist/builtin/subagents/src/runs/background/async-execution-single.ts +13 -2
  80. package/dist/builtin/subagents/src/runs/background/async-execution-types.ts +3 -0
  81. package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +1 -1
  82. package/dist/builtin/subagents/src/runs/background/completion-claims.ts +189 -0
  83. package/dist/builtin/subagents/src/runs/background/completion-dedupe.ts +44 -7
  84. package/dist/builtin/subagents/src/runs/background/completion-notification.ts +34 -0
  85. package/dist/builtin/subagents/src/runs/background/notify.ts +72 -22
  86. package/dist/builtin/subagents/src/runs/background/result-delivery-processor.ts +232 -0
  87. package/dist/builtin/subagents/src/runs/background/result-file-claims.ts +151 -0
  88. package/dist/builtin/subagents/src/runs/background/result-quarantine.ts +72 -0
  89. package/dist/builtin/subagents/src/runs/background/result-retry-scheduler.ts +48 -0
  90. package/dist/builtin/subagents/src/runs/background/result-status.ts +81 -0
  91. package/dist/builtin/subagents/src/runs/background/result-watcher-data.ts +59 -0
  92. package/dist/builtin/subagents/src/runs/background/result-watcher.ts +177 -233
  93. package/dist/builtin/subagents/src/runs/background/run-id-resolver.ts +3 -2
  94. package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +73 -14
  95. package/dist/builtin/subagents/src/runs/background/subagent-runner-streaming.ts +29 -15
  96. package/dist/builtin/subagents/src/runs/background/top-level-async.ts +1 -2
  97. package/dist/builtin/subagents/src/runs/foreground/chain-execution-dynamic-step.ts +1 -0
  98. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-runner.ts +1 -0
  99. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-step.ts +1 -0
  100. package/dist/builtin/subagents/src/runs/foreground/chain-execution-sequential-step.ts +7 -9
  101. package/dist/builtin/subagents/src/runs/foreground/chain-execution-types.ts +3 -13
  102. package/dist/builtin/subagents/src/runs/foreground/chain-execution.ts +2 -15
  103. package/dist/builtin/subagents/src/runs/foreground/execution-attempt-finalize.ts +2 -2
  104. package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +63 -46
  105. package/dist/builtin/subagents/src/runs/foreground/execution-detach-reservations.ts +48 -0
  106. package/dist/builtin/subagents/src/runs/foreground/execution-detach-route.ts +17 -0
  107. package/dist/builtin/subagents/src/runs/foreground/execution-run-sync.ts +39 -26
  108. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +3 -1
  109. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-chain.ts +3 -51
  110. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-context.ts +6 -11
  111. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-input.ts +11 -2
  112. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +2 -0
  113. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel.ts +5 -112
  114. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-resume.ts +2 -0
  115. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +68 -118
  116. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-status.ts +79 -7
  117. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-types.ts +2 -2
  118. package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +3 -0
  119. package/dist/builtin/subagents/src/runs/shared/pi-args.ts +2 -2
  120. package/dist/builtin/subagents/src/runs/shared/pi-spawn.ts +55 -12
  121. package/dist/builtin/subagents/src/shared/artifacts.ts +22 -11
  122. package/dist/builtin/subagents/src/shared/event-jsonl-writer.ts +294 -0
  123. package/dist/builtin/subagents/src/shared/exclusive-file-publication.ts +44 -0
  124. package/dist/builtin/subagents/src/shared/jsonl-writer.ts +1 -0
  125. package/dist/builtin/subagents/src/shared/model-info.ts +2 -2
  126. package/dist/builtin/subagents/src/shared/settings.ts +20 -10
  127. package/dist/builtin/subagents/src/shared/types-async.ts +3 -1
  128. package/dist/builtin/subagents/src/shared/types-config.ts +2 -0
  129. package/dist/builtin/subagents/src/shared/types-runtime.ts +3 -2
  130. package/dist/builtin/subagents/src/slash/slash-commands.ts +9 -12
  131. package/dist/builtin/subagents/src/slash/slash-live-state.ts +63 -32
  132. package/dist/builtin/subagents/src/tui/render-result.ts +7 -0
  133. package/dist/builtin/subagents/src/tui/render-stable-output.ts +1 -0
  134. package/dist/builtin/subagents/src/tui/render-widget.ts +157 -89
  135. package/dist/builtin/web-access/CHANGELOG.md +28 -0
  136. package/dist/builtin/web-access/README.md +4 -0
  137. package/dist/builtin/web-access/content-tools.ts +8 -3
  138. package/dist/builtin/web-access/index-heavy.ts +1 -1
  139. package/dist/builtin/web-access/index.ts +190 -46
  140. package/dist/builtin/web-access/lifecycle-lease.ts +38 -0
  141. package/dist/builtin/web-access/package.json +2 -2
  142. package/dist/builtin/web-access/result-renderers.ts +1 -1
  143. package/dist/builtin/web-access/summary-review.ts +1 -1
  144. package/dist/builtin/web-access/web-search-activity.ts +1 -1
  145. package/dist/builtin/web-access/web-search-return.ts +7 -0
  146. package/dist/builtin/web-access/web-search-summary.ts +1 -1
  147. package/dist/builtin/web-access/web-search-tool.ts +4 -2
  148. package/dist/builtin/workflows/CHANGELOG.md +86 -0
  149. package/dist/builtin/workflows/README.md +5 -5
  150. package/dist/builtin/workflows/builtin/deep-research-codebase-utils.ts +27 -4
  151. package/dist/builtin/workflows/builtin/goal-runner.ts +86 -27
  152. package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +10 -0
  153. package/dist/builtin/workflows/builtin/ralph-core.ts +9 -9
  154. package/dist/builtin/workflows/builtin/ralph-models.ts +71 -36
  155. package/dist/builtin/workflows/builtin/ralph-runner.ts +20 -31
  156. package/dist/builtin/workflows/package.json +2 -2
  157. package/dist/builtin/workflows/skills/impeccable/SKILL.md +16 -13
  158. package/dist/builtin/workflows/skills/impeccable/reference/adapt.md +1 -0
  159. package/dist/builtin/workflows/skills/impeccable/reference/adapt.native.md +58 -0
  160. package/dist/builtin/workflows/skills/impeccable/reference/android.md +40 -0
  161. package/dist/builtin/workflows/skills/impeccable/reference/animate.md +2 -0
  162. package/dist/builtin/workflows/skills/impeccable/reference/audit.md +2 -0
  163. package/dist/builtin/workflows/skills/impeccable/reference/audit.native.md +139 -0
  164. package/dist/builtin/workflows/skills/impeccable/reference/bolder.md +69 -62
  165. package/dist/builtin/workflows/skills/impeccable/reference/critique.md +21 -7
  166. package/dist/builtin/workflows/skills/impeccable/reference/document.md +1 -1
  167. package/dist/builtin/workflows/skills/impeccable/reference/hooks.md +92 -0
  168. package/dist/builtin/workflows/skills/impeccable/reference/init.md +29 -7
  169. package/dist/builtin/workflows/skills/impeccable/reference/ios.md +45 -0
  170. package/dist/builtin/workflows/skills/impeccable/reference/layout.md +25 -1
  171. package/dist/builtin/workflows/skills/impeccable/reference/typeset.md +23 -1
  172. package/dist/builtin/workflows/skills/impeccable/scripts/context-signals.mjs +2 -1
  173. package/dist/builtin/workflows/skills/impeccable/scripts/context.mjs +75 -14
  174. package/dist/builtin/workflows/skills/impeccable/scripts/detector/browser/injected/index.mjs +1 -1
  175. package/dist/builtin/workflows/skills/impeccable/scripts/detector/cli/main.mjs +31 -0
  176. package/dist/builtin/workflows/skills/impeccable/scripts/detector/design-system.mjs +64 -0
  177. package/dist/builtin/workflows/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +118 -11
  178. package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs +16 -11
  179. package/dist/builtin/workflows/skills/impeccable/scripts/detector/registry/antipatterns.mjs +66 -0
  180. package/dist/builtin/workflows/skills/impeccable/scripts/detector/rules/checks.mjs +42 -10
  181. package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/fonts.mjs +30 -0
  182. package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/page.mjs +4 -6
  183. package/dist/builtin/workflows/skills/impeccable/scripts/hook-admin.mjs +660 -0
  184. package/dist/builtin/workflows/skills/impeccable/scripts/hook-before-edit.mjs +516 -0
  185. package/dist/builtin/workflows/skills/impeccable/scripts/hook-lib.mjs +1764 -0
  186. package/dist/builtin/workflows/skills/impeccable/scripts/hook.mjs +61 -0
  187. package/dist/builtin/workflows/skills/impeccable/scripts/lib/impeccable-config.mjs +4 -2
  188. package/dist/builtin/workflows/skills/impeccable/scripts/lib/is-generated.mjs +2 -2
  189. package/dist/builtin/workflows/skills/impeccable/scripts/live/svelte-component.mjs +13 -16
  190. package/dist/builtin/workflows/skills/impeccable/scripts/live-accept.mjs +17 -11
  191. package/dist/builtin/workflows/skills/impeccable/scripts/live-browser.js +104 -37
  192. package/dist/builtin/workflows/skills/impeccable/scripts/live-wrap.mjs +9 -0
  193. package/dist/builtin/workflows/src/durable/backend.ts +12 -0
  194. package/dist/builtin/workflows/src/durable/dbos-backend.ts +17 -1
  195. package/dist/builtin/workflows/src/durable/resume-catalog.ts +12 -0
  196. package/dist/builtin/workflows/src/durable/resume-runtime.ts +5 -2
  197. package/dist/builtin/workflows/src/durable/stage-primitive.ts +2 -1
  198. package/dist/builtin/workflows/src/durable/types.ts +16 -0
  199. package/dist/builtin/workflows/src/engine/primitives/task.ts +3 -1
  200. package/dist/builtin/workflows/src/engine/run-durable-finalize.ts +1 -2
  201. package/dist/builtin/workflows/src/engine/run-returned-status.ts +50 -16
  202. package/dist/builtin/workflows/src/engine/run.ts +20 -19
  203. package/dist/builtin/workflows/src/engine/runtime.ts +5 -0
  204. package/dist/builtin/workflows/src/extension/extension-factory.ts +3 -0
  205. package/dist/builtin/workflows/src/extension/extension-lifecycle.ts +9 -2
  206. package/dist/builtin/workflows/src/extension/extension-runtime-state.ts +137 -27
  207. package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +22 -6
  208. package/dist/builtin/workflows/src/extension/public-types.ts +1 -1
  209. package/dist/builtin/workflows/src/extension/workflow-command-completions.ts +13 -1
  210. package/dist/builtin/workflows/src/extension/workflow-command-registration.ts +19 -4
  211. package/dist/builtin/workflows/src/extension/workflow-command-surfaces.ts +9 -0
  212. package/dist/builtin/workflows/src/extension/workflow-prompts.ts +17 -22
  213. package/dist/builtin/workflows/src/extension/workflow-run-control-command.ts +48 -23
  214. package/dist/builtin/workflows/src/extension/workflow-schema.ts +15 -2
  215. package/dist/builtin/workflows/src/extension/workflow-tool-control.ts +20 -8
  216. package/dist/builtin/workflows/src/extension/workflow-tool.ts +24 -8
  217. package/dist/builtin/workflows/src/runs/background/status.ts +4 -3
  218. package/dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts +29 -8
  219. package/dist/builtin/workflows/src/runs/foreground/executor-hil.ts +1 -1
  220. package/dist/builtin/workflows/src/runs/foreground/executor-stage-factory.ts +3 -2
  221. package/dist/builtin/workflows/src/runs/shared/model-fallback-candidates.ts +1 -1
  222. package/dist/builtin/workflows/src/runs/shared/worktree-git.ts +155 -20
  223. package/dist/builtin/workflows/src/runs/shared/worktree-types.ts +6 -0
  224. package/dist/builtin/workflows/src/runs/shared/worktree.ts +2 -1
  225. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +2 -2
  226. package/dist/builtin/workflows/src/shared/authoring-contract-stage.ts +2 -2
  227. package/dist/builtin/workflows/src/shared/resume-continuation.ts +2 -0
  228. package/dist/builtin/workflows/src/shared/returned-run-status.ts +116 -0
  229. package/dist/builtin/workflows/src/shared/workflow-failures-decisions.ts +2 -0
  230. package/dist/builtin/workflows/src/tui/graph-view-render-helpers.ts +21 -3
  231. package/dist/builtin/workflows/src/tui/graph-view-state.ts +3 -0
  232. package/dist/builtin/workflows/src/tui/graph-view-types.ts +3 -0
  233. package/dist/builtin/workflows/src/tui/stage-chat-view-archive-history.ts +1 -23
  234. package/dist/builtin/workflows/src/tui/stage-chat-view-footer-status.ts +54 -9
  235. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +5 -2
  236. package/dist/builtin/workflows/src/tui/status-list.ts +22 -15
  237. package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +4 -4
  238. package/dist/cli/args.d.ts.map +1 -1
  239. package/dist/cli/args.js +2 -2
  240. package/dist/cli/args.js.map +1 -1
  241. package/dist/core/agent-session-auto-compaction.d.ts +23 -3
  242. package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
  243. package/dist/core/agent-session-auto-compaction.js +129 -17
  244. package/dist/core/agent-session-auto-compaction.js.map +1 -1
  245. package/dist/core/agent-session-events.d.ts.map +1 -1
  246. package/dist/core/agent-session-events.js +9 -1
  247. package/dist/core/agent-session-events.js.map +1 -1
  248. package/dist/core/agent-session-message-queue.d.ts.map +1 -1
  249. package/dist/core/agent-session-message-queue.js +1 -1
  250. package/dist/core/agent-session-message-queue.js.map +1 -1
  251. package/dist/core/agent-session-methods.d.ts +6 -3
  252. package/dist/core/agent-session-methods.d.ts.map +1 -1
  253. package/dist/core/agent-session-methods.js.map +1 -1
  254. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  255. package/dist/core/agent-session-prompt.js +2 -2
  256. package/dist/core/agent-session-prompt.js.map +1 -1
  257. package/dist/core/agent-session-retry.d.ts.map +1 -1
  258. package/dist/core/agent-session-retry.js +1 -1
  259. package/dist/core/agent-session-retry.js.map +1 -1
  260. package/dist/core/agent-session-services.d.ts.map +1 -1
  261. package/dist/core/agent-session-services.js +3 -2
  262. package/dist/core/agent-session-services.js.map +1 -1
  263. package/dist/core/agent-session-types.d.ts.map +1 -1
  264. package/dist/core/agent-session-types.js +1 -1
  265. package/dist/core/agent-session-types.js.map +1 -1
  266. package/dist/core/agent-session.d.ts +4 -2
  267. package/dist/core/agent-session.d.ts.map +1 -1
  268. package/dist/core/agent-session.js +4 -2
  269. package/dist/core/agent-session.js.map +1 -1
  270. package/dist/core/anthropic-thinking-guard.d.ts +5 -5
  271. package/dist/core/anthropic-thinking-guard.d.ts.map +1 -1
  272. package/dist/core/anthropic-thinking-guard.js +42 -32
  273. package/dist/core/anthropic-thinking-guard.js.map +1 -1
  274. package/dist/core/atomic-guide-command.d.ts.map +1 -1
  275. package/dist/core/atomic-guide-command.js +15 -15
  276. package/dist/core/atomic-guide-command.js.map +1 -1
  277. package/dist/core/auth-storage.d.ts.map +1 -1
  278. package/dist/core/auth-storage.js +14 -9
  279. package/dist/core/auth-storage.js.map +1 -1
  280. package/dist/core/compaction/compaction.d.ts +2 -0
  281. package/dist/core/compaction/compaction.d.ts.map +1 -1
  282. package/dist/core/compaction/compaction.js +79 -46
  283. package/dist/core/compaction/compaction.js.map +1 -1
  284. package/dist/core/compaction/context-assistant-turns.d.ts +42 -0
  285. package/dist/core/compaction/context-assistant-turns.d.ts.map +1 -0
  286. package/dist/core/compaction/context-assistant-turns.js +87 -0
  287. package/dist/core/compaction/context-assistant-turns.js.map +1 -0
  288. package/dist/core/compaction/context-compaction-critical.d.ts +1 -1
  289. package/dist/core/compaction/context-compaction-critical.d.ts.map +1 -1
  290. package/dist/core/compaction/context-compaction-critical.js +2 -2
  291. package/dist/core/compaction/context-compaction-critical.js.map +1 -1
  292. package/dist/core/compaction/context-compaction-eviction-alternates.d.ts +18 -0
  293. package/dist/core/compaction/context-compaction-eviction-alternates.d.ts.map +1 -0
  294. package/dist/core/compaction/context-compaction-eviction-alternates.js +186 -0
  295. package/dist/core/compaction/context-compaction-eviction-alternates.js.map +1 -0
  296. package/dist/core/compaction/context-compaction-eviction.d.ts +10 -2
  297. package/dist/core/compaction/context-compaction-eviction.d.ts.map +1 -1
  298. package/dist/core/compaction/context-compaction-eviction.js +196 -146
  299. package/dist/core/compaction/context-compaction-eviction.js.map +1 -1
  300. package/dist/core/compaction/context-compaction-prompt.d.ts.map +1 -1
  301. package/dist/core/compaction/context-compaction-prompt.js +1 -1
  302. package/dist/core/compaction/context-compaction-prompt.js.map +1 -1
  303. package/dist/core/compaction/context-compaction-types.d.ts +2 -0
  304. package/dist/core/compaction/context-compaction-types.d.ts.map +1 -1
  305. package/dist/core/compaction/context-compaction-types.js.map +1 -1
  306. package/dist/core/compaction/context-deletion-application.d.ts +5 -4
  307. package/dist/core/compaction/context-deletion-application.d.ts.map +1 -1
  308. package/dist/core/compaction/context-deletion-application.js +17 -15
  309. package/dist/core/compaction/context-deletion-application.js.map +1 -1
  310. package/dist/core/compaction/context-deletion-store.d.ts.map +1 -1
  311. package/dist/core/compaction/context-deletion-store.js +1 -1
  312. package/dist/core/compaction/context-deletion-store.js.map +1 -1
  313. package/dist/core/compaction/context-deletion-targets.d.ts +2 -1
  314. package/dist/core/compaction/context-deletion-targets.d.ts.map +1 -1
  315. package/dist/core/compaction/context-deletion-targets.js +36 -31
  316. package/dist/core/compaction/context-deletion-targets.js.map +1 -1
  317. package/dist/core/compaction/context-deletion-tool-helpers.d.ts.map +1 -1
  318. package/dist/core/compaction/context-deletion-tool-helpers.js +116 -43
  319. package/dist/core/compaction/context-deletion-tool-helpers.js.map +1 -1
  320. package/dist/core/compaction/context-transcript-analysis.d.ts +1 -2
  321. package/dist/core/compaction/context-transcript-analysis.d.ts.map +1 -1
  322. package/dist/core/compaction/context-transcript-analysis.js +33 -37
  323. package/dist/core/compaction/context-transcript-analysis.js.map +1 -1
  324. package/dist/core/copilot-model-synthesis.d.ts.map +1 -1
  325. package/dist/core/copilot-model-synthesis.js +3 -1
  326. package/dist/core/copilot-model-synthesis.js.map +1 -1
  327. package/dist/core/extensions/loader-virtual-modules.d.ts +8 -1
  328. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  329. package/dist/core/extensions/loader-virtual-modules.js +2 -1
  330. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  331. package/dist/core/extensions/provider-types.d.ts +2 -7
  332. package/dist/core/extensions/provider-types.d.ts.map +1 -1
  333. package/dist/core/extensions/provider-types.js.map +1 -1
  334. package/dist/core/footer-data-provider.d.ts +6 -0
  335. package/dist/core/footer-data-provider.d.ts.map +1 -1
  336. package/dist/core/footer-data-provider.js +72 -29
  337. package/dist/core/footer-data-provider.js.map +1 -1
  338. package/dist/core/messages.d.ts +9 -0
  339. package/dist/core/messages.d.ts.map +1 -1
  340. package/dist/core/messages.js +100 -18
  341. package/dist/core/messages.js.map +1 -1
  342. package/dist/core/model-registry-builtins.d.ts.map +1 -1
  343. package/dist/core/model-registry-builtins.js +5 -0
  344. package/dist/core/model-registry-builtins.js.map +1 -1
  345. package/dist/core/model-registry-custom-loader.d.ts.map +1 -1
  346. package/dist/core/model-registry-custom-loader.js +49 -8
  347. package/dist/core/model-registry-custom-loader.js.map +1 -1
  348. package/dist/core/model-registry-dynamic.d.ts.map +1 -1
  349. package/dist/core/model-registry-dynamic.js +11 -5
  350. package/dist/core/model-registry-dynamic.js.map +1 -1
  351. package/dist/core/model-registry-loader.d.ts.map +1 -1
  352. package/dist/core/model-registry-loader.js +8 -0
  353. package/dist/core/model-registry-loader.js.map +1 -1
  354. package/dist/core/model-registry-schemas.d.ts +93 -8
  355. package/dist/core/model-registry-schemas.d.ts.map +1 -1
  356. package/dist/core/model-registry-schemas.js +24 -12
  357. package/dist/core/model-registry-schemas.js.map +1 -1
  358. package/dist/core/model-registry-types.d.ts +7 -6
  359. package/dist/core/model-registry-types.d.ts.map +1 -1
  360. package/dist/core/model-registry-types.js.map +1 -1
  361. package/dist/core/model-registry.d.ts +5 -0
  362. package/dist/core/model-registry.d.ts.map +1 -1
  363. package/dist/core/model-registry.js +23 -0
  364. package/dist/core/model-registry.js.map +1 -1
  365. package/dist/core/model-resolver-cli.d.ts.map +1 -1
  366. package/dist/core/model-resolver-cli.js +33 -5
  367. package/dist/core/model-resolver-cli.js.map +1 -1
  368. package/dist/core/model-resolver-initial.d.ts +6 -1
  369. package/dist/core/model-resolver-initial.d.ts.map +1 -1
  370. package/dist/core/model-resolver-initial.js +12 -7
  371. package/dist/core/model-resolver-initial.js.map +1 -1
  372. package/dist/core/model-resolver.d.ts +1 -1
  373. package/dist/core/model-resolver.d.ts.map +1 -1
  374. package/dist/core/model-resolver.js +1 -1
  375. package/dist/core/model-resolver.js.map +1 -1
  376. package/dist/core/openai-responses-payload-sanitizer.d.ts +1 -0
  377. package/dist/core/openai-responses-payload-sanitizer.d.ts.map +1 -1
  378. package/dist/core/openai-responses-payload-sanitizer.js +24 -9
  379. package/dist/core/openai-responses-payload-sanitizer.js.map +1 -1
  380. package/dist/core/resource-loader-context-files.d.ts +1 -0
  381. package/dist/core/resource-loader-context-files.d.ts.map +1 -1
  382. package/dist/core/resource-loader-context-files.js +13 -10
  383. package/dist/core/resource-loader-context-files.js.map +1 -1
  384. package/dist/core/sdk.d.ts.map +1 -1
  385. package/dist/core/sdk.js +2 -2
  386. package/dist/core/sdk.js.map +1 -1
  387. package/dist/core/session-entry-normalization.d.ts +7 -0
  388. package/dist/core/session-entry-normalization.d.ts.map +1 -0
  389. package/dist/core/session-entry-normalization.js +14 -0
  390. package/dist/core/session-entry-normalization.js.map +1 -0
  391. package/dist/core/session-manager-core.d.ts.map +1 -1
  392. package/dist/core/session-manager-core.js +1 -0
  393. package/dist/core/session-manager-core.js.map +1 -1
  394. package/dist/core/session-manager-history.d.ts +2 -2
  395. package/dist/core/session-manager-history.d.ts.map +1 -1
  396. package/dist/core/session-manager-history.js +127 -108
  397. package/dist/core/session-manager-history.js.map +1 -1
  398. package/dist/core/settings-manager-basic-accessors.d.ts +2 -2
  399. package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
  400. package/dist/core/settings-manager-basic-accessors.js.map +1 -1
  401. package/dist/core/settings-types.d.ts +1 -1
  402. package/dist/core/settings-types.d.ts.map +1 -1
  403. package/dist/core/settings-types.js.map +1 -1
  404. package/dist/core/slash-commands.d.ts +2 -0
  405. package/dist/core/slash-commands.d.ts.map +1 -1
  406. package/dist/core/slash-commands.js +141 -0
  407. package/dist/core/slash-commands.js.map +1 -1
  408. package/dist/core/tools/bash.d.ts.map +1 -1
  409. package/dist/core/tools/bash.js +11 -8
  410. package/dist/core/tools/bash.js.map +1 -1
  411. package/dist/index.d.ts +1 -0
  412. package/dist/index.d.ts.map +1 -1
  413. package/dist/index.js +1 -0
  414. package/dist/index.js.map +1 -1
  415. package/dist/main-deferred-startup.d.ts.map +1 -1
  416. package/dist/main-deferred-startup.js +2 -2
  417. package/dist/main-deferred-startup.js.map +1 -1
  418. package/dist/main-early-input.d.ts.map +1 -1
  419. package/dist/main-early-input.js +7 -0
  420. package/dist/main-early-input.js.map +1 -1
  421. package/dist/main-session.d.ts.map +1 -1
  422. package/dist/main-session.js +1 -0
  423. package/dist/main-session.js.map +1 -1
  424. package/dist/main.d.ts.map +1 -1
  425. package/dist/main.js +1 -1
  426. package/dist/main.js.map +1 -1
  427. package/dist/modes/interactive/components/chat-session-host-actions.d.ts.map +1 -1
  428. package/dist/modes/interactive/components/chat-session-host-actions.js +0 -1
  429. package/dist/modes/interactive/components/chat-session-host-actions.js.map +1 -1
  430. package/dist/modes/interactive/components/settings-selector-options.d.ts.map +1 -1
  431. package/dist/modes/interactive/components/settings-selector-options.js +3 -1
  432. package/dist/modes/interactive/components/settings-selector-options.js.map +1 -1
  433. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  434. package/dist/modes/interactive/components/thinking-selector.js +2 -1
  435. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  436. package/dist/modes/interactive/interactive-agent-events.d.ts.map +1 -1
  437. package/dist/modes/interactive/interactive-agent-events.js +3 -1
  438. package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
  439. package/dist/modes/interactive/interactive-autocomplete.d.ts.map +1 -1
  440. package/dist/modes/interactive/interactive-autocomplete.js +21 -9
  441. package/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
  442. package/dist/modes/interactive/interactive-child-ordering.d.ts +7 -0
  443. package/dist/modes/interactive/interactive-child-ordering.d.ts.map +1 -0
  444. package/dist/modes/interactive/interactive-child-ordering.js +26 -0
  445. package/dist/modes/interactive/interactive-child-ordering.js.map +1 -0
  446. package/dist/modes/interactive/interactive-deferred-startup.d.ts.map +1 -1
  447. package/dist/modes/interactive/interactive-deferred-startup.js +43 -30
  448. package/dist/modes/interactive/interactive-deferred-startup.js.map +1 -1
  449. package/dist/modes/interactive/interactive-hotkeys-debug.d.ts.map +1 -1
  450. package/dist/modes/interactive/interactive-hotkeys-debug.js +1 -0
  451. package/dist/modes/interactive/interactive-hotkeys-debug.js.map +1 -1
  452. package/dist/modes/interactive/interactive-input-handling.d.ts.map +1 -1
  453. package/dist/modes/interactive/interactive-input-handling.js +41 -6
  454. package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
  455. package/dist/modes/interactive/interactive-mode-base.d.ts +3 -0
  456. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  457. package/dist/modes/interactive/interactive-mode-base.js +3 -0
  458. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  459. package/dist/modes/interactive/interactive-mode-deps.d.ts +2 -2
  460. package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
  461. package/dist/modes/interactive/interactive-mode-deps.js +2 -2
  462. package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
  463. package/dist/modes/interactive/interactive-mode-surface.d.ts +2 -2
  464. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  465. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  466. package/dist/modes/interactive/interactive-model-routing.d.ts.map +1 -1
  467. package/dist/modes/interactive/interactive-model-routing.js +11 -4
  468. package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
  469. package/dist/modes/interactive/interactive-process-lifecycle.d.ts.map +1 -1
  470. package/dist/modes/interactive/interactive-process-lifecycle.js +0 -3
  471. package/dist/modes/interactive/interactive-process-lifecycle.js.map +1 -1
  472. package/dist/modes/interactive/interactive-render-chat.d.ts.map +1 -1
  473. package/dist/modes/interactive/interactive-render-chat.js +15 -1
  474. package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
  475. package/dist/modes/interactive/interactive-session-routing.d.ts.map +1 -1
  476. package/dist/modes/interactive/interactive-session-routing.js +5 -1
  477. package/dist/modes/interactive/interactive-session-routing.js.map +1 -1
  478. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  479. package/dist/modes/interactive/interactive-startup.js +20 -21
  480. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  481. package/dist/modes/interactive/theme/global-theme.d.ts.map +1 -1
  482. package/dist/modes/interactive/theme/global-theme.js +26 -2
  483. package/dist/modes/interactive/theme/global-theme.js.map +1 -1
  484. package/dist/modes/interactive/theme/theme-class.d.ts +1 -1
  485. package/dist/modes/interactive/theme/theme-class.d.ts.map +1 -1
  486. package/dist/modes/interactive/theme/theme-class.js +2 -0
  487. package/dist/modes/interactive/theme/theme-class.js.map +1 -1
  488. package/dist/utils/clipboard-image.d.ts.map +1 -1
  489. package/dist/utils/clipboard-image.js +3 -0
  490. package/dist/utils/clipboard-image.js.map +1 -1
  491. package/dist/utils/fs-watch.d.ts +24 -1
  492. package/dist/utils/fs-watch.d.ts.map +1 -1
  493. package/dist/utils/fs-watch.js +60 -5
  494. package/dist/utils/fs-watch.js.map +1 -1
  495. package/docs/changelog.mdx +19 -0
  496. package/docs/compaction.md +60 -49
  497. package/docs/custom-provider.md +18 -5
  498. package/docs/development.md +4 -0
  499. package/docs/extensions.md +11 -2
  500. package/docs/json.md +1 -1
  501. package/docs/models.md +69 -10
  502. package/docs/providers.md +1 -1
  503. package/docs/quickstart.md +12 -8
  504. package/docs/rpc.md +2 -2
  505. package/docs/sdk.md +1 -1
  506. package/docs/settings.md +4 -4
  507. package/docs/subagents.md +40 -5
  508. package/docs/tools.md +1 -1
  509. package/docs/usage.md +4 -2
  510. package/docs/windows.md +4 -0
  511. package/docs/workflows.md +33 -48
  512. package/examples/extensions/preset.ts +2 -2
  513. package/examples/extensions/subagent/README.md +2 -2
  514. package/examples/extensions/subagent/index.ts +1 -2
  515. package/examples/extensions/subagent/schemas.ts +4 -1
  516. package/examples/sdk/12-full-control.ts +1 -1
  517. package/npm-shrinkwrap.json +48 -51
  518. package/package.json +7 -7
  519. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-behavior.ts +0 -75
  520. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-component.ts +0 -202
  521. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-edit.ts +0 -97
  522. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-editor.ts +0 -160
  523. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-frame.ts +0 -72
  524. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-render-modes.ts +0 -161
  525. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-render-selectors.ts +0 -203
  526. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-selectors.ts +0 -234
  527. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-state.ts +0 -103
  528. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-types.ts +0 -29
  529. package/dist/builtin/subagents/src/runs/foreground/chain-clarify.ts +0 -9
  530. package/dist/builtin/subagents/src/runs/foreground/chain-execution-clarify.ts +0 -117
@@ -1,11 +1,16 @@
1
1
  import type { AgentToolUpdateCallback, ExtensionAPI, ExtensionContext, ToolInfo } from "@bastani/atomic";
2
- import type { McpExtensionState } from "./state.ts";
3
- import type { McpConfig } from "./types.ts";
4
- import type { MetadataCache } from "./metadata-cache.ts";
2
+ import type { McpExtensionState } from "./state.js";
3
+ import type { McpConfig } from "./types.js";
4
+ import type { MetadataCache } from "./metadata-cache.js";
5
+ import type { ProxyToolResult } from "./proxy-types.js";
6
+ import { waitForCaller } from "./caller-wait.js";
7
+ import { McpSessionCleanupBarrier } from "./session-cleanup-barrier.js";
8
+ import { McpStateChangedError } from "./state-lease.js";
9
+ import { registerMcpCommands } from "./command-registration.js";
5
10
  import { Type } from "typebox";
6
- import { loadMcpConfig } from "./config.ts";
7
- import { getConfigPathFromArgv } from "./utils.ts";
8
- import { renderMcpToolResult } from "./tool-result-renderer.ts";
11
+ import { loadMcpConfig } from "./config.js";
12
+ import { getConfigPathFromArgv } from "./utils.js";
13
+ import { renderMcpToolResult } from "./tool-result-renderer.js";
9
14
 
10
15
  /**
11
16
  * Marker substring from the host's stale-context error (see ExtensionRunner.invalidate).
@@ -13,16 +18,19 @@ import { renderMcpToolResult } from "./tool-result-renderer.ts";
13
18
  * workflow child stage session, or a reload/replace) without emitting `session_shutdown`.
14
19
  */
15
20
  const STALE_EXTENSION_CONTEXT_MARKER = "extension ctx is stale";
21
+ const STALE_INITIALIZATION_PREFIX = "Stale MCP session initialization cancelled";
22
+
23
+ interface ActiveMcpSession {
24
+ readonly generation: number;
25
+ readonly ctx: ExtensionContext;
26
+ readonly cleanup: Promise<void>;
27
+ }
16
28
 
17
29
  function isStaleExtensionContextError(error: unknown): boolean {
18
30
  return error instanceof Error && error.message.includes(STALE_EXTENSION_CONTEXT_MARKER);
19
31
  }
20
32
 
21
- /**
22
- * Probe whether a captured extension context is still active. Every `ctx` getter runs
23
- * the host's `assertActive()` guard, so a cheap property read surfaces staleness without
24
- * mutating anything. Returns false when the context has been invalidated by a dispose.
25
- */
33
+ /** Probe the host guard to determine whether a captured context remains active. */
26
34
  function isContextActive(ctx: ExtensionContext): boolean {
27
35
  try {
28
36
  void ctx.cwd;
@@ -39,24 +47,29 @@ export default function mcpAdapter(pi: ExtensionAPI) {
39
47
  let lifecycleGeneration = 0;
40
48
  let registeredDirectToolNames = new Set<string>();
41
49
  let registeredProxyTool = false;
50
+ let startupWarmupCancel: (() => void) | null = null;
51
+ let activeSession: ActiveMcpSession | null = null;
52
+ let stateOwner: ActiveMcpSession | null = null;
53
+ const cleanupBarrier = new McpSessionCleanupBarrier();
42
54
 
43
55
  async function registerDirectToolsFromConfig(
44
56
  config: McpConfig,
45
57
  cache: MetadataCache | null,
46
58
  ): Promise<{ directToolCount: number; missingConfiguredDirectToolServers: string[] }> {
47
59
  const [{ resolveDirectTools, createDirectToolExecutor, getMissingConfiguredDirectToolServers }, { truncateAtWord }] = await Promise.all([
48
- import("./direct-tools.ts"),
49
- import("./utils.ts"),
60
+ import("./direct-tools.js"),
61
+ import("./utils.js"),
50
62
  ]);
51
63
  const prefix = config.settings?.toolPrefix ?? "server";
52
64
  const envRaw = process.env.MCP_DIRECT_TOOLS;
65
+ const envDirectTools = envRaw?.split(",").map(s => s.trim()).filter(Boolean);
53
66
  const directSpecs = envRaw === "__none__"
54
67
  ? []
55
68
  : resolveDirectTools(
56
69
  config,
57
70
  cache,
58
71
  prefix,
59
- envRaw?.split(",").map(s => s.trim()).filter(Boolean),
72
+ envDirectTools,
60
73
  );
61
74
  for (const spec of directSpecs) {
62
75
  if (registeredDirectToolNames.has(spec.prefixedName)) continue;
@@ -67,7 +80,11 @@ export default function mcpAdapter(pi: ExtensionAPI) {
67
80
  description: spec.description || "(no description)",
68
81
  promptSnippet: truncateAtWord(spec.description, 100) || `MCP tool from ${spec.serverName}`,
69
82
  parameters: Type.Unsafe((spec.inputSchema || { type: "object", properties: {} }) as never),
70
- execute: createDirectToolExecutor(() => state, () => initPromise, spec),
83
+ execute: createDirectToolExecutor(
84
+ () => ensureMcpInitialized(),
85
+ (candidate) => isOwnedState(candidate),
86
+ spec,
87
+ ),
71
88
  renderResult: renderMcpToolResult,
72
89
  });
73
90
  }
@@ -75,48 +92,54 @@ export default function mcpAdapter(pi: ExtensionAPI) {
75
92
  refreshTools?.();
76
93
  return {
77
94
  directToolCount: directSpecs.length,
78
- missingConfiguredDirectToolServers: getMissingConfiguredDirectToolServers(config, cache),
95
+ missingConfiguredDirectToolServers: getMissingConfiguredDirectToolServers(config, cache, envDirectTools),
79
96
  };
80
97
  }
81
98
 
82
99
  async function registerDirectTools(nextState: McpExtensionState): Promise<{ directToolCount: number; missingConfiguredDirectToolServers: string[] }> {
83
- const { loadMetadataCache } = await import("./metadata-cache.ts");
100
+ const { loadMetadataCache } = await import("./metadata-cache.js");
84
101
  return registerDirectToolsFromConfig(nextState.config, loadMetadataCache());
85
102
  }
86
103
 
87
- async function shutdownOAuthFlow(): Promise<void> {
88
- const { shutdownOAuth } = await import("./mcp-auth-flow.ts");
89
- await shutdownOAuth();
104
+ async function shutdownOAuthFlow(reason: string): Promise<void> {
105
+ const { shutdownOAuth } = await import("./mcp-auth-flow.js");
106
+ await shutdownOAuth(reason);
90
107
  }
91
108
 
92
109
  async function shutdownState(currentState: McpExtensionState | null, reason: string): Promise<void> {
93
110
  if (!currentState) return;
94
-
95
- if (currentState.uiServer) {
96
- currentState.uiServer.close(reason);
97
- currentState.uiServer = null;
111
+ const failures: unknown[] = [];
112
+ const uiServer = currentState.uiServer;
113
+ currentState.uiServer = null;
114
+ try {
115
+ uiServer?.close(reason);
116
+ } catch (error) {
117
+ failures.push(error);
98
118
  }
99
-
100
- let flushError: unknown;
101
119
  try {
102
- const { flushMetadataCache } = await import("./init.ts");
120
+ const { flushMetadataCache } = await import("./init.js");
103
121
  flushMetadataCache(currentState);
104
122
  } catch (error) {
105
- flushError = error;
123
+ failures.push(error);
106
124
  }
107
-
108
125
  try {
109
126
  await currentState.lifecycle.gracefulShutdown();
110
127
  } catch (error) {
111
- if (flushError) {
112
- console.error("MCP: graceful shutdown failed after metadata flush error", error);
113
- } else {
114
- throw error;
115
- }
128
+ failures.push(error);
129
+ }
130
+ for (const error of failures.slice(1)) {
131
+ console.error("MCP: additional state shutdown failure", error);
116
132
  }
133
+ if (failures.length > 0) throw failures[0];
134
+ }
117
135
 
118
- if (flushError) {
119
- throw flushError;
136
+ async function cleanupSessionResources(currentState: McpExtensionState | null, reason: string, label: string): Promise<void> {
137
+ const results = await Promise.allSettled([
138
+ shutdownState(currentState, reason),
139
+ shutdownOAuthFlow(reason),
140
+ ]);
141
+ for (const result of results) {
142
+ if (result.status === "rejected") console.error(label, result.reason);
120
143
  }
121
144
  }
122
145
 
@@ -129,17 +152,152 @@ export default function mcpAdapter(pi: ExtensionAPI) {
129
152
  type: "string",
130
153
  });
131
154
 
155
+ function cancelStartupWarmup(): void {
156
+ startupWarmupCancel?.();
157
+ startupWarmupCancel = null;
158
+ }
159
+
160
+ function isCurrentSession(session: ActiveMcpSession): boolean {
161
+ return activeSession === session
162
+ && lifecycleGeneration === session.generation
163
+ && isContextActive(session.ctx);
164
+ }
165
+
166
+ function isOwnedState(candidate: McpExtensionState, owner = stateOwner): boolean {
167
+ return state === candidate && owner !== null && stateOwner === owner && isCurrentSession(owner);
168
+ }
169
+
170
+ function assertOwnedState(candidate: McpExtensionState, owner: ActiveMcpSession): void {
171
+ if (!isOwnedState(candidate, owner)) throw new McpStateChangedError();
172
+ }
173
+
174
+ async function initializeSession(
175
+ session: ActiveMcpSession,
176
+ expectedPromise: { current: Promise<McpExtensionState> | null },
177
+ ): Promise<McpExtensionState> {
178
+ await session.cleanup;
179
+ if (!isCurrentSession(session)) {
180
+ throw new Error(`${STALE_INITIALIZATION_PREFIX} before startup`);
181
+ }
182
+
183
+ const [{ initializeMcp, updateStatusBar }, { scheduleMcpStartupWarmup }] = await Promise.all([
184
+ import("./init.js"),
185
+ import("./startup-warmup.js"),
186
+ ]);
187
+ if (!isCurrentSession(session)) {
188
+ throw new Error(`${STALE_INITIALIZATION_PREFIX} before startup`);
189
+ }
190
+
191
+ let candidate: McpExtensionState | null = null;
192
+ try {
193
+ candidate = await initializeMcp(pi, session.ctx);
194
+ const initializedState = candidate;
195
+ if (!isCurrentSession(session) || initPromise !== expectedPromise.current) {
196
+ throw new Error(`${STALE_INITIALIZATION_PREFIX} after startup`);
197
+ }
198
+
199
+ const directToolState = await registerDirectTools(initializedState);
200
+ if (!isCurrentSession(session) || initPromise !== expectedPromise.current) {
201
+ throw new Error(`${STALE_INITIALIZATION_PREFIX} after tool registration`);
202
+ }
203
+ if (
204
+ initializedState.config.settings?.disableProxyTool !== true
205
+ || directToolState.directToolCount === 0
206
+ || directToolState.missingConfiguredDirectToolServers.length > 0
207
+ ) {
208
+ registerProxyTool();
209
+ }
210
+
211
+ updateStatusBar(initializedState);
212
+ let cancelWarmup: (() => void) | null = null;
213
+ const warmup = scheduleMcpStartupWarmup(initializedState, {
214
+ shouldContinue: () => isCurrentSession(session) && state === initializedState,
215
+ onDirectToolsChanged: async () => {
216
+ if (!isCurrentSession(session) || state !== initializedState) return;
217
+ await registerDirectTools(initializedState);
218
+ },
219
+ onSettled: () => {
220
+ if (isCurrentSession(session) && state === initializedState && startupWarmupCancel === cancelWarmup) {
221
+ startupWarmupCancel = null;
222
+ }
223
+ },
224
+ });
225
+ cancelWarmup = () => warmup.cancel();
226
+ startupWarmupCancel = cancelWarmup;
227
+ stateOwner = session;
228
+ state = initializedState;
229
+ return initializedState;
230
+ } catch (error) {
231
+ if (candidate && state !== candidate) {
232
+ try {
233
+ await shutdownState(candidate, "failed_initialization");
234
+ } catch (cleanupError) {
235
+ console.error("MCP: failed to clean unpublished initialization state", cleanupError);
236
+ }
237
+ }
238
+ throw error;
239
+ }
240
+ }
241
+
242
+ function ensureMcpInitialized(): Promise<McpExtensionState> {
243
+ const session = activeSession;
244
+ if (!session || session.generation !== lifecycleGeneration || !isContextActive(session.ctx)) {
245
+ return Promise.reject(new Error("MCP initialization unavailable: no active session"));
246
+ }
247
+ if (state) {
248
+ if (stateOwner === session && isOwnedState(state, session)) return Promise.resolve(state);
249
+ return Promise.reject(new Error("MCP initialization unavailable: stale session state"));
250
+ }
251
+ if (initPromise) return initPromise;
252
+
253
+ const expectedPromise: { current: Promise<McpExtensionState> | null } = { current: null };
254
+ const attempt = initializeSession(session, expectedPromise);
255
+ expectedPromise.current = attempt;
256
+ initPromise = attempt;
257
+ void attempt.then(
258
+ () => {
259
+ if (initPromise === attempt) initPromise = null;
260
+ },
261
+ (error: unknown) => {
262
+ if (activeSession !== session || session.generation !== lifecycleGeneration) return;
263
+ const message = error instanceof Error ? error.message : String(error);
264
+ if (!message.startsWith(STALE_INITIALIZATION_PREFIX) && !isStaleExtensionContextError(error)) {
265
+ console.error(
266
+ `MCP initialization failed for session generation ${session.generation}; a later MCP call will retry:`,
267
+ error,
268
+ );
269
+ }
270
+ if (initPromise === attempt) initPromise = null;
271
+ },
272
+ );
273
+ return attempt;
274
+ }
275
+
132
276
  pi.on("session_start", async (_event, ctx) => {
133
277
  const generation = ++lifecycleGeneration;
134
278
  const previousState = state;
279
+ const retiredInitialization = initPromise;
135
280
  state = null;
281
+ stateOwner = null;
136
282
  initPromise = null;
137
283
  registeredDirectToolNames = new Set<string>();
284
+ cancelStartupWarmup();
285
+ const previousStateCleanup = cleanupSessionResources(
286
+ previousState,
287
+ "session_restart",
288
+ "MCP: failed to shut down previous session state",
289
+ );
290
+ const cleanup = cleanupBarrier.retain([retiredInitialization, previousStateCleanup]);
291
+ const isStartCurrent = (): boolean => generation === lifecycleGeneration && isContextActive(ctx);
292
+ await cleanup;
293
+ if (!isStartCurrent()) return;
138
294
 
139
295
  try {
140
296
  const config = loadMcpConfig(earlyConfigPath, ctx.cwd);
141
- const { loadMetadataCache } = await import("./metadata-cache.ts");
297
+ const { loadMetadataCache } = await import("./metadata-cache.js");
298
+ if (!isStartCurrent()) return;
142
299
  const directToolState = await registerDirectToolsFromConfig(config, loadMetadataCache());
300
+ if (!isStartCurrent()) return;
143
301
  if (
144
302
  config.settings?.disableProxyTool !== true
145
303
  || directToolState.directToolCount === 0
@@ -148,189 +306,44 @@ export default function mcpAdapter(pi: ExtensionAPI) {
148
306
  registerProxyTool();
149
307
  }
150
308
  } catch (error) {
151
- if (isStaleExtensionContextError(error)) return;
309
+ if (!isStartCurrent() || isStaleExtensionContextError(error)) return;
152
310
  console.error("MCP: failed to register cached startup tools; enabling MCP proxy fallback", error);
153
311
  registerProxyTool();
154
312
  }
155
313
 
156
- const promiseRef: { current: Promise<McpExtensionState> | null } = { current: null };
157
- const promise = (async () => {
158
- try {
159
- await Promise.all([
160
- shutdownState(previousState, "session_restart"),
161
- shutdownOAuthFlow(),
162
- ]);
163
- } catch (error) {
164
- console.error("MCP: failed to shut down previous session state", error);
165
- }
166
-
167
- if (generation !== lifecycleGeneration || !isContextActive(ctx)) {
168
- throw new Error("Stale MCP session initialization cancelled before startup");
169
- }
170
-
171
- const { initializeMcp, updateStatusBar } = await import("./init.ts");
172
- if (generation !== lifecycleGeneration || !isContextActive(ctx)) {
173
- throw new Error("Stale MCP session initialization cancelled before startup");
174
- }
175
-
176
- const nextState = await initializeMcp(pi, ctx);
177
- if (generation !== lifecycleGeneration || initPromise !== promiseRef.current || !isContextActive(ctx)) {
178
- try {
179
- await shutdownState(nextState, "stale_session_start");
180
- } catch (error) {
181
- console.error("MCP: failed to clean stale session state", error);
182
- }
183
- throw new Error("Stale MCP session initialization cancelled after startup");
184
- }
185
-
186
- state = nextState;
187
- updateStatusBar(nextState);
188
- const directToolState = await registerDirectTools(nextState);
189
- if (
190
- nextState.config.settings?.disableProxyTool !== true
191
- || directToolState.directToolCount === 0
192
- || directToolState.missingConfiguredDirectToolServers.length > 0
193
- ) {
194
- registerProxyTool();
195
- }
196
- if (initPromise === promiseRef.current) {
197
- initPromise = null;
198
- }
199
- return nextState;
200
- })();
201
- promiseRef.current = promise;
202
- initPromise = promise;
203
- promise.catch((err) => {
204
- if (generation !== lifecycleGeneration) {
205
- return;
206
- }
207
- if (initPromise !== promise && initPromise !== null) {
208
- return;
209
- }
210
- const message = err instanceof Error ? err.message : String(err);
211
- if (
212
- !message.startsWith("Stale MCP session initialization cancelled") &&
213
- !isStaleExtensionContextError(err)
214
- ) {
215
- console.error("MCP initialization failed:", err);
216
- }
217
- if (initPromise === promise) {
218
- initPromise = null;
219
- }
220
- });
314
+ if (!isStartCurrent()) return;
315
+ activeSession = { generation, ctx, cleanup };
316
+ void ensureMcpInitialized().catch(() => undefined);
221
317
  });
222
318
 
223
319
  pi.on("session_shutdown", async () => {
224
320
  ++lifecycleGeneration;
225
321
  const currentState = state;
322
+ const retiredInitialization = initPromise;
323
+ activeSession = null;
226
324
  state = null;
325
+ stateOwner = null;
227
326
  initPromise = null;
228
327
  registeredDirectToolNames = new Set<string>();
229
-
230
- try {
231
- await Promise.all([
232
- shutdownState(currentState, "session_shutdown"),
233
- shutdownOAuthFlow(),
234
- ]);
235
- } catch (error) {
236
- console.error("MCP: session shutdown cleanup failed", error);
237
- }
238
- });
239
-
240
- pi.registerCommand("mcp", {
241
- description: "Show MCP server status",
242
- handler: async (args, ctx) => {
243
- if (!state && initPromise) {
244
- try {
245
- state = await initPromise;
246
- } catch (error) {
247
- const message = error instanceof Error ? error.message : String(error);
248
- if (ctx.hasUI) ctx.ui.notify(`MCP initialization failed: ${message}`, "error");
249
- return;
250
- }
251
- }
252
- if (!state) {
253
- if (ctx.hasUI) ctx.ui.notify("MCP not initialized", "error");
254
- return;
255
- }
256
-
257
- const { showStatus, showTools, reconnectServers, logoutServer, openMcpPanel, openMcpSetup } = await import("./commands.ts");
258
- const parts = args?.trim()?.split(/\s+/) ?? [];
259
- const subcommand = parts[0] ?? "";
260
- const targetServer = parts[1];
261
- const rest = parts.slice(1).join(" ");
262
-
263
- switch (subcommand) {
264
- case "reconnect":
265
- await reconnectServers(state, ctx, targetServer);
266
- break;
267
- case "tools":
268
- await showTools(state, ctx);
269
- break;
270
- case "setup": {
271
- const result = await openMcpSetup(state, pi, ctx, earlyConfigPath, "setup");
272
- if (result?.configChanged) {
273
- await ctx.reload();
274
- return;
275
- }
276
- break;
277
- }
278
- case "logout": {
279
- const serverName = rest;
280
- if (!serverName) {
281
- if (ctx.hasUI) ctx.ui.notify("Usage: /mcp logout <server>", "error");
282
- return;
283
- }
284
- await logoutServer(serverName, state, ctx);
285
- break;
286
- }
287
- case "status":
288
- case "":
289
- default:
290
- if (ctx.hasUI) {
291
- const result = await openMcpPanel(state, pi, ctx, earlyConfigPath);
292
- if (result?.configChanged) {
293
- await ctx.reload();
294
- return;
295
- }
296
- } else {
297
- await showStatus(state, ctx);
298
- }
299
- break;
300
- }
301
- },
328
+ cancelStartupWarmup();
329
+
330
+ const stateCleanup = cleanupSessionResources(
331
+ currentState,
332
+ "session_shutdown",
333
+ "MCP: session shutdown cleanup failed",
334
+ );
335
+ await cleanupBarrier.retain([retiredInitialization, stateCleanup]);
302
336
  });
303
337
 
304
- pi.registerCommand("mcp-auth", {
305
- description: "Authenticate with an MCP server (OAuth)",
306
- handler: async (args, ctx) => {
307
- const serverName = args?.trim();
308
- if (!serverName && !ctx.hasUI) {
309
- return;
310
- }
311
-
312
- if (!state && initPromise) {
313
- try {
314
- state = await initPromise;
315
- } catch (error) {
316
- const message = error instanceof Error ? error.message : String(error);
317
- if (ctx.hasUI) ctx.ui.notify(`MCP initialization failed: ${message}`, "error");
318
- return;
319
- }
320
- }
321
- if (!state) {
322
- if (ctx.hasUI) ctx.ui.notify("MCP not initialized", "error");
323
- return;
324
- }
325
-
326
- const { authenticateServer, openMcpAuthPanel } = await import("./commands.ts");
327
- if (!serverName) {
328
- await openMcpAuthPanel(state, pi, ctx, earlyConfigPath);
329
- return;
330
- }
331
-
332
- await authenticateServer(serverName, state.config, ctx);
333
- },
338
+ registerMcpCommands(pi, earlyConfigPath, async () => {
339
+ const readyState = await ensureMcpInitialized();
340
+ const readyOwner = stateOwner;
341
+ if (!readyOwner) throw new McpStateChangedError();
342
+ assertOwnedState(readyState, readyOwner);
343
+ return {
344
+ state: readyState,
345
+ assertActive: () => assertOwnedState(readyState, readyOwner),
346
+ };
334
347
  });
335
348
 
336
349
  function registerProxyTool(): void {
@@ -363,7 +376,8 @@ export default function mcpAdapter(pi: ExtensionAPI) {
363
376
  includeSchemas?: boolean;
364
377
  server?: string;
365
378
  action?: string;
366
- }, _signal: AbortSignal | undefined, _onUpdate: AgentToolUpdateCallback<Record<string, unknown>> | undefined, _ctx: ExtensionContext) {
379
+ }, signal: AbortSignal | undefined, _onUpdate: AgentToolUpdateCallback<Record<string, unknown>> | undefined, _ctx: ExtensionContext) {
380
+ signal?.throwIfAborted();
367
381
  let parsedArgs: Record<string, unknown> | undefined;
368
382
  if (params.args) {
369
383
  try {
@@ -380,44 +394,65 @@ export default function mcpAdapter(pi: ExtensionAPI) {
380
394
  }
381
395
  }
382
396
 
383
- if (!state && initPromise) {
384
- try {
385
- state = await initPromise;
386
- } catch (error) {
387
- const message = error instanceof Error ? error.message : String(error);
388
- return {
389
- content: [{ type: "text" as const, text: `MCP initialization failed: ${message}` }],
390
- details: { error: "init_failed", message },
391
- };
392
- }
397
+ let readyState: McpExtensionState;
398
+ try {
399
+ readyState = await waitForCaller(ensureMcpInitialized, signal);
400
+ } catch (error) {
401
+ signal?.throwIfAborted();
402
+ const message = error instanceof Error ? error.message : String(error);
403
+ return {
404
+ content: [{ type: "text" as const, text: `MCP initialization failed: ${message}` }],
405
+ details: { error: "init_failed", message },
406
+ };
393
407
  }
394
- if (!state) {
408
+ signal?.throwIfAborted();
409
+ const readyOwner = stateOwner;
410
+ if (!readyOwner || !isOwnedState(readyState, readyOwner)) {
395
411
  return {
396
- content: [{ type: "text" as const, text: "MCP not initialized" }],
397
- details: { error: "not_initialized" },
412
+ content: [{ type: "text" as const, text: "MCP session changed during initialization" }],
413
+ details: { error: "init_cancelled", message: "Session changed before MCP execution" },
398
414
  };
399
415
  }
416
+ const assertActive = (): void => assertOwnedState(readyState, readyOwner);
400
417
 
401
- const { executeCall, executeConnect, executeDescribe, executeList, executeSearch, executeStatus, executeUiMessages } = await import("./proxy-modes.ts");
402
- if (params.action === "ui-messages") {
403
- return executeUiMessages(state);
404
- }
405
- if (params.tool) {
406
- return executeCall(state, params.tool, parsedArgs, params.server, getPiTools);
407
- }
408
- if (params.connect) {
409
- return executeConnect(state, params.connect);
410
- }
411
- if (params.describe) {
412
- return executeDescribe(state, params.describe);
413
- }
414
- if (params.search) {
415
- return executeSearch(state, params.search, params.regex, params.server, params.includeSchemas);
416
- }
417
- if (params.server) {
418
- return executeList(state, params.server);
418
+ const { executeCall, executeConnect, executeDescribe, executeList, executeSearch, executeStatus, executeUiMessages } = await import("./proxy-modes.js");
419
+ signal?.throwIfAborted();
420
+ try {
421
+ assertActive();
422
+ } catch (error) {
423
+ if (error instanceof McpStateChangedError) {
424
+ return {
425
+ content: [{ type: "text" as const, text: "MCP session changed during execution" }],
426
+ details: { error: "state_changed", message: "Session changed before MCP execution completed" },
427
+ };
428
+ }
429
+ throw error;
419
430
  }
420
- return executeStatus(state);
431
+ const stateChangedResult = (): ProxyToolResult => ({
432
+ content: [{ type: "text" as const, text: "MCP session changed during execution" }],
433
+ details: { error: "state_changed", message: "Session changed before MCP execution completed" },
434
+ });
435
+ const finish = async (start: () => ProxyToolResult | Promise<ProxyToolResult>): Promise<ProxyToolResult> => {
436
+ try {
437
+ signal?.throwIfAborted();
438
+ assertActive();
439
+ const result = await start();
440
+ signal?.throwIfAborted();
441
+ assertActive();
442
+ return result;
443
+ } catch (error) {
444
+ signal?.throwIfAborted();
445
+ if (error instanceof McpStateChangedError) return stateChangedResult();
446
+ throw error;
447
+ }
448
+ };
449
+ if (params.action === "ui-messages") return finish(() => executeUiMessages(readyState, assertActive));
450
+ if (params.tool) return finish(() => executeCall(readyState, params.tool!, parsedArgs, params.server, getPiTools, signal, undefined, assertActive));
451
+ if (params.connect) return finish(() => executeConnect(readyState, params.connect!, signal, undefined, assertActive));
452
+ if (params.describe) return finish(() => executeDescribe(readyState, params.describe!, params.server, signal, assertActive));
453
+ if (params.search) return finish(() => executeSearch(readyState, params.search!, params.regex, params.server, params.includeSchemas, signal, assertActive));
454
+ if (params.server) return finish(() => executeList(readyState, params.server!, signal, assertActive));
455
+ return finish(() => executeStatus(readyState, assertActive));
421
456
  },
422
457
  });
423
458
  }