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
|
@@ -12,6 +12,41 @@ function normalizeReasoningEffort(value, allowed) {
|
|
|
12
12
|
return allowed.includes(effort) ? effort : null;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* OpenRouter's unified `reasoning` field, shared by its Chat and Responses
|
|
17
|
+
* wires: `openRouterReasoningEffort`, else the turn effort, else the configured
|
|
18
|
+
* effort; `none` disables reasoning. Null when no effort applies.
|
|
19
|
+
*/
|
|
20
|
+
export function openRouterReasoning(opts = {}, config = {}) {
|
|
21
|
+
const effort = normalizeReasoningEffort(opts.openRouterReasoningEffort ?? opts.effort ?? config?.reasoningEffort, [
|
|
22
|
+
'none',
|
|
23
|
+
'minimal',
|
|
24
|
+
'low',
|
|
25
|
+
'medium',
|
|
26
|
+
'high',
|
|
27
|
+
'xhigh',
|
|
28
|
+
'max',
|
|
29
|
+
]);
|
|
30
|
+
if (effort === 'none') return { enabled: false };
|
|
31
|
+
return effort ? { enabled: true, effort } : null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function deepseekRawEffort(opts, config) {
|
|
35
|
+
return opts.deepseekReasoningEffort ?? opts.effort ?? config?.reasoningEffort;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** 'enabled' | 'disabled' as the DeepSeek request will carry it, or null when nothing sets it. */
|
|
39
|
+
export function deepseekThinkingMode(opts = {}, config = {}) {
|
|
40
|
+
const rawThinking = opts.deepseekThinking ?? opts.thinking ?? config?.thinking;
|
|
41
|
+
const rawEffort = deepseekRawEffort(opts, config);
|
|
42
|
+
if (rawThinking === undefined && rawEffort === undefined) return null;
|
|
43
|
+
const thinkingMode = String(rawThinking?.type ?? rawThinking ?? rawEffort)
|
|
44
|
+
.trim()
|
|
45
|
+
.toLowerCase();
|
|
46
|
+
const disabled = rawThinking === false || thinkingMode === 'disabled' || thinkingMode === 'none';
|
|
47
|
+
return disabled ? 'disabled' : 'enabled';
|
|
48
|
+
}
|
|
49
|
+
|
|
15
50
|
// Keep provider extensions isolated: fields accepted by one OpenAI-compatible
|
|
16
51
|
// backend are frequently rejected by another even when the core Chat schema
|
|
17
52
|
// is shared.
|
|
@@ -23,22 +58,14 @@ export function applyCompatProviderChatOptions(params, providerName, opts = {},
|
|
|
23
58
|
protocol: 'openai-chat',
|
|
24
59
|
model: modelInfo,
|
|
25
60
|
effort: opts.effort ?? config?.reasoningEffort,
|
|
61
|
+
baseURL: config?.baseURL,
|
|
26
62
|
});
|
|
27
63
|
Object.assign(params, fields);
|
|
28
64
|
return params;
|
|
29
65
|
}
|
|
30
66
|
if (providerName === 'openrouter') {
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
'minimal',
|
|
34
|
-
'low',
|
|
35
|
-
'medium',
|
|
36
|
-
'high',
|
|
37
|
-
'xhigh',
|
|
38
|
-
'max',
|
|
39
|
-
]);
|
|
40
|
-
if (effort === 'none') params.reasoning = { enabled: false };
|
|
41
|
-
else if (effort) params.reasoning = { enabled: true, effort };
|
|
67
|
+
const reasoning = openRouterReasoning(opts, config);
|
|
68
|
+
if (reasoning) params.reasoning = reasoning;
|
|
42
69
|
return params;
|
|
43
70
|
}
|
|
44
71
|
if (providerName === 'xai') {
|
|
@@ -53,22 +80,17 @@ export function applyCompatProviderChatOptions(params, providerName, opts = {},
|
|
|
53
80
|
return params;
|
|
54
81
|
}
|
|
55
82
|
if (providerName === 'deepseek') {
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
.toLowerCase();
|
|
62
|
-
const disabled = rawThinking === false || thinkingMode === 'disabled' || thinkingMode === 'none';
|
|
63
|
-
params.thinking = { type: disabled ? 'disabled' : 'enabled' };
|
|
64
|
-
if (!disabled) {
|
|
65
|
-
const effort = String(rawEffort ?? '')
|
|
83
|
+
const mode = deepseekThinkingMode(opts, config);
|
|
84
|
+
if (mode) {
|
|
85
|
+
params.thinking = { type: mode };
|
|
86
|
+
if (mode === 'enabled') {
|
|
87
|
+
const effort = String(deepseekRawEffort(opts, config) ?? '')
|
|
66
88
|
.trim()
|
|
67
89
|
.toLowerCase();
|
|
68
|
-
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
else if (effort === 'low') params.reasoning_effort = 'low';
|
|
90
|
+
// DeepSeek documents low/high/max; `ultra` is its alias for max,
|
|
91
|
+
// `minimal` for low, `medium`/`xhigh` for high; `low` must not be promoted.
|
|
92
|
+
if (effort === 'max' || effort === 'ultra') params.reasoning_effort = 'max';
|
|
93
|
+
else if (effort === 'low' || effort === 'minimal') params.reasoning_effort = 'low';
|
|
72
94
|
else if (['medium', 'high', 'xhigh'].includes(effort)) params.reasoning_effort = 'high';
|
|
73
95
|
}
|
|
74
96
|
}
|
|
@@ -11,12 +11,16 @@ export const OPENAI_COMPAT_PRESETS = {
|
|
|
11
11
|
},
|
|
12
12
|
// OpenCode Go - low-cost coding-model subscription gateway.
|
|
13
13
|
'opencode-go': {
|
|
14
|
-
baseURL: 'https://opencode.ai/
|
|
14
|
+
baseURL: 'https://opencode.ai/inference/go/v1',
|
|
15
15
|
defaultModel: 'glm-5.2',
|
|
16
|
+
// The gateway expects an application User-Agent (not the SDK default).
|
|
17
|
+
extraHeaders: { 'User-Agent': 'mixdog' },
|
|
16
18
|
},
|
|
17
19
|
openrouter: {
|
|
18
20
|
baseURL: 'https://openrouter.ai/api/v1',
|
|
19
21
|
defaultModel: 'openrouter/auto',
|
|
22
|
+
// OpenRouter documents cache_control on Chat content blocks.
|
|
23
|
+
chatCacheControl: true,
|
|
20
24
|
extraHeaders: {
|
|
21
25
|
'HTTP-Referer': 'https://github.com/tribgames/mixdog',
|
|
22
26
|
'X-OpenRouter-Title': 'mixdog',
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* openai-compat-reasoning-field.mjs — provider-specific reasoning shapes on the
|
|
3
|
+
* Chat Completions wire that the plain `reasoning_content` string path misses.
|
|
4
|
+
*
|
|
5
|
+
* Together AI (docs.together.ai/docs/inference/chat/reasoning): the chain of
|
|
6
|
+
* thought arrives on `reasoning` OR `reasoning_content` (model dependent), on
|
|
7
|
+
* the message and on each streaming delta, and must be passed back "under the
|
|
8
|
+
* same key" on prior assistant turns. vLLM reports it on `reasoning` (formerly
|
|
9
|
+
* `reasoning_content`), Groq on `message.reasoning` (reasoning_format parsed).
|
|
10
|
+
* OpenRouter reports plain text on `reasoning` next to `reasoning_details`.
|
|
11
|
+
*
|
|
12
|
+
* Mistral (docs.mistral.ai/studio/conversations/reasoning): with reasoning on,
|
|
13
|
+
* `message.content` / `delta.content` is a list of typed chunks —
|
|
14
|
+
* `{type:'thinking', thinking:[{type:'text', text}]}` and `{type:'text', text}`
|
|
15
|
+
* — and the full assistant message, thinking chunk included, goes back in the
|
|
16
|
+
* history. Receiving is by the response shape (an array), never by model name.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/** `message.providerMetadata[key].reasoningField`: the key a reply's reasoning arrived on. */
|
|
20
|
+
export const COMPAT_REASONING_METADATA_KEY = 'openaiCompat';
|
|
21
|
+
|
|
22
|
+
const TOGETHER_HOSTS = ['together.xyz', 'together.ai'];
|
|
23
|
+
const GROQ_HOSTS = ['groq.com'];
|
|
24
|
+
const MISTRAL_HOSTS = ['mistral.ai'];
|
|
25
|
+
|
|
26
|
+
function hostMatches(baseURL, domains) {
|
|
27
|
+
let host;
|
|
28
|
+
try {
|
|
29
|
+
host = new URL(String(baseURL || '')).hostname.toLowerCase();
|
|
30
|
+
} catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
return domains.some((domain) => host === domain || host.endsWith(`.${domain}`));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function isTogetherBaseURL(baseURL) {
|
|
37
|
+
return hostMatches(baseURL, TOGETHER_HOSTS);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Where an endpoint family reports reasoning and how a prior turn's reasoning
|
|
42
|
+
* goes back. `readsReasoningAlias`: the `reasoning` key is a reasoning field
|
|
43
|
+
* (otherwise only `reasoning_content` is). `resend`:
|
|
44
|
+
* same_key — back under the key it arrived on (Together, vLLM)
|
|
45
|
+
* reasoning — plain text as `reasoning`; reasoning_details win (OpenRouter)
|
|
46
|
+
* content_chunks — as a `thinking` chunk in the assistant content (Mistral)
|
|
47
|
+
* none — never echoed; the docs do not ask for it (Groq)
|
|
48
|
+
*/
|
|
49
|
+
const SHAPES = Object.freeze({
|
|
50
|
+
together: Object.freeze({ id: 'together', readsReasoningAlias: true, resend: 'same_key' }),
|
|
51
|
+
vllm: Object.freeze({ id: 'vllm', readsReasoningAlias: true, resend: 'same_key' }),
|
|
52
|
+
groq: Object.freeze({ id: 'groq', readsReasoningAlias: true, resend: 'none' }),
|
|
53
|
+
mistral: Object.freeze({ id: 'mistral', readsReasoningAlias: false, resend: 'content_chunks' }),
|
|
54
|
+
openrouter: Object.freeze({ id: 'openrouter', readsReasoningAlias: true, resend: 'reasoning' }),
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The reasoning shape of a provider, or null for the plain `reasoning_content`
|
|
59
|
+
* path. OpenRouter is by provider name, Together/Groq/Mistral by the provider's
|
|
60
|
+
* own base URL, vLLM (no fixed host) by the model row's `vllm` wire format.
|
|
61
|
+
*/
|
|
62
|
+
export function compatReasoningShape({ providerName, baseURL, wireFormat } = {}) {
|
|
63
|
+
if (providerName === 'openrouter') return SHAPES.openrouter;
|
|
64
|
+
if (wireFormat === 'together' || isTogetherBaseURL(baseURL)) return SHAPES.together;
|
|
65
|
+
if (wireFormat === 'vllm') return SHAPES.vllm;
|
|
66
|
+
if (hostMatches(baseURL, GROQ_HOSTS)) return SHAPES.groq;
|
|
67
|
+
if (hostMatches(baseURL, MISTRAL_HOSTS)) return SHAPES.mistral;
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The receive field worth recording for replay: `reasoning` (non-default key)
|
|
73
|
+
* or `content_chunks` (Mistral), per shape; `reasoning_content` is the default
|
|
74
|
+
* and needs no record. Null when nothing needs remembering.
|
|
75
|
+
*/
|
|
76
|
+
export function replayReasoningField(shape, source) {
|
|
77
|
+
if (!shape) return null;
|
|
78
|
+
if (shape.resend === 'same_key' && source === 'reasoning') return 'reasoning';
|
|
79
|
+
if (shape.resend === 'content_chunks' && source === 'content_chunks') return 'content_chunks';
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Whether a reply's reasoning source is captured under this shape. */
|
|
84
|
+
export function capturesShapeReasoning(shape, source) {
|
|
85
|
+
if (!shape) return source === 'content_chunks';
|
|
86
|
+
if (source === 'content_chunks') return true;
|
|
87
|
+
return source === 'reasoning_content' || (shape.readsReasoningAlias && source === 'reasoning');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Assistant content with the prior reasoning replayed as a leading `thinking` chunk. */
|
|
91
|
+
export function contentWithThinkingChunk(content, reasoning) {
|
|
92
|
+
const thinking = { type: 'thinking', thinking: [{ type: 'text', text: reasoning }] };
|
|
93
|
+
if (Array.isArray(content)) return [thinking, ...content];
|
|
94
|
+
return typeof content === 'string' && content ? [thinking, { type: 'text', text: content }] : [thinking];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function thinkingText(thinking) {
|
|
98
|
+
if (typeof thinking === 'string') return thinking;
|
|
99
|
+
if (!Array.isArray(thinking)) return '';
|
|
100
|
+
return thinking
|
|
101
|
+
.map((inner) => (typeof inner === 'string' ? inner : typeof inner?.text === 'string' ? inner.text : ''))
|
|
102
|
+
.join('');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Ordered `{kind:'reasoning'|'text', text}` parts of an array-shaped `content`,
|
|
107
|
+
* or null when `content` is not an array (the plain string/absent shape).
|
|
108
|
+
*/
|
|
109
|
+
export function chatContentParts(content) {
|
|
110
|
+
if (!Array.isArray(content)) return null;
|
|
111
|
+
const parts = [];
|
|
112
|
+
for (const chunk of content) {
|
|
113
|
+
if (typeof chunk === 'string') {
|
|
114
|
+
parts.push({ kind: 'text', text: chunk });
|
|
115
|
+
} else if (chunk?.type === 'thinking') {
|
|
116
|
+
parts.push({ kind: 'reasoning', text: thinkingText(chunk.thinking) });
|
|
117
|
+
} else if (chunk?.type === 'text' && typeof chunk.text === 'string') {
|
|
118
|
+
parts.push({ kind: 'text', text: chunk.text });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return parts;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Content text, reasoning and reasoning source of one non-streaming message.
|
|
126
|
+
* `reasoning_content` keeps priority; the `reasoning` alias is read only under
|
|
127
|
+
* a shape that reports reasoning there; thinking chunks fill in when no field
|
|
128
|
+
* carried reasoning.
|
|
129
|
+
*/
|
|
130
|
+
export function readChatMessage(message, { shape = null } = {}) {
|
|
131
|
+
const parts = chatContentParts(message?.content);
|
|
132
|
+
const content = parts
|
|
133
|
+
? parts
|
|
134
|
+
.filter((part) => part.kind === 'text')
|
|
135
|
+
.map((part) => part.text)
|
|
136
|
+
.join('')
|
|
137
|
+
: typeof message?.content === 'string'
|
|
138
|
+
? message.content
|
|
139
|
+
: '';
|
|
140
|
+
if (typeof message?.reasoning_content === 'string') {
|
|
141
|
+
return { content, reasoningContent: message.reasoning_content, reasoningSource: 'reasoning_content' };
|
|
142
|
+
}
|
|
143
|
+
if (shape?.readsReasoningAlias && typeof message?.reasoning === 'string') {
|
|
144
|
+
return { content, reasoningContent: message.reasoning, reasoningSource: 'reasoning' };
|
|
145
|
+
}
|
|
146
|
+
const thinking = parts?.filter((part) => part.kind === 'reasoning');
|
|
147
|
+
if (thinking?.length) {
|
|
148
|
+
return { content, reasoningContent: thinking.map((part) => part.text).join(''), reasoningSource: 'content_chunks' };
|
|
149
|
+
}
|
|
150
|
+
return { content, reasoningContent: null, reasoningSource: null };
|
|
151
|
+
}
|
|
@@ -7,18 +7,20 @@ import {
|
|
|
7
7
|
writeXaiResponsesCacheTrace,
|
|
8
8
|
} from './openai-compat-xai.mjs';
|
|
9
9
|
import { createProviderReplay } from './lib/provider-replay.mjs';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
import { reportedCostUsd } from './lib/usage-primitives.mjs';
|
|
11
|
+
import { stampStreamOutcome, STREAM_TRANSPORTS } from './lib/stream-outcome.mjs';
|
|
12
|
+
import { failingFinishReasonError } from './openai-compat-stream-common.mjs';
|
|
13
|
+
import {
|
|
14
|
+
COMPAT_REASONING_METADATA_KEY,
|
|
15
|
+
capturesShapeReasoning,
|
|
16
|
+
replayReasoningField,
|
|
17
|
+
} from './openai-compat-reasoning-field.mjs';
|
|
13
18
|
|
|
14
19
|
export function compatReportedCostUsd(providerName, usage) {
|
|
15
|
-
if (providerName === 'openrouter')
|
|
16
|
-
const cost = reportedNumber(usage?.cost);
|
|
17
|
-
return Number.isFinite(cost) && cost >= 0 ? cost : undefined;
|
|
18
|
-
}
|
|
20
|
+
if (providerName === 'openrouter') return reportedCostUsd(usage?.cost);
|
|
19
21
|
if (providerName === 'xai') {
|
|
20
|
-
const ticks =
|
|
21
|
-
return
|
|
22
|
+
const ticks = reportedCostUsd(usage?.cost_in_usd_ticks);
|
|
23
|
+
return ticks === undefined ? undefined : Number((ticks * 1e-10).toFixed(8));
|
|
22
24
|
}
|
|
23
25
|
return undefined;
|
|
24
26
|
}
|
|
@@ -77,12 +79,11 @@ export function traceCompatResponseUsage({
|
|
|
77
79
|
});
|
|
78
80
|
}
|
|
79
81
|
|
|
80
|
-
// Responses-wire reported cost:
|
|
81
|
-
//
|
|
82
|
+
// Responses-wire reported cost: xAI `cost_in_usd_ticks` when present, else a
|
|
83
|
+
// gateway `cost` (decimal USD). null/empty/negative is "not reported", never a
|
|
84
|
+
// reported $0.
|
|
82
85
|
export function responsesReportedCostUsd(usage) {
|
|
83
|
-
|
|
84
|
-
if (Number.isFinite(cost) && cost >= 0) return cost;
|
|
85
|
-
return costUsdFromTicks(usage?.cost_in_usd_ticks);
|
|
86
|
+
return costUsdFromTicks(usage?.cost_in_usd_ticks) ?? reportedCostUsd(usage?.cost);
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
export function chatCompletionUsage(providerName, usage) {
|
|
@@ -136,11 +137,33 @@ export function normalizeCompatChatResponse({
|
|
|
136
137
|
cacheRoutingKey,
|
|
137
138
|
cacheRouting,
|
|
138
139
|
replaysReasoningContent,
|
|
140
|
+
reasoningShape = null,
|
|
139
141
|
}) {
|
|
140
142
|
const response = assembled.response;
|
|
141
143
|
const choice = response.choices[0];
|
|
142
144
|
const toolCalls = assembled.toolCalls;
|
|
143
145
|
const stopReason = choice?.finish_reason || null;
|
|
146
|
+
const failingFinish = failingFinishReasonError(stopReason, providerName);
|
|
147
|
+
if (failingFinish) {
|
|
148
|
+
const err = failingFinish;
|
|
149
|
+
const partialContent = assembled.content || '';
|
|
150
|
+
Object.assign(err, {
|
|
151
|
+
partialContent,
|
|
152
|
+
partialToolCalls: Array.isArray(toolCalls) && toolCalls.length ? toolCalls : undefined,
|
|
153
|
+
pendingToolUse: false,
|
|
154
|
+
partialModel: response.model || useModel,
|
|
155
|
+
...(response.usage ? { partialUsage: chatCompletionUsage(providerName, response.usage) } : {}),
|
|
156
|
+
});
|
|
157
|
+
stampStreamOutcome(err, {
|
|
158
|
+
transport: STREAM_TRANSPORTS.NON_STREAMING,
|
|
159
|
+
provider: 'openai-compat',
|
|
160
|
+
terminalObserved: false,
|
|
161
|
+
continuation: true,
|
|
162
|
+
textObservedChars: partialContent.length,
|
|
163
|
+
toolCallsComplete: err.partialToolCalls?.length || 0,
|
|
164
|
+
});
|
|
165
|
+
throw err;
|
|
166
|
+
}
|
|
144
167
|
if (
|
|
145
168
|
(stopReason === 'length' && Array.isArray(toolCalls) && toolCalls.length > 0) ||
|
|
146
169
|
stopReason === 'content_filter'
|
|
@@ -150,7 +173,7 @@ export function normalizeCompatChatResponse({
|
|
|
150
173
|
code: 'PROVIDER_INCOMPLETE',
|
|
151
174
|
providerIncomplete: true,
|
|
152
175
|
finishReason: stopReason,
|
|
153
|
-
partialContent:
|
|
176
|
+
partialContent: assembled.content || '',
|
|
154
177
|
partialToolCalls: toolCalls,
|
|
155
178
|
model: response.model || useModel,
|
|
156
179
|
responseId: response.id || null,
|
|
@@ -182,14 +205,30 @@ export function normalizeCompatChatResponse({
|
|
|
182
205
|
cachedTokens: extractCompatCachedTokens(response.usage),
|
|
183
206
|
});
|
|
184
207
|
}
|
|
208
|
+
// Together/vLLM/Groq/OpenRouter report reasoning on `reasoning` or
|
|
209
|
+
// `reasoning_content`; Mistral reports it as thinking chunks inside
|
|
210
|
+
// `content`. Both are captured by the provider's own shape / the response
|
|
211
|
+
// shape, whatever the replay flag says.
|
|
212
|
+
const reasoningField = replayReasoningField(reasoningShape, assembled.reasoningSource);
|
|
185
213
|
const capturesReasoningContent =
|
|
186
|
-
providerName === 'deepseek' ||
|
|
214
|
+
providerName === 'deepseek' ||
|
|
215
|
+
providerName === 'xai' ||
|
|
216
|
+
providerName === 'mixdog-local' ||
|
|
217
|
+
replaysReasoningContent ||
|
|
218
|
+
capturesShapeReasoning(reasoningShape, assembled.reasoningSource);
|
|
187
219
|
const reasoningContent =
|
|
188
220
|
capturesReasoningContent && typeof assembled.reasoningContent === 'string' ? assembled.reasoningContent : null;
|
|
189
221
|
const reasoningDetails =
|
|
190
222
|
providerName === 'openrouter' && Array.isArray(choice?.message?.reasoning_details)
|
|
191
223
|
? choice.message.reasoning_details
|
|
192
224
|
: null;
|
|
225
|
+
// Replay sends reasoning back under the field it arrived on.
|
|
226
|
+
const providerMetadata = {
|
|
227
|
+
...(reasoningDetails?.length ? { openrouter: { reasoning_details: reasoningDetails } } : {}),
|
|
228
|
+
...(reasoningContent !== null && reasoningField
|
|
229
|
+
? { [COMPAT_REASONING_METADATA_KEY]: { reasoningField } }
|
|
230
|
+
: {}),
|
|
231
|
+
};
|
|
193
232
|
return {
|
|
194
233
|
content: assembled.content || '',
|
|
195
234
|
// Streamed chunks can omit `model`; fall back to the requested
|
|
@@ -205,11 +244,7 @@ export function normalizeCompatChatResponse({
|
|
|
205
244
|
// instead of silently treating a truncated answer as complete.
|
|
206
245
|
...(stopReason === 'length' && (assembled.content || '').length > 0 ? { truncated: true } : {}),
|
|
207
246
|
...(reasoningContent !== null ? { reasoningContent } : {}),
|
|
208
|
-
...(
|
|
209
|
-
? {
|
|
210
|
-
providerMetadata: { openrouter: { reasoning_details: reasoningDetails } },
|
|
211
|
-
}
|
|
212
|
-
: {}),
|
|
247
|
+
...(Object.keys(providerMetadata).length ? { providerMetadata } : {}),
|
|
213
248
|
usage: response.usage ? chatCompletionUsage(providerName, response.usage) : undefined,
|
|
214
249
|
};
|
|
215
250
|
}
|
|
@@ -309,8 +344,14 @@ export function normalizeXaiResponsesWebSocket({
|
|
|
309
344
|
cacheLane,
|
|
310
345
|
}) {
|
|
311
346
|
const responseId = result.responseId || previousResponseId || null;
|
|
312
|
-
|
|
313
|
-
|
|
347
|
+
// The WS send result drops the collector's `responseItems`; its own
|
|
348
|
+
// owner-tagged `providerReplay` (traceProvider 'xai') still carries every
|
|
349
|
+
// output item in order: encrypted reasoning and server-executed tool_search
|
|
350
|
+
// call/output pairs. Always taken, so they survive to the next turn as xAI
|
|
351
|
+
// requires.
|
|
352
|
+
const responseItems = result.responseItems ?? result.providerReplay?.items;
|
|
353
|
+
const encryptedReasoningItems = encryptedXaiReasoningItems(responseItems);
|
|
354
|
+
const providerReplay = createProviderReplay('xai-responses', responseItems);
|
|
314
355
|
const encryptedReasoningHistory = xaiEncryptedReasoningHistory(opts, messages, encryptedReasoningItems);
|
|
315
356
|
const rawUsage = result.usage?.raw || result.usage || null;
|
|
316
357
|
const response = {
|
|
@@ -2,11 +2,18 @@
|
|
|
2
2
|
// wire event type maps to one handler over the shared stream `state`; `ctx`
|
|
3
3
|
// carries the label, the caller callbacks and the leaked-text relay.
|
|
4
4
|
import { typedStatusFrom } from './retry-classifier.mjs';
|
|
5
|
-
import {
|
|
5
|
+
import { applyCompatErrorContract } from './openai-compat-error-contract.mjs';
|
|
6
|
+
import {
|
|
7
|
+
customToolCallFromResponseItem,
|
|
8
|
+
nativeToolSearchCallFromArguments,
|
|
9
|
+
withToolCallNamespace,
|
|
10
|
+
} from './custom-tool-wire.mjs';
|
|
11
|
+
import { createRefusals } from './openai-ws-response-state/refusals.mjs';
|
|
6
12
|
import { emitCompatToolCallOnce } from './openai-compat-stream-common.mjs';
|
|
7
13
|
import { truncatedCompatStreamError, parseCompletedToolCallArgumentsJson } from './lib/openai-tool-args.mjs';
|
|
8
14
|
import { incompleteReasonFromEvent, isMaxOutputIncompleteReason } from './lib/responses-terminal-fields.mjs';
|
|
9
15
|
import { responsesUsage } from './openai-compat-response-normalization.mjs';
|
|
16
|
+
import { normalizeGatewayErrorDetail } from './provider-error-kind.mjs';
|
|
10
17
|
|
|
11
18
|
// An incomplete response was still billed: carry its reported usage on the
|
|
12
19
|
// error so the provider-boundary accounting records it.
|
|
@@ -34,16 +41,20 @@ function signal(ctx, kind) {
|
|
|
34
41
|
// through the fatal-code deny-list / default-retry classification.
|
|
35
42
|
function typedResponsesFailure(message, event) {
|
|
36
43
|
const err = new Error(message);
|
|
37
|
-
|
|
44
|
+
// A gateway's canonical error_type (OpenRouter's top-level `error_type`)
|
|
45
|
+
// replaces the lossy native code before anything classifies it.
|
|
46
|
+
const detail = normalizeGatewayErrorDetail(event?.response?.error || event?.error || null, event);
|
|
38
47
|
const typed = typedStatusFrom(detail, event);
|
|
39
48
|
if (typed) err.httpStatus = typed;
|
|
40
49
|
const code = detail?.code ?? detail?.type ?? event?.code ?? null;
|
|
41
50
|
if (code != null && code !== '') err.providerErrorCode = String(code);
|
|
42
51
|
if (detail) err.providerError = detail;
|
|
43
52
|
err.providerWireError = true;
|
|
44
|
-
return err;
|
|
53
|
+
return applyCompatErrorContract(err, detail || (event?.code != null ? { code: event.code } : null));
|
|
45
54
|
}
|
|
46
55
|
|
|
56
|
+
const streamLabel = (ctx) => ctx?.label || 'compat Responses';
|
|
57
|
+
|
|
47
58
|
// Reconcile a COMPLETED function_call item into state.toolCalls: fill in the
|
|
48
59
|
// id/name a streamed call may still be missing, or adopt the item as a new
|
|
49
60
|
// call. `response.output_item.done` and the `response.completed` sweep see the
|
|
@@ -58,18 +69,22 @@ function reconcileCompatFunctionCallItem(state, item, label, onToolCall) {
|
|
|
58
69
|
if (tc) {
|
|
59
70
|
if (!tc.id && item.call_id) tc.id = item.call_id;
|
|
60
71
|
if (!tc.name && item.name) tc.name = item.name;
|
|
72
|
+
withToolCallNamespace(tc, item);
|
|
61
73
|
if (tc.id && tc.name) delete tc._pendingItemId;
|
|
62
74
|
emitCompatToolCallOnce(state, tc, onToolCall);
|
|
63
75
|
} else if (item.call_id && item.name) {
|
|
64
|
-
const call =
|
|
65
|
-
|
|
66
|
-
name: item.name,
|
|
67
|
-
arguments: parseCompletedToolCallArgumentsJson(item.arguments, label, {
|
|
76
|
+
const call = withToolCallNamespace(
|
|
77
|
+
{
|
|
68
78
|
id: item.call_id,
|
|
69
79
|
name: item.name,
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
80
|
+
arguments: parseCompletedToolCallArgumentsJson(item.arguments, label, {
|
|
81
|
+
id: item.call_id,
|
|
82
|
+
name: item.name,
|
|
83
|
+
finishReason: 'done',
|
|
84
|
+
}),
|
|
85
|
+
},
|
|
86
|
+
item
|
|
87
|
+
);
|
|
73
88
|
state.toolCalls.push(call);
|
|
74
89
|
emitCompatToolCallOnce(state, call, onToolCall);
|
|
75
90
|
}
|
|
@@ -78,6 +93,9 @@ function reconcileCompatFunctionCallItem(state, item, label, onToolCall) {
|
|
|
78
93
|
|
|
79
94
|
function pushToolSearchCall(state, item, ctx) {
|
|
80
95
|
if (item?.type !== 'tool_search_call') return;
|
|
96
|
+
// Server-executed search already ran inside the response; it stays in
|
|
97
|
+
// providerReplay only and is never a local load_tool dispatch.
|
|
98
|
+
if (item.execution === 'server') return;
|
|
81
99
|
const callId = item.call_id || item.id || '';
|
|
82
100
|
if (!callId || state.toolCalls.some((call) => call.id === callId)) return;
|
|
83
101
|
const searchArgs =
|
|
@@ -162,10 +180,10 @@ function onReasoningDelta(event, state, ctx) {
|
|
|
162
180
|
function onOutputItemAdded(event, state, ctx) {
|
|
163
181
|
const type = event.item?.type;
|
|
164
182
|
if (type === 'function_call') {
|
|
165
|
-
state.pendingCalls.set(
|
|
166
|
-
|
|
167
|
-
callId: event.item.call_id || '',
|
|
168
|
-
|
|
183
|
+
state.pendingCalls.set(
|
|
184
|
+
event.item.id || '',
|
|
185
|
+
withToolCallNamespace({ name: event.item.name || '', callId: event.item.call_id || '' }, event.item)
|
|
186
|
+
);
|
|
169
187
|
state.toolTracker?.mark(event.item);
|
|
170
188
|
state.toolInFlight = true;
|
|
171
189
|
} else if (type === 'custom_tool_call' || type === 'tool_search_call') {
|
|
@@ -191,26 +209,47 @@ function onToolInputDelta(event, state, ctx) {
|
|
|
191
209
|
function onFunctionCallArgumentsDone(event, state, ctx) {
|
|
192
210
|
const itemId = event.item_id || '';
|
|
193
211
|
const pending = state.pendingCalls.get(itemId);
|
|
194
|
-
const call =
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
212
|
+
const call = withToolCallNamespace(
|
|
213
|
+
{
|
|
214
|
+
id: pending?.callId || event.call_id || '',
|
|
215
|
+
name: pending?.name || event.name || '',
|
|
216
|
+
// `*.done` ⇒ arguments are complete; a parse failure is
|
|
217
|
+
// deterministic bad JSON (permanent), not stream truncation.
|
|
218
|
+
arguments: parseCompletedToolCallArgumentsJson(event.arguments, ctx.label, {
|
|
219
|
+
id: pending?.callId || event.call_id,
|
|
220
|
+
name: pending?.name || event.name,
|
|
221
|
+
finishReason: 'done',
|
|
222
|
+
}),
|
|
223
|
+
_pendingItemId: itemId,
|
|
224
|
+
},
|
|
225
|
+
pending
|
|
226
|
+
);
|
|
206
227
|
state.toolCalls.push(call);
|
|
207
228
|
if (call.id && call.name) delete call._pendingItemId;
|
|
208
229
|
emitCompatToolCallOnce(state, call, ctx.onToolCall);
|
|
209
230
|
signal(ctx, 'tool');
|
|
210
231
|
}
|
|
211
232
|
|
|
233
|
+
// Refusal parts (streamed deltas, done text, final message parts) fold into
|
|
234
|
+
// one typed refusal on state.refusals; the stream collector turns it into a
|
|
235
|
+
// `stopReason:'refusal'` result instead of an empty success.
|
|
236
|
+
const refusalsOf = (state) => (state.refusals ||= createRefusals());
|
|
237
|
+
|
|
238
|
+
function onRefusalDelta(event, state, ctx) {
|
|
239
|
+
state.sawOutput = true;
|
|
240
|
+
refusalsOf(state).delta(event);
|
|
241
|
+
signal(ctx, 'semantic');
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function onRefusalDone(event, state, ctx) {
|
|
245
|
+
state.sawOutput = true;
|
|
246
|
+
refusalsOf(state).done(event);
|
|
247
|
+
signal(ctx, 'semantic');
|
|
248
|
+
}
|
|
249
|
+
|
|
212
250
|
function onOutputItemDone(event, state, ctx) {
|
|
213
251
|
const item = event.item || {};
|
|
252
|
+
if (item.type === 'message') refusalsOf(state).absorbMessage(item);
|
|
214
253
|
if (item.type === 'function_call') {
|
|
215
254
|
const itemId = reconcileCompatFunctionCallItem(state, item, ctx.label, ctx.onToolCall);
|
|
216
255
|
// Drop the resolved function item from pendingCalls before
|
|
@@ -289,6 +328,7 @@ function onCompleted(event, state, ctx) {
|
|
|
289
328
|
}
|
|
290
329
|
|
|
291
330
|
function onDone(event, state, ctx) {
|
|
331
|
+
const label = streamLabel(ctx);
|
|
292
332
|
if (!event.response || event.response.status === 'completed') {
|
|
293
333
|
state.completed = true;
|
|
294
334
|
// A stream that never emits response.completed: this frame carries usage.
|
|
@@ -298,7 +338,7 @@ function onDone(event, state, ctx) {
|
|
|
298
338
|
if (event.response.status === 'failed') {
|
|
299
339
|
const msg = event.response?.error?.message || 'response.done failed';
|
|
300
340
|
throw withIncompleteUsage(
|
|
301
|
-
typedResponsesFailure(
|
|
341
|
+
typedResponsesFailure(`${label} stream response.done failed: ${msg}`, event),
|
|
302
342
|
event,
|
|
303
343
|
state
|
|
304
344
|
);
|
|
@@ -306,27 +346,31 @@ function onDone(event, state, ctx) {
|
|
|
306
346
|
if (event.response.status === 'incomplete') {
|
|
307
347
|
const reason = incompleteReasonFromEvent(event);
|
|
308
348
|
if (isMaxOutputIncompleteReason(reason)) return settleMaxOutputIncomplete(event, state, ctx, reason);
|
|
309
|
-
throw withIncompleteUsage(new Error(
|
|
349
|
+
throw withIncompleteUsage(new Error(`${label} stream response.done incomplete: ${reason}`), event, state);
|
|
310
350
|
}
|
|
311
351
|
}
|
|
312
352
|
|
|
313
|
-
function onFailed(event, state) {
|
|
353
|
+
function onFailed(event, state, ctx) {
|
|
314
354
|
const msg = event.response?.error?.message || event.error?.message || event.message || 'response.failed';
|
|
315
355
|
// The wire event's OWN typed status/code is preserved verbatim. A
|
|
316
356
|
// forbidden/unknown failure is never coerced into a synthetic 500:
|
|
317
357
|
// without typed evidence it stays unclassified and is surfaced.
|
|
318
|
-
throw withIncompleteUsage(
|
|
358
|
+
throw withIncompleteUsage(
|
|
359
|
+
typedResponsesFailure(`${streamLabel(ctx)} stream response.failed: ${msg}`, event),
|
|
360
|
+
event,
|
|
361
|
+
state
|
|
362
|
+
);
|
|
319
363
|
}
|
|
320
364
|
|
|
321
365
|
function onIncomplete(event, state, ctx) {
|
|
322
366
|
const reason = incompleteReasonFromEvent(event);
|
|
323
367
|
if (isMaxOutputIncompleteReason(reason)) return settleMaxOutputIncomplete(event, state, ctx, reason);
|
|
324
|
-
throw withIncompleteUsage(new Error(
|
|
368
|
+
throw withIncompleteUsage(new Error(`${streamLabel(ctx)} stream response.incomplete: ${reason}`), event, state);
|
|
325
369
|
}
|
|
326
370
|
|
|
327
|
-
function onError(event) {
|
|
371
|
+
function onError(event, _state, ctx) {
|
|
328
372
|
const msg = event.message || event.error?.message || 'unknown';
|
|
329
|
-
throw typedResponsesFailure(
|
|
373
|
+
throw typedResponsesFailure(`${streamLabel(ctx)} stream error: ${msg}`, event);
|
|
330
374
|
}
|
|
331
375
|
|
|
332
376
|
const RESPONSES_EVENT_HANDLERS = new Map([
|
|
@@ -334,6 +378,8 @@ const RESPONSES_EVENT_HANDLERS = new Map([
|
|
|
334
378
|
['response.output_text.delta', onOutputTextDelta],
|
|
335
379
|
['response.reasoning_text.delta', onReasoningDelta],
|
|
336
380
|
['response.reasoning_summary_text.delta', onReasoningDelta],
|
|
381
|
+
['response.refusal.delta', onRefusalDelta],
|
|
382
|
+
['response.refusal.done', onRefusalDone],
|
|
337
383
|
['response.output_item.added', onOutputItemAdded],
|
|
338
384
|
['response.function_call_arguments.delta', onToolInputDelta],
|
|
339
385
|
['response.custom_tool_call_input.delta', onToolInputDelta],
|