@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
@@ -5,21 +5,15 @@ import { DEGENERATE_MESSAGE, trimDegenerateTail } from "./repetition.js";
5
5
  import { STREAM_TORN_WARNING, createRepetitionPoll, createStreamEndLedger, modelOutputInvalidOf, noteResponseModel, nameMissingCause, parseStreamedToolArgs, placeTurnNotes, truncationCauseClause } from "./stream-shared.js";
6
6
  import { admitToolCallId, providerResultIds, providerToolCallId, responseToolCallIds } from "./tool-call-id.js";
7
7
  import { emitBrainTelemetry, reportReasoningWireFacts } from "./status-sink.js";
8
- import { errorResultMediaNote, IMAGE_OMITTED_NO_VISION, modelSupportsVision, sendableImages } from "./media-degrade.js";
9
- import { ANTHROPIC_RESERVED, OUTPUT_CAP_KEYS, applyExtraBody, effectiveOutputCap, headerBagOnce, lockHeader, mergeHeaders, takeHeaderCasefold } from "./request-params.js";
8
+ import { errorResultMediaNote, IMAGE_OMITTED_NO_VISION, imageWithholdOf, reportImagesWithheld, sendableImages } from "./media-degrade.js";
9
+ import { ANTHROPIC_RESERVED, OUTPUT_CAP_KEYS, applyExtraBody, declaredRequestValues, effectiveOutputCap, headerBagOnce, headerListEntries, lockHeader, mergeHeaders, takeHeaderSpellings } from "./request-params.js";
10
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 { NAMES_AS_WRITTEN, resolveProviderDialect, endpointToolNames } from "./provider-dialect.js";
13
- import { MIN_THINKING_TOKENS, budgetCapSkipsThinking, declaredEffortLevels, reasoningBudgetShare, reasoningRequestCarried, resolveEffort } from "./reasoning.js";
13
+ import { applyReasoningToRequest, mergeReasoningHeaders } from "./reasoning-request.js";
14
14
  import { runStreamingBrain } from "./stream-engine.js";
15
15
  import { refuseRetiredTimeoutKnobs } from "./timeout.js";
16
16
  import { resolveFetch } from "./transport.js";
17
- function thinkingBudget(maxTokens, share, fixed, hardCap = false) {
18
- const max = hardCap ? maxTokens : Math.max(maxTokens, MIN_THINKING_TOKENS * 2);
19
- const want = fixed ?? Math.floor(max * share);
20
- const budget = Math.min(Math.max(MIN_THINKING_TOKENS, want), max - 1);
21
- return { max, budget };
22
- }
23
17
  const EPHEMERAL = { type: "ephemeral" };
24
18
  const DOCUMENT_OMITTED_NO_VISION = "[PDF document omitted: the serving model does not support document input; extract the text via Bash instead (e.g. `pdftotext`).]";
25
19
  function textOf(content) {
@@ -27,7 +21,7 @@ function textOf(content) {
27
21
  ? content
28
22
  : content.filter((c) => c.type === "text" && typeof c.text === "string").map((c) => c.text).join("");
29
23
  }
30
- function toUserBlocks(content, supportsVision = true) {
24
+ function toUserBlocks(content, withhold) {
31
25
  if (typeof content === "string") {
32
26
  return content.length > 0 ? [{ type: "text", text: content }] : [];
33
27
  }
@@ -38,7 +32,7 @@ function toUserBlocks(content, supportsVision = true) {
38
32
  blocks.push({ type: "text", text: c.text });
39
33
  }
40
34
  else if (c.type === "image" && c.data && c.mimeType) {
41
- if (supportsVision)
35
+ if (withhold === undefined)
42
36
  blocks.push({ type: "image", source: { type: "base64", media_type: c.mimeType, data: c.data } });
43
37
  else {
44
38
  omitted++;
@@ -46,12 +40,13 @@ function toUserBlocks(content, supportsVision = true) {
46
40
  }
47
41
  }
48
42
  }
49
- if (omitted > 0)
50
- emitBrainTelemetry({ kind: "vision_placeholder", count: omitted });
43
+ if (withhold !== undefined)
44
+ reportImagesWithheld(withhold, omitted);
51
45
  return blocks;
52
46
  }
53
47
  function toAnthropicMessages(ctx, model, toolNames) {
54
- const supportsVision = modelSupportsVision(model);
48
+ const imageWithhold = imageWithholdOf(model);
49
+ const supportsVision = imageWithhold === undefined;
55
50
  const raw = [];
56
51
  let pendingDocs = [];
57
52
  const flushDocs = () => {
@@ -65,7 +60,7 @@ function toAnthropicMessages(ctx, model, toolNames) {
65
60
  if (m.role !== "toolResult")
66
61
  flushDocs();
67
62
  if (m.role === "user") {
68
- const ub = toUserBlocks(m.content, supportsVision);
63
+ const ub = toUserBlocks(m.content, imageWithhold);
69
64
  raw.push({ role: "user", content: ub.length ? ub : [{ type: "text", text: NO_CONTENT }] });
70
65
  }
71
66
  else if (m.role === "assistant") {
@@ -97,7 +92,7 @@ function toAnthropicMessages(ctx, model, toolNames) {
97
92
  const docs = parts ? parts.filter((c) => c.type === "document") : [];
98
93
  const rest = docs.length > 0 && parts ? parts.filter((c) => c.type !== "document") : m.content;
99
94
  const hasImage = !m.isError && Array.isArray(rest) && rest.some((c) => c.type === "image");
100
- let inner = hasImage ? toUserBlocks(rest, supportsVision) : textOf(rest);
95
+ let inner = hasImage ? toUserBlocks(rest, imageWithhold) : textOf(rest);
101
96
  if (docs.length > 0 && !m.isError) {
102
97
  if (supportsVision) {
103
98
  for (const d of docs) {
@@ -290,68 +285,32 @@ export function createAnthropicBrain(given = {}) {
290
285
  if (options?.temperature !== undefined && anthCompat.supportsTemperature !== false) {
291
286
  body.temperature = options.temperature;
292
287
  }
293
- let builtReasoningFacts;
294
- let thinkingOn = false;
295
- if (reasoningRequestCarried(model, options?.reasoning)) {
296
- if (anthCompat.thinkingMode === "adaptive") {
297
- body.thinking = { type: "adaptive" };
298
- thinkingOn = true;
299
- }
300
- else {
301
- const hardCap = overrides?.maxOutputTokens !== undefined || options?.maxTokens !== undefined;
302
- builtReasoningFacts = { outputCapTokens: body.max_tokens, hardOutputCap: hardCap };
303
- if (budgetCapSkipsThinking(builtReasoningFacts.outputCapTokens, builtReasoningFacts.hardOutputCap)) {
304
- body.thinking = undefined;
305
- delete body.thinking;
306
- }
307
- else {
308
- const share = config.thinkingBudgetShare ?? reasoningBudgetShare(options.reasoning);
309
- const { max, budget } = thinkingBudget(body.max_tokens, share, config.thinkingBudgetTokens, hardCap);
310
- body.max_tokens = max;
311
- body.thinking = { type: "enabled", budget_tokens: budget };
312
- thinkingOn = true;
313
- }
314
- }
315
- if (thinkingOn)
316
- delete body.temperature;
317
- }
318
- else if (model.reasoning && options?.reasoning === "off" && anthCompat.thinkingMode !== "adaptive") {
319
- body.thinking = { type: "disabled" };
320
- }
321
- const betas = [];
322
- let sendEffortBeta = false;
323
- const declaredEffort = declaredEffortLevels(anthCompat.effortLevels);
324
- if (declaredEffort !== undefined && reasoningRequestCarried(model, options?.reasoning)) {
325
- const { effective } = resolveEffort(options.reasoning, declaredEffort);
326
- const wireEffort = effective === "minimal" ? "low" : effective;
327
- body.output_config = { effort: wireEffort };
328
- sendEffortBeta = true;
329
- }
330
- if (sendEffortBeta)
331
- betas.push("effort-2025-11-24");
332
- if (anthCompat.contextManagement && thinkingOn) {
333
- body.context_management = { edits: [{ type: "clear_thinking_20251015", keep: "all" }] };
334
- betas.push("context-management-2025-06-27");
335
- }
336
- if (anthCompat.interleavedThinking) {
337
- betas.push("interleaved-thinking-2025-05-14");
338
- }
339
- const headers = mergeHeaders(modelHeaders, config.headers, optionsHeaders);
288
+ const hardCap = overrides?.maxOutputTokens !== undefined || options?.maxTokens !== undefined;
289
+ const { body: reasoningBody, headers: reasoningHeaders, wireFacts: builtReasoningFacts, } = applyReasoningToRequest({
290
+ api: "anthropic-messages",
291
+ model,
292
+ level: options?.reasoning,
293
+ body,
294
+ budget: { capIsHard: hardCap, share: config.thinkingBudgetShare, tokens: config.thinkingBudgetTokens },
295
+ });
296
+ const headerLayers = [modelHeaders, config.headers, optionsHeaders];
297
+ const headers = mergeHeaders(...headerLayers);
340
298
  applyRouteCredentialHeaders(headers, routeCredential);
341
- if (betas.length > 0) {
342
- const existing = (takeHeaderCasefold(headers, "anthropic-beta") ?? "").split(",").map((b) => b.trim()).filter(Boolean);
343
- for (const beta of betas) {
344
- if (!existing.includes(beta))
345
- existing.push(beta);
346
- }
347
- headers["anthropic-beta"] = existing.join(",");
299
+ const declaredBetas = headerLayers.flatMap((layer) => Object.entries(layer ?? {}).flatMap(([name, value]) => (name.toLowerCase() === "anthropic-beta" ? headerListEntries(value) : [])));
300
+ const declared = declaredRequestValues([...headerLayers, headers], [config.version, ...declaredBetas], apiKey);
301
+ takeHeaderSpellings(headers, "anthropic-beta");
302
+ for (const layer of headerLayers) {
303
+ for (const [name, value] of Object.entries(layer ?? {}))
304
+ if (name.toLowerCase() === "anthropic-beta")
305
+ mergeReasoningHeaders(headers, { [name]: value });
348
306
  }
307
+ mergeReasoningHeaders(headers, reasoningHeaders);
349
308
  lockHeader(headers, "content-type", "application/json");
350
309
  lockHeader(headers, "anthropic-version", config.version ?? "2023-06-01");
351
310
  if (apiKey)
352
311
  lockHeader(headers, ANTHROPIC_KEY_HEADER, apiKey);
353
- const builtThinkingRequested = body.thinking !== undefined;
354
- const builtMaxTokens = body.max_tokens;
312
+ const builtThinkingRequested = reasoningBody.thinking !== undefined;
313
+ const builtMaxTokens = reasoningBody.max_tokens;
355
314
  const builtMaxTokensLane = overrides?.maxOutputTokens !== undefined
356
315
  ? "engine"
357
316
  : options?.maxTokens !== undefined
@@ -359,10 +318,11 @@ export function createAnthropicBrain(given = {}) {
359
318
  : model.maxTokens !== undefined
360
319
  ? "model"
361
320
  : "config-default";
362
- const { body: wire, dropped: extraBodyDropped } = applyExtraBody(body, model, ANTHROPIC_RESERVED);
321
+ const { body: wire, dropped: extraBodyDropped } = applyExtraBody(reasoningBody, model, ANTHROPIC_RESERVED);
363
322
  return {
364
323
  url,
365
324
  headers,
325
+ declared,
366
326
  body: JSON.stringify(wire),
367
327
  extraBodyDropped,
368
328
  route: requestRouteOf(routeCredential, rootOrigin),
@@ -396,7 +356,7 @@ export function createAnthropicBrain(given = {}) {
396
356
  let lastDegenCheckThinking = 0;
397
357
  const detectRep = config.detectRepetition !== false;
398
358
  let messageStopped = false;
399
- const afterEnd = createStreamEndLedger();
359
+ const afterEnd = createStreamEndLedger(ctrl.providerWords);
400
360
  const streamEnded = () => stopReason != null || messageStopped;
401
361
  const mergeDeltaUsage = (u) => {
402
362
  if (!u)
@@ -473,7 +433,7 @@ export function createAnthropicBrain(given = {}) {
473
433
  else if (acc.type === "tool_use") {
474
434
  const closed = acc.stopped === true || !endedCut;
475
435
  if (!acc.toolName) {
476
- (nameMissingCause(closed) === "truncated" ? malformed : unnamed).push(`id="${acc.toolId || "?"}"(${acc.toolJson.slice(0, 200)})`);
436
+ (nameMissingCause(closed) === "truncated" ? malformed : unnamed).push(`id="${ctrl.providerWords(acc.toolId || "?")}"(${ctrl.providerWords(acc.toolJson).slice(0, 200)})`);
477
437
  }
478
438
  else {
479
439
  const tc = closeToolUseBlock(acc, responseIds, closed);
@@ -482,7 +442,7 @@ export function createAnthropicBrain(given = {}) {
482
442
  finalContent.push(tc);
483
443
  }
484
444
  else {
485
- malformed.push(`${acc.toolName}(${acc.toolJson.slice(0, 200)})`);
445
+ malformed.push(`${ctrl.providerWords(acc.toolName)}(${ctrl.providerWords(acc.toolJson).slice(0, 200)})`);
486
446
  }
487
447
  }
488
448
  }
@@ -623,8 +583,13 @@ export function createAnthropicBrain(given = {}) {
623
583
  const d = evt.delta;
624
584
  if (d?.stop_reason)
625
585
  stopReason = d.stop_reason;
626
- if (d?.stop_details)
627
- stopDetails = d.stop_details;
586
+ if (d?.stop_details) {
587
+ const raw = d.stop_details;
588
+ stopDetails = {
589
+ ...(typeof raw.category === "string" ? { category: ctrl.providerWords(raw.category) } : {}),
590
+ ...(typeof raw.explanation === "string" ? { explanation: ctrl.providerWords(raw.explanation) } : {}),
591
+ };
592
+ }
628
593
  mergeDeltaUsage(evt.usage);
629
594
  break;
630
595
  }
@@ -639,7 +604,7 @@ export function createAnthropicBrain(given = {}) {
639
604
  const inputTooLong = e?.type === "request_too_large" ||
640
605
  (e?.type === "invalid_request_error" && typeof e.message === "string" && startsWithInputTooLongAnchor(e.message));
641
606
  ctrl.keepOutput({ content: assembleTurn({}).content, ...reportedUsage() });
642
- throw new BrainError(anthropicStreamErrorCode(e?.type), `anthropic stream error (${e?.type ?? "unknown"}): ${e?.message ?? ""}`, undefined, { apiError: true, ...(e === undefined ? {} : inputTooLong ? { inputTooLong: true } : { inputTooLongRuledOut: true }) });
607
+ throw new BrainError(anthropicStreamErrorCode(e?.type), `anthropic stream error ${ctrl.providerWords(`(${e?.type ?? "unknown"}): ${e?.message ?? ""}`)}`, undefined, { apiError: true, ...(e === undefined ? {} : inputTooLong ? { inputTooLong: true } : { inputTooLongRuledOut: true }) });
643
608
  }
644
609
  default:
645
610
  break;
@@ -679,7 +644,7 @@ export function createAnthropicBrain(given = {}) {
679
644
  }
680
645
  catch {
681
646
  malformedFrames++;
682
- malformedSample ??= data.slice(0, 160);
647
+ malformedSample ??= ctrl.providerWords(data).slice(0, 160);
683
648
  return;
684
649
  }
685
650
  handleEvent(evt);
@@ -7,15 +7,26 @@
7
7
  * sentence that drifts is a string consumers grep for.
8
8
  */
9
9
  import type { Model } from "../internal/llm.js";
10
+ import { type CapabilityDeclaration } from "./model-capability.js";
11
+ /** Why a request's images are withheld from the SERVING model: the entry's image declaration, when it is not held
12
+ * (the withheld-capability report's `cause`, `status-sink.ts`). */
13
+ export type ImageWithholdCause = Exclude<CapabilityDeclaration, "declared_on">;
14
+ /** A request whose images are withheld: which model, and why. */
15
+ export interface ImageWithhold {
16
+ readonly modelId: string;
17
+ readonly cause: ImageWithholdCause;
18
+ }
10
19
  /**
11
- * Whether the SERVING model accepts image input (`Model.input` contains "image").
12
- *
13
- * An ABSENT `input` is deliberately permissive (vision on): the field is caller-supplied metadata,
14
- * and treating "not declared" as "not capable" would silently downgrade every caller who never
15
- * filled it in. A caller that genuinely serves a text-only endpoint declares `input: ["text"]` and
16
- * gets the placeholder path — the case a text-only API rejects with a hard 400 on an image part.
20
+ * The image row of the capability table for one request: `undefined` = images ride as images; otherwise the model and
21
+ * the declaration that withholds them. Read off the one capability reading (`capabilityHeld` / `capabilityOf`), so an
22
+ * entry that never declared `input` gets its images exactly as the table says, and an entry that declares a list without
23
+ * `"image"` gets the placeholder path — the case a text-only API rejects with a hard 400 on an image part. No model =
24
+ * images ride.
17
25
  */
18
- export declare function modelSupportsVision(model?: Model): boolean;
26
+ export declare function imageWithholdOf(model?: Model): ImageWithhold | undefined;
27
+ /** Report `count` images of one request replaced by placeholders — the one emit for every lane: the operator trace frame
28
+ * (telemetry, per request) and the leg's withheld-capability account (the person's notice, once per conversation). */
29
+ export declare function reportImagesWithheld(withhold: ImageWithhold, count: number): void;
19
30
  /** Placeholder for an image block dropped because the serving model declares no image input. */
20
31
  export declare const IMAGE_OMITTED_NO_VISION = "[image omitted: the serving model does not support image input]";
21
32
  /** {@link IMAGE_OMITTED_NO_VISION}, counted — a batch of dropped images states how many were lost. */
@@ -1,5 +1,16 @@
1
- export function modelSupportsVision(model) {
2
- return model?.input === undefined ? true : model.input.includes("image");
1
+ import { capabilityHeld, capabilityOf } from "./model-capability.js";
2
+ import { emitBrainTelemetry, reportCapabilityWithheld } from "./status-sink.js";
3
+ export function imageWithholdOf(model) {
4
+ if (model === undefined)
5
+ return undefined;
6
+ const declared = capabilityOf(model, "image");
7
+ return declared === "declared_on" || capabilityHeld(model, "image") ? undefined : { modelId: model.id, cause: declared };
8
+ }
9
+ export function reportImagesWithheld(withhold, count) {
10
+ if (count === 0)
11
+ return;
12
+ emitBrainTelemetry({ kind: "vision_placeholder", count });
13
+ reportCapabilityWithheld({ modelId: withhold.modelId, capability: "image", cause: withhold.cause, count });
3
14
  }
4
15
  export const IMAGE_OMITTED_NO_VISION = "[image omitted: the serving model does not support image input]";
5
16
  export function imagesOmittedNoVisionNote(count) {
@@ -0,0 +1,37 @@
1
+ /**
2
+ * The ONE reading of a model's capability declarations — image input and reasoning.
3
+ *
4
+ * A `Model` declares each capability in one of three states: on (`reasoning: true`; `input` lists `"image"`), off
5
+ * (`reasoning: false`; an `input` list without `"image"`), or not at all (the key is absent). Every reader in the engine
6
+ * (bar the PDF profile's no-metadata shortcut in `pdfModelCapabilitiesOf`, which looks at the absence itself) asks {@link capabilityOf} for the declaration, or {@link capabilityHeld} for "does the engine treat this model as
7
+ * having it", and what an undeclared capability means is stated once, in {@link UNKNOWN_CAPABILITY_READS} — no caller
8
+ * decides it for itself. A request never carries a capability declared off; one declared on is never dropped here.
9
+ *
10
+ * A declaration of the wrong shape is refused where it is read: a `reasoning` that is not a boolean, or an `input` that
11
+ * is not a list of strings, throws, naming the model and the key. Reading it some other way (by truthiness, or as
12
+ * undeclared) would turn a typo into a capability nobody declared.
13
+ */
14
+ import type { Model } from "../internal/llm.js";
15
+ /** The capabilities a model declares. `image` = accepts image input (`Model.input` lists `"image"`). */
16
+ export declare const MODEL_CAPABILITIES: readonly ["image", "reasoning"];
17
+ export type ModelCapability = (typeof MODEL_CAPABILITIES)[number];
18
+ /** What a model's entry says about one capability. `unknown` = the entry does not say. */
19
+ export declare const CAPABILITY_DECLARATIONS: readonly ["declared_on", "declared_off", "unknown"];
20
+ export type CapabilityDeclaration = (typeof CAPABILITY_DECLARATIONS)[number];
21
+ /**
22
+ * What the engine does with a capability the entry does not declare, per capability — the only place this is said.
23
+ * Image input is used (an entry that never filled in `input` keeps the images it was always sent). Reasoning is not:
24
+ * no thinking keys go out for an entry that does not declare `reasoning` (the request is the provider's default).
25
+ */
26
+ export declare const UNKNOWN_CAPABILITY_READS: Readonly<Record<ModelCapability, "held" | "not_held">>;
27
+ /** The part of a model this module reads (`id` only names the model in a refusal; the structural readers that take a
28
+ * model-shaped object without one still get the same answer). */
29
+ export type CapabilityDeclaringModel = {
30
+ readonly id?: Model["id"];
31
+ readonly reasoning?: unknown;
32
+ readonly input?: unknown;
33
+ };
34
+ /** The entry's declaration of `cap`. Throws a `TypeError` on a declaration of the wrong shape (see the module note). */
35
+ export declare function capabilityOf(model: CapabilityDeclaringModel, cap: ModelCapability): CapabilityDeclaration;
36
+ /** Whether the engine treats the model as having `cap`: declared on, or undeclared where {@link UNKNOWN_CAPABILITY_READS} says held. */
37
+ export declare function capabilityHeld(model: CapabilityDeclaringModel, cap: ModelCapability): boolean;
@@ -0,0 +1,34 @@
1
+ export const MODEL_CAPABILITIES = Object.freeze(["image", "reasoning"]);
2
+ export const CAPABILITY_DECLARATIONS = Object.freeze(["declared_on", "declared_off", "unknown"]);
3
+ export const UNKNOWN_CAPABILITY_READS = Object.freeze({
4
+ image: "held",
5
+ reasoning: "not_held",
6
+ });
7
+ function typeWordOf(value) {
8
+ return value === null ? "null" : Array.isArray(value) ? "array" : typeof value;
9
+ }
10
+ function nameOf(model) {
11
+ return typeof model.id === "string" ? `"${model.id}"` : "a model with no id";
12
+ }
13
+ export function capabilityOf(model, cap) {
14
+ if (cap === "reasoning") {
15
+ const declared = model.reasoning;
16
+ if (declared === undefined)
17
+ return "unknown";
18
+ if (typeof declared !== "boolean") {
19
+ throw new TypeError(`Model.reasoning of ${nameOf(model)} must be true, false or absent; got ${typeWordOf(declared)}`);
20
+ }
21
+ return declared ? "declared_on" : "declared_off";
22
+ }
23
+ const input = model.input;
24
+ if (input === undefined)
25
+ return "unknown";
26
+ if (!Array.isArray(input) || !input.every((m) => typeof m === "string")) {
27
+ throw new TypeError(`Model.input of ${nameOf(model)} must be a list of input kinds or absent; got ${Array.isArray(input) ? "a list holding a non-string" : typeWordOf(input)}`);
28
+ }
29
+ return input.includes("image") ? "declared_on" : "declared_off";
30
+ }
31
+ export function capabilityHeld(model, cap) {
32
+ const declared = capabilityOf(model, cap);
33
+ return declared === "declared_on" || (declared === "unknown" && UNKNOWN_CAPABILITY_READS[cap] === "held");
34
+ }
@@ -19,16 +19,10 @@ import type { AnthropicMessagesCompat, Model } from "../internal/llm.js";
19
19
  * - `supportsTemperature: false` — CC never sends temperature to this class, thinking on OR off.
20
20
  */
21
21
  export declare const FABLE_5_COMPAT: AnthropicMessagesCompat;
22
- /**
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.
26
- */
27
- export declare const FABLE_5_PROMPT_GUIDANCE: readonly string[];
28
22
  /**
29
23
  * A ready-to-use `claude-fable-5` {@link Model} (registry facts: 1M-token native context
30
24
  * window, 64k default max output — the 128k tier is opt-in via `maxTokens` override, knowledge
31
- * cutoff Jan 2026, `default_effort: "high"`). Override anything per deployment; set `cost` for
32
- * accounting (not baked — see module note).
25
+ * cutoff Jan 2026, `default_effort: "high"`, prompt capabilities `lean_prompt` + `fable_5_mitigations`).
26
+ * Override anything per deployment; set `cost` for accounting (not baked — see module note).
33
27
  */
34
28
  export declare function fable5Model(overrides?: Partial<Model>): Model;
@@ -1,15 +1,9 @@
1
- import { catalogText } from "../prompt-assembly/catalog/index.js";
2
1
  import { ANTHROPIC_DEFAULT_BASE_URL } from "./anthropic.js";
3
2
  export const FABLE_5_COMPAT = {
4
3
  thinkingMode: "adaptive",
5
4
  effortLevels: ["low", "medium", "high", "xhigh", "max"],
6
5
  supportsTemperature: false,
7
6
  };
8
- export const FABLE_5_PROMPT_GUIDANCE = [
9
- catalogText("core/behavior.fable-classic.final-message"),
10
- catalogText("core/behavior.fable-classic.autonomy"),
11
- catalogText("core/behavior.fable-classic.tool-json"),
12
- ];
13
7
  export function fable5Model(overrides = {}) {
14
8
  return {
15
9
  id: "claude-fable-5",
@@ -25,6 +19,7 @@ export function fable5Model(overrides = {}) {
25
19
  maxTokens: 64_000,
26
20
  charsPerToken: 3,
27
21
  compat: { ...FABLE_5_COMPAT },
22
+ promptTraits: ["lean_prompt", "fable_5_mitigations"],
28
23
  ...overrides,
29
24
  };
30
25
  }
@@ -4,12 +4,12 @@ import { DEGENERATE_MESSAGE, trimDegenerateTail } from "./repetition.js";
4
4
  import { STREAM_TORN_WARNING, createRepetitionPoll, modelOutputInvalidOf, noteResponseModel, nameMissingCause, parseStreamedToolArgs, placeTurnNotes } from "./stream-shared.js";
5
5
  import { admitToolCallId, providerResultIds, providerToolCallId, responseToolCallIds } from "./tool-call-id.js";
6
6
  import { emitBrainTelemetry } from "./status-sink.js";
7
- import { errorResultMediaNote, IMAGE_OMITTED_NO_VISION, imagesOmittedNoVisionNote, modelSupportsVision, sendableImages } from "./media-degrade.js";
8
- import { OUTPUT_CAP_KEYS, RESPONSES_RESERVED, applyExtraBody, effectiveOutputCap, headerBagOnce, lockHeader, mergeHeaders } from "./request-params.js";
7
+ import { errorResultMediaNote, IMAGE_OMITTED_NO_VISION, imageWithholdOf, imagesOmittedNoVisionNote, reportImagesWithheld, sendableImages } from "./media-degrade.js";
8
+ import { OUTPUT_CAP_KEYS, RESPONSES_RESERVED, applyExtraBody, declaredRequestValues, effectiveOutputCap, headerBagOnce, lockHeader, mergeHeaders } from "./request-params.js";
9
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 { NAMES_AS_WRITTEN, resolveProviderDialect, endpointToolNames } from "./provider-dialect.js";
12
- import { declaredOffSpelling, mintEffortWireValue, reasoningRequestCarried } from "./reasoning.js";
12
+ import { applyReasoningToRequest } from "./reasoning-request.js";
13
13
  import { runStreamingBrain } from "./stream-engine.js";
14
14
  import { refuseRetiredTimeoutKnobs } from "./timeout.js";
15
15
  import { resolveFetch } from "./transport.js";
@@ -18,9 +18,6 @@ const DEGENERATE_POLL_CHARS = 64;
18
18
  const MALFORMED_SAMPLE_CHARS = 160;
19
19
  const MALFORMED_ARGS_CHARS = 200;
20
20
  const CAPABILITY_DIAGNOSTIC_TYPE = "responses_capability";
21
- function responsesCompat(model) {
22
- return (model.compat ?? {});
23
- }
24
21
  const NO_CONTENT = "(no content)";
25
22
  const DOCUMENT_OMITTED = "[PDF document omitted: PDF direct read requires an Anthropic-family model; re-Read the file (the engine will extract text/render pages when possible) or extract the text via Bash instead (e.g. `pdftotext`).]";
26
23
  function textOf(content) {
@@ -38,16 +35,17 @@ function functionCallOutputText(text, hasCarriedImages, original) {
38
35
  return "(image attached below)";
39
36
  return Array.isArray(original) && original.length > 0 ? "(non-text tool result omitted)" : "";
40
37
  }
41
- function toUserParts(content, supportsVision) {
38
+ function toUserParts(content, withhold) {
42
39
  if (typeof content === "string") {
43
40
  return content === "" ? [] : [{ type: "input_text", text: content }];
44
41
  }
42
+ const supportsVision = withhold === undefined;
45
43
  const nDocs = content.filter((c) => c.type === "document").length;
46
44
  if (nDocs > 0)
47
45
  emitBrainTelemetry({ kind: "document_placeholder", count: nDocs });
48
46
  const images = content.filter((c) => c.type === "image" && c.data !== undefined && c.mimeType !== undefined);
49
- if (!supportsVision && images.length > 0)
50
- emitBrainTelemetry({ kind: "vision_placeholder", count: images.length });
47
+ if (withhold !== undefined)
48
+ reportImagesWithheld(withhold, images.length);
51
49
  const parts = [];
52
50
  for (const c of content) {
53
51
  if (c.type === "text" && typeof c.text === "string" && c.text.length > 0) {
@@ -66,7 +64,8 @@ function toUserParts(content, supportsVision) {
66
64
  return parts;
67
65
  }
68
66
  function toResponsesInput(ctx, model, replayReasoning, toolNames) {
69
- const supportsVision = modelSupportsVision(model);
67
+ const imageWithhold = imageWithholdOf(model);
68
+ const supportsVision = imageWithhold === undefined;
70
69
  const out = [];
71
70
  let pendingImages = [];
72
71
  const flushImages = () => {
@@ -88,7 +87,7 @@ function toResponsesInput(ctx, model, replayReasoning, toolNames) {
88
87
  if (m.role !== "toolResult")
89
88
  flushImages();
90
89
  if (m.role === "user") {
91
- const parts = toUserParts(m.content, supportsVision);
90
+ const parts = toUserParts(m.content, imageWithhold);
92
91
  out.push({
93
92
  type: "message",
94
93
  role: "user",
@@ -124,8 +123,8 @@ function toResponsesInput(ctx, model, replayReasoning, toolNames) {
124
123
  const mediaImages = sendableImages(Array.isArray(m.content) ? m.content : []);
125
124
  const rawImages = m.isError ? [] : mediaImages;
126
125
  const images = supportsVision ? rawImages : [];
127
- if (!supportsVision && rawImages.length > 0)
128
- emitBrainTelemetry({ kind: "vision_placeholder", count: rawImages.length });
126
+ if (imageWithhold !== undefined)
127
+ reportImagesWithheld(imageWithhold, rawImages.length);
129
128
  const nDocs = Array.isArray(m.content) ? m.content.filter((c) => c.type === "document").length : 0;
130
129
  if (nDocs > 0)
131
130
  emitBrainTelemetry({ kind: "document_placeholder", count: nDocs });
@@ -157,16 +156,6 @@ function toResponsesTools(ctx, toolNames) {
157
156
  strict: false,
158
157
  }));
159
158
  }
160
- function resolveWireEffort(model, reasoning) {
161
- if (model.reasoning && reasoning === "off")
162
- return declaredOffSpelling(model);
163
- const compat = responsesCompat(model);
164
- if (compat.supportsReasoningEffort === false)
165
- return undefined;
166
- if (!reasoningRequestCarried(model, reasoning))
167
- return undefined;
168
- return mintEffortWireValue(reasoning, model, compat.reasoningEffortLevels).wireValue;
169
- }
170
159
  function computeUsage(model, raw) {
171
160
  const input = raw?.input_tokens ?? 0;
172
161
  const output = raw?.output_tokens ?? 0;
@@ -266,7 +255,6 @@ export function createOpenResponsesBrain(given = {}) {
266
255
  "remove it, or serve this model through the chat-completions lane, which does support it");
267
256
  }
268
257
  const requestedMaxTokens = overrides?.maxOutputTokens ?? options?.maxTokens ?? model.maxTokens;
269
- const effort = resolveWireEffort(model, options?.reasoning);
270
258
  const body = {
271
259
  model: model.id,
272
260
  input: toResponsesInput(context, model, config.replayReasoning !== false, builtToolNames),
@@ -290,17 +278,18 @@ export function createOpenResponsesBrain(given = {}) {
290
278
  builtMaxTokens = undefined;
291
279
  builtMaxTokensLane = "unset";
292
280
  }
293
- if (effort !== undefined)
294
- body.reasoning = { effort };
281
+ const { body: reasoningBody, effort } = applyReasoningToRequest({ api: "openai-responses", model, level: options?.reasoning, body });
295
282
  const headers = mergeHeaders(modelHeaders, config.headers, optionsHeaders);
296
283
  applyRouteCredentialHeaders(headers, routeCredential);
284
+ const declared = declaredRequestValues([modelHeaders, config.headers, optionsHeaders, headers], [], apiKey);
297
285
  lockHeader(headers, "content-type", "application/json");
298
286
  if (apiKey)
299
287
  lockHeader(headers, OPEN_RESPONSES_KEY_HEADER, `Bearer ${apiKey}`);
300
- const { body: wire, dropped: extraBodyDropped } = applyExtraBody(body, model, RESPONSES_RESERVED);
288
+ const { body: wire, dropped: extraBodyDropped } = applyExtraBody(reasoningBody, model, RESPONSES_RESERVED);
301
289
  return {
302
290
  url,
303
291
  headers,
292
+ declared,
304
293
  body: JSON.stringify(wire),
305
294
  extraBodyDropped,
306
295
  route: requestRouteOf(routeCredential, rootOrigin),
@@ -576,10 +565,10 @@ export function createOpenResponsesBrain(given = {}) {
576
565
  case "response.failed": {
577
566
  noteResponseModel(partial, frame.response?.model, model.id);
578
567
  const err = frame.response?.error;
579
- throw new BrainError(responsesErrorCode(err?.code), `responses stream failed (${err?.code ?? "unknown"}): ${err?.message ?? ""}`, undefined, { apiError: true });
568
+ throw new BrainError(responsesErrorCode(err?.code), `responses stream failed ${ctrl.providerWords(`(${err?.code ?? "unknown"}): ${err?.message ?? ""}`)}`, undefined, { apiError: true });
580
569
  }
581
570
  case "error": {
582
- throw new BrainError(responsesErrorCode(frame.code), `responses stream error (${frame.code ?? "unknown"}): ${frame.message ?? ""}`, undefined, { apiError: true });
571
+ throw new BrainError(responsesErrorCode(frame.code), `responses stream error ${ctrl.providerWords(`(${frame.code ?? "unknown"}): ${frame.message ?? ""}`)}`, undefined, { apiError: true });
583
572
  }
584
573
  default:
585
574
  return;
@@ -620,7 +609,7 @@ export function createOpenResponsesBrain(given = {}) {
620
609
  }
621
610
  catch {
622
611
  malformedFrames++;
623
- malformedSample ??= data.slice(0, MALFORMED_SAMPLE_CHARS);
612
+ malformedSample ??= ctrl.providerWords(data).slice(0, MALFORMED_SAMPLE_CHARS);
624
613
  return;
625
614
  }
626
615
  handleFrame(frame);
@@ -673,10 +662,10 @@ export function createOpenResponsesBrain(given = {}) {
673
662
  finalContent.push(tc);
674
663
  }
675
664
  else if (acc.name) {
676
- malformed.push(`${acc.name}(${acc.args.slice(0, MALFORMED_ARGS_CHARS)})`);
665
+ malformed.push(`${ctrl.providerWords(acc.name)}(${ctrl.providerWords(acc.args).slice(0, MALFORMED_ARGS_CHARS)})`);
677
666
  }
678
667
  else {
679
- (nameMissingCause(closed) === "truncated" ? malformed : unnamed).push(`call_id="${acc.callId || "?"}"(${acc.args.slice(0, MALFORMED_ARGS_CHARS)})`);
668
+ (nameMissingCause(closed) === "truncated" ? malformed : unnamed).push(`call_id="${ctrl.providerWords(acc.callId || "?")}"(${ctrl.providerWords(acc.args).slice(0, MALFORMED_ARGS_CHARS)})`);
680
669
  }
681
670
  }
682
671
  }
@@ -721,14 +710,14 @@ export function createOpenResponsesBrain(given = {}) {
721
710
  : safetyCut
722
711
  ? `[refusal] response cut by the provider content filter (incomplete_details.reason="${INCOMPLETE_CONTENT_FILTER}") — the output was censored/truncated for policy and is unreliable`
723
712
  : refused
724
- ? `[refusal] response refused by the model for policy reasons: ${accumRefusal.trim()}`
713
+ ? `[refusal] response refused by the model for policy reasons: ${ctrl.providerWords(accumRefusal.trim())}`
725
714
  : (toolError ??
726
715
  (truncatedEmpty && !dynamicCut && !staticReasoningCut
727
716
  ? reasoningSeen
728
717
  ? `[length_empty] response truncated at max_output_tokens (${maxTokensNote}) with no answer text — the model spent the whole budget on reasoning; raise the cap, or lower the reasoning effort for this task.`
729
718
  : `[length_empty] response truncated at max_output_tokens (${maxTokensNote}) with no answer text — raise the cap`
730
719
  : emptyNoFinish
731
- ? `[stream_torn] model stream ended with no content and ${terminalStatus === undefined ? "no terminal response event" : `a terminal status "${terminalStatus}" with no reason this client recognises (incomplete_details.reason=${incompleteReason ?? "absent"})`} — the response was lost (a torn stream or an in-band provider error frame)${malformedFrames > 0 ? ` — ${malformedFrames} unparseable data frame(s) were dropped on this stream (first sample: ${JSON.stringify(malformedSample)})` : ""}`
720
+ ? `[stream_torn] model stream ended with no content and ${terminalStatus === undefined ? "no terminal response event" : `a terminal status "${ctrl.providerWords(terminalStatus)}" with no reason this client recognises (incomplete_details.reason=${incompleteReason === undefined ? "absent" : ctrl.providerWords(String(incompleteReason))})`} — the response was lost (a torn stream or an in-band provider error frame)${malformedFrames > 0 ? ` — ${malformedFrames} unparseable data frame(s) were dropped on this stream (first sample: ${JSON.stringify(malformedSample)})` : ""}`
732
721
  : undefined));
733
722
  const errored = degenerate ||
734
723
  safetyCut ||