@gajae-code/coding-agent 0.17.2 → 0.17.4

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 (349) hide show
  1. package/CHANGELOG.md +194 -0
  2. package/dist/types/cli/daemon-cli.d.ts +3 -1
  3. package/dist/types/cli/github-release.d.ts +17 -0
  4. package/dist/types/cli/public-command-entry.d.ts +56 -0
  5. package/dist/types/cli/public-command-errors.d.ts +126 -0
  6. package/dist/types/cli/public-command-evidence.d.ts +99 -0
  7. package/dist/types/cli/public-command-help.d.ts +65 -0
  8. package/dist/types/cli/public-command-registry.d.ts +69 -0
  9. package/dist/types/cli/session-picker.d.ts +1 -1
  10. package/dist/types/cli/setup-cli.d.ts +1 -0
  11. package/dist/types/cli/skills-cli.d.ts +5 -0
  12. package/dist/types/cli.d.ts +3 -0
  13. package/dist/types/commands/daemon.d.ts +4 -50
  14. package/dist/types/commands/sdk.d.ts +20 -37
  15. package/dist/types/commands/setup.d.ts +3 -0
  16. package/dist/types/commands/skills.d.ts +9 -0
  17. package/dist/types/config/autorouting-tier-map.d.ts +18 -0
  18. package/dist/types/config/file-lock.d.ts +9 -1
  19. package/dist/types/config/model-profile-activation.d.ts +45 -1
  20. package/dist/types/config/model-registry.d.ts +11 -2
  21. package/dist/types/config/settings-schema.d.ts +11 -0
  22. package/dist/types/coordinator-mcp/question-state.d.ts +6 -1
  23. package/dist/types/daemon/operator-contract.d.ts +5 -1
  24. package/dist/types/eval/js/worker-protocol.d.ts +2 -0
  25. package/dist/types/extensibility/extensions/types.d.ts +12 -0
  26. package/dist/types/extensibility/gjc-plugins/registry.d.ts +4 -0
  27. package/dist/types/extensibility/runtime-skill-discovery.d.ts +18 -0
  28. package/dist/types/extensibility/shared-events.d.ts +3 -1
  29. package/dist/types/gjc-runtime/session-state-lock.d.ts +61 -0
  30. package/dist/types/internal-urls/embedded-protocol.d.ts +9 -0
  31. package/dist/types/internal-urls/index.d.ts +1 -0
  32. package/dist/types/internal-urls/parse.d.ts +9 -1
  33. package/dist/types/main.d.ts +22 -0
  34. package/dist/types/modes/acp/acp-agent.d.ts +55 -1
  35. package/dist/types/modes/acp/startup-provenance.d.ts +16 -0
  36. package/dist/types/modes/components/custom-provider-wizard.d.ts +19 -1
  37. package/dist/types/modes/components/session-selector.d.ts +5 -2
  38. package/dist/types/modes/components/user-message-selector.d.ts +5 -2
  39. package/dist/types/modes/controllers/command-controller.d.ts +1 -1
  40. package/dist/types/modes/controllers/selector-controller.d.ts +1 -1
  41. package/dist/types/modes/interactive-mode.d.ts +1 -1
  42. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +11 -1
  43. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +14 -1
  44. package/dist/types/modes/types.d.ts +2 -2
  45. package/dist/types/runtime/process-lifecycle.d.ts +2 -0
  46. package/dist/types/runtime-mcp/manager.d.ts +56 -0
  47. package/dist/types/runtime-mcp/pool.d.ts +17 -0
  48. package/dist/types/runtime-mcp/redaction.d.ts +20 -0
  49. package/dist/types/runtime-mcp/startup-policy.d.ts +6 -0
  50. package/dist/types/runtime-mcp/tool-bridge.d.ts +9 -0
  51. package/dist/types/runtime-mcp/transports/http.d.ts +11 -0
  52. package/dist/types/sdk/broker/broker.d.ts +13 -2
  53. package/dist/types/sdk/broker/identity.d.ts +3 -1
  54. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +23 -3
  55. package/dist/types/sdk/broker/lifecycle.d.ts +15 -8
  56. package/dist/types/sdk/broker/runtime.d.ts +1 -1
  57. package/dist/types/sdk/broker/session-index.d.ts +22 -3
  58. package/dist/types/sdk/broker/spawn-authority.d.ts +4 -0
  59. package/dist/types/sdk/broker/stderr-drainer.d.ts +13 -0
  60. package/dist/types/sdk/bus/index.d.ts +19 -0
  61. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +3 -1
  62. package/dist/types/sdk/bus/telegram-daemon.d.ts +5 -0
  63. package/dist/types/sdk/cli/master-cli.d.ts +6 -10
  64. package/dist/types/sdk/cli/rows.d.ts +19 -1
  65. package/dist/types/sdk/cli/session-cli.d.ts +22 -5
  66. package/dist/types/sdk/client/client.d.ts +2 -0
  67. package/dist/types/sdk/guides/cli.d.ts +3 -4
  68. package/dist/types/sdk/guides/verify.d.ts +2 -0
  69. package/dist/types/sdk/host/host.d.ts +9 -0
  70. package/dist/types/sdk/host/session-runtime.d.ts +31 -0
  71. package/dist/types/sdk/host/types.d.ts +10 -0
  72. package/dist/types/sdk/index.d.ts +1 -0
  73. package/dist/types/sdk/prompt-deadline-flush.d.ts +83 -0
  74. package/dist/types/sdk/prompt-deadline-manager.d.ts +37 -0
  75. package/dist/types/sdk/prompt-tool-boundary.d.ts +73 -0
  76. package/dist/types/sdk/router/session-router.d.ts +2 -0
  77. package/dist/types/sdk/startup-capability.d.ts +2 -0
  78. package/dist/types/sdk/transport/relay.d.ts +1 -0
  79. package/dist/types/sdk/transport/serve-cli.d.ts +48 -4
  80. package/dist/types/sdk/transport/stdio.d.ts +5 -1
  81. package/dist/types/session/agent-session.d.ts +168 -21
  82. package/dist/types/session/fallback-chain-controller.d.ts +6 -6
  83. package/dist/types/session/fold-coordinator.d.ts +17 -3
  84. package/dist/types/session/internal/managed-session-storage.d.ts +7 -1
  85. package/dist/types/session/session-manager.d.ts +64 -1
  86. package/dist/types/session/session-work-lease.d.ts +14 -0
  87. package/dist/types/setup/model-onboarding-guidance.d.ts +1 -1
  88. package/dist/types/setup/provider-onboarding.d.ts +81 -1
  89. package/dist/types/tools/bash.d.ts +37 -11
  90. package/dist/types/tools/job.d.ts +1 -1
  91. package/dist/types/tools/steer-fold.d.ts +31 -0
  92. package/dist/types/utils/git.d.ts +28 -2
  93. package/dist/types/utils/mupdf-embedded.d.ts +2 -0
  94. package/dist/types/utils/mupdf.d.ts +4 -0
  95. package/dist/types/utils/session-title-generation.d.ts +6 -0
  96. package/dist/types/utils/title-generator.d.ts +11 -2
  97. package/dist/types/web/scrapers/types.d.ts +3 -0
  98. package/package.json +18 -10
  99. package/scripts/build-binary.ts +9 -3
  100. package/scripts/compile-args.ts +0 -9
  101. package/scripts/embed-mupdf.ts +52 -0
  102. package/scripts/generate-sdk-operation-inventory.ts +31 -1
  103. package/scripts/vendor-markit.ts +196 -0
  104. package/src/async/job-manager.ts +22 -1
  105. package/src/cli/daemon-cli.ts +53 -18
  106. package/src/cli/github-release.ts +87 -5
  107. package/src/cli/mcp-cli.ts +38 -4
  108. package/src/cli/public-command-entry.ts +450 -0
  109. package/src/cli/public-command-errors.ts +581 -0
  110. package/src/cli/public-command-evidence.ts +717 -0
  111. package/src/cli/public-command-help.ts +360 -0
  112. package/src/cli/public-command-registry.ts +535 -0
  113. package/src/cli/session-picker.ts +2 -1
  114. package/src/cli/setup-cli.ts +9 -1
  115. package/src/cli/skills-cli.ts +46 -2
  116. package/src/cli.ts +61 -1
  117. package/src/commands/daemon.ts +65 -69
  118. package/src/commands/sdk.ts +175 -117
  119. package/src/commands/setup.ts +2 -0
  120. package/src/commands/skills.ts +11 -0
  121. package/src/config/autorouting-tier-map.ts +14 -0
  122. package/src/config/file-lock.ts +147 -51
  123. package/src/config/model-profile-activation.ts +334 -43
  124. package/src/config/model-registry.ts +183 -25
  125. package/src/config/settings-schema.ts +26 -2
  126. package/src/coordinator-mcp/policy.ts +10 -5
  127. package/src/coordinator-mcp/question-gate-codec.ts +17 -0
  128. package/src/coordinator-mcp/question-state.ts +175 -8
  129. package/src/coordinator-mcp/server.ts +507 -81
  130. package/src/coordinator-mcp/session-reaper.ts +6 -4
  131. package/src/crash/record-loader.ts +6 -2
  132. package/src/daemon/operator-contract.ts +26 -12
  133. package/src/defaults/gjc/skills/ultragoal/SKILL.md +1 -1
  134. package/src/eval/js/context-manager.ts +8 -8
  135. package/src/eval/js/worker-core.ts +9 -4
  136. package/src/eval/js/worker-protocol.ts +2 -0
  137. package/src/extensibility/extensions/runner.ts +52 -4
  138. package/src/extensibility/extensions/types.ts +10 -0
  139. package/src/extensibility/gjc-plugins/registry.ts +196 -37
  140. package/src/extensibility/runtime-skill-discovery.ts +61 -3
  141. package/src/extensibility/shared-events.ts +3 -1
  142. package/src/gjc-runtime/session-state-lock.ts +165 -24
  143. package/src/gjc-runtime/ultragoal-succession.ts +31 -3
  144. package/src/internal-urls/docs-index.generated.ts +20 -19
  145. package/src/internal-urls/embedded-protocol.ts +83 -0
  146. package/src/internal-urls/index.ts +1 -0
  147. package/src/internal-urls/parse.ts +21 -1
  148. package/src/internal-urls/router.ts +4 -2
  149. package/src/main.ts +123 -55
  150. package/src/modes/acp/acp-agent.ts +408 -35
  151. package/src/modes/acp/startup-provenance.ts +59 -0
  152. package/src/modes/components/custom-provider-wizard.ts +308 -7
  153. package/src/modes/components/oauth-selector.ts +9 -0
  154. package/src/modes/components/session-selector.ts +47 -4
  155. package/src/modes/components/user-message-selector.ts +57 -15
  156. package/src/modes/controllers/command-controller.ts +58 -32
  157. package/src/modes/controllers/extension-ui-controller.ts +33 -7
  158. package/src/modes/controllers/input-controller.ts +4 -0
  159. package/src/modes/controllers/selector-controller.ts +161 -15
  160. package/src/modes/interactive-mode.ts +21 -7
  161. package/src/modes/runtime-init.ts +1 -0
  162. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +124 -7
  163. package/src/modes/shared/agent-wire/workflow-gate-types.ts +16 -2
  164. package/src/modes/types.ts +2 -2
  165. package/src/prompts/agent-fragments/browser-aside.md +1 -0
  166. package/src/prompts/system/title-system.md +1 -1
  167. package/src/prompts/tools/bash.md +1 -1
  168. package/src/prompts/tools/job.md +1 -1
  169. package/src/prompts/tools/read.md +2 -0
  170. package/src/runtime/network-prewarm-service.test.ts +36 -1
  171. package/src/runtime/network-prewarm-service.ts +28 -3
  172. package/src/runtime/process-lifecycle.ts +22 -11
  173. package/src/runtime-mcp/config.ts +16 -1
  174. package/src/runtime-mcp/manager.ts +689 -55
  175. package/src/runtime-mcp/pool.test.ts +31 -0
  176. package/src/runtime-mcp/pool.ts +304 -28
  177. package/src/runtime-mcp/redaction.ts +42 -0
  178. package/src/runtime-mcp/startup-policy.ts +7 -0
  179. package/src/runtime-mcp/tool-bridge.ts +71 -0
  180. package/src/runtime-mcp/transports/http.ts +108 -25
  181. package/src/sdk/acp/adapter.ts +27 -8
  182. package/src/sdk/broker/broker.ts +378 -52
  183. package/src/sdk/broker/identity.ts +9 -1
  184. package/src/sdk/broker/lifecycle-ledger.ts +95 -31
  185. package/src/sdk/broker/lifecycle.ts +690 -141
  186. package/src/sdk/broker/runtime.ts +1 -1
  187. package/src/sdk/broker/session-index.ts +97 -4
  188. package/src/sdk/broker/spawn-authority.ts +35 -7
  189. package/src/sdk/broker/stderr-drainer.ts +59 -0
  190. package/src/sdk/bus/chat-daemon-control.ts +2 -2
  191. package/src/sdk/bus/chat-daemon-runtime.ts +1 -0
  192. package/src/sdk/bus/index.ts +690 -80
  193. package/src/sdk/bus/telegram-daemon-cli.ts +31 -2
  194. package/src/sdk/bus/telegram-daemon-contract.ts +3 -1
  195. package/src/sdk/bus/telegram-daemon.ts +10 -3
  196. package/src/sdk/cli/master-cli.ts +47 -36
  197. package/src/sdk/cli/rows.ts +30 -7
  198. package/src/sdk/cli/session-cli.ts +687 -184
  199. package/src/sdk/client/client.ts +18 -0
  200. package/src/sdk/guides/catalog.ts +2 -2
  201. package/src/sdk/guides/cli.ts +20 -62
  202. package/src/sdk/guides/verify.ts +14 -0
  203. package/src/sdk/host/host.ts +49 -5
  204. package/src/sdk/host/session-runtime.test.ts +138 -2
  205. package/src/sdk/host/session-runtime.ts +311 -97
  206. package/src/sdk/host/types.ts +12 -1
  207. package/src/sdk/host/websocket-transport.lifecycle.test.ts +84 -0
  208. package/src/sdk/host/websocket-transport.ts +40 -6
  209. package/src/sdk/index.ts +11 -0
  210. package/src/sdk/prompt-deadline-flush.ts +334 -0
  211. package/src/sdk/prompt-deadline-manager.ts +133 -1
  212. package/src/sdk/prompt-tool-boundary.ts +121 -0
  213. package/src/sdk/protocol/operation-inventory.generated.json +106 -0
  214. package/src/sdk/router/session-router.ts +9 -1
  215. package/src/sdk/session.ts +182 -7
  216. package/src/sdk/startup-capability.ts +1 -1
  217. package/src/sdk/transport/relay.ts +71 -6
  218. package/src/sdk/transport/serve-cli.ts +397 -42
  219. package/src/sdk/transport/socket.ts +12 -11
  220. package/src/sdk/transport/stdio.ts +7 -3
  221. package/src/session/agent-session.ts +2437 -400
  222. package/src/session/fallback-chain-controller.ts +6 -7
  223. package/src/session/fold-coordinator.ts +24 -5
  224. package/src/session/internal/managed-session-scope.ts +58 -18
  225. package/src/session/internal/managed-session-storage.ts +304 -11
  226. package/src/session/session-manager.ts +382 -44
  227. package/src/session/session-work-lease.ts +34 -0
  228. package/src/setup/model-onboarding-guidance.ts +1 -1
  229. package/src/setup/provider-onboarding.ts +397 -24
  230. package/src/slash-commands/builtin-registry.ts +258 -14
  231. package/src/task/index.ts +14 -2
  232. package/src/tools/bash.ts +98 -78
  233. package/src/tools/fetch.ts +119 -20
  234. package/src/tools/job.ts +151 -25
  235. package/src/tools/output-meta.ts +15 -2
  236. package/src/tools/path-utils.ts +27 -3
  237. package/src/tools/read.ts +3 -3
  238. package/src/tools/steer-fold.ts +107 -0
  239. package/src/tools/tool-catalog.generated.ts +29 -2
  240. package/src/tools/tool-errors.ts +4 -0
  241. package/src/utils/git.ts +53 -3
  242. package/src/utils/markit.ts +55 -41
  243. package/src/utils/mupdf-assets.d.ts +4 -0
  244. package/src/utils/mupdf-embedded.ts +4 -0
  245. package/src/utils/mupdf.ts +129 -0
  246. package/src/utils/session-title-generation.ts +29 -0
  247. package/src/utils/title-generator.ts +46 -2
  248. package/src/web/scrapers/types.ts +24 -3
  249. package/vendor/markit-ai/LICENSE +21 -0
  250. package/vendor/markit-ai/MANIFEST.json +412 -0
  251. package/vendor/markit-ai/dist/commands/config.d.ts +4 -0
  252. package/vendor/markit-ai/dist/commands/config.js +139 -0
  253. package/vendor/markit-ai/dist/commands/convert.d.ts +6 -0
  254. package/vendor/markit-ai/dist/commands/convert.js +113 -0
  255. package/vendor/markit-ai/dist/commands/formats.d.ts +2 -0
  256. package/vendor/markit-ai/dist/commands/formats.js +92 -0
  257. package/vendor/markit-ai/dist/commands/init.d.ts +2 -0
  258. package/vendor/markit-ai/dist/commands/init.js +29 -0
  259. package/vendor/markit-ai/dist/commands/onboard.d.ts +2 -0
  260. package/vendor/markit-ai/dist/commands/onboard.js +61 -0
  261. package/vendor/markit-ai/dist/commands/plugin.d.ts +4 -0
  262. package/vendor/markit-ai/dist/commands/plugin.js +58 -0
  263. package/vendor/markit-ai/dist/config.d.ts +26 -0
  264. package/vendor/markit-ai/dist/config.js +42 -0
  265. package/vendor/markit-ai/dist/converters/audio.d.ts +7 -0
  266. package/vendor/markit-ai/dist/converters/audio.js +104 -0
  267. package/vendor/markit-ai/dist/converters/csv.d.ts +7 -0
  268. package/vendor/markit-ai/dist/converters/csv.js +83 -0
  269. package/vendor/markit-ai/dist/converters/docx.d.ts +6 -0
  270. package/vendor/markit-ai/dist/converters/docx.js +57 -0
  271. package/vendor/markit-ai/dist/converters/epub.d.ts +8 -0
  272. package/vendor/markit-ai/dist/converters/epub.js +128 -0
  273. package/vendor/markit-ai/dist/converters/github.d.ts +18 -0
  274. package/vendor/markit-ai/dist/converters/github.js +148 -0
  275. package/vendor/markit-ai/dist/converters/html.d.ts +6 -0
  276. package/vendor/markit-ai/dist/converters/html.js +30 -0
  277. package/vendor/markit-ai/dist/converters/image.d.ts +6 -0
  278. package/vendor/markit-ai/dist/converters/image.js +124 -0
  279. package/vendor/markit-ai/dist/converters/ipynb.d.ts +6 -0
  280. package/vendor/markit-ai/dist/converters/ipynb.js +75 -0
  281. package/vendor/markit-ai/dist/converters/iwork.d.ts +20 -0
  282. package/vendor/markit-ai/dist/converters/iwork.js +391 -0
  283. package/vendor/markit-ai/dist/converters/json.d.ts +6 -0
  284. package/vendor/markit-ai/dist/converters/json.js +21 -0
  285. package/vendor/markit-ai/dist/converters/pdf/columns.d.ts +35 -0
  286. package/vendor/markit-ai/dist/converters/pdf/columns.js +93 -0
  287. package/vendor/markit-ai/dist/converters/pdf/extract.d.ts +19 -0
  288. package/vendor/markit-ai/dist/converters/pdf/extract.js +514 -0
  289. package/vendor/markit-ai/dist/converters/pdf/grid.d.ts +25 -0
  290. package/vendor/markit-ai/dist/converters/pdf/grid.js +795 -0
  291. package/vendor/markit-ai/dist/converters/pdf/headers.d.ts +24 -0
  292. package/vendor/markit-ai/dist/converters/pdf/headers.js +108 -0
  293. package/vendor/markit-ai/dist/converters/pdf/index.d.ts +19 -0
  294. package/vendor/markit-ai/dist/converters/pdf/index.js +136 -0
  295. package/vendor/markit-ai/dist/converters/pdf/mupdf-loader.js +9 -0
  296. package/vendor/markit-ai/dist/converters/pdf/render.d.ts +24 -0
  297. package/vendor/markit-ai/dist/converters/pdf/render.js +513 -0
  298. package/vendor/markit-ai/dist/converters/pdf/types.d.ts +75 -0
  299. package/vendor/markit-ai/dist/converters/pdf/types.js +1 -0
  300. package/vendor/markit-ai/dist/converters/plain-text.d.ts +6 -0
  301. package/vendor/markit-ai/dist/converters/plain-text.js +87 -0
  302. package/vendor/markit-ai/dist/converters/pptx.d.ts +8 -0
  303. package/vendor/markit-ai/dist/converters/pptx.js +289 -0
  304. package/vendor/markit-ai/dist/converters/rss.d.ts +11 -0
  305. package/vendor/markit-ai/dist/converters/rss.js +138 -0
  306. package/vendor/markit-ai/dist/converters/wikipedia.d.ts +6 -0
  307. package/vendor/markit-ai/dist/converters/wikipedia.js +33 -0
  308. package/vendor/markit-ai/dist/converters/xlsx.d.ts +8 -0
  309. package/vendor/markit-ai/dist/converters/xlsx.js +147 -0
  310. package/vendor/markit-ai/dist/converters/xml.d.ts +6 -0
  311. package/vendor/markit-ai/dist/converters/xml.js +18 -0
  312. package/vendor/markit-ai/dist/converters/yaml.d.ts +6 -0
  313. package/vendor/markit-ai/dist/converters/yaml.js +17 -0
  314. package/vendor/markit-ai/dist/converters/zip.d.ts +8 -0
  315. package/vendor/markit-ai/dist/converters/zip.js +57 -0
  316. package/vendor/markit-ai/dist/index.d.ts +30 -0
  317. package/vendor/markit-ai/dist/index.js +26 -0
  318. package/vendor/markit-ai/dist/main.d.ts +2 -0
  319. package/vendor/markit-ai/dist/main.js +191 -0
  320. package/vendor/markit-ai/dist/markit.d.ts +45 -0
  321. package/vendor/markit-ai/dist/markit.js +267 -0
  322. package/vendor/markit-ai/dist/plugins/api.d.ts +7 -0
  323. package/vendor/markit-ai/dist/plugins/api.js +42 -0
  324. package/vendor/markit-ai/dist/plugins/index.d.ts +4 -0
  325. package/vendor/markit-ai/dist/plugins/index.js +3 -0
  326. package/vendor/markit-ai/dist/plugins/installer.d.ts +25 -0
  327. package/vendor/markit-ai/dist/plugins/installer.js +176 -0
  328. package/vendor/markit-ai/dist/plugins/loader.d.ts +6 -0
  329. package/vendor/markit-ai/dist/plugins/loader.js +61 -0
  330. package/vendor/markit-ai/dist/plugins/types.d.ts +25 -0
  331. package/vendor/markit-ai/dist/plugins/types.js +1 -0
  332. package/vendor/markit-ai/dist/providers/anthropic.d.ts +2 -0
  333. package/vendor/markit-ai/dist/providers/anthropic.js +47 -0
  334. package/vendor/markit-ai/dist/providers/index.d.ts +21 -0
  335. package/vendor/markit-ai/dist/providers/index.js +56 -0
  336. package/vendor/markit-ai/dist/providers/openai.d.ts +2 -0
  337. package/vendor/markit-ai/dist/providers/openai.js +76 -0
  338. package/vendor/markit-ai/dist/providers/types.d.ts +26 -0
  339. package/vendor/markit-ai/dist/providers/types.js +1 -0
  340. package/vendor/markit-ai/dist/types.d.ts +36 -0
  341. package/vendor/markit-ai/dist/types.js +1 -0
  342. package/vendor/markit-ai/dist/utils/exit-codes.d.ts +4 -0
  343. package/vendor/markit-ai/dist/utils/exit-codes.js +4 -0
  344. package/vendor/markit-ai/dist/utils/output.d.ts +22 -0
  345. package/vendor/markit-ai/dist/utils/output.js +31 -0
  346. package/vendor/markit-ai/dist/utils/turndown.d.ts +8 -0
  347. package/vendor/markit-ai/dist/utils/turndown.js +70 -0
  348. package/vendor/markit-ai/package.json +74 -0
  349. package/vendor/markit-ai.patch +49 -0
@@ -758,6 +758,37 @@ describe("MCPConnectionPool", () => {
758
758
  await pool.shutdown();
759
759
  });
760
760
 
761
+ test("fences a pending acquisition when a prepared replacement publishes first", async () => {
762
+ const openStarted = Promise.withResolvers<void>();
763
+ const allowOpen = Promise.withResolvers<MCPServerConnection>();
764
+ let opens = 0;
765
+ const replacementTransport = new FakeTransport();
766
+ const pool = new MCPConnectionPool({
767
+ connect: async (name, config) => {
768
+ opens += 1;
769
+ if (opens === 1) {
770
+ openStarted.resolve();
771
+ return allowOpen.promise;
772
+ }
773
+ return connection(name, config, replacementTransport);
774
+ },
775
+ });
776
+ const configValue = config();
777
+ const pending = pool.acquire("server", configValue, { sessionId: "replacement-fence" });
778
+ await openStarted.promise;
779
+
780
+ const replacement = await pool.prepareReplacement("server", configValue, {
781
+ sessionId: "replacement-fence",
782
+ });
783
+ replacement.commit();
784
+ allowOpen.resolve(connection("server", configValue, new FakeTransport()));
785
+
786
+ await expect(pending).rejects.toBeInstanceOf(MCPPoolAcquireAbortError);
787
+ expect(pool.isCurrentLease(replacement.lease)).toBe(true);
788
+ await replacement.lease.release();
789
+ await pool.shutdown();
790
+ });
791
+
761
792
  test("onEvent rejects after pool shutdown invalidates the lease", async () => {
762
793
  const transport = new FakeTransport();
763
794
  const pool = new MCPConnectionPool({ connect: async (name, cfg) => connection(name, cfg, transport) });
@@ -208,6 +208,7 @@ type RetiredAcquisitionCleanup = {
208
208
  error: MCPPoolAcquireAbortError;
209
209
  failure?: MCPConnectionCleanupFailure;
210
210
  retry?: Promise<void>;
211
+ entry?: PoolEntry;
211
212
  };
212
213
 
213
214
  function errorMessage(error: unknown): string {
@@ -245,6 +246,14 @@ export interface MCPPoolLease {
245
246
  release(): Promise<void>;
246
247
  }
247
248
 
249
+ export interface MCPPreparedReplacement {
250
+ readonly lease: MCPPoolLease;
251
+ canCommit(): boolean;
252
+ publish(): void;
253
+ commit(): void;
254
+ abort(): Promise<void>;
255
+ }
256
+
248
257
  class MCPPoolLeaseImpl implements MCPPoolLease {
249
258
  readonly generation: number;
250
259
  readonly key: string;
@@ -407,6 +416,8 @@ export class MCPConnectionPool {
407
416
  readonly #pending = new Map<string, PendingEntry>();
408
417
  readonly #allLeases = new Set<MCPPoolLeaseImpl>();
409
418
  readonly #retiredEntries = new Set<PoolEntry>();
419
+ readonly #preparedEntries = new Set<PoolEntry>();
420
+ readonly #pendingPreparedReplacements = new Set<Promise<void>>();
410
421
  readonly #retiredAcquisitionCleanups = new Map<string, RetiredAcquisitionCleanup>();
411
422
  readonly #restartOwners = new Set<string>();
412
423
  readonly #restartWaiters = new Map<string, { promise: Promise<boolean>; resolve: (value: boolean) => void }>();
@@ -480,26 +491,42 @@ export class MCPConnectionPool {
480
491
  this.#restartWaiters.delete(key);
481
492
  }
482
493
 
494
+ private retiredCleanupId(key: string, generation: number): string {
495
+ return JSON.stringify([key, generation]);
496
+ }
497
+
498
+ private getRetiredAcquisitionCleanup(key: string, generation: number): RetiredAcquisitionCleanup | undefined {
499
+ return this.#retiredAcquisitionCleanups.get(this.retiredCleanupId(key, generation));
500
+ }
501
+
502
+ private getRetiredAcquisitionCleanupForKey(key: string): RetiredAcquisitionCleanup | undefined {
503
+ for (const cleanup of this.#retiredAcquisitionCleanups.values()) {
504
+ if (cleanup.key === key) return cleanup;
505
+ }
506
+ return undefined;
507
+ }
508
+
483
509
  private retainCancelledAcquireCleanup(
484
510
  key: string,
485
511
  name: string,
486
512
  pending: PendingEntry,
487
513
  cause: unknown,
488
514
  ): RetiredAcquisitionCleanup {
489
- const current = this.#retiredAcquisitionCleanups.get(key);
490
- if (current) return current;
491
515
  const completion = pending.settlement;
492
516
  const generation = pending.entry?.generation;
493
517
  if (!completion || generation === undefined) {
494
518
  throw new Error(`MCP cancelled acquisition cleanup is missing its flight identity: ${key}`);
495
519
  }
520
+ const current = this.getRetiredAcquisitionCleanup(key, generation);
521
+ if (current) return current;
496
522
  const error = new MCPPoolAcquireAbortError(name, key, cause, completion, generation);
497
523
  const owner: RetiredAcquisitionCleanup = { key, serverName: name, generation, completion, error };
498
- this.#retiredAcquisitionCleanups.set(key, owner);
524
+ const ownerId = this.retiredCleanupId(key, generation);
525
+ this.#retiredAcquisitionCleanups.set(ownerId, owner);
499
526
  void completion.then(
500
527
  () => {
501
- if (this.#retiredAcquisitionCleanups.get(key) === owner && !owner.retry) {
502
- this.#retiredAcquisitionCleanups.delete(key);
528
+ if (this.#retiredAcquisitionCleanups.get(ownerId) === owner && !owner.retry) {
529
+ this.#retiredAcquisitionCleanups.delete(ownerId);
503
530
  }
504
531
  },
505
532
  error => {
@@ -507,14 +534,42 @@ export class MCPConnectionPool {
507
534
  owner.failure = error;
508
535
  return;
509
536
  }
510
- if (this.#retiredAcquisitionCleanups.get(key) === owner && !owner.retry) {
511
- this.#retiredAcquisitionCleanups.delete(key);
537
+ if (this.#retiredAcquisitionCleanups.get(ownerId) === owner && !owner.retry) {
538
+ this.#retiredAcquisitionCleanups.delete(ownerId);
512
539
  }
513
540
  },
514
541
  );
515
542
  return owner;
516
543
  }
517
544
 
545
+ private retainPreparedCleanup(
546
+ key: string,
547
+ name: string,
548
+ generation: number,
549
+ cause: unknown,
550
+ transport: MCPTransport,
551
+ entry?: PoolEntry,
552
+ ): RetiredAcquisitionCleanup {
553
+ const current = this.getRetiredAcquisitionCleanup(key, generation);
554
+ if (current) return current;
555
+ const failure =
556
+ cause instanceof MCPConnectionCleanupFailure ? cause : new MCPConnectionCleanupFailure(cause, transport);
557
+ const completion = Promise.reject<void>(failure);
558
+ void completion.catch(() => {});
559
+ const error = new MCPPoolAcquireAbortError(name, key, failure, completion, generation);
560
+ const owner: RetiredAcquisitionCleanup = {
561
+ key,
562
+ serverName: name,
563
+ generation,
564
+ completion,
565
+ error,
566
+ failure,
567
+ entry,
568
+ };
569
+ this.#retiredAcquisitionCleanups.set(this.retiredCleanupId(key, generation), owner);
570
+ return owner;
571
+ }
572
+
518
573
  private notifyPendingAcquireCleanup(
519
574
  listener: MCPPoolAcquireOptions["onCleanupPending"],
520
575
  owner: RetiredAcquisitionCleanup,
@@ -532,14 +587,17 @@ export class MCPConnectionPool {
532
587
 
533
588
  /** @internal Whether this pool still owns the notified abandoned-acquire flight. */
534
589
  hasPendingAcquireCleanup(error: MCPPoolAcquireAbortError): boolean {
535
- const owner = this.#retiredAcquisitionCleanups.get(error.poolKey);
536
- return owner?.generation === error.cleanupGeneration;
590
+ return (
591
+ error.cleanupGeneration !== undefined &&
592
+ this.getRetiredAcquisitionCleanup(error.poolKey, error.cleanupGeneration) !== undefined
593
+ );
537
594
  }
538
595
 
539
596
  /** @internal Current retained failure for one notified abandoned-acquire generation. */
540
597
  getPendingAcquireCleanupFailure(error: MCPPoolAcquireAbortError): MCPConnectionCleanupFailure | undefined {
541
- const owner = this.#retiredAcquisitionCleanups.get(error.poolKey);
542
- return owner && owner.generation === error.cleanupGeneration ? owner.failure : undefined;
598
+ return error.cleanupGeneration === undefined
599
+ ? undefined
600
+ : this.getRetiredAcquisitionCleanup(error.poolKey, error.cleanupGeneration)?.failure;
543
601
  }
544
602
 
545
603
  /** @internal Prevent manager-level duplication of the pool's retained cleanup owner. */
@@ -566,9 +624,10 @@ export class MCPConnectionPool {
566
624
 
567
625
  /** @internal Join and retry one generation of abandoned acquisition cleanup. */
568
626
  async closePendingAcquireCleanup(key: string, generation: number): Promise<void> {
569
- const owner = this.#retiredAcquisitionCleanups.get(key);
570
- if (!owner || owner.generation !== generation) return;
627
+ const owner = this.getRetiredAcquisitionCleanup(key, generation);
628
+ if (!owner) return;
571
629
  if (owner.retry) return owner.retry;
630
+ const ownerId = this.retiredCleanupId(key, generation);
572
631
  let tracked!: Promise<void>;
573
632
  tracked = (async () => {
574
633
  let failure = owner.failure;
@@ -584,15 +643,21 @@ export class MCPConnectionPool {
584
643
  try {
585
644
  await failure.close();
586
645
  } catch (error) {
587
- if (this.#retiredAcquisitionCleanups.get(key) === owner) {
646
+ if (this.#retiredAcquisitionCleanups.get(ownerId) === owner) {
588
647
  owner.failure = error instanceof MCPConnectionCleanupFailure ? error : failure;
589
648
  }
590
649
  throw error;
591
650
  }
592
651
  }
593
- if (this.#retiredAcquisitionCleanups.get(key) === owner) this.#retiredAcquisitionCleanups.delete(key);
652
+ if (owner.entry) {
653
+ owner.entry.closePromise = undefined;
654
+ await this.closeEntry(owner.entry);
655
+ this.#preparedEntries.delete(owner.entry);
656
+ }
657
+ if (this.#retiredAcquisitionCleanups.get(ownerId) === owner) this.#retiredAcquisitionCleanups.delete(ownerId);
594
658
  })().finally(() => {
595
- if (this.#retiredAcquisitionCleanups.get(key) === owner && owner.retry === tracked) owner.retry = undefined;
659
+ if (this.#retiredAcquisitionCleanups.get(ownerId) === owner && owner.retry === tracked)
660
+ owner.retry = undefined;
596
661
  });
597
662
  owner.retry = tracked;
598
663
  return tracked;
@@ -610,7 +675,7 @@ export class MCPConnectionPool {
610
675
  );
611
676
  }
612
677
  for (;;) {
613
- const cleanup = this.#retiredAcquisitionCleanups.get(key);
678
+ const cleanup = this.getRetiredAcquisitionCleanupForKey(key);
614
679
  if (!cleanup) break;
615
680
  this.notifyPendingAcquireCleanup(options.onCleanupPending, cleanup);
616
681
  await this.closePendingAcquireCleanup(cleanup.key, cleanup.generation);
@@ -658,6 +723,175 @@ export class MCPConnectionPool {
658
723
  return lease;
659
724
  }
660
725
 
726
+ /**
727
+ * Prepared MCP replacements fence and retain acquisition cleanup ownership
728
+ * The caller validates its catalog first, then commits the key swap
729
+ * synchronously or aborts and closes only the candidate.
730
+ */
731
+ async prepareReplacement(
732
+ name: string,
733
+ config: MCPServerConfig,
734
+ options: MCPPoolAcquireOptions = {},
735
+ ): Promise<MCPPreparedReplacement> {
736
+ if (this.#shuttingDown) throw new Error("MCP connection pool is shut down");
737
+ const key = computeMCPPoolKey(name, config, options);
738
+ if (options.signal?.aborted) {
739
+ throw new MCPPoolAcquireAbortError(
740
+ name,
741
+ key,
742
+ options.signal.reason ?? new Error(`MCP replacement preparation aborted: ${name}`),
743
+ );
744
+ }
745
+ for (;;) {
746
+ const cleanup = this.getRetiredAcquisitionCleanupForKey(key);
747
+ if (!cleanup) break;
748
+ this.notifyPendingAcquireCleanup(options.onCleanupPending, cleanup);
749
+ await this.closePendingAcquireCleanup(cleanup.key, cleanup.generation);
750
+ }
751
+ if (options.signal?.aborted) {
752
+ throw new MCPPoolAcquireAbortError(
753
+ name,
754
+ key,
755
+ options.signal.reason ?? new Error(`MCP replacement preparation aborted: ${name}`),
756
+ );
757
+ }
758
+ const pending = this.#pending.get(key);
759
+ if (pending && !pending.cancelled && !pending.settled) {
760
+ this.cancelPendingEntry(
761
+ key,
762
+ pending,
763
+ new MCPPoolAcquireAbortError(
764
+ name,
765
+ key,
766
+ new Error(`MCP connection acquisition superseded by replacement: ${name}`),
767
+ ),
768
+ );
769
+ }
770
+ const identity = buildMCPPoolKeyIdentity(name, config, options);
771
+ const generation = (this.#entryGenerations.get(key) ?? 0) + 1;
772
+ this.#entryGenerations.set(key, generation);
773
+ const openSignal = options.signal
774
+ ? AbortSignal.any([options.signal, this.#shutdownController.signal])
775
+ : this.#shutdownController.signal;
776
+ const preparedFlight = Promise.withResolvers<void>();
777
+ this.#pendingPreparedReplacements.add(preparedFlight.promise);
778
+ let connection: MCPServerConnection;
779
+ try {
780
+ connection = await this.#connect(name, config, {
781
+ signal: openSignal,
782
+ advertiseRoots: options.advertiseRoots,
783
+ onNotification: options.onNotification,
784
+ onRequest: options.onRequest,
785
+ });
786
+ if (this.#shuttingDown) {
787
+ try {
788
+ await connection.transport.close();
789
+ } catch (closeError) {
790
+ const cleanup = this.retainPreparedCleanup(
791
+ key,
792
+ name,
793
+ generation,
794
+ new AggregateError(
795
+ [new Error(`MCP replacement connected after pool shutdown: ${name}`), closeError],
796
+ `MCP late replacement cleanup failed: ${name}`,
797
+ ),
798
+ connection.transport,
799
+ );
800
+ this.notifyPendingAcquireCleanup(options.onCleanupPending, cleanup);
801
+ logger.error("MCP late replacement transport close failed", {
802
+ path: `mcp:${name}`,
803
+ poolKey: key,
804
+ error: closeError,
805
+ });
806
+ throw cleanup.failure!;
807
+ }
808
+ throw new Error(`MCP connection pool is shut down`);
809
+ }
810
+ } catch (error) {
811
+ preparedFlight.resolve();
812
+ this.#pendingPreparedReplacements.delete(preparedFlight.promise);
813
+ throw error;
814
+ }
815
+ const entry: PoolEntry = {
816
+ generation,
817
+ key,
818
+ name,
819
+ config,
820
+ identity,
821
+ connection,
822
+ refCount: 1,
823
+ leases: new Set(),
824
+ rootsByLease: new Map(),
825
+ resourceSubscriptionCounts: new Map(),
826
+ resourceSubscriptionUpdate: Promise.resolve(),
827
+ state: "connected",
828
+ events: [],
829
+ };
830
+ try {
831
+ this.installTransportHandlers(entry, options);
832
+ this.#preparedEntries.add(entry);
833
+ } finally {
834
+ preparedFlight.resolve();
835
+ this.#pendingPreparedReplacements.delete(preparedFlight.promise);
836
+ }
837
+ const lease = new MCPPoolLeaseImpl(this, entry);
838
+ entry.leases.add(lease);
839
+ entry.rootsByLease.set(lease, []);
840
+ this.#allLeases.add(lease);
841
+ let settled = false;
842
+ const canCommit = (): boolean => entry.state === "connected" && entry.connection.transport.connected;
843
+ const publish = (): void => {
844
+ if (settled) throw new Error(`MCP prepared replacement already settled: ${name}`);
845
+ if (this.#shuttingDown || !canCommit()) {
846
+ throw new Error(`MCP prepared replacement closed before publish: ${name}`);
847
+ }
848
+ settled = true;
849
+ this.#preparedEntries.delete(entry);
850
+ const predecessor = this.#entries.get(key);
851
+ if (predecessor) this.retireEntry(predecessor);
852
+ this.#entries.set(key, entry);
853
+ this.record(entry, "connected");
854
+ };
855
+ return {
856
+ lease,
857
+ canCommit,
858
+ publish,
859
+ commit: () => {
860
+ if (!canCommit()) {
861
+ throw new Error(`MCP prepared replacement closed before commit: ${name}`);
862
+ }
863
+ publish();
864
+ },
865
+ abort: async () => {
866
+ if (settled) return;
867
+ lease.invalidate(new Error(`MCP prepared replacement aborted: ${name}`));
868
+ entry.leases.delete(lease);
869
+ entry.rootsByLease.delete(lease);
870
+ this.#allLeases.delete(lease);
871
+ entry.refCount = 0;
872
+ try {
873
+ await this.closeEntry(entry);
874
+ } catch (closeError) {
875
+ const cleanup = this.retainPreparedCleanup(
876
+ key,
877
+ name,
878
+ generation,
879
+ new AggregateError(
880
+ [new Error(`MCP prepared replacement aborted: ${name}`), closeError],
881
+ `MCP prepared replacement cleanup failed: ${name}`,
882
+ ),
883
+ entry.connection.transport,
884
+ entry,
885
+ );
886
+ this.notifyPendingAcquireCleanup(options.onCleanupPending, cleanup);
887
+ throw cleanup.failure!;
888
+ }
889
+ settled = true;
890
+ this.#preparedEntries.delete(entry);
891
+ },
892
+ };
893
+ }
894
+
661
895
  private waitForPendingEntry(
662
896
  key: string,
663
897
  name: string,
@@ -858,7 +1092,13 @@ export class MCPConnectionPool {
858
1092
  onRequest: options.onRequest,
859
1093
  });
860
1094
  entry.connection = connection;
861
- if (pending.cancelled || this.#pending.get(key) !== pending || this.#shuttingDown) {
1095
+ const superseded = this.#entryGenerations.get(key) !== generation;
1096
+ if (pending.cancelled || this.#pending.get(key) !== pending || this.#shuttingDown || superseded) {
1097
+ if (superseded && !pending.cancelled) {
1098
+ pending.cancelled = true;
1099
+ pending.cancellationReason = new Error(`MCP connection acquisition superseded: ${name}`);
1100
+ pending.openAbortController.abort(pending.cancellationReason);
1101
+ }
862
1102
  try {
863
1103
  await connection.transport.close();
864
1104
  } catch (closeError) {
@@ -1141,29 +1381,51 @@ export class MCPConnectionPool {
1141
1381
  pending.waiters.clear();
1142
1382
  if (this.#pending.get(key) === pending) this.#pending.delete(key);
1143
1383
  }
1144
- for (const cleanup of this.#retiredAcquisitionCleanups.values()) {
1145
- const failure = this.getPendingAcquireCleanupFailure(cleanup.error);
1146
- if (!failure) continue;
1147
- void this.closePendingAcquireCleanup(cleanup.key, cleanup.generation).catch(error =>
1384
+ await Promise.allSettled([...this.#pendingPreparedReplacements]);
1385
+ const retainedCleanups = [...this.#retiredAcquisitionCleanups.values()].filter(cleanup =>
1386
+ this.getPendingAcquireCleanupFailure(cleanup.error),
1387
+ );
1388
+ const retainedCleanupResults = await Promise.allSettled(
1389
+ retainedCleanups.map(cleanup => this.closePendingAcquireCleanup(cleanup.key, cleanup.generation)),
1390
+ );
1391
+ for (const [index, result] of retainedCleanupResults.entries()) {
1392
+ if (result.status === "rejected") {
1393
+ const cleanup = retainedCleanups[index];
1148
1394
  logger.error("MCP pool shutdown pending acquire cleanup failed", {
1149
- serverName: cleanup.serverName,
1150
- poolKey: cleanup.key,
1151
- error,
1152
- }),
1153
- );
1395
+ serverName: cleanup?.serverName,
1396
+ poolKey: cleanup?.key,
1397
+ error: result.reason,
1398
+ });
1399
+ }
1154
1400
  }
1155
1401
  for (const lease of this.#allLeases) lease.invalidate(reason);
1156
1402
  this.#allLeases.clear();
1157
- const entries = [...new Set([...this.#entries.values(), ...this.#retiredEntries])];
1403
+ const entries = [...new Set([...this.#entries.values(), ...this.#retiredEntries, ...this.#preparedEntries])];
1158
1404
  for (const entry of entries) {
1159
1405
  for (const lease of entry.leases) lease.invalidate(reason);
1160
1406
  entry.leases.clear();
1161
1407
  entry.rootsByLease.clear();
1162
1408
  }
1163
1409
  const closeResults = await Promise.allSettled(entries.map(entry => this.closeEntry(entry)));
1410
+ const failedEntryCleanups: RetiredAcquisitionCleanup[] = [];
1164
1411
  for (const [index, result] of closeResults.entries()) {
1165
1412
  if (result.status === "rejected") {
1166
1413
  const entry = entries[index];
1414
+ if (entry) {
1415
+ failedEntryCleanups.push(
1416
+ this.retainPreparedCleanup(
1417
+ entry.key,
1418
+ entry.name,
1419
+ entry.generation,
1420
+ new AggregateError(
1421
+ [new Error(`MCP pool shutdown closing entry: ${entry.name}`), result.reason],
1422
+ `MCP pool shutdown cleanup failed: ${entry.name}`,
1423
+ ),
1424
+ entry.connection.transport,
1425
+ entry,
1426
+ ),
1427
+ );
1428
+ }
1167
1429
  logger.error("MCP pool shutdown close failed", {
1168
1430
  serverName: entry?.name,
1169
1431
  poolKey: entry?.key,
@@ -1171,8 +1433,22 @@ export class MCPConnectionPool {
1171
1433
  });
1172
1434
  }
1173
1435
  }
1436
+ const failedEntryCleanupResults = await Promise.allSettled(
1437
+ failedEntryCleanups.map(cleanup => this.closePendingAcquireCleanup(cleanup.key, cleanup.generation)),
1438
+ );
1439
+ for (const [index, result] of failedEntryCleanupResults.entries()) {
1440
+ if (result.status === "rejected") {
1441
+ const cleanup = failedEntryCleanups[index];
1442
+ logger.error("MCP pool shutdown retry cleanup failed", {
1443
+ serverName: cleanup?.serverName,
1444
+ poolKey: cleanup?.key,
1445
+ error: result.reason,
1446
+ });
1447
+ }
1448
+ }
1174
1449
  this.#entries.clear();
1175
1450
  this.#retiredEntries.clear();
1451
+ this.#preparedEntries.clear();
1176
1452
  this.#restartOwners.clear();
1177
1453
  for (const waiter of this.#restartWaiters.values()) waiter.resolve(false);
1178
1454
  this.#restartWaiters.clear();
@@ -1,3 +1,5 @@
1
+ import type { AgentSession } from "../session/agent-session";
2
+
1
3
  const REDACTED = "<redacted>";
2
4
  const SENSITIVE_KEY_PATTERN = /(?:token|secret|key|credential|password|authorization|auth|bearer|cookie|session)/i;
3
5
 
@@ -28,3 +30,43 @@ export function redactMCPDiagnosticValue(value: unknown): unknown {
28
30
  ]),
29
31
  );
30
32
  }
33
+
34
+ /**
35
+ * Capability granted to a session that the root interactive entry point created
36
+ * with an explicit `--mcp-config` path. Holding it is the only way to read exact
37
+ * MCP status; it carries no manager, transport, or configuration reference.
38
+ */
39
+ export interface ExactMcpControls {
40
+ readonly grantSource: "root-interactive-exact-config";
41
+ /**
42
+ * The exact config this session was started with. Status needs it because a
43
+ * tools-only manager deletes a server from its own bookkeeping when the
44
+ * connection fails, so the manager alone can never report a server that did
45
+ * not come up — the very case an operator runs `/mcp` to see.
46
+ */
47
+ readonly configPath: string;
48
+ }
49
+
50
+ /**
51
+ * Exact MCP capability lives in a revocable export-blocked leaf WeakMap.
52
+ *
53
+ * The registry lives in this module because the file is a dependency-free leaf
54
+ * whose package subpath is blocked (`./runtime-mcp/*` is null in package.json
55
+ * exports) and which no barrel re-exports, so nothing outside this package can
56
+ * reach the map or mint a capability. Keep it that way: runtime imports here
57
+ * must stay at zero and the session type is referenced with `import type` only.
58
+ */
59
+ const exactMcpControlsBySession = new WeakMap<AgentSession, ExactMcpControls>();
60
+
61
+ export function attachExactMcpControls(session: AgentSession, controls: ExactMcpControls): void {
62
+ exactMcpControlsBySession.set(session, controls);
63
+ }
64
+
65
+ export function getExactMcpControls(session: AgentSession): ExactMcpControls | undefined {
66
+ return exactMcpControlsBySession.get(session);
67
+ }
68
+
69
+ /** Revoke controls when the AgentSession object adopts a new logical identity. */
70
+ export function revokeExactMcpControls(session: AgentSession): void {
71
+ exactMcpControlsBySession.delete(session);
72
+ }
@@ -2,6 +2,13 @@ import type { MCPServerConfig } from "./types";
2
2
 
3
3
  export type AutoloadStatus = "autoload" | "autoload-off" | "disabled";
4
4
 
5
+ /** Ordinary standalone sessions stop blocking on MCP startup after this wait. */
6
+ export const DEFAULT_MCP_STARTUP_WAIT_MS = 250;
7
+ /** Grace added to the largest declared per-server startup window. */
8
+ export const MCP_STARTUP_WAIT_GRACE_MS = 500;
9
+ /** Ordinary startup never blocks longer than this batch ceiling. */
10
+ export const MAX_MCP_STARTUP_WAIT_MS = 1_750;
11
+
5
12
  /** Pure startup policy shared by runtime-facing CLI inspection and doctor. */
6
13
  export function computeAutoloadStatus(
7
14
  name: string,