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
|
@@ -90,8 +90,7 @@ const _oauthRefreshes = new Map();
|
|
|
90
90
|
// Anthropic OAuth contract for first-party OAuth clients: Claude requests
|
|
91
91
|
// are gated on this exact system-prompt prefix (Haiku 5.5 included).
|
|
92
92
|
const CLAUDE_CODE_SYSTEM_PREFIX = "You are Claude Code, Anthropic's official CLI for Claude.";
|
|
93
|
-
const OAUTH_BETA_HEADERS =
|
|
94
|
-
'oauth-2025-04-20,interleaved-thinking-2025-05-14,context-management-2025-06-27,extended-cache-ttl-2025-04-11';
|
|
93
|
+
const OAUTH_BETA_HEADERS = 'oauth-2025-04-20,interleaved-thinking-2025-05-14,context-management-2025-06-27';
|
|
95
94
|
|
|
96
95
|
function logQuiet(line) {
|
|
97
96
|
if (!process.env.MIXDOG_QUIET_PROVIDER_LOG) process.stderr.write(`[anthropic-oauth] ${line}\n`);
|
|
@@ -676,9 +675,7 @@ export class AnthropicOAuthProvider {
|
|
|
676
675
|
response.status === 400 &&
|
|
677
676
|
opts.fast === true &&
|
|
678
677
|
!opts._fastModeRetry &&
|
|
679
|
-
fastModeDowngraded(
|
|
680
|
-
noteFastModeCapacityError({ httpStatus: 400, message: scrubbedText }, { fast: true })
|
|
681
|
-
)
|
|
678
|
+
fastModeDowngraded(noteFastModeCapacityError({ httpStatus: 400, message: scrubbedText }, { fast: true }))
|
|
682
679
|
) {
|
|
683
680
|
process.stderr.write(`[anthropic-oauth] fast mode is not enabled for this account; retrying at standard speed\n`);
|
|
684
681
|
return this.send(messages, useModel, tools, { ...opts, _fastModeRetry: true });
|
|
@@ -13,6 +13,7 @@ import { ANTHROPIC_MAX_MIDSTREAM_RETRIES, parseSSEStream } from './anthropic-sse
|
|
|
13
13
|
import { buildAnthropicBetaHeaders } from './anthropic-betas.mjs';
|
|
14
14
|
import { buildAnthropicApiRequest } from './anthropic-api-request.mjs';
|
|
15
15
|
import { isCustomProviderName } from './custom-reasoning.mjs';
|
|
16
|
+
import { createAnthropicApiKeyFetch } from './anthropic-api-key-fetch.mjs';
|
|
16
17
|
import { ANTHROPIC_EFFORT_LEVELS, withEffortRejectionFallback } from './effort-rejection.mjs';
|
|
17
18
|
import { armFirstByteWatchdog, createAnthropicApiTransport } from './anthropic-api-transport.mjs';
|
|
18
19
|
import { createAnthropicApiRecovery } from './anthropic-api-recovery.mjs';
|
|
@@ -75,6 +76,9 @@ export class AnthropicProvider {
|
|
|
75
76
|
return new (loadAnthropic())({
|
|
76
77
|
...credentials,
|
|
77
78
|
...(this.config.baseURL ? { baseURL: this.config.baseURL } : {}),
|
|
79
|
+
// Gzip only toward the official origin (decided per request URL); a
|
|
80
|
+
// custom-* gateway keeps the SDK's plain fetch.
|
|
81
|
+
...(custom ? {} : { fetch: createAnthropicApiKeyFetch() }),
|
|
78
82
|
defaultHeaders: {
|
|
79
83
|
...(betaHeaders ? { 'anthropic-beta': betaHeaders } : {}),
|
|
80
84
|
...(keyless ? { 'x-api-key': null, authorization: null } : {}),
|
|
@@ -193,6 +193,18 @@ function antigravityCatalogModels() {
|
|
|
193
193
|
return _mirror || ANTIGRAVITY_MODELS;
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
+
/**
|
|
197
|
+
* The catalog `family` ('gemini-pro', 'gemini-flash', 'gpt-oss') of a picker
|
|
198
|
+
* id or one of its wire ids, or null when no record carries one (Claude, or
|
|
199
|
+
* an id the catalog does not list).
|
|
200
|
+
*/
|
|
201
|
+
export function antigravityModelFamily(model, models = antigravityCatalogModels()) {
|
|
202
|
+
const id = String(model || '');
|
|
203
|
+
const wires = (entry) => (entry?.wire && typeof entry.wire === 'object' ? Object.values(entry.wire) : [entry?.wire]);
|
|
204
|
+
const record = models.find((entry) => entry?.id === id) || models.find((entry) => wires(entry).includes(id));
|
|
205
|
+
return typeof record?.family === 'string' && record.family ? record.family : null;
|
|
206
|
+
}
|
|
207
|
+
|
|
196
208
|
/**
|
|
197
209
|
* Turn a picker model + effort into the wire id the gateway accepts. Tiered
|
|
198
210
|
* families consume the effort (the id encodes it); a bare id whose record
|
|
@@ -228,17 +240,34 @@ function quotaRow(label, bucket) {
|
|
|
228
240
|
};
|
|
229
241
|
}
|
|
230
242
|
|
|
231
|
-
|
|
243
|
+
// The gateway's bucket ids; group names are display text and may change.
|
|
244
|
+
const GEMINI_5H_BUCKET_ID = 'gemini-5h';
|
|
245
|
+
const GEMINI_WEEKLY_BUCKET_ID = 'gemini-weekly';
|
|
246
|
+
const ARGON_WEEKLY_BUCKET_ID = 'gemini-argon-wtu-weekly';
|
|
247
|
+
// The "Claude and GPT models" group (Claude Opus, Claude Sonnet, GPT-OSS) has
|
|
248
|
+
// its own pair of buckets, separate from the Gemini counters.
|
|
249
|
+
const THIRD_PARTY_5H_BUCKET_ID = '3p-5h';
|
|
250
|
+
const THIRD_PARTY_WEEKLY_BUCKET_ID = '3p-weekly';
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Gemini 5H/7D rows from retrieveUserQuotaSummary, the separate weekly limit
|
|
254
|
+
* of the Gemini 4 Argon group (its own group with only a weekly bucket), and
|
|
255
|
+
* the Claude/GPT-OSS 5H/7D pair. Rows are selected by bucket id and window.
|
|
256
|
+
* Missing fields stay omitted.
|
|
257
|
+
*/
|
|
232
258
|
export function antigravityQuotaWindows(summary) {
|
|
233
|
-
const groups = Array.isArray(summary?.groups) ? summary.groups : []
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
259
|
+
const groups = (Array.isArray(summary?.groups) ? summary.groups : []).filter(
|
|
260
|
+
(entry) => entry && typeof entry === 'object'
|
|
261
|
+
);
|
|
262
|
+
const buckets = groups.flatMap((entry) => (Array.isArray(entry.buckets) ? entry.buckets : []));
|
|
263
|
+
const bucket = (id, window) =>
|
|
264
|
+
buckets.find((entry) => entry && typeof entry === 'object' && entry.bucketId === id && entry.window === window) ??
|
|
265
|
+
null;
|
|
266
|
+
return [
|
|
267
|
+
quotaRow('5H', bucket(GEMINI_5H_BUCKET_ID, '5h')),
|
|
268
|
+
quotaRow('7D', bucket(GEMINI_WEEKLY_BUCKET_ID, 'weekly')),
|
|
269
|
+
quotaRow('7D Argon', bucket(ARGON_WEEKLY_BUCKET_ID, 'weekly')),
|
|
270
|
+
quotaRow('5H Claude/GPT', bucket(THIRD_PARTY_5H_BUCKET_ID, '5h')),
|
|
271
|
+
quotaRow('7D Claude/GPT', bucket(THIRD_PARTY_WEEKLY_BUCKET_ID, 'weekly')),
|
|
272
|
+
].filter(Boolean);
|
|
244
273
|
}
|
|
@@ -20,7 +20,11 @@ import { preconnect } from '../../../shared/llm/http-agent.mjs';
|
|
|
20
20
|
import { createAntigravityStreamCollector } from './antigravity-stream.mjs';
|
|
21
21
|
import { createAntigravityRequest } from './antigravity-transport.mjs';
|
|
22
22
|
import { finalizeAntigravityTurn } from './antigravity-response.mjs';
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
ANTIGRAVITY_ACCOUNT_COOLDOWN_POLICY,
|
|
25
|
+
antigravityFirstBytePolicy,
|
|
26
|
+
antigravityFirstResponseBudget,
|
|
27
|
+
} from './antigravity-retry-policy.mjs';
|
|
24
28
|
import {
|
|
25
29
|
CONTENT_ENDPOINT,
|
|
26
30
|
ANTIGRAVITY_MODELS,
|
|
@@ -97,6 +101,13 @@ export class AntigravityOAuthProvider {
|
|
|
97
101
|
return configured || CONTENT_ENDPOINT;
|
|
98
102
|
}
|
|
99
103
|
|
|
104
|
+
// Longest one send to `model` may wait for response headers / first output,
|
|
105
|
+
// the whole transport retry ladder included; the agent watchdog's
|
|
106
|
+
// first-response deadlines are floored above it.
|
|
107
|
+
firstResponseBudget(model) {
|
|
108
|
+
return antigravityFirstResponseBudget(antigravityFirstBytePolicy(model || DEFAULT_ANTIGRAVITY_MODEL));
|
|
109
|
+
}
|
|
110
|
+
|
|
100
111
|
_buildBody(messages, model, tools, opts) {
|
|
101
112
|
const body = buildAntigravityRequest(messages, model, tools, opts, this._projectId);
|
|
102
113
|
dumpAntigravityRequest(body);
|
|
@@ -169,6 +180,7 @@ export class AntigravityOAuthProvider {
|
|
|
169
180
|
signal: passthrough.signal,
|
|
170
181
|
collector,
|
|
171
182
|
sleepFn: this.config.sleepFn,
|
|
183
|
+
firstByte: antigravityFirstBytePolicy(useModel),
|
|
172
184
|
});
|
|
173
185
|
try {
|
|
174
186
|
try {
|
|
@@ -60,9 +60,8 @@ function coalesceClaudeThoughts(parts) {
|
|
|
60
60
|
out.push(part);
|
|
61
61
|
continue;
|
|
62
62
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
: { ...part, text: typeof part.text === 'string' ? part.text : '' };
|
|
63
|
+
const partText = typeof part.text === 'string' ? part.text : '';
|
|
64
|
+
open = open ? { ...open, ...part, text: `${open.text}${partText}` } : { ...part, text: partText };
|
|
66
65
|
if (typeof part.thoughtSignature === 'string') {
|
|
67
66
|
out.push(open);
|
|
68
67
|
open = null;
|
|
@@ -72,6 +71,30 @@ function coalesceClaudeThoughts(parts) {
|
|
|
72
71
|
return out;
|
|
73
72
|
}
|
|
74
73
|
|
|
74
|
+
// The validator-bypass sentinel is a Gemini wire token: the Claude bridge
|
|
75
|
+
// sends a thinking block carrying it (or no signature at all) without a
|
|
76
|
+
// signature and Anthropic rejects the request ("thinking.signature: Field
|
|
77
|
+
// required"). Only a signature this route recorded is replayed to Claude;
|
|
78
|
+
// any other signature is removed, and a thinking block left without one (an
|
|
79
|
+
// interrupted run, another model's or provider's turn, legacy metadata) is
|
|
80
|
+
// dropped rather than turned into visible text.
|
|
81
|
+
const hasOwnClaudeSignature = (part) =>
|
|
82
|
+
typeof part.thoughtSignature === 'string' &&
|
|
83
|
+
part.thoughtSignature !== '' &&
|
|
84
|
+
part.thoughtSignature !== THOUGHT_SIGNATURE_SENTINEL;
|
|
85
|
+
|
|
86
|
+
function claudeReplayParts(parts, own) {
|
|
87
|
+
const signed = parts.map((part) => {
|
|
88
|
+
if (!part || typeof part !== 'object' || !('thoughtSignature' in part)) return part;
|
|
89
|
+
if (own && hasOwnClaudeSignature(part)) return part;
|
|
90
|
+
const { thoughtSignature: _foreign, ...unsigned } = part;
|
|
91
|
+
return unsigned;
|
|
92
|
+
});
|
|
93
|
+
return coalesceClaudeThoughts(signed.filter((part) => !isEmptyPlainTextPart(part))).filter(
|
|
94
|
+
(part) => part?.thought !== true || hasOwnClaudeSignature(part)
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
75
98
|
function signatureSafeMessages(messages, model) {
|
|
76
99
|
const claude = isAntigravityClaude(model);
|
|
77
100
|
return messages.flatMap((message) => {
|
|
@@ -80,11 +103,8 @@ function signatureSafeMessages(messages, model) {
|
|
|
80
103
|
// Repair tool signatures only after the complete history establishes
|
|
81
104
|
// the active turn, not while normalizing an isolated older message.
|
|
82
105
|
const sourceParts = ownParts || toGeminiContents([message], model, { repairToolSignatures: false })[0]?.parts;
|
|
83
|
-
const parts =
|
|
84
|
-
|
|
85
|
-
? coalesceClaudeThoughts(sourceParts.filter((part) => !isEmptyPlainTextPart(part)))
|
|
86
|
-
: sourceParts;
|
|
87
|
-
// A turn that held only empty parts is omitted, not sent as parts:[].
|
|
106
|
+
const parts = claude && sourceParts ? claudeReplayParts(sourceParts, !!ownParts) : sourceParts;
|
|
107
|
+
// A turn that held only empty or dropped parts is omitted, not sent as parts:[].
|
|
88
108
|
if (sourceParts?.length && !parts.length) return [];
|
|
89
109
|
if (!parts?.length) return [message];
|
|
90
110
|
for (const part of parts) {
|
|
@@ -100,6 +120,56 @@ function signatureSafeMessages(messages, model) {
|
|
|
100
120
|
});
|
|
101
121
|
}
|
|
102
122
|
|
|
123
|
+
const isToolResultTurn = (content) =>
|
|
124
|
+
content?.role === 'user' && !!content.parts?.some((part) => part?.functionResponse);
|
|
125
|
+
const isPromptTurn = (content) => content?.role === 'user' && !isToolResultTurn(content);
|
|
126
|
+
const hasSignedThinking = (content) =>
|
|
127
|
+
!!content?.parts?.some((part) => part?.thought === true && hasOwnClaudeSignature(part));
|
|
128
|
+
|
|
129
|
+
// With thinking on, Claude rejects a tool loop whose turn did not open with a
|
|
130
|
+
// signed thinking block, and a block that was dropped (unsigned, foreign or
|
|
131
|
+
// compacted away) cannot be restored. The outgoing request closes that loop
|
|
132
|
+
// instead: the closed part loses its thinking, a short model reply
|
|
133
|
+
// acknowledges the tool results, and a user nudge opens a fresh turn that
|
|
134
|
+
// Claude starts with new thinking. The closure sits after the results of the
|
|
135
|
+
// turn's last unthought model message, so later steps keep the signed
|
|
136
|
+
// thinking that the fresh turn produced. Wire-only: the caller's messages and
|
|
137
|
+
// recorded replays are never touched.
|
|
138
|
+
function closeUnthoughtToolLoop(contents) {
|
|
139
|
+
if (!isToolResultTurn(contents.at(-1))) return contents;
|
|
140
|
+
const promptIndex = contents.findLastIndex(isPromptTurn);
|
|
141
|
+
const modelIndexes = [];
|
|
142
|
+
for (let index = promptIndex + 1; index < contents.length; index += 1) {
|
|
143
|
+
if (contents[index]?.role === 'model') modelIndexes.push(index);
|
|
144
|
+
}
|
|
145
|
+
if (!modelIndexes.length || hasSignedThinking(contents[modelIndexes[0]])) return contents;
|
|
146
|
+
const unthought = modelIndexes.findLast((index) => !hasSignedThinking(contents[index]));
|
|
147
|
+
let cut = unthought + 1;
|
|
148
|
+
let results = 0;
|
|
149
|
+
while (isToolResultTurn(contents[cut])) {
|
|
150
|
+
results += contents[cut].parts.filter((part) => part?.functionResponse).length;
|
|
151
|
+
cut += 1;
|
|
152
|
+
}
|
|
153
|
+
if (!results) return contents;
|
|
154
|
+
const closed = contents.slice(0, cut).flatMap((content) => {
|
|
155
|
+
if (content?.role !== 'model') return [content];
|
|
156
|
+
const parts = content.parts.filter((part) => part?.thought !== true);
|
|
157
|
+
return parts.length ? [{ ...content, parts }] : [];
|
|
158
|
+
});
|
|
159
|
+
const ack = results === 1 ? '[Tool result received.]' : `[${results} tool results received.]`;
|
|
160
|
+
return [
|
|
161
|
+
...closed,
|
|
162
|
+
{ role: 'model', parts: [{ text: ack }] },
|
|
163
|
+
{ role: 'user', parts: [{ text: '[Continue.]' }] },
|
|
164
|
+
...contents.slice(cut),
|
|
165
|
+
];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// The request turns Claude thinking on through an effort level or token
|
|
169
|
+
// budget; a `-thinking` wire id thinks without either.
|
|
170
|
+
const claudeThinkingEnabled = (model, thinkingConfig) =>
|
|
171
|
+
!!(thinkingConfig.thinkingLevel || thinkingConfig.thinkingBudget) || /-thinking$/i.test(String(model));
|
|
172
|
+
|
|
103
173
|
function sessionId(contents) {
|
|
104
174
|
const first = contents.find((content) => content?.role === 'user');
|
|
105
175
|
const text = first?.parts?.map((part) => (typeof part?.text === 'string' ? part.text : '')).join('') || '';
|
|
@@ -155,10 +225,11 @@ export function buildAntigravityRequest(messages, model, tools, opts = {}, proje
|
|
|
155
225
|
.map((message) => message.content)
|
|
156
226
|
.join('\n\n');
|
|
157
227
|
const chatMessages = messages.filter((message) => message.role !== 'system');
|
|
158
|
-
const
|
|
159
|
-
if (!
|
|
228
|
+
const history = toGeminiContents(signatureSafeMessages(chatMessages, model), model);
|
|
229
|
+
if (!history.length) throw new Error('No messages to send');
|
|
160
230
|
const claude = isAntigravityClaude(model);
|
|
161
231
|
const thinkingConfig = claude ? claudeThinkingConfig(opts) : antigravityGeminiThinkingConfig(model, opts);
|
|
232
|
+
const contents = claude && claudeThinkingEnabled(model, thinkingConfig) ? closeUnthoughtToolLoop(history) : history;
|
|
162
233
|
const generationConfig = {
|
|
163
234
|
...(claude ? { maxOutputTokens: CLAUDE_MAX_OUTPUT_TOKENS } : {}),
|
|
164
235
|
...(thinkingConfig ? { thinkingConfig } : {}),
|
|
@@ -14,11 +14,28 @@
|
|
|
14
14
|
* rotate; advice beyond 60s surfaces at once.
|
|
15
15
|
* QUOTA_EXHAUSTED (and any day/plan window): never retried here.
|
|
16
16
|
*
|
|
17
|
+
* First byte: the gateway queues or thinks server-side and sends the
|
|
18
|
+
* response headers together with the first chunk, so the window is chosen
|
|
19
|
+
* per model class from the catalog `family`: Pro-class Gemini (Pro tiers,
|
|
20
|
+
* Argon) waits MIXDOG_ANTIGRAVITY_FIRST_BYTE_TIMEOUT_MS (300s, clamped to
|
|
21
|
+
* the provider ceiling PROVIDER_MAX_BEFORE_WARN_MS, 285s by default),
|
|
22
|
+
* Flash-class Gemini the shared Gemini window (60s); both apply to the
|
|
23
|
+
* headers and again to the first chunk. A header or first-chunk timeout is
|
|
24
|
+
* retried at most MIXDOG_ANTIGRAVITY_FIRST_BYTE_RETRIES times (1), each
|
|
25
|
+
* retry doubling the window up to that ceiling; connect, 5xx and drop
|
|
26
|
+
* failures keep the full ladder (MIXDOG_ANTIGRAVITY_RETRY_MAX_ATTEMPTS, 4
|
|
27
|
+
* attempts, at MIXDOG_ANTIGRAVITY_RETRY_BACKOFF_MS 1s / 2s / 4s). Models
|
|
28
|
+
* without a Gemini family (Claude, GPT-OSS, unlisted ids) keep the shared
|
|
29
|
+
* Gemini window on that ladder.
|
|
30
|
+
*
|
|
17
31
|
* Replay stays gated by the stream-outcome contract: an attempt that exposed
|
|
18
32
|
* text or dispatched a tool is never re-issued.
|
|
19
33
|
*/
|
|
20
34
|
import { readStreamOutcome } from './lib/stream-outcome.mjs';
|
|
21
35
|
import { DETERMINISTIC_KINDS, providerErrorKind } from './provider-error-kind.mjs';
|
|
36
|
+
import { PROVIDER_MAX_BEFORE_WARN_MS, firstBytePolicyBudget, resolveTimeoutMs } from '../stall-policy.mjs';
|
|
37
|
+
import { GEMINI_FIRST_BYTE_TIMEOUT_MS } from './gemini-stream.mjs';
|
|
38
|
+
import { antigravityModelFamily } from './antigravity-oauth-catalog.mjs';
|
|
22
39
|
|
|
23
40
|
export const ANTIGRAVITY_CAPACITY_RETRIES = 3;
|
|
24
41
|
export const ANTIGRAVITY_CAPACITY_BASE_MS = 1000;
|
|
@@ -29,21 +46,103 @@ export const ANTIGRAVITY_CAPACITY_BUDGET_MS = 60_000;
|
|
|
29
46
|
export const ANTIGRAVITY_QUICK_RETRY_MS = 1000;
|
|
30
47
|
export const ANTIGRAVITY_QUICK_RETRY_MAX_ADVICE_MS = 60_000;
|
|
31
48
|
|
|
49
|
+
const DEFAULT_RETRY_BACKOFF_MS = Object.freeze([1000, 1000, 2000, 4000]);
|
|
50
|
+
|
|
51
|
+
function envInt(env, name, fallback, min, max) {
|
|
52
|
+
const raw = env?.[name];
|
|
53
|
+
if (raw == null || String(raw).trim() === '') return fallback;
|
|
54
|
+
const n = Number(raw);
|
|
55
|
+
if (!Number.isInteger(n)) return fallback;
|
|
56
|
+
return Math.min(Math.max(n, min), max);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function envBackoffMs(env, name) {
|
|
60
|
+
const raw = String(env?.[name] ?? '').trim();
|
|
61
|
+
if (!raw) return DEFAULT_RETRY_BACKOFF_MS;
|
|
62
|
+
const steps = raw.split(',').map((step) => Number(step.trim()));
|
|
63
|
+
if (!steps.every((step) => Number.isInteger(step) && step >= 0)) return DEFAULT_RETRY_BACKOFF_MS;
|
|
64
|
+
return Object.freeze(steps);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The same-host ladder for everything that is not a 429, read from the
|
|
69
|
+
* environment: attempts (1–6), the backoff list (index n is the wait before
|
|
70
|
+
* attempt n) and how many first-byte timeouts a thinking model may retry.
|
|
71
|
+
*/
|
|
72
|
+
export function resolveAntigravityRetryConfig(env = process.env) {
|
|
73
|
+
return {
|
|
74
|
+
maxAttempts: envInt(env, 'MIXDOG_ANTIGRAVITY_RETRY_MAX_ATTEMPTS', ANTIGRAVITY_CAPACITY_RETRIES + 1, 1, 6),
|
|
75
|
+
backoffMs: envBackoffMs(env, 'MIXDOG_ANTIGRAVITY_RETRY_BACKOFF_MS'),
|
|
76
|
+
firstByteRetries: envInt(env, 'MIXDOG_ANTIGRAVITY_FIRST_BYTE_RETRIES', 1, 0, 5),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const RETRY_CONFIG = resolveAntigravityRetryConfig();
|
|
81
|
+
|
|
32
82
|
// withRetry options for everything that is not a 429: transient transport and
|
|
33
83
|
// 5xx failures use the capacity schedule (the reference has no other same-host
|
|
34
84
|
// retry; the leading duplicate is the sleep-before-attempt index).
|
|
35
85
|
export const ANTIGRAVITY_RETRY = Object.freeze({
|
|
36
|
-
maxAttempts:
|
|
37
|
-
backoffMs:
|
|
86
|
+
maxAttempts: RETRY_CONFIG.maxAttempts,
|
|
87
|
+
backoffMs: RETRY_CONFIG.backoffMs,
|
|
38
88
|
retryJitterRatio: ANTIGRAVITY_CAPACITY_JITTER_RATIO,
|
|
39
89
|
// 429s are handled by antigravity429WaitMs, not the generic loop.
|
|
40
90
|
retry429: false,
|
|
41
91
|
});
|
|
42
92
|
|
|
93
|
+
export const ANTIGRAVITY_FIRST_BYTE_RETRIES = RETRY_CONFIG.firstByteRetries;
|
|
94
|
+
|
|
95
|
+
// Pro-class window: 300s requested, clamped to the provider ceiling.
|
|
96
|
+
export const ANTIGRAVITY_FIRST_BYTE_TIMEOUT_MS = resolveTimeoutMs('MIXDOG_ANTIGRAVITY_FIRST_BYTE_TIMEOUT_MS', 300_000, {
|
|
97
|
+
minMs: 30_000,
|
|
98
|
+
maxMs: PROVIDER_MAX_BEFORE_WARN_MS,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// First-attempt window per catalog family.
|
|
102
|
+
const FAMILY_FIRST_BYTE_MS = Object.freeze({
|
|
103
|
+
'gemini-pro': ANTIGRAVITY_FIRST_BYTE_TIMEOUT_MS,
|
|
104
|
+
'gemini-flash': GEMINI_FIRST_BYTE_TIMEOUT_MS,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Models without a Gemini family: the shared Gemini window on the ordinary ladder.
|
|
108
|
+
export const ANTIGRAVITY_UNCLASSED_FIRST_BYTE = Object.freeze({
|
|
109
|
+
timeoutMs: GEMINI_FIRST_BYTE_TIMEOUT_MS,
|
|
110
|
+
maxMs: GEMINI_FIRST_BYTE_TIMEOUT_MS,
|
|
111
|
+
retries: null,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* First-byte policy (see firstByteWindowMs) for one model, picker or wire id.
|
|
116
|
+
* The class comes from the catalog record's `family`.
|
|
117
|
+
*/
|
|
118
|
+
export function antigravityFirstBytePolicy(model, models) {
|
|
119
|
+
const timeoutMs = FAMILY_FIRST_BYTE_MS[antigravityModelFamily(model, models)];
|
|
120
|
+
if (!timeoutMs) return ANTIGRAVITY_UNCLASSED_FIRST_BYTE;
|
|
121
|
+
return {
|
|
122
|
+
timeoutMs,
|
|
123
|
+
maxMs: PROVIDER_MAX_BEFORE_WARN_MS,
|
|
124
|
+
retries: Math.min(ANTIGRAVITY_FIRST_BYTE_RETRIES, ANTIGRAVITY_RETRY.maxAttempts - 1),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Longest a send may wait before its first output across the whole transport
|
|
130
|
+
* ladder ({ transportMs, semanticMs }, see firstBytePolicyBudget): the agent
|
|
131
|
+
* watchdog must not fire inside it. Drops and 5xx share the ladder with
|
|
132
|
+
* first-byte timeouts, so the budget is every backoff step of the ladder plus
|
|
133
|
+
* the windows of the first-byte timeouts the policy permits (all attempts for
|
|
134
|
+
* a policy without its own retry cap).
|
|
135
|
+
*/
|
|
136
|
+
export function antigravityFirstResponseBudget(policy, backoffMs = ANTIGRAVITY_RETRY.backoffMs) {
|
|
137
|
+
return firstBytePolicyBudget(policy, { attempts: ANTIGRAVITY_RETRY.maxAttempts, backoffMs });
|
|
138
|
+
}
|
|
139
|
+
|
|
43
140
|
/** Capacity wait for retry number `retryIndex` (0-based): 1s, 2s, 4s, 8s cap, ±10%. */
|
|
44
|
-
|
|
141
|
+
function antigravityCapacityDelayMs(retryIndex) {
|
|
45
142
|
const base = Math.min(ANTIGRAVITY_CAPACITY_BASE_MS * 2 ** retryIndex, ANTIGRAVITY_CAPACITY_MAX_MS);
|
|
46
|
-
return Math.round(
|
|
143
|
+
return Math.round(
|
|
144
|
+
base * (1 - ANTIGRAVITY_CAPACITY_JITTER_RATIO + Math.random() * 2 * ANTIGRAVITY_CAPACITY_JITTER_RATIO)
|
|
145
|
+
);
|
|
47
146
|
}
|
|
48
147
|
|
|
49
148
|
export function isAntigravityCapacityError(err) {
|
|
@@ -60,7 +159,12 @@ export function antigravity429WaitMs(err, state) {
|
|
|
60
159
|
if (status !== 429 && !(capacity && (status === 503 || status === 529))) return null;
|
|
61
160
|
if (readStreamOutcome(err).replaySafe !== true) return null;
|
|
62
161
|
const { kind, retryAfterMs } = providerErrorKind(err);
|
|
63
|
-
if (
|
|
162
|
+
if (
|
|
163
|
+
DETERMINISTIC_KINDS.has(kind) ||
|
|
164
|
+
err.code === 'quota_exhausted' ||
|
|
165
|
+
err.quotaScope === 'day' ||
|
|
166
|
+
err.quotaScope === 'plan'
|
|
167
|
+
) {
|
|
64
168
|
return null;
|
|
65
169
|
}
|
|
66
170
|
// Capacity waits at least the advised RetryInfo delay (the local schedule
|
|
@@ -80,10 +80,11 @@ export function createAntigravityStreamCollector({ tools, useModel, onToolCall,
|
|
|
80
80
|
textLeakGuard = null;
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
-
const consume = async (res, attemptSignal) => {
|
|
83
|
+
const consume = async (res, attemptSignal, { firstByteTimeoutMs } = {}) => {
|
|
84
84
|
try {
|
|
85
85
|
return await consumeGeminiRestStreamResponse(res, {
|
|
86
86
|
signal: attemptSignal,
|
|
87
|
+
firstByteTimeoutMs,
|
|
87
88
|
onStreamDelta,
|
|
88
89
|
onTextDelta: relayText,
|
|
89
90
|
onChunk,
|
|
@@ -6,15 +6,22 @@
|
|
|
6
6
|
* account-verification URL Google hides in the error details), and the
|
|
7
7
|
* per-attempt hand-off of the live stream to the turn collector.
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
emitProviderRetryStage,
|
|
11
|
+
markProviderRecoveryExhausted,
|
|
12
|
+
sleepWithAbort,
|
|
13
|
+
withRetry,
|
|
14
|
+
} from './retry-classifier.mjs';
|
|
10
15
|
import {
|
|
11
16
|
ANTIGRAVITY_RETRY,
|
|
17
|
+
ANTIGRAVITY_UNCLASSED_FIRST_BYTE,
|
|
12
18
|
antigravity429WaitMs,
|
|
13
19
|
isAntigravityCapacityError,
|
|
14
20
|
} from './antigravity-retry-policy.mjs';
|
|
15
|
-
import { createTimeoutSignal } from '../stall-policy.mjs';
|
|
21
|
+
import { createTimeoutSignal, firstByteWindowMs } from '../stall-policy.mjs';
|
|
22
|
+
import { MODEL_THINKING_STAGE } from '../../../shared/quiet-progress.mjs';
|
|
23
|
+
import { TIMEOUT_PHASE, isFirstByteTimeout } from '../../../shared/provider-timeout-phase.mjs';
|
|
16
24
|
import { getLlmDispatcher } from '../../../shared/llm/http-agent.mjs';
|
|
17
|
-
import { GEMINI_FIRST_BYTE_TIMEOUT_MS } from './gemini-stream.mjs';
|
|
18
25
|
import { _scrubTokens } from './antigravity-oauth-tokens.mjs';
|
|
19
26
|
import { applyGeminiErrorContract } from './gemini-error-contract.mjs';
|
|
20
27
|
import { DETERMINISTIC_KINDS, providerErrorKind } from './provider-error-kind.mjs';
|
|
@@ -77,8 +84,10 @@ export function antigravityError(res, text, endpoint) {
|
|
|
77
84
|
.map((link) => link?.url)
|
|
78
85
|
.find((url) => typeof url === 'string' && url.length > 0);
|
|
79
86
|
const metadataUrl = (key) =>
|
|
80
|
-
detailEntries.find(
|
|
81
|
-
|
|
87
|
+
detailEntries.find(
|
|
88
|
+
(entry) =>
|
|
89
|
+
entry?.reason === 'VALIDATION_REQUIRED' && typeof entry.metadata?.[key] === 'string' && entry.metadata[key]
|
|
90
|
+
)?.metadata[key];
|
|
82
91
|
const validationUrl =
|
|
83
92
|
helpUrl ||
|
|
84
93
|
metadataUrl('validation_url') ||
|
|
@@ -105,19 +114,53 @@ export function antigravityError(res, text, endpoint) {
|
|
|
105
114
|
* @param {object} deps.opts send options (stage heartbeat)
|
|
106
115
|
* @param {AbortSignal|null} deps.signal retry-loop signal (session pass-through)
|
|
107
116
|
* @param {{ beginAttempt: Function, consume: Function }} deps.collector
|
|
117
|
+
* @param {{ timeoutMs: number, maxMs: number, retries: number|null }} [deps.firstByte]
|
|
118
|
+
* first-byte window per attempt (antigravityFirstBytePolicy)
|
|
108
119
|
* @returns {() => Promise<object>} one retried request that resolves the final payload
|
|
109
120
|
*/
|
|
110
|
-
export function createAntigravityRequest({
|
|
121
|
+
export function createAntigravityRequest({
|
|
122
|
+
fetchFn,
|
|
123
|
+
endpoint,
|
|
124
|
+
headers,
|
|
125
|
+
body,
|
|
126
|
+
opts,
|
|
127
|
+
signal,
|
|
128
|
+
collector,
|
|
129
|
+
sleepFn,
|
|
130
|
+
firstByte = ANTIGRAVITY_UNCLASSED_FIRST_BYTE,
|
|
131
|
+
}) {
|
|
111
132
|
const log = (attempt, lastErr, delayMs) => {
|
|
133
|
+
// A first-byte timeout runs on its own, shorter retry budget.
|
|
134
|
+
const firstByteLimited = isFirstByteTimeout(lastErr) && firstByte.retries != null;
|
|
112
135
|
emitProviderRetryStage(opts.onStageChange, {
|
|
113
136
|
attempt: attempt + 1,
|
|
114
|
-
maxAttempts:
|
|
137
|
+
maxAttempts: firstByteLimited
|
|
138
|
+
? Math.min(ANTIGRAVITY_RETRY.maxAttempts, firstByte.retries + 1)
|
|
139
|
+
: ANTIGRAVITY_RETRY.maxAttempts,
|
|
115
140
|
lastErr,
|
|
116
141
|
delayMs,
|
|
117
142
|
});
|
|
118
143
|
process.stderr.write(`[antigravity] retry ${attempt + 1} after ${lastErr?.message || 'transient error'}\n`);
|
|
119
144
|
};
|
|
120
|
-
|
|
145
|
+
// Stamps what the attempt tells the user: how many attempts ran and, for a
|
|
146
|
+
// first-byte timeout, how long the model was given in total. A timeout past
|
|
147
|
+
// the first-byte retry budget ends the ladder here. A caller's cancellation
|
|
148
|
+
// reason may be shared by other requests and is never stamped.
|
|
149
|
+
const noteFailure = (err, { attemptSignal, windowMs, send }) => {
|
|
150
|
+
if (!err || typeof err !== 'object' || attemptSignal?.aborted) return err;
|
|
151
|
+
send.attempts += 1;
|
|
152
|
+
err.attempts = send.attempts;
|
|
153
|
+
if (!isFirstByteTimeout(err)) return err;
|
|
154
|
+
send.firstByteTimeouts += 1;
|
|
155
|
+
send.firstByteWaitedMs += windowMs;
|
|
156
|
+
err.waitedMs = send.firstByteWaitedMs;
|
|
157
|
+
err.providerLabel = 'Antigravity';
|
|
158
|
+
if (firstByte.retries != null && send.firstByteTimeouts > firstByte.retries) {
|
|
159
|
+
markProviderRecoveryExhausted(err, { owner: 'antigravity-first-byte', attempts: send.attempts, terminal: true });
|
|
160
|
+
}
|
|
161
|
+
return err;
|
|
162
|
+
};
|
|
163
|
+
const attemptOnce = (send) =>
|
|
121
164
|
withRetry(
|
|
122
165
|
async ({ signal: attemptSignal }) => {
|
|
123
166
|
try {
|
|
@@ -125,37 +168,63 @@ export function createAntigravityRequest({ fetchFn, endpoint, headers, body, opt
|
|
|
125
168
|
} catch {
|
|
126
169
|
/* heartbeat */
|
|
127
170
|
}
|
|
128
|
-
const
|
|
129
|
-
let res;
|
|
171
|
+
const windowMs = firstByteWindowMs(firstByte, send.firstByteTimeouts);
|
|
130
172
|
try {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
173
|
+
const firstByteTimer = createTimeoutSignal(attemptSignal, windowMs, 'Antigravity first byte');
|
|
174
|
+
let res;
|
|
175
|
+
try {
|
|
176
|
+
const response = fetchFn(`${endpoint}/v1internal:streamGenerateContent?alt=sse`, {
|
|
177
|
+
method: 'POST',
|
|
178
|
+
headers,
|
|
179
|
+
body,
|
|
180
|
+
signal: firstByteTimer.signal,
|
|
181
|
+
dispatcher: getLlmDispatcher(),
|
|
182
|
+
});
|
|
183
|
+
// The request is on the wire and its headers are pending: the
|
|
184
|
+
// gateway sends them only with the first chunk, so this wait is
|
|
185
|
+
// the model's queueing and thinking time.
|
|
186
|
+
try {
|
|
187
|
+
opts.onStageChange?.(MODEL_THINKING_STAGE);
|
|
188
|
+
} catch {
|
|
189
|
+
/* heartbeat */
|
|
190
|
+
}
|
|
191
|
+
res = await response;
|
|
192
|
+
} catch (err) {
|
|
193
|
+
// Fetch surfaces AbortError; rethrow the timer/parent
|
|
194
|
+
// reason so same-host retry sees EPROVIDERTIMEOUT and
|
|
195
|
+
// a caller cancel stays a cancel.
|
|
196
|
+
if (firstByteTimer.signal.aborted && firstByteTimer.signal.reason instanceof Error) {
|
|
197
|
+
const reason = firstByteTimer.signal.reason;
|
|
198
|
+
if (!attemptSignal?.aborted) reason.timeoutPhase = TIMEOUT_PHASE.HEADERS;
|
|
199
|
+
throw reason;
|
|
200
|
+
}
|
|
201
|
+
throw err;
|
|
202
|
+
} finally {
|
|
203
|
+
firstByteTimer.cleanup();
|
|
144
204
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
205
|
+
// Headers arrived: the connection is live even while the model
|
|
206
|
+
// has not produced its first chunk.
|
|
207
|
+
try {
|
|
208
|
+
opts.onStreamDelta?.('transport');
|
|
209
|
+
} catch {}
|
|
210
|
+
if (!res.ok) {
|
|
211
|
+
const text = await res.text().catch(() => '');
|
|
212
|
+
const failure = antigravityError(res, text, endpoint);
|
|
213
|
+
// Capacity is paced by the local schedule below; the generic loop
|
|
214
|
+
// would sleep whatever wait the server names.
|
|
215
|
+
if (isCapacityFailure(failure)) markProviderRecoveryExhausted(failure, { owner: 'antigravity-capacity' });
|
|
216
|
+
throw failure;
|
|
217
|
+
}
|
|
218
|
+
try {
|
|
219
|
+
opts.onStageChange?.('streaming');
|
|
220
|
+
} catch {
|
|
221
|
+
/* heartbeat */
|
|
222
|
+
}
|
|
223
|
+
collector.beginAttempt();
|
|
224
|
+
return await collector.consume(res, attemptSignal, { firstByteTimeoutMs: windowMs });
|
|
225
|
+
} catch (err) {
|
|
226
|
+
throw noteFailure(err, { attemptSignal, windowMs, send });
|
|
156
227
|
}
|
|
157
|
-
collector.beginAttempt();
|
|
158
|
-
return collector.consume(res, attemptSignal);
|
|
159
228
|
},
|
|
160
229
|
{
|
|
161
230
|
...ANTIGRAVITY_RETRY,
|
|
@@ -170,9 +239,10 @@ export function createAntigravityRequest({ fetchFn, endpoint, headers, body, opt
|
|
|
170
239
|
// gets one quick retry, a spent quota surfaces.
|
|
171
240
|
return async () => {
|
|
172
241
|
const state = { capacityRetries: 0, quickRetried: false };
|
|
242
|
+
const send = { attempts: 0, firstByteTimeouts: 0, firstByteWaitedMs: 0 };
|
|
173
243
|
for (let tried = 1; ; tried++) {
|
|
174
244
|
try {
|
|
175
|
-
return await attemptOnce();
|
|
245
|
+
return await attemptOnce(send);
|
|
176
246
|
} catch (err) {
|
|
177
247
|
const waitMs = antigravity429WaitMs(err, state);
|
|
178
248
|
if (waitMs == null) {
|
|
@@ -79,7 +79,10 @@ export function modelEndpoints(item) {
|
|
|
79
79
|
// The route for a model with these declared endpoints (null: undeclared, Chat).
|
|
80
80
|
// `undefined`: nothing describes the model, so no wire is ruled out.
|
|
81
81
|
function commandCodeRoute(model, endpoints, ctx = {}) {
|
|
82
|
-
return resolveWireRoute(PROVIDER_ID, model, {
|
|
82
|
+
return resolveWireRoute(PROVIDER_ID, model, {
|
|
83
|
+
...ctx,
|
|
84
|
+
endpoints: endpoints === undefined ? null : (endpoints ?? ['chat']),
|
|
85
|
+
});
|
|
83
86
|
}
|
|
84
87
|
|
|
85
88
|
/**
|
|
@@ -366,7 +366,9 @@ export async function resolveCursorOAuthAccessToken({ forceRefresh = false, fetc
|
|
|
366
366
|
try {
|
|
367
367
|
saveCredentials({ ...persisted, reauth_required: true });
|
|
368
368
|
} catch (saveError) {
|
|
369
|
-
process.stderr.write(
|
|
369
|
+
process.stderr.write(
|
|
370
|
+
`[cursor-oauth] dead-account mark failed: ${String(saveError?.message || saveError).slice(0, 200)}\n`
|
|
371
|
+
);
|
|
370
372
|
}
|
|
371
373
|
}
|
|
372
374
|
}
|