mixdog 1.4.0 → 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/scripts/build-shipped-history.mjs +115 -33
- package/scripts/check-voice-runtime-inputs.mjs +25 -0
- package/scripts/gate-local.mjs +183 -63
- package/scripts/latest-guard.mjs +21 -9
- package/scripts/lib/gate-scheduler.mjs +138 -32
- package/scripts/lib/gate-timing-reporter.mjs +16 -0
- package/scripts/lib/isolated-test-env.mjs +10 -5
- package/scripts/lib/run-node-tests.mjs +91 -66
- package/scripts/lib/scoped-temp.d.mts +16 -0
- package/scripts/lib/scoped-temp.mjs +124 -0
- package/scripts/lib/stale-temp.mjs +44 -0
- package/scripts/lib/test-failure-records.mjs +14 -1
- package/scripts/lib/test-failure-summary.mjs +16 -4
- package/scripts/lib/test-spawn-ledger.mjs +12 -3
- package/scripts/post-release-check.mjs +1 -6
- package/scripts/pptx-kit-index.mjs +17 -5
- package/scripts/suite-health.mjs +115 -24
- package/scripts/test-data-dir.mjs +10 -7
- package/scripts/test.mjs +9 -14
- package/src/agents/advisor/AGENT.md +4 -4
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/explore/AGENT.md +22 -0
- package/src/agents/explore/agent.json +6 -0
- package/src/app.mjs +4 -0
- package/src/cli.mjs +7 -0
- package/src/defaults/agents.json +7 -0
- package/src/defaults/shipped-history.json +23 -2
- package/src/defaults/skills/browser-use/SKILL.md +10 -5
- package/src/defaults/skills/code-tidy/SKILL.md +71 -102
- package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
- package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
- package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
- package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
- package/src/defaults/skills/computer-use/SKILL.md +16 -4
- package/src/defaults/skills/goal-management/SKILL.md +1 -1
- package/src/defaults/skills/setup/references/actions.md +12 -6
- package/src/defaults/skills/setup/references/surfaces.md +2 -2
- package/src/defaults/skills/setup-guide/SKILL.md +5 -2
- package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
- package/src/defaults/skills/skill-creator/SKILL.md +85 -190
- package/src/defaults/skills/skill-creator/references/design.md +70 -162
- package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
- package/src/defaults/skills/test-suite/SKILL.md +194 -0
- package/src/defaults/skills/test-suite/references/case-management.md +51 -0
- package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
- package/src/defaults/skills/test-suite/references/reliability.md +49 -0
- package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
- package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
- package/src/defaults/skills/visualize/SKILL.md +6 -2
- package/src/lib/rules-builder.cjs +35 -42
- package/src/output-styles/common.md +2 -2
- package/src/output-styles/simple.md +1 -1
- package/src/rules/agent/AGENT.md +5 -4
- package/src/rules/lead/LEAD.md +12 -7
- package/src/rules/shared/10-tool-workflow.md +3 -1
- package/src/rules/shared/20-research.md +3 -6
- package/src/rules/shared/40-editing.md +1 -0
- package/src/rules/shared/45-destructive.md +0 -2
- package/src/rules/shared/50-execution.md +2 -0
- package/src/rules/shared/60-verification.md +10 -9
- package/src/rules/shared/70-delivery.md +8 -9
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -1
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +156 -24
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -0
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
- package/src/runtime/agent/orchestrator/cache-break-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/config.mjs +12 -7
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +8 -8
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +5 -26
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +3 -1
- package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +122 -12
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +5 -3
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +13 -2
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +152 -58
- package/src/runtime/agent/orchestrator/mcp/client.mjs +51 -18
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +88 -54
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +42 -26
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +54 -8
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +37 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +31 -21
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +14 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +1 -10
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
- package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/devin.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +248 -41
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -11
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +45 -6
- package/src/runtime/agent/orchestrator/providers/lib/first-output-window.mjs +58 -0
- package/src/runtime/agent/orchestrator/providers/lib/listen-on.mjs +14 -0
- package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +1 -10
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +14 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +4 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +5 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +13 -3
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +13 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +81 -42
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +160 -31
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +22 -12
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +49 -22
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/registry.mjs +45 -2
- package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +567 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +41 -13
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -6
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +7 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +6 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +14 -5
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
- package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +1 -3
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +102 -12
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -8
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +103 -23
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +160 -36
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +164 -23
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +139 -19
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +38 -7
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +100 -22
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -6
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +33 -3
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +9 -2
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +14 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +23 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +39 -21
- package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +50 -28
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +30 -13
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +63 -6
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +35 -13
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +24 -14
- package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
- package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +10 -6
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +56 -29
- package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +30 -7
- package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +37 -8
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +252 -39
- package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +164 -4
- package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +61 -2
- package/src/runtime/agent/orchestrator/stall-policy.mjs +23 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +46 -20
- package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +67 -31
- package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +25 -13
- package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +6 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +23 -12
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +1 -8
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +96 -20
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/federation.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/isolated-test-env.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
- package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +103 -13
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +34 -10
- package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +28 -4
- package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -2
- package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
- package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
- package/src/runtime/channels/lib/whisper-port.mjs +29 -11
- package/src/runtime/channels/lib/whisper-server.mjs +10 -1
- package/src/runtime/computer-bridge/action-schema.mjs +2 -2
- package/src/runtime/computer-bridge/core-actions.mjs +2 -2
- package/src/runtime/computer-bridge/error-recovery.mjs +5 -4
- package/src/runtime/computer-bridge/linux-action-capabilities.mjs +24 -5
- package/src/runtime/computer-bridge/linux-readiness.d.mts +7 -2
- package/src/runtime/connectors/connector-accounts-mcp.mjs +236 -103
- package/src/runtime/connectors/gmail-app-password.mjs +3 -3
- package/src/runtime/explore/explorer.mjs +93 -0
- package/src/runtime/explore/tool-defs.mjs +35 -0
- package/src/runtime/explore/tool.mjs +123 -0
- package/src/runtime/local-provider/server-process.mjs +2 -1
- package/src/runtime/media/adapters/gemini-video.mjs +4 -1
- package/src/runtime/media/adapters/xai-media.mjs +2 -1
- package/src/runtime/memory/index.mjs +4 -0
- package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
- package/src/runtime/memory/lib/embedding-worker.mjs +10 -3
- package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +1 -7
- package/src/runtime/memory/lib/memory-chunk-quality.mjs +1 -6
- package/src/runtime/office/authoring/pdf-author-action.mjs +1 -6
- package/src/runtime/office/design/design-art-direction.mjs +29 -27
- package/src/runtime/office/pdf/pdf-writer.mjs +6 -1
- package/src/runtime/office/portable/portable-snapshot-docx.mjs +7 -1
- package/src/runtime/office/portable/portable-snapshot-shared.mjs +6 -1
- package/src/runtime/office/quality/assurance-rendered.mjs +9 -2
- package/src/runtime/office/quality/assurance-structure-docx.mjs +4 -2
- package/src/runtime/office/quality/design-review.mjs +1 -5
- package/src/runtime/office/quality/document-brief.mjs +1 -5
- package/src/runtime/office/quality/forced-break-pages.mjs +9 -6
- package/src/runtime/office/quality/quality-pipeline.mjs +1 -1
- package/src/runtime/shared/agent-route-config.mjs +17 -2
- package/src/runtime/shared/atomic-file.mjs +103 -2
- package/src/runtime/shared/background-tasks.mjs +15 -6
- package/src/runtime/shared/bot-owned-work.mjs +56 -0
- package/src/runtime/shared/connector-accounts.mjs +5 -5
- package/src/runtime/shared/connector-catalog.d.mts +11 -4
- package/src/runtime/shared/connector-catalog.mjs +60 -52
- package/src/runtime/shared/custom-provider-keys.mjs +20 -0
- package/src/runtime/shared/defaults-separation.mjs +1 -4
- package/src/runtime/shared/fetch-safe-listen.d.mts +16 -0
- package/src/runtime/shared/fetch-safe-listen.mjs +50 -0
- package/src/runtime/shared/file-has-data.mjs +26 -2
- package/src/runtime/shared/file-lock.mjs +13 -15
- package/src/runtime/shared/git-launch.d.mts +9 -0
- package/src/runtime/shared/git-launch.mjs +213 -0
- package/src/runtime/shared/git-runner-worker.mjs +2 -1
- package/src/runtime/shared/handoff-artifacts.d.mts +2 -1
- package/src/runtime/shared/handoff-artifacts.mjs +18 -8
- package/src/runtime/shared/idle-auto-clear-gate.mjs +29 -7
- package/src/runtime/shared/llm/cost.mjs +11 -2
- package/src/runtime/shared/llm/http-agent.mjs +313 -29
- package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
- package/src/runtime/shared/llm/model-catalog.mjs +46 -6
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
- package/src/runtime/shared/llm/system-proxy.mjs +452 -0
- package/src/runtime/shared/loopback-listener.mjs +25 -2
- package/src/runtime/shared/model-route-chain.d.mts +7 -2
- package/src/runtime/shared/model-route-chain.mjs +22 -4
- package/src/runtime/shared/open-url.mjs +10 -0
- package/src/runtime/shared/provider-accounts.mjs +52 -2
- package/src/runtime/shared/session-activity-signal.mjs +14 -0
- package/src/runtime/shared/session-scratch.mjs +37 -0
- package/src/runtime/shared/staged-install-worker.mjs +5 -0
- package/src/runtime/shared/staged-update.mjs +47 -2
- package/src/runtime/shared/tool-card-model/agent-surface.mjs +1 -3
- package/src/runtime/shared/tool-card-model/card-status.mjs +15 -2
- package/src/runtime/shared/tool-result-summary.mjs +1 -1
- package/src/runtime/shared/tool-surface.mjs +113 -36
- package/src/runtime/shared/tool-work-units.mjs +6 -0
- package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
- package/src/runtime/shared/turn-worktree-snapshot.mjs +414 -54
- package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
- package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
- package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
- package/src/runtime/shared/worktrees/branch-management.mjs +9 -3
- package/src/runtime/shared/worktrees/contract.mjs +4 -1
- package/src/runtime/shared/worktrees/git.mjs +72 -0
- package/src/runtime/shared/worktrees/manager.mjs +285 -168
- package/src/runtime/shared/worktrees/test-support.mjs +6 -10
- package/src/runtime/tidy/install.mjs +95 -15
- package/src/runtime/tidy/languages.mjs +17 -15
- package/src/runtime/tidy/process.mjs +7 -4
- package/src/runtime/tidy/resolve.mjs +19 -16
- package/src/runtime/tidy/runners/biome.mjs +3 -3
- package/src/runtime/tidy/tool.mjs +1 -1
- package/src/runtime/tidy/worktree.mjs +10 -6
- package/src/runtime/visualize-bridge/client.mjs +6 -1
- package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
- package/src/runtime/web-search/index.mjs +1 -1
- package/src/session-runtime/agent-home-delivery.mjs +41 -0
- package/src/session-runtime/agent-task-sessions.mjs +458 -312
- package/src/session-runtime/agent-tool-routing.mjs +8 -41
- package/src/session-runtime/boot/tools.mjs +7 -1
- package/src/session-runtime/bot-status.mjs +107 -101
- package/src/session-runtime/bot-target.mjs +38 -0
- package/src/session-runtime/channel-config-api.mjs +6 -1
- package/src/session-runtime/connector-merge-migration.mjs +18 -15
- package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
- package/src/session-runtime/conversation-import/discovery.mjs +401 -36
- package/src/session-runtime/conversation-import/service.mjs +35 -8
- package/src/session-runtime/handoff-attachments.mjs +82 -31
- package/src/session-runtime/held-requests.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +12 -13
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +1 -0
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -0
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
- package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +145 -112
- package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
- package/src/session-runtime/lifecycle/session-catalog.mjs +9 -1
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -1
- package/src/session-runtime/lifecycle/teardown.mjs +1 -1
- package/src/session-runtime/mcp-glue/server-catalog.mjs +16 -10
- package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
- package/src/session-runtime/mixy-heartbeat.mjs +1 -1
- package/src/session-runtime/model-route/set-route.mjs +11 -2
- package/src/session-runtime/provider-auth/login.mjs +2 -2
- package/src/session-runtime/provider-catalog-cache.mjs +82 -36
- package/src/session-runtime/provider-models/catalog-load.mjs +23 -6
- package/src/session-runtime/provider-models.mjs +4 -2
- package/src/session-runtime/resource-mcp-api.mjs +98 -35
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +44 -31
- package/src/session-runtime/resource-mcp-secrets.mjs +28 -11
- package/src/session-runtime/resource-mcp-servers.mjs +5 -4
- package/src/session-runtime/resource-recall-api.mjs +6 -1
- package/src/session-runtime/runtime-feature-gates.mjs +5 -1
- package/src/session-runtime/services/agent-tool/execute.mjs +14 -9
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +20 -4
- package/src/session-runtime/services/agent-tool/model-select.mjs +48 -7
- package/src/session-runtime/services/agent-tool/render.mjs +71 -17
- package/src/session-runtime/services/agent-tool/send-flow.mjs +10 -2
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +4 -1
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +6 -2
- package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
- package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
- package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
- package/src/session-runtime/services/daemon-candidate.mjs +4 -1
- package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
- package/src/session-runtime/services/plugin-admin.mjs +10 -6
- package/src/session-runtime/services/provider-admin.mjs +283 -11
- package/src/session-runtime/session-turn-api.mjs +2 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +4 -1
- package/src/session-runtime/settings-system-api.mjs +1 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
- package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
- package/src/session-runtime/setup-tool/executor.mjs +6 -2
- package/src/session-runtime/setup-tool/tool-defs.mjs +2 -1
- package/src/session-runtime/tool-policy/policy-stage.mjs +1 -0
- package/src/session-runtime/turn/agent-ops.mjs +23 -0
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +49 -11
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +25 -5
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
- package/src/session-runtime/workspace/activity-guards.mjs +176 -0
- package/src/session-runtime/workspace/session-view.mjs +149 -0
- package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
- package/src/session-runtime/workspace/transition-runner.mjs +188 -0
- package/src/session-runtime/workspace/transitions.mjs +108 -1041
- package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
- package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
- package/src/session-runtime/workspace/worktree-maintenance.mjs +80 -0
- package/src/session-runtime/workspace/worktree-setup.mjs +85 -0
- package/src/session-runtime/workspace/worktree-tool.mjs +73 -56
- package/src/standalone/daemon-desktop-runtime.mjs +2 -0
- package/src/standalone/daemon-session-control.mjs +169 -138
- package/src/standalone/daemon.mjs +7 -0
- package/src/standalone/desktop-service-registry.mjs +9 -0
- package/src/standalone/local-session-runtime.mjs +5 -1
- package/src/standalone/session-client/daemon-unavailable.mjs +3 -0
- package/src/standalone/session-client.mjs +5 -1
- package/src/standalone/session-frame-stream.mjs +83 -11
- package/src/standalone/session-protocol.mjs +4 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
- package/src/standalone/session-service/agent-tree.mjs +45 -9
- package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
- package/src/standalone/session-service/session-calls/session-action.mjs +10 -3
- package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
- package/src/standalone/session-service/stored-reader.mjs +127 -40
- package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
- package/src/tui/App.jsx +154 -164
- package/src/tui/app/app-view/floating-panel.jsx +10 -4
- package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
- package/src/tui/app/clipboard.mjs +21 -10
- package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +1 -3
- package/src/tui/app/model-picker/route-selection.mjs +5 -6
- package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
- package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
- package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
- package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
- package/src/tui/app/provider-setup/oauth-actions.mjs +58 -21
- package/src/tui/app/provider-setup/provider-items.mjs +8 -2
- package/src/tui/app/provider-setup-picker.mjs +29 -18
- package/src/tui/app/shell-layout/row-budgets.mjs +12 -10
- package/src/tui/app/slash-commands.mjs +1 -0
- package/src/tui/app/slash-dispatch/session-commands.mjs +46 -0
- package/src/tui/app/slash-dispatch.mjs +1 -1
- package/src/tui/app/use-btw-panel.mjs +29 -0
- package/src/tui/app/use-context-panel-refresh.mjs +31 -0
- package/src/tui/app/use-model-catalog-cache.mjs +13 -10
- package/src/tui/app/use-mouse-input.mjs +11 -0
- package/src/tui/app/use-onboarding-start.mjs +8 -3
- package/src/tui/app/use-panel-transition.mjs +10 -1
- package/src/tui/app/use-pasted-buffers.mjs +28 -20
- package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
- package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
- package/src/tui/app/use-prompt-queue-history.mjs +3 -2
- package/src/tui/app/use-selection-focus.mjs +11 -2
- package/src/tui/app/use-selection-geometry.mjs +18 -9
- package/src/tui/app/use-selection-paint.mjs +4 -4
- package/src/tui/app/use-selection-stitch.mjs +3 -3
- package/src/tui/app/use-slash-palette.mjs +62 -0
- package/src/tui/app/use-terminal-chrome.mjs +2 -2
- package/src/tui/app/use-transcript-activity.mjs +47 -32
- package/src/tui/app/use-transcript-follow.mjs +12 -4
- package/src/tui/app/use-transcript-scroll.mjs +46 -17
- package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
- package/src/tui/app/use-transcript-window/geometry.mjs +19 -5
- package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
- package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
- package/src/tui/app/use-transcript-window.mjs +21 -11
- package/src/tui/app/use-tui-ready.mjs +18 -0
- package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
- package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
- package/src/tui/components/Picker.jsx +27 -3
- package/src/tui/components/QuestionPanel.jsx +13 -4
- package/src/tui/components/SignInUrl.jsx +68 -0
- package/src/tui/components/TextEntryPanel.jsx +76 -46
- package/src/tui/components/sign-in-url-layout.mjs +24 -0
- package/src/tui/dist/index.mjs +1963 -1361
- package/src/tui/session/goal-turn-state.mjs +6 -2
- package/src/tui/session/session-api/controls.mjs +4 -0
- package/src/tui/session/session-api/extensions.mjs +8 -0
- package/src/tui/session/session-api/intake/abort.mjs +2 -1
- package/src/tui/session/session-api/intake.mjs +2 -0
- package/src/tui/session/session-api/integrations.mjs +2 -2
- package/src/tui/session/session-api/routes-agent-definitions.mjs +1 -0
- package/src/tui/session/session-api/settings.mjs +2 -2
- package/src/tui/session/session-flow/queue/take-entries.mjs +11 -0
- package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
- package/src/tui/session/transcript-spill.mjs +92 -4
- package/src/tui/session/transcript-store.mjs +2 -0
- package/src/ui/statusline-agents.mjs +1 -3
- package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
|
@@ -20,7 +20,7 @@ import { cwdWithinProjects } from '../../../shared/extension-scopes.mjs';
|
|
|
20
20
|
import { resolvePluginData } from '../../../shared/plugin-paths.mjs';
|
|
21
21
|
import { mixyIdentityDir, userDefinitionDir } from '../../../shared/agent-store.mjs';
|
|
22
22
|
import { isSelfMcpToolName, parseMcpToolName } from '../../../shared/tool-primitives.mjs';
|
|
23
|
-
import { connectorToolDefault } from '../../../shared/connector-catalog.mjs';
|
|
23
|
+
import { connectorById, connectorToolDefault } from '../../../shared/connector-catalog.mjs';
|
|
24
24
|
import { MIXY_AGENT_ID } from '../session/agent-home.mjs';
|
|
25
25
|
import { AGENT_MODE, sessionModeOf } from '../session/agent-mode.mjs';
|
|
26
26
|
import { serverConnector } from './server-connectors.mjs';
|
|
@@ -214,12 +214,43 @@ export function connectorToolPermission(policy, toolOrName) {
|
|
|
214
214
|
const mcp = parseMcpToolName(toolOrName);
|
|
215
215
|
if (!mcp || isSelfMcpToolName(toolOrName)) return 'auto';
|
|
216
216
|
if (policy && !connectorEnabled(policy, mcp.server)) return 'disabled';
|
|
217
|
-
// An explicit per-tool entry decides; otherwise a
|
|
218
|
-
// high-risk tools ask (connectorToolDefault) and any
|
|
219
|
-
|
|
217
|
+
// An explicit per-tool entry of the tool's connector decides; otherwise a
|
|
218
|
+
// catalog connector's high-risk tools ask (connectorToolDefault) and any
|
|
219
|
+
// other tool is auto.
|
|
220
|
+
const [own] = connectorToolEntries(policy?.tools, connectorGroupId(mcp.server), mcp.tool);
|
|
221
|
+
return own || connectorToolDefault(serverConnector(mcp.server), mcp.tool);
|
|
220
222
|
}
|
|
221
223
|
|
|
222
224
|
export const PERMISSION_RANK = Object.freeze({ disabled: 0, needs_approval: 1, auto: 2 });
|
|
225
|
+
|
|
226
|
+
/** The connector a server (account) belongs to: `gmail-2` → `gmail` for a
|
|
227
|
+
* catalog connector; any other id is its own. A tool's permission is stored
|
|
228
|
+
* once, under this id, and governs every account. */
|
|
229
|
+
export function connectorGroupId(serverId) {
|
|
230
|
+
const base = String(serverId).replace(/-\d+$/, '');
|
|
231
|
+
return base !== serverId && connectorById(base) ? base : serverId;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const accountNumber = (id) => Number(/-(\d+)$/.exec(id)?.[1] ?? 0);
|
|
235
|
+
|
|
236
|
+
/** The entries for `tool` under the connector `group` or any of its accounts,
|
|
237
|
+
* topmost first: the connector's own, then the lowest-numbered account. An
|
|
238
|
+
* account only holds one in data saved before permissions were kept per
|
|
239
|
+
* connector; the first entry is the one that applies. */
|
|
240
|
+
export function connectorToolEntries(tools, group, tool) {
|
|
241
|
+
return Object.entries(tools || {})
|
|
242
|
+
.filter(([id, own]) => connectorGroupId(id) === group && CONNECTOR_PERMISSIONS.includes(own?.[tool]))
|
|
243
|
+
.sort(([a], [b]) => accountNumber(a) - accountNumber(b))
|
|
244
|
+
.map(([, own]) => own[tool]);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const UNLISTED_ACCOUNT = '\0unlisted account';
|
|
248
|
+
|
|
249
|
+
/** Rank of `tool` on one account of connector `group`: 0 when that account is
|
|
250
|
+
* off, else the topmost entry for the connector, else `unset` (no override:
|
|
251
|
+
* at least asks / at most runs freely). */
|
|
252
|
+
const accountRank = (tools, off, account, group, tool, unset) =>
|
|
253
|
+
off.has(account) ? 0 : (PERMISSION_RANK[connectorToolEntries(tools, group, tool)[0]] ?? unset);
|
|
223
254
|
export const NO_WIDEN_MESSAGE = 'This change would widen what the bot may do without asking; make it on the desktop.';
|
|
224
255
|
|
|
225
256
|
/** Whether replacing the stored policy `before` (a stored value, a parsed
|
|
@@ -243,21 +274,100 @@ function connectorPolicyWidens(before, after) {
|
|
|
243
274
|
for (const server of offBefore) if (!offAfter.has(server)) return true;
|
|
244
275
|
const toolsBefore = old.tools || {};
|
|
245
276
|
const toolsAfter = next.tools || {};
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
277
|
+
// Judged per connector and tool: the accounts of one connector share them.
|
|
278
|
+
const pairs = new Set(
|
|
279
|
+
[toolsBefore, toolsAfter].flatMap((tools) =>
|
|
280
|
+
Object.entries(tools).flatMap(([id, own]) => Object.keys(own || {}).map((tool) => `${connectorGroupId(id)}\0${tool}`))
|
|
281
|
+
)
|
|
282
|
+
);
|
|
283
|
+
for (const pair of pairs) {
|
|
284
|
+
const [group, tool] = pair.split('\0');
|
|
285
|
+
// Each account on its own: one that is off does not hold back its siblings.
|
|
286
|
+
// Plus one account the policy never names: it is on in both policies, so it
|
|
287
|
+
// stands for every installed account that is not listed.
|
|
288
|
+
const accounts = new Set([
|
|
289
|
+
UNLISTED_ACCOUNT,
|
|
290
|
+
...[group, ...offBefore, ...offAfter, ...Object.keys(toolsBefore), ...Object.keys(toolsAfter)].filter(
|
|
291
|
+
(id) => connectorGroupId(id) === group
|
|
292
|
+
),
|
|
293
|
+
]);
|
|
294
|
+
for (const account of accounts) {
|
|
295
|
+
const was = accountRank(toolsBefore, offBefore, account, group, tool, 1);
|
|
296
|
+
const now = accountRank(toolsAfter, offAfter, account, group, tool, 2);
|
|
252
297
|
if (now > was) return true;
|
|
253
298
|
}
|
|
254
299
|
}
|
|
255
300
|
return false;
|
|
256
301
|
}
|
|
257
302
|
|
|
258
|
-
/**
|
|
303
|
+
/** The `code` of the error a refused widening throws. */
|
|
304
|
+
export const CONNECTOR_POLICY_WIDENS = 'CONNECTOR_POLICY_WIDENS';
|
|
305
|
+
/** An approved tool change met a restriction newer than its request. */
|
|
306
|
+
export const CONNECTOR_TOOL_NARROWED = 'CONNECTOR_TOOL_NARROWED';
|
|
307
|
+
/** An approved tool change found the tool already at that level or more. */
|
|
308
|
+
export const CONNECTOR_TOOL_ALREADY = 'CONNECTOR_TOOL_ALREADY';
|
|
309
|
+
|
|
310
|
+
const codedError = (code, message) => Object.assign(new Error(message), { code });
|
|
311
|
+
|
|
312
|
+
// The one change a person approved on a card (setup-tool connector-widen-approval.mjs),
|
|
313
|
+
// set only for the synchronous stretch of its write.
|
|
314
|
+
let approvedToolChange = null;
|
|
315
|
+
|
|
316
|
+
/** Run `write` (a writer whose noWiden check runs synchronously, before it
|
|
317
|
+
* writes) with one approved change `{ server, tool, from, to }`: its check
|
|
318
|
+
* then lets exactly that tool go to `to`, judged on the stored policy it
|
|
319
|
+
* writes over, and nothing else widen. Returns what `write` returns. */
|
|
320
|
+
export function withApprovedConnectorToolChange(change, write) {
|
|
321
|
+
approvedToolChange = change;
|
|
322
|
+
try {
|
|
323
|
+
return write();
|
|
324
|
+
} finally {
|
|
325
|
+
approvedToolChange = null;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// The approved tool's entries (the connector's, and any account's) pinned to
|
|
330
|
+
// one value in both policies, so the comparison judges every other tool and switch.
|
|
331
|
+
const pinTool = (policy, group, tool) => {
|
|
332
|
+
const tools = Object.fromEntries(
|
|
333
|
+
Object.entries(policy?.tools || {}).map(([id, own]) => [
|
|
334
|
+
id,
|
|
335
|
+
connectorGroupId(id) === group ? { ...own, [tool]: 'disabled' } : own,
|
|
336
|
+
])
|
|
337
|
+
);
|
|
338
|
+
tools[group] = { ...tools[group], [tool]: 'disabled' };
|
|
339
|
+
return { off: policy?.off || [], tools };
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
function assertApprovedToolChange(before, after, { server, tool, from, to }) {
|
|
343
|
+
let old;
|
|
344
|
+
try {
|
|
345
|
+
old = before == null ? { off: [], tools: {} } : parseConnectorPolicy(before);
|
|
346
|
+
} catch {
|
|
347
|
+
throw codedError(CONNECTOR_POLICY_WIDENS, NO_WIDEN_MESSAGE);
|
|
348
|
+
}
|
|
349
|
+
// The approved change is the connector's: its one entry goes to `to`.
|
|
350
|
+
const group = connectorGroupId(server);
|
|
351
|
+
if (old.allow || after?.tools?.[group]?.[tool] !== to) throw codedError(CONNECTOR_POLICY_WIDENS, NO_WIDEN_MESSAGE);
|
|
352
|
+
if (connectorPolicyWidens(pinTool(old, group, tool), pinTool(after, group, tool))) {
|
|
353
|
+
throw codedError(CONNECTOR_POLICY_WIDENS, NO_WIDEN_MESSAGE);
|
|
354
|
+
}
|
|
355
|
+
// No override: it asks at least (as connectorPolicyWidens reads it).
|
|
356
|
+
const was = accountRank(old.tools, new Set(old.off), server, group, tool, 1);
|
|
357
|
+
if (was < PERMISSION_RANK[from]) {
|
|
358
|
+
throw codedError(CONNECTOR_TOOL_NARROWED, 'A newer restriction on this tool landed meanwhile; it was kept.');
|
|
359
|
+
}
|
|
360
|
+
if (was >= PERMISSION_RANK[to]) {
|
|
361
|
+
throw codedError(CONNECTOR_TOOL_ALREADY, 'The tool already has this permission or more; nothing changed.');
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/** Throws NO_WIDEN_MESSAGE (code CONNECTOR_POLICY_WIDENS) when `after` could
|
|
366
|
+
* widen `before` (see connectorPolicyWidens); inside
|
|
367
|
+
* withApprovedConnectorToolChange, only its approved change may. */
|
|
259
368
|
export function assertConnectorPolicyNotWidened(before, after) {
|
|
260
|
-
if (
|
|
369
|
+
if (approvedToolChange) return assertApprovedToolChange(before, after, approvedToolChange);
|
|
370
|
+
if (connectorPolicyWidens(before, after)) throw codedError(CONNECTOR_POLICY_WIDENS, NO_WIDEN_MESSAGE);
|
|
261
371
|
}
|
|
262
372
|
|
|
263
373
|
let toolPermissionWriter = null;
|
|
@@ -69,8 +69,10 @@ function run(cmd, args, { strict = false, timeoutMs = ENUMERATION_DEADLINE_MS }
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
// Snapshot the whole process table once: parent map + a per-pid identity
|
|
72
|
-
// token (Windows CreationDate, POSIX lstart) so a later kill
|
|
73
|
-
// number was not recycled onto a different process before
|
|
72
|
+
// token (Windows CreationDate as a UTC FILETIME, POSIX lstart) so a later kill
|
|
73
|
+
// can prove a pid number was not recycled onto a different process before
|
|
74
|
+
// signalling it. The FILETIME form orders against the spawn server's root
|
|
75
|
+
// creation time and carries no local-time offset.
|
|
74
76
|
// POSIX rows also carry the process group id (Windows has none).
|
|
75
77
|
async function enumerate({ strict = false } = {}) {
|
|
76
78
|
const childrenOf = new Map();
|
|
@@ -84,7 +86,7 @@ async function enumerate({ strict = false } = {}) {
|
|
|
84
86
|
'-NoProfile',
|
|
85
87
|
'-NonInteractive',
|
|
86
88
|
'-Command',
|
|
87
|
-
`${strict ? "$ErrorActionPreference = 'Stop'; " : ''}Get-CimInstance Win32_Process | ForEach-Object { $created = if ($_.CreationDate) { $_.CreationDate.
|
|
89
|
+
`${strict ? "$ErrorActionPreference = 'Stop'; " : ''}Get-CimInstance Win32_Process | ForEach-Object { $created = if ($_.CreationDate) { $_.CreationDate.ToFileTimeUtc() } else { '' }; "$($_.ProcessId) $($_.ParentProcessId) $($_.Name) $created" }`,
|
|
88
90
|
],
|
|
89
91
|
{ strict, timeoutMs: ENUMERATION_DEADLINE_MS }
|
|
90
92
|
)
|
|
@@ -307,14 +307,25 @@ export function resolveMcpTransportKind(cfg) {
|
|
|
307
307
|
throw new Error(`Invalid config: need autoDetect, type (stdio/http/sse/ws), url (http), or command (stdio)`);
|
|
308
308
|
}
|
|
309
309
|
|
|
310
|
-
/** The exact URL
|
|
311
|
-
*
|
|
310
|
+
/** The exact URL an HTTP/SSE server config signs in at with OAuth; null for
|
|
311
|
+
* other transports. */
|
|
312
312
|
export function resolveMcpOAuthUrl(cfg) {
|
|
313
313
|
const kind = resolveMcpTransportKind(cfg);
|
|
314
314
|
if (kind !== 'http' && kind !== 'sse') return null;
|
|
315
315
|
return normalizeMcpTransportUrl(expandEnvVars(String(cfg.url ?? '')), kind);
|
|
316
316
|
}
|
|
317
317
|
|
|
318
|
+
/** What the OAuth credentials of an HTTP/SSE server config are stored under:
|
|
319
|
+
* its exact URL, or a connector account's own `oauthKey` (another account
|
|
320
|
+
* of the connector signs in at the same URL), whatever the URL. Null for
|
|
321
|
+
* other transports. */
|
|
322
|
+
export function resolveMcpOAuthCredentialKey(cfg) {
|
|
323
|
+
const url = resolveMcpOAuthUrl(cfg);
|
|
324
|
+
if (!url) return null;
|
|
325
|
+
const own = typeof cfg.oauthKey === 'string' ? cfg.oauthKey.trim() : '';
|
|
326
|
+
return own ? `mcp-account:${own}` : url;
|
|
327
|
+
}
|
|
328
|
+
|
|
318
329
|
// MCP per-tool-call timeout. Default 2min: a hung/unresponsive MCP server
|
|
319
330
|
// (e.g. a busy editor) must not stall a tool call indefinitely. Genuinely
|
|
320
331
|
// long-running tools can raise/disable it via MIXDOG_MCP_CALL_TIMEOUT_MS or a
|
|
@@ -8,24 +8,30 @@ import { createMcpOAuth } from './oauth.mjs';
|
|
|
8
8
|
import { mcpOAuthClientFor, mcpOAuthDisplayName } from './oauth-client.mjs';
|
|
9
9
|
import { googleMcpService, withGoogleMcp } from '../../../connectors/google-mcp.mjs';
|
|
10
10
|
import { gmailAppPasswordService, withGmailAppPasswordMcp } from '../../../connectors/gmail-app-password.mjs';
|
|
11
|
-
import {
|
|
11
|
+
import { withConnectorAccountsMcp } from '../../../connectors/connector-accounts-mcp.mjs';
|
|
12
12
|
import {
|
|
13
13
|
connectorAccountsOf,
|
|
14
14
|
connectorLiveAccountServers,
|
|
15
15
|
gmailAppPasswordAccount,
|
|
16
16
|
} from '../../../shared/connector-catalog.mjs';
|
|
17
|
-
import {
|
|
17
|
+
import { runAbortable } from '../../../shared/abort-race.mjs';
|
|
18
|
+
import { isMcpOAuthReauthenticationRequired, storedMcpOAuthIdentity } from './oauth.mjs';
|
|
19
|
+
import { shutdownStdioChild } from './child-tree.mjs';
|
|
20
|
+
import { listAllMcpTools } from './client-handshake.mjs';
|
|
18
21
|
import {
|
|
19
22
|
AUTO_DETECT_PORTS,
|
|
23
|
+
MCP_MAX_TIMER_MS,
|
|
20
24
|
expandEnvVars,
|
|
21
25
|
findMissingMcpEnvVars,
|
|
22
26
|
mcpUrlForLog,
|
|
23
27
|
normalizeMcpTransportUrl,
|
|
24
28
|
resolveMcpHttpHeaders,
|
|
29
|
+
resolveMcpOAuthCredentialKey,
|
|
25
30
|
resolveMcpOAuthUrl,
|
|
26
31
|
resolveMcpStdioEnvironment,
|
|
27
32
|
resolveMcpTransportKind,
|
|
28
33
|
scrubMcpConnectionMessage,
|
|
34
|
+
scrubMcpSecrets,
|
|
29
35
|
} from './client-config.mjs';
|
|
30
36
|
|
|
31
37
|
/**
|
|
@@ -76,57 +82,142 @@ export function hasConfiguredMcpAuth(cfg) {
|
|
|
76
82
|
);
|
|
77
83
|
}
|
|
78
84
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
// A stdio account (Postgres) runs one process per account config, shared by
|
|
86
|
+
// the connector server of every scope like any stdio server (client.mjs):
|
|
87
|
+
// account config → its connection, which closes with its last holder.
|
|
88
|
+
const sharedAccountConnections = new Map();
|
|
89
|
+
|
|
90
|
+
/** Close one account connection: a stdio child with its whole process tree. */
|
|
91
|
+
async function closeAccountConnection(connection) {
|
|
92
|
+
connection.dead = true;
|
|
93
|
+
if (connection.transport?._process) await shutdownStdioChild(connection.transport).catch(() => {});
|
|
94
|
+
await connection.client.close().catch(() => {});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Whether a call failure is the account server's own JSON-RPC answer: its
|
|
98
|
+
* connection stays. */
|
|
99
|
+
const answeredError = (error) => error?.name === 'McpError' && error.code !== -32000;
|
|
100
|
+
|
|
101
|
+
/** The address a remote account is signed in as, '' when none is known. */
|
|
102
|
+
function signedInAs(accountCfg) {
|
|
87
103
|
try {
|
|
88
|
-
url = resolveMcpOAuthUrl(accountCfg);
|
|
89
|
-
if (hasConfiguredMcpAuth(accountCfg))
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
104
|
+
const url = resolveMcpOAuthUrl(accountCfg);
|
|
105
|
+
if (!url || hasConfiguredMcpAuth(accountCfg)) return '';
|
|
106
|
+
return storedMcpOAuthIdentity(url, resolveMcpOAuthCredentialKey(accountCfg))?.account || '';
|
|
107
|
+
} catch {
|
|
108
|
+
return '';
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** One account of a connector server (connector-catalog.mjs
|
|
113
|
+
* connectorAccountServer) as connector-accounts-mcp.mjs calls it: its own
|
|
114
|
+
* MCP connection through the transport it had as a server of its own — its
|
|
115
|
+
* key header, its app password, its local command, or its own
|
|
116
|
+
* non-interactive OAuth sign-in (refreshed as needed; a new sign-in goes
|
|
117
|
+
* through 계정 바꾸기, never through a tool call). Connected on first use and
|
|
118
|
+
* again after its connection failed. */
|
|
119
|
+
function connectorAccountClient(serverName, accountCfg, { sdk, log, oauthOptions }) {
|
|
120
|
+
const { interactive: _interactive, ...ownOAuth } = oauthOptions || {};
|
|
121
|
+
const address = gmailAppPasswordAccount(accountCfg);
|
|
122
|
+
const shareKey = resolveMcpTransportKind(accountCfg) === 'stdio' ? JSON.stringify(accountCfg) : null;
|
|
123
|
+
const secretsOf = (connection) => connection?.transport?.oauth?.secrets() || [];
|
|
124
|
+
const accountError = (error, connection) => {
|
|
125
|
+
if (isMcpOAuthReauthenticationRequired(error)) {
|
|
126
|
+
return Object.assign(new Error('Sign-in required; sign this account in again in Connectors.'), {
|
|
127
|
+
authRequired: true,
|
|
128
|
+
});
|
|
98
129
|
}
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
close: () => oauth.close(),
|
|
130
|
+
const reason = scrubMcpConnectionMessage(error?.message || String(error), accountCfg, secretsOf(connection));
|
|
131
|
+
return new Error(appendMcpStderrTail(reason, connection?.stderrTail?.() || ''));
|
|
132
|
+
};
|
|
133
|
+
const open = () => {
|
|
134
|
+
const connection = { users: 0, dead: false };
|
|
135
|
+
try {
|
|
136
|
+
const made = createMcpTransport({ name: accountCfg.name, cfg: accountCfg, sdk, log, oauthOptions: ownOAuth });
|
|
137
|
+
connection.transport = made.transport;
|
|
138
|
+
connection.stderrTail = made.stderrTail;
|
|
139
|
+
} catch (error) {
|
|
140
|
+
// A broken account (no sign-in client, an invalid address) stays listed with why.
|
|
141
|
+
connection.dead = true;
|
|
142
|
+
connection.client = { close: async () => {} };
|
|
143
|
+
connection.ready = Promise.reject(error);
|
|
144
|
+
connection.ready.catch(() => {});
|
|
145
|
+
return connection;
|
|
146
|
+
}
|
|
147
|
+
const client = new sdk.Client({ name: `mixdog-agent/${serverName}`, version: '1.0.0' });
|
|
148
|
+
connection.client = client;
|
|
149
|
+
const retire = () => {
|
|
150
|
+
connection.dead = true;
|
|
151
|
+
if (shareKey && sharedAccountConnections.get(shareKey) === connection) sharedAccountConnections.delete(shareKey);
|
|
124
152
|
};
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
153
|
+
client.onclose = retire;
|
|
154
|
+
connection.retire = retire;
|
|
155
|
+
connection.ready = (async () => {
|
|
156
|
+
await client.connect(connection.transport, { timeout: MCP_MAX_TIMER_MS });
|
|
157
|
+
const tools = client.getServerCapabilities()?.tools
|
|
158
|
+
? (await listAllMcpTools(client, { timeout: MCP_MAX_TIMER_MS }))?.tools
|
|
159
|
+
: [];
|
|
160
|
+
if (!Array.isArray(tools)) throw new Error('The account listed its tools in an invalid shape');
|
|
161
|
+
return { instructions: client.getInstructions() || '', tools };
|
|
162
|
+
})();
|
|
163
|
+
connection.ready.catch(() => {
|
|
164
|
+
retire();
|
|
165
|
+
void closeAccountConnection(connection);
|
|
166
|
+
});
|
|
167
|
+
return connection;
|
|
168
|
+
};
|
|
169
|
+
let held = null;
|
|
170
|
+
const release = () => {
|
|
171
|
+
const connection = held;
|
|
172
|
+
held = null;
|
|
173
|
+
if (!connection || --connection.users > 0) return;
|
|
174
|
+
connection.retire?.();
|
|
175
|
+
void closeAccountConnection(connection);
|
|
176
|
+
};
|
|
177
|
+
const acquire = () => {
|
|
178
|
+
if (held && !held.dead) return held;
|
|
179
|
+
release();
|
|
180
|
+
let connection = shareKey ? sharedAccountConnections.get(shareKey) : null;
|
|
181
|
+
if (!connection || connection.dead) {
|
|
182
|
+
connection = open();
|
|
183
|
+
if (shareKey && !connection.dead) sharedAccountConnections.set(shareKey, connection);
|
|
184
|
+
}
|
|
185
|
+
connection.users += 1;
|
|
186
|
+
held = connection;
|
|
187
|
+
return connection;
|
|
188
|
+
};
|
|
189
|
+
return {
|
|
190
|
+
name: accountCfg.name,
|
|
191
|
+
email: address || signedInAs(accountCfg),
|
|
192
|
+
async connect(signal) {
|
|
193
|
+
const connection = acquire();
|
|
194
|
+
try {
|
|
195
|
+
return await runAbortable(signal, () => connection.ready);
|
|
196
|
+
} catch (error) {
|
|
197
|
+
throw accountError(error, connection);
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
async callTool(params, { signal, onprogress } = {}) {
|
|
201
|
+
const connection = acquire();
|
|
202
|
+
try {
|
|
203
|
+
await runAbortable(signal, () => connection.ready);
|
|
204
|
+
// The caller's deadline governs (it resets on the progress passed up).
|
|
205
|
+
const result = await connection.client.callTool(params, undefined, {
|
|
206
|
+
signal,
|
|
207
|
+
timeout: MCP_MAX_TIMER_MS,
|
|
208
|
+
...(onprogress ? { onprogress } : {}),
|
|
209
|
+
});
|
|
210
|
+
return scrubMcpSecrets(result, secretsOf(connection));
|
|
211
|
+
} catch (error) {
|
|
212
|
+
const failed = accountError(error, connection);
|
|
213
|
+
if (answeredError(error)) return { content: [{ type: 'text', text: failed.message }], isError: true };
|
|
214
|
+
// A connection a call failed on is opened again for the next call.
|
|
215
|
+
if (!signal?.aborted) connection.retire?.();
|
|
216
|
+
throw failed;
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
close: release,
|
|
220
|
+
};
|
|
130
221
|
}
|
|
131
222
|
|
|
132
223
|
// The SDK's WebSocket transport opens its socket without a way to set request
|
|
@@ -177,13 +268,15 @@ function missingEnvWarnings(name, cfg, strictEnv, log) {
|
|
|
177
268
|
return warnings;
|
|
178
269
|
}
|
|
179
270
|
|
|
180
|
-
// A
|
|
181
|
-
// transport closes every account client.
|
|
182
|
-
function connectorAccountsTransport({ name, cfg, Transport, url, accountServers, oauthOptions, log }) {
|
|
183
|
-
const accounts = accountServers.map((accountCfg) =>
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
});
|
|
271
|
+
// A connector server: one server, every account behind it (its account choice
|
|
272
|
+
// on `connectorAccounts`); closing the transport closes every account client.
|
|
273
|
+
function connectorAccountsTransport({ name, cfg, Transport, url, accountServers, sdk, oauthOptions, log }) {
|
|
274
|
+
const accounts = accountServers.map((accountCfg) =>
|
|
275
|
+
connectorAccountClient(name, accountCfg, { sdk, log, oauthOptions })
|
|
276
|
+
);
|
|
277
|
+
const fetchImpl = withConnectorAccountsMcp({ connector: cfg.connector, accounts });
|
|
278
|
+
const transport = new Transport(new URL(url), { fetch: fetchImpl });
|
|
279
|
+
transport.connectorAccounts = fetchImpl.connectorAccounts;
|
|
187
280
|
const close = transport.close.bind(transport);
|
|
188
281
|
transport.close = async () => {
|
|
189
282
|
for (const account of accounts) account.close();
|
|
@@ -204,6 +297,7 @@ function remoteHttpTransport({ name, cfg, kind, Transport, url, oauthOptions, lo
|
|
|
204
297
|
if (!hasConfiguredMcpAuth(cfg)) {
|
|
205
298
|
oauth = createMcpOAuth({
|
|
206
299
|
url,
|
|
300
|
+
credentialKey: resolveMcpOAuthCredentialKey(cfg),
|
|
207
301
|
serverName: mcpOAuthDisplayName(cfg, name),
|
|
208
302
|
oauthClient: mcpOAuthClientFor(cfg, url),
|
|
209
303
|
...oauthOptions,
|
|
@@ -291,7 +385,7 @@ export function createMcpTransport({ name, cfg, sdk, log, strictEnv, oauthOption
|
|
|
291
385
|
throw new Error(`Every account of "${name}" is disabled`);
|
|
292
386
|
}
|
|
293
387
|
const transport = accountServers.length
|
|
294
|
-
? connectorAccountsTransport({ name, cfg, Transport, url, accountServers, oauthOptions, log })
|
|
388
|
+
? connectorAccountsTransport({ name, cfg, Transport, url, accountServers, sdk, oauthOptions, log })
|
|
295
389
|
: remoteHttpTransport({ name, cfg, kind, Transport, url, oauthOptions, log });
|
|
296
390
|
return { transport, autoDetectAdvert: null, stderrTail: noStderrTail, warnings };
|
|
297
391
|
}
|
|
@@ -25,6 +25,7 @@ import { currentToolExecutionOwner } from '../../../shared/tool-execution-owner.
|
|
|
25
25
|
import { positiveInt } from '../../../shared/numbers.mjs';
|
|
26
26
|
import {
|
|
27
27
|
providerSafeMcpToolName,
|
|
28
|
+
resolveMcpOAuthCredentialKey,
|
|
28
29
|
resolveMcpOAuthUrl,
|
|
29
30
|
resolveMcpRequestTimeouts,
|
|
30
31
|
resolveMcpTransportKind,
|
|
@@ -39,6 +40,7 @@ import { mcpOAuthClientFor, mcpOAuthDisplayName } from './oauth-client.mjs';
|
|
|
39
40
|
import { googleMcpService, withGoogleMcp } from '../../../connectors/google-mcp.mjs';
|
|
40
41
|
import { gmailAppPasswordService } from '../../../connectors/gmail-app-password.mjs';
|
|
41
42
|
import { connectorLiveAccountServers } from '../../../shared/connector-catalog.mjs';
|
|
43
|
+
import { CONVERSATION_META } from '../../../connectors/connector-accounts-mcp.mjs';
|
|
42
44
|
import {
|
|
43
45
|
clearMcpOAuth,
|
|
44
46
|
commitMcpOAuthSwitch,
|
|
@@ -503,10 +505,15 @@ export async function executeMcpTool(name, args, options = {}) {
|
|
|
503
505
|
const serverName = server.name;
|
|
504
506
|
const toolName = definition?.mcpToolName || match[2];
|
|
505
507
|
const callSignal = options?.signal || null;
|
|
508
|
+
// A connector server's call names the conversation it is made in: its
|
|
509
|
+
// account default, and the account it makes the last used.
|
|
510
|
+
const conversation = String(options?.conversation || '').trim();
|
|
511
|
+
const metaFor = (target) =>
|
|
512
|
+
conversation && target.transport?.connectorAccounts ? { [CONVERSATION_META]: conversation } : undefined;
|
|
506
513
|
const dispatch = (target) =>
|
|
507
514
|
definition?.mcpOperation
|
|
508
515
|
? _callMcpFeatureWithTimeout(target, definition.mcpOperation, args, callSignal)
|
|
509
|
-
: _callToolWithTimeout(target, toolName, args, callSignal);
|
|
516
|
+
: _callToolWithTimeout(target, toolName, args, callSignal, metaFor(target));
|
|
510
517
|
let retryServer = null;
|
|
511
518
|
const secrets = () => oauthSecrets(server.transport, retryServer?.transport);
|
|
512
519
|
const gate = callAdmissionFor(server);
|
|
@@ -999,7 +1006,7 @@ export function raceMcpAbort(promise, signal, message) {
|
|
|
999
1006
|
});
|
|
1000
1007
|
}
|
|
1001
1008
|
|
|
1002
|
-
async function _callToolWithTimeout(server, toolName, args, signal = null) {
|
|
1009
|
+
async function _callToolWithTimeout(server, toolName, args, signal = null, meta = undefined) {
|
|
1003
1010
|
// The request's signal goes INTO the SDK: an aborted caller (or our own
|
|
1004
1011
|
// timeout) cancels the live JSON-RPC request (notifications/cancelled)
|
|
1005
1012
|
// instead of merely walking away from it. The abort race additionally frees
|
|
@@ -1008,7 +1015,8 @@ async function _callToolWithTimeout(server, toolName, args, signal = null) {
|
|
|
1008
1015
|
return runMcpRequest(
|
|
1009
1016
|
server,
|
|
1010
1017
|
signal,
|
|
1011
|
-
(options) =>
|
|
1018
|
+
(options) =>
|
|
1019
|
+
server.client.callTool({ name: toolName, arguments: args, ...(meta ? { _meta: meta } : {}) }, undefined, options),
|
|
1012
1020
|
{
|
|
1013
1021
|
abortMessage: `MCP tool call aborted (server="${server?.name}", tool="${toolName}")`,
|
|
1014
1022
|
timeoutMessage: (ms) =>
|
|
@@ -1119,6 +1127,24 @@ export function isMcpTool(name) {
|
|
|
1119
1127
|
export function isRegisteredMcpTool(name, scopeId = DEFAULT_MCP_SCOPE_ID) {
|
|
1120
1128
|
return Boolean(resolveMcpToolTarget(scopeId, name)?.definition);
|
|
1121
1129
|
}
|
|
1130
|
+
/**
|
|
1131
|
+
* The account (`{ name, label }`: its unique name, which binds a call to it,
|
|
1132
|
+
* and what it is shown as) a call of the prefixed tool `name` with `args`
|
|
1133
|
+
* would use on its connector server, made in `conversation`
|
|
1134
|
+
* (connectors/connector-accounts-mcp.mjs): the one `args.account` names, else
|
|
1135
|
+
* the one used last. Null when the tool's server holds no accounts. Throws the
|
|
1136
|
+
* refusal (usable accounts listed) when that account cannot be used.
|
|
1137
|
+
*/
|
|
1138
|
+
export function resolveMcpToolAccount(name, args, { scopeId = DEFAULT_MCP_SCOPE_ID, conversation = '' } = {}) {
|
|
1139
|
+
const target = resolveMcpToolTarget(normalizeMcpScopeId(scopeId), name);
|
|
1140
|
+
const accounts = target?.server?.transport?.connectorAccounts;
|
|
1141
|
+
if (!accounts || target.definition?.mcpOperation) return null;
|
|
1142
|
+
return accounts.choose({
|
|
1143
|
+
tool: target.definition?.mcpToolName || MCP_TOOL_NAME_RE.exec(name)?.[2],
|
|
1144
|
+
wanted: args?.account,
|
|
1145
|
+
conversation: String(conversation || '').trim(),
|
|
1146
|
+
});
|
|
1147
|
+
}
|
|
1122
1148
|
/** True when the prefixed name is `read_email` of a server whose every
|
|
1123
1149
|
* endpoint Mixdog answers in-process (the Gmail app-password connector,
|
|
1124
1150
|
* alone or behind the multi-account server): its result is a mail as the
|
|
@@ -1272,18 +1298,19 @@ export function isMcpLoginPending(name, options = {}) {
|
|
|
1272
1298
|
* for servers that never use MCP OAuth.
|
|
1273
1299
|
*/
|
|
1274
1300
|
export function getMcpServerOAuthState(cfg) {
|
|
1275
|
-
let
|
|
1301
|
+
let key;
|
|
1276
1302
|
try {
|
|
1277
|
-
|
|
1303
|
+
key = resolveMcpOAuthCredentialKey(cfg);
|
|
1278
1304
|
} catch {
|
|
1279
1305
|
return null;
|
|
1280
1306
|
}
|
|
1281
|
-
if (!
|
|
1282
|
-
const
|
|
1307
|
+
if (!key || hasConfiguredMcpAuth(cfg)) return null;
|
|
1308
|
+
const url = resolveMcpOAuthUrl(cfg);
|
|
1309
|
+
const signedIn = hasStoredMcpOAuthTokens(url, key);
|
|
1283
1310
|
if (!signedIn) return { signedIn };
|
|
1284
1311
|
// Who it is signed in as (never guessed: empty when the server named nobody)
|
|
1285
1312
|
// and whether 계정 바꾸기 can make the provider show its account choice.
|
|
1286
|
-
const who = storedMcpOAuthIdentity(url);
|
|
1313
|
+
const who = storedMcpOAuthIdentity(url, key);
|
|
1287
1314
|
return {
|
|
1288
1315
|
signedIn,
|
|
1289
1316
|
account: typeof who?.account === 'string' ? who.account : '',
|
|
@@ -1298,32 +1325,38 @@ export function startMcpServerOAuthSwitch(cfg, launch, serverName) {
|
|
|
1298
1325
|
if (!url) throw new Error(`MCP server "${serverName}" does not use OAuth sign-in`);
|
|
1299
1326
|
return startMcpOAuthSwitch({
|
|
1300
1327
|
url,
|
|
1328
|
+
credentialKey: resolveMcpOAuthCredentialKey(cfg),
|
|
1301
1329
|
launch,
|
|
1302
1330
|
serverName: mcpOAuthDisplayName(cfg, serverName),
|
|
1303
1331
|
oauthClient: mcpOAuthClientFor(cfg, url),
|
|
1304
1332
|
...(googleMcpService(url) ? { fetchImpl: withGoogleMcp() } : {}),
|
|
1305
1333
|
});
|
|
1306
1334
|
}
|
|
1307
|
-
/** Store a switch's sign-in
|
|
1335
|
+
/** Store a switch's sign-in as the server's (its URL's, or its own key's);
|
|
1336
|
+
* resolves its rollback. */
|
|
1308
1337
|
export function commitMcpServerOAuthSwitch(cfg, signIn) {
|
|
1309
|
-
return commitMcpOAuthSwitch({
|
|
1338
|
+
return commitMcpOAuthSwitch({
|
|
1339
|
+
url: resolveMcpOAuthUrl(cfg),
|
|
1340
|
+
credentialKey: resolveMcpOAuthCredentialKey(cfg),
|
|
1341
|
+
signIn,
|
|
1342
|
+
});
|
|
1310
1343
|
}
|
|
1311
1344
|
/**
|
|
1312
|
-
* Log out of an HTTP/SSE server
|
|
1313
|
-
* registration stored for it
|
|
1314
|
-
* exact URL, and drop them from live
|
|
1315
|
-
* revokes the grant where the
|
|
1316
|
-
* `{ revoked }`.
|
|
1345
|
+
* Log out of an HTTP/SSE server: delete the OAuth tokens and client
|
|
1346
|
+
* registration stored for it (shared by every server configured with that
|
|
1347
|
+
* exact URL, unless it has its own credential key), and drop them from live
|
|
1348
|
+
* connections. `options.revoke` also revokes the grant where the
|
|
1349
|
+
* authorization server documents how; resolves `{ revoked }`.
|
|
1317
1350
|
*/
|
|
1318
1351
|
export async function clearMcpServerOAuth(cfg, options = {}) {
|
|
1319
|
-
let
|
|
1352
|
+
let key;
|
|
1320
1353
|
try {
|
|
1321
|
-
|
|
1354
|
+
key = resolveMcpOAuthCredentialKey(cfg);
|
|
1322
1355
|
} catch {
|
|
1323
1356
|
// A config without a valid remote URL never connected, so never logged in.
|
|
1324
1357
|
return { revoked: false };
|
|
1325
1358
|
}
|
|
1326
|
-
if (
|
|
1359
|
+
if (key) return clearMcpOAuth({ url: resolveMcpOAuthUrl(cfg), credentialKey: key, revoke: options.revoke === true });
|
|
1327
1360
|
return { revoked: false };
|
|
1328
1361
|
}
|
|
1329
1362
|
/**
|