@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,14 +1,19 @@
1
1
  import type { ToolInfo } from "@bastani/atomic";
2
- import type { McpExtensionState } from "./state.ts";
3
- import type { McpContent, ToolMetadata } from "./types.ts";
4
- import { getServerPrefix } from "./types.ts";
5
- import { lazyConnect, updateServerMetadata, updateMetadataCache, getFailureAgeSeconds, updateStatusBar } from "./init.ts";
6
- import { getToolNames, findToolByName, formatSchema } from "./tool-metadata.ts";
7
- import { transformMcpContent } from "./tool-registrar.ts";
8
- import { maybeStartUiSession, type UiSessionRuntime } from "./ui-session.ts";
9
- import { unflattenToolArguments } from "./utils.ts";
10
- import { attemptAutoAuth, getAuthRequiredMessage } from "./proxy-auth.ts";
11
- import type { ProxyToolResult } from "./proxy-types.ts";
2
+ import type { McpExtensionState } from "./state.js";
3
+ import type { McpContent, ToolMetadata } from "./types.js";
4
+ import { getServerPrefix } from "./types.js";
5
+ import { lazyConnect, updateServerMetadata, updateMetadataCache, getFailureAgeSeconds, updateStatusBar } from "./init.js";
6
+ import { getToolNames, findToolByName, formatSchema } from "./tool-metadata.js";
7
+ import { transformMcpContent } from "./tool-registrar.js";
8
+ import { maybeStartUiSession, type UiSessionRuntime } from "./ui-session.js";
9
+ import { unflattenToolArguments } from "./utils.js";
10
+ import { attemptAutoAuth, getAuthRequiredMessage, type AutoAuthResult } from "./proxy-auth.js";
11
+ import type { ProxyToolResult } from "./proxy-types.js";
12
+ import { CallToolResultSchema } from "@modelcontextprotocol/sdk/types.js";
13
+ import { waitForCaller, waitForCallerWithLateCleanup } from "./caller-wait.js";
14
+ import { notifyUiCancellation, rethrowHostAbortAfterUiCancellation } from "./apps-cancellation.js";
15
+ import { asCallToolResult } from "./call-tool-result.js";
16
+ import { assertMcpStateLease, McpStateChangedError, type AssertMcpStateLease } from "./state-lease.js";
12
17
 
13
18
  export async function executeCall(
14
19
  state: McpExtensionState,
@@ -16,7 +21,12 @@ export async function executeCall(
16
21
  args?: Record<string, unknown>,
17
22
  serverOverride?: string,
18
23
  getPiTools?: () => ToolInfo[],
24
+ signal?: AbortSignal,
25
+ startAutoAuth: (state: McpExtensionState, serverName: string) => Promise<AutoAuthResult> = attemptAutoAuth,
26
+ assertActive?: AssertMcpStateLease,
19
27
  ): Promise<ProxyToolResult> {
28
+ signal?.throwIfAborted();
29
+ assertMcpStateLease(assertActive);
20
30
  let serverName: string | undefined = serverOverride;
21
31
  let toolMeta: ToolMetadata | undefined;
22
32
  let autoAuthAttempted = false;
@@ -43,14 +53,18 @@ export async function executeCall(
43
53
  }
44
54
 
45
55
  if (serverName && !toolMeta) {
46
- const connected = await lazyConnect(state, serverName);
56
+ const connected = await waitForCaller(() => lazyConnect(state, serverName!), signal);
57
+ signal?.throwIfAborted();
58
+ assertMcpStateLease(assertActive);
47
59
  if (connected) {
48
60
  toolMeta = findToolByName(state.toolMetadata.get(serverName), toolName);
49
61
  } else {
50
62
  const needsAuthConnection = state.manager.getConnection(serverName);
51
63
  if (needsAuthConnection?.status === "needs-auth") {
52
64
  autoAuthAttempted = true;
53
- const autoAuth = await attemptAutoAuth(state, serverName);
65
+ const autoAuth = await waitForCaller(() => startAutoAuth(state, serverName!), signal);
66
+ signal?.throwIfAborted();
67
+ assertMcpStateLease(assertActive);
54
68
  if (autoAuth.status === "failed") {
55
69
  return {
56
70
  content: [{ type: "text" as const, text: autoAuth.message }],
@@ -58,9 +72,13 @@ export async function executeCall(
58
72
  };
59
73
  }
60
74
  if (autoAuth.status === "success") {
61
- await state.manager.close(serverName);
75
+ await waitForCaller(() => state.manager.close(serverName!), signal);
76
+ signal?.throwIfAborted();
77
+ assertMcpStateLease(assertActive);
62
78
  state.failureTracker.delete(serverName);
63
- const connectedAfterAuth = await lazyConnect(state, serverName);
79
+ const connectedAfterAuth = await waitForCaller(() => lazyConnect(state, serverName!), signal);
80
+ signal?.throwIfAborted();
81
+ assertMcpStateLease(assertActive);
64
82
  if (connectedAfterAuth) {
65
83
  toolMeta = findToolByName(state.toolMetadata.get(serverName), toolName);
66
84
  if (!toolMeta) {
@@ -106,10 +124,14 @@ export async function executeCall(
106
124
  const failedAgo = getFailureAgeSeconds(state, configuredServer);
107
125
  if (failedAgo !== null && existingConnection?.status !== "needs-auth") continue;
108
126
 
109
- let connected = await lazyConnect(state, configuredServer);
127
+ let connected = await waitForCaller(() => lazyConnect(state, configuredServer), signal);
128
+ signal?.throwIfAborted();
129
+ assertMcpStateLease(assertActive);
110
130
  if (!connected && state.manager.getConnection(configuredServer)?.status === "needs-auth" && !autoAuthAttempted) {
111
131
  autoAuthAttempted = true;
112
- const autoAuth = await attemptAutoAuth(state, configuredServer);
132
+ const autoAuth = await waitForCaller(() => startAutoAuth(state, configuredServer), signal);
133
+ signal?.throwIfAborted();
134
+ assertMcpStateLease(assertActive);
113
135
  if (autoAuth.status === "failed") {
114
136
  return {
115
137
  content: [{ type: "text" as const, text: autoAuth.message }],
@@ -117,9 +139,13 @@ export async function executeCall(
117
139
  };
118
140
  }
119
141
  if (autoAuth.status === "success") {
120
- await state.manager.close(configuredServer);
142
+ await waitForCaller(() => state.manager.close(configuredServer), signal);
143
+ signal?.throwIfAborted();
144
+ assertMcpStateLease(assertActive);
121
145
  state.failureTracker.delete(configuredServer);
122
- connected = await lazyConnect(state, configuredServer);
146
+ connected = await waitForCaller(() => lazyConnect(state, configuredServer), signal);
147
+ signal?.throwIfAborted();
148
+ assertMcpStateLease(assertActive);
123
149
  }
124
150
  }
125
151
 
@@ -162,7 +188,9 @@ export async function executeCall(
162
188
  if (connection?.status === "needs-auth") {
163
189
  if (!autoAuthAttempted) {
164
190
  autoAuthAttempted = true;
165
- const autoAuth = await attemptAutoAuth(state, serverName);
191
+ const autoAuth = await waitForCaller(() => startAutoAuth(state, serverName!), signal);
192
+ signal?.throwIfAborted();
193
+ assertMcpStateLease(assertActive);
166
194
  if (autoAuth.status === "failed") {
167
195
  return {
168
196
  content: [{ type: "text" as const, text: autoAuth.message }],
@@ -170,7 +198,9 @@ export async function executeCall(
170
198
  };
171
199
  }
172
200
  if (autoAuth.status === "success") {
173
- await state.manager.close(serverName);
201
+ await waitForCaller(() => state.manager.close(serverName!), signal);
202
+ signal?.throwIfAborted();
203
+ assertMcpStateLease(assertActive);
174
204
  state.failureTracker.delete(serverName);
175
205
  connection = state.manager.getConnection(serverName);
176
206
  }
@@ -202,14 +232,19 @@ export async function executeCall(
202
232
  }
203
233
 
204
234
  try {
235
+ assertMcpStateLease(assertActive);
205
236
  if (state.ui) {
206
237
  state.ui.setStatus("mcp", `MCP: connecting to ${serverName}...`);
207
238
  }
208
- connection = await state.manager.connect(serverName, definition);
239
+ connection = await waitForCaller(() => state.manager.connect(serverName, definition), signal);
240
+ signal?.throwIfAborted();
241
+ assertMcpStateLease(assertActive);
209
242
  if (connection.status === "needs-auth") {
210
243
  if (!autoAuthAttempted) {
211
244
  autoAuthAttempted = true;
212
- const autoAuth = await attemptAutoAuth(state, serverName);
245
+ const autoAuth = await waitForCaller(() => startAutoAuth(state, serverName!), signal);
246
+ signal?.throwIfAborted();
247
+ assertMcpStateLease(assertActive);
213
248
  if (autoAuth.status === "failed") {
214
249
  return {
215
250
  content: [{ type: "text" as const, text: autoAuth.message }],
@@ -217,8 +252,12 @@ export async function executeCall(
217
252
  };
218
253
  }
219
254
  if (autoAuth.status === "success") {
220
- await state.manager.close(serverName);
221
- connection = await state.manager.connect(serverName, definition);
255
+ await waitForCaller(() => state.manager.close(serverName!), signal);
256
+ signal?.throwIfAborted();
257
+ assertMcpStateLease(assertActive);
258
+ connection = await waitForCaller(() => state.manager.connect(serverName, definition), signal);
259
+ signal?.throwIfAborted();
260
+ assertMcpStateLease(assertActive);
222
261
  }
223
262
  }
224
263
 
@@ -230,6 +269,7 @@ export async function executeCall(
230
269
  };
231
270
  }
232
271
  }
272
+ assertMcpStateLease(assertActive);
233
273
  state.failureTracker.delete(serverName);
234
274
  updateServerMetadata(state, serverName);
235
275
  updateMetadataCache(state, serverName);
@@ -246,6 +286,8 @@ export async function executeCall(
246
286
  };
247
287
  }
248
288
  } catch (error) {
289
+ signal?.throwIfAborted();
290
+ assertMcpStateLease(assertActive);
249
291
  state.failureTracker.set(serverName, Date.now());
250
292
  updateStatusBar(state);
251
293
  const message = error instanceof Error ? error.message : String(error);
@@ -259,11 +301,15 @@ export async function executeCall(
259
301
  let uiSession: UiSessionRuntime | null = null;
260
302
 
261
303
  try {
304
+ assertMcpStateLease(assertActive);
262
305
  state.manager.touch(serverName);
263
306
  state.manager.incrementInFlight(serverName);
264
307
 
265
308
  if (toolMeta.resourceUri) {
266
- const result = await connection.client.readResource({ uri: toolMeta.resourceUri });
309
+ assertMcpStateLease(assertActive);
310
+ const result = await connection.client.readResource({ uri: toolMeta.resourceUri }, { signal });
311
+ signal?.throwIfAborted();
312
+ assertMcpStateLease(assertActive);
267
313
  const content = (result.contents ?? []).map(c => ({
268
314
  type: "text" as const,
269
315
  text: "text" in c ? c.text : ("blob" in c ? `[Binary data: ${(c as { mimeType?: string }).mimeType ?? "unknown"}]` : JSON.stringify(c)),
@@ -275,15 +321,24 @@ export async function executeCall(
275
321
  }
276
322
 
277
323
  uiSession = toolMeta.uiResourceUri
278
- ? await maybeStartUiSession(state, {
279
- serverName,
280
- toolName: toolMeta.originalName,
281
- toolArgs: args ?? {},
282
- uiResourceUri: toolMeta.uiResourceUri,
283
- streamMode: toolMeta.uiStreamMode,
284
- })
324
+ ? await waitForCallerWithLateCleanup(
325
+ () => maybeStartUiSession(state, {
326
+ serverName,
327
+ toolName: toolMeta.originalName,
328
+ toolArgs: args ?? {},
329
+ uiResourceUri: toolMeta.uiResourceUri!,
330
+ streamMode: toolMeta.uiStreamMode,
331
+ }),
332
+ signal,
333
+ (lateSession) => {
334
+ if (lateSession && !lateSession.reused) lateSession.close("caller cancelled during UI startup");
335
+ },
336
+ )
285
337
  : null;
338
+ signal?.throwIfAborted();
339
+ assertMcpStateLease(assertActive);
286
340
 
341
+ assertMcpStateLease(assertActive);
287
342
  const resultPromise = connection.client.callTool({
288
343
  name: toolMeta.originalName,
289
344
  // Normalize provider-flattened argument keys (e.g. Gemini's `keywords[0]`)
@@ -292,11 +347,14 @@ export async function executeCall(
292
347
  // preserved unless the schema proves the head is a container.
293
348
  arguments: unflattenToolArguments(args, toolMeta.inputSchema),
294
349
  _meta: uiSession?.requestMeta,
295
- });
350
+ }, CallToolResultSchema, { signal });
296
351
 
297
352
  if (toolMeta.uiResourceUri) {
298
- const result = await resultPromise;
299
- uiSession?.sendToolResult(result as unknown as import("@modelcontextprotocol/sdk/types.js").CallToolResult);
353
+ const sdkResult = await resultPromise;
354
+ signal?.throwIfAborted();
355
+ assertMcpStateLease(assertActive);
356
+ const result = asCallToolResult(sdkResult);
357
+ uiSession?.sendToolResult(result);
300
358
  const mcpContent = (result.content ?? []) as McpContent[];
301
359
  const content = transformMcpContent(mcpContent);
302
360
 
@@ -326,7 +384,10 @@ export async function executeCall(
326
384
  };
327
385
  }
328
386
 
329
- const result = await resultPromise;
387
+ const sdkResult = await resultPromise;
388
+ signal?.throwIfAborted();
389
+ assertMcpStateLease(assertActive);
390
+ const result = asCallToolResult(sdkResult);
330
391
 
331
392
  const mcpContent = (result.content ?? []) as McpContent[];
332
393
  const content = transformMcpContent(mcpContent);
@@ -353,8 +414,11 @@ export async function executeCall(
353
414
  details: { mode: "call", mcpResult: result, server: serverName, tool: toolMeta.originalName },
354
415
  };
355
416
  } catch (error) {
417
+ await rethrowHostAbortAfterUiCancellation(signal, uiSession);
356
418
  const message = error instanceof Error ? error.message : String(error);
357
- uiSession?.sendToolCancelled(message);
419
+ await notifyUiCancellation(uiSession, message);
420
+ signal?.throwIfAborted();
421
+ assertMcpStateLease(assertActive);
358
422
 
359
423
  let errorWithSchema = `Failed to call tool: ${message}`;
360
424
  if (toolMeta.inputSchema) {
@@ -366,10 +430,17 @@ export async function executeCall(
366
430
  details: { mode: "call", error: "call_failed", message },
367
431
  };
368
432
  } finally {
369
- if (uiSession?.reused) {
370
- uiSession.close();
433
+ let staleState = false;
434
+ try {
435
+ assertMcpStateLease(assertActive);
436
+ } catch (error) {
437
+ if (error instanceof McpStateChangedError) staleState = true;
438
+ else throw error;
439
+ }
440
+ if (uiSession && (uiSession.reused || staleState)) {
441
+ uiSession.close(staleState ? "stale MCP session" : undefined);
371
442
  }
372
443
  state.manager.decrementInFlight(serverName);
373
- state.manager.touch(serverName);
444
+ if (!staleState) state.manager.touch(serverName);
374
445
  }
375
446
  }
@@ -1,11 +1,21 @@
1
- import type { McpExtensionState } from "./state.ts";
2
- import { updateMetadataCache, updateStatusBar } from "./init.ts";
3
- import { buildToolMetadata } from "./tool-metadata.ts";
4
- import { attemptAutoAuth, getAuthRequiredMessage } from "./proxy-auth.ts";
5
- import { executeList } from "./proxy-info-modes.ts";
6
- import type { ProxyToolResult } from "./proxy-types.ts";
1
+ import type { McpExtensionState } from "./state.js";
2
+ import { updateMetadataCache, updateStatusBar } from "./init.js";
3
+ import { buildToolMetadata } from "./tool-metadata.js";
4
+ import { attemptAutoAuth, getAuthRequiredMessage, type AutoAuthResult } from "./proxy-auth.js";
5
+ import { executeList } from "./proxy-info-modes.js";
6
+ import type { ProxyToolResult } from "./proxy-types.js";
7
+ import { waitForCaller } from "./caller-wait.js";
8
+ import { assertMcpStateLease, type AssertMcpStateLease } from "./state-lease.js";
7
9
 
8
- export async function executeConnect(state: McpExtensionState, serverName: string): Promise<ProxyToolResult> {
10
+ export async function executeConnect(
11
+ state: McpExtensionState,
12
+ serverName: string,
13
+ signal?: AbortSignal,
14
+ startAutoAuth: (state: McpExtensionState, serverName: string) => Promise<AutoAuthResult> = attemptAutoAuth,
15
+ assertActive?: AssertMcpStateLease,
16
+ ): Promise<ProxyToolResult> {
17
+ signal?.throwIfAborted();
18
+ assertMcpStateLease(assertActive);
9
19
  const definition = state.config.mcpServers[serverName];
10
20
  if (!definition) {
11
21
  return {
@@ -15,12 +25,15 @@ export async function executeConnect(state: McpExtensionState, serverName: strin
15
25
  }
16
26
 
17
27
  try {
18
- if (state.ui) {
19
- state.ui.setStatus("mcp", `MCP: connecting to ${serverName}...`);
20
- }
21
- let connection = await state.manager.connect(serverName, definition);
28
+ assertMcpStateLease(assertActive);
29
+ if (state.ui) state.ui.setStatus("mcp", `MCP: connecting to ${serverName}...`);
30
+ let connection = await waitForCaller(() => state.manager.connect(serverName, definition), signal);
31
+ signal?.throwIfAborted();
32
+ assertMcpStateLease(assertActive);
22
33
  if (connection.status === "needs-auth") {
23
- const autoAuth = await attemptAutoAuth(state, serverName);
34
+ const autoAuth = await waitForCaller(() => startAutoAuth(state, serverName), signal);
35
+ signal?.throwIfAborted();
36
+ assertMcpStateLease(assertActive);
24
37
  if (autoAuth.status === "failed") {
25
38
  return {
26
39
  content: [{ type: "text" as const, text: autoAuth.message }],
@@ -28,8 +41,12 @@ export async function executeConnect(state: McpExtensionState, serverName: strin
28
41
  };
29
42
  }
30
43
  if (autoAuth.status === "success") {
31
- await state.manager.close(serverName);
32
- connection = await state.manager.connect(serverName, definition);
44
+ await waitForCaller(() => state.manager.close(serverName), signal);
45
+ signal?.throwIfAborted();
46
+ assertMcpStateLease(assertActive);
47
+ connection = await waitForCaller(() => state.manager.connect(serverName, definition), signal);
48
+ signal?.throwIfAborted();
49
+ assertMcpStateLease(assertActive);
33
50
  }
34
51
  if (connection.status === "needs-auth") {
35
52
  const message = getAuthRequiredMessage(state, serverName);
@@ -39,14 +56,17 @@ export async function executeConnect(state: McpExtensionState, serverName: strin
39
56
  };
40
57
  }
41
58
  }
59
+ assertMcpStateLease(assertActive);
42
60
  const prefix = state.config.settings?.toolPrefix ?? "server";
43
61
  const { metadata } = buildToolMetadata(connection.tools, connection.resources, definition, serverName, prefix);
44
62
  state.toolMetadata.set(serverName, metadata);
45
63
  updateMetadataCache(state, serverName);
46
64
  state.failureTracker.delete(serverName);
47
65
  updateStatusBar(state);
48
- return executeList(state, serverName);
66
+ return executeList(state, serverName, signal, assertActive);
49
67
  } catch (error) {
68
+ signal?.throwIfAborted();
69
+ assertMcpStateLease(assertActive);
50
70
  state.failureTracker.set(serverName, Date.now());
51
71
  updateStatusBar(state);
52
72
  const message = error instanceof Error ? error.message : String(error);
@@ -1,13 +1,15 @@
1
- import type { McpExtensionState } from "./state.ts";
2
- import type { ToolMetadata } from "./types.ts";
3
- import { getServerPrefix, parseUiPromptHandoff } from "./types.ts";
4
- import { getFailureAgeSeconds } from "./init.ts";
5
- import { findToolByName, formatSchema } from "./tool-metadata.ts";
6
- import { truncateAtWord } from "./utils.ts";
7
- import { hydrateMissingMetadata } from "./metadata-hydration.ts";
8
- import type { ProxyToolResult } from "./proxy-types.ts";
9
-
10
- export function executeUiMessages(state: McpExtensionState): ProxyToolResult {
1
+ import type { McpExtensionState } from "./state.js";
2
+ import type { ToolMetadata } from "./types.js";
3
+ import { getServerPrefix, parseUiPromptHandoff } from "./types.js";
4
+ import { getFailureAgeSeconds } from "./init.js";
5
+ import { findToolByName, formatSchema } from "./tool-metadata.js";
6
+ import { truncateAtWord } from "./utils.js";
7
+ import { hydrateMissingMetadata } from "./metadata-hydration.js";
8
+ import type { ProxyToolResult } from "./proxy-types.js";
9
+ import { assertMcpStateLease, type AssertMcpStateLease } from "./state-lease.js";
10
+
11
+ export function executeUiMessages(state: McpExtensionState, assertActive?: AssertMcpStateLease): ProxyToolResult {
12
+ assertMcpStateLease(assertActive);
11
13
  const sessions = state.completedUiSessions;
12
14
 
13
15
  if (sessions.length === 0) {
@@ -71,6 +73,7 @@ export function executeUiMessages(state: McpExtensionState): ProxyToolResult {
71
73
  }
72
74
 
73
75
  const count = sessions.length;
76
+ assertMcpStateLease(assertActive);
74
77
  state.completedUiSessions = [];
75
78
 
76
79
  return {
@@ -85,7 +88,8 @@ export function executeUiMessages(state: McpExtensionState): ProxyToolResult {
85
88
  };
86
89
  }
87
90
 
88
- export function executeStatus(state: McpExtensionState): ProxyToolResult {
91
+ export function executeStatus(state: McpExtensionState, assertActive?: AssertMcpStateLease): ProxyToolResult {
92
+ assertMcpStateLease(assertActive);
89
93
  const servers: Array<{ name: string; status: string; toolCount: number; failedAgo: number | null }> = [];
90
94
 
91
95
  for (const name of Object.keys(state.config.mcpServers)) {
@@ -169,33 +173,46 @@ function prefixHydrationCandidates(state: McpExtensionState, toolName: string):
169
173
  .map(({ serverName }) => serverName);
170
174
  }
171
175
 
172
- async function hydrateDescribeMetadata(state: McpExtensionState, toolName: string, server?: string): Promise<void> {
176
+ async function hydrateDescribeMetadata(
177
+ state: McpExtensionState,
178
+ toolName: string,
179
+ server?: string,
180
+ signal?: AbortSignal,
181
+ assertActive?: AssertMcpStateLease,
182
+ ): Promise<void> {
183
+ signal?.throwIfAborted();
184
+ assertMcpStateLease(assertActive);
173
185
  if (server) {
174
- await hydrateMissingMetadata(state, { server });
186
+ await hydrateMissingMetadata(state, { server }, signal, assertActive);
175
187
  return;
176
188
  }
177
189
 
178
190
  const candidates = prefixHydrationCandidates(state, toolName);
179
191
  if (candidates.length > 0) {
180
192
  for (const candidate of candidates) {
181
- await hydrateMissingMetadata(state, { server: candidate });
193
+ await hydrateMissingMetadata(state, { server: candidate }, signal, assertActive);
182
194
  if (findToolMetadata(state, toolName, candidate)) return;
183
195
  }
184
196
  return;
185
197
  }
186
198
 
187
199
  if (findToolMetadata(state, toolName)) return;
188
- await hydrateMissingMetadata(state);
200
+ await hydrateMissingMetadata(state, undefined, signal, assertActive);
189
201
  }
190
202
 
191
203
  export async function executeDescribe(
192
204
  state: McpExtensionState,
193
205
  toolName: string,
194
206
  server?: string,
207
+ signal?: AbortSignal,
208
+ assertActive?: AssertMcpStateLease,
195
209
  ): Promise<ProxyToolResult> {
210
+ signal?.throwIfAborted();
211
+ assertMcpStateLease(assertActive);
196
212
  let found = findToolMetadata(state, toolName, server);
197
213
  if (!found) {
198
- await hydrateDescribeMetadata(state, toolName, server);
214
+ await hydrateDescribeMetadata(state, toolName, server, signal, assertActive);
215
+ assertMcpStateLease(assertActive);
199
216
  found = findToolMetadata(state, toolName, server);
200
217
  }
201
218
 
@@ -235,7 +252,11 @@ export async function executeSearch(
235
252
  regex?: boolean,
236
253
  server?: string,
237
254
  includeSchemas?: boolean,
255
+ signal?: AbortSignal,
256
+ assertActive?: AssertMcpStateLease,
238
257
  ): Promise<ProxyToolResult> {
258
+ signal?.throwIfAborted();
259
+ assertMcpStateLease(assertActive);
239
260
  const showSchemas = includeSchemas !== false;
240
261
 
241
262
  const matches: Array<{ server: string; tool: ToolMetadata }> = [];
@@ -261,7 +282,8 @@ export async function executeSearch(
261
282
  details: { mode: "search", error: "invalid_pattern", query },
262
283
  };
263
284
  }
264
- await hydrateMissingMetadata(state, { server });
285
+ await hydrateMissingMetadata(state, { server }, signal, assertActive);
286
+ assertMcpStateLease(assertActive);
265
287
 
266
288
  for (const [serverName, metadata] of state.toolMetadata.entries()) {
267
289
  if (server && serverName !== server) continue;
@@ -319,7 +341,14 @@ export async function executeSearch(
319
341
  };
320
342
  }
321
343
 
322
- export async function executeList(state: McpExtensionState, server: string): Promise<ProxyToolResult> {
344
+ export async function executeList(
345
+ state: McpExtensionState,
346
+ server: string,
347
+ signal?: AbortSignal,
348
+ assertActive?: AssertMcpStateLease,
349
+ ): Promise<ProxyToolResult> {
350
+ signal?.throwIfAborted();
351
+ assertMcpStateLease(assertActive);
323
352
  if (!state.config.mcpServers[server]) {
324
353
  return {
325
354
  content: [{ type: "text" as const, text: `Server "${server}" not found. Use mcp({}) to see available servers.` }],
@@ -328,7 +357,8 @@ export async function executeList(state: McpExtensionState, server: string): Pro
328
357
  }
329
358
 
330
359
  if (!state.toolMetadata.has(server)) {
331
- await hydrateMissingMetadata(state, { server });
360
+ await hydrateMissingMetadata(state, { server }, signal, assertActive);
361
+ assertMcpStateLease(assertActive);
332
362
  }
333
363
 
334
364
  const metadata = state.toolMetadata.get(server);
@@ -1,3 +1,3 @@
1
- export { executeUiMessages, executeStatus, executeDescribe, executeSearch, executeList } from "./proxy-info-modes.ts";
2
- export { executeConnect } from "./proxy-connect.ts";
3
- export { executeCall } from "./proxy-call.ts";
1
+ export { executeUiMessages, executeStatus, executeDescribe, executeSearch, executeList } from "./proxy-info-modes.js";
2
+ export { executeConnect } from "./proxy-connect.js";
3
+ export { executeCall } from "./proxy-call.js";
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Retain teardown work across MCP lifecycle generations without allowing a
3
+ * non-abortable producer to block every later generation forever.
4
+ */
5
+ type CleanupTask = PromiseLike<object | string | void>;
6
+
7
+ const DEFAULT_CLEANUP_DEADLINE_MS = 2_000;
8
+
9
+ function observeWithin(task: CleanupTask, deadlineMs: number, onTimeout: () => void): Promise<void> {
10
+ const observed = Promise.resolve(task).then(() => undefined, () => undefined);
11
+ let timer: ReturnType<typeof setTimeout> | undefined;
12
+ const deadline = new Promise<void>((resolve) => {
13
+ timer = setTimeout(() => {
14
+ onTimeout();
15
+ resolve();
16
+ }, deadlineMs);
17
+ timer.unref?.();
18
+ });
19
+ return Promise.race([observed, deadline]).finally(() => {
20
+ if (timer) clearTimeout(timer);
21
+ });
22
+ }
23
+
24
+ export class McpSessionCleanupBarrier {
25
+ private settled: Promise<void> = Promise.resolve();
26
+
27
+ constructor(private readonly deadlineMs = DEFAULT_CLEANUP_DEADLINE_MS) {}
28
+
29
+ wait(): Promise<void> {
30
+ return this.settled;
31
+ }
32
+
33
+ retain(tasks: readonly (CleanupTask | null | undefined)[]): Promise<void> {
34
+ const observed = tasks.filter((task): task is CleanupTask => task !== null && task !== undefined);
35
+ const prior = this.settled;
36
+ const next = Promise.all([
37
+ observeWithin(prior, this.deadlineMs, () => console.error("MCP: prior cleanup exceeded its deadline; continuing with fenced state")),
38
+ ...observed.map((task) => observeWithin(task, this.deadlineMs, () => console.error("MCP: cleanup task exceeded its deadline; continuing with fenced state"))),
39
+ ]).then(() => undefined);
40
+ this.settled = next;
41
+ return next;
42
+ }
43
+ }
@@ -0,0 +1,12 @@
1
+ export type AssertMcpStateLease = () => void;
2
+
3
+ export class McpStateChangedError extends Error {
4
+ constructor() {
5
+ super("MCP session changed during execution");
6
+ this.name = "McpStateChangedError";
7
+ }
8
+ }
9
+
10
+ export function assertMcpStateLease(assertActive?: AssertMcpStateLease): void {
11
+ assertActive?.();
12
+ }
@@ -7,12 +7,12 @@ import type {
7
7
  CallToolRequest,
8
8
  CallToolResult,
9
9
  } from "@modelcontextprotocol/sdk/types.js";
10
- import type { ConsentManager } from "./consent-manager.ts";
11
- import { ServerError, wrapError } from "./errors.ts";
12
- import { buildHostHtmlTemplate, buildCspMetaContent, applyCspMeta } from "./host-html-template.ts";
13
- import { logger } from "./logger.ts";
14
- import { parseBody, sendJson, validateTokenBody, validateTokenQuery } from "./ui-server-http.ts";
15
- import type { McpServerManager } from "./server-manager.ts";
10
+ import type { ConsentManager } from "./consent-manager.js";
11
+ import { ServerError, wrapError } from "./errors.js";
12
+ import { buildHostHtmlTemplate, buildCspMetaContent, applyCspMeta } from "./host-html-template.js";
13
+ import { logger } from "./logger.js";
14
+ import { parseBody, sendJson, validateTokenBody, validateTokenQuery } from "./ui-server-http.js";
15
+ import type { McpServerManager } from "./server-manager.js";
16
16
  import {
17
17
  extractUiPromptText,
18
18
  getVisualizationStreamEnvelope,
@@ -26,7 +26,7 @@ import {
26
26
  type UiResourceContent,
27
27
  type UiSessionMessages,
28
28
  type UiStreamSummary,
29
- } from "./types.ts";
29
+ } from "./types.js";
30
30
 
31
31
  const ABANDONED_GRACE_MS = 60_000;
32
32
  const WATCHDOG_INTERVAL_MS = 5_000;
@@ -58,7 +58,7 @@ export interface UiServerHandle {
58
58
  sendToolInput: (args: Record<string, unknown>) => void;
59
59
  sendToolResult: (result: CallToolResult) => void;
60
60
  sendResultPatch: (result: CallToolResult) => void;
61
- sendToolCancelled: (reason: string) => void;
61
+ sendToolCancelled: (reason: string) => void | Promise<void>;
62
62
  sendHostContext: (context: UiHostContext) => void;
63
63
  /** Get accumulated messages from this session */
64
64
  getSessionMessages: () => UiSessionMessages;