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.
- package/README.md +18 -0
- package/package.json +2 -1
- package/scripts/gate-local.mjs +19 -3
- package/scripts/model-catalog-audit.mjs +1 -15
- package/scripts/provider-pingpong-live.mjs +509 -0
- package/src/agents/advisor/AGENT.md +1 -1
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/reviewer/AGENT.md +3 -3
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +6 -0
- package/src/defaults/skills/setup/SKILL.md +6 -1
- package/src/defaults/skills/setup/references/actions.md +44 -22
- package/src/defaults/skills/setup/references/surfaces.md +10 -8
- package/src/headless-exec.mjs +15 -8
- package/src/lib/keychain-cjs.cjs +7 -4
- package/src/output-styles/common.md +11 -10
- package/src/repl/slash-commands.mjs +16 -1
- package/src/rules/agent/AGENT.md +5 -5
- package/src/rules/lead/LEAD.md +5 -5
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -4
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +10 -0
- package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
- package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
- package/src/runtime/agent/orchestrator/config.mjs +5 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +36 -7
- package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +49 -10
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +40 -3
- package/src/runtime/agent/orchestrator/mcp/client.mjs +230 -96
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +103 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +150 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +111 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +87 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +95 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-request.mjs +122 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +9 -0
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +229 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +188 -29
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +94 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +98 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-fast-mode.mjs +39 -18
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +55 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +48 -37
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +10 -7
- package/src/runtime/agent/orchestrator/providers/anthropic-midstream-recovery.mjs +18 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +13 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-midstream.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-recovery.mjs +23 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +46 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request.mjs +14 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +102 -45
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +69 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-server-fallback.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +40 -7
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +30 -9
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +88 -21
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +30 -10
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +106 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +10 -61
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +94 -15
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +117 -72
- package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +75 -10
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-guards.mjs +97 -2
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +103 -23
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +43 -2
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +103 -33
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +32 -6
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +27 -3
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +64 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +70 -6
- package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
- package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
- package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +80 -18
- package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +46 -8
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +273 -0
- package/src/runtime/agent/orchestrator/providers/gemini-family.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/gemini-history-signatures.mjs +9 -4
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +180 -0
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +369 -112
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +140 -35
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +70 -24
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +80 -29
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +69 -19
- package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +246 -42
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
- package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +388 -0
- package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
- package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
- package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +48 -22
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +119 -18
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +33 -1
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +4 -9
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +123 -61
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +27 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +37 -7
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +50 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +47 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
- package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +151 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +64 -23
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +79 -33
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +172 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +144 -15
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +193 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +66 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +109 -26
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +27 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +34 -20
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +23 -4
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +37 -28
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +274 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +72 -32
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +43 -15
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-stamps.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +7 -3
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +1 -3
- package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +37 -4
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +12 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +22 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +12 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +76 -33
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +44 -16
- package/src/runtime/agent/orchestrator/providers/openai-retry-policy.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -16
- package/src/runtime/agent/orchestrator/providers/openai-ws-handshake.mjs +16 -8
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -35
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/policy.mjs +25 -14
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
- package/src/runtime/agent/orchestrator/providers/openai-ws-terminal.mjs +18 -11
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +41 -22
- package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +170 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +75 -70
- package/src/runtime/agent/orchestrator/providers/openrouter.mjs +75 -0
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +720 -0
- package/src/runtime/agent/orchestrator/providers/registry.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/retry-backoff.mjs +46 -7
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +123 -219
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +148 -45
- package/src/runtime/agent/orchestrator/providers/retry-midstream.mjs +81 -16
- package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
- package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
- package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +157 -0
- package/src/runtime/agent/orchestrator/providers/wire-route.mjs +512 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +183 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +100 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +21 -0
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
- package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +0 -18
- package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +57 -28
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +19 -16
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +1 -97
- package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
- package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +14 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +176 -71
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +62 -10
- package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +14 -93
- package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +120 -0
- package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
- package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +91 -1
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
- package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +21 -10
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +132 -0
- package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +30 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +67 -20
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +104 -19
- package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +150 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +7 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +30 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +57 -21
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +5 -10
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +208 -14
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +16 -4
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +25 -3
- package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +19 -2
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +18 -7
- package/src/runtime/agent/orchestrator/session/manager.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +168 -29
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/side-question.mjs +192 -0
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +17 -3
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +58 -2
- package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +41 -28
- package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +12 -1
- package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/store/write-guards.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +22 -10
- package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/store.mjs +19 -3
- package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +77 -0
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +20 -1
- package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +12 -15
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +5 -5
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +14 -10
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +49 -34
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
- package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
- package/src/runtime/computer-bridge/action-schema.mjs +44 -21
- package/src/runtime/github/tool.mjs +92 -2
- package/src/runtime/memory/index.mjs +1 -0
- package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
- package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
- package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
- package/src/runtime/memory/lib/pg/process.mjs +65 -50
- package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
- package/src/runtime/memory/lib/pg/supervisor.mjs +124 -16
- package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
- package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
- package/src/runtime/office/README.md +2 -2
- package/src/runtime/office/authoring/html-document-author.mjs +2 -0
- package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-measure.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +2 -0
- package/src/runtime/office/core/office-actions-read.mjs +3 -0
- package/src/runtime/office/core/office-render-preview.mjs +2 -0
- package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
- package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
- package/src/runtime/office/core/office-sessions.mjs +5 -0
- package/src/runtime/office/core/office-transactions.mjs +3 -0
- package/src/runtime/office/core/office-write-ledger.mjs +98 -0
- package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
- package/src/runtime/office/index.mjs +30 -0
- package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
- package/src/runtime/office/pdf/pdf-render.mjs +23 -7
- package/src/runtime/office/pdf/pdf-security.mjs +2 -0
- package/src/runtime/office/portable/portable-opc.mjs +4 -1
- package/src/runtime/office/quality/visual-diff.mjs +2 -0
- package/src/runtime/office/shared/values.mjs +0 -5
- package/src/runtime/shared/background-tasks.mjs +92 -14
- package/src/runtime/shared/bounded-file-read.mjs +13 -0
- package/src/runtime/shared/bounded-line-diff.mjs +182 -0
- package/src/runtime/shared/buffered-appender.mjs +18 -0
- package/src/runtime/shared/config.mjs +78 -18
- package/src/runtime/shared/err-text.mjs +31 -0
- package/src/runtime/shared/error-presentation.mjs +159 -19
- package/src/runtime/shared/file-permissions.d.mts +6 -1
- package/src/runtime/shared/file-permissions.mjs +54 -6
- package/src/runtime/shared/llm/anthropic-betas.mjs +4 -3
- package/src/runtime/shared/llm/anthropic-effort.mjs +129 -134
- package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +50 -14
- package/src/runtime/shared/llm/model-catalog.mjs +53 -40
- package/src/runtime/shared/llm/openai-daybreak.mjs +4 -16
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +11 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +13 -4
- package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
- package/src/runtime/shared/llm/usage-rollup.mjs +0 -1
- package/src/runtime/shared/loopback-listener.mjs +9 -0
- package/src/runtime/shared/model-display.mjs +13 -0
- package/src/runtime/shared/provider-api-key.mjs +2 -0
- package/src/runtime/shared/quota-resume-store.mjs +11 -0
- package/src/runtime/shared/review-diff.mjs +52 -0
- package/src/runtime/shared/session-baseline-store.mjs +960 -0
- package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
- package/src/runtime/shared/session-sidebar-host.mjs +38 -0
- package/src/runtime/shared/slow-span.mjs +114 -0
- package/src/runtime/shared/statusline/statusline-format.mjs +4 -4
- package/src/runtime/shared/statusline/statusline-segments.mjs +28 -4
- package/src/runtime/shared/task-notification-envelope.mjs +2 -2
- package/src/runtime/shared/tool-card-model/card-header.mjs +6 -1
- package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
- package/src/runtime/shared/tool-card-model.mjs +5 -2
- package/src/runtime/shared/tool-output-limit.mjs +4 -0
- package/src/runtime/shared/tool-primitives.mjs +13 -0
- package/src/runtime/shared/tool-result-summary.mjs +8 -1
- package/src/runtime/shared/tool-surface.mjs +18 -3
- package/src/runtime/shared/tool-work-units.mjs +40 -4
- package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
- package/src/runtime/shared/transcript-writer.mjs +10 -2
- package/src/runtime/shared/turn-changes.mjs +670 -274
- package/src/runtime/shared/turn-review-reply.mjs +8 -39
- package/src/runtime/shared/turn-snapshot-store.mjs +94 -2
- package/src/runtime/shared/turn-snapshot.mjs +986 -690
- package/src/runtime/shared/turn-worktree-snapshot.mjs +279 -262
- package/src/runtime/shared/user-data-guard.mjs +262 -49
- package/src/runtime/shared/worktrees/carry.mjs +531 -0
- package/src/runtime/shared/worktrees/contract.mjs +34 -24
- package/src/runtime/shared/worktrees/file-recovery.mjs +68 -0
- package/src/runtime/shared/worktrees/git-head.mjs +205 -0
- package/src/runtime/shared/worktrees/git.mjs +8 -3
- package/src/runtime/shared/worktrees/maintenance.mjs +1 -1
- package/src/runtime/shared/worktrees/manager.mjs +156 -8
- package/src/runtime/shared/worktrees/merge.mjs +31 -21
- package/src/runtime/shared/worktrees/paths.d.mts +6 -0
- package/src/runtime/shared/worktrees/test-support.mjs +19 -4
- package/src/runtime/terminal-bridge/client.mjs +44 -11
- package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
- package/src/runtime/tidy/apply.mjs +47 -2
- package/src/runtime/tidy/run-engines.mjs +11 -5
- package/src/session-runtime/agent-tool-routing.mjs +19 -13
- package/src/session-runtime/boot/apis.mjs +19 -5
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/infrastructure.mjs +12 -1
- package/src/session-runtime/boot/session.mjs +0 -1
- package/src/session-runtime/boot/tools.mjs +4 -1
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +65 -0
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +11 -4
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +115 -18
- package/src/session-runtime/internal-tool-executor.mjs +6 -2
- package/src/session-runtime/lifecycle/cold-heir.mjs +188 -0
- package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
- package/src/session-runtime/lifecycle/session-catalog.mjs +14 -3
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +29 -6
- package/src/session-runtime/lifecycle/teardown.mjs +73 -8
- package/src/session-runtime/lifecycle-api.mjs +1 -0
- package/src/session-runtime/mcp-glue/connect.mjs +46 -14
- package/src/session-runtime/mcp-glue/server-catalog.mjs +20 -3
- package/src/session-runtime/mcp-glue.mjs +3 -0
- package/src/session-runtime/mcp-oauth-login.mjs +174 -0
- package/src/session-runtime/model-route/model-switch-target.mjs +34 -0
- package/src/session-runtime/model-route/set-route.mjs +85 -17
- package/src/session-runtime/model-route/web-search-route.mjs +1 -1
- package/src/session-runtime/native-web-search/routes.mjs +22 -3
- package/src/session-runtime/native-web-search-usage.mjs +51 -0
- package/src/session-runtime/native-web-search.mjs +10 -1
- package/src/session-runtime/new-session-config.mjs +4 -2
- package/src/session-runtime/provider-auth/login.mjs +4 -0
- package/src/session-runtime/provider-models/model-meta.mjs +12 -3
- package/src/session-runtime/quick-model-rows/web-search-rows.mjs +13 -8
- package/src/session-runtime/quick-web-search-models.mjs +13 -38
- package/src/session-runtime/resource-extension-sync.mjs +4 -0
- package/src/session-runtime/resource-mcp-api.mjs +98 -2
- package/src/session-runtime/resource-scope-decorate.mjs +10 -3
- package/src/session-runtime/runtime-review-api.mjs +21 -2
- package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
- package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +13 -1
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +7 -2
- package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
- package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +73 -7
- package/src/session-runtime/services/agent-tool/send-flow.mjs +22 -4
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +2 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +22 -5
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +15 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +8 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -2
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
- package/src/session-runtime/services/agent-tool/worker-index.mjs +46 -7
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +17 -0
- package/src/session-runtime/services/agent-tool.mjs +3 -0
- package/src/session-runtime/services/channel-admin.mjs +19 -3
- package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
- package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
- package/src/session-runtime/services/provider-admin.mjs +81 -15
- package/src/session-runtime/session-transcript-purge.mjs +32 -0
- package/src/session-runtime/session-turn-api.mjs +14 -5
- package/src/session-runtime/settings-builtin-tools-api.mjs +9 -0
- package/src/session-runtime/settings-compaction-api.mjs +1 -0
- package/src/session-runtime/setup-tool/executor.mjs +36 -6
- package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
- package/src/session-runtime/setup-tool/settings-contract.mjs +13 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +13 -4
- package/src/session-runtime/skills-api.mjs +3 -5
- package/src/session-runtime/tool-surface.mjs +5 -1
- package/src/session-runtime/turn/compaction-gate.mjs +25 -0
- package/src/session-runtime/turn/session-ops.mjs +7 -5
- package/src/session-runtime/turn/side-question-ops.mjs +22 -0
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +5 -1
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +8 -3
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +10 -0
- package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
- package/src/session-runtime/turn/turn-run.mjs +25 -9
- package/src/session-runtime/usage-stats-api.mjs +43 -11
- package/src/session-runtime/workspace/project-branches.mjs +7 -5
- package/src/session-runtime/workspace/transition-steps.mjs +129 -31
- package/src/session-runtime/workspace/transitions.mjs +190 -15
- package/src/standalone/daemon-agent-control.mjs +9 -1
- package/src/standalone/daemon-drain-policy.mjs +8 -0
- package/src/standalone/daemon-local-session-bridge.mjs +14 -1
- package/src/standalone/daemon-owner.mjs +17 -4
- package/src/standalone/daemon-pg-stop.mjs +51 -0
- package/src/standalone/daemon-stop-budget.d.mts +2 -0
- package/src/standalone/daemon-stop-budget.mjs +18 -0
- package/src/standalone/daemon-stored-session-views.mjs +2 -0
- package/src/standalone/daemon-telemetry.mjs +74 -0
- package/src/standalone/daemon.mjs +64 -8
- package/src/standalone/desktop-service-registry.mjs +5 -0
- package/src/standalone/local-session-runtime.mjs +70 -19
- package/src/standalone/session-client.mjs +42 -0
- package/src/standalone/session-protocol.mjs +14 -0
- package/src/standalone/session-proxy/projection.mjs +41 -4
- package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
- package/src/standalone/session-runtime-inline-host.mjs +1 -0
- package/src/standalone/session-service/agent-tree/agent-cancel.mjs +33 -2
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +26 -10
- package/src/standalone/session-service/agent-tree.mjs +12 -0
- package/src/standalone/session-service/quota-resume.mjs +8 -0
- package/src/standalone/session-service/retention/busy.mjs +15 -1
- package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
- package/src/standalone/session-service-api.mjs +11 -1
- package/src/standalone/session-service.mjs +1 -0
- package/src/standalone/session-state-patch.d.mts +2 -1
- package/src/standalone/session-state-patch.mjs +41 -1
- package/src/tui/App.jsx +25 -0
- package/src/tui/app/app-view/floating-panel.jsx +26 -1
- package/src/tui/app/app-view.jsx +1 -0
- package/src/tui/app/btw-controller.mjs +118 -0
- package/src/tui/app/create-app-pickers.mjs +6 -0
- package/src/tui/app/extension-pickers/mcp-login.mjs +107 -0
- package/src/tui/app/extension-pickers/mcp-servers-picker.mjs +2 -1
- package/src/tui/app/extension-pickers.mjs +2 -1
- package/src/tui/app/model-options.mjs +11 -16
- package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
- package/src/tui/app/shell-layout/surfaces.mjs +3 -1
- package/src/tui/app/slash-commands.mjs +20 -5
- package/src/tui/app/slash-dispatch/panel-commands.mjs +16 -1
- package/src/tui/app/slash-dispatch/session-commands.mjs +19 -6
- package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
- package/src/tui/app/use-global-key-input.mjs +5 -12
- package/src/tui/app/use-prompt-handlers.mjs +11 -0
- package/src/tui/components/BtwPanel.jsx +53 -0
- package/src/tui/components/QuestionPanel.jsx +275 -0
- package/src/tui/components/StatusLine.jsx +2 -0
- package/src/tui/components/question-panel-model.mjs +156 -0
- package/src/tui/components/status-line/local-line.mjs +5 -2
- package/src/tui/components/status-line/use-statusline-text.mjs +7 -1
- package/src/tui/dist/index.mjs +3221 -1500
- package/src/tui/session/context-state.mjs +4 -2
- package/src/tui/session/quota-resume.mjs +46 -14
- package/src/tui/session/session-api/commands.mjs +43 -24
- package/src/tui/session/session-api/controls.mjs +2 -2
- package/src/tui/session/session-api/extensions.mjs +22 -0
- package/src/tui/session/session-api/integrations.mjs +16 -2
- package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
- package/src/tui/session/session-api/lifecycle.mjs +7 -2
- package/src/tui/session/session-api/routes.mjs +71 -7
- package/src/tui/session/session-api/settings.mjs +11 -14
- package/src/tui/session/session-api.mjs +1 -0
- package/src/tui/session/session-flow/drain.mjs +7 -1
- package/src/tui/session/session-flow/failed-turn-rewind.mjs +10 -4
- package/src/tui/session/tool-approval.mjs +10 -7
- package/src/tui/session/transcript-spill.mjs +14 -7
- package/src/tui/session/turn-stream.mjs +174 -31
- package/src/tui/session/turn.mjs +46 -16
- package/src/tui/statusline-ansi-bridge.mjs +1 -1
- package/src/ui/statusline-agents.mjs +15 -4
- package/src/ui/statusline.mjs +7 -3
- package/src/ui/streaming-markdown-heal.mjs +34 -3
- package/src/vendor/statusline/src/gateway/claude-current.mjs +14 -4
- package/src/workflows/default/WORKFLOW.md +3 -1
- package/src/runtime/memory/lib/memory-session-merge.mjs +0 -32
- package/src/runtime/shared/llm/usage-session-history.mjs +0 -266
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wire-route.mjs — which wire a gateway model is reached on.
|
|
3
|
+
*
|
|
4
|
+
* A gateway that speaks several wires (OpenRouter, OpenCode Go, Command Code,
|
|
5
|
+
* DeepSeek) sends each model over its brand-native or best-supported wire:
|
|
6
|
+
* 'messages' (Anthropic Messages), 'responses' (OpenAI Responses), 'chat'
|
|
7
|
+
* (Chat Completions) or 'gemini' (generateContent). One answer per
|
|
8
|
+
* provider+model, in this order:
|
|
9
|
+
*
|
|
10
|
+
* 1. an explicit per-model user override (provider config `modelWires`),
|
|
11
|
+
* 2. catalog / endpoint metadata (models.dev SDK package, the roster's
|
|
12
|
+
* advertised endpoints),
|
|
13
|
+
* 3. the provider's model-family table,
|
|
14
|
+
* 4. the provider default.
|
|
15
|
+
*
|
|
16
|
+
* Every tier is limited to the wires the gateway actually serves for that
|
|
17
|
+
* model (`offered`, narrowed by advertised endpoints), so no tier can guess an
|
|
18
|
+
* endpoint the gateway does not offer.
|
|
19
|
+
*
|
|
20
|
+
* A session pins its answer (`session.wireRoute`) before its first request,
|
|
21
|
+
* so the tool snapshot, history lowering, request serialization and usage
|
|
22
|
+
* normalization of every later turn follow the same wire; an existing session
|
|
23
|
+
* keeps the wire it started on even after this table changes.
|
|
24
|
+
*
|
|
25
|
+
* `nativeDeferredTools` marks, per wire, whether the gateway is verified to
|
|
26
|
+
* carry provider-native deferred tools (defer_loading + tool_reference on
|
|
27
|
+
* Messages, tool_search output on Responses). It is OFF for every gateway
|
|
28
|
+
* until verified live. A route pinned before its session's first request
|
|
29
|
+
* records the flag (`nativeDeferredTools: true`); the session's tool surface
|
|
30
|
+
* follows that record, so flipping a flag later only affects new sessions.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
export const WIRES = Object.freeze(['messages', 'responses', 'chat', 'gemini']);
|
|
34
|
+
|
|
35
|
+
const GO_RESPONSES = /^(?:muse-spark-|gpt-|grok-)/i;
|
|
36
|
+
const GO_MESSAGES = /^(?:minimax-|qwen|claude-)/i;
|
|
37
|
+
const GO_GEMINI = /^gemini-/i;
|
|
38
|
+
// Before Claude joined the cold-catalog Messages prefixes.
|
|
39
|
+
const GO_MESSAGES_BEFORE_CLAUDE = /^(?:minimax-|qwen)/i;
|
|
40
|
+
|
|
41
|
+
// Unverified: no gateway wire carries native deferred tools yet.
|
|
42
|
+
const nativeDeferredOff = () => ({ messages: false, responses: false });
|
|
43
|
+
|
|
44
|
+
export const PROFILES = Object.freeze({
|
|
45
|
+
// OpenRouter serves every model on /chat/completions, /responses and
|
|
46
|
+
// /messages; Claude is native on Messages, OpenAI GPT/o-series on Responses.
|
|
47
|
+
openrouter: {
|
|
48
|
+
offered: ['chat', 'messages', 'responses'],
|
|
49
|
+
nativeDeferredTools: nativeDeferredOff(),
|
|
50
|
+
families: [
|
|
51
|
+
{ match: /^~?anthropic\//i, wire: 'messages' },
|
|
52
|
+
{ match: /^(?:openai\/(?:gpt-|o\d)|~openai\/)/i, wire: 'responses' },
|
|
53
|
+
],
|
|
54
|
+
defaultWire: 'chat',
|
|
55
|
+
legacy: () => 'chat',
|
|
56
|
+
},
|
|
57
|
+
// OpenCode Go answers each brand on one wire (models.dev names it per model;
|
|
58
|
+
// the prefixes are the cold-catalog fallback): Gemini on its generateContent
|
|
59
|
+
// endpoint, Claude / MiniMax / Qwen on Messages, GPT / Grok / Muse on
|
|
60
|
+
// Responses, the rest on Chat.
|
|
61
|
+
'opencode-go': {
|
|
62
|
+
offered: ['chat', 'responses', 'messages', 'gemini'],
|
|
63
|
+
nativeDeferredTools: nativeDeferredOff(),
|
|
64
|
+
families: [
|
|
65
|
+
{ match: GO_RESPONSES, wire: 'responses' },
|
|
66
|
+
{ match: GO_MESSAGES, wire: 'messages' },
|
|
67
|
+
{ match: GO_GEMINI, wire: 'gemini' },
|
|
68
|
+
],
|
|
69
|
+
defaultWire: 'chat',
|
|
70
|
+
// Sessions created before the Gemini wire existed sent Gemini models to Chat.
|
|
71
|
+
legacy: ({ model, catalogWire }) => {
|
|
72
|
+
if (catalogWire && catalogWire !== 'gemini') return catalogWire;
|
|
73
|
+
if (GO_RESPONSES.test(model)) return 'responses';
|
|
74
|
+
return GO_MESSAGES_BEFORE_CLAUDE.test(model) ? 'messages' : 'chat';
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
// Command Code declares per-model endpoints: GPT / Muse / Grok prefer
|
|
78
|
+
// Responses when advertised, otherwise Chat, Messages when it is the only
|
|
79
|
+
// wire, and a Responses-only model stays reachable.
|
|
80
|
+
'command-code-oauth': {
|
|
81
|
+
offered: ['chat', 'messages', 'responses'],
|
|
82
|
+
nativeDeferredTools: nativeDeferredOff(),
|
|
83
|
+
families: [
|
|
84
|
+
{ match: /(?:^|\/)(?:gpt-|muse-|grok-)/i, wire: 'responses' },
|
|
85
|
+
// Claude answers on /messages only: it keeps that wire even when the
|
|
86
|
+
// roster cannot be read (the other families wait for the roster).
|
|
87
|
+
{ match: /(?:^|\/)claude-/i, wire: 'messages', cold: true },
|
|
88
|
+
],
|
|
89
|
+
defaultWire: 'chat',
|
|
90
|
+
preference: ['chat', 'messages', 'responses'],
|
|
91
|
+
legacy: ({ endpoints }) => (endpoints.includes('chat') || !endpoints.includes('messages') ? 'chat' : 'messages'),
|
|
92
|
+
},
|
|
93
|
+
// DeepSeek's Anthropic endpoint carries thinking + tool blocks for agent/tool
|
|
94
|
+
// sessions; Chat stays the wire for tool-less one-shot requests. It has no
|
|
95
|
+
// Responses endpoint.
|
|
96
|
+
deepseek: {
|
|
97
|
+
offered: ['chat', 'messages'],
|
|
98
|
+
nativeDeferredTools: nativeDeferredOff(),
|
|
99
|
+
families: [{ match: /^deepseek-/i, wire: 'messages', agentOnly: true }],
|
|
100
|
+
defaultWire: 'chat',
|
|
101
|
+
legacy: () => 'chat',
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// User-defined providers (`custom-<uuid>`): one profile per configured
|
|
106
|
+
// provider, registered when the provider is built (customWireProfile).
|
|
107
|
+
const CUSTOM_PROFILES = new Map();
|
|
108
|
+
|
|
109
|
+
function profileOf(provider) {
|
|
110
|
+
const name = String(provider || '');
|
|
111
|
+
return Object.hasOwn(PROFILES, name) ? PROFILES[name] : CUSTOM_PROFILES.get(name) || null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* The profile of a user-defined OpenAI-compatible provider: the wires its
|
|
116
|
+
* endpoint is declared to serve (`wires`, default the protocol's own wire),
|
|
117
|
+
* the protocol's wire as default and as the wire every existing session
|
|
118
|
+
* started on. No model-family table: only the per-model `modelWires`
|
|
119
|
+
* override picks another wire.
|
|
120
|
+
*/
|
|
121
|
+
export function customWireProfile({ protocolWire, wires = null }) {
|
|
122
|
+
const offered = Array.isArray(wires) && wires.length ? [...wires] : [protocolWire];
|
|
123
|
+
return {
|
|
124
|
+
offered,
|
|
125
|
+
nativeDeferredTools: nativeDeferredOff(),
|
|
126
|
+
families: [],
|
|
127
|
+
defaultWire: protocolWire,
|
|
128
|
+
legacy: () => protocolWire,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Register (or replace) the profile of user-defined provider `provider`. */
|
|
133
|
+
export function registerWireProfile(provider, profile) {
|
|
134
|
+
CUSTOM_PROFILES.set(String(provider || ''), profile);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Whether `provider` routes models through this table. */
|
|
138
|
+
export function hasWireProfile(provider) {
|
|
139
|
+
return profileOf(provider) !== null;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Whether `provider` serves `wire` at all. */
|
|
143
|
+
export function providerOffersWire(provider, wire) {
|
|
144
|
+
return Boolean(profileOf(provider)?.offered.includes(wire));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Whether `provider`'s `wire` is verified to carry native deferred tools. */
|
|
148
|
+
export function wireSupportsNativeDeferredTools(provider, wire) {
|
|
149
|
+
return profileOf(provider)?.nativeDeferredTools?.[wire] === true;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const NATIVE_DEFERRED_FAMILY = Object.freeze({ messages: 'anthropic', responses: 'openai' });
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* The native deferred-tool family ('anthropic' | 'openai') a pinned route
|
|
156
|
+
* gives `provider`, or '' — a route for another provider, one pinned without
|
|
157
|
+
* verified support, or a wire with no native contract (Chat, Gemini).
|
|
158
|
+
*/
|
|
159
|
+
export function nativeDeferredFamilyForRoute(provider, route) {
|
|
160
|
+
if (!route || route.nativeDeferredTools !== true) return '';
|
|
161
|
+
const name = String(provider || '')
|
|
162
|
+
.trim()
|
|
163
|
+
.toLowerCase();
|
|
164
|
+
if (!name || String(route.provider || '').toLowerCase() !== name) return '';
|
|
165
|
+
return NATIVE_DEFERRED_FAMILY[route.wire] || '';
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @param {string} provider
|
|
170
|
+
* @param {string} model the routing id (an alias slug stays the alias)
|
|
171
|
+
* @param {object} [ctx]
|
|
172
|
+
* @param {string|null} [ctx.override] the user's per-model wire
|
|
173
|
+
* @param {string|null} [ctx.catalogWire] the catalog's wire for this model
|
|
174
|
+
* @param {string[]|null} [ctx.endpoints] the wires the gateway advertises for this model
|
|
175
|
+
* @param {boolean} [ctx.known] false when no metadata describes the model at all
|
|
176
|
+
* @param {boolean} [ctx.agent] an agent/tool session (or a send carrying tools)
|
|
177
|
+
* @param {boolean} [ctx.legacy] the wire an existing session started on before this table
|
|
178
|
+
* @param {string[]} [ctx.exclude] wires that must not be chosen (the one a send was just refused on)
|
|
179
|
+
* @returns {{ wire: string, profileId: string, source: string }|null} null for a
|
|
180
|
+
* provider without a profile, or a model no offered wire serves
|
|
181
|
+
*/
|
|
182
|
+
export function resolveWireRoute(
|
|
183
|
+
provider,
|
|
184
|
+
model,
|
|
185
|
+
{
|
|
186
|
+
override = null,
|
|
187
|
+
catalogWire = null,
|
|
188
|
+
endpoints = null,
|
|
189
|
+
known = true,
|
|
190
|
+
agent = false,
|
|
191
|
+
legacy = false,
|
|
192
|
+
keep = null,
|
|
193
|
+
exclude = [],
|
|
194
|
+
} = {}
|
|
195
|
+
) {
|
|
196
|
+
const profile = profileOf(provider);
|
|
197
|
+
if (!profile) return null;
|
|
198
|
+
const id = String(model || '');
|
|
199
|
+
const route = (wire, source) => ({ wire, profileId: `${provider}:${wire}`, source });
|
|
200
|
+
const advertised = (
|
|
201
|
+
Array.isArray(endpoints) ? profile.offered.filter((wire) => endpoints.includes(wire)) : profile.offered
|
|
202
|
+
).filter((wire) => !exclude.includes(wire));
|
|
203
|
+
const usable = (wire) => advertised.includes(wire);
|
|
204
|
+
// A wire the session already pinned stays while the model is still offered
|
|
205
|
+
// on it (a model nothing describes keeps its pin: no metadata, no change).
|
|
206
|
+
if (keep && (known === false ? profile.offered : advertised).includes(keep)) return route(keep, 'pinned');
|
|
207
|
+
// Nothing describes this model (no roster row, no cached row): the
|
|
208
|
+
// gateway's conventional wire, flagged so a session never pins the guess.
|
|
209
|
+
// A model with no advertised wire at all is not routable.
|
|
210
|
+
const unknown = () => {
|
|
211
|
+
// A family that is certain without metadata (`cold`: Claude on Command
|
|
212
|
+
// Code answers on Messages only) outranks the conventional wire.
|
|
213
|
+
const cold = profile.families.find((rule) => rule.cold === true && rule.match.test(id) && usable(rule.wire));
|
|
214
|
+
const wire =
|
|
215
|
+
cold?.wire ||
|
|
216
|
+
(usable(profile.defaultWire) ? profile.defaultWire : (profile.preference || profile.offered).find(usable));
|
|
217
|
+
return wire ? route(wire, 'unknown') : null;
|
|
218
|
+
};
|
|
219
|
+
if (legacy) {
|
|
220
|
+
if (known === false) return unknown();
|
|
221
|
+
// The wire a pre-table session started on, while the model still offers
|
|
222
|
+
// it; otherwise the fresh resolution below (never an unadvertised wire).
|
|
223
|
+
const legacyWire = profile.legacy({ model: id, catalogWire: usable(catalogWire) ? catalogWire : null, endpoints: advertised });
|
|
224
|
+
if (usable(legacyWire)) return route(legacyWire, 'legacy');
|
|
225
|
+
}
|
|
226
|
+
if (override && usable(override)) return route(override, 'override');
|
|
227
|
+
if (known === false) return unknown();
|
|
228
|
+
if (catalogWire && usable(catalogWire)) return route(catalogWire, 'catalog');
|
|
229
|
+
if (Array.isArray(endpoints) && advertised.length === 1) return route(advertised[0], 'endpoints');
|
|
230
|
+
const family = profile.families.find(
|
|
231
|
+
(rule) => rule.match.test(id) && (rule.agentOnly !== true || agent) && usable(rule.wire)
|
|
232
|
+
);
|
|
233
|
+
if (family) return route(family.wire, 'family');
|
|
234
|
+
if (usable(profile.defaultWire)) return route(profile.defaultWire, 'default');
|
|
235
|
+
const preferred = (profile.preference || profile.offered).find(usable);
|
|
236
|
+
return preferred ? route(preferred, 'endpoints') : null;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* The route one send uses: the session's pinned route when it names this
|
|
241
|
+
* provider and model, else a fresh resolution (a send carrying tools counts as
|
|
242
|
+
* an agent/tool request). Resolved before the request is built, so lowering,
|
|
243
|
+
* serialization and usage normalization all follow one answer.
|
|
244
|
+
*/
|
|
245
|
+
export async function sendWireRoute(provider, model, tools, sendOpts, messages = null) {
|
|
246
|
+
const route = await resolveSendRoute(provider, model, tools, sendOpts, messages);
|
|
247
|
+
// A provider with a wire table that offers the model nowhere: nothing is sent.
|
|
248
|
+
if (!route && hasWireProfile(provider.name)) throw modelNotRoutableError(provider.name, model);
|
|
249
|
+
return route;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Status codes a gateway answers when it does not serve the model on the wire
|
|
253
|
+
// asked: 405 / 501 name the endpoint itself; 400 / 404 / 415 / 422 count only
|
|
254
|
+
// when the body also says the endpoint or route is unsupported. Auth (401,
|
|
255
|
+
// 403), quota / billing (402, 429) and server errors never qualify.
|
|
256
|
+
const ENDPOINT_STATUSES = new Set([405, 501]);
|
|
257
|
+
const REJECTION_STATUSES = new Set([400, 404, 415, 422]);
|
|
258
|
+
const ENDPOINT_WORDS = /\b(?:endpoints?|routes?)\b|\/(?:v1\/)?(?:messages|responses|chat\/completions)\b|chat completions/i;
|
|
259
|
+
const UNSUPPORTED_WORDS =
|
|
260
|
+
/\bunsupported\b|not (?:be )?(?:supported|available|served|implemented)|(?:does not|doesn't|do not|don't) (?:support|serve)|only (?:available|supported|served)|wrong endpoint|use (?:the )?\/?(?:v1\/)?(?:messages|responses|chat\/completions)\b/i;
|
|
261
|
+
// A typed code / type that names an auth, quota, billing or parameter failure
|
|
262
|
+
// is never a wire rejection, whatever its message says about endpoints.
|
|
263
|
+
const NON_WIRE_ERROR_TYPE =
|
|
264
|
+
/auth|permission|forbidden|api_?key|token|quota|billing|credit|balance|payment|insufficient|rate_?limit|too_many|overload|capacity|(?:unsupported|unknown|unrecognized|invalid)_?(?:parameter|param|field|argument|value)|invalid_?(?:request_)?param|context_?length|max_?tokens/i;
|
|
265
|
+
// The same families in message wording.
|
|
266
|
+
const NON_WIRE_ERROR_TEXT =
|
|
267
|
+
/\b(?:unsupported|unknown|unrecognized|unexpected|invalid|extra|not permitted|not allowed)\s+(?:request\s+)?(?:parameters?|params?|fields?|arguments?|propert(?:y|ies)|options?|values?|keys?)\b|\bparameters?\b[^.]{0,40}\b(?:not supported|unsupported|not allowed)|\bquota\b|\bbilling\b|\bcredits?\b|\bbalance\b|\binsufficient\b|rate[ -]?limit|too many requests|unauthori[sz]ed|\bforbidden\b|invalid api key|api key|\bpayment\b|\bsubscription\b/i;
|
|
268
|
+
|
|
269
|
+
const errorTypes = (error) =>
|
|
270
|
+
[
|
|
271
|
+
error.code,
|
|
272
|
+
error.type,
|
|
273
|
+
error.providerErrorCode,
|
|
274
|
+
error.providerErrorType,
|
|
275
|
+
error.error?.code,
|
|
276
|
+
error.error?.type,
|
|
277
|
+
error.providerError?.code,
|
|
278
|
+
error.providerError?.type,
|
|
279
|
+
].filter((part) => typeof part === 'string');
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Whether `error` is a clear "this model is not served on this wire"
|
|
283
|
+
* rejection — the only failure a send may answer by switching wire. Typed
|
|
284
|
+
* HTTP evidence only; an aborted, stalled or already-streaming failure
|
|
285
|
+
* (anything that exposed output) never qualifies.
|
|
286
|
+
*/
|
|
287
|
+
export function isWireUnsupportedError(error) {
|
|
288
|
+
if (!error || typeof error !== 'object') return false;
|
|
289
|
+
if (error.liveTextEmitted === true || error.emittedToolCall === true || error.unsafeToRetry === true) return false;
|
|
290
|
+
if (error.streamStalled === true || error.name === 'AbortError') return false;
|
|
291
|
+
if (error.quotaExhausted === true || error.reauthRequired === true) return false;
|
|
292
|
+
// A body that points at one request field (`param`) is a parameter error.
|
|
293
|
+
if (typeof error.param === 'string' || typeof error.error?.param === 'string') return false;
|
|
294
|
+
if (errorTypes(error).some((type) => NON_WIRE_ERROR_TYPE.test(type))) return false;
|
|
295
|
+
const status = Number(error.status ?? error.httpStatus ?? error.statusCode ?? error.response?.status);
|
|
296
|
+
const text = [error.message, error.error?.message, error.providerError?.message, error.error]
|
|
297
|
+
.filter((part) => typeof part === 'string')
|
|
298
|
+
.join(' ');
|
|
299
|
+
if (NON_WIRE_ERROR_TEXT.test(text)) return false;
|
|
300
|
+
if (ENDPOINT_STATUSES.has(status)) return true;
|
|
301
|
+
if (!REJECTION_STATUSES.has(status)) return false;
|
|
302
|
+
return ENDPOINT_WORDS.test(text) && UNSUPPORTED_WORDS.test(text);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// The send options with the output callbacks wrapped: `emitted()` turns true
|
|
306
|
+
// as soon as the caller was shown text, reasoning or a tool call.
|
|
307
|
+
function trackOutput(sendOpts) {
|
|
308
|
+
let emitted = false;
|
|
309
|
+
const wrap = (fn, shows = () => true) =>
|
|
310
|
+
typeof fn === 'function'
|
|
311
|
+
? (...args) => {
|
|
312
|
+
if (shows(...args)) emitted = true;
|
|
313
|
+
return fn(...args);
|
|
314
|
+
}
|
|
315
|
+
: fn;
|
|
316
|
+
const opts = { ...(sendOpts || {}) };
|
|
317
|
+
opts.onTextDelta = wrap(opts.onTextDelta);
|
|
318
|
+
opts.onToolCall = wrap(opts.onToolCall);
|
|
319
|
+
opts.onStreamDelta = wrap(opts.onStreamDelta, (kind) => kind === 'text' || kind === 'reasoning' || kind === 'tool');
|
|
320
|
+
return { opts, emitted: () => emitted };
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* One send on its resolved route, with at most one switch of wire: when the
|
|
325
|
+
* gateway clearly rejects the model on that wire before anything reached the
|
|
326
|
+
* caller, the same request goes once more on the next wire the model is
|
|
327
|
+
* served on, and the session records the new route (history written on the
|
|
328
|
+
* old wire is lowered, as for any reroute). Never on an auth, quota, abort or
|
|
329
|
+
* mid-stream failure, and never a second time.
|
|
330
|
+
*
|
|
331
|
+
* @param {(wire: string|undefined, history: object[], opts: object) => Promise<object>} dispatch
|
|
332
|
+
* sends `history` on `wire` through the provider's engine for that wire
|
|
333
|
+
*/
|
|
334
|
+
export async function sendOnRoute(provider, model, tools, sendOpts, messages, dispatch) {
|
|
335
|
+
const route = await sendWireRoute(provider, model, tools, sendOpts, messages);
|
|
336
|
+
const opts = withoutWireSwitches(sendOpts);
|
|
337
|
+
const tracked = trackOutput(opts);
|
|
338
|
+
try {
|
|
339
|
+
const result = await dispatch(route?.wire, lowerHistoryForRoute(messages, route), tracked.opts);
|
|
340
|
+
// A route re-resolved on this send (its pinned wire was dropped from the
|
|
341
|
+
// provider's config) is reported back like a refusal reroute below.
|
|
342
|
+
if (route?.source === 'reroute' && result && typeof result === 'object' && !Object.isFrozen(result)) {
|
|
343
|
+
result.wireReroute = route;
|
|
344
|
+
}
|
|
345
|
+
return result;
|
|
346
|
+
} catch (error) {
|
|
347
|
+
if (!route || tracked.emitted() || opts.signal?.aborted || !isWireUnsupportedError(error)) throw error;
|
|
348
|
+
const agent = Array.isArray(tools) && tools.length > 0;
|
|
349
|
+
const next = (await provider.resolveWireRoute(model, { agent, exclude: [route.wire] })) || null;
|
|
350
|
+
if (!next || next.wire === route.wire) throw error;
|
|
351
|
+
const session = sendOpts?.session;
|
|
352
|
+
const rerouted = {
|
|
353
|
+
provider: provider.name,
|
|
354
|
+
model,
|
|
355
|
+
...next,
|
|
356
|
+
source: 'reroute',
|
|
357
|
+
reroutedFrom: route.wire,
|
|
358
|
+
reroutedReason: 'unsupported',
|
|
359
|
+
loweredAssistantCount: countAssistants(session?.messages ?? messages),
|
|
360
|
+
};
|
|
361
|
+
// The pin names its own provider and model, so a projected session (the
|
|
362
|
+
// model proxy's PC side carries no identity fields) is recognised by it.
|
|
363
|
+
if (pinMatches(session?.wireRoute, provider.name, model)) session.wireRoute = rerouted;
|
|
364
|
+
const result = await dispatch(rerouted.wire, lowerHistoryForRoute(messages, rerouted), opts);
|
|
365
|
+
// The authoritative route travels back with the result, for a caller
|
|
366
|
+
// whose session is not the object updated above (a proxied send).
|
|
367
|
+
if (result && typeof result === 'object' && !Object.isFrozen(result)) result.wireReroute = rerouted;
|
|
368
|
+
return result;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const pinMatches = (pin, providerName, model) => Boolean(pin) && pin.provider === providerName && pin.model === model;
|
|
373
|
+
|
|
374
|
+
function modelNotRoutableError(provider, model) {
|
|
375
|
+
return Object.assign(new Error(`[${provider}] model ${model} is not routable: no wire it is served on is offered`), {
|
|
376
|
+
code: 'MODEL_NOT_ROUTABLE',
|
|
377
|
+
provider,
|
|
378
|
+
model,
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Strip the competing wire switches from send options: the resolved route is
|
|
384
|
+
* the only authority on which wire a request goes out on.
|
|
385
|
+
*/
|
|
386
|
+
export function withoutWireSwitches(sendOpts) {
|
|
387
|
+
const { compatWireApi: _wire, responsesTransport: _transport, ...rest } = sendOpts || {};
|
|
388
|
+
return rest;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Every message field a provider adapter replays as wire-native state.
|
|
392
|
+
const WIRE_REPLAY_FIELDS = [
|
|
393
|
+
'providerReplay',
|
|
394
|
+
'reasoning',
|
|
395
|
+
'thinkingBlocks',
|
|
396
|
+
'assistantBlocks',
|
|
397
|
+
'reasoningItems',
|
|
398
|
+
'reasoningContent',
|
|
399
|
+
'providerMetadata',
|
|
400
|
+
];
|
|
401
|
+
|
|
402
|
+
const countAssistants = (messages) =>
|
|
403
|
+
Array.isArray(messages) ? messages.filter((message) => message?.role === 'assistant').length : 0;
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* History as the route's wire may see it. A rerouted session (its pinned wire
|
|
407
|
+
* was no longer offered) carries `loweredAssistantCount`: the assistant turns
|
|
408
|
+
* recorded on the old wire. Their wire-native replay (reasoning, thinking
|
|
409
|
+
* blocks, native items) is dropped; turns produced on the new wire keep theirs.
|
|
410
|
+
*/
|
|
411
|
+
export function lowerHistoryForRoute(messages, route) {
|
|
412
|
+
const count = route?.source === 'reroute' ? route.loweredAssistantCount : 0;
|
|
413
|
+
if (!(count > 0) || !Array.isArray(messages)) return messages;
|
|
414
|
+
let seen = 0;
|
|
415
|
+
return messages.map((message) => {
|
|
416
|
+
if (message?.role !== 'assistant' || seen++ >= count) return message;
|
|
417
|
+
if (!WIRE_REPLAY_FIELDS.some((field) => field in message)) return message;
|
|
418
|
+
const plain = { ...message };
|
|
419
|
+
for (const field of WIRE_REPLAY_FIELDS) delete plain[field];
|
|
420
|
+
return plain;
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
async function resolveSendRoute(provider, model, tools, sendOpts, messages) {
|
|
425
|
+
const agent = Array.isArray(tools) && tools.length > 0;
|
|
426
|
+
// The session's current pin outranks a copy carried in the send options: a
|
|
427
|
+
// reroute updates the session, and later sends of the same turn reuse opts.
|
|
428
|
+
const sessionPin = sendOpts?.session?.wireRoute;
|
|
429
|
+
const pinned = pinMatches(sessionPin, provider.name, model) ? sessionPin : (sendOpts?.wireRoute ?? sessionPin);
|
|
430
|
+
if (pinMatches(pinned, provider.name, model)) {
|
|
431
|
+
// The pin stands while the model's current endpoints still offer its wire
|
|
432
|
+
// (the provider may have been edited to drop it); otherwise the route is
|
|
433
|
+
// resolved fresh (not legacy) and the reroute is recorded.
|
|
434
|
+
const current = (await provider.resolveWireRoute(model, { agent, keep: pinned.wire })) || null;
|
|
435
|
+
if (current?.source === 'pinned') return pinned;
|
|
436
|
+
if (current && current.source !== 'unknown') {
|
|
437
|
+
const session = sendOpts?.session;
|
|
438
|
+
// An explicit reroute: recorded on the pin, with the history already
|
|
439
|
+
// written on the old wire marked for lowering.
|
|
440
|
+
const repinned = {
|
|
441
|
+
provider: provider.name,
|
|
442
|
+
model,
|
|
443
|
+
...current,
|
|
444
|
+
source: 'reroute',
|
|
445
|
+
reroutedFrom: pinned.wire,
|
|
446
|
+
loweredAssistantCount: countAssistants(session?.messages ?? messages),
|
|
447
|
+
};
|
|
448
|
+
if (session?.wireRoute === pinned) session.wireRoute = repinned;
|
|
449
|
+
return repinned;
|
|
450
|
+
}
|
|
451
|
+
return current;
|
|
452
|
+
}
|
|
453
|
+
// A session created before this table that already talked to its model keeps
|
|
454
|
+
// its wire even when the pin could not resolve (no metadata yet) and the
|
|
455
|
+
// metadata recovered by this send: resolve as legacy and pin it now.
|
|
456
|
+
const legacySession = legacySessionOf(sendOpts?.session, provider.name, model);
|
|
457
|
+
const route = (await provider.resolveWireRoute(model, legacySession ? { agent, legacy: true } : { agent })) || null;
|
|
458
|
+
if (legacySession && route && route.source !== 'unknown' && legacySession.wireRoute === undefined) {
|
|
459
|
+
legacySession.wireRoute = { provider: provider.name, model, ...route };
|
|
460
|
+
return legacySession.wireRoute;
|
|
461
|
+
}
|
|
462
|
+
return route;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// `wireRoute` is absent (not null) on a session created before the table.
|
|
466
|
+
const isLegacySession = (subject) => subject.wireRoute === undefined && hasAssistantHistory(subject);
|
|
467
|
+
|
|
468
|
+
// The session of this send when it is an existing one for this provider and model.
|
|
469
|
+
function legacySessionOf(candidate, providerName, model) {
|
|
470
|
+
return candidate && candidate.provider === providerName && candidate.model === model && isLegacySession(candidate)
|
|
471
|
+
? candidate
|
|
472
|
+
: null;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const hasAssistantHistory = (session) =>
|
|
476
|
+
Array.isArray(session?.messages) && session.messages.some((message) => message?.role === 'assistant');
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Pin the session's wire before its turn reaches the request boundary.
|
|
480
|
+
* `session.wireRoute` is null on a session created with this table (resolved
|
|
481
|
+
* fresh) and absent on one created before it: such a session that already
|
|
482
|
+
* talked to its model keeps the wire it started on. A route change (another
|
|
483
|
+
* provider or model) resolves fresh. A single-wire adapter pins nothing, and
|
|
484
|
+
* a resolution that failed or had no metadata is not pinned — the send
|
|
485
|
+
* resolves again and surfaces the real failure.
|
|
486
|
+
*
|
|
487
|
+
* Only a route pinned before the session's first answered request records
|
|
488
|
+
* verified native deferred-tool support: a session that already talked on
|
|
489
|
+
* the bridge keeps it.
|
|
490
|
+
*/
|
|
491
|
+
export async function pinSessionWireRoute(session, provider) {
|
|
492
|
+
if (!session?.provider || !session.model) return null;
|
|
493
|
+
const current = session.wireRoute;
|
|
494
|
+
if (current && current.provider === session.provider && current.model === session.model) return current;
|
|
495
|
+
if (typeof provider?.resolveWireRoute !== 'function') return null;
|
|
496
|
+
// Decided before any await: the turn appends its own messages afterwards.
|
|
497
|
+
const answered = hasAssistantHistory(session);
|
|
498
|
+
const legacy = current === undefined && answered;
|
|
499
|
+
const { provider: providerName, model } = session;
|
|
500
|
+
let route;
|
|
501
|
+
try {
|
|
502
|
+
route = await provider.resolveWireRoute(model, { agent: true, legacy });
|
|
503
|
+
} catch {
|
|
504
|
+
return null;
|
|
505
|
+
}
|
|
506
|
+
if (!route || route.source === 'unknown') return null;
|
|
507
|
+
// The route changed while resolving: the newer route pins on its own turn.
|
|
508
|
+
if (session.provider !== providerName || session.model !== model) return null;
|
|
509
|
+
const nativeDeferred = !answered && wireSupportsNativeDeferredTools(providerName, route.wire);
|
|
510
|
+
session.wireRoute = { provider: providerName, model, ...route, ...(nativeDeferred ? { nativeDeferredTools: true } : {}) };
|
|
511
|
+
return session.wireRoute;
|
|
512
|
+
}
|