@sema-agent/core 7.48.0 → 7.49.1

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 (421) hide show
  1. package/CHANGELOG.md +457 -0
  2. package/README.md +2 -2
  3. package/dist/agents/cascade.d.ts +2 -5
  4. package/dist/agents/child-failure.d.ts +20 -0
  5. package/dist/agents/child-failure.js +28 -0
  6. package/dist/agents/cross-session-ref.d.ts +11 -3
  7. package/dist/agents/cross-session-ref.js +6 -0
  8. package/dist/agents/cumulative-stats.d.ts +12 -15
  9. package/dist/agents/cumulative-stats.js +1 -1
  10. package/dist/agents/extra-tool-names.js +1 -1
  11. package/dist/agents/inherited-tool-pool.d.ts +17 -13
  12. package/dist/agents/inherited-tool-pool.js +4 -3
  13. package/dist/agents/peer-session-drain.d.ts +3 -2
  14. package/dist/agents/peer-session-drain.js +5 -4
  15. package/dist/agents/send-message-tool.js +2 -9
  16. package/dist/agents/subagent.d.ts +10 -29
  17. package/dist/agents/subagent.js +65 -53
  18. package/dist/agents/suspend-guard.d.ts +1 -1
  19. package/dist/agents/tool-filter.d.ts +76 -65
  20. package/dist/agents/tool-filter.js +122 -92
  21. package/dist/agents/verify.d.ts +4 -7
  22. package/dist/agents/verify.js +6 -7
  23. package/dist/bench/metrics.d.ts +1 -2
  24. package/dist/brain/anthropic.js +133 -79
  25. package/dist/brain/errors.d.ts +53 -6
  26. package/dist/brain/errors.js +22 -2
  27. package/dist/brain/input-too-long.d.ts +40 -19
  28. package/dist/brain/input-too-long.js +3 -16
  29. package/dist/brain/open-responses.js +19 -10
  30. package/dist/brain/openai.js +123 -32
  31. package/dist/brain/provider-dialect.d.ts +214 -0
  32. package/dist/brain/provider-dialect.js +186 -0
  33. package/dist/brain/request-params.d.ts +27 -8
  34. package/dist/brain/request-params.js +7 -12
  35. package/dist/brain/request-route.d.ts +84 -0
  36. package/dist/brain/request-route.js +41 -0
  37. package/dist/brain/retry.d.ts +8 -0
  38. package/dist/brain/retry.js +10 -4
  39. package/dist/brain/route-adjudicator.d.ts +7 -0
  40. package/dist/brain/route-adjudicator.js +5 -1
  41. package/dist/brain/status-sink.d.ts +20 -0
  42. package/dist/brain/status-sink.js +11 -0
  43. package/dist/brain/stream-engine.d.ts +52 -1
  44. package/dist/brain/stream-engine.js +81 -24
  45. package/dist/brain/stream-shared.d.ts +57 -11
  46. package/dist/brain/stream-shared.js +28 -2
  47. package/dist/core/a2a.d.ts +1 -0
  48. package/dist/core/agent-config-dir.js +3 -2
  49. package/dist/core/allow-entry.d.ts +21 -12
  50. package/dist/core/allow-entry.js +38 -31
  51. package/dist/core/arg-summary.d.ts +21 -28
  52. package/dist/core/arg-summary.js +235 -88
  53. package/dist/core/ask-origin.d.ts +42 -24
  54. package/dist/core/ask-origin.js +18 -13
  55. package/dist/core/auto-mode-prompt-assets.d.ts +2 -2
  56. package/dist/core/auto-mode-prompt-assets.js +1 -1
  57. package/dist/core/auto-mode-prompt.d.ts +11 -1
  58. package/dist/core/auto-mode-prompt.js +13 -10
  59. package/dist/core/auto-mode-rebuild.d.ts +7 -0
  60. package/dist/core/auto-mode-rebuild.js +4 -1
  61. package/dist/core/canonical-json.d.ts +3 -0
  62. package/dist/core/canonical-json.js +2 -1
  63. package/dist/core/checkpoint-requirements.d.ts +892 -0
  64. package/dist/core/checkpoint-requirements.js +333 -0
  65. package/dist/core/checkpoint-store.d.ts +94 -65
  66. package/dist/core/checkpoint-store.js +14 -26
  67. package/dist/core/child-clamp-seats.d.ts +228 -69
  68. package/dist/core/child-clamp-seats.js +211 -17
  69. package/dist/core/classifier-unavailable-arm.d.ts +5 -1
  70. package/dist/core/classifier-unavailable-arm.js +3 -3
  71. package/dist/core/compliance.d.ts +3 -0
  72. package/dist/core/compliance.js +9 -4
  73. package/dist/core/credential-vocabulary.d.ts +140 -0
  74. package/dist/core/credential-vocabulary.js +131 -0
  75. package/dist/core/decision-receipt.js +1 -1
  76. package/dist/core/effective-path-target.d.ts +73 -16
  77. package/dist/core/effective-path-target.js +63 -33
  78. package/dist/core/engine-notice.d.ts +43 -11
  79. package/dist/core/file-history-store.js +2 -2
  80. package/dist/core/fs-write-gate-policy.d.ts +4 -0
  81. package/dist/core/fs-write-gate-policy.js +22 -5
  82. package/dist/core/gate-bounded-await.d.ts +28 -13
  83. package/dist/core/gate-bounded-await.js +41 -4
  84. package/dist/core/gate-fold.d.ts +1 -1
  85. package/dist/core/gate-fold.js +24 -25
  86. package/dist/core/gate-lanes.js +16 -15
  87. package/dist/core/gate-outcome.d.ts +20 -5
  88. package/dist/core/gate-outcome.js +5 -0
  89. package/dist/core/governance-codes.d.ts +11 -4
  90. package/dist/core/governance-codes.js +14 -3
  91. package/dist/core/hooks.d.ts +21 -0
  92. package/dist/core/locked-config.d.ts +8 -0
  93. package/dist/core/locked-config.js +14 -2
  94. package/dist/core/lsp.js +3 -5
  95. package/dist/core/mailbox-store.d.ts +3 -4
  96. package/dist/core/mcp-connection-pool.d.ts +75 -0
  97. package/dist/core/mcp-connection-pool.js +128 -0
  98. package/dist/core/mcp-failure.d.ts +2 -1
  99. package/dist/core/mcp-failure.js +13 -2
  100. package/dist/core/mcp.d.ts +4 -0
  101. package/dist/core/mcp.js +70 -43
  102. package/dist/core/memory-engine/content-origin.js +2 -14
  103. package/dist/core/memory-engine/engine.d.ts +32 -22
  104. package/dist/core/memory-engine/engine.js +103 -55
  105. package/dist/core/memory-engine/file-backend.d.ts +13 -30
  106. package/dist/core/memory-engine/file-backend.js +37 -252
  107. package/dist/core/memory-engine/index.d.ts +1 -1
  108. package/dist/core/memory-engine/index.js +1 -1
  109. package/dist/core/memory-engine/layout.d.ts +139 -9
  110. package/dist/core/memory-engine/layout.js +350 -7
  111. package/dist/core/memory-engine/scope-contract.d.ts +10 -0
  112. package/dist/core/memory-engine/scope-contract.js +8 -0
  113. package/dist/core/memory-engine/session-incarnation.d.ts +14 -4
  114. package/dist/core/memory-engine/session-incarnation.js +5 -2
  115. package/dist/core/memory-engine/types.d.ts +10 -1
  116. package/dist/core/memory.js +5 -17
  117. package/dist/core/model-seat.d.ts +4 -4
  118. package/dist/core/model-seat.js +1 -1
  119. package/dist/core/mounted-mcp.d.ts +57 -0
  120. package/dist/core/mounted-mcp.js +19 -0
  121. package/dist/core/namespaced-rule-name.d.ts +29 -0
  122. package/dist/core/namespaced-rule-name.js +52 -0
  123. package/dist/core/park-selfcheck.d.ts +1 -1
  124. package/dist/core/park-selfcheck.js +16 -6
  125. package/dist/core/path-guard-rows.d.ts +99 -0
  126. package/dist/core/path-guard-rows.js +45 -0
  127. package/dist/core/path-identity.d.ts +22 -16
  128. package/dist/core/path-identity.js +10 -10
  129. package/dist/core/path-rule-binding.d.ts +2 -1
  130. package/dist/core/path-rule-binding.js +3 -1
  131. package/dist/core/pause-registry.d.ts +16 -2
  132. package/dist/core/pause-registry.js +6 -0
  133. package/dist/core/permission-rule-consent.js +0 -7
  134. package/dist/core/permission-rule-model.d.ts +68 -24
  135. package/dist/core/permission-rule-model.js +105 -24
  136. package/dist/core/permission-rule-store.js +2 -2
  137. package/dist/core/permission-rules.d.ts +3 -30
  138. package/dist/core/permission-rules.js +4 -54
  139. package/dist/core/read-root-candidate.d.ts +1 -3
  140. package/dist/core/read-root-candidate.js +4 -15
  141. package/dist/core/real-approval.d.ts +4 -3
  142. package/dist/core/retired-keys.d.ts +13 -0
  143. package/dist/core/retired-keys.js +14 -0
  144. package/dist/core/roles.d.ts +2 -3
  145. package/dist/core/roles.js +15 -6
  146. package/dist/core/runner/assemble-result.d.ts +0 -7
  147. package/dist/core/runner/assemble-result.js +19 -31
  148. package/dist/core/runner/caller-roster.d.ts +78 -0
  149. package/dist/core/runner/caller-roster.js +219 -0
  150. package/dist/core/runner/checkpoint-scope.d.ts +16 -16
  151. package/dist/core/runner/checkpoint-scope.js +2 -2
  152. package/dist/core/runner/child-tree.js +2 -2
  153. package/dist/core/runner/contracts.d.ts +68 -35
  154. package/dist/core/runner/decide-continuation.d.ts +51 -3
  155. package/dist/core/runner/decide-continuation.js +76 -21
  156. package/dist/core/runner/denial-limit-arms.d.ts +17 -5
  157. package/dist/core/runner/denial-limit-arms.js +11 -9
  158. package/dist/core/runner/extra-body-dropped-seat.d.ts +8 -0
  159. package/dist/core/runner/extra-body-dropped-seat.js +22 -0
  160. package/dist/core/runner/finish-reason-seat.d.ts +9 -0
  161. package/dist/core/runner/finish-reason-seat.js +40 -0
  162. package/dist/core/runner/gate-exit.d.ts +44 -32
  163. package/dist/core/runner/gate-exit.js +112 -25
  164. package/dist/core/runner/inherited-ask-grants.js +6 -4
  165. package/dist/core/runner/mcp-redial.d.ts +3 -3
  166. package/dist/core/runner/mcp-redial.js +3 -4
  167. package/dist/core/runner/permission-rule-lanes.d.ts +1 -2
  168. package/dist/core/runner/permission-rule-lanes.js +5 -4
  169. package/dist/core/runner/prepare-artifact.d.ts +4 -0
  170. package/dist/core/runner/prepare-artifact.js +2 -1
  171. package/dist/core/runner/prepare-ask-lane.d.ts +2 -0
  172. package/dist/core/runner/prepare-ask-lane.js +12 -6
  173. package/dist/core/runner/prepare-boundary-parks.d.ts +5 -8
  174. package/dist/core/runner/prepare-boundary-parks.js +4 -7
  175. package/dist/core/runner/prepare-caps-and-workflow.d.ts +11 -15
  176. package/dist/core/runner/prepare-caps-and-workflow.js +19 -27
  177. package/dist/core/runner/prepare-config-doors.d.ts +9 -9
  178. package/dist/core/runner/prepare-config-doors.js +10 -5
  179. package/dist/core/runner/prepare-defer-classify.d.ts +2 -2
  180. package/dist/core/runner/prepare-defer-classify.js +5 -3
  181. package/dist/core/runner/prepare-delegation-surface.d.ts +1 -1
  182. package/dist/core/runner/prepare-delegation-surface.js +3 -3
  183. package/dist/core/runner/prepare-gate-stations.d.ts +4 -4
  184. package/dist/core/runner/prepare-gate-stations.js +9 -7
  185. package/dist/core/runner/prepare-hands-readface.d.ts +7 -7
  186. package/dist/core/runner/prepare-hands-readface.js +7 -7
  187. package/dist/core/runner/prepare-inherited-gate.d.ts +7 -6
  188. package/dist/core/runner/prepare-inherited-gate.js +14 -15
  189. package/dist/core/runner/prepare-listings.d.ts +7 -24
  190. package/dist/core/runner/prepare-listings.js +4 -5
  191. package/dist/core/runner/prepare-memory-engine-session.d.ts +2 -0
  192. package/dist/core/runner/prepare-memory-engine-session.js +4 -3
  193. package/dist/core/runner/prepare-memory.d.ts +6 -0
  194. package/dist/core/runner/prepare-memory.js +13 -13
  195. package/dist/core/runner/prepare-offload-wrappers.d.ts +5 -0
  196. package/dist/core/runner/prepare-offload-wrappers.js +3 -3
  197. package/dist/core/runner/prepare-park-ask.d.ts +7 -8
  198. package/dist/core/runner/prepare-park-ask.js +17 -10
  199. package/dist/core/runner/prepare-policy-chain.js +24 -44
  200. package/dist/core/runner/prepare-project-context.d.ts +1 -1
  201. package/dist/core/runner/prepare-project-context.js +3 -4
  202. package/dist/core/runner/prepare-protocol-tools.d.ts +9 -3
  203. package/dist/core/runner/prepare-protocol-tools.js +3 -4
  204. package/dist/core/runner/prepare-run-refs.d.ts +3 -0
  205. package/dist/core/runner/prepare-run-refs.js +2 -1
  206. package/dist/core/runner/prepare-safety-scan.d.ts +4 -8
  207. package/dist/core/runner/prepare-safety-scan.js +1 -2
  208. package/dist/core/runner/prepare-suspend-saga.d.ts +7 -1
  209. package/dist/core/runner/prepare-suspend-saga.js +28 -12
  210. package/dist/core/runner/prepare-task.d.ts +1 -1
  211. package/dist/core/runner/prepare-task.js +67 -56
  212. package/dist/core/runner/prepare-wiring-manifest.d.ts +11 -10
  213. package/dist/core/runner/prepare-wiring-manifest.js +5 -8
  214. package/dist/core/runner/resume-apply.js +7 -14
  215. package/dist/core/runner/resume-checkpoint-screen.js +11 -4
  216. package/dist/core/runner/resume-internals-and-config.js +2 -2
  217. package/dist/core/runner/resume-policy-outcome.js +5 -32
  218. package/dist/core/runner/resume-review-outcome.js +4 -1
  219. package/dist/core/runner/retired-runner-deps.d.ts +6 -0
  220. package/dist/core/runner/retired-runner-deps.js +10 -1
  221. package/dist/core/runner/run-brain-sinks.d.ts +4 -0
  222. package/dist/core/runner/run-brain-sinks.js +5 -2
  223. package/dist/core/runner/run-harness-handlers.js +29 -36
  224. package/dist/core/runner/run-leg.d.ts +0 -2
  225. package/dist/core/runner/run-leg.js +32 -33
  226. package/dist/core/runner/run-terminal-adoption.js +4 -3
  227. package/dist/core/runner/runtask.js +8 -8
  228. package/dist/core/runner/session-rule-policy.js +5 -5
  229. package/dist/core/runner/stream-settle-backstop.js +7 -4
  230. package/dist/core/runner/sub-agent-deny-lists.d.ts +51 -12
  231. package/dist/core/runner/sub-agent-deny-lists.js +111 -80
  232. package/dist/core/runner/terminal-account.d.ts +48 -0
  233. package/dist/core/runner/terminal-account.js +186 -0
  234. package/dist/core/runner/tool-end-body.d.ts +54 -17
  235. package/dist/core/runner/tool-end-body.js +27 -2
  236. package/dist/core/runner/tool-face-overlay.d.ts +3 -1
  237. package/dist/core/runner/tool-face-overlay.js +6 -4
  238. package/dist/core/runner/tool-occurrence.d.ts +106 -0
  239. package/dist/core/runner/tool-occurrence.js +123 -0
  240. package/dist/core/runner/tool-progress-lane.d.ts +16 -8
  241. package/dist/core/runner/tool-progress-lane.js +25 -34
  242. package/dist/core/runner/tool-turn-repair-seat.d.ts +28 -4
  243. package/dist/core/runner/tool-turn-repair-seat.js +36 -13
  244. package/dist/core/runner/turn-attachments.d.ts +1 -1
  245. package/dist/core/runner/write-protection-station.d.ts +21 -9
  246. package/dist/core/runner/write-protection-station.js +20 -17
  247. package/dist/core/runner-deps.d.ts +12 -22
  248. package/dist/core/secret-env.d.ts +16 -5
  249. package/dist/core/secret-env.js +23 -63
  250. package/dist/core/sensitive-path-policy.d.ts +19 -18
  251. package/dist/core/sensitive-path-policy.js +73 -49
  252. package/dist/core/session-reconcile.d.ts +3 -0
  253. package/dist/core/session-reconcile.js +5 -4
  254. package/dist/core/session-store.d.ts +5 -0
  255. package/dist/core/session-store.js +12 -0
  256. package/dist/core/session.d.ts +13 -0
  257. package/dist/core/shared-memory/normalize.d.ts +17 -4
  258. package/dist/core/shared-memory/normalize.js +7 -7
  259. package/dist/core/shell-lexer.js +5 -4
  260. package/dist/core/shell-wrapper-projection.js +1 -1
  261. package/dist/core/skill-grant.js +1 -1
  262. package/dist/core/store-contracts/checkpoint-store-contract.js +13 -0
  263. package/dist/core/store-contracts/mailbox-store-contract.d.ts +7 -14
  264. package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +27 -0
  265. package/dist/core/store-contracts/session-store-incarnation-contract.js +92 -0
  266. package/dist/core/stub-env.d.ts +2 -0
  267. package/dist/core/stub-env.js +1 -0
  268. package/dist/core/synthetic-read-verdict.js +2 -2
  269. package/dist/core/task-event.d.ts +59 -5
  270. package/dist/core/task-result.d.ts +1 -1
  271. package/dist/core/task-spec.d.ts +42 -9
  272. package/dist/core/terminal-cause.d.ts +94 -11
  273. package/dist/core/tighten-task-spec.d.ts +5 -4
  274. package/dist/core/tighten-task-spec.js +20 -25
  275. package/dist/core/tool-catalog-entries.d.ts +5 -7
  276. package/dist/core/tool-catalog-entries.js +14 -15
  277. package/dist/core/tool-face.d.ts +47 -0
  278. package/dist/core/tool-face.js +5 -0
  279. package/dist/core/tool-model-gate.d.ts +5 -5
  280. package/dist/core/tool-name-aliases.d.ts +26 -2
  281. package/dist/core/tool-name-aliases.js +13 -0
  282. package/dist/core/tool-name-list.d.ts +30 -0
  283. package/dist/core/tool-name-list.js +55 -0
  284. package/dist/core/tool-name-readings.d.ts +1 -9
  285. package/dist/core/tool-name-readings.js +1 -3
  286. package/dist/core/tool-policy.d.ts +195 -85
  287. package/dist/core/tool-policy.js +165 -380
  288. package/dist/core/tool-registry.d.ts +44 -1
  289. package/dist/core/tool-registry.js +26 -0
  290. package/dist/core/tool-roster.d.ts +19 -1
  291. package/dist/core/tool-roster.js +21 -2
  292. package/dist/core/tool-spec-members.d.ts +45 -0
  293. package/dist/core/tool-spec-members.js +169 -0
  294. package/dist/core/tool-spec.d.ts +46 -8
  295. package/dist/core/tools.d.ts +6 -2
  296. package/dist/core/tools.js +8 -4
  297. package/dist/core/untrusted-egress.js +29 -26
  298. package/dist/core/untrusted-text.d.ts +13 -10
  299. package/dist/core/untrusted-text.js +6 -44
  300. package/dist/core/workflow-journal-store.d.ts +4 -1
  301. package/dist/core/write-protect.d.ts +65 -29
  302. package/dist/core/write-protect.js +235 -177
  303. package/dist/engine/compaction/compaction.d.ts +2 -2
  304. package/dist/engine/execution-env/node-execution-env.d.ts +5 -23
  305. package/dist/engine/execution-env/node-execution-env.js +16 -38
  306. package/dist/engine/execution-env/symlink-chain.d.ts +23 -0
  307. package/dist/engine/execution-env/symlink-chain.js +32 -0
  308. package/dist/engine/harness/types.d.ts +7 -0
  309. package/dist/engine/llm/tool-turns.d.ts +3 -0
  310. package/dist/engine/llm/tool-turns.js +1 -0
  311. package/dist/engine/llm/types.d.ts +59 -23
  312. package/dist/engine/loop/agent-loop.js +16 -2
  313. package/dist/engine/session/memory-repo.js +11 -3
  314. package/dist/engine/session/repo-utils.d.ts +8 -0
  315. package/dist/engine/session/repo-utils.js +13 -0
  316. package/dist/index.d.ts +20 -23
  317. package/dist/index.js +17 -20
  318. package/dist/internal/harness.d.ts +1 -1
  319. package/dist/internal/harness.js +1 -1
  320. package/dist/internal/llm.d.ts +2 -2
  321. package/dist/internal/llm.js +1 -1
  322. package/dist/orchestration/governance-baseline-validity.js +1 -1
  323. package/dist/orchestration/run-spec.js +3 -3
  324. package/dist/orchestration/run-workflow-tool.d.ts +16 -35
  325. package/dist/orchestration/run-workflow-tool.js +38 -78
  326. package/dist/orchestration/workflow-governance.d.ts +21 -25
  327. package/dist/orchestration/workflow-governance.js +38 -78
  328. package/dist/orchestration/workflow-primitives.d.ts +7 -22
  329. package/dist/orchestration/workflow-primitives.js +5 -12
  330. package/dist/orchestration/workflow-types.d.ts +1 -1
  331. package/dist/orchestration/workflow.d.ts +61 -11
  332. package/dist/orchestration/workflow.js +189 -117
  333. package/dist/scenarios/full-body.d.ts +1 -1
  334. package/dist/shell/lex.d.ts +0 -21
  335. package/dist/shell/lex.js +250 -68
  336. package/dist/shell/shell-words.d.ts +35 -0
  337. package/dist/shell/shell-words.js +65 -0
  338. package/dist/stores/file/checkpoint-store.d.ts +5 -5
  339. package/dist/stores/file/checkpoint-store.js +5 -2
  340. package/dist/stores/file/index.d.ts +0 -8
  341. package/dist/stores/file/index.js +0 -12
  342. package/dist/stores/file/session-store.d.ts +3 -0
  343. package/dist/stores/file/session-store.js +44 -19
  344. package/dist/tools/artifact/artifact-tool.js +2 -0
  345. package/dist/tools/fs/bash-program-position.d.ts +12 -4
  346. package/dist/tools/fs/bash-program-position.js +32 -9
  347. package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
  348. package/dist/tools/fs/bash-readonly-classifier.js +8 -7
  349. package/dist/tools/fs/containment-face.d.ts +4 -0
  350. package/dist/tools/fs/containment-face.js +3 -0
  351. package/dist/tools/fs/fs-shared.d.ts +10 -0
  352. package/dist/tools/fs/fs-shared.js +18 -0
  353. package/dist/tools/fs/fs-write.js +4 -2
  354. package/dist/tools/fs/index.d.ts +1 -1
  355. package/dist/tools/fs/program-read-model.d.ts +46 -20
  356. package/dist/tools/fs/program-read-model.js +50 -20
  357. package/dist/tools/fs/program-read-model.rows.d.ts +0 -14
  358. package/dist/tools/fs/program-read-model.rows.js +16 -15
  359. package/dist/tools/fs/read-deny-home.d.ts +33 -47
  360. package/dist/tools/fs/read-deny-home.js +35 -49
  361. package/dist/tools/fs/read-deny.d.ts +23 -22
  362. package/dist/tools/fs/read-deny.js +114 -89
  363. package/dist/tools/fs/removal-targets.d.ts +56 -23
  364. package/dist/tools/fs/removal-targets.js +65 -87
  365. package/dist/tools/fs/safety.d.ts +29 -22
  366. package/dist/tools/fs/safety.js +17 -11
  367. package/dist/tools/fs/search.js +10 -8
  368. package/dist/tools/fs/shell-read-argv.js +1 -1
  369. package/dist/tools/fs/shell-read-bindings.d.ts +169 -37
  370. package/dist/tools/fs/shell-read-bindings.js +324 -86
  371. package/dist/tools/fs/shell-read-builtins.d.ts +35 -0
  372. package/dist/tools/fs/shell-read-builtins.js +43 -0
  373. package/dist/tools/fs/shell-read-check.d.ts +15 -1
  374. package/dist/tools/fs/shell-read-check.js +67 -43
  375. package/dist/tools/fs/shell-read-establish.js +6 -6
  376. package/dist/tools/fs/shell-read-functions.d.ts +22 -0
  377. package/dist/tools/fs/shell-read-functions.js +29 -0
  378. package/dist/tools/fs/shell-read-judge.d.ts +51 -18
  379. package/dist/tools/fs/shell-read-judge.js +40 -4
  380. package/dist/tools/fs/shell-read-plan.d.ts +12 -6
  381. package/dist/tools/fs/shell-read-plan.js +118 -113
  382. package/dist/tools/fs/shell-read-start.d.ts +29 -6
  383. package/dist/tools/fs/shell-read-start.js +16 -9
  384. package/dist/tools/fs/shell-read-word.js +4 -0
  385. package/dist/tools/fs/shell-read-workdir.d.ts +156 -0
  386. package/dist/tools/fs/shell-read-workdir.js +281 -0
  387. package/dist/tools/fs/shell-read-write-targets.d.ts +5 -2
  388. package/dist/tools/fs/shell-read-write-targets.js +14 -5
  389. package/dist/tools/fs/shell-reentry-text.d.ts +4 -6
  390. package/dist/tools/fs/shell-reentry-text.js +3 -11
  391. package/dist/tools/task-list.d.ts +1 -2
  392. package/dist/tools/web.js +1 -1
  393. package/package.json +4 -1
  394. package/test/export-surface.snapshot.json +107 -143
  395. package/wire-changes/core@7.49.0.json +4765 -0
  396. package/dist/agents/teacher.d.ts +0 -159
  397. package/dist/agents/teacher.js +0 -577
  398. package/dist/agents/team.d.ts +0 -226
  399. package/dist/agents/team.js +0 -257
  400. package/dist/core/strategy-store.d.ts +0 -238
  401. package/dist/core/strategy-store.js +0 -253
  402. package/dist/orchestration/builtin-workflows.d.ts +0 -133
  403. package/dist/orchestration/builtin-workflows.js +0 -159
  404. package/dist/scenarios/env.d.ts +0 -40
  405. package/dist/scenarios/env.js +0 -39
  406. package/dist/scenarios/scenario-registry.d.ts +0 -110
  407. package/dist/scenarios/scenario-registry.js +0 -140
  408. package/dist/scenarios/teacher-quickstart.d.ts +0 -40
  409. package/dist/scenarios/teacher-quickstart.js +0 -12
  410. package/dist/stores/cc/lockfile.d.ts +0 -10
  411. package/dist/stores/cc/lockfile.js +0 -98
  412. package/dist/stores/cc/mailbox-store.d.ts +0 -20
  413. package/dist/stores/cc/mailbox-store.js +0 -255
  414. package/dist/stores/cc/roster-adapter.d.ts +0 -12
  415. package/dist/stores/cc/roster-adapter.js +0 -117
  416. package/dist/stores/cc/sidecar-transcript.d.ts +0 -97
  417. package/dist/stores/cc/sidecar-transcript.js +0 -264
  418. package/dist/stores/cc/task-list-store.d.ts +0 -2
  419. package/dist/stores/cc/task-list-store.js +0 -125
  420. package/dist/stores/file/strategy-store.d.ts +0 -97
  421. package/dist/stores/file/strategy-store.js +0 -341
@@ -2,12 +2,13 @@ import {} from "../internal/llm.js";
2
2
  import { BrainError } from "./errors.js";
3
3
  import { startsWithInputTooLongAnchor } from "./input-too-long.js";
4
4
  import { DEGENERATE_MESSAGE, trimDegenerateTail } from "./repetition.js";
5
- import { STREAM_TORN_WARNING, createRepetitionPoll, noteResponseModel, parseStreamedToolArgs, placeTurnNotes, truncationCauseClause } from "./stream-shared.js";
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
8
  import { errorResultMediaNote, IMAGE_OMITTED_NO_VISION, modelSupportsVision, sendableImages } from "./media-degrade.js";
9
9
  import { ANTHROPIC_RESERVED, OUTPUT_CAP_KEYS, applyExtraBody, effectiveOutputCap, lockHeader, mergeHeaders, takeHeaderCasefold } from "./request-params.js";
10
- import { adjudicateModelRoute, applyRouteCredentialHeaders, assertServableRequestRoot, createBrainRouteJudge, joinRequestUrl, resolveRequestRoot, resolveRouteCredential, routeRefusalText } from "./route-adjudicator.js";
10
+ import { adjudicateModelRoute, applyRouteCredentialHeaders, assertServableRequestRoot, createBrainRouteJudge, joinRequestUrl, resolveRequestRootOf, resolveRouteCredential, routeRefusalText } from "./route-adjudicator.js";
11
+ import { requestRouteOf } from "./request-route.js";
11
12
  import { MIN_THINKING_TOKENS, budgetCapSkipsThinking, declaredEffortLevels, reasoningBudgetShare, reasoningRequestCarried, resolveEffort } from "./reasoning.js";
12
13
  import { runStreamingBrain } from "./stream-engine.js";
13
14
  import { refuseRetiredTimeoutKnobs } from "./timeout.js";
@@ -213,12 +214,12 @@ function computeUsage(model, u) {
213
214
  },
214
215
  };
215
216
  }
216
- function closeToolUseBlock(acc, responseIds) {
217
+ function closeToolUseBlock(acc, responseIds, closed) {
217
218
  if (acc.closedTc)
218
219
  return acc.closedTc;
219
220
  if (!acc.toolName)
220
221
  return undefined;
221
- const args = parseStreamedToolArgs(acc.toolJson);
222
+ const args = parseStreamedToolArgs(acc.toolJson, closed);
222
223
  if (args === undefined)
223
224
  return undefined;
224
225
  const { engineId, wireId } = admitToolCallId(acc.toolId, "toolu_", responseIds);
@@ -243,7 +244,7 @@ export function createAnthropicBrain(config = {}) {
243
244
  maxRetries: options?.maxRetries,
244
245
  stallTimeouts: options?.stallTimeouts,
245
246
  buildRequest: (overrides) => {
246
- const root = resolveRequestRoot(model.baseUrl, config.baseUrl, "https://api.anthropic.com");
247
+ const { root, origin: rootOrigin } = resolveRequestRootOf(model.baseUrl, config.baseUrl, "https://api.anthropic.com");
247
248
  const routeCredential = resolveRouteCredential({
248
249
  optionsApiKey: options?.apiKey,
249
250
  optionsHeaders: options?.headers,
@@ -349,11 +350,13 @@ export function createAnthropicBrain(config = {}) {
349
350
  : model.maxTokens !== undefined
350
351
  ? "model"
351
352
  : "config-default";
352
- const wire = applyExtraBody(body, model.extraBody, ANTHROPIC_RESERVED);
353
+ const { body: wire, dropped: extraBodyDropped } = applyExtraBody(body, model.extraBody, ANTHROPIC_RESERVED);
353
354
  return {
354
355
  url: joinRequestUrl(root, "/v1/messages"),
355
356
  headers,
356
357
  body: JSON.stringify(wire),
358
+ extraBodyDropped,
359
+ route: requestRouteOf(routeCredential, rootOrigin),
357
360
  outputCapTokens: effectiveOutputCap(wire, OUTPUT_CAP_KEYS.anthropic),
358
361
  capDerivedPaths: [...OUTPUT_CAP_KEYS.anthropic, "thinking.budget_tokens"],
359
362
  onCommitted: () => {
@@ -371,7 +374,6 @@ export function createAnthropicBrain(config = {}) {
371
374
  const responseIds = responseToolCallIds();
372
375
  const usageRaw = {};
373
376
  let stopReason = null;
374
- const terminalFrameSeen = () => stopReason != null;
375
377
  let stopDetails;
376
378
  let nextContentIndex = 0;
377
379
  let malformedFrames = 0;
@@ -382,7 +384,116 @@ export function createAnthropicBrain(config = {}) {
382
384
  let lastDegenCheck = 0;
383
385
  let lastDegenCheckThinking = 0;
384
386
  const detectRep = config.detectRepetition !== false;
387
+ let messageStopped = false;
388
+ const afterEnd = createStreamEndLedger();
389
+ const streamEnded = () => stopReason != null || messageStopped;
390
+ const mergeDeltaUsage = (u) => {
391
+ if (!u)
392
+ return;
393
+ if (u.output_tokens !== undefined)
394
+ usageRaw.output_tokens = u.output_tokens;
395
+ if (u.input_tokens != null && u.input_tokens > 0)
396
+ usageRaw.input_tokens = u.input_tokens;
397
+ if (u.cache_read_input_tokens != null && u.cache_read_input_tokens > 0)
398
+ usageRaw.cache_read_input_tokens = u.cache_read_input_tokens;
399
+ if (u.cache_creation_input_tokens != null && u.cache_creation_input_tokens > 0) {
400
+ usageRaw.cache_creation_input_tokens = u.cache_creation_input_tokens;
401
+ }
402
+ };
403
+ const reportedUsage = () => ({
404
+ usage: computeUsage(model, usageRaw),
405
+ ...(Object.keys(usageRaw).length === 0 ? { usageMissing: true } : {}),
406
+ });
407
+ const wordOf = (v) => (typeof v === "string" && v !== "" ? v : "?");
408
+ const refuseAfterEnd = (evt) => {
409
+ switch (evt.type) {
410
+ case "message_delta": {
411
+ mergeDeltaUsage(evt.usage);
412
+ const late = evt.delta?.stop_reason;
413
+ if (typeof late === "string" && late !== "" && late !== stopReason)
414
+ afterEnd.note("ending", late);
415
+ return;
416
+ }
417
+ case "content_block_start":
418
+ afterEnd.note("content", wordOf(evt.content_block?.type));
419
+ return;
420
+ case "content_block_delta":
421
+ afterEnd.note("content", wordOf(evt.delta?.type));
422
+ return;
423
+ case "content_block_stop":
424
+ case "message_start":
425
+ afterEnd.note("content", evt.type);
426
+ return;
427
+ case "error":
428
+ afterEnd.note("error", wordOf(evt.error?.type));
429
+ return;
430
+ default:
431
+ return;
432
+ }
433
+ };
434
+ const assembleTurn = (stampOn) => {
435
+ const finalContent = [];
436
+ const toolCalls = [];
437
+ const malformed = [];
438
+ const unnamed = [];
439
+ let anyText = false;
440
+ let reasoningSeen = false;
441
+ const endedCut = stopReason === "max_tokens" || stopReason == null;
442
+ for (const [, acc] of [...blocks.entries()].sort((a, b) => a[0] - b[0])) {
443
+ if (acc.type === "thinking") {
444
+ if (acc.text.length > 0 || acc.redacted === true)
445
+ reasoningSeen = true;
446
+ const block = { type: "thinking", thinking: acc.text };
447
+ const sig = acc.signature || acc.startSignature;
448
+ if (sig)
449
+ block.thinkingSignature = sig;
450
+ if (acc.redacted)
451
+ block.redacted = true;
452
+ finalContent.push(block);
453
+ }
454
+ else if (acc.type === "text") {
455
+ const text = acc === degenTextBlock && rep.cut !== undefined ? trimDegenerateTail(acc.text, rep.cut) : acc.text;
456
+ if (text) {
457
+ finalContent.push({ type: "text", text });
458
+ if (text.trim())
459
+ anyText = true;
460
+ }
461
+ }
462
+ else if (acc.type === "tool_use") {
463
+ const closed = acc.stopped === true || !endedCut;
464
+ if (!acc.toolName) {
465
+ (nameMissingCause(closed) === "truncated" ? malformed : unnamed).push(`id="${acc.toolId || "?"}"(${acc.toolJson.slice(0, 200)})`);
466
+ }
467
+ else {
468
+ const tc = closeToolUseBlock(acc, responseIds, closed);
469
+ if (tc) {
470
+ toolCalls.push(tc);
471
+ finalContent.push(tc);
472
+ }
473
+ else {
474
+ malformed.push(`${acc.toolName}(${acc.toolJson.slice(0, 200)})`);
475
+ }
476
+ }
477
+ }
478
+ }
479
+ const notes = [];
480
+ if (malformed.length > 0) {
481
+ notes.push({ cause: "truncated", count: malformed.length, text: `\n[note: ${malformed.length} tool call(s) were truncated (stop_reason="${stopReason ?? "?"}") and dropped — re-issue them next turn: ${malformed.join("; ")}]` });
482
+ }
483
+ if (unnamed.length > 0) {
484
+ notes.push({ cause: "unnamed", count: unnamed.length, text: `\n[note: ${unnamed.length} tool call(s) arrived with no tool name and were dropped — re-issue them next turn with an explicit tool name: ${unnamed.join("; ")}]` });
485
+ }
486
+ if (malformedFrames > 0) {
487
+ notes.push({ cause: "bad_frame", count: malformedFrames, text: `\n[note: ${malformedFrames} provider stream frame(s) were not valid JSON and were dropped — the streamed output may be missing content (first sample: ${JSON.stringify(malformedSample)})]` });
488
+ }
489
+ placeTurnNotes(stampOn, finalContent, notes);
490
+ return { content: finalContent, toolCalls, malformed, unnamed, anyText, reasoningSeen };
491
+ };
385
492
  const handleEvent = (evt) => {
493
+ if (streamEnded()) {
494
+ refuseAfterEnd(evt);
495
+ return;
496
+ }
386
497
  switch (evt.type) {
387
498
  case "message_start": {
388
499
  const msg = evt.message;
@@ -490,7 +601,7 @@ export function createAnthropicBrain(config = {}) {
490
601
  out.push({ type: "text_end", contentIndex: idx, content: acc.text, partial: { ...partial } });
491
602
  }
492
603
  else if (acc?.type === "tool_use") {
493
- const tc = closeToolUseBlock(acc, responseIds);
604
+ const tc = closeToolUseBlock(acc, responseIds, true);
494
605
  if (tc) {
495
606
  out.push({ type: "toolcall_end", contentIndex: idx, toolCall: tc, partial: { ...partial } });
496
607
  }
@@ -503,21 +614,12 @@ export function createAnthropicBrain(config = {}) {
503
614
  stopReason = d.stop_reason;
504
615
  if (d?.stop_details)
505
616
  stopDetails = d.stop_details;
506
- const u = evt.usage;
507
- if (u) {
508
- if (u.output_tokens !== undefined)
509
- usageRaw.output_tokens = u.output_tokens;
510
- if (u.input_tokens != null && u.input_tokens > 0)
511
- usageRaw.input_tokens = u.input_tokens;
512
- if (u.cache_read_input_tokens != null && u.cache_read_input_tokens > 0) {
513
- usageRaw.cache_read_input_tokens = u.cache_read_input_tokens;
514
- }
515
- if (u.cache_creation_input_tokens != null && u.cache_creation_input_tokens > 0) {
516
- usageRaw.cache_creation_input_tokens = u.cache_creation_input_tokens;
517
- }
518
- }
617
+ mergeDeltaUsage(evt.usage);
519
618
  break;
520
619
  }
620
+ case "message_stop":
621
+ messageStopped = true;
622
+ break;
521
623
  case "error": {
522
624
  const rawError = evt.error;
523
625
  const e = typeof rawError === "object" && rawError !== null && !Array.isArray(rawError)
@@ -525,6 +627,7 @@ export function createAnthropicBrain(config = {}) {
525
627
  : undefined;
526
628
  const inputTooLong = e?.type === "request_too_large" ||
527
629
  (e?.type === "invalid_request_error" && typeof e.message === "string" && startsWithInputTooLongAnchor(e.message));
630
+ ctrl.keepOutput({ content: assembleTurn({}).content, ...reportedUsage() });
528
631
  throw new BrainError(anthropicStreamErrorCode(e?.type), `anthropic stream error (${e?.type ?? "unknown"}): ${e?.message ?? ""}`, undefined, { apiError: true, ...(e === undefined ? {} : inputTooLong ? { inputTooLong: true } : { inputTooLongRuledOut: true }) });
529
632
  }
530
633
  default:
@@ -541,7 +644,7 @@ export function createAnthropicBrain(config = {}) {
541
644
  hasSubstantiveText,
542
645
  hasCompletedToolCall,
543
646
  hasOnlyThinking: hasThinking && !hasSubstantiveText && !hasCompletedToolCall,
544
- terminalFrameSeen: terminalFrameSeen(),
647
+ terminalFrameSeen: streamEnded(),
545
648
  };
546
649
  },
547
650
  sealForRetry() {
@@ -571,69 +674,18 @@ export function createAnthropicBrain(config = {}) {
571
674
  handleEvent(evt);
572
675
  },
573
676
  finalize(opts) {
574
- const finalContent = [];
575
- const toolCalls = [];
576
- const malformed = [];
577
- const unnamed = [];
578
- let anyText = false;
579
- let reasoningSeen = false;
580
- for (const [, acc] of [...blocks.entries()].sort((a, b) => a[0] - b[0])) {
581
- if (acc.type === "thinking") {
582
- if (acc.text.length > 0 || acc.redacted === true)
583
- reasoningSeen = true;
584
- const block = { type: "thinking", thinking: acc.text };
585
- const sig = acc.signature || acc.startSignature;
586
- if (sig)
587
- block.thinkingSignature = sig;
588
- if (acc.redacted)
589
- block.redacted = true;
590
- finalContent.push(block);
591
- }
592
- else if (acc.type === "text") {
593
- const text = acc === degenTextBlock && rep.cut !== undefined ? trimDegenerateTail(acc.text, rep.cut) : acc.text;
594
- if (text) {
595
- finalContent.push({ type: "text", text });
596
- if (text.trim())
597
- anyText = true;
598
- }
599
- }
600
- else if (acc.type === "tool_use") {
601
- if (!acc.toolName) {
602
- unnamed.push(`id="${acc.toolId || "?"}"(${acc.toolJson.slice(0, 200)})`);
603
- }
604
- else {
605
- const tc = closeToolUseBlock(acc, responseIds);
606
- if (tc) {
607
- toolCalls.push(tc);
608
- finalContent.push(tc);
609
- }
610
- else {
611
- malformed.push(`${acc.toolName}(${acc.toolJson.slice(0, 200)})`);
612
- }
613
- }
614
- }
615
- }
677
+ const { content: finalContent, toolCalls, malformed, unnamed, anyText, reasoningSeen } = assembleTurn(partial);
616
678
  const doneReason = mapStopReason(stopReason, toolCalls.length > 0);
617
679
  const noUsableContent = toolCalls.length === 0 && !anyText;
618
680
  const toolErrorParts = [];
681
+ const capFacts = { capStop: stopReason === "max_tokens", outputTokens: usageRaw.output_tokens, capTokens: sentMaxTokens };
619
682
  if (malformed.length > 0) {
620
- toolErrorParts.push(`tool call argument(s) not valid JSON (likely truncated, stop_reason="${stopReason ?? "?"}"${truncationCauseClause({ capStop: stopReason === "max_tokens", outputTokens: usageRaw.output_tokens, capTokens: sentMaxTokens, terminalFrameSeen: terminalFrameSeen() })}): ${malformed.join("; ")}`);
683
+ toolErrorParts.push(`tool call argument(s) not valid JSON (likely truncated, stop_reason="${stopReason ?? "?"}"${truncationCauseClause({ ...capFacts, terminalFrameSeen: streamEnded() })}): ${malformed.join("; ")}`);
621
684
  }
622
685
  if (unnamed.length > 0) {
623
686
  toolErrorParts.push(`tool call(s) arrived with no tool name and cannot be executed (stop_reason="${stopReason ?? "?"}"): ${unnamed.join("; ")}`);
624
687
  }
625
688
  const toolError = toolErrorParts.length > 0 ? toolErrorParts.join(" | ") : undefined;
626
- const notes = [];
627
- if (malformed.length > 0) {
628
- notes.push({ cause: "truncated", count: malformed.length, text: `\n[note: ${malformed.length} tool call(s) were truncated (stop_reason="${stopReason ?? "?"}") and dropped — re-issue them next turn: ${malformed.join("; ")}]` });
629
- }
630
- if (unnamed.length > 0) {
631
- notes.push({ cause: "unnamed", count: unnamed.length, text: `\n[note: ${unnamed.length} tool call(s) arrived with no tool name and were dropped — re-issue them next turn with an explicit tool name: ${unnamed.join("; ")}]` });
632
- }
633
- if (malformedFrames > 0) {
634
- notes.push({ cause: "bad_frame", count: malformedFrames, text: `\n[note: ${malformedFrames} provider stream frame(s) were not valid JSON and were dropped — the streamed output may be missing content (first sample: ${JSON.stringify(malformedSample)})]` });
635
- }
636
- placeTurnNotes(partial, finalContent, notes);
637
689
  const truncatedEmpty = stopReason === "max_tokens" && noUsableContent && !toolError;
638
690
  const dynamicCut = truncatedEmpty && options?.maxTokensDynamic === true;
639
691
  const staticReasoningCut = truncatedEmpty && !dynamicCut && reasoningSeen && options?.staticReasoningCutDowngrade === true;
@@ -669,7 +721,7 @@ export function createAnthropicBrain(config = {}) {
669
721
  emptyNoFinish ||
670
722
  (toolError !== undefined && noUsableContent) ||
671
723
  (truncatedEmpty && !dynamicCut && !staticReasoningCut);
672
- const tornWithContent = !errored && opts?.truncated !== true && !terminalFrameSeen() && !noUsableContent && !degenerate;
724
+ const tornWithContent = !errored && opts?.truncated !== true && !streamEnded() && !noUsableContent && !degenerate;
673
725
  const errorMessageOut = tornWithContent ? (errorMessage ? `${errorMessage}\n${STREAM_TORN_WARNING}` : STREAM_TORN_WARNING) : errorMessage;
674
726
  const errorKind = degenerate
675
727
  ? "degenerate"
@@ -678,20 +730,22 @@ export function createAnthropicBrain(config = {}) {
678
730
  : !safetyCut && toolError === undefined && truncatedEmpty && !dynamicCut && !staticReasoningCut
679
731
  ? "length_empty"
680
732
  : undefined;
733
+ const modelOutputInvalid = errored && toolError !== undefined && !degenerate && !safetyCut && !contextWindowExceeded ? modelOutputInvalidOf({ truncated: malformed.length, unnamed: unnamed.length }, capFacts) : undefined;
681
734
  const finalMessage = {
682
735
  ...partial,
683
736
  content: finalContent.length > 0 ? finalContent : [{ type: "text", text: "" }],
684
737
  stopReason: errored ? "error" : doneReason,
685
- usage: computeUsage(model, usageRaw),
686
- ...(Object.keys(usageRaw).length === 0 ? { usageMissing: true } : {}),
738
+ ...reportedUsage(),
687
739
  timestamp: Date.now(),
688
740
  ...(errorMessageOut ? { errorMessage: errorMessageOut } : {}),
689
741
  ...(errorKind ? { errorKind } : {}),
742
+ ...(modelOutputInvalid !== undefined ? { modelOutputInvalid } : {}),
690
743
  ...(tornWithContent ? { partialFinalized: true } : {}),
691
744
  ...(rep.cut !== undefined || rep.spared.length > 0
692
745
  ? { repetition: { ...(rep.cut !== undefined ? { cut: rep.cut } : {}), ...(rep.spared.length > 0 ? { spared: rep.spared } : {}) } }
693
746
  : {}),
694
747
  ...(staticReasoningCut ? { staticReasoningCut: true } : {}),
748
+ ...(afterEnd.ignored !== undefined ? { streamEndIgnored: afterEnd.ignored } : {}),
695
749
  ...(stopDetails
696
750
  ? {
697
751
  diagnostics: [
@@ -6,6 +6,7 @@
6
6
  * → a transient outage worth retrying. Only `network`/`server`/`rate_limit` are retried by the brains.
7
7
  */
8
8
  import type { Usage } from "../internal/llm.js";
9
+ import type { ProviderCondition, ProviderConditionSource } from "./provider-dialect.js";
9
10
  /** A zeroed `Usage` for synthetic error/short-circuit assistant messages (no tokens spent). Shared by
10
11
  * the circuit-breaker, degradation, and routing brains so the empty-usage shape lives in one place. */
11
12
  export declare const ZERO_USAGE: Usage;
@@ -48,7 +49,7 @@ export declare class BrainError extends Error {
48
49
  * suppresses the loop's prose fallback — a reflected "prompt is too long" inside an unrelated
49
50
  * error body must not drive a context-shrinking recovery. Mutually exclusive with
50
51
  * `inputTooLong`; BOTH absent = classification could not establish provenance ("unknown"),
51
- * and the prose fallback keeps its historic reach. */
52
+ * and the prose fallback keeps its historic reach unless {@link errorBodyIncomplete} is set. */
52
53
  readonly inputTooLongRuledOut?: true;
53
54
  /**
54
55
  * This failure was produced AT THE PROVIDER BOUNDARY — a transport attempt was made against the
@@ -64,15 +65,33 @@ export declare class BrainError extends Error {
64
65
  * conservative reading for every pre-existing and third-party construction site.
65
66
  */
66
67
  readonly apiError?: true;
67
- /** The provider's own word for a REFUSED request (a 4xx answer), read from its JSON error envelope by
68
- * {@link readProviderErrorCode} at the HTTP throw. Lifted onto `AssistantMessage.apiErrorCode` at the terminal-shell
69
- * mint. Absent when the answer was not a 4xx or the envelope stated no word in the echo shape. */
68
+ /** The provider's own word for the failure it stated, read from its JSON error envelope: a REFUSED request's
69
+ * (a 4xx answer, read by {@link readProviderErrorCode} at the HTTP throw) or an in-band error frame's (no status).
70
+ * Lifted onto `AssistantMessage.apiErrorCode` at the terminal-shell mint. Absent when neither stated a word in the
71
+ * echo shape. */
70
72
  readonly providerCode?: string;
73
+ /** What the provider said about the account or its capacity, judged off the provider dialect table
74
+ * (`provider-dialect.ts`) — on every failure the provider stated (an HTTP failure status, an in-band error
75
+ * frame). Lifted onto `AssistantMessage.providerCondition` beside {@link providerConditionSource}. */
76
+ readonly providerCondition?: ProviderCondition;
77
+ readonly providerConditionSource?: ProviderConditionSource;
78
+ /** With a `quota_exhausted` condition whose evidence stated it: when the quota lifts, wall-clock epoch ms. */
79
+ readonly providerResetAtMs?: number;
80
+ /** The failed response's body did not end (cut at the read bound, torn, unreadable), so it stated nothing: no
81
+ * verdict, word or context-limit reading came from it, and the prefix quoted in the message is no evidence
82
+ * either. Lifted onto `AssistantMessage.errorBodyIncomplete`. */
83
+ readonly errorBodyIncomplete?: true;
71
84
  constructor(code: BrainErrorCode, detail: string, status?: number, opts?: {
72
85
  inputTooLong?: boolean;
73
86
  inputTooLongRuledOut?: boolean;
74
87
  apiError?: boolean;
75
88
  providerCode?: string;
89
+ verdict?: {
90
+ condition: ProviderCondition;
91
+ source: ProviderConditionSource;
92
+ resetAtMs?: number;
93
+ };
94
+ errorBodyIncomplete?: boolean;
76
95
  });
77
96
  }
78
97
  /** The provider's diagnostic object out of a JSON error body, or undefined when the body establishes no provenance
@@ -83,14 +102,42 @@ export declare function providerErrorObject(body: string): {
83
102
  code?: unknown;
84
103
  type?: unknown;
85
104
  } | undefined;
105
+ /** The envelope's WORD — `error.code` when it is a string, else `error.type` when that is — the one reading of "what
106
+ * the provider called this failure": the echoed `apiErrorCode` and the dialect table's word rows both read it here. */
107
+ export declare function providerErrorWord(err: {
108
+ code?: unknown;
109
+ type?: unknown;
110
+ } | undefined): string | undefined;
86
111
  /**
87
112
  * The provider's own word for a refused request, from its JSON error envelope: `error.code` when it is a string (the
88
113
  * OpenAI-family code, e.g. `context_length_exceeded`), else `error.type` (the Anthropic-family word, e.g.
89
114
  * `invalid_request_error`). Read structurally, never from prose. Carried only in the provider echo shape
90
115
  * ({@link isProviderEchoShape}); a word outside it is dropped whole — absent, never truncated — and counted as one
91
- * `echo_dropped` event (`field: "apiErrorCode"`). An envelope that states neither yields nothing.
116
+ * `echo_dropped` event (`field: "apiErrorCode"`). An envelope that states neither yields nothing, and so does a body
117
+ * that did not end ({@link statedEnvelope}).
92
118
  */
93
- export declare function readProviderErrorCode(body: string): string | undefined;
119
+ export declare function readProviderErrorCode(body: FailedBody | undefined): string | undefined;
120
+ /** A failed response's body as read. */
121
+ export interface FailedBody {
122
+ /** Whatever text arrived: the terminal message quotes it, and that is all a prefix is good for. */
123
+ readonly text: string;
124
+ /**
125
+ * Whether the body ENDED on its own, rather than being cut by the byte cap, the time bound, an abort, or a torn
126
+ * stream. Parseability is NOT a substitute: a stream that emits a complete envelope and never closes leaves valid
127
+ * JSON in the buffer when the time bound fires, and an envelope followed by padding past the byte cap parses too
128
+ * (trailing whitespace is legal JSON). A body that did not end states nothing, in any seat.
129
+ */
130
+ readonly endedNormally: boolean;
131
+ }
132
+ /** What a failed response's body states — its envelope — and only when the body ended ({@link FailedBody}). Every
133
+ * reader of a failed body (the dialect verdict, the echoed word) reads it through here. */
134
+ export declare function statedEnvelope(body: FailedBody | undefined): ReturnType<typeof providerErrorObject>;
135
+ /** The envelope's word as the echo seat carries it ({@link readProviderErrorCode}, for an envelope already in hand —
136
+ * an in-band error frame's): carried in the echo shape, else dropped whole and counted once. */
137
+ export declare function carriedProviderWord(err: {
138
+ code?: unknown;
139
+ type?: unknown;
140
+ } | undefined): string | undefined;
94
141
  export { isProviderEchoShape, PROVIDER_ECHO_SHAPE } from "./provider-echo-shape.js";
95
142
  /** How the brains read one provider echo value: a non-string or the empty string states nothing (`absent` — no field,
96
143
  * nothing counted); a string in {@link isProviderEchoShape} is `carried`; any other string is `refused` (dropped and
@@ -19,6 +19,10 @@ export class BrainError extends Error {
19
19
  inputTooLongRuledOut;
20
20
  apiError;
21
21
  providerCode;
22
+ providerCondition;
23
+ providerConditionSource;
24
+ providerResetAtMs;
25
+ errorBodyIncomplete;
22
26
  constructor(code, detail, status, opts) {
23
27
  super(`[${code}] ${detail}`);
24
28
  this.name = "BrainError";
@@ -32,6 +36,14 @@ export class BrainError extends Error {
32
36
  this.apiError = true;
33
37
  if (opts?.providerCode !== undefined)
34
38
  this.providerCode = opts.providerCode;
39
+ if (opts?.verdict !== undefined) {
40
+ this.providerCondition = opts.verdict.condition;
41
+ this.providerConditionSource = opts.verdict.source;
42
+ if (opts.verdict.resetAtMs !== undefined)
43
+ this.providerResetAtMs = opts.verdict.resetAtMs;
44
+ }
45
+ if (opts?.errorBodyIncomplete === true)
46
+ this.errorBodyIncomplete = true;
35
47
  }
36
48
  }
37
49
  export function providerErrorObject(body) {
@@ -52,9 +64,17 @@ export function providerErrorObject(body) {
52
64
  return undefined;
53
65
  return err;
54
66
  }
67
+ export function providerErrorWord(err) {
68
+ return typeof err?.code === "string" ? err.code : typeof err?.type === "string" ? err.type : undefined;
69
+ }
55
70
  export function readProviderErrorCode(body) {
56
- const err = providerErrorObject(body);
57
- const word = typeof err?.code === "string" ? err.code : typeof err?.type === "string" ? err.type : undefined;
71
+ return carriedProviderWord(statedEnvelope(body));
72
+ }
73
+ export function statedEnvelope(body) {
74
+ return body !== undefined && body.endedNormally ? providerErrorObject(body.text) : undefined;
75
+ }
76
+ export function carriedProviderWord(err) {
77
+ const word = providerErrorWord(err);
58
78
  const reading = providerEchoReading(word);
59
79
  if (reading === "carried")
60
80
  return word;
@@ -1,24 +1,45 @@
1
- /** True when the (provider-authored) diagnostic OPENS with the context-limit refusal family. */
2
- export declare function startsWithInputTooLongAnchor(diagnostic: string): boolean;
3
1
  /**
4
- * Three-state classification verdict (adversarial-review r1: a binary answer conflated "the
5
- * provider said something ELSE" with "we could not read the provider", and the loop's prose
6
- * fallback then re-opened the reflected-text hole for exactly the errors this module HAD
7
- * examined):
8
- * - `"yes"` — provenance-checked input-too-long; the caller stamps the typed cause.
9
- * - `"no"` — the classification is AUTHORITATIVE-NEGATIVE: either the status can never carry
10
- * this refusal (5xx, auth, rate limit — reflected prose in those bodies must not
11
- * drive a context-shrinking recovery), or the provider's own diagnostic envelope
12
- * parsed and states a different error. The caller marks the terminal shell
13
- * ruled-out, which SUPPRESSES the loop's prose fallback for this message.
14
- * - `"unknown"` — a PTL-capable status whose body established no provenance (text/plain gateway,
15
- * truncated read): nothing is stamped either way, and the loop's historic prose
16
- * fallback keeps working for gateways that speak prose only.
2
+ * design/374 slice 2 — TYPED input-too-long classification for provider refusals.
3
+ *
4
+ * "The request INPUT alone exceeds the model's context limit" is recognizable from prose over the
5
+ * human-facing `errorMessage`, but such a classifier cannot tell a provider's own diagnostic from
6
+ * caller text a gateway reflected, and breaks the moment a provider rewords. The classification runs
7
+ * at the BRAIN boundary, where provenance is decidable, and the verdict rides
8
+ * `BrainError.inputTooLong` → `AssistantMessage.errorKind: "input_too_long"` (the same typed lane
9
+ * `degenerate`/`length_empty` already use).
10
+ *
11
+ * PROVENANCE DISCIPLINE (mirrors `context-overflow.ts`, the sibling classifier for the
12
+ * input+max_tokens overflow — a DIFFERENT error: there the input fits and lowering the output cap
13
+ * self-heals; here the input alone does not fit and only shrinking the input helps):
14
+ * - The only text source is the provider's diagnostic FIELD: `error.message` of a JSON object
15
+ * body whose `error` is itself an object (both the Anthropic `{type:"error",error:{…}}` and
16
+ * the OpenAI `{error:{…}}` envelopes reduce to this). A plain-text body, a string `error`, a
17
+ * top-level `message` — refused: each is a guess about gateway formatting that would trade a
18
+ * hypothetical classification for a field a gateway may fill with caller content.
19
+ * - Prose is matched ANCHORED at the start of that field only, against the conservative
20
+ * context-limit FAMILY (case-insensitive; the family and its member list live with the rows that
21
+ * carry them, `provider-dialect.ts`). A gateway that inlines the offending request ("validation
22
+ * failed; offending prompt: prompt is too long…") therefore cannot classify: caller text must
23
+ * never steer a retry.
24
+ * - Structural signals need no prose at all: a provider's own context-limit CODE (OpenAI-family
25
+ * `context_length_exceeded`; an endpoint's declared code such as GLM's `1261`), and HTTP 413 (the
26
+ * transport's own "request entity too large"). A code the endpoint declares for something else
27
+ * outranks every sentence: the provider named the failure, a sentence beside it cannot rename it.
28
+ *
29
+ * The verdict is a column of the provider dialect table (`provider-dialect.ts`): a context-limit
30
+ * refusal is a row whose `inputTooLong` flag is set, read by the same lookup that names the failure's
31
+ * `providerCondition`. This module is the reader face for a response no endpoint is known for.
32
+ *
33
+ * Misclassification cost: inside a PARSED provider envelope a miss is an AUTHORITATIVE negative
34
+ * that SUPPRESSES the loop's prose fallback — which is why the family must carry every observed
35
+ * genuine opening; prose-only bodies keep the fallback reach via the "unknown" arm. A FALSE HIT
36
+ * costs one bounded recovery attempt, and only on a 400/413/422 the request already failed on.
17
37
  */
18
- export type InputTooLongVerdict = "yes" | "no" | "unknown";
38
+ import { type InputTooLongVerdict } from "./provider-dialect.js";
39
+ export { startsWithInputTooLongAnchor, type InputTooLongVerdict } from "./provider-dialect.js";
19
40
  /**
20
- * Classify an HTTP refusal as input-too-long. `body` is the (bounded) error-body text as read;
21
- * a truncated read that no longer parses as JSON answers `"unknown"` (413 excepted — the status
22
- * alone is the provider's statement).
41
+ * Classify an HTTP refusal as input-too-long against the generic rows (an endpoint no dialect declares).
42
+ * `body` is the error-body text, read whole; one that does not parse as a JSON envelope answers `"unknown"`
43
+ * (413 excepted — the status alone is the provider's statement).
23
44
  */
24
45
  export declare function classifyInputTooLong(status: number, body: string): InputTooLongVerdict;
@@ -1,18 +1,5 @@
1
- import { providerErrorObject } from "./errors.js";
2
- const INPUT_TOO_LONG_ANCHORED_RE = /^(?:prompt is too long|input is too long|this model's maximum context length is |context.{0,3}length|context window (?:limit|exceeded)|reached its context window|too many tokens|maximum context|input length and `max_tokens` exceed context limit|(?:the )?request(?: \([^)]{0,40}\))? exceeds|(?:the )?input token count(?: \([^)]{0,40}\))? exceeds|requested tokens(?: \([^)]{0,40}\))? exceed|your input exceeds|(?:the )?number of tokens in the request exceeds)/i;
3
- const INPUT_TOO_LONG_STATUSES = new Set([400, 413, 422]);
4
- export function startsWithInputTooLongAnchor(diagnostic) {
5
- return INPUT_TOO_LONG_ANCHORED_RE.test(diagnostic.trimStart());
6
- }
1
+ import { judgeHttpFailure } from "./provider-dialect.js";
2
+ export { startsWithInputTooLongAnchor } from "./provider-dialect.js";
7
3
  export function classifyInputTooLong(status, body) {
8
- if (!INPUT_TOO_LONG_STATUSES.has(status))
9
- return "no";
10
- if (status === 413)
11
- return "yes";
12
- const err = providerErrorObject(body);
13
- if (err === undefined)
14
- return "unknown";
15
- if (err.code === "context_length_exceeded")
16
- return "yes";
17
- return typeof err.message === "string" && startsWithInputTooLongAnchor(err.message) ? "yes" : "no";
4
+ return judgeHttpFailure({ dialect: undefined, status, body: { text: body, endedNormally: true } }).inputTooLong;
18
5
  }