@sema-agent/core 7.54.1 → 7.55.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 (399) hide show
  1. package/CHANGELOG.md +437 -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/cc-peer-directory.d.ts +36 -0
  5. package/dist/agents/cc-peer-directory.js +138 -0
  6. package/dist/agents/cc-peer-wire.d.ts +105 -0
  7. package/dist/agents/cc-peer-wire.js +98 -0
  8. package/dist/agents/cc-uds-peer-channel.d.ts +40 -0
  9. package/dist/agents/cc-uds-peer-channel.js +457 -0
  10. package/dist/agents/cross-session-envelope.d.ts +4 -1
  11. package/dist/agents/cross-session-envelope.js +8 -1
  12. package/dist/agents/cross-session-judge.d.ts +2 -2
  13. package/dist/agents/list-agents-tool.js +2 -1
  14. package/dist/agents/observer.d.ts +4 -5
  15. package/dist/agents/observer.js +2 -1
  16. package/dist/agents/peer-admission.d.ts +6 -0
  17. package/dist/agents/peer-admission.js +4 -1
  18. package/dist/agents/peer-directory.d.ts +43 -9
  19. package/dist/agents/peer-directory.js +66 -23
  20. package/dist/agents/peer-notices.d.ts +1 -1
  21. package/dist/agents/peer-session-drain.d.ts +3 -1
  22. package/dist/agents/peer-session-drain.js +1 -0
  23. package/dist/agents/read-inbox-tool.js +2 -1
  24. package/dist/agents/retain-ledger.d.ts +1 -1
  25. package/dist/agents/roster-store.d.ts +1 -1
  26. package/dist/agents/send-message-tool.d.ts +10 -0
  27. package/dist/agents/send-message-tool.js +34 -5
  28. package/dist/agents/subagent.d.ts +34 -79
  29. package/dist/agents/subagent.js +45 -46
  30. package/dist/agents/tool-filter.d.ts +29 -46
  31. package/dist/agents/tool-filter.js +8 -31
  32. package/dist/agents/verify.d.ts +3 -3
  33. package/dist/brain/anthropic.js +14 -9
  34. package/dist/brain/errors.d.ts +15 -0
  35. package/dist/brain/errors.js +10 -0
  36. package/dist/brain/model-presets.d.ts +4 -4
  37. package/dist/brain/open-responses.js +15 -10
  38. package/dist/brain/openai.js +17 -12
  39. package/dist/brain/provider-dialect.d.ts +39 -3
  40. package/dist/brain/provider-dialect.js +28 -0
  41. package/dist/brain/reasoning.d.ts +1 -1
  42. package/dist/brain/request-params.d.ts +55 -5
  43. package/dist/brain/request-params.js +35 -3
  44. package/dist/brain/retry.d.ts +1 -1
  45. package/dist/brain/route-adjudicator.d.ts +15 -0
  46. package/dist/brain/route-adjudicator.js +15 -0
  47. package/dist/brain/stream-engine.js +6 -5
  48. package/dist/brain/stream-shared.d.ts +1 -1
  49. package/dist/core/advisor-verdict.d.ts +120 -0
  50. package/dist/core/advisor-verdict.js +92 -0
  51. package/dist/core/agent-definition.d.ts +7 -8
  52. package/dist/core/allow-entry.d.ts +49 -23
  53. package/dist/core/allow-entry.js +57 -32
  54. package/dist/core/allow-rule-shadow.d.ts +7 -0
  55. package/dist/core/approval-object.d.ts +2 -1
  56. package/dist/core/approval-object.js +6 -6
  57. package/dist/core/ask-origin.d.ts +63 -11
  58. package/dist/core/ask-origin.js +27 -5
  59. package/dist/core/ask-question.js +10 -4
  60. package/dist/core/auto-compaction.d.ts +11 -8
  61. package/dist/core/auto-compaction.js +4 -2
  62. package/dist/core/auto-mode-arming.d.ts +2 -2
  63. package/dist/core/auto-mode-defaults.d.ts +8 -8
  64. package/dist/core/auto-mode-prompt-assets.d.ts +3 -3
  65. package/dist/core/auto-mode-prompt.d.ts +1 -1
  66. package/dist/core/auto-mode.d.ts +17 -9
  67. package/dist/core/auto-mode.js +9 -6
  68. package/dist/core/background-agent-store.d.ts +3 -3
  69. package/dist/core/canonical-json.d.ts +1 -1
  70. package/dist/core/canonical-json.js +2 -2
  71. package/dist/core/checkpoint-requirements.d.ts +6 -3
  72. package/dist/core/checkpoint-requirements.js +4 -14
  73. package/dist/core/checkpoint-store.d.ts +80 -51
  74. package/dist/core/checkpoint-store.js +56 -74
  75. package/dist/core/child-clamp-seats.d.ts +6 -0
  76. package/dist/core/child-clamp-seats.js +3 -16
  77. package/dist/core/compliance.d.ts +2 -2
  78. package/dist/core/context-edit.d.ts +6 -7
  79. package/dist/core/cross-boundary-taint.d.ts +9 -3
  80. package/dist/core/cross-boundary-taint.js +5 -3
  81. package/dist/core/decision-receipt.js +2 -2
  82. package/dist/core/effective-path-target.d.ts +1 -1
  83. package/dist/core/engine-notice.d.ts +19 -5
  84. package/dist/core/exec-output-tail.d.ts +1 -1
  85. package/dist/core/file-history-retention.d.ts +1 -1
  86. package/dist/core/file-history-store.d.ts +59 -9
  87. package/dist/core/file-history-store.js +35 -17
  88. package/dist/core/gate-fold.js +3 -2
  89. package/dist/core/gate-lanes.js +12 -8
  90. package/dist/core/gate-outcome.d.ts +17 -4
  91. package/dist/core/gate-outcome.js +30 -0
  92. package/dist/core/governance-codes.d.ts +13 -3
  93. package/dist/core/governance-codes.js +10 -0
  94. package/dist/core/hands-band.d.ts +1 -1
  95. package/dist/core/hooks.d.ts +4 -4
  96. package/dist/core/host-target.d.ts +49 -0
  97. package/dist/core/host-target.js +59 -0
  98. package/dist/core/image-downsample.d.ts +1 -1
  99. package/dist/core/lsp-diagnostics.d.ts +4 -4
  100. package/dist/core/lsp.d.ts +3 -3
  101. package/dist/core/mailbox-store.d.ts +4 -0
  102. package/dist/core/mcp-connection-pool.d.ts +18 -2
  103. package/dist/core/mcp-connection-pool.js +53 -6
  104. package/dist/core/mcp-failure.d.ts +23 -4
  105. package/dist/core/mcp-failure.js +26 -11
  106. package/dist/core/mcp-listing-drift.d.ts +10 -0
  107. package/dist/core/mcp-listing-drift.js +6 -0
  108. package/dist/core/mcp-server-link.d.ts +173 -0
  109. package/dist/core/mcp-server-link.js +127 -0
  110. package/dist/core/mcp-server-spec.d.ts +4 -2
  111. package/dist/core/mcp-session-end.d.ts +26 -0
  112. package/dist/core/mcp-session-end.js +29 -0
  113. package/dist/core/mcp-startup-request.d.ts +17 -0
  114. package/dist/core/mcp-startup-request.js +17 -0
  115. package/dist/core/mcp.d.ts +13 -13
  116. package/dist/core/mcp.js +187 -162
  117. package/dist/core/media-byte-cap.d.ts +1 -1
  118. package/dist/core/memory-engine/engine.d.ts +9 -9
  119. package/dist/core/memory-engine/provenance-wording.d.ts +1 -1
  120. package/dist/core/memory-engine/tools.js +4 -1
  121. package/dist/core/mode-policy.d.ts +1 -1
  122. package/dist/core/namespaced-rule-name.d.ts +33 -7
  123. package/dist/core/namespaced-rule-name.js +39 -25
  124. package/dist/core/output-style.d.ts +1 -1
  125. package/dist/core/param-rule-reach.d.ts +15 -0
  126. package/dist/core/param-rule-reach.js +30 -0
  127. package/dist/core/parent-spec-seat.d.ts +8 -1
  128. package/dist/core/parent-spec-seat.js +4 -0
  129. package/dist/core/pause-registry.d.ts +16 -5
  130. package/dist/core/pause-registry.js +6 -2
  131. package/dist/core/peer-channel.d.ts +70 -0
  132. package/dist/core/peer-channel.js +1 -0
  133. package/dist/core/permission-rule-consent.d.ts +11 -5
  134. package/dist/core/permission-rule-consent.js +37 -30
  135. package/dist/core/permission-rule-model.d.ts +233 -64
  136. package/dist/core/permission-rule-model.js +384 -85
  137. package/dist/core/permission-rule-provider.d.ts +2 -1
  138. package/dist/core/permission-rule-store.d.ts +20 -25
  139. package/dist/core/permission-rule-store.js +1 -4
  140. package/dist/core/permission-rule-sync.d.ts +11 -2
  141. package/dist/core/permission-rule-sync.js +8 -1
  142. package/dist/core/permission-rules.d.ts +49 -11
  143. package/dist/core/permission-rules.js +123 -89
  144. package/dist/core/persisted-rule-arms.d.ts +4 -2
  145. package/dist/core/present-plan-tool.js +3 -1
  146. package/dist/core/protocol-naming.d.ts +2 -2
  147. package/dist/core/read-only-shell-table.d.ts +1 -1
  148. package/dist/core/read-only-shell.d.ts +1 -1
  149. package/dist/core/roles.d.ts +6 -2
  150. package/dist/core/roles.js +45 -44
  151. package/dist/core/rule-offer-read.d.ts +53 -0
  152. package/dist/core/rule-offer-read.js +146 -0
  153. package/dist/core/rule-owner.d.ts +46 -0
  154. package/dist/core/rule-owner.js +28 -0
  155. package/dist/core/runner/advisor-instructions.d.ts +70 -0
  156. package/dist/core/runner/advisor-instructions.js +61 -0
  157. package/dist/core/runner/advisor-tool.d.ts +33 -0
  158. package/dist/core/runner/advisor-tool.js +112 -0
  159. package/dist/core/runner/announce-once-ledger.d.ts +4 -26
  160. package/dist/core/runner/announce-once-ledger.js +14 -46
  161. package/dist/core/runner/approval-feedback.js +6 -3
  162. package/dist/core/runner/assemble-result.d.ts +1 -1
  163. package/dist/core/runner/caller-roster.d.ts +7 -0
  164. package/dist/core/runner/caller-roster.js +11 -0
  165. package/dist/core/runner/classifier-ladder.d.ts +27 -5
  166. package/dist/core/runner/classifier-ladder.js +12 -11
  167. package/dist/core/runner/compaction-restate.d.ts +10 -6
  168. package/dist/core/runner/compaction-restate.js +9 -3
  169. package/dist/core/runner/contracts.d.ts +13 -9
  170. package/dist/core/runner/conversation-segment.d.ts +28 -0
  171. package/dist/core/runner/conversation-segment.js +42 -0
  172. package/dist/core/runner/cross-boundary-lane.d.ts +6 -5
  173. package/dist/core/runner/cross-boundary-lane.js +26 -15
  174. package/dist/core/runner/decide-continuation.d.ts +7 -4
  175. package/dist/core/runner/decide-continuation.js +2 -2
  176. package/dist/core/runner/denial-limit-arms.d.ts +2 -2
  177. package/dist/core/runner/derived-route-fallback.d.ts +24 -24
  178. package/dist/core/runner/derived-route-fallback.js +9 -7
  179. package/dist/core/runner/gate-exit.d.ts +6 -0
  180. package/dist/core/runner/gate-exit.js +7 -2
  181. package/dist/core/runner/initial-run-state.js +1 -1
  182. package/dist/core/runner/permission-rule-lanes.d.ts +2 -2
  183. package/dist/core/runner/permission-rule-lanes.js +14 -7
  184. package/dist/core/runner/person-path-rows.js +1 -1
  185. package/dist/core/runner/prepare-advisor.d.ts +63 -0
  186. package/dist/core/runner/prepare-advisor.js +77 -0
  187. package/dist/core/runner/prepare-caps-and-workflow.js +1 -1
  188. package/dist/core/runner/prepare-config-doors.d.ts +6 -4
  189. package/dist/core/runner/prepare-config-doors.js +18 -12
  190. package/dist/core/runner/prepare-delegation-surface.d.ts +2 -2
  191. package/dist/core/runner/prepare-delegation-surface.js +1 -1
  192. package/dist/core/runner/prepare-file-history.js +39 -39
  193. package/dist/core/runner/prepare-gate-stations.d.ts +1 -4
  194. package/dist/core/runner/prepare-gate-stations.js +2 -7
  195. package/dist/core/runner/prepare-inherited-gate.d.ts +5 -4
  196. package/dist/core/runner/prepare-inherited-gate.js +3 -3
  197. package/dist/core/runner/prepare-park-ask.js +7 -7
  198. package/dist/core/runner/prepare-policy-chain.d.ts +1 -1
  199. package/dist/core/runner/prepare-policy-chain.js +4 -10
  200. package/dist/core/runner/prepare-project-context.d.ts +5 -2
  201. package/dist/core/runner/prepare-project-context.js +6 -3
  202. package/dist/core/runner/prepare-prompt-inputs.js +1 -1
  203. package/dist/core/runner/prepare-protocol-tools.d.ts +2 -2
  204. package/dist/core/runner/prepare-protocol-tools.js +3 -2
  205. package/dist/core/runner/prepare-safety-scan.d.ts +9 -12
  206. package/dist/core/runner/prepare-safety-scan.js +8 -6
  207. package/dist/core/runner/prepare-task.js +15 -18
  208. package/dist/core/runner/prepare-tool-disclosure-mount.js +6 -4
  209. package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -3
  210. package/dist/core/runner/prepare-wiring-manifest.js +2 -2
  211. package/dist/core/runner/resume-policy-outcome.js +1 -1
  212. package/dist/core/runner/retired-runner-deps.js +1 -1
  213. package/dist/core/runner/run-attachment-seats.js +0 -1
  214. package/dist/core/runner/run-compaction-machinery.d.ts +1 -1
  215. package/dist/core/runner/run-compaction-machinery.js +2 -12
  216. package/dist/core/runner/run-git-lane.d.ts +1 -0
  217. package/dist/core/runner/run-harness-handlers.js +2 -3
  218. package/dist/core/runner/run-leg.js +13 -0
  219. package/dist/core/runner/run-settle-and-teardown.js +1 -1
  220. package/dist/core/runner/run-telemetry-and-budget-seats.js +1 -1
  221. package/dist/core/runner/run-turn-boundary.d.ts +1 -0
  222. package/dist/core/runner/run-turn-boundary.js +14 -12
  223. package/dist/core/runner/session-rule-policy.d.ts +22 -21
  224. package/dist/core/runner/session-rule-policy.js +13 -28
  225. package/dist/core/runner/side-call-account.d.ts +32 -8
  226. package/dist/core/runner/side-call-account.js +23 -1
  227. package/dist/core/runner/strict-output-schema.d.ts +1 -1
  228. package/dist/core/runner/sub-agent-deny-lists.js +4 -3
  229. package/dist/core/runner/synthetic-tools.d.ts +10 -13
  230. package/dist/core/runner/synthetic-tools.js +4 -2
  231. package/dist/core/runner/tool-disclosure.js +2 -1
  232. package/dist/core/runner/tool-face-overlay.d.ts +2 -1
  233. package/dist/core/runner/tool-face-overlay.js +17 -1
  234. package/dist/core/runner/tool-progress-lane.d.ts +2 -2
  235. package/dist/core/runner/tool-turn-repair-seat.d.ts +3 -2
  236. package/dist/core/runner/turn-attachments.d.ts +60 -67
  237. package/dist/core/runner-deps.d.ts +37 -37
  238. package/dist/core/runtime-caps.d.ts +4 -4
  239. package/dist/core/safety-merge-corpus.js +17 -1
  240. package/dist/core/same-plain-value.d.ts +40 -0
  241. package/dist/core/same-plain-value.js +49 -0
  242. package/dist/core/scheduler.d.ts +1 -1
  243. package/dist/core/sensitive-path-policy.d.ts +1 -1
  244. package/dist/core/sensitive-path-policy.js +1 -1
  245. package/dist/core/session-policy-store.d.ts +77 -22
  246. package/dist/core/session-policy-store.js +56 -14
  247. package/dist/core/session-reconcile.d.ts +2 -2
  248. package/dist/core/session-store.d.ts +80 -30
  249. package/dist/core/session-store.js +118 -76
  250. package/dist/core/session.d.ts +24 -46
  251. package/dist/core/shared-memory/tools.js +3 -1
  252. package/dist/core/shared-memory/types.d.ts +1 -1
  253. package/dist/core/side-query.d.ts +10 -0
  254. package/dist/core/side-query.js +5 -0
  255. package/dist/core/store-contracts/checkpoint-store-contract.js +29 -2
  256. package/dist/core/store-contracts/file-history-store-contract.js +43 -3
  257. package/dist/core/store-contracts/session-policy-store-contract.d.ts +7 -0
  258. package/dist/core/store-contracts/session-policy-store-contract.js +130 -0
  259. package/dist/core/store-contracts/session-repo-contract.js +125 -0
  260. package/dist/core/store-contracts/session-store-contract.d.ts +4 -7
  261. package/dist/core/store-contracts/session-store-contract.js +215 -41
  262. package/dist/core/store-contracts/workflow-journal-store-contract.js +26 -1
  263. package/dist/core/surrogate-safe-slice.d.ts +3 -3
  264. package/dist/core/task-event.d.ts +10 -4
  265. package/dist/core/task-notification.d.ts +3 -3
  266. package/dist/core/task-registry-agent.d.ts +4 -4
  267. package/dist/core/task-registry-shared.d.ts +4 -4
  268. package/dist/core/task-registry-shared.js +1 -0
  269. package/dist/core/task-registry.d.ts +4 -4
  270. package/dist/core/task-registry.js +3 -1
  271. package/dist/core/task-result.d.ts +3 -3
  272. package/dist/core/task-spec.d.ts +52 -52
  273. package/dist/core/task-stream.d.ts +6 -6
  274. package/dist/core/task-tool-shape.d.ts +4 -4
  275. package/dist/core/tighten-task-spec.d.ts +1 -1
  276. package/dist/core/tool-catalog-entries.d.ts +19 -2
  277. package/dist/core/tool-catalog-entries.js +57 -42
  278. package/dist/core/tool-conformance.js +1 -0
  279. package/dist/core/tool-errors.d.ts +2 -2
  280. package/dist/core/tool-face-reader.js +5 -3
  281. package/dist/core/tool-face.d.ts +21 -2
  282. package/dist/core/tool-face.js +1 -1
  283. package/dist/core/tool-model-gate.d.ts +3 -3
  284. package/dist/core/tool-name-aliases.d.ts +29 -8
  285. package/dist/core/tool-name-aliases.js +27 -3
  286. package/dist/core/tool-name-readings.d.ts +5 -8
  287. package/dist/core/tool-name-readings.js +1 -2
  288. package/dist/core/tool-policy.d.ts +24 -5
  289. package/dist/core/tool-policy.js +34 -10
  290. package/dist/core/tool-registry.d.ts +14 -7
  291. package/dist/core/tool-registry.js +17 -7
  292. package/dist/core/tool-result-store.js +2 -1
  293. package/dist/core/tool-roster.d.ts +47 -18
  294. package/dist/core/tool-roster.js +53 -32
  295. package/dist/core/tool-spec-members.js +1 -1
  296. package/dist/core/tool-spec.d.ts +35 -21
  297. package/dist/core/tools.js +3 -2
  298. package/dist/core/trace.d.ts +4 -0
  299. package/dist/core/untrusted-egress.d.ts +1 -1
  300. package/dist/core/untrusted-text.d.ts +1 -1
  301. package/dist/core/warm-resume.d.ts +1 -1
  302. package/dist/core/wiring-manifest.d.ts +49 -0
  303. package/dist/core/wiring-manifest.js +13 -5
  304. package/dist/core/workflow-journal-store.d.ts +62 -0
  305. package/dist/core/workflow-journal-store.js +77 -1
  306. package/dist/core/workflow-run-store.d.ts +6 -0
  307. package/dist/core/workflow-run-store.js +2 -0
  308. package/dist/engine/compaction/compaction.d.ts +9 -9
  309. package/dist/engine/execution-env/node-execution-env.d.ts +19 -5
  310. package/dist/engine/execution-env/node-execution-env.js +43 -22
  311. package/dist/engine/harness/agent-harness.d.ts +14 -8
  312. package/dist/engine/harness/agent-harness.js +33 -26
  313. package/dist/engine/harness/types.d.ts +29 -7
  314. package/dist/engine/harness/types.js +12 -1
  315. package/dist/engine/llm/types.d.ts +9 -9
  316. package/dist/engine/llm/validation.d.ts +4 -1
  317. package/dist/engine/llm/validation.js +13 -1
  318. package/dist/engine/loop/agent-loop.d.ts +1 -1
  319. package/dist/engine/loop/agent-loop.js +10 -8
  320. package/dist/engine/loop/types.d.ts +15 -13
  321. package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
  322. package/dist/engine/session/memory-repo.d.ts +10 -11
  323. package/dist/engine/session/memory-repo.js +13 -8
  324. package/dist/engine/session/parent-chain-guard.d.ts +3 -2
  325. package/dist/engine/session/parent-chain-guard.js +1 -1
  326. package/dist/engine/session/repo-utils.d.ts +31 -3
  327. package/dist/engine/session/repo-utils.js +42 -5
  328. package/dist/index.d.ts +27 -15
  329. package/dist/index.js +21 -11
  330. package/dist/internal/harness-types.d.ts +1 -1
  331. package/dist/internal/harness.d.ts +3 -3
  332. package/dist/internal/harness.js +2 -2
  333. package/dist/internal/llm.d.ts +1 -1
  334. package/dist/internal/llm.js +1 -1
  335. package/dist/orchestration/goal.js +2 -2
  336. package/dist/orchestration/run-workflow-tool.d.ts +2 -2
  337. package/dist/orchestration/run-workflow-tool.js +5 -3
  338. package/dist/orchestration/workflow-size-guideline.d.ts +4 -4
  339. package/dist/orchestration/workflow-types.d.ts +18 -0
  340. package/dist/orchestration/workflow-types.js +6 -0
  341. package/dist/orchestration/workflow.d.ts +2 -13
  342. package/dist/orchestration/workflow.js +21 -31
  343. package/dist/prompt-assembly/event-registry.js +1 -0
  344. package/dist/prompt-assembly/tool-catalog.d.ts +3 -0
  345. package/dist/prompt-assembly/tool-catalog.js +3 -0
  346. package/dist/prompts/default.d.ts +14 -14
  347. package/dist/scenarios/full-body.d.ts +4 -4
  348. package/dist/stores/file/adoption/adopt.d.ts +4 -3
  349. package/dist/stores/file/adoption/adopt.js +24 -31
  350. package/dist/stores/file/adoption/marker.d.ts +6 -13
  351. package/dist/stores/file/adoption/marker.js +6 -15
  352. package/dist/stores/file/checkpoint-store.d.ts +3 -0
  353. package/dist/stores/file/checkpoint-store.js +9 -3
  354. package/dist/stores/file/file-history-store.d.ts +20 -19
  355. package/dist/stores/file/file-history-store.js +152 -135
  356. package/dist/stores/file/fs-atomic.d.ts +15 -0
  357. package/dist/stores/file/fs-atomic.js +89 -14
  358. package/dist/stores/file/index.d.ts +1 -1
  359. package/dist/stores/file/mailbox-store.d.ts +3 -0
  360. package/dist/stores/file/mailbox-store.js +3 -1
  361. package/dist/stores/file/permission-rule-adopt.d.ts +1 -1
  362. package/dist/stores/file/permission-rule-adopt.js +15 -16
  363. package/dist/stores/file/permission-rule-store.d.ts +18 -2
  364. package/dist/stores/file/permission-rule-store.js +21 -14
  365. package/dist/stores/file/session-policy-store.d.ts +3 -3
  366. package/dist/stores/file/session-store.d.ts +26 -11
  367. package/dist/stores/file/session-store.js +77 -40
  368. package/dist/stores/file/workflow-journal-store.d.ts +10 -4
  369. package/dist/stores/file/workflow-journal-store.js +28 -13
  370. package/dist/tools/artifact/artifact-text.d.ts +1 -1
  371. package/dist/tools/artifact/artifact-tool.js +2 -1
  372. package/dist/tools/fs/bash-readonly-classifier.d.ts +3 -3
  373. package/dist/tools/fs/fs-bash.d.ts +2 -2
  374. package/dist/tools/fs/fs-bash.js +3 -1
  375. package/dist/tools/fs/fs-shared.d.ts +8 -8
  376. package/dist/tools/fs/gh-rate-limit.d.ts +1 -1
  377. package/dist/tools/fs/notebook.d.ts +2 -2
  378. package/dist/tools/fs/read-deny.d.ts +29 -7
  379. package/dist/tools/fs/read-deny.js +63 -22
  380. package/dist/tools/fs/removal-targets.d.ts +1 -1
  381. package/dist/tools/fs/safety.d.ts +9 -9
  382. package/dist/tools/fs/search.d.ts +6 -6
  383. package/dist/tools/fs/shell-read-check.js +6 -1
  384. package/dist/tools/fs/shell-read-judge.d.ts +4 -0
  385. package/dist/tools/fs/shell-read-judge.js +5 -2
  386. package/dist/tools/loop-tick.d.ts +2 -2
  387. package/dist/tools/scheduler-tools.js +5 -1
  388. package/dist/tools/task-list.d.ts +7 -7
  389. package/dist/tools/task-list.js +5 -1
  390. package/dist/tools/todo.js +2 -1
  391. package/dist/tools/web.d.ts +1 -1
  392. package/dist/tools/web.js +40 -37
  393. package/dist/tools/worktree.d.ts +3 -3
  394. package/dist/tools/worktree.js +3 -1
  395. package/package.json +1 -1
  396. package/test/export-surface.snapshot.json +5756 -5638
  397. package/wire-changes/core@7.55.0.json +3318 -0
  398. package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +0 -39
  399. package/dist/core/store-contracts/session-store-incarnation-contract.js +0 -95
@@ -142,20 +142,28 @@ export const FAILURE_CLASSIFIER = [
142
142
  },
143
143
  ];
144
144
  export function classifyMcpFailure(err, at) {
145
- for (const rule of FAILURE_CLASSIFIER) {
146
- if (!rule.when(err, at))
147
- continue;
148
- const read = rule.reads(err);
149
- const dialled = at.phase === "connect" && !CONNECT_KEEPS_THE_TABLE_VERDICT.has(read.kind);
150
- return { ...read, delivered: dialled ? "no" : DELIVERED_BY_KIND[read.kind] };
151
- }
152
- return { kind: "unknown", delivered: "unknown" };
145
+ const read = classOf(err, at);
146
+ const dialled = at.phase === "connect" && !CONNECT_KEEPS_THE_TABLE_VERDICT.has(read.kind);
147
+ return { ...read, delivered: dialled ? "no" : DELIVERED_BY_KIND[read.kind] };
148
+ }
149
+ function classOf(err, at) {
150
+ for (const rule of FAILURE_CLASSIFIER)
151
+ if (rule.when(err, at))
152
+ return rule.reads(err);
153
+ return { kind: "unknown" };
153
154
  }
154
- export function describeHttpTransportFailure(err) {
155
- const f = classifyMcpFailure(err, { phase: "request" });
155
+ function answersLostSession(read, at) {
156
+ return at.phase === "request" && at.session === true && read.kind === "http_status" && read.httpStatus === 404;
157
+ }
158
+ export function describeHttpTransportFailure(err, at = { phase: "request" }) {
159
+ const f = classifyMcpFailure(err, at);
156
160
  switch (f.kind) {
157
161
  case "http_status":
158
- return { condition: `its HTTP endpoint answered ${f.httpStatus} instead of an MCP response`, delivered: f.delivered, httpStatus: f.httpStatus };
162
+ return {
163
+ condition: sessionGone(err, at) ? LOST_SESSION : `its HTTP endpoint answered ${f.httpStatus} instead of an MCP response`,
164
+ delivered: f.delivered,
165
+ httpStatus: f.httpStatus,
166
+ };
159
167
  case "not_mcp_response":
160
168
  return { condition: "its HTTP endpoint answered something that is not an MCP response", delivered: f.delivered };
161
169
  case "connect_refused": {
@@ -176,3 +184,10 @@ export function describeHttpTransportFailure(err) {
176
184
  return undefined;
177
185
  }
178
186
  }
187
+ export function sessionGone(err, at) {
188
+ return answersLostSession(classOf(err, at), at);
189
+ }
190
+ export 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)";
191
+ export function namingLostSession(err, at, text) {
192
+ return sessionGone(err, at) ? `${LOST_SESSION}: ${text}` : text;
193
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The gate a connection's listing records for an entry no listing of THAT connection reached — one it carries from the connection it
3
+ * replaced, after a walk that stopped early. Such an entry keeps its tool mounted but vouches for nothing: no minted gate equals it, so the
4
+ * tool is not sent until a listing of this connection reaches it.
5
+ */
6
+ export declare const UNPROVEN_GATE = "unproven";
7
+ /** The gate of one minted tool: the raw name it is sent under (two raw names can mint one tool name), its axis (the minted name left out), the listing-derived members of the tool object, and its task-support refusal. */
8
+ export declare function mcpToolGate(remoteName: string, axis: {
9
+ readonly name: string;
10
+ } | undefined, face: object, taskRequired: boolean): string;
@@ -0,0 +1,6 @@
1
+ import { canonicalize } from "./canonical-json.js";
2
+ export const UNPROVEN_GATE = "unproven";
3
+ export function mcpToolGate(remoteName, axis, face, taskRequired) {
4
+ const gates = axis === undefined ? null : Object.fromEntries(Object.entries(axis).filter(([key]) => key !== "name"));
5
+ return canonicalize({ remoteName, axis: gates, face, taskRequired });
6
+ }
@@ -0,0 +1,173 @@
1
+ /**
2
+ * How a tool call finds its server's connection. The connection under a server is not for life: a re-dial replaces it — at the host's
3
+ * request, or because the server dropped the session a call was sent on (`sessionGone`) — and the tools already mounted keep reaching
4
+ * the server. One rule decides where a mounted tool may be sent ({@link reach}): only on the server's LIVE connection, and only while the
5
+ * latest listing taken on that connection — by this leg or by another holder of a pooled one — through this leg's intake, mints the tool
6
+ * the gate it was mounted with (mcp-listing-drift.ts). The listing is compared, never adopted: the leg's roster stays the leg's own. No connection ⇒ the
7
+ * server is down; another gate ⇒ the tool is refused before it runs, until a re-dial or refresh re-folds the roster. Neither the connection
8
+ * a tool was minted around nor whoever opened the re-dial that replaced it enters the answer.
9
+ *
10
+ * A call that finds its session gone recovers once ({@link callThroughLink}). The re-dials of a server go one at a time ({@link Flights}):
11
+ * a host verb that finds one running is refused; a call joins the one running, and starts one only for the connection that lost its
12
+ * session while that connection is still the live one — a call that lost its session on a connection already replaced is sent on the
13
+ * replacement, so a late 404 never closes a connection other calls have moved to.
14
+ */
15
+ import type { Client } from "@modelcontextprotocol/sdk/client/index.js";
16
+ import type { McpExchangeOutcome } from "./mcp-failure.js";
17
+ /** Mutable per-server liveness flag, shared between a server's tool closures and its transport-close hook.
18
+ * `pendingElicitations` (RB-199 FO-1 codex review): a live count of in-flight `onElicit` waits on THIS
19
+ * server — the idle watchdog ({@link armMcpIdleWatchdog}) reads it before aborting a call (incremented when the wait starts,
20
+ * decremented in a `finally`): elicitation is a nested incoming request the
21
+ * server sends WHILE the outer callTool stays open (the elicitation handler's own LIVE-ONLY note in mcp.ts:
22
+ * "the handler runs WHILE the agent's `callTool` awaits the server, so the connection is held")
23
+ * — a human answering a form legitimately produces no progress notifications on the outer call for
24
+ * as long as they take, and the HTTP idle default (5min) is well within normal human response time. */
25
+ export interface ServerHealth {
26
+ dead: boolean;
27
+ /**
28
+ * THE liveness writer for this server — one lifecycle-aware function every observation goes through,
29
+ * so no site can record an outage the engine itself caused. It writes `McpServerStatus.liveness`
30
+ * on the SAME record the merge stage pushes into `MaterializedMcp.statuses` (never a second copy), and
31
+ * it is SILENT while the task is tearing down, for the reason `announceClose` is: our own dispose
32
+ * closes every transport, and stamping "this server died" on the way out is a lie a consumer reading
33
+ * the statuses afterwards cannot tell from the truth.
34
+ *
35
+ * Same slot discipline as `announce.fn`: filled by the merge stage (which is where the lifecycle flag
36
+ * lives), and DISARMED when this handle is deliberately replaced — a re-dial's own close is not an
37
+ * outage either, and the in-flight calls it fails belong to a connection we chose to replace.
38
+ */
39
+ observe?: (outcome: McpExchangeOutcome) => void;
40
+ pendingElicitations: number;
41
+ /** Stamped on EVERY
42
+ * elicitation close (finally, unconditional — not just when the count returns to 0). Closes a race
43
+ * the count alone cannot: an idle check can land microseconds after the count drops to 0 but before
44
+ * the server has had any real chance to reply to the outer call — that check must still treat the
45
+ * close as fresh activity, not silence. 0 = never closed. */
46
+ lastElicitationClosedAt: number;
47
+ }
48
+ /** Identity-tagged abort reason for {@link armMcpIdleWatchdog}'s own `.abort()` calls (independent review
49
+ * hardening): attribution reads `signal.reason === IDLE_WATCHDOG_ABORT_REASON`, a single atomic identity
50
+ * check, rather than re-reading two separate `.aborted` booleans after the fact and inferring which fired
51
+ * first — closes a theoretical (unconfirmed in review) same-tick interleaving window between the idle
52
+ * timer's own abort and an unrelated outer-signal abort landing in an already-queued microtask. */
53
+ export declare const IDLE_WATCHDOG_ABORT_REASON: unique symbol;
54
+ /**
55
+ * RB-199 FO-1 (independent review, "sweep the class"): a reusable idle watchdog shared by EVERY
56
+ * agent-reachable MCP request that can otherwise hang on nothing but the huge total-ceiling default —
57
+ * callTool AND the three resource tools (list/read/directory), all of which had only the single
58
+ * `mcpToolTimeoutMs()` bound before this RB. Elicitation-aware by construction (server-scoped
59
+ * `health.pendingElicitations`/`lastElicitationClosedAt` — see the ServerHealth docstring): a pending
60
+ * elicitation on ANY call to this server can legitimately stall the server's single request-processing
61
+ * turn, so it freezes the clock for every idle watchdog on that server, not just the call that issued it.
62
+ * `rearm()` is the reset-on-liveness hook — callTool's `onprogress` calls it every notification (the only
63
+ * MCP method family with a progress channel); a caller with no progress channel (resource calls have
64
+ * none — `resources/*` carries no `_meta.progressToken`) may still call it once per unit of real
65
+ * evidence-of-life it does have (e.g. `readDirViaExtension` calls it once per page received).
66
+ */
67
+ export declare function armMcpIdleWatchdog(health: ServerHealth, idleMs: number, outerSignal: AbortSignal | undefined): {
68
+ combinedSignal: AbortSignal;
69
+ idleSignal: AbortSignal;
70
+ rearm: () => void;
71
+ dispose: () => void;
72
+ };
73
+ /** One `tools/list` entry as the lenient listing parse keeps it (mcp.ts `LenientListToolsResultSchema`) — every field the intake
74
+ * pipeline actually reads (`intakeListedTools`), `inputSchema` UNVALIDATED (see that schema's docstring). */
75
+ export interface LenientListedTool {
76
+ name: string;
77
+ description?: string;
78
+ inputSchema?: unknown;
79
+ annotations?: unknown;
80
+ _meta?: unknown;
81
+ /** codex review (RB-199 FO-2 follow-up, confirmed HIGH): carried through UNVALIDATED (same posture as
82
+ * inputSchema) so `cacheMcpToolMetadata` (mcp.ts) can restore what `client.listTools()` used to do for
83
+ * free. Not fed through core's own gate — see that function's docstring for why. */
84
+ outputSchema?: unknown;
85
+ execution?: unknown;
86
+ }
87
+ /**
88
+ * The server's listing as one connection knows it, from whichever of its holders listed last (each leg of a pooled run lists on the
89
+ * shared connection) — what every holder's mounted tools are checked against, each through its own leg's intake, and what a leg mounts.
90
+ *
91
+ * Three rules, all here and nowhere else. Listings answer in the order they were opened: an answer that arrives after a later-opened one
92
+ * was recorded is superseded and records nothing. A walk that stopped early cannot prove a tool gone: an incomplete answer speaks only for
93
+ * the names it reached, and every other name keeps its entry from the listing before it (on a new connection, from what the connection it
94
+ * replaced knew — `carried`). And an entry vouches for a tool's gate only if a listing of THIS connection reached it: one carried across
95
+ * from the connection this one replaced keeps its tool mounted but stays `unproven` (its tool is not sent) until a listing of this
96
+ * connection reaches it — a reconnect is exactly when a declaration may have changed. The entries kept are the server's raw ones, not what
97
+ * an intake accepted, so a tool the walk did reach and the intake then dropped is gone, and every kept entry goes through the intake again.
98
+ * Accepted cost: an entry this connection listed earlier and a later walk did not reach is still read as it was listed — a tool the server
99
+ * withdrew or re-declared on an unreached page, with no reconnect between, is read as before until a walk reaches it (as it would be if
100
+ * nothing had listed again); calling a withdrawn one fails at the server.
101
+ */
102
+ export declare class ConnectionListing<T extends {
103
+ readonly name: string;
104
+ }> {
105
+ private opened;
106
+ private recorded;
107
+ private entries;
108
+ private unprovenNames;
109
+ /** Open a listing, before its request goes out: its place in the order. */
110
+ open(): number;
111
+ /** The answer of the listing opened at `at`, as the server's listing (`view`), with the names it kept from before (`kept`) and the kept names no listing of this connection reached (`unproven`); recorded unless a listing opened after it already answered. */
112
+ answer(at: number, entries: readonly T[], incomplete: boolean, carried?: readonly T[]): {
113
+ readonly recorded: boolean;
114
+ readonly view: readonly T[];
115
+ readonly kept: ReadonlySet<string>;
116
+ readonly unproven: ReadonlySet<string>;
117
+ };
118
+ latest(): {
119
+ readonly at: number;
120
+ readonly entries: readonly T[];
121
+ readonly unproven: ReadonlySet<string>;
122
+ };
123
+ }
124
+ /** A server's connection with its health record, as a call dispatches on it. */
125
+ export interface McpLiveConnection {
126
+ readonly client: Client;
127
+ readonly health: ServerHealth;
128
+ /** Minted tool name → the gate the connection's latest listing ({@link ConnectionListing}) mints it, through this leg's intake. */
129
+ gates(): ReadonlyMap<string, string>;
130
+ }
131
+ export interface McpServerLink {
132
+ /** The connection the materialization holds for the server now; `undefined` while it holds none (a re-dial's old one is gone and the new one has not landed, or the last dial failed). */
133
+ live(): McpLiveConnection | undefined;
134
+ /** Recover the session `lost` lost: join the re-dial running for the server, or start one while `lost` is still the live connection. Settles when there is nothing left to wait for. */
135
+ recover(lost: McpLiveConnection): Promise<unknown>;
136
+ }
137
+ /** Why a tool may not be sent on a live connection: its listing mints the tool another gate or none (`changed`), or no listing of the connection has reached it (`unreached`). */
138
+ export type McpListingRefusal = "changed" | "unreached";
139
+ /** Where the tool `name` minted with `gate` may be sent now: the live connection, `"gone"` when there is none (or it closed), or why its listing does not vouch for the tool ({@link McpListingRefusal}). */
140
+ export declare function reach(link: McpServerLink, name: string, gate: string): McpLiveConnection | "gone" | McpListingRefusal;
141
+ /** An attempt whose session was found gone: the connection it was sent on, and its failure as it would have been thrown then. */
142
+ export declare class Resendable {
143
+ readonly on: McpLiveConnection;
144
+ readonly error: unknown;
145
+ constructor(on: McpLiveConnection, error: unknown);
146
+ }
147
+ /**
148
+ * One tool call through the link. `send` makes one attempt on a connection (`resent` on the second) and answers {@link Resendable} for a
149
+ * lost session. Such a call is recovered once: it waits for the shared re-dial — or for its own `signal`, which ends the call at once —
150
+ * and is sent again only on a connection that replaced the lost one and where {@link reach} says it may go. A call that is not sent again,
151
+ * whatever the reason (no replacement, a declined re-dial that left the lost connection in place, a replacement whose listing does not
152
+ * vouch for the tool, its abort), ends with its first attempt's failure; a second lost session ends with that one. `gone` and an
153
+ * {@link McpListingRefusal} answer only a call that was never sent.
154
+ */
155
+ export declare function callThroughLink<R extends object>(link: McpServerLink, name: string, gate: string, signal: AbortSignal | undefined, send: (on: McpLiveConnection, resent: boolean) => Promise<R | Resendable>, gone: () => never): Promise<R | McpListingRefusal>;
156
+ /** The answer to a call {@link reach} refused before it was sent: the pre-send refusal record (`delivered: "no"`; `code` beside `error`, as the revocation refusal's). */
157
+ export declare function listingRefusal(refusal: McpListingRefusal, remoteName: string, server: string): {
158
+ content: Array<{
159
+ type: "text";
160
+ text: string;
161
+ }>;
162
+ details: Record<string, string>;
163
+ terminate: false;
164
+ isError: true;
165
+ };
166
+ /** The runs of one kind of work that may only run once at a time per key (a server's re-dial). */
167
+ export declare class Flights<V> {
168
+ private readonly open;
169
+ /** The flight running under `key`, or `undefined`. */
170
+ running(key: string): Promise<V> | undefined;
171
+ /** Start `run` as the flight of `key`; it leaves the table when it settles. The caller has checked that none is running. */
172
+ start(key: string, run: () => Promise<V>): Promise<V>;
173
+ }
@@ -0,0 +1,127 @@
1
+ import { UNPROVEN_GATE } from "./mcp-listing-drift.js";
2
+ import { inlineUntrusted } from "./untrusted-text.js";
3
+ export const IDLE_WATCHDOG_ABORT_REASON = Symbol("mcp-idle-watchdog-abort");
4
+ export function armMcpIdleWatchdog(health, idleMs, outerSignal) {
5
+ const idleController = new AbortController();
6
+ let timer;
7
+ const rearm = () => {
8
+ if (timer !== undefined)
9
+ clearTimeout(timer);
10
+ const armedAt = Date.now();
11
+ timer = setTimeout(() => {
12
+ if (health.pendingElicitations > 0 || health.lastElicitationClosedAt > armedAt) {
13
+ rearm();
14
+ return;
15
+ }
16
+ idleController.abort(IDLE_WATCHDOG_ABORT_REASON);
17
+ }, idleMs);
18
+ };
19
+ rearm();
20
+ return {
21
+ combinedSignal: outerSignal !== undefined ? AbortSignal.any([outerSignal, idleController.signal]) : idleController.signal,
22
+ idleSignal: idleController.signal,
23
+ rearm,
24
+ dispose: () => {
25
+ if (timer !== undefined)
26
+ clearTimeout(timer);
27
+ },
28
+ };
29
+ }
30
+ export class ConnectionListing {
31
+ opened = 0;
32
+ recorded = -1;
33
+ entries = [];
34
+ unprovenNames = new Set();
35
+ open() {
36
+ return this.opened++;
37
+ }
38
+ answer(at, entries, incomplete, carried) {
39
+ const reached = new Set(entries.map((e) => e.name));
40
+ const fresh = this.recorded === -1;
41
+ const before = incomplete ? (fresh ? (carried ?? []) : this.entries).filter((e) => !reached.has(e.name)) : [];
42
+ const view = before.length > 0 ? [...entries, ...before] : entries;
43
+ const kept = new Set(before.map((e) => e.name));
44
+ const unproven = fresh ? kept : new Set([...this.unprovenNames].filter((n) => kept.has(n)));
45
+ if (at < this.recorded)
46
+ return { recorded: false, view, kept, unproven };
47
+ this.recorded = at;
48
+ this.entries = view;
49
+ this.unprovenNames = unproven;
50
+ return { recorded: true, view, kept, unproven };
51
+ }
52
+ latest() {
53
+ return { at: this.recorded, entries: this.entries, unproven: this.unprovenNames };
54
+ }
55
+ }
56
+ export function reach(link, name, gate) {
57
+ const live = link.live();
58
+ if (live === undefined || live.health.dead)
59
+ return "gone";
60
+ const listed = live.gates().get(name);
61
+ if (listed === UNPROVEN_GATE)
62
+ return "unreached";
63
+ return listed === gate ? live : "changed";
64
+ }
65
+ export class Resendable {
66
+ on;
67
+ error;
68
+ constructor(on, error) {
69
+ this.on = on;
70
+ this.error = error;
71
+ }
72
+ }
73
+ export async function callThroughLink(link, name, gate, signal, send, gone) {
74
+ const first = reach(link, name, gate);
75
+ if (first === "gone")
76
+ gone();
77
+ if (typeof first === "string")
78
+ return first;
79
+ const res = await send(first, false);
80
+ if (!(res instanceof Resendable))
81
+ return res;
82
+ if (!(await settlesFirst(link.recover(res.on), signal)))
83
+ throw res.error;
84
+ const next = reach(link, name, gate);
85
+ if (typeof next === "string" || next === res.on)
86
+ throw res.error;
87
+ const again = await send(next, true);
88
+ if (again instanceof Resendable)
89
+ throw again.error;
90
+ return again;
91
+ }
92
+ export function listingRefusal(refusal, remoteName, server) {
93
+ const changed = refusal === "changed";
94
+ const code = changed ? "mcp.tool_declaration_changed" : "mcp.tool_listing_unreached";
95
+ return {
96
+ content: [{ type: "text", text: `The call to tool ${inlineUntrusted(remoteName)} was refused before it was sent: MCP server "${inlineUntrusted(server)}" ${changed ? "no longer declares this tool the way it was mounted (its safety declaration changed, or a complete listing no longer lists it)" : "has not listed this tool since it was reconnected (the re-listing stopped before it reached the tool), so whether the server still declares it the way it was mounted is unknown"}. The server did not execute it. Every call to this tool is refused the same way until a listing of the connection reaches the tool, so don't retry it.` }],
97
+ details: { error: code, code, delivered: "no", server },
98
+ terminate: false,
99
+ isError: true,
100
+ };
101
+ }
102
+ function settlesFirst(work, signal) {
103
+ const settled = work.then(() => true, () => true);
104
+ if (signal === undefined)
105
+ return settled;
106
+ if (signal.aborted)
107
+ return Promise.resolve(false);
108
+ return new Promise((resolve) => {
109
+ const stop = () => resolve(false);
110
+ signal.addEventListener("abort", stop, { once: true });
111
+ void settled.then((v) => {
112
+ signal.removeEventListener("abort", stop);
113
+ resolve(v);
114
+ });
115
+ });
116
+ }
117
+ export class Flights {
118
+ open = new Map();
119
+ running(key) {
120
+ return this.open.get(key);
121
+ }
122
+ start(key, run) {
123
+ const flight = run().finally(() => this.open.delete(key));
124
+ this.open.set(key, flight);
125
+ return flight;
126
+ }
127
+ }
@@ -1,6 +1,6 @@
1
1
  import { type ReceiptFault } from "./mods/kernel/receive.js";
2
2
  import type { ToolContentOrigin, ToolEffect } from "./tool-spec.js";
3
- import type { ToolFamily, ToolPathTarget, ToolRenderHints, ToolRuleFace } from "./tool-face.js";
3
+ import type { ToolFamily, ToolHostTarget, ToolPathTarget, ToolRenderHints, ToolRuleFace } from "./tool-face.js";
4
4
  /** Definition of an MCP server to connect to for the duration of one task, then discard. */
5
5
  export interface McpServerSpec {
6
6
  /** Stable name; tool names are namespaced as `mcp__<server>__<tool>` (the protocol prefix, then this name as the peer segment) to avoid collisions. */
@@ -82,7 +82,8 @@ export interface McpServerSpec {
82
82
  /**
83
83
  * design/388 §1.1 / §2.7 — the OPTIONAL per-tool FACE overlay for this server's tools (keyed by the server's
84
84
  * RAW tool name, like {@link allowTools} / {@link toolAxes}): a deployment lets an MCP tool enter a specialised
85
- * approval card, be confirmed by path, carry a display name / summary, or narrow its rule vocabulary. TRUSTED
85
+ * approval card, be confirmed by path, carry a display name / summary, or narrow its rule vocabulary (a `hostTarget` is
86
+ * refused here: host rules are written for the engine's fetch tool name only, which no MCP tool answers to). TRUSTED
86
87
  * (the deployment writes it). It is read once by `readToolFaces` at the preparation door and at `materializeMcpTools`: a
87
88
  * declaration that does not fit on its own (a member the types do not have, a member of the wrong kind, a word outside a
88
89
  * closed table, a reserved approval card, an empty tool name) refuses the entry under `config.tool_face_invalid` — the whole
@@ -94,6 +95,7 @@ export interface McpServerSpec {
94
95
  toolFaces?: Record<string, {
95
96
  family?: ToolFamily;
96
97
  pathTarget?: ToolPathTarget;
98
+ hostTarget?: ToolHostTarget;
97
99
  renderHints?: ToolRenderHints;
98
100
  ruleFace?: ToolRuleFace;
99
101
  }>;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Ending an MCP HTTP session. A Streamable HTTP connection owns a SESSION on the server, and the transport's own `close()` only aborts
3
+ * the local fetches — the server keeps the session until it reaps it. The protocol has the client end the session with a DELETE, so
4
+ * the transport this engine dials with ends its session in its own `close()`: first the DELETE (bounded), then the close. Every way a
5
+ * connection is let go — a run's end, a re-dial, a dial that failed or was stopped, the pool's last release, the SDK closing a
6
+ * handshake it rejected — closes the transport, so every way ends the session, with no helper to remember at each site. A stdio
7
+ * transport has no session; its close is unchanged.
8
+ *
9
+ * The session-end request is courtesy, not a condition of closing: a server that refuses it (405 — it keeps its sessions), no longer
10
+ * knows the session (404), cannot be reached or does not answer within {@link MCP_SESSION_END_WAIT_MS} costs the close that long at most
11
+ * and nothing else — the close runs regardless and aborts a request still in the air.
12
+ */
13
+ import type { Client } from "@modelcontextprotocol/sdk/client/index.js";
14
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
15
+ import type { McpRequestSite } from "./mcp-failure.js";
16
+ /** The longest a close waits for the server to answer the request that ends its session. */
17
+ export declare const MCP_SESSION_END_WAIT_MS = 2000;
18
+ /** The Streamable HTTP transport this engine dials with: closing it ends the server's session first. */
19
+ export declare class SessionEndingTransport extends StreamableHTTPClientTransport {
20
+ private closing;
21
+ /** One close however many ask: a second caller (the SDK closes a transport it rejected, and so does the dial after it) waits for the first's, rather than aborting its DELETE. */
22
+ close(): Promise<void>;
23
+ private endSessionThenClose;
24
+ }
25
+ /** Where a request about to be sent on `client` is judged (`sessionGone` in mcp-failure.ts): under the session the server issued, when the connection holds one. Read before the request goes out — what counts is the session it carried. */
26
+ export declare function requestSite(client: Client): McpRequestSite;
@@ -0,0 +1,29 @@
1
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
2
+ export const MCP_SESSION_END_WAIT_MS = 2_000;
3
+ export class SessionEndingTransport extends StreamableHTTPClientTransport {
4
+ closing;
5
+ close() {
6
+ this.closing ??= this.endSessionThenClose();
7
+ return this.closing;
8
+ }
9
+ async endSessionThenClose() {
10
+ if (this.sessionId !== undefined) {
11
+ let timer;
12
+ const wait = new Promise((resolve) => {
13
+ timer = setTimeout(resolve, MCP_SESSION_END_WAIT_MS);
14
+ timer.unref();
15
+ });
16
+ try {
17
+ await Promise.race([this.terminateSession().catch(() => undefined), wait]);
18
+ }
19
+ finally {
20
+ clearTimeout(timer);
21
+ }
22
+ }
23
+ await super.close();
24
+ }
25
+ }
26
+ export function requestSite(client) {
27
+ const transport = client.transport;
28
+ return transport instanceof StreamableHTTPClientTransport && transport.sessionId !== undefined ? { phase: "request", session: true } : { phase: "request" };
29
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The options of the FIRST TOOL LISTING of an MCP dial: the phase's bound, and the run's abort for as long as the listing is in the air.
3
+ * The abort is what lets a run that was cancelled stop waiting on a server that never answers it (the bound alone is a minute at the
4
+ * SDK's default); the dial then fails like any dial that did not finish.
5
+ *
6
+ * The listing runs on a connection the pool may share, so the abort cannot hang the transport up — it ends the listing request only. The
7
+ * SDK's request keeps a listener on the signal it is given for the life of that signal, and an abort that reaches it later sends the
8
+ * server a `notifications/cancelled` for a request long answered. So the request is given a signal of its own that follows the run's
9
+ * only while the listing is in flight. (The handshake owns its transport until it lands and stops by closing it — see the dial.)
10
+ */
11
+ /** What the SDK's request takes of a startup call. */
12
+ export interface StartupRequestOptions {
13
+ timeout?: number;
14
+ signal?: AbortSignal;
15
+ }
16
+ /** Run one startup request under `bound` (milliseconds, absent = the SDK's default) and, when given, the run's `abort`. Throws the abort's reason at once when it already fired. */
17
+ export declare function underStartupBound<T>(bound: number | undefined, abort: AbortSignal | undefined, request: (options: StartupRequestOptions | undefined) => Promise<T>): Promise<T>;
@@ -0,0 +1,17 @@
1
+ export async function underStartupBound(bound, abort, request) {
2
+ if (abort === undefined)
3
+ return request(bound !== undefined ? { timeout: bound } : undefined);
4
+ abort.throwIfAborted();
5
+ const inFlight = new AbortController();
6
+ const follow = () => inFlight.abort(abort.reason);
7
+ abort.addEventListener("abort", follow, { once: true });
8
+ try {
9
+ return await request({ ...(bound !== undefined ? { timeout: bound } : {}), signal: inFlight.signal });
10
+ }
11
+ catch (err) {
12
+ throw abort.aborted ? abort.reason : err;
13
+ }
14
+ finally {
15
+ abort.removeEventListener("abort", follow);
16
+ }
17
+ }
@@ -144,7 +144,7 @@ export interface MaterializedMcp {
144
144
  * [cc216] Tools DROPPED at intake because the server advertised a schema no provider accepts
145
145
  * ({@link mcpToolSchemaProblem}) — without the drop, one malformed tool schema riding the wire
146
146
  * fails the WHOLE model request (provider 400), bricking the task for every healthy tool
147
- * (CC 2.1.216 ships the same intake prune, `tengu_mcp_drop_invalid_tool_schemas`).
147
+ * (the reference ships the same intake prune, `tengu_mcp_drop_invalid_tool_schemas` (cli296.js:218844)).
148
148
  *
149
149
  * HONEST REACH (pinned in mcp-dropped-tools.test.ts): listings arrive through the lenient reader
150
150
  * (`listToolsLenient` — raw request, no SDK-client zod pass), so a string-root or otherwise odd
@@ -177,7 +177,7 @@ export interface MaterializedMcp {
177
177
  */
178
178
  statuses: McpServerStatus[];
179
179
  /**
180
- * RefreshMcpTools (CC 2.1.218 parity, anchored to the CLI form) — re-read the tool list of one server (or
180
+ * `RefreshMcpTools` (cli296.js:157909) — re-read the tool list of one server (or
181
181
  * every CONNECTED server when `server` is omitted) over the EXISTING connection. NEVER dials or
182
182
  * re-dials: a dead/never-connected server reports `not_connected` (so does one whose connection closed while the walk was reading); a live listTools failure
183
183
  * reports `failed` (the connection is left as-is). A refreshed entry carries the NEW intake
@@ -198,7 +198,7 @@ export interface MaterializedMcp {
198
198
  * cache seeding cannot drift between a first connect and a re-dial: one function, not one
199
199
  * convention.
200
200
  *
201
- * ONE SERVER, NAMED — CC 2.1.259's control-channel request carries a REQUIRED `serverName` and has
201
+ * ONE SERVER, NAMED — the reference's control-channel request carries a REQUIRED `serverName` and has
202
202
  * no all-servers form, and an all-servers arm would close HEALTHY connections to re-dial them (a
203
203
  * stdio server owning a device or a port is exactly the one that cannot be re-dialed while its
204
204
  * predecessor still holds the device). CLOSE-THEN-DIAL, so a re-dial that FAILS leaves the server
@@ -370,7 +370,7 @@ export interface McpServerStatus {
370
370
  liveness?: McpServerLiveness;
371
371
  }
372
372
  /**
373
- * design/108 ① (CC 2.1.187 parity) — the GLOBAL `mcp__` marker prefix. CC names every MCP tool
373
+ * design/108 ① — the GLOBAL `mcp__` marker prefix. CC names every MCP tool
374
374
  * `mcp__<server>__<tool>` so a consumer (permission allowlist, bypass-exempt, the flywheel's whitelist) can
375
375
  * identify an MCP-originated tool by prefix ALONE, without knowing the per-deployment server names. Exported so
376
376
  * downstream consumers share one source (the durable-resume canonicalizer is retired — RB-476-A).
@@ -401,8 +401,8 @@ export declare function truncateMcpErrorText(s: string): string;
401
401
  */
402
402
  export declare const MCP_TOOL_TIMEOUT_DEFAULT_MS = 100000000;
403
403
  /**
404
- * The bounds EVERY `MCP_*` millisecond knob resolves into — CC 223-same (`MNs` @354067 and the idle leg
405
- * `Pyd` @354076 both clamp into `[1000, 2147483647]`; the constants were already ported here, the clamp
404
+ * The bounds EVERY `MCP_*` millisecond knob resolves into: both the timeout and the idle leg clamp into
405
+ * `[1000, 2147483647]`; the constants were already ported here, the clamp
406
406
  * was not).
407
407
  *
408
408
  * The ceiling is not cosmetic: `setTimeout` stores its delay in a signed 32-bit field, so a larger value
@@ -434,7 +434,7 @@ export declare function mcpToolTimeoutMs(): number;
434
434
  */
435
435
  export declare function mcpToolTotalTimeoutMs(perCallMs: number): number;
436
436
  /**
437
- * RB-199 FO-1 (form-one audit, CC 2.1.220): a server that goes SILENT — alive, transport open, no error,
437
+ * RB-199 FO-1 (form-one audit): a server that goes SILENT — alive, transport open, no error,
438
438
  * no close, just never responds and never emits progress — has no bound tighter than the (deliberately
439
439
  * enormous, ~27.8h-default) total ceiling above. CC bounds this with a SEPARATE idle watchdog distinct
440
440
  * from its total ceiling (`j7u` @345484: stdio 30min / http-sse 5min).
@@ -475,8 +475,8 @@ export { normalizeNameSegment as normalizeMcpName, clampNameSegment } from "./pr
475
475
  export * from "./image-downsample.js";
476
476
  /**
477
477
  * design/116 W5-2 — compact, jq-friendly type signature for a `structuredContent` value, e.g.
478
- * `{title: string, items: [{id: number}]}`. Port of CC 2.1.187 `inferCompactSchema` (services/mcp/client.ts,
479
- * beside the structuredContent branch at client.ts:2676-2683): depth-2, first array element as the element
478
+ * `{title: string, items: [{id: number}]}`. Port of the reference's compact-schema inference:
479
+ * depth-2, first array element as the element
480
480
  * type, ≤10 object entries then `, ...`.
481
481
  */
482
482
  export declare function inferCompactSchema(value: unknown, depth?: number): string;
@@ -535,7 +535,7 @@ export declare function mapContent(content: Array<McpContentItem>, serverName?:
535
535
  * `\p{Cc}` is deliberately NOT here: newlines and tabs are legitimate description formatting.
536
536
  */
537
537
  export declare const MCP_INVISIBLE_TEXT_RE: RegExp;
538
- /** One tool's schema-normalization outcome (CC 220 `zyo` @336616-336654's return shape). */
538
+ /** One tool's schema-normalization outcome. */
539
539
  export type McpSchemaNormalizeResult = {
540
540
  outcome: "unchanged";
541
541
  } | {
@@ -548,7 +548,7 @@ export type McpSchemaNormalizeResult = {
548
548
  reason: string;
549
549
  };
550
550
  /**
551
- * RB-199 FO-2 (form-one audit, CC 2.1.220 `zyo` @336616-336654): flatten a root-level `anyOf`/`oneOf`/
551
+ * RB-199 FO-2 (form-one audit): flatten a root-level `anyOf`/`oneOf`/
552
552
  * `allOf` combinator into a plain `{type:"object", properties, required}` shape a provider's tool-schema
553
553
  * validator accepts, INSTEAD of leaving `mcpToolSchemaProblem` below to drop the whole tool. Without this,
554
554
  * a server advertising the common "zod union" combinator shape (structurally VALID JSON Schema — the
@@ -576,7 +576,7 @@ export declare function normalizeMcpToolSchema(schema: unknown): McpSchemaNormal
576
576
  * CORE-authored reason string when the schema would be rejected at the provider wire, else
577
577
  * `undefined` (tool is kept). Deliberately CONSERVATIVE (fail-open): only shapes that are
578
578
  * *structurally* unusable are dropped — anything a provider might accept rides through. An ABSENT
579
- * schema is fine (intake defaults it to `{type:"object"}` below). CC 2.1.216 gates the same prune
579
+ * schema is fine (intake defaults it to `{type:"object"}` below). The reference gates the same prune
580
580
  * per-server via remote config (its rollout mechanism, not the mechanism itself); sema's gate is
581
581
  * the deterministic predicate alone. RB-199 FO-2: run {@link normalizeMcpToolSchema} on the schema
582
582
  * FIRST — a root-level anyOf/oneOf/allOf reaching this gate unflattened is exactly the shape this
@@ -616,7 +616,7 @@ reminderDisclosure?: {
616
616
  }, poolOpts?: {
617
617
  pool: McpConnectionPool;
618
618
  ownsPool?: boolean;
619
- }, promptSections?: PromptSectionDisposer, dialable?: (spec: McpServerSpec) => boolean): Promise<MaterializedMcp>;
619
+ }, promptSections?: PromptSectionDisposer, dialable?: (spec: McpServerSpec) => boolean, signal?: AbortSignal): Promise<MaterializedMcp>;
620
620
  /**
621
621
  * Fold the caller's AUTHORITATIVE per-tool override (design F: caller = trust root) over the server-hint axis.
622
622
  * Unlike server hints, the caller may RAISE or LOWER any axis: `effect` sets the repeat-safety class (lower to