@sema-agent/core 7.55.0 → 7.57.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 (502) hide show
  1. package/CHANGELOG.md +1054 -0
  2. package/LICENSE +1 -1
  3. package/dist/agents/cascade.js +1 -1
  4. package/dist/agents/cc-peer-directory.js +1 -0
  5. package/dist/agents/child-model-seat.d.ts +0 -11
  6. package/dist/agents/child-model-seat.js +0 -3
  7. package/dist/agents/list-agents-tool.d.ts +3 -1
  8. package/dist/agents/list-agents-tool.js +7 -7
  9. package/dist/agents/org-delivery-gate.js +3 -4
  10. package/dist/agents/peer-directory.d.ts +22 -4
  11. package/dist/agents/peer-directory.js +24 -2
  12. package/dist/agents/peer-held-queue.d.ts +69 -49
  13. package/dist/agents/peer-held-queue.js +255 -106
  14. package/dist/agents/peer-session-drain.js +65 -45
  15. package/dist/agents/repair-loop.js +2 -2
  16. package/dist/agents/send-message-tool.js +7 -6
  17. package/dist/agents/subagent.d.ts +6 -4
  18. package/dist/agents/subagent.js +72 -68
  19. package/dist/agents/tool-filter.d.ts +7 -5
  20. package/dist/agents/tool-filter.js +12 -9
  21. package/dist/agents/verify.d.ts +3 -2
  22. package/dist/agents/verify.js +3 -3
  23. package/dist/brain/anthropic.js +45 -80
  24. package/dist/brain/media-degrade.d.ts +18 -7
  25. package/dist/brain/media-degrade.js +13 -2
  26. package/dist/brain/model-capability.d.ts +37 -0
  27. package/dist/brain/model-capability.js +34 -0
  28. package/dist/brain/model-presets.d.ts +2 -8
  29. package/dist/brain/model-presets.js +1 -6
  30. package/dist/brain/open-responses.js +23 -34
  31. package/dist/brain/openai.js +25 -96
  32. package/dist/brain/provider-dialect.d.ts +3 -2
  33. package/dist/brain/provider-dialect.js +2 -2
  34. package/dist/brain/reasoning-request.d.ts +96 -0
  35. package/dist/brain/reasoning-request.js +174 -0
  36. package/dist/brain/reasoning.d.ts +11 -11
  37. package/dist/brain/reasoning.js +4 -3
  38. package/dist/brain/request-params.d.ts +13 -4
  39. package/dist/brain/request-params.js +21 -5
  40. package/dist/brain/status-sink.d.ts +20 -0
  41. package/dist/brain/status-sink.js +7 -0
  42. package/dist/brain/stream-engine.d.ts +9 -0
  43. package/dist/brain/stream-engine.js +24 -10
  44. package/dist/brain/stream-shared.d.ts +5 -4
  45. package/dist/brain/stream-shared.js +4 -4
  46. package/dist/core/a2a.d.ts +2 -1
  47. package/dist/core/a2a.js +19 -13
  48. package/dist/core/agent-definition.d.ts +10 -0
  49. package/dist/core/allow-entry.d.ts +23 -23
  50. package/dist/core/allow-entry.js +42 -46
  51. package/dist/core/allow-rule-shadow.d.ts +3 -3
  52. package/dist/core/approval-object.d.ts +21 -5
  53. package/dist/core/approval-object.js +44 -17
  54. package/dist/core/ask-origin.d.ts +66 -20
  55. package/dist/core/ask-origin.js +63 -23
  56. package/dist/core/ask-question.d.ts +51 -8
  57. package/dist/core/ask-question.js +3 -4
  58. package/dist/core/ask-unresolvable-notice.d.ts +8 -3
  59. package/dist/core/ask-unresolvable-notice.js +16 -2
  60. package/dist/core/auto-compaction.d.ts +71 -6
  61. package/dist/core/auto-compaction.js +42 -26
  62. package/dist/core/background-agent-store.d.ts +6 -2
  63. package/dist/core/background-agent-store.js +1 -1
  64. package/dist/core/checkpoint-generation.d.ts +53 -0
  65. package/dist/core/checkpoint-generation.js +35 -0
  66. package/dist/core/checkpoint-queries.d.ts +180 -0
  67. package/dist/core/checkpoint-queries.js +272 -0
  68. package/dist/core/checkpoint-requirements.d.ts +19 -1
  69. package/dist/core/checkpoint-requirements.js +6 -0
  70. package/dist/core/checkpoint-store.d.ts +105 -53
  71. package/dist/core/checkpoint-store.js +43 -20
  72. package/dist/core/cross-boundary-taint.d.ts +6 -5
  73. package/dist/core/cross-boundary-taint.js +5 -5
  74. package/dist/core/decision-receipt.d.ts +37 -3
  75. package/dist/core/decision-receipt.js +17 -17
  76. package/dist/core/delegation-not-started.d.ts +6 -0
  77. package/dist/core/delegation-not-started.js +17 -0
  78. package/dist/core/engine-attestation.d.ts +93 -0
  79. package/dist/core/engine-attestation.js +70 -0
  80. package/dist/core/engine-capabilities.d.ts +4 -1
  81. package/dist/core/engine-capabilities.js +1 -1
  82. package/dist/core/engine-notice.d.ts +32 -12
  83. package/dist/core/engine-notice.js +6 -0
  84. package/dist/core/file-history-store.d.ts +104 -22
  85. package/dist/core/file-history-store.js +37 -19
  86. package/dist/core/gate-fold.d.ts +1 -1
  87. package/dist/core/gate-fold.js +22 -10
  88. package/dist/core/gate-lanes.js +73 -65
  89. package/dist/core/gate-outcome.d.ts +26 -5
  90. package/dist/core/gate-outcome.js +26 -0
  91. package/dist/core/governance-codes.d.ts +5 -1
  92. package/dist/core/governance-codes.js +6 -0
  93. package/dist/core/hooks.d.ts +19 -18
  94. package/dist/core/hooks.js +3 -1
  95. package/dist/core/host-floor.d.ts +128 -0
  96. package/dist/core/host-floor.js +206 -0
  97. package/dist/core/host-target.d.ts +38 -3
  98. package/dist/core/host-target.js +38 -5
  99. package/dist/core/mailbox-store.d.ts +62 -1
  100. package/dist/core/mailbox-store.js +59 -0
  101. package/dist/core/mcp-name-judge.d.ts +46 -0
  102. package/dist/core/mcp-name-judge.js +61 -0
  103. package/dist/core/mcp-probe.d.ts +1 -1
  104. package/dist/core/mcp-probe.js +2 -5
  105. package/dist/core/mcp.d.ts +5 -1
  106. package/dist/core/mcp.js +70 -64
  107. package/dist/core/memory-engine/consolidation-driver.js +4 -3
  108. package/dist/core/memory-engine/delegation-settlement.js +15 -24
  109. package/dist/core/memory-engine/distiller.js +26 -17
  110. package/dist/core/memory-engine/engine.js +4 -4
  111. package/dist/core/memory-engine/layout.d.ts +60 -8
  112. package/dist/core/memory-engine/layout.js +70 -8
  113. package/dist/core/model-seat.d.ts +10 -3
  114. package/dist/core/mods/classic-events.d.ts +67 -0
  115. package/dist/core/mods/classic-events.js +1 -0
  116. package/dist/core/mods/dollar.d.ts +13 -0
  117. package/dist/core/mods/extension-call.d.ts +31 -0
  118. package/dist/core/mods/extension-call.js +43 -0
  119. package/dist/core/mods/kernel/dispatch.d.ts +20 -3
  120. package/dist/core/mods/kernel/dispatch.js +140 -69
  121. package/dist/core/mods/kernel/events.d.ts +47 -11
  122. package/dist/core/mods/kernel/events.js +66 -42
  123. package/dist/core/mods/kernel/index.d.ts +4 -4
  124. package/dist/core/mods/kernel/index.js +2 -2
  125. package/dist/core/mods/kernel/receive.d.ts +39 -5
  126. package/dist/core/mods/kernel/receive.js +290 -17
  127. package/dist/core/mods/kernel/registration.d.ts +33 -2
  128. package/dist/core/mods/kernel/registration.js +6 -7
  129. package/dist/core/mods/kernel/site-rules.d.ts +44 -16
  130. package/dist/core/mods/kernel/site-rules.js +24 -42
  131. package/dist/core/mods/spec-seats.d.ts +69 -0
  132. package/dist/core/mods/spec-seats.js +114 -0
  133. package/dist/core/mods/stations.d.ts +28 -8
  134. package/dist/core/mods/stations.js +29 -13
  135. package/dist/core/mods/tool-call.d.ts +79 -0
  136. package/dist/core/mods/tool-call.js +152 -0
  137. package/dist/core/namespaced-rule-name.d.ts +32 -38
  138. package/dist/core/namespaced-rule-name.js +29 -36
  139. package/dist/core/parent-spec-seat.d.ts +6 -1
  140. package/dist/core/parent-spec-seat.js +2 -0
  141. package/dist/core/park-selfcheck.js +3 -0
  142. package/dist/core/permission-rule-consent.d.ts +24 -3
  143. package/dist/core/permission-rule-consent.js +136 -41
  144. package/dist/core/permission-rule-model.d.ts +57 -5
  145. package/dist/core/permission-rule-model.js +90 -31
  146. package/dist/core/permission-rule-org.d.ts +6 -2
  147. package/dist/core/permission-rule-org.js +8 -4
  148. package/dist/core/permission-rule-provider.d.ts +5 -2
  149. package/dist/core/permission-rule-provider.js +41 -11
  150. package/dist/core/permission-rule-store.d.ts +3 -2
  151. package/dist/core/permission-rule-store.js +11 -2
  152. package/dist/core/permission-rule-sync.js +3 -2
  153. package/dist/core/permission-rule-syntax.d.ts +5 -4
  154. package/dist/core/permission-rule-syntax.js +2 -2
  155. package/dist/core/permission-rules.d.ts +4 -4
  156. package/dist/core/permission-rules.js +11 -20
  157. package/dist/core/persisted-rule-arms.d.ts +2 -2
  158. package/dist/core/persisted-rule-arms.js +10 -12
  159. package/dist/core/principal-name.d.ts +20 -0
  160. package/dist/core/principal-name.js +22 -0
  161. package/dist/core/prompt-section-seat.js +4 -6
  162. package/dist/core/protocol-http-auth.d.ts +40 -5
  163. package/dist/core/protocol-http-auth.js +168 -4
  164. package/dist/core/protocol-naming.d.ts +20 -0
  165. package/dist/core/protocol-naming.js +20 -3
  166. package/dist/core/read-only-shell.d.ts +20 -5
  167. package/dist/core/read-only-shell.js +29 -14
  168. package/dist/core/remote-env.d.ts +37 -1
  169. package/dist/core/remote-env.js +11 -0
  170. package/dist/core/resume-startup-cause.d.ts +24 -2
  171. package/dist/core/resume-startup-cause.js +20 -1
  172. package/dist/core/retired-keys.d.ts +16 -0
  173. package/dist/core/retired-keys.js +16 -4
  174. package/dist/core/rewrite-rejudge.d.ts +60 -0
  175. package/dist/core/rewrite-rejudge.js +36 -0
  176. package/dist/core/roles.d.ts +28 -1
  177. package/dist/core/roles.js +81 -26
  178. package/dist/core/rule-lane-reads.d.ts +20 -15
  179. package/dist/core/rule-lane-reads.js +45 -17
  180. package/dist/core/rule-owner.d.ts +3 -3
  181. package/dist/core/rule-owner.js +3 -2
  182. package/dist/core/runner/announce-once-ledger.d.ts +14 -0
  183. package/dist/core/runner/announce-once-ledger.js +5 -0
  184. package/dist/core/runner/assemble-result.d.ts +1 -0
  185. package/dist/core/runner/assemble-result.js +1 -1
  186. package/dist/core/runner/call-hook-stations.d.ts +3 -2
  187. package/dist/core/runner/caller-roster.d.ts +16 -4
  188. package/dist/core/runner/caller-roster.js +33 -6
  189. package/dist/core/runner/capability-withheld-seat.d.ts +5 -0
  190. package/dist/core/runner/capability-withheld-seat.js +24 -0
  191. package/dist/core/runner/classifier-ladder.d.ts +7 -9
  192. package/dist/core/runner/classifier-ladder.js +3 -3
  193. package/dist/core/runner/compact-session.d.ts +10 -0
  194. package/dist/core/runner/compact-session.js +202 -0
  195. package/dist/core/runner/compaction-call-options.d.ts +2 -2
  196. package/dist/core/runner/compaction-seams.d.ts +21 -1
  197. package/dist/core/runner/compaction-seams.js +11 -8
  198. package/dist/core/runner/construction-doors.js +3 -0
  199. package/dist/core/runner/contracts.d.ts +50 -40
  200. package/dist/core/runner/cross-boundary-lane.d.ts +17 -13
  201. package/dist/core/runner/cross-boundary-lane.js +40 -27
  202. package/dist/core/runner/denial-limit-arms.d.ts +2 -2
  203. package/dist/core/runner/denial-limit-arms.js +1 -1
  204. package/dist/core/runner/derived-route-fallback.d.ts +13 -0
  205. package/dist/core/runner/derived-route-fallback.js +6 -0
  206. package/dist/core/runner/env-capability-census.d.ts +3 -2
  207. package/dist/core/runner/env-capability-census.js +9 -3
  208. package/dist/core/runner/file-history-request.d.ts +18 -0
  209. package/dist/core/runner/file-history-request.js +21 -13
  210. package/dist/core/runner/file-history-restore.d.ts +45 -0
  211. package/dist/core/runner/file-history-restore.js +46 -0
  212. package/dist/core/runner/gate-exit.d.ts +3 -3
  213. package/dist/core/runner/gate-exit.js +4 -3
  214. package/dist/core/runner/image.d.ts +7 -17
  215. package/dist/core/runner/image.js +9 -60
  216. package/dist/core/runner/permission-rule-lanes.d.ts +11 -11
  217. package/dist/core/runner/permission-rule-lanes.js +39 -17
  218. package/dist/core/runner/person-path-rows.d.ts +12 -9
  219. package/dist/core/runner/person-path-rows.js +18 -7
  220. package/dist/core/runner/prepare-acquire-reconcile.d.ts +3 -0
  221. package/dist/core/runner/prepare-acquire-reconcile.js +2 -1
  222. package/dist/core/runner/prepare-ask-lane.d.ts +2 -2
  223. package/dist/core/runner/prepare-ask-lane.js +5 -2
  224. package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -6
  225. package/dist/core/runner/prepare-caps-and-workflow.js +4 -3
  226. package/dist/core/runner/prepare-config-doors.d.ts +35 -38
  227. package/dist/core/runner/prepare-config-doors.js +46 -28
  228. package/dist/core/runner/prepare-defer-classify.d.ts +4 -3
  229. package/dist/core/runner/prepare-defer-classify.js +7 -8
  230. package/dist/core/runner/prepare-file-history.d.ts +48 -8
  231. package/dist/core/runner/prepare-file-history.js +7 -39
  232. package/dist/core/runner/prepare-gate-stations.d.ts +1 -1
  233. package/dist/core/runner/prepare-gate-stations.js +10 -1
  234. package/dist/core/runner/prepare-hands-readface.d.ts +5 -9
  235. package/dist/core/runner/prepare-hands-readface.js +17 -14
  236. package/dist/core/runner/prepare-inherited-gate.d.ts +6 -3
  237. package/dist/core/runner/prepare-inherited-gate.js +5 -3
  238. package/dist/core/runner/prepare-memory-engine-session.js +1 -1
  239. package/dist/core/runner/prepare-park-ask.d.ts +2 -0
  240. package/dist/core/runner/prepare-park-ask.js +7 -7
  241. package/dist/core/runner/prepare-policy-chain.d.ts +6 -3
  242. package/dist/core/runner/prepare-policy-chain.js +67 -76
  243. package/dist/core/runner/prepare-prompt-assembly.d.ts +5 -7
  244. package/dist/core/runner/prepare-prompt-assembly.js +10 -8
  245. package/dist/core/runner/prepare-prompt-inputs.d.ts +11 -9
  246. package/dist/core/runner/prepare-prompt-inputs.js +3 -5
  247. package/dist/core/runner/prepare-protocol-tools.d.ts +2 -0
  248. package/dist/core/runner/prepare-protocol-tools.js +3 -3
  249. package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
  250. package/dist/core/runner/prepare-safety-scan.js +0 -17
  251. package/dist/core/runner/prepare-suspend-saga.d.ts +2 -0
  252. package/dist/core/runner/prepare-suspend-saga.js +5 -6
  253. package/dist/core/runner/prepare-task.d.ts +5 -2
  254. package/dist/core/runner/prepare-task.js +48 -43
  255. package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +20 -4
  256. package/dist/core/runner/prepare-tool-disclosure-mount.js +33 -23
  257. package/dist/core/runner/prepare-turn-wiring.d.ts +0 -4
  258. package/dist/core/runner/prepare-turn-wiring.js +2 -7
  259. package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -2
  260. package/dist/core/runner/prepare-wiring-manifest.js +3 -3
  261. package/dist/core/runner/resume-admission.js +1 -1
  262. package/dist/core/runner/resume-apply.js +11 -12
  263. package/dist/core/runner/resume-checkpoint-screen.js +3 -0
  264. package/dist/core/runner/resume-claim.d.ts +4 -2
  265. package/dist/core/runner/resume-claim.js +15 -8
  266. package/dist/core/runner/retired-runner-deps.js +1 -0
  267. package/dist/core/runner/rewind-files.d.ts +12 -0
  268. package/dist/core/runner/rewind-files.js +90 -0
  269. package/dist/core/runner/run-attachment-seats.js +2 -1
  270. package/dist/core/runner/run-brain-sinks.d.ts +4 -1
  271. package/dist/core/runner/run-brain-sinks.js +4 -2
  272. package/dist/core/runner/run-harness-handlers.js +12 -4
  273. package/dist/core/runner/run-leg.d.ts +1 -1
  274. package/dist/core/runner/run-leg.js +40 -39
  275. package/dist/core/runner/run-notification-lane.d.ts +2 -0
  276. package/dist/core/runner/run-notification-lane.js +2 -2
  277. package/dist/core/runner/run-recovery-lanes.js +3 -4
  278. package/dist/core/runner/run-settle-and-teardown.js +7 -12
  279. package/dist/core/runner/run-terminal-adoption.js +3 -4
  280. package/dist/core/runner/run-turn-boundary.js +4 -15
  281. package/dist/core/runner/runtask.d.ts +10 -0
  282. package/dist/core/runner/runtask.js +35 -42
  283. package/dist/core/runner/send-message-continuation.js +1 -1
  284. package/dist/core/runner/session-read-file-states.d.ts +15 -0
  285. package/dist/core/runner/session-read-file-states.js +28 -0
  286. package/dist/core/runner/session-rule-policy.js +4 -3
  287. package/dist/core/runner/session-verb-doors.d.ts +28 -0
  288. package/dist/core/runner/session-verb-doors.js +48 -0
  289. package/dist/core/runner/session-write-ledger.d.ts +30 -0
  290. package/dist/core/runner/session-write-ledger.js +101 -0
  291. package/dist/core/runner/shell-env-withheld.d.ts +33 -0
  292. package/dist/core/runner/shell-env-withheld.js +51 -0
  293. package/dist/core/runner/skills-seat.js +6 -2
  294. package/dist/core/runner/stream-settle-backstop.js +12 -15
  295. package/dist/core/runner/sub-agent-deny-lists.d.ts +25 -3
  296. package/dist/core/runner/sub-agent-deny-lists.js +25 -17
  297. package/dist/core/runner/synthetic-tools.d.ts +6 -0
  298. package/dist/core/runner/synthetic-tools.js +4 -1
  299. package/dist/core/runner/teardown-bounded.d.ts +1 -0
  300. package/dist/core/runner/teardown-bounded.js +1 -0
  301. package/dist/core/runner/tool-disclosure.d.ts +10 -12
  302. package/dist/core/runner/tool-disclosure.js +1 -3
  303. package/dist/core/runner/tool-end-body.d.ts +1 -1
  304. package/dist/core/runner/tool-end-body.js +10 -9
  305. package/dist/core/runner/tool-not-executed.d.ts +5 -0
  306. package/dist/core/runner/tool-not-executed.js +11 -0
  307. package/dist/core/runner/tool-occurrence.d.ts +8 -0
  308. package/dist/core/runner/tool-occurrence.js +7 -0
  309. package/dist/core/runner/turn-attachments.d.ts +33 -15
  310. package/dist/core/runner/turn-attachments.js +62 -37
  311. package/dist/core/runner-deps.d.ts +7 -7
  312. package/dist/core/safety-axis-vocab.d.ts +6 -4
  313. package/dist/core/safety-axis-vocab.js +6 -5
  314. package/dist/core/safety-merge-corpus.js +11 -3
  315. package/dist/core/secret-env.d.ts +30 -3
  316. package/dist/core/secret-env.js +47 -8
  317. package/dist/core/select-model.js +3 -3
  318. package/dist/core/session-policy-store.d.ts +32 -15
  319. package/dist/core/session-policy-store.js +156 -36
  320. package/dist/core/session-store.d.ts +29 -10
  321. package/dist/core/session-store.js +51 -19
  322. package/dist/core/session.d.ts +82 -16
  323. package/dist/core/session.js +53 -0
  324. package/dist/core/shell-read-silence.d.ts +11 -12
  325. package/dist/core/shell-read-silence.js +9 -5
  326. package/dist/core/shell-run-candidates.js +3 -1
  327. package/dist/core/shell-wrapper-projection.d.ts +1 -1
  328. package/dist/core/shell-wrapper-projection.js +1 -1
  329. package/dist/core/shell-wrapper-table.d.ts +14 -7
  330. package/dist/core/shell-wrapper-table.js +5 -4
  331. package/dist/core/side-query.js +10 -1
  332. package/dist/core/skill-grant.d.ts +7 -2
  333. package/dist/core/skill-grant.js +5 -0
  334. package/dist/core/skills-directory.js +6 -2
  335. package/dist/core/store-contracts/background-agent-store-contract.js +1 -0
  336. package/dist/core/store-contracts/checkpoint-store-contract.d.ts +11 -1
  337. package/dist/core/store-contracts/checkpoint-store-contract.js +141 -2
  338. package/dist/core/store-contracts/file-history-store-contract.js +40 -1
  339. package/dist/core/store-contracts/mailbox-store-contract.js +49 -1
  340. package/dist/core/store-contracts/peer-directory-contract.d.ts +7 -2
  341. package/dist/core/store-contracts/peer-directory-contract.js +14 -2
  342. package/dist/core/store-contracts/session-repo-contract.js +51 -0
  343. package/dist/core/store-contracts/session-store-contract.d.ts +2 -1
  344. package/dist/core/store-contracts/session-store-contract.js +150 -14
  345. package/dist/core/stub-env.d.ts +2 -0
  346. package/dist/core/stub-env.js +1 -0
  347. package/dist/core/synthetic-read-verdict.js +3 -3
  348. package/dist/core/task-event.d.ts +32 -4
  349. package/dist/core/task-notification.d.ts +16 -12
  350. package/dist/core/task-registry-agent.d.ts +8 -4
  351. package/dist/core/task-registry-agent.js +14 -8
  352. package/dist/core/task-registry-shared.d.ts +35 -6
  353. package/dist/core/task-registry-shared.js +11 -0
  354. package/dist/core/task-registry.d.ts +10 -1
  355. package/dist/core/task-registry.js +12 -2
  356. package/dist/core/task-result.d.ts +18 -0
  357. package/dist/core/task-spec.d.ts +18 -13
  358. package/dist/core/tighten-task-spec.js +2 -1
  359. package/dist/core/tool-catalog-entries.d.ts +23 -0
  360. package/dist/core/tool-catalog-entries.js +14 -2
  361. package/dist/core/tool-check-reading.d.ts +11 -0
  362. package/dist/core/tool-check-reading.js +11 -6
  363. package/dist/core/tool-model-gate.d.ts +2 -2
  364. package/dist/core/tool-name-aliases.d.ts +48 -18
  365. package/dist/core/tool-name-aliases.js +36 -19
  366. package/dist/core/tool-name-readings.d.ts +6 -32
  367. package/dist/core/tool-name-readings.js +2 -9
  368. package/dist/core/tool-policy.d.ts +78 -204
  369. package/dist/core/tool-policy.js +152 -204
  370. package/dist/core/tool-result-store.js +3 -0
  371. package/dist/core/tool-roster.d.ts +14 -19
  372. package/dist/core/tool-roster.js +11 -44
  373. package/dist/core/tool-spec-members.js +7 -2
  374. package/dist/core/tool-spec.d.ts +19 -11
  375. package/dist/core/tools.js +49 -9
  376. package/dist/core/trace.d.ts +6 -3
  377. package/dist/core/trace.js +2 -1
  378. package/dist/core/types.d.ts +1 -1
  379. package/dist/core/untrusted-egress.d.ts +20 -0
  380. package/dist/core/untrusted-egress.js +77 -3
  381. package/dist/core/user-attachment.d.ts +8 -1
  382. package/dist/core/user-attachment.js +64 -4
  383. package/dist/core/wiring-manifest.d.ts +9 -0
  384. package/dist/core/wiring-manifest.js +1 -0
  385. package/dist/core/workflow-journal-store.js +1 -1
  386. package/dist/engine/compaction/compaction.js +3 -2
  387. package/dist/engine/execution-env/node-execution-env.d.ts +7 -3
  388. package/dist/engine/execution-env/node-execution-env.js +11 -2
  389. package/dist/engine/harness/agent-harness.d.ts +32 -6
  390. package/dist/engine/harness/agent-harness.js +65 -9
  391. package/dist/engine/harness/types.d.ts +29 -2
  392. package/dist/engine/llm/types.d.ts +28 -11
  393. package/dist/engine/loop/agent-loop.d.ts +23 -4
  394. package/dist/engine/loop/agent-loop.js +42 -30
  395. package/dist/engine/loop/types.d.ts +16 -6
  396. package/dist/engine/session/memory-repo.d.ts +9 -2
  397. package/dist/engine/session/memory-repo.js +11 -1
  398. package/dist/engine/session/repo-utils.d.ts +6 -5
  399. package/dist/engine/session/repo-utils.js +14 -6
  400. package/dist/index.d.ts +34 -17
  401. package/dist/index.js +22 -11
  402. package/dist/internal/harness-types.d.ts +1 -1
  403. package/dist/internal/harness.d.ts +2 -1
  404. package/dist/internal/harness.js +1 -0
  405. package/dist/internal/llm.d.ts +1 -1
  406. package/dist/orchestration/run-workflow-tool.d.ts +6 -4
  407. package/dist/orchestration/run-workflow-tool.js +5 -3
  408. package/dist/orchestration/workflow.d.ts +3 -0
  409. package/dist/orchestration/workflow.js +36 -18
  410. package/dist/primitives/credential-ref.d.ts +89 -0
  411. package/dist/primitives/credential-ref.js +125 -0
  412. package/dist/primitives/index.d.ts +2 -0
  413. package/dist/primitives/index.js +1 -0
  414. package/dist/prompt-assembly/artifact.d.ts +2 -2
  415. package/dist/prompt-assembly/artifact.js +5 -3
  416. package/dist/prompt-assembly/assemble.d.ts +3 -2
  417. package/dist/prompt-assembly/assemble.js +1 -1
  418. package/dist/prompt-assembly/catalog/schema.d.ts +43 -12
  419. package/dist/prompt-assembly/catalog/schema.js +34 -2
  420. package/dist/prompt-assembly/catalog/sections.js +0 -1
  421. package/dist/prompt-assembly/composer.d.ts +3 -1
  422. package/dist/prompt-assembly/composer.js +1 -1
  423. package/dist/prompt-assembly/event-registry.js +1 -0
  424. package/dist/prompt-assembly/overlay.js +3 -3
  425. package/dist/prompt-assembly/renderers.d.ts +1 -1
  426. package/dist/prompt-assembly/renderers.js +0 -3
  427. package/dist/prompt-assembly/role-base.d.ts +15 -0
  428. package/dist/prompt-assembly/role-base.js +9 -0
  429. package/dist/prompt-assembly/select.d.ts +39 -14
  430. package/dist/prompt-assembly/select.js +47 -16
  431. package/dist/prompt-assembly/sugar.d.ts +17 -11
  432. package/dist/prompt-assembly/sugar.js +8 -3
  433. package/dist/prompt-assembly/tool-catalog.d.ts +37 -3
  434. package/dist/prompt-assembly/tool-catalog.js +114 -4
  435. package/dist/prompt-assembly/turn-snapshot.d.ts +4 -10
  436. package/dist/prompt-assembly/turn-snapshot.js +0 -3
  437. package/dist/prompt-assembly/types.d.ts +0 -7
  438. package/dist/scenarios/full-body.d.ts +11 -11
  439. package/dist/scenarios/full-body.js +4 -3
  440. package/dist/shell/lex.js +10 -1
  441. package/dist/stores/file/adoption/adopt.js +4 -3
  442. package/dist/stores/file/adoption/marker.js +3 -2
  443. package/dist/stores/file/checkpoint-store.d.ts +21 -4
  444. package/dist/stores/file/checkpoint-store.js +38 -7
  445. package/dist/stores/file/file-history-store.js +18 -11
  446. package/dist/stores/file/index.js +2 -1
  447. package/dist/stores/file/mailbox-store.d.ts +2 -1
  448. package/dist/stores/file/mailbox-store.js +26 -1
  449. package/dist/stores/file/permission-rule-adopt.js +4 -3
  450. package/dist/stores/file/permission-rule-store.js +11 -5
  451. package/dist/stores/file/session-store.d.ts +29 -6
  452. package/dist/stores/file/session-store.js +42 -50
  453. package/dist/tools/artifact/artifact-tool.js +3 -2
  454. package/dist/tools/fs/bash-program-position.d.ts +19 -2
  455. package/dist/tools/fs/bash-program-position.js +56 -9
  456. package/dist/tools/fs/bash-readonly-classifier.d.ts +15 -19
  457. package/dist/tools/fs/bash-readonly-classifier.js +5 -10
  458. package/dist/tools/fs/fs-bash.js +15 -8
  459. package/dist/tools/fs/fs-glob.d.ts +86 -0
  460. package/dist/tools/fs/fs-glob.js +226 -0
  461. package/dist/tools/fs/fs-read.js +14 -14
  462. package/dist/tools/fs/fs-search-tools.js +7 -7
  463. package/dist/tools/fs/pattern-kill-guard.d.ts +23 -0
  464. package/dist/tools/fs/pattern-kill-guard.js +429 -0
  465. package/dist/tools/fs/pdf.d.ts +9 -6
  466. package/dist/tools/fs/pdf.js +3 -3
  467. package/dist/tools/fs/program-read-model.d.ts +57 -7
  468. package/dist/tools/fs/program-read-model.js +11 -1
  469. package/dist/tools/fs/program-read-model.rows.js +78 -21
  470. package/dist/tools/fs/read-deny-home.js +3 -2
  471. package/dist/tools/fs/removal-targets.d.ts +17 -7
  472. package/dist/tools/fs/removal-targets.js +47 -20
  473. package/dist/tools/fs/search.d.ts +10 -0
  474. package/dist/tools/fs/search.js +20 -26
  475. package/dist/tools/fs/shell-read-argv.js +89 -12
  476. package/dist/tools/fs/shell-read-bindings.d.ts +31 -0
  477. package/dist/tools/fs/shell-read-bindings.js +41 -0
  478. package/dist/tools/fs/shell-read-check.d.ts +10 -0
  479. package/dist/tools/fs/shell-read-check.js +13 -20
  480. package/dist/tools/fs/shell-read-environment.d.ts +5 -1
  481. package/dist/tools/fs/shell-read-environment.js +3 -2
  482. package/dist/tools/fs/shell-read-establish.d.ts +15 -0
  483. package/dist/tools/fs/shell-read-establish.js +19 -20
  484. package/dist/tools/fs/shell-read-identity.d.ts +12 -9
  485. package/dist/tools/fs/shell-read-identity.js +9 -4
  486. package/dist/tools/fs/shell-read-plan.js +24 -16
  487. package/dist/tools/fs/shell-read-start.d.ts +6 -1
  488. package/dist/tools/fs/shell-read-write-targets.d.ts +5 -1
  489. package/dist/tools/fs/shell-read-write-targets.js +2 -3
  490. package/dist/tools/fs/shell-reentry-text.d.ts +9 -0
  491. package/dist/tools/fs/shell-reentry-text.js +40 -2
  492. package/dist/tools/todo.js +63 -63
  493. package/dist/tools/web.d.ts +19 -14
  494. package/dist/tools/web.js +46 -61
  495. package/package.json +1 -1
  496. package/test/export-surface.snapshot.json +221 -7
  497. package/wire-changes/core-stores-sql@7.57.0.json +29 -0
  498. package/wire-changes/core@7.56.0.json +3891 -0
  499. package/wire-changes/core@7.57.0.json +1487 -0
  500. package/wire-changes/mods-kernel@7.56.0.json +303 -0
  501. package/wire-changes/mods-kernel@7.57.0.json +29 -0
  502. package/wire-changes/primitives@7.57.0.json +245 -0
@@ -668,14 +668,13 @@ export interface PersistedRuleHitRule {
668
668
  * the whole command is a one-element set (the historical case); a compound admitted by the conjunction
669
669
  * of per-segment rules (design/375 §5.1) is the set of those rules, in segment order. For a `deny` or an
670
670
  * `ask` the set is the one rule of that behavior that reaches the call (the lane's precedence walk —
671
- * deny > ask > allow — already chose it). `rules` is non-empty by contract — an empty set covers nothing
672
- * and is not a hit (the normalizer reads it as a clean negative).
671
+ * deny > ask > allow — already chose it). `rules` is non-empty by contract: a lane with no rule for the call answers
672
+ * `undefined`, and an empty set is an answer the gate cannot read (`unreadable`).
673
673
  *
674
674
  * Why dots and not an id: a persisted rule HAS no scalar id — it is a (behavior, text, scope) group whose identity is
675
675
  * the set of add dots that redeemed it, and two concurrently approved records for one text each carry their own.
676
676
  *
677
- * The pre-375 single-rule object shape (`{ rule, dots? }`) and the pre-behavior `{ rules }` shape are NOT accepted:
678
- * on this loosening seam an unrecognized answer degrades to a clean negative (more asks), never to a match.
677
+ * The pre-375 `{ rule, dots? }` and the pre-behavior `{ rules }` shapes are NOT accepted: they read as `unreadable`.
679
678
  */
680
679
  export interface PersistedRuleHit {
681
680
  /** What the deciding rule(s) say about the call — the closed set's word. */
@@ -699,7 +698,8 @@ export interface PersistedRuleUnreadable {
699
698
  /** WHY the lane could not read: absent for a store (or partition) read failure — the store form, a real-approval ask of
700
699
  * class `rule_unreadable`; for a CALL the lane could not read against the person's standing deny/ask rows (an
701
700
  * expansion where a rule reads a word, an unterminated quote, a syntax error) the lexer's reason — the call form, an allow
702
- * tightens to a real-approval ask of the same class. Both carry the origin `rule_store_unavailable`. */
701
+ * tightens to a real-approval ask of the same class — also the gate's reading of a lane answer it cannot read (the reason
702
+ * then names this seat and the failed field). Both carry the origin `rule_store_unavailable`. */
703
703
  readonly reason?: string;
704
704
  }
705
705
  /**
@@ -714,8 +714,8 @@ export interface PersistedRuleUnreadable {
714
714
  export interface PersistedRuleCoverage {
715
715
  readonly segmentCoverage: readonly import("./permission-rule-model.js").SegmentCoverage[];
716
716
  }
717
- /** Every shape a lane may answer with. The retired bare-string form (a single allow rule's text) is read
718
- * by the normalizer as a clean negative, like every other unrecognized shape. */
717
+ /** Every shape a lane may answer with: `undefined` and the coverage answer say "no rule speaks"; any other value (`null`, a
718
+ * bare string, a `behavior` outside the closed set, …) is read by the normalizer as `unreadable`, naming the field. */
719
719
  export type PersistedRuleAnswer = PersistedRuleHit | PersistedRuleCoverage | PersistedRuleUnreadable | undefined;
720
720
  /** Inputs to the two-phase tool gate. `adjudicate`/`resolveAsk` are pre-bound to the task abort
721
721
  * signal; when the caller also supplies {@link ToolGateInput.callSignal}, the Runner's closures
@@ -1099,7 +1099,7 @@ export interface ToolGateInput extends PermissionSeatInputs, SkillGateSeats, All
1099
1099
  * notice is composed from (`ask-unresolvable-notice.ts`); `parkLaneExisted` = a park lane was armed for this run; `remedy` = the
1100
1100
  * caller-side change that would have let the call run, present for the causes that say nobody could be asked (`approver_unavailable`,
1101
1101
  * `no_approver_wired`) — for arguments no approval can be bound to, the binding's own sentence (the remedy's approver half would not
1102
- * let them run). Observe-only: a throwing seat never alters the deny. Absent ⇒ the deny stands silently (no notice sink).
1102
+ * let them run); `remedies` = its ways out as data, beside `remedy`. Observe-only: a throwing seat never alters the deny. Absent ⇒ the deny stands silently (no notice sink).
1103
1103
  */
1104
1104
  onAskUnresolvable?: (info: {
1105
1105
  toolName: string;
@@ -1107,6 +1107,7 @@ export interface ToolGateInput extends PermissionSeatInputs, SkillGateSeats, All
1107
1107
  cause: import("./ask-unresolvable-notice.js").AskUnresolvableCause;
1108
1108
  parkLaneExisted: boolean;
1109
1109
  remedy?: string;
1110
+ remedies?: readonly import("./ask-origin.js").ApprovalRemedy[];
1110
1111
  }) => void;
1111
1112
  /**
1112
1113
  * design/153 §2/§7.4 (件4 复审, MED): true means this call's ask is MARKED — an inherited ancestor
@@ -1173,7 +1174,7 @@ export interface ToolGateInput extends PermissionSeatInputs, SkillGateSeats, All
1173
1174
  persistedRules?: {
1174
1175
  /** The lane's verdict for this call — a {@link PersistedRuleHit} naming the behavior that spoke and
1175
1176
  * the rule set it stands on, a coverage-carrying clean negative, an unreadable report, or
1176
- * `undefined` (the store was READ and no rule speaks). Must not throw — and a store (or a partition of it) that cannot
1177
+ * `undefined` (the store was READ and no rule speaks; `null` is not that word). Must not throw — and a store (or a partition of it) that cannot
1177
1178
  * be read answers `{ unreadable: true }`, not `undefined`: it fails closed (a row nobody could read may forbid the call;
1178
1179
  * the decision becomes a real-approval ask) and the evidence records `"unavailable"`, not `"no_match"`; the lane owns
1179
1180
  * announcing the skip. A call unreadable against the rows answers `{ unreadable: true, reason }` (the call form).
@@ -1183,9 +1184,9 @@ export interface ToolGateInput extends PermissionSeatInputs, SkillGateSeats, All
1183
1184
  * per-segment conjunction (design/375 §5.1) is the set of the covering rules. The dots are a rule's
1184
1185
  * durable identity, and the text is not one (it reaches a card sanitized and capped); a lane that
1185
1186
  * can name them lets the shadowed-ask evidence say WHICH stored rules matched rather than merely
1186
- * what they looked like. The retired shapes — a bare rule TEXT, the pre-375 `{ rule, dots? }` object,
1187
- * a `{ rules }` hit without its behavior — are read as a clean negative by the normalizer: a stale
1188
- * lane degrades toward asking, never toward an allow. Consulted on EVERY decision (a deny/ask row
1187
+ * what they looked like. Every answer outside the shapes above (`null`, a bare rule TEXT, the pre-375 `{ rule, dots? }`
1188
+ * object, a hit without a closed-set `behavior` or a non-empty `rules`) reads as `{ unreadable: true, reason }` — the
1189
+ * call form, naming this seat and the failed field: a real-approval ask, never "no rule". Consulted on EVERY decision (a deny/ask row
1189
1190
  * must be able to tighten an allow), so the lane pays one store read per call on the tools it
1190
1191
  * speaks for; the runner's lane hands the org layer's read to it, so a governed deployment still
1191
1192
  * pays one. */
@@ -1251,8 +1252,8 @@ export interface ToolGateInput extends PermissionSeatInputs, SkillGateSeats, All
1251
1252
  /**
1252
1253
  * F-012 L2 — the SANDBOX ADMISSION leg. Present ONLY when the runner armed the mode: the execution
1253
1254
  * env DECLARES isolation (`RemoteExecutionEnv.capabilities.isolation === true` — a Runner-resolved
1254
- * fact, never caller self-report) AND the park prerequisites hold (durable park configured + a
1255
- * checkpoint store that explicitly declares `redecision.reopen`). Absent ⇒ the whole step does not
1255
+ * fact, never caller self-report) AND the park prerequisites hold (durable park configured + a wired
1256
+ * checkpoint store — every store carries the required `reopen`, read at its seat). Absent ⇒ the whole step does not
1256
1257
  * exist and the decision path is byte-identical to a build without it.
1257
1258
  *
1258
1259
  * Semantics (the ruling): inside a declared sandbox, an engine-authored "confirm a potentially
@@ -1394,10 +1395,10 @@ export declare function askCarryRowMembers(carry: AskCarry | undefined): {
1394
1395
  * 2. **adjudicate** — run the tool policy on the FINAL `currentInput` (never the model's stale args),
1395
1396
  * fold it with any remembered hook-ask via `deny > ask > allow`, and resolve a surviving `ask`
1396
1397
  * through `onAsk`. The policy ALWAYS runs regardless of the hook's verdict. A policy `allow` may
1397
- * itself carry an `updatedInput` rewrite (redact/clamp), applied last over any hook rewrite.
1398
+ * itself carry an `updatedInput` rewrite (redact/clamp), applied last over any hook rewrite — which the hook, having
1399
+ * judged the earlier bytes, judges once (rewrite-rejudge.ts: a deny or yet another form there refuses the call).
1398
1400
  *
1399
- * Because both phases run in this one linear function, the ordering — and the "policy is final"
1400
- * invariant — is enforced by the call stack, not by registration convention. Returns the gate result
1401
- * for the harness `tool_call` hook plus the PreToolUse context to attach to the tool result.
1401
+ * Both phases run in this one linear function, so the ordering — and the "policy is final" invariant — is the call stack's,
1402
+ * not a registration convention. Returns the gate result for the `tool_call` hook plus the PreToolUse context for the result.
1402
1403
  */
1403
1404
  export declare function runToolGate(input: ToolGateInput): Promise<ToolGateResult>;
@@ -98,6 +98,7 @@ function preToolUseAnswerViolation(answer) {
98
98
  return undefined;
99
99
  return typeof r.message === "string" ? r.message : "the PreToolUse answer was refused by the engine";
100
100
  }
101
+ const PRE_TOOL_USE_RANKS = Object.freeze({ of: (a) => { const r = a === ENGINE_CORE_ANSWER ? undefined : screenPreToolUseResult(a); return !r ? 0 : r.action === "deny" ? 3 : r.action === "ask" ? (r.requiresRealApproval === true ? 2 : 1) : 0; }, top: 3 });
101
102
  function preToolUseRefusedReason(subject, failed) {
102
103
  if (failed === undefined) {
103
104
  return `the task was cancelled while a PreToolUse hook was still screening ${subject}; the call was NOT executed ` + `(fail-closed). No verdict was reached — this is the run ending, not the tool failing.`;
@@ -130,7 +131,7 @@ export function createPreToolUseScreening(input) {
130
131
  screen: async (args, subject) => {
131
132
  let outcome;
132
133
  try {
133
- outcome = await dispatchClassic(bus, "classic.PreToolUse", eventOf(args), { ...(input.abortSignal !== undefined ? { signal: input.abortSignal } : {}), checkAnswer: preToolUseAnswerViolation });
134
+ outcome = await dispatchClassic(bus, "classic.PreToolUse", eventOf(args), { ...(input.abortSignal !== undefined ? { signal: input.abortSignal } : {}), checkAnswer: preToolUseAnswerViolation, ranks: PRE_TOOL_USE_RANKS });
134
135
  }
135
136
  catch (err) {
136
137
  return { kind: "refused", reason: preToolUseRefusedReason(subject, { kind: "failed", registration: "engine", cause: "threw", reason: `could not raise the screening: ${describeThrown(err)}`, skipped: [] }) };
@@ -162,6 +163,7 @@ export function createPreToolUseConstraintPolicy(chain, env) {
162
163
  participant: judges,
163
164
  ...(signal !== undefined ? { signal } : {}),
164
165
  checkAnswer: (a) => (a === ENGINE_CORE_ANSWER ? undefined : preToolUseAnswerViolation(a)),
166
+ ranks: PRE_TOOL_USE_RANKS,
165
167
  });
166
168
  }
167
169
  catch (err) {
@@ -0,0 +1,128 @@
1
+ import { type HostReading } from "./host-target.js";
2
+ import type { ToolPolicy } from "./tool-policy.js";
3
+ /**
4
+ * Is this host obviously internal — loopback / private ranges / link-local incl. cloud metadata / CGNAT / IPv6 ULA, site-local,
5
+ * unspecified, IPv4-mapped, NAT64? Classifies with `net.isIP` rather than a string-prefix regex (a prefix regex both under-matches
6
+ * — `::ffff:`, NAT64, CGNAT, `::` — and over-matches any DNS name starting `fc`/`fd`). Numeric IPv4 forms (decimal/octal/hex) are
7
+ * normalized to dotted-decimal by `URL` before this is called. Checks the LITERAL host: it does NOT resolve DNS, so a name that
8
+ * resolves to a private address is not caught here (a connection-layer concern).
9
+ */
10
+ export declare function isPrivateHost(host: string): boolean;
11
+ /**
12
+ * `RunnerDeps.hostFloor` — the hosts this deployment's structured egress may reach, read by the gate and by every engine executor
13
+ * that opens a connection (the fetch tool, task images, MCP http servers, A2A peers, WebSearch's SearXNG backend). Entries are host patterns: `example.com` (that
14
+ * host) or `*.example.com` (every host below it, never itself).
15
+ */
16
+ export interface HostFloorDeclaration {
17
+ /** Hosts this deployment never reaches. */
18
+ readonly deny?: readonly string[];
19
+ /** Present ⇒ the ONLY hosts this deployment reaches (`[]` = none, legal and explicit). An entry that names a private address (or
20
+ * `localhost`) also lifts the private-network floor for it — the deployment named it. */
21
+ readonly only?: readonly string[];
22
+ }
23
+ /** Where a host stands on the floor. */
24
+ export type HostFloorReach = "denied" | "outside_only" | "admitted";
25
+ /** The floor's posture — what the wiring manifest reports (counts, never the entries' text). */
26
+ export interface HostFloorPosture {
27
+ readonly onlyMode: boolean;
28
+ readonly denyCount: number;
29
+ readonly onlyCount: number;
30
+ }
31
+ /** A compiled host floor (frozen). */
32
+ export interface HostFloor {
33
+ /** The entries in their one spelling (`example.com`, `*.example.com`) — what an enforcement point outside the engine (an egress
34
+ * proxy, a container policy) is generated from. */
35
+ readonly entries: {
36
+ readonly deny: readonly string[];
37
+ readonly only?: readonly string[];
38
+ };
39
+ readonly posture: HostFloorPosture;
40
+ /** Where this host (as `hostOfUrl` reads it) stands: a `deny` entry reaches it ⇒ `denied`; an `only` list that reaches it not ⇒
41
+ * `outside_only`; else `admitted`. */
42
+ reach(host: string): HostFloorReach;
43
+ /** Does an `only` entry name this host — the one way a private host becomes reachable? */
44
+ lifts(host: string): boolean;
45
+ }
46
+ /** The code a host floor that does not read refuses the prepare with (and a resume before its claim). */
47
+ export declare const HOST_FLOOR_INVALID_CODE = "config.host_floor_invalid";
48
+ /**
49
+ * The declaration as the engine holds it: read ONCE through the engine's declaration receipt (`DECLARATION_RECEIPT_MODE`: every own
50
+ * member off its captured descriptor, a getter called once, every level copied and frozen; a Proxy at any level, a non-plain object —
51
+ * a `Map`, a class instance, an object of another prototype — and anything that is not data refused). A frozen copy received again is
52
+ * the same data, so the Runner's construction (which keeps this copy) and every prepare after it read one declaration.
53
+ */
54
+ export declare function receiveHostFloor(declared: unknown): unknown;
55
+ /**
56
+ * Compile `RunnerDeps.hostFloor` once (absent ⇒ undefined: no floor), from the declaration's receipt ({@link receiveHostFloor}). A
57
+ * declaration that does not read — not plain data, not a record, a member other than `deny` / `only`, a member that is not a list,
58
+ * an entry that is no host pattern, an `only` entry every host of which a `deny` entry also reaches (it could never admit anything)
59
+ * — throws {@link HOST_FLOOR_INVALID_CODE}, naming the member and entry.
60
+ */
61
+ export declare function compileHostFloor(declared: HostFloorDeclaration | undefined): HostFloor | undefined;
62
+ /** The floor's half of the judge, on a host reading: a host it does not admit, or no host it can read, is refused (the sentence);
63
+ * undefined when the floor admits it. The gate's narrowing layer reads this half alone (the private-network floor is the
64
+ * connecting executor's). */
65
+ export declare function floorRefusal(reading: HostReading, floor: HostFloor): string | undefined;
66
+ /**
67
+ * The gate's reader of the floor — a deny-only narrowing layer core owns (no rule, mode or approver clears it): a call whose URL slot
68
+ * (`callHostTargetOf`, the protective reading) names a host the floor does not admit, or names no host it can read, is refused before
69
+ * anything else is asked; a call with no URL slot is not this layer's. Composed by the policy chain like the other narrowing layers, so
70
+ * it also re-judges a rewritten call and an approved call on resume.
71
+ */
72
+ export declare function hostFloorPolicy(floor: HostFloor): ToolPolicy;
73
+ /**
74
+ * THE judge of one egress hop, before it is requested: the URL must be http(s) and name a host the rules can read (`hostOfUrl`), the
75
+ * deployment's floor must admit that host, and — for an executor that holds the private-network floor (`privateFloor`: the fetch
76
+ * tool and task images) — a private host must be one an `only` entry names. Returns the refusal sentence, or undefined.
77
+ */
78
+ export declare function hopRefusal(url: URL, floor: HostFloor | undefined, privateFloor: boolean): string | undefined;
79
+ /** The code a protocol peer's request is refused with when the hop judge refuses its URL — the declared endpoint at a dial, an A2A
80
+ * card's endpoint, a redirect target (a `config.*` word: the deployment named a peer its own floor does not admit — and, floor or
81
+ * none, a peer's redirect that names credentials or whose Location does not read gets it too). */
82
+ export declare const HOST_FLOOR_REFUSED_CODE = "config.host_floor_refused";
83
+ /** The refusal a protocol request carries when {@link hopRefusal} refuses its URL (no private-network floor: an MCP endpoint and an
84
+ * A2A peer's declared URL are the deployment's own declaration; an A2A card's endpoint and a redirect target are the peer's words and get none
85
+ * today). `what` names the request (`mcp: server "x"`, `a2a: peer "y"`). */
86
+ export declare function peerRequestRefusal(what: string, url: URL, floor: HostFloor | undefined): (Error & {
87
+ code: string;
88
+ }) | undefined;
89
+ /** How a transport follows redirects: its hop judge, whether it takes a judged redirect, and its hop budget. */
90
+ export interface FollowLaw {
91
+ /** The hop judge (each transport binds {@link hopRefusal} to its floor and its private-network posture). */
92
+ readonly refusal: (url: URL) => string | undefined;
93
+ /** Whether a redirect the judge admitted is followed (else it is handed back as `unfollowed`). */
94
+ readonly follows: (from: URL, to: URL) => boolean;
95
+ /** Redirects followed at most (the request after the last one is refused as `too_many`). */
96
+ readonly maxRedirects: number;
97
+ /** Every hop's response, 3xx included, as it arrives. */
98
+ readonly onResponse?: (res: Response) => void;
99
+ }
100
+ /** One request's outcome under a {@link FollowLaw}. */
101
+ export type FollowOutcome = {
102
+ readonly kind: "answered";
103
+ readonly res: Response;
104
+ } | {
105
+ readonly kind: "refused";
106
+ readonly reason: string;
107
+ } | {
108
+ readonly kind: "unfollowed";
109
+ readonly res: Response;
110
+ readonly from: URL;
111
+ readonly to: URL;
112
+ } | {
113
+ readonly kind: "too_many";
114
+ };
115
+ /** The request init a followed hop is sent with. */
116
+ export interface FollowInit {
117
+ readonly method: string;
118
+ readonly headers: Readonly<Record<string, string>>;
119
+ readonly body?: string;
120
+ readonly signal?: AbortSignal;
121
+ }
122
+ /**
123
+ * ONE request, following redirects by hand: every hop is judged ({@link FollowLaw.refusal}) BEFORE it is requested — the first URL
124
+ * and every redirect target — so a hop the judge refuses is never contacted; a judged redirect the transport does not take is handed
125
+ * back with its response; a status outside the fetch standard's redirect set (301, 302, 303, 307, 308), or one of them without a
126
+ * Location, is the answer. A Location that does not parse is a refusal. A redirect's response that is followed or refused is released.
127
+ */
128
+ export declare function fetchFollowing(doFetch: typeof fetch, start: URL, init: FollowInit, law: FollowLaw): Promise<FollowOutcome>;
@@ -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
+ }
@@ -11,12 +11,47 @@
11
11
  * Leaf module: it reads the catalog's host slots (the protective floor) and the name-reading seat, nothing else.
12
12
  */
13
13
  import { type ToolCallLike } from "./tool-registry.js";
14
- /** The host a spelling names as the URL parser reads it (trailing dots read off), or undefined when the spelling is more or
15
- * less than a host: empty, carrying whitespace or a separator a URL reads as something else, a port (a `:` outside an
16
- * address's brackets), credentials, a path. */
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. */
17
27
  export declare function hostOfSpelling(spelled: string): string | undefined;
18
28
  /** Is this host (as {@link hostOfUrl} reads it) an address — the URL parser's IPv4 form or a bracketed IPv6? */
19
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;
20
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:
21
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
22
57
  * are read off (`https://2130706433../` — the parser keeps the name, the rule side reads `127.0.0.1`). */
@@ -1,23 +1,56 @@
1
1
  import { hostTargetOf } from "./tool-registry.js";
2
2
  import { seatOf } from "./tool-name-readings.js";
3
- export function hostOfSpelling(spelled) {
3
+ export function readSpelledHost(spelled) {
4
4
  if (spelled === "" || /[\s/\\@?#%]/.test(spelled) || (spelled.includes(":") && !/^\[[^\]]+\]$/.test(spelled)))
5
- return undefined;
5
+ return { problem: "not_a_host" };
6
6
  let url;
7
7
  try {
8
8
  url = new URL(`https://${spelled}/`);
9
9
  }
10
10
  catch {
11
- return undefined;
11
+ return { problem: "not_a_host" };
12
12
  }
13
13
  if (url.port !== "" || url.username !== "" || url.password !== "" || url.pathname !== "/" || url.search !== "" || url.hash !== "")
14
- return undefined;
14
+ return { problem: "not_a_host" };
15
15
  const host = url.hostname.replace(/\.+$/, "");
16
- return host === "" ? undefined : host;
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;
17
23
  }
18
24
  export function isAddressHost(host) {
19
25
  return host.startsWith("[") || /^\d+\.\d+\.\d+\.\d+$/.test(host);
20
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
+ }
21
54
  export const HOST_UNREADABLE_REASONS = Object.freeze(["not_text", "not_url", "not_http", "credentials", "unstable"]);
22
55
  export const HOST_UNREADABLE_SENTENCE = Object.freeze({
23
56
  not_text: "the URL argument is not a string",