mixdog 1.2.1 → 1.2.3

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 (557) hide show
  1. package/README.md +18 -0
  2. package/package.json +2 -1
  3. package/scripts/gate-local.mjs +19 -3
  4. package/scripts/model-catalog-audit.mjs +1 -15
  5. package/scripts/provider-pingpong-live.mjs +509 -0
  6. package/src/agents/advisor/AGENT.md +1 -1
  7. package/src/agents/advisor/agent.json +1 -1
  8. package/src/agents/reviewer/AGENT.md +3 -3
  9. package/src/agents/reviewer/agent.json +1 -1
  10. package/src/defaults/shipped-history.json +6 -0
  11. package/src/defaults/skills/setup/SKILL.md +6 -1
  12. package/src/defaults/skills/setup/references/actions.md +44 -22
  13. package/src/defaults/skills/setup/references/surfaces.md +10 -8
  14. package/src/headless-exec.mjs +15 -8
  15. package/src/lib/keychain-cjs.cjs +7 -4
  16. package/src/output-styles/common.md +11 -10
  17. package/src/repl/slash-commands.mjs +16 -1
  18. package/src/rules/agent/AGENT.md +5 -5
  19. package/src/rules/lead/LEAD.md +5 -5
  20. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -4
  21. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +10 -0
  22. package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
  23. package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
  24. package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
  25. package/src/runtime/agent/orchestrator/config.mjs +5 -0
  26. package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
  27. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
  28. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
  29. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +36 -7
  30. package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +49 -10
  31. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +40 -3
  32. package/src/runtime/agent/orchestrator/mcp/client.mjs +230 -96
  33. package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +103 -0
  34. package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +150 -0
  35. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +111 -0
  36. package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +87 -0
  37. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +95 -0
  38. package/src/runtime/agent/orchestrator/mcp/oauth-request.mjs +122 -0
  39. package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +9 -0
  40. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +229 -0
  41. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +188 -29
  42. package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +2 -1
  43. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
  44. package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +94 -31
  45. package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +98 -0
  46. package/src/runtime/agent/orchestrator/providers/anthropic-fast-mode.mjs +39 -18
  47. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +55 -0
  48. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +48 -37
  49. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +10 -7
  50. package/src/runtime/agent/orchestrator/providers/anthropic-midstream-recovery.mjs +18 -4
  51. package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +13 -1
  52. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  53. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-midstream.mjs +10 -1
  54. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-recovery.mjs +23 -9
  55. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +46 -20
  56. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request.mjs +14 -9
  57. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +102 -45
  58. package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +69 -0
  59. package/src/runtime/agent/orchestrator/providers/anthropic-server-fallback.mjs +4 -0
  60. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
  61. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
  62. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
  63. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
  64. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
  65. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
  66. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
  67. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +10 -1
  68. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
  69. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +40 -7
  70. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +30 -9
  71. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +7 -0
  72. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +88 -21
  73. package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +30 -10
  74. package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +106 -0
  75. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +10 -61
  76. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +94 -15
  77. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  78. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +117 -72
  79. package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
  80. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +75 -10
  81. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  82. package/src/runtime/agent/orchestrator/providers/cursor-wire-guards.mjs +97 -2
  83. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +103 -23
  84. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +43 -2
  85. package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +103 -33
  86. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +32 -6
  87. package/src/runtime/agent/orchestrator/providers/cursor.mjs +27 -3
  88. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +64 -1
  89. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +70 -6
  90. package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
  91. package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
  92. package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
  93. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +80 -18
  94. package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
  95. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +46 -8
  96. package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +273 -0
  97. package/src/runtime/agent/orchestrator/providers/gemini-family.mjs +9 -0
  98. package/src/runtime/agent/orchestrator/providers/gemini-history-signatures.mjs +9 -4
  99. package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
  100. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +3 -1
  101. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +180 -0
  102. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +369 -112
  103. package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +3 -1
  104. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +140 -35
  105. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +70 -24
  106. package/src/runtime/agent/orchestrator/providers/gemini.mjs +80 -29
  107. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  108. package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
  109. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +69 -19
  110. package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
  111. package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
  112. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +246 -42
  113. package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
  114. package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
  115. package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +388 -0
  116. package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
  117. package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
  118. package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
  119. package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
  120. package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +48 -22
  121. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +119 -18
  122. package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
  123. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +3 -0
  124. package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +2 -1
  125. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
  126. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
  127. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +33 -1
  128. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +4 -9
  129. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -0
  130. package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
  131. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +123 -61
  132. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
  133. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +27 -2
  134. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +37 -7
  135. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
  136. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +1 -0
  137. package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +50 -0
  138. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +47 -2
  139. package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
  140. package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
  141. package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +151 -0
  142. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +64 -23
  143. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +79 -33
  144. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
  145. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +172 -0
  146. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +3 -2
  147. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +144 -15
  148. package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +193 -0
  149. package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +66 -2
  150. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +9 -2
  151. package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
  152. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +109 -26
  153. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +27 -6
  154. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +34 -20
  155. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +23 -4
  156. package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +37 -28
  157. package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +274 -0
  158. package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +72 -32
  159. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
  160. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +43 -15
  161. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
  162. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
  163. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +5 -2
  164. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-stamps.mjs +2 -2
  165. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +7 -3
  166. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
  167. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +2 -2
  168. package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +1 -3
  169. package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
  170. package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +37 -4
  171. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +12 -1
  172. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +22 -2
  173. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +12 -1
  174. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +76 -33
  175. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
  176. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +44 -16
  177. package/src/runtime/agent/orchestrator/providers/openai-retry-policy.mjs +9 -0
  178. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -16
  179. package/src/runtime/agent/orchestrator/providers/openai-ws-handshake.mjs +16 -8
  180. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
  181. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -35
  182. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
  183. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +1 -2
  184. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/policy.mjs +25 -14
  185. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
  186. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
  187. package/src/runtime/agent/orchestrator/providers/openai-ws-terminal.mjs +18 -11
  188. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +41 -22
  189. package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +170 -0
  190. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +75 -70
  191. package/src/runtime/agent/orchestrator/providers/openrouter.mjs +75 -0
  192. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +720 -0
  193. package/src/runtime/agent/orchestrator/providers/registry.mjs +4 -1
  194. package/src/runtime/agent/orchestrator/providers/retry-backoff.mjs +46 -7
  195. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +123 -219
  196. package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +2 -0
  197. package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +148 -45
  198. package/src/runtime/agent/orchestrator/providers/retry-midstream.mjs +81 -16
  199. package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
  200. package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
  201. package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +157 -0
  202. package/src/runtime/agent/orchestrator/providers/wire-route.mjs +512 -0
  203. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
  204. package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +183 -0
  205. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +100 -0
  206. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +3 -0
  207. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +21 -0
  208. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
  209. package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +0 -18
  210. package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +57 -28
  211. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +19 -16
  212. package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +1 -97
  213. package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
  214. package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
  215. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +14 -3
  216. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
  217. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  218. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
  219. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +176 -71
  220. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +62 -10
  221. package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
  222. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +5 -1
  223. package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
  224. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +14 -93
  225. package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
  226. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +120 -0
  227. package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
  228. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
  229. package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +2 -1
  230. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
  231. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +91 -1
  232. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
  233. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
  234. package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
  235. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -0
  236. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +21 -10
  237. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +132 -0
  238. package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +30 -0
  239. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +67 -20
  240. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +104 -19
  241. package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
  242. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
  243. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -4
  244. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
  245. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +150 -0
  246. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +7 -2
  247. package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +30 -2
  248. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +11 -2
  249. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +2 -1
  250. package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
  251. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +57 -21
  252. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
  253. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
  254. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
  255. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
  256. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +5 -10
  257. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +208 -14
  258. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +16 -4
  259. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +25 -3
  260. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
  261. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +19 -2
  262. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -0
  263. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
  264. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +18 -7
  265. package/src/runtime/agent/orchestrator/session/manager.mjs +2 -1
  266. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
  267. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +168 -29
  268. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
  269. package/src/runtime/agent/orchestrator/session/side-question.mjs +192 -0
  270. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +17 -3
  271. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
  272. package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +58 -2
  273. package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +6 -3
  274. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +41 -28
  275. package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
  276. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +12 -1
  277. package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +3 -1
  278. package/src/runtime/agent/orchestrator/session/store/write-guards.mjs +16 -0
  279. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +22 -10
  280. package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
  281. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +6 -0
  282. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +13 -0
  283. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +13 -1
  284. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +10 -2
  285. package/src/runtime/agent/orchestrator/session/store.mjs +19 -3
  286. package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +1 -0
  287. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +1 -1
  288. package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
  289. package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
  290. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
  291. package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +77 -0
  292. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +20 -1
  293. package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
  294. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +2 -2
  295. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
  296. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +12 -15
  297. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
  298. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +5 -5
  299. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +14 -10
  300. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +49 -34
  301. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
  302. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
  303. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
  304. package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
  305. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
  306. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
  307. package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
  308. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
  309. package/src/runtime/computer-bridge/action-schema.mjs +44 -21
  310. package/src/runtime/github/tool.mjs +92 -2
  311. package/src/runtime/memory/index.mjs +1 -0
  312. package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
  313. package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
  314. package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
  315. package/src/runtime/memory/lib/pg/process.mjs +65 -50
  316. package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
  317. package/src/runtime/memory/lib/pg/supervisor.mjs +124 -16
  318. package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
  319. package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
  320. package/src/runtime/office/README.md +2 -2
  321. package/src/runtime/office/authoring/html-document-author.mjs +2 -0
  322. package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
  323. package/src/runtime/office/authoring/pptx-html-measure.mjs +2 -0
  324. package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
  325. package/src/runtime/office/authoring/xlsx-html-runner.mjs +2 -0
  326. package/src/runtime/office/core/office-actions-read.mjs +3 -0
  327. package/src/runtime/office/core/office-render-preview.mjs +2 -0
  328. package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
  329. package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
  330. package/src/runtime/office/core/office-sessions.mjs +5 -0
  331. package/src/runtime/office/core/office-transactions.mjs +3 -0
  332. package/src/runtime/office/core/office-write-ledger.mjs +98 -0
  333. package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
  334. package/src/runtime/office/index.mjs +30 -0
  335. package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
  336. package/src/runtime/office/pdf/pdf-render.mjs +23 -7
  337. package/src/runtime/office/pdf/pdf-security.mjs +2 -0
  338. package/src/runtime/office/portable/portable-opc.mjs +4 -1
  339. package/src/runtime/office/quality/visual-diff.mjs +2 -0
  340. package/src/runtime/office/shared/values.mjs +0 -5
  341. package/src/runtime/shared/background-tasks.mjs +92 -14
  342. package/src/runtime/shared/bounded-file-read.mjs +13 -0
  343. package/src/runtime/shared/bounded-line-diff.mjs +182 -0
  344. package/src/runtime/shared/buffered-appender.mjs +18 -0
  345. package/src/runtime/shared/config.mjs +78 -18
  346. package/src/runtime/shared/err-text.mjs +31 -0
  347. package/src/runtime/shared/error-presentation.mjs +159 -19
  348. package/src/runtime/shared/file-permissions.d.mts +6 -1
  349. package/src/runtime/shared/file-permissions.mjs +54 -6
  350. package/src/runtime/shared/llm/anthropic-betas.mjs +4 -3
  351. package/src/runtime/shared/llm/anthropic-effort.mjs +129 -134
  352. package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +50 -14
  353. package/src/runtime/shared/llm/model-catalog.mjs +53 -40
  354. package/src/runtime/shared/llm/openai-daybreak.mjs +4 -16
  355. package/src/runtime/shared/llm/provider-catalog-registry.mjs +11 -0
  356. package/src/runtime/shared/llm/provider-model-identities.mjs +13 -4
  357. package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
  358. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
  359. package/src/runtime/shared/llm/usage-rollup.mjs +0 -1
  360. package/src/runtime/shared/loopback-listener.mjs +9 -0
  361. package/src/runtime/shared/model-display.mjs +13 -0
  362. package/src/runtime/shared/provider-api-key.mjs +2 -0
  363. package/src/runtime/shared/quota-resume-store.mjs +11 -0
  364. package/src/runtime/shared/review-diff.mjs +52 -0
  365. package/src/runtime/shared/session-baseline-store.mjs +960 -0
  366. package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
  367. package/src/runtime/shared/session-sidebar-host.mjs +38 -0
  368. package/src/runtime/shared/slow-span.mjs +114 -0
  369. package/src/runtime/shared/statusline/statusline-format.mjs +4 -4
  370. package/src/runtime/shared/statusline/statusline-segments.mjs +28 -4
  371. package/src/runtime/shared/task-notification-envelope.mjs +2 -2
  372. package/src/runtime/shared/tool-card-model/card-header.mjs +6 -1
  373. package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
  374. package/src/runtime/shared/tool-card-model.mjs +5 -2
  375. package/src/runtime/shared/tool-output-limit.mjs +4 -0
  376. package/src/runtime/shared/tool-primitives.mjs +13 -0
  377. package/src/runtime/shared/tool-result-summary.mjs +8 -1
  378. package/src/runtime/shared/tool-surface.mjs +18 -3
  379. package/src/runtime/shared/tool-work-units.mjs +40 -4
  380. package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
  381. package/src/runtime/shared/transcript-writer.mjs +10 -2
  382. package/src/runtime/shared/turn-changes.mjs +670 -274
  383. package/src/runtime/shared/turn-review-reply.mjs +8 -39
  384. package/src/runtime/shared/turn-snapshot-store.mjs +94 -2
  385. package/src/runtime/shared/turn-snapshot.mjs +986 -690
  386. package/src/runtime/shared/turn-worktree-snapshot.mjs +279 -262
  387. package/src/runtime/shared/user-data-guard.mjs +262 -49
  388. package/src/runtime/shared/worktrees/carry.mjs +531 -0
  389. package/src/runtime/shared/worktrees/contract.mjs +34 -24
  390. package/src/runtime/shared/worktrees/file-recovery.mjs +68 -0
  391. package/src/runtime/shared/worktrees/git-head.mjs +205 -0
  392. package/src/runtime/shared/worktrees/git.mjs +8 -3
  393. package/src/runtime/shared/worktrees/maintenance.mjs +1 -1
  394. package/src/runtime/shared/worktrees/manager.mjs +156 -8
  395. package/src/runtime/shared/worktrees/merge.mjs +31 -21
  396. package/src/runtime/shared/worktrees/paths.d.mts +6 -0
  397. package/src/runtime/shared/worktrees/test-support.mjs +19 -4
  398. package/src/runtime/terminal-bridge/client.mjs +44 -11
  399. package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
  400. package/src/runtime/tidy/apply.mjs +47 -2
  401. package/src/runtime/tidy/run-engines.mjs +11 -5
  402. package/src/session-runtime/agent-tool-routing.mjs +19 -13
  403. package/src/session-runtime/boot/apis.mjs +19 -5
  404. package/src/session-runtime/boot/facade.mjs +1 -0
  405. package/src/session-runtime/boot/infrastructure.mjs +12 -1
  406. package/src/session-runtime/boot/session.mjs +0 -1
  407. package/src/session-runtime/boot/tools.mjs +4 -1
  408. package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
  409. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +65 -0
  410. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
  411. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +11 -4
  412. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +115 -18
  413. package/src/session-runtime/internal-tool-executor.mjs +6 -2
  414. package/src/session-runtime/lifecycle/cold-heir.mjs +188 -0
  415. package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
  416. package/src/session-runtime/lifecycle/session-catalog.mjs +14 -3
  417. package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
  418. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +29 -6
  419. package/src/session-runtime/lifecycle/teardown.mjs +73 -8
  420. package/src/session-runtime/lifecycle-api.mjs +1 -0
  421. package/src/session-runtime/mcp-glue/connect.mjs +46 -14
  422. package/src/session-runtime/mcp-glue/server-catalog.mjs +20 -3
  423. package/src/session-runtime/mcp-glue.mjs +3 -0
  424. package/src/session-runtime/mcp-oauth-login.mjs +174 -0
  425. package/src/session-runtime/model-route/model-switch-target.mjs +34 -0
  426. package/src/session-runtime/model-route/set-route.mjs +85 -17
  427. package/src/session-runtime/model-route/web-search-route.mjs +1 -1
  428. package/src/session-runtime/native-web-search/routes.mjs +22 -3
  429. package/src/session-runtime/native-web-search-usage.mjs +51 -0
  430. package/src/session-runtime/native-web-search.mjs +10 -1
  431. package/src/session-runtime/new-session-config.mjs +4 -2
  432. package/src/session-runtime/provider-auth/login.mjs +4 -0
  433. package/src/session-runtime/provider-models/model-meta.mjs +12 -3
  434. package/src/session-runtime/quick-model-rows/web-search-rows.mjs +13 -8
  435. package/src/session-runtime/quick-web-search-models.mjs +13 -38
  436. package/src/session-runtime/resource-extension-sync.mjs +4 -0
  437. package/src/session-runtime/resource-mcp-api.mjs +98 -2
  438. package/src/session-runtime/resource-scope-decorate.mjs +10 -3
  439. package/src/session-runtime/runtime-review-api.mjs +21 -2
  440. package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
  441. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +13 -1
  442. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +7 -2
  443. package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
  444. package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
  445. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +73 -7
  446. package/src/session-runtime/services/agent-tool/send-flow.mjs +22 -4
  447. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +2 -0
  448. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +22 -5
  449. package/src/session-runtime/services/agent-tool/tag-registry.mjs +15 -1
  450. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +8 -1
  451. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -2
  452. package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
  453. package/src/session-runtime/services/agent-tool/worker-index.mjs +46 -7
  454. package/src/session-runtime/services/agent-tool/worker-rows.mjs +17 -0
  455. package/src/session-runtime/services/agent-tool.mjs +3 -0
  456. package/src/session-runtime/services/channel-admin.mjs +19 -3
  457. package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
  458. package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
  459. package/src/session-runtime/services/provider-admin.mjs +81 -15
  460. package/src/session-runtime/session-transcript-purge.mjs +32 -0
  461. package/src/session-runtime/session-turn-api.mjs +14 -5
  462. package/src/session-runtime/settings-builtin-tools-api.mjs +9 -0
  463. package/src/session-runtime/settings-compaction-api.mjs +1 -0
  464. package/src/session-runtime/setup-tool/executor.mjs +36 -6
  465. package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
  466. package/src/session-runtime/setup-tool/settings-contract.mjs +13 -3
  467. package/src/session-runtime/setup-tool/tool-defs.mjs +13 -4
  468. package/src/session-runtime/skills-api.mjs +3 -5
  469. package/src/session-runtime/tool-surface.mjs +5 -1
  470. package/src/session-runtime/turn/compaction-gate.mjs +25 -0
  471. package/src/session-runtime/turn/session-ops.mjs +7 -5
  472. package/src/session-runtime/turn/side-question-ops.mjs +22 -0
  473. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +5 -1
  474. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +8 -3
  475. package/src/session-runtime/turn/turn-run/turn-settle.mjs +10 -0
  476. package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
  477. package/src/session-runtime/turn/turn-run.mjs +25 -9
  478. package/src/session-runtime/usage-stats-api.mjs +43 -11
  479. package/src/session-runtime/workspace/project-branches.mjs +7 -5
  480. package/src/session-runtime/workspace/transition-steps.mjs +129 -31
  481. package/src/session-runtime/workspace/transitions.mjs +190 -15
  482. package/src/standalone/daemon-agent-control.mjs +9 -1
  483. package/src/standalone/daemon-drain-policy.mjs +8 -0
  484. package/src/standalone/daemon-local-session-bridge.mjs +14 -1
  485. package/src/standalone/daemon-owner.mjs +17 -4
  486. package/src/standalone/daemon-pg-stop.mjs +51 -0
  487. package/src/standalone/daemon-stop-budget.d.mts +2 -0
  488. package/src/standalone/daemon-stop-budget.mjs +18 -0
  489. package/src/standalone/daemon-stored-session-views.mjs +2 -0
  490. package/src/standalone/daemon-telemetry.mjs +74 -0
  491. package/src/standalone/daemon.mjs +64 -8
  492. package/src/standalone/desktop-service-registry.mjs +5 -0
  493. package/src/standalone/local-session-runtime.mjs +70 -19
  494. package/src/standalone/session-client.mjs +42 -0
  495. package/src/standalone/session-protocol.mjs +14 -0
  496. package/src/standalone/session-proxy/projection.mjs +41 -4
  497. package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
  498. package/src/standalone/session-runtime-inline-host.mjs +1 -0
  499. package/src/standalone/session-service/agent-tree/agent-cancel.mjs +33 -2
  500. package/src/standalone/session-service/agent-tree/agent-turns.mjs +26 -10
  501. package/src/standalone/session-service/agent-tree.mjs +12 -0
  502. package/src/standalone/session-service/quota-resume.mjs +8 -0
  503. package/src/standalone/session-service/retention/busy.mjs +15 -1
  504. package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
  505. package/src/standalone/session-service-api.mjs +11 -1
  506. package/src/standalone/session-service.mjs +1 -0
  507. package/src/standalone/session-state-patch.d.mts +2 -1
  508. package/src/standalone/session-state-patch.mjs +41 -1
  509. package/src/tui/App.jsx +25 -0
  510. package/src/tui/app/app-view/floating-panel.jsx +26 -1
  511. package/src/tui/app/app-view.jsx +1 -0
  512. package/src/tui/app/btw-controller.mjs +118 -0
  513. package/src/tui/app/create-app-pickers.mjs +6 -0
  514. package/src/tui/app/extension-pickers/mcp-login.mjs +107 -0
  515. package/src/tui/app/extension-pickers/mcp-servers-picker.mjs +2 -1
  516. package/src/tui/app/extension-pickers.mjs +2 -1
  517. package/src/tui/app/model-options.mjs +11 -16
  518. package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
  519. package/src/tui/app/shell-layout/surfaces.mjs +3 -1
  520. package/src/tui/app/slash-commands.mjs +20 -5
  521. package/src/tui/app/slash-dispatch/panel-commands.mjs +16 -1
  522. package/src/tui/app/slash-dispatch/session-commands.mjs +19 -6
  523. package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
  524. package/src/tui/app/use-global-key-input.mjs +5 -12
  525. package/src/tui/app/use-prompt-handlers.mjs +11 -0
  526. package/src/tui/components/BtwPanel.jsx +53 -0
  527. package/src/tui/components/QuestionPanel.jsx +275 -0
  528. package/src/tui/components/StatusLine.jsx +2 -0
  529. package/src/tui/components/question-panel-model.mjs +156 -0
  530. package/src/tui/components/status-line/local-line.mjs +5 -2
  531. package/src/tui/components/status-line/use-statusline-text.mjs +7 -1
  532. package/src/tui/dist/index.mjs +3221 -1500
  533. package/src/tui/session/context-state.mjs +4 -2
  534. package/src/tui/session/quota-resume.mjs +46 -14
  535. package/src/tui/session/session-api/commands.mjs +43 -24
  536. package/src/tui/session/session-api/controls.mjs +2 -2
  537. package/src/tui/session/session-api/extensions.mjs +22 -0
  538. package/src/tui/session/session-api/integrations.mjs +16 -2
  539. package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
  540. package/src/tui/session/session-api/lifecycle.mjs +7 -2
  541. package/src/tui/session/session-api/routes.mjs +71 -7
  542. package/src/tui/session/session-api/settings.mjs +11 -14
  543. package/src/tui/session/session-api.mjs +1 -0
  544. package/src/tui/session/session-flow/drain.mjs +7 -1
  545. package/src/tui/session/session-flow/failed-turn-rewind.mjs +10 -4
  546. package/src/tui/session/tool-approval.mjs +10 -7
  547. package/src/tui/session/transcript-spill.mjs +14 -7
  548. package/src/tui/session/turn-stream.mjs +174 -31
  549. package/src/tui/session/turn.mjs +46 -16
  550. package/src/tui/statusline-ansi-bridge.mjs +1 -1
  551. package/src/ui/statusline-agents.mjs +15 -4
  552. package/src/ui/statusline.mjs +7 -3
  553. package/src/ui/streaming-markdown-heal.mjs +34 -3
  554. package/src/vendor/statusline/src/gateway/claude-current.mjs +14 -4
  555. package/src/workflows/default/WORKFLOW.md +3 -1
  556. package/src/runtime/memory/lib/memory-session-merge.mjs +0 -32
  557. package/src/runtime/shared/llm/usage-session-history.mjs +0 -266
@@ -42,8 +42,12 @@ import { AnthropicFallbackTriggeredError } from './retry-classifier.mjs';
42
42
  import { ANTHROPIC_MAX_MIDSTREAM_RETRIES, parseSSEStream, _classifyMidstreamError } from './anthropic-sse.mjs';
43
43
  import { buildAnthropicBetaHeaders, supportsAnthropicFastMode } from './anthropic-betas.mjs';
44
44
  import { applyAnthropicServerFallback } from './anthropic-server-fallback.mjs';
45
- import { fastModeAvailable } from './anthropic-fast-mode.mjs';
45
+ import { fastModeAvailable, fastModeDowngraded, noteFastModeCapacityError } from './anthropic-fast-mode.mjs';
46
46
  import { ANTHROPIC_VERSION, anthropicQuotaError, createAnthropicOAuthRequest } from './anthropic-oauth-request.mjs';
47
+ import { isRefreshableAuthRejection } from './anthropic-oauth-request/initial-status.mjs';
48
+ import { applyAnthropicErrorContract } from './anthropic-error-contract.mjs';
49
+ import { adjustMaxTokensForContextOverflow } from './anthropic-max-tokens-recovery.mjs';
50
+ import { announceAnthropicModelFallback, createAnthropicOverloadTracker } from './anthropic-overload-fallback.mjs';
47
51
  import { createAnthropicOAuthRecovery } from './anthropic-oauth-recovery.mjs';
48
52
  import { createMidState, createMidstreamRecovery } from './anthropic-oauth-midstream.mjs';
49
53
  import { assertAnthropicStreamNotEmpty } from './anthropic-midstream-recovery.mjs';
@@ -51,6 +55,7 @@ import { applyAnthropicEffortToBody, shouldIncludeEffortBeta } from './anthropic
51
55
  import { ANTHROPIC_EFFORT_LEVELS, withEffortRejectionFallback } from './effort-rejection.mjs';
52
56
  import { getLlmDispatcher, preconnect } from '../../../shared/llm/http-agent.mjs';
53
57
  import {
58
+ anthropicThinkingActive,
54
59
  applyAnthropicCacheMarkers,
55
60
  clampAnthropicThinkingBudget as clampThinkingBudgetTokens,
56
61
  deferredAnthropicTools as sharedDeferredAnthropicTools,
@@ -58,6 +63,7 @@ import {
58
63
  resolveAnthropicCacheTtls as resolveCacheTtls,
59
64
  resolveAnthropicMessageCacheSlots,
60
65
  sanitizeAnthropicInputSchema,
66
+ sharedCachePrefixBoundary,
61
67
  toAnthropicMessages,
62
68
  toAnthropicToolChoice,
63
69
  } from './lib/anthropic-request-utils.mjs';
@@ -91,12 +97,6 @@ function logQuiet(line) {
91
97
  if (!process.env.MIXDOG_QUIET_PROVIDER_LOG) process.stderr.write(`[anthropic-oauth] ${line}\n`);
92
98
  }
93
99
 
94
- function requiresSystemPrefix(model) {
95
- // Every Claude OAuth model needs the first-party system prefix for OAuth
96
- // pool routing; without it the server answers 429 rate_limit_error "Error".
97
- return /^claude-/.test(String(model || '').toLowerCase());
98
- }
99
-
100
100
  function buildOAuthBetaHeaders(body, { fastMode = false, toolSearch = false, model, opts = {} } = {}) {
101
101
  return buildAnthropicBetaHeaders({
102
102
  base: usesAnthropicEffortBody(body) ? `${OAUTH_BETA_HEADERS},${EFFORT_CONFIGURATION_BETA}` : OAUTH_BETA_HEADERS,
@@ -114,23 +114,21 @@ function buildOAuthBetaHeaders(body, { fastMode = false, toolSearch = false, mod
114
114
  // content (even the prefix concatenated with extra text in the same block)
115
115
  // falls into the standard pool and Opus/Sonnet return 429. Splitting into
116
116
  // two blocks — [prefix, rest] — keeps both routing and user instructions.
117
- function buildSystemBlocks(systemMsgs, model, systemTtl, tier3Ttl) {
117
+ function buildSystemBlocks(systemMsgs, systemTtl, tier3Ttl) {
118
118
  // systemMsgs is an array of { content, cacheTier } — each non-empty element
119
119
  // becomes its own Anthropic content block with its own cache_control
120
120
  // breakpoint. Blocks tagged cacheTier:'tier3' (BP3 sessionMarker) take the
121
121
  // tier3 TTL; every other block (BP1 baseRules / BP2 stableSystem) takes the
122
122
  // system TTL. Invariant: callers must pass an array.
123
123
  const items = systemBlockItems(systemMsgs);
124
- const gated = requiresSystemPrefix(model);
125
124
 
126
- const blocks = [];
127
- if (gated) {
128
- blocks.push({ type: 'text', text: CLAUDE_CODE_SYSTEM_PREFIX });
129
- }
125
+ // Every model on the OAuth route is routed by this prefix block, so it is
126
+ // sent unconditionally rather than keyed on the model id.
127
+ const blocks = [{ type: 'text', text: CLAUDE_CODE_SYSTEM_PREFIX }];
130
128
  for (let i = 0; i < items.length; i++) {
131
129
  let body = items[i].text;
132
130
  // Strip a duplicated OAuth system prefix from the first block if present.
133
- if (gated && i === 0 && body.startsWith(CLAUDE_CODE_SYSTEM_PREFIX)) {
131
+ if (i === 0 && body.startsWith(CLAUDE_CODE_SYSTEM_PREFIX)) {
134
132
  body = body.slice(CLAUDE_CODE_SYSTEM_PREFIX.length).trim();
135
133
  if (!body) continue;
136
134
  }
@@ -170,10 +168,10 @@ function buildSystemBlocks(systemMsgs, model, systemTtl, tier3Ttl) {
170
168
  // 1. MIXDOG_ANTHROPIC_MAX_OUTPUT_TOKENS env override, if set, wins outright.
171
169
  // 2. Catalog outputTokens (trusted over hardcoded heuristics when present),
172
170
  // clamped to [MAX_TOKENS_FLOOR, safetyCap].
173
- // 3. Static MAX_TOKENS table / family heuristic fallback when the catalog
174
- // has no entry for this model, also clamped to the safety cap.
175
- function resolveMaxTokens(model) {
176
- return resolveAnthropicMaxTokens(model, { catalogLookup: _catalogOutputTokens });
171
+ // 3. Shared model catalog outputTokens, then the floor, when the live
172
+ // roster has no entry for this model.
173
+ function resolveMaxTokens(model, { modelMaxOutputTokens = null } = {}) {
174
+ return resolveAnthropicMaxTokens(model, { catalogLookup: _catalogOutputTokens, modelMaxOutputTokens });
177
175
  }
178
176
 
179
177
  // --- Message conversion ---
@@ -195,29 +193,38 @@ function requestAnthropicTools(tools, messages, opts) {
195
193
  function buildRequestBody(messages, model, tools, sendOpts) {
196
194
  const systemMsgs = messages.filter((m) => m.role === 'system');
197
195
  const chatMsgs = messages.filter((m) => m.role !== 'system');
198
- const maxTokens = resolveMaxTokens(model);
199
196
  const opts = sendOpts || {};
197
+ const maxTokens = resolveMaxTokens(model, { modelMaxOutputTokens: opts.modelMaxOutputTokens });
200
198
  const effortProjection = projectEffortConfiguration(messages, 'anthropic-oauth', model, opts);
201
199
  const ttls = resolveCacheTtls(opts);
202
200
  // Each system message becomes its own Anthropic content block with its own
203
201
  // breakpoint: BP1 baseRules + BP2 stableSystem at ttls.system, BP3
204
202
  // sessionMarker (cacheTier:'tier3') at ttls.tier3.
205
- const systemBlocks = buildSystemBlocks(systemMsgs, model, ttls?.system, ttls?.tier3);
203
+ const systemBlocks = buildSystemBlocks(systemMsgs, ttls?.system, ttls?.tier3);
206
204
 
207
205
  // Message-tail cache budget (4-BP layout + ANTHROPIC_MSG_SLOTS) is shared
208
206
  // with anthropic.mjs — see resolveAnthropicMessageCacheSlots.
209
- const messageCacheSlots = resolveAnthropicMessageCacheSlots(systemBlocks, ttls);
210
207
  // Tools are resolved BEFORE the messages: the lowering needs the final
211
208
  // tool list to drop tool_reference blocks whose tool no longer ships in
212
209
  // this request (otherwise the API rejects the whole turn).
213
210
  const requestTools = requestAnthropicTools(tools, chatMsgs, opts);
211
+ const messageCacheSlots = resolveAnthropicMessageCacheSlots(systemBlocks, ttls, { tools: requestTools });
214
212
  // Build → sanitize (once, inside toAnthropicMessages) → mark. Markers are
215
213
  // applied to the FINAL sanitized array by invariant, so block drops /
216
214
  // inserts / reorders performed by the sanitizer can never move or delete a
217
215
  // marked block. NEVER sanitize again after this (see send path).
216
+ const lowerHistory = (history, projection) =>
217
+ lowerAnthropicEffortHistory(
218
+ history.filter((m) => m.role !== 'system'),
219
+ (segment) => toAnthropicMessages(segment, requestTools),
220
+ projection
221
+ );
218
222
  const anthropicMessages = applyAnthropicCacheMarkers(
219
- lowerAnthropicEffortHistory(chatMsgs, (segment) => toAnthropicMessages(segment, requestTools), effortProjection),
220
- messageCacheSlots
223
+ lowerHistory(chatMsgs, effortProjection),
224
+ messageCacheSlots,
225
+ sharedCachePrefixBoundary(messages, opts, (prefix) =>
226
+ lowerHistory(prefix, projectEffortConfiguration(prefix, 'anthropic-oauth', model, opts))
227
+ )
221
228
  );
222
229
 
223
230
  const body = {
@@ -242,10 +249,8 @@ function buildRequestBody(messages, model, tools, sendOpts) {
242
249
  // tool_choice only when tools are actually present (Anthropic rejects
243
250
  // tool_choice without tools). 'none' rides the hard-cap final turn to
244
251
  // forbid tool USE while keeping the tools prefix stable for cache reuse.
245
- if (body.tools) {
246
- const toolChoice = toAnthropicToolChoice(opts.toolChoice);
247
- if (toolChoice) body.tool_choice = toolChoice;
248
- }
252
+ // Key reserved for wire order; resolved after thinking is applied.
253
+ if (body.tools) body.tool_choice = undefined;
249
254
 
250
255
  applyAnthropicEffortToBody(body, {
251
256
  model,
@@ -256,6 +261,16 @@ function buildRequestBody(messages, model, tools, sendOpts) {
256
261
  progressUpdates: true,
257
262
  });
258
263
 
264
+ if (body.tools) {
265
+ const toolChoice = toAnthropicToolChoice(opts.toolChoice, {
266
+ thinking: anthropicThinkingActive(body),
267
+ disableParallelToolUse: opts.disableParallelToolUse === true,
268
+ onThinkingConflict: opts.toolChoiceThinkingConflict,
269
+ });
270
+ if (toolChoice) body.tool_choice = toolChoice;
271
+ else delete body.tool_choice;
272
+ }
273
+
259
274
  // Skipped while the fast capacity pool is in cooldown (or permanently
260
275
  // unavailable) so a drained pool is not re-probed every turn.
261
276
  if (opts.fast === true && supportsAnthropicFastMode(model) && fastModeAvailable()) {
@@ -480,6 +495,12 @@ export class AnthropicOAuthProvider {
480
495
  // totalSignal is therefore a pure pass-through of externalSignal with no timer.
481
496
  const totalTimeout = createPassthroughSignal(externalSignal);
482
497
  const totalSignal = totalTimeout.signal;
498
+ // Request-loop 529s and SSE overload events share one counter; at the
499
+ // limit the configured fallback model takes over the whole send.
500
+ const overload = createAnthropicOverloadTracker({
501
+ model: useModel,
502
+ fallbackModel: opts._fallbackTriggered ? undefined : opts.fallbackModel,
503
+ });
483
504
  const { requestWithRetry, cleanupCancelHandler } = createAnthropicOAuthRequest({
484
505
  provider: this,
485
506
  opts,
@@ -487,6 +508,7 @@ export class AnthropicOAuthProvider {
487
508
  useModel,
488
509
  sessionId,
489
510
  totalSignal,
511
+ overload,
490
512
  betaHeadersFor: (requestBody) =>
491
513
  buildOAuthBetaHeaders(requestBody, {
492
514
  fastMode: this.fastModeBetaHeaderLatched,
@@ -516,24 +538,14 @@ export class AnthropicOAuthProvider {
516
538
  recovery,
517
539
  onStageChange,
518
540
  retry529: opts.retry529 !== false,
541
+ overload,
519
542
  });
520
543
 
544
+ let maxTokensAdjusted = false;
521
545
  try {
522
546
  for (let attemptIndex = 0; attemptIndex <= ANTHROPIC_MAX_MIDSTREAM_RETRIES; attemptIndex++) {
523
547
  let response, controller, cancelHandler;
524
- try {
525
- ({ response, controller, cancelHandler } = await requestWithRetry(auth.creds.accessToken));
526
- } catch (err) {
527
- if (err instanceof AnthropicFallbackTriggeredError) {
528
- process.stderr.write(`[anthropic-oauth] ${err.message}\n`);
529
- return this.send(messages, err.fallbackModel, tools, {
530
- ...opts,
531
- fallbackModel: undefined,
532
- _fallbackTriggered: true,
533
- });
534
- }
535
- throw err;
536
- }
548
+ ({ response, controller, cancelHandler } = await requestWithRetry(auth.creds.accessToken));
537
549
 
538
550
  // Refresh on 401, and only Anthropic's exact official revoked-token
539
551
  // 403 signature. Ordinary permission/policy 403s are terminal.
@@ -541,8 +553,7 @@ export class AnthropicOAuthProvider {
541
553
  if (response.status === 401 || response.status === 403) {
542
554
  rejectedAuthBody = await response.text().catch(() => '');
543
555
  }
544
- const revoked403 = response.status === 403 && String(rejectedAuthBody).includes('OAuth token has been revoked');
545
- if (response.status === 401 || revoked403) {
556
+ if (isRefreshableAuthRejection(response.status, rejectedAuthBody)) {
546
557
  process.stderr.write(`[anthropic-oauth] ${response.status} — forcing refresh and retrying once\n`);
547
558
  cleanupCancelHandler(cancelHandler);
548
559
  // Body was drained above; abort closes any remaining transport
@@ -555,6 +566,20 @@ export class AnthropicOAuthProvider {
555
566
  rejectedAuthBody = null;
556
567
  }
557
568
 
569
+ // "input length and max_tokens exceed context limit": shrink max_tokens
570
+ // to what the context has room for and replay once.
571
+ if (response.status === 400 && !maxTokensAdjusted) {
572
+ rejectedAuthBody = await response.text().catch(() => '');
573
+ if (adjustMaxTokensForContextOverflow(body, 400, rejectedAuthBody)) {
574
+ maxTokensAdjusted = true;
575
+ cleanupCancelHandler(cancelHandler);
576
+ try {
577
+ controller?.abort?.();
578
+ } catch {}
579
+ ({ response, controller, cancelHandler } = await requestWithRetry(auth.creds.accessToken));
580
+ rejectedAuthBody = null;
581
+ }
582
+ }
558
583
  if (!response.ok) {
559
584
  cleanupCancelHandler(cancelHandler);
560
585
  return await this._resendAfterRejection({
@@ -615,6 +640,18 @@ export class AnthropicOAuthProvider {
615
640
  }
616
641
  }
617
642
  throw midstream.exhaustedError();
643
+ } catch (err) {
644
+ // The fallback trigger can surface from the request loop, a mid-stream
645
+ // overload, or the non-streaming recovery: handle it around the whole
646
+ // operation, not just the first request.
647
+ if (!(err instanceof AnthropicFallbackTriggeredError)) throw err;
648
+ process.stderr.write(`[anthropic-oauth] ${err.message}\n`);
649
+ announceAnthropicModelFallback(onStageChange, _displayModel(useModel), _displayModel(err.fallbackModel));
650
+ return await this.send(messages, err.fallbackModel, tools, {
651
+ ...opts,
652
+ fallbackModel: undefined,
653
+ _fallbackTriggered: true,
654
+ });
618
655
  } finally {
619
656
  totalTimeout.cleanup();
620
657
  }
@@ -632,6 +669,21 @@ export class AnthropicOAuthProvider {
632
669
  throw anthropicQuotaError(response.status, response.headers, safeText);
633
670
  }
634
671
 
672
+ // An account that cannot use fast mode answers the speed field with a
673
+ // 400. Fast mode is now off for this process, so replaying the turn once
674
+ // builds a standard-speed request.
675
+ if (
676
+ response.status === 400 &&
677
+ opts.fast === true &&
678
+ !opts._fastModeRetry &&
679
+ fastModeDowngraded(
680
+ noteFastModeCapacityError({ httpStatus: 400, message: scrubbedText }, { fast: true })
681
+ )
682
+ ) {
683
+ process.stderr.write(`[anthropic-oauth] fast mode is not enabled for this account; retrying at standard speed\n`);
684
+ return this.send(messages, useModel, tools, { ...opts, _fastModeRetry: true });
685
+ }
686
+
635
687
  // A newer model that rejects the mid-conversation effort update: switch
636
688
  // the updates off for it in this process and replay the turn once
637
689
  // without them (the request keeps its turn effort).
@@ -694,9 +746,14 @@ export class AnthropicOAuthProvider {
694
746
  return this.send(messages, fallbackModel || model, tools, { ...opts, _modelRetry: true });
695
747
  }
696
748
  const err = new Error(`Anthropic OAuth API ${response.status}: ${safeText}`);
697
- err.status = response.status;
698
- err.httpStatus = response.status;
699
- throw err;
749
+ // 413 stays `request_too_large` (a byte/media size refusal) and a 400
750
+ // "prompt is too long" stays `invalid_request_error`, so the core can tell
751
+ // a payload it must shrink from a context it can compact.
752
+ throw applyAnthropicErrorContract(err, {
753
+ status: response.status,
754
+ headers: response.headers,
755
+ bodyText: scrubbedText,
756
+ });
700
757
  }
701
758
 
702
759
  // Traces + catalog upkeep for a streamed turn, then the empty-stream guard.
@@ -0,0 +1,69 @@
1
+ /**
2
+ * anthropic-overload-fallback.mjs — one overload counter per logical send,
3
+ * shared by the request loop (HTTP 529 before a stream exists) and the SSE
4
+ * parser (`overloaded_error` event after one started). Both reach it through
5
+ * the same error fields — `status: 529` / `code: 'overloaded_error'` — so a
6
+ * mix of the two trips the configured fallback model after the same number of
7
+ * consecutive overloads, instead of each path counting only its own.
8
+ *
9
+ * The request loop's counter is withRetry's `overloadState`; this tracker owns
10
+ * that object, so the SSE path increments the very counter the loop reads.
11
+ */
12
+ import { ANTHROPIC_MAX_CONSECUTIVE_529 } from './retry-backoff.mjs';
13
+ import { AnthropicFallbackTriggeredError } from './retry-classifier.mjs';
14
+
15
+ export const OVERLOADED_ERROR_CODE = 'overloaded_error';
16
+
17
+ /** Consecutive 529s end the request only for API-key (non-subscriber) first-party Opus. */
18
+ export function isTerminalOverloadModel(model) {
19
+ return /^claude-opus-/.test(String(model || '').trim().toLowerCase());
20
+ }
21
+
22
+ export function isAnthropicOverloadError(err) {
23
+ const status = Number(err?.httpStatus || err?.status || err?.response?.status || 0);
24
+ return status === 529 || String(err?.code || '').toLowerCase() === OVERLOADED_ERROR_CODE;
25
+ }
26
+
27
+ /**
28
+ * @param {{ model: string, fallbackModel?: string|null, terminalAtLimit?: boolean }} deps fallbackModel is
29
+ * already undefined when this send IS the fallback (no second hop).
30
+ */
31
+ export function createAnthropicOverloadTracker({ model, fallbackModel, terminalAtLimit = false }) {
32
+ const canFallback = Boolean(fallbackModel) && fallbackModel !== model;
33
+ // Handed to every withRetry of the send as `overloadState`: the request
34
+ // loop increments this same object on each 529.
35
+ const state = { consecutive529Errors: 0 };
36
+ return {
37
+ state,
38
+ // Repeated-overload stop, handed to withRetry as `stopAfterRepeated529`: with no
39
+ // fallback model, API-key Opus stops after repeated 529s. A configured
40
+ // fallback always wins (the executor checks it first).
41
+ stopAfterRepeated529: terminalAtLimit && !canFallback,
42
+ /**
43
+ * An overload SSE error. Returns the fallback trigger to throw once the
44
+ * consecutive limit is reached and a fallback model is configured.
45
+ */
46
+ noteStreamOverload(err) {
47
+ state.consecutive529Errors += 1;
48
+ if (state.consecutive529Errors < ANTHROPIC_MAX_CONSECUTIVE_529) return null;
49
+ if (canFallback) return new AnthropicFallbackTriggeredError(model, fallbackModel, err);
50
+ // No fallback model: API-key Opus stops here ("Repeated 529 Overloaded
51
+ // errors") instead of spending the full budget.
52
+ if (!terminalAtLimit) return null;
53
+ err.repeated529 = true;
54
+ return err;
55
+ },
56
+ };
57
+ }
58
+
59
+ /** Visible model-switch notice on the existing display-only stage channel. */
60
+ export function announceAnthropicModelFallback(onStageChange, fromLabel, toLabel) {
61
+ if (typeof onStageChange !== 'function') return;
62
+ try {
63
+ onStageChange('reconnecting', {
64
+ message: `${fromLabel} is overloaded — continuing on ${toLabel}`,
65
+ });
66
+ } catch {
67
+ /* display-only */
68
+ }
69
+ }
@@ -6,6 +6,10 @@ function normalizedModelId(value) {
6
6
  return typeof raw === 'string' ? raw.trim() : '';
7
7
  }
8
8
 
9
+ // Kept as an id pattern: no catalog field declares server-side fallback, and
10
+ // `fallbacks` is a beta-gated body field other models reject (a wrong "yes" is
11
+ // a 400, a wrong "no" only skips an optional refusal fallback), so unknown ids
12
+ // stay off.
9
13
  export function supportsAnthropicServerFallback(model) {
10
14
  const id = normalizeClaudeModelId(normalizedModelId(model));
11
15
  return /^claude-(?:opus|fable)-5(?:$|[-@])/.test(id);
@@ -36,6 +36,20 @@ export function createTurnBlocks() {
36
36
  const appendText = (index, chunk) => {
37
37
  text.set(index, (text.get(index) || '') + (chunk || ''));
38
38
  };
39
+ // Per-index citations of a text block (content_block_start `citations` plus
40
+ // streamed citations_delta), replayed verbatim on the text block they cite.
41
+ const citations = new Map();
42
+ const appendCitation = (index, citation) => {
43
+ if (!citation || typeof citation !== 'object') return;
44
+ if (!text.has(index)) text.set(index, '');
45
+ let copy;
46
+ try {
47
+ copy = structuredClone(citation);
48
+ } catch {
49
+ copy = { ...citation };
50
+ }
51
+ citations.set(index, [...(citations.get(index) || []), copy]);
52
+ };
39
53
  // Client tool_use blocks that were actually dispatched, kept for the same
40
54
  // ordered replay list (deduped/skipped calls are intentionally absent).
41
55
  const clientToolUse = new Map();
@@ -61,7 +75,11 @@ export function createTurnBlocks() {
61
75
  ...thinking.entries(),
62
76
  ...[...text.entries()].map(([index, value]) => [
63
77
  index,
64
- { type: 'text', text: typeof value === 'string' ? value : '' },
78
+ {
79
+ type: 'text',
80
+ text: typeof value === 'string' ? value : '',
81
+ ...(citations.get(index)?.length ? { citations: citations.get(index) } : {}),
82
+ },
65
83
  ]),
66
84
  ...completedNativeBlocks(),
67
85
  ...clientToolUse.entries(),
@@ -105,6 +123,7 @@ export function createTurnBlocks() {
105
123
  pendingToolInputs,
106
124
  clientToolUse,
107
125
  appendText,
126
+ appendCitation,
108
127
  toolInputInFlight,
109
128
  orderedThinkingBlocks,
110
129
  orderedAssistantBlocks,
@@ -88,14 +88,27 @@ export function createContentBlockDelta({ turn, blocks, state, leak, relayText,
88
88
  progress('tool');
89
89
  };
90
90
 
91
- return (index, delta) => {
91
+ const stampTtft = () => {
92
+ if (state && !state.ttftAt) state.ttftAt = Date.now();
93
+ };
94
+
95
+ const onContentBlockDelta = (index, delta) => {
92
96
  if (delta?.type) turn.contentBlockTypes.add(delta.type);
93
97
  // Time-to-first-token: stamp the first content delta (text / thinking /
94
98
  // tool input_json) exactly once so the SSE trace can separate first-byte
95
99
  // latency from total stream/generation time.
96
- if (state && !state.ttftAt) state.ttftAt = Date.now();
100
+ stampTtft();
97
101
  if (delta?.type === 'text_delta') onTextDelta(index, delta.text);
102
+ if (delta?.type === 'citations_delta') blocks.appendCitation(index, delta.citation);
98
103
  if (delta?.type === 'thinking_delta' || delta?.type === 'signature_delta') onThinkingDelta(index, delta);
99
104
  if (delta?.type === 'input_json_delta') onInputJsonDelta(index, delta.partial_json);
100
105
  };
106
+ // A text block may open with non-empty `text` on content_block_start: it is
107
+ // model output and takes the same path as a text_delta (live relay, leak
108
+ // guard, returned content, ordered replay copy).
109
+ onContentBlockDelta.seedText = (index, initialText) => {
110
+ stampTtft();
111
+ onTextDelta(index, initialText);
112
+ };
113
+ return onContentBlockDelta;
101
114
  }
@@ -19,7 +19,7 @@ function cloneNativeBlock(block) {
19
19
  }
20
20
  }
21
21
 
22
- export function createContentBlockStart({ turn, blocks, state, progress }) {
22
+ export function createContentBlockStart({ turn, blocks, state, progress, seedText }) {
23
23
  const seedThinkingBlock = (index, block) => {
24
24
  if (block.type === 'redacted_thinking') {
25
25
  // Opaque redacted payload: real reasoning content, exposed as a block.
@@ -61,9 +61,16 @@ export function createContentBlockStart({ turn, blocks, state, progress }) {
61
61
  });
62
62
  }
63
63
  if (block?.type === 'text') {
64
- // Seed the ordered text slot (a text block may open with a non-empty
65
- // `text` before any delta).
66
- blocks.appendText(index, typeof block.text === 'string' ? block.text : '');
64
+ // Seed the ordered text slot. An empty block still needs its slot (it
65
+ // separates thinking runs); a non-empty opening `text` is model output
66
+ // and is routed exactly like a text_delta so it reaches the returned and
67
+ // live content once.
68
+ const initialText = typeof block.text === 'string' ? block.text : '';
69
+ if (initialText) seedText(index, initialText);
70
+ else blocks.appendText(index, '');
71
+ if (Array.isArray(block.citations)) {
72
+ for (const citation of block.citations) blocks.appendCitation(index, citation);
73
+ }
67
74
  }
68
75
  if (NATIVE_SERVER_TOOL_CALL_BLOCK_TYPES.has(block?.type)) {
69
76
  // Verbatim seed; `input` is completed from the streamed
@@ -26,6 +26,9 @@ export function createMessageEvents({ turn, blocks, state }) {
26
26
  if (event.delta && (event.delta.stop_details != null || event.delta.category != null)) {
27
27
  turn.stopDetails = stopDetailsFrom(event.delta);
28
28
  }
29
+ if (event.delta?.stop_sequence != null) {
30
+ turn.stopSequence = event.delta.stop_sequence;
31
+ }
29
32
  if (event.usage) updateTurnUsage(turn.usage, event.usage);
30
33
  // A terminal stop_reason while ANY tool input is still streaming ends the
31
34
  // turn truncated, immediately: the model declared it stopped sampling, so
@@ -21,18 +21,25 @@ export function createTurnEvents({
21
21
  labels,
22
22
  }) {
23
23
  const { onMessageStart, onMessageDelta, onMessageStop } = createMessageEvents({ turn, blocks, state });
24
+ const onContentBlockDelta = createContentBlockDelta({
25
+ turn,
26
+ blocks,
27
+ state,
28
+ leak,
29
+ relayText,
30
+ progress,
31
+ relayProgressUpdates,
32
+ });
24
33
  return {
25
34
  onMessageStart,
26
- onContentBlockStart: createContentBlockStart({ turn, blocks, state, progress }),
27
- onContentBlockDelta: createContentBlockDelta({
35
+ onContentBlockStart: createContentBlockStart({
28
36
  turn,
29
37
  blocks,
30
38
  state,
31
- leak,
32
- relayText,
33
39
  progress,
34
- relayProgressUpdates,
40
+ seedText: onContentBlockDelta.seedText,
35
41
  }),
42
+ onContentBlockDelta,
36
43
  onContentBlockStop: createContentBlockStop({ turn, blocks, state, leak, progress, onToolCall, labels }),
37
44
  onMessageDelta,
38
45
  onMessageStop,
@@ -138,6 +138,7 @@ export function createTurnOutcome({ turn, blocks, state, labels = OAUTH_STREAM_L
138
138
  usage: turn.usage,
139
139
  stopReason: turn.stopReason,
140
140
  stopDetails: turn.stopDetails,
141
+ ...(turn.stopSequence != null ? { stopSequence: turn.stopSequence } : {}),
141
142
  hasThinkingContent: turn.hasThinkingContent,
142
143
  contentBlockTypes: Array.from(turn.contentBlockTypes),
143
144
  // Ordered extended-thinking blocks (verbatim thinking text + signature)
@@ -5,6 +5,8 @@
5
5
  * module of the turn reads and writes this one object; nothing about the
6
6
  * turn's progress is hidden in a closure.
7
7
  */
8
+ import { reportedCostUsd } from '../lib/usage-primitives.mjs';
9
+ import { normalizeServerToolUse } from '../lib/anthropic-server-tool-usage.mjs';
8
10
 
9
11
  export function createAnthropicTurnState() {
10
12
  return {
@@ -16,6 +18,9 @@ export function createAnthropicTurnState() {
16
18
  usage: { inputTokens: 0, outputTokens: 0, cachedTokens: 0, cacheWriteTokens: 0, raw: null },
17
19
  stopReason: null,
18
20
  stopDetails: undefined,
21
+ // The custom stop sequence that ended the turn (message_delta
22
+ // delta.stop_sequence); stays undefined unless the API reports one.
23
+ stopSequence: undefined,
19
24
  fallbackEvents: [],
20
25
  // Set when a terminal frame (message_delta stop_reason / message_stop)
21
26
  // arrived while tool input was still in flight — used only to word the
@@ -35,6 +40,15 @@ export function updateTurnUsage(usage, raw) {
35
40
  if (raw.cache_creation?.ephemeral_1h_input_tokens != null) {
36
41
  usage.cacheWrite1hTokens = raw.cache_creation.ephemeral_1h_input_tokens;
37
42
  }
43
+ // A gateway's reported cost (OpenRouter puts `cost` on the final usage). It
44
+ // rides the turn usage itself, so a success, an abandoned attempt and a
45
+ // failure's partial usage all carry it to the provider-boundary ledger.
46
+ const costUsd = reportedCostUsd(raw.cost);
47
+ if (costUsd !== undefined) usage.costUsd = costUsd;
48
+ // Server-tool counters are cumulative in message_delta; a later report
49
+ // replaces the earlier one, an absent one preserves it.
50
+ const serverToolUse = normalizeServerToolUse(raw);
51
+ if (serverToolUse) usage.serverToolUse = serverToolUse;
38
52
  usage.raw = { ...(usage.raw || {}), ...raw };
39
53
  // Input excludes cache; all three slots contribute to prompt volume.
40
54
  usage.promptTokens = usage.inputTokens + usage.cachedTokens + usage.cacheWriteTokens;
@@ -75,9 +75,11 @@ const ANTHROPIC_SSE_ERROR_TYPE_STATUS = new Map([
75
75
  ['authentication_error', 401],
76
76
  ['permission_error', 403],
77
77
  ['not_found_error', 404],
78
+ ['conflict_error', 409],
78
79
  ['request_too_large', 413],
79
80
  ['rate_limit_error', 429],
80
81
  ['api_error', 500],
82
+ ['timeout_error', 504],
81
83
  ['overloaded_error', 529],
82
84
  ]);
83
85
 
@@ -109,6 +111,13 @@ function _anthropicSseError(event, labels) {
109
111
  err.httpStatus = status;
110
112
  err.status = status;
111
113
  }
114
+ // Provider-boundary contract: `code` is the lowercased Anthropic error type
115
+ // (an overload carries `overloaded_error` + 529, which the overload counter
116
+ // reads); an untyped `error` frame keeps the generic SSE code. A 413 is a
117
+ // byte-size refusal, never a prompt-token one.
118
+ const wireType = typeof type === 'string' ? type.trim().toLowerCase() : '';
119
+ if (status === 413) err.code = 'request_too_large';
120
+ else if (wireType && wireType !== 'error') err.code = wireType;
112
121
  // Wire-error marker: an error type OUTSIDE the documented enumeration
113
122
  // (no status resolved above) default-retries under the shared wire-error
114
123
  // contract instead of failing the turn as 'unknown'. Typed statuses and
@@ -162,7 +171,7 @@ function applyAnthropicSseEvent(framedEvent, { turn, watchdogs, state, progress,
162
171
  return false;
163
172
  }
164
173
  } catch (err) {
165
- if (err?.code === 'EANTHROPIC_SSE_ERROR') throw err;
174
+ if (err?.name === 'AnthropicSseError') throw err;
166
175
  /* skip malformed events */
167
176
  return false;
168
177
  }
@@ -10,6 +10,7 @@
10
10
  * account for usage identically.
11
11
  */
12
12
  import { traceAgentUsage } from '../agent-trace.mjs';
13
+ import { reportedCostUsd } from './lib/usage-primitives.mjs';
13
14
 
14
15
  /**
15
16
  * @param {object} parseResult the assembled turn (streaming or normalized non-streaming)
@@ -26,6 +27,7 @@ export function buildAnthropicTurnResult(parseResult, { provider, useModel, opts
26
27
  const output = parseResult.usage?.outputTokens || 0;
27
28
  const promptTokens = parseResult.usage?.promptTokens ?? input + cacheRead + cacheWrite;
28
29
  const liveModel = parseResult.model || useModel;
30
+ const costUsd = parseResult.usage?.costUsd ?? reportedCostUsd(usageRaw?.cost);
29
31
 
30
32
  if (usageRaw || input || output || cacheRead || cacheWrite) {
31
33
  traceAgentUsage({
@@ -53,6 +55,8 @@ export function buildAnthropicTurnResult(parseResult, { provider, useModel, opts
53
55
  model: liveModel,
54
56
  toolCalls: parseResult.toolCalls,
55
57
  stopReason: parseResult.stopReason || null,
58
+ ...(parseResult.stopDetails != null ? { stopDetails: parseResult.stopDetails } : {}),
59
+ ...(parseResult.stopSequence != null ? { stopSequence: parseResult.stopSequence } : {}),
56
60
  hasThinkingContent: !!parseResult.hasThinkingContent,
57
61
  contentBlockTypes: Array.isArray(parseResult.contentBlockTypes) ? parseResult.contentBlockTypes : [],
58
62
  // Round-trip adaptive-thinking blocks (verbatim thinking +
@@ -84,6 +88,11 @@ export function buildAnthropicTurnResult(parseResult, { provider, useModel, opts
84
88
  cacheWriteTokens: cacheWrite,
85
89
  ...(parseResult.usage?.cacheWrite1hTokens ? { cacheWrite1hTokens: parseResult.usage.cacheWrite1hTokens } : {}),
86
90
  promptTokens,
91
+ // A gateway-reported cost (OpenRouter `usage.cost`), when the turn has one.
92
+ ...(costUsd !== undefined ? { costUsd } : {}),
93
+ ...(parseResult.usage?.serverToolUse ? { serverToolUse: parseResult.usage.serverToolUse } : {}),
94
+ // Raw provider usage (incl. server_tool_use counters), as on the OAuth path.
95
+ ...(usageRaw ? { raw: usageRaw } : {}),
87
96
  },
88
97
  };
89
98
  }