mixdog 1.2.0 → 1.2.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/README.md +7 -5
- package/package.json +1 -1
- package/scripts/gate-local.mjs +19 -3
- package/scripts/model-catalog-audit.mjs +1 -15
- package/src/agents/reviewer/AGENT.md +3 -3
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +5 -0
- package/src/defaults/skills/pptx/SKILL.md +6 -6
- package/src/defaults/skills/pptx/references/review.md +6 -4
- package/src/defaults/skills/pptx/scripts/source-extract.mjs +1 -1
- package/src/defaults/skills/setup/references/actions.md +13 -3
- package/src/defaults/skills/visualize/SKILL.md +12 -9
- package/src/repl/slash-commands.mjs +16 -1
- package/src/rules/shared/60-verification.md +3 -1
- package/src/rules/shared/70-delivery.md +4 -2
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -4
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +10 -0
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +26 -5
- package/src/runtime/agent/orchestrator/config.mjs +10 -4
- package/src/runtime/agent/orchestrator/context/collect.mjs +2 -1
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +11 -5
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +74 -21
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +122 -15
- package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +54 -11
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +104 -9
- package/src/runtime/agent/orchestrator/mcp/client.mjs +358 -140
- package/src/runtime/agent/orchestrator/mcp/lazy-output-validator.mjs +25 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +103 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +150 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +111 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +87 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +95 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-request.mjs +122 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +9 -0
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +229 -0
- package/src/runtime/agent/orchestrator/mcp/plugin-placeholders.mjs +54 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +294 -44
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +94 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +96 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-fast-mode.mjs +39 -18
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +55 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +25 -21
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-midstream-recovery.mjs +18 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +13 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-midstream.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-recovery.mjs +23 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +46 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request.mjs +14 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +73 -35
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +69 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-server-fallback.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +8 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +53 -18
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +30 -9
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +30 -14
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +93 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +82 -9
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +337 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-tokens.mjs +159 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +447 -0
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +38 -5
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-guards.mjs +97 -2
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +102 -23
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +103 -33
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +29 -6
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +18 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -4
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +86 -19
- package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +29 -8
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +191 -0
- package/src/runtime/agent/orchestrator/providers/gemini-family.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/gemini-history-signatures.mjs +9 -4
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +180 -0
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +21 -82
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +71 -12
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +21 -20
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +97 -51
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +68 -19
- package/src/runtime/agent/orchestrator/providers/lib/gemini-model-catalog.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-bridge.mjs +1080 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +15 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +35 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +4 -9
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +12 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +6 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +5 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +22 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +50 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +23 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +16 -8
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +94 -13
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +193 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +66 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +6 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +23 -14
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +26 -6
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +42 -25
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +274 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +72 -32
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +18 -11
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-stamps.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +2 -3
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +1 -3
- package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +34 -3
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +22 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +5 -9
- package/src/runtime/agent/orchestrator/providers/openai-retry-policy.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-handshake.mjs +16 -8
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/policy.mjs +25 -14
- package/src/runtime/agent/orchestrator/providers/openai-ws-terminal.mjs +18 -11
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +35 -24
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +581 -0
- package/src/runtime/agent/orchestrator/providers/registry.mjs +35 -9
- package/src/runtime/agent/orchestrator/providers/retry-backoff.mjs +46 -7
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +118 -219
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +148 -45
- package/src/runtime/agent/orchestrator/providers/retry-midstream.mjs +81 -16
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +15 -55
- package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +15 -2
- package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +0 -18
- package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +57 -28
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +19 -16
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +268 -181
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +21 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +54 -3
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +284 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +270 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/sqlite-gate.mjs +27 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +628 -0
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +184 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +136 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +128 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +127 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +101 -0
- package/src/runtime/agent/orchestrator/session/explicit-skills.mjs +83 -5
- package/src/runtime/agent/orchestrator/session/imported-message.mjs +11 -0
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -4
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +102 -18
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +42 -5
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +14 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +20 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +50 -23
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +22 -14
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +18 -7
- package/src/runtime/agent/orchestrator/session/manager.mjs +0 -1
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +155 -29
- package/src/runtime/agent/orchestrator/session/store/listing.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/store/write-guards.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +22 -10
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +819 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +22 -12
- package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +158 -0
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +183 -374
- package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +41 -3
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +38 -17
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +12 -15
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +17 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -0
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +5 -5
- package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +6 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +173 -22
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +8 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +5 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +15 -2
- package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +13 -10
- package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +17 -12
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/apply-patch/codex-batch.mjs +4 -4
- package/src/runtime/agent/orchestrator/tools/patch/apply-patch/route.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/read-redirects.mjs +34 -30
- package/src/runtime/agent/orchestrator/tools/patch/sequence/units.mjs +7 -7
- package/src/runtime/agent/orchestrator/tools/patch/sequence.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +4 -0
- package/src/runtime/attachments/store.d.mts +3 -0
- package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +1 -1
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +16 -4
- package/src/runtime/channels/lib/worker-main.mjs +17 -14
- package/src/runtime/computer-bridge/linux-readiness.mjs +0 -2
- package/src/runtime/effort-judge/judge-client.mjs +56 -18
- package/src/runtime/memory/lib/memory.mjs +1 -1
- package/src/runtime/memory/lib/pg/process.mjs +34 -24
- package/src/runtime/memory/lib/pg/supervisor.mjs +16 -13
- package/src/runtime/memory/lib/session-ingest.mjs +2 -2
- package/src/runtime/office/README.md +1 -1
- package/src/runtime/office/shared/values.mjs +0 -5
- package/src/runtime/shared/atomic-file.mjs +25 -4
- package/src/runtime/shared/background-tasks.mjs +92 -14
- package/src/runtime/shared/err-text.mjs +25 -0
- package/src/runtime/shared/error-presentation.mjs +159 -19
- package/src/runtime/shared/extension-scopes.mjs +5 -3
- package/src/runtime/shared/file-lock.mjs +37 -11
- package/src/runtime/shared/llm/anthropic-betas.mjs +4 -3
- package/src/runtime/shared/llm/anthropic-effort.mjs +134 -131
- package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +50 -14
- package/src/runtime/shared/llm/model-catalog.mjs +53 -52
- package/src/runtime/shared/llm/openai-daybreak.mjs +4 -16
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +17 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +13 -4
- package/src/runtime/shared/llm/usage-rollup.mjs +0 -1
- package/src/runtime/shared/model-display.mjs +13 -0
- package/src/runtime/shared/plugin-manifest.mjs +18 -9
- package/src/runtime/shared/pristine-execution-contract.json +9 -2
- package/src/runtime/shared/pristine-execution.mjs +28 -4
- package/src/runtime/shared/provider-accounts.mjs +124 -20
- package/src/runtime/shared/provider-api-key.mjs +12 -0
- package/src/runtime/shared/quota-resume-store.mjs +11 -0
- package/src/runtime/shared/session-baseline-store.mjs +960 -0
- package/src/runtime/shared/shell-display.mjs +9 -3
- package/src/runtime/shared/skill-mentions.d.mts +10 -0
- package/src/runtime/shared/skill-mentions.mjs +133 -0
- package/src/runtime/shared/skill-script-runtime.mjs +264 -0
- package/src/runtime/shared/statusline/statusline-format.mjs +4 -4
- package/src/runtime/shared/task-notification-envelope.mjs +2 -2
- package/src/runtime/shared/tool-primitives.mjs +35 -2
- package/src/runtime/shared/turn-changes.mjs +447 -219
- package/src/runtime/shared/turn-snapshot-store.mjs +182 -1
- package/src/runtime/shared/turn-snapshot.mjs +170 -48
- package/src/runtime/shared/turn-worktree-snapshot.mjs +160 -51
- package/src/runtime/shared/worker-requests.mjs +15 -2
- package/src/runtime/shared/worktrees/contract.mjs +0 -24
- package/src/runtime/shared/worktrees/test-support.mjs +19 -4
- package/src/session-runtime/automation-agents.mjs +8 -2
- package/src/session-runtime/boot/apis.mjs +61 -0
- package/src/session-runtime/boot/config.mjs +5 -2
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/infrastructure.mjs +35 -18
- package/src/session-runtime/conversation-import/discovery.mjs +698 -0
- package/src/session-runtime/conversation-import/service.mjs +369 -0
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +10 -5
- package/src/session-runtime/cwd-plugins/plugin-status.mjs +47 -42
- package/src/session-runtime/lifecycle/session-catalog.mjs +2 -0
- package/src/session-runtime/lifecycle/teardown.mjs +1 -1
- package/src/session-runtime/mcp-glue/connect.mjs +83 -16
- package/src/session-runtime/mcp-glue/plugin-servers.mjs +499 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +135 -33
- package/src/session-runtime/mcp-glue.mjs +25 -2
- package/src/session-runtime/mcp-oauth-login.mjs +174 -0
- package/src/session-runtime/model-route/model-switch-target.mjs +34 -0
- package/src/session-runtime/model-route/set-route.mjs +83 -15
- package/src/session-runtime/model-route/web-search-route.mjs +1 -1
- package/src/session-runtime/native-web-search/routes.mjs +22 -3
- package/src/session-runtime/new-session-config.mjs +3 -2
- package/src/session-runtime/notification-bus.mjs +9 -2
- package/src/session-runtime/provider-auth/accounts.mjs +33 -15
- package/src/session-runtime/provider-models/model-meta.mjs +12 -3
- package/src/session-runtime/provider-models/web-search-catalog.mjs +5 -1
- package/src/session-runtime/provider-readiness.mjs +16 -10
- package/src/session-runtime/quick-model-rows/web-search-rows.mjs +13 -8
- package/src/session-runtime/quick-web-search-models.mjs +13 -38
- package/src/session-runtime/resource-extension-sync.mjs +24 -5
- package/src/session-runtime/resource-mcp-api.mjs +198 -78
- package/src/session-runtime/resource-plugins-api.mjs +29 -41
- package/src/session-runtime/resource-scope-decorate.mjs +6 -8
- package/src/session-runtime/resource-skills-api.mjs +23 -2
- package/src/session-runtime/runtime-review-api.mjs +13 -0
- package/src/session-runtime/schedule-session-run.mjs +1 -1
- package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +13 -1
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +7 -2
- package/src/session-runtime/services/agent-tool/send-flow.mjs +22 -4
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +2 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +22 -5
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +8 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -2
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +17 -0
- package/src/session-runtime/services/channel-session-router.mjs +4 -1
- package/src/session-runtime/services/hook-bus/command-handler.mjs +4 -1
- package/src/session-runtime/services/hook-bus/handlers.mjs +7 -3
- package/src/session-runtime/services/provider-admin.mjs +64 -18
- package/src/session-runtime/services/usage-dashboard-model.mjs +3 -0
- package/src/session-runtime/settings-compaction-api.mjs +1 -0
- package/src/session-runtime/setup-tool/executor.mjs +12 -1
- package/src/session-runtime/setup-tool/extended-actions.mjs +1 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +1 -0
- package/src/session-runtime/setup-tool/tool-defs.mjs +7 -1
- package/src/session-runtime/skills-api.mjs +7 -3
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/webhook-session-run.mjs +16 -4
- package/src/skill-script-entry.mjs +36 -0
- package/src/standalone/daemon-drain-policy.mjs +8 -0
- package/src/standalone/daemon-stored-session-views.mjs +11 -3
- package/src/standalone/daemon-telemetry.mjs +55 -0
- package/src/standalone/daemon.mjs +44 -11
- package/src/standalone/session-protocol.mjs +12 -0
- package/src/standalone/session-service/agent-tree/agent-cancel.mjs +33 -2
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +26 -10
- package/src/standalone/session-service/agent-tree.mjs +12 -0
- package/src/standalone/session-service/quota-resume.mjs +8 -0
- package/src/standalone/session-service/retention/busy.mjs +15 -1
- package/src/standalone/session-service/session-calls/session-action.mjs +6 -1
- package/src/standalone/session-service-api.mjs +5 -0
- package/src/standalone/session-service.mjs +1 -0
- package/src/tui/App.jsx +9 -1
- package/src/tui/app/app-view/floating-panel.jsx +9 -1
- package/src/tui/app/app-view.jsx +7 -0
- package/src/tui/app/create-app-pickers.mjs +4 -0
- package/src/tui/app/extension-pickers/mcp-login.mjs +107 -0
- package/src/tui/app/extension-pickers/mcp-servers-picker.mjs +2 -1
- package/src/tui/app/extension-pickers/plugins-pickers.mjs +35 -16
- package/src/tui/app/extension-pickers.mjs +2 -1
- package/src/tui/app/model-options.mjs +13 -16
- package/src/tui/app/skill-mention-palette.mjs +88 -0
- package/src/tui/app/slash-commands.mjs +7 -2
- package/src/tui/app/slash-dispatch/panel-commands.mjs +16 -1
- package/src/tui/app/slash-palette.mjs +23 -7
- package/src/tui/app/transcript-row-estimate.mjs +11 -3
- package/src/tui/app/use-prompt-draft-flow.mjs +7 -2
- package/src/tui/app/use-prompt-state.mjs +5 -0
- package/src/tui/components/Message.jsx +22 -1
- package/src/tui/components/PromptInput.jsx +21 -3
- package/src/tui/components/SlashCommandPalette.jsx +12 -3
- package/src/tui/components/StatusLine.jsx +2 -0
- package/src/tui/components/TranscriptItem.jsx +9 -1
- package/src/tui/components/prompt-input/key-handler.mjs +21 -8
- package/src/tui/components/status-line/local-line.mjs +5 -2
- package/src/tui/components/status-line/use-statusline-text.mjs +7 -1
- package/src/tui/components/user-message-skills.mjs +38 -0
- package/src/tui/dist/index.mjs +1323 -214
- package/src/tui/session/queue-helpers.mjs +7 -2
- package/src/tui/session/quota-resume.mjs +46 -14
- package/src/tui/session/session-api/commands.mjs +33 -24
- package/src/tui/session/session-api/extensions.mjs +26 -2
- package/src/tui/session/session-api/integrations.mjs +7 -0
- package/src/tui/session/session-api/lifecycle.mjs +5 -1
- package/src/tui/session/session-api/routes.mjs +71 -7
- package/src/tui/session/session-api/settings.mjs +12 -14
- package/src/tui/session/session-flow/drain.mjs +21 -5
- package/src/tui/session/session-flow/failed-turn-rewind.mjs +10 -4
- package/src/tui/session/tui-steering-persist.mjs +25 -9
- package/src/tui/session/turn.mjs +55 -15
- package/src/tui/statusline-ansi-bridge.mjs +1 -1
- package/src/ui/statusline-agents.mjs +15 -4
- package/src/ui/statusline.mjs +7 -3
- package/src/ui/streaming-markdown-heal.mjs +34 -3
- package/src/vendor/statusline/src/gateway/claude-current.mjs +14 -4
- package/src/runtime/effort-judge/previous-human-request.mjs +0 -162
- package/src/runtime/effort-judge/verified-context-input.mjs +0 -10
- package/src/runtime/memory/lib/memory-session-merge.mjs +0 -32
- package/src/runtime/shared/llm/usage-session-history.mjs +0 -266
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { anySignal, loginFailed, reauthenticationRequired } from './oauth-shared.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The authenticated `fetch` of one server over its credential `cache`: it
|
|
5
|
+
* sends the cached token to the server's own endpoints and, on a challenge,
|
|
6
|
+
* joins the single login in flight (starting it with `login` when none is).
|
|
7
|
+
*/
|
|
8
|
+
export function createAuthorizedFetch({ url, cache, login, fetchImpl, lifetimeSignal }) {
|
|
9
|
+
const { creds } = cache;
|
|
10
|
+
let flight;
|
|
11
|
+
let waiters = 0;
|
|
12
|
+
let flightController;
|
|
13
|
+
// An unreadable (e.g. locked) keychain must not block a server that needs no
|
|
14
|
+
// authentication; credentials are required only on challenge.
|
|
15
|
+
const storeReadable = () =>
|
|
16
|
+
cache.ready().then(
|
|
17
|
+
() => true,
|
|
18
|
+
() => false
|
|
19
|
+
);
|
|
20
|
+
// One request, carrying the cached token only to the server's own endpoints.
|
|
21
|
+
// Reports the revision and token it was sent with, and whether the cached
|
|
22
|
+
// token could not be verified.
|
|
23
|
+
async function sendRequest(input, options, signal, sameOrigin) {
|
|
24
|
+
let unreadable = false;
|
|
25
|
+
if (creds.tokens && sameOrigin) {
|
|
26
|
+
try {
|
|
27
|
+
await cache.observeStoredRevision();
|
|
28
|
+
} catch {
|
|
29
|
+
// Unverifiable (e.g. locked keychain): never send the cached token.
|
|
30
|
+
creds.tokens = creds.loaded = undefined;
|
|
31
|
+
unreadable = true;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
signal.throwIfAborted();
|
|
35
|
+
const { observed: revision, tokens } = creds;
|
|
36
|
+
const headers = new Headers(options.headers);
|
|
37
|
+
if (tokens && sameOrigin) headers.set('Authorization', `Bearer ${tokens.access_token}`);
|
|
38
|
+
else headers.delete('Authorization');
|
|
39
|
+
const response = await fetchImpl(input, { ...options, headers, signal, redirect: 'error' });
|
|
40
|
+
return { response, revision, tokens, unreadable };
|
|
41
|
+
}
|
|
42
|
+
function startLogin(challenge, requestLogin, browser, attemptedToken, serverName) {
|
|
43
|
+
flightController = new AbortController();
|
|
44
|
+
flight = login(challenge, flightController.signal, requestLogin(), browser, attemptedToken, serverName).finally(
|
|
45
|
+
() => {
|
|
46
|
+
flight = undefined;
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
// Wait for the login in flight; the last waiter to leave cancels it.
|
|
51
|
+
async function awaitLogin(signal, onAuthorized) {
|
|
52
|
+
waiters++;
|
|
53
|
+
let abort;
|
|
54
|
+
try {
|
|
55
|
+
await Promise.race([
|
|
56
|
+
flight,
|
|
57
|
+
new Promise((_, reject) => {
|
|
58
|
+
abort = () => reject(loginFailed());
|
|
59
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
60
|
+
if (signal.aborted) abort();
|
|
61
|
+
}),
|
|
62
|
+
]);
|
|
63
|
+
// The login settled with tokens stored, before the retry is sent.
|
|
64
|
+
onAuthorized();
|
|
65
|
+
} finally {
|
|
66
|
+
signal.removeEventListener('abort', abort);
|
|
67
|
+
if (--waiters === 0 && flight) {
|
|
68
|
+
flightController.abort();
|
|
69
|
+
// The cancelled login's own failure is not this request's.
|
|
70
|
+
await flight.catch(() => {});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async function authorizedFetch(
|
|
75
|
+
input,
|
|
76
|
+
options = {},
|
|
77
|
+
requestLogin = () => false,
|
|
78
|
+
browser,
|
|
79
|
+
isTransportEndpoint = () => false,
|
|
80
|
+
serverName = undefined,
|
|
81
|
+
onAuthorized = () => {}
|
|
82
|
+
) {
|
|
83
|
+
let storeUnreadable = !(await storeReadable());
|
|
84
|
+
lifetimeSignal.throwIfAborted();
|
|
85
|
+
const signal = anySignal(lifetimeSignal, options.signal);
|
|
86
|
+
const target = new URL(input);
|
|
87
|
+
const server = new URL(url);
|
|
88
|
+
const sameOrigin = target.href === server.href || (target.origin === server.origin && isTransportEndpoint(input));
|
|
89
|
+
const sent = await sendRequest(input, options, signal, sameOrigin);
|
|
90
|
+
const { response } = sent;
|
|
91
|
+
const attemptedToken = sent.tokens;
|
|
92
|
+
storeUnreadable ||= sent.unreadable;
|
|
93
|
+
if (!sameOrigin || ![401, 403].includes(response.status)) return response;
|
|
94
|
+
const { extractWWWAuthenticateParams } = await import('@modelcontextprotocol/sdk/client/auth.js');
|
|
95
|
+
const challenge = extractWWWAuthenticateParams(response);
|
|
96
|
+
if (response.status === 403 && challenge.error !== 'insufficient_scope') return response;
|
|
97
|
+
await response.body?.cancel();
|
|
98
|
+
if (storeUnreadable) throw reauthenticationRequired();
|
|
99
|
+
if (!flight && creds.tokens === attemptedToken) {
|
|
100
|
+
startLogin(challenge, requestLogin, browser, attemptedToken, serverName);
|
|
101
|
+
}
|
|
102
|
+
if (flight) await awaitLogin(signal, onAuthorized);
|
|
103
|
+
lifetimeSignal.throwIfAborted();
|
|
104
|
+
signal.throwIfAborted();
|
|
105
|
+
const retry = await sendRequest(input, options, signal, sameOrigin);
|
|
106
|
+
const retried = retry.response;
|
|
107
|
+
if (retried.status === 401 || retried.status === 403) {
|
|
108
|
+
await retried.body?.cancel();
|
|
109
|
+
// Forget the rejected tokens unless a refresh (here or in another
|
|
110
|
+
// process) or a log-out replaced them since this retry was sent.
|
|
111
|
+
await cache.update(
|
|
112
|
+
() => {
|
|
113
|
+
creds.tokens = undefined;
|
|
114
|
+
},
|
|
115
|
+
{ expected: retry.revision }
|
|
116
|
+
);
|
|
117
|
+
throw reauthenticationRequired();
|
|
118
|
+
}
|
|
119
|
+
return retried;
|
|
120
|
+
}
|
|
121
|
+
return { fetch: authorizedFetch, cancelLogin: () => flightController?.abort() };
|
|
122
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const REAUTHENTICATION_REQUIRED_MESSAGE = 'MCP OAuth reauthenticationRequired: sign in to connect';
|
|
2
|
+
export const reauthenticationRequired = () =>
|
|
3
|
+
Object.assign(new Error(REAUTHENTICATION_REQUIRED_MESSAGE), {
|
|
4
|
+
code: 'reauthenticationRequired',
|
|
5
|
+
});
|
|
6
|
+
export const loginFailed = () => new Error('MCP OAuth login failed, cancelled, or timed out');
|
|
7
|
+
|
|
8
|
+
// `signal`, also aborted by the caller's optional `other` signal.
|
|
9
|
+
export const anySignal = (signal, other) => AbortSignal.any(other ? [signal, other] : [signal]);
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import keychain from '../../../../lib/keychain-cjs.cjs';
|
|
4
|
+
import { openInBrowser } from '../../../shared/open-url.mjs';
|
|
5
|
+
import { normalizeMcpTransportUrl } from './client-config.mjs';
|
|
6
|
+
import {
|
|
7
|
+
MCP_OAUTH_CALLBACK_MAX_BYTES,
|
|
8
|
+
MCP_OAUTH_CALLBACK_NOT_PENDING,
|
|
9
|
+
parsePastedMcpOAuthCallback,
|
|
10
|
+
} from './oauth-callback.mjs';
|
|
11
|
+
import {
|
|
12
|
+
TOKENS_FLAG,
|
|
13
|
+
createCredentialCache,
|
|
14
|
+
credentialFile,
|
|
15
|
+
readStoredCredentials,
|
|
16
|
+
withCredentialLock,
|
|
17
|
+
writeRevisionMarker,
|
|
18
|
+
} from './oauth-credentials.mjs';
|
|
19
|
+
import { createLoginFlow } from './oauth-login.mjs';
|
|
20
|
+
import { createOAuthProvider } from './oauth-provider.mjs';
|
|
21
|
+
import { createAuthorizedFetch } from './oauth-request.mjs';
|
|
22
|
+
import { REAUTHENTICATION_REQUIRED_MESSAGE, anySignal } from './oauth-shared.mjs';
|
|
23
|
+
|
|
24
|
+
export { MCP_OAUTH_CALLBACK_MAX_BYTES, MCP_OAUTH_CALLBACK_NOT_PENDING, parsePastedMcpOAuthCallback };
|
|
25
|
+
|
|
26
|
+
export const MCP_OAUTH_TIMEOUT_MS = 5 * 60_000;
|
|
27
|
+
|
|
28
|
+
const scopes = new WeakMap();
|
|
29
|
+
|
|
30
|
+
/** Whether a connect failed only because the server needs an (explicit) OAuth
|
|
31
|
+
* sign-in. Transports may wrap the error (SSE re-raises it as an event
|
|
32
|
+
* message), so the message and cause chain count too. */
|
|
33
|
+
export function isMcpOAuthReauthenticationRequired(error) {
|
|
34
|
+
for (let current = error, depth = 0; current && depth < 5; current = current.cause, depth++) {
|
|
35
|
+
if (current.code === 'reauthenticationRequired') return true;
|
|
36
|
+
if (String(current.message ?? current).includes(REAUTHENTICATION_REQUIRED_MESSAGE)) return true;
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// One keychain entry per exact server URL. Windows stores each account as a
|
|
42
|
+
// file name, so the account is a hash of the URL and nothing else.
|
|
43
|
+
export function mcpOAuthAccount(url) {
|
|
44
|
+
return `mcp-oauth.${createHash('sha256').update(url).digest('hex')}`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Whether OAuth tokens are stored for one server URL, read from the
|
|
48
|
+
* non-secret revision marker without touching the keychain. */
|
|
49
|
+
export function hasStoredMcpOAuthTokens(url) {
|
|
50
|
+
try {
|
|
51
|
+
const marker = readFileSync(credentialFile(mcpOAuthAccount(normalizeMcpTransportUrl(url)), 'rev'), 'utf8');
|
|
52
|
+
return marker.endsWith(TOKENS_FLAG);
|
|
53
|
+
} catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Log out of one MCP server URL: delete its stored tokens and client
|
|
59
|
+
* registration and drop them from live connections, which then need an
|
|
60
|
+
* explicit reconnect to log in again. */
|
|
61
|
+
export async function clearMcpOAuth({ url, credentialStore = keychain }) {
|
|
62
|
+
url = normalizeMcpTransportUrl(url);
|
|
63
|
+
const account = mcpOAuthAccount(url);
|
|
64
|
+
await withCredentialLock(account, async () => {
|
|
65
|
+
await writeRevisionMarker(account, null);
|
|
66
|
+
if ((await readStoredCredentials(credentialStore, account)) != null)
|
|
67
|
+
await credentialStore.deleteSecretAsync(account);
|
|
68
|
+
});
|
|
69
|
+
scopes.get(credentialStore)?.get(url)?.oauth.clear();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// The keychain is the only durable store. Exact URLs, including query strings,
|
|
73
|
+
// partition clients and tokens even when servers share an authorization issuer.
|
|
74
|
+
export function createMcpOAuth({
|
|
75
|
+
url,
|
|
76
|
+
credentialStore = keychain,
|
|
77
|
+
interactive = false,
|
|
78
|
+
isTransportEndpoint = () => false,
|
|
79
|
+
serverName,
|
|
80
|
+
...options
|
|
81
|
+
}) {
|
|
82
|
+
url = normalizeMcpTransportUrl(url);
|
|
83
|
+
let entries = scopes.get(credentialStore);
|
|
84
|
+
if (!entries) {
|
|
85
|
+
entries = new Map();
|
|
86
|
+
scopes.set(credentialStore, entries);
|
|
87
|
+
}
|
|
88
|
+
let entry = entries.get(url);
|
|
89
|
+
if (!entry) {
|
|
90
|
+
entry = { oauth: createSharedOAuth({ url, credentialStore, ...options }), users: 0 };
|
|
91
|
+
entries.set(url, entry);
|
|
92
|
+
}
|
|
93
|
+
entry.users++;
|
|
94
|
+
const lifetime = new AbortController();
|
|
95
|
+
let onStart = () => {};
|
|
96
|
+
let loginAllowed = interactive === true;
|
|
97
|
+
let loginStarted = false;
|
|
98
|
+
let loginCompleted = false;
|
|
99
|
+
return {
|
|
100
|
+
provider: entry.oauth.provider,
|
|
101
|
+
signal: lifetime.signal,
|
|
102
|
+
set onStart(value) {
|
|
103
|
+
onStart = value;
|
|
104
|
+
},
|
|
105
|
+
/** Whether this connection was opened by an explicit sign-in. */
|
|
106
|
+
get interactive() {
|
|
107
|
+
return interactive === true;
|
|
108
|
+
},
|
|
109
|
+
/** Whether this connection started an interactive (browser) login. */
|
|
110
|
+
get loginStarted() {
|
|
111
|
+
return loginStarted;
|
|
112
|
+
},
|
|
113
|
+
/** Whether that login obtained tokens (the sign-in itself completed). */
|
|
114
|
+
get loginCompleted() {
|
|
115
|
+
return loginCompleted;
|
|
116
|
+
},
|
|
117
|
+
finishConnect() {
|
|
118
|
+
loginAllowed = false;
|
|
119
|
+
},
|
|
120
|
+
/** Every OAuth token this connection held, for scrubbing errors and results. */
|
|
121
|
+
secrets: () => entry.oauth.secrets(),
|
|
122
|
+
/** Answer the browser login this connection started with the redirect URL
|
|
123
|
+
* pasted from the browser, exactly as the loopback callback would. */
|
|
124
|
+
completeCallback(pasted) {
|
|
125
|
+
if (!loginStarted || loginCompleted || lifetime.signal.aborted) throw new Error(MCP_OAUTH_CALLBACK_NOT_PENDING);
|
|
126
|
+
entry.oauth.completeCallback(pasted);
|
|
127
|
+
},
|
|
128
|
+
async fetch(input, init = {}) {
|
|
129
|
+
const signal = anySignal(lifetime.signal, init.signal);
|
|
130
|
+
let startedHere = false;
|
|
131
|
+
return entry.oauth.fetch(
|
|
132
|
+
input,
|
|
133
|
+
{ ...init, signal },
|
|
134
|
+
() => {
|
|
135
|
+
if (!loginAllowed) return false;
|
|
136
|
+
loginAllowed = false;
|
|
137
|
+
loginStarted = startedHere = true;
|
|
138
|
+
onStart();
|
|
139
|
+
return true;
|
|
140
|
+
},
|
|
141
|
+
options.openBrowser,
|
|
142
|
+
isTransportEndpoint,
|
|
143
|
+
serverName,
|
|
144
|
+
// The login this request started stored tokens (a cancel, denial,
|
|
145
|
+
// timeout or failed exchange never gets here); the retry after it may
|
|
146
|
+
// still fail on its own.
|
|
147
|
+
() => {
|
|
148
|
+
if (startedHere) loginCompleted = true;
|
|
149
|
+
}
|
|
150
|
+
);
|
|
151
|
+
},
|
|
152
|
+
close() {
|
|
153
|
+
if (lifetime.signal.aborted) return;
|
|
154
|
+
lifetime.abort();
|
|
155
|
+
if (--entry.users === 0) {
|
|
156
|
+
entry.oauth.close();
|
|
157
|
+
entries.delete(url);
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function createSharedOAuth({
|
|
164
|
+
url,
|
|
165
|
+
credentialStore,
|
|
166
|
+
openBrowser = openInBrowser,
|
|
167
|
+
fetchImpl = fetch,
|
|
168
|
+
timeoutMs = MCP_OAUTH_TIMEOUT_MS,
|
|
169
|
+
}) {
|
|
170
|
+
const lifetime = new AbortController();
|
|
171
|
+
const cache = createCredentialCache({ url, credentialStore, account: mcpOAuthAccount(url) });
|
|
172
|
+
const { creds } = cache;
|
|
173
|
+
const flow = {
|
|
174
|
+
listener: undefined,
|
|
175
|
+
state: undefined,
|
|
176
|
+
verifier: undefined,
|
|
177
|
+
allowBrowser: false,
|
|
178
|
+
browserOpened: false,
|
|
179
|
+
launchBrowser: openBrowser,
|
|
180
|
+
finishCallback: undefined,
|
|
181
|
+
};
|
|
182
|
+
const provider = createOAuthProvider({ cache, flow, lifetimeSignal: lifetime.signal });
|
|
183
|
+
const { login, stopListening, closeListener, answerCallback } = createLoginFlow({
|
|
184
|
+
url,
|
|
185
|
+
cache,
|
|
186
|
+
flow,
|
|
187
|
+
provider,
|
|
188
|
+
lifetimeSignal: lifetime.signal,
|
|
189
|
+
openBrowser,
|
|
190
|
+
fetchImpl,
|
|
191
|
+
timeoutMs,
|
|
192
|
+
});
|
|
193
|
+
const requests = createAuthorizedFetch({
|
|
194
|
+
url,
|
|
195
|
+
cache,
|
|
196
|
+
login,
|
|
197
|
+
fetchImpl,
|
|
198
|
+
lifetimeSignal: lifetime.signal,
|
|
199
|
+
});
|
|
200
|
+
return {
|
|
201
|
+
provider,
|
|
202
|
+
signal: lifetime.signal,
|
|
203
|
+
fetch: requests.fetch,
|
|
204
|
+
secrets: () => [...cache.held],
|
|
205
|
+
/** Answer the pending browser login with a pasted redirect URL: the same
|
|
206
|
+
* state check, PKCE exchange and persistence as the loopback callback,
|
|
207
|
+
* whose listener closes. An invalid paste leaves the login pending. */
|
|
208
|
+
completeCallback(pasted) {
|
|
209
|
+
if (!flow.finishCallback || !flow.browserOpened || !flow.state || !creds.redirectUrl) {
|
|
210
|
+
throw new Error(MCP_OAUTH_CALLBACK_NOT_PENDING);
|
|
211
|
+
}
|
|
212
|
+
const { code } = parsePastedMcpOAuthCallback(pasted, { redirectUrl: creds.redirectUrl, state: flow.state });
|
|
213
|
+
stopListening();
|
|
214
|
+
// A denial (no code) fails the login without echoing its description.
|
|
215
|
+
answerCallback(code);
|
|
216
|
+
},
|
|
217
|
+
/** Forget in-memory credentials (after a log-out) and cancel a login in
|
|
218
|
+
* progress; the next request re-reads the keychain. */
|
|
219
|
+
clear() {
|
|
220
|
+
requests.cancelLogin();
|
|
221
|
+
cache.clear();
|
|
222
|
+
},
|
|
223
|
+
close() {
|
|
224
|
+
lifetime.abort();
|
|
225
|
+
flow.finishCallback?.();
|
|
226
|
+
closeListener();
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mcp/plugin-placeholders.mjs — plugin root/data placeholders in an MCP server
|
|
3
|
+
* config. Pure: no filesystem access; the caller supplies the directories.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const ROOT_NAMES = ['CLAUDE_PLUGIN_ROOT', 'CODEX_PLUGIN_ROOT', 'PLUGIN_ROOT', 'MIXDOG_PLUGIN_ROOT'];
|
|
7
|
+
const DATA_NAMES = ['CLAUDE_PLUGIN_DATA', 'PLUGIN_DATA', 'MIXDOG_PLUGIN_DATA'];
|
|
8
|
+
const PLACEHOLDER_RE = new RegExp(`\\$\\{(${[...ROOT_NAMES, ...DATA_NAMES].join('|')})\\}`, 'g');
|
|
9
|
+
const CONFIG_FIELDS = ['command', 'args', 'env', 'url', 'headers', 'cwd'];
|
|
10
|
+
|
|
11
|
+
// Substituted paths use forward slashes on Windows so a path that lands in a
|
|
12
|
+
// command line or argument is not read as backslash escapes; Windows accepts
|
|
13
|
+
// them everywhere.
|
|
14
|
+
function normalizePath(path, platform) {
|
|
15
|
+
return platform === 'win32' ? path.replace(/\\/g, '/') : path;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function substitute(value, replacements) {
|
|
19
|
+
if (typeof value === 'string') {
|
|
20
|
+
// Function replacement: `$` sequences in paths are inserted literally.
|
|
21
|
+
return value.replace(PLACEHOLDER_RE, (match, name) => replacements.get(name) ?? match);
|
|
22
|
+
}
|
|
23
|
+
if (Array.isArray(value)) return value.map((v) => substitute(v, replacements));
|
|
24
|
+
if (value && typeof value === 'object') {
|
|
25
|
+
const out = {};
|
|
26
|
+
for (const [k, v] of Object.entries(value)) out[k] = substitute(v, replacements);
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Returns a copy of `config` with plugin root/data placeholders replaced in
|
|
34
|
+
* command, args, env, url, headers and cwd. A placeholder whose directory is
|
|
35
|
+
* not supplied is left as written. Run before ordinary env expansion.
|
|
36
|
+
*/
|
|
37
|
+
export function resolvePluginPlaceholders(config, { root, data, platform = process.platform } = {}) {
|
|
38
|
+
const replacements = new Map();
|
|
39
|
+
if (root) for (const name of ROOT_NAMES) replacements.set(name, normalizePath(String(root), platform));
|
|
40
|
+
if (data) for (const name of DATA_NAMES) replacements.set(name, normalizePath(String(data), platform));
|
|
41
|
+
const out = { ...config };
|
|
42
|
+
for (const field of CONFIG_FIELDS) {
|
|
43
|
+
if (out[field] !== undefined) out[field] = substitute(out[field], replacements);
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Environment variables a plugin-owned server process receives (raw paths). */
|
|
49
|
+
export function pluginServerEnv({ root, data } = {}) {
|
|
50
|
+
const env = {};
|
|
51
|
+
if (root) for (const name of ['CLAUDE_PLUGIN_ROOT', 'MIXDOG_PLUGIN_ROOT', 'PLUGIN_ROOT']) env[name] = String(root);
|
|
52
|
+
if (data) for (const name of ['CLAUDE_PLUGIN_DATA', 'MIXDOG_PLUGIN_DATA', 'PLUGIN_DATA']) env[name] = String(data);
|
|
53
|
+
return env;
|
|
54
|
+
}
|