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
@@ -1,6 +1,8 @@
1
1
  import { randomBytes } from 'node:crypto';
2
2
  import { PROVIDER_FIRST_BYTE_TIMEOUT_MS, providerTimeoutError, streamStalledError } from '../stall-policy.mjs';
3
3
  import { typedStatusFrom } from './retry-classifier.mjs';
4
+ import { applyCompatErrorContract } from './openai-compat-error-contract.mjs';
5
+ import { truncatedCompatStreamError } from './lib/openai-tool-args.mjs';
4
6
 
5
7
  // Shared lifecycle and replay boundaries for both OpenAI-compatible protocols.
6
8
 
@@ -22,10 +24,68 @@ function markInBandWireError(err) {
22
24
  if (typed && !err.httpStatus) err.httpStatus = typed;
23
25
  const code = detail.code ?? detail.type ?? null;
24
26
  if (code != null && code !== '' && !err.providerErrorCode) err.providerErrorCode = String(code);
27
+ applyCompatErrorContract(err, detail);
25
28
  } catch {}
26
29
  return err;
27
30
  }
28
31
 
32
+ /**
33
+ * A frame the SDK failed to JSON-decode. Raised only at the wire-decoding
34
+ * boundary (the iterator's own next()); consumers stamp the exposure evidence
35
+ * (partial output, replay safety) on it in their failure path.
36
+ */
37
+ export function malformedCompatStreamError(label, cause) {
38
+ const err = new Error(`${label || 'compat SSE'} malformed stream frame: ${cause?.message || 'invalid JSON'}`, {
39
+ cause,
40
+ });
41
+ err.name = 'MalformedStreamError';
42
+ err.code = 'malformed_stream';
43
+ err.malformedStream = true;
44
+ return err;
45
+ }
46
+
47
+ /**
48
+ * A chat `finish_reason: network_error` is an interruption the gateway reports
49
+ * in-band, never a completion. Typed as a truncated stream so the shared
50
+ * classifier treats it as transient; exposure gates decide replay.
51
+ */
52
+ export function networkInterruptedCompatStreamError(label) {
53
+ const err = truncatedCompatStreamError(label, 'finish_reason=network_error');
54
+ err.name = 'StreamInterruptedError';
55
+ err.streamInterrupted = true;
56
+ err.finishReason = 'network_error';
57
+ return err;
58
+ }
59
+
60
+ export function isNetworkErrorFinishReason(finishReason) {
61
+ return typeof finishReason === 'string' && finishReason.trim().toLowerCase() === 'network_error';
62
+ }
63
+
64
+ /**
65
+ * A chat `finish_reason: error` means the upstream failed the generation
66
+ * (gateways surface it as a 502 upstream_error). Typed like the network interruption, with the gateway status.
67
+ */
68
+ export function upstreamErrorCompatStreamError(label) {
69
+ const err = truncatedCompatStreamError(label, 'finish_reason=error');
70
+ err.name = 'StreamInterruptedError';
71
+ err.streamInterrupted = true;
72
+ err.finishReason = 'error';
73
+ err.status = 502;
74
+ err.code = 'upstream_error';
75
+ return err;
76
+ }
77
+
78
+ export function isErrorFinishReason(finishReason) {
79
+ return typeof finishReason === 'string' && finishReason.trim().toLowerCase() === 'error';
80
+ }
81
+
82
+ /** The typed interruption for a failing chat finish_reason, or null for any other value. */
83
+ export function failingFinishReasonError(finishReason, label) {
84
+ if (isNetworkErrorFinishReason(finishReason)) return networkInterruptedCompatStreamError(label);
85
+ if (isErrorFinishReason(finishReason)) return upstreamErrorCompatStreamError(label);
86
+ return null;
87
+ }
88
+
29
89
  export function synthLeakedOpenAICall(recovered) {
30
90
  let args = recovered?.arguments;
31
91
  if (args === null || typeof args !== 'object' || Array.isArray(args)) args = {};
@@ -59,7 +119,7 @@ export function closeCompatStream(stream, iterator) {
59
119
 
60
120
  export async function nextAsyncWithWatchdog(
61
121
  iterator,
62
- { signal, idleMs, idleDeadlineAt, idleEnabled, idleLabel, emittedToolCall } = {}
122
+ { signal, idleMs, idleDeadlineAt, idleEnabled, idleLabel, streamLabel, emittedToolCall } = {}
63
123
  ) {
64
124
  let idleTimer = null;
65
125
  let idleReject = null;
@@ -106,7 +166,11 @@ export async function nextAsyncWithWatchdog(
106
166
  };
107
167
  signal.addEventListener('abort', onAbort, { once: true });
108
168
  }
109
- iterator.next().then(resolve, reject);
169
+ // The SDK JSON-decodes each frame inside next(): a SyntaxError here is a
170
+ // malformed wire frame, typed at this boundary and nowhere else.
171
+ iterator.next().then(resolve, (error) =>
172
+ reject(error instanceof SyntaxError ? malformedCompatStreamError(streamLabel || idleLabel, error) : error)
173
+ );
110
174
  });
111
175
  } catch (err) {
112
176
  if (idleTimedOut)
@@ -31,6 +31,7 @@ import {
31
31
  finalizeResponsesStream,
32
32
  unresolvedSalvageError,
33
33
  } from './openai-compat-responses-state.mjs';
34
+ import { createRefusals, refusalResultFields } from './openai-ws-response-state/refusals.mjs';
34
35
  import { responsesUsage } from './openai-compat-response-normalization.mjs';
35
36
  import { noteAbandonedUsage } from '../../../shared/llm/usage-context.mjs';
36
37
 
@@ -99,6 +100,7 @@ export async function consumeCompatResponsesStream(
99
100
  idleDeadlineAt: state.semanticIdleDeadlineAt,
100
101
  idleEnabled: sawFirstEvent && idleEnabled && state.semanticIdleDeadlineAt > 0,
101
102
  idleLabel: `${label} SSE idle`,
103
+ streamLabel: label,
102
104
  // Unsafe-to-retry once any tool call (native or recovered-leaked)
103
105
  // has been emitted this stream — avoid a double side-effect.
104
106
  emittedToolCall: () => state.emittedToolCall || leakedCalls.length > 0,
@@ -144,13 +146,18 @@ export async function consumeCompatResponsesStream(
144
146
  }
145
147
  throw stampOutcome(err);
146
148
  }
147
- const unresolved = unresolvedSalvageError(state);
149
+ const unresolved = unresolvedSalvageError(state, label);
148
150
  if (unresolved) {
149
151
  attachPartialState(unresolved, state, leakedCalls);
150
152
  throw stampOutcome(unresolved);
151
153
  }
152
154
  try {
153
- return finalizeResponsesStream(state, { leakedCalls, parseResponsesToolCalls, responseOutputText, label });
155
+ const result = finalizeResponsesStream(state, { leakedCalls, parseResponsesToolCalls, responseOutputText, label });
156
+ // The terminal output bundle's refusal parts join the streamed ones (keyed
157
+ // by item id + content index, so copies of one part fold into one text).
158
+ state.refusals ||= createRefusals();
159
+ for (const item of result.response?.output || []) state.refusals.absorbMessage(item);
160
+ return { ...result, ...refusalResultFields(state.refusals, result.content) };
154
161
  } catch (err) {
155
162
  attachPartialState(err, state, leakedCalls);
156
163
  throw stampOutcome(err);
@@ -37,6 +37,8 @@ export function extractCompatCachedTokens(usage) {
37
37
  usage?.input_tokens_details?.cached_tokens,
38
38
  usage?.prompt_cache_hit_tokens,
39
39
  usage?.cached_prompt_text_tokens,
40
+ // Together reports it top-level; first-positive wins, so it never stacks on a nested count.
41
+ usage?.cached_tokens,
40
42
  ];
41
43
  for (const v of candidates) {
42
44
  const n = Number(v);
@@ -17,7 +17,11 @@ import {
17
17
  } from './media-normalization.mjs';
18
18
  import { customToolCallFromResponseItem, nativeToolSearchCallFromArguments } from './custom-tool-wire.mjs';
19
19
  import { providerReplayItems } from './lib/provider-replay.mjs';
20
+ import { acceptedWireTools } from './lib/claude-bridge-schema.mjs';
20
21
  import { ensureResponsesCallOutputs } from './lib/wire-pairing.mjs';
22
+ import { responsesEffortUpdates } from './effort-configuration.mjs';
23
+ import { convertMessagesToResponsesInput } from './openai-responses-input.mjs';
24
+ import { COMPAT_REASONING_METADATA_KEY, contentWithThinkingChunk } from './openai-compat-reasoning-field.mjs';
21
25
 
22
26
  function positiveTokenInt(value) {
23
27
  const n = Number(value);
@@ -38,19 +42,23 @@ export function toOpenAIMessages(messages, providerName, options = {}) {
38
42
  // strict providers (xai) reject unknown roles/types and would 400 the
39
43
  // request. Documented in v0.1.160 (GPT reasoning replay).
40
44
  //
41
- // DeepSeek splits by model: thinking-mode models with tools REQUIRE the
42
- // prior turn's `reasoning_content` echoed back (400 without it), while
43
- // `deepseek-reasoner` REJECTS it with a 400. The caller decides per model
44
- // through options.replaysReasoningContent — see
45
- // deepseekReplaysReasoningContent below. xAI reasoning models preserve
46
- // their official multi-turn shape and cache prefix stability when prior
47
- // assistant reasoning_content is replayed; reasoning_effort itself remains
48
- // caller/user-selected.
45
+ // DeepSeek thinking-mode models with tools REQUIRE the prior turn's
46
+ // `reasoning_content` echoed back (400 without it); without tools it is
47
+ // ignored, so the caller (options.replaysReasoningContent) always replays it.
48
+ // xAI reasoning models preserve their official multi-turn shape and cache
49
+ // prefix stability when prior assistant reasoning_content is replayed;
50
+ // reasoning_effort itself remains caller/user-selected.
49
51
  //
50
52
  // Custom providers pass options.customReplay (custom-reasoning.mjs replay
51
53
  // eligibility). When it is a boolean it alone decides; a replaying custom
52
54
  // endpoint also needs a non-empty reasoning_content on every assistant
53
55
  // tool-call turn, so missing/empty reasoning there is padded with " ".
56
+ //
57
+ // options.reasoningShape (openai-compat-reasoning-field.mjs) names the
58
+ // endpoint families with their own reasoning fields; they decide the resend
59
+ // key and win over the flags above. options.developerRole keeps the
60
+ // `developer` role for endpoints that document it; every other chat endpoint
61
+ // only knows `system`, so developer instructions go out as system messages.
54
62
  const customReplay = typeof options.customReplay === 'boolean' ? options.customReplay : null;
55
63
  const replaysReasoningContent = customReplay ?? (options.replaysReasoningContent === true || providerName === 'xai');
56
64
  const out = [];
@@ -61,8 +69,25 @@ export function toOpenAIMessages(messages, providerName, options = {}) {
61
69
  const details = metadata?.reasoning_details ?? metadata?.reasoningDetails;
62
70
  return Array.isArray(details) && details.length ? details : null;
63
71
  };
72
+ const shape = options.reasoningShape || null;
73
+ // Receive and resend fields differ per endpoint family: the key a reply's
74
+ // reasoning arrived on is recorded in providerMetadata at receive time.
75
+ const receivedField = (message) => message?.providerMetadata?.[COMPAT_REASONING_METADATA_KEY]?.reasoningField;
76
+ const attachShapeReasoning = (msg, message, stored) => {
77
+ if (!stored) return;
78
+ if (shape.resend === 'same_key') {
79
+ msg[receivedField(message) === 'reasoning' ? 'reasoning' : 'reasoning_content'] = stored;
80
+ } else if (shape.resend === 'reasoning') {
81
+ // OpenRouter: reasoning_details replace the text when present.
82
+ if (!openRouterReasoningDetails(message)) msg.reasoning = stored;
83
+ } else if (shape.resend === 'content_chunks' && receivedField(message) === 'content_chunks') {
84
+ msg.content = contentWithThinkingChunk(msg.content, stored);
85
+ }
86
+ };
64
87
  const attachAssistantReasoning = (msg, message) => {
65
- if (customReplay) {
88
+ if (shape) {
89
+ attachShapeReasoning(msg, message, typeof message.reasoningContent === 'string' ? message.reasoningContent : '');
90
+ } else if (customReplay) {
66
91
  const stored = typeof message.reasoningContent === 'string' ? message.reasoningContent : '';
67
92
  if (stored) msg.reasoning_content = stored;
68
93
  else if (Array.isArray(msg.tool_calls) && msg.tool_calls.length) msg.reasoning_content = ' ';
@@ -103,8 +128,12 @@ export function toOpenAIMessages(messages, providerName, options = {}) {
103
128
  continue;
104
129
  }
105
130
  const msg = {
106
- role: m.role,
107
- content: normalizeContentForOpenAIChat(m.content, { role: m.role, nativePdf: options.nativePdf }),
131
+ role: m.role === 'developer' && options.developerRole !== true ? 'system' : m.role,
132
+ content: normalizeContentForOpenAIChat(m.content, {
133
+ role: m.role,
134
+ nativePdf: options.nativePdf,
135
+ cacheControl: options.cacheControl === true,
136
+ }),
108
137
  };
109
138
  out.push(m.role === 'assistant' ? attachAssistantReasoning(msg, m) : msg);
110
139
  }
@@ -112,18 +141,6 @@ export function toOpenAIMessages(messages, providerName, options = {}) {
112
141
  return out;
113
142
  }
114
143
 
115
- // deepseek-reasoner returns 400 when `reasoning_content` appears in the input
116
- // messages; every other DeepSeek thinking model needs it back once tools are in
117
- // play. Unknown DeepSeek ids default to replaying: a missing echo breaks the
118
- // tool loop, while a stray field on a non-thinking model is ignored.
119
- export function deepseekReplaysReasoningContent(model) {
120
- return !/reasoner/.test(
121
- String(model || '')
122
- .trim()
123
- .toLowerCase()
124
- );
125
- }
126
-
127
144
  export function toOpenAITools(tools) {
128
145
  return tools.map((t) => ({
129
146
  type: 'function',
@@ -145,9 +162,42 @@ function functionToolFromSessionTool(t, name = t?.name) {
145
162
  };
146
163
  }
147
164
 
148
- export function toResponsesTools(tools, options = {}) {
165
+ // xAI hosts tool search itself (docs.x.ai progressive tool disclosure): a
166
+ // `{type:'tool_search'}` server tool loads the definitions of function tools
167
+ // marked `defer_loading: true`, and the server returns the search as
168
+ // tool_search_call / tool_search_output items. The client loader (`load_tool`)
169
+ // is therefore replaced by that one server tool; with deferred tools but no
170
+ // loader the server tool is still added, or the deferred tools could never load.
171
+ function toServerToolSearchTools(tools) {
172
+ let hasSearch = false;
173
+ let hasDeferred = false;
174
+ const out = tools.map((t) => {
175
+ if (t?.name === 'load_tool' || t?.name === 'tool_search') {
176
+ if (hasSearch) return null;
177
+ hasSearch = true;
178
+ return { type: 'tool_search' };
179
+ }
180
+ if (t?.deferLoading === true || t?.defer_loading === true) {
181
+ hasDeferred = true;
182
+ return { ...functionToolFromSessionTool(t), defer_loading: true };
183
+ }
184
+ return functionToolFromSessionTool(t);
185
+ });
186
+ if (hasDeferred && !hasSearch) out.push({ type: 'tool_search' });
187
+ return out.filter(Boolean);
188
+ }
189
+
190
+ export function toResponsesTools(allTools, options = {}) {
149
191
  const provider = String(options?.provider || '').toLowerCase();
192
+ // A Responses endpoint rejects the whole request for one invalid
193
+ // `parameters`; a tool broken even after lowering is left out and reported.
194
+ const tools = acceptedWireTools(allTools, 'openai', options?.onToolExcluded, `[${provider || 'responses'}] tool`);
195
+ if (options?.serverToolSearch === true) return toServerToolSearchTools(tools);
196
+ // A route pinned with verified native deferred tools declares the native
197
+ // client tool_search tool and marks deferred definitions `defer_loading`.
198
+ const nativeDeferred = options?.nativeDeferredTools === true;
150
199
  const allowNativeToolSearch =
200
+ nativeDeferred ||
151
201
  options?.nativeToolSearch === true ||
152
202
  (options?.nativeToolSearch !== false && (provider === 'openai' || provider === 'openai-oauth'));
153
203
  return tools.map((t) => {
@@ -169,6 +219,9 @@ export function toResponsesTools(tools, options = {}) {
169
219
  // tools (e.g. apply_patch) as ordinary function tools instead. Grammar
170
220
  // tools may carry no usable inputSchema, so fall back to a permissive
171
221
  // object schema so grok still registers a valid function tool.
222
+ if (nativeDeferred && (t?.deferLoading === true || t?.defer_loading === true)) {
223
+ return { ...functionToolFromSessionTool(t), defer_loading: true };
224
+ }
172
225
  return functionToolFromSessionTool(t);
173
226
  });
174
227
  }
@@ -236,7 +289,7 @@ export function parseResponsesToolCalls(response, label) {
236
289
  } else if (item?.type === 'custom_tool_call') {
237
290
  const call = customToolCallFromResponseItem(item);
238
291
  if (call) out.push(call);
239
- } else if (item?.type === 'tool_search_call') {
292
+ } else if (item?.type === 'tool_search_call' && item.execution !== 'server') {
240
293
  const searchArgs =
241
294
  item.arguments && typeof item.arguments === 'object' && !Array.isArray(item.arguments)
242
295
  ? item.arguments
@@ -408,25 +461,54 @@ export function toXaiResponsesInput(messages, providerState, options = {}) {
408
461
  let history = [];
409
462
  if (Array.isArray(state?.encryptedReasoningHistory)) history = state.encryptedReasoningHistory;
410
463
  else if (Array.isArray(state?.encryptedReasoningItems)) {
411
- history = [{ messageIndex: seen, items: state.encryptedReasoningItems }];
464
+ history = [{ messageIndex: seen, items: state.encryptedReasoningItems, owner: state.owner }];
412
465
  }
413
466
  for (const entry of history) {
414
467
  const index = Number(entry?.messageIndex);
415
468
  if (!Number.isInteger(index) || index < 0 || !Array.isArray(entry?.items)) continue;
469
+ // Owner-tagged reasoning (compat routes) never replays under another
470
+ // owner, even when a caller passes provider state across providers.
471
+ if (entry.owner !== undefined && entry.owner !== replayProvider) continue;
416
472
  const bucket = reasoningByMessageIndex.get(index) || [];
417
473
  bucket.push(...entry.items.map((item) => ({ ...item })));
418
474
  reasoningByMessageIndex.set(index, bucket);
419
475
  }
420
476
  }
477
+ if (options.nativeLowering === true) {
478
+ // Native-item-capable Responses routes share the first-party lowering:
479
+ // native tool_search / custom calls keep their own output type, and only
480
+ // this route's own replay tag and reasoning state are replayed.
481
+ return {
482
+ input: convertMessagesToResponsesInput(messages, {
483
+ startIndex,
484
+ includeSystem,
485
+ nativePdf: options.nativePdf,
486
+ replayProvider,
487
+ // Compat-owned tool_search payloads are tagged with the route name.
488
+ nativeToolSearchProvider: options.providerName,
489
+ replayOwnedReasoning: true,
490
+ reasoningByMessageIndex,
491
+ effortProjection: options.effortProjection,
492
+ splitToolContent: (content) => splitToolContentForXaiResponses(content, { nativePdf: options.nativePdf }),
493
+ }),
494
+ previousResponseId,
495
+ startIndex,
496
+ continuationResetReason: resetReason,
497
+ };
498
+ }
421
499
  const pendingToolMedia = [];
422
500
  const flushToolMedia = () => {
423
501
  if (!pendingToolMedia.length) return;
424
502
  input.push({ role: 'user', content: pendingToolMedia.splice(0) });
425
503
  };
504
+ // `options.effortProjection` (custom GPT-6+ routes) carries wire-ready effort updates.
505
+ const effortUpdates = responsesEffortUpdates(options.effortProjection);
426
506
  for (let messageIndex = startIndex; messageIndex < messages.length; messageIndex += 1) {
427
507
  const m = messages[messageIndex];
428
508
  if (!includeSystem && m.role === 'system') continue;
509
+ const updates = effortUpdates.before(m);
429
510
  if (m.role !== 'tool') flushToolMedia();
511
+ input.push(...updates);
430
512
  const orderedReplay = m.role === 'assistant' ? providerReplayItems(m, replayProvider) : undefined;
431
513
  if (orderedReplay?.length) {
432
514
  input.push(...orderedReplay);
@@ -444,6 +526,7 @@ export function toXaiResponsesInput(messages, providerState, options = {}) {
444
526
  flushToolMedia();
445
527
  const trailingReasoning = reasoningByMessageIndex.get(messages.length);
446
528
  if (trailingReasoning) input.push(...trailingReasoning);
529
+ input.push(...effortUpdates.end());
447
530
  // Wire-level pairing guard: replay envelopes can carry a call whose
448
531
  // result never committed (cancel/abort). The provider hard-rejects the
449
532
  // unpaired call, so synthesize the missing outputs here.
@@ -1,9 +1,11 @@
1
1
  import { resolveProviderApiKey } from '../../../shared/provider-api-key.mjs';
2
2
  import { markProviderRecoveryExhausted, withRetry } from './retry-classifier.mjs';
3
+ import { compatRetryOptions, withCompatRetryProfile } from './openai-compat-retry-profile.mjs';
3
4
  import { consumeCompatResponsesStream } from './openai-compat-stream.mjs';
4
5
  import { PROVIDER_FIRST_BYTE_TIMEOUT_MS, createPassthroughSignal } from '../stall-policy.mjs';
5
6
  import {
6
7
  nativeResponsesTools,
8
+ resolveCompatMaxOutputTokens,
7
9
  toOpenAIMessages,
8
10
  toResponsesTools,
9
11
  toXaiResponsesInput,
@@ -25,17 +27,34 @@ import { applyCompatToolChoice, compatStreamRetryReporter } from './compat-reque
25
27
  import { envFlag as _envFlag } from '../../../shared/env.mjs';
26
28
  import { resolveResponsesTransportPolicy, RESPONSES_TRANSPORT_CAPABILITIES } from './openai-transport-policy.mjs';
27
29
 
30
+ // Server-side tool search is strictly opt-in, from the provider's own config
31
+ // (`xaiServerToolSearch`, shared by grok-oauth's inner xai provider) or the
32
+ // request opts. Unset, every xAI request body is unchanged: deferred tools go
33
+ // out as plain function tools and the client `load_tool` stays a function.
34
+ // Server-executed search items replay through the owner-tagged providerReplay
35
+ // envelope in either mode and are never dispatched locally.
36
+ function xaiServerToolSearchEnabled(provider, opts) {
37
+ return (opts.xaiServerToolSearch ?? provider.config?.xaiServerToolSearch) === true;
38
+ }
39
+
28
40
  // Tool list, parallel tool calls, tool choice and reasoning effort shared by
29
41
  // the HTTP/SSE and WebSocket Responses bodies.
30
42
  function applyXaiResponsesToolsAndEffort(params, { provider, tools, opts, useModel }) {
31
43
  const nativeTools = nativeResponsesTools(opts);
32
44
  if (tools?.length || nativeTools.length) {
33
- params.tools = [...nativeTools, ...toResponsesTools(tools || [], { provider: 'xai' })];
45
+ const toolOptions = xaiServerToolSearchEnabled(provider, opts)
46
+ ? { provider: 'xai', serverToolSearch: true, onToolExcluded: opts.onToolExcluded }
47
+ : { provider: 'xai', onToolExcluded: opts.onToolExcluded };
48
+ params.tools = [...nativeTools, ...toResponsesTools(tools || [], toolOptions)];
34
49
  }
35
50
  // Explicit parallel tool calls, matching the OpenAI Responses
36
51
  // reference shape. Probe-verified accepted by api.x.ai (HTTP 200,
37
- // 2026-08-16); absent, the service default decides per turn.
38
- if (params.tools?.length) params.parallel_tool_calls = true;
52
+ // 2026-08-16); absent, the service default decides per turn. An explicit
53
+ // caller `parallelToolCalls:false` is honored (docs.x.ai function-calling).
54
+ if (params.tools?.length) params.parallel_tool_calls = opts.parallelToolCalls !== false;
55
+ // Caller output cap (docs.x.ai text best-practices): max_output_tokens.
56
+ const maxOutputTokens = resolveCompatMaxOutputTokens(opts);
57
+ if (maxOutputTokens) params.max_output_tokens = maxOutputTokens;
39
58
  applyCompatToolChoice(params, opts);
40
59
  const reasoningEffort = normalizeXaiReasoningEffort(
41
60
  opts.xaiReasoningEffort ??
@@ -91,7 +110,7 @@ export async function sendXaiResponses(provider, messages, useModel, tools, opts
91
110
  let streamed;
92
111
  try {
93
112
  streamed = await withRetry(
94
- async ({ signal: attemptSignal }) => {
113
+ withCompatRetryProfile(provider.name, async ({ signal: attemptSignal }) => {
95
114
  const stream = await withRetry(
96
115
  ({ signal: openSignal }) => provider.client.responses.create(params, { signal: openSignal }),
97
116
  {
@@ -127,11 +146,12 @@ export async function sendXaiResponses(provider, messages, useModel, tools, opts
127
146
  }
128
147
  throw error;
129
148
  }
130
- },
149
+ }),
131
150
  {
132
151
  signal: totalSignal.signal,
133
152
  onRetry: compatStreamRetryReporter('xai:responses', opts),
134
153
  retry529: opts.retry529,
154
+ ...compatRetryOptions(provider.name),
135
155
  }
136
156
  );
137
157
  } finally {
@@ -199,7 +219,8 @@ export async function sendXaiResponsesWebSocket(provider, messages, useModel, to
199
219
  onTextDelta: typeof opts.onTextDelta === 'function' ? opts.onTextDelta : null,
200
220
  onStageChange: typeof opts.onStageChange === 'function' ? opts.onStageChange : null,
201
221
  externalSignal: signal,
202
- poolKey: opts.sessionId || opts.session?.id || null,
222
+ // A forked request runs in its own transport scope (transport-scope.mjs).
223
+ poolKey: opts.transportScope || opts.sessionId || opts.session?.id || null,
203
224
  cacheKey: cacheRouting.key,
204
225
  iteration,
205
226
  useModel,
@@ -14,7 +14,7 @@ import { appendAgentTrace } from '../agent-trace.mjs';
14
14
  import { resolveProviderCacheKey, resolveProviderPromptCacheLane } from '../agent-runtime/cache-strategy.mjs';
15
15
  import { shouldFallbackTransport } from './retry-classifier.mjs';
16
16
  import { envFlag as _envFlag } from '../../../shared/env.mjs';
17
- import { getModelsDevRowSync } from '../../../shared/llm/model-catalog.mjs';
17
+ import { getModelMetadataSync, getModelsDevRowSync } from '../../../shared/llm/model-catalog.mjs';
18
18
  import {
19
19
  traceHash,
20
20
  stableTraceStringify,
@@ -166,26 +166,35 @@ export function normalizeXaiReasoningEffort(value) {
166
166
  return ['low', 'medium', 'high', 'xhigh'].includes(effort) ? effort : null;
167
167
  }
168
168
 
169
- // grok-3, grok-4 and grok-4-fast REJECT reasoning_effort outright (HTTP 400
170
- // "does not support parameter reasoningEffort"), so the parameter ships only
171
- // for the families that document it. An unknown/absent model id keeps the
172
- // parameter — a custom xAI-compatible deployment that never saw the 400 must
173
- // not silently lose the caller's effort choice.
169
+ const hasEffortValues = (modelOptions) =>
170
+ (modelOptions || []).some((option) => option?.type === 'effort' && option.values?.length > 0);
171
+
172
+ // The first Grok generations (grok-3, grok-4, grok-4-fast, grok-code-fast)
173
+ // REJECT reasoning_effort outright (HTTP 400 "does not support parameter
174
+ // reasoningEffort"). That generation is closed: it is told apart by a bare
175
+ // major with no minor version, so a later release never matches.
176
+ const LEGACY_NO_EFFORT_GROK = /^grok[-_]?(?:[123]|4|code)(?![.\d])/;
177
+
178
+ // The parameter ships when the catalog says the model takes it. A model the
179
+ // catalog does not list yet is sent the caller's effort (the server decides),
180
+ // as is an unknown/absent model id — a custom xAI-compatible deployment that
181
+ // never saw the 400 must not silently lose the caller's effort choice. Only
182
+ // the closed legacy generation above is held back offline, because sending to
183
+ // it hard-fails.
174
184
  export function xaiModelSupportsReasoningEffort(model) {
175
185
  const id = String(model || '')
176
186
  .trim()
177
187
  .toLowerCase();
178
188
  if (!id) return true;
179
189
  if (!id.startsWith('grok')) return true;
180
- // The catalog answers first: a listed model takes the parameter exactly
181
- // when it publishes effort values (grok-4.3 does, grok-4.20-*-reasoning
182
- // does not), so a new release needs no edit here.
190
+ // The catalog answers first, from the live roster and the pricing catalogs:
191
+ // a model that publishes effort values takes the parameter.
192
+ if (hasEffortValues(getModelMetadataSync(id, 'xai')?.reasoningOptions)) return true;
193
+ // A listed model takes the parameter exactly when it publishes effort
194
+ // values (grok-4.3 does, grok-4.20-*-reasoning does not).
183
195
  const listed = getModelsDevRowSync(id, 'xai');
184
- if (listed) {
185
- return (listed.reasoning_options || []).some((option) => option?.type === 'effort' && option.values?.length > 0);
186
- }
187
- // grok-4.5 / grok-4.6 and anything newer in that line.
188
- return /grok[-_]?4\.(?:[5-9]|\d{2,})/.test(id);
196
+ if (listed) return hasEffortValues(listed.reasoning_options);
197
+ return !LEGACY_NO_EFFORT_GROK.test(id);
189
198
  }
190
199
 
191
200
  function opencodeGoReasoningEffortValues(modelInfo) {
@@ -226,13 +235,18 @@ export function useXaiResponsesApi(opts, config) {
226
235
  }
227
236
 
228
237
  export function useXaiResponsesWebSocket(opts, config) {
238
+ // A pinned route (grok-oauth's cli-chat-proxy) takes its transport from the
239
+ // config alone: the xAI WebSocket connector targets api.x.ai, so no request
240
+ // option or env override may carry the OAuth bearer there.
229
241
  const raw =
230
- opts?.xaiResponsesTransport ??
231
- opts?.xaiTransport ??
232
- config?.responsesTransport ??
233
- config?.transport ??
234
- process.env.MIXDOG_XAI_RESPONSES_TRANSPORT ??
235
- process.env.MIXDOG_XAI_TRANSPORT;
242
+ config?.transportPinned === true
243
+ ? config.responsesTransport
244
+ : (opts?.xaiResponsesTransport ??
245
+ opts?.xaiTransport ??
246
+ config?.responsesTransport ??
247
+ config?.transport ??
248
+ process.env.MIXDOG_XAI_RESPONSES_TRANSPORT ??
249
+ process.env.MIXDOG_XAI_TRANSPORT);
236
250
  // Reference xAI/Grok parity is HTTP/SSE. WebSocket remains available only
237
251
  // when a caller explicitly selects a WS transport.
238
252
  if (raw == null || raw === '') return false;
@@ -13,7 +13,9 @@ import {
13
13
  _shouldFallbackXaiWsToHttp,
14
14
  } from './openai-compat-xai.mjs';
15
15
  import { withEffortRejectionFallback } from './effort-rejection.mjs';
16
+ import { applyCompatErrorContract } from './openai-compat-error-contract.mjs';
16
17
  import { sendCompatResponses } from './openai-compat-responses.mjs';
18
+ import { COMPAT_RETRY_POLICY, COMPAT_RETRY_PROFILES, XAI_COMPAT_RETRY_POLICY } from './openai-compat-retry-profile.mjs';
17
19
  import { sendCompatChat, recoverCompatNonStreaming } from './openai-compat-chat-send.mjs';
18
20
  import { sendXaiResponses, sendXaiResponsesWebSocket } from './openai-compat-xai-send.mjs';
19
21
  import {
@@ -71,9 +73,14 @@ export class OpenAICompatProvider {
71
73
  const baseURL = assertSafeBaseURL(config.baseURL || preset?.baseURL || 'http://localhost:8080/v1', name);
72
74
  const apiKey = resolveProviderApiKey(name, config) || 'no-key';
73
75
  this.name = name;
76
+ // A profiled provider's limits are final: no loop-level recovery cycles on top.
77
+ if (COMPAT_RETRY_PROFILES[name]) this.retryPolicy = name === 'xai' ? XAI_COMPAT_RETRY_POLICY : COMPAT_RETRY_POLICY;
74
78
  this.config = config;
75
79
  this.baseURL = baseURL;
76
80
  this.apiKey = apiKey;
81
+ // Whether Chat content blocks keep their Anthropic-style `cache_control`
82
+ // (OpenRouter documents it); a gateway that does not ignores or rejects it.
83
+ this.chatCacheControl = (config.chatCacheControl ?? preset?.chatCacheControl) === true;
77
84
  // Merge caller-supplied headers (config.extraHeaders) over the preset's.
78
85
  // Used e.g. by grok-oauth to inject the Grok CLI client headers for the
79
86
  // grok-build proxy. Backward-compatible: providers that pass no
@@ -168,9 +175,19 @@ export class OpenAICompatProvider {
168
175
  }
169
176
  async _doSend(messages, model, tools, sendOpts) {
170
177
  const useModel = model || this.defaultModel;
171
- return withEffortRejectionFallback(this.name, useModel, sendOpts || {}, this.config?.reasoningEffort, (opts) =>
172
- this._sendWithOpts(messages, useModel, tools, opts)
173
- );
178
+ try {
179
+ return await withEffortRejectionFallback(
180
+ this.name,
181
+ useModel,
182
+ sendOpts || {},
183
+ this.config?.reasoningEffort,
184
+ (opts) => this._sendWithOpts(messages, useModel, tools, opts)
185
+ );
186
+ } catch (err) {
187
+ // Every provider built on this transport (custom, grok, muse, mimo,
188
+ // command-code, local) leaves through here with the boundary contract.
189
+ throw applyCompatErrorContract(err);
190
+ }
174
191
  }
175
192
  async _sendWithOpts(messages, useModel, tools, opts) {
176
193
  // Re-warm a kept-alive socket to the provider origin before the turn so
@@ -242,7 +259,9 @@ export class OpenAICompatProvider {
242
259
  return fetchCompatModelItems(this);
243
260
  }
244
261
  async listModels() {
245
- return listCompatModels(this);
262
+ // A failed /models request must surface; an empty list would be cached as
263
+ // a complete catalog by the shared catalog loader.
264
+ return listCompatModels(this, { throwOnError: true });
246
265
  }
247
266
  async isAvailable() {
248
267
  return isCompatProviderAvailable(this);