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,172 @@
|
|
|
1
|
+
// Shared by openai-compat-responses-native.test.mjs and the one-off generator
|
|
2
|
+
// that produced openai-compat-responses-head-parity.json by running these same
|
|
3
|
+
// captures against the pre-change (HEAD) converters.
|
|
4
|
+
import { sendCompatResponses } from './openai-compat-responses.mjs';
|
|
5
|
+
import { OpenAICompatProvider } from './openai-compat.mjs';
|
|
6
|
+
import { buildRequestBody } from './openai-responses-payload.mjs';
|
|
7
|
+
import { createProviderReplay } from './lib/provider-replay.mjs';
|
|
8
|
+
|
|
9
|
+
export const SERVER_CALL = {
|
|
10
|
+
type: 'tool_search_call',
|
|
11
|
+
id: 'ts_srv',
|
|
12
|
+
call_id: null,
|
|
13
|
+
execution: 'server',
|
|
14
|
+
arguments: { query: 'q' },
|
|
15
|
+
};
|
|
16
|
+
export const SERVER_OUTPUT = { type: 'tool_search_output', id: 'tso_srv', call_id: null, execution: 'server', tools: [] };
|
|
17
|
+
export const REPLY = { type: 'message', role: 'assistant', content: [{ type: 'output_text', text: 'ok' }] };
|
|
18
|
+
|
|
19
|
+
export const ROUTES = [
|
|
20
|
+
['opencode-go', 'gpt-5.5'],
|
|
21
|
+
['muse-code', 'muse-spark'],
|
|
22
|
+
['command-code', 'gpt-5.5'],
|
|
23
|
+
['custom-cmd', 'openai/gpt-5.6-sol'],
|
|
24
|
+
['openrouter', 'openai/gpt-5.5'],
|
|
25
|
+
['xai', 'grok-4'],
|
|
26
|
+
['opencode-go', 'grok-4'],
|
|
27
|
+
];
|
|
28
|
+
export const FIRST_PARTY = [
|
|
29
|
+
['openai', 'gpt-5.5'],
|
|
30
|
+
['openai-oauth', 'gpt-5.5'],
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
export const replayOwner = (name) => `compat-responses:${name}`;
|
|
34
|
+
|
|
35
|
+
const search = (name) => ({
|
|
36
|
+
provider: name,
|
|
37
|
+
openaiTools: [{ type: 'function', name: 'x', description: 'd', parameters: { type: 'object', properties: {} } }],
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
export function nativeHistory() {
|
|
41
|
+
return [
|
|
42
|
+
{ role: 'user', content: 'go' },
|
|
43
|
+
{
|
|
44
|
+
role: 'assistant',
|
|
45
|
+
content: '',
|
|
46
|
+
toolCalls: [
|
|
47
|
+
{ id: 'ts1', name: 'load_tool', arguments: { names: ['x'] }, nativeType: 'tool_search_call' },
|
|
48
|
+
{ id: 'cu1', name: 'apply_patch', arguments: { patch: 'P' }, nativeType: 'custom_tool_call' },
|
|
49
|
+
{ id: 'fn1', name: 'Read', arguments: { path: 'a' } },
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
{ role: 'tool', toolCallId: 'ts1', content: 'loaded' },
|
|
53
|
+
{ role: 'tool', toolCallId: 'cu1', content: 'patched' },
|
|
54
|
+
{ role: 'tool', toolCallId: 'fn1', content: 'file' },
|
|
55
|
+
{ role: 'user', content: 'next' },
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Left by a previous openai-oauth route: native search/custom calls, native
|
|
60
|
+
// search results carrying loaded tools, phase-tagged assistant turns, a Skill
|
|
61
|
+
// result with loadable tools, and a foreign openai-responses replay.
|
|
62
|
+
export function oauthHistory() {
|
|
63
|
+
return [
|
|
64
|
+
{ role: 'system', content: 'sys' },
|
|
65
|
+
{ role: 'user', content: 'go' },
|
|
66
|
+
{ role: 'assistant', content: 'working', phase: 'commentary', toolCalls: [] },
|
|
67
|
+
{
|
|
68
|
+
role: 'assistant',
|
|
69
|
+
content: 'looking',
|
|
70
|
+
phase: 'commentary',
|
|
71
|
+
reasoningItems: [{ id: 'rs', encrypted_content: 'ENC', summary: [] }],
|
|
72
|
+
toolCalls: [
|
|
73
|
+
{ id: 'ts1', name: 'load_tool', arguments: { names: ['x'] }, nativeType: 'tool_search_call' },
|
|
74
|
+
{ id: 'cu1', name: 'apply_patch', arguments: { patch: 'P' }, nativeType: 'custom_tool_call' },
|
|
75
|
+
{ id: 'sk1', name: 'Skill', arguments: { name: 's' } },
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
{ role: 'tool', toolCallId: 'ts1', content: 'loaded', nativeToolSearch: search('openai-oauth') },
|
|
79
|
+
{ role: 'tool', toolCallId: 'cu1', content: 'patched' },
|
|
80
|
+
{ role: 'tool', toolCallId: 'sk1', content: 'skill', nativeToolSearch: search('openai-oauth') },
|
|
81
|
+
{
|
|
82
|
+
role: 'assistant',
|
|
83
|
+
content: '',
|
|
84
|
+
toolCalls: [{ id: 'f2', name: 'Read', arguments: { path: 'a' } }],
|
|
85
|
+
providerReplay: createProviderReplay('openai-responses', [
|
|
86
|
+
{ type: 'tool_search_call', call_id: 'ts9', execution: 'client', arguments: {} },
|
|
87
|
+
]),
|
|
88
|
+
},
|
|
89
|
+
{ role: 'tool', toolCallId: 'f2', content: 'file' },
|
|
90
|
+
{ role: 'user', content: 'next' },
|
|
91
|
+
];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Same-owner replay envelope holding a server-executed search pair.
|
|
95
|
+
export function serverSearchReplayHistory(owner) {
|
|
96
|
+
return [
|
|
97
|
+
{ role: 'user', content: 'find tools' },
|
|
98
|
+
{
|
|
99
|
+
role: 'assistant',
|
|
100
|
+
content: 'done',
|
|
101
|
+
providerReplay: createProviderReplay(owner, [
|
|
102
|
+
{ type: 'reasoning', id: 'rs_1', encrypted_content: 'ENC', summary: [] },
|
|
103
|
+
SERVER_CALL,
|
|
104
|
+
SERVER_OUTPUT,
|
|
105
|
+
{ type: 'function_call', call_id: 'c1', name: 'Read', arguments: '{}' },
|
|
106
|
+
]),
|
|
107
|
+
toolCalls: [{ id: 'c1', name: 'Read', arguments: {} }],
|
|
108
|
+
},
|
|
109
|
+
{ role: 'tool', toolCallId: 'c1', content: 'ok' },
|
|
110
|
+
{ role: 'user', content: 'next' },
|
|
111
|
+
];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Pre-change flag-off cases: [label, history(name), providerState?]
|
|
115
|
+
export const COMPAT_CASES = [
|
|
116
|
+
['native', () => nativeHistory()],
|
|
117
|
+
['oauth', () => oauthHistory()],
|
|
118
|
+
['own-search-output', (name) => {
|
|
119
|
+
const h = nativeHistory();
|
|
120
|
+
h[2] = { ...h[2], nativeToolSearch: search(name) };
|
|
121
|
+
return h;
|
|
122
|
+
}],
|
|
123
|
+
['server-replay', (name, owner = replayOwner(name)) => serverSearchReplayHistory(owner)],
|
|
124
|
+
];
|
|
125
|
+
|
|
126
|
+
export function compatProvider(name, config = {}) {
|
|
127
|
+
const requests = [];
|
|
128
|
+
const provider = Object.assign(Object.create(OpenAICompatProvider.prototype), {
|
|
129
|
+
name,
|
|
130
|
+
config: { preconnect: false, ...config },
|
|
131
|
+
nativePdf: true,
|
|
132
|
+
client: {
|
|
133
|
+
responses: {
|
|
134
|
+
create: async (params) => {
|
|
135
|
+
requests.push(structuredClone(params));
|
|
136
|
+
return (async function* () {
|
|
137
|
+
yield {
|
|
138
|
+
type: 'response.completed',
|
|
139
|
+
response: { id: 'resp-1', model: params.model, status: 'completed', output: [REPLY] },
|
|
140
|
+
};
|
|
141
|
+
})();
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
return { provider, requests };
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export async function captureCompat(name, model, history, opts = {}, config = {}) {
|
|
150
|
+
const { provider, requests } = compatProvider(name, config);
|
|
151
|
+
await sendCompatResponses(provider, history, model, [], { sessionId: 'sess-1', ...opts });
|
|
152
|
+
return requests[0];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function captureFirstParty(name, model, history) {
|
|
156
|
+
return JSON.parse(JSON.stringify(buildRequestBody(history, model, [], { promptCacheProvider: name, sessionId: 'sess-1' })));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export async function captureAll() {
|
|
160
|
+
const out = {};
|
|
161
|
+
for (const [name, model] of ROUTES) {
|
|
162
|
+
for (const [label, build] of COMPAT_CASES) {
|
|
163
|
+
out[`compat/${name}/${model}/${label}`] = await captureCompat(name, model, build(name));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
for (const [name, model] of FIRST_PARTY) {
|
|
167
|
+
for (const [label, build] of COMPAT_CASES) {
|
|
168
|
+
out[`first-party/${name}/${label}`] = captureFirstParty(name, model, build(name, 'openai-responses'));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return out;
|
|
172
|
+
}
|
|
@@ -139,11 +139,11 @@ export function createResponsesOutcomeStamper(state, leakedCalls) {
|
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
/** A streamed function_call whose id/name never arrived cannot be dispatched. */
|
|
142
|
-
export function unresolvedSalvageError(state) {
|
|
142
|
+
export function unresolvedSalvageError(state, label) {
|
|
143
143
|
const unresolved = state.toolCalls.find((t) => t._pendingItemId);
|
|
144
144
|
if (!unresolved) return null;
|
|
145
145
|
return new Error(
|
|
146
|
-
|
|
146
|
+
`${label || 'compat Responses'} stream function_call salvage failed: missing call_id/name for item_id=${unresolved._pendingItemId || '?'}`
|
|
147
147
|
);
|
|
148
148
|
}
|
|
149
149
|
|
|
@@ -169,5 +169,6 @@ export function finalizeResponsesStream(state, { leakedCalls, parseResponsesTool
|
|
|
169
169
|
model: state.model || response.model || null,
|
|
170
170
|
responseId: state.responseId || response.id || null,
|
|
171
171
|
stopReason: state.stopReason || null,
|
|
172
|
+
reasoningEmitted: state.emittedReasoning === true,
|
|
172
173
|
};
|
|
173
174
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
// turn tool loops keep the model's reasoning chain without server storage.
|
|
8
8
|
|
|
9
9
|
import { markProviderRecoveryExhausted, withRetry } from './retry-classifier.mjs';
|
|
10
|
+
import { compatRetryOptions, withCompatRetryProfile } from './openai-compat-retry-profile.mjs';
|
|
10
11
|
import { consumeCompatResponsesStream } from './openai-compat-stream.mjs';
|
|
11
12
|
import { getModelMetadataSync } from './model-catalog.mjs';
|
|
12
13
|
import { PROVIDER_FIRST_BYTE_TIMEOUT_MS, createPassthroughSignal } from '../stall-policy.mjs';
|
|
@@ -21,9 +22,12 @@ import {
|
|
|
21
22
|
toXaiResponsesInput,
|
|
22
23
|
xaiSystemInstructions,
|
|
23
24
|
} from './openai-compat-wire.mjs';
|
|
25
|
+
import { nativeDeferredFamilyForRoute } from './wire-route.mjs';
|
|
24
26
|
import { preparePdfTextForProvider } from './media-normalization.mjs';
|
|
25
27
|
import { normalizeOpencodeGoReasoningEffort } from './openai-compat-xai.mjs';
|
|
26
28
|
import { isCustomProviderName, resolveCustomReasoning } from './custom-reasoning.mjs';
|
|
29
|
+
import { projectEffortConfiguration, withEffortConfigurationFallback } from './effort-configuration.mjs';
|
|
30
|
+
import { normalizeCacheKey } from '../agent-runtime/cache-strategy.mjs';
|
|
27
31
|
import { createProviderReplay } from './lib/provider-replay.mjs';
|
|
28
32
|
import {
|
|
29
33
|
applyCompatToolChoice,
|
|
@@ -53,9 +57,88 @@ function resolveReasoning(provider, useModel, opts) {
|
|
|
53
57
|
return reasoningEffort ? { effort: reasoningEffort } : null;
|
|
54
58
|
}
|
|
55
59
|
|
|
60
|
+
/**
|
|
61
|
+
* A custom route's mid-conversation effort projection (GPT-6+ on this wire)
|
|
62
|
+
* with every effort in the row's wire value, or null for the per-request
|
|
63
|
+
* effort. Consecutive efforts sharing one wire value collapse into none; an
|
|
64
|
+
* effort the row cannot serve falls back to the per-request effort.
|
|
65
|
+
*/
|
|
66
|
+
function customEffortProjection(provider, useModel, messages, opts) {
|
|
67
|
+
if (!isCustomProviderName(provider.name)) return null;
|
|
68
|
+
const projection = projectEffortConfiguration(messages, provider.name, useModel, {
|
|
69
|
+
...opts,
|
|
70
|
+
protocol: 'openai-responses',
|
|
71
|
+
});
|
|
72
|
+
if (!projection) return null;
|
|
73
|
+
const model = provider.getCachedModelInfo?.(useModel) || null;
|
|
74
|
+
const wire = (effort) =>
|
|
75
|
+
resolveCustomReasoning({ protocol: 'openai-responses', model, effort }).fields.reasoning?.effort || null;
|
|
76
|
+
const initialEffort = wire(projection.initialEffort);
|
|
77
|
+
if (!initialEffort) return null;
|
|
78
|
+
const updates = new Map();
|
|
79
|
+
let current = initialEffort;
|
|
80
|
+
for (const [message, effort] of projection.updates) {
|
|
81
|
+
const value = wire(effort);
|
|
82
|
+
if (!value) return null;
|
|
83
|
+
if (value !== current) {
|
|
84
|
+
current = value;
|
|
85
|
+
updates.set(message, value);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return { ...projection, initialEffort, effort: current, updates };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Whether the endpoint takes `prompt_cache_key`. An explicit
|
|
92
|
+
// `opts.responsesPromptCacheKey` / `config.responsesPromptCacheKey` boolean
|
|
93
|
+
// decides; otherwise only custom routes (which always had it) send it.
|
|
94
|
+
function supportsPromptCacheKey(provider, opts) {
|
|
95
|
+
const declared = opts.responsesPromptCacheKey ?? provider.config?.responsesPromptCacheKey;
|
|
96
|
+
return typeof declared === 'boolean' ? declared : isCustomProviderName(provider.name);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Native Responses items (tool_search_call/output, custom_tool_call/output) in
|
|
100
|
+
// replayed history are strictly opt-in: only a route that declares
|
|
101
|
+
// `responsesNativeItems: true` (opts or config) gets the first-party lowering.
|
|
102
|
+
// Every other route keeps the function-only lowering byte for byte.
|
|
103
|
+
function supportsNativeResponsesItems(provider, opts) {
|
|
104
|
+
return (opts.responsesNativeItems ?? provider.config?.responsesNativeItems) === true || hasNativeDeferredTools(provider, opts);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// A session whose pinned route verified native deferred tools on the Responses
|
|
108
|
+
// wire (flag off in every PROFILES entry today): tool_search is declared
|
|
109
|
+
// natively and loaded tools replay as tool_search_output.
|
|
110
|
+
function hasNativeDeferredTools(provider, opts) {
|
|
111
|
+
return nativeDeferredFamilyForRoute(provider.name, opts.wireRoute ?? opts.session?.wireRoute) === 'openai';
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* A route's session identity: its prompt_cache_key and (custom routes) session
|
|
116
|
+
* headers, '' without a session. The session wins over the provider-scoped
|
|
117
|
+
* cache key, so parallel sessions never evict each other; a one-shot role
|
|
118
|
+
* ('shared' scope, a fresh session per call) keys on the provider key instead.
|
|
119
|
+
* Never the effort, so an effort change keeps the cache routing.
|
|
120
|
+
*/
|
|
121
|
+
function customSessionCacheKey(provider, opts) {
|
|
122
|
+
if (!supportsPromptCacheKey(provider, opts)) return '';
|
|
123
|
+
const explicit = opts.promptCacheKey || opts.providerCacheKey || opts.session?.promptCacheKey;
|
|
124
|
+
return normalizeCacheKey(
|
|
125
|
+
opts.promptCacheScope === 'shared' ? explicit || opts.sessionId : opts.sessionId || explicit
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
56
129
|
/** The request body: lowered transcript plus the per-turn knobs (output cap,
|
|
57
|
-
* tools and tool choice, reasoning effort). */
|
|
58
|
-
function buildCompatResponsesParams({
|
|
130
|
+
* tools and tool choice, reasoning effort, session cache key). */
|
|
131
|
+
function buildCompatResponsesParams({
|
|
132
|
+
provider,
|
|
133
|
+
useModel,
|
|
134
|
+
input,
|
|
135
|
+
previousResponseId,
|
|
136
|
+
tools,
|
|
137
|
+
opts,
|
|
138
|
+
instructions,
|
|
139
|
+
effortProjection,
|
|
140
|
+
sessionCacheKey,
|
|
141
|
+
}) {
|
|
59
142
|
const params = {
|
|
60
143
|
model: useModel,
|
|
61
144
|
input,
|
|
@@ -67,18 +150,27 @@ function buildCompatResponsesParams({ provider, useModel, input, previousRespons
|
|
|
67
150
|
const maxOutputTokens = resolveCompatMaxOutputTokens(opts);
|
|
68
151
|
if (maxOutputTokens) params.max_output_tokens = maxOutputTokens;
|
|
69
152
|
if (tools?.length) {
|
|
70
|
-
params.tools = toResponsesTools(tools, {
|
|
153
|
+
params.tools = toResponsesTools(tools, {
|
|
154
|
+
provider: provider.name,
|
|
155
|
+
onToolExcluded: opts.onToolExcluded,
|
|
156
|
+
...(hasNativeDeferredTools(provider, opts) ? { nativeDeferredTools: true } : {}),
|
|
157
|
+
});
|
|
71
158
|
params.parallel_tool_calls = true;
|
|
72
159
|
}
|
|
73
160
|
applyCompatToolChoice(params, opts);
|
|
74
|
-
|
|
161
|
+
// A projected conversation keeps its initial effort on top; changes ride as input items.
|
|
162
|
+
const reasoning = effortProjection
|
|
163
|
+
? { effort: effortProjection.initialEffort }
|
|
164
|
+
: resolveReasoning(provider, useModel, opts);
|
|
75
165
|
if (reasoning) params.reasoning = reasoning;
|
|
76
166
|
// Opt-in system-as-instructions: set before the hook so the hook can override it.
|
|
77
167
|
if (instructions) params.instructions = instructions;
|
|
168
|
+
if (sessionCacheKey) params.prompt_cache_key = sessionCacheKey;
|
|
78
169
|
// Opt-in per-provider final shaping (a provider passes the hook in its config).
|
|
79
170
|
const hook = provider.config?.responsesParamsHook;
|
|
80
171
|
if (typeof hook === 'function') {
|
|
81
|
-
const modelInfo =
|
|
172
|
+
const modelInfo =
|
|
173
|
+
(typeof provider.getCachedModelInfo === 'function' && provider.getCachedModelInfo(useModel)) || null;
|
|
82
174
|
hook(params, { useModel, opts, modelInfo });
|
|
83
175
|
}
|
|
84
176
|
return params;
|
|
@@ -90,16 +182,16 @@ function buildCompatResponsesParams({ provider, useModel, input, previousRespons
|
|
|
90
182
|
* that re-opens the request. A content-idle stall is terminal for this
|
|
91
183
|
* transport, so it is marked recovery-exhausted rather than retried.
|
|
92
184
|
*/
|
|
93
|
-
async function streamCompatResponses({ provider, params, label, signal, opts }) {
|
|
185
|
+
async function streamCompatResponses({ provider, params, label, signal, opts, headers }) {
|
|
94
186
|
const totalSignal = createPassthroughSignal(signal);
|
|
95
187
|
try {
|
|
96
188
|
return await withRetry(
|
|
97
|
-
async ({ signal: attemptSignal }) => {
|
|
189
|
+
withCompatRetryProfile(provider.name, async ({ signal: attemptSignal }) => {
|
|
98
190
|
const stream = await withRetry(
|
|
99
191
|
({ signal: openSignal }) =>
|
|
100
192
|
provider.client.responses.create(params, {
|
|
101
193
|
signal: openSignal,
|
|
102
|
-
...(
|
|
194
|
+
...(headers ? { headers } : {}),
|
|
103
195
|
}),
|
|
104
196
|
{
|
|
105
197
|
signal: attemptSignal,
|
|
@@ -130,11 +222,12 @@ async function streamCompatResponses({ provider, params, label, signal, opts })
|
|
|
130
222
|
}
|
|
131
223
|
throw error;
|
|
132
224
|
}
|
|
133
|
-
},
|
|
225
|
+
}),
|
|
134
226
|
{
|
|
135
227
|
signal: totalSignal.signal,
|
|
136
228
|
onRetry: compatStreamRetryReporter(label, opts),
|
|
137
229
|
retry529: opts.retry529,
|
|
230
|
+
...compatRetryOptions(provider.name),
|
|
138
231
|
}
|
|
139
232
|
);
|
|
140
233
|
} finally {
|
|
@@ -142,12 +235,36 @@ async function streamCompatResponses({ provider, params, label, signal, opts })
|
|
|
142
235
|
}
|
|
143
236
|
}
|
|
144
237
|
|
|
238
|
+
// OpenRouter's Responses endpoint is stateless: it does not store responses or
|
|
239
|
+
// resolve `previous_response_id`. Imported server-side continuation state (a
|
|
240
|
+
// previous id, or a stored response) is rejected up front rather than sent.
|
|
241
|
+
function assertOpenRouterStateless(provider, opts) {
|
|
242
|
+
if (provider.name !== 'openrouter') return;
|
|
243
|
+
const imported = opts.providerState?.[COMPAT_RESPONSES_STATE_KEY];
|
|
244
|
+
const previous = typeof imported?.previousResponseId === 'string' && imported.previousResponseId !== '';
|
|
245
|
+
if (!previous && imported?.store !== true) return;
|
|
246
|
+
throw Object.assign(
|
|
247
|
+
new Error(
|
|
248
|
+
'openrouter Responses is stateless: imported previous_response_id / store:true continuation state is not supported'
|
|
249
|
+
),
|
|
250
|
+
{ code: 'OPENROUTER_RESPONSES_STATELESS_ONLY', provider: provider.name }
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
145
254
|
/**
|
|
146
255
|
* Send one turn over `POST {baseURL}/responses` (streaming) using the
|
|
147
256
|
* provider's existing OpenAI SDK client. Returns the same result shape as
|
|
148
|
-
* the chat/completions path so the agent loop stays wire-agnostic.
|
|
257
|
+
* the chat/completions path so the agent loop stays wire-agnostic. A custom
|
|
258
|
+
* route whose model rejects the mid-conversation effort update is replayed
|
|
259
|
+
* once with the per-request effort.
|
|
149
260
|
*/
|
|
150
|
-
export
|
|
261
|
+
export function sendCompatResponses(provider, messages, useModel, tools, opts = {}) {
|
|
262
|
+
const send = (sendOpts) => sendCompatResponsesOnce(provider, messages, useModel, tools, sendOpts);
|
|
263
|
+
if (!isCustomProviderName(provider.name)) return send(opts);
|
|
264
|
+
return withEffortConfigurationFallback(provider.name, useModel, opts, send);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
async function sendCompatResponsesOnce(provider, messages, useModel, tools, opts) {
|
|
151
268
|
const replayProvider = compatResponsesReplayProvider(provider.name);
|
|
152
269
|
const signal = opts.signal || null;
|
|
153
270
|
if (signal?.aborted) {
|
|
@@ -156,17 +273,21 @@ export async function sendCompatResponses(provider, messages, useModel, tools, o
|
|
|
156
273
|
}
|
|
157
274
|
const label = `${provider.name}:responses`;
|
|
158
275
|
messages = await preparePdfTextForProvider(messages, provider);
|
|
276
|
+
assertOpenRouterStateless(provider, opts);
|
|
277
|
+
const effortProjection = customEffortProjection(provider, useModel, messages, opts);
|
|
278
|
+
const sessionCacheKey = customSessionCacheKey(provider, opts);
|
|
159
279
|
const { input, previousResponseId, continuationResetReason } = toXaiResponsesInput(messages, opts.providerState, {
|
|
280
|
+
effortProjection,
|
|
160
281
|
model: useModel,
|
|
161
282
|
stateKey: COMPAT_RESPONSES_STATE_KEY,
|
|
162
283
|
replayProvider,
|
|
163
284
|
providerName: provider.name,
|
|
285
|
+
nativeLowering: supportsNativeResponsesItems(provider, opts),
|
|
164
286
|
nativePdf: provider.nativePdf,
|
|
165
287
|
// Opt-in: system prompts travel as top-level `instructions`, not input items.
|
|
166
288
|
includeSystem: provider.config?.responsesSystemAsInstructions !== true,
|
|
167
289
|
});
|
|
168
|
-
const instructions =
|
|
169
|
-
provider.config?.responsesSystemAsInstructions === true ? xaiSystemInstructions(messages) : '';
|
|
290
|
+
const instructions = provider.config?.responsesSystemAsInstructions === true ? xaiSystemInstructions(messages) : '';
|
|
170
291
|
const params = buildCompatResponsesParams({
|
|
171
292
|
provider,
|
|
172
293
|
useModel,
|
|
@@ -175,14 +296,20 @@ export async function sendCompatResponses(provider, messages, useModel, tools, o
|
|
|
175
296
|
tools,
|
|
176
297
|
opts,
|
|
177
298
|
instructions,
|
|
299
|
+
effortProjection,
|
|
300
|
+
sessionCacheKey,
|
|
178
301
|
});
|
|
302
|
+
// The session identity also travels as headers; caller headers win.
|
|
303
|
+
const headers = sessionCacheKey && isCustomProviderName(provider.name)
|
|
304
|
+
? { 'session-id': sessionCacheKey, 'x-client-request-id': sessionCacheKey, ...opts.requestHeaders }
|
|
305
|
+
: opts.requestHeaders;
|
|
179
306
|
|
|
180
307
|
try {
|
|
181
308
|
opts.onStageChange?.('requesting');
|
|
182
309
|
} catch {
|
|
183
310
|
/* heartbeat best-effort */
|
|
184
311
|
}
|
|
185
|
-
const streamed = await streamCompatResponses({ provider, params, label, signal, opts });
|
|
312
|
+
const streamed = await streamCompatResponses({ provider, params, label, signal, opts, headers });
|
|
186
313
|
const response = streamed.response;
|
|
187
314
|
const usage = response?.usage || null;
|
|
188
315
|
const inputTokens = Number(usage?.input_tokens ?? usage?.prompt_tokens ?? 0);
|
|
@@ -206,7 +333,7 @@ export async function sendCompatResponses(provider, messages, useModel, tools, o
|
|
|
206
333
|
const messageIndex = Array.isArray(messages) ? messages.length : 0;
|
|
207
334
|
const encryptedReasoningHistory = [
|
|
208
335
|
...(Array.isArray(priorState?.encryptedReasoningHistory) ? priorState.encryptedReasoningHistory : []),
|
|
209
|
-
...(reasoningItems.length ? [{ messageIndex, items: reasoningItems }] : []),
|
|
336
|
+
...(reasoningItems.length ? [{ messageIndex, items: reasoningItems, owner: replayProvider }] : []),
|
|
210
337
|
];
|
|
211
338
|
const searchSources = collectCompatResponseSearchSources(response);
|
|
212
339
|
const usageSummary = usage ? responsesUsage(usage) : undefined;
|
|
@@ -215,6 +342,7 @@ export async function sendCompatResponses(provider, messages, useModel, tools, o
|
|
|
215
342
|
model: response?.model || useModel,
|
|
216
343
|
toolCalls: streamed.toolCalls,
|
|
217
344
|
stopReason: streamed.stopReason || null,
|
|
345
|
+
...(streamed.refusal ? { refusal: streamed.refusal } : {}),
|
|
218
346
|
...(streamed.stopReason === 'length' && (streamed.content || '').length > 0 ? { truncated: true } : {}),
|
|
219
347
|
citations: searchSources.citations.length ? searchSources.citations : undefined,
|
|
220
348
|
webSearchCalls: searchSources.webSearchCalls.length ? searchSources.webSearchCalls : undefined,
|
|
@@ -225,6 +353,7 @@ export async function sendCompatResponses(provider, messages, useModel, tools, o
|
|
|
225
353
|
previousResponseId: null,
|
|
226
354
|
responseId: response?.id || null,
|
|
227
355
|
store: false,
|
|
356
|
+
owner: replayProvider,
|
|
228
357
|
encryptedReasoningItems: reasoningItems,
|
|
229
358
|
encryptedReasoningHistory,
|
|
230
359
|
seenMessageCount: messageIndex,
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
// Per-provider request retry profile for the OpenAI-compatible family. Each
|
|
2
|
+
// provider carries its own retry constants; the
|
|
3
|
+
// shared withRetry still owns classification, the exposure/replay veto,
|
|
4
|
+
// quota refusals, x-should-retry and Retry-After. Providers with no profile
|
|
5
|
+
// keep the shared defaults.
|
|
6
|
+
//
|
|
7
|
+
// `backoffMs[n]` is the base wait before retry n (index 0 is never read, so
|
|
8
|
+
// the first value is the duplicate the withRetry schedule expects).
|
|
9
|
+
// statusRetryCaps — retries allowed for one status (for example a
|
|
10
|
+
// 429 stops after a single retry, whatever the overall budget).
|
|
11
|
+
// terminalStatuses — statuses that are terminal although the
|
|
12
|
+
// shared classifier would retry them.
|
|
13
|
+
// retryOnlyStatuses — the complete retryable error set: any other 4xx/5xx
|
|
14
|
+
// status surfaces.
|
|
15
|
+
// maxRetryAfterMs — give up instead of waiting longer than this.
|
|
16
|
+
// maxFailedAttemptMs — a 5xx that took longer than this is not replayed.
|
|
17
|
+
// retryEmptyResponse — a completed turn with no text, tool call or
|
|
18
|
+
// reasoning is re-asked inside the ladder (nothing was exposed); a number
|
|
19
|
+
// bounds how many times per send, true leaves it to the ladder.
|
|
20
|
+
// adviceWindow - outside exceptStatuses, Retry-After is clamped to maxMs
|
|
21
|
+
// and jittered by jitterRatio (the advice of the excepted statuses stays raw).
|
|
22
|
+
// recycleDispatcherOn5xx — a retried 5xx rebuilds the shared HTTP pool.
|
|
23
|
+
// adviceAtLeastBackoff — the advice is a floor under the jittered backoff step.
|
|
24
|
+
// Every stop is provider-terminal: the profile's limits are final, so the
|
|
25
|
+
// agent loop never re-runs a stopped or exhausted request (see
|
|
26
|
+
// COMPAT_RETRY_POLICY).
|
|
27
|
+
import { markProviderRecoveryExhausted } from './retry-classifier.mjs';
|
|
28
|
+
import { retryAfterMsFromError } from './provider-error-kind.mjs';
|
|
29
|
+
import { STREAM_TRANSPORTS, stampStreamOutcome } from './lib/stream-outcome.mjs';
|
|
30
|
+
import { jitterDelayMs } from './retry-backoff.mjs';
|
|
31
|
+
|
|
32
|
+
const statusOf = (err) => Number(err?.httpStatus || err?.status || err?.response?.status || 0);
|
|
33
|
+
|
|
34
|
+
/** Loop retry policy of every profiled provider: no recovery cycles on top of the profile. */
|
|
35
|
+
export const COMPAT_RETRY_POLICY = Object.freeze({ recoveryCycles: false });
|
|
36
|
+
|
|
37
|
+
/** xAI additionally treats an in-band invalid-request error as retryable. */
|
|
38
|
+
export const XAI_COMPAT_RETRY_POLICY = Object.freeze({ ...COMPAT_RETRY_POLICY, inBandInvalidRequestRetryable: true });
|
|
39
|
+
|
|
40
|
+
export const COMPAT_RETRY_PROFILES = Object.freeze({
|
|
41
|
+
// A budget of 15 sends (the retry limit is reached when the next retry number
|
|
42
|
+
// equals it, so 14 waits), 2s doubling to 30s, ±20% jitter, one retry for a
|
|
43
|
+
// 429. Outside a 429, Retry-After is capped at 30s and jittered.
|
|
44
|
+
xai: Object.freeze({
|
|
45
|
+
maxAttempts: 15,
|
|
46
|
+
backoffMs: [2000, 2000, 4000, 8000, 16000, 30000],
|
|
47
|
+
retryJitterRatio: 0.2,
|
|
48
|
+
statusRetryCaps: { 429: 1 },
|
|
49
|
+
terminalStatuses: [408, 409, 425],
|
|
50
|
+
retryEmptyResponse: true,
|
|
51
|
+
adviceWindow: Object.freeze({ maxMs: 30_000, jitterRatio: 0.2, exceptStatuses: [429] }),
|
|
52
|
+
recycleDispatcherOn5xx: true,
|
|
53
|
+
}),
|
|
54
|
+
// 5 retries, 500ms doubling to 10s, ±10% jitter;
|
|
55
|
+
// a Retry-After beyond the 10s ceiling is not waited out.
|
|
56
|
+
deepseek: Object.freeze({
|
|
57
|
+
maxAttempts: 6,
|
|
58
|
+
backoffMs: [500, 500, 1000, 2000, 4000, 8000],
|
|
59
|
+
retryJitterRatio: 0.1,
|
|
60
|
+
maxRetryAfterMs: 10_000,
|
|
61
|
+
terminalStatuses: [408, 409, 425],
|
|
62
|
+
retryEmptyResponse: true,
|
|
63
|
+
}),
|
|
64
|
+
// The HTTP transport layer governs one request: 6 sends, 500ms doubling, no
|
|
65
|
+
// jitter, a Retry-After beyond 60s is not waited out; only 408, 429 and 5xx
|
|
66
|
+
// are transient, every other 4xx is terminal. A benign empty completion is
|
|
67
|
+
// re-asked at most twice.
|
|
68
|
+
'muse-code-oauth': Object.freeze({
|
|
69
|
+
maxAttempts: 6,
|
|
70
|
+
backoffMs: [500, 500, 1000, 2000, 4000, 8000],
|
|
71
|
+
retryJitterRatio: 0,
|
|
72
|
+
terminalStatuses: [409, 425],
|
|
73
|
+
maxRetryAfterMs: 60_000,
|
|
74
|
+
retryEmptyResponse: 2,
|
|
75
|
+
}),
|
|
76
|
+
// server budget 8 retries (2s doubling to 30s,
|
|
77
|
+
// ±10%), rate-limit budget 5 retries; 408, 409, 501 and 505 are terminal
|
|
78
|
+
// (425 stays retryable); a Retry-After beyond 300s is not waited out.
|
|
79
|
+
'mimo-oauth': Object.freeze({
|
|
80
|
+
maxAttempts: 9,
|
|
81
|
+
backoffMs: [2000, 2000, 4000, 8000, 16000, 30000],
|
|
82
|
+
retryJitterRatio: 0.1,
|
|
83
|
+
statusRetryCaps: { 429: 5 },
|
|
84
|
+
terminalStatuses: [408, 409, 501, 505],
|
|
85
|
+
maxRetryAfterMs: 300_000,
|
|
86
|
+
}),
|
|
87
|
+
// 3 sends (400ms doubling to 5s) for exactly
|
|
88
|
+
// 500/502/503/504/520/521/522 — every 4xx (429 included) and every other
|
|
89
|
+
// 5xx is terminal; a failed attempt slower than 15s is returned.
|
|
90
|
+
'command-code-oauth': Object.freeze({
|
|
91
|
+
maxAttempts: 3,
|
|
92
|
+
backoffMs: [400, 400, 800],
|
|
93
|
+
retryOnlyStatuses: [500, 502, 503, 504, 520, 521, 522],
|
|
94
|
+
maxFailedAttemptMs: 15_000,
|
|
95
|
+
maxRetryAfterMs: 60_000,
|
|
96
|
+
adviceAtLeastBackoff: true,
|
|
97
|
+
}),
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
/** withRetry options (attempt budget, schedule, jitter) for a provider; {} for the shared defaults. */
|
|
101
|
+
export function compatRetryOptions(providerName) {
|
|
102
|
+
const profile = COMPAT_RETRY_PROFILES[providerName];
|
|
103
|
+
if (!profile) return {};
|
|
104
|
+
return {
|
|
105
|
+
maxAttempts: profile.maxAttempts,
|
|
106
|
+
backoffMs: profile.backoffMs,
|
|
107
|
+
retryJitterRatio: profile.retryJitterRatio,
|
|
108
|
+
finalOnExhaust: true,
|
|
109
|
+
...(profile.adviceAtLeastBackoff ? { adviceAtLeastBackoff: true } : {}),
|
|
110
|
+
...(profile.recycleDispatcherOn5xx ? { recycleDispatcherOn5xx: true } : {}),
|
|
111
|
+
...(profile.retryJitterMode ? { retryJitterMode: profile.retryJitterMode } : {}),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function profileStops(profile, err, { attempt, elapsedMs }) {
|
|
116
|
+
const status = statusOf(err);
|
|
117
|
+
if (profile.terminalStatuses?.includes(status)) return true;
|
|
118
|
+
const cap = profile.statusRetryCaps?.[status];
|
|
119
|
+
if (cap !== undefined && attempt >= cap) return true;
|
|
120
|
+
if (profile.retryOnlyStatuses && status >= 400 && status < 600 && !profile.retryOnlyStatuses.includes(status)) {
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
if (profile.maxFailedAttemptMs && status >= 500 && status < 600 && elapsedMs > profile.maxFailedAttemptMs) {
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
const advice = retryAfterMsFromError(err);
|
|
127
|
+
return profile.maxRetryAfterMs !== undefined && advice != null && advice > profile.maxRetryAfterMs;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Restamps the advice as a deadline (the highest-precedence source) so the
|
|
131
|
+
// shared loop waits the clamped, jittered value instead of the raw one.
|
|
132
|
+
function shapeAdvice(window, err) {
|
|
133
|
+
if (!window || !err || typeof err !== 'object' || window.exceptStatuses?.includes(statusOf(err))) return;
|
|
134
|
+
const advice = retryAfterMsFromError(err);
|
|
135
|
+
if (advice == null) return;
|
|
136
|
+
err.retryAfterAt = Date.now() + jitterDelayMs(Math.min(advice, window.maxMs), window.jitterRatio);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// A completed turn that produced nothing: no text, tool call or reasoning, and
|
|
140
|
+
// a normal finish (a Responses turn carries no stop reason when it completes).
|
|
141
|
+
function isEmptyNormalFinish(result) {
|
|
142
|
+
if (!result || typeof result !== 'object') return false;
|
|
143
|
+
if (result.stopReason != null && result.stopReason !== 'stop') return false;
|
|
144
|
+
return (
|
|
145
|
+
!String(result.content ?? '').trim() &&
|
|
146
|
+
!result.toolCalls?.length &&
|
|
147
|
+
!result.reasoningContent &&
|
|
148
|
+
!result.reasoningDetails?.length &&
|
|
149
|
+
result.reasoningEmitted !== true
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function emptyResponseError(providerName) {
|
|
154
|
+
const err = Object.assign(new Error(`${providerName} returned an empty response`), {
|
|
155
|
+
code: 'server_error',
|
|
156
|
+
emptyResponse: true,
|
|
157
|
+
});
|
|
158
|
+
// The turn finished: a failed ladder must not reopen it as a non-streaming request.
|
|
159
|
+
stampStreamOutcome(err, { transport: STREAM_TRANSPORTS.SSE, terminalObserved: true });
|
|
160
|
+
return err;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Wrap one withRetry attempt with the provider's profile: a failure the
|
|
165
|
+
* profile treats as final is marked recovery-exhausted and provider-terminal
|
|
166
|
+
* (withRetry then surfaces it unchanged and no outer layer replays it), and a
|
|
167
|
+
* profiled empty response is raised as a retryable failure.
|
|
168
|
+
*/
|
|
169
|
+
export function withCompatRetryProfile(providerName, attemptFn) {
|
|
170
|
+
const profile = COMPAT_RETRY_PROFILES[providerName];
|
|
171
|
+
if (!profile) return attemptFn;
|
|
172
|
+
let emptyRetries = 0;
|
|
173
|
+
return async (ctx) => {
|
|
174
|
+
const startedAt = Date.now();
|
|
175
|
+
try {
|
|
176
|
+
const result = await attemptFn(ctx);
|
|
177
|
+
if (profile.retryEmptyResponse && isEmptyNormalFinish(result)) {
|
|
178
|
+
const bound = profile.retryEmptyResponse === true ? Infinity : profile.retryEmptyResponse;
|
|
179
|
+
if (emptyRetries < bound) {
|
|
180
|
+
emptyRetries += 1;
|
|
181
|
+
throw emptyResponseError(providerName);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return result;
|
|
185
|
+
} catch (err) {
|
|
186
|
+
if (profileStops(profile, err, { attempt: ctx?.attempt | 0, elapsedMs: Date.now() - startedAt })) {
|
|
187
|
+
throw markProviderRecoveryExhausted(err, { owner: `${providerName}-retry-profile`, terminal: true });
|
|
188
|
+
}
|
|
189
|
+
shapeAdvice(profile.adviceWindow, err);
|
|
190
|
+
throw err;
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
}
|