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
|
@@ -61,7 +61,13 @@ function toolResultEntry(message, text, toolNames) {
|
|
|
61
61
|
const isError = message.mixdog_tool_error === true;
|
|
62
62
|
const toolName = toolNames.get(toolCallId) || '';
|
|
63
63
|
return {
|
|
64
|
-
toolResult: {
|
|
64
|
+
toolResult: {
|
|
65
|
+
toolCallId,
|
|
66
|
+
content: text,
|
|
67
|
+
media,
|
|
68
|
+
isError,
|
|
69
|
+
...(message.mixdog_read_window?.lineClipped === true ? { readWindow: { lineClipped: true } } : {}),
|
|
70
|
+
},
|
|
65
71
|
entry: {
|
|
66
72
|
role: 'tool',
|
|
67
73
|
id: toolCallId,
|
|
@@ -170,9 +176,7 @@ export function buildRequestContext(tools, cloudRule) {
|
|
|
170
176
|
{
|
|
171
177
|
serverName: 'mixdog',
|
|
172
178
|
instructions:
|
|
173
|
-
'
|
|
174
|
-
'Follow their descriptions and input schemas. Prefer them over Cursor native tools; ' +
|
|
175
|
-
'native tools do not directly access the Mixdog environment. ' +
|
|
179
|
+
'Do not use Cursor native tools; use only the tools provided by the mixdog MCP server, following their descriptions and declared input schemas. ' +
|
|
176
180
|
'If a needed tool is not available, use the provided tool discovery mechanism rather than inventing a tool.',
|
|
177
181
|
},
|
|
178
182
|
]
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* close verdict and the bounded in-place restart.
|
|
5
5
|
*/
|
|
6
6
|
import {
|
|
7
|
+
MAX_CONNECT_FRAME_BYTES,
|
|
7
8
|
isCursorAuthError,
|
|
8
9
|
isCursorThrottleError,
|
|
9
10
|
isRetryableCursorStreamError,
|
|
@@ -13,6 +14,10 @@ import { emitProviderRetryStage, markProviderRecoveryExhausted, retryAfterMsFrom
|
|
|
13
14
|
import { createFrameParser, cursorError, parseEndStream } from './cursor-wire-transport.mjs';
|
|
14
15
|
import { processServerMessage } from './cursor-wire-stream-messages.mjs';
|
|
15
16
|
|
|
17
|
+
// A parked HTTP/2 run can still receive parallel execs. Keep their raw chunks
|
|
18
|
+
// with the transport until the next SSE consumer attaches.
|
|
19
|
+
const parkedInputs = new WeakMap();
|
|
20
|
+
|
|
16
21
|
// Resolves after `ms`, or early when the stream is cancelled.
|
|
17
22
|
function abortableSleep(ms, signal) {
|
|
18
23
|
return new Promise((resolve) => {
|
|
@@ -51,7 +56,9 @@ export function createBridgeController(ctx) {
|
|
|
51
56
|
modelParameters: run.modelParameters,
|
|
52
57
|
maxMode: run.maxMode,
|
|
53
58
|
sessionId: run.sessionId,
|
|
59
|
+
ownerSessionId: run.ownerSessionId,
|
|
54
60
|
pending: state.pending,
|
|
61
|
+
executions: state.executions,
|
|
55
62
|
sawTurnEnded: state.sawTurnEnded,
|
|
56
63
|
});
|
|
57
64
|
sink.finish('tool_calls');
|
|
@@ -80,13 +87,11 @@ export function createBridgeController(ctx) {
|
|
|
80
87
|
const serverDelay = retryAfterMsFromError(error);
|
|
81
88
|
// Server advice is honored in full for every retryable kind; local
|
|
82
89
|
// backoff applies only when the server gave none.
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
: backoffMs(throttled ? throttleCount + 1 : retryCount + 1);
|
|
90
|
+
const backoffAttempt = (throttled ? throttleCount : retryCount) + 1;
|
|
91
|
+
const delayMs = Number.isFinite(serverDelay) ? serverDelay : backoffMs(backoffAttempt);
|
|
86
92
|
const throttleOk = throttled && throttleCount < tuning.maxThrottleRetries;
|
|
87
93
|
const authOk = authFailure && authCount < tuning.maxAuthRetries;
|
|
88
|
-
const canRetry =
|
|
89
|
-
retryCount < tuning.maxRetries && recoveryEligible && (retryable || throttleOk || authOk);
|
|
94
|
+
const canRetry = retryCount < tuning.maxRetries && recoveryEligible && (retryable || throttleOk || authOk);
|
|
90
95
|
if (!canRetry) {
|
|
91
96
|
// A fresh Cursor run owns its bounded in-place retries. Mark
|
|
92
97
|
// exhaustion so the outer loop does not multiply that budget.
|
|
@@ -96,8 +101,7 @@ export function createBridgeController(ctx) {
|
|
|
96
101
|
// A throttle that spent its bounded retries is final for the turn too.
|
|
97
102
|
if (
|
|
98
103
|
recoveryEligible &&
|
|
99
|
-
((retryable && retryCount >= tuning.maxRetries) ||
|
|
100
|
-
(throttled && throttleCount >= tuning.maxThrottleRetries))
|
|
104
|
+
((retryable && retryCount >= tuning.maxRetries) || (throttled && throttleCount >= tuning.maxThrottleRetries))
|
|
101
105
|
) {
|
|
102
106
|
markProviderRecoveryExhausted(error, { owner: 'cursor-wire', attempts: retryCount + 1 });
|
|
103
107
|
}
|
|
@@ -118,6 +122,9 @@ export function createBridgeController(ctx) {
|
|
|
118
122
|
lastErr: error,
|
|
119
123
|
delayMs,
|
|
120
124
|
});
|
|
125
|
+
let restartReason = 'transient';
|
|
126
|
+
if (throttled) restartReason = 'throttle';
|
|
127
|
+
else if (authFailure) restartReason = 'auth';
|
|
121
128
|
void sleep(delayMs, cancelSignal).then(async () => {
|
|
122
129
|
if (isCancelled() || state.closed) return;
|
|
123
130
|
try {
|
|
@@ -126,7 +133,7 @@ export function createBridgeController(ctx) {
|
|
|
126
133
|
attempt: retryCount,
|
|
127
134
|
fromCheckpoint: !throttled && Boolean(run.conversation.checkpoint),
|
|
128
135
|
visibleOutput: state.visibleOutput,
|
|
129
|
-
reason:
|
|
136
|
+
reason: restartReason,
|
|
130
137
|
error,
|
|
131
138
|
});
|
|
132
139
|
if (isCancelled() || state.closed) {
|
|
@@ -200,6 +207,11 @@ export function createBridgeController(ctx) {
|
|
|
200
207
|
const attach = (ownedBridge, nextHeartbeat) => {
|
|
201
208
|
live.bridge = ownedBridge;
|
|
202
209
|
live.heartbeat = nextHeartbeat;
|
|
210
|
+
let inbox = parkedInputs.get(ownedBridge);
|
|
211
|
+
if (!inbox) {
|
|
212
|
+
inbox = { chunks: [], bytes: 0 };
|
|
213
|
+
parkedInputs.set(ownedBridge, inbox);
|
|
214
|
+
}
|
|
203
215
|
const messageCtx = {
|
|
204
216
|
state,
|
|
205
217
|
filter,
|
|
@@ -208,14 +220,26 @@ export function createBridgeController(ctx) {
|
|
|
208
220
|
tools: run.tools,
|
|
209
221
|
cloudRule: run.cloudRule,
|
|
210
222
|
sessionId: run.sessionId,
|
|
223
|
+
ownerSessionId: run.ownerSessionId,
|
|
211
224
|
};
|
|
212
225
|
const frameParser = createFrameParser(
|
|
213
226
|
// Server requests answer on whichever bridge is live when they arrive.
|
|
214
227
|
(bytes) => watchdog.progress(processServerMessage(bytes, { ...messageCtx, bridge: live.bridge })),
|
|
215
228
|
(bytes) => onEndStream(ownedBridge, bytes)
|
|
216
229
|
);
|
|
217
|
-
|
|
218
|
-
if (live.bridge !== ownedBridge ||
|
|
230
|
+
const receive = (chunk) => {
|
|
231
|
+
if (live.bridge !== ownedBridge || isCancelled()) return;
|
|
232
|
+
if (state.closed) {
|
|
233
|
+
if (inbox.bytes + chunk.byteLength > MAX_CONNECT_FRAME_BYTES) {
|
|
234
|
+
ownedBridge.close(
|
|
235
|
+
cursorError('Cursor parked input exceeds the buffer limit', { code: 'stream_buffer_limit' })
|
|
236
|
+
);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
inbox.chunks.push(chunk);
|
|
240
|
+
inbox.bytes += chunk.byteLength;
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
219
243
|
state.chunkSeq += 1;
|
|
220
244
|
try {
|
|
221
245
|
frameParser(chunk);
|
|
@@ -227,9 +251,15 @@ export function createBridgeController(ctx) {
|
|
|
227
251
|
} catch (error) {
|
|
228
252
|
ownedBridge.close(error);
|
|
229
253
|
}
|
|
230
|
-
}
|
|
254
|
+
};
|
|
255
|
+
ownedBridge.onData(receive);
|
|
231
256
|
ownedBridge.onClose((error) => onBridgeClose(ownedBridge, nextHeartbeat, frameParser, error));
|
|
232
257
|
watchdog.start();
|
|
258
|
+
while (!state.closed && !isCancelled() && inbox.chunks.length) {
|
|
259
|
+
const chunk = inbox.chunks.shift();
|
|
260
|
+
inbox.bytes -= chunk.byteLength;
|
|
261
|
+
receive(chunk);
|
|
262
|
+
}
|
|
233
263
|
};
|
|
234
264
|
|
|
235
265
|
return { attach };
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
* to the shared stream state and relayed to the SSE sink. Returns the
|
|
4
4
|
* message's forward-progress kind for the watchdog.
|
|
5
5
|
*/
|
|
6
|
+
import { randomUUID } from 'node:crypto';
|
|
7
|
+
import { registerCursorNativeCall } from './cursor-native-context.mjs';
|
|
6
8
|
import { appendAgentTrace } from '../agent-trace.mjs';
|
|
7
9
|
import { decodeMessage } from './cursor-wire-protobuf.mjs';
|
|
8
10
|
import { MAX_CHECKPOINT_BYTES, cursorInteractionProgress } from './cursor-wire-guards.mjs';
|
|
9
11
|
import { buildCursorInteractionResponse } from './cursor-wire-interactions.mjs';
|
|
10
12
|
import { cursorError } from './cursor-wire-transport.mjs';
|
|
11
|
-
import { handleExecMessage, handleKvMessage, sendClientMessage } from './cursor-wire-exec.mjs';
|
|
13
|
+
import { handleExecMessage, handleKvMessage, sendClientMessage, sendToolResult } from './cursor-wire-exec.mjs';
|
|
12
14
|
|
|
13
15
|
// Unknown fields seen on every live frame: AgentServerMessage field 8 (timing
|
|
14
16
|
// doubles) and InteractionUpdate field 25 (epoch-ms timestamp). Never traced.
|
|
@@ -43,6 +45,31 @@ function traceUnknownFields(trace, sessionId, scope, unknown, noise) {
|
|
|
43
45
|
}
|
|
44
46
|
}
|
|
45
47
|
|
|
48
|
+
// Parent edit outcomes are diagnostics, not executable calls or read results.
|
|
49
|
+
function traceNativeEditFailure(trace, sessionId, update) {
|
|
50
|
+
const completed = update.toolCallCompleted;
|
|
51
|
+
const result = completed?.toolCall?.editToolCall?.result;
|
|
52
|
+
if (!result) return;
|
|
53
|
+
const outcome = ['fileNotFound', 'readPermissionDenied', 'writePermissionDenied', 'rejected', 'error'].find(
|
|
54
|
+
(key) => result[key] !== undefined
|
|
55
|
+
);
|
|
56
|
+
if (!outcome) return;
|
|
57
|
+
try {
|
|
58
|
+
trace({
|
|
59
|
+
sessionId,
|
|
60
|
+
kind: 'cursor_native_edit_failure',
|
|
61
|
+
provider: 'cursor',
|
|
62
|
+
payload: {
|
|
63
|
+
callId: (completed.callId || '').slice(0, 256),
|
|
64
|
+
modelCallId: (completed.modelCallId || '').slice(0, 256),
|
|
65
|
+
outcome,
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
} catch {
|
|
69
|
+
/* best-effort */
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
46
73
|
// Relays one interaction update to the SSE stream and returns its progress.
|
|
47
74
|
function applyInteractionUpdate(update, state, filter, emit) {
|
|
48
75
|
if (update.textDelta?.text) {
|
|
@@ -79,9 +106,32 @@ function applyCheckpointUpdate(update, conversation, state) {
|
|
|
79
106
|
}
|
|
80
107
|
|
|
81
108
|
// Announces a newly pending native/MCP tool call as a completion chunk once.
|
|
82
|
-
function announcePendingToolCall(state, pending, emit) {
|
|
83
|
-
|
|
109
|
+
function announcePendingToolCall(state, pending, emit, bridge, ownerSessionId) {
|
|
110
|
+
state.executions ??= new Map();
|
|
111
|
+
const executions = state.executions;
|
|
112
|
+
const execId = pending.exec.execId ?? pending.exec.id;
|
|
113
|
+
const previous = execId !== undefined ? executions.get(execId) : undefined;
|
|
114
|
+
if (previous) {
|
|
115
|
+
if (previous.completedResult) {
|
|
116
|
+
sendToolResult(
|
|
117
|
+
bridge,
|
|
118
|
+
{ ...previous, exec: pending.exec },
|
|
119
|
+
previous.completedResult.result,
|
|
120
|
+
previous.completedResult.ok
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
// A parent call can issue distinct executions; each needs its own local result.
|
|
126
|
+
if ([...executions.values(), ...state.pending].some((entry) => entry.toolCallId === pending.toolCallId)) {
|
|
127
|
+
pending.toolCallId = randomUUID();
|
|
128
|
+
}
|
|
129
|
+
if (execId !== undefined) executions.set(execId, pending);
|
|
130
|
+
registerCursorNativeCall(ownerSessionId, pending, executions);
|
|
84
131
|
state.pending.push(pending);
|
|
132
|
+
// Native execs may await their result before the server completes a step.
|
|
133
|
+
// The bridge hands off only after all currently received frames are whole.
|
|
134
|
+
if (pending.native) state.batchBoundaryReady = true;
|
|
85
135
|
emit({
|
|
86
136
|
tool_calls: [
|
|
87
137
|
{
|
|
@@ -101,12 +151,24 @@ function announcePendingToolCall(state, pending, emit) {
|
|
|
101
151
|
*/
|
|
102
152
|
export function processServerMessage(
|
|
103
153
|
bytes,
|
|
104
|
-
{
|
|
154
|
+
{
|
|
155
|
+
state,
|
|
156
|
+
filter,
|
|
157
|
+
emit,
|
|
158
|
+
conversation,
|
|
159
|
+
tools,
|
|
160
|
+
cloudRule,
|
|
161
|
+
bridge,
|
|
162
|
+
sessionId = '',
|
|
163
|
+
ownerSessionId = '',
|
|
164
|
+
trace = appendAgentTrace,
|
|
165
|
+
}
|
|
105
166
|
) {
|
|
106
167
|
const message = decodeMessage('AgentServerMessage', bytes);
|
|
107
168
|
traceUnknownFields(trace, sessionId, 'agent_server_message', message.$unknown, NOISE_SERVER_FIELDS);
|
|
108
169
|
if (message.interactionUpdate) {
|
|
109
170
|
traceUnknownFields(trace, sessionId, 'interaction_update', message.interactionUpdate.$unknown, NOISE_UPDATE_FIELDS);
|
|
171
|
+
traceNativeEditFailure(trace, sessionId, message.interactionUpdate);
|
|
110
172
|
}
|
|
111
173
|
if (message.interactionUpdate) return applyInteractionUpdate(message.interactionUpdate, state, filter, emit);
|
|
112
174
|
if (message.kvServerMessage) {
|
|
@@ -119,7 +181,7 @@ export function processServerMessage(
|
|
|
119
181
|
}
|
|
120
182
|
if (message.execServerMessage) {
|
|
121
183
|
const handled = handleExecMessage(bridge, message.execServerMessage, tools, cloudRule, (pending) =>
|
|
122
|
-
announcePendingToolCall(state, pending, emit)
|
|
184
|
+
announcePendingToolCall(state, pending, emit, bridge, ownerSessionId)
|
|
123
185
|
);
|
|
124
186
|
return handled === false ? 'park' : 'work';
|
|
125
187
|
}
|
|
@@ -328,11 +328,12 @@ function createPendingToolBatchResponse(active, model, key) {
|
|
|
328
328
|
}
|
|
329
329
|
|
|
330
330
|
// Stream state shared by the sink, the message router and the bridge controller.
|
|
331
|
-
function freshStreamState(sawTurnEnded) {
|
|
331
|
+
function freshStreamState(sawTurnEnded, executions) {
|
|
332
332
|
return {
|
|
333
333
|
outputTokens: 0,
|
|
334
334
|
contextTokens: null,
|
|
335
335
|
pending: [],
|
|
336
|
+
executions,
|
|
336
337
|
closed: false,
|
|
337
338
|
sawEnd: false,
|
|
338
339
|
sawTurnEnded: sawTurnEnded === true,
|
|
@@ -360,7 +361,9 @@ function createStreamResponse({
|
|
|
360
361
|
// Owning session, carried into the stored run so a session close can find
|
|
361
362
|
// and tear down the pending batch's bridge/heartbeat.
|
|
362
363
|
sessionId = '',
|
|
364
|
+
ownerSessionId = sessionId,
|
|
363
365
|
sawTurnEnded = false,
|
|
366
|
+
executions = new Map(),
|
|
364
367
|
restart = null,
|
|
365
368
|
sleep = undefined,
|
|
366
369
|
onStageChange = null,
|
|
@@ -376,7 +379,7 @@ function createStreamResponse({
|
|
|
376
379
|
const stream = new ReadableStream({
|
|
377
380
|
start(controller) {
|
|
378
381
|
const filter = thinkingFilter();
|
|
379
|
-
const state = freshStreamState(sawTurnEnded);
|
|
382
|
+
const state = freshStreamState(sawTurnEnded, executions);
|
|
380
383
|
const tuning = resolveCursorStreamTuning();
|
|
381
384
|
watchdog = createCursorStreamWatchdog({
|
|
382
385
|
idleTimeoutMs: tuning.idleTimeoutMs,
|
|
@@ -400,7 +403,7 @@ function createStreamResponse({
|
|
|
400
403
|
watchdog,
|
|
401
404
|
sink,
|
|
402
405
|
tuning,
|
|
403
|
-
run: { key, conversation, tools, cloudRule, modelParameters, maxMode, sessionId },
|
|
406
|
+
run: { key, conversation, tools, cloudRule, modelParameters, maxMode, sessionId, ownerSessionId },
|
|
404
407
|
runs,
|
|
405
408
|
restart,
|
|
406
409
|
sleep,
|
|
@@ -449,6 +452,7 @@ function resumeRun(active, toolResults, userText, model, key) {
|
|
|
449
452
|
}
|
|
450
453
|
const payload = { ...result, content: String(result.content ?? '') };
|
|
451
454
|
if (pendingUserText && pending.exec.execId === lastExecId) {
|
|
455
|
+
if (pending.native?.resultType === 'readResult') pending.nativeUserMessage = pendingUserText;
|
|
452
456
|
payload.content += `\n\n<user_message>\n${pendingUserText}\n</user_message>`;
|
|
453
457
|
userTextDelivered = true;
|
|
454
458
|
}
|
|
@@ -471,7 +475,11 @@ function noUserMessageResponse() {
|
|
|
471
475
|
});
|
|
472
476
|
}
|
|
473
477
|
|
|
474
|
-
export async function handleChatCompletion(
|
|
478
|
+
export async function handleChatCompletion(
|
|
479
|
+
body,
|
|
480
|
+
accessToken,
|
|
481
|
+
{ onStageChange = null, getAccessToken = null, resetActiveRun = false, ownerSessionId = '' } = {}
|
|
482
|
+
) {
|
|
475
483
|
await warmCursorClientVersion();
|
|
476
484
|
const parsed = parseMessages(body.messages);
|
|
477
485
|
if (
|
|
@@ -492,6 +500,7 @@ export async function handleChatCompletion(body, accessToken, { onStageChange =
|
|
|
492
500
|
const cloudRule = parsed.systems.join('\n\n') || undefined;
|
|
493
501
|
const active = activeRuns.get(key);
|
|
494
502
|
if (
|
|
503
|
+
!resetActiveRun &&
|
|
495
504
|
active &&
|
|
496
505
|
parsed.toolResults.length &&
|
|
497
506
|
active.bridge.alive &&
|
|
@@ -531,6 +540,7 @@ export async function handleChatCompletion(body, accessToken, { onStageChange =
|
|
|
531
540
|
maxMode,
|
|
532
541
|
key,
|
|
533
542
|
sessionId,
|
|
543
|
+
ownerSessionId,
|
|
534
544
|
onStageChange,
|
|
535
545
|
restart: async ({ fromCheckpoint, reason, error }) => {
|
|
536
546
|
if (reason === 'throttle') {
|
|
@@ -49,6 +49,7 @@ function toCursorMessages(messages, providerName, { nativePdf } = {}) {
|
|
|
49
49
|
...toolMessage,
|
|
50
50
|
mixdog_tool_error: message.toolKind === 'error' || message.isError === true,
|
|
51
51
|
...(media.length ? { mixdog_tool_media: media } : {}),
|
|
52
|
+
...(message.readWindow?.lineClipped === true ? { mixdog_read_window: { lineClipped: true } } : {}),
|
|
52
53
|
});
|
|
53
54
|
}
|
|
54
55
|
return output;
|
|
@@ -545,6 +546,9 @@ function selectCursorVariant(group, { effort = null, fast = false } = {}) {
|
|
|
545
546
|
class CursorProviderBase {
|
|
546
547
|
// Cursor's chat wire has no document block: PDFs lower to text.
|
|
547
548
|
nativePdf = false;
|
|
549
|
+
// Native read results are judged as exact source windows, so the tool
|
|
550
|
+
// finalizer reports their clipped lines next to the text.
|
|
551
|
+
consumesReadWindows = true;
|
|
548
552
|
|
|
549
553
|
static inputExcludesCache = false;
|
|
550
554
|
// The in-place stream retry budget is the whole recovery: a spent budget
|
|
@@ -640,6 +644,13 @@ class CursorProviderBase {
|
|
|
640
644
|
const response = await runtime.handleChatCompletion(body, accessToken, {
|
|
641
645
|
onStageChange: sendOpts.onStageChange,
|
|
642
646
|
getAccessToken: (options) => this._accessToken({ signal, ...options }),
|
|
647
|
+
// A deliberate history reset must reach Cursor's private parked run,
|
|
648
|
+
// not just the orchestrator's providerState.
|
|
649
|
+
resetActiveRun: Boolean(sendOpts.cacheBreakIntent),
|
|
650
|
+
// Native read/edit capabilities are process-local. An explicit empty
|
|
651
|
+
// executor (the model-proxy host: tools run in the server daemon)
|
|
652
|
+
// keeps every call an ordinary Mixdog tool call.
|
|
653
|
+
ownerSessionId: String(sendOpts.toolExecutionSessionId ?? (sendOpts.sessionId || '')),
|
|
643
654
|
});
|
|
644
655
|
try {
|
|
645
656
|
sendOpts.onStageChange?.('streaming');
|
|
@@ -699,7 +710,9 @@ class CursorProviderBase {
|
|
|
699
710
|
const sessionScope = String(
|
|
700
711
|
sendOpts.transportScope ||
|
|
701
712
|
sendOpts.sessionId ||
|
|
702
|
-
sendOpts.providerCacheKey ||
|
|
713
|
+
sendOpts.providerCacheKey ||
|
|
714
|
+
sendOpts.promptCacheKey ||
|
|
715
|
+
`cursor-call:${randomUUID()}`
|
|
703
716
|
);
|
|
704
717
|
const openAiTools = tools?.length
|
|
705
718
|
? toOpenAITools(acceptedWireTools(tools, 'openai', sendOpts.onToolExcluded, '[cursor] tool'))
|
|
@@ -386,6 +386,14 @@ function catalogLevels(row) {
|
|
|
386
386
|
return levels.size ? [...levels].sort(byRank) : null;
|
|
387
387
|
}
|
|
388
388
|
|
|
389
|
+
function reasoningLevelFields(levels) {
|
|
390
|
+
if (!levels) return {};
|
|
391
|
+
return {
|
|
392
|
+
reasoningOptions: levels.length ? [{ type: 'effort', values: [...levels] }] : [],
|
|
393
|
+
reasoningLevels: [...levels],
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
|
|
389
397
|
function effectiveRow(base, override, { providerId, discovered, newModelsHidden }) {
|
|
390
398
|
const ov = override || {};
|
|
391
399
|
const reasoning = ov.reasoning || {};
|
|
@@ -413,12 +421,7 @@ function effectiveRow(base, override, { providerId, discovered, newModelsHidden
|
|
|
413
421
|
hidden,
|
|
414
422
|
manual: ov.manual === true,
|
|
415
423
|
supportsReasoning: levels ? levels.some((level) => level !== 'none') : base.supportsReasoning === true,
|
|
416
|
-
...(levels
|
|
417
|
-
? {
|
|
418
|
-
reasoningOptions: levels.length ? [{ type: 'effort', values: [...levels] }] : [],
|
|
419
|
-
reasoningLevels: [...levels],
|
|
420
|
-
}
|
|
421
|
-
: {}),
|
|
424
|
+
...reasoningLevelFields(levels),
|
|
422
425
|
customReasoning: { wireFormat: reasoning.wireFormat ?? 'standard', wireValues, replay },
|
|
423
426
|
...(replay ? { reasoningContentField: 'reasoning_content' } : {}),
|
|
424
427
|
};
|
|
@@ -173,7 +173,11 @@ export async function createCustomProvider(id, config) {
|
|
|
173
173
|
if (providerOffersWire(providerId, 'messages')) {
|
|
174
174
|
const { AnthropicProvider } = await import('./anthropic.mjs');
|
|
175
175
|
// The Anthropic SDK appends /v1/messages itself; the endpoint's /v1 base maps to it.
|
|
176
|
-
messagesEngine = new AnthropicProvider({
|
|
176
|
+
messagesEngine = new AnthropicProvider({
|
|
177
|
+
...engine,
|
|
178
|
+
name: providerId,
|
|
179
|
+
baseURL: cfg.baseURL.replace(/\/v1$/i, ''),
|
|
180
|
+
});
|
|
177
181
|
messagesEngine.nativePdf = false;
|
|
178
182
|
}
|
|
179
183
|
class CompatBase extends OpenAICompatProvider {
|
|
@@ -207,7 +211,8 @@ export async function createCustomProvider(id, config) {
|
|
|
207
211
|
// The bound Messages engine reads the parent's model rows, so a routed
|
|
208
212
|
// Messages request carries the same row-driven thinking/effort as the
|
|
209
213
|
// Anthropic protocol.
|
|
210
|
-
if (provider.messagesEngine)
|
|
214
|
+
if (provider.messagesEngine)
|
|
215
|
+
provider.messagesEngine.getCachedModelInfo = (model) => provider.getCachedModelInfo(model);
|
|
211
216
|
provider.customConfig = cfg;
|
|
212
217
|
provider._customKeyless = keyless;
|
|
213
218
|
provider._applyCustomRows(provider._customRows());
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isVisibleStreamProgress } from '../../../shared/stream-progress.mjs';
|
|
1
2
|
import { anthropicEffortLevelsFor, normalizeAnthropicEffortInput } from './anthropic-effort.mjs';
|
|
2
3
|
import { CUSTOM_EFFORT_LEVELS, customEffortLevels, isCustomProviderName } from './custom-reasoning.mjs';
|
|
3
4
|
import { codexModelSupportsEffortUpdates } from './openai-oauth-catalog.mjs';
|
|
@@ -72,19 +73,40 @@ export function isEffortConfigurationRejection(status, text) {
|
|
|
72
73
|
/**
|
|
73
74
|
* Runs `send(opts)`; when the model rejects the mid-conversation effort
|
|
74
75
|
* update, switches the updates off for it and replays the request once
|
|
75
|
-
* without them.
|
|
76
|
+
* without them. Never replay after output reached the caller, cancellation,
|
|
77
|
+
* or an explicit opt-out; a late error is not evidence of missing support.
|
|
76
78
|
*/
|
|
77
79
|
export async function withEffortConfigurationFallback(provider, model, opts, send) {
|
|
80
|
+
let streamed = false;
|
|
81
|
+
const track =
|
|
82
|
+
(callback, isProgress = false) =>
|
|
83
|
+
(...args) => {
|
|
84
|
+
if (!isProgress || isVisibleStreamProgress(args[0])) streamed = true;
|
|
85
|
+
return callback(...args);
|
|
86
|
+
};
|
|
87
|
+
const tracked = { ...opts };
|
|
88
|
+
if (typeof opts?.onStreamDelta === 'function') tracked.onStreamDelta = track(opts.onStreamDelta, true);
|
|
89
|
+
if (typeof opts?.onTextDelta === 'function') tracked.onTextDelta = track(opts.onTextDelta);
|
|
90
|
+
if (typeof opts?.onToolCall === 'function') tracked.onToolCall = track(opts.onToolCall);
|
|
78
91
|
try {
|
|
79
|
-
return await send(
|
|
92
|
+
return await send(tracked);
|
|
80
93
|
} catch (error) {
|
|
81
94
|
const status = error?.status ?? error?.httpStatus;
|
|
82
|
-
|
|
95
|
+
const emitted =
|
|
96
|
+
streamed || error?.liveTextEmitted === true || error?.emittedToolCall === true || error?.unsafeToRetry === true;
|
|
97
|
+
if (
|
|
98
|
+
opts?._effortConfigurationRetry ||
|
|
99
|
+
opts?.effortConfigurationEnabled === false ||
|
|
100
|
+
opts?.signal?.aborted ||
|
|
101
|
+
emitted ||
|
|
102
|
+
!isEffortConfigurationRejection(status, error?.message)
|
|
103
|
+
)
|
|
104
|
+
throw error;
|
|
83
105
|
markEffortConfigurationUnsupported(provider, model);
|
|
84
106
|
process.stderr.write(
|
|
85
107
|
`[${provider}] ${model} rejected the mid-conversation effort update; retrying once without it\n`
|
|
86
108
|
);
|
|
87
|
-
return send({ ...
|
|
109
|
+
return send({ ...tracked, effortConfigurationEnabled: false, _effortConfigurationRetry: true });
|
|
88
110
|
}
|
|
89
111
|
}
|
|
90
112
|
const OPENAI_PROVIDERS = new Set(['openai', 'openai-oauth']);
|
|
@@ -77,7 +77,9 @@ const GEMINI_CACHE_MIN_TOKENS = 4096;
|
|
|
77
77
|
// Minimum prefix tokens for an explicit cache, or null when the docs exclude
|
|
78
78
|
// the model from explicit caching.
|
|
79
79
|
export function geminiExplicitCacheMinTokens(model) {
|
|
80
|
-
const bare = String(model || '')
|
|
80
|
+
const bare = String(model || '')
|
|
81
|
+
.replace(/^models\//i, '')
|
|
82
|
+
.toLowerCase();
|
|
81
83
|
const major = /^gemini-(\d+)/.exec(bare);
|
|
82
84
|
if (major && Number(major[1]) >= 4) return null;
|
|
83
85
|
if (/^gemini-2\.5-(?:pro|flash)(?!-lite)(?:-|$)/.test(bare)) return 2048;
|
|
@@ -263,19 +265,23 @@ export function _resolveGeminiCacheUsage({ usageMetadata, cachedContent, provide
|
|
|
263
265
|
// the prompt portion.
|
|
264
266
|
const toolUseTokens = firstFinite(usageMetadata?.toolUsePromptTokenCount, usageMetadata?.tool_use_prompt_token_count);
|
|
265
267
|
const inputTokens = hasExplicitPromptTokens ? promptTokens + toolUseTokens : Math.max(0, totalTokens - outputTokens);
|
|
266
|
-
const
|
|
268
|
+
const reportedCachedCount = [
|
|
267
269
|
// generateContent UsageMetadata field.
|
|
268
270
|
usageMetadata?.cachedContentTokenCount,
|
|
269
271
|
usageMetadata?.cached_content_token_count,
|
|
270
272
|
// Newer SDK convenience alias documented for implicit cache hits.
|
|
271
273
|
usageMetadata?.totalCachedTokens,
|
|
272
|
-
usageMetadata?.total_cached_tokens
|
|
273
|
-
|
|
274
|
+
usageMetadata?.total_cached_tokens,
|
|
275
|
+
]
|
|
276
|
+
.map((value) => (value == null ? NaN : Number(value)))
|
|
277
|
+
.find((value) => Number.isFinite(value) && value >= 0);
|
|
278
|
+
const reportedCachedTokens = reportedCachedCount ?? 0;
|
|
274
279
|
const cachedFallbackTokens = cachedContent ? Number(providerState?.gemini?.cacheTokenSize || 0) || 0 : 0;
|
|
275
|
-
|
|
280
|
+
// An explicit zero is a measured miss, not missing usage metadata.
|
|
281
|
+
const rawCachedTokens = reportedCachedCount ?? cachedFallbackTokens;
|
|
276
282
|
const cachedTokens = inputTokens > 0 ? Math.min(rawCachedTokens, inputTokens) : rawCachedTokens;
|
|
277
283
|
let cacheTokenSource = 'none';
|
|
278
|
-
if (
|
|
284
|
+
if (reportedCachedCount !== undefined) cacheTokenSource = 'usage_metadata';
|
|
279
285
|
else if (cachedFallbackTokens > 0) cacheTokenSource = 'cache_create_fallback';
|
|
280
286
|
return {
|
|
281
287
|
inputTokens,
|
|
@@ -97,7 +97,10 @@ export function geminiErrorContract({ details, errorDetails, googleStatus, messa
|
|
|
97
97
|
const scope = scopeOf(String(violation?.quotaId || ''));
|
|
98
98
|
if (scope) scopes.add(scope);
|
|
99
99
|
// A spent allowance is named by the typed violation, not by prose.
|
|
100
|
-
if (
|
|
100
|
+
if (
|
|
101
|
+
String(violation?.quotaValue ?? '').trim() === '0' ||
|
|
102
|
+
LIMIT_ZERO_RE.test(String(violation?.description || ''))
|
|
103
|
+
) {
|
|
101
104
|
zeroLimit = true;
|
|
102
105
|
}
|
|
103
106
|
}
|
|
@@ -121,7 +124,9 @@ export function geminiErrorContract({ details, errorDetails, googleStatus, messa
|
|
|
121
124
|
CAPACITY_REASONS.has(reason) ||
|
|
122
125
|
(!reason && scopes.size === 0 && retryAfterMs === undefined && CAPACITY_MESSAGE_RE.test(text));
|
|
123
126
|
// A per-day violation outlasts any per-minute one reported with it.
|
|
124
|
-
let quotaScope
|
|
127
|
+
let quotaScope;
|
|
128
|
+
if (scopes.has('day')) quotaScope = 'day';
|
|
129
|
+
else if (scopes.has('minute')) quotaScope = 'minute';
|
|
125
130
|
if (retryAfterMs === undefined) {
|
|
126
131
|
const named = MESSAGE_DELAY_RE.exec(text);
|
|
127
132
|
if (named) retryAfterMs = adviceMs(named[1]);
|
|
@@ -158,10 +163,13 @@ export function geminiInBandError(chunk, label) {
|
|
|
158
163
|
if (!detail || (typeof detail !== 'object' && typeof detail !== 'string')) return null;
|
|
159
164
|
const body = typeof detail === 'object' ? detail : { message: detail };
|
|
160
165
|
const googleStatus = typeof body.status === 'string' ? body.status : '';
|
|
161
|
-
const status =
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
166
|
+
const status =
|
|
167
|
+
Number.isFinite(Number(body.code)) && Number(body.code) > 0
|
|
168
|
+
? Number(body.code)
|
|
169
|
+
: GOOGLE_STATUS_HTTP[googleStatus.toUpperCase()];
|
|
170
|
+
const err = new Error(
|
|
171
|
+
`${label} in-band error${status ? ` ${status}` : ''}: ${String(body.message || googleStatus || 'unknown').slice(0, 300)}`
|
|
172
|
+
);
|
|
165
173
|
err.name = 'GeminiInBandError';
|
|
166
174
|
if (status) {
|
|
167
175
|
err.status = status;
|
|
@@ -44,10 +44,10 @@ export function buildGeminiRequest(messages, useModel, tools, opts) {
|
|
|
44
44
|
// explicit opts.includeThoughts still wins.
|
|
45
45
|
const thinkingConfig = geminiThinkingConfig(useModel, opts, { includeThoughts: true });
|
|
46
46
|
const controls = geminiGenerationControls(opts);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
let generationConfig;
|
|
48
|
+
if (thinkingConfig || Object.keys(controls).length) {
|
|
49
|
+
generationConfig = { ...(thinkingConfig ? { thinkingConfig } : {}), ...controls };
|
|
50
|
+
}
|
|
51
51
|
const systemInstruction =
|
|
52
52
|
messages
|
|
53
53
|
.filter((m) => m.role === 'system')
|
|
@@ -149,6 +149,7 @@ export function resolveGeminiUsage(response, opts, cachedContent, useModel) {
|
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
export function geminiSendResult(parsed, useModel, opts, resolvedUsage) {
|
|
152
|
+
if (parsed.providerReplay) parsed.providerReplay.requestContext = { model: useModel };
|
|
152
153
|
return {
|
|
153
154
|
content: parsed.content,
|
|
154
155
|
model: useModel,
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
// First-byte and idle watchdogs of one Gemini REST SSE body. Either timeout
|
|
2
2
|
// cancels the reader and fails the pending read, so the caller surfaces a typed
|
|
3
|
-
// timeout instead of waiting on a stalled socket.
|
|
4
|
-
|
|
3
|
+
// timeout instead of waiting on a stalled socket. The idle timer re-arms only
|
|
4
|
+
// on decoded payloads (semantic progress), so it uses the semantic window.
|
|
5
|
+
// Each timeout names its phase (`timeoutPhase`): 'first-chunk' before any
|
|
6
|
+
// payload, 'idle' after one.
|
|
7
|
+
import { PROVIDER_SEMANTIC_IDLE_TIMEOUT_MS, PROVIDER_SSE_IDLE_WATCHDOG_ENABLED } from '../../stall-policy.mjs';
|
|
8
|
+
import { TIMEOUT_PHASE } from '../../../../shared/provider-timeout-phase.mjs';
|
|
5
9
|
|
|
6
10
|
export function createRestStreamWatchdogs({ reader, label, firstByteTimeoutMs, timeoutError }) {
|
|
7
11
|
let idleTimedOut = false;
|
|
@@ -19,11 +23,18 @@ export function createRestStreamWatchdogs({ reader, label, firstByteTimeoutMs, t
|
|
|
19
23
|
pendingReject = null;
|
|
20
24
|
reject(err);
|
|
21
25
|
};
|
|
22
|
-
const idleError = () =>
|
|
26
|
+
const idleError = () =>
|
|
27
|
+
Object.assign(timeoutError(`${label} SSE idle`, PROVIDER_SEMANTIC_IDLE_TIMEOUT_MS), {
|
|
28
|
+
timeoutPhase: TIMEOUT_PHASE.IDLE,
|
|
29
|
+
});
|
|
23
30
|
|
|
24
31
|
let firstByteTimer = setTimeout(() => {
|
|
25
32
|
cancelReader('first byte timeout');
|
|
26
|
-
failPending(
|
|
33
|
+
failPending(
|
|
34
|
+
Object.assign(timeoutError(`${label} first byte`, firstByteTimeoutMs), {
|
|
35
|
+
timeoutPhase: TIMEOUT_PHASE.FIRST_CHUNK,
|
|
36
|
+
})
|
|
37
|
+
);
|
|
27
38
|
}, firstByteTimeoutMs);
|
|
28
39
|
firstByteTimer.unref?.();
|
|
29
40
|
const clearFirstByte = () => {
|
|
@@ -46,7 +57,7 @@ export function createRestStreamWatchdogs({ reader, label, firstByteTimeoutMs, t
|
|
|
46
57
|
idleTimedOut = true;
|
|
47
58
|
cancelReader('SSE idle timeout');
|
|
48
59
|
failPending(idleError());
|
|
49
|
-
},
|
|
60
|
+
}, PROVIDER_SEMANTIC_IDLE_TIMEOUT_MS);
|
|
50
61
|
idleTimer.unref?.();
|
|
51
62
|
},
|
|
52
63
|
// One reader.read() with its reject handle registered for the watchdogs;
|
|
@@ -148,7 +148,12 @@ export async function runGeminiStreamAttempts({ run, signal, onRetry, sleepFn, a
|
|
|
148
148
|
} catch (err) {
|
|
149
149
|
const waitMs = connected ? geminiMidstreamDelayMs(err, streamAttempt, signal) : null;
|
|
150
150
|
if (waitMs == null) throw err;
|
|
151
|
-
onRetry?.({
|
|
151
|
+
onRetry?.({
|
|
152
|
+
attempt: streamAttempt + 1,
|
|
153
|
+
maxAttempts: GEMINI_MIDSTREAM_MAX_ATTEMPTS,
|
|
154
|
+
lastErr: err,
|
|
155
|
+
delayMs: waitMs,
|
|
156
|
+
});
|
|
152
157
|
await sleepWithAbort(waitMs, signal, sleepFn, 'Gemini stream retry wait aborted');
|
|
153
158
|
continue;
|
|
154
159
|
}
|