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
|
@@ -8,9 +8,11 @@ import { typedStatusFrom } from '../../retry-classifier.mjs';
|
|
|
8
8
|
import {
|
|
9
9
|
endTurnFromEvent,
|
|
10
10
|
incompleteReasonFromEvent,
|
|
11
|
+
isIncompleteToolItem,
|
|
11
12
|
isMaxOutputIncompleteReason,
|
|
12
13
|
} from '../../lib/responses-terminal-fields.mjs';
|
|
13
|
-
import {
|
|
14
|
+
import { applyErrorContract, markContentFilter } from '../../openai-error-contract.mjs';
|
|
15
|
+
import { toolInputPending } from '../response-state.mjs';
|
|
14
16
|
import { normalizeWsUsage } from '../../openai-ws-response-state/usage.mjs';
|
|
15
17
|
|
|
16
18
|
// Typed status only — nothing is synthesized from text. The frame itself is
|
|
@@ -19,11 +21,14 @@ import { normalizeWsUsage } from '../../openai-ws-response-state/usage.mjs';
|
|
|
19
21
|
function wireFailureError(message, event, detail, typedSources) {
|
|
20
22
|
const err = new Error(message);
|
|
21
23
|
err.responseFailed = event;
|
|
22
|
-
const typed = typedStatusFrom(...typedSources);
|
|
23
|
-
if (typed) err.httpStatus = typed;
|
|
24
24
|
const code = detail?.code ?? detail?.type ?? null;
|
|
25
25
|
if (typeof code === 'string' && code) err.providerErrorCode = code;
|
|
26
|
-
return err
|
|
26
|
+
return applyErrorContract(err, {
|
|
27
|
+
status: typedStatusFrom(...typedSources),
|
|
28
|
+
code: typeof code === 'string' ? code : undefined,
|
|
29
|
+
error: detail,
|
|
30
|
+
event,
|
|
31
|
+
});
|
|
27
32
|
}
|
|
28
33
|
|
|
29
34
|
export function createTerminalFrameEvents({ state, items, text, outcome, meaningful }) {
|
|
@@ -32,6 +37,13 @@ export function createTerminalFrameEvents({ state, items, text, outcome, meaning
|
|
|
32
37
|
const absorbCompletedOutput = (output) => {
|
|
33
38
|
let reported = false;
|
|
34
39
|
for (const item of output) {
|
|
40
|
+
if (isIncompleteToolItem(item)) {
|
|
41
|
+
state.toolTracker.mark(item);
|
|
42
|
+
state.toolInFlight = true;
|
|
43
|
+
meaningful('tool');
|
|
44
|
+
reported = true;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
35
47
|
items.pushResponseItem(item);
|
|
36
48
|
if (item.type === 'message') {
|
|
37
49
|
if (text.absorbCompletedMessage(item)) reported = true;
|
|
@@ -89,7 +101,7 @@ export function createTerminalFrameEvents({ state, items, text, outcome, meaning
|
|
|
89
101
|
absorbTerminalResponse(event.response || {});
|
|
90
102
|
const reason = incompleteReasonFromEvent(event);
|
|
91
103
|
if (!isMaxOutputIncompleteReason(reason)) {
|
|
92
|
-
const err = new Error(`${
|
|
104
|
+
const err = markContentFilter(new Error(`${state.label} ${frame}: ${reason}`), reason);
|
|
93
105
|
// Still billed: the provider-boundary accounting records reported usage.
|
|
94
106
|
if (state.usage) {
|
|
95
107
|
err.partialUsage = state.usage;
|
|
@@ -97,31 +109,47 @@ export function createTerminalFrameEvents({ state, items, text, outcome, meaning
|
|
|
97
109
|
}
|
|
98
110
|
throw err;
|
|
99
111
|
}
|
|
112
|
+
for (const item of event.response?.output || []) {
|
|
113
|
+
if (isIncompleteToolItem(item)) {
|
|
114
|
+
state.toolTracker.mark(item);
|
|
115
|
+
state.toolInFlight = true;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
100
118
|
if (toolInputPending(state)) {
|
|
101
|
-
|
|
119
|
+
// Same carried state as the WS path: text (leak-guard tail flushed),
|
|
120
|
+
// the calls already complete and dispatched, model and billed usage.
|
|
121
|
+
text.flushLeak();
|
|
122
|
+
const err = outcome.stampToolSafety(new Error(`${state.label} ${frame} (max_output_tokens) with tool call in flight`));
|
|
123
|
+
outcome.attachStreamPartial(err);
|
|
102
124
|
err.streamStalled = true;
|
|
103
125
|
err.pendingToolUse = true;
|
|
104
|
-
err.
|
|
105
|
-
err.partialModel = state.model || undefined;
|
|
126
|
+
err.incompleteReason = reason;
|
|
106
127
|
if (state.usage) err.partialUsage = state.usage;
|
|
107
128
|
throw err;
|
|
108
129
|
}
|
|
109
130
|
state.completed = true;
|
|
110
131
|
state.stopReason = 'length';
|
|
132
|
+
state.incompleteReason = reason;
|
|
111
133
|
};
|
|
112
134
|
|
|
113
135
|
const onDone = (event) => {
|
|
114
|
-
if (!event.response
|
|
115
|
-
if (event.response) absorbTerminalResponse(event.response);
|
|
136
|
+
if (!event.response) {
|
|
116
137
|
state.completed = true;
|
|
117
138
|
// Terminal success frame for streams that never emit a separate
|
|
118
139
|
// response.completed — same optional end_turn.
|
|
119
140
|
setEndTurn(event);
|
|
141
|
+
} else if (event.response.status === 'completed') {
|
|
142
|
+
// Same terminal as response.completed: usage, end_turn and the output
|
|
143
|
+
// bundle reconciled through the same deduplicated collectors.
|
|
144
|
+
onCompleted(event);
|
|
120
145
|
} else if (event.response.status === 'failed') {
|
|
121
146
|
const msg = event.response?.error?.message || 'response.done failed';
|
|
122
|
-
const err = new Error(`${
|
|
123
|
-
|
|
124
|
-
|
|
147
|
+
const err = new Error(`${state.label} response.done failed: ${msg}`);
|
|
148
|
+
applyErrorContract(err, {
|
|
149
|
+
status: typedStatusFrom(event.response?.error, event.error, event),
|
|
150
|
+
error: event.response?.error || event.error || null,
|
|
151
|
+
event,
|
|
152
|
+
});
|
|
125
153
|
throw withFailedUsage(err, event);
|
|
126
154
|
} else if (event.response.status === 'incomplete') {
|
|
127
155
|
onIncomplete(event, 'response.done incomplete');
|
|
@@ -131,7 +159,7 @@ export function createTerminalFrameEvents({ state, items, text, outcome, meaning
|
|
|
131
159
|
const failedFrameError = (event) =>
|
|
132
160
|
withFailedUsage(
|
|
133
161
|
wireFailureError(
|
|
134
|
-
`${
|
|
162
|
+
`${state.label} response.failed: ${event.response?.error?.message || event.error?.message || event.message || 'response.failed'}`,
|
|
135
163
|
event,
|
|
136
164
|
event.response?.error || event.error || null,
|
|
137
165
|
[event.response?.error, event.error, event]
|
|
@@ -142,7 +170,7 @@ export function createTerminalFrameEvents({ state, items, text, outcome, meaning
|
|
|
142
170
|
// Same wire-error contract as response.failed.
|
|
143
171
|
const errorFrameError = (event) =>
|
|
144
172
|
wireFailureError(
|
|
145
|
-
`${
|
|
173
|
+
`${state.label} error: ${event.message || event.error?.message || 'unknown'}`,
|
|
146
174
|
event,
|
|
147
175
|
{ code: event.error?.code ?? event.error?.type ?? event.code ?? null },
|
|
148
176
|
[event.error, event]
|
package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs
CHANGED
|
@@ -42,6 +42,16 @@ export function createResponseEvents({ state, items, text, outcome, meaningful,
|
|
|
42
42
|
case 'response.function_call_arguments.done':
|
|
43
43
|
output.onFunctionCallArgumentsDone(event);
|
|
44
44
|
break;
|
|
45
|
+
// Refusal text is collected for the typed refusal result, never relayed
|
|
46
|
+
// as visible answer text.
|
|
47
|
+
case 'response.refusal.delta':
|
|
48
|
+
state.refusals.delta(event);
|
|
49
|
+
meaningful('semantic');
|
|
50
|
+
break;
|
|
51
|
+
case 'response.refusal.done':
|
|
52
|
+
state.refusals.done(event);
|
|
53
|
+
meaningful('semantic');
|
|
54
|
+
break;
|
|
45
55
|
case 'response.output_item.done':
|
|
46
56
|
output.onOutputItemDone(event.item || {});
|
|
47
57
|
break;
|
package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs
CHANGED
|
@@ -5,7 +5,12 @@
|
|
|
5
5
|
* pending function_call completion.
|
|
6
6
|
*/
|
|
7
7
|
import { makeInvalidToolArgsMarker } from '../lib/openai-tool-args.mjs';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
customToolCallFromResponseItem,
|
|
10
|
+
nativeToolSearchCallFromArguments,
|
|
11
|
+
qualifiedToolCallName,
|
|
12
|
+
withToolCallNamespace,
|
|
13
|
+
} from '../custom-tool-wire.mjs';
|
|
9
14
|
|
|
10
15
|
// Completed function_call.arguments parse for the OpenAI Responses stream.
|
|
11
16
|
// A function_call item arrives only on a completion/done signal, so a
|
|
@@ -37,7 +42,7 @@ export function createResponseItems({ state, onToolCall }) {
|
|
|
37
42
|
if (!call?.id) return;
|
|
38
43
|
if (state.emittedToolCallIds.has(call.id)) return;
|
|
39
44
|
state.emittedToolCallIds.add(call.id);
|
|
40
|
-
if (!state.toolDedupe.shouldDispatch(call
|
|
45
|
+
if (!state.toolDedupe.shouldDispatch(qualifiedToolCallName(call), call.arguments, call.id)) return;
|
|
41
46
|
state.emittedToolCall = true;
|
|
42
47
|
try {
|
|
43
48
|
onToolCall?.(call);
|
|
@@ -77,6 +82,8 @@ export function createResponseItems({ state, onToolCall }) {
|
|
|
77
82
|
};
|
|
78
83
|
const pushToolSearchCall = (item) => {
|
|
79
84
|
if (item?.type !== 'tool_search_call') return;
|
|
85
|
+
// Server-executed search already ran inside the response; replay-only.
|
|
86
|
+
if (item.execution === 'server') return;
|
|
80
87
|
const callId = item.call_id || item.id || '';
|
|
81
88
|
if (!callId || state.toolCalls.some((t) => t.id === callId)) return;
|
|
82
89
|
let args = {};
|
|
@@ -104,6 +111,7 @@ export function createResponseItems({ state, onToolCall }) {
|
|
|
104
111
|
const completePendingCall = (tc, item) => {
|
|
105
112
|
if (!tc.id && item.call_id) tc.id = item.call_id;
|
|
106
113
|
if (!tc.name && item.name) tc.name = item.name;
|
|
114
|
+
withToolCallNamespace(tc, item);
|
|
107
115
|
if (tc.id && tc.name) {
|
|
108
116
|
delete tc._pendingItemId;
|
|
109
117
|
emitToolCall(tc);
|
|
@@ -119,11 +127,14 @@ export function createResponseItems({ state, onToolCall }) {
|
|
|
119
127
|
if (tc) {
|
|
120
128
|
completePendingCall(tc, item);
|
|
121
129
|
} else if (item.call_id && item.name) {
|
|
122
|
-
const call =
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
130
|
+
const call = withToolCallNamespace(
|
|
131
|
+
{
|
|
132
|
+
id: item.call_id,
|
|
133
|
+
name: item.name,
|
|
134
|
+
arguments: parseJsonObject(item.arguments),
|
|
135
|
+
},
|
|
136
|
+
item
|
|
137
|
+
);
|
|
127
138
|
state.toolCalls.push(call);
|
|
128
139
|
emitToolCall(call);
|
|
129
140
|
}
|
package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs
CHANGED
|
@@ -8,8 +8,8 @@ import { traceAgentSse, traceAgentUsage } from '../../agent-trace.mjs';
|
|
|
8
8
|
import { dedupeToolCallList } from '../lib/leaked-toolcall.mjs';
|
|
9
9
|
import { _displayCodexModel } from '../openai-codex-model.mjs';
|
|
10
10
|
import { createProviderReplay } from '../lib/provider-replay.mjs';
|
|
11
|
-
import { LABEL } from './response-state.mjs';
|
|
12
11
|
import { createResponseStamps } from './response-stamps.mjs';
|
|
12
|
+
import { refusalResultFields } from '../openai-ws-response-state/refusals.mjs';
|
|
13
13
|
|
|
14
14
|
export function createResponseOutcome({ state }) {
|
|
15
15
|
const { stampToolSafety, stampOutcome, stallPartial, stampStreamError, attachStreamPartial, endedEarlyError } =
|
|
@@ -50,7 +50,7 @@ export function createResponseOutcome({ state }) {
|
|
|
50
50
|
throw stampOutcome(
|
|
51
51
|
stampToolSafety(
|
|
52
52
|
new Error(
|
|
53
|
-
`${
|
|
53
|
+
`${state.label} function_call salvage failed: missing call_id/name for item_id=${unresolved._pendingItemId || '?'}`
|
|
54
54
|
)
|
|
55
55
|
)
|
|
56
56
|
);
|
|
@@ -75,6 +75,7 @@ export function createResponseOutcome({ state }) {
|
|
|
75
75
|
webSearchCalls: state.webSearchCalls.length ? state.webSearchCalls : undefined,
|
|
76
76
|
usage: state.usage || undefined,
|
|
77
77
|
stopReason: state.stopReason || undefined,
|
|
78
|
+
incompleteReason: state.incompleteReason || undefined,
|
|
78
79
|
// Only present when the terminal frame carried the wire field.
|
|
79
80
|
...(typeof state.endTurn === 'boolean' ? { endTurn: state.endTurn } : {}),
|
|
80
81
|
// Text-only max-output cutoff (status:'incomplete'/reason=max_output_tokens
|
|
@@ -84,6 +85,8 @@ export function createResponseOutcome({ state }) {
|
|
|
84
85
|
...(state.stopReason === 'length' && state.content.length > 0 ? { truncated: true } : {}),
|
|
85
86
|
responseId: state.responseId || undefined,
|
|
86
87
|
serviceTier: state.serviceTier || undefined,
|
|
88
|
+
// A refused turn: typed stop reason and the refusal text.
|
|
89
|
+
...refusalResultFields(state.refusals, state.content),
|
|
87
90
|
};
|
|
88
91
|
};
|
|
89
92
|
|
package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-stamps.mjs
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { stampStreamOutcome, STREAM_TRANSPORTS } from '../lib/stream-outcome.mjs';
|
|
11
11
|
import { createProviderReplay } from '../lib/provider-replay.mjs';
|
|
12
|
-
import {
|
|
12
|
+
import { toolInputPending } from './response-state.mjs';
|
|
13
13
|
|
|
14
14
|
export function createResponseStamps({ state }) {
|
|
15
15
|
const stampToolSafety = (err) => {
|
|
@@ -111,7 +111,7 @@ export function createResponseStamps({ state }) {
|
|
|
111
111
|
const err = attachStreamPartial(
|
|
112
112
|
stampToolSafety(
|
|
113
113
|
new Error(
|
|
114
|
-
`${
|
|
114
|
+
`${state.label} ended before response.completed (text=${state.content.length} chars, toolCalls=${state.toolCalls.length})`
|
|
115
115
|
)
|
|
116
116
|
)
|
|
117
117
|
);
|
package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs
CHANGED
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { createActiveToolItemTracker } from '../tool-stream-state.mjs';
|
|
9
9
|
import { createToolCallDedupe } from '../lib/leaked-toolcall.mjs';
|
|
10
|
+
import { createRefusals } from '../openai-ws-response-state/refusals.mjs';
|
|
10
11
|
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
export function createResponseState() {
|
|
12
|
+
export function createResponseState(label) {
|
|
14
13
|
return {
|
|
14
|
+
label,
|
|
15
15
|
content: '',
|
|
16
16
|
model: '',
|
|
17
17
|
responseId: '',
|
|
@@ -32,8 +32,12 @@ export function createResponseState() {
|
|
|
32
32
|
citationKeys: new Set(),
|
|
33
33
|
webSearchCalls: [],
|
|
34
34
|
webSearchCallKeys: new Set(),
|
|
35
|
+
// Refusal parts (streamed and final), folded into one typed refusal.
|
|
36
|
+
refusals: createRefusals(),
|
|
35
37
|
completed: false,
|
|
36
38
|
stopReason: null,
|
|
39
|
+
// Why a max-output cutoff completed the turn (response.incomplete_details).
|
|
40
|
+
incompleteReason: null,
|
|
37
41
|
// Normalized wire `end_turn` from the terminal frame; undefined unless the
|
|
38
42
|
// server actually supplied a boolean.
|
|
39
43
|
endTurn: undefined,
|
package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs
CHANGED
|
@@ -97,10 +97,18 @@ export function createTextRelay({ state, body, onTextDelta, meaningful, emitTool
|
|
|
97
97
|
};
|
|
98
98
|
const absorbCompletedMessage = (item) => {
|
|
99
99
|
let reported = false;
|
|
100
|
+
// Decided once per message item (as the WS completed-item fold does), so
|
|
101
|
+
// every content part of an item with no streamed text is absorbed rather
|
|
102
|
+
// than only the first one that fills `state.content`.
|
|
103
|
+
const absorbText = !state.content;
|
|
100
104
|
for (const part of item.content || []) {
|
|
101
|
-
if (
|
|
105
|
+
if (absorbText && part.type === 'output_text' && absorbCompletedText(part)) reported = true;
|
|
102
106
|
if (part.type === 'output_text') pushOutputTextAnnotations(part, state.citations, state.citationKeys);
|
|
103
107
|
}
|
|
108
|
+
if (state.refusals.absorbMessage(item)) {
|
|
109
|
+
meaningful('semantic');
|
|
110
|
+
reported = true;
|
|
111
|
+
}
|
|
104
112
|
return reported;
|
|
105
113
|
};
|
|
106
114
|
|
|
@@ -26,8 +26,8 @@ import { createResponseEvents } from './openai-http-sse-response-state/response-
|
|
|
26
26
|
* @param {(kind: string) => void} deps.meaningful semantic progress (re-arms the idle watchdog)
|
|
27
27
|
* @param {() => void} deps.onServerEvent first-event → semantic-idle handover
|
|
28
28
|
*/
|
|
29
|
-
export function createHttpSseResponseState({ body, onToolCall, onTextDelta, meaningful, onServerEvent }) {
|
|
30
|
-
const state = createResponseState();
|
|
29
|
+
export function createHttpSseResponseState({ body, onToolCall, onTextDelta, meaningful, onServerEvent, label }) {
|
|
30
|
+
const state = createResponseState(label);
|
|
31
31
|
const outcome = createResponseOutcome({ state });
|
|
32
32
|
const items = createResponseItems({ state, onToolCall });
|
|
33
33
|
const text = createTextRelay({ state, body, onTextDelta, meaningful, emitToolCall: items.emitToolCall });
|
|
@@ -20,8 +20,6 @@ import {
|
|
|
20
20
|
streamStalledError,
|
|
21
21
|
} from '../stall-policy.mjs';
|
|
22
22
|
|
|
23
|
-
const LABEL = 'OpenAI OAuth HTTP fallback';
|
|
24
|
-
|
|
25
23
|
function positiveOverride(value) {
|
|
26
24
|
const ms = Number(value);
|
|
27
25
|
return Number.isFinite(ms) && ms > 0 ? ms : 0;
|
|
@@ -34,7 +32,7 @@ function positiveOverride(value) {
|
|
|
34
32
|
* @param {{ signal?: AbortSignal, cleanup(): void }} deps.totalTimeout
|
|
35
33
|
* @param {() => object} deps.stallPartial streamed partial state attached to a semantic-idle stall
|
|
36
34
|
*/
|
|
37
|
-
export function createHttpSseWatchdogs({ opts, reader, totalTimeout, stallPartial }) {
|
|
35
|
+
export function createHttpSseWatchdogs({ opts, reader, totalTimeout, stallPartial, label: LABEL }) {
|
|
38
36
|
let abortReason = null;
|
|
39
37
|
let pendingReadReject = null;
|
|
40
38
|
const rejectPendingRead = (err) => {
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Public OpenAI API model capabilities for Responses request construction.
|
|
2
|
+
// Catalog metadata decides where it declares a capability; otherwise the
|
|
3
|
+
// documented model-family rules below apply. The Codex (openai-oauth) route is
|
|
4
|
+
// separate: its backend serves only current GPT-5.x models and keeps its own
|
|
5
|
+
// defaults, so none of these gates apply to it.
|
|
6
|
+
// reasoning: https://developers.openai.com/api/docs/guides/reasoning/
|
|
7
|
+
// tool_search: https://developers.openai.com/api/docs/guides/tools-tool-search/ (gpt-5.4 and later)
|
|
8
|
+
// cache: https://developers.openai.com/api/docs/guides/prompt-caching/
|
|
9
|
+
import { getModelMetadataSync } from '../../../shared/llm/model-catalog.mjs';
|
|
10
|
+
|
|
11
|
+
const SNAPSHOT_SUFFIX = /-\d{4}-\d{2}-\d{2}$/;
|
|
12
|
+
const modelId = (model) => String(model?.id || model || '').trim();
|
|
13
|
+
|
|
14
|
+
// The catalog metadata of one model. A dated snapshot reads as its undated
|
|
15
|
+
// alias when only the alias is listed.
|
|
16
|
+
export function openAiCatalogMeta(model) {
|
|
17
|
+
const id = modelId(model);
|
|
18
|
+
for (const candidate of new Set([id, id.replace(SNAPSHOT_SUFFIX, '')])) {
|
|
19
|
+
const meta = candidate ? getModelMetadataSync(candidate, 'openai') : null;
|
|
20
|
+
if (meta) return meta;
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// gpt-5.4 -> [5, 4]; gpt-6-astra -> [6, 0]; non-GPT ids -> null.
|
|
26
|
+
// A bare multi-digit major with no minor or family suffix (gpt-60) is not a
|
|
27
|
+
// generation id.
|
|
28
|
+
function gptVersion(id) {
|
|
29
|
+
const m = /^gpt-(\d+)(?:\.(\d+))?(?=-|$)/.exec(id);
|
|
30
|
+
if (!m || (m[1].length > 1 && m[2] === undefined && m[0] === id)) return null;
|
|
31
|
+
return [Number(m[1]), Number(m[2] || 0)];
|
|
32
|
+
}
|
|
33
|
+
const atLeast = (version, major, minor) =>
|
|
34
|
+
Boolean(version) && (version[0] > major || (version[0] === major && version[1] >= minor));
|
|
35
|
+
|
|
36
|
+
// Reasoning models: the o-series and GPT-5 and later (gpt-5-chat-latest is the
|
|
37
|
+
// non-reasoning chat snapshot).
|
|
38
|
+
export function openAiPublicSupportsReasoning(model) {
|
|
39
|
+
const flag = openAiCatalogMeta(model)?.supportsReasoning;
|
|
40
|
+
if (typeof flag === 'boolean') return flag;
|
|
41
|
+
const id = modelId(model);
|
|
42
|
+
if (/^gpt-5-chat/.test(id)) return false;
|
|
43
|
+
return /^o\d/.test(id) || atLeast(gptVersion(id), 5, 0);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// text.verbosity is documented for GPT-5 and later.
|
|
47
|
+
export function openAiPublicSupportsVerbosity(model) {
|
|
48
|
+
return atLeast(gptVersion(modelId(model)), 5, 0);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Native tool_search: Responses API gpt-5.4 and later.
|
|
52
|
+
export function openAiPublicSupportsToolSearch(model) {
|
|
53
|
+
return atLeast(gptVersion(modelId(model)), 5, 4);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// GPT-5.6 and later take prompt_cache_options.ttl instead of prompt_cache_retention.
|
|
57
|
+
export function openAiUsesPromptCacheOptions(model) {
|
|
58
|
+
return atLeast(gptVersion(modelId(model)), 5, 6);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Documented extended (24h) prompt_cache_retention list; dated snapshots read
|
|
62
|
+
// as their alias.
|
|
63
|
+
const EXTENDED_RETENTION = new Set([
|
|
64
|
+
'gpt-5.5',
|
|
65
|
+
'gpt-5.5-pro',
|
|
66
|
+
'gpt-5.4',
|
|
67
|
+
'gpt-5.2',
|
|
68
|
+
'gpt-5.1-codex-max',
|
|
69
|
+
'gpt-5.1',
|
|
70
|
+
'gpt-5.1-codex',
|
|
71
|
+
'gpt-5.1-codex-mini',
|
|
72
|
+
'gpt-5.1-chat-latest',
|
|
73
|
+
'gpt-5',
|
|
74
|
+
'gpt-5-codex',
|
|
75
|
+
'gpt-4.1',
|
|
76
|
+
]);
|
|
77
|
+
export function openAiSupportsExtendedRetention(model) {
|
|
78
|
+
const id = modelId(model);
|
|
79
|
+
return EXTENDED_RETENTION.has(id) || EXTENDED_RETENTION.has(id.replace(SNAPSHOT_SUFFIX, ''));
|
|
80
|
+
}
|
|
@@ -13,6 +13,9 @@ import { codexCatalogHas } from './openai-oauth-catalog.mjs';
|
|
|
13
13
|
import { _displayCodexModel } from './openai-codex-model.mjs';
|
|
14
14
|
import { _envFlag, _shouldUseOpenAIHttpFallback } from './openai-oauth-http-sse.mjs';
|
|
15
15
|
import { isWsMessageTooBigClose } from './retry-classifier.mjs';
|
|
16
|
+
import { waitForRetryDeadline } from './openai-error-contract.mjs';
|
|
17
|
+
import { isReplaySafe } from './lib/stream-outcome.mjs';
|
|
18
|
+
import { noteErrorUsage } from './lib/note-error-usage.mjs';
|
|
16
19
|
|
|
17
20
|
function openAiOAuthHandshakeErrorPolicy({ status }) {
|
|
18
21
|
if (Number(status) === 404) {
|
|
@@ -99,7 +102,9 @@ export function createOpenAiOAuthDispatch({
|
|
|
99
102
|
for (const [key, expiresAt] of provider._httpFallbackUntilByPoolKey) {
|
|
100
103
|
if (!(expiresAt > now)) provider._httpFallbackUntilByPoolKey.delete(key);
|
|
101
104
|
}
|
|
102
|
-
|
|
105
|
+
// A forked transport scope follows its session's switch; it records its own.
|
|
106
|
+
const sessionUntil = opts.sessionId ? provider._httpFallbackUntilByPoolKey.get(opts.sessionId) || 0 : 0;
|
|
107
|
+
return Math.max(provider._httpFallbackUntilByPoolKey.get(poolKey) || 0, sessionUntil) > now;
|
|
103
108
|
};
|
|
104
109
|
const markStickyHttpFallback = () => {
|
|
105
110
|
if (!poolKey) return;
|
|
@@ -130,6 +135,17 @@ export function createOpenAiOAuthDispatch({
|
|
|
130
135
|
});
|
|
131
136
|
} catch {}
|
|
132
137
|
};
|
|
138
|
+
// A 401 is recoverable once per send, and only while nothing the turn
|
|
139
|
+
// produced could be duplicated by reissuing it.
|
|
140
|
+
const canReissueAfter401 = (err) =>
|
|
141
|
+
Number(err?.httpStatus || err?.status || 0) === 401 &&
|
|
142
|
+
authState.authRefreshed !== true &&
|
|
143
|
+
!externalSignal?.aborted &&
|
|
144
|
+
err?.liveTextEmitted !== true &&
|
|
145
|
+
err?.emittedToolCall !== true &&
|
|
146
|
+
err?.toolCallEmitted !== true &&
|
|
147
|
+
err?.unsafeToRetry !== true &&
|
|
148
|
+
isReplaySafe(err);
|
|
133
149
|
const dispatchHttp = async (reason, originalErr = null, { sticky = false } = {}) => {
|
|
134
150
|
// Transport switching is a session decision, not an HTTP-success
|
|
135
151
|
// side effect. Persist it before the fallback can fail or abort.
|
|
@@ -158,9 +174,10 @@ export function createOpenAiOAuthDispatch({
|
|
|
158
174
|
if (!process.env.MIXDOG_QUIET_PROVIDER_LOG)
|
|
159
175
|
process.stderr.write(`[openai-oauth] WebSocket unhealthy (${reason}); falling back to HTTP/SSE\n`);
|
|
160
176
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
177
|
+
// The server's retry deadline outlives a transport switch.
|
|
178
|
+
if (originalErr && reason !== 'forced') await waitForRetryDeadline(originalErr, externalSignal, opts._sleepFn);
|
|
179
|
+
const sendHttpOnce = () =>
|
|
180
|
+
sendHttp({
|
|
164
181
|
auth: authState.tokens,
|
|
165
182
|
body,
|
|
166
183
|
opts,
|
|
@@ -175,6 +192,22 @@ export function createOpenAiOAuthDispatch({
|
|
|
175
192
|
useModel,
|
|
176
193
|
fetchFn: opts._fetchFn,
|
|
177
194
|
});
|
|
195
|
+
let result;
|
|
196
|
+
try {
|
|
197
|
+
try {
|
|
198
|
+
result = await sendHttpOnce();
|
|
199
|
+
} catch (firstErr) {
|
|
200
|
+
if (!canReissueAfter401(firstErr)) throw firstErr;
|
|
201
|
+
// Same bounded, replay-safe recovery the WS path applies: one forced
|
|
202
|
+
// refresh per send, one reissue of the identical request.
|
|
203
|
+
noteErrorUsage(firstErr);
|
|
204
|
+
traceTransportError(firstErr, 'primary', 'http');
|
|
205
|
+
process.stderr.write('[openai-oauth-http] 401 — forcing refresh and retrying once over HTTP/SSE\n');
|
|
206
|
+
authState.authRefreshed = true;
|
|
207
|
+
provider._refreshFallbackUntil = 0;
|
|
208
|
+
authState.tokens = await provider.ensureAuth({ forceRefresh: true, reason: '401' });
|
|
209
|
+
result = await sendHttpOnce();
|
|
210
|
+
}
|
|
178
211
|
} catch (httpErr) {
|
|
179
212
|
// The current transport owns the terminal decision, including
|
|
180
213
|
// auth, rate limits, cancellation and output-safety markers.
|
|
@@ -16,9 +16,12 @@ import { CODEX_OAUTH_ORIGINATOR } from './openai-codex-endpoints.mjs';
|
|
|
16
16
|
import { parseProviderJsonBatch } from './stream-json-pool.mjs';
|
|
17
17
|
import { envFlag as _envFlag } from '../../../shared/env.mjs';
|
|
18
18
|
import { activateCodexTurnState } from './openai-turn-state.mjs';
|
|
19
|
+
import { httpLabel } from './openai-error-contract.mjs';
|
|
19
20
|
import { openHttpSseResponse } from './openai-http-sse-request.mjs';
|
|
20
21
|
import { createHttpSseWatchdogs } from './openai-http-sse-watchdogs.mjs';
|
|
21
22
|
import { createHttpSseResponseState } from './openai-http-sse-response-state.mjs';
|
|
23
|
+
import { codexUserAgent, codexVersionHeader } from './codex-client-meta.mjs';
|
|
24
|
+
import { _codexBetaFeatures } from './openai-ws-headers.mjs';
|
|
22
25
|
export { _envFlag };
|
|
23
26
|
|
|
24
27
|
function _sseEventsFromBuffer(buffer) {
|
|
@@ -72,6 +75,11 @@ export function _buildOpenAIHttpFallbackHeaders({
|
|
|
72
75
|
originator: CODEX_OAUTH_ORIGINATOR,
|
|
73
76
|
'chatgpt-account-id': auth.account_id || '',
|
|
74
77
|
'x-client-request-id': randomBytes(16).toString('hex'),
|
|
78
|
+
// Codex identity shared with the WS handshake (build_responses_headers);
|
|
79
|
+
// WS-only OpenAI-Beta value stays HTTP-specific above.
|
|
80
|
+
'User-Agent': codexUserAgent(),
|
|
81
|
+
version: codexVersionHeader(),
|
|
82
|
+
'x-codex-beta-features': _codexBetaFeatures(),
|
|
75
83
|
};
|
|
76
84
|
if (cacheKey && !statelessConversation) {
|
|
77
85
|
const sid = String(cacheKey);
|
|
@@ -165,6 +173,7 @@ export async function sendViaHttpSse({
|
|
|
165
173
|
onStageChange?.('streaming');
|
|
166
174
|
} catch {}
|
|
167
175
|
const sseStartedAt = Date.now();
|
|
176
|
+
const label = httpLabel(auth);
|
|
168
177
|
const reader = response.body.getReader();
|
|
169
178
|
const decoder = new TextDecoder();
|
|
170
179
|
let ttftMs = null;
|
|
@@ -173,6 +182,7 @@ export async function sendViaHttpSse({
|
|
|
173
182
|
reader,
|
|
174
183
|
totalTimeout,
|
|
175
184
|
stallPartial: () => state.stallPartial(),
|
|
185
|
+
label,
|
|
176
186
|
});
|
|
177
187
|
const meaningful = (kind = 'semantic') => {
|
|
178
188
|
if (ttftMs == null) ttftMs = Date.now() - sseStartedAt;
|
|
@@ -187,6 +197,7 @@ export async function sendViaHttpSse({
|
|
|
187
197
|
onTextDelta,
|
|
188
198
|
meaningful,
|
|
189
199
|
onServerEvent: watchdogs.noteServerEvent,
|
|
200
|
+
label,
|
|
190
201
|
});
|
|
191
202
|
const foldFrames = async (text) => {
|
|
192
203
|
const parsed = _sseEventsFromBuffer(text);
|
|
@@ -202,7 +213,7 @@ export async function sendViaHttpSse({
|
|
|
202
213
|
if (totalTimeout.signal?.aborted) {
|
|
203
214
|
watchdogs.clearSemanticIdle();
|
|
204
215
|
const reason = totalTimeout.signal.reason;
|
|
205
|
-
throw reason instanceof Error ? reason : new Error(
|
|
216
|
+
throw reason instanceof Error ? reason : new Error(`${label} aborted`);
|
|
206
217
|
}
|
|
207
218
|
const abortReason = watchdogs.abortReason();
|
|
208
219
|
if (abortReason) throw abortReason;
|
|
@@ -189,6 +189,7 @@ export function forgetOpenAIOAuthCredentials() {
|
|
|
189
189
|
}
|
|
190
190
|
|
|
191
191
|
// --- Token refresh ---
|
|
192
|
+
const PERMANENT_REFRESH_FAILURE_RE = /invalid_grant|revoked|reused|refresh_token_(?:expired|invalidated)/i;
|
|
192
193
|
async function exchangeRefreshToken(refreshToken, previousIdentity = null) {
|
|
193
194
|
const controller = new AbortController();
|
|
194
195
|
const timeout = setTimeout(() => controller.abort(), TOKEN_REFRESH_TIMEOUT_MS);
|
|
@@ -214,10 +215,17 @@ async function exchangeRefreshToken(refreshToken, previousIdentity = null) {
|
|
|
214
215
|
// CLI's single-use lineage) from transient failures, so the caller can
|
|
215
216
|
// re-read disk and retry once with a newer token instead of
|
|
216
217
|
// collapsing every failure to a generic null.
|
|
217
|
-
|
|
218
|
+
// Only a CONFIRMED permanent refusal sets reauthRequired: a 401, or a
|
|
219
|
+
// typed refresh-token code. A bare 400/5xx/429 is not evidence the
|
|
220
|
+
// refresh token is dead.
|
|
221
|
+
if (res.status === 401 || PERMANENT_REFRESH_FAILURE_RE.test(text)) {
|
|
218
222
|
throw Object.assign(new Error(`OpenAI OAuth token refresh ${res.status} (invalid_grant)`), {
|
|
219
223
|
isInvalidGrant: true,
|
|
220
224
|
reauthRequired: true,
|
|
225
|
+
status: res.status,
|
|
226
|
+
httpStatus: res.status,
|
|
227
|
+
code: 'invalid_grant',
|
|
228
|
+
headers: res.headers,
|
|
221
229
|
});
|
|
222
230
|
}
|
|
223
231
|
return null;
|
|
@@ -312,7 +320,19 @@ async function refreshUnderLock({ currentToken, force, reason, startingTokens })
|
|
|
312
320
|
process.stderr.write(`[openai-oauth] Refresh failed (${msg}); using still-valid current token\n`);
|
|
313
321
|
return { tokens: reusable, coastOnCurrent: true };
|
|
314
322
|
}
|
|
315
|
-
|
|
323
|
+
const failure = new Error(`OpenAI OAuth token refresh failed (${msg}). Re-authenticate via provider login.`);
|
|
324
|
+
// The wrapper must not hide a confirmed permanent refusal from the account pool.
|
|
325
|
+
if (err?.reauthRequired === true) {
|
|
326
|
+
Object.assign(failure, {
|
|
327
|
+
reauthRequired: true,
|
|
328
|
+
isInvalidGrant: true,
|
|
329
|
+
status: err.status,
|
|
330
|
+
httpStatus: err.httpStatus,
|
|
331
|
+
code: err.code,
|
|
332
|
+
headers: err.headers,
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
throw failure;
|
|
316
336
|
}
|
|
317
337
|
}
|
|
318
338
|
|
|
@@ -86,6 +86,9 @@ export class OpenAIOAuthProvider {
|
|
|
86
86
|
// so input alone is the context footprint. See registry.mjs.
|
|
87
87
|
static inputExcludesCache = false;
|
|
88
88
|
name = 'openai-oauth';
|
|
89
|
+
// Loop retry policy (send-with-recovery loopRetryPolicy): a connect failure waits for
|
|
90
|
+
// the network, and a content_filter refusal is replayed under the budget.
|
|
91
|
+
retryPolicy = Object.freeze({ unboundedConnectionRetry: true, contentFilterRetryable: true });
|
|
89
92
|
tokens = null;
|
|
90
93
|
_refreshFallbackUntil = 0;
|
|
91
94
|
// Sticky transport fallback is isolated by the WS pool/session key. A
|
|
@@ -149,6 +152,11 @@ export class OpenAIOAuthProvider {
|
|
|
149
152
|
return this.tokens;
|
|
150
153
|
}
|
|
151
154
|
|
|
155
|
+
/** Drop a disposed transport scope's sticky transport record. */
|
|
156
|
+
releaseTransportScope(scope) {
|
|
157
|
+
this._httpFallbackUntilByPoolKey.delete(scope);
|
|
158
|
+
}
|
|
159
|
+
|
|
152
160
|
send(messages, model, tools, sendOpts) {
|
|
153
161
|
return withEffortConfigurationFallback('openai-oauth', model, sendOpts || {}, (opts) =>
|
|
154
162
|
this._sendOnce(messages, model, tools, opts)
|
|
@@ -204,7 +212,8 @@ export class OpenAIOAuthProvider {
|
|
|
204
212
|
// session. cacheKey is body.prompt_cache_key and affects prompt-cache
|
|
205
213
|
// routing only; Codex handshake identity comes from sendOpts and remains
|
|
206
214
|
// independent so a future cache-lane policy cannot merge conversations.
|
|
207
|
-
|
|
215
|
+
// A forked request runs in its own transport scope (transport-scope.mjs).
|
|
216
|
+
const poolKey = opts.transportScope || opts.sessionId || null;
|
|
208
217
|
const cacheKey = body.prompt_cache_key || resolveProviderCacheKey(opts, 'openai-oauth');
|
|
209
218
|
const iteration = Number.isFinite(Number(opts.iteration)) ? Number(opts.iteration) : null;
|
|
210
219
|
const sendWs = typeof opts._sendViaWebSocketFn === 'function' ? opts._sendViaWebSocketFn : sendViaWebSocket;
|
|
@@ -277,6 +286,8 @@ export class OpenAIOAuthProvider {
|
|
|
277
286
|
process.stderr.write(`[agent-trace] provider-${status}-retry attempt=1\n`);
|
|
278
287
|
}
|
|
279
288
|
this._refreshFallbackUntil = 0;
|
|
289
|
+
// One forced refresh per send, shared with the HTTP/SSE dispatch.
|
|
290
|
+
authState.authRefreshed = true;
|
|
280
291
|
authState.tokens = await this.ensureAuth({ forceRefresh: true, reason: String(status) });
|
|
281
292
|
try {
|
|
282
293
|
const result = await dispatch.dispatchWs(true);
|