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
|
@@ -179,6 +179,9 @@ const PROVIDER_MODULES = {
|
|
|
179
179
|
openai: ['./openai-ws.mjs', 'OpenAIDirectProvider'],
|
|
180
180
|
'mixdog-local': ['./mixdog-local.mjs', 'MixdogLocalProvider'],
|
|
181
181
|
'opencode-go': ['./opencode-go.mjs', 'OpenCodeGoProvider'],
|
|
182
|
+
// Multi-wire preset gateways (wire-route.mjs picks the wire per model).
|
|
183
|
+
openrouter: ['./openrouter.mjs', 'OpenRouterProvider'],
|
|
184
|
+
deepseek: ['./deepseek.mjs', 'DeepSeekProvider'],
|
|
182
185
|
};
|
|
183
186
|
|
|
184
187
|
// User-defined providers (cfg.type === 'custom') are keyed by a generated
|
|
@@ -209,7 +212,7 @@ async function instantiateProvider(name, Ctor, cfg, proxyChannel = null) {
|
|
|
209
212
|
return wrapProviderAdmission(createModelProxyProvider(name, cfg, proxyChannel ?? getModelProxyChannel()), name);
|
|
210
213
|
}
|
|
211
214
|
if (isCustomProviderConfig(name, cfg)) return wrapProviderAdmission(await Ctor(name, cfg), name);
|
|
212
|
-
if (Object.hasOwn(OPENAI_COMPAT_PRESETS, name) && name
|
|
215
|
+
if (Object.hasOwn(OPENAI_COMPAT_PRESETS, name) && !Object.hasOwn(PROVIDER_MODULES, name)) {
|
|
213
216
|
return wrapProviderAdmission(new Ctor(name, cfg), name);
|
|
214
217
|
}
|
|
215
218
|
return createAccountPoolProvider(name, () => wrapProviderAdmission(new Ctor(cfg), name));
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
PROVIDER_RETRY_JITTER_RATIO,
|
|
6
6
|
PROVIDER_RETRY_MAX_ATTEMPTS,
|
|
7
7
|
} from '../stall-policy.mjs';
|
|
8
|
+
import { providerErrorKind } from './provider-error-kind.mjs';
|
|
8
9
|
|
|
9
10
|
/** Anthropic request budget: 10 retries (11 attempts).
|
|
10
11
|
* CLAUDE_CODE_MAX_RETRIES is intentionally read per request for reload/tests.
|
|
@@ -32,17 +33,23 @@ export function anthropicRequestTimeoutMs() {
|
|
|
32
33
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : 600_000;
|
|
33
34
|
}
|
|
34
35
|
|
|
36
|
+
// Consecutive overloads after which Anthropic switches to its fallback model
|
|
37
|
+
// (passed to withRetry as `overloadFallbackAfter`).
|
|
35
38
|
export const ANTHROPIC_MAX_CONSECUTIVE_529 = 3;
|
|
36
39
|
|
|
37
|
-
|
|
40
|
+
/** Thrown by withRetry when `overloadFallbackAfter` consecutive overloads hand the send to `fallbackModel`. */
|
|
41
|
+
export class ModelFallbackTriggeredError extends Error {
|
|
38
42
|
constructor(originalModel, fallbackModel, cause) {
|
|
39
|
-
super(`
|
|
40
|
-
this.name = '
|
|
43
|
+
super(`Model fallback triggered: ${originalModel} -> ${fallbackModel}`, { cause });
|
|
44
|
+
this.name = 'ModelFallbackTriggeredError';
|
|
41
45
|
this.originalModel = originalModel;
|
|
42
46
|
this.fallbackModel = fallbackModel;
|
|
43
47
|
}
|
|
44
48
|
}
|
|
45
49
|
|
|
50
|
+
// Existing provider imports keep working: the same class under its old name.
|
|
51
|
+
export const AnthropicFallbackTriggeredError = ModelFallbackTriggeredError;
|
|
52
|
+
|
|
46
53
|
// Default backoff schedule used by withRetry when caller does not override.
|
|
47
54
|
// Mirrors anthropic-oauth's 5-attempt curve (immediate + 1s/2s/4s/8s) so the
|
|
48
55
|
// total cap stays under 15s. Total upper bound = sum = 15s.
|
|
@@ -51,9 +58,36 @@ export const DEFAULT_MAX_ATTEMPTS = PROVIDER_RETRY_MAX_ATTEMPTS;
|
|
|
51
58
|
|
|
52
59
|
const MIDSTREAM_BACKOFF_MS = [250, 1000, 2000, 4000];
|
|
53
60
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
const ADVICE_RETRYABLE_KINDS = new Set(['overloaded', 'rate_limited', 'transient']);
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The wait before a mid-stream re-issue: the server's advice (Retry-After /
|
|
65
|
+
* retryAfterMs) in full for a retryable kind — never capped below its value —
|
|
66
|
+
* else the caller's bounded backoff step. Advice never makes a terminal kind
|
|
67
|
+
* retryable; that is the classifier's verdict, not this wait's. The retry
|
|
68
|
+
* COUNT stays the caller's budget; the sleep stays the caller's abortable one.
|
|
69
|
+
*/
|
|
70
|
+
export function midstreamRetryDelayMs(err, backoffMs) {
|
|
71
|
+
const { kind, retryAfterMs } = providerErrorKind(err);
|
|
72
|
+
if (retryAfterMs != null && ADVICE_RETRYABLE_KINDS.has(kind)) return Math.max(0, retryAfterMs);
|
|
73
|
+
return Math.max(0, Number(backoffMs) || 0);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** The mid-stream wait for `retryNumber`; pass the failure as `err` so server
|
|
77
|
+
* advice on a retryable kind replaces the jittered step (midstreamRetryDelayMs). */
|
|
78
|
+
// `schedule` / `jitterRatio` default to the shared values; a provider passes
|
|
79
|
+
// its own (e.g. openai-retry-policy.mjs).
|
|
80
|
+
export function midstreamBackoffFor(
|
|
81
|
+
retryNumber,
|
|
82
|
+
schedule = MIDSTREAM_BACKOFF_MS,
|
|
83
|
+
err = null,
|
|
84
|
+
jitterRatio,
|
|
85
|
+
jitterMode = 'symmetric'
|
|
86
|
+
) {
|
|
87
|
+
const steps = schedule || MIDSTREAM_BACKOFF_MS;
|
|
88
|
+
const raw = steps[Math.min(Math.max(retryNumber, 1), steps.length) - 1];
|
|
89
|
+
const step = jitterDelayMs(raw, jitterRatio ?? PROVIDER_RETRY_JITTER_RATIO, jitterMode);
|
|
90
|
+
return err ? midstreamRetryDelayMs(err, step) : step;
|
|
57
91
|
}
|
|
58
92
|
|
|
59
93
|
export function jitterDelayMs(ms, ratio = PROVIDER_RETRY_JITTER_RATIO, mode = 'symmetric') {
|
|
@@ -62,7 +96,12 @@ export function jitterDelayMs(ms, ratio = PROVIDER_RETRY_JITTER_RATIO, mode = 's
|
|
|
62
96
|
const r = Math.min(Math.max(Number(ratio) || 0, 0), 1);
|
|
63
97
|
if (!r) return Math.round(base);
|
|
64
98
|
const spread = base * r;
|
|
65
|
-
|
|
99
|
+
// 'positive': upward only; 'negative': downward only, base × (1 − r·rand);
|
|
100
|
+
// otherwise symmetric ±r.
|
|
101
|
+
let offset;
|
|
102
|
+
if (mode === 'positive') offset = Math.random() * spread;
|
|
103
|
+
else if (mode === 'negative') offset = -Math.random() * spread;
|
|
104
|
+
else offset = (Math.random() * 2 - 1) * spread;
|
|
66
105
|
return Math.max(0, Math.round(base + offset));
|
|
67
106
|
}
|
|
68
107
|
|
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
// Structural error classification: typed status, transience, auth, context
|
|
2
2
|
// overflow, retry-after and stream-close verdicts shared by every provider.
|
|
3
3
|
import { readStreamOutcome } from './lib/stream-outcome.mjs';
|
|
4
|
+
import {
|
|
5
|
+
BARE_FETCH_TRANSPORT_MESSAGE_RE,
|
|
6
|
+
DETERMINISTIC_KINDS,
|
|
7
|
+
QUOTA_KINDS,
|
|
8
|
+
REQUEST_SIZE_PATTERNS,
|
|
9
|
+
TLS_RECORD_FAILURE_RE,
|
|
10
|
+
TOKEN_CONTEXT_OVERFLOW_PATTERNS,
|
|
11
|
+
TRANSIENT_SDK_NAMES,
|
|
12
|
+
boundedCauseChain,
|
|
13
|
+
isToolSurfaceExceedsContextError,
|
|
14
|
+
isTransientErrorCode,
|
|
15
|
+
providerErrorKind,
|
|
16
|
+
typedCodeKind,
|
|
17
|
+
typedErrorCode,
|
|
18
|
+
} from './provider-error-kind.mjs';
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
boundedCauseChain,
|
|
22
|
+
errorHeaderValue,
|
|
23
|
+
headerValue,
|
|
24
|
+
isTransientErrorCode,
|
|
25
|
+
providerErrorKind,
|
|
26
|
+
retryAfterMsFromError,
|
|
27
|
+
typedErrorCode,
|
|
28
|
+
} from './provider-error-kind.mjs';
|
|
4
29
|
|
|
5
30
|
// HTTP statuses considered transient — safe to retry with backoff.
|
|
6
31
|
// 408 — request timeout
|
|
@@ -15,22 +40,18 @@ export const TRANSIENT_STATUSES = new Set([408, 409, 425]);
|
|
|
15
40
|
// 400/422 — bad request (deterministic)
|
|
16
41
|
const AUTH_STATUSES = new Set([401, 403]);
|
|
17
42
|
const PERMANENT_STATUSES = new Set([400, 404, 405, 410, 415, 422]);
|
|
18
|
-
// Cloudflare origin-TLS pages never clear on retry
|
|
43
|
+
// Cloudflare origin-TLS pages never clear on retry.
|
|
19
44
|
export const TERMINAL_EDGE_STATUSES = new Set([525, 526]);
|
|
20
45
|
const GEMINI_TRANSIENT_RPC_CODES = new Set(['UNAVAILABLE', 'DEADLINE_EXCEEDED', 'ABORTED', 'INTERNAL']);
|
|
21
46
|
const PREVIOUS_RESPONSE_NOT_FOUND = 'previous_response_not_found';
|
|
22
47
|
export const WEBSOCKET_CONNECTION_LIMIT = 'websocket_connection_limit_reached';
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
'
|
|
27
|
-
'
|
|
28
|
-
'
|
|
29
|
-
'HeadersTimeoutError',
|
|
30
|
-
'BodyTimeoutError',
|
|
48
|
+
// Token-context codes only: a byte-size `request_too_large` is not cured by
|
|
49
|
+
// compaction (see isContextOverflowError).
|
|
50
|
+
const CONTEXT_OVERFLOW_CODES = new Set([
|
|
51
|
+
'context_length_exceeded',
|
|
52
|
+
'context_window_exceeded',
|
|
53
|
+
'model_context_window_exceeded',
|
|
31
54
|
]);
|
|
32
|
-
const ANTHROPIC_RESET_HEADER = 'anthropic-ratelimit-unified-reset';
|
|
33
|
-
const ANTHROPIC_RESET_CAP_MS = 300_000;
|
|
34
55
|
|
|
35
56
|
// Structured status fields a provider error / wire event may carry. A value is
|
|
36
57
|
// accepted only when it is a real numeric HTTP status; string codes
|
|
@@ -59,8 +80,11 @@ const statusOfError = (err) => Number(err?.httpStatus || err?.status || err?.res
|
|
|
59
80
|
|
|
60
81
|
// The verdict a typed HTTP status (or a typed stream shape) gives, in
|
|
61
82
|
// precedence order; null when the status decides nothing.
|
|
62
|
-
function classifyByStatus(err, status) {
|
|
83
|
+
function classifyByStatus(err, status, options = {}) {
|
|
63
84
|
if (AUTH_STATUSES.has(status)) return 'auth';
|
|
85
|
+
// Opt-in: 499 "client closed request" from Google
|
|
86
|
+
// frontends is retried; others keep it a deterministic 4xx.
|
|
87
|
+
if (status === 499 && options.retry499 === true) return 'transient';
|
|
64
88
|
// Stale previous_response_id is recoverable by dropping the chain and
|
|
65
89
|
// re-issuing a full frame, which is the retryable path. A typed
|
|
66
90
|
// 400 here is not a deterministic payload refusal.
|
|
@@ -90,7 +114,7 @@ function classifyByStatus(err, status) {
|
|
|
90
114
|
* 'unknown' — neither; default to permanent in safety-critical paths,
|
|
91
115
|
* or retry once in best-effort paths.
|
|
92
116
|
*/
|
|
93
|
-
export function classifyError(err) {
|
|
117
|
+
export function classifyError(err, options = {}) {
|
|
94
118
|
if (!err) return 'unknown';
|
|
95
119
|
// Canonical stream-outcome contract owns replay safety: exposed
|
|
96
120
|
// text/reasoning or a dispatched/ambiguous complete tool call makes
|
|
@@ -105,14 +129,34 @@ export function classifyError(err) {
|
|
|
105
129
|
// across the bounded chain before considering stale connection causes.
|
|
106
130
|
const chain = boundedCauseChain(err);
|
|
107
131
|
if (chain.some(isExplicitUserAbortError)) return 'permanent';
|
|
108
|
-
//
|
|
132
|
+
// A typed provider code outranks the HTTP status (429+server_is_overloaded
|
|
133
|
+
// is an overload, 403+cyber_policy a policy refusal, 5xx+insufficient_quota
|
|
134
|
+
// a billing refusal).
|
|
135
|
+
// Typed evidence only: message wording never synthesizes a verdict here.
|
|
136
|
+
const { kind } = providerErrorKind(err, { text: false });
|
|
109
137
|
const status = statusOfError(err);
|
|
110
|
-
|
|
138
|
+
// Opt-in: a status-only 499 "client closed request" is retried instead of
|
|
139
|
+
// read as a 4xx; a typed code on it decides as usual.
|
|
140
|
+
if (status === 499 && options.retry499 === true && kind === 'invalid_request' && !typedCodeKind(err)) {
|
|
141
|
+
return 'transient';
|
|
142
|
+
}
|
|
143
|
+
if (kind === 'auth' || kind === 'permission') return 'auth';
|
|
144
|
+
if (DETERMINISTIC_KINDS.has(kind)) return 'permanent';
|
|
145
|
+
// An origin-TLS edge failure is final whatever code accompanies it.
|
|
146
|
+
if (TERMINAL_EDGE_STATUSES.has(status)) return 'permanent';
|
|
147
|
+
// A deterministic wire code outranks a numeric 5xx on the same event.
|
|
148
|
+
if (classifyWireErrorEvent(err) === 'permanent') return 'permanent';
|
|
149
|
+
if (kind === 'overloaded') return 'transient';
|
|
150
|
+
// A typed transient kind decides whatever status accompanies it (401 +
|
|
151
|
+
// server_error is a server fault).
|
|
152
|
+
if (kind === 'transient') return 'transient';
|
|
153
|
+
// Current typed HTTP status outranks stale stream/connection annotations.
|
|
154
|
+
return classifyByStatus(err, status, options) || classifyByTransport(err, chain, status) || 'unknown';
|
|
111
155
|
}
|
|
112
156
|
|
|
113
157
|
// A turn that ended on a malformed or unexpected tool call produced no usable
|
|
114
|
-
// call at all (the typed finish reason says so); the
|
|
115
|
-
//
|
|
158
|
+
// call at all (the typed finish reason says so); the same request is re-asked,
|
|
159
|
+
// bounded, instead of failing the turn.
|
|
116
160
|
const INVALID_TOOL_CALL_FINISH_REASONS = new Set(['MALFORMED_FUNCTION_CALL', 'UNEXPECTED_TOOL_CALL']);
|
|
117
161
|
|
|
118
162
|
function isInvalidToolCallFinish(err) {
|
|
@@ -132,9 +176,9 @@ function classifyByTransport(err, chain, status) {
|
|
|
132
176
|
// so without this it classified as 'unknown' and no loop-level replay was
|
|
133
177
|
// ever attempted (observed live: pooled WS retired by the server between
|
|
134
178
|
// turns → close 1000 before response.created → the whole turn failed).
|
|
135
|
-
//
|
|
136
|
-
//
|
|
137
|
-
//
|
|
179
|
+
// The same disconnect is retryable (a stream fallback/retry applies); the
|
|
180
|
+
// exposure deny above still fails closed for anything already relayed or
|
|
181
|
+
// dispatched.
|
|
138
182
|
if (isNonTerminalStreamClose(err)) return 'transient';
|
|
139
183
|
|
|
140
184
|
// Cursor's resumed tool-result stream cannot safely reopen the same wire
|
|
@@ -172,58 +216,6 @@ function classifyByTransport(err, chain, status) {
|
|
|
172
216
|
return classifyWireErrorEvent(err) || null;
|
|
173
217
|
}
|
|
174
218
|
|
|
175
|
-
const MAX_CAUSE_CHAIN_DEPTH = 8;
|
|
176
|
-
// 'terminated' / 'other side closed' / 'socket hang up' are the body-read
|
|
177
|
-
// forms of the same disconnect (undici aborts the response body when the peer
|
|
178
|
-
// closes mid-stream and may not attach a cause).
|
|
179
|
-
const BARE_FETCH_TRANSPORT_MESSAGE_RE =
|
|
180
|
-
/^(?:fetch failed|failed to fetch|couldn'?t fetch\.?|load failed|network error|terminated|other side closed|socket hang up)$/i;
|
|
181
|
-
const TRANSIENT_ERROR_CODES = new Set([
|
|
182
|
-
'ECONNRESET',
|
|
183
|
-
'ETIMEDOUT',
|
|
184
|
-
'ESOCKETTIMEDOUT',
|
|
185
|
-
'EAI_AGAIN',
|
|
186
|
-
'ENOTFOUND',
|
|
187
|
-
'EAI_NODATA',
|
|
188
|
-
'ECONNREFUSED',
|
|
189
|
-
'ENETUNREACH',
|
|
190
|
-
'EHOSTUNREACH',
|
|
191
|
-
'EPIPE',
|
|
192
|
-
'EPROVIDERTIMEOUT',
|
|
193
|
-
'EGEMINITIMEOUT',
|
|
194
|
-
'ESTREAMSTALL',
|
|
195
|
-
'EWSACQUIRETIMEOUT',
|
|
196
|
-
'UND_ERR_SOCKET',
|
|
197
|
-
'UND_ERR_CONNECT_TIMEOUT',
|
|
198
|
-
'UND_ERR_HEADERS_TIMEOUT',
|
|
199
|
-
'UND_ERR_BODY_TIMEOUT',
|
|
200
|
-
'UND_ERR_CONNECT',
|
|
201
|
-
'EPROTO',
|
|
202
|
-
'UND_ERR_DESTROYED',
|
|
203
|
-
'UND_ERR_CLOSED',
|
|
204
|
-
'ECONNABORTED',
|
|
205
|
-
'ENETRESET',
|
|
206
|
-
'ERR_STREAM_DESTROYED',
|
|
207
|
-
'ERR_HTTP2_STREAM_ERROR',
|
|
208
|
-
'ERR_HTTP2_SESSION_ERROR',
|
|
209
|
-
'ERR_HTTP2_INVALID_SESSION',
|
|
210
|
-
'ERR_SOCKET_CONNECTION_TIMEOUT',
|
|
211
|
-
'ERR_SSL_WRONG_VERSION_NUMBER',
|
|
212
|
-
'ERR_STREAM_PREMATURE_CLOSE',
|
|
213
|
-
]);
|
|
214
|
-
|
|
215
|
-
// TLS record corruption on a flaky link or a meddling proxy. Node builds the
|
|
216
|
-
// ERR_SSL_* code from the OpenSSL reason string, which differs across OpenSSL
|
|
217
|
-
// versions (…SSLV3_ALERT_BAD_RECORD_MAC, …SSL/TLS_ALERT_BAD_RECORD_MAC,
|
|
218
|
-
// …DECRYPTION_FAILED_OR_BAD_RECORD_MAC), so the stable suffix names the class.
|
|
219
|
-
const TLS_RECORD_FAILURE_RE = /^ERR_SSL_[A-Z0-9_/]*BAD_RECORD_MAC$/i;
|
|
220
|
-
|
|
221
|
-
/** True for a socket/TLS errno that describes a transient transport fault. */
|
|
222
|
-
export function isTransientErrorCode(code) {
|
|
223
|
-
const value = String(code || '');
|
|
224
|
-
return TRANSIENT_ERROR_CODES.has(value) || TLS_RECORD_FAILURE_RE.test(value);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
219
|
// Cursor's HTTP/2 bridge preserves provider-specific codes in `cursorCode`.
|
|
228
220
|
// These codes all describe an incomplete transport turn, not a model verdict.
|
|
229
221
|
// Replay permission remains fail-closed in the stream-outcome gate above.
|
|
@@ -342,9 +334,8 @@ export function isToolInputCut(err) {
|
|
|
342
334
|
// The provider was never reached: name resolution, routing, refusal or the
|
|
343
335
|
// connect handshake failed, so nothing was sent or received. Only this class
|
|
344
336
|
// is worth waiting out for minutes — the identical request succeeds once the
|
|
345
|
-
// network is back (a lift, a sleeping laptop, a router reboot),
|
|
346
|
-
//
|
|
347
|
-
// recovers. A stream that dropped mid-response is not this class: it keeps
|
|
337
|
+
// network is back (a lift, a sleeping laptop, a router reboot), so a sampling
|
|
338
|
+
// turn is kept alive until such a connection recovers. A stream that dropped mid-response is not this class: it keeps
|
|
348
339
|
// the short, bounded retry budget.
|
|
349
340
|
const CONNECT_FAILURE_CODES = new Set([
|
|
350
341
|
'ENOTFOUND',
|
|
@@ -382,9 +373,14 @@ export function isServerUnavailable(err) {
|
|
|
382
373
|
if (!err || (typeof err !== 'object' && typeof err !== 'function')) return false;
|
|
383
374
|
const chain = boundedCauseChain(err);
|
|
384
375
|
if (chain.some(isExplicitUserAbortError)) return false;
|
|
376
|
+
// Typed kind first: an overload (any status) is this class; quota, billing,
|
|
377
|
+
// policy, auth, request refusals and rate limits never are.
|
|
378
|
+
const { kind } = providerErrorKind(err);
|
|
379
|
+
if (kind === 'overloaded') return true;
|
|
380
|
+
if (kind !== 'transient' && kind !== 'unknown') return false;
|
|
385
381
|
const status = statusOfError(err);
|
|
386
382
|
if (status) return status === 408 || (status >= 500 && status < 600 && !TERMINAL_EDGE_STATUSES.has(status));
|
|
387
|
-
if (isRetryableWireErrorEvent(err)) return
|
|
383
|
+
if (isRetryableWireErrorEvent(err)) return true;
|
|
388
384
|
return chain.some((item) => {
|
|
389
385
|
const rpc = [item?.geminiStatus, item?.error?.status, typeof item?.status === 'string' ? item.status : ''];
|
|
390
386
|
if (rpc.some((field) => GEMINI_TRANSIENT_RPC_CODES.has(String(field || '').toUpperCase()))) return true;
|
|
@@ -414,21 +410,11 @@ export function canFallbackNonStreaming(err, { signal } = {}) {
|
|
|
414
410
|
// A cut mid tool-argument stream is replayed by the loop with a split-call
|
|
415
411
|
// notice, never re-issued unchanged here.
|
|
416
412
|
if (isToolInputCut(err)) return false;
|
|
413
|
+
// A provider-terminal verdict ends recovery; no re-issue of any shape.
|
|
414
|
+
if (boundedCauseChain(err).some((item) => item?.providerRecoveryTerminal === true)) return false;
|
|
417
415
|
return classifyError(err) === 'transient' || outcome.stallObserved === true || outcome.truncatedStream === true;
|
|
418
416
|
}
|
|
419
417
|
|
|
420
|
-
export function boundedCauseChain(err) {
|
|
421
|
-
const chain = [];
|
|
422
|
-
const seen = new Set();
|
|
423
|
-
let cursor = err;
|
|
424
|
-
while (cursor && chain.length < MAX_CAUSE_CHAIN_DEPTH && !seen.has(cursor)) {
|
|
425
|
-
chain.push(cursor);
|
|
426
|
-
seen.add(cursor);
|
|
427
|
-
cursor = cursor?.cause;
|
|
428
|
-
}
|
|
429
|
-
return chain;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
418
|
export function isExplicitUserAbortError(err) {
|
|
433
419
|
if (!err || (typeof err !== 'object' && typeof err !== 'function')) return false;
|
|
434
420
|
if (err.name === 'AbortError' || err.name === 'APIUserAbortError' || err.code === 'ABORT_ERR') return true;
|
|
@@ -462,34 +448,10 @@ export function isCursorTransientTransportError(err) {
|
|
|
462
448
|
// Patterns cover OpenAI ("maximum context length", "reduce the length"),
|
|
463
449
|
// Anthropic ("prompt is too long"), and generic "input exceeds the context
|
|
464
450
|
// window" phrasing. Match is case-insensitive over err.message.
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
/context[_ ]length[_ ]exceeded/i,
|
|
470
|
-
/prompt is too long/i,
|
|
471
|
-
/reduce the length of (?:the )?(?:messages|input|prompt)/i,
|
|
472
|
-
// Wordings other backends use for the same refusal, each tied to a context
|
|
473
|
-
// or input-length noun so a tokens-per-minute rate limit never matches.
|
|
474
|
-
/prompt too long/i, // z.ai, Ollama
|
|
475
|
-
/prompt exceeds max length/i, // z.ai CN endpoint
|
|
476
|
-
/input is too long for requested model/i, // Amazon Bedrock
|
|
477
|
-
/input token count.*exceeds the maximum/i, // Google
|
|
478
|
-
/request payload size exceeds the limit/i, // Google (400, byte-size limit)
|
|
479
|
-
// A 413 re-wrapped by a proxy or aggregator without its status.
|
|
480
|
-
/request entity too large/i,
|
|
481
|
-
/request exceeds the maximum size/i,
|
|
482
|
-
/maximum prompt length is \d+/i, // xAI
|
|
483
|
-
/exceeds (?:the )?maximum allowed input length/i, // OpenRouter relays
|
|
484
|
-
/is longer than the model'?s context length/i, // Together AI
|
|
485
|
-
/exceeds the available context size/i, // llama.cpp server
|
|
486
|
-
/greater than the context length/i, // LM Studio
|
|
487
|
-
/context window exceeds limit/i, // MiniMax
|
|
488
|
-
/exceeded model token limit/i, // Kimi
|
|
489
|
-
/too large for model with \d+ maximum context length/i, // Mistral
|
|
490
|
-
/range of input length should be/i, // DashScope / Qwen
|
|
491
|
-
/model_context_window_exceeded/i, // z.ai finish reason surfaced as text
|
|
492
|
-
];
|
|
451
|
+
// Untyped byte-size wordings (no status, no code) keep routing here: an
|
|
452
|
+
// unlabelled proxy refusal is most often an oversized history.
|
|
453
|
+
const CONTEXT_OVERFLOW_PATTERNS = [...TOKEN_CONTEXT_OVERFLOW_PATTERNS, ...REQUEST_SIZE_PATTERNS];
|
|
454
|
+
const REQUEST_TOO_LARGE_KIND = 'request_too_large';
|
|
493
455
|
|
|
494
456
|
/**
|
|
495
457
|
* True when `err` is a context-window-exceeded provider rejection. Walks
|
|
@@ -502,89 +464,37 @@ const CONTEXT_OVERFLOW_PATTERNS = [
|
|
|
502
464
|
*/
|
|
503
465
|
export function isContextOverflowError(err, _depth = 0) {
|
|
504
466
|
if (!err || _depth > 2) return false;
|
|
505
|
-
|
|
467
|
+
// A local fixed-overhead refusal (anywhere in the chain, at any recursion
|
|
468
|
+
// level) is never a provider overflow: compacting history cannot help it,
|
|
469
|
+
// whatever its text names.
|
|
470
|
+
if (isToolSurfaceExceedsContextError(err)) return false;
|
|
506
471
|
const code = typedErrorCode(err);
|
|
507
472
|
if (code && CONTEXT_OVERFLOW_CODES.has(code)) return true;
|
|
473
|
+
// A typed byte/media-size refusal (a size code, or HTTP 413 without a
|
|
474
|
+
// token-context code) is not a token-context overflow: compaction cannot
|
|
475
|
+
// shrink it, so only token-context wording may still qualify it.
|
|
476
|
+
const sizeTyped =
|
|
477
|
+
typeof err === 'object' &&
|
|
478
|
+
boundedCauseChain(err).some(
|
|
479
|
+
(item) => item && typeof item === 'object' && providerErrorKind(item, { text: false }).kind === REQUEST_TOO_LARGE_KIND
|
|
480
|
+
);
|
|
481
|
+
const patterns = sizeTyped ? TOKEN_CONTEXT_OVERFLOW_PATTERNS : CONTEXT_OVERFLOW_PATTERNS;
|
|
508
482
|
const msg = (typeof err === 'string' ? err : err?.message) || '';
|
|
509
|
-
if (msg &&
|
|
483
|
+
if (msg && patterns.some((re) => re.test(msg))) return true;
|
|
510
484
|
if (err.cause != null && err.cause !== err) return isContextOverflowError(err.cause, _depth + 1);
|
|
511
485
|
if (err.response?.data != null) return isContextOverflowError(err.response.data, _depth + 1);
|
|
512
486
|
return false;
|
|
513
487
|
}
|
|
514
488
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
return null;
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
export function retryAfterMsFromError(err) {
|
|
526
|
-
const headers = err?.headers || err?.response?.headers || err?.data?.responseHeaders || null;
|
|
527
|
-
const retryAfterMs = headerValue(headers, 'retry-after-ms');
|
|
528
|
-
if (retryAfterMs != null && retryAfterMs !== '') {
|
|
529
|
-
const n = Number(retryAfterMs);
|
|
530
|
-
if (Number.isFinite(n) && n >= 0) return n;
|
|
531
|
-
}
|
|
532
|
-
const retryAfter = headerValue(headers, 'retry-after');
|
|
533
|
-
if (retryAfter != null && retryAfter !== '') {
|
|
534
|
-
const seconds = Number(retryAfter);
|
|
535
|
-
if (Number.isFinite(seconds) && seconds >= 0) return Math.ceil(seconds * 1000);
|
|
536
|
-
const dateMs = Date.parse(String(retryAfter));
|
|
537
|
-
if (!Number.isNaN(dateMs)) return Math.max(0, dateMs - Date.now());
|
|
538
|
-
}
|
|
539
|
-
// Google RPC RetryInfo encodes retryDelay as a protobuf Duration. Preserve
|
|
540
|
-
// the same precedence as Retry-After: a server-provided retry window means
|
|
541
|
-
// RESOURCE_EXHAUSTED is request-local, not a permanent quota refusal.
|
|
542
|
-
const detailLists = [err?.details, err?.error?.details, err?.data?.error?.details];
|
|
543
|
-
for (const details of detailLists) {
|
|
544
|
-
if (!Array.isArray(details)) continue;
|
|
545
|
-
for (const detail of details) {
|
|
546
|
-
const delay = detail?.retryDelay;
|
|
547
|
-
if (typeof delay === 'string') {
|
|
548
|
-
const match = delay.trim().match(/^(\d+(?:\.\d+)?)s$/);
|
|
549
|
-
if (match) return Math.ceil(Number(match[1]) * 1000);
|
|
550
|
-
} else if (delay && typeof delay === 'object') {
|
|
551
|
-
const seconds = Number(delay.seconds || 0);
|
|
552
|
-
const nanos = Number(delay.nanos || 0);
|
|
553
|
-
const ms = seconds * 1000 + nanos / 1_000_000;
|
|
554
|
-
if (Number.isFinite(ms) && ms >= 0) return Math.ceil(ms);
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
const resetHeader = headerValue(headers, ANTHROPIC_RESET_HEADER);
|
|
559
|
-
if (resetHeader != null && resetHeader !== '') {
|
|
560
|
-
const resetUnixSec = Number(resetHeader);
|
|
561
|
-
if (Number.isFinite(resetUnixSec) && resetUnixSec > 0) {
|
|
562
|
-
const delayMs = Math.ceil(resetUnixSec * 1000 - Date.now());
|
|
563
|
-
if (delayMs > 0) return Math.min(delayMs, ANTHROPIC_RESET_CAP_MS);
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
// Codex parses the server-supplied window from a TYPED rate_limit_exceeded
|
|
567
|
-
// payload. Message text never decides whether to retry — only how long to
|
|
568
|
-
// wait after the typed code is already in hand. Headers / RetryInfo win.
|
|
569
|
-
if (typedErrorCode(err) === RATE_LIMIT_EXCEEDED) {
|
|
570
|
-
const delay = rateLimitRetryAfterMsFromMessage(err);
|
|
571
|
-
if (delay != null) return delay;
|
|
572
|
-
}
|
|
573
|
-
return null;
|
|
574
|
-
}
|
|
575
|
-
|
|
489
|
+
/**
|
|
490
|
+
* True for an explicit quota / plan / billing refusal (providerErrorKind
|
|
491
|
+
* quota_exhausted, entitlement or billing). No wait recovers it, so retry
|
|
492
|
+
* layers never replay it, even when the server attached a Retry-After.
|
|
493
|
+
* RESOURCE_EXHAUSTED with a 429, retry advice or a per-minute scope is a
|
|
494
|
+
* request-local rate limit instead.
|
|
495
|
+
*/
|
|
576
496
|
export function isPermanentQuotaError(err) {
|
|
577
|
-
|
|
578
|
-
// Gemini uses RESOURCE_EXHAUSTED for both daily quota and per-minute
|
|
579
|
-
// rate limits. A 429 is request-local (Google/LiteLLM retry); without a
|
|
580
|
-
// 429 the same code stays a deterministic quota refusal.
|
|
581
|
-
const permanentCodes = new Set(['insufficient_quota', 'quota_exceeded']);
|
|
582
|
-
if (status !== 429) permanentCodes.add('resource_exhausted');
|
|
583
|
-
for (const item of boundedCauseChain(err)) {
|
|
584
|
-
const codes = [item?.code, item?.error?.code];
|
|
585
|
-
if (codes.some((code) => permanentCodes.has(String(code || '').toLowerCase()))) return true;
|
|
586
|
-
}
|
|
587
|
-
return false;
|
|
497
|
+
return QUOTA_KINDS.has(providerErrorKind(err).kind);
|
|
588
498
|
}
|
|
589
499
|
|
|
590
500
|
// ── Wire error events: default-retry with a fatal-code deny-list ────────────
|
|
@@ -595,7 +505,7 @@ export function isPermanentQuotaError(err) {
|
|
|
595
505
|
// server_error, server_is_overloaded, slow_down, or an event with no code at
|
|
596
506
|
// all — is a server-side fault and is retried under the bounded budgets
|
|
597
507
|
// (observed live 2026-08-11: two turns failed on typed `server_error`
|
|
598
|
-
// response.failed events that
|
|
508
|
+
// response.failed events that are server-side faults).
|
|
599
509
|
export const WIRE_ERROR_FATAL_CODES = new Set([
|
|
600
510
|
'context_length_exceeded',
|
|
601
511
|
'context_window_exceeded',
|
|
@@ -614,17 +524,26 @@ export const WIRE_ERROR_FATAL_CODES = new Set([
|
|
|
614
524
|
'permission_error',
|
|
615
525
|
'permission_denied',
|
|
616
526
|
'billing_not_active',
|
|
527
|
+
// Billing / spend refusals.
|
|
528
|
+
'credit_balance_exhausted',
|
|
529
|
+
'organization_spend_limit_exceeded',
|
|
530
|
+
'project_spend_limit_exceeded',
|
|
531
|
+
'organization_usage_limit_exceeded',
|
|
532
|
+
'billing_hard_limit_reached',
|
|
533
|
+
'payment_required',
|
|
534
|
+
// Policy refusals.
|
|
535
|
+
'cyber_policy_violation',
|
|
536
|
+
'bio_policy_violation',
|
|
537
|
+
'misalignment_policy_violation',
|
|
538
|
+
'content_policy_violation',
|
|
539
|
+
'content_filter',
|
|
540
|
+
// Flex tier capacity: the same request at the same tier is refused again.
|
|
541
|
+
'flex_unavailable',
|
|
542
|
+
// Byte/media size and token context.
|
|
543
|
+
'request_too_large',
|
|
544
|
+
'model_context_window_exceeded',
|
|
617
545
|
]);
|
|
618
546
|
|
|
619
|
-
export function typedErrorCode(err) {
|
|
620
|
-
const failed = err?.responseFailed;
|
|
621
|
-
const detail = failed?.response?.error || failed?.error || err?.providerError || failed || null;
|
|
622
|
-
for (const field of [detail?.code, detail?.type, err?.providerErrorCode, err?.code, err?.error?.code]) {
|
|
623
|
-
if (typeof field === 'string' && field.trim()) return field.trim().toLowerCase();
|
|
624
|
-
}
|
|
625
|
-
return '';
|
|
626
|
-
}
|
|
627
|
-
|
|
628
547
|
/**
|
|
629
548
|
* True when the typed wire/SDK code is previous_response_not_found.
|
|
630
549
|
* Callers drop lastResponseId / previous_response_id and re-issue a full frame.
|
|
@@ -657,30 +576,15 @@ export function isStaleKeepAliveError(err) {
|
|
|
657
576
|
});
|
|
658
577
|
}
|
|
659
578
|
|
|
660
|
-
const RATE_LIMIT_RETRY_AFTER_RE = /try again in\s*(\d+(?:\.\d+)?)\s*(ms|s|seconds?)\b/i;
|
|
661
|
-
|
|
662
|
-
function rateLimitRetryAfterMsFromMessage(err) {
|
|
663
|
-
const failed = err?.responseFailed;
|
|
664
|
-
const detail = failed?.response?.error || failed?.error || err?.providerError || err?.error || null;
|
|
665
|
-
const messages = [detail?.message, err?.message];
|
|
666
|
-
for (const message of messages) {
|
|
667
|
-
if (typeof message !== 'string' || !message) continue;
|
|
668
|
-
const match = message.match(RATE_LIMIT_RETRY_AFTER_RE);
|
|
669
|
-
if (!match) continue;
|
|
670
|
-
const value = Number(match[1]);
|
|
671
|
-
if (!Number.isFinite(value) || value < 0) continue;
|
|
672
|
-
const unit = String(match[2] || '').toLowerCase();
|
|
673
|
-
return unit === 'ms' ? Math.ceil(value) : Math.ceil(value * 1000);
|
|
674
|
-
}
|
|
675
|
-
return null;
|
|
676
|
-
}
|
|
677
|
-
|
|
678
579
|
// 'transient' | 'permanent' for errors born from a provider wire error event;
|
|
679
580
|
// null for everything else (no blanket retry for untyped local failures).
|
|
581
|
+
// A fatal code or a deterministic kind (quota, billing, plan, policy, auth,
|
|
582
|
+
// permission, context, size) outranks any numeric 5xx the event carries.
|
|
680
583
|
function classifyWireErrorEvent(err) {
|
|
681
584
|
if (!err || (err.responseFailed == null && err.providerWireError !== true)) return null;
|
|
682
585
|
const code = typedErrorCode(err);
|
|
683
586
|
if (code && WIRE_ERROR_FATAL_CODES.has(code)) return 'permanent';
|
|
587
|
+
if (DETERMINISTIC_KINDS.has(providerErrorKind(err, { text: false }).kind)) return 'permanent';
|
|
684
588
|
return 'transient';
|
|
685
589
|
}
|
|
686
590
|
|
|
@@ -696,7 +600,7 @@ export function isRetryableWireErrorEvent(err) {
|
|
|
696
600
|
}
|
|
697
601
|
|
|
698
602
|
/**
|
|
699
|
-
*
|
|
603
|
+
* Mid-stream wire error event: a mid-stream wire fault is retryable even when the
|
|
700
604
|
* envelope type is invalid_request_error, unless a typed 4xx status or a
|
|
701
605
|
* deterministic refusal code (quota/context/auth) is present.
|
|
702
606
|
*/
|
|
@@ -50,6 +50,7 @@ export {
|
|
|
50
50
|
ANTHROPIC_RETRY_BACKOFF_MS,
|
|
51
51
|
ANTHROPIC_RETRY_JITTER_RATIO,
|
|
52
52
|
AnthropicFallbackTriggeredError,
|
|
53
|
+
ModelFallbackTriggeredError,
|
|
53
54
|
STREAM_STALL_RETRY_BUDGET_MS,
|
|
54
55
|
anthropicMaxAttempts,
|
|
55
56
|
anthropicRequestTimeoutMs,
|
|
@@ -71,6 +72,7 @@ export {
|
|
|
71
72
|
createStreamSafetyStamps,
|
|
72
73
|
emitProviderRetryStage,
|
|
73
74
|
isProviderRecoveryExhausted,
|
|
75
|
+
isProviderRecoveryTerminal,
|
|
74
76
|
markProviderRecoveryExhausted,
|
|
75
77
|
retryDelayLabel,
|
|
76
78
|
withRetry,
|