mixdog 1.2.3 → 1.2.5
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/mobile-release.mjs +5 -4
- 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 +7 -1
- package/src/defaults/skills/image/SKILL.md +21 -23
- package/src/lib/keychain-cjs.cjs +13 -11
- package/src/output-styles/common.md +2 -1
- package/src/rules/agent/AGENT.md +7 -5
- package/src/rules/lead/LEAD.md +13 -13
- 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 +160 -212
- 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/desktop-service-registry.mjs +32 -5
- 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 +529 -270
- 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/ui/streaming-markdown-heal.mjs +70 -18
- 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
|
@@ -876,11 +876,11 @@ const isFailedToolResult = (message) => message.toolKind === 'error' || message.
|
|
|
876
876
|
// recorded part, and a recorded Gemini part may carry no id at all, in which
|
|
877
877
|
// case the response carries none either. An unmatched result keeps its own id.
|
|
878
878
|
function toGeminiToolResult(message, toolNameByCallId, nestMedia, callsByFinalId) {
|
|
879
|
-
const
|
|
879
|
+
const replayedCall = callsByFinalId?.get(message.toolCallId);
|
|
880
|
+
const functionName = replayedCall?.name || toolNameByCallId?.get(message.toolCallId) || message.toolCallId || '';
|
|
880
881
|
const { response: rawResponse, mediaParts } = splitGeminiToolContent(message.content);
|
|
881
882
|
const response = isFailedToolResult(message) && 'result' in rawResponse ? { error: rawResponse.result } : rawResponse;
|
|
882
883
|
const functionResponse = { name: functionName, response };
|
|
883
|
-
const replayedCall = callsByFinalId?.get(message.toolCallId);
|
|
884
884
|
const responseId = replayedCall ? replayedCall.id : message.toolCallId;
|
|
885
885
|
if (typeof responseId === 'string' && responseId) functionResponse.id = responseId;
|
|
886
886
|
if (!nestMedia) return { functionResponsePart: { functionResponse }, mediaParts };
|
|
@@ -895,16 +895,20 @@ function toGeminiToolResult(message, toolNameByCallId, nestMedia, callsByFinalId
|
|
|
895
895
|
// A replay recorded by a non-Gemini model (Claude behind Antigravity) carries
|
|
896
896
|
// signatures Gemini rejects: its replay envelope and the signed metadata
|
|
897
897
|
// derived from the same response must not reach a Gemini request.
|
|
898
|
-
function hasForeignReplay(message) {
|
|
898
|
+
function hasForeignReplay(message, model) {
|
|
899
899
|
const replay = message?.providerReplay;
|
|
900
900
|
if (replay?.provider !== 'gemini' && replay?.provider !== 'antigravity') return false;
|
|
901
901
|
const recorded = replay.requestContext?.model;
|
|
902
|
-
return
|
|
902
|
+
return (
|
|
903
|
+
typeof recorded === 'string' &&
|
|
904
|
+
recorded !== '' &&
|
|
905
|
+
(!isGeminiFamilyModel(recorded) || (replay.provider === 'gemini' && model && recorded !== model))
|
|
906
|
+
);
|
|
903
907
|
}
|
|
904
908
|
|
|
905
|
-
function toGeminiContent(message) {
|
|
909
|
+
function toGeminiContent(message, model) {
|
|
906
910
|
if (!message || message.role === 'system') return null;
|
|
907
|
-
const foreign = message.role === 'assistant' && hasForeignReplay(message);
|
|
911
|
+
const foreign = message.role === 'assistant' && hasForeignReplay(message, model);
|
|
908
912
|
if (foreign) message = { ...message, providerMetadata: undefined };
|
|
909
913
|
const orderedReplay =
|
|
910
914
|
message.role === 'assistant' && !foreign ? providerReplayItems(message, ['gemini', 'antigravity']) : undefined;
|
|
@@ -1019,7 +1023,7 @@ export function toGeminiContents(messages, model = '', { repairToolSignatures =
|
|
|
1019
1023
|
for (const tc of m.toolCalls) {
|
|
1020
1024
|
if (tc?.id && tc?.name) toolNameByCallId.set(tc.id, tc.name);
|
|
1021
1025
|
}
|
|
1022
|
-
const content = toGeminiContent(m);
|
|
1026
|
+
const content = toGeminiContent(m, model);
|
|
1023
1027
|
assistantContent.set(m, content);
|
|
1024
1028
|
const replayed = (content?.parts || []).filter((part) => part?.functionCall);
|
|
1025
1029
|
m.toolCalls.forEach((tc, index) => {
|
|
@@ -1039,6 +1043,7 @@ export function toGeminiContents(messages, model = '', { repairToolSignatures =
|
|
|
1039
1043
|
// first (one per call, in call order), then the media the results carried as
|
|
1040
1044
|
// sibling inlineData/fileData parts.
|
|
1041
1045
|
let toolTurn = null;
|
|
1046
|
+
let toolCallOrder = new Map();
|
|
1042
1047
|
const nestMedia = supportsFunctionResponseParts(model);
|
|
1043
1048
|
for (const message of messages) {
|
|
1044
1049
|
if (message?.role === 'tool') {
|
|
@@ -1049,16 +1054,23 @@ export function toGeminiContents(messages, model = '', { repairToolSignatures =
|
|
|
1049
1054
|
callsByFinalId
|
|
1050
1055
|
);
|
|
1051
1056
|
if (!toolTurn) {
|
|
1052
|
-
toolTurn = { content: { role: 'user', parts: [] }, responseCount: 0 };
|
|
1057
|
+
toolTurn = { content: { role: 'user', parts: [] }, responseCount: 0, responseOrder: [] };
|
|
1053
1058
|
contents.push(toolTurn.content);
|
|
1054
1059
|
}
|
|
1055
|
-
|
|
1060
|
+
// Completion order is not call order. Anonymous parallel calls to the
|
|
1061
|
+
// same function can only be correlated by their original position.
|
|
1062
|
+
const order = toolCallOrder.get(message.toolCallId) ?? Infinity;
|
|
1063
|
+
const next = toolTurn.responseOrder.findIndex((value) => value > order);
|
|
1064
|
+
const index = next < 0 ? toolTurn.responseCount : next;
|
|
1065
|
+
toolTurn.responseOrder.splice(index, 0, order);
|
|
1066
|
+
toolTurn.content.parts.splice(index, 0, functionResponsePart);
|
|
1056
1067
|
toolTurn.responseCount += 1;
|
|
1057
1068
|
toolTurn.content.parts.push(...mediaParts);
|
|
1058
1069
|
continue;
|
|
1059
1070
|
}
|
|
1060
1071
|
toolTurn = null;
|
|
1061
|
-
|
|
1072
|
+
toolCallOrder = new Map((message.toolCalls || []).map((call, index) => [call.id, index]));
|
|
1073
|
+
const content = assistantContent.has(message) ? assistantContent.get(message) : toGeminiContent(message, model);
|
|
1062
1074
|
if (content) contents.push(content);
|
|
1063
1075
|
}
|
|
1064
1076
|
return repairToolSignatures ? ensureGeminiToolCallSignatures(contents, model) : contents;
|
|
@@ -513,7 +513,8 @@ function createLeakGuardFinalizer(textLeakGuard) {
|
|
|
513
513
|
// `unwrapChunk` adapts a transport that nests the Gemini payload one level
|
|
514
514
|
// deeper. Cloud Code Assist (Antigravity) streams `{ response: { candidates … } }`
|
|
515
515
|
// while the public API streams the candidates directly; everything downstream —
|
|
516
|
-
// aggregation, leak guard, watchdogs — stays shared.
|
|
516
|
+
// aggregation, leak guard, watchdogs — stays shared. `firstByteTimeoutMs` is
|
|
517
|
+
// the wait for the first chunk once the response headers arrived.
|
|
517
518
|
export async function consumeGeminiRestStreamResponse(
|
|
518
519
|
response,
|
|
519
520
|
{
|
|
@@ -525,6 +526,7 @@ export async function consumeGeminiRestStreamResponse(
|
|
|
525
526
|
unwrapChunk = null,
|
|
526
527
|
onChunk = null,
|
|
527
528
|
failureUsage = null,
|
|
529
|
+
firstByteTimeoutMs = GEMINI_FIRST_BYTE_TIMEOUT_MS,
|
|
528
530
|
}
|
|
529
531
|
) {
|
|
530
532
|
const unwrap =
|
|
@@ -548,7 +550,7 @@ export async function consumeGeminiRestStreamResponse(
|
|
|
548
550
|
const watchdogs = createRestStreamWatchdogs({
|
|
549
551
|
reader,
|
|
550
552
|
label,
|
|
551
|
-
firstByteTimeoutMs
|
|
553
|
+
firstByteTimeoutMs,
|
|
552
554
|
timeoutError: geminiTimeoutError,
|
|
553
555
|
});
|
|
554
556
|
// One decoded chunk: collected for aggregation and relayed to every sink.
|
|
@@ -19,21 +19,43 @@ function catalogThinkingLevels(model, provider) {
|
|
|
19
19
|
// Documented ranges: 2.5 Pro 128–32768 (cannot disable), 2.5 Flash 0–24576,
|
|
20
20
|
// 2.5 Flash-Lite 0 or 512–24576; -1 is dynamic thinking for all of them.
|
|
21
21
|
function budgetSpec(model) {
|
|
22
|
-
const bare = String(model || '')
|
|
22
|
+
const bare = String(model || '')
|
|
23
|
+
.replace(/^models\//i, '')
|
|
24
|
+
.toLowerCase();
|
|
23
25
|
if (!/^gemini-2\.5(?:-|$)/.test(bare)) return null;
|
|
24
26
|
if (/^gemini-2\.5-pro/.test(bare)) {
|
|
25
|
-
return {
|
|
27
|
+
return {
|
|
28
|
+
name: 'Gemini 2.5 Pro',
|
|
29
|
+
min: 128,
|
|
30
|
+
max: 32768,
|
|
31
|
+
canDisable: false,
|
|
32
|
+
efforts: { minimal: 128, low: 1024, medium: 8192, high: 32768 },
|
|
33
|
+
};
|
|
26
34
|
}
|
|
27
35
|
if (/^gemini-2\.5-flash-lite/.test(bare)) {
|
|
28
|
-
return {
|
|
36
|
+
return {
|
|
37
|
+
name: 'Gemini 2.5 Flash-Lite',
|
|
38
|
+
min: 512,
|
|
39
|
+
max: 24576,
|
|
40
|
+
canDisable: true,
|
|
41
|
+
efforts: { minimal: 512, low: 1024, medium: 8192, high: 24576 },
|
|
42
|
+
};
|
|
29
43
|
}
|
|
30
|
-
return {
|
|
44
|
+
return {
|
|
45
|
+
name: 'Gemini 2.5 Flash',
|
|
46
|
+
min: 0,
|
|
47
|
+
max: 24576,
|
|
48
|
+
canDisable: true,
|
|
49
|
+
efforts: { minimal: 0, low: 1024, medium: 8192, high: 24576 },
|
|
50
|
+
};
|
|
31
51
|
}
|
|
32
52
|
|
|
33
53
|
// Levels documented for models whose ladder differs from the generic wire
|
|
34
54
|
// vocabulary (a catalog ladder, when declared, still takes precedence).
|
|
35
55
|
function documentedThinkingLevels(model) {
|
|
36
|
-
const bare = String(model || '')
|
|
56
|
+
const bare = String(model || '')
|
|
57
|
+
.replace(/^models\//i, '')
|
|
58
|
+
.toLowerCase();
|
|
37
59
|
if (bare === 'gemini-4-argon' || bare === 'gemini-3.8-flash') return ['low', 'medium', 'high'];
|
|
38
60
|
return null;
|
|
39
61
|
}
|
|
@@ -47,7 +69,9 @@ function checkBudget(model, spec, budget) {
|
|
|
47
69
|
throw new TypeError(`${model} (${spec.name}) cannot disable thinking; thinkingBudget 0 is not allowed.`);
|
|
48
70
|
}
|
|
49
71
|
if (budget !== 0 && (budget < spec.min || budget > spec.max)) {
|
|
50
|
-
throw new TypeError(
|
|
72
|
+
throw new TypeError(
|
|
73
|
+
`${model} (${spec.name}) thinkingBudget must be -1, ${spec.canDisable ? '0, or ' : ''}${spec.min}–${spec.max}; received ${budget}.`
|
|
74
|
+
);
|
|
51
75
|
}
|
|
52
76
|
}
|
|
53
77
|
|
|
@@ -75,7 +99,9 @@ export function geminiThinkingConfig(model, opts = {}, { includeThoughts, provid
|
|
|
75
99
|
}
|
|
76
100
|
if (spec && level) {
|
|
77
101
|
if (!Object.hasOwn(spec.efforts, level)) {
|
|
78
|
-
throw new TypeError(
|
|
102
|
+
throw new TypeError(
|
|
103
|
+
`${model} supports thinking levels ${Object.keys(spec.efforts).join(', ')}; received ${level}.`
|
|
104
|
+
);
|
|
79
105
|
}
|
|
80
106
|
config.thinkingBudget = spec.efforts[level];
|
|
81
107
|
} else if (level) {
|
|
@@ -731,8 +731,17 @@ export class GeminiProvider {
|
|
|
731
731
|
}
|
|
732
732
|
|
|
733
733
|
async _streamViaSdk(stream) {
|
|
734
|
-
const {
|
|
735
|
-
|
|
734
|
+
const {
|
|
735
|
+
opts,
|
|
736
|
+
signal,
|
|
737
|
+
useModel,
|
|
738
|
+
systemInstruction,
|
|
739
|
+
geminiTools,
|
|
740
|
+
toolConfig,
|
|
741
|
+
generationConfig,
|
|
742
|
+
safetySettings,
|
|
743
|
+
contents,
|
|
744
|
+
} = stream;
|
|
736
745
|
const genModel = this._currentGenAI().getGenerativeModel({
|
|
737
746
|
model: useModel,
|
|
738
747
|
systemInstruction,
|
|
@@ -3,7 +3,7 @@ import { createNpmVersionSource, maxSemver } from './npm-cli-version.mjs';
|
|
|
3
3
|
// Grok CLI client version for the cli-chat-proxy version gate (HTTP 426).
|
|
4
4
|
// Effective = env override, else max(floor, learned-from-426, live npm latest
|
|
5
5
|
// of the official @xai-official/grok CLI).
|
|
6
|
-
export const GROK_CLI_VERSION_FLOOR = '1.0.
|
|
6
|
+
export const GROK_CLI_VERSION_FLOOR = '1.0.62';
|
|
7
7
|
export const GROK_CLI_NPM_PACKAGE = '@xai-official/grok';
|
|
8
8
|
|
|
9
9
|
const live = createNpmVersionSource(GROK_CLI_NPM_PACKAGE, { persistKey: 'grok-cli' });
|
|
@@ -37,7 +37,9 @@ function lastEligibleBlockIndex(content) {
|
|
|
37
37
|
export function countAnthropicCacheControls(value) {
|
|
38
38
|
if (Array.isArray(value)) return value.reduce((sum, item) => sum + countAnthropicCacheControls(item), 0);
|
|
39
39
|
if (!value || typeof value !== 'object') return 0;
|
|
40
|
-
return (
|
|
40
|
+
return (
|
|
41
|
+
(value.cache_control ? 1 : 0) + (Array.isArray(value.content) ? countAnthropicCacheControls(value.content) : 0)
|
|
42
|
+
);
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
function stripCacheControl(block, budget) {
|
|
@@ -546,7 +548,12 @@ function toAnthropicTools(tools, logTag, onToolExcluded) {
|
|
|
546
548
|
// `supportsDisableParallelToolUse: false` (gateway capability).
|
|
547
549
|
export function toAnthropicToolChoice(
|
|
548
550
|
toolChoice,
|
|
549
|
-
{
|
|
551
|
+
{
|
|
552
|
+
thinking = false,
|
|
553
|
+
disableParallelToolUse = false,
|
|
554
|
+
supportsDisableParallelToolUse = true,
|
|
555
|
+
onThinkingConflict = 'fallback',
|
|
556
|
+
} = {}
|
|
550
557
|
) {
|
|
551
558
|
let choice;
|
|
552
559
|
if (toolChoice === 'none') choice = { type: 'none' };
|
|
@@ -203,7 +203,8 @@ function assertObjectRoot(schema, rule) {
|
|
|
203
203
|
function buildSchema(inputSchema) {
|
|
204
204
|
if (!isPlainObject(inputSchema)) throw new SchemaProblem('', 'the input schema must be a JSON object schema');
|
|
205
205
|
const { $schema, ...rest } = inputSchema;
|
|
206
|
-
const schema =
|
|
206
|
+
const schema =
|
|
207
|
+
dialectOf(inputSchema) === 'draft-07' ? translateDraft07(rest, '', true, DRAFT07) : structuredClone(rest);
|
|
207
208
|
assertValidDraft202012(schema);
|
|
208
209
|
assertObjectRoot(schema, 'anthropic');
|
|
209
210
|
return schema;
|
|
@@ -222,8 +223,7 @@ function repairRoot(schema) {
|
|
|
222
223
|
if (Array.isArray(type) && type.includes('object')) return { ...schema, type: 'object' };
|
|
223
224
|
if (type !== undefined || Object.hasOwn(schema, '$ref')) return schema;
|
|
224
225
|
const out = { type: 'object', ...schema };
|
|
225
|
-
if (!Object.hasOwn(out, 'properties') && !ROOT_FORBIDDEN_KEYS.some((k) => Object.hasOwn(out, k)))
|
|
226
|
-
out.properties = {};
|
|
226
|
+
if (!Object.hasOwn(out, 'properties') && !ROOT_FORBIDDEN_KEYS.some((k) => Object.hasOwn(out, k))) out.properties = {};
|
|
227
227
|
return out;
|
|
228
228
|
}
|
|
229
229
|
|
|
@@ -232,7 +232,8 @@ function refsIntoDefinitions(node) {
|
|
|
232
232
|
if (Array.isArray(node)) return node.some(refsIntoDefinitions);
|
|
233
233
|
if (!isPlainObject(node)) return false;
|
|
234
234
|
return Object.entries(node).some(
|
|
235
|
-
([key, value]) =>
|
|
235
|
+
([key, value]) =>
|
|
236
|
+
(key === '$ref' && typeof value === 'string' && /^#\/definitions(\/|$)/.test(value)) || refsIntoDefinitions(value)
|
|
236
237
|
);
|
|
237
238
|
}
|
|
238
239
|
|
|
@@ -348,7 +349,10 @@ export function claudeBridgeInputSchema(inputSchema) {
|
|
|
348
349
|
// Not valid as written: lower undeclared draft-07/04 constructs and
|
|
349
350
|
// fill the root type; only a schema still broken is excluded.
|
|
350
351
|
const repaired = repairedToolInputSchema(inputSchema, 'anthropic');
|
|
351
|
-
result =
|
|
352
|
+
result =
|
|
353
|
+
repaired && !wireProblem(repaired, 'anthropic')
|
|
354
|
+
? { schema: repaired }
|
|
355
|
+
: { pointer: error.pointer, reason: error.message };
|
|
352
356
|
}
|
|
353
357
|
if (key !== null) {
|
|
354
358
|
if (cache.size >= CACHE_LIMIT) cache.clear();
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// Shared request-body compression for provider POSTs (Anthropic gzip, Codex
|
|
2
|
+
// zstd). Policy in one place:
|
|
3
|
+
// - bodies below REQ_COMPRESSION_MIN_BYTES are never compressed (CPU + header
|
|
4
|
+
// cost outweighs the upload saving);
|
|
5
|
+
// - a request that already carries Content-Encoding is never double-encoded;
|
|
6
|
+
// - a compression failure fails open to the plain body;
|
|
7
|
+
// - a 400/415 on a compressed request is drained and the SAME request is
|
|
8
|
+
// resent once uncompressed; compression latches off process-wide only when
|
|
9
|
+
// that plain resend succeeds (the encoding was the cause). If the resend
|
|
10
|
+
// fails too, nothing latches and the resend's response is returned.
|
|
11
|
+
import { promisify } from 'node:util';
|
|
12
|
+
import { gzip } from 'node:zlib';
|
|
13
|
+
|
|
14
|
+
export const REQ_COMPRESSION_MIN_BYTES = 8 * 1024;
|
|
15
|
+
|
|
16
|
+
export function createCompressionLatch(envVar) {
|
|
17
|
+
let latched = false;
|
|
18
|
+
return {
|
|
19
|
+
disabled: () => latched || process.env[envVar] === '0',
|
|
20
|
+
latchOff: () => {
|
|
21
|
+
latched = true;
|
|
22
|
+
},
|
|
23
|
+
reset: () => {
|
|
24
|
+
latched = false;
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// One latch for every api.anthropic.com /v1/messages path (OAuth + API key).
|
|
30
|
+
export const anthropicGzipLatch = createCompressionLatch('MIXDOG_ANTHROPIC_REQ_GZIP');
|
|
31
|
+
// Compress on the libuv threadpool so large turn bodies never block the main thread.
|
|
32
|
+
export const gzipAsync = promisify(gzip);
|
|
33
|
+
|
|
34
|
+
export const hasContentEncoding = (headers) => new Headers(headers || {}).has('content-encoding');
|
|
35
|
+
|
|
36
|
+
export function withContentEncoding(headers, encoding) {
|
|
37
|
+
if (headers instanceof Headers || Array.isArray(headers)) {
|
|
38
|
+
const next = new Headers(headers);
|
|
39
|
+
next.delete('content-length');
|
|
40
|
+
next.set('Content-Encoding', encoding);
|
|
41
|
+
return next;
|
|
42
|
+
}
|
|
43
|
+
const rest = Object.fromEntries(
|
|
44
|
+
Object.entries(headers || {}).filter(([name]) => name.toLowerCase() !== 'content-length')
|
|
45
|
+
);
|
|
46
|
+
return { ...rest, 'Content-Encoding': encoding };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Fail open: any compression error yields the plain body.
|
|
50
|
+
export async function compressBody(raw, compress, encoding) {
|
|
51
|
+
try {
|
|
52
|
+
return { bytes: await compress(raw), encoding };
|
|
53
|
+
} catch {
|
|
54
|
+
return { bytes: raw, encoding: null };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const isEncodingRejection = (response) => response.status === 400 || response.status === 415;
|
|
59
|
+
|
|
60
|
+
export async function resendIfEncodingRejected({ response, encoded, resend, latch }) {
|
|
61
|
+
if (!encoded || !isEncodingRejection(response)) return response;
|
|
62
|
+
try {
|
|
63
|
+
await response.arrayBuffer();
|
|
64
|
+
} catch {
|
|
65
|
+
/* drain best-effort */
|
|
66
|
+
}
|
|
67
|
+
const retry = await resend();
|
|
68
|
+
if (retry.ok) latch.latchOff();
|
|
69
|
+
return retry;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Send `raw` compressed when eligible, with the rejection resend above.
|
|
74
|
+
* `send(bytes, headers)` performs one HTTP request.
|
|
75
|
+
*/
|
|
76
|
+
export async function sendWithCompression({ raw, headers, encoding, compress, latch, send }) {
|
|
77
|
+
const plain = () => send(raw, headers);
|
|
78
|
+
if (latch.disabled() || raw.length < REQ_COMPRESSION_MIN_BYTES || hasContentEncoding(headers)) return plain();
|
|
79
|
+
const packed = await compressBody(raw, compress, encoding);
|
|
80
|
+
if (!packed.encoding) return plain();
|
|
81
|
+
const response = await send(packed.bytes, withContentEncoding(headers, encoding));
|
|
82
|
+
return resendIfEncodingRejected({ response, encoded: true, resend: plain, latch });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export const sendGzipCompressed = ({ compress = gzipAsync, ...rest }) =>
|
|
86
|
+
sendWithCompression({ ...rest, encoding: 'gzip', compress, latch: anthropicGzipLatch });
|
|
@@ -29,8 +29,10 @@ function isObject(value) {
|
|
|
29
29
|
// answered by the server inside the same response. It is never a client call
|
|
30
30
|
// awaiting a client output, so the guard neither pairs nor synthesizes it.
|
|
31
31
|
function isServerToolSearch(item) {
|
|
32
|
-
return (
|
|
33
|
-
(item.
|
|
32
|
+
return (
|
|
33
|
+
(item.type === 'tool_search_call' || item.type === 'tool_search_output') &&
|
|
34
|
+
(item.execution === 'server' || item.call_id === null)
|
|
35
|
+
);
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
function responsesCallId(item) {
|
|
@@ -167,7 +167,11 @@ function officeTextForFile(file) {
|
|
|
167
167
|
});
|
|
168
168
|
if (file.ref) return memoized(officeTextMemo, `ref:${file.ref}\0${file.filename || ''}`, compute);
|
|
169
169
|
if (file.part && inlineOfficeText.has(file.part)) return inlineOfficeText.get(file.part);
|
|
170
|
-
const key = createHash('sha256')
|
|
170
|
+
const key = createHash('sha256')
|
|
171
|
+
.update(file.filename || '')
|
|
172
|
+
.update('\0')
|
|
173
|
+
.update(file.data)
|
|
174
|
+
.digest('hex');
|
|
171
175
|
const text = memoized(officeTextMemo, key, compute);
|
|
172
176
|
if (file.part) inlineOfficeText.set(file.part, text);
|
|
173
177
|
return text;
|
|
@@ -403,15 +407,19 @@ export async function preparePdfTextForProvider(messages, provider) {
|
|
|
403
407
|
continue;
|
|
404
408
|
}
|
|
405
409
|
if (file && fileKind(file) === 'pdf') found.push({ part, file });
|
|
406
|
-
else if (noDocuments && (file || part.type === 'document'))
|
|
410
|
+
else if (noDocuments && (file || part.type === 'document'))
|
|
411
|
+
texts.set(part, file ? textFormOfFilePart(part) : documentSourceText(part));
|
|
407
412
|
}
|
|
408
413
|
}
|
|
409
414
|
if (!found.length && !texts.size) return messages;
|
|
410
415
|
const extracted = await Promise.all(found.map(({ file }) => pdfTextFor(file)));
|
|
411
|
-
found.forEach(({ part, file }, i) =>
|
|
416
|
+
found.forEach(({ part, file }, i) => {
|
|
417
|
+
texts.set(part, `--- ${fileLabel(file)} ---\n${extracted[i]}`);
|
|
418
|
+
});
|
|
412
419
|
return messages.map((message) => {
|
|
413
420
|
// A message whose content is one bare part becomes a one-part array.
|
|
414
|
-
if (texts.has(message?.content))
|
|
421
|
+
if (texts.has(message?.content))
|
|
422
|
+
return { ...message, content: [{ type: 'text', text: texts.get(message.content) }] };
|
|
415
423
|
const content = replacePdfParts(message?.content, texts);
|
|
416
424
|
return content === message?.content ? message : { ...message, content };
|
|
417
425
|
});
|
|
@@ -681,7 +689,10 @@ export function contentMediaBytes(content, { nativePdf = true } = {}) {
|
|
|
681
689
|
if (!part || typeof part !== 'object') continue;
|
|
682
690
|
if (isAttachmentReference(part)) {
|
|
683
691
|
if (part.type === 'image') bytes += Math.ceil((Number(part.sizeBytes) || 0) / 3) * 4;
|
|
684
|
-
else if (
|
|
692
|
+
else if (
|
|
693
|
+
part.type === 'file' &&
|
|
694
|
+
countsAsMedia(String(part.mimeType || part.mediaType || 'application/pdf'), '')
|
|
695
|
+
) {
|
|
685
696
|
bytes += Math.ceil((Number(part.sizeBytes) || 0) / 3) * 4;
|
|
686
697
|
}
|
|
687
698
|
continue;
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { noteErrorUsage } from './lib/note-error-usage.mjs';
|
|
10
10
|
import { fileMtimeMs, scrubOAuthSecrets } from './lib/oauth-token-utils.mjs';
|
|
11
11
|
import { OpenAICompatProvider, preloadOpenAICompatRuntime } from './openai-compat.mjs';
|
|
12
|
-
import { COMPAT_RETRY_POLICY } from './openai-compat-retry-profile.mjs';
|
|
12
|
+
import { COMPAT_RETRY_POLICY, compatFirstResponseBudget } from './openai-compat-retry-profile.mjs';
|
|
13
13
|
import { fetchCompatModelItems, listCompatModels } from './openai-compat-models.mjs';
|
|
14
14
|
import { makeModelCache } from './model-cache.mjs';
|
|
15
15
|
import {
|
|
@@ -152,6 +152,12 @@ export class MimoOAuthProvider {
|
|
|
152
152
|
return this.tokens;
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
// The inner client's chat profile sets a longer first-byte window; the
|
|
156
|
+
// budget needs no credentials, so it is read from the profile directly.
|
|
157
|
+
firstResponseBudget() {
|
|
158
|
+
return compatFirstResponseBudget(this.name, MIMO_CHAT_PROFILE);
|
|
159
|
+
}
|
|
160
|
+
|
|
155
161
|
_ensureInner() {
|
|
156
162
|
const { apiKey, baseUrl } = this.ensureAuth();
|
|
157
163
|
const key = `${baseUrl}:${apiKey}`;
|
|
@@ -90,6 +90,15 @@ export function inlineModelProxyAttachments(messages, { maxBytes = MODEL_PROXY_I
|
|
|
90
90
|
return out ?? messages;
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
/** A first-response budget the PC reported, or null for anything malformed. */
|
|
94
|
+
function reportedBudget(value) {
|
|
95
|
+
const transportMs = Number(value?.transportMs);
|
|
96
|
+
const semanticMs = Number(value?.semanticMs);
|
|
97
|
+
return transportMs > 0 && semanticMs > 0 && Number.isFinite(transportMs) && Number.isFinite(semanticMs)
|
|
98
|
+
? { transportMs, semanticMs }
|
|
99
|
+
: null;
|
|
100
|
+
}
|
|
101
|
+
|
|
93
102
|
export class ModelProxyProvider {
|
|
94
103
|
#channel;
|
|
95
104
|
#modelInfo = new Map();
|
|
@@ -101,6 +110,7 @@ export class ModelProxyProvider {
|
|
|
101
110
|
this.#channel = channel;
|
|
102
111
|
// Adapter traits are reported by the PC's real instance.
|
|
103
112
|
if (typeof this.config.modelProxy?.nativePdf === 'boolean') this.nativePdf = this.config.modelProxy.nativePdf;
|
|
113
|
+
if (this.config.modelProxy?.consumesReadWindows === true) this.consumesReadWindows = true;
|
|
104
114
|
}
|
|
105
115
|
|
|
106
116
|
#call(method, fields = {}, options = {}) {
|
|
@@ -110,18 +120,16 @@ export class ModelProxyProvider {
|
|
|
110
120
|
async send(messages, model, tools, sendOpts) {
|
|
111
121
|
const { options, callbacks } = splitModelProxySendOptions(sendOpts);
|
|
112
122
|
const finalized = isFinalizedProviderRequestTools(tools);
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
{ signal: sendOpts?.signal || null, callbacks }
|
|
124
|
-
);
|
|
123
|
+
const fields = {
|
|
124
|
+
model: model ?? null,
|
|
125
|
+
messages: inlineModelProxyAttachments(messages),
|
|
126
|
+
tools: Array.isArray(tools) ? tools : null,
|
|
127
|
+
toolsFinalized: finalized,
|
|
128
|
+
nativePrefixCount: finalized ? providerNativeToolPrefixCount(tools) : 0,
|
|
129
|
+
options,
|
|
130
|
+
};
|
|
131
|
+
const signal = sendOpts?.signal || null;
|
|
132
|
+
const result = await this.#call('send', fields, { signal, callbacks });
|
|
125
133
|
// The PC rerouted the wire (a clear "unsupported" refusal) and reports the
|
|
126
134
|
// route it used: the daemon's own session adopts it, so the next proxied
|
|
127
135
|
// turn starts on the new wire instead of repeating the refusal.
|
|
@@ -163,6 +171,16 @@ export class ModelProxyProvider {
|
|
|
163
171
|
return this.#modelInfo.get(String(model ?? '')) ?? null;
|
|
164
172
|
}
|
|
165
173
|
|
|
174
|
+
/** The PC adapter's first-response budget for `model`: the catalog's
|
|
175
|
+
* model-specific figure, else the adapter's own from its provider config;
|
|
176
|
+
* null keeps the agent watchdog default. */
|
|
177
|
+
firstResponseBudget(model) {
|
|
178
|
+
return (
|
|
179
|
+
reportedBudget(this.getCachedModelInfo(model)?.firstResponseBudget) ??
|
|
180
|
+
reportedBudget(this.config.modelProxy?.firstResponseBudget)
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
166
184
|
/** The PC adapter's wire route for `model` (its config and roster decide);
|
|
167
185
|
* null for a single-wire adapter, which is remembered so every later turn
|
|
168
186
|
* skips the round trip. */
|
|
@@ -222,10 +240,12 @@ export function loadModelProxyProviderConfig({
|
|
|
222
240
|
channel = getModelProxyChannel(),
|
|
223
241
|
now = Date.now,
|
|
224
242
|
waitMs = MODEL_PROXY_CONFIG_WAIT_MS,
|
|
243
|
+
force = false,
|
|
225
244
|
} = {}) {
|
|
226
245
|
const generation = channel.generation;
|
|
227
246
|
const cached = _providerConfigCache;
|
|
228
247
|
if (
|
|
248
|
+
!force &&
|
|
229
249
|
cached &&
|
|
230
250
|
cached.channel === channel &&
|
|
231
251
|
cached.generation === generation &&
|
|
@@ -234,7 +254,16 @@ export function loadModelProxyProviderConfig({
|
|
|
234
254
|
return Promise.resolve(cached.value);
|
|
235
255
|
}
|
|
236
256
|
const inFlight = _providerConfigInFlight;
|
|
237
|
-
|
|
257
|
+
// A forced read starts after the caller's change, never reuses an older
|
|
258
|
+
// snapshot. Short setup reads also cannot inherit a registry init's budget.
|
|
259
|
+
if (
|
|
260
|
+
!force &&
|
|
261
|
+
inFlight &&
|
|
262
|
+
inFlight.channel === channel &&
|
|
263
|
+
inFlight.generation === generation &&
|
|
264
|
+
inFlight.waitMs === waitMs
|
|
265
|
+
)
|
|
266
|
+
return inFlight.promise;
|
|
238
267
|
const promise = (async () => {
|
|
239
268
|
const deadline = Date.now() + waitMs;
|
|
240
269
|
let delay = CONFIG_RETRY_FIRST_MS;
|
|
@@ -247,12 +276,27 @@ export function loadModelProxyProviderConfig({
|
|
|
247
276
|
}
|
|
248
277
|
}
|
|
249
278
|
try {
|
|
250
|
-
const
|
|
279
|
+
const remaining = deadline - Date.now();
|
|
280
|
+
if (remaining <= 0) throw new ModelProxyUnavailableError('the desktop provider request timed out');
|
|
281
|
+
const controller = new AbortController();
|
|
282
|
+
const timer = setTimeout(
|
|
283
|
+
() => controller.abort(new ModelProxyUnavailableError('the desktop provider request timed out')),
|
|
284
|
+
remaining
|
|
285
|
+
);
|
|
286
|
+
timer.unref?.();
|
|
287
|
+
let reply;
|
|
288
|
+
try {
|
|
289
|
+
reply = await channel.request({ provider: '', method: 'providerConfig' }, { signal: controller.signal });
|
|
290
|
+
} finally {
|
|
291
|
+
clearTimeout(timer);
|
|
292
|
+
}
|
|
251
293
|
const raw = reply?.providers && typeof reply.providers === 'object' ? reply.providers : {};
|
|
252
294
|
// Defense in depth: the PC already strips secrets before sending.
|
|
253
295
|
const value = stripModelProxySecrets(raw);
|
|
254
296
|
if (providerConfigReady(reply, value)) {
|
|
255
|
-
|
|
297
|
+
// An older read may finish after a forced refresh; only the newest
|
|
298
|
+
// request may publish to the shared cache.
|
|
299
|
+
if (channel.generation === generation && _providerConfigInFlight === entry) {
|
|
256
300
|
_providerConfigCache = { at: now(), value, channel, generation };
|
|
257
301
|
}
|
|
258
302
|
return value;
|
|
@@ -268,7 +312,7 @@ export function loadModelProxyProviderConfig({
|
|
|
268
312
|
delay = Math.min(delay * 2, CONFIG_RETRY_MAX_MS);
|
|
269
313
|
}
|
|
270
314
|
})();
|
|
271
|
-
const entry = { channel, generation, promise };
|
|
315
|
+
const entry = { channel, generation, waitMs, promise };
|
|
272
316
|
_providerConfigInFlight = entry;
|
|
273
317
|
const clear = () => {
|
|
274
318
|
if (_providerConfigInFlight === entry) _providerConfigInFlight = null;
|
|
@@ -56,11 +56,6 @@ function resolveProbeState(paths, evaluate) {
|
|
|
56
56
|
return sawUnreadable ? 'unreadable' : 'absent';
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
function pushUnique(list, value) {
|
|
60
|
-
if (!value || typeof value !== 'string') return;
|
|
61
|
-
if (!list.includes(value)) list.push(value);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
59
|
// Short-TTL memo. Under simultaneous multi-agent launch, buildDefaultConfig
|
|
65
60
|
// and registry lazy-init call these probes in bursts; each probe does
|
|
66
61
|
// synchronous existsSync + readFileSync disk work. Cache the STATE per key
|
|
@@ -113,9 +108,11 @@ function memoProbe(key, paths, compute, extraSignature = '') {
|
|
|
113
108
|
}
|
|
114
109
|
|
|
115
110
|
function anthropicOAuthState() {
|
|
116
|
-
const paths = [
|
|
117
|
-
|
|
118
|
-
|
|
111
|
+
const paths = [
|
|
112
|
+
boundProviderAuthPath('anthropic-oauth') ||
|
|
113
|
+
process.env.ANTHROPIC_OAUTH_CREDENTIALS_PATH ||
|
|
114
|
+
ANTHROPIC_DEFAULT_CREDENTIALS_PATH,
|
|
115
|
+
];
|
|
119
116
|
return memoProbe('anthropic-oauth', paths, () => {
|
|
120
117
|
return resolveProbeState(paths, (docs) => {
|
|
121
118
|
const candidates = [];
|
|
@@ -176,9 +173,7 @@ function mimoOAuthState() {
|
|
|
176
173
|
process.env.MIMO_OAUTH_CREDENTIALS_PATH ||
|
|
177
174
|
join(resolvePluginData(), 'mimo-oauth.json'),
|
|
178
175
|
];
|
|
179
|
-
return memoProbe('mimo-oauth', paths, () =>
|
|
180
|
-
resolveProbeState(paths, (docs) => docs.some((own) => !!own?.apiKey))
|
|
181
|
-
);
|
|
176
|
+
return memoProbe('mimo-oauth', paths, () => resolveProbeState(paths, (docs) => docs.some((own) => !!own?.apiKey)));
|
|
182
177
|
}
|
|
183
178
|
|
|
184
179
|
function commandCodeOAuthState() {
|
|
@@ -230,7 +225,10 @@ function cursorEnvTokenFingerprint() {
|
|
|
230
225
|
}
|
|
231
226
|
|
|
232
227
|
function cursorOAuthState() {
|
|
233
|
-
|
|
228
|
+
// Match the adapter: selected account, then explicit path, then legacy file.
|
|
229
|
+
// An environment token must not authenticate a different selected account.
|
|
230
|
+
const bound = boundProviderAuthPath('cursor-oauth');
|
|
231
|
+
const paths = [bound || process.env.CURSOR_OAUTH_CREDENTIALS_PATH || join(resolvePluginData(), 'cursor-oauth.json')];
|
|
234
232
|
// The env token is the whole answer on this branch and has no file metadata
|
|
235
233
|
// behind it, so its VALUE is what the memo signature has to track: a length
|
|
236
234
|
// (or a bare present/absent flag) let a swap to an equal-length expired token
|
|
@@ -245,7 +243,7 @@ function cursorOAuthState() {
|
|
|
245
243
|
// Expiry is read by the one shared JWT reader (cursor-auth.cursorTokenExpiry),
|
|
246
244
|
// which answers 0 for a non-JWT or unparseable token — exactly the "assume
|
|
247
245
|
// usable" outcome this branch already took for those shapes.
|
|
248
|
-
if (process.env.CURSOR_ACCESS_TOKEN) {
|
|
246
|
+
if (process.env.CURSOR_ACCESS_TOKEN && !bound) {
|
|
249
247
|
const expiresAt = cursorTokenExpiry(process.env.CURSOR_ACCESS_TOKEN);
|
|
250
248
|
return expiresAt === 0 || expiresAt > Date.now() ? 'present' : 'absent';
|
|
251
249
|
}
|