mixdog 1.4.1 → 1.4.3
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 +4 -3
- package/scripts/build-shipped-history.mjs +125 -33
- package/scripts/gate-local.mjs +220 -63
- package/scripts/graph-parity.mjs +8 -3
- package/scripts/lib/gate-scheduler.mjs +139 -32
- package/scripts/lib/gate-timing-reporter.mjs +16 -0
- package/scripts/lib/run-node-tests.mjs +71 -34
- package/scripts/lib/scoped-temp.mjs +1 -0
- package/scripts/lib/test-failure-records.mjs +14 -1
- package/scripts/lib/test-failure-summary.mjs +9 -4
- package/scripts/lib/test-spawn-ledger.mjs +43 -3
- package/scripts/post-release-check.mjs +26 -16
- package/scripts/pptx-kit-index.mjs +5 -6
- package/scripts/provider-pingpong-live.mjs +1 -1
- package/scripts/prune-embedding-runtime.mjs +3 -1
- package/scripts/release-paths.mjs +7 -1
- package/scripts/suite-health.mjs +110 -28
- 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/cli.mjs +7 -0
- package/src/defaults/agents.json +7 -0
- package/src/defaults/shipped-history.json +38 -2
- package/src/defaults/skills/browser-use/SKILL.md +4 -1
- 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 +12 -2
- package/src/defaults/skills/setup/SKILL.md +2 -2
- package/src/defaults/skills/setup/references/actions.md +28 -9
- package/src/defaults/skills/setup/references/surfaces.md +5 -2
- package/src/defaults/skills/setup-guide/SKILL.md +11 -3
- 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/instruction-text.cjs +36 -0
- package/src/lib/rules-builder.cjs +40 -50
- package/src/orchestration/balanced.md +23 -0
- package/src/orchestration/focused.md +22 -0
- package/src/orchestration/none.md +5 -0
- package/src/orchestration/swarm.md +24 -0
- package/src/rules/agent-mode/AGENT_MODE.md +3 -1
- package/src/rules/agent-mode/MIXY.md +2 -2
- package/src/rules/lead/LEAD.md +3 -3
- package/src/rules/shared/20-research.md +3 -6
- package/src/rules/shared/40-editing.md +1 -0
- package/src/rules/shared/60-verification.md +10 -9
- package/src/rules/shared/70-delivery.md +4 -3
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +3 -3
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -2
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +132 -21
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -9
- package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +2 -2
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +67 -0
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +1 -0
- package/src/runtime/agent/orchestrator/config.mjs +12 -7
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +7 -7
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +9 -30
- package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +124 -12
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +204 -49
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +16 -7
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +157 -57
- package/src/runtime/agent/orchestrator/mcp/client.mjs +54 -23
- package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +1 -1
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +8 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +83 -52
- package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +1 -1
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +14 -0
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +43 -27
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +43 -8
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +30 -28
- 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-sse-turn/turn-events/content-block-stop.mjs +3 -3
- 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.mjs +1 -1
- 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/gemini-response.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +48 -31
- 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.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-response-normalization.mjs +4 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2784 -2872
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +5 -8
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +26 -28
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +288 -300
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +1 -0
- 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 +33 -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 +576 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +10 -30
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +32 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +0 -11
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +8 -0
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +17 -3
- package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +47 -27
- package/src/runtime/agent/orchestrator/runtime-core/goal-deadlines.mjs +141 -10
- package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +26 -63
- package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +28 -3
- package/src/runtime/agent/orchestrator/runtime-core/goal-runtime.mjs +36 -11
- package/src/runtime/agent/orchestrator/runtime-core/goal-state.mjs +88 -56
- package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +51 -32
- package/src/runtime/agent/orchestrator/runtime-core/goal-text.mjs +45 -145
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +15 -98
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +32 -99
- package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +23 -78
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +69 -47
- package/src/runtime/agent/orchestrator/runtime-core/todo-list.mjs +367 -0
- package/src/runtime/agent/orchestrator/runtime-core/todo-tool-defs.mjs +47 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-availability.mjs +155 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +12 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +119 -35
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +15 -6
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +28 -22
- package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +30 -0
- 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/attachment-preflight.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +94 -10
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -12
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +4 -4
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +11 -6
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +6 -6
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +7 -3
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +11 -1
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +37 -8
- package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/image-strip-recovery.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +11 -1
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +8 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/todo-check.mjs +196 -0
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +116 -50
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +8 -1
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +5 -6
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +27 -3
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +18 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
- package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
- package/src/runtime/agent/orchestrator/session/loop/turn-report.mjs +35 -0
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +103 -50
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +9 -7
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +21 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +27 -11
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-open.mjs +37 -34
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +25 -15
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +79 -24
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +12 -1
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +9 -1
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-path.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/prompt-settings.mjs +598 -0
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -14
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +56 -14
- package/src/runtime/agent/orchestrator/session/manager/session-lock.mjs +31 -0
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +59 -20
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +2 -0
- 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 +18 -4
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +8 -9
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +339 -88
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +135 -11
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +377 -104
- package/src/runtime/agent/orchestrator/session/manager/turn-durability.mjs +144 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +48 -30
- package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +12 -6
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +8 -1
- package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/save-session-worker.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +23 -2
- package/src/runtime/agent/orchestrator/session/store/sweep/sub-agent-retention.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/store/transcript-durability.mjs +88 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/store-summary-log.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +243 -38
- package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +177 -8
- package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
- package/src/runtime/agent/orchestrator/session/store.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +9 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/agent-envelope.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +2 -2
- package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -5
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +21 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/worktree-add-guard.mjs +77 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +0 -1
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +42 -28
- package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +30 -14
- package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
- package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +0 -1
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
- package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +0 -10
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +95 -20
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +1 -24
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary/child-kill.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +1 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/modes/calls.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/modes/symbols.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +4 -5
- package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +3 -4
- package/src/runtime/agent/orchestrator/tools/code-graph.mjs +4 -22
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- 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 +105 -15
- 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 +35 -11
- package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -6
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +0 -1
- package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
- package/src/runtime/attachments/attachment-reference.mjs +1 -1
- package/src/runtime/attachments/pdf-extract.mjs +1 -1
- package/src/runtime/attachments/store.d.mts +1 -0
- package/src/runtime/attachments/store.mjs +2 -2
- package/src/runtime/channels/lib/config-reload-watch.mjs +42 -0
- package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +29 -9
- package/src/runtime/channels/lib/scheduler.mjs +33 -0
- package/src/runtime/channels/lib/schedules-db.mjs +11 -4
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +4 -1
- package/src/runtime/channels/lib/webhooks-db.mjs +9 -3
- package/src/runtime/channels/lib/whisper-port.mjs +19 -10
- package/src/runtime/channels/lib/whisper-server.mjs +22 -13
- package/src/runtime/channels/lib/worker-main.mjs +9 -31
- package/src/runtime/computer-bridge/linux-readiness.mjs +10 -14
- package/src/runtime/connectors/connector-accounts-mcp.mjs +372 -103
- package/src/runtime/connectors/gmail-app-password.mjs +4 -4
- package/src/runtime/connectors/google-mcp.mjs +1 -1
- package/src/runtime/effort-judge/judge-client.mjs +2 -2
- package/src/runtime/effort-judge/judge-input.mjs +4 -4
- package/src/runtime/explore/explorer.mjs +88 -0
- package/src/runtime/explore/tool-defs.mjs +35 -0
- package/src/runtime/explore/tool.mjs +123 -0
- package/src/runtime/local-provider/hardware.mjs +1 -1
- package/src/runtime/media/adapters/codex-image.mjs +3 -3
- package/src/runtime/media/adapters/gemini-video.mjs +1 -1
- package/src/runtime/media/media-usage.mjs +1 -1
- package/src/runtime/media/store.mjs +1 -1
- package/src/runtime/memory/index.mjs +15 -1
- package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
- package/src/runtime/memory/lib/embedding-reindex.mjs +27 -0
- package/src/runtime/memory/lib/embedding-worker.mjs +4 -0
- package/src/runtime/memory/lib/memory-embed.mjs +83 -14
- package/src/runtime/memory/lib/memory-process-lock.mjs +159 -36
- package/src/runtime/memory/lib/memory-text-utils.mjs +6 -1
- package/src/runtime/memory/lib/memory.mjs +17 -0
- package/src/runtime/memory/lib/pg/process.mjs +1 -1
- package/src/runtime/memory/lib/pg/supervisor.mjs +16 -96
- package/src/runtime/memory/lib/recall-hybrid/hybrid-sql.mjs +12 -3
- package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
- package/src/runtime/office/authoring/pptx-author-action.mjs +1 -1
- package/src/runtime/office/authoring/xlsx-html-build.mjs +1 -1
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
- package/src/runtime/office/capabilities.mjs +1 -1
- package/src/runtime/office/core/office-core.mjs +1 -1
- package/src/runtime/office/design/content-model.mjs +3 -3
- package/src/runtime/office/design/docx/design-docx/section.mjs +6 -6
- package/src/runtime/office/design/xlsx/design-xlsx-components.mjs +1 -1
- package/src/runtime/office/design/xlsx/design-xlsx.mjs +1 -1
- package/src/runtime/office/pdf/ocr-engine.mjs +1 -1
- package/src/runtime/office/pdf/pdf-writer.mjs +4 -4
- package/src/runtime/office/portable/portable-docx-operations.mjs +2 -2
- package/src/runtime/office/portable/portable-soffice.mjs +8 -6
- package/src/runtime/office/portable/xlsx-contract.mjs +1 -1
- package/src/runtime/office/quality/assurance-structure-docx.mjs +1 -1
- package/src/runtime/shared/agent-route-config.mjs +17 -2
- package/src/runtime/shared/atomic-file.d.mts +8 -0
- package/src/runtime/shared/atomic-file.mjs +103 -2
- package/src/runtime/shared/background-tasks.mjs +37 -10
- package/src/runtime/shared/background-wait.mjs +66 -0
- package/src/runtime/shared/child-guardian.mjs +17 -7
- package/src/runtime/shared/config.mjs +313 -16
- package/src/runtime/shared/connector-accounts.mjs +5 -5
- package/src/runtime/shared/connector-catalog.d.mts +14 -8
- package/src/runtime/shared/connector-catalog.mjs +70 -52
- package/src/runtime/shared/custom-provider-keys.mjs +20 -0
- package/src/runtime/shared/file-has-data.mjs +26 -2
- package/src/runtime/shared/file-lock.mjs +21 -18
- 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/git-runner.mjs +7 -2
- package/src/runtime/shared/idle-gc.mjs +30 -7
- package/src/runtime/shared/llm/cost.mjs +6 -1
- package/src/runtime/shared/llm/http-agent.mjs +316 -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 +453 -0
- package/src/runtime/shared/llm/usage-ledger-quota.mjs +31 -12
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +84 -8
- package/src/runtime/shared/llm/usage-ledger.mjs +3 -0
- package/src/runtime/shared/llm/usage-rollup.mjs +48 -0
- package/src/runtime/shared/maintenance-schedule.mjs +109 -0
- package/src/runtime/shared/process-runner.mjs +8 -4
- package/src/runtime/shared/provider-accounts.mjs +52 -2
- package/src/runtime/shared/routine-trigger.d.mts +13 -0
- package/src/runtime/shared/routine-trigger.mjs +34 -0
- package/src/runtime/shared/run-child.d.mts +2 -1
- package/src/runtime/shared/run-child.mjs +70 -18
- package/src/runtime/shared/session-scratch.mjs +14 -2
- package/src/runtime/shared/shipped-definitions.mjs +7 -1
- 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.golden.json +3 -12
- package/src/runtime/shared/tool-execution-contract.mjs +2 -0
- package/src/runtime/shared/tool-surface.mjs +110 -36
- package/src/runtime/shared/tool-work-units.mjs +35 -6
- package/src/runtime/shared/turn-snapshot.mjs +26 -4
- package/src/runtime/shared/turn-worktree-snapshot.mjs +409 -54
- package/src/runtime/shared/worker-requests.mjs +17 -3
- 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 +5 -3
- package/src/runtime/shared/worktrees/contract.mjs +16 -6
- package/src/runtime/shared/worktrees/dependencies.mjs +127 -89
- package/src/runtime/shared/worktrees/disk.mjs +79 -2
- package/src/runtime/shared/worktrees/git.mjs +97 -7
- package/src/runtime/shared/worktrees/include.mjs +6 -4
- package/src/runtime/shared/worktrees/maintenance.mjs +422 -30
- package/src/runtime/shared/worktrees/manager.mjs +962 -197
- package/src/runtime/shared/worktrees/settings.mjs +33 -7
- package/src/runtime/shared/worktrees/test-support.mjs +5 -1
- package/src/runtime/shared/worktrees/worker-snapshots.mjs +82 -0
- package/src/runtime/tidy/install.mjs +95 -15
- package/src/runtime/tidy/languages.mjs +17 -15
- package/src/runtime/tidy/process.mjs +9 -5
- 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 +4 -1
- package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
- package/src/runtime/web-search/index.mjs +4 -23
- package/src/runtime/web-search/lib/web-tools.mjs +2 -2
- package/src/runtime/web-search/tool-defs.mjs +17 -26
- package/src/session-runtime/agent-profile-changes.mjs +55 -4
- package/src/session-runtime/agent-task-sessions.mjs +410 -353
- package/src/session-runtime/boot/apis.mjs +27 -4
- package/src/session-runtime/boot/begin.mjs +2 -0
- package/src/session-runtime/boot/config.mjs +10 -1
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/providers.mjs +70 -3
- package/src/session-runtime/boot/session.mjs +2 -0
- package/src/session-runtime/boot/tools.mjs +71 -25
- package/src/session-runtime/bot-status.mjs +103 -103
- package/src/session-runtime/channel-config-api.mjs +1 -0
- package/src/session-runtime/config-change-effects.mjs +179 -0
- package/src/session-runtime/config-lifecycle/config-writers.mjs +1 -0
- package/src/session-runtime/config-lifecycle.mjs +160 -24
- package/src/session-runtime/connector-merge-migration.mjs +18 -15
- package/src/session-runtime/conversation-import/discovery.mjs +245 -47
- package/src/session-runtime/conversation-import/service.mjs +12 -5
- package/src/session-runtime/goal-facade-api.mjs +49 -3
- package/src/session-runtime/handoff-attachments.mjs +1 -1
- package/src/session-runtime/held-requests.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +3 -0
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -2
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -11
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +161 -120
- package/src/session-runtime/internal-tool-executor.mjs +12 -19
- package/src/session-runtime/lifecycle/cold-heir.mjs +7 -0
- package/src/session-runtime/lifecycle/memory-ingest.mjs +3 -3
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +53 -5
- package/src/session-runtime/lifecycle/session-switch.mjs +13 -2
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +10 -5
- package/src/session-runtime/lifecycle/teardown.mjs +1 -1
- package/src/session-runtime/lifecycle-api.mjs +1 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +27 -10
- package/src/session-runtime/mcp-glue/server-connection.mjs +34 -8
- 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 +40 -7
- package/src/session-runtime/native-web-search/routes.mjs +3 -3
- package/src/session-runtime/provider-auth/login.mjs +2 -2
- package/src/session-runtime/provider-auth/refresh.mjs +6 -3
- package/src/session-runtime/provider-auth/setup.mjs +1 -1
- package/src/session-runtime/provider-readiness.mjs +53 -4
- package/src/session-runtime/resource-api.mjs +1 -1
- package/src/session-runtime/resource-extension-sync.mjs +4 -8
- package/src/session-runtime/resource-mcp-api.mjs +98 -35
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +49 -32
- package/src/session-runtime/resource-mcp-secrets.mjs +27 -10
- package/src/session-runtime/resource-mcp-servers.mjs +5 -4
- package/src/session-runtime/resource-plugins-api.mjs +4 -0
- package/src/session-runtime/routine-executor.mjs +152 -0
- package/src/session-runtime/routine-home-turn.mjs +46 -5
- package/src/session-runtime/runtime-facade.mjs +5 -0
- package/src/session-runtime/runtime-feature-gates.mjs +2 -11
- package/src/session-runtime/schedule-session-run.mjs +1 -0
- package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +6 -1
- package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +7 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +120 -8
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +12 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +5 -0
- 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 +28 -7
- package/src/session-runtime/services/agent-tool.mjs +51 -1
- package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
- package/src/session-runtime/services/channel-admin.mjs +18 -0
- 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/hook-bus/command-handler.mjs +7 -11
- package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
- package/src/session-runtime/services/plugin-admin.mjs +14 -6
- package/src/session-runtime/services/provider-admin.mjs +281 -10
- package/src/session-runtime/services/seeds.mjs +7 -0
- package/src/session-runtime/services/usage-stats-model.mjs +32 -11
- package/src/session-runtime/session-create/materialize.mjs +4 -2
- package/src/session-runtime/session-create/session-options.mjs +2 -0
- package/src/session-runtime/session-turn-api.mjs +2 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +5 -10
- 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 +14 -3
- package/src/session-runtime/setup-tool/extended-actions.mjs +2 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +28 -0
- package/src/session-runtime/setup-tool/tool-defs.mjs +28 -2
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +40 -43
- package/src/session-runtime/tool-policy/mode-switch.mjs +1 -1
- package/src/session-runtime/tool-policy/policy-stage.mjs +106 -8
- package/src/session-runtime/tool-policy/workflow-overlay.mjs +2 -1
- package/src/session-runtime/tool-policy-refresh.mjs +182 -5
- package/src/session-runtime/tool-surface.mjs +38 -1
- package/src/session-runtime/turn/agent-ops.mjs +33 -2
- package/src/session-runtime/turn/session-ops.mjs +2 -0
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +5 -0
- package/src/session-runtime/turn/turn-run.mjs +1 -1
- package/src/session-runtime/webhook-session-run.mjs +2 -0
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +46 -11
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +2 -0
- package/src/session-runtime/workflow-agents-api/instruction-files.mjs +165 -0
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +5 -4
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +2 -3
- package/src/session-runtime/workflow-agents-api.mjs +2 -0
- package/src/session-runtime/workspace/activity-guards.mjs +176 -0
- package/src/session-runtime/workspace/project-branches.mjs +1 -1
- 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 +128 -1070
- 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 +200 -0
- package/src/session-runtime/workspace/worktree-setup.mjs +97 -0
- package/src/session-runtime/workspace/worktree-tool.mjs +70 -54
- package/src/standalone/daemon-agent-control.mjs +25 -8
- package/src/standalone/daemon-desktop-runtime.mjs +8 -2
- package/src/standalone/daemon-lag-profiler.mjs +7 -7
- package/src/standalone/daemon-session-control.mjs +151 -136
- package/src/standalone/daemon.mjs +61 -2
- package/src/standalone/desktop-service-registry.mjs +9 -0
- package/src/standalone/local-session-runtime.mjs +21 -1
- package/src/standalone/session-client/daemon-unavailable.mjs +4 -1
- package/src/standalone/session-client.mjs +5 -1
- package/src/standalone/session-frame-stream.mjs +83 -11
- package/src/standalone/session-protocol.mjs +15 -0
- package/src/standalone/session-service/agent-route-follow.mjs +23 -20
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +18 -6
- 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/quota-resume.mjs +9 -0
- package/src/standalone/session-service/session-calls/session-action.mjs +51 -1
- package/src/standalone/session-service/session-calls/session-turns.mjs +37 -18
- package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
- package/src/standalone/session-service/session-calls/turn-gate.mjs +34 -0
- package/src/standalone/session-service/session-calls.mjs +2 -1
- package/src/standalone/session-service/stored-reader.mjs +127 -40
- package/src/tui/App.jsx +162 -164
- package/src/tui/app/app-view/floating-panel.jsx +3 -0
- package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
- package/src/tui/app/clipboard.mjs +22 -11
- package/src/tui/app/create-app-pickers.mjs +2 -0
- package/src/tui/app/doctor.mjs +2 -2
- package/src/tui/app/panel-signature.mjs +1 -1
- 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 +25 -6
- package/src/tui/app/provider-setup-picker.mjs +20 -13
- package/src/tui/app/settings-picker.mjs +53 -8
- package/src/tui/app/shell-layout/row-budgets.mjs +14 -12
- package/src/tui/app/slash-commands.mjs +2 -1
- package/src/tui/app/slash-dispatch/route-commands.mjs +1 -1
- package/src/tui/app/slash-dispatch/session-commands.mjs +47 -1
- 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 +5 -4
- 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 +48 -33
- 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 +20 -6
- 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/SignInUrl.jsx +68 -0
- package/src/tui/components/TextEntryPanel.jsx +76 -46
- package/src/tui/components/prompt-input/escape-policy.d.mts +0 -1
- package/src/tui/components/prompt-input/escape-policy.mjs +1 -1
- package/src/tui/components/question-panel-model.mjs +4 -4
- package/src/tui/components/sign-in-url-layout.mjs +24 -0
- package/src/tui/components/tool-execution/standard-card.jsx +3 -4
- package/src/tui/components/user-message-skills.mjs +1 -1
- package/src/tui/dist/index.mjs +2205 -1371
- package/src/tui/markdown/render-ansi.mjs +1 -1
- package/src/tui/session/agent-job-feed/notification-router.mjs +10 -0
- package/src/tui/session/agent-job-feed.mjs +2 -0
- package/src/tui/session/context-state.mjs +3 -0
- package/src/tui/session/goal-turn-state.mjs +6 -2
- package/src/tui/session/quota-resume.mjs +1 -1
- 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/lifecycle/dispose.mjs +1 -0
- package/src/tui/session/session-api/lifecycle/session-reset.mjs +7 -0
- package/src/tui/session/session-api/routes-agent-definitions.mjs +6 -0
- package/src/tui/session/session-api/settings.mjs +2 -2
- package/src/tui/session/session-api/worktree.mjs +13 -1
- package/src/tui/session/session-flow/drain.mjs +11 -14
- package/src/tui/session/tool-card-results/grouped-result.mjs +2 -2
- 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/tui/session/turn-quiet.mjs +1 -1
- package/src/tui/session/turn.mjs +3 -0
- package/src/tui/session/worktree-setup-notice.mjs +1 -1
- package/src/tui/spinner-meta.mjs +3 -3
- package/src/tui/spinner-verbs.mjs +2 -2
- package/src/defaults/skills/goal-management/SKILL.md +0 -169
- package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
- package/src/runtime/agent/orchestrator/runtime-core/goal-tasks.mjs +0 -156
- package/src/session-runtime/goal-tasks.mjs +0 -1
|
@@ -145,6 +145,20 @@ export function createOAuthProvider({ cache, flow, lifetimeSignal, client = null
|
|
|
145
145
|
// access_type=offline, without which no refresh token is issued).
|
|
146
146
|
if (client?.scopes) target.searchParams.set('scope', client.scopes.join(' '));
|
|
147
147
|
for (const [key, value] of Object.entries(client?.authParams || {})) target.searchParams.set(key, value);
|
|
148
|
+
// A dynamically registered client asks for offline access when the
|
|
149
|
+
// authorization server lists it (MCP SEP-2207): the SDK sends only the
|
|
150
|
+
// resource's scopes (Vercel's `openid`), and without `offline_access`
|
|
151
|
+
// such a server issues no refresh token, so the sign-in ends within the
|
|
152
|
+
// hour. `prompt=consent` is what the SDK adds beside that scope. An
|
|
153
|
+
// empty scope stays empty: the server's default scopes would be lost.
|
|
154
|
+
if (!client) {
|
|
155
|
+
const scope = target.searchParams.get('scope');
|
|
156
|
+
const offered = creds.discovery?.authorizationServerMetadata?.scopes_supported;
|
|
157
|
+
if (scope && offered?.includes('offline_access') && !scope.split(' ').includes('offline_access')) {
|
|
158
|
+
target.searchParams.set('scope', `${scope} offline_access`);
|
|
159
|
+
target.searchParams.append('prompt', 'consent');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
148
162
|
// The explicit sign-in's account mode (mcp-oauth-login.mjs) decides the
|
|
149
163
|
// provider's documented account-choice parameter, if any.
|
|
150
164
|
await flow.launchBrowser(withAccountParams(target.href, flow.launchBrowser.accountMode || 'connect').href);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash, randomBytes } from 'node:crypto';
|
|
2
2
|
import { readFileSync } from 'node:fs';
|
|
3
|
-
import keychain from '
|
|
3
|
+
import { keychainSecretStore as keychain } from '../../../shared/config.mjs';
|
|
4
4
|
import { openInBrowser } from '../../../shared/open-url.mjs';
|
|
5
5
|
import { normalizeMcpTransportUrl } from './client-config.mjs';
|
|
6
6
|
import {
|
|
@@ -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).
|
|
@@ -520,7 +524,7 @@ function rotationReason(evidence, accountBlocked) {
|
|
|
520
524
|
|
|
521
525
|
// The pool's send: walks the eligible accounts until one answers, blocking
|
|
522
526
|
// the ones whose quota window is exhausted along the way.
|
|
523
|
-
function poolSend(providerName, account) {
|
|
527
|
+
function poolSend(providerName, account, servedBy) {
|
|
524
528
|
return async function send(messages, model, tools, options = {}) {
|
|
525
529
|
const request = { providerName, model, account, options };
|
|
526
530
|
// This send's record of the roster: the accounts it tried, those it found
|
|
@@ -541,7 +545,8 @@ function poolSend(providerName, account) {
|
|
|
541
545
|
options.signal?.throwIfAborted();
|
|
542
546
|
const pool = readProviderAccountPool(providerName);
|
|
543
547
|
if (!pool.accounts.length) {
|
|
544
|
-
|
|
548
|
+
// A custom provider's key has no plan meter to consult.
|
|
549
|
+
if (!isCustomKeyProvider(providerName)) throwIfPlanQuotaSpent(providerName, pool, model);
|
|
545
550
|
return account('default').send(messages, model, tools, options);
|
|
546
551
|
}
|
|
547
552
|
const policy = providerAccountPolicy(pool);
|
|
@@ -559,7 +564,7 @@ function poolSend(providerName, account) {
|
|
|
559
564
|
}
|
|
560
565
|
ledger.attempted.add(row.id);
|
|
561
566
|
sends += 1;
|
|
562
|
-
const bound = boundAccountSend(providerName, row, messages, options);
|
|
567
|
+
const bound = boundAccountSend(providerName, row, messages, options, servedBy);
|
|
563
568
|
try {
|
|
564
569
|
const result = await account(row.id).send(bound.history, model, tools, bound.opts);
|
|
565
570
|
quotaStrikes.delete(`${providerName}:${row.id}`);
|
|
@@ -660,3 +665,33 @@ export function createAccountPoolProvider(providerName, create) {
|
|
|
660
665
|
}
|
|
661
666
|
);
|
|
662
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
|
+
}
|
|
@@ -189,8 +189,7 @@ export async function buildAnthropicApiRequest({
|
|
|
189
189
|
// Diagnostic: per-block prefix hashes of exactly what is sent.
|
|
190
190
|
recordAnthropicPrefix(anthropicPrefixSessionId(opts), anthropicPrefixFingerprint(params));
|
|
191
191
|
|
|
192
|
-
const
|
|
193
|
-
config,
|
|
192
|
+
const betas = requestBetasFor(params, {
|
|
194
193
|
opts,
|
|
195
194
|
isCustom,
|
|
196
195
|
fastLatched,
|
|
@@ -198,8 +197,10 @@ export async function buildAnthropicApiRequest({
|
|
|
198
197
|
capabilityModel,
|
|
199
198
|
effortProjection,
|
|
200
199
|
});
|
|
200
|
+
const requestHeaders = requestHeadersFor(betas, { config, opts });
|
|
201
201
|
|
|
202
|
-
|
|
202
|
+
// `betas`: the selected beta names, whether or not this route sends them as a header.
|
|
203
|
+
return { params, requestHeaders, betas, knownToolNames, fastModeLatched: fastLatched };
|
|
203
204
|
}
|
|
204
205
|
|
|
205
206
|
/** The turn's thinking/effort fields on `params` (in place): a custom
|
|
@@ -247,35 +248,36 @@ function resolveRequestToolChoice(params, opts, config) {
|
|
|
247
248
|
else delete params.tool_choice;
|
|
248
249
|
}
|
|
249
250
|
|
|
250
|
-
/** The
|
|
251
|
-
*
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
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 }) {
|
|
256
276
|
// Per-call headers override the client defaultHeaders, so the
|
|
257
277
|
// constructor-level disableBetaHeaders opt-out must be honoured here
|
|
258
278
|
// too — otherwise opencode-go's anthropic-compatible routing
|
|
259
279
|
// (disableBetaHeaders:true) would still send beta strings that a
|
|
260
280
|
// third-party endpoint may reject.
|
|
261
|
-
|
|
262
|
-
// request body needs (row-driven effort, deferred tools).
|
|
263
|
-
let betaHeaders = null;
|
|
264
|
-
if (!config?.disableBetaHeaders) {
|
|
265
|
-
const betas = [
|
|
266
|
-
buildAnthropicBetaHeaders({
|
|
267
|
-
...(isCustom ? { base: '' } : {}),
|
|
268
|
-
fastMode: fastLatched,
|
|
269
|
-
toolSearch: hasDeferredTools,
|
|
270
|
-
// Custom: the beta follows the resolver's output, not the model id.
|
|
271
|
-
effort: isCustom ? Boolean(params.output_config?.effort) : shouldIncludeEffortBeta(capabilityModel, opts),
|
|
272
|
-
serverFallback: params.fallbacks === 'default',
|
|
273
|
-
thinkingDisplayUpdates: params.thinking?.display === 'updates',
|
|
274
|
-
turnScopedSystem: hasAnthropicTurnScopedMessages(params.messages),
|
|
275
|
-
}),
|
|
276
|
-
...(effortProjection ? [EFFORT_CONFIGURATION_BETA] : []),
|
|
277
|
-
].filter(Boolean);
|
|
278
|
-
if (betas.length) betaHeaders = { 'anthropic-beta': betas.join(',') };
|
|
279
|
-
}
|
|
281
|
+
const betaHeaders = !config?.disableBetaHeaders && betas.length ? { 'anthropic-beta': betas.join(',') } : null;
|
|
280
282
|
return betaHeaders || opts.requestHeaders ? { ...(betaHeaders || {}), ...(opts.requestHeaders || {}) } : null;
|
|
281
283
|
}
|
|
@@ -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.316';
|
|
14
14
|
export const CLAUDE_CLI_NPM_PACKAGE = '@anthropic-ai/claude-code';
|
|
15
15
|
|
|
16
16
|
const CACHE_SCHEMA_VERSION = 1;
|
|
@@ -22,7 +22,12 @@ import {
|
|
|
22
22
|
expiryFromAccessToken,
|
|
23
23
|
isDefinitiveOAuthFailure,
|
|
24
24
|
normalizeAccountIdentity,
|
|
25
|
+
oauthBodySummary,
|
|
25
26
|
oauthCredentialStatus,
|
|
27
|
+
oauthFailureReason,
|
|
28
|
+
oauthPublicError,
|
|
29
|
+
oauthRequestError,
|
|
30
|
+
oauthResponseJson,
|
|
26
31
|
scrubOAuthSecrets,
|
|
27
32
|
} from './lib/oauth-token-utils.mjs';
|
|
28
33
|
import { createOAuthPkce, parseOAuthCodeInput } from './lib/oauth-pkce.mjs';
|
|
@@ -271,7 +276,7 @@ export function _scrubTokens(text, secretValues = []) {
|
|
|
271
276
|
}
|
|
272
277
|
|
|
273
278
|
function _tokenEndpointError(operation, status, text, secretValues = []) {
|
|
274
|
-
const safeDetail =
|
|
279
|
+
const safeDetail = oauthBodySummary(text, secretValues);
|
|
275
280
|
const detail = safeDetail ? `: ${safeDetail}` : '';
|
|
276
281
|
const compatibility =
|
|
277
282
|
status === 403
|
|
@@ -282,7 +287,7 @@ function _tokenEndpointError(operation, status, text, secretValues = []) {
|
|
|
282
287
|
' update Mixdog or set MIXDOG_CLI_VERSION to the installed official Claude Code version;' +
|
|
283
288
|
' then retry sign-in via /providers without an intercepting network layer if applicable.'
|
|
284
289
|
: '';
|
|
285
|
-
return new Error(`${operation} ${status}${detail}.${compatibility}`);
|
|
290
|
+
return oauthPublicError(new Error(`${operation} ${status}${detail}.${compatibility}`));
|
|
286
291
|
}
|
|
287
292
|
|
|
288
293
|
export function isAnthropicOAuthRefreshDisabled() {
|
|
@@ -578,21 +583,26 @@ async function exchangeAuthorizationCode({ pkce, code, state, redirectUri, signa
|
|
|
578
583
|
const cleanCode = String(code || '').trim();
|
|
579
584
|
if (!cleanCode) throw new Error('[anthropic-oauth] authorization code is required');
|
|
580
585
|
const timeoutSignal = AbortSignal.timeout(OAUTH_TOKEN_TIMEOUT_MS);
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
586
|
+
let tokenRes;
|
|
587
|
+
try {
|
|
588
|
+
tokenRes = await fetch(TOKEN_URL, {
|
|
589
|
+
method: 'POST',
|
|
590
|
+
headers: tokenEndpointHeaders(),
|
|
591
|
+
body: JSON.stringify({
|
|
592
|
+
grant_type: 'authorization_code',
|
|
593
|
+
code: cleanCode,
|
|
594
|
+
redirect_uri: redirectUri,
|
|
595
|
+
client_id: CLAUDE_CODE_CLIENT_ID,
|
|
596
|
+
code_verifier: pkce.verifier,
|
|
597
|
+
state,
|
|
598
|
+
}),
|
|
599
|
+
redirect: 'error',
|
|
600
|
+
signal: signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal,
|
|
601
|
+
dispatcher: getLlmDispatcher(),
|
|
602
|
+
});
|
|
603
|
+
} catch (err) {
|
|
604
|
+
throw oauthRequestError('[anthropic-oauth] token exchange', err);
|
|
605
|
+
}
|
|
596
606
|
if (!tokenRes.ok) {
|
|
597
607
|
const text = await tokenRes.text().catch(() => '');
|
|
598
608
|
throw _tokenEndpointError('[anthropic-oauth] token exchange', tokenRes.status, text, [
|
|
@@ -601,7 +611,7 @@ async function exchangeAuthorizationCode({ pkce, code, state, redirectUri, signa
|
|
|
601
611
|
state,
|
|
602
612
|
]);
|
|
603
613
|
}
|
|
604
|
-
const json = await tokenRes
|
|
614
|
+
const json = await oauthResponseJson(tokenRes, '[anthropic-oauth] token exchange');
|
|
605
615
|
const accessToken = json?.access_token || json?.accessToken;
|
|
606
616
|
const refreshToken = json?.refresh_token || json?.refreshToken;
|
|
607
617
|
if (!accessToken || !refreshToken) {
|
|
@@ -727,10 +737,10 @@ export async function beginOAuthLogin({ openBrowserFn = null, openBrowser = true
|
|
|
727
737
|
await acceptCode(code, OAUTH_REDIRECT_URI);
|
|
728
738
|
res.writeHead(200, { 'Content-Type': OAUTH_PAGE_CONTENT_TYPE, Connection: 'close' });
|
|
729
739
|
res.end(oauthSuccessHtml('Claude'));
|
|
730
|
-
} catch {
|
|
731
|
-
// The shared exchange reports its error through waitForCallback.
|
|
740
|
+
} catch (err) {
|
|
741
|
+
// The shared exchange also reports its error through waitForCallback.
|
|
732
742
|
res.writeHead(500, { 'Content-Type': OAUTH_PAGE_CONTENT_TYPE, Connection: 'close' });
|
|
733
|
-
res.end(oauthErrorHtml('Claude could not complete the token exchange.'));
|
|
743
|
+
res.end(oauthErrorHtml(oauthFailureReason('Claude could not complete the token exchange.', err)));
|
|
734
744
|
}
|
|
735
745
|
});
|
|
736
746
|
timeout = setTimeout(() => finish(null), OAUTH_LOGIN_TIMEOUT_MS);
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
import { makeInvalidToolArgsMarker } from '../../lib/openai-tool-args.mjs';
|
|
8
8
|
import { OAUTH_STREAM_LABELS } from '../../lib/anthropic-stream-labels.mjs';
|
|
9
9
|
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
10
|
+
// A bare JSON.parse would throw into the surrounding broad catch, which
|
|
11
|
+
// swallows the whole tool_call — the loop never sees it and the assistant
|
|
12
|
+
// turn ends with an unmatched tool_use id. A malformed input still
|
|
13
13
|
// produces a tool_call (with an invalid-args marker and a logged error)
|
|
14
14
|
// instead of a silent drop or accidental `{}` dispatch. Tool arguments must
|
|
15
15
|
// be a plain object: Anthropic's tool_use input is always a JSON object, but
|
|
@@ -266,7 +266,9 @@ export async function exchangeAuthorizationCode({ code, verifier, fetchFn = fetc
|
|
|
266
266
|
});
|
|
267
267
|
if (!res.ok) {
|
|
268
268
|
const text = await res.text().catch(() => '');
|
|
269
|
-
|
|
269
|
+
// The authorization code is redacted by value: `code` alone is not a secret field.
|
|
270
|
+
const detail = _scrubTokens(text, [cleanCode, verifier]).slice(0, 300);
|
|
271
|
+
throw new Error(`[antigravity-oauth] token exchange ${res.status}: ${detail}`);
|
|
270
272
|
}
|
|
271
273
|
const json = await res.json();
|
|
272
274
|
if (!json?.access_token || !json?.refresh_token) {
|
|
@@ -231,8 +231,8 @@ export function saveTokens(tokens) {
|
|
|
231
231
|
);
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
-
export function _scrubTokens(text) {
|
|
235
|
-
return scrubOAuthSecrets(text);
|
|
234
|
+
export function _scrubTokens(text, secretValues = []) {
|
|
235
|
+
return scrubOAuthSecrets(text, secretValues);
|
|
236
236
|
}
|
|
237
237
|
|
|
238
238
|
export function hasAntigravityOAuthCredentials() {
|
|
@@ -20,7 +20,7 @@ import { createNpmVersionSource, maxSemver } from './npm-cli-version.mjs';
|
|
|
20
20
|
// version (gpt-6.1-sol requires >= 0.159.0, measured 2026-10-09), so the
|
|
21
21
|
// release workflow raises this to the published CLI version on every release
|
|
22
22
|
// (scripts/sync-client-version-floors.mjs).
|
|
23
|
-
export const CODEX_CLIENT_VERSION_FLOOR = '0.
|
|
23
|
+
export const CODEX_CLIENT_VERSION_FLOOR = '0.166.0';
|
|
24
24
|
export const CODEX_CLI_NPM_PACKAGE = '@openai/codex';
|
|
25
25
|
const live = createNpmVersionSource(CODEX_CLI_NPM_PACKAGE, { persistKey: 'codex-cli' });
|
|
26
26
|
|
|
@@ -361,7 +361,7 @@ export class CommandCodeOAuthProvider {
|
|
|
361
361
|
if (Array.isArray(body?.data)) list = body.data;
|
|
362
362
|
else if (Array.isArray(body)) list = body;
|
|
363
363
|
const items = list.filter((item) => modelWire(item));
|
|
364
|
-
publish(items.map(rosterRow));
|
|
364
|
+
await publish(items.map(rosterRow));
|
|
365
365
|
if (this.tokens?.apiKey === apiKey) {
|
|
366
366
|
// Rows accumulate for one key: a later roster that misses a model
|
|
367
367
|
// leaves the endpoints it was last listed with.
|
|
@@ -12,13 +12,21 @@ export const CUSTOM_REASONING_LEVELS = CUSTOM_EFFORT_LEVELS;
|
|
|
12
12
|
export const CUSTOM_REASONING_WIRE_FORMATS = Object.freeze(['standard', 'deepseek', 'together', 'vllm']);
|
|
13
13
|
export const CUSTOM_PROVIDER_AUTH_MODES = Object.freeze(['key', 'none']);
|
|
14
14
|
export const CUSTOM_MODEL_OVERRIDE_LIMIT = 500;
|
|
15
|
+
export const CUSTOM_HEADER_LIMIT = 64;
|
|
15
16
|
|
|
16
17
|
const UNSAFE_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
17
18
|
const MAX_MODEL_ID = 256;
|
|
18
19
|
const MAX_NAME = 200;
|
|
19
20
|
const MAX_WIRE_VALUE = 64;
|
|
21
|
+
const MAX_HEADER_TEXT = 4096;
|
|
20
22
|
// biome-ignore lint/suspicious/noControlCharactersInRegex: rejecting control characters is the point.
|
|
21
23
|
const CONTROL_CHARS = /[\u0000-\u001f\u007f]/;
|
|
24
|
+
// RFC 9110 field-name token, and a field value of visible ASCII, space, tab and
|
|
25
|
+
// obs-text (what a fetch Headers value can carry).
|
|
26
|
+
const HEADER_NAME = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
|
27
|
+
const HEADER_VALUE = /^[\t\x20-\x7e\x80-\xff]*$/;
|
|
28
|
+
// The API key field owns authentication; a header may not carry a credential.
|
|
29
|
+
const AUTH_HEADERS = new Set(['authorization', 'x-api-key', 'api-key']);
|
|
22
30
|
|
|
23
31
|
function fail(message) {
|
|
24
32
|
throw new Error(`[custom-provider] ${message}`);
|
|
@@ -84,6 +92,7 @@ const V2_TOP_LEVEL_KEYS = new Set([
|
|
|
84
92
|
'modelOverrides',
|
|
85
93
|
'wires',
|
|
86
94
|
'modelWires',
|
|
95
|
+
'headers',
|
|
87
96
|
'id',
|
|
88
97
|
'apiKey',
|
|
89
98
|
'apiKeyEnv',
|
|
@@ -295,6 +304,34 @@ function normalizeModelWires(raw, protocol, wires) {
|
|
|
295
304
|
return out;
|
|
296
305
|
}
|
|
297
306
|
|
|
307
|
+
// `headers`: extra HTTP headers sent with every request to the endpoint
|
|
308
|
+
// (inference, model discovery, connection test). Names are case-insensitive
|
|
309
|
+
// tokens; the credential headers belong to the API key field.
|
|
310
|
+
function normalizeHeaders(raw) {
|
|
311
|
+
if (raw === undefined) return {};
|
|
312
|
+
if (!isPlainObject(raw)) fail('headers must be an object of header names to string values');
|
|
313
|
+
const names = Object.keys(raw);
|
|
314
|
+
if (names.length > CUSTOM_HEADER_LIMIT) fail(`at most ${CUSTOM_HEADER_LIMIT} headers are allowed`);
|
|
315
|
+
const seen = new Set();
|
|
316
|
+
const entries = [];
|
|
317
|
+
for (const name of names) {
|
|
318
|
+
if (name.length > MAX_HEADER_TEXT || !HEADER_NAME.test(name))
|
|
319
|
+
fail(`headers has an invalid header name: ${JSON.stringify(name.slice(0, 64))}`);
|
|
320
|
+
const lower = name.toLowerCase();
|
|
321
|
+
if (AUTH_HEADERS.has(lower)) fail(`headers must not set ${name}: authentication belongs to the API key field`);
|
|
322
|
+
if (seen.has(lower)) fail(`headers has duplicate header: ${name}`);
|
|
323
|
+
seen.add(lower);
|
|
324
|
+
if (typeof raw[name] !== 'string') fail(`headers.${name} must be a string`);
|
|
325
|
+
// Validate before trimming, and trim only HTTP whitespace (space, tab), so
|
|
326
|
+
// CR/LF is refused rather than stripped and other characters are kept.
|
|
327
|
+
if (!HEADER_VALUE.test(raw[name])) fail(`headers.${name} has an invalid value`);
|
|
328
|
+
const value = raw[name].replace(/^[ \t]+|[ \t]+$/g, '');
|
|
329
|
+
if (value.length > MAX_HEADER_TEXT) fail(`headers.${name} has an invalid value`);
|
|
330
|
+
entries.push([name, value]);
|
|
331
|
+
}
|
|
332
|
+
return Object.fromEntries(entries);
|
|
333
|
+
}
|
|
334
|
+
|
|
298
335
|
// Legacy (pre-v2) `models: [{ id, name?, contextWindow?, maxOutputTokens? }]`
|
|
299
336
|
// become manual, visible overrides; their presence hides newly discovered ids.
|
|
300
337
|
function migrateLegacy(input) {
|
|
@@ -336,6 +373,7 @@ export function normalizeCustomProviderConfig(input) {
|
|
|
336
373
|
fail('modelOverrides and discovery require schemaVersion 2');
|
|
337
374
|
if (input.wires !== undefined || input.modelWires !== undefined)
|
|
338
375
|
fail('wires and modelWires require schemaVersion 2');
|
|
376
|
+
if (input.headers !== undefined) fail('headers require schemaVersion 2');
|
|
339
377
|
source = migrateLegacy(input);
|
|
340
378
|
} else if (Number.isInteger(version) && version > CUSTOM_PROVIDER_SCHEMA_VERSION)
|
|
341
379
|
fail(`unsupported schemaVersion ${version}; update mixdog to use this provider`);
|
|
@@ -368,6 +406,7 @@ export function normalizeCustomProviderConfig(input) {
|
|
|
368
406
|
const newModelsHidden = optionalBoolean(discovery.newModelsHidden, 'discovery.newModelsHidden') ?? false;
|
|
369
407
|
const wires = normalizeWires(source.wires, protocol);
|
|
370
408
|
const modelWires = normalizeModelWires(source.modelWires, protocol, wires);
|
|
409
|
+
const headers = normalizeHeaders(source.headers);
|
|
371
410
|
return {
|
|
372
411
|
type: 'custom',
|
|
373
412
|
schemaVersion: CUSTOM_PROVIDER_SCHEMA_VERSION,
|
|
@@ -377,6 +416,7 @@ export function normalizeCustomProviderConfig(input) {
|
|
|
377
416
|
enabled: source.enabled !== false,
|
|
378
417
|
auth,
|
|
379
418
|
...(apiKeyEnv && auth === 'key' ? { apiKeyEnv } : {}),
|
|
419
|
+
...(Object.keys(headers).length ? { headers } : {}),
|
|
380
420
|
discovery: { newModelsHidden },
|
|
381
421
|
modelOverrides: normalizeOverrides(source.modelOverrides, protocol, legacy),
|
|
382
422
|
...(wires ? { wires } : {}),
|