@sema-agent/core 7.51.2 → 7.53.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 (446) hide show
  1. package/CHANGELOG.md +698 -2
  2. package/README.md +3 -1
  3. package/dist/agents/agent-transcript-tool.d.ts +1 -1
  4. package/dist/agents/cascade.js +4 -0
  5. package/dist/agents/cross-session-envelope.d.ts +8 -0
  6. package/dist/agents/cross-session-envelope.js +6 -0
  7. package/dist/agents/cross-session-judge.d.ts +21 -1
  8. package/dist/agents/cross-session-judge.js +8 -0
  9. package/dist/agents/cross-session-ref.d.ts +5 -0
  10. package/dist/agents/cross-session-ref.js +1 -0
  11. package/dist/agents/cumulative-stats.d.ts +3 -0
  12. package/dist/agents/cumulative-stats.js +3 -0
  13. package/dist/agents/list-agents-tool.d.ts +1 -1
  14. package/dist/agents/org-delivery-gate.d.ts +122 -0
  15. package/dist/agents/org-delivery-gate.js +69 -0
  16. package/dist/agents/peer-held-queue.d.ts +9 -4
  17. package/dist/agents/peer-held-queue.js +6 -5
  18. package/dist/agents/peer-session-drain.d.ts +35 -5
  19. package/dist/agents/peer-session-drain.js +271 -180
  20. package/dist/agents/read-inbox-tool.d.ts +8 -1
  21. package/dist/agents/read-inbox-tool.js +5 -1
  22. package/dist/agents/repair-loop.js +4 -0
  23. package/dist/agents/send-message-tool.d.ts +11 -16
  24. package/dist/agents/send-message-tool.js +11 -13
  25. package/dist/agents/subagent.d.ts +3 -0
  26. package/dist/agents/subagent.js +105 -76
  27. package/dist/agents/tool-filter.d.ts +58 -13
  28. package/dist/agents/tool-filter.js +34 -14
  29. package/dist/bench/metrics.d.ts +1 -0
  30. package/dist/brain/anthropic.d.ts +6 -1
  31. package/dist/brain/anthropic.js +17 -13
  32. package/dist/brain/model-presets.d.ts +4 -5
  33. package/dist/brain/model-presets.js +6 -5
  34. package/dist/brain/open-responses.js +16 -12
  35. package/dist/brain/openai.js +16 -12
  36. package/dist/brain/request-params.d.ts +12 -33
  37. package/dist/brain/request-params.js +5 -2
  38. package/dist/brain/request-route.d.ts +9 -8
  39. package/dist/brain/request-route.js +1 -0
  40. package/dist/brain/route-adjudicator.d.ts +123 -47
  41. package/dist/brain/route-adjudicator.js +171 -42
  42. package/dist/brain/route-conformance.js +2 -2
  43. package/dist/brain/routing.d.ts +24 -1
  44. package/dist/brain/routing.js +54 -19
  45. package/dist/brain/status-sink.d.ts +18 -0
  46. package/dist/brain/status-sink.js +7 -0
  47. package/dist/brain/timeout.js +5 -4
  48. package/dist/core/a2a.d.ts +5 -2
  49. package/dist/core/a2a.js +30 -13
  50. package/dist/core/allow-entry.d.ts +42 -9
  51. package/dist/core/allow-entry.js +25 -18
  52. package/dist/core/auto-compaction.d.ts +80 -20
  53. package/dist/core/auto-compaction.js +65 -18
  54. package/dist/core/auto-promote.d.ts +2 -1
  55. package/dist/core/auto-promote.js +2 -2
  56. package/dist/core/caller-tool-name.d.ts +9 -0
  57. package/dist/core/caller-tool-name.js +13 -0
  58. package/dist/core/checkpoint-requirements.d.ts +7 -1
  59. package/dist/core/checkpoint-requirements.js +2 -0
  60. package/dist/core/checkpoint-store.d.ts +57 -24
  61. package/dist/core/checkpoint-store.js +3 -3
  62. package/dist/core/child-clamp-seats.d.ts +6 -0
  63. package/dist/core/child-clamp-seats.js +2 -1
  64. package/dist/core/compliance.js +3 -1
  65. package/dist/core/credential-vocabulary.d.ts +33 -8
  66. package/dist/core/credential-vocabulary.js +32 -7
  67. package/dist/core/decision-receipt.d.ts +2 -2
  68. package/dist/core/delegation-frames.d.ts +9 -2
  69. package/dist/core/delegation-name.d.ts +18 -0
  70. package/dist/core/delegation-name.js +47 -0
  71. package/dist/core/effective-path-target.d.ts +25 -6
  72. package/dist/core/effective-path-target.js +24 -2
  73. package/dist/core/engine-capabilities.d.ts +8 -1
  74. package/dist/core/engine-capabilities.js +1 -1
  75. package/dist/core/engine-notice.d.ts +49 -21
  76. package/dist/core/frontmatter-fence.d.ts +10 -0
  77. package/dist/core/frontmatter-fence.js +6 -0
  78. package/dist/core/gate-fold.js +8 -25
  79. package/dist/core/gate-lanes.js +358 -274
  80. package/dist/core/gate-outcome.d.ts +11 -6
  81. package/dist/core/governance-codes.d.ts +11 -4
  82. package/dist/core/governance-codes.js +12 -3
  83. package/dist/core/hands-band-screen.d.ts +7 -0
  84. package/dist/core/hands-band-screen.js +32 -0
  85. package/dist/core/hooks.d.ts +283 -739
  86. package/dist/core/hooks.js +100 -193
  87. package/dist/{tools/fs → core}/image-admission.d.ts +21 -3
  88. package/dist/{tools/fs → core}/image-admission.js +24 -6
  89. package/dist/core/locked-config.d.ts +84 -32
  90. package/dist/core/locked-config.js +128 -42
  91. package/dist/core/mcp-connection-pool.d.ts +4 -1
  92. package/dist/core/mcp-connection-pool.js +7 -2
  93. package/dist/core/mcp-probe.d.ts +12 -9
  94. package/dist/core/mcp-probe.js +3 -3
  95. package/dist/core/mcp-server-spec.d.ts +104 -10
  96. package/dist/core/mcp-server-spec.js +183 -33
  97. package/dist/core/mcp.d.ts +31 -20
  98. package/dist/core/mcp.js +66 -56
  99. package/dist/core/memory-engine/data-plane.js +5 -1
  100. package/dist/core/memory-engine/distiller.js +16 -2
  101. package/dist/core/memory-engine/engine.d.ts +22 -30
  102. package/dist/core/memory-engine/engine.js +16 -10
  103. package/dist/core/memory-engine/frontmatter.d.ts +6 -0
  104. package/dist/core/memory-engine/frontmatter.js +19 -16
  105. package/dist/core/memory.d.ts +2 -2
  106. package/dist/core/mode-policy.d.ts +5 -16
  107. package/dist/core/mode-policy.js +7 -19
  108. package/dist/core/model-seat.d.ts +4 -1
  109. package/dist/core/mods/dollar.d.ts +109 -0
  110. package/dist/core/mods/dollar.js +154 -0
  111. package/dist/core/mods/host.d.ts +23 -0
  112. package/dist/core/mods/host.js +21 -0
  113. package/dist/core/mods/kernel/budget.d.ts +43 -0
  114. package/dist/core/mods/kernel/budget.js +83 -0
  115. package/dist/core/mods/kernel/dispatch.d.ts +100 -0
  116. package/dist/core/mods/kernel/dispatch.js +699 -0
  117. package/dist/core/mods/kernel/events.d.ts +245 -0
  118. package/dist/core/mods/kernel/events.js +210 -0
  119. package/dist/core/mods/kernel/index.d.ts +6 -0
  120. package/dist/core/mods/kernel/index.js +5 -0
  121. package/dist/core/mods/kernel/receive.d.ts +94 -0
  122. package/dist/core/mods/kernel/receive.js +188 -0
  123. package/dist/core/mods/kernel/registration.d.ts +131 -0
  124. package/dist/core/mods/kernel/registration.js +102 -0
  125. package/dist/core/mods/kernel/site-rules.d.ts +149 -0
  126. package/dist/core/mods/kernel/site-rules.js +296 -0
  127. package/dist/core/mods/stations.d.ts +344 -0
  128. package/dist/core/mods/stations.js +437 -0
  129. package/dist/core/mounted-mcp.d.ts +57 -0
  130. package/dist/core/mounted-mcp.js +71 -2
  131. package/dist/core/own-property-receipt.d.ts +13 -0
  132. package/dist/core/own-property-receipt.js +13 -23
  133. package/dist/core/parent-spec-seat.d.ts +18 -7
  134. package/dist/core/parent-spec-seat.js +6 -2
  135. package/dist/core/path-identity.js +2 -1
  136. package/dist/core/permission-rule-model.d.ts +58 -9
  137. package/dist/core/permission-rule-model.js +81 -7
  138. package/dist/core/permission-rule-org.d.ts +163 -33
  139. package/dist/core/permission-rule-org.js +205 -71
  140. package/dist/core/permission-rule-syntax.d.ts +15 -0
  141. package/dist/core/permission-rule-syntax.js +24 -16
  142. package/dist/core/permission-rules.d.ts +14 -2
  143. package/dist/core/permission-rules.js +63 -23
  144. package/dist/core/prompt-section-seat.d.ts +15 -27
  145. package/dist/core/prompt-section-seat.js +73 -40
  146. package/dist/core/protocol-http-auth.d.ts +3 -1
  147. package/dist/core/protocol-http-auth.js +2 -0
  148. package/dist/core/reminder-mint.d.ts +2 -2
  149. package/dist/core/remote-env.d.ts +24 -12
  150. package/dist/core/remote-env.js +1 -0
  151. package/dist/core/resume-startup-cause.d.ts +16 -1
  152. package/dist/core/resume-startup-cause.js +4 -1
  153. package/dist/core/retention.js +7 -2
  154. package/dist/core/retired-keys.d.ts +12 -2
  155. package/dist/core/retired-keys.js +15 -1
  156. package/dist/core/roles.js +60 -10
  157. package/dist/core/rule-lane-reads.js +1 -1
  158. package/dist/core/runner/announce-once-ledger.d.ts +31 -1
  159. package/dist/core/runner/announce-once-ledger.js +22 -0
  160. package/dist/core/runner/assemble-result.d.ts +9 -0
  161. package/dist/core/runner/assemble-result.js +3 -1
  162. package/dist/core/runner/call-hook-stations.d.ts +23 -27
  163. package/dist/core/runner/call-hook-stations.js +58 -42
  164. package/dist/core/runner/caller-stop-gate.d.ts +25 -0
  165. package/dist/core/runner/caller-stop-gate.js +7 -0
  166. package/dist/core/runner/compaction-seams.d.ts +8 -22
  167. package/dist/core/runner/compaction-seams.js +28 -53
  168. package/dist/core/runner/construction-doors.js +11 -1
  169. package/dist/core/runner/contracts.d.ts +86 -83
  170. package/dist/core/runner/credential-origin-seat.d.ts +2 -0
  171. package/dist/core/runner/credential-origin-seat.js +19 -0
  172. package/dist/core/runner/extra-body-dropped-seat.d.ts +2 -6
  173. package/dist/core/runner/gate-exit.d.ts +47 -36
  174. package/dist/core/runner/gate-exit.js +12 -5
  175. package/dist/core/runner/image.js +1 -2
  176. package/dist/core/runner/inline-image.js +1 -1
  177. package/dist/core/runner/mcp-redial.d.ts +52 -10
  178. package/dist/core/runner/mcp-redial.js +38 -9
  179. package/dist/core/runner/notice-seat-input.d.ts +11 -0
  180. package/dist/core/runner/notice-seat-input.js +1 -0
  181. package/dist/core/runner/permission-rule-lanes.d.ts +5 -2
  182. package/dist/core/runner/permission-rule-lanes.js +22 -10
  183. package/dist/core/runner/person-path-rows.d.ts +3 -1
  184. package/dist/core/runner/person-path-rows.js +3 -2
  185. package/dist/core/runner/prepare-acquire-reconcile.js +5 -1
  186. package/dist/core/runner/prepare-ask-lane.d.ts +5 -7
  187. package/dist/core/runner/prepare-ask-lane.js +6 -15
  188. package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -2
  189. package/dist/core/runner/prepare-caps-and-workflow.js +25 -8
  190. package/dist/core/runner/prepare-config-doors.d.ts +52 -1
  191. package/dist/core/runner/prepare-config-doors.js +168 -143
  192. package/dist/core/runner/prepare-defer-classify.js +7 -11
  193. package/dist/core/runner/prepare-delegation-surface.d.ts +2 -2
  194. package/dist/core/runner/prepare-delegation-surface.js +7 -5
  195. package/dist/core/runner/prepare-gate-stations.d.ts +8 -11
  196. package/dist/core/runner/prepare-gate-stations.js +11 -10
  197. package/dist/core/runner/prepare-hands-readface.d.ts +1 -1
  198. package/dist/core/runner/prepare-hands-readface.js +2 -1
  199. package/dist/core/runner/prepare-inherited-gate.d.ts +8 -12
  200. package/dist/core/runner/prepare-inherited-gate.js +10 -23
  201. package/dist/core/runner/prepare-listings.d.ts +1 -1
  202. package/dist/core/runner/prepare-listings.js +4 -2
  203. package/dist/core/runner/prepare-memory-engine-session.d.ts +0 -6
  204. package/dist/core/runner/prepare-memory-engine-session.js +20 -7
  205. package/dist/core/runner/prepare-memory.d.ts +3 -2
  206. package/dist/core/runner/prepare-memory.js +6 -2
  207. package/dist/core/runner/prepare-offload-wrappers.d.ts +4 -4
  208. package/dist/core/runner/prepare-offload-wrappers.js +2 -1
  209. package/dist/core/runner/prepare-park-ask.js +10 -14
  210. package/dist/core/runner/prepare-policy-chain.d.ts +17 -15
  211. package/dist/core/runner/prepare-policy-chain.js +104 -109
  212. package/dist/core/runner/prepare-project-context.d.ts +1 -1
  213. package/dist/core/runner/prepare-project-context.js +11 -12
  214. package/dist/core/runner/prepare-prompt-assembly.d.ts +45 -40
  215. package/dist/core/runner/prepare-prompt-assembly.js +138 -101
  216. package/dist/core/runner/prepare-prompt-inputs.d.ts +28 -23
  217. package/dist/core/runner/prepare-prompt-inputs.js +11 -10
  218. package/dist/core/runner/prepare-protocol-tools.d.ts +11 -7
  219. package/dist/core/runner/prepare-protocol-tools.js +20 -13
  220. package/dist/core/runner/prepare-question-face.d.ts +4 -2
  221. package/dist/core/runner/prepare-question-face.js +4 -3
  222. package/dist/core/runner/prepare-safety-scan.js +6 -10
  223. package/dist/core/runner/prepare-suspend-saga.d.ts +6 -0
  224. package/dist/core/runner/prepare-suspend-saga.js +7 -5
  225. package/dist/core/runner/prepare-task.js +41 -23
  226. package/dist/core/runner/prepare-turn-wiring.d.ts +13 -15
  227. package/dist/core/runner/prepare-turn-wiring.js +29 -27
  228. package/dist/core/runner/prepare-wiring-manifest.d.ts +13 -9
  229. package/dist/core/runner/prepare-wiring-manifest.js +14 -11
  230. package/dist/core/runner/resume-admission.d.ts +4 -1
  231. package/dist/core/runner/resume-admission.js +7 -5
  232. package/dist/core/runner/resume-apply.d.ts +5 -2
  233. package/dist/core/runner/resume-apply.js +24 -42
  234. package/dist/core/runner/resume-checkpoint-screen.d.ts +1 -0
  235. package/dist/core/runner/resume-checkpoint-screen.js +9 -1
  236. package/dist/core/runner/resume-internals-and-config.d.ts +3 -3
  237. package/dist/core/runner/resume-internals-and-config.js +3 -8
  238. package/dist/core/runner/resume-preflight.js +38 -16
  239. package/dist/core/runner/retired-runner-deps.d.ts +5 -6
  240. package/dist/core/runner/retired-runner-deps.js +4 -5
  241. package/dist/core/runner/run-brain-sinks.d.ts +3 -2
  242. package/dist/core/runner/run-brain-sinks.js +5 -1
  243. package/dist/core/runner/run-compaction-machinery.d.ts +7 -1
  244. package/dist/core/runner/run-compaction-machinery.js +7 -33
  245. package/dist/core/runner/run-harness-handlers.js +4 -2
  246. package/dist/core/runner/run-identity-wiring.d.ts +3 -1
  247. package/dist/core/runner/run-identity-wiring.js +3 -2
  248. package/dist/core/runner/run-leg.js +103 -95
  249. package/dist/core/runner/run-notification-lane.js +1 -0
  250. package/dist/core/runner/run-recovery-lanes.d.ts +3 -0
  251. package/dist/core/runner/run-recovery-lanes.js +14 -11
  252. package/dist/core/runner/run-settle-and-teardown.js +9 -28
  253. package/dist/core/runner/run-stop-and-final-verify.js +18 -25
  254. package/dist/core/runner/run-terminal-adoption.d.ts +3 -0
  255. package/dist/core/runner/run-terminal-adoption.js +34 -22
  256. package/dist/core/runner/run-tool-mount-facts.js +5 -3
  257. package/dist/core/runner/run-turn-boundary.js +32 -37
  258. package/dist/core/runner/runtask.d.ts +6 -7
  259. package/dist/core/runner/runtask.js +15 -73
  260. package/dist/core/runner/session-rule-policy.d.ts +5 -5
  261. package/dist/core/runner/session-rule-policy.js +13 -8
  262. package/dist/core/runner/side-call-account.d.ts +68 -0
  263. package/dist/core/runner/side-call-account.js +61 -0
  264. package/dist/core/runner/skills-seat.d.ts +15 -0
  265. package/dist/core/runner/skills-seat.js +57 -0
  266. package/dist/core/runner/stream-halt-verbs.js +12 -17
  267. package/dist/core/runner/stream-lifecycle-verbs.js +8 -5
  268. package/dist/core/runner/stream-steer-verb.d.ts +1 -1
  269. package/dist/core/runner/stream-steer-verb.js +20 -38
  270. package/dist/core/runner/sub-agent-deny-lists.d.ts +124 -23
  271. package/dist/core/runner/sub-agent-deny-lists.js +230 -71
  272. package/dist/core/runner/synthetic-tools.d.ts +5 -2
  273. package/dist/core/runner/synthetic-tools.js +2 -12
  274. package/dist/core/runner/tool-end-body.d.ts +5 -6
  275. package/dist/core/runner/tool-end-body.js +6 -4
  276. package/dist/core/runner/tool-not-executed.d.ts +15 -0
  277. package/dist/core/runner/tool-not-executed.js +30 -0
  278. package/dist/core/runner/tool-occurrence.d.ts +8 -7
  279. package/dist/core/runner/tool-occurrence.js +5 -5
  280. package/dist/core/runner/tool-result-media-seat.d.ts +1 -1
  281. package/dist/core/runner-deps.d.ts +43 -36
  282. package/dist/core/safety-merge-corpus.js +18 -2
  283. package/dist/core/secret-env.d.ts +88 -20
  284. package/dist/core/secret-env.js +192 -38
  285. package/dist/core/session-policy-store.d.ts +71 -16
  286. package/dist/core/session-policy-store.js +138 -28
  287. package/dist/core/session-reconcile.d.ts +4 -0
  288. package/dist/core/session-reconcile.js +2 -1
  289. package/dist/core/shell-read-silence.js +3 -32
  290. package/dist/core/side-query.d.ts +5 -3
  291. package/dist/core/skill-grant.d.ts +3 -2
  292. package/dist/core/skill-grant.js +17 -9
  293. package/dist/core/skills-directory.d.ts +31 -11
  294. package/dist/core/skills-directory.js +655 -104
  295. package/dist/core/store-contracts/mailbox-store-contract.js +13 -0
  296. package/dist/core/task-event.d.ts +49 -3
  297. package/dist/core/task-notification.js +2 -2
  298. package/dist/core/task-result.d.ts +8 -0
  299. package/dist/core/task-spec.d.ts +20 -19
  300. package/dist/core/task-stream.d.ts +14 -4
  301. package/dist/core/tighten-task-spec.d.ts +4 -3
  302. package/dist/core/tighten-task-spec.js +2 -4
  303. package/dist/core/tool-check-reading.d.ts +74 -0
  304. package/dist/core/tool-check-reading.js +80 -0
  305. package/dist/core/tool-policy.d.ts +62 -18
  306. package/dist/core/tool-policy.js +86 -15
  307. package/dist/core/tool-registry.d.ts +20 -0
  308. package/dist/core/tool-registry.js +4 -0
  309. package/dist/core/tool-spec.d.ts +10 -6
  310. package/dist/core/tools.js +2 -0
  311. package/dist/core/trace.d.ts +51 -32
  312. package/dist/core/types.d.ts +2 -2
  313. package/dist/core/types.js +1 -1
  314. package/dist/core/unc-spelling.d.ts +10 -0
  315. package/dist/core/unc-spelling.js +3 -0
  316. package/dist/core/untrusted-egress.d.ts +8 -0
  317. package/dist/core/untrusted-egress.js +4 -1
  318. package/dist/core/untrusted-text.d.ts +16 -0
  319. package/dist/core/untrusted-text.js +7 -2
  320. package/dist/core/user-attachment.d.ts +25 -4
  321. package/dist/core/user-attachment.js +63 -42
  322. package/dist/core/wiring-manifest.d.ts +18 -15
  323. package/dist/core/wiring-manifest.js +2 -2
  324. package/dist/engine/compaction/utils.js +1 -2
  325. package/dist/engine/execution-env/node-execution-env.d.ts +4 -3
  326. package/dist/engine/execution-env/symlink-chain.js +1 -1
  327. package/dist/engine/harness/agent-harness.d.ts +1 -1
  328. package/dist/engine/harness/agent-harness.js +5 -4
  329. package/dist/engine/harness/types.d.ts +20 -16
  330. package/dist/engine/harness/types.js +7 -1
  331. package/dist/engine/llm/types.d.ts +12 -7
  332. package/dist/engine/loop/agent-loop.d.ts +12 -1
  333. package/dist/engine/loop/agent-loop.js +18 -6
  334. package/dist/engine/loop/types.d.ts +8 -2
  335. package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
  336. package/dist/engine/session/import-validate.js +3 -10
  337. package/dist/engine/session/session.d.ts +4 -4
  338. package/dist/engine/session/session.js +4 -4
  339. package/dist/index.d.ts +33 -23
  340. package/dist/index.js +23 -15
  341. package/dist/internal/harness.d.ts +2 -1
  342. package/dist/internal/harness.js +2 -1
  343. package/dist/orchestration/goal.d.ts +24 -1
  344. package/dist/orchestration/goal.js +3 -2
  345. package/dist/orchestration/run-spec.d.ts +4 -6
  346. package/dist/orchestration/run-spec.js +39 -63
  347. package/dist/orchestration/run-workflow-tool.js +1 -2
  348. package/dist/orchestration/workflow.d.ts +11 -3
  349. package/dist/orchestration/workflow.js +11 -2
  350. package/dist/prompt-assembly/artifact-store.d.ts +72 -56
  351. package/dist/prompt-assembly/artifact-store.js +60 -52
  352. package/dist/prompt-assembly/artifact.d.ts +90 -76
  353. package/dist/prompt-assembly/artifact.js +197 -145
  354. package/dist/prompt-assembly/assemble.d.ts +36 -29
  355. package/dist/prompt-assembly/assemble.js +34 -220
  356. package/dist/prompt-assembly/bands.d.ts +20 -0
  357. package/dist/prompt-assembly/bands.js +18 -0
  358. package/dist/prompt-assembly/catalog/constitution.d.ts +23 -0
  359. package/dist/prompt-assembly/catalog/constitution.js +69 -0
  360. package/dist/prompt-assembly/catalog/core-behavior.d.ts +9 -0
  361. package/dist/prompt-assembly/catalog/core-behavior.js +85 -0
  362. package/dist/prompt-assembly/catalog/index.d.ts +11 -0
  363. package/dist/prompt-assembly/catalog/index.js +60 -0
  364. package/dist/prompt-assembly/catalog/memory.d.ts +13 -0
  365. package/dist/prompt-assembly/catalog/memory.js +6 -0
  366. package/dist/prompt-assembly/catalog/modes.d.ts +15 -0
  367. package/dist/prompt-assembly/catalog/modes.js +137 -0
  368. package/dist/prompt-assembly/catalog/role.d.ts +10 -0
  369. package/dist/prompt-assembly/catalog/role.js +157 -0
  370. package/dist/prompt-assembly/catalog/schema.d.ts +138 -0
  371. package/dist/prompt-assembly/catalog/schema.js +25 -0
  372. package/dist/prompt-assembly/catalog/sections.d.ts +9 -0
  373. package/dist/prompt-assembly/catalog/sections.js +98 -0
  374. package/dist/prompt-assembly/catalog/team.d.ts +4 -0
  375. package/dist/prompt-assembly/catalog/team.js +258 -0
  376. package/dist/prompt-assembly/composer.d.ts +26 -28
  377. package/dist/prompt-assembly/composer.js +124 -46
  378. package/dist/prompt-assembly/epoch.d.ts +89 -79
  379. package/dist/prompt-assembly/epoch.js +115 -142
  380. package/dist/prompt-assembly/explain.d.ts +58 -34
  381. package/dist/prompt-assembly/explain.js +21 -24
  382. package/dist/prompt-assembly/overlay.d.ts +137 -0
  383. package/dist/prompt-assembly/overlay.js +339 -0
  384. package/dist/prompt-assembly/renderers.d.ts +21 -0
  385. package/dist/prompt-assembly/renderers.js +39 -0
  386. package/dist/prompt-assembly/section-usage.d.ts +3 -3
  387. package/dist/prompt-assembly/section-usage.js +1 -1
  388. package/dist/prompt-assembly/select.d.ts +71 -0
  389. package/dist/prompt-assembly/select.js +106 -0
  390. package/dist/prompt-assembly/sugar.d.ts +31 -0
  391. package/dist/prompt-assembly/sugar.js +20 -0
  392. package/dist/prompt-assembly/turn-snapshot.d.ts +3 -2
  393. package/dist/prompt-assembly/types.d.ts +45 -148
  394. package/dist/prompts/coordinator.d.ts +2 -21
  395. package/dist/prompts/coordinator.js +3 -255
  396. package/dist/prompts/cowork.d.ts +27 -16
  397. package/dist/prompts/cowork.js +2 -23
  398. package/dist/prompts/default.d.ts +38 -511
  399. package/dist/prompts/default.js +20 -288
  400. package/dist/prompts/supervisor.d.ts +6 -71
  401. package/dist/prompts/supervisor.js +6 -117
  402. package/dist/stores/file/permission-rule-store.d.ts +1 -1
  403. package/dist/stores/file/permission-rule-store.js +2 -1
  404. package/dist/tools/artifact/artifact-tool.js +4 -3
  405. package/dist/tools/fs/bash-readonly-classifier.d.ts +6 -5
  406. package/dist/tools/fs/dir-entries.d.ts +4 -2
  407. package/dist/tools/fs/dir-entries.js +16 -4
  408. package/dist/tools/fs/fs-bash.d.ts +1 -1
  409. package/dist/tools/fs/fs-bash.js +22 -11
  410. package/dist/tools/fs/fs-pdf.js +17 -13
  411. package/dist/tools/fs/fs-read.js +4 -3
  412. package/dist/tools/fs/fs-shared.d.ts +1 -10
  413. package/dist/tools/fs/fs-shared.js +3 -4
  414. package/dist/tools/fs/fs-write.js +2 -1
  415. package/dist/tools/fs/notebook.js +1 -1
  416. package/dist/tools/fs/pdf.d.ts +20 -10
  417. package/dist/tools/fs/pdf.js +19 -10
  418. package/dist/tools/fs/program-read-model.d.ts +68 -8
  419. package/dist/tools/fs/program-read-model.js +112 -33
  420. package/dist/tools/fs/program-read-model.rows.js +30 -10
  421. package/dist/tools/fs/read-deny-home.d.ts +25 -9
  422. package/dist/tools/fs/read-deny-home.js +28 -27
  423. package/dist/tools/fs/read-deny.d.ts +41 -11
  424. package/dist/tools/fs/read-deny.js +51 -5
  425. package/dist/tools/fs/safety.d.ts +4 -26
  426. package/dist/tools/fs/safety.js +10 -32
  427. package/dist/tools/fs/search.js +15 -10
  428. package/dist/tools/fs/shell-read-argv.d.ts +3 -2
  429. package/dist/tools/fs/shell-read-argv.js +118 -38
  430. package/dist/tools/fs/shell-read-establish.d.ts +5 -5
  431. package/dist/tools/fs/shell-read-establish.js +11 -61
  432. package/dist/tools/fs/shell-read-identity.js +6 -3
  433. package/dist/tools/fs/shell-read-judge.d.ts +13 -15
  434. package/dist/tools/fs/shell-read-judge.js +18 -4
  435. package/dist/tools/fs/shell-read-plan.d.ts +2 -2
  436. package/dist/tools/web.js +1 -1
  437. package/package.json +13 -1
  438. package/test/export-surface.snapshot.json +306 -103
  439. package/wire-changes/core@7.52.0.json +5859 -0
  440. package/wire-changes/core@7.53.0.json +1946 -0
  441. package/dist/core/hook-seats.d.ts +0 -66
  442. package/dist/core/hook-seats.js +0 -37
  443. package/dist/prompt-assembly/packs/sema-default.d.ts +0 -2
  444. package/dist/prompt-assembly/packs/sema-default.js +0 -147
  445. package/dist/prompts/simple-sections.d.ts +0 -58
  446. package/dist/prompts/simple-sections.js +0 -43
@@ -9,30 +9,36 @@ import { type ToolNameListReading } from "../core/tool-name-list.js";
9
9
  * root run (`TaskSpec.allowTools` / `TaskSpec.excludeTools`) and every child (its definition's lists, under the ceiling of the
10
10
  * run that spawned it), so there is no spawn-time filter and no complement anywhere.
11
11
  *
12
- * - an allowed list absent, or holding `"*"`, sets no allowlist on its layer; otherwise the layer keeps only what it names
12
+ * - an allowed list absent, or holding `"*"` (any spelling the rule syntax reads as it: `*()`, `*(*)`), sets no allowlist on
13
+ * its layer; otherwise the layer keeps only what it names
13
14
  * (`[]` keeps nothing — intentional, not a mistake);
14
15
  * - a denied list removes what it names from whatever remains (a denied tool always loses);
15
16
  * - a layer above a run (its ceiling) bounds it: a child's `"*"` never widens what its parent could use.
16
17
  *
17
- * An entry is read as the reference reads a rule string ({@link readDeniedEntry}: `Tool(content)` names `Tool`, the content is
18
- * not read, the whole tool is hidden); a protocol spelling (`mcp__srv`, `mcp__srv__*`, a glob over the tool segment) reaches the
18
+ * An entry is read by the rule syntax ({@link readDeniedEntry}: `Tool(content)` names `Tool`, the content is not read, the
19
+ * whole tool is hidden; an entry the syntax cannot read names no tool); a protocol spelling (`mcp__srv`, `mcp__srv__*`, a glob over the tool segment) reaches the
19
20
  * tools of that peer, including ones it lists later; an entry no tool answers to is kept by name and reaches one mounted later.
20
21
  * Judged at the prepare that receives it: a spelling no tool name can have is refused, an unknown name told (`sub-agent-deny-lists.ts`).
21
22
  *
22
- * Note: `"*"` in an allowed list is the "allow all" sentinel, so a tool literally NAMED `"*"` cannot be
23
- * the sole allowed tool via this path (tool names are conventionally identifiers, so this is moot).
23
+ * `"*"` in an allowed list is the "allow all" sentinel and never a name: no tool is named `*` (the caller tool name
24
+ * contract, `caller-tool-name.ts`, refuses it at the mount; engine and protocol-minted names never are).
24
25
  */
25
26
  /**
26
- * How ONE denied-tools entry is read — the reference reads each as a rule string, without trimming: `Tool(content)` names
27
- * `Tool` (the content is dropped, so the whole tool is hidden), `Tool()` and `Tool(*)` are the bare name, and anything else
28
- * — a malformed paren form, an entry with surrounding whitespace — is the whole string, which names no tool. A value that is
29
- * not a string (a list a host read from a file can hold anything) names no tool either: it reads as `not_a_string` with a
30
- * fixed label of its TYPE, and nothing about the value is read, converted or printed — `typeof` and the array test only.
27
+ * How ONE denied-tools entry is read — by the rule syntax's own test of a rule spelling (`ruleSpellingOf`, the one every entry
28
+ * list's reader asks), exactly as written: `Tool(content)` names `Tool` (the content is not read here, so the whole tool is
29
+ * hidden), `Tool()` and `Tool(*)` are the bare name. An entry the syntax cannot read — surrounding whitespace, a tool name
30
+ * outside its spelling (a blank or an invisible character before the `(`, a leading `-`), a parenthesis that does not close
31
+ * the entry — names no tool: `unreadable`, the entry as written. A value that is not a string (a list a host read from a file
32
+ * can hold anything) names no tool either: it reads as `not_a_string` with a fixed label of its TYPE, and nothing about the
33
+ * value is read, converted or printed — `typeof` and the array test only.
31
34
  */
32
35
  export type DeniedEntryReading = {
33
36
  readonly kind: "name";
34
37
  readonly name: string;
35
38
  readonly content: boolean;
39
+ } | {
40
+ readonly kind: "unreadable";
41
+ readonly entry: string;
36
42
  } | {
37
43
  readonly kind: "not_a_string";
38
44
  readonly type: string;
@@ -79,13 +85,31 @@ export interface ToolNameListReach {
79
85
  readonly covering: readonly string[];
80
86
  readonly wholeProtocols: ReadonlySet<ProtocolId>;
81
87
  }
88
+ /**
89
+ * The tool ONE entry of a list on `side` reaches ({@link readDeniedEntry}) — the one per-entry reading every list reader takes:
90
+ * `Tool()` / `Tool(*)` are the bare `Tool` (`*()` / `*(*)` the wildcard `*`); a denied `Tool(content)` hides the whole `Tool`;
91
+ * an allowed one, an unreadable entry or a non-string reaches nothing (`undefined`).
92
+ */
93
+ export declare function toolNameOfEntry(entry: unknown, side: ToolNameListSide): string | undefined;
94
+ /**
95
+ * Is this entry a bare tool name as the rule syntax reads it, written as such (`Read`, `mcp__srv__*`, `*`; never `Read()`,
96
+ * `Read(*)`, `Read(x)`, an unreadable spelling or a non-string)? The one form a checkpoint row records and is read back in.
97
+ */
98
+ export declare function isCanonicalToolName(entry: unknown): boolean;
99
+ /**
100
+ * A tool-name list as a checkpoint row records it: each entry as {@link toolNameOfEntry} reads it, in canonical spelling, an
101
+ * allowed entry that admits nothing left out — the copy reaches what the list reached, in the spelling a reader accepts
102
+ * ({@link isCanonicalToolName}). An unreadable entry stays as written: prepare refuses it before the park, the reader again.
103
+ */
104
+ export declare function persistedToolNameList(entries: readonly string[], side: ToolNameListSide): string[];
82
105
  /**
83
106
  * What an allowed-tools value admits, or `undefined` when it names no allowlist: absent, `null`, or a list holding the
84
- * wildcard. A list admits its string entries (an entry that is not a string admits nothing); a value that is not a list admits
85
- * NOTHING — the judge before the run refuses it, and a reader that meets it first fails closed.
107
+ * wildcard — an entry {@link toolNameOfEntry} reads as `*` (`*`, `*()`, `*(*)`). A list admits its string entries (an entry that
108
+ * is not a string admits nothing); a value that is not a list admits NOTHING — the judge before the run refuses it, and a
109
+ * reader that meets it first fails closed.
86
110
  */
87
111
  export declare function readAllowedToolList(allowTools: unknown): ToolNameListReach | undefined;
88
- /** What a denied value hides: its string entries read as {@link readDeniedEntry} reads them (an entry that is not a string, or a value that is not a list, hides nothing). */
112
+ /** What a denied value hides: its string entries read as {@link readDeniedEntry} reads them (an entry it reads as `unreadable` or not a string, or a value that is not a list, hides nothing here — the judgment before the run refuses each). */
89
113
  export declare function readDeniedToolList(denyTools: unknown): ToolNameListReach;
90
114
  /** Does the list reach this tool — through its wire name, any alias it declares, or a protocol spelling that covers it? The one matcher. */
91
115
  export declare function listReaches(reach: ToolNameListReach, tool: {
@@ -99,6 +123,9 @@ type UniverseTool = {
99
123
  };
100
124
  /** The wire names a leg of these kinds relies on (the catalog's protocol column). */
101
125
  export declare function protocolToolNames(legs: readonly ToolLegKind[]): string[];
126
+ /** Is this value a layer — an object (not a list) with the two lists `allow` / `deny`? One that is not admits NOTHING here;
127
+ * the judge before the run (`judgeRunToolLists`) refuses it, and a reader that meets it first fails closed. */
128
+ export declare function isToolSelectorLayer(layer: unknown): layer is ToolSelectorLayer;
102
129
  /**
103
130
  * Compile ONE run's tool selector from its layers (the ceiling it was spawned under, then its own lists — the LAST layer is its own)
104
131
  * and the kinds of leg it is. Each list is read by the one reading ({@link readAllowedToolList} / {@link readDeniedToolList}) and
@@ -108,6 +135,24 @@ export declare function protocolToolNames(legs: readonly ToolLegKind[]): string[
108
135
  * producer passes frozen copies of the lists it read.
109
136
  */
110
137
  export declare function compileToolSelector(layers: readonly ToolSelectorLayer[], legs?: readonly ToolLegKind[]): ToolSelector;
138
+ /**
139
+ * What a leg's tool valve leaves mounted — its one reading: nothing under the run's whole-face switch (`excludeAllTools`: every
140
+ * tool unmounts, protocol tools included), else what the compiled selector admits. The valve unmounts by it, and every question
141
+ * prepare asks about the post-valve roster before the valve runs (the full shell's reachability, the memory write channel, the
142
+ * persistence verdict, the two memory pairs' planning) asks it too.
143
+ */
144
+ export declare function valveLeaves(spec: {
145
+ readonly excludeAllTools?: true;
146
+ }, selector: Pick<ToolSelector, "admits">): (tool: UniverseTool) => boolean;
147
+ /**
148
+ * The valve's reading at the SERVER level — {@link valveLeaves} asked of a whole peer before any of its tools is known: can the valve
149
+ * leave a tool of the peer `prefix` (`mcp__srv__`) at all? Nothing under the run's whole-face switch; else what the compiled selector's
150
+ * lists can reach of the peer ({@link ToolSelector.admitsPeer} — read off the lists, never off what the server lists). A peer this
151
+ * answers `false` for leaves no tool on the roster whatever it lists, so a run has no reason to dial it or to teach its instructions.
152
+ */
153
+ export declare function valveLeavesPeer(spec: {
154
+ readonly excludeAllTools?: true;
155
+ }, selector: Pick<ToolSelector, "admitsPeer">): (prefix: string) => boolean;
111
156
  /** One protocol tool a denylist reaches, and whose list it is: the leg's own (the last layer) or one it inherits (a ceiling layer). */
112
157
  export interface DeniedProtocolTool {
113
158
  readonly name: string;
@@ -1,6 +1,6 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { canonicalize, UNCANONICALIZABLE } from "../core/canonical-json.js";
3
- import { parsePermissionRule } from "../core/permission-rule-syntax.js";
3
+ import { ruleSpellingOf } from "../core/permission-rule-syntax.js";
4
4
  import { TOOL_CATALOG_ENTRIES } from "../core/tool-catalog-entries.js";
5
5
  import { isNamespacedCoveringRuleName, namespacedRuleNameCovers } from "../core/namespaced-rule-name.js";
6
6
  import { protocolOf } from "../core/protocol-table.js";
@@ -9,9 +9,9 @@ import { readToolNameList, snapshotToolNameList, valueTypeLabel } from "../core/
9
9
  export function readDeniedEntry(entry) {
10
10
  if (typeof entry !== "string")
11
11
  return { kind: "not_a_string", type: valueTypeLabel(entry) };
12
- if (entry !== entry.trim())
13
- return { kind: "name", name: entry, content: false };
14
- const parsed = parsePermissionRule(entry);
12
+ const parsed = ruleSpellingOf(entry);
13
+ if (parsed === undefined)
14
+ return { kind: "unreadable", entry };
15
15
  return { kind: "name", name: parsed.toolName, content: parsed.ruleContent !== undefined };
16
16
  }
17
17
  const LIST_NOUN = { allowed: "allowed tools", denied: "denied tools" };
@@ -52,18 +52,28 @@ export function snapshotDefinitionLists(def) {
52
52
  copy.denyTools = snapshotToolNameList(copy.denyTools);
53
53
  return copy;
54
54
  }
55
+ export function toolNameOfEntry(entry, side) {
56
+ const read = readDeniedEntry(entry);
57
+ return read.kind === "name" && (side === "denied" || !read.content) ? read.name : undefined;
58
+ }
59
+ export function isCanonicalToolName(entry) {
60
+ const read = readDeniedEntry(entry);
61
+ return read.kind === "name" && !read.content && read.name === entry;
62
+ }
63
+ export function persistedToolNameList(entries, side) {
64
+ return entries.flatMap((entry) => {
65
+ const name = toolNameOfEntry(entry, side);
66
+ if (name !== undefined)
67
+ return [name];
68
+ return readDeniedEntry(entry).kind === "name" ? [] : [entry];
69
+ });
70
+ }
55
71
  function reachOf(entries, side) {
56
72
  const names = new Set();
57
73
  const covering = [];
58
74
  const wholeProtocols = new Set();
59
75
  for (const entry of entries) {
60
- let name;
61
- if (side === "denied") {
62
- const read = readDeniedEntry(entry);
63
- name = read.kind === "name" ? read.name : undefined;
64
- }
65
- else
66
- name = typeof entry === "string" ? entry : undefined;
76
+ const name = toolNameOfEntry(entry, side);
67
77
  if (name === undefined)
68
78
  continue;
69
79
  const split = splitNamespacedName(name);
@@ -85,7 +95,7 @@ export function readAllowedToolList(allowTools) {
85
95
  const list = readToolNameList(allowTools);
86
96
  if (list.kind !== "entries")
87
97
  return reachOf([], "allowed");
88
- if (list.entries.includes("*"))
98
+ if (list.entries.some((entry) => toolNameOfEntry(entry, "allowed") === "*"))
89
99
  return undefined;
90
100
  return reachOf(list.entries, "allowed");
91
101
  }
@@ -129,9 +139,13 @@ function reachCoversPeer(reach, peer) {
129
139
  return split !== undefined && split.ns.id === peer.ns && split.peer === peer.peer && (split.tool === undefined || split.tool === "*");
130
140
  });
131
141
  }
142
+ export function isToolSelectorLayer(layer) {
143
+ return typeof layer === "object" && layer !== null && !Array.isArray(layer);
144
+ }
145
+ const NO_TOOL_LAYER = Object.freeze({ allow: reachOf([], "allowed"), deny: reachOf([], "denied") });
132
146
  export function compileToolSelector(layers, legs = []) {
133
147
  const kept = Object.freeze([...layers]);
134
- const compiled = kept.map((l) => ({ allow: readAllowedToolList(l.allow), deny: readDeniedToolList(l.deny) }));
148
+ const compiled = kept.map((l) => (isToolSelectorLayer(l) ? { allow: readAllowedToolList(l.allow), deny: readDeniedToolList(l.deny) } : NO_TOOL_LAYER));
135
149
  const admittedBy = (ls, tool) => ls.every((l) => (l.allow === undefined || listReaches(l.allow, tool)) && !listReaches(l.deny, tool));
136
150
  const protocol = new Map(PROTOCOL_ROWS.filter((r) => r.legs.some((l) => legs.includes(l))).map((r) => [r.name, r.underCeiling]));
137
151
  return Object.freeze({
@@ -153,8 +167,14 @@ export function compileToolSelector(layers, legs = []) {
153
167
  },
154
168
  });
155
169
  }
170
+ export function valveLeaves(spec, selector) {
171
+ return spec.excludeAllTools === true ? () => false : (tool) => selector.admits(tool);
172
+ }
173
+ export function valveLeavesPeer(spec, selector) {
174
+ return spec.excludeAllTools === true ? () => false : (prefix) => selector.admitsPeer(prefix);
175
+ }
156
176
  export function deniedProtocolTools(layers, legs) {
157
- const denies = layers.map((l) => readDeniedToolList(l.deny));
177
+ const denies = layers.map((l) => readDeniedToolList(isToolSelectorLayer(l) ? l.deny : undefined));
158
178
  const own = denies.slice(-1);
159
179
  const inherited = denies.slice(0, -1);
160
180
  const hits = new Map();
@@ -158,6 +158,7 @@ export interface CoreStatsSubset {
158
158
  nestedSubagentMicroUsd: number;
159
159
  memoryConsolidationMicroUsd: number;
160
160
  compactionMicroUsd: number;
161
+ sideCallMicroUsd?: number;
161
162
  };
162
163
  nested?: {
163
164
  costMicroUsd?: number;
@@ -1,7 +1,7 @@
1
1
  import type { Brain } from "../core/types.js";
2
2
  import { type StreamEngineConfig } from "./stream-engine.js";
3
3
  export interface AnthropicBrainConfig extends StreamEngineConfig {
4
- /** Base URL of the Anthropic(-compatible) API. Default `https://api.anthropic.com`. Overridden by model.baseUrl. */
4
+ /** Base URL of the Anthropic(-compatible) API. Default {@link ANTHROPIC_DEFAULT_BASE_URL}. Overridden by model.baseUrl. */
5
5
  baseUrl?: string;
6
6
  /** API key (`x-api-key`). Overridden by per-call options.apiKey / getApiKeyAndHeaders. */
7
7
  apiKey?: string;
@@ -35,6 +35,11 @@ export interface AnthropicBrainConfig extends StreamEngineConfig {
35
35
  */
36
36
  thinkingBudgetTokens?: number;
37
37
  }
38
+ /** This lane's own default endpoint: where a request goes when neither the entry nor the config names a root,
39
+ * and so the root a key on the config is paired with when the config declares none. Exported so that every place that
40
+ * names the Anthropic API's own root — the {@link fable5Model} preset, a host's disclosure of where a default request
41
+ * lands — reads this one spelling. */
42
+ export declare const ANTHROPIC_DEFAULT_BASE_URL = "https://api.anthropic.com";
38
43
  /**
39
44
  * Create a Brain for the Anthropic Messages API (`/v1/messages`) with **prompt caching** and
40
45
  * **extended-thinking replay**. Translates the unified Context into an Anthropic request and the
@@ -6,8 +6,8 @@ import { STREAM_TORN_WARNING, createRepetitionPoll, createStreamEndLedger, model
6
6
  import { admitToolCallId, providerResultIds, providerToolCallId, responseToolCallIds } from "./tool-call-id.js";
7
7
  import { emitBrainTelemetry, reportReasoningWireFacts } from "./status-sink.js";
8
8
  import { errorResultMediaNote, IMAGE_OMITTED_NO_VISION, modelSupportsVision, sendableImages } from "./media-degrade.js";
9
- import { ANTHROPIC_RESERVED, OUTPUT_CAP_KEYS, applyExtraBody, effectiveOutputCap, lockHeader, mergeHeaders, takeHeaderCasefold } from "./request-params.js";
10
- import { adjudicateModelRoute, applyRouteCredentialHeaders, assertServableRequestRoot, brainConfigSnapshot, createBrainRouteJudge, joinRequestUrl, resolveRequestRootOf, resolveRouteCredential, routeRefusalText } from "./route-adjudicator.js";
9
+ import { ANTHROPIC_RESERVED, OUTPUT_CAP_KEYS, applyExtraBody, effectiveOutputCap, headerBagOnce, lockHeader, mergeHeaders, takeHeaderCasefold } from "./request-params.js";
10
+ import { admitRouteRequest, applyRouteCredentialHeaders, assertServableRequestRoot, brainConfigSnapshot, createBrainRouteJudge, joinRequestUrl, resolveRequestRootOf, resolveRouteCredential } from "./route-adjudicator.js";
11
11
  import { requestRouteOf } from "./request-route.js";
12
12
  import { MIN_THINKING_TOKENS, budgetCapSkipsThinking, declaredEffortLevels, reasoningBudgetShare, reasoningRequestCarried, resolveEffort } from "./reasoning.js";
13
13
  import { runStreamingBrain } from "./stream-engine.js";
@@ -226,7 +226,8 @@ function closeToolUseBlock(acc, responseIds, closed) {
226
226
  acc.closedTc = { type: "toolCall", id: engineId, ...(wireId !== engineId ? { wireId } : {}), name: acc.toolName, arguments: args };
227
227
  return acc.closedTc;
228
228
  }
229
- const ANTHROPIC_LANE_DEFAULT = "https://api.anthropic.com";
229
+ export const ANTHROPIC_DEFAULT_BASE_URL = "https://api.anthropic.com";
230
+ const ANTHROPIC_KEY_HEADER = "x-api-key";
230
231
  export function createAnthropicBrain(given = {}) {
231
232
  const config = brainConfigSnapshot(given, "createAnthropicBrain config");
232
233
  assertServableRequestRoot(config.baseUrl, "config.baseUrl");
@@ -246,17 +247,19 @@ export function createAnthropicBrain(given = {}) {
246
247
  maxRetries: options?.maxRetries,
247
248
  stallTimeouts: options?.stallTimeouts,
248
249
  buildRequest: (overrides) => {
249
- const { root, origin: rootOrigin } = resolveRequestRootOf(model.baseUrl, config.baseUrl, ANTHROPIC_LANE_DEFAULT);
250
+ const routed = { id: model.id, baseUrl: model.baseUrl };
251
+ const { root, origin: rootOrigin } = resolveRequestRootOf(routed.baseUrl, config.baseUrl, ANTHROPIC_DEFAULT_BASE_URL);
252
+ const modelHeaders = headerBagOnce(model.headers);
253
+ const optionsHeaders = headerBagOnce(options?.headers);
250
254
  const routeCredential = resolveRouteCredential({
251
255
  optionsApiKey: options?.apiKey,
252
- optionsHeaders: options?.headers,
253
- modelHeaders: model.headers,
256
+ optionsHeaders,
257
+ modelHeaders,
254
258
  configApiKey: config.apiKey,
255
259
  configHeaders: config.headers,
260
+ keyHeader: ANTHROPIC_KEY_HEADER,
256
261
  });
257
- const routeVerdict = adjudicateModelRoute(model, routeCredential, { baseUrl: config.baseUrl, laneDefault: ANTHROPIC_LANE_DEFAULT });
258
- if (!routeVerdict.ok)
259
- throw new BrainError("invalid_request", routeRefusalText(routeVerdict));
262
+ const routeAdmission = admitRouteRequest(routed, routeCredential, { baseUrl: config.baseUrl, laneDefault: ANTHROPIC_DEFAULT_BASE_URL });
260
263
  const apiKey = routeCredential.apiKey;
261
264
  const nonEmptyBlocks = context.systemBlocks?.filter((b) => b.text.length > 0);
262
265
  const system = nonEmptyBlocks?.length
@@ -329,8 +332,8 @@ export function createAnthropicBrain(given = {}) {
329
332
  if (anthCompat.interleavedThinking) {
330
333
  betas.push("interleaved-thinking-2025-05-14");
331
334
  }
332
- const headers = mergeHeaders(model.headers, config.headers, options?.headers);
333
- applyRouteCredentialHeaders(headers, routeCredential, { model: model.headers, options: options?.headers });
335
+ const headers = mergeHeaders(modelHeaders, config.headers, optionsHeaders);
336
+ applyRouteCredentialHeaders(headers, routeCredential);
334
337
  if (betas.length > 0) {
335
338
  const existing = (takeHeaderCasefold(headers, "anthropic-beta") ?? "").split(",").map((b) => b.trim()).filter(Boolean);
336
339
  for (const beta of betas) {
@@ -342,7 +345,7 @@ export function createAnthropicBrain(given = {}) {
342
345
  lockHeader(headers, "content-type", "application/json");
343
346
  lockHeader(headers, "anthropic-version", config.version ?? "2023-06-01");
344
347
  if (apiKey)
345
- headers["x-api-key"] = apiKey;
348
+ lockHeader(headers, ANTHROPIC_KEY_HEADER, apiKey);
346
349
  const builtThinkingRequested = body.thinking !== undefined;
347
350
  const builtMaxTokens = body.max_tokens;
348
351
  const builtMaxTokensLane = overrides?.maxOutputTokens !== undefined
@@ -362,6 +365,7 @@ export function createAnthropicBrain(given = {}) {
362
365
  outputCapTokens: effectiveOutputCap(wire, OUTPUT_CAP_KEYS.anthropic),
363
366
  capDerivedPaths: [...OUTPUT_CAP_KEYS.anthropic, "thinking.budget_tokens"],
364
367
  onCommitted: () => {
368
+ routeAdmission();
365
369
  thinkingRequested = builtThinkingRequested;
366
370
  sentMaxTokens = builtMaxTokens;
367
371
  sentMaxTokensLane = builtMaxTokensLane;
@@ -768,5 +772,5 @@ export function createAnthropicBrain(given = {}) {
768
772
  },
769
773
  });
770
774
  };
771
- return { stream, adjudicateRoute: createBrainRouteJudge({ ...config, laneDefault: ANTHROPIC_LANE_DEFAULT }) };
775
+ return { stream, adjudicateRoute: createBrainRouteJudge({ ...config, laneDefault: ANTHROPIC_DEFAULT_BASE_URL, keyHeader: ANTHROPIC_KEY_HEADER }) };
772
776
  }
@@ -20,12 +20,11 @@ import type { AnthropicMessagesCompat, Model } from "../internal/llm.js";
20
20
  */
21
21
  export declare const FABLE_5_COMPAT: AnthropicMessagesCompat;
22
22
  /**
23
- * Fable-5 behavioral guidance (CC 2.1.198 `fable_5_mitigations` — Anthropic's own runtime patches
24
- * for this model class's known behavior pitfalls, adapted; design/119 S3). Carried on the Model as
25
- * `promptGuidance` DATA — the injection mechanism (`Model.promptGuidance` → system-prompt tail) is
26
- * generic and model-name-free.
23
+ * The fable lines the classic prompt shape serves. They are prompt text, so they live with the prompt
24
+ * text; this name stays exported for hosts that read them. The preset below no longer carries them as
25
+ * `promptGuidance`: the prompt composes them itself, once, where they are the only fable text.
27
26
  */
28
- export declare const FABLE_5_PROMPT_GUIDANCE: string[];
27
+ export declare const FABLE_5_PROMPT_GUIDANCE: readonly string[];
29
28
  /**
30
29
  * A ready-to-use `claude-fable-5` {@link Model} (CC 2.1.198 registry facts: 1M-token native context
31
30
  * window, 64k default max output — the 128k tier is opt-in via `maxTokens` override, knowledge
@@ -1,12 +1,14 @@
1
+ import { catalogText } from "../prompt-assembly/catalog/index.js";
2
+ import { ANTHROPIC_DEFAULT_BASE_URL } from "./anthropic.js";
1
3
  export const FABLE_5_COMPAT = {
2
4
  thinkingMode: "adaptive",
3
5
  effortLevels: ["low", "medium", "high", "xhigh", "max"],
4
6
  supportsTemperature: false,
5
7
  };
6
8
  export const FABLE_5_PROMPT_GUIDANCE = [
7
- "Your final message of a turn is the only text the caller is guaranteed to read. Put every conclusion, answer, and deliverable in it — lead with the outcome, then supporting detail. Never leave a result only in an intermediate message or in your reasoning.",
8
- "When operating autonomously: before ending your turn, check that the task is actually complete (not just planned); before any state-changing action, re-verify that the evidence supports that specific action rather than pattern-matching a familiar case.",
9
- "When calling tools, provide exactly ONE complete JSON value per parameter — never concatenate multiple values, never truncate, never wrap a value in commentary.",
9
+ catalogText("core/behavior.fable-classic.final-message"),
10
+ catalogText("core/behavior.fable-classic.autonomy"),
11
+ catalogText("core/behavior.fable-classic.tool-json"),
10
12
  ];
11
13
  export function fable5Model(overrides = {}) {
12
14
  return {
@@ -14,7 +16,7 @@ export function fable5Model(overrides = {}) {
14
16
  name: "Claude Fable 5",
15
17
  api: "anthropic-messages",
16
18
  provider: "anthropic",
17
- baseUrl: "https://api.anthropic.com",
19
+ baseUrl: ANTHROPIC_DEFAULT_BASE_URL,
18
20
  reasoning: true,
19
21
  defaultThinking: "high",
20
22
  input: ["text", "image"],
@@ -23,7 +25,6 @@ export function fable5Model(overrides = {}) {
23
25
  maxTokens: 64_000,
24
26
  charsPerToken: 3,
25
27
  compat: { ...FABLE_5_COMPAT },
26
- promptGuidance: [...FABLE_5_PROMPT_GUIDANCE],
27
28
  ...overrides,
28
29
  };
29
30
  }
@@ -5,13 +5,14 @@ import { STREAM_TORN_WARNING, createRepetitionPoll, modelOutputInvalidOf, noteRe
5
5
  import { admitToolCallId, providerResultIds, providerToolCallId, responseToolCallIds } from "./tool-call-id.js";
6
6
  import { emitBrainTelemetry } from "./status-sink.js";
7
7
  import { errorResultMediaNote, IMAGE_OMITTED_NO_VISION, imagesOmittedNoVisionNote, modelSupportsVision, sendableImages } from "./media-degrade.js";
8
- import { OUTPUT_CAP_KEYS, RESPONSES_RESERVED, applyExtraBody, effectiveOutputCap, lockHeader, mergeHeaders } from "./request-params.js";
9
- import { adjudicateModelRoute, applyRouteCredentialHeaders, assertServableRequestRoot, brainConfigSnapshot, createBrainRouteJudge, joinRequestUrl, resolveRequestRootOf, resolveRouteCredential, routeRefusalText } from "./route-adjudicator.js";
8
+ import { OUTPUT_CAP_KEYS, RESPONSES_RESERVED, applyExtraBody, effectiveOutputCap, headerBagOnce, lockHeader, mergeHeaders } from "./request-params.js";
9
+ import { admitRouteRequest, applyRouteCredentialHeaders, assertServableRequestRoot, brainConfigSnapshot, createBrainRouteJudge, joinRequestUrl, resolveRequestRootOf, resolveRouteCredential } from "./route-adjudicator.js";
10
10
  import { requestRouteOf } from "./request-route.js";
11
11
  import { declaredOffSpelling, mintEffortWireValue, reasoningRequestCarried } from "./reasoning.js";
12
12
  import { runStreamingBrain } from "./stream-engine.js";
13
13
  import { refuseRetiredTimeoutKnobs } from "./timeout.js";
14
14
  import { resolveFetch } from "./transport.js";
15
+ const OPEN_RESPONSES_KEY_HEADER = "authorization";
15
16
  const DEGENERATE_POLL_CHARS = 64;
16
17
  const MALFORMED_SAMPLE_CHARS = 160;
17
18
  const MALFORMED_ARGS_CHARS = 200;
@@ -239,20 +240,22 @@ export function createOpenResponsesBrain(given = {}) {
239
240
  maxRetries: options?.maxRetries,
240
241
  stallTimeouts: options?.stallTimeouts,
241
242
  buildRequest: (overrides) => {
242
- const { root, origin: rootOrigin } = resolveRequestRootOf(model.baseUrl, config.baseUrl);
243
+ const routed = { id: model.id, baseUrl: model.baseUrl };
244
+ const { root, origin: rootOrigin } = resolveRequestRootOf(routed.baseUrl, config.baseUrl);
243
245
  if (!root) {
244
246
  throw new Error("createOpenResponsesBrain: no baseUrl configured (set config.baseUrl or model.baseUrl)");
245
247
  }
248
+ const modelHeaders = headerBagOnce(model.headers);
249
+ const optionsHeaders = headerBagOnce(options?.headers);
246
250
  const routeCredential = resolveRouteCredential({
247
251
  optionsApiKey: options?.apiKey,
248
- optionsHeaders: options?.headers,
249
- modelHeaders: model.headers,
252
+ optionsHeaders,
253
+ modelHeaders,
250
254
  configApiKey: config.apiKey,
251
255
  configHeaders: config.headers,
256
+ keyHeader: OPEN_RESPONSES_KEY_HEADER,
252
257
  });
253
- const routeVerdict = adjudicateModelRoute(model, routeCredential, { baseUrl: config.baseUrl });
254
- if (!routeVerdict.ok)
255
- throw new BrainError("invalid_request", routeRefusalText(routeVerdict));
258
+ const routeAdmission = admitRouteRequest(routed, routeCredential, { baseUrl: config.baseUrl });
256
259
  const apiKey = routeCredential.apiKey;
257
260
  if (options?.stop !== undefined && options.stop.length > 0) {
258
261
  throw new Error("createOpenResponsesBrain: options.stop is not expressible in the Open Responses request (the wire form has no stop-sequence field); " +
@@ -285,11 +288,11 @@ export function createOpenResponsesBrain(given = {}) {
285
288
  }
286
289
  if (effort !== undefined)
287
290
  body.reasoning = { effort };
288
- const headers = mergeHeaders(model.headers, config.headers, options?.headers);
289
- applyRouteCredentialHeaders(headers, routeCredential, { model: model.headers, options: options?.headers });
291
+ const headers = mergeHeaders(modelHeaders, config.headers, optionsHeaders);
292
+ applyRouteCredentialHeaders(headers, routeCredential);
290
293
  lockHeader(headers, "content-type", "application/json");
291
294
  if (apiKey)
292
- headers["authorization"] = `Bearer ${apiKey}`;
295
+ lockHeader(headers, OPEN_RESPONSES_KEY_HEADER, `Bearer ${apiKey}`);
293
296
  const { body: wire, dropped: extraBodyDropped } = applyExtraBody(body, model.extraBody, RESPONSES_RESERVED);
294
297
  return {
295
298
  url: joinRequestUrl(root, "/responses"),
@@ -300,6 +303,7 @@ export function createOpenResponsesBrain(given = {}) {
300
303
  outputCapTokens: effectiveOutputCap(wire, OUTPUT_CAP_KEYS.responses),
301
304
  capDerivedPaths: OUTPUT_CAP_KEYS.responses,
302
305
  onCommitted: () => {
306
+ routeAdmission();
303
307
  sentMaxTokens = builtMaxTokens;
304
308
  sentMaxTokensLane = builtMaxTokensLane;
305
309
  sentEffort = effort;
@@ -773,5 +777,5 @@ export function createOpenResponsesBrain(given = {}) {
773
777
  },
774
778
  });
775
779
  };
776
- return { stream, adjudicateRoute: createBrainRouteJudge(config) };
780
+ return { stream, adjudicateRoute: createBrainRouteJudge({ ...config, keyHeader: OPEN_RESPONSES_KEY_HEADER }) };
777
781
  }
@@ -5,15 +5,16 @@ import { STREAM_TORN_WARNING, createRepetitionPoll, createStreamEndLedger, echoF
5
5
  import { admitToolCallId, providerResultIds, providerToolCallId, responseToolCallIds } from "./tool-call-id.js";
6
6
  import { emitBrainTelemetry } from "./status-sink.js";
7
7
  import { errorResultMediaNote, IMAGE_OMITTED_NO_VISION, imagesOmittedNoVisionNote, modelSupportsVision, sendableImages } from "./media-degrade.js";
8
- import { OPENAI_RESERVED, OUTPUT_CAP_KEYS, applyExtraBody, effectiveOutputCap, lockHeader, mergeHeaders } from "./request-params.js";
8
+ import { OPENAI_RESERVED, OUTPUT_CAP_KEYS, applyExtraBody, effectiveOutputCap, headerBagOnce, lockHeader, mergeHeaders } from "./request-params.js";
9
9
  import { BrainError, providerErrorWord } from "./errors.js";
10
10
  import { inBandProviderError } from "./provider-dialect.js";
11
- import { adjudicateModelRoute, applyRouteCredentialHeaders, assertServableRequestRoot, brainConfigSnapshot, createBrainRouteJudge, joinRequestUrl, resolveRequestRootOf, resolveRouteCredential, routeRefusalText } from "./route-adjudicator.js";
11
+ import { admitRouteRequest, applyRouteCredentialHeaders, assertServableRequestRoot, brainConfigSnapshot, createBrainRouteJudge, joinRequestUrl, resolveRequestRootOf, resolveRouteCredential } from "./route-adjudicator.js";
12
12
  import { requestRouteOf } from "./request-route.js";
13
13
  import { declaredOffSpelling, mintEffortWireValue, reasoningRequestCarried } from "./reasoning.js";
14
14
  import { runStreamingBrain } from "./stream-engine.js";
15
15
  import { refuseRetiredTimeoutKnobs } from "./timeout.js";
16
16
  import { resolveFetch } from "./transport.js";
17
+ const OPENAI_KEY_HEADER = "authorization";
17
18
  function closeToolCallAccum(acc, responseIds, closed) {
18
19
  if (acc.closedTc)
19
20
  return acc.closedTc;
@@ -342,20 +343,22 @@ export function createOpenAIBrain(given = {}) {
342
343
  maxRetries: options?.maxRetries,
343
344
  stallTimeouts: options?.stallTimeouts,
344
345
  buildRequest: (overrides) => {
345
- const { root, origin: rootOrigin } = resolveRequestRootOf(model.baseUrl, config.baseUrl);
346
+ const routed = { id: model.id, baseUrl: model.baseUrl };
347
+ const { root, origin: rootOrigin } = resolveRequestRootOf(routed.baseUrl, config.baseUrl);
346
348
  if (!root) {
347
349
  throw new Error("createOpenAIBrain: no baseUrl configured (set config.baseUrl or model.baseUrl)");
348
350
  }
351
+ const modelHeaders = headerBagOnce(model.headers);
352
+ const optionsHeaders = headerBagOnce(options?.headers);
349
353
  const routeCredential = resolveRouteCredential({
350
354
  optionsApiKey: options?.apiKey,
351
- optionsHeaders: options?.headers,
352
- modelHeaders: model.headers,
355
+ optionsHeaders,
356
+ modelHeaders,
353
357
  configApiKey: config.apiKey,
354
358
  configHeaders: config.headers,
359
+ keyHeader: OPENAI_KEY_HEADER,
355
360
  });
356
- const routeVerdict = adjudicateModelRoute(model, routeCredential, { baseUrl: config.baseUrl });
357
- if (!routeVerdict.ok)
358
- throw new BrainError("invalid_request", routeRefusalText(routeVerdict));
361
+ const routeAdmission = admitRouteRequest(routed, routeCredential, { baseUrl: config.baseUrl });
359
362
  const apiKey = routeCredential.apiKey;
360
363
  const body = {
361
364
  model: model.id,
@@ -385,11 +388,11 @@ export function createOpenAIBrain(given = {}) {
385
388
  if (options?.stop)
386
389
  body.stop = options.stop;
387
390
  applyThinking(body, model, options?.reasoning);
388
- const headers = mergeHeaders(model.headers, config.headers, options?.headers);
389
- applyRouteCredentialHeaders(headers, routeCredential, { model: model.headers, options: options?.headers });
391
+ const headers = mergeHeaders(modelHeaders, config.headers, optionsHeaders);
392
+ applyRouteCredentialHeaders(headers, routeCredential);
390
393
  lockHeader(headers, "content-type", "application/json");
391
394
  if (apiKey)
392
- headers["authorization"] = `Bearer ${apiKey}`;
395
+ lockHeader(headers, OPENAI_KEY_HEADER, `Bearer ${apiKey}`);
393
396
  const { body: wire, dropped: extraBodyDropped } = applyExtraBody(body, model.extraBody, OPENAI_RESERVED);
394
397
  return {
395
398
  url: joinRequestUrl(root, "/chat/completions"),
@@ -400,6 +403,7 @@ export function createOpenAIBrain(given = {}) {
400
403
  outputCapTokens: effectiveOutputCap(wire, OUTPUT_CAP_KEYS.openai),
401
404
  capDerivedPaths: [mtField],
402
405
  onCommitted: () => {
406
+ routeAdmission();
403
407
  sentMaxTokens = builtMaxTokens;
404
408
  sentMaxTokensLane = builtMaxTokensLane;
405
409
  },
@@ -749,5 +753,5 @@ export function createOpenAIBrain(given = {}) {
749
753
  },
750
754
  });
751
755
  };
752
- return { stream, adjudicateRoute: createBrainRouteJudge(config) };
756
+ return { stream, adjudicateRoute: createBrainRouteJudge({ ...config, keyHeader: OPENAI_KEY_HEADER }) };
753
757
  }
@@ -1,19 +1,3 @@
1
- /**
2
- * Request-parameter passthrough (design/40). A deployment can set official provider params it wants but
3
- * core doesn't model as first-class fields (OpenAI `frequency_penalty`/`presence_penalty`/`top_p`/`seed`/
4
- * `logit_bias`; Anthropic `top_k`/`top_p`/`stop_sequences`; …) via `Model.extraBody`, and core merges them
5
- * into the brain's request body. Anchored at the **Model** level (not per-turn) so the serialized body
6
- * stays byte-stable across turns → the prefix cache holds (design/9/31).
7
- *
8
- * Symmetric: each brain owns its structural + tuning keys (`reserved`) and ALWAYS wins — `extraBody` can
9
- * only supply the long tail, never clobber `messages`/`tools`/`temperature`/etc. Stripping is the safety
10
- * enforcement (the brains are standalone-usable), and a strip is never silent: {@link applyExtraBody}
11
- * RETURNS the keys it stripped, the brain reports them on the request it built
12
- * (`SSERequest.extraBodyDropped`), the stream engine reports them to the run's sink when it commits that
13
- * request (`reportExtraBodyDropped`), and the Runner announces them (`route.extra_body_reserved_dropped`).
14
- * One reading, at the one place the strip happens — so an `extraBody` a host brain swapped in for a single
15
- * request, or one on the compaction model, is said the same way the task's own model spec is.
16
- */
17
1
  /** OpenAI request-body keys core owns; `extraBody` cannot override these. */
18
2
  export declare const OPENAI_RESERVED: ReadonlySet<string>;
19
3
  /** Anthropic request-body keys core owns; `extraBody` cannot override these. (Note the asymmetry vs
@@ -43,16 +27,6 @@ export declare function applyExtraBody(body: Record<string, unknown>, extraBody:
43
27
  body: Record<string, unknown>;
44
28
  dropped: readonly string[];
45
29
  };
46
- /** The auth-bearing header names (case-fold), single-sourced for the credential enforcement
47
- * (`applyRouteCredentialHeaders`, route-adjudicator.ts — the ONE authority over auth spelling: a
48
- * per-model winner strips every carrier, any case, and re-asserts the winning bag's own),
49
- * {@link mergeHeaders} (which EXEMPTS them — see there), and the route credential resolver (which
50
- * reads carrier PRESENCE per bag to classify a headers-borne credential). The former per-call
51
- * strip helper that lived here (`stripAuthHeaders` — "per-call auth replaces construction-time
52
- * auth", triggered on `options.apiKey` presence) is retired: the three brains now run the
53
- * route-credential resolution instead, whose per-model arm strips a strict superset of what the
54
- * helper did. */
55
- export declare const AUTH_CARRIER_NAMES: ReadonlySet<string>;
56
30
  /**
57
31
  * #343 — the shared USER-HEADER merge layer (`model.headers` → construction `config.headers` →
58
32
  * per-call `options.headers`, later bag wins), CASE-FOLD deduplicated: HTTP header field names are
@@ -62,10 +36,11 @@ export declare const AUTH_CARRIER_NAMES: ReadonlySet<string>;
62
36
  * override silently defeated. A later bag's entry replaces an earlier case-variant instead; the
63
37
  * WINNER'S spelling and value survive (a single-spelling config is byte-identical on the wire).
64
38
  *
65
- * EXEMPT: the auth carriers (`authorization` / `x-api-key`, any case) pass through with plain
66
- * spread semantics (same-spelling override only, no case-fold dedup), so that the credential
67
- * enforcement (`applyRouteCredentialHeaders`, route-adjudicator.ts) stays the ONE authority over
68
- * auth spelling and this layer never becomes a second, subtly different one.
39
+ * EXEMPT: the credential headers ({@link isCredentialHeaderName}, the engine's one reading of which
40
+ * header carries a credential: `authorization`, `x-api-key`, `api-key`, `cookie`, …, any case) pass
41
+ * through with plain spread semantics (same-spelling override only, no case-fold dedup), so that the
42
+ * credential enforcement (`applyRouteCredentialHeaders`, route-adjudicator.ts) stays the ONE authority
43
+ * over credential spelling and this layer never becomes a second, subtly different one.
69
44
  *
70
45
  * The exemption is NOT what keeps a header-only `ANTHROPIC_AUTH_TOKEN` alive: dedup keeps the
71
46
  * winner's spelling, a lone `Authorization` has nothing to dedup against, and the credential
@@ -90,9 +65,9 @@ export declare const AUTH_CARRIER_NAMES: ReadonlySet<string>;
90
65
  * user-bag merge precisely so they "can NEVER be overridden" (council design/40) — and without the
91
66
  * delete a user bag carrying `Content-Type: text/plain` survives BESIDE the lowercase lock, the
92
67
  * platform `Headers` fold turning the pair into `text/plain, application/json` on the wire: a lock
93
- * that decides nothing. Auth carriers are deliberately NOT routed through here (credential replacement + the
94
- * header-only boot flow are the pinned jurisdiction of `applyRouteCredentialHeaders`,
95
- * route-adjudicator.ts).
68
+ * that decides nothing. WHICH credential headers ride is the jurisdiction of `applyRouteCredentialHeaders`
69
+ * (route-adjudicator.ts); the key header a brain writes after it (`authorization` / `x-api-key`, from the
70
+ * apiKey knob) is a lock like any other — one value per name, whatever spelling a bag carried.
96
71
  */
97
72
  export declare function lockHeader(headers: Record<string, string>, lowerName: string, value: string): void;
98
73
  /**
@@ -103,6 +78,10 @@ export declare function lockHeader(headers: Record<string, string>, lowerName: s
103
78
  * losing the user's betas from the merge AND double-sending the header).
104
79
  */
105
80
  export declare function takeHeaderCasefold(headers: Record<string, string>, lowerName: string): string | undefined;
81
+ /** A caller's header bag read ONCE, into a plain copy of its own enumerable entries — what a request build hands both
82
+ * the route law (which credential rides, and its identity) and the merge (what goes on the wire), so a bag whose getters
83
+ * or keys answer differently on a second read cannot be judged as one bag and sent as another. */
84
+ export declare function headerBagOnce(bag: Readonly<Record<string, string>> | undefined): Record<string, string> | undefined;
106
85
  export declare function mergeHeaders(...bags: Array<Record<string, string> | undefined>): Record<string, string>;
107
86
  /**
108
87
  * The output-cap key(s) each lane's wire form uses. A lane's set is exactly the keys THAT lane's