@sema-agent/core 7.54.1 → 7.56.0

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 (621) hide show
  1. package/CHANGELOG.md +950 -0
  2. package/dist/agents/agent-transcript-tool.js +2 -1
  3. package/dist/agents/builtin-agents.d.ts +12 -14
  4. package/dist/agents/cascade.js +1 -1
  5. package/dist/agents/cc-peer-directory.d.ts +36 -0
  6. package/dist/agents/cc-peer-directory.js +139 -0
  7. package/dist/agents/cc-peer-wire.d.ts +105 -0
  8. package/dist/agents/cc-peer-wire.js +98 -0
  9. package/dist/agents/cc-uds-peer-channel.d.ts +40 -0
  10. package/dist/agents/cc-uds-peer-channel.js +457 -0
  11. package/dist/agents/child-model-seat.d.ts +0 -11
  12. package/dist/agents/child-model-seat.js +0 -3
  13. package/dist/agents/cross-session-envelope.d.ts +4 -1
  14. package/dist/agents/cross-session-envelope.js +8 -1
  15. package/dist/agents/cross-session-judge.d.ts +2 -2
  16. package/dist/agents/list-agents-tool.d.ts +3 -1
  17. package/dist/agents/list-agents-tool.js +9 -8
  18. package/dist/agents/observer.d.ts +4 -5
  19. package/dist/agents/observer.js +2 -1
  20. package/dist/agents/peer-admission.d.ts +6 -0
  21. package/dist/agents/peer-admission.js +4 -1
  22. package/dist/agents/peer-directory.d.ts +65 -13
  23. package/dist/agents/peer-directory.js +90 -25
  24. package/dist/agents/peer-notices.d.ts +1 -1
  25. package/dist/agents/peer-session-drain.d.ts +3 -1
  26. package/dist/agents/peer-session-drain.js +3 -2
  27. package/dist/agents/read-inbox-tool.js +2 -1
  28. package/dist/agents/repair-loop.js +2 -2
  29. package/dist/agents/retain-ledger.d.ts +1 -1
  30. package/dist/agents/roster-store.d.ts +1 -1
  31. package/dist/agents/send-message-tool.d.ts +10 -0
  32. package/dist/agents/send-message-tool.js +37 -8
  33. package/dist/agents/subagent.d.ts +39 -82
  34. package/dist/agents/subagent.js +109 -106
  35. package/dist/agents/tool-filter.d.ts +31 -46
  36. package/dist/agents/tool-filter.js +13 -33
  37. package/dist/agents/verify.d.ts +6 -5
  38. package/dist/agents/verify.js +3 -3
  39. package/dist/brain/anthropic.js +43 -81
  40. package/dist/brain/errors.d.ts +15 -0
  41. package/dist/brain/errors.js +10 -0
  42. package/dist/brain/media-degrade.d.ts +18 -7
  43. package/dist/brain/media-degrade.js +13 -2
  44. package/dist/brain/model-capability.d.ts +37 -0
  45. package/dist/brain/model-capability.js +34 -0
  46. package/dist/brain/model-presets.d.ts +6 -12
  47. package/dist/brain/model-presets.js +1 -6
  48. package/dist/brain/open-responses.js +27 -35
  49. package/dist/brain/openai.js +30 -98
  50. package/dist/brain/provider-dialect.d.ts +39 -3
  51. package/dist/brain/provider-dialect.js +28 -0
  52. package/dist/brain/reasoning-request.d.ts +96 -0
  53. package/dist/brain/reasoning-request.js +174 -0
  54. package/dist/brain/reasoning.d.ts +12 -12
  55. package/dist/brain/reasoning.js +4 -3
  56. package/dist/brain/request-params.d.ts +62 -9
  57. package/dist/brain/request-params.js +42 -7
  58. package/dist/brain/retry.d.ts +1 -1
  59. package/dist/brain/route-adjudicator.d.ts +15 -0
  60. package/dist/brain/route-adjudicator.js +15 -0
  61. package/dist/brain/status-sink.d.ts +20 -0
  62. package/dist/brain/status-sink.js +7 -0
  63. package/dist/brain/stream-engine.js +6 -5
  64. package/dist/brain/stream-shared.d.ts +1 -1
  65. package/dist/core/a2a.d.ts +2 -1
  66. package/dist/core/a2a.js +19 -13
  67. package/dist/core/advisor-verdict.d.ts +120 -0
  68. package/dist/core/advisor-verdict.js +92 -0
  69. package/dist/core/agent-definition.d.ts +17 -8
  70. package/dist/core/allow-entry.d.ts +69 -36
  71. package/dist/core/allow-entry.js +81 -52
  72. package/dist/core/allow-rule-shadow.d.ts +10 -3
  73. package/dist/core/approval-object.d.ts +2 -1
  74. package/dist/core/approval-object.js +6 -6
  75. package/dist/core/ask-origin.d.ts +127 -29
  76. package/dist/core/ask-origin.js +87 -25
  77. package/dist/core/ask-question.d.ts +51 -8
  78. package/dist/core/ask-question.js +12 -7
  79. package/dist/core/ask-unresolvable-notice.d.ts +8 -3
  80. package/dist/core/ask-unresolvable-notice.js +16 -2
  81. package/dist/core/auto-compaction.d.ts +11 -8
  82. package/dist/core/auto-compaction.js +4 -2
  83. package/dist/core/auto-mode-arming.d.ts +2 -2
  84. package/dist/core/auto-mode-defaults.d.ts +8 -8
  85. package/dist/core/auto-mode-prompt-assets.d.ts +3 -3
  86. package/dist/core/auto-mode-prompt.d.ts +1 -1
  87. package/dist/core/auto-mode.d.ts +17 -9
  88. package/dist/core/auto-mode.js +9 -6
  89. package/dist/core/background-agent-store.d.ts +3 -3
  90. package/dist/core/canonical-json.d.ts +1 -1
  91. package/dist/core/canonical-json.js +2 -2
  92. package/dist/core/checkpoint-generation.d.ts +53 -0
  93. package/dist/core/checkpoint-generation.js +35 -0
  94. package/dist/core/checkpoint-queries.d.ts +180 -0
  95. package/dist/core/checkpoint-queries.js +272 -0
  96. package/dist/core/checkpoint-requirements.d.ts +19 -4
  97. package/dist/core/checkpoint-requirements.js +8 -14
  98. package/dist/core/checkpoint-store.d.ts +165 -72
  99. package/dist/core/checkpoint-store.js +79 -82
  100. package/dist/core/child-clamp-seats.d.ts +6 -0
  101. package/dist/core/child-clamp-seats.js +3 -16
  102. package/dist/core/compliance.d.ts +2 -2
  103. package/dist/core/context-edit.d.ts +6 -7
  104. package/dist/core/cross-boundary-taint.d.ts +11 -4
  105. package/dist/core/cross-boundary-taint.js +3 -3
  106. package/dist/core/decision-receipt.d.ts +37 -3
  107. package/dist/core/decision-receipt.js +19 -19
  108. package/dist/core/delegation-not-started.d.ts +6 -0
  109. package/dist/core/delegation-not-started.js +17 -0
  110. package/dist/core/effective-path-target.d.ts +1 -1
  111. package/dist/core/engine-attestation.d.ts +93 -0
  112. package/dist/core/engine-attestation.js +70 -0
  113. package/dist/core/engine-capabilities.d.ts +4 -1
  114. package/dist/core/engine-capabilities.js +1 -1
  115. package/dist/core/engine-notice.d.ts +45 -12
  116. package/dist/core/exec-output-tail.d.ts +1 -1
  117. package/dist/core/file-history-retention.d.ts +1 -1
  118. package/dist/core/file-history-store.d.ts +147 -21
  119. package/dist/core/file-history-store.js +58 -32
  120. package/dist/core/gate-fold.d.ts +1 -1
  121. package/dist/core/gate-fold.js +24 -11
  122. package/dist/core/gate-lanes.js +81 -68
  123. package/dist/core/gate-outcome.d.ts +40 -6
  124. package/dist/core/gate-outcome.js +56 -0
  125. package/dist/core/governance-codes.d.ts +17 -3
  126. package/dist/core/governance-codes.js +16 -0
  127. package/dist/core/hands-band.d.ts +1 -1
  128. package/dist/core/hooks.d.ts +21 -20
  129. package/dist/core/hooks.js +3 -1
  130. package/dist/core/host-floor.d.ts +128 -0
  131. package/dist/core/host-floor.js +206 -0
  132. package/dist/core/host-target.d.ts +84 -0
  133. package/dist/core/host-target.js +92 -0
  134. package/dist/core/image-downsample.d.ts +1 -1
  135. package/dist/core/lsp-diagnostics.d.ts +4 -4
  136. package/dist/core/lsp.d.ts +3 -3
  137. package/dist/core/mailbox-store.d.ts +4 -0
  138. package/dist/core/mcp-connection-pool.d.ts +18 -2
  139. package/dist/core/mcp-connection-pool.js +53 -6
  140. package/dist/core/mcp-failure.d.ts +23 -4
  141. package/dist/core/mcp-failure.js +26 -11
  142. package/dist/core/mcp-listing-drift.d.ts +10 -0
  143. package/dist/core/mcp-listing-drift.js +6 -0
  144. package/dist/core/mcp-server-link.d.ts +173 -0
  145. package/dist/core/mcp-server-link.js +127 -0
  146. package/dist/core/mcp-server-spec.d.ts +4 -2
  147. package/dist/core/mcp-session-end.d.ts +26 -0
  148. package/dist/core/mcp-session-end.js +29 -0
  149. package/dist/core/mcp-startup-request.d.ts +17 -0
  150. package/dist/core/mcp-startup-request.js +17 -0
  151. package/dist/core/mcp.d.ts +17 -13
  152. package/dist/core/mcp.js +240 -189
  153. package/dist/core/media-byte-cap.d.ts +1 -1
  154. package/dist/core/memory-engine/delegation-settlement.js +15 -24
  155. package/dist/core/memory-engine/engine.d.ts +9 -9
  156. package/dist/core/memory-engine/engine.js +4 -4
  157. package/dist/core/memory-engine/layout.d.ts +60 -8
  158. package/dist/core/memory-engine/layout.js +65 -6
  159. package/dist/core/memory-engine/provenance-wording.d.ts +1 -1
  160. package/dist/core/memory-engine/tools.js +4 -1
  161. package/dist/core/mode-policy.d.ts +1 -1
  162. package/dist/core/model-seat.d.ts +10 -3
  163. package/dist/core/mods/classic-events.d.ts +67 -0
  164. package/dist/core/mods/classic-events.js +1 -0
  165. package/dist/core/mods/dollar.d.ts +13 -0
  166. package/dist/core/mods/extension-call.d.ts +31 -0
  167. package/dist/core/mods/extension-call.js +43 -0
  168. package/dist/core/mods/kernel/dispatch.d.ts +20 -3
  169. package/dist/core/mods/kernel/dispatch.js +140 -69
  170. package/dist/core/mods/kernel/events.d.ts +47 -11
  171. package/dist/core/mods/kernel/events.js +66 -42
  172. package/dist/core/mods/kernel/index.d.ts +4 -4
  173. package/dist/core/mods/kernel/index.js +2 -2
  174. package/dist/core/mods/kernel/receive.d.ts +39 -5
  175. package/dist/core/mods/kernel/receive.js +290 -17
  176. package/dist/core/mods/kernel/registration.d.ts +33 -2
  177. package/dist/core/mods/kernel/registration.js +6 -7
  178. package/dist/core/mods/kernel/site-rules.d.ts +44 -16
  179. package/dist/core/mods/kernel/site-rules.js +24 -42
  180. package/dist/core/mods/spec-seats.d.ts +69 -0
  181. package/dist/core/mods/spec-seats.js +114 -0
  182. package/dist/core/mods/stations.d.ts +28 -8
  183. package/dist/core/mods/stations.js +29 -13
  184. package/dist/core/mods/tool-call.d.ts +79 -0
  185. package/dist/core/mods/tool-call.js +152 -0
  186. package/dist/core/namespaced-rule-name.d.ts +44 -24
  187. package/dist/core/namespaced-rule-name.js +50 -43
  188. package/dist/core/output-style.d.ts +1 -1
  189. package/dist/core/param-rule-reach.d.ts +15 -0
  190. package/dist/core/param-rule-reach.js +30 -0
  191. package/dist/core/parent-spec-seat.d.ts +13 -1
  192. package/dist/core/parent-spec-seat.js +6 -0
  193. package/dist/core/park-selfcheck.js +1 -0
  194. package/dist/core/pause-registry.d.ts +16 -5
  195. package/dist/core/pause-registry.js +6 -2
  196. package/dist/core/peer-channel.d.ts +70 -0
  197. package/dist/core/peer-channel.js +1 -0
  198. package/dist/core/permission-rule-consent.d.ts +30 -5
  199. package/dist/core/permission-rule-consent.js +147 -50
  200. package/dist/core/permission-rule-model.d.ts +245 -65
  201. package/dist/core/permission-rule-model.js +421 -107
  202. package/dist/core/permission-rule-org.d.ts +6 -2
  203. package/dist/core/permission-rule-org.js +7 -3
  204. package/dist/core/permission-rule-provider.d.ts +6 -2
  205. package/dist/core/permission-rule-provider.js +41 -11
  206. package/dist/core/permission-rule-store.d.ts +22 -26
  207. package/dist/core/permission-rule-store.js +12 -6
  208. package/dist/core/permission-rule-sync.d.ts +11 -2
  209. package/dist/core/permission-rule-sync.js +11 -3
  210. package/dist/core/permission-rule-syntax.d.ts +5 -4
  211. package/dist/core/permission-rule-syntax.js +2 -2
  212. package/dist/core/permission-rules.d.ts +53 -15
  213. package/dist/core/permission-rules.js +125 -100
  214. package/dist/core/persisted-rule-arms.d.ts +6 -4
  215. package/dist/core/persisted-rule-arms.js +10 -12
  216. package/dist/core/present-plan-tool.js +3 -1
  217. package/dist/core/principal-name.d.ts +20 -0
  218. package/dist/core/principal-name.js +22 -0
  219. package/dist/core/prompt-section-seat.js +4 -6
  220. package/dist/core/protocol-http-auth.d.ts +26 -5
  221. package/dist/core/protocol-http-auth.js +137 -4
  222. package/dist/core/protocol-naming.d.ts +2 -2
  223. package/dist/core/read-only-shell-table.d.ts +1 -1
  224. package/dist/core/read-only-shell.d.ts +1 -1
  225. package/dist/core/retired-keys.d.ts +16 -0
  226. package/dist/core/retired-keys.js +16 -4
  227. package/dist/core/rewrite-rejudge.d.ts +60 -0
  228. package/dist/core/rewrite-rejudge.js +36 -0
  229. package/dist/core/roles.d.ts +34 -3
  230. package/dist/core/roles.js +66 -53
  231. package/dist/core/rule-lane-reads.d.ts +20 -15
  232. package/dist/core/rule-lane-reads.js +45 -17
  233. package/dist/core/rule-offer-read.d.ts +53 -0
  234. package/dist/core/rule-offer-read.js +146 -0
  235. package/dist/core/rule-owner.d.ts +46 -0
  236. package/dist/core/rule-owner.js +29 -0
  237. package/dist/core/runner/advisor-instructions.d.ts +70 -0
  238. package/dist/core/runner/advisor-instructions.js +61 -0
  239. package/dist/core/runner/advisor-tool.d.ts +33 -0
  240. package/dist/core/runner/advisor-tool.js +112 -0
  241. package/dist/core/runner/announce-once-ledger.d.ts +18 -26
  242. package/dist/core/runner/announce-once-ledger.js +19 -46
  243. package/dist/core/runner/approval-feedback.js +6 -3
  244. package/dist/core/runner/assemble-result.d.ts +2 -1
  245. package/dist/core/runner/assemble-result.js +1 -1
  246. package/dist/core/runner/call-hook-stations.d.ts +3 -2
  247. package/dist/core/runner/caller-roster.d.ts +21 -2
  248. package/dist/core/runner/caller-roster.js +38 -0
  249. package/dist/core/runner/capability-withheld-seat.d.ts +5 -0
  250. package/dist/core/runner/capability-withheld-seat.js +24 -0
  251. package/dist/core/runner/classifier-ladder.d.ts +33 -13
  252. package/dist/core/runner/classifier-ladder.js +15 -14
  253. package/dist/core/runner/compaction-restate.d.ts +10 -6
  254. package/dist/core/runner/compaction-restate.js +9 -3
  255. package/dist/core/runner/construction-doors.js +3 -0
  256. package/dist/core/runner/contracts.d.ts +40 -33
  257. package/dist/core/runner/conversation-segment.d.ts +28 -0
  258. package/dist/core/runner/conversation-segment.js +42 -0
  259. package/dist/core/runner/cross-boundary-lane.d.ts +21 -16
  260. package/dist/core/runner/cross-boundary-lane.js +58 -34
  261. package/dist/core/runner/decide-continuation.d.ts +7 -4
  262. package/dist/core/runner/decide-continuation.js +2 -2
  263. package/dist/core/runner/denial-limit-arms.d.ts +4 -4
  264. package/dist/core/runner/denial-limit-arms.js +1 -1
  265. package/dist/core/runner/derived-route-fallback.d.ts +24 -24
  266. package/dist/core/runner/derived-route-fallback.js +9 -7
  267. package/dist/core/runner/file-history-request.d.ts +18 -0
  268. package/dist/core/runner/file-history-request.js +21 -13
  269. package/dist/core/runner/file-history-restore.d.ts +45 -0
  270. package/dist/core/runner/file-history-restore.js +46 -0
  271. package/dist/core/runner/gate-exit.d.ts +9 -3
  272. package/dist/core/runner/gate-exit.js +11 -5
  273. package/dist/core/runner/image.d.ts +7 -17
  274. package/dist/core/runner/image.js +9 -60
  275. package/dist/core/runner/initial-run-state.js +1 -1
  276. package/dist/core/runner/permission-rule-lanes.d.ts +6 -6
  277. package/dist/core/runner/permission-rule-lanes.js +38 -15
  278. package/dist/core/runner/person-path-rows.d.ts +12 -9
  279. package/dist/core/runner/person-path-rows.js +19 -8
  280. package/dist/core/runner/prepare-advisor.d.ts +63 -0
  281. package/dist/core/runner/prepare-advisor.js +77 -0
  282. package/dist/core/runner/prepare-ask-lane.d.ts +2 -2
  283. package/dist/core/runner/prepare-ask-lane.js +5 -2
  284. package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -6
  285. package/dist/core/runner/prepare-caps-and-workflow.js +5 -4
  286. package/dist/core/runner/prepare-config-doors.d.ts +31 -38
  287. package/dist/core/runner/prepare-config-doors.js +57 -34
  288. package/dist/core/runner/prepare-defer-classify.d.ts +4 -3
  289. package/dist/core/runner/prepare-defer-classify.js +7 -8
  290. package/dist/core/runner/prepare-delegation-surface.d.ts +2 -2
  291. package/dist/core/runner/prepare-delegation-surface.js +1 -1
  292. package/dist/core/runner/prepare-file-history.d.ts +48 -8
  293. package/dist/core/runner/prepare-file-history.js +41 -73
  294. package/dist/core/runner/prepare-gate-stations.d.ts +2 -5
  295. package/dist/core/runner/prepare-gate-stations.js +12 -8
  296. package/dist/core/runner/prepare-hands-readface.d.ts +2 -8
  297. package/dist/core/runner/prepare-hands-readface.js +15 -14
  298. package/dist/core/runner/prepare-inherited-gate.d.ts +11 -7
  299. package/dist/core/runner/prepare-inherited-gate.js +8 -6
  300. package/dist/core/runner/prepare-memory-engine-session.js +1 -1
  301. package/dist/core/runner/prepare-park-ask.js +12 -12
  302. package/dist/core/runner/prepare-policy-chain.d.ts +7 -4
  303. package/dist/core/runner/prepare-policy-chain.js +68 -81
  304. package/dist/core/runner/prepare-project-context.d.ts +5 -2
  305. package/dist/core/runner/prepare-project-context.js +6 -3
  306. package/dist/core/runner/prepare-prompt-assembly.d.ts +5 -7
  307. package/dist/core/runner/prepare-prompt-assembly.js +10 -8
  308. package/dist/core/runner/prepare-prompt-inputs.d.ts +11 -9
  309. package/dist/core/runner/prepare-prompt-inputs.js +4 -6
  310. package/dist/core/runner/prepare-protocol-tools.d.ts +4 -2
  311. package/dist/core/runner/prepare-protocol-tools.js +5 -4
  312. package/dist/core/runner/prepare-safety-scan.d.ts +9 -12
  313. package/dist/core/runner/prepare-safety-scan.js +8 -23
  314. package/dist/core/runner/prepare-suspend-saga.d.ts +2 -0
  315. package/dist/core/runner/prepare-suspend-saga.js +5 -6
  316. package/dist/core/runner/prepare-task.d.ts +1 -1
  317. package/dist/core/runner/prepare-task.js +41 -35
  318. package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +7 -4
  319. package/dist/core/runner/prepare-tool-disclosure-mount.js +24 -18
  320. package/dist/core/runner/prepare-turn-wiring.d.ts +0 -4
  321. package/dist/core/runner/prepare-turn-wiring.js +2 -7
  322. package/dist/core/runner/prepare-wiring-manifest.d.ts +11 -4
  323. package/dist/core/runner/prepare-wiring-manifest.js +3 -3
  324. package/dist/core/runner/resume-admission.js +1 -1
  325. package/dist/core/runner/resume-apply.js +11 -12
  326. package/dist/core/runner/resume-checkpoint-screen.js +3 -0
  327. package/dist/core/runner/resume-claim.d.ts +4 -2
  328. package/dist/core/runner/resume-claim.js +15 -8
  329. package/dist/core/runner/resume-policy-outcome.js +1 -1
  330. package/dist/core/runner/retired-runner-deps.js +2 -1
  331. package/dist/core/runner/rewind-files.d.ts +15 -0
  332. package/dist/core/runner/rewind-files.js +132 -0
  333. package/dist/core/runner/run-attachment-seats.js +2 -2
  334. package/dist/core/runner/run-brain-sinks.d.ts +4 -1
  335. package/dist/core/runner/run-brain-sinks.js +4 -2
  336. package/dist/core/runner/run-compaction-machinery.d.ts +1 -1
  337. package/dist/core/runner/run-compaction-machinery.js +2 -12
  338. package/dist/core/runner/run-git-lane.d.ts +1 -0
  339. package/dist/core/runner/run-harness-handlers.js +14 -7
  340. package/dist/core/runner/run-leg.d.ts +1 -1
  341. package/dist/core/runner/run-leg.js +43 -18
  342. package/dist/core/runner/run-settle-and-teardown.js +3 -2
  343. package/dist/core/runner/run-telemetry-and-budget-seats.js +1 -1
  344. package/dist/core/runner/run-turn-boundary.d.ts +1 -0
  345. package/dist/core/runner/run-turn-boundary.js +15 -22
  346. package/dist/core/runner/runtask.d.ts +3 -0
  347. package/dist/core/runner/runtask.js +8 -9
  348. package/dist/core/runner/session-read-file-states.d.ts +15 -0
  349. package/dist/core/runner/session-read-file-states.js +28 -0
  350. package/dist/core/runner/session-rule-policy.d.ts +22 -21
  351. package/dist/core/runner/session-rule-policy.js +17 -31
  352. package/dist/core/runner/shell-env-withheld.d.ts +33 -0
  353. package/dist/core/runner/shell-env-withheld.js +51 -0
  354. package/dist/core/runner/side-call-account.d.ts +32 -8
  355. package/dist/core/runner/side-call-account.js +23 -1
  356. package/dist/core/runner/skills-seat.js +6 -2
  357. package/dist/core/runner/stream-settle-backstop.js +1 -1
  358. package/dist/core/runner/strict-output-schema.d.ts +1 -1
  359. package/dist/core/runner/sub-agent-deny-lists.js +4 -6
  360. package/dist/core/runner/synthetic-tools.d.ts +16 -13
  361. package/dist/core/runner/synthetic-tools.js +8 -3
  362. package/dist/core/runner/tool-disclosure.d.ts +10 -12
  363. package/dist/core/runner/tool-disclosure.js +3 -4
  364. package/dist/core/runner/tool-end-body.d.ts +1 -1
  365. package/dist/core/runner/tool-end-body.js +10 -9
  366. package/dist/core/runner/tool-face-overlay.d.ts +2 -1
  367. package/dist/core/runner/tool-face-overlay.js +17 -1
  368. package/dist/core/runner/tool-not-executed.d.ts +5 -0
  369. package/dist/core/runner/tool-not-executed.js +11 -0
  370. package/dist/core/runner/tool-occurrence.d.ts +8 -0
  371. package/dist/core/runner/tool-occurrence.js +7 -0
  372. package/dist/core/runner/tool-progress-lane.d.ts +2 -2
  373. package/dist/core/runner/tool-turn-repair-seat.d.ts +3 -2
  374. package/dist/core/runner/turn-attachments.d.ts +91 -80
  375. package/dist/core/runner/turn-attachments.js +62 -37
  376. package/dist/core/runner-deps.d.ts +42 -42
  377. package/dist/core/runtime-caps.d.ts +4 -4
  378. package/dist/core/safety-axis-vocab.d.ts +6 -4
  379. package/dist/core/safety-axis-vocab.js +6 -5
  380. package/dist/core/safety-merge-corpus.js +26 -2
  381. package/dist/core/same-plain-value.d.ts +40 -0
  382. package/dist/core/same-plain-value.js +49 -0
  383. package/dist/core/scheduler.d.ts +1 -1
  384. package/dist/core/secret-env.d.ts +26 -3
  385. package/dist/core/secret-env.js +44 -8
  386. package/dist/core/select-model.js +3 -3
  387. package/dist/core/sensitive-path-policy.d.ts +1 -1
  388. package/dist/core/sensitive-path-policy.js +1 -1
  389. package/dist/core/session-policy-store.d.ts +102 -35
  390. package/dist/core/session-policy-store.js +210 -48
  391. package/dist/core/session-reconcile.d.ts +2 -2
  392. package/dist/core/session-store.d.ts +106 -37
  393. package/dist/core/session-store.js +165 -91
  394. package/dist/core/session.d.ts +101 -57
  395. package/dist/core/session.js +53 -0
  396. package/dist/core/shared-memory/tools.js +3 -1
  397. package/dist/core/shared-memory/types.d.ts +1 -1
  398. package/dist/core/shell-read-silence.d.ts +11 -12
  399. package/dist/core/shell-read-silence.js +9 -5
  400. package/dist/core/shell-run-candidates.js +3 -1
  401. package/dist/core/shell-wrapper-projection.js +1 -1
  402. package/dist/core/shell-wrapper-table.d.ts +14 -7
  403. package/dist/core/shell-wrapper-table.js +5 -4
  404. package/dist/core/side-query.d.ts +10 -0
  405. package/dist/core/side-query.js +15 -1
  406. package/dist/core/skill-grant.d.ts +7 -2
  407. package/dist/core/skill-grant.js +5 -0
  408. package/dist/core/skills-directory.js +6 -2
  409. package/dist/core/store-contracts/checkpoint-store-contract.d.ts +11 -1
  410. package/dist/core/store-contracts/checkpoint-store-contract.js +168 -3
  411. package/dist/core/store-contracts/file-history-store-contract.js +74 -4
  412. package/dist/core/store-contracts/peer-directory-contract.d.ts +7 -2
  413. package/dist/core/store-contracts/peer-directory-contract.js +14 -2
  414. package/dist/core/store-contracts/session-policy-store-contract.d.ts +7 -0
  415. package/dist/core/store-contracts/session-policy-store-contract.js +130 -0
  416. package/dist/core/store-contracts/session-repo-contract.js +176 -0
  417. package/dist/core/store-contracts/session-store-contract.d.ts +6 -8
  418. package/dist/core/store-contracts/session-store-contract.js +361 -51
  419. package/dist/core/store-contracts/workflow-journal-store-contract.js +26 -1
  420. package/dist/core/stub-env.d.ts +2 -0
  421. package/dist/core/stub-env.js +1 -0
  422. package/dist/core/surrogate-safe-slice.d.ts +3 -3
  423. package/dist/core/synthetic-read-verdict.js +3 -3
  424. package/dist/core/task-event.d.ts +42 -8
  425. package/dist/core/task-notification.d.ts +19 -15
  426. package/dist/core/task-registry-agent.d.ts +4 -4
  427. package/dist/core/task-registry-shared.d.ts +4 -4
  428. package/dist/core/task-registry-shared.js +1 -0
  429. package/dist/core/task-registry.d.ts +13 -4
  430. package/dist/core/task-registry.js +14 -2
  431. package/dist/core/task-result.d.ts +21 -3
  432. package/dist/core/task-spec.d.ts +69 -64
  433. package/dist/core/task-stream.d.ts +6 -6
  434. package/dist/core/task-tool-shape.d.ts +4 -4
  435. package/dist/core/tighten-task-spec.d.ts +1 -1
  436. package/dist/core/tighten-task-spec.js +2 -1
  437. package/dist/core/tool-catalog-entries.d.ts +36 -2
  438. package/dist/core/tool-catalog-entries.js +69 -43
  439. package/dist/core/tool-check-reading.d.ts +11 -0
  440. package/dist/core/tool-check-reading.js +11 -6
  441. package/dist/core/tool-conformance.js +1 -0
  442. package/dist/core/tool-errors.d.ts +2 -2
  443. package/dist/core/tool-face-reader.js +5 -3
  444. package/dist/core/tool-face.d.ts +21 -2
  445. package/dist/core/tool-face.js +1 -1
  446. package/dist/core/tool-model-gate.d.ts +5 -5
  447. package/dist/core/tool-name-aliases.d.ts +29 -8
  448. package/dist/core/tool-name-aliases.js +22 -4
  449. package/dist/core/tool-name-readings.d.ts +10 -43
  450. package/dist/core/tool-name-readings.js +2 -11
  451. package/dist/core/tool-policy.d.ts +85 -196
  452. package/dist/core/tool-policy.js +150 -175
  453. package/dist/core/tool-registry.d.ts +14 -7
  454. package/dist/core/tool-registry.js +17 -7
  455. package/dist/core/tool-result-store.js +5 -1
  456. package/dist/core/tool-roster.d.ts +57 -33
  457. package/dist/core/tool-roster.js +56 -68
  458. package/dist/core/tool-spec-members.js +8 -3
  459. package/dist/core/tool-spec.d.ts +53 -31
  460. package/dist/core/tools.js +51 -10
  461. package/dist/core/trace.d.ts +6 -2
  462. package/dist/core/types.d.ts +1 -1
  463. package/dist/core/untrusted-egress.d.ts +1 -1
  464. package/dist/core/untrusted-text.d.ts +1 -1
  465. package/dist/core/user-attachment.d.ts +8 -1
  466. package/dist/core/user-attachment.js +64 -4
  467. package/dist/core/warm-resume.d.ts +1 -1
  468. package/dist/core/wiring-manifest.d.ts +58 -0
  469. package/dist/core/wiring-manifest.js +14 -5
  470. package/dist/core/workflow-journal-store.d.ts +62 -0
  471. package/dist/core/workflow-journal-store.js +78 -2
  472. package/dist/core/workflow-run-store.d.ts +6 -0
  473. package/dist/core/workflow-run-store.js +2 -0
  474. package/dist/engine/compaction/compaction.d.ts +9 -9
  475. package/dist/engine/compaction/compaction.js +3 -2
  476. package/dist/engine/execution-env/node-execution-env.d.ts +26 -8
  477. package/dist/engine/execution-env/node-execution-env.js +54 -24
  478. package/dist/engine/harness/agent-harness.d.ts +39 -9
  479. package/dist/engine/harness/agent-harness.js +87 -33
  480. package/dist/engine/harness/types.d.ts +58 -9
  481. package/dist/engine/harness/types.js +12 -1
  482. package/dist/engine/llm/types.d.ts +36 -19
  483. package/dist/engine/llm/validation.d.ts +4 -1
  484. package/dist/engine/llm/validation.js +13 -1
  485. package/dist/engine/loop/agent-loop.d.ts +23 -1
  486. package/dist/engine/loop/agent-loop.js +26 -34
  487. package/dist/engine/loop/types.d.ts +31 -19
  488. package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
  489. package/dist/engine/session/memory-repo.d.ts +18 -12
  490. package/dist/engine/session/memory-repo.js +24 -9
  491. package/dist/engine/session/parent-chain-guard.d.ts +3 -2
  492. package/dist/engine/session/parent-chain-guard.js +1 -1
  493. package/dist/engine/session/repo-utils.d.ts +32 -3
  494. package/dist/engine/session/repo-utils.js +50 -5
  495. package/dist/index.d.ts +47 -23
  496. package/dist/index.js +35 -17
  497. package/dist/internal/harness-types.d.ts +1 -1
  498. package/dist/internal/harness.d.ts +3 -3
  499. package/dist/internal/harness.js +2 -2
  500. package/dist/internal/llm.d.ts +2 -2
  501. package/dist/internal/llm.js +1 -1
  502. package/dist/orchestration/goal.js +2 -2
  503. package/dist/orchestration/run-workflow-tool.d.ts +8 -6
  504. package/dist/orchestration/run-workflow-tool.js +10 -6
  505. package/dist/orchestration/workflow-size-guideline.d.ts +4 -4
  506. package/dist/orchestration/workflow-types.d.ts +18 -0
  507. package/dist/orchestration/workflow-types.js +6 -0
  508. package/dist/orchestration/workflow.d.ts +5 -13
  509. package/dist/orchestration/workflow.js +57 -49
  510. package/dist/prompt-assembly/artifact.d.ts +2 -2
  511. package/dist/prompt-assembly/artifact.js +5 -3
  512. package/dist/prompt-assembly/assemble.d.ts +3 -2
  513. package/dist/prompt-assembly/assemble.js +1 -1
  514. package/dist/prompt-assembly/catalog/schema.d.ts +43 -12
  515. package/dist/prompt-assembly/catalog/schema.js +34 -2
  516. package/dist/prompt-assembly/catalog/sections.js +0 -1
  517. package/dist/prompt-assembly/composer.d.ts +3 -1
  518. package/dist/prompt-assembly/composer.js +1 -1
  519. package/dist/prompt-assembly/event-registry.js +2 -0
  520. package/dist/prompt-assembly/overlay.js +3 -3
  521. package/dist/prompt-assembly/renderers.d.ts +1 -1
  522. package/dist/prompt-assembly/renderers.js +0 -3
  523. package/dist/prompt-assembly/role-base.d.ts +15 -0
  524. package/dist/prompt-assembly/role-base.js +9 -0
  525. package/dist/prompt-assembly/select.d.ts +39 -14
  526. package/dist/prompt-assembly/select.js +47 -16
  527. package/dist/prompt-assembly/sugar.d.ts +17 -11
  528. package/dist/prompt-assembly/sugar.js +8 -3
  529. package/dist/prompt-assembly/tool-catalog.d.ts +39 -2
  530. package/dist/prompt-assembly/tool-catalog.js +117 -4
  531. package/dist/prompt-assembly/turn-snapshot.d.ts +4 -10
  532. package/dist/prompt-assembly/turn-snapshot.js +0 -3
  533. package/dist/prompt-assembly/types.d.ts +0 -7
  534. package/dist/prompts/default.d.ts +14 -14
  535. package/dist/scenarios/full-body.d.ts +15 -15
  536. package/dist/scenarios/full-body.js +4 -3
  537. package/dist/shell/lex.js +10 -1
  538. package/dist/stores/file/adoption/adopt.d.ts +4 -3
  539. package/dist/stores/file/adoption/adopt.js +27 -33
  540. package/dist/stores/file/adoption/marker.d.ts +6 -13
  541. package/dist/stores/file/adoption/marker.js +9 -17
  542. package/dist/stores/file/checkpoint-store.d.ts +24 -0
  543. package/dist/stores/file/checkpoint-store.js +45 -7
  544. package/dist/stores/file/file-history-store.d.ts +20 -19
  545. package/dist/stores/file/file-history-store.js +157 -141
  546. package/dist/stores/file/fs-atomic.d.ts +15 -0
  547. package/dist/stores/file/fs-atomic.js +89 -14
  548. package/dist/stores/file/index.d.ts +1 -1
  549. package/dist/stores/file/index.js +2 -1
  550. package/dist/stores/file/mailbox-store.d.ts +3 -0
  551. package/dist/stores/file/mailbox-store.js +3 -1
  552. package/dist/stores/file/permission-rule-adopt.d.ts +1 -1
  553. package/dist/stores/file/permission-rule-adopt.js +18 -18
  554. package/dist/stores/file/permission-rule-store.d.ts +18 -2
  555. package/dist/stores/file/permission-rule-store.js +31 -18
  556. package/dist/stores/file/session-policy-store.d.ts +3 -3
  557. package/dist/stores/file/session-store.d.ts +54 -16
  558. package/dist/stores/file/session-store.js +114 -85
  559. package/dist/stores/file/workflow-journal-store.d.ts +10 -4
  560. package/dist/stores/file/workflow-journal-store.js +28 -13
  561. package/dist/tools/artifact/artifact-text.d.ts +1 -1
  562. package/dist/tools/artifact/artifact-tool.js +5 -3
  563. package/dist/tools/fs/bash-program-position.d.ts +19 -2
  564. package/dist/tools/fs/bash-program-position.js +56 -9
  565. package/dist/tools/fs/bash-readonly-classifier.d.ts +3 -3
  566. package/dist/tools/fs/fs-bash.d.ts +2 -2
  567. package/dist/tools/fs/fs-bash.js +8 -6
  568. package/dist/tools/fs/fs-glob.d.ts +86 -0
  569. package/dist/tools/fs/fs-glob.js +226 -0
  570. package/dist/tools/fs/fs-read.js +14 -14
  571. package/dist/tools/fs/fs-search-tools.js +7 -7
  572. package/dist/tools/fs/fs-shared.d.ts +8 -8
  573. package/dist/tools/fs/gh-rate-limit.d.ts +1 -1
  574. package/dist/tools/fs/notebook.d.ts +2 -2
  575. package/dist/tools/fs/pattern-kill-guard.d.ts +22 -0
  576. package/dist/tools/fs/pattern-kill-guard.js +397 -0
  577. package/dist/tools/fs/pdf.d.ts +9 -6
  578. package/dist/tools/fs/pdf.js +3 -3
  579. package/dist/tools/fs/program-read-model.d.ts +57 -7
  580. package/dist/tools/fs/program-read-model.js +11 -1
  581. package/dist/tools/fs/program-read-model.rows.js +78 -21
  582. package/dist/tools/fs/read-deny-home.js +3 -2
  583. package/dist/tools/fs/read-deny.d.ts +29 -7
  584. package/dist/tools/fs/read-deny.js +63 -22
  585. package/dist/tools/fs/removal-targets.d.ts +18 -8
  586. package/dist/tools/fs/removal-targets.js +47 -20
  587. package/dist/tools/fs/safety.d.ts +9 -9
  588. package/dist/tools/fs/search.d.ts +16 -6
  589. package/dist/tools/fs/search.js +20 -26
  590. package/dist/tools/fs/shell-read-argv.js +89 -12
  591. package/dist/tools/fs/shell-read-bindings.d.ts +31 -0
  592. package/dist/tools/fs/shell-read-bindings.js +41 -0
  593. package/dist/tools/fs/shell-read-check.js +12 -20
  594. package/dist/tools/fs/shell-read-environment.d.ts +5 -1
  595. package/dist/tools/fs/shell-read-environment.js +3 -2
  596. package/dist/tools/fs/shell-read-establish.d.ts +15 -0
  597. package/dist/tools/fs/shell-read-establish.js +19 -20
  598. package/dist/tools/fs/shell-read-judge.d.ts +4 -0
  599. package/dist/tools/fs/shell-read-judge.js +5 -2
  600. package/dist/tools/fs/shell-read-plan.js +24 -16
  601. package/dist/tools/fs/shell-read-start.d.ts +6 -1
  602. package/dist/tools/fs/shell-read-write-targets.d.ts +5 -1
  603. package/dist/tools/fs/shell-read-write-targets.js +2 -3
  604. package/dist/tools/fs/shell-reentry-text.d.ts +9 -0
  605. package/dist/tools/fs/shell-reentry-text.js +40 -2
  606. package/dist/tools/loop-tick.d.ts +2 -2
  607. package/dist/tools/scheduler-tools.js +5 -1
  608. package/dist/tools/task-list.d.ts +7 -7
  609. package/dist/tools/task-list.js +5 -1
  610. package/dist/tools/todo.js +65 -64
  611. package/dist/tools/web.d.ts +20 -15
  612. package/dist/tools/web.js +55 -69
  613. package/dist/tools/worktree.d.ts +3 -3
  614. package/dist/tools/worktree.js +3 -1
  615. package/package.json +1 -1
  616. package/test/export-surface.snapshot.json +5894 -5638
  617. package/wire-changes/core@7.55.0.json +3318 -0
  618. package/wire-changes/core@7.56.0.json +3891 -0
  619. package/wire-changes/mods-kernel@7.56.0.json +303 -0
  620. package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +0 -39
  621. package/dist/core/store-contracts/session-store-incarnation-contract.js +0 -95
package/dist/core/mcp.js CHANGED
@@ -2,15 +2,18 @@ import { egressText } from "./untrusted-egress.js";
2
2
  import { __resetEnvKnobAnnouncements } from "./env-knob-announce.js";
3
3
  import { resolveEnvBudget } from "./env-budget.js";
4
4
  import { MCP_NAMESPACE } from "./protocol-table.js";
5
- import { resolveProtocolHttpHeaders } from "./protocol-http-auth.js";
5
+ import { declaredHeaderValues, resolveProtocolHttpHeaders, scrubRequestEcho } from "./protocol-http-auth.js";
6
6
  import { disposeSectionEntry, sectionAnswerWarning } from "./prompt-section-seat.js";
7
7
  import { findNamespacePrefixCollision, mintNamespacePrefix, mintNamespacedToolName, normalizeNameSegment } from "./protocol-naming.js";
8
8
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
9
9
  import { McpConnectionPool } from "./mcp-connection-pool.js";
10
+ import { SessionEndingTransport, requestSite } from "./mcp-session-end.js";
11
+ import { mcpToolGate, UNPROVEN_GATE } from "./mcp-listing-drift.js";
12
+ import { ConnectionListing, Flights, IDLE_WATCHDOG_ABORT_REASON, Resendable, armMcpIdleWatchdog, callThroughLink, listingRefusal } from "./mcp-server-link.js";
13
+ import { underStartupBound } from "./mcp-startup-request.js";
10
14
  import { LIST_MCP_RESOURCES, MCP_RESOURCE_LIST_ALLOW, MCP_RESOURCE_READ_ALLOW, READ_MCP_RESOURCE, READ_MCP_RESOURCE_DIR, retractInstructions, tellInstructions, toldOnDial, unretractInstructions, withdrawInstructionAdds } from "./mounted-mcp.js";
11
15
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
12
- import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
13
- import { classifyMcpFailure, describeHttpTransportFailure, livenessOf } from "./mcp-failure.js";
16
+ import { classifyMcpFailure, describeHttpTransportFailure, livenessOf, namingLostSession, sessionGone } from "./mcp-failure.js";
14
17
  import { lstat, mkdir, writeFile } from "node:fs/promises";
15
18
  import { tmpdir } from "node:os";
16
19
  import { join } from "node:path";
@@ -19,6 +22,7 @@ import { DEFAULT_REQUEST_TIMEOUT_MSEC } from "@modelcontextprotocol/sdk/shared/p
19
22
  import { MCP_IMAGE_MAX_BASE64, sharpImageResizer } from "./image-downsample.js";
20
23
  import { sliceHeadSafe, sliceTailSafe } from "./surrogate-safe-slice.js";
21
24
  import { truncateError } from "./tool-errors.js";
25
+ import { peerRequestRefusal } from "./host-floor.js";
22
26
  import { delimitUntrusted, inlineUntrusted, sanitizeUntrustedText } from "./untrusted-text.js";
23
27
  import { discloseReminderShaped, observeReminderMarkEcho } from "./reminder-disclosure.js";
24
28
  import { MARKED_BLOCK_AFTER_DATA } from "./reminder-mint.js";
@@ -128,33 +132,6 @@ export function mcpIdleTimeoutMs(kind) {
128
132
  function idleKindOf(kind) {
129
133
  return kind === "stdio" ? "stdio" : "http";
130
134
  }
131
- const IDLE_WATCHDOG_ABORT_REASON = Symbol("mcp-idle-watchdog-abort");
132
- function armMcpIdleWatchdog(health, idleMs, outerSignal) {
133
- const idleController = new AbortController();
134
- let timer;
135
- const rearm = () => {
136
- if (timer !== undefined)
137
- clearTimeout(timer);
138
- const armedAt = Date.now();
139
- timer = setTimeout(() => {
140
- if (health.pendingElicitations > 0 || health.lastElicitationClosedAt > armedAt) {
141
- rearm();
142
- return;
143
- }
144
- idleController.abort(IDLE_WATCHDOG_ABORT_REASON);
145
- }, idleMs);
146
- };
147
- rearm();
148
- return {
149
- combinedSignal: outerSignal !== undefined ? AbortSignal.any([outerSignal, idleController.signal]) : idleController.signal,
150
- idleSignal: idleController.signal,
151
- rearm,
152
- dispose: () => {
153
- if (timer !== undefined)
154
- clearTimeout(timer);
155
- },
156
- };
157
- }
158
135
  export function mcpStartupTimeoutMs(server) {
159
136
  const fromEnv = parseEnvMs("MCP_TIMEOUT");
160
137
  const own = server?.startupTimeoutMs;
@@ -185,21 +162,24 @@ export function collapseMcpErrorPrefix(message) {
185
162
  out = out.slice(m[0].length);
186
163
  }
187
164
  }
188
- function sanitizeMcpErrorTextInPlace(err) {
165
+ function sanitizeMcpErrorTextInPlace(err, declared) {
189
166
  if (!(err instanceof Error))
190
167
  return;
191
- const sanitized = egressText("same-principal", err instanceof McpError ? collapseMcpErrorPrefix(err.message) : err.message);
168
+ const sanitized = mcpRemoteText(err instanceof McpError ? collapseMcpErrorPrefix(err.message) : err.message, declared);
192
169
  if (sanitized !== err.message)
193
170
  err.message = sanitized;
194
171
  }
195
- function namedMcpFailureText(err) {
196
- const detail = remoteErrorText(err, { collapse: true });
172
+ function namedMcpFailureText(err, declared) {
173
+ const detail = remoteErrorText(err, declared, { collapse: true });
197
174
  const condition = thrownIs(err, McpError) ? describeMcpSpecErrorCode(readMember(err, "code")) : undefined;
198
175
  return condition !== undefined ? `${condition}: ${detail}` : detail;
199
176
  }
200
- function remoteErrorText(err, opts) {
177
+ function remoteErrorText(err, declared, opts) {
201
178
  const raw = thrownText(err);
202
- return egressText("same-principal", opts?.collapse === true ? collapseMcpErrorPrefix(raw) : raw);
179
+ return mcpRemoteText(opts?.collapse === true ? collapseMcpErrorPrefix(raw) : raw, declared);
180
+ }
181
+ function mcpRemoteText(text, declared) {
182
+ return egressText("same-principal", scrubRequestEcho(text, declared));
203
183
  }
204
184
  function writeEffectWarning(writeEffect) {
205
185
  return writeEffect
@@ -218,7 +198,7 @@ function rethrowHonestMcpError(err, ctx) {
218
198
  }
219
199
  throw e;
220
200
  };
221
- sanitizeMcpErrorTextInPlace(err);
201
+ sanitizeMcpErrorTextInPlace(err, ctx.declared);
222
202
  if (ctx.idle?.signal.reason === IDLE_WATCHDOG_ABORT_REASON) {
223
203
  ctx.liveness?.observe?.("timeout");
224
204
  const serverLabel = inlineUntrusted(ctx.server);
@@ -231,7 +211,7 @@ function rethrowHonestMcpError(err, ctx) {
231
211
  finish(err);
232
212
  const serverLabel = inlineUntrusted(ctx.server);
233
213
  const fenceServerText = (label, raw) => delimitUntrusted(label, truncateMcpErrorText(raw));
234
- const failure = classifyMcpFailure(err, { phase: "request" });
214
+ const failure = classifyMcpFailure(err, ctx.site);
235
215
  ctx.liveness?.observe?.(failure.kind);
236
216
  const details = (extra) => ({ code: failure.kind, delivered: failure.delivered, server: ctx.server, ...extra });
237
217
  switch (failure.kind) {
@@ -248,12 +228,14 @@ function rethrowHonestMcpError(err, ctx) {
248
228
  case "not_mcp_response":
249
229
  case "connect_refused":
250
230
  case "connection_failed": {
251
- const httpFailure = describeHttpTransportFailure(err);
252
- const detail = remoteErrorText(err);
231
+ const httpFailure = describeHttpTransportFailure(err, ctx.site);
232
+ const detail = remoteErrorText(err, ctx.declared);
253
233
  const fenced = `\nThe transport error follows as external/untrusted data:\n${fenceServerText(`${ctx.server} transport error`, detail)}`;
254
- finish(markMcpFailure(new Error(failure.delivered === "no"
255
- ? `${ctx.what} could not reach MCP server "${serverLabel}": ${httpFailure.condition}. The request was not delivered, so the server did not execute it. This server's tools and resources will keep failing until its endpoint is reachable again — do not retry them; use an alternative if one exists.${fenced}`
256
- : `${ctx.what} failed at the transport layer of MCP server "${serverLabel}": ${httpFailure.condition}. The request may or may not have executed on the server — the outcome is unknown.${writeEffectWarning(ctx.writeEffect)}${fenced}`, { cause: err }), details(failure.httpStatus !== undefined ? { httpStatus: failure.httpStatus } : undefined)));
234
+ finish(markMcpFailure(new Error(sessionGone(err, ctx.site)
235
+ ? `${ctx.what} met a lost session on MCP server "${serverLabel}": ${httpFailure.condition}; ${ctx.resent === true ? "the call was sent again once on a fresh session, and the server reported that one gone too — if the server executed it before answering, it ran twice" : "the call was not sent again — if the server executed it before answering, it ran"}. The outcome is unknown.${writeEffectWarning(ctx.writeEffect)}${fenced}`
236
+ : failure.delivered === "no"
237
+ ? `${ctx.what} could not reach MCP server "${serverLabel}": ${httpFailure.condition}. The request was not delivered, so the server did not execute it. This server's tools and resources will keep failing until its endpoint is reachable again — do not retry them; use an alternative if one exists.${fenced}`
238
+ : `${ctx.what} failed at the transport layer of MCP server "${serverLabel}": ${httpFailure.condition}. The request may or may not have executed on the server — the outcome is unknown.${writeEffectWarning(ctx.writeEffect)}${fenced}`, { cause: err }), details(failure.httpStatus !== undefined ? { httpStatus: failure.httpStatus } : undefined)));
257
239
  }
258
240
  case "protocol": {
259
241
  const code = err.code;
@@ -262,7 +244,7 @@ function rethrowHonestMcpError(err, ctx) {
262
244
  finish(markMcpFailure(new Error(`${ctx.what} on MCP server "${serverLabel}" was rejected with MCP protocol error ${code} — ${condition}. The server's error text follows as external/untrusted data:\n${fenceServerText(`${ctx.server} error`, err.message)}`, { cause: err }), details({ specErrorCode: code })));
263
245
  }
264
246
  if (ctx.attributeServer) {
265
- finish(markMcpFailure(new Error(`${ctx.what} on MCP server "${serverLabel}" failed. The server's error text follows as external/untrusted data:\n${fenceServerText(`${ctx.server} error`, remoteErrorText(err))}`, { cause: err }), details()));
247
+ finish(markMcpFailure(new Error(`${ctx.what} on MCP server "${serverLabel}" failed. The server's error text follows as external/untrusted data:\n${fenceServerText(`${ctx.server} error`, remoteErrorText(err, ctx.declared))}`, { cause: err }), details()));
266
248
  }
267
249
  finish(markMcpFailure(err, details()));
268
250
  }
@@ -270,7 +252,7 @@ function rethrowHonestMcpError(err, ctx) {
270
252
  case "invalid_config":
271
253
  case "unknown": {
272
254
  if (ctx.attributeServer) {
273
- finish(markMcpFailure(new Error(`${ctx.what} on MCP server "${serverLabel}" failed. The server's error text follows as external/untrusted data:\n${fenceServerText(`${ctx.server} error`, remoteErrorText(err))}`, { cause: err }), details()));
255
+ finish(markMcpFailure(new Error(`${ctx.what} on MCP server "${serverLabel}" failed. The server's error text follows as external/untrusted data:\n${fenceServerText(`${ctx.server} error`, remoteErrorText(err, ctx.declared))}`, { cause: err }), details()));
274
256
  }
275
257
  if (err instanceof Error)
276
258
  finish(markMcpFailure(err, details()));
@@ -396,7 +378,7 @@ function buildTransport(spec, principal, kind) {
396
378
  if (!("url" in t))
397
379
  throw new Error(`MCP server "${spec.name}": transport kind "${String(kind)}" carries no url`);
398
380
  const headers = resolveProtocolHttpHeaders(MCP_NAMESPACE.id, t, principal);
399
- return new StreamableHTTPClientTransport(new URL(t.url), {
381
+ return new SessionEndingTransport(new URL(t.url), {
400
382
  requestInit: headers ? { headers } : undefined,
401
383
  fetch: declaredEndpointFetch,
402
384
  });
@@ -663,7 +645,7 @@ export function mcpToolSchemaProblem(schema) {
663
645
  }
664
646
  return undefined;
665
647
  }
666
- export async function materializeMcpTools(specs, principal, onElicit, imageResizer, reminderDisclosure, mcpRevocations, poolOpts, promptSections, dialable) {
648
+ export async function materializeMcpTools(specs, principal, onElicit, imageResizer, reminderDisclosure, mcpRevocations, poolOpts, promptSections, dialable, signal, hostFloor) {
667
649
  const snapshot = snapshotMcpEntries(specs);
668
650
  const axesRefused = new WeakMap();
669
651
  const entries = snapshot.map((spec) => {
@@ -722,11 +704,10 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
722
704
  const droppedTools = [];
723
705
  let disposing = false;
724
706
  const serverHandles = [];
725
- const redialsInFlight = new Set();
726
707
  const commitConnectedServer = (spec, s, transportKind) => {
727
708
  const raised = [];
728
709
  connections.push({ client: s.client, close: s.close });
729
- const handle = { name: spec.name, spec, client: s.client, openListing: s.openListing, health: s.health, tools: s.tools, listedRaw: s.listedTools, transportKind, announce: s.announce, instructions: s.instructions };
710
+ const handle = { name: spec.name, spec, client: s.client, openListing: s.openListing, health: s.health, tools: s.tools, listing: s.listing, gatesAt: s.gatesAt, gates: () => gatesNow(handle), transportKind, announce: s.announce, instructions: s.instructions };
730
711
  const hIdx = serverHandles.findIndex((h) => h.name === spec.name);
731
712
  if (hIdx === -1)
732
713
  serverHandles.push(handle);
@@ -786,11 +767,37 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
786
767
  }
787
768
  };
788
769
  const dialKinds = entries.map(readDialKind);
770
+ const liveOf = (server) => serverHandles.find((h) => h.name === server);
771
+ const gatesNow = (h) => {
772
+ const latest = h.listing.latest();
773
+ if (latest.at !== h.gatesAt.at)
774
+ h.gatesAt = { at: latest.at, gates: intakeListedTools({ tools: [...latest.entries], unproven: latest.unproven }, h.spec, linkOf(h.name), echoOf(h.spec), imageResizer, mcpDisclosure, isServerRevoked, h.transportKind).gates };
775
+ return h.gatesAt.gates;
776
+ };
777
+ const linkOf = (server) => ({
778
+ live: () => liveOf(server),
779
+ recover: (lost) => redialFlights.running(server) ?? (liveOf(server) === lost ? redialFlights.start(server, () => redialDial(server)) : Promise.resolve()),
780
+ });
781
+ const endpointRefusal = (spec, dialKind) => {
782
+ const transport = spec.transport;
783
+ const raw = dialKind !== "stdio" && typeof transport === "object" && transport !== null && "url" in transport ? transport.url : undefined;
784
+ let url;
785
+ try {
786
+ if (typeof raw !== "string")
787
+ return undefined;
788
+ url = new URL(raw);
789
+ }
790
+ catch {
791
+ return undefined;
792
+ }
793
+ return peerRequestRefusal(`mcp: server "${inlineUntrusted(spec.name, 120)}"`, url, hostFloor);
794
+ };
789
795
  const dialServer = (spec, dialKind, dialOpts) => {
790
- const refusal = axesRefused.get(spec);
791
- return refusal !== undefined ? Promise.reject(refusal) : connectServer(spec, principal, onElicit, imageResizer, mcpDisclosure, isServerRevoked, dialKind, poolOpts?.pool, dialOpts);
796
+ const refusal = axesRefused.get(spec) ?? endpointRefusal(spec, dialKind);
797
+ return refusal !== undefined ? Promise.reject(refusal) : connectServer(spec, principal, onElicit, imageResizer, mcpDisclosure, isServerRevoked, dialKind, poolOpts?.pool, { ...dialOpts, link: linkOf(spec.name), ...(signal !== undefined ? { signal } : {}) });
792
798
  };
793
799
  const prefixOf = (name) => mintNamespacePrefix(MCP_NAMESPACE, name);
800
+ const echoOf = (spec) => declaredHeaderValues(spec.transport, principal);
794
801
  const heldCount = (name) => serverHandles.find((h) => h.name === name)?.tools.length ?? 0;
795
802
  const reconcileInstructions = (name, after, connected) => {
796
803
  if (!connected)
@@ -820,10 +827,11 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
820
827
  commitConnectedServer(spec, s, dialKinds[i]);
821
828
  }
822
829
  else {
823
- warnings.push(asServerWarning(spec, r.reason));
830
+ const declared = echoOf(spec);
831
+ warnings.push(asServerWarning(spec, r.reason, declared));
824
832
  const { kind, delivered, httpStatus } = classifyMcpFailure(r.reason, { phase: "connect", transport: dialKinds[i] });
825
833
  const liveness = livenessOf(kind, Date.now());
826
- statuses.push({ name: spec.name, status: "failed", errorCode: kind, delivered, ...(httpStatus !== undefined ? { httpStatus } : {}), error: namedMcpFailureText(r.reason), ...(liveness !== undefined ? { liveness } : {}) });
834
+ statuses.push({ name: spec.name, status: "failed", errorCode: kind, delivered, ...(httpStatus !== undefined ? { httpStatus } : {}), error: namedMcpFailureText(r.reason, declared), ...(liveness !== undefined ? { liveness } : {}) });
827
835
  }
828
836
  }
829
837
  const resourceTools = buildResourceTools(resourceServers, isServerRevoked);
@@ -834,89 +842,89 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
834
842
  await Promise.allSettled(settled.map((r) => (r.status === "fulfilled" && r.value !== null ? r.value.close() : Promise.resolve())));
835
843
  throw mergeErr;
836
844
  }
837
- const redialOnce = async (server) => {
845
+ const declineRedial = (server, outcome, reason) => ({ server, prefix: prefixOf(server), outcome, reason, toolCount: heldCount(server), added: [], removed: [] });
846
+ const redialFlights = new Flights();
847
+ const ownerStopped = () => (disposing ? "this materialization is being disposed — the task is tearing down" : signal?.aborted === true ? "the run was aborted" : undefined);
848
+ const redialDial = async (server) => {
838
849
  const prefix = prefixOf(server);
839
- const declined = (outcome, reason) => ({ server, prefix, outcome, reason, toolCount: heldCount(server), added: [], removed: [] });
840
- if (disposing)
841
- return declined("refused", "this materialization is being disposed — the task is tearing down");
850
+ const declined = (outcome, reason) => declineRedial(server, outcome, reason);
851
+ const stopped = ownerStopped();
852
+ if (stopped !== undefined)
853
+ return declined("refused", stopped);
842
854
  const spec = entries.find((e) => e.name === server);
843
855
  if (spec === undefined)
844
856
  return declined("not_declared", `no MCP server named ${inlineUntrusted(server, 120)} is declared for this task`);
845
857
  if (isServerRevoked(server))
846
858
  return declined("refused", "server revoked by the operator — the re-dial did not contact it");
847
- if (redialsInFlight.has(server))
848
- return declined("refused", "a re-dial of this server is already in flight — wait for it to settle");
849
- redialsInFlight.add(server);
850
- try {
851
- const hIdx = serverHandles.findIndex((h) => h.name === server);
852
- const prior = hIdx === -1 ? undefined : serverHandles[hIdx];
853
- const priorNames = prior ? prior.tools.map((t) => t.name) : [];
854
- if (prior) {
855
- prior.announce.fn = undefined;
856
- prior.health.observe = undefined;
857
- serverHandles.splice(hIdx, 1);
858
- const cIdx = connections.findIndex((c) => c.client === prior.client);
859
- const priorConnection = cIdx === -1 ? undefined : connections.splice(cIdx, 1)[0];
860
- await (priorConnection?.close() ?? prior.client.close()).catch(() => undefined);
861
- }
862
- const dialKind = readDialKind(spec);
863
- let connected;
864
- try {
865
- connected = await dialServer(spec, dialKind, { fresh: true, sections: promptSections });
866
- }
867
- catch (err) {
868
- const { kind, delivered, httpStatus } = classifyMcpFailure(err, { phase: "connect", transport: dialKind });
869
- const redialLiveness = livenessOf(kind, Date.now());
870
- const status = { name: server, status: "failed", errorCode: kind, delivered, ...(httpStatus !== undefined ? { httpStatus } : {}), error: namedMcpFailureText(err), ...(redialLiveness !== undefined ? { liveness: redialLiveness } : {}) };
871
- const sIdx = statuses.findIndex((st) => st.name === server);
872
- if (sIdx === -1)
873
- statuses.push(status);
874
- else
875
- statuses[sIdx] = status;
876
- const raised = asServerWarning(spec, err);
877
- warnings.push(raised);
878
- reconcileInstructions(server, undefined, false);
879
- return {
880
- server,
881
- prefix,
882
- outcome: "refused",
883
- reason: inlineUntrusted(namedMcpFailureText(err), 240),
884
- toolCount: 0,
885
- added: [],
886
- removed: priorNames,
887
- tools: [],
888
- axes: [],
889
- dropped: [],
890
- warnings: [raised.message],
891
- status,
892
- };
893
- }
894
- if (disposing) {
895
- await connected.close().catch(() => undefined);
896
- return declined("refused", "this materialization was disposed while the re-dial was in flight — the new connection was closed");
897
- }
898
- const raised = commitConnectedServer(spec, connected, dialKind);
899
- reconcileInstructions(server, connected.instructions, true);
900
- const newNames = connected.tools.map((t) => t.name);
859
+ const hIdx = serverHandles.findIndex((h) => h.name === server);
860
+ const prior = hIdx === -1 ? undefined : serverHandles[hIdx];
861
+ const priorNames = prior ? prior.tools.map((t) => t.name) : [];
862
+ if (prior) {
863
+ prior.announce.fn = undefined;
864
+ prior.health.observe = undefined;
865
+ serverHandles.splice(hIdx, 1);
866
+ const cIdx = connections.findIndex((c) => c.client === prior.client);
867
+ const priorConnection = cIdx === -1 ? undefined : connections.splice(cIdx, 1)[0];
868
+ await (priorConnection?.close() ?? prior.client.close()).catch(() => undefined);
869
+ }
870
+ const dialKind = readDialKind(spec);
871
+ const dialed = await dialServer(spec, dialKind, { fresh: true, sections: promptSections, ...(prior !== undefined ? { carried: prior.listing.latest().entries } : {}) }).then((connected) => ({ connected }), (err) => ({ err }));
872
+ const stoppedLate = ownerStopped();
873
+ if (stoppedLate !== undefined) {
874
+ if ("connected" in dialed)
875
+ await dialed.connected.close().catch(() => undefined);
876
+ return declined("refused", `${stoppedLate} while the re-dial was in flight — nothing new was kept or recorded`);
877
+ }
878
+ if ("err" in dialed) {
879
+ const err = dialed.err;
880
+ const { kind, delivered, httpStatus } = classifyMcpFailure(err, { phase: "connect", transport: dialKind });
881
+ const redialLiveness = livenessOf(kind, Date.now());
882
+ const declared = echoOf(spec);
883
+ const failure = namedMcpFailureText(err, declared);
884
+ const status = { name: server, status: "failed", errorCode: kind, delivered, ...(httpStatus !== undefined ? { httpStatus } : {}), error: failure, ...(redialLiveness !== undefined ? { liveness: redialLiveness } : {}) };
885
+ const sIdx = statuses.findIndex((st) => st.name === server);
886
+ if (sIdx === -1)
887
+ statuses.push(status);
888
+ else
889
+ statuses[sIdx] = status;
890
+ const raised = asServerWarning(spec, err, declared);
891
+ warnings.push(raised);
892
+ reconcileInstructions(server, undefined, false);
901
893
  return {
902
894
  server,
903
895
  prefix,
904
- outcome: "reconnected",
905
- toolCount: newNames.length,
906
- added: newNames.filter((n) => !priorNames.includes(n)),
907
- removed: priorNames.filter((n) => !newNames.includes(n)),
908
- tools: connected.tools,
909
- axes: connected.axes,
910
- dropped: connected.dropped.map((d) => ({ server: inlineUntrusted(server, 160), ...d })),
911
- ...(raised.length > 0 ? { warnings: raised.map((w) => w.message) } : {}),
912
- status: connected.status,
913
- ...(connected.listingIncomplete !== undefined ? { listingIncomplete: connected.listingIncomplete } : {}),
896
+ outcome: "refused",
897
+ reason: inlineUntrusted(failure, 240),
898
+ toolCount: 0,
899
+ added: [],
900
+ removed: priorNames,
901
+ tools: [],
902
+ axes: [],
903
+ dropped: [],
904
+ warnings: [raised.message],
905
+ status,
914
906
  };
915
907
  }
916
- finally {
917
- redialsInFlight.delete(server);
918
- }
908
+ const { connected } = dialed;
909
+ const raised = commitConnectedServer(spec, connected, dialKind);
910
+ reconcileInstructions(server, connected.instructions, true);
911
+ const newNames = connected.tools.map((t) => t.name);
912
+ return {
913
+ server,
914
+ prefix,
915
+ outcome: "reconnected",
916
+ toolCount: newNames.length,
917
+ added: newNames.filter((n) => !priorNames.includes(n)),
918
+ removed: priorNames.filter((n) => !newNames.includes(n)),
919
+ tools: connected.tools,
920
+ axes: connected.axes,
921
+ dropped: connected.dropped.map((d) => ({ server: inlineUntrusted(server, 160), ...d })),
922
+ ...(raised.length > 0 ? { warnings: raised.map((w) => w.message) } : {}),
923
+ status: connected.status,
924
+ ...(connected.listingIncomplete !== undefined ? { listingIncomplete: connected.listingIncomplete } : {}),
925
+ };
919
926
  };
927
+ const redialOnce = (server) => (redialFlights.running(server) === undefined ? redialFlights.start(server, () => redialDial(server)) : Promise.resolve(declineRedial(server, "refused", "a re-dial of this server is already in flight — wait for it to settle")));
920
928
  return {
921
929
  tools,
922
930
  toolAxes,
@@ -940,20 +948,25 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
940
948
  results.push({ server: h.name, prefix: prefixOf(h.name), status: "revoked", toolCount: h.tools.length, added: [], removed: [], error: "server revoked by the operator — the refresh did not contact it" });
941
949
  continue;
942
950
  }
951
+ const site = requestSite(h.client);
943
952
  try {
953
+ const at = h.listing.open();
944
954
  const cacheTools = h.openListing();
945
- const listed = await listToolsLenient(h.client);
946
- const advertised = new Set(listed.tools.map((t) => t.name));
947
- const retainedRaw = listed.incomplete !== undefined ? h.listedRaw.filter((t) => !advertised.has(t.name)) : [];
948
- const mergedRaw = retainedRaw.length > 0 ? [...listed.tools, ...retainedRaw] : listed.tools;
949
- const { serverTools, serverAxes, dropped, accepted } = intakeListedTools({ tools: mergedRaw }, h.spec, h.client, h.health, imageResizer, mcpDisclosure, isServerRevoked, h.transportKind);
950
- cacheTools(accepted, new Set(retainedRaw.map((t) => t.name)));
955
+ const listed = await listToolsLenient(h.client, undefined, echoOf(h.spec));
956
+ const answered = h.listing.answer(at, listed.tools, listed.incomplete !== undefined);
957
+ const mergedRaw = answered.view;
958
+ if (!answered.recorded) {
959
+ results.push({ server: h.name, prefix: prefixOf(h.name), status: "failed", toolCount: h.tools.length, added: [], removed: [], error: "a later listing of this server was opened and applied while this one was in the air — this one was discarded" });
960
+ continue;
961
+ }
962
+ const { serverTools, serverAxes, gates, dropped, accepted } = intakeListedTools({ tools: [...mergedRaw], unproven: answered.unproven }, h.spec, linkOf(h.name), echoOf(h.spec), imageResizer, mcpDisclosure, isServerRevoked, h.transportKind);
963
+ cacheTools(accepted, answered.kept);
951
964
  const priorNames = h.tools.map((t) => t.name);
952
965
  const newNames = serverTools.map((t) => t.name);
953
966
  const added = newNames.filter((n) => !priorNames.includes(n));
954
967
  const removed = priorNames.filter((n) => !newNames.includes(n));
955
968
  h.tools = serverTools;
956
- h.listedRaw = mergedRaw;
969
+ h.gatesAt = { at, gates };
957
970
  results.push({
958
971
  server: h.name,
959
972
  prefix: prefixOf(h.name),
@@ -971,7 +984,7 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
971
984
  });
972
985
  }
973
986
  catch (err) {
974
- h.health.observe?.(classifyMcpFailure(err, { phase: "request" }).kind);
987
+ h.health.observe?.(classifyMcpFailure(err, site).kind);
975
988
  results.push({
976
989
  server: h.name,
977
990
  prefix: prefixOf(h.name),
@@ -979,7 +992,7 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
979
992
  toolCount: h.tools.length,
980
993
  added: [],
981
994
  removed: [],
982
- error: inlineUntrusted(namedMcpFailureText(err), 240),
995
+ error: inlineUntrusted(namingLostSession(err, site, namedMcpFailureText(err, echoOf(h.spec))), 240),
983
996
  });
984
997
  }
985
998
  }
@@ -1094,7 +1107,7 @@ export async function walkMcpListPages(fetchPage, opts) {
1094
1107
  catch (err) {
1095
1108
  if (pages === 0 || opts.signal?.aborted)
1096
1109
  throw err;
1097
- return { items, incomplete: { reason: "page_error", pages, error: remoteErrorText(err) } };
1110
+ return { items, incomplete: { reason: "page_error", pages, error: remoteErrorText(err, opts.declared ?? []) } };
1098
1111
  }
1099
1112
  opts.onPage?.();
1100
1113
  const pageStart = items.length;
@@ -1177,13 +1190,13 @@ async function readDirViaExtension(rs, uri, signal, timeoutMs, watchdog) {
1177
1190
  if (err instanceof McpError && err.code === ErrorCode.InvalidParams) {
1178
1191
  if (pages > 0)
1179
1192
  return { kind: "ok", resources, cursorInvalid: true };
1180
- const detail = remoteErrorText(err, { collapse: true });
1193
+ const detail = remoteErrorText(err, rs.declared, { collapse: true });
1181
1194
  return { kind: classifyDirReadInvalidParams(detail), detail };
1182
1195
  }
1183
1196
  if (err instanceof McpError && err.code === ErrorCode.MethodNotFound)
1184
1197
  return { kind: "unsupported" };
1185
1198
  if (pages > 0 && !signal?.aborted) {
1186
- return { kind: "ok", resources, incomplete: remoteErrorText(err) };
1199
+ return { kind: "ok", resources, incomplete: remoteErrorText(err, rs.declared) };
1187
1200
  }
1188
1201
  throw err;
1189
1202
  }
@@ -1266,6 +1279,7 @@ function buildResourceTools(resourceServers, isServerRevoked = () => false) {
1266
1279
  }
1267
1280
  const idleMs = mcpIdleTimeoutMs(rs.transportKind);
1268
1281
  const watchdog = armMcpIdleWatchdog(rs.health, idleMs, signal);
1282
+ const site = requestSite(rs.client);
1269
1283
  try {
1270
1284
  const walk = await walkMcpListPages(async (cursor, remainingMs) => {
1271
1285
  const page = await rs.client
@@ -1274,7 +1288,7 @@ function buildResourceTools(resourceServers, isServerRevoked = () => false) {
1274
1288
  throw watchdog.idleSignal.reason === IDLE_WATCHDOG_ABORT_REASON ? new Error(idleWatchdogTripText(idleMs)) : err;
1275
1289
  });
1276
1290
  return { items: page.resources, ...(page.nextCursor !== undefined ? { nextCursor: page.nextCursor } : {}) };
1277
- }, { budgetMs: mcpToolTimeoutMs(), onPage: () => watchdog.rearm(), fingerprintOf: listEntryFingerprint, ...(signal !== undefined ? { signal } : {}) });
1291
+ }, { budgetMs: mcpToolTimeoutMs(), onPage: () => watchdog.rearm(), fingerprintOf: listEntryFingerprint, declared: rs.declared, ...(signal !== undefined ? { signal } : {}) });
1278
1292
  all.push(...walk.items.map((r) => ({ server: rs.server, ...r })));
1279
1293
  const lines = walk.items.map((r) => resourceLine(r));
1280
1294
  const body = lines.length ? lines.join("\n") : "(no resources)";
@@ -1287,11 +1301,12 @@ function buildResourceTools(resourceServers, isServerRevoked = () => false) {
1287
1301
  }
1288
1302
  }
1289
1303
  catch (err) {
1304
+ sanitizeMcpErrorTextInPlace(err, rs.declared);
1290
1305
  if (signal?.aborted)
1291
1306
  throw err;
1292
1307
  const msg = watchdog.idleSignal.reason === IDLE_WATCHDOG_ABORT_REASON
1293
1308
  ? idleWatchdogTripText(idleMs)
1294
- : remoteErrorText(err);
1309
+ : namingLostSession(err, site, remoteErrorText(err, rs.declared));
1295
1310
  errors.push({ server: rs.server, error: msg });
1296
1311
  sections.push(`[${rs.server}] Error: could not list resources: ${inlineUntrusted(msg)}`);
1297
1312
  }
@@ -1345,11 +1360,12 @@ function buildResourceTools(resourceServers, isServerRevoked = () => false) {
1345
1360
  const timeoutMs = mcpToolTimeoutMs();
1346
1361
  const idleMs = mcpIdleTimeoutMs(rs.transportKind);
1347
1362
  const watchdog = armMcpIdleWatchdog(rs.health, idleMs, signal);
1363
+ const site = requestSite(rs.client);
1348
1364
  let res;
1349
1365
  try {
1350
1366
  res = await rs.client
1351
1367
  .readResource({ uri }, { signal: watchdog.combinedSignal, timeout: timeoutMs })
1352
- .catch((err) => rethrowHonestMcpError(err, { server, what, timeoutMs, writeEffect: false, signal, attributeServer: true, idle: { signal: watchdog.idleSignal, idleMs }, liveness: rs.health }));
1368
+ .catch((err) => rethrowHonestMcpError(err, { server, declared: rs.declared, what, timeoutMs, writeEffect: false, signal, attributeServer: true, site, idle: { signal: watchdog.idleSignal, idleMs }, liveness: rs.health }));
1353
1369
  rs.health.observe?.("completed");
1354
1370
  }
1355
1371
  finally {
@@ -1406,10 +1422,11 @@ function buildResourceTools(resourceServers, isServerRevoked = () => false) {
1406
1422
  const timeoutMs = mcpToolTimeoutMs();
1407
1423
  const idleMs = mcpIdleTimeoutMs(rs.transportKind);
1408
1424
  const watchdog = armMcpIdleWatchdog(rs.health, idleMs, signal);
1425
+ const site = requestSite(rs.client);
1409
1426
  try {
1410
1427
  const ext = rs.client.getServerCapabilities()?.extensions?.[MCP_SKILLS_EXTENSION];
1411
1428
  if (ext?.directoryRead === true) {
1412
- const r = await readDirViaExtension(rs, uri, signal, timeoutMs, watchdog).catch((err) => rethrowHonestMcpError(err, { server, what, timeoutMs, writeEffect: false, signal, attributeServer: true, idle: { signal: watchdog.idleSignal, idleMs }, liveness: rs.health }));
1429
+ const r = await readDirViaExtension(rs, uri, signal, timeoutMs, watchdog).catch((err) => rethrowHonestMcpError(err, { server, declared: rs.declared, what, timeoutMs, writeEffect: false, signal, attributeServer: true, site, idle: { signal: watchdog.idleSignal, idleMs }, liveness: rs.health }));
1413
1430
  const serverSaid = (detail) => `\nThe server's error text follows as external/untrusted data:\n${delimitUntrusted(`${server} error`, truncateMcpErrorText(detail))}`;
1414
1431
  if (r.kind === "not_found") {
1415
1432
  return {
@@ -1437,10 +1454,10 @@ function buildResourceTools(resourceServers, isServerRevoked = () => false) {
1437
1454
  const walk = await walkMcpListPages(async (cursor, remainingMs) => {
1438
1455
  const page = await rs.client
1439
1456
  .listResources(cursor === undefined ? undefined : { cursor }, { signal: watchdog.combinedSignal, timeout: remainingMs })
1440
- .catch((err) => rethrowHonestMcpError(err, { server, what, timeoutMs: remainingMs, writeEffect: false, signal, attributeServer: true, idle: { signal: watchdog.idleSignal, idleMs }, liveness: rs.health }));
1457
+ .catch((err) => rethrowHonestMcpError(err, { server, declared: rs.declared, what, timeoutMs: remainingMs, writeEffect: false, signal, attributeServer: true, site, idle: { signal: watchdog.idleSignal, idleMs }, liveness: rs.health }));
1441
1458
  rs.health.observe?.("completed");
1442
1459
  return { items: page.resources, ...(page.nextCursor !== undefined ? { nextCursor: page.nextCursor } : {}) };
1443
- }, { budgetMs: timeoutMs, onPage: () => watchdog.rearm(), fingerprintOf: listEntryFingerprint, ...(signal !== undefined ? { signal } : {}) });
1460
+ }, { budgetMs: timeoutMs, onPage: () => watchdog.rearm(), fingerprintOf: listEntryFingerprint, declared: rs.declared, ...(signal !== undefined ? { signal } : {}) });
1444
1461
  const dirPrefix = uri.endsWith("/") ? uri : `${uri}/`;
1445
1462
  const children = walk.items.filter((r) => typeof r.uri === "string" && r.uri !== uri && r.uri.startsWith(dirPrefix));
1446
1463
  return renderDirChildren(server, uri, children, walk.incomplete ? { listing: walk.incomplete } : undefined);
@@ -1505,7 +1522,7 @@ export function parseCallToolResultLenient(data) {
1505
1522
  return { success: true, data: { ...parsed.data, structuredContent } };
1506
1523
  }
1507
1524
  const LENIENT_CALL_TOOL_RESULT_SCHEMA = { safeParse: parseCallToolResultLenient };
1508
- async function listToolsLenient(client, options) {
1525
+ async function listToolsLenient(client, options, declared) {
1509
1526
  if (!client.getServerCapabilities()?.tools)
1510
1527
  return { tools: [], toolsCapabilityAbsent: true };
1511
1528
  const walk = await walkMcpListPages(async (cursor, remainingMs) => {
@@ -1518,6 +1535,7 @@ async function listToolsLenient(client, options) {
1518
1535
  }, {
1519
1536
  budgetMs: options?.timeout ?? DEFAULT_REQUEST_TIMEOUT_MSEC,
1520
1537
  fingerprintOf: listEntryFingerprint,
1538
+ declared,
1521
1539
  ...(options?.signal !== undefined ? { signal: options.signal } : {}),
1522
1540
  });
1523
1541
  return { tools: walk.items, ...(walk.incomplete !== undefined ? { incomplete: walk.incomplete } : {}) };
@@ -1532,7 +1550,8 @@ async function connectServer(spec, principal, onElicit, imageResizer, reminderDi
1532
1550
  const announce = {};
1533
1551
  const startupMs = mcpStartupTimeoutMs(spec);
1534
1552
  const startupOpts = startupMs !== undefined ? { timeout: startupMs } : undefined;
1535
- const dialClient = async () => {
1553
+ const dialClient = async (stop = dialOpts?.signal) => {
1554
+ stop?.throwIfAborted();
1536
1555
  const client = new Client({ name: `sema-core/${spec.name}`, version: "0.1.0" }, { capabilities: elicitOn ? { elicitation: { form: {} } } : {} });
1537
1556
  if (elicitOn) {
1538
1557
  client.setRequestHandler(ElicitRequestSchema, async (request, extra) => {
@@ -1555,12 +1574,17 @@ async function connectServer(spec, principal, onElicit, imageResizer, reminderDi
1555
1574
  });
1556
1575
  }
1557
1576
  const transport = buildTransport(spec, principal, transportKind);
1577
+ const hangUp = () => void client.close().catch(() => undefined);
1578
+ stop?.addEventListener("abort", hangUp, { once: true });
1558
1579
  try {
1559
1580
  await client.connect(transport, startupOpts);
1560
1581
  }
1561
1582
  catch (err) {
1562
1583
  await client.close().catch(() => undefined);
1563
- throw err;
1584
+ throw stop?.aborted === true ? stop.reason : err;
1585
+ }
1586
+ finally {
1587
+ stop?.removeEventListener("abort", hangUp);
1564
1588
  }
1565
1589
  return client;
1566
1590
  };
@@ -1580,10 +1604,14 @@ async function connectServer(spec, principal, onElicit, imageResizer, reminderDi
1580
1604
  lease.onClose(onClosed);
1581
1605
  else
1582
1606
  client.onclose = onClosed;
1607
+ const listing = lease?.listing ?? new ConnectionListing();
1608
+ const at = listing.open();
1583
1609
  const cacheTools = openListing();
1584
- const listed = await listToolsLenient(client, startupOpts);
1585
- const { serverTools, serverAxes, dropped, advisories, accepted } = intakeListedTools(listed, spec, client, health, imageResizer, reminderDisclosure, isServerRevoked, transportKind);
1586
- cacheTools(accepted);
1610
+ const declared = declaredHeaderValues(spec.transport, principal);
1611
+ const listed = await underStartupBound(startupMs, dialOpts?.signal, (options) => listToolsLenient(client, options, declared));
1612
+ const answered = listing.answer(at, listed.tools, listed.incomplete !== undefined, dialOpts.carried);
1613
+ const { serverTools, serverAxes, gates, dropped, advisories, accepted } = intakeListedTools({ tools: [...answered.view], unproven: answered.unproven }, spec, dialOpts.link, declared, imageResizer, reminderDisclosure, isServerRevoked, transportKind);
1614
+ cacheTools(accepted, answered.kept);
1587
1615
  const caps = client.getServerCapabilities();
1588
1616
  const resourceInfo = caps?.resources
1589
1617
  ? {
@@ -1612,14 +1640,15 @@ async function connectServer(spec, principal, onElicit, imageResizer, reminderDi
1612
1640
  announce,
1613
1641
  tools: serverTools,
1614
1642
  axes: serverAxes,
1643
+ listing,
1644
+ gatesAt: { at, gates },
1615
1645
  dropped,
1616
1646
  schemaAdvisories: advisories,
1617
1647
  ...(listed.toolsCapabilityAbsent === true ? { toolsCapabilityAbsent: true } : {}),
1618
- listedTools: listed.tools,
1619
1648
  ...(instructions ? { instructions } : {}),
1620
1649
  ...(disposed?.defect !== undefined ? { instructionsDefect: disposed.defect } : {}),
1621
1650
  ...(listed.incomplete !== undefined ? { listingIncomplete: listed.incomplete } : {}),
1622
- ...(resourceInfo && (resourceInfo.listAllowed || resourceInfo.readAllowed) ? { resourceServer: { server: spec.name, client, health, transportKind: idleKindOf(transportKind), ...resourceInfo } } : {}),
1651
+ ...(resourceInfo && (resourceInfo.listAllowed || resourceInfo.readAllowed) ? { resourceServer: { server: spec.name, client, health, transportKind: idleKindOf(transportKind), declared, ...resourceInfo } } : {}),
1623
1652
  };
1624
1653
  }
1625
1654
  catch (err) {
@@ -1627,10 +1656,11 @@ async function connectServer(spec, principal, onElicit, imageResizer, reminderDi
1627
1656
  throw err;
1628
1657
  }
1629
1658
  }
1630
- function intakeListedTools(listed, spec, client, health, imageResizer, reminderDisclosure, isServerRevoked, transportKind) {
1659
+ function intakeListedTools(listed, spec, link, declared, imageResizer, reminderDisclosure, isServerRevoked, transportKind) {
1631
1660
  const declaredContentOrigin = spec.contentOrigin;
1632
1661
  const serverTools = [];
1633
1662
  const serverAxes = [];
1663
+ const gates = new Map();
1634
1664
  const dropped = [];
1635
1665
  const accepted = [];
1636
1666
  const advisories = [];
@@ -1697,6 +1727,9 @@ function intakeListedTools(listed, spec, client, health, imageResizer, reminderD
1697
1727
  if (interaction.advisory !== undefined)
1698
1728
  advisories.push({ tool: inlineUntrusted(t.name), reason: interaction.advisory });
1699
1729
  const mcpAlwaysLoad = mcpToolMeta?.["anthropic/alwaysLoad"] === true;
1730
+ const gateFace = { ...(interaction.declared ? { mcpRequiresUserInteraction: true } : {}), ...(t.annotations?.readOnlyHint === true ? { mcpReadOnlyHint: true } : {}) };
1731
+ const gate = mcpToolGate(remoteName, axis, gateFace, taskRequired);
1732
+ gates.set(namespacedName, listed.unproven?.has(remoteName) === true ? UNPROVEN_GATE : gate);
1700
1733
  const mounted = {
1701
1734
  name: namespacedName,
1702
1735
  description: capMcpToolDescription(effectiveDescription ?? `MCP tool ${inlineUntrusted(sanitizeMcpModelFacingText(remoteName))} from ${spec.name}`),
@@ -1704,8 +1737,8 @@ function intakeListedTools(listed, spec, client, health, imageResizer, reminderD
1704
1737
  parameters: (effectiveInputSchema ?? { type: "object" }),
1705
1738
  ...(mcpMaxResultSizeChars !== undefined ? { mcpMaxResultSizeChars } : {}),
1706
1739
  ...(mcpAlwaysLoad ? { mcpAlwaysLoad: true } : {}),
1707
- ...(interaction.declared ? { mcpRequiresUserInteraction: true } : {}),
1708
- mcpRemoteName: remoteName, ...boundaryFlowFace(spec.toolAxes?.[remoteName]), ...(t.annotations?.readOnlyHint === true ? { mcpReadOnlyHint: true } : {}), permissionSeat: "passthrough",
1740
+ ...gateFace,
1741
+ mcpRemoteName: remoteName, ...boundaryFlowFace(spec.toolAxes?.[remoteName]), permissionSeat: "passthrough",
1709
1742
  execute: async (_toolCallId, params, signal) => {
1710
1743
  const what = `The call to tool ${inlineUntrusted(remoteName)}`;
1711
1744
  if (isServerRevoked?.(spec.name) === true) {
@@ -1724,38 +1757,56 @@ function intakeListedTools(listed, spec, client, health, imageResizer, reminderD
1724
1757
  isError: true,
1725
1758
  };
1726
1759
  }
1727
- if (health.dead)
1728
- throwDeadServer(spec.name, what);
1729
1760
  const timeoutMs = mcpToolTimeoutMs();
1730
1761
  const idleMs = mcpIdleTimeoutMs(idleKindOf(transportKind));
1731
- const watchdog = armMcpIdleWatchdog(health, idleMs, signal);
1732
- let res;
1733
- try {
1734
- res = await client
1735
- .callTool({ name: remoteName, arguments: (params ?? {}) }, LENIENT_CALL_TOOL_RESULT_SCHEMA, {
1736
- signal: watchdog.combinedSignal,
1737
- timeout: timeoutMs,
1738
- resetTimeoutOnProgress: true,
1739
- onprogress: () => watchdog.rearm(),
1740
- maxTotalTimeout: mcpToolTotalTimeoutMs(timeoutMs),
1741
- })
1742
- .catch((err) => rethrowHonestMcpError(err, {
1743
- server: spec.name,
1744
- what,
1745
- timeoutMs,
1746
- writeEffect,
1747
- signal,
1748
- idle: { signal: watchdog.idleSignal, idleMs },
1749
- liveness: health,
1750
- ...(reminderDisclosure !== undefined
1751
- ? { reminder: { mark: reminderDisclosure.mark, outlet: "mcp", ...(reminderDisclosure.counts !== undefined ? { counts: reminderDisclosure.counts } : {}) } }
1752
- : {}),
1753
- }));
1754
- health.observe?.("completed");
1755
- }
1756
- finally {
1757
- watchdog.dispose();
1758
- }
1762
+ const send = async (conn, resent) => {
1763
+ const site = requestSite(conn.client);
1764
+ const watchdog = armMcpIdleWatchdog(conn.health, idleMs, signal);
1765
+ try {
1766
+ const res = await conn.client
1767
+ .callTool({ name: remoteName, arguments: (params ?? {}) }, LENIENT_CALL_TOOL_RESULT_SCHEMA, {
1768
+ signal: watchdog.combinedSignal,
1769
+ timeout: timeoutMs,
1770
+ resetTimeoutOnProgress: true,
1771
+ onprogress: () => watchdog.rearm(),
1772
+ maxTotalTimeout: mcpToolTotalTimeoutMs(timeoutMs),
1773
+ })
1774
+ .catch((err) => {
1775
+ try {
1776
+ return rethrowHonestMcpError(err, {
1777
+ server: spec.name,
1778
+ declared,
1779
+ what,
1780
+ timeoutMs,
1781
+ writeEffect,
1782
+ signal,
1783
+ site,
1784
+ ...(resent ? { resent: true } : {}),
1785
+ idle: { signal: watchdog.idleSignal, idleMs },
1786
+ liveness: conn.health,
1787
+ ...(reminderDisclosure !== undefined
1788
+ ? { reminder: { mark: reminderDisclosure.mark, outlet: "mcp", ...(reminderDisclosure.counts !== undefined ? { counts: reminderDisclosure.counts } : {}) } }
1789
+ : {}),
1790
+ });
1791
+ }
1792
+ catch (failure) {
1793
+ if (sessionGone(err, site) && signal?.aborted !== true)
1794
+ return new Resendable(conn, failure);
1795
+ throw failure;
1796
+ }
1797
+ });
1798
+ if (res instanceof Resendable)
1799
+ return res;
1800
+ conn.health.observe?.("completed");
1801
+ return res;
1802
+ }
1803
+ finally {
1804
+ watchdog.dispose();
1805
+ }
1806
+ };
1807
+ const res = await callThroughLink(link, namespacedName, gate, signal, send, () => throwDeadServer(spec.name, what));
1808
+ if (typeof res === "string")
1809
+ return listingRefusal(res, remoteName, spec.name);
1759
1810
  const mapped = await mapContent(res.content, spec.name, imageResizer);
1760
1811
  if (res.isError === true) {
1761
1812
  const parts = [];
@@ -1768,7 +1819,7 @@ function intakeListedTools(listed, spec, client, health, imageResizer, reminderD
1768
1819
  const errScLine = structuredContentErrorLine(res.structuredContent, parts.join("\n"));
1769
1820
  if (errScLine !== undefined)
1770
1821
  parts.push(errScLine);
1771
- const body = truncateMcpErrorText(egressText("same-principal", parts.join("\n").trim()));
1822
+ const body = truncateMcpErrorText(mcpRemoteText(parts.join("\n").trim(), declared));
1772
1823
  const msg = body
1773
1824
  ? `MCP tool ${inlineUntrusted(remoteName)} reported an error. The server's error content follows as external/untrusted data:\n${delimitUntrusted(`${spec.name} tool error`, body)}`
1774
1825
  : `MCP tool ${inlineUntrusted(remoteName)} reported an error`;
@@ -1815,10 +1866,10 @@ function intakeListedTools(listed, spec, client, health, imageResizer, reminderD
1815
1866
  serverTools.push(declaredContentOrigin !== undefined ? withContentOrigin(mounted, declaredContentOrigin) : mounted);
1816
1867
  accepted.push(t);
1817
1868
  }
1818
- return { serverTools, serverAxes, dropped, advisories, accepted };
1869
+ return { serverTools, serverAxes, gates, dropped, advisories, accepted };
1819
1870
  }
1820
- function asServerWarning(spec, err) {
1821
- const warning = new Error(`mcp: server "${spec.name}" failed to connect — skipped (${namedMcpFailureText(err)})`, { cause: sanitizedCause(err) });
1871
+ function asServerWarning(spec, err, declared) {
1872
+ const warning = new Error(`mcp: server "${spec.name}" failed to connect — skipped (${namedMcpFailureText(err, declared)})`, { cause: sanitizedCause(err, declared) });
1822
1873
  warning.code = "mcp.server_unavailable";
1823
1874
  return warning;
1824
1875
  }
@@ -1843,8 +1894,8 @@ function dialDecision(dialable, spec) {
1843
1894
  }
1844
1895
  throw Object.assign(new Error(`MCP materialization refused: the dialable seat could not decide whether to dial server "${inlineUntrusted(spec.name, 120)}" — ${inlineUntrusted(why, 240)}. No server was dialed.`, cause), { code: "config.mcp_dialable_failed" });
1845
1896
  }
1846
- function sanitizedCause(err) {
1847
- const copy = new Error(namedMcpFailureText(err));
1897
+ function sanitizedCause(err, declared) {
1898
+ const copy = new Error(namedMcpFailureText(err, declared));
1848
1899
  const name = thrownName(err);
1849
1900
  if (name !== undefined) {
1850
1901
  if (name !== "")