mixdog 1.4.0 → 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/scripts/build-shipped-history.mjs +115 -33
- package/scripts/check-voice-runtime-inputs.mjs +25 -0
- package/scripts/gate-local.mjs +183 -63
- package/scripts/latest-guard.mjs +21 -9
- package/scripts/lib/gate-scheduler.mjs +138 -32
- package/scripts/lib/gate-timing-reporter.mjs +16 -0
- package/scripts/lib/isolated-test-env.mjs +10 -5
- package/scripts/lib/run-node-tests.mjs +91 -66
- package/scripts/lib/scoped-temp.d.mts +16 -0
- package/scripts/lib/scoped-temp.mjs +124 -0
- package/scripts/lib/stale-temp.mjs +44 -0
- package/scripts/lib/test-failure-records.mjs +14 -1
- package/scripts/lib/test-failure-summary.mjs +16 -4
- package/scripts/lib/test-spawn-ledger.mjs +12 -3
- package/scripts/post-release-check.mjs +1 -6
- package/scripts/pptx-kit-index.mjs +17 -5
- package/scripts/suite-health.mjs +115 -24
- package/scripts/test-data-dir.mjs +10 -7
- package/scripts/test.mjs +9 -14
- package/src/agents/advisor/AGENT.md +4 -4
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/explore/AGENT.md +22 -0
- package/src/agents/explore/agent.json +6 -0
- package/src/app.mjs +4 -0
- package/src/cli.mjs +7 -0
- package/src/defaults/agents.json +7 -0
- package/src/defaults/shipped-history.json +23 -2
- package/src/defaults/skills/browser-use/SKILL.md +10 -5
- package/src/defaults/skills/code-tidy/SKILL.md +71 -102
- package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
- package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
- package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
- package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
- package/src/defaults/skills/computer-use/SKILL.md +16 -4
- package/src/defaults/skills/goal-management/SKILL.md +1 -1
- package/src/defaults/skills/setup/references/actions.md +12 -6
- package/src/defaults/skills/setup/references/surfaces.md +2 -2
- package/src/defaults/skills/setup-guide/SKILL.md +5 -2
- package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
- package/src/defaults/skills/skill-creator/SKILL.md +85 -190
- package/src/defaults/skills/skill-creator/references/design.md +70 -162
- package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
- package/src/defaults/skills/test-suite/SKILL.md +194 -0
- package/src/defaults/skills/test-suite/references/case-management.md +51 -0
- package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
- package/src/defaults/skills/test-suite/references/reliability.md +49 -0
- package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
- package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
- package/src/defaults/skills/visualize/SKILL.md +6 -2
- package/src/lib/rules-builder.cjs +35 -42
- package/src/output-styles/common.md +2 -2
- package/src/output-styles/simple.md +1 -1
- package/src/rules/agent/AGENT.md +5 -4
- package/src/rules/lead/LEAD.md +12 -7
- package/src/rules/shared/10-tool-workflow.md +3 -1
- package/src/rules/shared/20-research.md +3 -6
- package/src/rules/shared/40-editing.md +1 -0
- package/src/rules/shared/45-destructive.md +0 -2
- package/src/rules/shared/50-execution.md +2 -0
- package/src/rules/shared/60-verification.md +10 -9
- package/src/rules/shared/70-delivery.md +8 -9
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -1
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +156 -24
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -0
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
- package/src/runtime/agent/orchestrator/cache-break-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/config.mjs +12 -7
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +8 -8
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +5 -26
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +3 -1
- package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +122 -12
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +5 -3
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +13 -2
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +152 -58
- package/src/runtime/agent/orchestrator/mcp/client.mjs +51 -18
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +88 -54
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +42 -26
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +54 -8
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +37 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +31 -21
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +14 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +1 -10
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
- package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/devin.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +248 -41
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -11
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +45 -6
- package/src/runtime/agent/orchestrator/providers/lib/first-output-window.mjs +58 -0
- package/src/runtime/agent/orchestrator/providers/lib/listen-on.mjs +14 -0
- package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +1 -10
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +14 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +4 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +5 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +13 -3
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +13 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +81 -42
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +160 -31
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +22 -12
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +49 -22
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/registry.mjs +45 -2
- package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +567 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +41 -13
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -6
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +7 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +6 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +14 -5
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
- package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +1 -3
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +102 -12
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -8
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +103 -23
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +160 -36
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +164 -23
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +139 -19
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +38 -7
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +100 -22
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -6
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +33 -3
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +9 -2
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +14 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +23 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +39 -21
- package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +50 -28
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +30 -13
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +63 -6
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +35 -13
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +24 -14
- package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
- package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +10 -6
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +56 -29
- package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +30 -7
- package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +37 -8
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +252 -39
- package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +164 -4
- package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +61 -2
- package/src/runtime/agent/orchestrator/stall-policy.mjs +23 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +46 -20
- package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +67 -31
- package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +25 -13
- package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +6 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +23 -12
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +1 -8
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +96 -20
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/federation.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/isolated-test-env.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
- package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +103 -13
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +34 -10
- package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +28 -4
- package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -2
- package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
- package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
- package/src/runtime/channels/lib/whisper-port.mjs +29 -11
- package/src/runtime/channels/lib/whisper-server.mjs +10 -1
- package/src/runtime/computer-bridge/action-schema.mjs +2 -2
- package/src/runtime/computer-bridge/core-actions.mjs +2 -2
- package/src/runtime/computer-bridge/error-recovery.mjs +5 -4
- package/src/runtime/computer-bridge/linux-action-capabilities.mjs +24 -5
- package/src/runtime/computer-bridge/linux-readiness.d.mts +7 -2
- package/src/runtime/connectors/connector-accounts-mcp.mjs +236 -103
- package/src/runtime/connectors/gmail-app-password.mjs +3 -3
- package/src/runtime/explore/explorer.mjs +93 -0
- package/src/runtime/explore/tool-defs.mjs +35 -0
- package/src/runtime/explore/tool.mjs +123 -0
- package/src/runtime/local-provider/server-process.mjs +2 -1
- package/src/runtime/media/adapters/gemini-video.mjs +4 -1
- package/src/runtime/media/adapters/xai-media.mjs +2 -1
- package/src/runtime/memory/index.mjs +4 -0
- package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
- package/src/runtime/memory/lib/embedding-worker.mjs +10 -3
- package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +1 -7
- package/src/runtime/memory/lib/memory-chunk-quality.mjs +1 -6
- package/src/runtime/office/authoring/pdf-author-action.mjs +1 -6
- package/src/runtime/office/design/design-art-direction.mjs +29 -27
- package/src/runtime/office/pdf/pdf-writer.mjs +6 -1
- package/src/runtime/office/portable/portable-snapshot-docx.mjs +7 -1
- package/src/runtime/office/portable/portable-snapshot-shared.mjs +6 -1
- package/src/runtime/office/quality/assurance-rendered.mjs +9 -2
- package/src/runtime/office/quality/assurance-structure-docx.mjs +4 -2
- package/src/runtime/office/quality/design-review.mjs +1 -5
- package/src/runtime/office/quality/document-brief.mjs +1 -5
- package/src/runtime/office/quality/forced-break-pages.mjs +9 -6
- package/src/runtime/office/quality/quality-pipeline.mjs +1 -1
- package/src/runtime/shared/agent-route-config.mjs +17 -2
- package/src/runtime/shared/atomic-file.mjs +103 -2
- package/src/runtime/shared/background-tasks.mjs +15 -6
- package/src/runtime/shared/bot-owned-work.mjs +56 -0
- package/src/runtime/shared/connector-accounts.mjs +5 -5
- package/src/runtime/shared/connector-catalog.d.mts +11 -4
- package/src/runtime/shared/connector-catalog.mjs +60 -52
- package/src/runtime/shared/custom-provider-keys.mjs +20 -0
- package/src/runtime/shared/defaults-separation.mjs +1 -4
- package/src/runtime/shared/fetch-safe-listen.d.mts +16 -0
- package/src/runtime/shared/fetch-safe-listen.mjs +50 -0
- package/src/runtime/shared/file-has-data.mjs +26 -2
- package/src/runtime/shared/file-lock.mjs +13 -15
- package/src/runtime/shared/git-launch.d.mts +9 -0
- package/src/runtime/shared/git-launch.mjs +213 -0
- package/src/runtime/shared/git-runner-worker.mjs +2 -1
- package/src/runtime/shared/handoff-artifacts.d.mts +2 -1
- package/src/runtime/shared/handoff-artifacts.mjs +18 -8
- package/src/runtime/shared/idle-auto-clear-gate.mjs +29 -7
- package/src/runtime/shared/llm/cost.mjs +11 -2
- package/src/runtime/shared/llm/http-agent.mjs +313 -29
- package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
- package/src/runtime/shared/llm/model-catalog.mjs +46 -6
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
- package/src/runtime/shared/llm/system-proxy.mjs +452 -0
- package/src/runtime/shared/loopback-listener.mjs +25 -2
- package/src/runtime/shared/model-route-chain.d.mts +7 -2
- package/src/runtime/shared/model-route-chain.mjs +22 -4
- package/src/runtime/shared/open-url.mjs +10 -0
- package/src/runtime/shared/provider-accounts.mjs +52 -2
- package/src/runtime/shared/session-activity-signal.mjs +14 -0
- package/src/runtime/shared/session-scratch.mjs +37 -0
- package/src/runtime/shared/staged-install-worker.mjs +5 -0
- package/src/runtime/shared/staged-update.mjs +47 -2
- package/src/runtime/shared/tool-card-model/agent-surface.mjs +1 -3
- package/src/runtime/shared/tool-card-model/card-status.mjs +15 -2
- package/src/runtime/shared/tool-result-summary.mjs +1 -1
- package/src/runtime/shared/tool-surface.mjs +113 -36
- package/src/runtime/shared/tool-work-units.mjs +6 -0
- package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
- package/src/runtime/shared/turn-worktree-snapshot.mjs +414 -54
- package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
- package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
- package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
- package/src/runtime/shared/worktrees/branch-management.mjs +9 -3
- package/src/runtime/shared/worktrees/contract.mjs +4 -1
- package/src/runtime/shared/worktrees/git.mjs +72 -0
- package/src/runtime/shared/worktrees/manager.mjs +285 -168
- package/src/runtime/shared/worktrees/test-support.mjs +6 -10
- package/src/runtime/tidy/install.mjs +95 -15
- package/src/runtime/tidy/languages.mjs +17 -15
- package/src/runtime/tidy/process.mjs +7 -4
- package/src/runtime/tidy/resolve.mjs +19 -16
- package/src/runtime/tidy/runners/biome.mjs +3 -3
- package/src/runtime/tidy/tool.mjs +1 -1
- package/src/runtime/tidy/worktree.mjs +10 -6
- package/src/runtime/visualize-bridge/client.mjs +6 -1
- package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
- package/src/runtime/web-search/index.mjs +1 -1
- package/src/session-runtime/agent-home-delivery.mjs +41 -0
- package/src/session-runtime/agent-task-sessions.mjs +458 -312
- package/src/session-runtime/agent-tool-routing.mjs +8 -41
- package/src/session-runtime/boot/tools.mjs +7 -1
- package/src/session-runtime/bot-status.mjs +107 -101
- package/src/session-runtime/bot-target.mjs +38 -0
- package/src/session-runtime/channel-config-api.mjs +6 -1
- package/src/session-runtime/connector-merge-migration.mjs +18 -15
- package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
- package/src/session-runtime/conversation-import/discovery.mjs +401 -36
- package/src/session-runtime/conversation-import/service.mjs +35 -8
- package/src/session-runtime/handoff-attachments.mjs +82 -31
- package/src/session-runtime/held-requests.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +12 -13
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +1 -0
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -0
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
- package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +145 -112
- package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
- package/src/session-runtime/lifecycle/session-catalog.mjs +9 -1
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -1
- package/src/session-runtime/lifecycle/teardown.mjs +1 -1
- package/src/session-runtime/mcp-glue/server-catalog.mjs +16 -10
- package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
- package/src/session-runtime/mixy-heartbeat.mjs +1 -1
- package/src/session-runtime/model-route/set-route.mjs +11 -2
- package/src/session-runtime/provider-auth/login.mjs +2 -2
- package/src/session-runtime/provider-catalog-cache.mjs +82 -36
- package/src/session-runtime/provider-models/catalog-load.mjs +23 -6
- package/src/session-runtime/provider-models.mjs +4 -2
- package/src/session-runtime/resource-mcp-api.mjs +98 -35
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +44 -31
- package/src/session-runtime/resource-mcp-secrets.mjs +28 -11
- package/src/session-runtime/resource-mcp-servers.mjs +5 -4
- package/src/session-runtime/resource-recall-api.mjs +6 -1
- package/src/session-runtime/runtime-feature-gates.mjs +5 -1
- package/src/session-runtime/services/agent-tool/execute.mjs +14 -9
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +20 -4
- package/src/session-runtime/services/agent-tool/model-select.mjs +48 -7
- package/src/session-runtime/services/agent-tool/render.mjs +71 -17
- package/src/session-runtime/services/agent-tool/send-flow.mjs +10 -2
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +4 -1
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +6 -2
- package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
- package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
- package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
- package/src/session-runtime/services/daemon-candidate.mjs +4 -1
- package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
- package/src/session-runtime/services/plugin-admin.mjs +10 -6
- package/src/session-runtime/services/provider-admin.mjs +283 -11
- package/src/session-runtime/session-turn-api.mjs +2 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +4 -1
- package/src/session-runtime/settings-system-api.mjs +1 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
- package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
- package/src/session-runtime/setup-tool/executor.mjs +6 -2
- package/src/session-runtime/setup-tool/tool-defs.mjs +2 -1
- package/src/session-runtime/tool-policy/policy-stage.mjs +1 -0
- package/src/session-runtime/turn/agent-ops.mjs +23 -0
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +49 -11
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +25 -5
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
- package/src/session-runtime/workspace/activity-guards.mjs +176 -0
- package/src/session-runtime/workspace/session-view.mjs +149 -0
- package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
- package/src/session-runtime/workspace/transition-runner.mjs +188 -0
- package/src/session-runtime/workspace/transitions.mjs +108 -1041
- package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
- package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
- package/src/session-runtime/workspace/worktree-maintenance.mjs +80 -0
- package/src/session-runtime/workspace/worktree-setup.mjs +85 -0
- package/src/session-runtime/workspace/worktree-tool.mjs +73 -56
- package/src/standalone/daemon-desktop-runtime.mjs +2 -0
- package/src/standalone/daemon-session-control.mjs +169 -138
- package/src/standalone/daemon.mjs +7 -0
- package/src/standalone/desktop-service-registry.mjs +9 -0
- package/src/standalone/local-session-runtime.mjs +5 -1
- package/src/standalone/session-client/daemon-unavailable.mjs +3 -0
- package/src/standalone/session-client.mjs +5 -1
- package/src/standalone/session-frame-stream.mjs +83 -11
- package/src/standalone/session-protocol.mjs +4 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
- package/src/standalone/session-service/agent-tree.mjs +45 -9
- package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
- package/src/standalone/session-service/session-calls/session-action.mjs +10 -3
- package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
- package/src/standalone/session-service/stored-reader.mjs +127 -40
- package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
- package/src/tui/App.jsx +154 -164
- package/src/tui/app/app-view/floating-panel.jsx +10 -4
- package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
- package/src/tui/app/clipboard.mjs +21 -10
- package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +1 -3
- package/src/tui/app/model-picker/route-selection.mjs +5 -6
- package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
- package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
- package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
- package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
- package/src/tui/app/provider-setup/oauth-actions.mjs +58 -21
- package/src/tui/app/provider-setup/provider-items.mjs +8 -2
- package/src/tui/app/provider-setup-picker.mjs +29 -18
- package/src/tui/app/shell-layout/row-budgets.mjs +12 -10
- package/src/tui/app/slash-commands.mjs +1 -0
- package/src/tui/app/slash-dispatch/session-commands.mjs +46 -0
- package/src/tui/app/slash-dispatch.mjs +1 -1
- package/src/tui/app/use-btw-panel.mjs +29 -0
- package/src/tui/app/use-context-panel-refresh.mjs +31 -0
- package/src/tui/app/use-model-catalog-cache.mjs +13 -10
- package/src/tui/app/use-mouse-input.mjs +11 -0
- package/src/tui/app/use-onboarding-start.mjs +8 -3
- package/src/tui/app/use-panel-transition.mjs +10 -1
- package/src/tui/app/use-pasted-buffers.mjs +28 -20
- package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
- package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
- package/src/tui/app/use-prompt-queue-history.mjs +3 -2
- package/src/tui/app/use-selection-focus.mjs +11 -2
- package/src/tui/app/use-selection-geometry.mjs +18 -9
- package/src/tui/app/use-selection-paint.mjs +4 -4
- package/src/tui/app/use-selection-stitch.mjs +3 -3
- package/src/tui/app/use-slash-palette.mjs +62 -0
- package/src/tui/app/use-terminal-chrome.mjs +2 -2
- package/src/tui/app/use-transcript-activity.mjs +47 -32
- package/src/tui/app/use-transcript-follow.mjs +12 -4
- package/src/tui/app/use-transcript-scroll.mjs +46 -17
- package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
- package/src/tui/app/use-transcript-window/geometry.mjs +19 -5
- package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
- package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
- package/src/tui/app/use-transcript-window.mjs +21 -11
- package/src/tui/app/use-tui-ready.mjs +18 -0
- package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
- package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
- package/src/tui/components/Picker.jsx +27 -3
- package/src/tui/components/QuestionPanel.jsx +13 -4
- package/src/tui/components/SignInUrl.jsx +68 -0
- package/src/tui/components/TextEntryPanel.jsx +76 -46
- package/src/tui/components/sign-in-url-layout.mjs +24 -0
- package/src/tui/dist/index.mjs +1963 -1361
- package/src/tui/session/goal-turn-state.mjs +6 -2
- package/src/tui/session/session-api/controls.mjs +4 -0
- package/src/tui/session/session-api/extensions.mjs +8 -0
- package/src/tui/session/session-api/intake/abort.mjs +2 -1
- package/src/tui/session/session-api/intake.mjs +2 -0
- package/src/tui/session/session-api/integrations.mjs +2 -2
- package/src/tui/session/session-api/routes-agent-definitions.mjs +1 -0
- package/src/tui/session/session-api/settings.mjs +2 -2
- package/src/tui/session/session-flow/queue/take-entries.mjs +11 -0
- package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
- package/src/tui/session/transcript-spill.mjs +92 -4
- package/src/tui/session/transcript-store.mjs +2 -0
- package/src/ui/statusline-agents.mjs +1 -3
- package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
|
@@ -1,10 +1,77 @@
|
|
|
1
1
|
import { createServer } from 'node:http';
|
|
2
|
+
import { listenOnFetchSafePort } from '../../../shared/fetch-safe-listen.mjs';
|
|
2
3
|
import { randomBytes } from 'node:crypto';
|
|
3
4
|
import { normalizeMcpTransportUrl } from './client-config.mjs';
|
|
4
5
|
import { identityFromTokenResponse } from './oauth-account.mjs';
|
|
5
6
|
import { answerOAuthCallback } from './oauth-callback.mjs';
|
|
6
7
|
import { anySignal, loginFailed, reauthenticationRequired, scopeNotGranted } from './oauth-shared.mjs';
|
|
7
8
|
|
|
9
|
+
// Fetch for the SDK: transport-URL normalized, no redirects, bounded by the
|
|
10
|
+
// login `signal`. The token endpoint's answer is read for who the tokens
|
|
11
|
+
// belong to (oauth-account.mjs): the SDK keeps only the token fields.
|
|
12
|
+
function makeSafeFetch({ fetchImpl, flow, signal }) {
|
|
13
|
+
return async (input, init = {}) => {
|
|
14
|
+
const response = await fetchImpl(normalizeMcpTransportUrl(input), {
|
|
15
|
+
...init,
|
|
16
|
+
redirect: 'error',
|
|
17
|
+
signal: anySignal(signal, init.signal),
|
|
18
|
+
});
|
|
19
|
+
if (response.ok && /(^|&)grant_type=/.test(String(init.body ?? ''))) {
|
|
20
|
+
flow.identity = identityFromTokenResponse(
|
|
21
|
+
await response
|
|
22
|
+
.clone()
|
|
23
|
+
.json()
|
|
24
|
+
.catch(() => null)
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
return response;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// The caller's progress hooks (mcp-oauth-login.mjs): the callback arrived,
|
|
32
|
+
// then the tokens are stored.
|
|
33
|
+
function reportProgress(browser, hook) {
|
|
34
|
+
try {
|
|
35
|
+
browser?.[hook]?.();
|
|
36
|
+
} catch {
|
|
37
|
+
/* progress reporting never fails the login */
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// The callback promise of one login, and the browser page held open for the
|
|
42
|
+
// loopback callback until the code exchange and scope check end: `settle()` is
|
|
43
|
+
// success, `settle({ code })` a failure. Bounded by `signal`, like the
|
|
44
|
+
// exchange itself. `setFlushing` receives each answered page's flush.
|
|
45
|
+
function awaitCallback({ flow, signal, stopListening, setFlushing }) {
|
|
46
|
+
let abort;
|
|
47
|
+
let respond;
|
|
48
|
+
const settle = (failure) => {
|
|
49
|
+
const answer = respond;
|
|
50
|
+
respond = undefined;
|
|
51
|
+
if (!answer) return undefined;
|
|
52
|
+
const flushed = answer(failure);
|
|
53
|
+
setFlushing(flushed);
|
|
54
|
+
return flushed;
|
|
55
|
+
};
|
|
56
|
+
const callback = new Promise((resolve, reject) => {
|
|
57
|
+
const finish = (code, page) => {
|
|
58
|
+
if (page) respond = page;
|
|
59
|
+
return code ? resolve(code) : reject(loginFailed());
|
|
60
|
+
};
|
|
61
|
+
flow.finishCallback = finish;
|
|
62
|
+
// Timeout, cancel or abort: the held page gets the generic failure now
|
|
63
|
+
// (the exchange or a credential write may be stalled past the deadline),
|
|
64
|
+
// and the listener closes once it is flushed.
|
|
65
|
+
abort = () => {
|
|
66
|
+
finish();
|
|
67
|
+
settle({});
|
|
68
|
+
stopListening();
|
|
69
|
+
};
|
|
70
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
71
|
+
});
|
|
72
|
+
return { callback, settle, abort };
|
|
73
|
+
}
|
|
74
|
+
|
|
8
75
|
/**
|
|
9
76
|
* The browser login of one connection over its credential `cache` and login
|
|
10
77
|
* `flow` state: the loopback callback listener and the SDK authorization
|
|
@@ -48,8 +115,10 @@ export function createLoginFlow({ url, cache, flow, provider, lifetimeSignal, op
|
|
|
48
115
|
await new Promise((resolve, reject) => {
|
|
49
116
|
flow.listener.once('error', reject);
|
|
50
117
|
// Retain the registered redirect URI if this connection later needs
|
|
51
|
-
// refresh or reauthorization; never register a different callback.
|
|
52
|
-
|
|
118
|
+
// refresh or reauthorization; never register a different callback. A new
|
|
119
|
+
// one is a port the browser can be redirected to.
|
|
120
|
+
if (creds.redirectUrl) flow.listener.listen(Number(new URL(creds.redirectUrl).port), '127.0.0.1', resolve);
|
|
121
|
+
else listenOnFetchSafePort(flow.listener, '127.0.0.1', resolve);
|
|
53
122
|
});
|
|
54
123
|
creds.redirectUrl = `http://127.0.0.1:${flow.listener.address().port}/oauth/callback`;
|
|
55
124
|
}
|
|
@@ -62,61 +131,19 @@ export function createLoginFlow({ url, cache, flow, provider, lifetimeSignal, op
|
|
|
62
131
|
// the token fields, so the token endpoint's answer is read here.
|
|
63
132
|
flow.identity = undefined;
|
|
64
133
|
flow.signal = signal;
|
|
65
|
-
const safeFetch =
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
.clone()
|
|
75
|
-
.json()
|
|
76
|
-
.catch(() => null)
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
return response;
|
|
80
|
-
};
|
|
81
|
-
// The caller's progress hooks (mcp-oauth-login.mjs): the callback arrived,
|
|
82
|
-
// then the tokens are stored.
|
|
83
|
-
const progress = (hook) => {
|
|
84
|
-
try {
|
|
85
|
-
browser?.[hook]?.();
|
|
86
|
-
} catch {
|
|
87
|
-
/* progress reporting never fails the login */
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
let abort;
|
|
91
|
-
// The browser page held open for the loopback callback until the code
|
|
92
|
-
// exchange and scope check end: `settle()` is success, `settle({ code })`
|
|
93
|
-
// a failure. Bounded by `signal`, like the exchange itself.
|
|
94
|
-
let respond;
|
|
95
|
-
const settle = (failure) => {
|
|
96
|
-
const answer = respond;
|
|
97
|
-
respond = undefined;
|
|
98
|
-
if (!answer) return undefined;
|
|
99
|
-
flushing = answer(failure);
|
|
100
|
-
return flushing;
|
|
101
|
-
};
|
|
102
|
-
const callback = new Promise((resolve, reject) => {
|
|
103
|
-
const finish = (code, page) => {
|
|
104
|
-
if (page) respond = page;
|
|
105
|
-
return code ? resolve(code) : reject(loginFailed());
|
|
106
|
-
};
|
|
107
|
-
flow.finishCallback = finish;
|
|
108
|
-
// Timeout, cancel or abort: the held page gets the generic failure now
|
|
109
|
-
// (the exchange or a credential write may be stalled past the deadline),
|
|
110
|
-
// and the listener closes once it is flushed.
|
|
111
|
-
abort = () => {
|
|
112
|
-
finish();
|
|
113
|
-
settle({});
|
|
114
|
-
stopListening();
|
|
115
|
-
};
|
|
116
|
-
signal.addEventListener('abort', abort, { once: true });
|
|
134
|
+
const safeFetch = makeSafeFetch({ fetchImpl, flow, signal });
|
|
135
|
+
const progress = (hook) => reportProgress(browser, hook);
|
|
136
|
+
const { callback, settle, abort } = awaitCallback({
|
|
137
|
+
flow,
|
|
138
|
+
signal,
|
|
139
|
+
stopListening,
|
|
140
|
+
setFlushing: (page) => {
|
|
141
|
+
flushing = page;
|
|
142
|
+
},
|
|
117
143
|
});
|
|
118
144
|
// A discovery/registration error can precede waiting for the callback.
|
|
119
145
|
callback.catch(() => {});
|
|
146
|
+
let codeReceived = false;
|
|
120
147
|
try {
|
|
121
148
|
signal.throwIfAborted();
|
|
122
149
|
const { auth } = await import('@modelcontextprotocol/sdk/client/auth.js');
|
|
@@ -138,6 +165,7 @@ export function createLoginFlow({ url, cache, flow, provider, lifetimeSignal, op
|
|
|
138
165
|
});
|
|
139
166
|
if (result === 'REDIRECT') {
|
|
140
167
|
const code = await callback;
|
|
168
|
+
codeReceived = true;
|
|
141
169
|
signal.throwIfAborted();
|
|
142
170
|
progress('onCallback');
|
|
143
171
|
const exchanged = await cache.withLock(async () => {
|
|
@@ -154,6 +182,12 @@ export function createLoginFlow({ url, cache, flow, provider, lifetimeSignal, op
|
|
|
154
182
|
await settle();
|
|
155
183
|
} catch (error) {
|
|
156
184
|
await settle({ code: error?.code });
|
|
185
|
+
// An authorization server that no longer knows our client_id answers the
|
|
186
|
+
// browser with an HTTP error, never a redirect or a token-endpoint
|
|
187
|
+
// invalid_client, so the SDK cannot see it: register again next time.
|
|
188
|
+
if (interactive && flow.browserOpened && !codeReceived && !provider.preRegistered) {
|
|
189
|
+
await provider.invalidateCredentials('client').catch(() => {});
|
|
190
|
+
}
|
|
157
191
|
// SDK errors may contain authorization server response bodies/secrets.
|
|
158
192
|
if (error?.code === 'reauthenticationRequired' || !interactive) throw reauthenticationRequired();
|
|
159
193
|
// Our own error names scopes only (no token data): the one to pass on.
|
|
@@ -50,28 +50,33 @@ export function isMcpOAuthScopeNotGranted(error) {
|
|
|
50
50
|
return false;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
// One keychain entry per exact server URL
|
|
54
|
-
//
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
// One keychain entry per credential key: the exact server URL, or a connector
|
|
54
|
+
// account's own key (client-config.mjs resolveMcpOAuthCredentialKey). Windows
|
|
55
|
+
// stores each account as a file name, so the account is a hash of the key and
|
|
56
|
+
// nothing else.
|
|
57
|
+
export function mcpOAuthAccount(key) {
|
|
58
|
+
return `mcp-oauth.${createHash('sha256').update(key).digest('hex')}`;
|
|
57
59
|
}
|
|
58
60
|
|
|
59
|
-
/**
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
/** What one sign-in is stored under: `credentialKey`, else the normalized URL. */
|
|
62
|
+
const credentialIdOf = (url, credentialKey) => credentialKey || normalizeMcpTransportUrl(url);
|
|
63
|
+
|
|
64
|
+
/** Whether OAuth tokens are stored for one server URL (or `credentialKey`),
|
|
65
|
+
* read from the non-secret revision marker without touching the keychain. */
|
|
66
|
+
export function hasStoredMcpOAuthTokens(url, credentialKey) {
|
|
62
67
|
try {
|
|
63
|
-
const marker = readFileSync(credentialFile(mcpOAuthAccount(
|
|
68
|
+
const marker = readFileSync(credentialFile(mcpOAuthAccount(credentialIdOf(url, credentialKey)), 'rev'), 'utf8');
|
|
64
69
|
return marker.endsWith(TOKENS_FLAG);
|
|
65
70
|
} catch {
|
|
66
71
|
return false;
|
|
67
72
|
}
|
|
68
73
|
}
|
|
69
74
|
|
|
70
|
-
/** Who the stored sign-in of one MCP server URL
|
|
71
|
-
* read: `{ account, workspace, forcedChoice }` (empty
|
|
72
|
-
* named nobody), or null when signed out. */
|
|
73
|
-
export function storedMcpOAuthIdentity(url) {
|
|
74
|
-
return readIdentityFile(mcpOAuthAccount(
|
|
75
|
+
/** Who the stored sign-in of one MCP server URL (or `credentialKey`) belongs
|
|
76
|
+
* to, without a keychain read: `{ account, workspace, forcedChoice }` (empty
|
|
77
|
+
* strings when the server named nobody), or null when signed out. */
|
|
78
|
+
export function storedMcpOAuthIdentity(url, credentialKey) {
|
|
79
|
+
return readIdentityFile(mcpOAuthAccount(credentialIdOf(url, credentialKey)));
|
|
75
80
|
}
|
|
76
81
|
|
|
77
82
|
// RFC 7009 revocation of the stored grant, only where the authorization server
|
|
@@ -114,9 +119,15 @@ async function revokeStoredGrant(saved, fetchImpl) {
|
|
|
114
119
|
* explicit reconnect to log in again. With `revoke`, the grant is first
|
|
115
120
|
* revoked at the authorization server where it documents a revocation
|
|
116
121
|
* endpoint. Resolves `{ revoked }`. */
|
|
117
|
-
export async function clearMcpOAuth({
|
|
118
|
-
url
|
|
119
|
-
|
|
122
|
+
export async function clearMcpOAuth({
|
|
123
|
+
url,
|
|
124
|
+
credentialKey,
|
|
125
|
+
credentialStore = keychain,
|
|
126
|
+
revoke = false,
|
|
127
|
+
fetchImpl = fetch,
|
|
128
|
+
}) {
|
|
129
|
+
const id = credentialIdOf(url, credentialKey);
|
|
130
|
+
const account = mcpOAuthAccount(id);
|
|
120
131
|
let revoked = false;
|
|
121
132
|
await withCredentialLock(account, async () => {
|
|
122
133
|
const saved = await readStoredCredentials(credentialStore, account);
|
|
@@ -125,7 +136,7 @@ export async function clearMcpOAuth({ url, credentialStore = keychain, revoke =
|
|
|
125
136
|
if (saved != null) await credentialStore.deleteSecretAsync(account);
|
|
126
137
|
await writeIdentityFile(account, null);
|
|
127
138
|
});
|
|
128
|
-
scopes.get(credentialStore)?.get(
|
|
139
|
+
scopes.get(credentialStore)?.get(id)?.oauth.clear();
|
|
129
140
|
return { revoked };
|
|
130
141
|
}
|
|
131
142
|
|
|
@@ -151,6 +162,7 @@ async function storeEntry(account, url, value, credentialStore) {
|
|
|
151
162
|
*/
|
|
152
163
|
export function startMcpOAuthSwitch({
|
|
153
164
|
url,
|
|
165
|
+
credentialKey,
|
|
154
166
|
launch,
|
|
155
167
|
serverName,
|
|
156
168
|
credentialStore = keychain,
|
|
@@ -209,7 +221,7 @@ export function startMcpOAuthSwitch({
|
|
|
209
221
|
timeoutMs,
|
|
210
222
|
});
|
|
211
223
|
const done = (async () => {
|
|
212
|
-
const saved = await readStoredCredentials(credentialStore, mcpOAuthAccount(url));
|
|
224
|
+
const saved = await readStoredCredentials(credentialStore, mcpOAuthAccount(credentialIdOf(url, credentialKey)));
|
|
213
225
|
if (saved) {
|
|
214
226
|
const value = JSON.parse(saved);
|
|
215
227
|
if (value.url === url) {
|
|
@@ -244,9 +256,9 @@ export function startMcpOAuthSwitch({
|
|
|
244
256
|
/** Store the sign-in a switch returned as the URL's sign-in; resolves a
|
|
245
257
|
* `rollback()` that restores the previous one (or none). Live connections
|
|
246
258
|
* adopt either through the revision marker on their next request. */
|
|
247
|
-
export async function commitMcpOAuthSwitch({ url, signIn, credentialStore = keychain }) {
|
|
259
|
+
export async function commitMcpOAuthSwitch({ url, credentialKey, signIn, credentialStore = keychain }) {
|
|
248
260
|
url = normalizeMcpTransportUrl(url);
|
|
249
|
-
const account = mcpOAuthAccount(url);
|
|
261
|
+
const account = mcpOAuthAccount(credentialIdOf(url, credentialKey));
|
|
250
262
|
let previous = null;
|
|
251
263
|
await withCredentialLock(account, async () => {
|
|
252
264
|
previous = await readStoredCredentials(credentialStore, account);
|
|
@@ -262,9 +274,11 @@ export async function commitMcpOAuthSwitch({ url, signIn, credentialStore = keyc
|
|
|
262
274
|
}
|
|
263
275
|
|
|
264
276
|
// The keychain is the only durable store. Exact URLs, including query strings,
|
|
265
|
-
// partition clients and tokens even when servers share an authorization issuer
|
|
277
|
+
// partition clients and tokens even when servers share an authorization issuer;
|
|
278
|
+
// a `credentialKey` (a connector account's own) partitions them at one URL.
|
|
266
279
|
export function createMcpOAuth({
|
|
267
280
|
url,
|
|
281
|
+
credentialKey,
|
|
268
282
|
credentialStore = keychain,
|
|
269
283
|
interactive = false,
|
|
270
284
|
isTransportEndpoint = () => false,
|
|
@@ -272,15 +286,16 @@ export function createMcpOAuth({
|
|
|
272
286
|
...options
|
|
273
287
|
}) {
|
|
274
288
|
url = normalizeMcpTransportUrl(url);
|
|
289
|
+
const id = credentialIdOf(url, credentialKey);
|
|
275
290
|
let entries = scopes.get(credentialStore);
|
|
276
291
|
if (!entries) {
|
|
277
292
|
entries = new Map();
|
|
278
293
|
scopes.set(credentialStore, entries);
|
|
279
294
|
}
|
|
280
|
-
let entry = entries.get(
|
|
295
|
+
let entry = entries.get(id);
|
|
281
296
|
if (!entry) {
|
|
282
|
-
entry = { oauth: createSharedOAuth({ url, credentialStore, ...options }), users: 0 };
|
|
283
|
-
entries.set(
|
|
297
|
+
entry = { oauth: createSharedOAuth({ url, account: mcpOAuthAccount(id), credentialStore, ...options }), users: 0 };
|
|
298
|
+
entries.set(id, entry);
|
|
284
299
|
}
|
|
285
300
|
entry.users++;
|
|
286
301
|
const lifetime = new AbortController();
|
|
@@ -346,7 +361,7 @@ export function createMcpOAuth({
|
|
|
346
361
|
lifetime.abort();
|
|
347
362
|
if (--entry.users === 0) {
|
|
348
363
|
entry.oauth.close();
|
|
349
|
-
entries.delete(
|
|
364
|
+
entries.delete(id);
|
|
350
365
|
}
|
|
351
366
|
},
|
|
352
367
|
};
|
|
@@ -354,6 +369,7 @@ export function createMcpOAuth({
|
|
|
354
369
|
|
|
355
370
|
function createSharedOAuth({
|
|
356
371
|
url,
|
|
372
|
+
account,
|
|
357
373
|
credentialStore,
|
|
358
374
|
openBrowser = openInBrowser,
|
|
359
375
|
fetchImpl = fetch,
|
|
@@ -361,7 +377,7 @@ function createSharedOAuth({
|
|
|
361
377
|
oauthClient = null,
|
|
362
378
|
}) {
|
|
363
379
|
const lifetime = new AbortController();
|
|
364
|
-
const cache = createCredentialCache({ url, credentialStore, account
|
|
380
|
+
const cache = createCredentialCache({ url, credentialStore, account });
|
|
365
381
|
const { creds } = cache;
|
|
366
382
|
const flow = {
|
|
367
383
|
listener: undefined,
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
providerAccountWithBlocks,
|
|
14
14
|
providerAccountBlockedUntil,
|
|
15
15
|
staleQuotaWindows,
|
|
16
|
+
isCustomKeyProvider,
|
|
16
17
|
} from '../../../shared/provider-accounts.mjs';
|
|
17
18
|
import { withProviderAccount, hasExplicitProviderAuthBinding } from '../../../shared/provider-auth-binding.mjs';
|
|
18
19
|
import { isExplicitUserAbortError, markProviderRecoveryExhausted } from './retry-classifier.mjs';
|
|
@@ -161,8 +162,11 @@ function quotaExhausted(error, providerName, model, rows, options = {}) {
|
|
|
161
162
|
// caller does not subscribe, and account-bound connection/delta state stays
|
|
162
163
|
// apart without changing the visible Mixdog session, so no stale server state
|
|
163
164
|
// crosses an account switch. `emitted()` reports whether output reached the
|
|
164
|
-
// caller.
|
|
165
|
-
|
|
165
|
+
// caller. `servedBy` names the account a history message or provider state
|
|
166
|
+
// came from; only that account's replay and state are passed on.
|
|
167
|
+
const replayAccount = (entry) => entry?.providerReplay?.accountId ?? entry?.providerAccountId;
|
|
168
|
+
|
|
169
|
+
function boundAccountSend(providerName, row, messages, options, servedBy = replayAccount) {
|
|
166
170
|
let emitted = false;
|
|
167
171
|
const opts = { ...options };
|
|
168
172
|
for (const key of ['onStreamDelta', 'onTextDelta', 'onToolCall', 'onThinkingDelta']) {
|
|
@@ -178,9 +182,9 @@ function boundAccountSend(providerName, row, messages, options) {
|
|
|
178
182
|
// The spend still belongs to the visible session (usage-accounting.mjs).
|
|
179
183
|
opts.usageSessionId = options.usageSessionId || options.sessionId;
|
|
180
184
|
}
|
|
181
|
-
opts.providerState = options.providerState
|
|
185
|
+
opts.providerState = servedBy(options.providerState) === row.id ? options.providerState : undefined;
|
|
182
186
|
const history = messages.map((message) => {
|
|
183
|
-
if (message
|
|
187
|
+
if (servedBy(message) === row.id) return message;
|
|
184
188
|
const { providerReplay, reasoning, thinkingBlocks, ...plain } = message;
|
|
185
189
|
return plain;
|
|
186
190
|
});
|
|
@@ -204,7 +208,7 @@ async function commitFallbackAccount(providerName, pool, row, model, refusalScop
|
|
|
204
208
|
// the binding survives a restart and eviction from this map, which only
|
|
205
209
|
// spares the history walk. Bounded, oldest binding first out.
|
|
206
210
|
const SESSION_ACCOUNT_LIMIT = 1000;
|
|
207
|
-
const ROUTING_METADATA_KEY = 'accountRouting';
|
|
211
|
+
export const ROUTING_METADATA_KEY = 'accountRouting';
|
|
208
212
|
const sessionAccounts = new Map();
|
|
209
213
|
|
|
210
214
|
// Forget every in-memory binding, as a restart does (tests).
|
|
@@ -244,6 +248,17 @@ function sessionAccountId(providerName, key, messages, options) {
|
|
|
244
248
|
return null;
|
|
245
249
|
}
|
|
246
250
|
|
|
251
|
+
/** The account a send of `model` for `sessionId` would try first right now —
|
|
252
|
+
* the session's binding and the choice poolSend makes for its first attempt
|
|
253
|
+
* — or null when the provider has no roster account or none is eligible. */
|
|
254
|
+
export function plannedAccountId(providerName, { sessionId = null, messages = [], providerState, model = '' } = {}) {
|
|
255
|
+
const pool = readProviderAccountPool(providerName);
|
|
256
|
+
if (!pool.accounts.length) return null;
|
|
257
|
+
const sessionKey = sessionId ? `${providerName}:${sessionId}` : null;
|
|
258
|
+
const boundId = sessionAccountId(providerName, sessionKey, messages, { providerState });
|
|
259
|
+
return chooseProviderAccount(pool, new Set(), Date.now(), model, { sessionAccountId: boundId })?.id || null;
|
|
260
|
+
}
|
|
261
|
+
|
|
247
262
|
// Stamp the serving account on the answer, independent of transport state,
|
|
248
263
|
// with the account the session stays bound to (`bindingId`).
|
|
249
264
|
function recordServingAccount(providerName, result, id, bindingId) {
|
|
@@ -509,7 +524,7 @@ function rotationReason(evidence, accountBlocked) {
|
|
|
509
524
|
|
|
510
525
|
// The pool's send: walks the eligible accounts until one answers, blocking
|
|
511
526
|
// the ones whose quota window is exhausted along the way.
|
|
512
|
-
function poolSend(providerName, account) {
|
|
527
|
+
function poolSend(providerName, account, servedBy) {
|
|
513
528
|
return async function send(messages, model, tools, options = {}) {
|
|
514
529
|
const request = { providerName, model, account, options };
|
|
515
530
|
// This send's record of the roster: the accounts it tried, those it found
|
|
@@ -530,7 +545,8 @@ function poolSend(providerName, account) {
|
|
|
530
545
|
options.signal?.throwIfAborted();
|
|
531
546
|
const pool = readProviderAccountPool(providerName);
|
|
532
547
|
if (!pool.accounts.length) {
|
|
533
|
-
|
|
548
|
+
// A custom provider's key has no plan meter to consult.
|
|
549
|
+
if (!isCustomKeyProvider(providerName)) throwIfPlanQuotaSpent(providerName, pool, model);
|
|
534
550
|
return account('default').send(messages, model, tools, options);
|
|
535
551
|
}
|
|
536
552
|
const policy = providerAccountPolicy(pool);
|
|
@@ -548,7 +564,7 @@ function poolSend(providerName, account) {
|
|
|
548
564
|
}
|
|
549
565
|
ledger.attempted.add(row.id);
|
|
550
566
|
sends += 1;
|
|
551
|
-
const bound = boundAccountSend(providerName, row, messages, options);
|
|
567
|
+
const bound = boundAccountSend(providerName, row, messages, options, servedBy);
|
|
552
568
|
try {
|
|
553
569
|
const result = await account(row.id).send(bound.history, model, tools, bound.opts);
|
|
554
570
|
quotaStrikes.delete(`${providerName}:${row.id}`);
|
|
@@ -649,3 +665,33 @@ export function createAccountPoolProvider(providerName, create) {
|
|
|
649
665
|
}
|
|
650
666
|
);
|
|
651
667
|
}
|
|
668
|
+
|
|
669
|
+
// Every key of a custom provider reaches one endpoint, so its answers carry
|
|
670
|
+
// no key-bound server state but what an answer's routing names: history from
|
|
671
|
+
// before the key pool (or from no pooled send) is the primary key's.
|
|
672
|
+
function customKeyServedBy(providerName) {
|
|
673
|
+
return (entry) => {
|
|
674
|
+
const routing = entry?.providerMetadata?.[ROUTING_METADATA_KEY];
|
|
675
|
+
if (routing?.provider === providerName && routing.accountId) return routing.accountId;
|
|
676
|
+
return replayAccount(entry) || 'default';
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
/**
|
|
681
|
+
* A custom provider's API keys as one roster (provider-accounts.mjs
|
|
682
|
+
* `setCustomProviderKeyIds`): `primary` is the `default` account and answers
|
|
683
|
+
* everything but `send`; `keyEngine(id)` is the engine sending with
|
|
684
|
+
* additional key `id`. Without additional keys the roster is empty and every
|
|
685
|
+
* send is the primary's own, unchanged.
|
|
686
|
+
*/
|
|
687
|
+
export function createCustomKeyPoolProvider(providerName, primary, keyEngine) {
|
|
688
|
+
const engines = new Map([['default', primary]]);
|
|
689
|
+
const account = (id) => {
|
|
690
|
+
if (!engines.has(id)) engines.set(id, keyEngine(id));
|
|
691
|
+
return engines.get(id);
|
|
692
|
+
};
|
|
693
|
+
const send = poolSend(providerName, account, customKeyServedBy(providerName));
|
|
694
|
+
return new Proxy(primary, {
|
|
695
|
+
get: (target, key, receiver) => (key === 'send' ? send : Reflect.get(target, key, receiver)),
|
|
696
|
+
});
|
|
697
|
+
}
|
|
@@ -52,7 +52,7 @@ export function createAnthropicApiRecovery({
|
|
|
52
52
|
: PROVIDER_NONSTREAM_TOTAL_TIMEOUT_MS;
|
|
53
53
|
const lifetime = createTimeoutSignal(totalSignal, timeoutMs, `${label} Anthropic non-streaming fallback`);
|
|
54
54
|
try {
|
|
55
|
-
const message = await transport.requestNonStreamingMessage(nonStreamingParams, lifetime.signal);
|
|
55
|
+
const message = await transport.requestNonStreamingMessage(nonStreamingParams, lifetime.signal, timeoutMs);
|
|
56
56
|
return buildTurnResult(normalizeAnthropicNonStreamingResponse(message, useModel));
|
|
57
57
|
} catch (error) {
|
|
58
58
|
if (error instanceof AnthropicFallbackTriggeredError || totalSignal?.aborted) throw error;
|
|
@@ -10,7 +10,11 @@
|
|
|
10
10
|
* anthropic-turn-result.mjs); nothing here touches the socket.
|
|
11
11
|
*/
|
|
12
12
|
import { prepareAnthropicImages } from './lib/anthropic-image-input.mjs';
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
anthropicPrefixFingerprint,
|
|
15
|
+
anthropicPrefixSessionId,
|
|
16
|
+
recordAnthropicPrefix,
|
|
17
|
+
} from './lib/anthropic-prefix-trace.mjs';
|
|
14
18
|
import { buildAnthropicBetaHeaders, supportsAnthropicFastMode } from './anthropic-betas.mjs';
|
|
15
19
|
import { applyAnthropicServerFallback } from './anthropic-server-fallback.mjs';
|
|
16
20
|
import { fastModeAvailable } from './anthropic-fast-mode.mjs';
|
|
@@ -93,7 +97,7 @@ export async function buildAnthropicApiRequest({
|
|
|
93
97
|
// Tools are resolved BEFORE the messages: the lowering needs the final
|
|
94
98
|
// tool list to drop tool_reference blocks whose tool no longer ships
|
|
95
99
|
// in this request (otherwise the API rejects the whole turn).
|
|
96
|
-
const requestTools = requestAnthropicTools(tools, chatMsgs, opts, name);
|
|
100
|
+
const requestTools = requestAnthropicTools(tools, chatMsgs, opts, name, config);
|
|
97
101
|
// Message-tail cache budget (4-BP layout + ANTHROPIC_MSG_SLOTS) is
|
|
98
102
|
// shared with anthropic-oauth — see resolveAnthropicMessageCacheSlots.
|
|
99
103
|
const messageCacheSlots = resolveAnthropicMessageCacheSlots(systemBlocks, ttls, { tools: requestTools });
|
|
@@ -183,10 +187,9 @@ export async function buildAnthropicApiRequest({
|
|
|
183
187
|
// (once) → mark → prepare image bytes → send.
|
|
184
188
|
params.stream = true;
|
|
185
189
|
// Diagnostic: per-block prefix hashes of exactly what is sent.
|
|
186
|
-
recordAnthropicPrefix(opts
|
|
190
|
+
recordAnthropicPrefix(anthropicPrefixSessionId(opts), anthropicPrefixFingerprint(params));
|
|
187
191
|
|
|
188
|
-
const
|
|
189
|
-
config,
|
|
192
|
+
const betas = requestBetasFor(params, {
|
|
190
193
|
opts,
|
|
191
194
|
isCustom,
|
|
192
195
|
fastLatched,
|
|
@@ -194,8 +197,10 @@ export async function buildAnthropicApiRequest({
|
|
|
194
197
|
capabilityModel,
|
|
195
198
|
effortProjection,
|
|
196
199
|
});
|
|
200
|
+
const requestHeaders = requestHeadersFor(betas, { config, opts });
|
|
197
201
|
|
|
198
|
-
|
|
202
|
+
// `betas`: the selected beta names, whether or not this route sends them as a header.
|
|
203
|
+
return { params, requestHeaders, betas, knownToolNames, fastModeLatched: fastLatched };
|
|
199
204
|
}
|
|
200
205
|
|
|
201
206
|
/** The turn's thinking/effort fields on `params` (in place): a custom
|
|
@@ -243,35 +248,36 @@ function resolveRequestToolChoice(params, opts, config) {
|
|
|
243
248
|
else delete params.tool_choice;
|
|
244
249
|
}
|
|
245
250
|
|
|
246
|
-
/** The
|
|
247
|
-
*
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
251
|
+
/** The anthropic-beta names the final body `params` needs. A custom endpoint
|
|
252
|
+
* gets no first-party base betas; only those its own request body needs
|
|
253
|
+
* (row-driven effort, deferred tools). */
|
|
254
|
+
function requestBetasFor(params, { opts, isCustom, fastLatched, hasDeferredTools, capabilityModel, effortProjection }) {
|
|
255
|
+
return [
|
|
256
|
+
buildAnthropicBetaHeaders({
|
|
257
|
+
...(isCustom ? { base: '' } : {}),
|
|
258
|
+
fastMode: fastLatched,
|
|
259
|
+
toolSearch: hasDeferredTools,
|
|
260
|
+
// Custom: the beta follows the resolver's output, not the model id.
|
|
261
|
+
effort: isCustom ? Boolean(params.output_config?.effort) : shouldIncludeEffortBeta(capabilityModel, opts),
|
|
262
|
+
serverFallback: params.fallbacks === 'default',
|
|
263
|
+
thinkingDisplayUpdates: params.thinking?.display === 'updates',
|
|
264
|
+
turnScopedSystem: hasAnthropicTurnScopedMessages(params.messages),
|
|
265
|
+
}),
|
|
266
|
+
...(effortProjection ? [EFFORT_CONFIGURATION_BETA] : []),
|
|
267
|
+
]
|
|
268
|
+
.join(',')
|
|
269
|
+
.split(',')
|
|
270
|
+
.filter(Boolean);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/** The per-request headers: the anthropic-beta header of `betas`, then the
|
|
274
|
+
* caller's `opts.requestHeaders`; null when none. */
|
|
275
|
+
function requestHeadersFor(betas, { config, opts }) {
|
|
252
276
|
// Per-call headers override the client defaultHeaders, so the
|
|
253
277
|
// constructor-level disableBetaHeaders opt-out must be honoured here
|
|
254
278
|
// too — otherwise opencode-go's anthropic-compatible routing
|
|
255
279
|
// (disableBetaHeaders:true) would still send beta strings that a
|
|
256
280
|
// third-party endpoint may reject.
|
|
257
|
-
|
|
258
|
-
// request body needs (row-driven effort, deferred tools).
|
|
259
|
-
let betaHeaders = null;
|
|
260
|
-
if (!config?.disableBetaHeaders) {
|
|
261
|
-
const betas = [
|
|
262
|
-
buildAnthropicBetaHeaders({
|
|
263
|
-
...(isCustom ? { base: '' } : {}),
|
|
264
|
-
fastMode: fastLatched,
|
|
265
|
-
toolSearch: hasDeferredTools,
|
|
266
|
-
// Custom: the beta follows the resolver's output, not the model id.
|
|
267
|
-
effort: isCustom ? Boolean(params.output_config?.effort) : shouldIncludeEffortBeta(capabilityModel, opts),
|
|
268
|
-
serverFallback: params.fallbacks === 'default',
|
|
269
|
-
thinkingDisplayUpdates: params.thinking?.display === 'updates',
|
|
270
|
-
turnScopedSystem: hasAnthropicTurnScopedMessages(params.messages),
|
|
271
|
-
}),
|
|
272
|
-
...(effortProjection ? [EFFORT_CONFIGURATION_BETA] : []),
|
|
273
|
-
].filter(Boolean);
|
|
274
|
-
if (betas.length) betaHeaders = { 'anthropic-beta': betas.join(',') };
|
|
275
|
-
}
|
|
281
|
+
const betaHeaders = !config?.disableBetaHeaders && betas.length ? { 'anthropic-beta': betas.join(',') } : null;
|
|
276
282
|
return betaHeaders || opts.requestHeaders ? { ...(betaHeaders || {}), ...(opts.requestHeaders || {}) } : null;
|
|
277
283
|
}
|
|
@@ -215,12 +215,18 @@ export function createAnthropicApiTransport({
|
|
|
215
215
|
}
|
|
216
216
|
};
|
|
217
217
|
|
|
218
|
-
|
|
218
|
+
// `timeoutMs` is the replay's own lifetime, handed to the SDK as the request
|
|
219
|
+
// timeout: without an explicit one the SDK refuses any stream:false body
|
|
220
|
+
// whose max_tokens it estimates past 10 minutes before sending it.
|
|
221
|
+
const requestNonStreamingMessage = (nonStreamingParams, signal, timeoutMs) =>
|
|
219
222
|
withRetry(
|
|
220
223
|
withBodyRecovery(nonStreamingParams, async ({ signal: attemptSignal }) => {
|
|
221
224
|
noteRequestServiceTier(nonStreamingParams.speed);
|
|
222
225
|
try {
|
|
223
|
-
return await client.messages.create(nonStreamingParams,
|
|
226
|
+
return await client.messages.create(nonStreamingParams, {
|
|
227
|
+
...requestOptions(attemptSignal),
|
|
228
|
+
timeout: timeoutMs,
|
|
229
|
+
});
|
|
224
230
|
} catch (err) {
|
|
225
231
|
throw annotateHttpFailure(err);
|
|
226
232
|
}
|
|
@@ -22,11 +22,15 @@ export function parseMaxTokensContextOverflow(status, message) {
|
|
|
22
22
|
const match = OVERFLOW_RE.exec(String(message || ''));
|
|
23
23
|
if (!match) return null;
|
|
24
24
|
const [inputTokens, maxTokens, contextLimit] = match.slice(1).map((value) => Number.parseInt(value, 10));
|
|
25
|
-
return [inputTokens, maxTokens, contextLimit].every(Number.isFinite)
|
|
25
|
+
return [inputTokens, maxTokens, contextLimit].every(Number.isFinite)
|
|
26
|
+
? { inputTokens, maxTokens, contextLimit }
|
|
27
|
+
: null;
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
const thinkingBudget = (body) =>
|
|
29
|
-
body?.thinking?.type === 'enabled' && Number(body.thinking.budget_tokens) > 0
|
|
31
|
+
body?.thinking?.type === 'enabled' && Number(body.thinking.budget_tokens) > 0
|
|
32
|
+
? Number(body.thinking.budget_tokens)
|
|
33
|
+
: 0;
|
|
30
34
|
|
|
31
35
|
/**
|
|
32
36
|
* Shrink `body.max_tokens` to fit the reported context. Returns true when the
|
|
@@ -159,8 +159,8 @@ function deferredAnthropicTools(activeTools, messages, opts, provider = 'anthrop
|
|
|
159
159
|
return sharedDeferredAnthropicTools(activeTools, messages, opts, provider);
|
|
160
160
|
}
|
|
161
161
|
// `provider`: the engine's name (a gateway Messages engine runs under its gateway's).
|
|
162
|
-
export function requestAnthropicTools(tools, messages, opts, provider = 'anthropic') {
|
|
163
|
-
return sharedRequestAnthropicTools(tools, messages, opts, provider);
|
|
162
|
+
export function requestAnthropicTools(tools, messages, opts, provider = 'anthropic', config = {}) {
|
|
163
|
+
return sharedRequestAnthropicTools(tools, messages, opts, provider, config);
|
|
164
164
|
}
|
|
165
165
|
// Test-only: expose the lowering so the steering-provenance test can assert
|
|
166
166
|
// the API-key provider keeps steering-tagged user turns distinct (mirrors
|
|
@@ -10,7 +10,7 @@ import { createNpmVersionSource, maxSemver } from './npm-cli-version.mjs';
|
|
|
10
10
|
// source release just to advance the user-agent version.
|
|
11
11
|
// Claude Opus 5.5 requires 2.1.280 or newer. The release workflow raises this
|
|
12
12
|
// to the published CLI version (scripts/sync-client-version-floors.mjs).
|
|
13
|
-
export const DEFAULT_CLI_VERSION = '2.1.
|
|
13
|
+
export const DEFAULT_CLI_VERSION = '2.1.312';
|
|
14
14
|
export const CLAUDE_CLI_NPM_PACKAGE = '@anthropic-ai/claude-code';
|
|
15
15
|
|
|
16
16
|
const CACHE_SCHEMA_VERSION = 1;
|