@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
@@ -0,0 +1,206 @@
1
+ import { isIP } from "node:net";
2
+ import { HOST_UNREADABLE_SENTENCE, callHostTargetOf, hostOfUrl, hostPatternAdmits, readHostPattern, spelledHostPattern } from "./host-target.js";
3
+ import { inlineUntrusted } from "./untrusted-text.js";
4
+ import { describeFault, isPlainRecord, receive } from "./mods/kernel/receive.js";
5
+ import { DECLARATION_RECEIPT_MODE } from "./own-property-receipt.js";
6
+ function isPrivateV4(ip) {
7
+ const o = ip.split(".").map(Number);
8
+ if (o.length !== 4 || o.some((n) => !Number.isInteger(n) || n < 0 || n > 255))
9
+ return true;
10
+ const [a = -1, b = -1] = o;
11
+ return (a === 127 ||
12
+ a === 10 ||
13
+ a === 0 ||
14
+ (a === 172 && b >= 16 && b <= 31) ||
15
+ (a === 192 && b === 168) ||
16
+ (a === 169 && b === 254) ||
17
+ (a === 100 && b >= 64 && b <= 127));
18
+ }
19
+ function embeddedV4(h) {
20
+ const fromHex = (hi, lo) => {
21
+ const a = parseInt(hi, 16), c = parseInt(lo, 16);
22
+ return `${(a >> 8) & 255}.${a & 255}.${(c >> 8) & 255}.${c & 255}`;
23
+ };
24
+ let m = /^(?:::ffff:|64:ff9b::)(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/.exec(h);
25
+ if (m)
26
+ return m[1];
27
+ m = /^(?:::ffff:|64:ff9b::)([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(h);
28
+ const [, hi, lo] = m ?? [];
29
+ return hi !== undefined && lo !== undefined ? fromHex(hi, lo) : undefined;
30
+ }
31
+ export function isPrivateHost(host) {
32
+ const h = host
33
+ .replace(/^\[|\]$/g, "")
34
+ .replace(/\.+$/, "")
35
+ .toLowerCase();
36
+ if (h === "localhost")
37
+ return true;
38
+ const fam = isIP(h);
39
+ if (fam === 0)
40
+ return false;
41
+ if (fam === 4)
42
+ return isPrivateV4(h);
43
+ const v4 = embeddedV4(h);
44
+ if (v4)
45
+ return isPrivateV4(v4);
46
+ if (h === "::1" || h === "::")
47
+ return true;
48
+ return /^fe[89ab]/.test(h) || /^f[cd]/.test(h) || /^fe[c-f]/.test(h);
49
+ }
50
+ export const HOST_FLOOR_INVALID_CODE = "config.host_floor_invalid";
51
+ const FLOOR_MEMBERS = ["deny", "only"];
52
+ function floorInvalid(what) {
53
+ return Object.assign(new Error(`RunnerDeps.hostFloor ${what} — a host floor that does not read is refused whole, never half-armed (an entry is a host pattern: \`example.com\` or \`*.example.com\`).`), { code: HOST_FLOOR_INVALID_CODE });
54
+ }
55
+ function readEntries(value, member) {
56
+ if (value === undefined)
57
+ return undefined;
58
+ if (!Array.isArray(value))
59
+ throw floorInvalid(`.${member} must be a list of host patterns (got ${value === null ? "null" : typeof value})`);
60
+ const list = value;
61
+ const patterns = [];
62
+ for (let i = 0; i < list.length; i++) {
63
+ const entry = list[i];
64
+ if (typeof entry !== "string")
65
+ throw floorInvalid(`.${member}[${i}] must be a string (got ${entry === null ? "null" : typeof entry})`);
66
+ const read = readHostPattern(entry);
67
+ if ("problem" in read) {
68
+ const why = read.problem === "every_host" ? "names every host"
69
+ : read.problem === "inner_wildcard" ? "carries a `*` other than a leading `*.`"
70
+ : read.problem === "below_address" ? "names hosts below an address, which has none"
71
+ : read.problem === "empty_label" ? "names a host with an empty label (a leading or doubled dot) — write the host itself, and every host below a domain as `*.<domain>`"
72
+ : "is more or less than a host (a scheme, a port, a path, credentials or whitespace)";
73
+ throw floorInvalid(`.${member}[${i}] "${inlineUntrusted(entry, 120)}" ${why}`);
74
+ }
75
+ patterns.push(read.pattern);
76
+ }
77
+ return patterns;
78
+ }
79
+ function covers(d, o) {
80
+ if (d.match === "host")
81
+ return o.match === "host" && o.host === d.host;
82
+ return o.host === d.host ? o.match === "subdomain" : hostPatternAdmits(d, o.host);
83
+ }
84
+ export function receiveHostFloor(declared) {
85
+ if (declared === undefined)
86
+ return undefined;
87
+ const received = receive(declared, DECLARATION_RECEIPT_MODE);
88
+ if (!received.ok)
89
+ throw floorInvalid(`could not be read as plain data — ${describeFault(received.fault)}`);
90
+ return received.value;
91
+ }
92
+ export function compileHostFloor(declared) {
93
+ const value = receiveHostFloor(declared);
94
+ if (value === undefined)
95
+ return undefined;
96
+ if (!isPlainRecord(value))
97
+ throw floorInvalid(`must be a record { deny?, only? } (got ${value === null ? "null" : Array.isArray(value) ? "a list" : typeof value})`);
98
+ const unknownMember = Object.keys(value).find((k) => !FLOOR_MEMBERS.includes(k));
99
+ if (unknownMember !== undefined)
100
+ throw floorInvalid(`has a member "${inlineUntrusted(unknownMember, 60)}" — its members are \`deny\` and \`only\``);
101
+ const deny = readEntries(value.deny, "deny") ?? [];
102
+ const only = readEntries(value.only, "only");
103
+ for (const o of only ?? []) {
104
+ const d = deny.find((candidate) => covers(candidate, o));
105
+ if (d !== undefined)
106
+ throw floorInvalid(`.only entry "${spelledHostPattern(o)}" is wholly denied by the .deny entry "${spelledHostPattern(d)}" — it could never admit a host`);
107
+ }
108
+ const reach = (host) => deny.some((d) => hostPatternAdmits(d, host)) ? "denied" : only !== undefined && !only.some((o) => hostPatternAdmits(o, host)) ? "outside_only" : "admitted";
109
+ return Object.freeze({
110
+ entries: Object.freeze({ deny: Object.freeze(deny.map(spelledHostPattern)), ...(only !== undefined ? { only: Object.freeze(only.map(spelledHostPattern)) } : {}) }),
111
+ posture: Object.freeze({ onlyMode: only !== undefined, denyCount: deny.length, onlyCount: only?.length ?? 0 }),
112
+ reach,
113
+ lifts: (host) => only !== undefined && reach(host) === "admitted",
114
+ });
115
+ }
116
+ export function floorRefusal(reading, floor) {
117
+ if ("unreadable" in reading)
118
+ return `${HOST_UNREADABLE_SENTENCE[reading.unreadable]}, and this deployment's host floor admits only a host it can read`;
119
+ const reach = floor.reach(reading.host);
120
+ if (reach === "admitted")
121
+ return undefined;
122
+ const host = inlineUntrusted(reading.host, 253);
123
+ return reach === "denied" ? `host "${host}" is denied by this deployment's host floor (hostFloor.deny)` : `host "${host}" is outside the hosts this deployment reaches (hostFloor.only)`;
124
+ }
125
+ export function hostFloorPolicy(floor) {
126
+ return {
127
+ check: (req) => {
128
+ const reading = callHostTargetOf(req, "tighten");
129
+ const refused = reading === undefined ? undefined : floorRefusal(reading, floor);
130
+ return refused === undefined ? { action: "allow" } : { action: "deny", message: `${refused} — no rule, mode or approval clears the deployment's host floor`, decisionReason: "rule" };
131
+ },
132
+ };
133
+ }
134
+ export function hopRefusal(url, floor, privateFloor) {
135
+ if (url.protocol !== "http:" && url.protocol !== "https:")
136
+ return `a non-http(s) URL (${inlineUntrusted(url.protocol, 40)}) was refused`;
137
+ const reading = hostOfUrl(url.toString());
138
+ if ("unreadable" in reading)
139
+ return `${HOST_UNREADABLE_SENTENCE[reading.unreadable]}; refused`;
140
+ const floored = floor !== undefined ? floorRefusal(reading, floor) : undefined;
141
+ if (floored !== undefined)
142
+ return `${floored}; refused`;
143
+ if (privateFloor && isPrivateHost(reading.host) && floor?.lifts(reading.host) !== true) {
144
+ return `host "${inlineUntrusted(reading.host, 253)}" is private/internal; refused (SSRF guard — reachable only when this deployment's hostFloor.only names it)`;
145
+ }
146
+ return undefined;
147
+ }
148
+ export const HOST_FLOOR_REFUSED_CODE = "config.host_floor_refused";
149
+ export function peerRequestRefusal(what, url, floor) {
150
+ const reason = hopRefusal(url, floor, false);
151
+ return reason === undefined ? undefined : Object.assign(new Error(`${what} is not contacted — ${reason}`), { code: HOST_FLOOR_REFUSED_CODE });
152
+ }
153
+ const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);
154
+ function release(res) {
155
+ const body = res.body;
156
+ if (typeof body?.cancel === "function")
157
+ void body.cancel().catch(() => undefined);
158
+ }
159
+ function followedInit(status, init) {
160
+ if (!(status === 303 || ((status === 301 || status === 302) && init.method === "POST")) || init.method === "GET" || init.method === "HEAD")
161
+ return init;
162
+ const BODY_HEADERS = ["content-type", "content-encoding", "content-language", "content-location", "content-length"];
163
+ const headers = Object.fromEntries(Object.entries(init.headers).filter(([k]) => !BODY_HEADERS.includes(k.toLowerCase())));
164
+ return { method: "GET", headers, ...(init.signal !== undefined ? { signal: init.signal } : {}) };
165
+ }
166
+ export async function fetchFollowing(doFetch, start, init, law) {
167
+ let current = start;
168
+ let hopInit = init;
169
+ for (let hop = 0; hop <= law.maxRedirects; hop++) {
170
+ const refused = law.refusal(current);
171
+ if (refused !== undefined)
172
+ return { kind: "refused", reason: refused };
173
+ const res = await doFetch(current.toString(), {
174
+ method: hopInit.method,
175
+ headers: hopInit.headers,
176
+ redirect: "manual",
177
+ ...(hopInit.body !== undefined ? { body: hopInit.body } : {}),
178
+ ...(hopInit.signal !== undefined ? { signal: hopInit.signal } : {}),
179
+ });
180
+ law.onResponse?.(res);
181
+ if (!REDIRECT_STATUSES.has(res.status))
182
+ return { kind: "answered", res };
183
+ const location = res.headers.get("location");
184
+ if (!location)
185
+ return { kind: "answered", res };
186
+ let next;
187
+ try {
188
+ next = new URL(location, current);
189
+ }
190
+ catch {
191
+ release(res);
192
+ return { kind: "refused", reason: `invalid redirect Location: ${inlineUntrusted(location, 200)}` };
193
+ }
194
+ const nextRefused = law.refusal(next);
195
+ if (nextRefused !== undefined) {
196
+ release(res);
197
+ return { kind: "refused", reason: nextRefused };
198
+ }
199
+ if (!law.follows(current, next))
200
+ return { kind: "unfollowed", res, from: current, to: next };
201
+ release(res);
202
+ hopInit = followedInit(res.status, hopInit);
203
+ current = next;
204
+ }
205
+ return { kind: "too_many" };
206
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * The HOST vocabulary, one home for how a host is spelled and read:
3
+ * · {@link hostOfSpelling} — the RULE side: the host a `<Tool>(domain:<host>)` rule names;
4
+ * · {@link hostOfUrl} — the CALL side: the host a URL names, which every host-rule judge reads as the call's subject and the
5
+ * engine's fetch tool reads as the host it connects to (one reading, two readers);
6
+ * · {@link callHostTargetOf} — which argument of a call carries that URL: the host face's protective and declared readings.
7
+ * Both sides go through the URL parser (lower case, IDN in its ASCII form, a full-width dot folded, an IPv4 shorthand expanded)
8
+ * and read trailing dots off; a call's host that does not read back as itself through the rule side's reader names no host a rule
9
+ * can be judged on, so a rule and a call that name one host always name it in one spelling.
10
+ *
11
+ * Leaf module: it reads the catalog's host slots (the protective floor) and the name-reading seat, nothing else.
12
+ */
13
+ import { type ToolCallLike } from "./tool-registry.js";
14
+ /**
15
+ * THE reading of a host's spelling: the host as the URL parser reads it (lower case, IDN in its ASCII form, a full-width dot
16
+ * folded, an IPv4 shorthand expanded, trailing dots read off), or why it names none — `empty_label` for a name with an empty
17
+ * label once its trailing dots are read off (`.evil.test`, `a..test`: no host has one, and nothing a rule or a floor entry is
18
+ * matched against ever does), `not_a_host` for a spelling that is more or less than a host (empty, carrying whitespace or a
19
+ * separator a URL reads as something else, a port — a `:` outside an address's brackets —, credentials, a path).
20
+ */
21
+ export declare function readSpelledHost(spelled: string): {
22
+ readonly host: string;
23
+ } | {
24
+ readonly problem: "empty_label" | "not_a_host";
25
+ };
26
+ /** The host a spelling names ({@link readSpelledHost}), or undefined when it names none. */
27
+ export declare function hostOfSpelling(spelled: string): string | undefined;
28
+ /** Is this host (as {@link hostOfUrl} reads it) an address — the URL parser's IPv4 form or a bracketed IPv6? */
29
+ export declare function isAddressHost(host: string): boolean;
30
+ /** A host pattern: one exact host (`host`), or every host BELOW a domain at any depth, never the domain itself (`subdomain`). */
31
+ export interface HostPattern {
32
+ readonly match: "host" | "subdomain";
33
+ readonly host: string;
34
+ }
35
+ /** Why a spelling is no host pattern: `*` alone (every host), a `*` other than a leading `*.`, a host with an empty label (a
36
+ * leading or doubled dot — "this domain and every host below" is two patterns, `example.com` and `*.example.com`), more or less
37
+ * than a host, a `*.` over an address (an address has no subdomains). */
38
+ export type HostPatternProblem = "every_host" | "inner_wildcard" | "empty_label" | "not_a_host" | "below_address";
39
+ /**
40
+ * THE reader of a host pattern's spelling — `example.com` or `*.example.com` — for every place one is written: the content of a
41
+ * `<Tool>(domain:<pattern>)` rule and an entry of the deployment's host floor. The `*.` operator is the spelling's leading two
42
+ * characters; the host after it is read by {@link readSpelledHost}, must hold no `*` as read (a full-width or small asterisk the
43
+ * parser folds included) and must read back as itself; each caller words its own refusal from the problem.
44
+ */
45
+ export declare function readHostPattern(spelled: string): {
46
+ readonly pattern: HostPattern;
47
+ } | {
48
+ readonly problem: HostPatternProblem;
49
+ };
50
+ /** A pattern as it is written back: the host, or `*.` and the domain. */
51
+ export declare function spelledHostPattern(pattern: HostPattern): string;
52
+ /** Does the pattern reach this host (as {@link hostOfUrl} reads it)? `host`: equal; `subdomain`: a name ending in `.<domain>` with
53
+ * at least one label before it and no empty label. */
54
+ export declare function hostPatternAdmits(pattern: HostPattern, host: string): boolean;
55
+ /** Why a URL names no host a rule can be judged on — the closed set the fetch tool maps to its own refusal sentences:
56
+ * not a string; not a URL; not http(s); credentials in it; a host that does not read back as itself once its trailing dots
57
+ * are read off (`https://2130706433../` — the parser keeps the name, the rule side reads `127.0.0.1`). */
58
+ export declare const HOST_UNREADABLE_REASONS: readonly ["not_text", "not_url", "not_http", "credentials", "unstable"];
59
+ export type HostUnreadableReason = (typeof HOST_UNREADABLE_REASONS)[number];
60
+ /** The host a URL names, or why it names none. */
61
+ export type HostReading = {
62
+ readonly host: string;
63
+ } | {
64
+ readonly unreadable: HostUnreadableReason;
65
+ };
66
+ /** The words a refusal states for each unreadable reason. */
67
+ export declare const HOST_UNREADABLE_SENTENCE: Readonly<Record<HostUnreadableReason, string>>;
68
+ /** THE call-side reading of a URL: the host it names (lower case, IDN in its ASCII form, trailing dots read off), or why it
69
+ * names none ({@link HostUnreadableReason}). */
70
+ export declare function hostOfUrl(value: unknown): HostReading;
71
+ /** Which reading a judge takes: `tighten` for a deny, an ask and the unreadable law; `grant` for an allow. */
72
+ export type HostReadingDirection = "tighten" | "grant";
73
+ /**
74
+ * The host a call reaches as every host-rule judge reads it — the rule policy's host lane, a person's stored rows, the entry
75
+ * lists, the approval card's offer — or undefined when the call has no URL slot in that direction:
76
+ * · `tighten` — the PROTECTIVE reading: the call face's own slot, else the catalog's slot under the first name the call
77
+ * answers to that declares one (a bare request, or a face that declares none). Borrowing a slot can only add a host to
78
+ * judge, so a deny or an ask keeps reaching a same-name tool;
79
+ * · `grant` — the DECLARED reading: the call face's own slot only. A tool that declares none (a caller's tool that merely took
80
+ * the fetch tool's name, a bare request) is not the tool the catalog describes, and no allow by host reaches it.
81
+ * The slot's value is read by {@link hostOfUrl}; a value that names no host answers `{ unreadable }`, and each judge's law
82
+ * says what that means for its direction.
83
+ */
84
+ export declare function callHostTargetOf(call: ToolCallLike, direction: HostReadingDirection): HostReading | undefined;
@@ -0,0 +1,92 @@
1
+ import { hostTargetOf } from "./tool-registry.js";
2
+ import { seatOf } from "./tool-name-readings.js";
3
+ export function readSpelledHost(spelled) {
4
+ if (spelled === "" || /[\s/\\@?#%]/.test(spelled) || (spelled.includes(":") && !/^\[[^\]]+\]$/.test(spelled)))
5
+ return { problem: "not_a_host" };
6
+ let url;
7
+ try {
8
+ url = new URL(`https://${spelled}/`);
9
+ }
10
+ catch {
11
+ return { problem: "not_a_host" };
12
+ }
13
+ if (url.port !== "" || url.username !== "" || url.password !== "" || url.pathname !== "/" || url.search !== "" || url.hash !== "")
14
+ return { problem: "not_a_host" };
15
+ const host = url.hostname.replace(/\.+$/, "");
16
+ if (host === "")
17
+ return { problem: "not_a_host" };
18
+ return !host.startsWith("[") && host.split(".").includes("") ? { problem: "empty_label" } : { host };
19
+ }
20
+ export function hostOfSpelling(spelled) {
21
+ const read = readSpelledHost(spelled);
22
+ return "host" in read ? read.host : undefined;
23
+ }
24
+ export function isAddressHost(host) {
25
+ return host.startsWith("[") || /^\d+\.\d+\.\d+\.\d+$/.test(host);
26
+ }
27
+ export function readHostPattern(spelled) {
28
+ if (spelled === "*")
29
+ return { problem: "every_host" };
30
+ const below = spelled.startsWith("*.");
31
+ const read = readSpelledHost(below ? spelled.slice(2) : spelled);
32
+ if ("problem" in read)
33
+ return read;
34
+ const host = read.host;
35
+ if (host.includes("*"))
36
+ return { problem: "inner_wildcard" };
37
+ if (hostOfSpelling(host) !== host)
38
+ return { problem: "not_a_host" };
39
+ if (below && isAddressHost(host))
40
+ return { problem: "below_address" };
41
+ return { pattern: { match: below ? "subdomain" : "host", host } };
42
+ }
43
+ export function spelledHostPattern(pattern) {
44
+ return pattern.match === "subdomain" ? `*.${pattern.host}` : pattern.host;
45
+ }
46
+ export function hostPatternAdmits(pattern, host) {
47
+ if (pattern.match === "host")
48
+ return host === pattern.host;
49
+ if (isAddressHost(host) || !host.endsWith(`.${pattern.host}`))
50
+ return false;
51
+ const labels = host.slice(0, -(pattern.host.length + 1));
52
+ return labels !== "" && !labels.split(".").includes("");
53
+ }
54
+ export const HOST_UNREADABLE_REASONS = Object.freeze(["not_text", "not_url", "not_http", "credentials", "unstable"]);
55
+ export const HOST_UNREADABLE_SENTENCE = Object.freeze({
56
+ not_text: "the URL argument is not a string",
57
+ not_url: "the URL does not parse",
58
+ not_http: "the URL is not http(s)",
59
+ credentials: "the URL carries credentials",
60
+ unstable: "the URL's host does not read back as one host",
61
+ });
62
+ export function hostOfUrl(value) {
63
+ if (typeof value !== "string")
64
+ return { unreadable: "not_text" };
65
+ let url;
66
+ try {
67
+ url = new URL(value);
68
+ }
69
+ catch {
70
+ return { unreadable: "not_url" };
71
+ }
72
+ if (url.protocol !== "http:" && url.protocol !== "https:")
73
+ return { unreadable: "not_http" };
74
+ if (url.username !== "" || url.password !== "")
75
+ return { unreadable: "credentials" };
76
+ const host = url.hostname.replace(/\.+$/, "");
77
+ return host !== "" && hostOfSpelling(host) === host ? { host } : { unreadable: "unstable" };
78
+ }
79
+ export function callHostTargetOf(call, direction) {
80
+ const slot = hostSlotOf(call, direction);
81
+ if (slot === undefined)
82
+ return undefined;
83
+ const args = call.args;
84
+ const own = typeof args === "object" && args !== null && !Array.isArray(args) && Object.hasOwn(args, slot.param);
85
+ return hostOfUrl(own ? args[slot.param] : undefined);
86
+ }
87
+ function hostSlotOf(call, direction) {
88
+ const declared = call.face?.hostTarget;
89
+ if (declared !== undefined || direction === "grant")
90
+ return declared;
91
+ return seatOf("floor.protectiveHostTarget", { get: hostTargetOf }, call)?.value;
92
+ }
@@ -7,7 +7,7 @@
7
7
  * `core/types.ts`) needed no changes on this car.
8
8
  */
9
9
  /**
10
- * design/116 W5-1 — the max base64 size of ONE inline image (5MB). Value = CC 2.1.187
10
+ * design/116 W5-1 — the max base64 size of ONE inline image (5MB). Value =
11
11
  * `API_IMAGE_MAX_BASE64_SIZE` (constants/apiLimits.ts:22, "5 * 1024 * 1024 // 5 MB" — the hard Anthropic API
12
12
  * limit on a base64 image block; CC resizes/compresses down to fit UNDER it, imageResizer.ts). An MCP server
13
13
  * returning a bigger image previously passed straight through = a context/API bomb.
@@ -83,7 +83,7 @@ export declare class LspDiagnosticsRegistry {
83
83
  * the map; a judgment that fails withholds them all). The run's drain already marked them delivered, so they do not come back. */
84
84
  export declare function withholdListedDiagnostics(files: LspFileDiagnostics[], withheldOf: (uris: readonly string[]) => Promise<ReadonlyMap<string, unknown>>): Promise<LspFileDiagnostics[]>;
85
85
  /**
86
- * CC 198 `formatDiagnosticsSummary` (198:320480-320499), verbatim shape:
86
+ * `formatDiagnosticsSummary` shape:
87
87
  * ```
88
88
  * {basename}:
89
89
  * {symbol} [Line {line+1}:{col+1}] {message}[ [{code}]][ ({source})]
@@ -96,16 +96,16 @@ export declare function withholdListedDiagnostics(files: LspFileDiagnostics[], w
96
96
  * repository. They land inside the `<new-diagnostics>` envelope, and (since this block is now
97
97
  * delivered inside a marked reminder shell) inside an authority-marked reminder too, so a diagnostic
98
98
  * message carrying `</new-diagnostics>` closed the envelope and placed server text at the top level
99
- * of engine-authored authority. CC 223 does not neutralize here either — a deliberate, disclosed
99
+ * of engine-authored authority. The reference does not neutralize here either — a deliberate, disclosed
100
100
  * hardening divergence: CC ships the same block inside the same reminder shell, so the hole exists on
101
101
  * both sides and only the fix is ours. Neutralization runs BEFORE the join, so the 4000-char cap
102
102
  * still bounds the FINAL text and can never cut inside a neutralized marker's own bytes.
103
103
  */
104
104
  export declare function formatDiagnosticsSummary(files: LspFileDiagnostics[]): string;
105
- /** CC 198 model-facing injection block (198:320500-320503), verbatim framing.
105
+ /** Model-facing injection block.
106
106
  *
107
107
  * DELIVERY (design/319 sibling work): the runner shells this block in a MARKED `<system-reminder>`
108
- * before steering it — CC 223 `case "diagnostics"` does the same (`ih([Vr({content: …})])` → the
108
+ * before steering it — the reference's `case "diagnostics"` does the same (`ih([Vr({content: …})])` → the
109
109
  * reminder wrap), and until that was matched this was the engine's only authority text reaching the
110
110
  * model as a bare block with no provenance mark at all. The block's own bytes are unchanged; the
111
111
  * shell is applied at the delivery site (runtask), not baked in here, so this exported renderer keeps
@@ -58,8 +58,8 @@ export interface LspSymbolInfo {
58
58
  * answered null/[] — today's behavior byte-for-byte, and what an external manager returning bare
59
59
  * `{kind:"none"}` keeps getting). The failure reasons exist because one literal "No results." used to cover
60
60
  * both real emptiness and every transport-level fault — a findReferences that TIMED OUT read as "no
61
- * references, safe to delete" (CC 2.1.220 keeps these apart: `Error performing ${operation}: ...` vs the
62
- * plain empty-result strings, (pretty220.js:474840, historical; not relocated in 250 — see cc-250 anchors)).
61
+ * references, safe to delete" (the reference keeps these apart: `Error performing ${operation}: ...` vs the
62
+ * plain empty-result strings).
63
63
  */
64
64
  export type LspNoneReason = "unsupported_operation" | "server_error" | "timeout" | "cancelled" | "server_terminated" | "no_call_hierarchy_item"
65
65
  /** HRD-LSP-7: the QUERIED file could not be read for the didOpen/didChange re-sync (deleted between the
@@ -246,7 +246,7 @@ export interface LspTransport {
246
246
  * gate (no read face) only; a gated read is the admitted held object's ({@link LspReadAdmission}). TOC = local fs; TOB =
247
247
  * the sandbox ExecutionEnv. */
248
248
  export type LspReadText = (filePath: string, signal?: AbortSignal) => Promise<string>;
249
- /** CC 2.1.220's LSP file cap (10MB — `File too large for LSP analysis`, (pretty220.js:474745, historical; not relocated in 250 — see cc-250 anchors)). Single-sourced
249
+ /** The LSP file cap (10MB — `File too large for LSP analysis`). Single-sourced
250
250
  * in core: the TOOL-layer check in {@link createLspTool} (the model-visible enforcement, CC-parity) and the
251
251
  * defense-in-depth throw in the engine's `defaultLspReadText` must agree on one number. */
252
252
  export declare const MAX_LSP_FILE_BYTES: number;
@@ -221,6 +221,10 @@ export interface MailboxStore {
221
221
  * (the in-memory reference); absent = undeclared (the CC inbox adapter). Read by
222
222
  * {@link mailboxCrossProcessMountVerdict}; any other value is a malformed declaration and refuses. */
223
223
  readonly crossProcessSafe?: boolean;
224
+ /** WHICH boxes this store serves, as an opaque word: two store objects with the same identity read and write
225
+ * the same boxes (one backing directory, one database), in whichever process they live. Absent = the store
226
+ * cannot say — and then no peer may assume that a box it appends to here is one another session drains. */
227
+ readonly identity?: string;
224
228
  /** Durably park one message. Refuses `"mailbox.recipient_tombstoned"` when the backend can see
225
229
  * that its recipient is in the deployment's pre-delete state (see the interface notes above). */
226
230
  append(scope: string, handle: string, msg: MailboxAppendMessage): Promise<number>;
@@ -18,6 +18,7 @@
18
18
  * answer to its questions belongs to the leg that is waiting on it.
19
19
  */
20
20
  import type { Client } from "@modelcontextprotocol/sdk/client/index.js";
21
+ import { ConnectionListing, type LenientListedTool } from "./mcp-server-link.js";
21
22
  import type { McpServerSpec } from "./mcp-server-spec.js";
22
23
  /** The slice of a listed tool the SDK client caches per connection (its output validator, its task-support flags). */
23
24
  export interface McpToolMeta {
@@ -31,6 +32,8 @@ export type McpListingWriter = (tools: ReadonlyArray<McpToolMeta>, apply: (all:
31
32
  /** One leg's hold on a pooled connection. */
32
33
  export interface McpLease {
33
34
  readonly client: Client;
35
+ /** The connection's listing, one record shared by every holder (mcp-server-link.ts `ConnectionListing`). */
36
+ readonly listing: ConnectionListing<LenientListedTool>;
34
37
  /**
35
38
  * Open a `tools/list` round trip on the connection — call it BEFORE the request. The returned writer records the result twice over:
36
39
  * as the connection's metadata for each listed tool, at this listing's version (its place in the order listings were opened on the
@@ -65,13 +68,26 @@ export declare class McpConnectionPool {
65
68
  * Lease the connection for `key`, dialling it with `dial` when none is live. `fresh` replaces the pool's current connection with a new
66
69
  * dial (a re-dial): the connection it replaces lives on until its other holders release it. Resolves `undefined` once the pool is
67
70
  * closed — the caller dials for itself. A dial that rejects rejects every waiter of that dial, and the pool keeps nothing of it.
71
+ *
72
+ * `signal` is the CALLER's abort, and it is that caller's alone: it ends this caller's wait (rejecting with its reason) and leaves the dial
73
+ * to the legs still waiting on it. The dial belongs to the pool: it is given a stop of its own, fired when the last leg waiting on it has
74
+ * walked away, so a leg's abort neither holds nor cancels a dial another leg still needs.
68
75
  */
69
- acquire(key: string, dial: () => Promise<Client>, opts?: {
76
+ acquire(key: string, dial: (stop: AbortSignal) => Promise<Client>, opts?: {
70
77
  fresh?: boolean;
78
+ signal?: AbortSignal;
71
79
  }): Promise<McpLease | undefined>;
80
+ /**
81
+ * Wait for a dial as one of its legs; this leg's abort ends only this leg's wait. The last leg to walk away abandons the dial in the
82
+ * same step as its abort (see {@link abandon}) — the table holds only dials some leg still waits on, so a leg that asks next dials afresh
83
+ * instead of joining a stopped dial and failing with another leg's abort.
84
+ */
85
+ private waitOn;
86
+ /** A dial nobody waits on any more: out of the table and stopped, and — had it landed already — the connection nobody leased is let go, so such a dial leaves no connection behind. */
87
+ private abandon;
72
88
  /** Make the next lease of `key` dial a new connection. */
73
89
  detach(key: string): void;
74
- /** No lease is granted after this; the connections still held stay open until their holders release them. */
90
+ /** No lease is granted after this; the connections still held stay open until their holders release them — one nobody holds is closed now. */
75
91
  close(): void;
76
92
  /** How many connections the pool holds open right now (for the lifecycle pins). */
77
93
  get live(): number;
@@ -1,4 +1,5 @@
1
1
  import { canonicalize } from "./canonical-json.js";
2
+ import { ConnectionListing } from "./mcp-server-link.js";
2
3
  export class McpConnectionPool {
3
4
  entries = new Map();
4
5
  dialing = new Map();
@@ -17,25 +18,67 @@ export class McpConnectionPool {
17
18
  async acquire(key, dial, opts) {
18
19
  if (this.shut)
19
20
  return undefined;
21
+ opts?.signal?.throwIfAborted();
20
22
  if (opts?.fresh === true)
21
23
  this.detach(key);
22
24
  let entry = this.entries.get(key);
23
25
  if (entry === undefined || entry.closed) {
24
26
  let pending = this.dialing.get(key);
25
27
  if (pending === undefined) {
26
- const started = this.dialNew(key, this.generation.get(key) ?? 0, dial);
27
- pending = started;
28
- this.dialing.set(key, started);
28
+ const stop = new AbortController();
29
+ const started = this.dialNew(key, this.generation.get(key) ?? 0, () => dial(stop.signal));
30
+ const own = { promise: started, waiters: 0, stop };
31
+ pending = own;
32
+ this.dialing.set(key, own);
29
33
  const settled = () => {
30
- if (this.dialing.get(key) === started)
34
+ if (this.dialing.get(key) === own)
31
35
  this.dialing.delete(key);
32
36
  };
33
37
  void started.then(settled, settled);
34
38
  }
35
- entry = await pending;
39
+ entry = await this.waitOn(key, pending, opts?.signal);
36
40
  }
37
41
  return this.lease(entry);
38
42
  }
43
+ async waitOn(key, dial, signal) {
44
+ dial.waiters++;
45
+ let waiting = true;
46
+ const stopWaiting = () => {
47
+ if (waiting)
48
+ dial.waiters--;
49
+ waiting = false;
50
+ };
51
+ try {
52
+ if (signal === undefined)
53
+ return await dial.promise;
54
+ return await new Promise((resolve, reject) => {
55
+ const walkAway = () => {
56
+ stopWaiting();
57
+ if (dial.waiters === 0)
58
+ this.abandon(key, dial, signal.reason);
59
+ reject(signal.reason);
60
+ };
61
+ signal.addEventListener("abort", walkAway, { once: true });
62
+ dial.promise.then(resolve, reject).finally(() => signal.removeEventListener("abort", walkAway));
63
+ });
64
+ }
65
+ finally {
66
+ stopWaiting();
67
+ }
68
+ }
69
+ abandon(key, dial, reason) {
70
+ if (this.dialing.get(key) === dial)
71
+ this.dialing.delete(key);
72
+ dial.stop.abort(reason);
73
+ dial.promise.then((entry) => {
74
+ if (entry.refs > 0 || entry.closed)
75
+ return;
76
+ entry.current = false;
77
+ if (this.entries.get(key) === entry)
78
+ this.entries.delete(key);
79
+ void entry.client.close().catch(() => undefined);
80
+ }, () => undefined);
81
+ }
39
82
  detach(key) {
40
83
  this.generation.set(key, (this.generation.get(key) ?? 0) + 1);
41
84
  const e = this.entries.get(key);
@@ -47,6 +90,9 @@ export class McpConnectionPool {
47
90
  }
48
91
  close() {
49
92
  this.shut = true;
93
+ for (const e of [...this.entries.values()])
94
+ if (e.refs === 0 && !e.closed)
95
+ void e.client.close().catch(() => undefined);
50
96
  }
51
97
  get live() {
52
98
  let n = 0;
@@ -57,7 +103,7 @@ export class McpConnectionPool {
57
103
  }
58
104
  async dialNew(key, generation, dial) {
59
105
  const client = await dial();
60
- const entry = { client, refs: 0, listeners: new Set(), holders: new Map(), meta: new Map(), nextVersion: 0, current: true, closed: false };
106
+ const entry = { client, listing: new ConnectionListing(), refs: 0, listeners: new Set(), holders: new Map(), meta: new Map(), nextVersion: 0, current: true, closed: false };
61
107
  client.onclose = () => {
62
108
  entry.closed = true;
63
109
  if (this.entries.get(key) === entry)
@@ -86,6 +132,7 @@ export class McpConnectionPool {
86
132
  };
87
133
  const lease = {
88
134
  client: entry.client,
135
+ listing: entry.listing,
89
136
  onClose: (fn) => {
90
137
  mine.add(fn);
91
138
  entry.listeners.add(fn);
@@ -120,14 +120,17 @@ export type McpExchangeOutcome = McpFailureKind | "completed";
120
120
  * mint of the record — no two sites can disagree about the word, about which words may carry
121
121
  * `errorCode`, or about what a completed exchange proves. */
122
122
  export declare function livenessOf(outcome: McpExchangeOutcome, observedAt: number): McpServerLiveness | undefined;
123
+ /** A request over an established connection; `session` when the request carried the session id the server issued at the handshake. */
124
+ export type McpRequestSite = {
125
+ phase: "request";
126
+ session?: true;
127
+ };
123
128
  /** Where the failure was judged: at the dial (connect + initial listing), where an errno on a stdio
124
129
  * transport is the child process failing to spawn, or on a request over an established connection. */
125
130
  export type McpFailureSite = {
126
131
  phase: "connect";
127
132
  transport: "stdio" | "http" | undefined;
128
- } | {
129
- phase: "request";
130
- };
133
+ } | McpRequestSite;
131
134
  /**
132
135
  * The one MCP failure record. Both fields are always present; `httpStatus` rides only with
133
136
  * `kind === "http_status"`.
@@ -213,4 +216,20 @@ export interface HttpTransportFailure {
213
216
  delivered: McpDelivered;
214
217
  httpStatus?: number;
215
218
  }
216
- export declare function describeHttpTransportFailure(err: unknown): HttpTransportFailure | undefined;
219
+ export declare function describeHttpTransportFailure(err: unknown, at?: McpRequestSite): HttpTransportFailure | undefined;
220
+ /**
221
+ * The one reading of a lost session: a request that carried the session id the server issued at the handshake (`at.session`) was
222
+ * answered 404 by the HTTP endpoint — the protocol's word for a session it no longer knows (a restart, a reaped session). It is the
223
+ * server's REPORT, not a proof that nothing ran: the call lane sends the request again once on a fresh session, and every face that
224
+ * renders the failure names it ({@link LOST_SESSION}), while its record stays the table's (`http_status`, `delivered: "unknown"`) — a
225
+ * server that executed the request and then answered 404 ran it. Read from the thrown value's structure and the site, never from the
226
+ * body's text. Nothing else qualifies: a 5xx, a timeout or a lost pipe leave the outcome unknown, a protocol error or a tool's own error
227
+ * means the server processed the call, a 400 is the protocol's word for a request that lacked its session header (a server that answers
228
+ * an unknown session 400 with words saying so is not read by its words), and a 404 on a connection that holds no session id is an
229
+ * endpoint answering, not a session ending.
230
+ */
231
+ export declare function sessionGone(err: unknown, at: McpFailureSite): boolean;
232
+ /** What every face says of a lost session ({@link sessionGone}). */
233
+ export declare const LOST_SESSION = "the server reported the session the request was sent on gone (its HTTP endpoint answered 404 to the session id it issued)";
234
+ /** A failure's text, with a lost session ({@link sessionGone}) named ahead of it — for a face that renders the failure as one line. */
235
+ export declare function namingLostSession(err: unknown, at: McpRequestSite, text: string): string;