mixdog 1.2.0 → 1.2.2
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 +7 -5
- package/package.json +1 -1
- package/scripts/gate-local.mjs +19 -3
- package/scripts/model-catalog-audit.mjs +1 -15
- package/src/agents/reviewer/AGENT.md +3 -3
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +5 -0
- package/src/defaults/skills/pptx/SKILL.md +6 -6
- package/src/defaults/skills/pptx/references/review.md +6 -4
- package/src/defaults/skills/pptx/scripts/source-extract.mjs +1 -1
- package/src/defaults/skills/setup/references/actions.md +13 -3
- package/src/defaults/skills/visualize/SKILL.md +12 -9
- package/src/repl/slash-commands.mjs +16 -1
- package/src/rules/shared/60-verification.md +3 -1
- package/src/rules/shared/70-delivery.md +4 -2
- 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/cache-mtime.mjs +26 -5
- package/src/runtime/agent/orchestrator/config.mjs +10 -4
- package/src/runtime/agent/orchestrator/context/collect.mjs +2 -1
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +11 -5
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +74 -21
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +122 -15
- package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +54 -11
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +104 -9
- package/src/runtime/agent/orchestrator/mcp/client.mjs +358 -140
- package/src/runtime/agent/orchestrator/mcp/lazy-output-validator.mjs +25 -0
- 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/mcp/plugin-placeholders.mjs +54 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +294 -44
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +94 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +96 -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 +25 -21
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +3 -1
- 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 +73 -35
- 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.mjs +8 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +53 -18
- 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 +30 -14
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +93 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +82 -9
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +337 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-tokens.mjs +159 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +447 -0
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +38 -5
- 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 +102 -23
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +103 -33
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +29 -6
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +18 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -4
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +86 -19
- package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +29 -8
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +191 -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-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 +21 -82
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +71 -12
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +21 -20
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +97 -51
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +68 -19
- package/src/runtime/agent/orchestrator/providers/lib/gemini-model-catalog.mjs +7 -1
- 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-bridge.mjs +1080 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +15 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +35 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +4 -9
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +12 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +6 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +5 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +22 -0
- 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 +6 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +23 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +16 -8
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +94 -13
- 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 +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +6 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +23 -14
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +26 -6
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +42 -25
- 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/terminal-frames.mjs +18 -11
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +1 -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 +2 -3
- 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-oauth-dispatch.mjs +34 -3
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +22 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +5 -9
- package/src/runtime/agent/orchestrator/providers/openai-retry-policy.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-handshake.mjs +16 -8
- 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-terminal.mjs +18 -11
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +35 -24
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +581 -0
- package/src/runtime/agent/orchestrator/providers/registry.mjs +35 -9
- package/src/runtime/agent/orchestrator/providers/retry-backoff.mjs +46 -7
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +118 -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/runtime-core/config-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +15 -55
- package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +15 -2
- 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 +268 -181
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +21 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +54 -3
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +284 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +270 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/sqlite-gate.mjs +27 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +628 -0
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +184 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +136 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +128 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +127 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +101 -0
- package/src/runtime/agent/orchestrator/session/explicit-skills.mjs +83 -5
- package/src/runtime/agent/orchestrator/session/imported-message.mjs +11 -0
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -4
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +102 -18
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +42 -5
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +14 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +20 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +50 -23
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +22 -14
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +18 -7
- package/src/runtime/agent/orchestrator/session/manager.mjs +0 -1
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +155 -29
- package/src/runtime/agent/orchestrator/session/store/listing.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +6 -0
- 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-catalog.mjs +819 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +22 -12
- package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +158 -0
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +183 -374
- package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +41 -3
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +38 -17
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +12 -15
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +17 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -0
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +5 -5
- package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +6 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +173 -22
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +8 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +5 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +15 -2
- package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +13 -10
- package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +17 -12
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/apply-patch/codex-batch.mjs +4 -4
- package/src/runtime/agent/orchestrator/tools/patch/apply-patch/route.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/read-redirects.mjs +34 -30
- package/src/runtime/agent/orchestrator/tools/patch/sequence/units.mjs +7 -7
- package/src/runtime/agent/orchestrator/tools/patch/sequence.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +4 -0
- package/src/runtime/attachments/store.d.mts +3 -0
- package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +1 -1
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +16 -4
- package/src/runtime/channels/lib/worker-main.mjs +17 -14
- package/src/runtime/computer-bridge/linux-readiness.mjs +0 -2
- package/src/runtime/effort-judge/judge-client.mjs +56 -18
- package/src/runtime/memory/lib/memory.mjs +1 -1
- package/src/runtime/memory/lib/pg/process.mjs +34 -24
- package/src/runtime/memory/lib/pg/supervisor.mjs +16 -13
- package/src/runtime/memory/lib/session-ingest.mjs +2 -2
- package/src/runtime/office/README.md +1 -1
- package/src/runtime/office/shared/values.mjs +0 -5
- package/src/runtime/shared/atomic-file.mjs +25 -4
- package/src/runtime/shared/background-tasks.mjs +92 -14
- package/src/runtime/shared/err-text.mjs +25 -0
- package/src/runtime/shared/error-presentation.mjs +159 -19
- package/src/runtime/shared/extension-scopes.mjs +5 -3
- package/src/runtime/shared/file-lock.mjs +37 -11
- package/src/runtime/shared/llm/anthropic-betas.mjs +4 -3
- package/src/runtime/shared/llm/anthropic-effort.mjs +134 -131
- package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +50 -14
- package/src/runtime/shared/llm/model-catalog.mjs +53 -52
- package/src/runtime/shared/llm/openai-daybreak.mjs +4 -16
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +17 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +13 -4
- package/src/runtime/shared/llm/usage-rollup.mjs +0 -1
- package/src/runtime/shared/model-display.mjs +13 -0
- package/src/runtime/shared/plugin-manifest.mjs +18 -9
- package/src/runtime/shared/pristine-execution-contract.json +9 -2
- package/src/runtime/shared/pristine-execution.mjs +28 -4
- package/src/runtime/shared/provider-accounts.mjs +124 -20
- package/src/runtime/shared/provider-api-key.mjs +12 -0
- package/src/runtime/shared/quota-resume-store.mjs +11 -0
- package/src/runtime/shared/session-baseline-store.mjs +960 -0
- package/src/runtime/shared/shell-display.mjs +9 -3
- package/src/runtime/shared/skill-mentions.d.mts +10 -0
- package/src/runtime/shared/skill-mentions.mjs +133 -0
- package/src/runtime/shared/skill-script-runtime.mjs +264 -0
- package/src/runtime/shared/statusline/statusline-format.mjs +4 -4
- package/src/runtime/shared/task-notification-envelope.mjs +2 -2
- package/src/runtime/shared/tool-primitives.mjs +35 -2
- package/src/runtime/shared/turn-changes.mjs +447 -219
- package/src/runtime/shared/turn-snapshot-store.mjs +182 -1
- package/src/runtime/shared/turn-snapshot.mjs +170 -48
- package/src/runtime/shared/turn-worktree-snapshot.mjs +160 -51
- package/src/runtime/shared/worker-requests.mjs +15 -2
- package/src/runtime/shared/worktrees/contract.mjs +0 -24
- package/src/runtime/shared/worktrees/test-support.mjs +19 -4
- package/src/session-runtime/automation-agents.mjs +8 -2
- package/src/session-runtime/boot/apis.mjs +61 -0
- package/src/session-runtime/boot/config.mjs +5 -2
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/infrastructure.mjs +35 -18
- package/src/session-runtime/conversation-import/discovery.mjs +698 -0
- package/src/session-runtime/conversation-import/service.mjs +369 -0
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +10 -5
- package/src/session-runtime/cwd-plugins/plugin-status.mjs +47 -42
- package/src/session-runtime/lifecycle/session-catalog.mjs +2 -0
- package/src/session-runtime/lifecycle/teardown.mjs +1 -1
- package/src/session-runtime/mcp-glue/connect.mjs +83 -16
- package/src/session-runtime/mcp-glue/plugin-servers.mjs +499 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +135 -33
- package/src/session-runtime/mcp-glue.mjs +25 -2
- 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 +83 -15
- 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/new-session-config.mjs +3 -2
- package/src/session-runtime/notification-bus.mjs +9 -2
- package/src/session-runtime/provider-auth/accounts.mjs +33 -15
- package/src/session-runtime/provider-models/model-meta.mjs +12 -3
- package/src/session-runtime/provider-models/web-search-catalog.mjs +5 -1
- package/src/session-runtime/provider-readiness.mjs +16 -10
- 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 +24 -5
- package/src/session-runtime/resource-mcp-api.mjs +198 -78
- package/src/session-runtime/resource-plugins-api.mjs +29 -41
- package/src/session-runtime/resource-scope-decorate.mjs +6 -8
- package/src/session-runtime/resource-skills-api.mjs +23 -2
- package/src/session-runtime/runtime-review-api.mjs +13 -0
- package/src/session-runtime/schedule-session-run.mjs +1 -1
- 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/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/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-rows.mjs +17 -0
- package/src/session-runtime/services/channel-session-router.mjs +4 -1
- package/src/session-runtime/services/hook-bus/command-handler.mjs +4 -1
- package/src/session-runtime/services/hook-bus/handlers.mjs +7 -3
- package/src/session-runtime/services/provider-admin.mjs +64 -18
- package/src/session-runtime/services/usage-dashboard-model.mjs +3 -0
- package/src/session-runtime/settings-compaction-api.mjs +1 -0
- package/src/session-runtime/setup-tool/executor.mjs +12 -1
- package/src/session-runtime/setup-tool/extended-actions.mjs +1 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +1 -0
- package/src/session-runtime/setup-tool/tool-defs.mjs +7 -1
- package/src/session-runtime/skills-api.mjs +7 -3
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/webhook-session-run.mjs +16 -4
- package/src/skill-script-entry.mjs +36 -0
- package/src/standalone/daemon-drain-policy.mjs +8 -0
- package/src/standalone/daemon-stored-session-views.mjs +11 -3
- package/src/standalone/daemon-telemetry.mjs +55 -0
- package/src/standalone/daemon.mjs +44 -11
- package/src/standalone/session-protocol.mjs +12 -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 +6 -1
- package/src/standalone/session-service-api.mjs +5 -0
- package/src/standalone/session-service.mjs +1 -0
- package/src/tui/App.jsx +9 -1
- package/src/tui/app/app-view/floating-panel.jsx +9 -1
- package/src/tui/app/app-view.jsx +7 -0
- package/src/tui/app/create-app-pickers.mjs +4 -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/plugins-pickers.mjs +35 -16
- package/src/tui/app/extension-pickers.mjs +2 -1
- package/src/tui/app/model-options.mjs +13 -16
- package/src/tui/app/skill-mention-palette.mjs +88 -0
- package/src/tui/app/slash-commands.mjs +7 -2
- package/src/tui/app/slash-dispatch/panel-commands.mjs +16 -1
- package/src/tui/app/slash-palette.mjs +23 -7
- package/src/tui/app/transcript-row-estimate.mjs +11 -3
- package/src/tui/app/use-prompt-draft-flow.mjs +7 -2
- package/src/tui/app/use-prompt-state.mjs +5 -0
- package/src/tui/components/Message.jsx +22 -1
- package/src/tui/components/PromptInput.jsx +21 -3
- package/src/tui/components/SlashCommandPalette.jsx +12 -3
- package/src/tui/components/StatusLine.jsx +2 -0
- package/src/tui/components/TranscriptItem.jsx +9 -1
- package/src/tui/components/prompt-input/key-handler.mjs +21 -8
- 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/components/user-message-skills.mjs +38 -0
- package/src/tui/dist/index.mjs +1323 -214
- package/src/tui/session/queue-helpers.mjs +7 -2
- package/src/tui/session/quota-resume.mjs +46 -14
- package/src/tui/session/session-api/commands.mjs +33 -24
- package/src/tui/session/session-api/extensions.mjs +26 -2
- package/src/tui/session/session-api/integrations.mjs +7 -0
- package/src/tui/session/session-api/lifecycle.mjs +5 -1
- package/src/tui/session/session-api/routes.mjs +71 -7
- package/src/tui/session/session-api/settings.mjs +12 -14
- package/src/tui/session/session-flow/drain.mjs +21 -5
- package/src/tui/session/session-flow/failed-turn-rewind.mjs +10 -4
- package/src/tui/session/tui-steering-persist.mjs +25 -9
- package/src/tui/session/turn.mjs +55 -15
- 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/runtime/effort-judge/previous-human-request.mjs +0 -162
- package/src/runtime/effort-judge/verified-context-input.mjs +0 -10
- package/src/runtime/memory/lib/memory-session-merge.mjs +0 -32
- package/src/runtime/shared/llm/usage-session-history.mjs +0 -266
|
@@ -10,7 +10,8 @@ import {
|
|
|
10
10
|
incompleteReasonFromEvent,
|
|
11
11
|
isMaxOutputIncompleteReason,
|
|
12
12
|
} from '../../lib/responses-terminal-fields.mjs';
|
|
13
|
-
import {
|
|
13
|
+
import { applyErrorContract, markContentFilter } from '../../openai-error-contract.mjs';
|
|
14
|
+
import { toolInputPending } from '../response-state.mjs';
|
|
14
15
|
import { normalizeWsUsage } from '../../openai-ws-response-state/usage.mjs';
|
|
15
16
|
|
|
16
17
|
// Typed status only — nothing is synthesized from text. The frame itself is
|
|
@@ -19,11 +20,14 @@ import { normalizeWsUsage } from '../../openai-ws-response-state/usage.mjs';
|
|
|
19
20
|
function wireFailureError(message, event, detail, typedSources) {
|
|
20
21
|
const err = new Error(message);
|
|
21
22
|
err.responseFailed = event;
|
|
22
|
-
const typed = typedStatusFrom(...typedSources);
|
|
23
|
-
if (typed) err.httpStatus = typed;
|
|
24
23
|
const code = detail?.code ?? detail?.type ?? null;
|
|
25
24
|
if (typeof code === 'string' && code) err.providerErrorCode = code;
|
|
26
|
-
return err
|
|
25
|
+
return applyErrorContract(err, {
|
|
26
|
+
status: typedStatusFrom(...typedSources),
|
|
27
|
+
code: typeof code === 'string' ? code : undefined,
|
|
28
|
+
error: detail,
|
|
29
|
+
event,
|
|
30
|
+
});
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
export function createTerminalFrameEvents({ state, items, text, outcome, meaningful }) {
|
|
@@ -89,7 +93,7 @@ export function createTerminalFrameEvents({ state, items, text, outcome, meaning
|
|
|
89
93
|
absorbTerminalResponse(event.response || {});
|
|
90
94
|
const reason = incompleteReasonFromEvent(event);
|
|
91
95
|
if (!isMaxOutputIncompleteReason(reason)) {
|
|
92
|
-
const err = new Error(`${
|
|
96
|
+
const err = markContentFilter(new Error(`${state.label} ${frame}: ${reason}`), reason);
|
|
93
97
|
// Still billed: the provider-boundary accounting records reported usage.
|
|
94
98
|
if (state.usage) {
|
|
95
99
|
err.partialUsage = state.usage;
|
|
@@ -98,7 +102,7 @@ export function createTerminalFrameEvents({ state, items, text, outcome, meaning
|
|
|
98
102
|
throw err;
|
|
99
103
|
}
|
|
100
104
|
if (toolInputPending(state)) {
|
|
101
|
-
const err = outcome.stampToolSafety(new Error(`${
|
|
105
|
+
const err = outcome.stampToolSafety(new Error(`${state.label} ${frame} (max_output_tokens) with tool call in flight`));
|
|
102
106
|
err.streamStalled = true;
|
|
103
107
|
err.pendingToolUse = true;
|
|
104
108
|
err.partialContent = state.content;
|
|
@@ -119,9 +123,12 @@ export function createTerminalFrameEvents({ state, items, text, outcome, meaning
|
|
|
119
123
|
setEndTurn(event);
|
|
120
124
|
} else if (event.response.status === 'failed') {
|
|
121
125
|
const msg = event.response?.error?.message || 'response.done failed';
|
|
122
|
-
const err = new Error(`${
|
|
123
|
-
|
|
124
|
-
|
|
126
|
+
const err = new Error(`${state.label} response.done failed: ${msg}`);
|
|
127
|
+
applyErrorContract(err, {
|
|
128
|
+
status: typedStatusFrom(event.response?.error, event.error, event),
|
|
129
|
+
error: event.response?.error || event.error || null,
|
|
130
|
+
event,
|
|
131
|
+
});
|
|
125
132
|
throw withFailedUsage(err, event);
|
|
126
133
|
} else if (event.response.status === 'incomplete') {
|
|
127
134
|
onIncomplete(event, 'response.done incomplete');
|
|
@@ -131,7 +138,7 @@ export function createTerminalFrameEvents({ state, items, text, outcome, meaning
|
|
|
131
138
|
const failedFrameError = (event) =>
|
|
132
139
|
withFailedUsage(
|
|
133
140
|
wireFailureError(
|
|
134
|
-
`${
|
|
141
|
+
`${state.label} response.failed: ${event.response?.error?.message || event.error?.message || event.message || 'response.failed'}`,
|
|
135
142
|
event,
|
|
136
143
|
event.response?.error || event.error || null,
|
|
137
144
|
[event.response?.error, event.error, event]
|
|
@@ -142,7 +149,7 @@ export function createTerminalFrameEvents({ state, items, text, outcome, meaning
|
|
|
142
149
|
// Same wire-error contract as response.failed.
|
|
143
150
|
const errorFrameError = (event) =>
|
|
144
151
|
wireFailureError(
|
|
145
|
-
`${
|
|
152
|
+
`${state.label} error: ${event.message || event.error?.message || 'unknown'}`,
|
|
146
153
|
event,
|
|
147
154
|
{ code: event.error?.code ?? event.error?.type ?? event.code ?? null },
|
|
148
155
|
[event.error, event]
|
package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs
CHANGED
|
@@ -8,7 +8,6 @@ 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';
|
|
13
12
|
|
|
14
13
|
export function createResponseOutcome({ state }) {
|
|
@@ -50,7 +49,7 @@ export function createResponseOutcome({ state }) {
|
|
|
50
49
|
throw stampOutcome(
|
|
51
50
|
stampToolSafety(
|
|
52
51
|
new Error(
|
|
53
|
-
`${
|
|
52
|
+
`${state.label} function_call salvage failed: missing call_id/name for item_id=${unresolved._pendingItemId || '?'}`
|
|
54
53
|
)
|
|
55
54
|
)
|
|
56
55
|
);
|
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
|
@@ -8,10 +8,9 @@
|
|
|
8
8
|
import { createActiveToolItemTracker } from '../tool-stream-state.mjs';
|
|
9
9
|
import { createToolCallDedupe } from '../lib/leaked-toolcall.mjs';
|
|
10
10
|
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
export function createResponseState() {
|
|
11
|
+
export function createResponseState(label) {
|
|
14
12
|
return {
|
|
13
|
+
label,
|
|
15
14
|
content: '',
|
|
16
15
|
model: '',
|
|
17
16
|
responseId: '',
|
|
@@ -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) => {
|
|
@@ -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) {
|
|
@@ -130,6 +133,17 @@ export function createOpenAiOAuthDispatch({
|
|
|
130
133
|
});
|
|
131
134
|
} catch {}
|
|
132
135
|
};
|
|
136
|
+
// A 401 is recoverable once per send, and only while nothing the turn
|
|
137
|
+
// produced could be duplicated by reissuing it.
|
|
138
|
+
const canReissueAfter401 = (err) =>
|
|
139
|
+
Number(err?.httpStatus || err?.status || 0) === 401 &&
|
|
140
|
+
authState.authRefreshed !== true &&
|
|
141
|
+
!externalSignal?.aborted &&
|
|
142
|
+
err?.liveTextEmitted !== true &&
|
|
143
|
+
err?.emittedToolCall !== true &&
|
|
144
|
+
err?.toolCallEmitted !== true &&
|
|
145
|
+
err?.unsafeToRetry !== true &&
|
|
146
|
+
isReplaySafe(err);
|
|
133
147
|
const dispatchHttp = async (reason, originalErr = null, { sticky = false } = {}) => {
|
|
134
148
|
// Transport switching is a session decision, not an HTTP-success
|
|
135
149
|
// side effect. Persist it before the fallback can fail or abort.
|
|
@@ -158,9 +172,10 @@ export function createOpenAiOAuthDispatch({
|
|
|
158
172
|
if (!process.env.MIXDOG_QUIET_PROVIDER_LOG)
|
|
159
173
|
process.stderr.write(`[openai-oauth] WebSocket unhealthy (${reason}); falling back to HTTP/SSE\n`);
|
|
160
174
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
175
|
+
// The server's retry deadline outlives a transport switch.
|
|
176
|
+
if (originalErr && reason !== 'forced') await waitForRetryDeadline(originalErr, externalSignal, opts._sleepFn);
|
|
177
|
+
const sendHttpOnce = () =>
|
|
178
|
+
sendHttp({
|
|
164
179
|
auth: authState.tokens,
|
|
165
180
|
body,
|
|
166
181
|
opts,
|
|
@@ -175,6 +190,22 @@ export function createOpenAiOAuthDispatch({
|
|
|
175
190
|
useModel,
|
|
176
191
|
fetchFn: opts._fetchFn,
|
|
177
192
|
});
|
|
193
|
+
let result;
|
|
194
|
+
try {
|
|
195
|
+
try {
|
|
196
|
+
result = await sendHttpOnce();
|
|
197
|
+
} catch (firstErr) {
|
|
198
|
+
if (!canReissueAfter401(firstErr)) throw firstErr;
|
|
199
|
+
// Same bounded, replay-safe recovery the WS path applies: one forced
|
|
200
|
+
// refresh per send, one reissue of the identical request.
|
|
201
|
+
noteErrorUsage(firstErr);
|
|
202
|
+
traceTransportError(firstErr, 'primary', 'http');
|
|
203
|
+
process.stderr.write('[openai-oauth-http] 401 — forcing refresh and retrying once over HTTP/SSE\n');
|
|
204
|
+
authState.authRefreshed = true;
|
|
205
|
+
provider._refreshFallbackUntil = 0;
|
|
206
|
+
authState.tokens = await provider.ensureAuth({ forceRefresh: true, reason: '401' });
|
|
207
|
+
result = await sendHttpOnce();
|
|
208
|
+
}
|
|
178
209
|
} catch (httpErr) {
|
|
179
210
|
// The current transport owns the terminal decision, including
|
|
180
211
|
// auth, rate limits, cancellation and output-safety markers.
|
|
@@ -16,6 +16,7 @@ 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';
|
|
@@ -165,6 +166,7 @@ export async function sendViaHttpSse({
|
|
|
165
166
|
onStageChange?.('streaming');
|
|
166
167
|
} catch {}
|
|
167
168
|
const sseStartedAt = Date.now();
|
|
169
|
+
const label = httpLabel(auth);
|
|
168
170
|
const reader = response.body.getReader();
|
|
169
171
|
const decoder = new TextDecoder();
|
|
170
172
|
let ttftMs = null;
|
|
@@ -173,6 +175,7 @@ export async function sendViaHttpSse({
|
|
|
173
175
|
reader,
|
|
174
176
|
totalTimeout,
|
|
175
177
|
stallPartial: () => state.stallPartial(),
|
|
178
|
+
label,
|
|
176
179
|
});
|
|
177
180
|
const meaningful = (kind = 'semantic') => {
|
|
178
181
|
if (ttftMs == null) ttftMs = Date.now() - sseStartedAt;
|
|
@@ -187,6 +190,7 @@ export async function sendViaHttpSse({
|
|
|
187
190
|
onTextDelta,
|
|
188
191
|
meaningful,
|
|
189
192
|
onServerEvent: watchdogs.noteServerEvent,
|
|
193
|
+
label,
|
|
190
194
|
});
|
|
191
195
|
const foldFrames = async (text) => {
|
|
192
196
|
const parsed = _sseEventsFromBuffer(text);
|
|
@@ -202,7 +206,7 @@ export async function sendViaHttpSse({
|
|
|
202
206
|
if (totalTimeout.signal?.aborted) {
|
|
203
207
|
watchdogs.clearSemanticIdle();
|
|
204
208
|
const reason = totalTimeout.signal.reason;
|
|
205
|
-
throw reason instanceof Error ? reason : new Error(
|
|
209
|
+
throw reason instanceof Error ? reason : new Error(`${label} aborted`);
|
|
206
210
|
}
|
|
207
211
|
const abortReason = watchdogs.abortReason();
|
|
208
212
|
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
|
|
@@ -277,6 +280,8 @@ export class OpenAIOAuthProvider {
|
|
|
277
280
|
process.stderr.write(`[agent-trace] provider-${status}-retry attempt=1\n`);
|
|
278
281
|
}
|
|
279
282
|
this._refreshFallbackUntil = 0;
|
|
283
|
+
// One forced refresh per send, shared with the HTTP/SSE dispatch.
|
|
284
|
+
authState.authRefreshed = true;
|
|
280
285
|
authState.tokens = await this.ensureAuth({ forceRefresh: true, reason: String(status) });
|
|
281
286
|
try {
|
|
282
287
|
const result = await dispatch.dispatchWs(true);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Transcript lowering is independent of request/turn metadata. A retained
|
|
2
2
|
// message must have the same wire representation in every subsequent request.
|
|
3
3
|
import { providerReplayItems } from './lib/provider-replay.mjs';
|
|
4
|
+
import { responsesEffortUpdates } from './effort-configuration.mjs';
|
|
4
5
|
import { ensureResponsesCallOutputs } from './lib/wire-pairing.mjs';
|
|
5
6
|
import { normalizeContentForOpenAIResponses, splitToolContentForOpenAIResponses } from './media-normalization.mjs';
|
|
6
7
|
import {
|
|
@@ -156,21 +157,16 @@ export function convertMessagesToResponsesInput(messages, opts = {}) {
|
|
|
156
157
|
if (!pendingToolMedia.length) return;
|
|
157
158
|
out.push(wireMessage('user', pendingToolMedia.splice(0)));
|
|
158
159
|
};
|
|
159
|
-
|
|
160
|
-
// message before it. Adjacent updates are rejected, so a batch update that
|
|
161
|
-
// a user message directly follows yields to that message's own.
|
|
162
|
-
let afterBatch = null;
|
|
160
|
+
const effortUpdates = responsesEffortUpdates(opts.effortProjection);
|
|
163
161
|
for (const m of messages) {
|
|
164
162
|
if (!m || m.role === 'system') continue;
|
|
165
|
-
const
|
|
163
|
+
const updates = effortUpdates.before(m);
|
|
166
164
|
if (m.role === 'tool') {
|
|
167
165
|
pushToolResult(m, { out, pendingToolMedia, pendingToolLoads, customToolCallNameById, nativeSearchCalls, opts });
|
|
168
|
-
if (changedEffort) afterBatch = changedEffort;
|
|
169
166
|
continue;
|
|
170
167
|
}
|
|
171
168
|
flushToolMedia();
|
|
172
|
-
|
|
173
|
-
afterBatch = null;
|
|
169
|
+
out.push(...updates);
|
|
174
170
|
// Preserve original assistant phases and item order even when encrypted
|
|
175
171
|
// reasoning is explicitly disabled. Never replay another provider's data.
|
|
176
172
|
const orderedReplay =
|
|
@@ -212,7 +208,7 @@ export function convertMessagesToResponsesInput(messages, opts = {}) {
|
|
|
212
208
|
pushReasoningItems(m, 'after');
|
|
213
209
|
}
|
|
214
210
|
flushToolMedia();
|
|
215
|
-
|
|
211
|
+
out.push(...effortUpdates.end());
|
|
216
212
|
// Wire-level pairing guard: replay envelopes can carry a call whose
|
|
217
213
|
// result never committed (cancel/abort). The provider hard-rejects the
|
|
218
214
|
// unpaired call, so synthesize the missing outputs here.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// OpenAI retry schedule: 200ms base, factor 2, ±10%.
|
|
2
|
+
// Provider-owned values; the shared retry core only takes them as options.
|
|
3
|
+
// CODEX_STREAM_BACKOFF_MS — indexed by the 1-based retry number
|
|
4
|
+
// (midstreamBackoffFor).
|
|
5
|
+
// CODEX_REQUEST_RETRY_BACKOFF_MS — leading duplicate for withRetry's
|
|
6
|
+
// sleep-before-attempt index.
|
|
7
|
+
export const CODEX_STREAM_BACKOFF_MS = Object.freeze([200, 400, 800, 1600, 3200]);
|
|
8
|
+
export const CODEX_REQUEST_RETRY_BACKOFF_MS = Object.freeze([200, ...CODEX_STREAM_BACKOFF_MS]);
|
|
9
|
+
export const CODEX_RETRY_JITTER_RATIO = 0.1;
|
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
import { appendFileSync, chmodSync } from 'node:fs';
|
|
10
10
|
import { errText } from '../../../shared/err-text.mjs';
|
|
11
11
|
import { _cfCookieCapture, _formatRedactedHeaders } from './openai-ws-headers.mjs';
|
|
12
|
+
import { httpResponseError } from './openai-error-contract.mjs';
|
|
13
|
+
|
|
14
|
+
// Enough of the handshake body to parse a typed JSON error; diagnostics are
|
|
15
|
+
// truncated separately by the error message.
|
|
16
|
+
const HANDSHAKE_BODY_LIMIT = 16 * 1024;
|
|
12
17
|
|
|
13
18
|
/** CF cookie jar refresh plus the opt-in upgrade-header dump. */
|
|
14
19
|
export function captureHandshakeUpgrade(auth, res) {
|
|
@@ -85,7 +90,7 @@ export function attachHandshakeFailureHandlers({ socket, errLabel, openStart, is
|
|
|
85
90
|
const status = res?.statusCode || 0;
|
|
86
91
|
let body = '';
|
|
87
92
|
res.on('data', (c) => {
|
|
88
|
-
if (body.length <
|
|
93
|
+
if (body.length < HANDSHAKE_BODY_LIMIT) body += c.toString('utf-8');
|
|
89
94
|
});
|
|
90
95
|
res.on('end', () => {
|
|
91
96
|
if (process.env.MIXDOG_DEBUG_AGENT) {
|
|
@@ -96,13 +101,16 @@ export function attachHandshakeFailureHandlers({ socket, errLabel, openStart, is
|
|
|
96
101
|
try {
|
|
97
102
|
socket.terminate();
|
|
98
103
|
} catch {}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
// Status, headers and the parsed body ride on the error; only the
|
|
105
|
+
// message is truncated.
|
|
106
|
+
const err = httpResponseError({
|
|
107
|
+
label: `${errLabel} handshake`,
|
|
108
|
+
status,
|
|
109
|
+
headers: res.headers,
|
|
110
|
+
text: body,
|
|
111
|
+
});
|
|
112
|
+
err.httpBody = body;
|
|
113
|
+
settle(false, err);
|
|
106
114
|
});
|
|
107
115
|
});
|
|
108
116
|
}
|
package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* WS send, plus the surface/backoff primitives both failure resolvers use.
|
|
4
4
|
*/
|
|
5
5
|
import { performance } from 'node:perf_hooks';
|
|
6
|
-
import { retryAfterMsFromError } from '../retry-classifier.mjs';
|
|
7
6
|
import { _sleepWithAbort, MIDSTREAM_WS_TRANSIENT_RETRY_LIMIT, midstreamBackoffFor, tag } from './policy.mjs';
|
|
8
7
|
|
|
9
8
|
export function createAttemptContext(deps) {
|
|
@@ -35,7 +34,7 @@ export function createAttemptContext(deps) {
|
|
|
35
34
|
const backoff = async (retryNumber, err = null) => {
|
|
36
35
|
const sleepStart = performance.now();
|
|
37
36
|
try {
|
|
38
|
-
await _sleepWithAbort(
|
|
37
|
+
await _sleepWithAbort(midstreamBackoffFor(retryNumber, err), externalSignal, sleepFn);
|
|
39
38
|
} catch (sleepErr) {
|
|
40
39
|
sendSpan.retryBackoffMs += performance.now() - sleepStart;
|
|
41
40
|
sendSpan.emit('error');
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
* policy.mjs — the WS send retry budget, its backoff curves and the
|
|
3
3
|
* classification wrappers shared by the handshake and stream resolvers.
|
|
4
4
|
*/
|
|
5
|
+
import { CODEX_RETRY_JITTER_RATIO, CODEX_STREAM_BACKOFF_MS } from '../openai-retry-policy.mjs';
|
|
5
6
|
import {
|
|
6
7
|
classifyHandshakeError,
|
|
7
8
|
classifyMidstreamError,
|
|
8
9
|
isWsMessageTooBigClose,
|
|
9
|
-
jitterDelayMs,
|
|
10
10
|
MIDSTREAM_RETRY_POLICY,
|
|
11
|
+
midstreamBackoffFor as sharedMidstreamBackoffFor,
|
|
11
12
|
sleepWithAbort,
|
|
12
13
|
} from '../retry-classifier.mjs';
|
|
13
14
|
|
|
@@ -15,23 +16,26 @@ import {
|
|
|
15
16
|
// by connect/handshake and pre-output stream failures.
|
|
16
17
|
export const MIDSTREAM_WS_TRANSIENT_RETRY_LIMIT = MIDSTREAM_RETRY_POLICY.ws.transientCloseRetries;
|
|
17
18
|
const MIDSTREAM_DEFAULT_RETRY_LIMIT = MIDSTREAM_RETRY_POLICY.ws.defaultRetries;
|
|
18
|
-
// The
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
// The stream retry schedule (200ms base, factor 2, ±10%) lives in
|
|
20
|
+
// openai-retry-policy.mjs, shared with the HTTP request loop.
|
|
21
|
+
// Advice-gated retry (OAuth and API-key WS alike): an overload and an untyped 429
|
|
22
|
+
// retry only when the server gave advice.
|
|
23
|
+
const ADVICE_GATES = Object.freeze({
|
|
24
|
+
overloadRetryRequiresAdvice: true,
|
|
25
|
+
generic429RetryRequiresAdvice: true,
|
|
26
|
+
});
|
|
22
27
|
// Policy object passed to the shared classifyMidstreamError for the WS path.
|
|
23
28
|
const WS_MIDSTREAM_POLICY = {
|
|
24
29
|
mode: 'ws',
|
|
25
30
|
transientCloseRetries: MIDSTREAM_RETRY_POLICY.ws.transientCloseRetries,
|
|
26
31
|
defaultRetries: MIDSTREAM_RETRY_POLICY.ws.defaultRetries,
|
|
32
|
+
...ADVICE_GATES,
|
|
27
33
|
};
|
|
28
34
|
|
|
29
35
|
// Kept for the _acquireWithRetry test seam and non-Codex callers.
|
|
30
36
|
// sendViaWebSocket deliberately invokes it with maxAttempts:1 so handshake
|
|
31
37
|
// failures consume the same stream budget as pre-output disconnects.
|
|
32
38
|
export const HANDSHAKE_MAX_ATTEMPTS = MIDSTREAM_WS_TRANSIENT_RETRY_LIMIT + 1;
|
|
33
|
-
const HANDSHAKE_BACKOFF_BASE_MS = 200;
|
|
34
|
-
const HANDSHAKE_BACKOFF_CAP_MS = 3200;
|
|
35
39
|
// These statuses are decisions made by the CURRENT attempt. They must never
|
|
36
40
|
// be replaced by a stale transient from an earlier retry: auth recovery,
|
|
37
41
|
// transport fallback, and Retry-After handling all depend on the live error.
|
|
@@ -47,8 +51,15 @@ export function _mustSurfaceCurrentAttempt(err, externalSignal) {
|
|
|
47
51
|
);
|
|
48
52
|
}
|
|
49
53
|
|
|
50
|
-
export function _classifyHandshakeError(
|
|
51
|
-
|
|
54
|
+
export function _classifyHandshakeError(
|
|
55
|
+
err,
|
|
56
|
+
{
|
|
57
|
+
retry429 = true,
|
|
58
|
+
overloadRetryRequiresAdvice = ADVICE_GATES.overloadRetryRequiresAdvice,
|
|
59
|
+
generic429RetryRequiresAdvice = ADVICE_GATES.generic429RetryRequiresAdvice,
|
|
60
|
+
} = {}
|
|
61
|
+
) {
|
|
62
|
+
return classifyHandshakeError(err, { retry429, overloadRetryRequiresAdvice, generic429RetryRequiresAdvice });
|
|
52
63
|
}
|
|
53
64
|
|
|
54
65
|
/**
|
|
@@ -103,15 +114,15 @@ export function midstreamRetryLimit(classifier) {
|
|
|
103
114
|
: MIDSTREAM_DEFAULT_RETRY_LIMIT;
|
|
104
115
|
}
|
|
105
116
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
117
|
+
// Passing the failure makes server advice replace the step for retryable
|
|
118
|
+
// kinds only (midstreamRetryDelayMs).
|
|
119
|
+
export function midstreamBackoffFor(retryNumber, err = null) {
|
|
120
|
+
return sharedMidstreamBackoffFor(retryNumber, CODEX_STREAM_BACKOFF_MS, err, CODEX_RETRY_JITTER_RATIO);
|
|
109
121
|
}
|
|
110
122
|
|
|
111
123
|
export function _backoffFor(attempt) {
|
|
112
124
|
// attempt is 1-based; exponential backoff is capped before jitter.
|
|
113
|
-
|
|
114
|
-
return jitterDelayMs(Math.min(raw, HANDSHAKE_BACKOFF_CAP_MS), CODEX_RETRY_JITTER_RATIO);
|
|
125
|
+
return midstreamBackoffFor(attempt);
|
|
115
126
|
}
|
|
116
127
|
|
|
117
128
|
export const _defaultSleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* builder returns a tagged Error the stream loop stores as terminalError.
|
|
5
5
|
*/
|
|
6
6
|
import { typedStatusFrom } from './retry-classifier.mjs';
|
|
7
|
+
import { applyErrorContract, markContentFilter } from './openai-error-contract.mjs';
|
|
7
8
|
import { _httpStatusFromWsClose } from './openai-ws-events.mjs';
|
|
8
9
|
|
|
9
10
|
/** A server `event.error` on any frame. Same wire-error contract as
|
|
@@ -17,10 +18,9 @@ export function serverErrorEventError(error, event) {
|
|
|
17
18
|
try {
|
|
18
19
|
err.payload = error;
|
|
19
20
|
err.responseFailed = event;
|
|
20
|
-
const typed = typedStatusFrom(error, event);
|
|
21
|
-
if (typed) err.httpStatus = typed;
|
|
22
21
|
const code = error.code ?? error.type ?? null;
|
|
23
22
|
if (typeof code === 'string' && code) err.providerErrorCode = code;
|
|
23
|
+
applyErrorContract(err, { status: typedStatusFrom(error, event), error, event });
|
|
24
24
|
} catch {}
|
|
25
25
|
return err;
|
|
26
26
|
}
|
|
@@ -32,23 +32,27 @@ export function serverErrorEventError(error, event) {
|
|
|
32
32
|
export function responseFailedError(event, { label, fallbackMessage, providerErrorCode = false }) {
|
|
33
33
|
const msg = event.response?.error?.message || event.error?.message || event.message || fallbackMessage;
|
|
34
34
|
const err = Object.assign(new Error(`${label}: ${msg}`), { responseFailed: event });
|
|
35
|
-
const
|
|
36
|
-
if (typed) err.httpStatus = typed;
|
|
35
|
+
const detail = event.response?.error || event.error || null;
|
|
37
36
|
if (providerErrorCode) {
|
|
38
|
-
const detail = event.response?.error || event.error || null;
|
|
39
37
|
const code = detail?.code ?? detail?.type ?? null;
|
|
40
38
|
if (typeof code === 'string' && code) err.providerErrorCode = code;
|
|
41
39
|
}
|
|
42
|
-
return err
|
|
40
|
+
return applyErrorContract(err, {
|
|
41
|
+
status: typedStatusFrom(event.response?.error, event.error, event),
|
|
42
|
+
error: detail,
|
|
43
|
+
event,
|
|
44
|
+
});
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
/** response.incomplete (or response.done status 'incomplete') for a reason
|
|
46
|
-
* other than max_output_tokens.
|
|
48
|
+
* other than max_output_tokens. A content_filter stop is a typed policy
|
|
49
|
+
* refusal (code 'content_filter'), not an untyped failure. */
|
|
47
50
|
export function responseIncompleteError(event, reasonStr, label) {
|
|
48
|
-
|
|
51
|
+
const err = Object.assign(new Error(`${label}: ${reasonStr}`), {
|
|
49
52
|
responseIncomplete: event,
|
|
50
53
|
incompleteReason: reasonStr,
|
|
51
54
|
});
|
|
55
|
+
return markContentFilter(err, reasonStr);
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
/** response.done with a status that is neither completed, failed nor incomplete. */
|
|
@@ -63,11 +67,14 @@ export function errorFrameError(event, label) {
|
|
|
63
67
|
const errMsg = String(event.message || event.error?.message || 'unknown');
|
|
64
68
|
const err = new Error(`${label}: ${errMsg}`);
|
|
65
69
|
err.responseFailed = event;
|
|
66
|
-
const typed = typedStatusFrom(event.error, event);
|
|
67
|
-
if (typed) err.httpStatus = typed;
|
|
68
70
|
const code = event.error?.code ?? event.error?.type ?? event.code ?? null;
|
|
69
71
|
if (typeof code === 'string' && code) err.providerErrorCode = code;
|
|
70
|
-
return err
|
|
72
|
+
return applyErrorContract(err, {
|
|
73
|
+
status: typedStatusFrom(event.error, event),
|
|
74
|
+
code: typeof code === 'string' ? code : undefined,
|
|
75
|
+
error: event.error,
|
|
76
|
+
event,
|
|
77
|
+
});
|
|
71
78
|
}
|
|
72
79
|
|
|
73
80
|
/** The socket closed before a terminal frame. */
|