mixdog 1.2.3 → 1.2.4
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/package.json +1 -1
- package/scripts/gate-local.mjs +6 -4
- package/scripts/lib/gate-scheduler.mjs +29 -11
- package/scripts/probe-provider-catalog.mjs +31 -0
- package/scripts/provider-pingpong-live.mjs +128 -38
- package/scripts/session-sweep.mjs +5 -25
- package/src/agents/maintainer/AGENT.md +1 -1
- package/src/agents/maintainer/agent.json +1 -1
- package/src/agents/reviewer/AGENT.md +2 -4
- package/src/agents/security/AGENT.md +1 -2
- package/src/agents/writer/AGENT.md +2 -3
- package/src/defaults/shipped-history.json +6 -1
- package/src/defaults/skills/image/SKILL.md +21 -23
- package/src/lib/keychain-cjs.cjs +13 -11
- package/src/rules/agent/AGENT.md +7 -5
- package/src/rules/lead/LEAD.md +7 -9
- package/src/rules/shared/45-destructive.md +4 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +28 -7
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -11
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +101 -23
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-api-key-fetch.mjs +36 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +26 -44
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +2 -5
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +41 -12
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +13 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +81 -10
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +109 -5
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +107 -37
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-native-context.mjs +48 -0
- package/src/runtime/agent/orchestrator/providers/cursor-wire-exec.mjs +144 -34
- package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +28 -4
- package/src/runtime/agent/orchestrator/providers/cursor-wire-request.mjs +8 -4
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +41 -11
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +67 -5
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +14 -4
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +14 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +9 -6
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -2
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +26 -4
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +12 -6
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +14 -6
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +4 -4
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/gemini-rest-stream/watchdogs.mjs +16 -5
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +6 -1
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +22 -10
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -2
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +33 -7
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +11 -2
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +9 -5
- package/src/runtime/agent/orchestrator/providers/lib/request-compression.mjs +86 -0
- package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +4 -2
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +16 -5
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +60 -16
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +11 -13
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +30 -19
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +42 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +13 -9
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +1 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +18 -7
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +36 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +51 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +11 -1
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +64 -52
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +1 -4
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +0 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +7 -6
- package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +13 -2
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/openrouter.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +5 -4
- package/src/runtime/agent/orchestrator/providers/registry.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/wire-route.mjs +14 -4
- package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +15 -3
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +6 -2
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +8 -6
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +30 -2
- package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +3 -2
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -3
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +3 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge-contract.mjs +6 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +10 -10
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +3 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +46 -8
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -8
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -2
- package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +24 -0
- package/src/runtime/agent/orchestrator/session/cache/tool-result-reuse.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -3
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +3 -11
- package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +6 -22
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +28 -0
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +0 -6
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +0 -6
- package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/historical-session-closure.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +2 -5
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +2 -4
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +0 -27
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -10
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +2 -9
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +1 -4
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +76 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +8 -9
- package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +1 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +3 -4
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +33 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-support.mjs +0 -4
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +21 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +38 -13
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +33 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +19 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +57 -13
- package/src/runtime/agent/orchestrator/session/manager/failed-turn-rewind.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +6 -120
- package/src/runtime/agent/orchestrator/session/manager/pending-persist-queue.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +29 -8
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +42 -49
- package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +50 -0
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +32 -14
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +17 -33
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +29 -13
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +45 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +2 -9
- package/src/runtime/agent/orchestrator/session/send-instrumentation.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/side-question.mjs +12 -7
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +5 -12
- package/src/runtime/agent/orchestrator/session/store/lifecycle-read.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/listing.mjs +2 -6
- package/src/runtime/agent/orchestrator/session/store/live-cache-eviction.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +46 -37
- package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/load-session.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +5 -11
- package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +59 -0
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/sweep/stale-sweep.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +27 -32
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +0 -8
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +6 -18
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +33 -106
- package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store-agent-worker-pool.mjs +5 -8
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +136 -196
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +50 -116
- package/src/runtime/agent/orchestrator/session/store-summary-locations.mjs +3 -29
- package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +7 -8
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +9 -20
- package/src/runtime/agent/orchestrator/session/store.mjs +3 -16
- package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +11 -12
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +37 -13
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +15 -4
- package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +4 -2
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +72 -15
- package/src/runtime/agent/orchestrator/session/turn-failure.mjs +45 -0
- package/src/runtime/agent/orchestrator/stall-policy.mjs +50 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +5 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +204 -10
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +160 -39
- package/src/runtime/agent/orchestrator/tools/builtin/git-partial-stage.mjs +7 -5
- package/src/runtime/agent/orchestrator/tools/builtin/grep-formatting.mjs +14 -5
- package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-context-expander.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-output.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-path-fanout.mjs +48 -44
- package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +10 -3
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +200 -17
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +5 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +20 -0
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +101 -2
- package/src/runtime/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +67 -0
- package/src/runtime/agent/orchestrator/tools/lib/process-table-fixture.mjs +50 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +303 -63
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +108 -18
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +77 -11
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +81 -5
- package/src/runtime/attachments/store.d.mts +9 -0
- package/src/runtime/attachments/store.mjs +80 -9
- package/src/runtime/browser-bridge/browser-action-contract.d.mts +0 -1
- package/src/runtime/browser-bridge/browser-action-contract.mjs +0 -2
- package/src/runtime/computer-bridge/action-schema.mjs +178 -178
- package/src/runtime/computer-bridge/linux-readiness.d.mts +0 -2
- package/src/runtime/computer-bridge/linux-readiness.mjs +0 -16
- package/src/runtime/effort-judge/judge-client.mjs +21 -4
- package/src/runtime/effort-judge/judge-worker.mjs +4 -1
- package/src/runtime/github/tool.mjs +118 -17
- package/src/runtime/media/adapters/codex-image.mjs +140 -21
- package/src/runtime/media/catalog.mjs +4 -4
- package/src/runtime/media/chatgpt-usage.mjs +55 -0
- package/src/runtime/media/defaults.mjs +37 -0
- package/src/runtime/media/jobs.mjs +12 -2
- package/src/runtime/media/lanes.mjs +12 -0
- package/src/runtime/media/tool-defs.mjs +15 -4
- package/src/runtime/media/tool.mjs +41 -12
- package/src/runtime/media/upstream-error.mjs +72 -6
- package/src/runtime/memory/lib/ingest/transcript-rows.mjs +1 -0
- package/src/runtime/memory/lib/pg/process.mjs +5 -7
- package/src/runtime/memory/lib/pg/supervisor.mjs +4 -1
- package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
- package/src/runtime/office/authoring/html-browser.mjs +18 -8
- package/src/runtime/office/authoring/pdf-html-runner.mjs +1 -1
- package/src/runtime/office/authoring/pptx-html-measure.mjs +1 -1
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
- package/src/runtime/office/core/office-write-ledger.mjs +1 -5
- package/src/runtime/office/index.mjs +2 -3
- package/src/runtime/office/pdf/pdf-analysis.mjs +0 -68
- package/src/runtime/session-search/session-search-ingest.mjs +1 -1
- package/src/runtime/shared/agent-reap-state.mjs +13 -0
- package/src/runtime/shared/atomic-file.d.mts +1 -1
- package/src/runtime/shared/background-tasks.mjs +6 -1
- package/src/runtime/shared/bounded-line-diff.mjs +11 -2
- package/src/runtime/shared/browser-launch.mjs +15 -0
- package/src/runtime/shared/err-text.mjs +42 -4
- package/src/runtime/shared/file-lock.mjs +6 -5
- package/src/runtime/shared/llm/anthropic-betas.mjs +1 -2
- package/src/runtime/shared/llm/provider-model-identities.mjs +1 -0
- package/src/runtime/shared/model-route-chain.d.mts +8 -0
- package/src/runtime/shared/model-route-chain.mjs +48 -0
- package/src/runtime/shared/model-route-fallback.mjs +22 -0
- package/src/runtime/shared/pid-liveness.mjs +12 -0
- package/src/runtime/shared/provider-api-key.mjs +6 -0
- package/src/runtime/shared/provider-timeout-phase.mjs +17 -0
- package/src/runtime/shared/quiet-progress.d.mts +35 -0
- package/src/runtime/shared/quiet-progress.mjs +101 -0
- package/src/runtime/shared/quota-resume-store.mjs +32 -1
- package/src/runtime/shared/read-row-numbers.mjs +44 -0
- package/src/runtime/shared/remote-intent.mjs +2 -42
- package/src/runtime/shared/slow-span.mjs +8 -1
- package/src/runtime/shared/statusline/statusline-segments.mjs +24 -2
- package/src/runtime/shared/tool-card-model/card-header.mjs +2 -1
- package/src/runtime/shared/tool-output-budget.mjs +2 -0
- package/src/runtime/shared/tool-result-summary.mjs +16 -2
- package/src/runtime/shared/tool-status.mjs +3 -2
- package/src/runtime/shared/tool-surface.mjs +2 -3
- package/src/runtime/shared/tool-work-units.mjs +22 -15
- package/src/runtime/shared/transcript-metadata.mjs +49 -1
- package/src/runtime/shared/transcript-turn-keys.mjs +33 -0
- package/src/runtime/shared/transcript-writer/transcript-file.mjs +10 -1
- package/src/runtime/shared/transcript-writer.mjs +14 -4
- package/src/runtime/shared/turn-changes.mjs +2 -1
- package/src/runtime/shared/turn-snapshot.mjs +11 -3
- package/src/runtime/shared/worktrees/activity-gate.mjs +175 -0
- package/src/runtime/shared/worktrees/branch-management.mjs +179 -0
- package/src/runtime/shared/worktrees/carry.mjs +6 -4
- package/src/runtime/shared/worktrees/contract.mjs +27 -1
- package/src/runtime/shared/worktrees/dependencies.mjs +456 -0
- package/src/runtime/shared/worktrees/file-recovery.mjs +29 -13
- package/src/runtime/shared/worktrees/git-head.mjs +22 -13
- package/src/runtime/shared/worktrees/include.mjs +125 -7
- package/src/runtime/shared/worktrees/lock.mjs +1 -1
- package/src/runtime/shared/worktrees/maintenance.mjs +20 -2
- package/src/runtime/shared/worktrees/manager.mjs +378 -32
- package/src/runtime/shared/worktrees/owner.mjs +2 -1
- package/src/runtime/shared/worktrees/preparation-report.mjs +79 -0
- package/src/runtime/shared/worktrees/setup-commands.mjs +232 -0
- package/src/runtime/shared/worktrees/workspace-visibility.mjs +17 -0
- package/src/runtime/terminal-bridge/client.mjs +14 -10
- package/src/session-runtime/boot/apis.mjs +7 -1
- package/src/session-runtime/boot/config.mjs +2 -0
- package/src/session-runtime/boot/facade.mjs +3 -0
- package/src/session-runtime/boot/session.mjs +3 -2
- package/src/session-runtime/boot/tools.mjs +3 -0
- package/src/session-runtime/conversation-import/service.mjs +1 -1
- package/src/session-runtime/goal-facade-api.mjs +2 -2
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +44 -18
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +4 -1
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +22 -8
- package/src/session-runtime/internal-tool-executor.mjs +2 -0
- package/src/session-runtime/lifecycle/cold-heir.mjs +0 -1
- package/src/session-runtime/lifecycle/session-catalog.mjs +14 -16
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +18 -53
- package/src/session-runtime/lifecycle/session-switch.mjs +1 -1
- package/src/session-runtime/lifecycle/shared.mjs +5 -6
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -5
- package/src/session-runtime/lifecycle/teardown.mjs +7 -16
- package/src/session-runtime/media-api.mjs +8 -0
- package/src/session-runtime/model-route/route-ownership.mjs +60 -0
- package/src/session-runtime/model-route/route-persist.mjs +3 -2
- package/src/session-runtime/model-route/set-route.mjs +114 -34
- package/src/session-runtime/model-route/web-search-route.mjs +7 -2
- package/src/session-runtime/model-route-api.mjs +4 -2
- package/src/session-runtime/native-web-search/routes.mjs +37 -24
- package/src/session-runtime/native-web-search.mjs +9 -8
- package/src/session-runtime/provider-auth/setup.mjs +4 -0
- package/src/session-runtime/provider-models/catalog-load.mjs +9 -0
- package/src/session-runtime/provider-models/web-search-catalog.mjs +23 -3
- package/src/session-runtime/provider-models.mjs +1 -0
- package/src/session-runtime/provider-usage.mjs +4 -0
- package/src/session-runtime/route-resolution.mjs +3 -1
- package/src/session-runtime/runtime-core.mjs +4 -0
- package/src/session-runtime/runtime-facade.mjs +6 -0
- package/src/session-runtime/services/agent-task-status.mjs +2 -0
- package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +0 -3
- package/src/session-runtime/services/agent-tool/close-flow.mjs +6 -7
- package/src/session-runtime/services/agent-tool/execute-send.mjs +2 -2
- package/src/session-runtime/services/agent-tool/execute-spawn.mjs +36 -3
- package/src/session-runtime/services/agent-tool/execute.mjs +9 -1
- package/src/session-runtime/services/agent-tool/helpers.mjs +30 -7
- package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +7 -2
- package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +6 -3
- package/src/session-runtime/services/agent-tool/lead-worker-index/lead-rows.mjs +3 -4
- package/src/session-runtime/services/agent-tool/lead-worker-index/reap-timers.mjs +9 -3
- package/src/session-runtime/services/agent-tool/lead-worker-index/row-settlement.mjs +7 -18
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +9 -6
- package/src/session-runtime/services/agent-tool/model-select.mjs +82 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -6
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +3 -1
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -5
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -4
- package/src/session-runtime/services/agent-tool/spawn-flow.mjs +2 -1
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
- package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +1 -3
- package/src/session-runtime/services/agent-tool/tag-registry/tag-refresh.mjs +1 -3
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +3 -9
- package/src/session-runtime/services/agent-tool/terminal-reaper/scan-admission.mjs +8 -41
- package/src/session-runtime/services/agent-tool/terminal-reaper/stale-rows.mjs +3 -3
- package/src/session-runtime/services/agent-tool/terminal-reaper.mjs +6 -23
- package/src/session-runtime/services/agent-tool/terminal-trace.mjs +0 -1
- package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +32 -20
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -2
- package/src/session-runtime/services/agent-tool/worker-index.mjs +28 -8
- package/src/session-runtime/services/agent-tool.mjs +4 -0
- package/src/session-runtime/services/agent-watchdog-registry.mjs +2 -0
- package/src/session-runtime/services/provider-admin.mjs +77 -0
- package/src/session-runtime/session-create/session-options.mjs +7 -5
- package/src/session-runtime/session-create/session-start-hook.mjs +2 -1
- package/src/session-runtime/session-transcript.mjs +4 -5
- package/src/session-runtime/session-turn-api.mjs +3 -9
- package/src/session-runtime/settings-builtin-tools-api.mjs +9 -6
- package/src/session-runtime/setup-tool/executor.mjs +23 -5
- package/src/session-runtime/setup-tool/extended-actions.mjs +6 -6
- package/src/session-runtime/setup-tool/settings-contract.mjs +7 -2
- package/src/session-runtime/setup-tool/tool-defs.mjs +13 -1
- package/src/session-runtime/tool-policy-refresh.mjs +83 -32
- package/src/session-runtime/turn/agent-ops.mjs +49 -2
- package/src/session-runtime/turn/side-question-ops.mjs +1 -4
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +2 -0
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +4 -0
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +8 -2
- package/src/session-runtime/turn/turn-run.mjs +1 -36
- package/src/session-runtime/usage-stats-api.mjs +4 -1
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +16 -1
- package/src/session-runtime/workspace/admission-gate.mjs +44 -15
- package/src/session-runtime/workspace/project-branches.mjs +28 -36
- package/src/session-runtime/workspace/transition-steps.mjs +96 -95
- package/src/session-runtime/workspace/transitions.mjs +248 -68
- package/src/standalone/channel-transport.mjs +3 -4
- package/src/standalone/daemon-desktop-runtime.mjs +32 -1
- package/src/standalone/daemon-pg-stop.mjs +1 -3
- package/src/standalone/daemon-session-control.mjs +88 -0
- package/src/standalone/daemon-stored-session-views.mjs +23 -3
- package/src/standalone/daemon.mjs +2 -0
- package/src/standalone/local-session-runtime.mjs +11 -12
- package/src/standalone/session-protocol.mjs +7 -0
- package/src/standalone/session-runtime-inline-host.mjs +2 -0
- package/src/standalone/session-service/agent-tree/agent-cancel.mjs +91 -49
- package/src/standalone/session-service/agent-tree/agent-child.mjs +19 -1
- package/src/standalone/session-service/agent-tree/agent-registry.mjs +25 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +9 -1
- package/src/standalone/session-service/agent-tree.mjs +28 -2
- package/src/standalone/session-service/entries/session-loads.mjs +16 -5
- package/src/standalone/session-service/entries.mjs +1 -0
- package/src/standalone/session-service/projection/transcript-window.mjs +39 -0
- package/src/standalone/session-service/quota-resume.mjs +28 -13
- package/src/standalone/session-service/session-calls/session-turns.mjs +17 -6
- package/src/standalone/session-service/session-calls/session-views.mjs +6 -0
- package/src/standalone/session-tool-output.mjs +82 -0
- package/src/tui/app/app-view.jsx +2 -1
- package/src/tui/app/provider-setup/provider-items.mjs +8 -0
- package/src/tui/app/provider-setup-picker.mjs +15 -3
- package/src/tui/app/slash-commands.mjs +6 -0
- package/src/tui/app/slash-dispatch/session-commands.mjs +49 -0
- package/src/tui/components/Spinner.jsx +4 -0
- package/src/tui/components/SpinnerByline.jsx +21 -2
- package/src/tui/components/status-line/local-line.mjs +10 -2
- package/src/tui/dist/index.mjs +478 -251
- package/src/tui/session/active-tool-summary.mjs +1 -1
- package/src/tui/session/context-state.mjs +0 -3
- package/src/tui/session/goal-continuation/continuation-queue.mjs +2 -3
- package/src/tui/session/goal-continuation/deadline-delivery.mjs +4 -2
- package/src/tui/session/goal-continuation/session-boundary.mjs +21 -0
- package/src/tui/session/quota-resume.mjs +140 -61
- package/src/tui/session/session-api/commands.mjs +4 -10
- package/src/tui/session/session-api/controls.mjs +12 -0
- package/src/tui/session/session-api/lifecycle/dispose.mjs +2 -9
- package/src/tui/session/session-api/lifecycle/resume.mjs +2 -7
- package/src/tui/session/session-api/lifecycle.mjs +13 -11
- package/src/tui/session/session-api/media.mjs +2 -0
- package/src/tui/session/session-api/routes.mjs +81 -57
- package/src/tui/session/session-api/settings.mjs +3 -3
- package/src/tui/session/session-api/worktree.mjs +3 -2
- package/src/tui/session/session-flow/auto-clear.mjs +1 -3
- package/src/tui/session/session-flow/drain.mjs +6 -4
- package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -0
- package/src/tui/session/session-flow/queue/take-entries.mjs +2 -1
- package/src/tui/session/session-flow/queue.mjs +1 -1
- package/src/tui/session/tool-approval.mjs +17 -8
- package/src/tui/session/transcript-store/streaming-tail.mjs +1 -1
- package/src/tui/session/tui-steering-persist.mjs +3 -5
- package/src/tui/session/turn-quiet.mjs +53 -0
- package/src/tui/session/turn-stream.mjs +5 -1
- package/src/tui/session/turn.mjs +38 -31
- package/src/tui/session/worktree-setup-notice.mjs +38 -0
- package/src/tui/spinner-meta.mjs +10 -0
- package/src/tui/spinner-verbs.mjs +3 -0
- package/src/ui/statusline.mjs +13 -3
- package/src/runtime/agent/orchestrator/providers/model-pricing-rates.mjs +0 -1
- package/src/runtime/agent/orchestrator/session/manager/foreign-pending-messages.mjs +0 -346
- package/src/runtime/agent/orchestrator/session/manager/session-owner-liveness.mjs +0 -117
- package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +0 -302
- package/src/session-runtime/services/agent-tool/terminal-reaper/reap-timers.mjs +0 -142
- package/src/session-runtime/turn/share-ops.mjs +0 -77
- package/src/tui/session/cross-surface-share.mjs +0 -406
- package/src/tui/session/live-share/delta.mjs +0 -153
- package/src/tui/session/live-share/mirror.mjs +0 -106
- package/src/tui/session/live-share/owner.mjs +0 -254
- package/src/tui/session/live-share/retry.mjs +0 -54
- package/src/tui/session/live-share/viewer/frame-router.mjs +0 -32
- package/src/tui/session/live-share/viewer/pipe-client.mjs +0 -108
- package/src/tui/session/live-share/viewer/submit-acks.mjs +0 -65
- package/src/tui/session/live-share/viewer/sync-waiters.mjs +0 -53
- package/src/tui/session/live-share/viewer.mjs +0 -99
- package/src/tui/session/live-share/wire.mjs +0 -44
- package/src/tui/session/live-share.mjs +0 -154
- package/src/tui/session/shared-dir-watch.mjs +0 -69
|
@@ -2,12 +2,51 @@ import { resolveProviderApiKey } from '../../../shared/provider-api-key.mjs';
|
|
|
2
2
|
import { enrichModels } from './model-catalog.mjs';
|
|
3
3
|
import { sanitizeModelList } from './model-list-sanitize.mjs';
|
|
4
4
|
import { PROVIDER_GENERATE_TOTAL_TIMEOUT_MS, createTimeoutSignal, resolveTimeoutMs } from '../stall-policy.mjs';
|
|
5
|
+
import { CUSTOM_EFFORT_LEVELS, normalizeCustomEffort } from './custom-reasoning.mjs';
|
|
5
6
|
|
|
6
7
|
const MODEL_LIST_TIMEOUT_MS = resolveTimeoutMs('MIXDOG_COMPAT_MODEL_LIST_TIMEOUT_MS', 10_000, {
|
|
7
8
|
minMs: 1_000,
|
|
8
9
|
maxMs: PROVIDER_GENERATE_TOTAL_TIMEOUT_MS,
|
|
9
10
|
});
|
|
10
11
|
|
|
12
|
+
/** Preserve endpoint-declared effort levels without inventing a default ladder. */
|
|
13
|
+
export function extractCompatReasoningEffort(model) {
|
|
14
|
+
if (!model || typeof model !== 'object') return null;
|
|
15
|
+
const rawLevels = [
|
|
16
|
+
model.reasoning_efforts,
|
|
17
|
+
model.reasoning_levels,
|
|
18
|
+
model.reasoningLevels,
|
|
19
|
+
model.capabilities?.reasoning_efforts,
|
|
20
|
+
model.capabilities?.reasoning_effort,
|
|
21
|
+
].find(Array.isArray);
|
|
22
|
+
if (rawLevels) {
|
|
23
|
+
const declared = new Set(
|
|
24
|
+
rawLevels
|
|
25
|
+
.map((level) => (typeof level === 'string' ? level : level?.value))
|
|
26
|
+
.filter((level) => typeof level === 'string')
|
|
27
|
+
.map(normalizeCustomEffort)
|
|
28
|
+
.filter(Boolean)
|
|
29
|
+
);
|
|
30
|
+
const levels = CUSTOM_EFFORT_LEVELS.filter((level) => declared.has(level));
|
|
31
|
+
if (levels.length > 0) {
|
|
32
|
+
return {
|
|
33
|
+
supportsReasoning: levels.some((level) => level !== 'none'),
|
|
34
|
+
reasoningLevels: levels,
|
|
35
|
+
reasoningOptions: [{ type: 'effort', values: [...levels] }],
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
if (
|
|
41
|
+
model.supports_reasoning_effort === true ||
|
|
42
|
+
model.capabilities?.reasoning_effort === true ||
|
|
43
|
+
model.capabilities?.reasoning_efforts === true
|
|
44
|
+
) {
|
|
45
|
+
return { supportsReasoning: true };
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
11
50
|
// `keyless` omits the Authorization header entirely (keyless endpoints);
|
|
12
51
|
// `signal` aborts the request together with the list timeout.
|
|
13
52
|
export async function fetchCompatModelItems(provider, { signal = null, keyless = false } = {}) {
|
|
@@ -70,17 +109,14 @@ export async function listCompatModels(provider, { throwOnError = false, signal
|
|
|
70
109
|
0
|
|
71
110
|
);
|
|
72
111
|
const outputTokens = Number(
|
|
73
|
-
m?.max_output_tokens ??
|
|
74
|
-
m?.output_tokens ??
|
|
75
|
-
m?.maxOutputTokens ??
|
|
76
|
-
m?.top_provider?.max_completion_tokens ??
|
|
77
|
-
0
|
|
112
|
+
m?.max_output_tokens ?? m?.output_tokens ?? m?.maxOutputTokens ?? m?.top_provider?.max_completion_tokens ?? 0
|
|
78
113
|
);
|
|
79
114
|
const mode = nativeMode(m);
|
|
80
115
|
// A catalog alias (OpenRouter `~anthropic/claude-opus-latest`) keeps its
|
|
81
116
|
// own slug for routing; the slug it currently points at is retained for
|
|
82
117
|
// capability lookup only.
|
|
83
118
|
const aliasTarget = typeof m?.alias_target === 'string' ? m.alias_target : m?.alias_target?.slug;
|
|
119
|
+
const effortInfo = extractCompatReasoningEffort(m);
|
|
84
120
|
models.push({
|
|
85
121
|
id: m?.id,
|
|
86
122
|
name: m?.id,
|
|
@@ -90,6 +126,7 @@ export async function listCompatModels(provider, { throwOnError = false, signal
|
|
|
90
126
|
created: typeof m?.created === 'number' ? m.created : null,
|
|
91
127
|
...(mode ? { mode } : {}),
|
|
92
128
|
...(typeof aliasTarget === 'string' && aliasTarget ? { aliasTarget } : {}),
|
|
129
|
+
...(effortInfo || {}),
|
|
93
130
|
});
|
|
94
131
|
}
|
|
95
132
|
const filtered = models.filter((m) => m.id);
|
|
@@ -98,7 +98,10 @@ function thinkingText(thinking) {
|
|
|
98
98
|
if (typeof thinking === 'string') return thinking;
|
|
99
99
|
if (!Array.isArray(thinking)) return '';
|
|
100
100
|
return thinking
|
|
101
|
-
.map((inner) =>
|
|
101
|
+
.map((inner) => {
|
|
102
|
+
if (typeof inner === 'string') return inner;
|
|
103
|
+
return typeof inner?.text === 'string' ? inner.text : '';
|
|
104
|
+
})
|
|
102
105
|
.join('');
|
|
103
106
|
}
|
|
104
107
|
|
|
@@ -129,14 +132,15 @@ export function chatContentParts(content) {
|
|
|
129
132
|
*/
|
|
130
133
|
export function readChatMessage(message, { shape = null } = {}) {
|
|
131
134
|
const parts = chatContentParts(message?.content);
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
135
|
+
let content;
|
|
136
|
+
if (parts) {
|
|
137
|
+
content = parts
|
|
138
|
+
.filter((part) => part.kind === 'text')
|
|
139
|
+
.map((part) => part.text)
|
|
140
|
+
.join('');
|
|
141
|
+
} else {
|
|
142
|
+
content = typeof message?.content === 'string' ? message.content : '';
|
|
143
|
+
}
|
|
140
144
|
if (typeof message?.reasoning_content === 'string') {
|
|
141
145
|
return { content, reasoningContent: message.reasoning_content, reasoningSource: 'reasoning_content' };
|
|
142
146
|
}
|
|
@@ -225,9 +225,7 @@ export function normalizeCompatChatResponse({
|
|
|
225
225
|
// Replay sends reasoning back under the field it arrived on.
|
|
226
226
|
const providerMetadata = {
|
|
227
227
|
...(reasoningDetails?.length ? { openrouter: { reasoning_details: reasoningDetails } } : {}),
|
|
228
|
-
...(reasoningContent !== null && reasoningField
|
|
229
|
-
? { [COMPAT_REASONING_METADATA_KEY]: { reasoningField } }
|
|
230
|
-
: {}),
|
|
228
|
+
...(reasoningContent !== null && reasoningField ? { [COMPAT_REASONING_METADATA_KEY]: { reasoningField } } : {}),
|
|
231
229
|
};
|
|
232
230
|
return {
|
|
233
231
|
content: assembled.content || '',
|
package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs
CHANGED
|
@@ -13,7 +13,13 @@ export const SERVER_CALL = {
|
|
|
13
13
|
execution: 'server',
|
|
14
14
|
arguments: { query: 'q' },
|
|
15
15
|
};
|
|
16
|
-
export const SERVER_OUTPUT = {
|
|
16
|
+
export const SERVER_OUTPUT = {
|
|
17
|
+
type: 'tool_search_output',
|
|
18
|
+
id: 'tso_srv',
|
|
19
|
+
call_id: null,
|
|
20
|
+
execution: 'server',
|
|
21
|
+
tools: [],
|
|
22
|
+
};
|
|
17
23
|
export const REPLY = { type: 'message', role: 'assistant', content: [{ type: 'output_text', text: 'ok' }] };
|
|
18
24
|
|
|
19
25
|
export const ROUTES = [
|
|
@@ -115,11 +121,14 @@ export function serverSearchReplayHistory(owner) {
|
|
|
115
121
|
export const COMPAT_CASES = [
|
|
116
122
|
['native', () => nativeHistory()],
|
|
117
123
|
['oauth', () => oauthHistory()],
|
|
118
|
-
[
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
124
|
+
[
|
|
125
|
+
'own-search-output',
|
|
126
|
+
(name) => {
|
|
127
|
+
const h = nativeHistory();
|
|
128
|
+
h[2] = { ...h[2], nativeToolSearch: search(name) };
|
|
129
|
+
return h;
|
|
130
|
+
},
|
|
131
|
+
],
|
|
123
132
|
['server-replay', (name, owner = replayOwner(name)) => serverSearchReplayHistory(owner)],
|
|
124
133
|
];
|
|
125
134
|
|
|
@@ -153,7 +162,9 @@ export async function captureCompat(name, model, history, opts = {}, config = {}
|
|
|
153
162
|
}
|
|
154
163
|
|
|
155
164
|
export function captureFirstParty(name, model, history) {
|
|
156
|
-
return JSON.parse(
|
|
165
|
+
return JSON.parse(
|
|
166
|
+
JSON.stringify(buildRequestBody(history, model, [], { promptCacheProvider: name, sessionId: 'sess-1' }))
|
|
167
|
+
);
|
|
157
168
|
}
|
|
158
169
|
|
|
159
170
|
export async function captureAll() {
|
|
@@ -66,6 +66,7 @@ function resolveReasoning(provider, useModel, opts) {
|
|
|
66
66
|
function customEffortProjection(provider, useModel, messages, opts) {
|
|
67
67
|
if (!isCustomProviderName(provider.name)) return null;
|
|
68
68
|
const projection = projectEffortConfiguration(messages, provider.name, useModel, {
|
|
69
|
+
...provider.config,
|
|
69
70
|
...opts,
|
|
70
71
|
protocol: 'openai-responses',
|
|
71
72
|
});
|
|
@@ -101,7 +102,10 @@ function supportsPromptCacheKey(provider, opts) {
|
|
|
101
102
|
// `responsesNativeItems: true` (opts or config) gets the first-party lowering.
|
|
102
103
|
// Every other route keeps the function-only lowering byte for byte.
|
|
103
104
|
function supportsNativeResponsesItems(provider, opts) {
|
|
104
|
-
return (
|
|
105
|
+
return (
|
|
106
|
+
(opts.responsesNativeItems ?? provider.config?.responsesNativeItems) === true ||
|
|
107
|
+
hasNativeDeferredTools(provider, opts)
|
|
108
|
+
);
|
|
105
109
|
}
|
|
106
110
|
|
|
107
111
|
// A session whose pinned route verified native deferred tools on the Responses
|
|
@@ -126,6 +130,33 @@ function customSessionCacheKey(provider, opts) {
|
|
|
126
130
|
);
|
|
127
131
|
}
|
|
128
132
|
|
|
133
|
+
// HTTP header names are case-insensitive. Do not shadow explicit SDK
|
|
134
|
+
// defaults, combine differently-cased identities, or stringify null deletions.
|
|
135
|
+
function customSessionHeaders(provider, sessionCacheKey, requestHeaders) {
|
|
136
|
+
if (!sessionCacheKey) return requestHeaders;
|
|
137
|
+
const headers = { 'session-id': sessionCacheKey, 'x-client-request-id': sessionCacheKey };
|
|
138
|
+
const clientOptions = provider.config?.clientOptions || {};
|
|
139
|
+
const configured = Object.hasOwn(clientOptions, 'defaultHeaders')
|
|
140
|
+
? clientOptions.defaultHeaders
|
|
141
|
+
: provider.defaultHeaders;
|
|
142
|
+
const entries = (source) =>
|
|
143
|
+
source instanceof Headers || Array.isArray(source) ? source : Object.entries(source || {});
|
|
144
|
+
const hasValue = (value) => (Array.isArray(value) ? value.some((item) => item !== undefined) : value !== undefined);
|
|
145
|
+
for (const source of [configured, requestHeaders]) {
|
|
146
|
+
for (const [name, value] of entries(source)) {
|
|
147
|
+
if (hasValue(value)) delete headers[name.toLowerCase()];
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (requestHeaders instanceof Headers) {
|
|
151
|
+
const merged = new Headers(requestHeaders);
|
|
152
|
+
for (const [name, value] of Object.entries(headers)) merged.set(name, value);
|
|
153
|
+
return merged;
|
|
154
|
+
}
|
|
155
|
+
if (Array.isArray(requestHeaders)) return [...Object.entries(headers), ...requestHeaders];
|
|
156
|
+
const supplied = Object.fromEntries(Object.entries(requestHeaders || {}).filter(([, value]) => hasValue(value)));
|
|
157
|
+
return { ...headers, ...supplied };
|
|
158
|
+
}
|
|
159
|
+
|
|
129
160
|
/** The request body: lowered transcript plus the per-turn knobs (output cap,
|
|
130
161
|
* tools and tool choice, reasoning effort, session cache key). */
|
|
131
162
|
function buildCompatResponsesParams({
|
|
@@ -300,8 +331,10 @@ async function sendCompatResponsesOnce(provider, messages, useModel, tools, opts
|
|
|
300
331
|
sessionCacheKey,
|
|
301
332
|
});
|
|
302
333
|
// The session identity also travels as headers; caller headers win.
|
|
303
|
-
|
|
304
|
-
|
|
334
|
+
// Custom routes only: a gateway route that opts into prompt_cache_key keeps
|
|
335
|
+
// its own headers.
|
|
336
|
+
const headers = isCustomProviderName(provider.name)
|
|
337
|
+
? customSessionHeaders(provider, sessionCacheKey, opts.requestHeaders)
|
|
305
338
|
: opts.requestHeaders;
|
|
306
339
|
|
|
307
340
|
try {
|
|
@@ -21,13 +21,18 @@
|
|
|
21
21
|
// and jittered by jitterRatio (the advice of the excepted statuses stays raw).
|
|
22
22
|
// recycleDispatcherOn5xx — a retried 5xx rebuilds the shared HTTP pool.
|
|
23
23
|
// adviceAtLeastBackoff — the advice is a floor under the jittered backoff step.
|
|
24
|
+
// firstByteRetries — a header or first-chunk timeout (`timeoutPhase`) is
|
|
25
|
+
// retried at most this many times, each retry on a doubled window capped
|
|
26
|
+
// at PROVIDER_MAX_BEFORE_WARN_MS; other transient errors keep the ladder.
|
|
24
27
|
// Every stop is provider-terminal: the profile's limits are final, so the
|
|
25
28
|
// agent loop never re-runs a stopped or exhausted request (see
|
|
26
29
|
// COMPAT_RETRY_POLICY).
|
|
27
30
|
import { markProviderRecoveryExhausted } from './retry-classifier.mjs';
|
|
28
31
|
import { retryAfterMsFromError } from './provider-error-kind.mjs';
|
|
29
32
|
import { STREAM_TRANSPORTS, stampStreamOutcome } from './lib/stream-outcome.mjs';
|
|
30
|
-
import { jitterDelayMs } from './retry-backoff.mjs';
|
|
33
|
+
import { DEFAULT_BACKOFF_MS, DEFAULT_MAX_ATTEMPTS, jitterDelayMs } from './retry-backoff.mjs';
|
|
34
|
+
import { PROVIDER_MAX_BEFORE_WARN_MS, firstBytePolicyBudget, firstByteWindowMs } from '../stall-policy.mjs';
|
|
35
|
+
import { isFirstByteTimeout } from '../../../shared/provider-timeout-phase.mjs';
|
|
31
36
|
|
|
32
37
|
const statusOf = (err) => Number(err?.httpStatus || err?.status || err?.response?.status || 0);
|
|
33
38
|
|
|
@@ -75,9 +80,11 @@ export const COMPAT_RETRY_PROFILES = Object.freeze({
|
|
|
75
80
|
}),
|
|
76
81
|
// server budget 8 retries (2s doubling to 30s,
|
|
77
82
|
// ±10%), rate-limit budget 5 retries; 408, 409, 501 and 505 are terminal
|
|
78
|
-
// (425 stays retryable); a Retry-After beyond 300s is not waited out.
|
|
83
|
+
// (425 stays retryable); a Retry-After beyond 300s is not waited out. A
|
|
84
|
+
// first-byte timeout gets one longer retry instead of the whole ladder.
|
|
79
85
|
'mimo-oauth': Object.freeze({
|
|
80
86
|
maxAttempts: 9,
|
|
87
|
+
firstByteRetries: 1,
|
|
81
88
|
backoffMs: [2000, 2000, 4000, 8000, 16000, 30000],
|
|
82
89
|
retryJitterRatio: 0.1,
|
|
83
90
|
statusRetryCaps: { 429: 5 },
|
|
@@ -112,6 +119,40 @@ export function compatRetryOptions(providerName) {
|
|
|
112
119
|
};
|
|
113
120
|
}
|
|
114
121
|
|
|
122
|
+
// The provider's first-byte policy (see firstByteWindowMs) on a base window:
|
|
123
|
+
// a profile's `firstByteRetries` caps first-byte retries on a doubling window;
|
|
124
|
+
// without it every attempt keeps the base window.
|
|
125
|
+
function compatFirstBytePolicy(providerName, baseMs) {
|
|
126
|
+
return {
|
|
127
|
+
timeoutMs: baseMs,
|
|
128
|
+
maxMs: PROVIDER_MAX_BEFORE_WARN_MS,
|
|
129
|
+
retries: COMPAT_RETRY_PROFILES[providerName]?.firstByteRetries ?? null,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** First-byte window of an attempt after `timeouts` first-byte timeouts. */
|
|
134
|
+
export function compatFirstByteWindowMs(providerName, baseMs, timeouts = 0) {
|
|
135
|
+
return firstByteWindowMs(compatFirstBytePolicy(providerName, baseMs), timeouts);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* First-response budget of a chat profile that sets its own first-byte window
|
|
140
|
+
* (`firstByteTimeoutMs`, applied to the headers and to the first chunk): the
|
|
141
|
+
* worst case over the profile's whole ladder, where drops and 5xx use up
|
|
142
|
+
* attempts and backoff alongside the first-byte timeouts the profile permits
|
|
143
|
+
* (see firstBytePolicyBudget). Null for a profile on the shared window, which
|
|
144
|
+
* the agent watchdog's default already covers.
|
|
145
|
+
*/
|
|
146
|
+
export function compatFirstResponseBudget(providerName, chatProfile) {
|
|
147
|
+
const windowMs = Number(chatProfile?.firstByteTimeoutMs);
|
|
148
|
+
if (!(windowMs > 0)) return null;
|
|
149
|
+
const options = compatRetryOptions(providerName);
|
|
150
|
+
return firstBytePolicyBudget(compatFirstBytePolicy(providerName, windowMs), {
|
|
151
|
+
attempts: options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS,
|
|
152
|
+
backoffMs: options.backoffMs ?? DEFAULT_BACKOFF_MS,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
115
156
|
function profileStops(profile, err, { attempt, elapsedMs }) {
|
|
116
157
|
const status = statusOf(err);
|
|
117
158
|
if (profile.terminalStatuses?.includes(status)) return true;
|
|
@@ -170,10 +211,11 @@ export function withCompatRetryProfile(providerName, attemptFn) {
|
|
|
170
211
|
const profile = COMPAT_RETRY_PROFILES[providerName];
|
|
171
212
|
if (!profile) return attemptFn;
|
|
172
213
|
let emptyRetries = 0;
|
|
214
|
+
let firstByteTimeouts = 0;
|
|
173
215
|
return async (ctx) => {
|
|
174
216
|
const startedAt = Date.now();
|
|
175
217
|
try {
|
|
176
|
-
const result = await attemptFn(ctx);
|
|
218
|
+
const result = await attemptFn({ ...ctx, firstByteTimeouts });
|
|
177
219
|
if (profile.retryEmptyResponse && isEmptyNormalFinish(result)) {
|
|
178
220
|
const bound = profile.retryEmptyResponse === true ? Infinity : profile.retryEmptyResponse;
|
|
179
221
|
if (emptyRetries < bound) {
|
|
@@ -183,6 +225,12 @@ export function withCompatRetryProfile(providerName, attemptFn) {
|
|
|
183
225
|
}
|
|
184
226
|
return result;
|
|
185
227
|
} catch (err) {
|
|
228
|
+
if (profile.firstByteRetries != null && isFirstByteTimeout(err) && !ctx?.signal?.aborted) {
|
|
229
|
+
firstByteTimeouts += 1;
|
|
230
|
+
if (firstByteTimeouts > profile.firstByteRetries) {
|
|
231
|
+
throw markProviderRecoveryExhausted(err, { owner: `${providerName}-first-byte`, terminal: true });
|
|
232
|
+
}
|
|
233
|
+
}
|
|
186
234
|
if (profileStops(profile, err, { attempt: ctx?.attempt | 0, elapsedMs: Date.now() - startedAt })) {
|
|
187
235
|
throw markProviderRecoveryExhausted(err, { owner: `${providerName}-retry-profile`, terminal: true });
|
|
188
236
|
}
|
|
@@ -15,7 +15,12 @@ import {
|
|
|
15
15
|
import { withEffortRejectionFallback } from './effort-rejection.mjs';
|
|
16
16
|
import { applyCompatErrorContract } from './openai-compat-error-contract.mjs';
|
|
17
17
|
import { sendCompatResponses } from './openai-compat-responses.mjs';
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
COMPAT_RETRY_POLICY,
|
|
20
|
+
COMPAT_RETRY_PROFILES,
|
|
21
|
+
XAI_COMPAT_RETRY_POLICY,
|
|
22
|
+
compatFirstResponseBudget,
|
|
23
|
+
} from './openai-compat-retry-profile.mjs';
|
|
19
24
|
import { sendCompatChat, recoverCompatNonStreaming } from './openai-compat-chat-send.mjs';
|
|
20
25
|
import { sendXaiResponses, sendXaiResponsesWebSocket } from './openai-compat-xai-send.mjs';
|
|
21
26
|
import {
|
|
@@ -100,6 +105,11 @@ export class OpenAICompatProvider {
|
|
|
100
105
|
}
|
|
101
106
|
}
|
|
102
107
|
}
|
|
108
|
+
// First-response budget of a chat profile with its own first-byte window;
|
|
109
|
+
// null keeps the agent watchdog default.
|
|
110
|
+
firstResponseBudget() {
|
|
111
|
+
return compatFirstResponseBudget(this.name, this.config?.chatProfile);
|
|
112
|
+
}
|
|
103
113
|
get _preconnectFn() {
|
|
104
114
|
return typeof this.config?.preconnectFn === 'function' ? this.config.preconnectFn : preconnect;
|
|
105
115
|
}
|
|
@@ -6,7 +6,16 @@
|
|
|
6
6
|
* Returns an OK response whose body is ready to stream; every failure path
|
|
7
7
|
* throws with the initial-response markers the retry classifier reads.
|
|
8
8
|
*/
|
|
9
|
+
import { promisify } from 'node:util';
|
|
9
10
|
import zlib from 'node:zlib';
|
|
11
|
+
import {
|
|
12
|
+
REQ_COMPRESSION_MIN_BYTES,
|
|
13
|
+
compressBody,
|
|
14
|
+
createCompressionLatch,
|
|
15
|
+
hasContentEncoding,
|
|
16
|
+
resendIfEncodingRejected,
|
|
17
|
+
withContentEncoding,
|
|
18
|
+
} from './lib/request-compression.mjs';
|
|
10
19
|
import { traceAgentFetch } from '../agent-trace.mjs';
|
|
11
20
|
import { PROVIDER_HTTP_RESPONSE_TIMEOUT_MS, createTimeoutSignal } from '../stall-policy.mjs';
|
|
12
21
|
import { CODEX_REQUEST_RETRY_BACKOFF_MS, CODEX_RETRY_JITTER_RATIO } from './openai-retry-policy.mjs';
|
|
@@ -37,7 +46,6 @@ const OPENAI_REQUEST_RETRY_OPTS = Object.freeze({
|
|
|
37
46
|
retryJitterRatio: CODEX_RETRY_JITTER_RATIO,
|
|
38
47
|
});
|
|
39
48
|
|
|
40
|
-
|
|
41
49
|
// Request-layer retry: 5xx and typed transport
|
|
42
50
|
// failures only. 408 and 429 are NOT retried here; they surface to the outer
|
|
43
51
|
// stream-retry layer, which owns their budget and honors Retry-After.
|
|
@@ -52,31 +60,29 @@ function isRetryableHttpFailure(err) {
|
|
|
52
60
|
}
|
|
53
61
|
// Request-body zstd gate. Namespace import: on Node runtimes without zlib
|
|
54
62
|
// zstd bindings the named export would fail at module load, so the call site
|
|
55
|
-
// typeof-guards zlib.
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
function _openaiReqZstdDisabled() {
|
|
59
|
-
return _openaiReqZstdLatch || process.env.MIXDOG_OPENAI_REQ_ZSTD === '0';
|
|
60
|
-
}
|
|
61
|
-
function _disableOpenaiReqZstd() {
|
|
62
|
-
_openaiReqZstdLatch = true;
|
|
63
|
-
}
|
|
64
|
-
function _zstdHeaders(headers, bodyForSend) {
|
|
65
|
-
return bodyForSend.encoding ? { ...headers, 'Content-Encoding': bodyForSend.encoding } : headers;
|
|
66
|
-
}
|
|
63
|
+
// typeof-guards zlib.zstdCompress instead.
|
|
64
|
+
const _openaiReqZstdLatch = createCompressionLatch('MIXDOG_OPENAI_REQ_ZSTD');
|
|
65
|
+
export const _resetOpenaiReqZstdLatchForTest = _openaiReqZstdLatch.reset;
|
|
67
66
|
|
|
68
67
|
// Request-body zstd: compression is enabled for the codex backend on the
|
|
69
68
|
// OpenAI provider — the server decompresses Content-Encoding: zstd.
|
|
70
|
-
// openai-direct is excluded: only the codex backend is verified.
|
|
71
|
-
//
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
69
|
+
// openai-direct is excluded: only the codex backend is verified. Compression
|
|
70
|
+
// runs on the libuv threadpool (zlib.zstdCompress, promisified) so it never
|
|
71
|
+
// blocks the main thread; runtimes without the async zstd binding send plain.
|
|
72
|
+
// Env kill-switch; the 400/415 resend + latch policy is shared
|
|
73
|
+
// (lib/request-compression.mjs).
|
|
74
|
+
async function encodeRequestBody(auth, headers, rawBytes) {
|
|
75
|
+
const plain = { bytes: rawBytes, encoding: null };
|
|
76
|
+
if (
|
|
77
|
+
auth?.type === 'openai-direct' ||
|
|
78
|
+
_openaiReqZstdLatch.disabled() ||
|
|
79
|
+
typeof zlib.zstdCompress !== 'function' ||
|
|
80
|
+
rawBytes.length < REQ_COMPRESSION_MIN_BYTES ||
|
|
81
|
+
hasContentEncoding(headers)
|
|
82
|
+
) {
|
|
83
|
+
return plain;
|
|
84
|
+
}
|
|
85
|
+
return compressBody(rawBytes, promisify(zlib.zstdCompress), 'zstd');
|
|
80
86
|
}
|
|
81
87
|
|
|
82
88
|
async function postWithRetries({
|
|
@@ -91,15 +97,32 @@ async function postWithRetries({
|
|
|
91
97
|
_sleepFn,
|
|
92
98
|
}) {
|
|
93
99
|
const label = httpLabel(auth);
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
let httpError = null;
|
|
97
|
-
for (let attempt = 0; attempt <= CODEX_REQUEST_MAX_RETRIES; attempt++) {
|
|
100
|
+
const bodyForSend = await encodeRequestBody(auth, headers, rawBytes);
|
|
101
|
+
const fetchOnce = async (bytes, sendHeaders) => {
|
|
98
102
|
const headerTimeout = createTimeoutSignal(
|
|
99
103
|
totalTimeout.signal,
|
|
100
104
|
PROVIDER_HTTP_RESPONSE_TIMEOUT_MS,
|
|
101
105
|
`${label} initial response`
|
|
102
106
|
);
|
|
107
|
+
try {
|
|
108
|
+
return await fetchFn(responsesUrl, {
|
|
109
|
+
method: 'POST',
|
|
110
|
+
headers: sendHeaders,
|
|
111
|
+
body: bytes,
|
|
112
|
+
signal: headerTimeout.signal,
|
|
113
|
+
dispatcher: getLlmDispatcher(),
|
|
114
|
+
});
|
|
115
|
+
} catch (err) {
|
|
116
|
+
throw headerTimeout.signal?.aborted && headerTimeout.signal.reason instanceof Error
|
|
117
|
+
? headerTimeout.signal.reason
|
|
118
|
+
: err;
|
|
119
|
+
} finally {
|
|
120
|
+
headerTimeout.cleanup();
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
let response;
|
|
124
|
+
let httpError = null;
|
|
125
|
+
for (let attempt = 0; attempt <= CODEX_REQUEST_MAX_RETRIES; attempt++) {
|
|
103
126
|
let requestError = null;
|
|
104
127
|
try {
|
|
105
128
|
// Keep the established stage name for consumers, while making each
|
|
@@ -113,32 +136,20 @@ async function postWithRetries({
|
|
|
113
136
|
retry: attempt > 0,
|
|
114
137
|
});
|
|
115
138
|
} catch {}
|
|
116
|
-
response =
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
139
|
+
response = bodyForSend.encoding
|
|
140
|
+
? await fetchOnce(bodyForSend.bytes, withContentEncoding(headers, bodyForSend.encoding))
|
|
141
|
+
: await fetchOnce(rawBytes, headers);
|
|
142
|
+
// Encoding rejection (400/415): resent uncompressed inside this attempt,
|
|
143
|
+
// so it never consumes a retry; the latch flips only if that succeeds.
|
|
144
|
+
response = await resendIfEncodingRejected({
|
|
145
|
+
response,
|
|
146
|
+
encoded: Boolean(bodyForSend.encoding),
|
|
147
|
+
resend: () => fetchOnce(rawBytes, headers),
|
|
148
|
+
latch: _openaiReqZstdLatch,
|
|
122
149
|
});
|
|
123
150
|
} catch (err) {
|
|
124
|
-
requestError =
|
|
125
|
-
headerTimeout.signal?.aborted && headerTimeout.signal.reason instanceof Error
|
|
126
|
-
? headerTimeout.signal.reason
|
|
127
|
-
: err;
|
|
128
|
-
} finally {
|
|
129
|
-
headerTimeout.cleanup();
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// zstd rejection fallback: a 400 on a compressed request latches
|
|
133
|
-
// compression OFF process-wide and replays this attempt uncompressed.
|
|
134
|
-
if (response && response.status === 400 && bodyForSend.encoding) {
|
|
135
|
-
_disableOpenaiReqZstd();
|
|
136
|
-
bodyForSend = { bytes: rawBytes, encoding: null };
|
|
137
|
-
await response.arrayBuffer().catch(() => {});
|
|
138
151
|
response = undefined;
|
|
139
|
-
|
|
140
|
-
attempt--;
|
|
141
|
-
continue;
|
|
152
|
+
requestError = err;
|
|
142
153
|
}
|
|
143
154
|
// The error body is read exactly once, here, into the contract fields.
|
|
144
155
|
httpError = null;
|
|
@@ -183,8 +194,9 @@ async function postWithRetries({
|
|
|
183
194
|
// Uncapped for retryable errors; the attempt count is
|
|
184
195
|
// the bound, and the abort signal cancels the wait.
|
|
185
196
|
// The shared schedule carries a leading duplicate (withRetry convention).
|
|
186
|
-
|
|
187
|
-
const delayMs =
|
|
197
|
+
const raw = OPENAI_REQUEST_RETRY_OPTS.backoffMs[attempt + 1];
|
|
198
|
+
const delayMs =
|
|
199
|
+
retryAfterMsFromError(attemptFailure) ?? jitterDelayMs(raw, OPENAI_REQUEST_RETRY_OPTS.retryJitterRatio);
|
|
188
200
|
emitProviderRetryStage(onStageChange, {
|
|
189
201
|
attempt: attempt + 2,
|
|
190
202
|
maxAttempts: CODEX_REQUEST_MAX_RETRIES + 1,
|
|
@@ -119,7 +119,9 @@ export function createTerminalFrameEvents({ state, items, text, outcome, meaning
|
|
|
119
119
|
// Same carried state as the WS path: text (leak-guard tail flushed),
|
|
120
120
|
// the calls already complete and dispatched, model and billed usage.
|
|
121
121
|
text.flushLeak();
|
|
122
|
-
const err = outcome.stampToolSafety(
|
|
122
|
+
const err = outcome.stampToolSafety(
|
|
123
|
+
new Error(`${state.label} ${frame} (max_output_tokens) with tool call in flight`)
|
|
124
|
+
);
|
|
123
125
|
outcome.attachStreamPartial(err);
|
|
124
126
|
err.streamStalled = true;
|
|
125
127
|
err.pendingToolUse = true;
|
|
@@ -254,7 +254,8 @@ export function convertMessagesToResponsesInput(messages, opts = {}) {
|
|
|
254
254
|
pushReasoningItems(m, 'after');
|
|
255
255
|
}
|
|
256
256
|
flushToolMedia();
|
|
257
|
-
if (opts.reasoningByMessageIndex?.has(messages.length))
|
|
257
|
+
if (opts.reasoningByMessageIndex?.has(messages.length))
|
|
258
|
+
out.push(...opts.reasoningByMessageIndex.get(messages.length));
|
|
258
259
|
out.push(...effortUpdates.end());
|
|
259
260
|
// Wire-level pairing guard: replay envelopes can carry a call whose
|
|
260
261
|
// result never committed (cancel/abort). The provider hard-rejects the
|
|
@@ -119,7 +119,13 @@ function responsesToolsList(tools, opts, nativeToolSearch) {
|
|
|
119
119
|
// must be a valid 2020-12 object schema -- lowered when it is not, left out
|
|
120
120
|
// and reported when it still is not.
|
|
121
121
|
const sendable = tools?.length
|
|
122
|
-
? acceptedWireTools(
|
|
122
|
+
? acceptedWireTools(
|
|
123
|
+
tools,
|
|
124
|
+
'openai',
|
|
125
|
+
opts.onToolExcluded,
|
|
126
|
+
`[${opts.promptCacheProvider || 'openai-oauth'}] tool`,
|
|
127
|
+
isResponsesFreeformTool
|
|
128
|
+
)
|
|
123
129
|
: [];
|
|
124
130
|
const functionTools = sendable.map((t) => toOpenAIResponsesTool(t, { nativeToolSearch }));
|
|
125
131
|
const nativeTools = Array.isArray(opts.nativeTools) ? opts.nativeTools.filter((t) => t && typeof t === 'object') : [];
|
|
@@ -293,10 +293,7 @@ const TRANSPORT_ONLY_FRAME_FIELDS = new Set(['stream', 'background']);
|
|
|
293
293
|
// response, so dropping them here strips the system/lead prompt from every
|
|
294
294
|
// continuation turn. Only an empty instructions string is omitted.
|
|
295
295
|
// Full frames pass the body unchanged and keep every key in place.
|
|
296
|
-
export function _buildResponseCreateFrame(
|
|
297
|
-
body,
|
|
298
|
-
{ previousResponseId = null, inputOverride } = {}
|
|
299
|
-
) {
|
|
296
|
+
export function _buildResponseCreateFrame(body, { previousResponseId = null, inputOverride } = {}) {
|
|
300
297
|
const src = body && typeof body === 'object' ? body : {};
|
|
301
298
|
if (previousResponseId == null && inputOverride === undefined) {
|
|
302
299
|
const frame = { type: 'response.create' };
|
|
@@ -29,10 +29,13 @@ import { getLlmDispatcher } from '../../../shared/llm/http-agent.mjs';
|
|
|
29
29
|
import { noteRequestServiceTier } from '../../../shared/llm/usage-context.mjs';
|
|
30
30
|
import { resolveProviderCacheKey, resolveProviderPromptCacheLane } from '../agent-runtime/cache-strategy.mjs';
|
|
31
31
|
|
|
32
|
+
function isUnsafeToRetry(err) {
|
|
33
|
+
return err?.liveTextEmitted === true || err?.emittedToolCall === true || err?.unsafeToRetry === true;
|
|
34
|
+
}
|
|
35
|
+
|
|
32
36
|
function shouldFallbackDirectTransport(err, options) {
|
|
33
37
|
const status = Number(err?.httpStatus || err?.status || 0);
|
|
34
|
-
|
|
35
|
-
if (unsafeToRetry || options?.signal?.aborted || options?.enabled === false) return false;
|
|
38
|
+
if (isUnsafeToRetry(err) || options?.signal?.aborted || options?.enabled === false) return false;
|
|
36
39
|
// Public OpenAI can reject the WebSocket upgrade while still supporting
|
|
37
40
|
// the same request over HTTP/SSE. Only the shared transport's explicit
|
|
38
41
|
// handshake marker may turn these application-looking statuses into a
|
|
@@ -205,8 +208,7 @@ export class OpenAIDirectProvider {
|
|
|
205
208
|
try {
|
|
206
209
|
return await sendHttp({ ...common, auth: a, opts, fetchFn: opts._fetchFn });
|
|
207
210
|
} catch (err) {
|
|
208
|
-
|
|
209
|
-
if (!reload || err?.httpStatus !== 401 || unsafe) throw err;
|
|
211
|
+
if (!reload || err?.httpStatus !== 401 || isUnsafeToRetry(err)) throw err;
|
|
210
212
|
// The replay discards this attempt; its reported usage stays billed.
|
|
211
213
|
noteErrorUsage(err);
|
|
212
214
|
process.stderr.write('[openai-ws] 401 — reloading apiKey and retrying once over HTTP\n');
|
|
@@ -252,8 +254,7 @@ export class OpenAIDirectProvider {
|
|
|
252
254
|
const status = err?.httpStatus;
|
|
253
255
|
// Live-text/tool invariant: never reissue a turn that already
|
|
254
256
|
// relayed visible output or dispatched a tool call.
|
|
255
|
-
const unsafeToRetry =
|
|
256
|
-
err?.liveTextEmitted === true || err?.emittedToolCall === true || err?.unsafeToRetry === true;
|
|
257
|
+
const unsafeToRetry = isUnsafeToRetry(err);
|
|
257
258
|
// (1) 401 → reload only OpenAI auth and retry once over WS.
|
|
258
259
|
// Ordinary 403 is a permission/policy decision, not evidence that
|
|
259
260
|
// an API key rotated. Match the OAuth path and keep it terminal.
|