mixdog 1.1.2 → 1.2.1
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 +8 -5
- package/package.json +2 -1
- package/scripts/lib/run-node-tests.mjs +9 -0
- package/scripts/prune-desktop-runtime.mjs +3 -0
- package/scripts/test-direct.mjs +4 -2
- package/src/defaults/shipped-history.json +10 -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 +18 -5
- package/src/defaults/skills/visualize/SKILL.md +160 -0
- package/src/defaults/skills/visualize/references/craft.md +88 -0
- package/src/headless-command.mjs +56 -3
- package/src/headless-exec.mjs +17 -1
- package/src/help.mjs +2 -0
- 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-dispatch/preset.mjs +1 -0
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +1 -0
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +2 -0
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +26 -5
- package/src/runtime/agent/orchestrator/config-presets.mjs +2 -0
- package/src/runtime/agent/orchestrator/config-providers-merge.mjs +17 -11
- package/src/runtime/agent/orchestrator/config-storage.mjs +1 -0
- package/src/runtime/agent/orchestrator/config.mjs +19 -5
- 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 +133 -15
- package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +55 -8
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +86 -8
- package/src/runtime/agent/orchestrator/mcp/client.mjs +474 -164
- package/src/runtime/agent/orchestrator/mcp/lazy-output-validator.mjs +25 -0
- package/src/runtime/agent/orchestrator/mcp/plugin-placeholders.mjs +54 -0
- package/src/runtime/agent/orchestrator/mcp/reconnect-singleflight.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +108 -17
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +15 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +32 -12
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -0
- 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 +444 -0
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-normalization.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -4
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +21 -6
- package/src/runtime/agent/orchestrator/providers/effort-rejection.mjs +244 -0
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +41 -28
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/lib/gemini-model-catalog.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +8 -40
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-tokens.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +51 -12
- package/src/runtime/agent/orchestrator/providers/model-cache.mjs +37 -2
- package/src/runtime/agent/orchestrator/providers/model-proxy-bridge.mjs +1080 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +82 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +556 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +251 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth-tokens.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +69 -102
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +15 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +6 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -1
- 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-xai-send.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +15 -4
- package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog-store.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +4 -4
- package/src/runtime/agent/orchestrator/providers/registry.mjs +47 -7
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +10 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +36 -3
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -11
- 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/model-capabilities.mjs +16 -1
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +278 -84
- 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/runtime-core/tool-defs.mjs +10 -3
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/cache/prefetch-cache.mjs +9 -5
- package/src/runtime/agent/orchestrator/session/cache/read-cache.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +284 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +268 -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/execution-tail.mjs +10 -3
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +24 -13
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +362 -0
- package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +253 -0
- 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/continuation.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/diagnostic.mjs +1 -7
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/refusal.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +7 -4
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +21 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +15 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +22 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +9 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +9 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +37 -16
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +17 -4
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +90 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +22 -12
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +32 -3
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +27 -0
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +0 -1
- package/src/runtime/agent/orchestrator/session/message-ids.mjs +123 -0
- package/src/runtime/agent/orchestrator/session/message-ids.test-support.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +33 -22
- package/src/runtime/agent/orchestrator/session/store/listing.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +10 -3
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +11 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +817 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +36 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +23 -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 +202 -374
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +20 -3
- 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 +48 -9
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +161 -0
- 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/cache-layers.mjs +52 -2
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +32 -22
- package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +10 -3
- 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-cache-policy.mjs +8 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +203 -33
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +32 -35
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +8 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +11 -12
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +9 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +83 -68
- package/src/runtime/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +8 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +20 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +16 -7
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +137 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +11 -10
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +21 -11
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +12 -1
- 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/builtin/task-tool.mjs +56 -13
- package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +58 -0
- 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/code-graph/trusted-roots.mjs +25 -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/patch/ui-diff.mjs +78 -5
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +4 -0
- package/src/runtime/attachments/store.d.mts +3 -0
- package/src/runtime/attachments/store.mjs +38 -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/session-ingest.mjs +2 -2
- package/src/runtime/shared/atomic-file.mjs +33 -6
- package/src/runtime/shared/best-effort-stderr.mjs +8 -0
- package/src/runtime/shared/code-graph-state.mjs +12 -0
- package/src/runtime/shared/defaults-separation.mjs +2 -0
- package/src/runtime/shared/extension-scopes.mjs +5 -3
- package/src/runtime/shared/file-lock.mjs +37 -11
- package/src/runtime/shared/git-runner-worker.mjs +3 -2
- package/src/runtime/shared/git-runner.mjs +4 -3
- package/src/runtime/shared/llm/anthropic-effort.mjs +14 -0
- package/src/runtime/shared/llm/default-context-window.mjs +6 -0
- package/src/runtime/shared/llm/model-catalog-projection.mjs +5 -4
- package/src/runtime/shared/llm/model-catalog.mjs +240 -130
- package/src/runtime/shared/llm/provider-catalog-cache.mjs +36 -28
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +162 -0
- package/src/runtime/shared/llm/provider-seed-rosters.mjs +130 -0
- package/src/runtime/shared/model-proxy-mode.d.mts +3 -0
- package/src/runtime/shared/model-proxy-mode.mjs +19 -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 +125 -21
- package/src/runtime/shared/provider-api-key.mjs +33 -1
- package/src/runtime/shared/schedule-model-ref.mjs +11 -2
- package/src/runtime/shared/session-usage-totals.mjs +19 -0
- package/src/runtime/shared/sharp-electron-linux.mjs +25 -0
- package/src/runtime/shared/shell-display.mjs +9 -3
- package/src/runtime/shared/singleton-owner.mjs +36 -6
- 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-segments.mjs +68 -14
- package/src/runtime/shared/tool-primitives.mjs +35 -2
- package/src/runtime/shared/tool-surface.mjs +7 -0
- package/src/runtime/shared/tool-work-units.mjs +14 -0
- package/src/runtime/shared/transcript-metadata.mjs +17 -1
- package/src/runtime/shared/turn-changes.mjs +791 -0
- package/src/runtime/shared/turn-snapshot-store.mjs +346 -12
- package/src/runtime/shared/turn-snapshot.mjs +690 -81
- package/src/runtime/shared/turn-worktree-snapshot.mjs +185 -15
- package/src/runtime/shared/worker-requests.mjs +15 -2
- package/src/runtime/shared/worktrees/cache-cleanups.mjs +52 -0
- package/src/runtime/shared/worktrees/contract.mjs +551 -0
- package/src/runtime/shared/worktrees/disk.mjs +57 -0
- package/src/runtime/shared/worktrees/git.mjs +247 -0
- package/src/runtime/shared/worktrees/include.mjs +480 -0
- package/src/runtime/shared/worktrees/lock.mjs +46 -0
- package/src/runtime/shared/worktrees/maintenance.mjs +96 -0
- package/src/runtime/shared/worktrees/manager.mjs +1215 -0
- package/src/runtime/shared/worktrees/merge.mjs +182 -0
- package/src/runtime/shared/worktrees/owner.mjs +46 -0
- package/src/runtime/shared/worktrees/paths.mjs +62 -0
- package/src/runtime/shared/worktrees/registry.mjs +110 -0
- package/src/runtime/shared/worktrees/settings.mjs +84 -0
- package/src/runtime/shared/worktrees/slug.mjs +62 -0
- package/src/runtime/shared/worktrees/test-support.mjs +96 -0
- package/src/runtime/visualize-bridge/client.mjs +181 -0
- package/src/runtime/visualize-bridge/tool-defs.mjs +97 -0
- package/src/session-runtime/automation-agents.mjs +8 -2
- package/src/session-runtime/boot/apis.mjs +90 -0
- package/src/session-runtime/boot/config.mjs +7 -2
- package/src/session-runtime/boot/facade.mjs +21 -0
- package/src/session-runtime/boot/infrastructure.mjs +30 -18
- package/src/session-runtime/boot/session.mjs +1 -0
- package/src/session-runtime/boot/tools.mjs +4 -0
- package/src/session-runtime/config-lifecycle.mjs +10 -1
- 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 +21 -6
- package/src/session-runtime/cwd-plugins/plugin-status.mjs +47 -42
- package/src/session-runtime/global-extensions.mjs +2 -2
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +27 -2
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +32 -1
- package/src/session-runtime/internal-tool-executor.mjs +9 -1
- package/src/session-runtime/lifecycle/session-catalog.mjs +8 -1
- package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +5 -0
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +21 -3
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +16 -0
- package/src/session-runtime/mcp-glue/connect.mjs +68 -16
- package/src/session-runtime/mcp-glue/plugin-servers.mjs +499 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +122 -33
- package/src/session-runtime/mcp-glue/server-input.mjs +29 -0
- package/src/session-runtime/mcp-glue.mjs +22 -2
- package/src/session-runtime/model-route/route-persist.mjs +3 -0
- package/src/session-runtime/model-route/set-route.mjs +15 -2
- package/src/session-runtime/new-session-config.mjs +3 -2
- package/src/session-runtime/notification-bus.mjs +18 -3
- package/src/session-runtime/provider-auth/accounts.mjs +33 -15
- package/src/session-runtime/provider-models/row-hydration.mjs +2 -0
- 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/resource-extension-sync.mjs +45 -7
- package/src/session-runtime/resource-mcp-api.mjs +121 -84
- 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/route-resolution.mjs +10 -1
- package/src/session-runtime/route-state.mjs +16 -2
- package/src/session-runtime/runtime-core.mjs +5 -0
- package/src/session-runtime/runtime-facade.mjs +8 -0
- package/src/session-runtime/runtime-review-api.mjs +9 -0
- package/src/session-runtime/schedule-session-run.mjs +1 -1
- package/src/session-runtime/services/agent-tool/helpers.mjs +5 -0
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +3 -0
- package/src/session-runtime/services/agent-tool/job-views/job-lookup.mjs +1 -0
- package/src/session-runtime/services/agent-tool/job-views/spawn-meta.mjs +1 -0
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +15 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +1 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +10 -2
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -7
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +2 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -0
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +1 -0
- package/src/session-runtime/services/agent-tool.mjs +1 -0
- package/src/session-runtime/services/channel-session-router.mjs +4 -1
- package/src/session-runtime/services/daemon-candidate.mjs +3 -2
- package/src/session-runtime/services/daemon-crash-capture/spawn-capture.mjs +55 -0
- 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/session-create/session-options.mjs +10 -1
- package/src/session-runtime/session-turn-api.mjs +1 -0
- package/src/session-runtime/settings-api.mjs +4 -2
- package/src/session-runtime/settings-builtin-tools-api.mjs +9 -2
- package/src/session-runtime/settings-worktree-api.mjs +17 -0
- package/src/session-runtime/setup-tool/executor.mjs +23 -5
- package/src/session-runtime/setup-tool/extended-actions.mjs +1 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +4 -1
- package/src/session-runtime/setup-tool/tool-defs.mjs +38 -4
- package/src/session-runtime/skills-api.mjs +7 -3
- package/src/session-runtime/turn/agent-ops.mjs +12 -1
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +14 -3
- package/src/session-runtime/turn/turn-run/snapshot-tracker.mjs +20 -15
- package/src/session-runtime/turn/turn-run/turn-open.mjs +4 -5
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +29 -1
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +6 -1
- package/src/session-runtime/turn/turn-run.mjs +6 -7
- package/src/session-runtime/webhook-session-run.mjs +16 -4
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +15 -3
- package/src/session-runtime/workspace/admission-gate.mjs +197 -0
- package/src/session-runtime/workspace/project-branches.mjs +136 -0
- package/src/session-runtime/workspace/transition-steps.mjs +364 -0
- package/src/session-runtime/workspace/transitions.mjs +651 -0
- package/src/session-runtime/workspace/workspace-state.mjs +112 -0
- package/src/skill-script-entry.mjs +36 -0
- package/src/standalone/channel-transport/http-routes.mjs +17 -0
- package/src/standalone/channel-transport.mjs +13 -1
- package/src/standalone/daemon-desktop-runtime.mjs +1 -0
- package/src/standalone/daemon-owner.mjs +372 -0
- package/src/standalone/daemon-stored-session-views.mjs +15 -4
- package/src/standalone/daemon.mjs +179 -8
- package/src/standalone/desktop-service-registry.mjs +20 -0
- package/src/standalone/local-session-runtime.mjs +11 -0
- package/src/standalone/session-client/attachment-calls.mjs +3 -1
- package/src/standalone/session-client/daemon-unavailable.mjs +62 -0
- package/src/standalone/session-client/lease-heartbeat.mjs +47 -0
- package/src/standalone/session-client.mjs +104 -13
- package/src/standalone/session-protocol.mjs +21 -0
- package/src/standalone/session-proxy.mjs +3 -0
- package/src/standalone/session-service/agent-tree/agent-child.mjs +4 -0
- package/src/standalone/session-service/agent-tree/agent-rehydrate.mjs +1 -0
- package/src/standalone/session-service/entries/lifecycle.mjs +6 -0
- package/src/standalone/session-service/projection/revisions.mjs +2 -0
- package/src/standalone/session-service/projection/transcript-window.mjs +149 -19
- package/src/standalone/session-service/projection/workspace.mjs +14 -0
- package/src/standalone/session-service/session-calls/session-action.mjs +17 -4
- package/src/standalone/session-transport/call-route.mjs +13 -0
- package/src/standalone/session-transport/client-registry/client-grace.mjs +45 -3
- package/src/standalone/session-transport/client-registry/registration-replays.mjs +1 -0
- package/src/standalone/session-transport/client-registry.mjs +20 -3
- package/src/standalone/session-transport/routes.mjs +79 -2
- package/src/standalone/session-transport/stack.mjs +2 -0
- package/src/standalone/session-transport.mjs +24 -1
- 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 +6 -0
- package/src/tui/app/extension-pickers/plugins-pickers.mjs +35 -16
- package/src/tui/app/message-selector.mjs +2 -1
- package/src/tui/app/model-options.mjs +37 -5
- package/src/tui/app/model-picker/provider-models-list.mjs +2 -2
- package/src/tui/app/model-picker.mjs +4 -2
- package/src/tui/app/skill-mention-palette.mjs +88 -0
- 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/TranscriptItem.jsx +9 -1
- package/src/tui/components/prompt-input/key-handler.mjs +21 -8
- package/src/tui/components/user-message-skills.mjs +38 -0
- package/src/tui/dist/index.mjs +839 -207
- package/src/tui/index.jsx +10 -2
- package/src/tui/session/compaction-view.mjs +147 -0
- package/src/tui/session/context-state.mjs +6 -0
- package/src/tui/session/initial-state.mjs +3 -0
- package/src/tui/session/queue-helpers.mjs +7 -2
- package/src/tui/session/quota-resume.mjs +2 -1
- package/src/tui/session/session-api/commands.mjs +10 -2
- package/src/tui/session/session-api/controls.mjs +4 -0
- package/src/tui/session/session-api/extensions.mjs +4 -2
- package/src/tui/session/session-api/intake/rewind.mjs +2 -1
- package/src/tui/session/session-api/integrations.mjs +17 -0
- package/src/tui/session/session-api/lifecycle/dispose.mjs +6 -1
- package/src/tui/session/session-api/lifecycle/inheritance.mjs +2 -0
- package/src/tui/session/session-api/lifecycle/resume.mjs +3 -0
- package/src/tui/session/session-api/routes.mjs +10 -1
- package/src/tui/session/session-api/settings.mjs +9 -0
- package/src/tui/session/session-api/worktree.mjs +60 -0
- package/src/tui/session/session-api.mjs +2 -0
- package/src/tui/session/session-flow/auto-clear.mjs +31 -12
- package/src/tui/session/session-flow/drain.mjs +27 -3
- package/src/tui/session/session-flow/session-reset.mjs +4 -3
- package/src/tui/session/session-flow.mjs +2 -0
- package/src/tui/session/transcript-intake.mjs +14 -5
- package/src/tui/session/tui-steering-persist.mjs +25 -9
- package/src/tui/session/turn-stream.mjs +32 -4
- package/src/tui/session/turn-tool-cards.mjs +10 -2
- package/src/tui/session/turn.mjs +56 -10
- package/src/runtime/effort-judge/previous-human-request.mjs +0 -162
- package/src/runtime/effort-judge/verified-context-input.mjs +0 -10
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
// Effective MCP server set and its status projection:
|
|
2
|
-
//
|
|
1
|
+
// Effective MCP server set and its status projection: the user's configured
|
|
2
|
+
// servers plus the servers registered plugins declare (resolved live, with
|
|
3
|
+
// explicit owner metadata), per-server config reads, and the live/failed rollup.
|
|
3
4
|
import { clean } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
4
5
|
import { envFlag } from '../../runtime/shared/env.mjs';
|
|
6
|
+
import { resolveMcpServerCatalog } from './plugin-servers.mjs';
|
|
5
7
|
|
|
6
8
|
function mcpServerStatus(cfg, live, fail) {
|
|
7
9
|
if (cfg?.enabled === false) return 'disabled';
|
|
@@ -9,7 +11,23 @@ function mcpServerStatus(cfg, live, fail) {
|
|
|
9
11
|
return fail ? 'failed' : 'disconnected';
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
|
|
14
|
+
const EMPTY_CATALOG = { servers: {}, sources: {}, entries: {}, plugins: {}, warnings: [], adoption: null };
|
|
15
|
+
|
|
16
|
+
// Internal markers on a resolved plugin config; never part of an editable config.
|
|
17
|
+
function withoutMarkers(cfg) {
|
|
18
|
+
const { _mixdogStrictEnv, _mixdogRootsFollowScope, _mixdogPlugin, ...rest } = cfg || {};
|
|
19
|
+
return rest;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function createMcpServerCatalog({
|
|
23
|
+
mcpClient,
|
|
24
|
+
getConfig,
|
|
25
|
+
getCurrentCwd = () => '',
|
|
26
|
+
getMcpScopeId,
|
|
27
|
+
getPluginDataDir = () => '',
|
|
28
|
+
listPlugins = () => [],
|
|
29
|
+
state,
|
|
30
|
+
}) {
|
|
13
31
|
function mcpTransportLabel(cfg = {}) {
|
|
14
32
|
if (cfg.autoDetect) return `autoDetect:${cfg.autoDetect}`;
|
|
15
33
|
try {
|
|
@@ -19,33 +37,59 @@ export function createMcpServerCatalog({ mcpClient, getConfig, getMcpScopeId, st
|
|
|
19
37
|
}
|
|
20
38
|
}
|
|
21
39
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
servers[name] = {
|
|
35
|
-
...cfg,
|
|
36
|
-
...(cfg?._mixdogPluginDisabled === true ? { enabled: false } : {}),
|
|
37
|
-
};
|
|
38
|
-
sources[name] = cfg?.env?.MIXDOG_PLUGIN_ROOT ? 'plugin' : 'config';
|
|
40
|
+
/** Everything this runtime would connect, resolved now. MCP is
|
|
41
|
+
* machine-global: project `.mcp.json` files and per-project overrides stay
|
|
42
|
+
* outside the chain; only plugin servers without a declared cwd follow this
|
|
43
|
+
* runtime's session cwd. */
|
|
44
|
+
function resolveCatalog() {
|
|
45
|
+
if (envFlag('MIXDOG_DISABLE_MCP')) return EMPTY_CATALOG;
|
|
46
|
+
let plugins = [];
|
|
47
|
+
let registryWarning = null;
|
|
48
|
+
try {
|
|
49
|
+
plugins = listPlugins() || [];
|
|
50
|
+
} catch (error) {
|
|
51
|
+
registryWarning = { message: `plugin MCP servers unavailable: ${error?.message || String(error)}` };
|
|
39
52
|
}
|
|
53
|
+
const catalog = resolveMcpServerCatalog({
|
|
54
|
+
config: getConfig() || {},
|
|
55
|
+
plugins,
|
|
56
|
+
cwd: clean(getCurrentCwd?.()),
|
|
57
|
+
dataDir: clean(getPluginDataDir?.()),
|
|
58
|
+
});
|
|
59
|
+
if (registryWarning) catalog.warnings.unshift(registryWarning);
|
|
60
|
+
return catalog;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function resolveEffectiveMcpServers() {
|
|
64
|
+
const { servers, sources } = resolveCatalog();
|
|
40
65
|
return { servers, sources };
|
|
41
66
|
}
|
|
42
67
|
|
|
68
|
+
/** Plugin owner of an effective server name, or null for a configured one. */
|
|
69
|
+
function pluginServer(name) {
|
|
70
|
+
const catalog = resolveCatalog();
|
|
71
|
+
const entry = catalog.entries[clean(name)];
|
|
72
|
+
return entry?.owner ? { ...entry, plugin: catalog.plugins[entry.owner.id] } : null;
|
|
73
|
+
}
|
|
74
|
+
|
|
43
75
|
function getMcpServerConfig(name) {
|
|
44
76
|
const serverName = clean(name);
|
|
45
77
|
if (!serverName) throw new Error('MCP server name is required');
|
|
46
|
-
const { servers, sources } =
|
|
78
|
+
const { servers, sources, entries } = resolveCatalog();
|
|
47
79
|
const effective = servers[serverName];
|
|
48
80
|
if (!effective) throw new Error(`MCP server not configured: ${serverName}`);
|
|
81
|
+
// An unadopted plugin copy has an owner but stays the user's editable config.
|
|
82
|
+
const owner = sources[serverName] === 'plugin' ? entries[serverName]?.owner || null : null;
|
|
83
|
+
if (owner) {
|
|
84
|
+
return {
|
|
85
|
+
name: serverName,
|
|
86
|
+
source: 'plugin',
|
|
87
|
+
enabled: effective.enabled !== false,
|
|
88
|
+
owner,
|
|
89
|
+
readOnly: true,
|
|
90
|
+
config: withoutMarkers({ ...effective, enabled: undefined }),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
49
93
|
const raw = getConfig()?.mcpServers?.[serverName];
|
|
50
94
|
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
51
95
|
throw new Error(`MCP server config is unavailable: ${serverName}`);
|
|
@@ -58,43 +102,88 @@ export function createMcpServerCatalog({ mcpClient, getConfig, getMcpScopeId, st
|
|
|
58
102
|
};
|
|
59
103
|
}
|
|
60
104
|
|
|
61
|
-
function
|
|
62
|
-
|
|
63
|
-
return { servers: [], configuredCount: 0, connectedCount: 0, failedCount: 0 };
|
|
64
|
-
}
|
|
65
|
-
const { servers: configured, sources } = resolveEffectiveMcpServers();
|
|
105
|
+
function statusRows(catalog) {
|
|
106
|
+
const { servers: configured, sources, entries } = catalog;
|
|
66
107
|
const connected = new Map((mcpClient.getMcpServerStatus?.(getMcpScopeId()) || []).map((row) => [row.name, row]));
|
|
67
108
|
const failures = new Map((state.mcpFailures || []).map((row) => [row.name, row]));
|
|
68
109
|
const servers = [];
|
|
69
110
|
for (const [name, cfg] of Object.entries(configured)) {
|
|
70
111
|
const live = connected.get(name);
|
|
71
|
-
|
|
72
|
-
|
|
112
|
+
// A registered server whose client reports it not alive (runtime
|
|
113
|
+
// failure after connect) is surfaced as failed, not connected.
|
|
114
|
+
const dead = live && (live.alive === false || live.connected === false);
|
|
115
|
+
const fail =
|
|
116
|
+
failures.get(name) || (dead ? { msg: live.error || live.lastError || 'MCP server is not alive' } : undefined);
|
|
117
|
+
const entry = entries[name] || {};
|
|
118
|
+
const row = {
|
|
73
119
|
name,
|
|
74
120
|
configured: true,
|
|
75
121
|
enabled: cfg?.enabled !== false,
|
|
76
|
-
connected: Boolean(live),
|
|
77
|
-
status: mcpServerStatus(cfg, live, fail),
|
|
122
|
+
connected: Boolean(live) && !dead,
|
|
123
|
+
status: mcpServerStatus(cfg, live && !dead, fail),
|
|
78
124
|
transport: mcpTransportLabel(cfg),
|
|
79
125
|
toolCount: live?.toolCount || 0,
|
|
80
126
|
tools: live?.tools || [],
|
|
81
127
|
capabilities: live?.capabilities || { tools: false, prompts: false, resources: false },
|
|
82
128
|
error: fail?.msg || null,
|
|
129
|
+
warnings: [...(entry.warnings || []), ...(live?.warnings || [])],
|
|
83
130
|
source: sources[name] || 'config',
|
|
84
|
-
}
|
|
131
|
+
};
|
|
132
|
+
if (entry.owner) {
|
|
133
|
+
row.owner = entry.owner;
|
|
134
|
+
row.pluginEnabled = entry.pluginEnabled;
|
|
135
|
+
row.serverEnabled = entry.serverEnabled;
|
|
136
|
+
if (!entry.pluginEnabled) row.disabledReason = 'plugin disabled';
|
|
137
|
+
else if (!entry.serverEnabled) row.disabledReason = 'server disabled';
|
|
138
|
+
}
|
|
139
|
+
servers.push(row);
|
|
85
140
|
connected.delete(name);
|
|
86
141
|
}
|
|
87
142
|
for (const live of connected.values()) {
|
|
88
143
|
servers.push({ ...live, configured: false, status: 'connected' });
|
|
89
144
|
}
|
|
90
145
|
servers.sort((a, b) => String(a.name).localeCompare(String(b.name)));
|
|
146
|
+
return servers;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function mcpStatus() {
|
|
150
|
+
if (envFlag('MIXDOG_DISABLE_MCP')) {
|
|
151
|
+
return { servers: [], configuredCount: 0, connectedCount: 0, failedCount: 0 };
|
|
152
|
+
}
|
|
153
|
+
const catalog = resolveCatalog();
|
|
154
|
+
const servers = statusRows(catalog);
|
|
155
|
+
const declarationErrors = Object.values(catalog.plugins).flatMap((plugin) =>
|
|
156
|
+
plugin.errors.map((error) => ({ plugin: plugin.id, ...error }))
|
|
157
|
+
);
|
|
91
158
|
return {
|
|
92
159
|
servers,
|
|
93
|
-
configuredCount: Object.keys(
|
|
160
|
+
configuredCount: Object.keys(catalog.servers).length,
|
|
94
161
|
connectedCount: servers.filter((row) => row.connected).length,
|
|
95
162
|
failedCount: servers.filter((row) => row.status === 'failed').length,
|
|
163
|
+
warnings: catalog.warnings,
|
|
164
|
+
declarationErrors,
|
|
96
165
|
};
|
|
97
166
|
}
|
|
98
167
|
|
|
99
|
-
|
|
168
|
+
/** Per plugin id: declaration format/errors and its server status rows. */
|
|
169
|
+
function pluginMcpSummary() {
|
|
170
|
+
const catalog = resolveCatalog();
|
|
171
|
+
const rows = new Map(statusRows(catalog).map((row) => [row.name, row]));
|
|
172
|
+
return new Map(
|
|
173
|
+
Object.values(catalog.plugins).map((plugin) => [
|
|
174
|
+
plugin.id,
|
|
175
|
+
{ format: plugin.format, errors: plugin.errors, servers: plugin.servers.map((name) => rows.get(name)) },
|
|
176
|
+
])
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
mcpTransportLabel,
|
|
182
|
+
resolveCatalog,
|
|
183
|
+
resolveEffectiveMcpServers,
|
|
184
|
+
pluginServer,
|
|
185
|
+
getMcpServerConfig,
|
|
186
|
+
mcpStatus,
|
|
187
|
+
pluginMcpSummary,
|
|
188
|
+
};
|
|
100
189
|
}
|
|
@@ -26,8 +26,37 @@ function coerceStringArray(value) {
|
|
|
26
26
|
return Array.isArray(value) ? value.map((entry) => clean(entry)).filter(Boolean) : [];
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
function positiveNumber(value, label) {
|
|
30
|
+
const n = Number(value);
|
|
31
|
+
if (!Number.isFinite(n) || n <= 0) throw new Error(`${label} must be a positive number`);
|
|
32
|
+
return n;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Per-server timeouts, stored under the keys client-config.mjs already reads:
|
|
36
|
+
// startupTimeoutSec/startupTimeoutMs and timeoutMs. A stored value (save
|
|
37
|
+
// merges the existing entry into the input) round-trips unchanged unless the
|
|
38
|
+
// setup-facing startupTimeoutSec/toolTimeoutSec overrides it.
|
|
39
|
+
function timeoutFields(input) {
|
|
40
|
+
const out = {};
|
|
41
|
+
const startupSec = input.startupTimeoutSec ?? input.startup_timeout_sec;
|
|
42
|
+
if (startupSec != null && startupSec !== '') out.startupTimeoutSec = positiveNumber(startupSec, 'startupTimeoutSec');
|
|
43
|
+
else if (input.startupTimeoutMs != null && input.startupTimeoutMs !== '')
|
|
44
|
+
out.startupTimeoutMs = positiveNumber(input.startupTimeoutMs, 'startupTimeoutMs');
|
|
45
|
+
if (input.toolTimeoutSec != null && input.toolTimeoutSec !== '')
|
|
46
|
+
out.timeoutMs = Math.round(positiveNumber(input.toolTimeoutSec, 'toolTimeoutSec') * 1000);
|
|
47
|
+
else if (input.timeoutMs != null && input.timeoutMs !== '')
|
|
48
|
+
out.timeoutMs = Math.round(positiveNumber(input.timeoutMs, 'timeoutMs'));
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
51
|
+
|
|
29
52
|
export function createMcpServerInput({ mcpClient, getCurrentCwd }) {
|
|
30
53
|
function normalizeMcpServerInput(input = {}) {
|
|
54
|
+
const result = normalizeTransport(input);
|
|
55
|
+
Object.assign(result.config, timeoutFields(input));
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function normalizeTransport(input) {
|
|
31
60
|
const currentCwd = getCurrentCwd();
|
|
32
61
|
const name = clean(input.name)
|
|
33
62
|
.toLowerCase()
|
|
@@ -6,11 +6,28 @@ import { createMcpServerCatalog } from './mcp-glue/server-catalog.mjs';
|
|
|
6
6
|
import { createMcpConnect } from './mcp-glue/connect.mjs';
|
|
7
7
|
import { createMcpServerInput } from './mcp-glue/server-input.mjs';
|
|
8
8
|
|
|
9
|
-
export function createMcpGlue({
|
|
10
|
-
|
|
9
|
+
export function createMcpGlue({
|
|
10
|
+
mcpClient,
|
|
11
|
+
getConfig,
|
|
12
|
+
getCurrentCwd,
|
|
13
|
+
getMcpScopeId = () => null,
|
|
14
|
+
getPluginDataDir,
|
|
15
|
+
listPlugins,
|
|
16
|
+
state,
|
|
17
|
+
}) {
|
|
18
|
+
const catalog = createMcpServerCatalog({
|
|
19
|
+
mcpClient,
|
|
20
|
+
getConfig,
|
|
21
|
+
getCurrentCwd,
|
|
22
|
+
getMcpScopeId,
|
|
23
|
+
getPluginDataDir,
|
|
24
|
+
listPlugins,
|
|
25
|
+
state,
|
|
26
|
+
});
|
|
11
27
|
const connect = createMcpConnect({
|
|
12
28
|
mcpClient,
|
|
13
29
|
getMcpScopeId,
|
|
30
|
+
getCurrentCwd,
|
|
14
31
|
state,
|
|
15
32
|
resolveEffectiveMcpServers: catalog.resolveEffectiveMcpServers,
|
|
16
33
|
mcpStatus: catalog.mcpStatus,
|
|
@@ -19,6 +36,9 @@ export function createMcpGlue({ mcpClient, getConfig, getCurrentCwd, getMcpScope
|
|
|
19
36
|
|
|
20
37
|
return {
|
|
21
38
|
mcpStatus: catalog.mcpStatus,
|
|
39
|
+
resolveMcpCatalog: catalog.resolveCatalog,
|
|
40
|
+
pluginMcpServer: catalog.pluginServer,
|
|
41
|
+
pluginMcpSummary: catalog.pluginMcpSummary,
|
|
22
42
|
getMcpServerConfig: catalog.getMcpServerConfig,
|
|
23
43
|
connectConfiguredMcp: connect.connectConfiguredMcp,
|
|
24
44
|
awaitInitialMcpConnect: connect.awaitInitialMcpConnect,
|
|
@@ -52,6 +52,9 @@ export function createRoutePersistence(deps) {
|
|
|
52
52
|
// A selection for the heir must not leak its tuning into the source model.
|
|
53
53
|
if (!sessionUsesRoute(session, route)) return;
|
|
54
54
|
session.fast = route.fast === true;
|
|
55
|
+
// Absent means on; only the off state is stored on the session.
|
|
56
|
+
if (route.autoEffort === false) session.autoEffort = false;
|
|
57
|
+
else delete session.autoEffort;
|
|
55
58
|
session.effort = route.effectiveEffort || null;
|
|
56
59
|
// The request path reads session.modelParameters; keep only serviceTier in step.
|
|
57
60
|
const { serviceTier: _previous, ...otherParameters } = session.modelParameters || {};
|
|
@@ -55,12 +55,23 @@ async function resolveSelectedRoute(deps, next) {
|
|
|
55
55
|
selectedRoute.effort,
|
|
56
56
|
selectedRoute.modelParameters
|
|
57
57
|
);
|
|
58
|
+
const contextState = resolveRouteContextState(selectedRoute, modelMeta);
|
|
59
|
+
// An exact selection is saved clamped, and not at all when it is the
|
|
60
|
+
// default window; an unknown window keeps it as requested.
|
|
61
|
+
const contextTokens =
|
|
62
|
+
contextState.contextDefaultPercent === undefined ? selectedRoute.contextTokens : contextState.contextTokens;
|
|
63
|
+
const { contextTokens: requestedTokens, ...routeFields } = selectedRoute;
|
|
64
|
+
// Tokens that land on the default window select the default, whatever
|
|
65
|
+
// percent travelled with them.
|
|
66
|
+
const tokensAtDefault = requestedTokens && !contextTokens && contextState.contextDefaultPercent !== undefined;
|
|
58
67
|
return {
|
|
59
68
|
selectedRoute: {
|
|
60
|
-
...
|
|
69
|
+
...routeFields,
|
|
70
|
+
...(tokensAtDefault ? { contextPercent: contextState.contextDefaultPercent } : {}),
|
|
61
71
|
fast: fastCapable ? selectedRoute.fast === true : false,
|
|
62
72
|
// Lets the saved model settings tell a chosen window from the default.
|
|
63
|
-
contextDefaultPercent:
|
|
73
|
+
contextDefaultPercent: contextState.contextDefaultPercent,
|
|
74
|
+
...(contextTokens ? { contextTokens } : {}),
|
|
64
75
|
},
|
|
65
76
|
fastCapable,
|
|
66
77
|
modelMeta,
|
|
@@ -92,9 +103,11 @@ function updateSessionInPlace(deps, session, updateOptions) {
|
|
|
92
103
|
provider: route.provider,
|
|
93
104
|
model: route.model,
|
|
94
105
|
fast: route.fast === true,
|
|
106
|
+
autoEffort: route.autoEffort !== false,
|
|
95
107
|
effort: route.effectiveEffort || null,
|
|
96
108
|
modelParameters: route.modelParameters || {},
|
|
97
109
|
contextPercent: route.contextPercent,
|
|
110
|
+
contextTokens: route.contextTokens || null,
|
|
98
111
|
selectedContextWindow: route.selectedContextWindow || null,
|
|
99
112
|
};
|
|
100
113
|
const updated = mgr.updateSessionRoute?.(session.id, fields, updateOptions);
|
|
@@ -21,7 +21,8 @@ export function createNewSessionConfig({
|
|
|
21
21
|
await flushPendingSessionConfigWrites();
|
|
22
22
|
await sharedCfgMod.pendingConfigWrites();
|
|
23
23
|
sharedCfgMod.invalidateConfigReadCache();
|
|
24
|
-
const
|
|
24
|
+
const mcpSettings = () => [rt.config.mcpServers, rt.config.pluginMcp];
|
|
25
|
+
const previousMcp = mcpSettings();
|
|
25
26
|
// Headless callers inject a deliberately isolated config. Never replace
|
|
26
27
|
// their explicit policy with the interactive profile on disk.
|
|
27
28
|
if (!initialConfig || typeof initialConfig !== 'object') {
|
|
@@ -34,7 +35,7 @@ export function createNewSessionConfig({
|
|
|
34
35
|
invalidatePreSessionToolSurface();
|
|
35
36
|
invalidateSkills();
|
|
36
37
|
await configureEmbedding(sharedCfgMod.readSection('memory')?.embedding || {});
|
|
37
|
-
if (!firstSession || !isDeepStrictEqual(previousMcp,
|
|
38
|
+
if (!firstSession || !isDeepStrictEqual(previousMcp, mcpSettings())) {
|
|
38
39
|
// Reused runtimes may still own old connections. This reset is scoped to
|
|
39
40
|
// the runtime that is constructing the new session, not to its peers.
|
|
40
41
|
await connectConfiguredMcp({ reset: true });
|
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
// pending queue so the model sees it next turn. The delivered registry keeps
|
|
4
4
|
// those two paths from double-injecting the same completion.
|
|
5
5
|
import { modelVisibleToolCompletionMessage } from '../runtime/shared/tool-execution-contract.mjs';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
PENDING_MODE_TASK_NOTIFICATION,
|
|
8
|
+
markCompletionEntry,
|
|
9
|
+
} from '../runtime/agent/orchestrator/session/manager/pending-messages.mjs';
|
|
7
10
|
import {
|
|
8
11
|
isDeliveredCompletion,
|
|
9
12
|
logDuplicateSkip,
|
|
@@ -29,7 +32,7 @@ function cleanSessionId(value) {
|
|
|
29
32
|
// the wake would leave its durable entry parked until the next user message.
|
|
30
33
|
// A completion whose owner is no longer the live session is still dropped (the
|
|
31
34
|
// durable queue carries it into that session's next turn).
|
|
32
|
-
export function createCompletionWakeScheduler({ getCurrentSessionId, getTurnApi, getOwnerLifecycle }) {
|
|
35
|
+
export function createCompletionWakeScheduler({ getCurrentSessionId, getTurnApi, getOwnerLifecycle, beforeWake }) {
|
|
33
36
|
// A closing/terminal owner never starts inference from a completion; the
|
|
34
37
|
// check runs at request time and again inside the delayed callback.
|
|
35
38
|
const ownerOpen = (sessionId) => {
|
|
@@ -55,6 +58,14 @@ export function createCompletionWakeScheduler({ getCurrentSessionId, getTurnApi,
|
|
|
55
58
|
` executionId=${executionId || 'unknown'} queuedMs=${delayMs}\n`
|
|
56
59
|
);
|
|
57
60
|
}
|
|
61
|
+
// Surface hook (idle auto-clear): compacts a cold-cache session before
|
|
62
|
+
// the wake sends it. A failing hook never blocks the wake.
|
|
63
|
+
if (typeof beforeWake === 'function') {
|
|
64
|
+
try {
|
|
65
|
+
await beforeWake(ownerSessionId);
|
|
66
|
+
} catch {}
|
|
67
|
+
if (cleanSessionId(getCurrentSessionId()) !== ownerSessionId || !ownerOpen(ownerSessionId)) return;
|
|
68
|
+
}
|
|
58
69
|
// The wake continues the user turn that launched the worker, so its
|
|
59
70
|
// review keeps that turn's Lead edits and worker diffs.
|
|
60
71
|
await turnApi.ask('', { submittedAt: queuedAt, continueTurn: true });
|
|
@@ -136,7 +147,11 @@ export function createNotificationBus({ listeners, mgr, onCompletionQueued, getO
|
|
|
136
147
|
if (!open) return false;
|
|
137
148
|
if (typeof mgr.enqueuePendingMessage !== 'function') return false;
|
|
138
149
|
try {
|
|
139
|
-
|
|
150
|
+
// A channel notification (webhook event rules, schedule injects, relays)
|
|
151
|
+
// is the runtime reporting, exactly as an attached TUI queues it: a
|
|
152
|
+
// task notification, so text inside it — fenced external webhook values
|
|
153
|
+
// included — never drives explicit skill selection.
|
|
154
|
+
return mgr.enqueuePendingMessage(targetSessionId, { content, mode: PENDING_MODE_TASK_NOTIFICATION }) > 0;
|
|
140
155
|
} catch {
|
|
141
156
|
return false;
|
|
142
157
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
// provider-auth/accounts.mjs — the per-provider account roster and account
|
|
2
2
|
// switching, with the bounded background usage sweep that refreshes quotas.
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
listProviderAccounts,
|
|
5
|
+
materializeProviderAccounts,
|
|
6
|
+
updateProviderAccounts,
|
|
7
|
+
} from '../services/provider-admin.mjs';
|
|
4
8
|
import { getProvider } from '../../runtime/agent/orchestrator/providers/registry.mjs';
|
|
5
9
|
import { fetchOAuthUsageSnapshot } from '../../runtime/agent/orchestrator/providers/oauth-usage.mjs';
|
|
6
10
|
|
|
@@ -11,21 +15,23 @@ export function createAccountApi(
|
|
|
11
15
|
// One in-flight usage sweep per provider; a reopened picker reuses it.
|
|
12
16
|
const accountUsageSweeps = new Map();
|
|
13
17
|
|
|
18
|
+
async function measureAccountUsage(providerId, provider, accounts, force = false) {
|
|
19
|
+
await awaitKeychainPrewarm();
|
|
20
|
+
for (let offset = 0; offset < accounts.length; offset += 4) {
|
|
21
|
+
await Promise.all(
|
|
22
|
+
accounts.slice(offset, offset + 4).map((account) => {
|
|
23
|
+
const target = { provider: providerId, accountId: account.id };
|
|
24
|
+
return fetchOAuthUsageSnapshot(target, provider.forAccount(account.id), () => {}, { force }).catch(
|
|
25
|
+
() => null
|
|
26
|
+
);
|
|
27
|
+
})
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
14
32
|
async function sweepAccountUsage(providerId, provider, accounts) {
|
|
15
33
|
try {
|
|
16
|
-
await
|
|
17
|
-
for (let offset = 0; offset < accounts.length; offset += 4) {
|
|
18
|
-
await Promise.all(
|
|
19
|
-
accounts
|
|
20
|
-
.slice(offset, offset + 4)
|
|
21
|
-
.map((account) =>
|
|
22
|
-
fetchOAuthUsageSnapshot(
|
|
23
|
-
{ provider: providerId, accountId: account.id },
|
|
24
|
-
provider.forAccount(account.id)
|
|
25
|
-
).catch(() => null)
|
|
26
|
-
)
|
|
27
|
-
);
|
|
28
|
-
}
|
|
34
|
+
await measureAccountUsage(providerId, provider, accounts);
|
|
29
35
|
} finally {
|
|
30
36
|
accountUsageSweeps.delete(providerId);
|
|
31
37
|
}
|
|
@@ -69,8 +75,20 @@ export function createAccountApi(
|
|
|
69
75
|
return pool;
|
|
70
76
|
},
|
|
71
77
|
async updateProviderAccounts(providerId, change) {
|
|
78
|
+
// `{ refreshUsage: true }` re-measures every account now (the roster's
|
|
79
|
+
// "Refresh usage") and changes nothing else in the roster. The implicit
|
|
80
|
+
// signed-in account is stored first so its measurement has a row to land on.
|
|
81
|
+
if (change?.refreshUsage === true && Object.keys(change).length === 1) {
|
|
82
|
+
const provider = getProvider(providerId);
|
|
83
|
+
if (typeof provider?.forAccount === 'function') {
|
|
84
|
+
await awaitKeychainPrewarm();
|
|
85
|
+
const { accounts } = await materializeProviderAccounts(providerId);
|
|
86
|
+
await measureAccountUsage(providerId, provider, accounts, true);
|
|
87
|
+
}
|
|
88
|
+
return listProviderAccounts(providerId);
|
|
89
|
+
}
|
|
72
90
|
await awaitKeychainPrewarm();
|
|
73
|
-
const result = updateProviderAccounts(providerId, change);
|
|
91
|
+
const result = await updateProviderAccounts(providerId, change);
|
|
74
92
|
reloadFullConfig();
|
|
75
93
|
invalidateProviderCaches();
|
|
76
94
|
warmProviderModelCache();
|
|
@@ -65,8 +65,10 @@ export function hydrateProviderModelRow(cfg, row) {
|
|
|
65
65
|
) || customAutoEffortCapable(row.provider, cfg?.providers?.[row.provider]?.protocol, row),
|
|
66
66
|
savedEffort: saved.effort || null,
|
|
67
67
|
savedFast: Object.hasOwn(saved, 'fast') ? saved.fast === true : undefined,
|
|
68
|
+
savedAutoEffort: Object.hasOwn(saved, 'autoEffort') ? saved.autoEffort !== false : undefined,
|
|
68
69
|
savedModelParameters: saved.modelParameters || {},
|
|
69
70
|
savedContextPercent: Number(saved.contextPercent) || undefined,
|
|
71
|
+
savedContextTokens: Number(saved.contextTokens) || undefined,
|
|
70
72
|
};
|
|
71
73
|
}
|
|
72
74
|
|
|
@@ -38,7 +38,11 @@ export function createWebSearchCatalog({
|
|
|
38
38
|
try {
|
|
39
39
|
let models = null;
|
|
40
40
|
if (forceRefresh && typeof provider._refreshModelCache === 'function') {
|
|
41
|
-
|
|
41
|
+
try {
|
|
42
|
+
models = await provider._refreshModelCache();
|
|
43
|
+
} catch {
|
|
44
|
+
models = null; // fall back to listModels below
|
|
45
|
+
}
|
|
42
46
|
}
|
|
43
47
|
if (!Array.isArray(models)) models = await provider.listModels();
|
|
44
48
|
if (!Array.isArray(models)) return [];
|
|
@@ -67,16 +67,17 @@ export function createProviderReadiness({ rt, keychain, getReg, getWarmProviderM
|
|
|
67
67
|
await awaitKeychainPrewarm();
|
|
68
68
|
if (rt.closeRequested) throw new Error('runtime is closing');
|
|
69
69
|
const initKey = providerInitCacheKey(providerConfig);
|
|
70
|
-
const existing = providerInitPromises.get(initKey);
|
|
71
|
-
if (existing) return await existing;
|
|
72
70
|
// Provider initialization is idempotent for one normalized config. Keep
|
|
73
71
|
// the fulfilled promise, not only the in-flight one: session resume used
|
|
74
72
|
// to rerun registry/keychain setup on every click even though neither the
|
|
75
73
|
// provider config nor the registry had changed. Auth/config mutations call
|
|
76
74
|
// invalidateProviderCaches(), which clears this gate and preserves the
|
|
77
75
|
// existing refresh semantics.
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
let providerInitPromise = providerInitPromises.get(initKey);
|
|
77
|
+
if (!providerInitPromise) {
|
|
78
|
+
providerInitPromise = Promise.resolve().then(() => getReg().initProviders(providerConfig));
|
|
79
|
+
providerInitPromises.set(initKey, providerInitPromise);
|
|
80
|
+
}
|
|
80
81
|
let result;
|
|
81
82
|
try {
|
|
82
83
|
result = await providerInitPromise;
|
|
@@ -84,13 +85,18 @@ export function createProviderReadiness({ rt, keychain, getReg, getWarmProviderM
|
|
|
84
85
|
if (providerInitPromises.get(initKey) === providerInitPromise) providerInitPromises.delete(initKey);
|
|
85
86
|
throw error;
|
|
86
87
|
}
|
|
87
|
-
if (!rt.
|
|
88
|
-
rt.startupProviderCatalogRefreshStarted = true;
|
|
89
|
-
rt.startupProviderCatalogRefreshPending = true;
|
|
88
|
+
if (!rt.closeRequested) {
|
|
90
89
|
try {
|
|
91
|
-
|
|
90
|
+
// The registry memoizes the refresh per catalog epoch; a provider set
|
|
91
|
+
// change yields a new promise, which gets its own completion handling.
|
|
92
|
+
const refresh = getReg().refreshProviderCatalogsOnStartup();
|
|
93
|
+
if (refresh === rt.startupProviderCatalogRefreshObserved) return result;
|
|
94
|
+
rt.startupProviderCatalogRefreshObserved = refresh;
|
|
95
|
+
rt.startupProviderCatalogRefreshPending = true;
|
|
96
|
+
const isLatest = () => rt.startupProviderCatalogRefreshObserved === refresh;
|
|
97
|
+
void Promise.resolve(refresh)
|
|
92
98
|
.then(() => {
|
|
93
|
-
rt.startupProviderCatalogRefreshPending = false;
|
|
99
|
+
if (isLatest()) rt.startupProviderCatalogRefreshPending = false;
|
|
94
100
|
if (rt.closeRequested) return;
|
|
95
101
|
// Fresh catalog rows invalidate model-derived caches, but the
|
|
96
102
|
// already initialized provider registry remains valid.
|
|
@@ -103,7 +109,7 @@ export function createProviderReadiness({ rt, keychain, getReg, getWarmProviderM
|
|
|
103
109
|
bootProfile('provider-catalogs:refresh-ready');
|
|
104
110
|
})
|
|
105
111
|
.catch((error) => {
|
|
106
|
-
rt.startupProviderCatalogRefreshPending = false;
|
|
112
|
+
if (isLatest()) rt.startupProviderCatalogRefreshPending = false;
|
|
107
113
|
bootProfile('provider-catalogs:refresh-failed', { error: error?.message || String(error) });
|
|
108
114
|
});
|
|
109
115
|
bootProfile('provider-catalogs:refresh-started');
|
|
@@ -28,17 +28,33 @@ export function createExtensionSync({
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
// Apply per-server MCP changes in order, then reconcile: a configured server
|
|
32
|
+
// added, renamed or removed can move a plugin server to another name, and
|
|
33
|
+
// only the reconcile connects it there and drops the stale name. Servers
|
|
34
|
+
// whose resolved config is unchanged stay untouched.
|
|
35
|
+
async function applyMcpChanges(changes) {
|
|
36
|
+
for (const { name, enabled } of changes) await connectConfiguredMcp({ only: name, enabled });
|
|
37
|
+
return connectConfiguredMcp({ reconcile: true });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function refreshState(kind, detail = null) {
|
|
32
41
|
reloadFullConfig?.();
|
|
33
42
|
if (kind === 'skills' || kind === 'plugins') invalidateSkills?.();
|
|
34
|
-
|
|
43
|
+
const mcpChanges = kind === 'mcp' ? detail?.mcpChanges : null;
|
|
44
|
+
if (Array.isArray(mcpChanges)) {
|
|
45
|
+
await applyMcpChanges(mcpChanges);
|
|
46
|
+
} else if (kind === 'plugins') {
|
|
47
|
+
// Plugin servers are derived from the registry: connect what is new or
|
|
48
|
+
// changed, drop what is gone or disabled, leave the rest connected.
|
|
49
|
+
await connectConfiguredMcp({ reconcile: true });
|
|
50
|
+
} else if (kind === 'mcp') {
|
|
35
51
|
await connectConfiguredMcp({ reset: true });
|
|
36
52
|
}
|
|
37
53
|
await refreshSurface(kind);
|
|
38
54
|
}
|
|
39
55
|
|
|
40
56
|
const subscription = subscribeGlobalExtensionChanges(refreshState);
|
|
41
|
-
const publish = (kind) => publishGlobalExtensionChange(kind, subscription.id);
|
|
57
|
+
const publish = (kind, detail = null) => publishGlobalExtensionChange(kind, subscription.id, detail);
|
|
42
58
|
|
|
43
59
|
function scheduleMcpToggle(serverName, enabled) {
|
|
44
60
|
const chain = mcpToggleChains.get(serverName) || { desired: enabled, running: null };
|
|
@@ -65,25 +81,47 @@ export function createExtensionSync({
|
|
|
65
81
|
|
|
66
82
|
/** Skills/plugins invalidate the skill cache; every kind rebuilds the
|
|
67
83
|
* pre-session surface and notifies the other runtimes. */
|
|
68
|
-
async function announce(kind, { invalidate = kind !== 'mcp' } = {}) {
|
|
84
|
+
async function announce(kind, { invalidate = kind !== 'mcp', detail = null } = {}) {
|
|
69
85
|
if (invalidate) invalidateSkills?.();
|
|
70
86
|
await refreshSurface(kind);
|
|
71
|
-
await publish(kind);
|
|
87
|
+
await publish(kind, detail);
|
|
72
88
|
}
|
|
73
89
|
|
|
74
|
-
/** Reconnect
|
|
75
|
-
|
|
90
|
+
/** Reconnect MCP after a config write, then announce. With `only`, just that
|
|
91
|
+
* server is (re)connected (or disconnected when `enabled` is false) and
|
|
92
|
+
* `drop` names (e.g. a renamed/removed server) are disconnected; every other
|
|
93
|
+
* server stays untouched. Without `only`, every configured server reconnects. */
|
|
94
|
+
async function reconnectMcpAndAnnounce({ only = null, enabled = true, drop = [] } = {}) {
|
|
95
|
+
if (only || drop.length > 0) {
|
|
96
|
+
// Other runtimes receive the same scoped change list, not a full reset.
|
|
97
|
+
const mcpChanges = [
|
|
98
|
+
...drop.map((name) => ({ name, enabled: false })),
|
|
99
|
+
...(only ? [{ name: only, enabled }] : []),
|
|
100
|
+
];
|
|
101
|
+
const status = await applyMcpChanges(mcpChanges);
|
|
102
|
+
await announce('mcp', { detail: { mcpChanges } });
|
|
103
|
+
return status;
|
|
104
|
+
}
|
|
76
105
|
const status = await connectConfiguredMcp({ reset: true });
|
|
77
106
|
await announce('mcp');
|
|
78
107
|
return status;
|
|
79
108
|
}
|
|
80
109
|
|
|
110
|
+
/** After a plugin registry change: reconcile this runtime's MCP connections
|
|
111
|
+
* with the derived server set first, then let peers do the same. */
|
|
112
|
+
async function reconcilePluginsAndAnnounce() {
|
|
113
|
+
const status = await connectConfiguredMcp({ reconcile: true });
|
|
114
|
+
await announce('plugins');
|
|
115
|
+
return status;
|
|
116
|
+
}
|
|
117
|
+
|
|
81
118
|
return {
|
|
82
119
|
refreshSurface,
|
|
83
120
|
publish,
|
|
84
121
|
scheduleMcpToggle,
|
|
85
122
|
announce,
|
|
86
123
|
reconnectMcpAndAnnounce,
|
|
124
|
+
reconcilePluginsAndAnnounce,
|
|
87
125
|
dispose: () => subscription.unsubscribe(),
|
|
88
126
|
};
|
|
89
127
|
}
|