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
@@ -18,6 +18,7 @@ import { withEffortConfigurationFallback } from './effort-configuration.mjs';
18
18
  import { enrichModels } from './model-catalog.mjs';
19
19
  import { sanitizeModelList } from './model-list-sanitize.mjs';
20
20
  import { sendViaHttpSse, _envFlag } from './openai-oauth-http-sse.mjs';
21
+ import { waitForRetryDeadline } from './openai-error-contract.mjs';
21
22
  import { isWsMessageTooBigClose, shouldFallbackTransport } from './retry-classifier.mjs';
22
23
  import { resolveOpenAiTransportPolicy } from './openai-transport-policy.mjs';
23
24
  import { applyOpenAIDirectCachePolicy } from './openai-direct-request.mjs';
@@ -77,6 +78,9 @@ export class OpenAIDirectProvider {
77
78
  // input_tokens INCLUDES cached tokens (OpenAI convention). See registry.mjs.
78
79
  static inputExcludesCache = false;
79
80
  name = 'openai';
81
+ // Loop retry policy (send-with-recovery loopRetryPolicy): a connect failure waits for
82
+ // the network, and a content_filter refusal is replayed under the budget.
83
+ retryPolicy = Object.freeze({ unboundedConnectionRetry: true, contentFilterRetryable: true });
80
84
  config;
81
85
  // Sessions (WS pool keys) the server refused with close 1009. Every later
82
86
  // full frame of such a session would be refused again, so it stays on
@@ -107,6 +111,10 @@ export class OpenAIDirectProvider {
107
111
  }
108
112
  return null;
109
113
  }
114
+ /** Drop a disposed transport scope's sticky transport record. */
115
+ releaseTransportScope(scope) {
116
+ this._httpFallbackPoolKeys.delete(scope);
117
+ }
110
118
  send(messages, model, tools, sendOpts) {
111
119
  return withEffortConfigurationFallback('openai', model, sendOpts || {}, (opts) =>
112
120
  this._sendOnce(messages, model, tools, opts)
@@ -135,8 +143,9 @@ export class OpenAIDirectProvider {
135
143
  // poolKey MUST be sessionId-only. Falling back to promptCacheKey would
136
144
  // let unrelated raw sessions sharing the same provider-scoped cache
137
145
  // bucket reuse each other's pooled socket and inherit lastResponseId
138
- // delta state, producing cross-session prompt corruption.
139
- const poolKey = opts.sessionId || null;
146
+ // delta state, producing cross-session prompt corruption. A forked
147
+ // request runs in its own transport scope (transport-scope.mjs).
148
+ const poolKey = opts.transportScope || opts.sessionId || null;
140
149
  // cacheKey (prompt_cache_key) only groups the server-side prefix-cache
141
150
  // shard — safe to share across sessions, unlike the sessionId poolKey
142
151
  // above. buildRequestBody derives it from the base namespace plus a
@@ -190,26 +199,14 @@ export class OpenAIDirectProvider {
190
199
  // any liveTextEmitted/emittedToolCall/unsafeToRetry outcome.
191
200
  const transportPolicy = resolveOpenAiTransportPolicy();
192
201
  const httpFallbackEnabled = transportPolicy.allowHttpFallback && _envFlag('MIXDOG_OPENAI_HTTP_FALLBACK', true);
193
- const dispatchHttp = (a) => {
194
- if (!process.env.MIXDOG_QUIET_PROVIDER_LOG) {
195
- process.stderr.write('[openai-ws] WebSocket unhealthy; falling back to HTTP/SSE\n');
196
- }
197
- return sendHttp({ ...common, auth: a, opts, fetchFn: opts._fetchFn });
198
- };
199
- // Transport-policy switch (MIXDOG_OAI_TRANSPORT). 'http-sse' forces the
200
- // HTTP/SSE transport directly — no WS attempt, so skip the fallback log
201
- // that dispatchHttp emits (it is not a fallback here). All other modes
202
- // ('auto'/'ws-full'/'ws-delta') keep the WS-first path below; ws-full vs
203
- // ws-delta only affects the delta gate inside openai-ws-delta.mjs.
204
- if (
205
- transportPolicy.transport === 'http' ||
206
- (poolKey && httpFallbackEnabled && this._httpFallbackPoolKeys.has(poolKey))
207
- ) {
202
+ // One HTTP/SSE send with the single replay-safe 401 key reload. `reload`
203
+ // is false when the key was already reloaded earlier in this send.
204
+ const sendHttpWithKeyReload = async (a, reload = true) => {
208
205
  try {
209
- return await sendHttp({ ...common, auth, opts, fetchFn: opts._fetchFn });
206
+ return await sendHttp({ ...common, auth: a, opts, fetchFn: opts._fetchFn });
210
207
  } catch (err) {
211
208
  const unsafe = err?.liveTextEmitted === true || err?.emittedToolCall === true || err?.unsafeToRetry === true;
212
- if (err?.httpStatus !== 401 || unsafe) throw err;
209
+ if (!reload || err?.httpStatus !== 401 || unsafe) throw err;
213
210
  // The replay discards this attempt; its reported usage stays billed.
214
211
  noteErrorUsage(err);
215
212
  process.stderr.write('[openai-ws] 401 — reloading apiKey and retrying once over HTTP\n');
@@ -222,10 +219,32 @@ export class OpenAIDirectProvider {
222
219
  fetchFn: opts._fetchFn,
223
220
  });
224
221
  }
222
+ };
223
+ const dispatchHttp = (a, reload = true) => {
224
+ if (!process.env.MIXDOG_QUIET_PROVIDER_LOG) {
225
+ process.stderr.write('[openai-ws] WebSocket unhealthy; falling back to HTTP/SSE\n');
226
+ }
227
+ return sendHttpWithKeyReload(a, reload);
228
+ };
229
+ // Transport-policy switch (MIXDOG_OAI_TRANSPORT). 'http-sse' forces the
230
+ // HTTP/SSE transport directly — no WS attempt, so skip the fallback log
231
+ // that dispatchHttp emits (it is not a fallback here). All other modes
232
+ // ('auto'/'ws-full'/'ws-delta') keep the WS-first path below; ws-full vs
233
+ // ws-delta only affects the delta gate inside openai-ws-delta.mjs.
234
+ if (
235
+ transportPolicy.transport === 'http' ||
236
+ (poolKey &&
237
+ httpFallbackEnabled &&
238
+ // A forked scope follows its session's refusal; it records its own.
239
+ (this._httpFallbackPoolKeys.has(poolKey) || this._httpFallbackPoolKeys.has(opts.sessionId)))
240
+ ) {
241
+ return await sendHttpWithKeyReload(auth);
225
242
  }
226
- const fallbackHttp = (a, error) => {
243
+ const fallbackHttp = async (a, error, reload = true) => {
227
244
  if (poolKey && isWsMessageTooBigClose(error)) this._httpFallbackPoolKeys.add(poolKey);
228
- return dispatchHttp(a);
245
+ // Changing transport must not bypass the server's retry deadline.
246
+ await waitForRetryDeadline(error, externalSignal, opts._sleepFn);
247
+ return dispatchHttp(a, reload);
229
248
  };
230
249
  try {
231
250
  return await dispatchWs(auth);
@@ -254,7 +273,7 @@ export class OpenAIDirectProvider {
254
273
  return await dispatchWs(retryAuth);
255
274
  } catch (retryErr) {
256
275
  if (shouldFallbackDirectTransport(retryErr, { signal: externalSignal, enabled: httpFallbackEnabled })) {
257
- return await fallbackHttp(retryAuth, retryErr);
276
+ return await fallbackHttp(retryAuth, retryErr, false);
258
277
  }
259
278
  throw retryErr;
260
279
  }
@@ -0,0 +1,170 @@
1
+ /**
2
+ * OpenCode Go's Gemini route: `@ai-sdk/google` models are served by the
3
+ * gateway's generateContent endpoint, `{base}/models/{id}:streamGenerateContent`
4
+ * (https://opencode.ai/docs/go/ — Endpoints table). This engine reuses the
5
+ * direct Gemini adapter's request builder, stream consumer, retry ladder and
6
+ * result shaping, and only moves the transport onto the gateway: the Go key
7
+ * (never GEMINI_API_KEY) goes to the Go origin only, as a bearer token and the
8
+ * `x-goog-api-key` header, with the session / User-Agent headers of every Go
9
+ * request. Gateway models have no explicit cachedContents.
10
+ */
11
+ import { GeminiProvider, geminiRestError } from './gemini.mjs';
12
+ import { GEMINI_FIRST_BYTE_TIMEOUT_MS, consumeGeminiRestStreamResponse } from './gemini-stream.mjs';
13
+ import { geminiBareModelId } from './gemini-cache-policy.mjs';
14
+ import { geminiFailureUsage } from './gemini-response.mjs';
15
+ import { geminiEndsWithFunctionResponse, runGeminiStreamAttempts } from './gemini-retry-policy.mjs';
16
+ import { geminiTextLeakGuardFor } from './gemini-sdk-request.mjs';
17
+ import { emitProviderRetryStage } from './retry-classifier.mjs';
18
+ import { originBoundFetch } from './lib/origin-bound-fetch.mjs';
19
+ import { createPassthroughSignal, createTimeoutSignal } from '../stall-policy.mjs';
20
+ import { getLlmDispatcher } from '../../../shared/llm/http-agent.mjs';
21
+ import { reloadProviderApiKey, resolveProviderApiKey } from '../../../shared/provider-api-key.mjs';
22
+
23
+ const PROVIDER = 'opencode-go';
24
+
25
+ /** The generateContent request body for a built Gemini request. */
26
+ export function openCodeGoGeminiBody({ contents, systemInstruction, geminiTools, toolConfig, generationConfig, safetySettings }) {
27
+ return {
28
+ contents,
29
+ ...(systemInstruction ? { systemInstruction: { parts: [{ text: systemInstruction }] } } : {}),
30
+ ...(geminiTools ? { tools: geminiTools } : {}),
31
+ ...(toolConfig ? { toolConfig } : {}),
32
+ ...(generationConfig ? { generationConfig } : {}),
33
+ ...(safetySettings ? { safetySettings } : {}),
34
+ };
35
+ }
36
+
37
+ export class OpenCodeGoGeminiEngine extends GeminiProvider {
38
+ name = PROVIDER;
39
+
40
+ /** @param {object} config the Go provider config; `baseURL` is the OpenAI-style `.../v1` base */
41
+ constructor(config) {
42
+ const base = String(config.baseURL || '').replace(/\/+$/, '');
43
+ super({
44
+ ...config,
45
+ fetchFn: originBoundFetch(new URL(base).origin, config.fetchImpl, PROVIDER),
46
+ // No Google host to warm and no Google SDK client: this engine never uses either.
47
+ preconnectFn: () => {},
48
+ createGenAI: () => null,
49
+ });
50
+ this.gatewayBase = base;
51
+ }
52
+
53
+ _getApiKey() {
54
+ return resolveProviderApiKey(PROVIDER, this.config);
55
+ }
56
+
57
+ reloadApiKey() {
58
+ const key = reloadProviderApiKey(PROVIDER, this.config);
59
+ if (key) this.config = { ...(this.config || {}), apiKey: key };
60
+ return key || '';
61
+ }
62
+
63
+ async isAvailable() {
64
+ return Boolean(this._getApiKey());
65
+ }
66
+
67
+ // The gateway has no cachedContents resource.
68
+ async _ensureGeminiCache() {
69
+ return null;
70
+ }
71
+
72
+ _headers(opts) {
73
+ const key = this._getApiKey();
74
+ return {
75
+ 'Content-Type': 'application/json',
76
+ ...(key ? { Authorization: `Bearer ${key}`, 'x-goog-api-key': key } : {}),
77
+ ...(this.config?.extraHeaders || {}),
78
+ ...(opts?.requestHeaders || {}),
79
+ };
80
+ }
81
+
82
+ _url(model, method) {
83
+ return `${this.gatewayBase}/models/${encodeURIComponent(geminiBareModelId(model))}:${method}`;
84
+ }
85
+
86
+ async _openGatewayStream(url, body, opts, attemptSignal) {
87
+ const openFirstByte = createTimeoutSignal(attemptSignal, GEMINI_FIRST_BYTE_TIMEOUT_MS, 'OpenCode Go Gemini first byte');
88
+ let res;
89
+ try {
90
+ res = await this._fetch(url, {
91
+ method: 'POST',
92
+ headers: this._headers(opts),
93
+ body: JSON.stringify(body),
94
+ signal: openFirstByte.signal,
95
+ dispatcher: getLlmDispatcher(),
96
+ });
97
+ } finally {
98
+ openFirstByte.cleanup();
99
+ }
100
+ if (!res.ok) {
101
+ throw geminiRestError(res, await res.text().catch(() => ''), 'OpenCode Go Gemini streamGenerateContent');
102
+ }
103
+ return res;
104
+ }
105
+
106
+ async _generateContent(model, body, opts, signal) {
107
+ const res = await this._fetch(this._url(model, 'generateContent'), {
108
+ method: 'POST',
109
+ headers: this._headers(opts),
110
+ body: JSON.stringify(body),
111
+ signal,
112
+ dispatcher: getLlmDispatcher(),
113
+ });
114
+ if (!res.ok) {
115
+ throw geminiRestError(res, await res.text().catch(() => ''), 'OpenCode Go Gemini generateContent');
116
+ }
117
+ return await res.json();
118
+ }
119
+
120
+ async _streamViaSdk(stream) {
121
+ const { opts, signal, useModel, contents, callbacks } = stream;
122
+ const body = openCodeGoGeminiBody(stream);
123
+ const url = `${this._url(useModel, 'streamGenerateContent')}?alt=sse`;
124
+ const passthrough = createPassthroughSignal(signal);
125
+ try {
126
+ return await runGeminiStreamAttempts({
127
+ signal: passthrough.signal,
128
+ sleepFn: this.config?.sleepFn,
129
+ onRetry: ({ attempt, maxAttempts, lastErr, delayMs }) => {
130
+ emitProviderRetryStage(opts.onStageChange, { attempt: attempt + 1, maxAttempts, lastErr, delayMs });
131
+ process.stderr.write(
132
+ `[opencode-go:gemini] retry attempt ${attempt + 1} after ${lastErr?.message || lastErr?.code || 'transient error'}\n`
133
+ );
134
+ },
135
+ afterToolResult: geminiEndsWithFunctionResponse(contents),
136
+ run: async ({ signal: attemptSignal, connected }) => {
137
+ try {
138
+ opts.onStageChange?.('requesting');
139
+ } catch {
140
+ /* heartbeat best-effort */
141
+ }
142
+ const res = await this._openGatewayStream(url, body, opts, attemptSignal);
143
+ connected();
144
+ const textLeakGuard = geminiTextLeakGuardFor(stream);
145
+ const response = await consumeGeminiRestStreamResponse(res, {
146
+ signal: attemptSignal,
147
+ onStreamDelta: callbacks.onStreamDelta,
148
+ onTextDelta: callbacks.onTextDelta,
149
+ textLeakGuard,
150
+ label: 'OpenCode Go Gemini streamGenerateContent',
151
+ failureUsage: geminiFailureUsage(opts, null, useModel),
152
+ });
153
+ return { response, textLeakGuard };
154
+ },
155
+ });
156
+ } catch (err) {
157
+ const recovered = await this._recoverGeminiNonStreaming({
158
+ streamErr: err,
159
+ signal: passthrough.signal,
160
+ opts,
161
+ model: useModel,
162
+ generate: (fallbackSignal) => this._generateContent(useModel, body, opts, fallbackSignal),
163
+ });
164
+ if (!recovered) throw err;
165
+ return { response: recovered, textLeakGuard: null };
166
+ } finally {
167
+ passthrough.cleanup();
168
+ }
169
+ }
170
+ }
@@ -1,30 +1,49 @@
1
1
  import { randomUUID } from 'node:crypto';
2
2
  import { AnthropicProvider } from './anthropic.mjs';
3
3
  import { OpenAICompatProvider, OPENAI_COMPAT_PRESETS } from './openai-compat.mjs';
4
- import { currentUsageContext } from '../../../shared/llm/usage-context.mjs';
5
4
  import { getModelMetadataSync, getModelsDevRowSync } from './model-catalog.mjs';
5
+ import { toInclusiveUsage, withInclusiveUsage } from './lib/inclusive-usage.mjs';
6
+ import { providerOffersWire, resolveWireRoute, sendOnRoute } from './wire-route.mjs';
7
+ import { gatewayMessagesOpts } from './wire-gateway.mjs';
8
+
9
+ // The Go Anthropic route: the shared request builder gets the model's output
10
+ // ceiling (models.dev limit) through the gateway options.
11
+ class OpenCodeGoMessagesEngine extends AnthropicProvider {
12
+ _sendOnce(messages, model, tools, opts) {
13
+ return super._sendOnce(messages, model, tools, gatewayMessagesOpts(this.config, model, messages, opts));
14
+ }
15
+ }
6
16
 
7
17
  // OpenCode Go publishes OpenAI chat/completions, OpenAI Responses, and
8
18
  // Anthropic Messages endpoints, and each upstream brand answers on only one
9
- // of them (muse-spark / gpt / grok 500 on chat/completions; minimax expects
10
- // Messages). models.dev names the SDK package per model, which is the
11
- // authoritative wire selector; the prefix tables are the cold-catalog fallback.
12
- const ANTHROPIC_MODEL_PREFIXES = ['minimax-', 'qwen'];
13
- const RESPONSES_MODEL_PREFIXES = ['muse-spark-', 'gpt-', 'grok-'];
19
+ // of them (muse-spark / gpt / grok 500 on chat/completions; minimax and
20
+ // Claude expect Messages). models.dev names the SDK package per model, which
21
+ // is the authoritative wire selector; wire-route.mjs holds the cold-catalog
22
+ // prefix fallback. `@ai-sdk/google` names the Gemini generateContent wire
23
+ // (opencode-go-gemini.mjs).
14
24
  const WIRE_API_BY_NPM = Object.freeze({
15
25
  '@ai-sdk/openai': 'responses',
16
26
  '@ai-sdk/anthropic': 'messages',
17
27
  '@ai-sdk/openai-compatible': 'chat',
28
+ '@ai-sdk/google': 'gemini',
18
29
  });
19
30
 
31
+ function openCodeGoCatalogWire(model) {
32
+ const npm = getModelsDevRowSync(String(model || ''), 'opencode-go')?.npm;
33
+ return typeof npm === 'string' && Object.hasOwn(WIRE_API_BY_NPM, npm) ? WIRE_API_BY_NPM[npm] : null;
34
+ }
35
+
36
+ function resolveOpenCodeGoWireRoute(model, ctx = {}) {
37
+ const catalogWire = openCodeGoCatalogWire(model);
38
+ // Each Go model answers on the one wire the catalog names: it narrows the
39
+ // offered endpoints, so an override cannot pick a wire the model lacks.
40
+ const endpoints = providerOffersWire('opencode-go', catalogWire) ? [catalogWire] : null;
41
+ return resolveWireRoute('opencode-go', model, { ...ctx, catalogWire, endpoints });
42
+ }
43
+
20
44
  /** Wire API for a Go model: 'responses' | 'messages' | 'chat'. */
21
45
  function openCodeGoWireApi(model) {
22
- const id = String(model || '').toLowerCase();
23
- const npm = getModelsDevRowSync(String(model || ''), 'opencode-go')?.npm;
24
- if (npm && WIRE_API_BY_NPM[npm]) return WIRE_API_BY_NPM[npm];
25
- if (RESPONSES_MODEL_PREFIXES.some((prefix) => id.startsWith(prefix))) return 'responses';
26
- if (ANTHROPIC_MODEL_PREFIXES.some((prefix) => id.startsWith(prefix))) return 'messages';
27
- return 'chat';
46
+ return resolveOpenCodeGoWireRoute(model).wire;
28
47
  }
29
48
 
30
49
  export function isAnthropicGoModel(model) {
@@ -48,42 +67,8 @@ export function openCodeGoEndpointForModel(model, configuredBaseURL) {
48
67
  return `${bases.openai}/chat/completions`;
49
68
  }
50
69
 
51
- // Usage objects already converted to the inclusive convention; a converted
52
- // object passing through another normalization (nested send) stays as is,
53
- // and one source object always converts to the same object, so an abandoned
54
- // attempt and the error that later carries it stay one record.
55
- const inclusiveUsage = new WeakSet();
56
- const convertedUsage = new WeakMap();
57
-
58
- export function toInclusiveOpenCodeGoUsage(usage) {
59
- if (!usage || inclusiveUsage.has(usage)) return usage;
60
- if (convertedUsage.has(usage)) return convertedUsage.get(usage);
61
- const input = Number(usage.inputTokens) || 0;
62
- const cached = Number(usage.cachedTokens) || 0;
63
- const cacheWrite = Number(usage.cacheWriteTokens) || 0;
64
- const inclusiveInput = input + cached + cacheWrite;
65
- const converted = {
66
- ...usage,
67
- inputTokens: inclusiveInput,
68
- promptTokens: Math.max(Number(usage.promptTokens) || 0, inclusiveInput),
69
- };
70
- inclusiveUsage.add(converted);
71
- convertedUsage.set(usage, converted);
72
- return converted;
73
- }
74
-
75
- function normalizeOpenCodeGoResultUsage(result, anthropicRoute) {
76
- if (!anthropicRoute || !result?.usage) return result;
77
- return { ...result, usage: toInclusiveOpenCodeGoUsage(result.usage) };
78
- }
79
-
80
- function normalizeOpenCodeGoError(error) {
81
- if (error && typeof error === 'object') {
82
- if (error.usage) error.usage = toInclusiveOpenCodeGoUsage(error.usage);
83
- if (error.partialUsage) error.partialUsage = toInclusiveOpenCodeGoUsage(error.partialUsage);
84
- }
85
- return error;
86
- }
70
+ // The Messages route reports usage in the provider's inclusive convention.
71
+ export const toInclusiveOpenCodeGoUsage = toInclusiveUsage;
87
72
 
88
73
  function opencodeGoContextWindow(modelId, current = 0) {
89
74
  const native = Number(current);
@@ -118,11 +103,15 @@ export class OpenCodeGoProvider {
118
103
  const preset = OPENAI_COMPAT_PRESETS['opencode-go'];
119
104
  const bases = resolveOpenCodeGoBaseURLs(config.baseURL || preset.baseURL);
120
105
  this.openai = new OpenAICompatProvider('opencode-go', { ...config, baseURL: bases.openai });
121
- this.anthropic = new AnthropicProvider({
106
+ this.anthropic = new OpenCodeGoMessagesEngine({
122
107
  ...config,
123
108
  name: 'opencode-go',
124
109
  baseURL: bases.anthropic,
125
110
  disableBetaHeaders: true,
111
+ // The preset's identifying headers (User-Agent) ride the Messages wire
112
+ // too; the user's own headers win.
113
+ extraHeaders: { ...(preset.extraHeaders || {}), ...(config.extraHeaders || {}) },
114
+ modelMaxOutputTokens: (model) => this.getCachedModelInfo(model)?.outputTokens,
126
115
  });
127
116
  // The Anthropic route answers for this provider: PDFs lower to text.
128
117
  this.anthropic.nativePdf = this.nativePdf;
@@ -142,29 +131,45 @@ export class OpenCodeGoProvider {
142
131
  'x-opencode-session': sessionId,
143
132
  },
144
133
  };
145
- const wire = openCodeGoWireApi(model);
146
- if (wire === 'responses') {
147
- // OpenAI-family brands on the gateway (Muse Spark, GPT, Grok)
148
- // only answer on /responses; the compat transport switches wire
149
- // shape per request via this flag.
150
- return this.openai.send(messages, model, tools, { ...(sendOpts || {}), compatWireApi: 'responses' });
151
- }
152
- if (wire === 'messages') {
153
- // The Anthropic-style Go endpoint reports cached read/write usage
154
- // and accepts the standard message shape. Preserve the caller's
155
- // cache strategy so the shared Anthropic live-tail marker advances
156
- // through tool loops instead of forcing every request fully cold.
157
- // Abandoned attempts noted by the inner provider use the same conversion.
158
- const identity = currentUsageContext();
159
- if (identity) identity.normalizeAbandonedUsage = toInclusiveOpenCodeGoUsage;
160
- try {
161
- const result = await this.anthropic.send(messages, model, tools, sendOpts);
162
- return normalizeOpenCodeGoResultUsage(result, true);
163
- } catch (error) {
164
- throw normalizeOpenCodeGoError(error);
134
+ // The session's pinned route, else this model's route (wire-route.mjs);
135
+ // the resolved route is the only wire authority (a caller's own wire
136
+ // switches never reach an engine), and one clear "unsupported" refusal
137
+ // moves the send to the next wire once.
138
+ return sendOnRoute(this, model, tools, sendOpts, messages, async (wire, history, opts) => {
139
+ if (wire === 'responses') {
140
+ // OpenAI-family brands on the gateway (Muse Spark, GPT, Grok)
141
+ // only answer on /responses; the compat transport switches wire
142
+ // shape per request via this flag.
143
+ return this.openai.send(history, model, tools, { ...opts, compatWireApi: 'responses' });
144
+ }
145
+ if (wire === 'messages') {
146
+ // The Anthropic-style Go endpoint reports cached read/write usage
147
+ // and accepts the standard message shape. Preserve the caller's
148
+ // cache strategy so the shared Anthropic live-tail marker advances
149
+ // through tool loops instead of forcing every request fully cold.
150
+ // Abandoned attempts noted by the inner provider use the same conversion.
151
+ return withInclusiveUsage(() => this.anthropic.send(history, model, tools, opts));
165
152
  }
153
+ if (wire === 'gemini') return (await this._geminiEngine()).send(history, model, tools, opts);
154
+ return this.openai.send(history, model, tools, opts);
155
+ });
156
+ }
157
+
158
+ // The Gemini generateContent route; the Google SDK loads only when a Gemini model is used.
159
+ async _geminiEngine() {
160
+ if (!this.gemini) {
161
+ const { OpenCodeGoGeminiEngine } = await import('./opencode-go-gemini.mjs');
162
+ this.gemini = new OpenCodeGoGeminiEngine({
163
+ ...this.config,
164
+ baseURL: this.openai.baseURL,
165
+ extraHeaders: { ...(OPENAI_COMPAT_PRESETS['opencode-go'].extraHeaders || {}), ...(this.config.extraHeaders || {}) },
166
+ });
166
167
  }
167
- return this.openai.send(messages, model, tools, sendOpts);
168
+ return this.gemini;
169
+ }
170
+
171
+ resolveWireRoute(model, ctx = {}) {
172
+ return resolveOpenCodeGoWireRoute(model, { ...ctx, override: this.config?.modelWires?.[model] ?? null });
168
173
  }
169
174
 
170
175
  async listModels() {
@@ -0,0 +1,75 @@
1
+ /**
2
+ * OpenRouter: one API key, three wires. Claude (`anthropic/*`, `~anthropic/*`)
3
+ * goes through the Anthropic Messages engine at https://openrouter.ai/api (the
4
+ * SDK appends /v1/messages); OpenAI GPT / o-series (`openai/gpt-*`,
5
+ * `openai/o*`, `~openai/*`) through the OpenAI-compatible engine's Responses
6
+ * wire; openrouter/auto and every other model through Chat Completions.
7
+ * Account-level provider-routing preferences stay OpenRouter's: no request
8
+ * names a provider order.
9
+ */
10
+ import { WireGatewayProvider, messagesBaseFromOpenAIBase } from './wire-gateway.mjs';
11
+ import { OPENAI_COMPAT_PRESETS } from './openai-compat-presets.mjs';
12
+ import { openRouterReasoning } from './openai-compat-options.mjs';
13
+
14
+ /**
15
+ * The Claude id a routing slug stands for: an alias (`~anthropic/claude-opus-latest`)
16
+ * reads its catalog `alias_target`, the vendor prefix and a `:variant` suffix
17
+ * drop. Capability lookup only — the request still names the routing slug.
18
+ */
19
+ export function openRouterCapabilityModel(model, aliasTarget = null) {
20
+ return String(aliasTarget || model || '')
21
+ .replace(/^~/, '')
22
+ .replace(/^anthropic\//i, '')
23
+ .replace(/:[^/]*$/, '');
24
+ }
25
+
26
+ // Responses requests carry the same reasoning control as Chat requests
27
+ // (`openRouterReasoningEffort`, else the turn effort, else the configured
28
+ // effort; `none` disables reasoning).
29
+ function openRouterResponsesParams(config) {
30
+ return (params, { opts }) => {
31
+ const reasoning = openRouterReasoning(opts, config);
32
+ if (reasoning) params.reasoning = reasoning;
33
+ else delete params.reasoning;
34
+ };
35
+ }
36
+
37
+ // The Messages route takes the same control: the effort to send ('none' = no
38
+ // thinking), or null to keep the engine's own handling.
39
+ function openRouterMessagesEffort(config) {
40
+ return (opts) => {
41
+ const reasoning = openRouterReasoning(opts, config);
42
+ if (!reasoning) return null;
43
+ return reasoning.enabled === false ? 'none' : reasoning.effort;
44
+ };
45
+ }
46
+
47
+ /** A roster row carrying `top_provider.max_completion_tokens` as its output ceiling. */
48
+ export function withTopProviderOutputCeiling(item) {
49
+ const ceiling = Number(item?.top_provider?.max_completion_tokens);
50
+ if (!(ceiling > 0) || item.max_output_tokens !== undefined) return item;
51
+ return { ...item, max_output_tokens: ceiling };
52
+ }
53
+
54
+ export class OpenRouterProvider extends WireGatewayProvider {
55
+ constructor(config = {}) {
56
+ const baseURL = config.baseURL || OPENAI_COMPAT_PRESETS.openrouter.baseURL;
57
+ super(
58
+ 'openrouter',
59
+ config,
60
+ {
61
+ baseURL: messagesBaseFromOpenAIBase(baseURL),
62
+ authScheme: 'bearer',
63
+ // OpenRouter Messages takes PDFs natively as document blocks.
64
+ nativePdf: true,
65
+ messagesEffort: openRouterMessagesEffort(config),
66
+ capabilityModel: (model) => openRouterCapabilityModel(model, this.getCachedModelInfo(model)?.aliasTarget),
67
+ },
68
+ { responsesParamsHook: openRouterResponsesParams(config) }
69
+ );
70
+ // The roster's output ceiling is `top_provider.max_completion_tokens`.
71
+ const fetchItems = this.openai._fetchModelItems.bind(this.openai);
72
+ this.openai._fetchModelItems = async (options) =>
73
+ (await fetchItems(options)).map(withTopProviderOutputCeiling);
74
+ }
75
+ }