mixdog 1.2.6 → 1.3.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/LICENSES/simple-icons-CC0-1.0.txt +30 -0
- package/NOTICE.md +71 -9
- package/package.json +4 -1
- package/scripts/check-model-recommendations.mjs +89 -0
- package/scripts/gate-local.mjs +7 -0
- package/scripts/lib/isolated-test-env.mjs +16 -0
- package/src/agents/reviewer/AGENT.md +4 -2
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +10 -0
- package/src/defaults/skills/browser-use/SKILL.md +5 -0
- package/src/defaults/skills/memory-management/SKILL.md +4 -1
- package/src/defaults/skills/setup/references/actions.md +14 -4
- package/src/defaults/skills/setup-guide/SKILL.md +178 -0
- package/src/defaults/skills/setup-guide/model-recommendations.json +333 -0
- package/src/lib/rules-builder.cjs +55 -6
- package/src/output-styles/common.md +13 -8
- package/src/rules/agent/AGENT.md +4 -0
- package/src/rules/agent-mode/AGENT_MODE.md +24 -0
- package/src/rules/agent-mode/MIXY.md +28 -0
- package/src/rules/agent-mode/ROUTINE.md +6 -0
- package/src/rules/lead/LEAD.md +7 -3
- package/src/rules/shared/70-delivery.md +3 -0
- package/src/runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs +86 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +77 -14
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +241 -14
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +4 -2
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +216 -0
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +5 -4
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +10 -1
- package/src/runtime/agent/orchestrator/mcp/client.mjs +115 -11
- package/src/runtime/agent/orchestrator/mcp/oauth-account.mjs +97 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +49 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +59 -9
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +32 -7
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +45 -6
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +195 -6
- package/src/runtime/agent/orchestrator/mcp/server-connectors.mjs +17 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +7 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +10 -3
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +7 -8
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/lib/tool-call-wire-ids.mjs +65 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +8 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +17 -12
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +14 -2
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +17 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +96 -1
- package/src/runtime/agent/orchestrator/runtime-core/context-status-shape.mjs +4 -0
- package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +6 -4
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +14 -0
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +1 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +12 -6
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +32 -5
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +21 -5
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +40 -7
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +52 -20
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/agent-home.d.mts +4 -0
- package/src/runtime/agent/orchestrator/session/agent-home.mjs +33 -0
- package/src/runtime/agent/orchestrator/session/agent-mode.mjs +62 -0
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.d.mts +31 -0
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.mjs +241 -0
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +166 -0
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +650 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +192 -0
- package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +95 -0
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +221 -0
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +195 -0
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +167 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +108 -6
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +74 -15
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +9 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +5 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +13 -3
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +49 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-lifecycle-epoch.mjs +0 -8
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +44 -16
- package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +50 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -5
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +39 -4
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +33 -24
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +58 -8
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +58 -0
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +27 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +32 -5
- package/src/runtime/agent/orchestrator/session/routine-result.d.mts +86 -0
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +329 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/store-record-strict-scan.mjs +28 -9
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -12
- package/src/runtime/agent/orchestrator/session/store-summary-last-message.mjs +46 -0
- package/src/runtime/agent/orchestrator/session/store-summary-visibility.mjs +0 -4
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +58 -10
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +92 -15
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +12 -0
- package/src/runtime/agent/orchestrator/tools/builtin/native-search-client.mjs +113 -5
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +4 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +25 -1
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +8 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +6 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +3 -0
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +75 -57
- package/src/runtime/attachments/store.mjs +6 -0
- package/src/runtime/browser-bridge/client.mjs +24 -0
- package/src/runtime/channels/lib/scheduler.mjs +40 -12
- package/src/runtime/channels/lib/schedules-db.mjs +71 -12
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +36 -16
- package/src/runtime/channels/lib/webhook.mjs +0 -1
- package/src/runtime/channels/lib/webhooks-db.mjs +100 -10
- package/src/runtime/channels/lib/worker-main.mjs +17 -20
- package/src/runtime/computer-bridge/client.mjs +28 -1
- package/src/runtime/connectors/gmail-app-password.mjs +690 -0
- package/src/runtime/connectors/google-mcp.mjs +446 -0
- package/src/runtime/effort-judge/judge-client.mjs +1 -1
- package/src/runtime/effort-judge/model-manifest.json +7 -7
- package/src/runtime/memory/lib/core-memory-access.mjs +69 -0
- package/src/runtime/memory/lib/core-memory-file.mjs +16 -8
- package/src/runtime/memory/lib/core-memory-index.mjs +15 -9
- package/src/runtime/memory/lib/core-memory-management.mjs +10 -4
- package/src/runtime/memory/lib/core-memory-store.mjs +53 -30
- package/src/runtime/memory/lib/core-memory-uniqueness.mjs +10 -6
- package/src/runtime/memory/lib/http-router/session-routes.mjs +3 -2
- package/src/runtime/memory/lib/memory-action-handlers/core-actions.mjs +44 -14
- package/src/runtime/memory/lib/memory-schema/core-and-meta.mjs +11 -0
- package/src/runtime/memory/lib/memory.mjs +7 -1
- package/src/runtime/memory/lib/query-core-recall.mjs +9 -1
- package/src/runtime/memory/lib/query-hybrid-search.mjs +2 -0
- package/src/runtime/memory/lib/tool-call-handler.mjs +2 -0
- package/src/runtime/memory/tool-defs.mjs +5 -0
- package/src/runtime/shared/agent-avatar-sprites.mjs +445 -0
- package/src/runtime/shared/agent-avatar.d.mts +64 -0
- package/src/runtime/shared/agent-avatar.mjs +320 -0
- package/src/runtime/shared/agent-kind.mjs +152 -0
- package/src/runtime/shared/agent-route-config.d.mts +4 -0
- package/src/runtime/shared/agent-route-config.mjs +30 -0
- package/src/runtime/shared/agent-store.mjs +132 -0
- package/src/runtime/shared/atomic-file.mjs +14 -1
- package/src/runtime/shared/bot-split-migration.mjs +457 -0
- package/src/runtime/shared/config-patch.mjs +20 -1
- package/src/runtime/shared/config.mjs +8 -1
- package/src/runtime/shared/connector-accounts.mjs +15 -0
- package/src/runtime/shared/connector-catalog.d.mts +51 -0
- package/src/runtime/shared/connector-catalog.mjs +228 -0
- package/src/runtime/shared/connector-triggers.d.mts +3 -0
- package/src/runtime/shared/connector-triggers.mjs +45 -0
- package/src/runtime/shared/err-text.mjs +3 -1
- package/src/runtime/shared/error-presentation.mjs +91 -6
- package/src/runtime/shared/google-oauth-client.mjs +24 -0
- package/src/runtime/shared/handoff-artifacts.d.mts +20 -0
- package/src/runtime/shared/handoff-artifacts.mjs +61 -0
- package/src/runtime/shared/held-request-host.d.mts +12 -0
- package/src/runtime/shared/held-request-host.mjs +71 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +6 -1
- package/src/runtime/shared/llm/usage-accounting.mjs +7 -1
- package/src/runtime/shared/model-route-fallback.mjs +79 -7
- package/src/runtime/shared/plain-preview.d.mts +1 -0
- package/src/runtime/shared/plain-preview.mjs +33 -0
- package/src/runtime/shared/routine-limits.d.mts +11 -0
- package/src/runtime/shared/routine-limits.mjs +21 -0
- package/src/runtime/shared/routine-trigger.d.mts +10 -0
- package/src/runtime/shared/routine-trigger.mjs +44 -0
- package/src/runtime/shared/schedule-model-ref.mjs +9 -10
- package/src/runtime/shared/sensitive-path-rules.d.mts +15 -0
- package/src/runtime/shared/sensitive-path-rules.mjs +256 -0
- package/src/runtime/shared/slow-span.mjs +4 -12
- package/src/runtime/shared/statusline/statusline-segments.mjs +13 -1
- package/src/runtime/shared/transcript-metadata.mjs +10 -0
- package/src/runtime/shared/turn-changes.mjs +0 -8
- package/src/runtime/shared/usage-readout-totals.mjs +58 -0
- package/src/runtime/shared/user-data-guard.mjs +119 -38
- package/src/session-runtime/agent-home-delivery.mjs +826 -0
- package/src/session-runtime/agent-profile-changes.mjs +21 -0
- package/src/session-runtime/agent-room-delivery.mjs +133 -0
- package/src/session-runtime/agent-task-sessions.mjs +460 -0
- package/src/session-runtime/boot/apis.mjs +63 -18
- package/src/session-runtime/boot/facade.mjs +5 -8
- package/src/session-runtime/boot/infrastructure.mjs +28 -17
- package/src/session-runtime/boot/providers.mjs +14 -4
- package/src/session-runtime/boot/tools.mjs +3 -0
- package/src/session-runtime/channel-config-api.mjs +53 -5
- package/src/session-runtime/config-lifecycle.mjs +43 -2
- package/src/session-runtime/cwd-plugins/core-memory-context.mjs +36 -20
- package/src/session-runtime/cwd-plugins/plugin-status.mjs +6 -1
- package/src/session-runtime/handoff-attachments.mjs +593 -0
- package/src/session-runtime/held-requests.mjs +228 -0
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +121 -0
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -1
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +31 -2
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +56 -3
- package/src/session-runtime/internal-tool-executor.mjs +2 -0
- package/src/session-runtime/lifecycle/session-catalog.mjs +9 -0
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +4 -0
- package/src/session-runtime/lifecycle/shared.mjs +6 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +8 -0
- package/src/session-runtime/mcp-glue/server-input.mjs +3 -0
- package/src/session-runtime/mcp-oauth-login.mjs +112 -15
- package/src/session-runtime/model-route/route-persist.mjs +2 -2
- package/src/session-runtime/model-route/route-tuning.mjs +7 -1
- package/src/session-runtime/model-route/set-route.mjs +35 -4
- package/src/session-runtime/native-web-search.mjs +2 -2
- package/src/session-runtime/new-session-config.mjs +6 -1
- package/src/session-runtime/owned-automation-run.mjs +229 -0
- package/src/session-runtime/resource-api.mjs +5 -0
- package/src/session-runtime/resource-mcp-api.mjs +107 -13
- package/src/session-runtime/resource-skills-api.mjs +12 -0
- package/src/session-runtime/room-member-gate.mjs +48 -0
- package/src/session-runtime/route-resolution.mjs +5 -11
- package/src/session-runtime/routine-home-turn.mjs +156 -0
- package/src/session-runtime/routine-owner.mjs +48 -0
- package/src/session-runtime/schedule-session-run.mjs +30 -64
- package/src/session-runtime/services/agent-tool/helpers.mjs +30 -1
- package/src/session-runtime/services/agent-tool/send-flow.mjs +11 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +19 -4
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +2 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +4 -1
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +5 -8
- package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
- package/src/session-runtime/services/channel-admin.mjs +93 -24
- package/src/session-runtime/services/memory-access.mjs +37 -0
- package/src/session-runtime/services/provider-admin.mjs +74 -39
- package/src/session-runtime/services/schedule-access.mjs +91 -0
- package/src/session-runtime/session-create/session-options.mjs +34 -7
- package/src/session-runtime/session-hooks.mjs +16 -8
- package/src/session-runtime/setup-tool/executor.mjs +79 -6
- package/src/session-runtime/setup-tool/extended-actions.mjs +90 -20
- package/src/session-runtime/setup-tool/settings-contract.mjs +14 -6
- package/src/session-runtime/setup-tool/tool-defs.mjs +8 -0
- package/src/session-runtime/skills-api.mjs +16 -1
- package/src/session-runtime/tool-policy-refresh.mjs +249 -29
- package/src/session-runtime/turn/session-ops.mjs +8 -1
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +10 -2
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +14 -0
- package/src/session-runtime/webhook-session-run.mjs +49 -67
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +239 -0
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +650 -25
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +67 -7
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +11 -4
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +11 -1
- package/src/session-runtime/workflow-agents-api.mjs +4 -1
- package/src/standalone/daemon-agent-control.mjs +1 -8
- package/src/standalone/daemon-session-control.mjs +21 -4
- package/src/standalone/daemon.mjs +31 -5
- package/src/standalone/session-protocol.mjs +27 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +46 -3
- package/src/standalone/session-service/agent-tree.mjs +4 -3
- package/src/standalone/session-service/session-calls/session-turns.mjs +28 -0
- package/src/standalone/session-service.mjs +19 -0
- package/src/tui/app/slash-commands.mjs +20 -0
- package/src/tui/dist/index.mjs +234 -95
- package/src/tui/session/context-state.mjs +6 -1
- package/src/tui/session/notice-surface.mjs +34 -4
- package/src/tui/session/queue-helpers.mjs +2 -1
- package/src/tui/session/session-api/extensions.mjs +4 -0
- package/src/tui/session/session-api/intake/submission.mjs +5 -0
- package/src/tui/session/session-api/integrations.mjs +8 -0
- package/src/tui/session/session-api/lifecycle/session-reset.mjs +13 -3
- package/src/tui/session/session-api/lifecycle.mjs +17 -1
- package/src/tui/session/session-api/routes.mjs +61 -5
- package/src/tui/session/session-flow/drain.mjs +12 -3
- package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -1
- package/src/tui/session/session-flow/queue/take-entries.mjs +3 -2
- package/src/tui/session/session-flow/steering.mjs +58 -24
- package/src/tui/session/tool-approval.mjs +26 -5
- package/src/tui/session/transcript-intake.mjs +8 -2
- package/src/tui/session/transcript-spill.mjs +5 -1
- package/src/tui/session/tui-steering-persist.mjs +65 -42
- package/src/tui/session/turn-live-call.mjs +64 -0
- package/src/tui/session/turn.mjs +34 -8
- package/src/session-runtime/automation-agents.mjs +0 -94
- package/src/session-runtime/automation-workflow.mjs +0 -59
|
@@ -29,15 +29,22 @@ export function createSessionOps(deps) {
|
|
|
29
29
|
} catch {}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
// `rebuildPrompt` (an agent chat's "대화 초기화"): refused while a turn
|
|
33
|
+
// runs, and the emptied session's prompt and tool surface are then rebuilt
|
|
34
|
+
// from the current rules, as a new session's are (refreshEmptySessionToolPolicy).
|
|
32
35
|
async function clear(options = {}) {
|
|
33
36
|
const session = getSession();
|
|
34
37
|
if (!session?.id) return false;
|
|
38
|
+
const rebuild = options.rebuildPrompt === true;
|
|
39
|
+
if (rebuild && getActiveTurnCount() > 0) throw new Error('The session is running a turn; wait for it to finish.');
|
|
35
40
|
const cleared = await mgr.clearSessionMessages(session.id, options);
|
|
36
41
|
if (!cleared) return false;
|
|
37
42
|
setSession(typeof cleared === 'object' ? cleared : mgr.getSession(session.id) || session);
|
|
38
43
|
if (options.recoverAgent === true) recoverAgentWorkers();
|
|
44
|
+
let promptRebuilt = false;
|
|
45
|
+
if (rebuild) promptRebuilt = (await refreshEmptySessionToolPolicy?.())?.appliedToCurrentSession === true;
|
|
39
46
|
invalidateContextStatusCache();
|
|
40
|
-
return true;
|
|
47
|
+
return rebuild ? { promptRebuilt } : true;
|
|
41
48
|
}
|
|
42
49
|
|
|
43
50
|
// Message-selector rewind: drop the chosen user prompt and everything
|
|
@@ -61,11 +61,17 @@ export function createAskCallbacks({ transcript, notifyFnForSession, scheduleSea
|
|
|
61
61
|
|
|
62
62
|
// The turn's change-record key rides the caller's transcript metadata (in
|
|
63
63
|
// place: the stream stamps assistantAt on this same object), so the
|
|
64
|
-
// persisted user row and completion carry it across restore.
|
|
64
|
+
// persisted user row and completion carry it across restore. A merged
|
|
65
|
+
// batch also names every submission it delivers, so a queued-input restore
|
|
66
|
+
// can tell each one delivered.
|
|
65
67
|
function stampCheckpoint(options) {
|
|
66
68
|
const meta = options.transcriptMeta;
|
|
69
|
+
if (!meta || typeof meta !== 'object') return meta;
|
|
67
70
|
const checkpointId = String(options.id || '').trim();
|
|
68
|
-
if (checkpointId
|
|
71
|
+
if (checkpointId) meta.checkpointId = checkpointId;
|
|
72
|
+
if (Array.isArray(options.submissionIds) && options.submissionIds.length > 1) {
|
|
73
|
+
meta.submissionIds = options.submissionIds.map(String);
|
|
74
|
+
}
|
|
69
75
|
return meta;
|
|
70
76
|
}
|
|
71
77
|
|
|
@@ -74,6 +80,8 @@ export function createAskCallbacks({ transcript, notifyFnForSession, scheduleSea
|
|
|
74
80
|
beforeToolExecution: () => turn.snapshot.promise || Promise.resolve(),
|
|
75
81
|
transcriptMeta: stampCheckpoint(options),
|
|
76
82
|
promptSource: options.promptSource,
|
|
83
|
+
// A routine turn's trusted selection text (its instructions only).
|
|
84
|
+
...(typeof options.skillSelection === 'string' ? { skillSelection: options.skillSelection } : {}),
|
|
77
85
|
retryFailedTurn: options.retryFailedTurn === true,
|
|
78
86
|
retryTurnId: options.retryTurnId,
|
|
79
87
|
retryAttemptId: options.retryAttemptId,
|
|
@@ -10,6 +10,8 @@ import { throwIfAborted } from '../../../runtime/shared/abort-race.mjs';
|
|
|
10
10
|
// UserPromptSubmit hook.
|
|
11
11
|
export function createTurnPreparation({
|
|
12
12
|
getSession,
|
|
13
|
+
setSession,
|
|
14
|
+
mgr,
|
|
13
15
|
getCurrentCwd,
|
|
14
16
|
awaitRoutePreparation,
|
|
15
17
|
createCurrentSession,
|
|
@@ -24,6 +26,7 @@ export function createTurnPreparation({
|
|
|
24
26
|
prepareTurnWorkspace,
|
|
25
27
|
admitTurnWorkspace,
|
|
26
28
|
applyPendingRoute,
|
|
29
|
+
applyPendingAgentProfile,
|
|
27
30
|
}) {
|
|
28
31
|
const scopedMcpTools = (session) => scopedMcpToolsFor(session, getConfig());
|
|
29
32
|
|
|
@@ -104,6 +107,15 @@ export function createTurnPreparation({
|
|
|
104
107
|
}
|
|
105
108
|
throwIfAborted(turn.signal);
|
|
106
109
|
assertSessionAdmission?.();
|
|
110
|
+
// askSession runs the turn on the session the store serves for this id.
|
|
111
|
+
// While this runtime idled, the store's idle sweep may have released the
|
|
112
|
+
// snapshot it holds, and the store then serves a fresh parse of the file:
|
|
113
|
+
// preparing the turn on the held copy would leave its one-shot work (the
|
|
114
|
+
// first-turn MCP fold, its flag) undone on the turn's session, which then
|
|
115
|
+
// rewrites the prompt it already sent on the next turn. Prepare the turn
|
|
116
|
+
// on the session it runs on (as completeTurn adopts it afterwards).
|
|
117
|
+
const stored = mgr.getSession(getSession().id);
|
|
118
|
+
if (stored && stored !== getSession()) setSession(stored);
|
|
107
119
|
// Turn admission: waits while this session's workspace transitions or
|
|
108
120
|
// another session changes the checkout this session works in, then holds
|
|
109
121
|
// the turn registered (released by settleTurn) so no checkout changes
|
|
@@ -131,6 +143,8 @@ export function createTurnPreparation({
|
|
|
131
143
|
assertSessionAdmission?.();
|
|
132
144
|
}
|
|
133
145
|
const modelSwitch = applyPendingRoute?.();
|
|
146
|
+
// An agent profile saved while the previous turn ran applies from this one.
|
|
147
|
+
await applyPendingAgentProfile?.();
|
|
134
148
|
options.onRouteApplied?.(getSession());
|
|
135
149
|
if (modelSwitch) options.onModelSwitch?.(modelSwitch);
|
|
136
150
|
ensureSessionTranscriptWriter?.();
|
|
@@ -1,83 +1,65 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Run an inbound webhook
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* name). Invoked from the channels worker's webhook dispatch.
|
|
2
|
+
* Run an inbound webhook: the endpoint's instructions and the fenced event
|
|
3
|
+
* payload become one turn in its owner bot's home thread
|
|
4
|
+
* (routine-home-turn.mjs). Invoked from the channels worker's webhook
|
|
5
|
+
* dispatch and the app's "Run now".
|
|
7
6
|
*/
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { modelRouteFields, parseScheduleModelRef } from '../runtime/shared/schedule-model-ref.mjs';
|
|
12
|
-
import { migrateCodexRoute } from '../runtime/agent/orchestrator/providers/openai-oauth-catalog-store.mjs';
|
|
13
|
-
import { automationWorkflowOpts } from './automation-workflow.mjs';
|
|
14
|
-
import { runAutomationTurns } from './automation-agents.mjs';
|
|
15
|
-
import { automationPromptContent } from '../runtime/shared/automation-attachments.mjs';
|
|
7
|
+
import { markEndpointRun } from '../runtime/channels/lib/webhooks-db.mjs';
|
|
8
|
+
import { runOwnedAutomation } from './owned-automation-run.mjs';
|
|
9
|
+
import { runRoutineTurn } from './routine-home-turn.mjs';
|
|
16
10
|
|
|
17
|
-
/**
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
11
|
+
/**
|
|
12
|
+
* One run of the endpoint in its owner's thread (Mixy when absent): a run
|
|
13
|
+
* while the previous one of the same endpoint is still going is skipped (and
|
|
14
|
+
* stamped), and every outcome is stamped on the endpoint. `prompt` carries the
|
|
15
|
+
* fenced payload; `skillSelection` only the endpoint's instructions.
|
|
16
|
+
*/
|
|
17
|
+
export async function runWebhookSession({ ownerAgentId = null, ...options }, deps = {}) {
|
|
18
|
+
const name = String(options.name || '').trim();
|
|
19
|
+
const { markRun = markEndpointRun, run = runWebhookTurn, ...ownedDeps } = deps;
|
|
20
|
+
const stamp = (outcome) =>
|
|
21
|
+
markRun(name, outcome, new Date()).catch((error) =>
|
|
22
|
+
process.stderr.write(`mixdog webhook: ${name} ${outcome} stamp failed: ${error?.message || error}\n`)
|
|
23
|
+
);
|
|
24
|
+
let outcome;
|
|
25
|
+
try {
|
|
26
|
+
// The dispatch's cancellation reaches the run as `signal`.
|
|
27
|
+
outcome = await runOwnedAutomation(
|
|
28
|
+
'webhook',
|
|
29
|
+
{ name, ownerAgentId },
|
|
30
|
+
({ signal }) => run({ ...options, ownerAgentId, signal }),
|
|
31
|
+
{ recordSkip: () => stamp('skipped'), signal: options.signal || null, ...ownedDeps }
|
|
32
|
+
);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
await stamp('failed');
|
|
35
|
+
throw error;
|
|
23
36
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (maintenance?.provider && maintenance?.model) return modelRouteFields(maintenance);
|
|
27
|
-
throw new Error('webhook run has no model: set one on the endpoint or configure maintenance.webhook');
|
|
37
|
+
if (!outcome.skipped) await stamp('success');
|
|
38
|
+
return outcome;
|
|
28
39
|
}
|
|
29
40
|
|
|
30
|
-
|
|
41
|
+
/** One turn in the owner's thread; `skillSelection` absent selects nothing. */
|
|
42
|
+
function runWebhookTurn({
|
|
31
43
|
name,
|
|
32
|
-
model = null,
|
|
33
44
|
prompt,
|
|
45
|
+
ownerAgentId = null,
|
|
34
46
|
cwd = null,
|
|
35
|
-
workflow = null,
|
|
36
47
|
attachments = null,
|
|
37
|
-
|
|
38
|
-
// Endpoint-authored instructions: the run's ONLY skill-selection input.
|
|
39
|
-
// `prompt` also carries the fenced external payload, which must never
|
|
40
|
-
// select a skill; absent means nothing selects.
|
|
48
|
+
event = '',
|
|
41
49
|
skillSelection = '',
|
|
50
|
+
signal = null,
|
|
42
51
|
}) {
|
|
43
52
|
const endpoint = String(name || '').trim();
|
|
44
|
-
const body = String(prompt || '').trim();
|
|
45
53
|
if (!endpoint) throw new Error('runWebhookSession: endpoint name required');
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
sourceName: endpoint,
|
|
57
|
-
...(projectCwd ? { cwd: projectCwd } : {}),
|
|
58
|
-
desktopSession: projectCwd
|
|
59
|
-
? { classification: 'project', projectPath: projectCwd }
|
|
60
|
-
: { classification: 'task', projectPath: null },
|
|
61
|
-
...automationWorkflowOpts(workflow),
|
|
54
|
+
return runRoutineTurn({
|
|
55
|
+
kind: 'webhook',
|
|
56
|
+
name: endpoint,
|
|
57
|
+
ownerAgentId,
|
|
58
|
+
prompt,
|
|
59
|
+
skillSelection: String(skillSelection ?? ''),
|
|
60
|
+
attachments,
|
|
61
|
+
cwd,
|
|
62
|
+
event,
|
|
63
|
+
signal,
|
|
62
64
|
});
|
|
63
|
-
// The user message leads with the endpoint's instructions, so Recent titles
|
|
64
|
-
// read as the user-authored intent rather than payload noise.
|
|
65
|
-
// Stored attachments ride along as composer-style content parts.
|
|
66
|
-
const content = automationPromptContent(body, attachments);
|
|
67
|
-
// askOpts.signal is the parent-abort link: it is cascaded onto the turn
|
|
68
|
-
// controller, so aborting it stops the in-flight provider/tool work instead
|
|
69
|
-
// of leaving a timed-out delivery's session running with live side effects.
|
|
70
|
-
const ask = (turnContent, askOpts) =>
|
|
71
|
-
askSession(session.id, turnContent, null, null, projectCwd || undefined, undefined, {
|
|
72
|
-
...askOpts,
|
|
73
|
-
...(signal ? { signal } : {}),
|
|
74
|
-
});
|
|
75
|
-
// Agents the run delegates to report back; each result is the next turn
|
|
76
|
-
// (runAutomationTurns marks those turns as task notifications).
|
|
77
|
-
const result = await runAutomationTurns(
|
|
78
|
-
session.id,
|
|
79
|
-
() => ask(content, { skillSelection: String(skillSelection ?? '') }),
|
|
80
|
-
ask
|
|
81
|
-
);
|
|
82
|
-
return { sessionId: session.id, result: String(result?.content || '') };
|
|
83
65
|
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { readdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import {
|
|
4
|
+
CONNECTOR_PERMISSIONS,
|
|
5
|
+
connectorEnabled,
|
|
6
|
+
DENY_ALL_CONNECTORS,
|
|
7
|
+
migrateLegacyConnectorPolicy,
|
|
8
|
+
PROJECT_CONNECTORS_FILE,
|
|
9
|
+
parseConnectorPolicy,
|
|
10
|
+
readProjectConnectorsFile,
|
|
11
|
+
storedConnectorPolicy,
|
|
12
|
+
} from '../../runtime/agent/orchestrator/mcp/agent-connectors.mjs';
|
|
13
|
+
import {
|
|
14
|
+
cwdWithinProjects,
|
|
15
|
+
extensionScopesFromConfig,
|
|
16
|
+
withExtensionScope,
|
|
17
|
+
} from '../../runtime/shared/extension-scopes.mjs';
|
|
18
|
+
import { withFileLockSync, writeJsonAtomicSync } from '../../runtime/shared/atomic-file.mjs';
|
|
19
|
+
import { listProjectsStrict } from '../../runtime/shared/projects.mjs';
|
|
20
|
+
import { isSelfMcpToolName, parseMcpToolName } from '../../runtime/shared/tool-primitives.mjs';
|
|
21
|
+
import { resolveDataDir } from './shared.mjs';
|
|
22
|
+
|
|
23
|
+
const samePath = (left, right) => cwdWithinProjects(left, [right]) && cwdWithinProjects(right, [left]);
|
|
24
|
+
const PLUGIN_REGISTRY_WARNING = /^plugin MCP servers unavailable/;
|
|
25
|
+
|
|
26
|
+
// Host-only surface for the connector switches ("사용할 커넥터"): the global
|
|
27
|
+
// MCP servers (with their sign-in state), and per agent and per project which
|
|
28
|
+
// of them are on. Every installed connector is on unless switched off there.
|
|
29
|
+
// Agent policies go through the agent editor, which keeps every other
|
|
30
|
+
// agent.json key; project policies live in <data>/project-connectors.json,
|
|
31
|
+
// keyed by the registered Project path.
|
|
32
|
+
export function createAgentConnectorsApi(deps, editor) {
|
|
33
|
+
const {
|
|
34
|
+
mcpStatus,
|
|
35
|
+
getMcpTools,
|
|
36
|
+
getConfig,
|
|
37
|
+
saveConfigAndAdopt,
|
|
38
|
+
resolveConfiguredMcpCatalog,
|
|
39
|
+
listProjects = listProjectsStrict,
|
|
40
|
+
} = deps;
|
|
41
|
+
const dataDir = () => resolveDataDir(deps);
|
|
42
|
+
const projectFile = () => join(dataDir(), PROJECT_CONNECTORS_FILE);
|
|
43
|
+
const installedIds = () => listConnectors().map(({ id }) => id);
|
|
44
|
+
const switches = (policy) => installedIds().map((id) => ({ id, enabled: connectorEnabled(policy, id) }));
|
|
45
|
+
// A legacy list or an unreadable policy becomes its deny-list equivalent
|
|
46
|
+
// over today's connectors before any edit, so an edit never widens it.
|
|
47
|
+
const editablePolicy = (agentId) =>
|
|
48
|
+
migrateLegacyConnectorPolicy(editor.getAgentConnectorPolicy(agentId), installedIds()) || { off: [], tools: {} };
|
|
49
|
+
|
|
50
|
+
function listConnectors() {
|
|
51
|
+
return (mcpStatus()?.servers || []).map((row) => ({
|
|
52
|
+
id: row.name,
|
|
53
|
+
enabled: row.enabled !== false,
|
|
54
|
+
status: row.status,
|
|
55
|
+
connected: row.connected === true,
|
|
56
|
+
authRequired: row.authRequired === true,
|
|
57
|
+
signedIn: row.oauth ? row.oauth.signedIn === true : null,
|
|
58
|
+
transport: row.transport,
|
|
59
|
+
toolCount: row.toolCount || 0,
|
|
60
|
+
source: row.source,
|
|
61
|
+
...(row.error ? { error: row.error } : {}),
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// `readOnly` is the server's own `readOnlyHint` (null when it gives none).
|
|
66
|
+
function listConnectorTools(connectorId) {
|
|
67
|
+
return (getMcpTools() || [])
|
|
68
|
+
.filter((tool) => !isSelfMcpToolName(tool) && parseMcpToolName(tool)?.server === connectorId)
|
|
69
|
+
.map((tool) => {
|
|
70
|
+
const annotations = tool.annotations && typeof tool.annotations === 'object' ? tool.annotations : {};
|
|
71
|
+
return {
|
|
72
|
+
name: parseMcpToolName(tool).tool,
|
|
73
|
+
description: tool.description || '',
|
|
74
|
+
annotations,
|
|
75
|
+
readOnly: typeof annotations.readOnlyHint === 'boolean' ? annotations.readOnlyHint : null,
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const requireId = (value, label) => {
|
|
81
|
+
const id = typeof value === 'string' ? value.trim() : '';
|
|
82
|
+
if (!id) throw new Error(`${label} is required`);
|
|
83
|
+
return id;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/** `[{ id, enabled }]`: each installed connector and whether the agent may use it. */
|
|
87
|
+
function getAgentConnectors(agentId) {
|
|
88
|
+
return switches(editor.getAgentConnectorPolicy(agentId));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Switch one connector on or off for the agent; returns its switches. */
|
|
92
|
+
async function setAgentConnectorEnabled(agentId, connectorId, enabled) {
|
|
93
|
+
const id = requireId(connectorId, 'connector id');
|
|
94
|
+
if (typeof enabled !== 'boolean') throw new TypeError('enabled must be a boolean');
|
|
95
|
+
const policy = editablePolicy(agentId);
|
|
96
|
+
const off = enabled ? policy.off.filter((entry) => entry !== id) : [...policy.off, id];
|
|
97
|
+
await editor.setAgentConnectorPolicy(agentId, storedConnectorPolicy({ off, tools: policy.tools }));
|
|
98
|
+
return getAgentConnectors(agentId);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Older per-tool overrides keep working (the profile no longer shows them):
|
|
102
|
+
// `permission` null drops the tool's entry, so the tool is auto again.
|
|
103
|
+
async function setAgentConnectorToolPermission(agentId, connectorId, toolName, permission) {
|
|
104
|
+
if (permission != null && !CONNECTOR_PERMISSIONS.includes(permission)) {
|
|
105
|
+
throw new Error(`permission must be one of ${CONNECTOR_PERMISSIONS.join(', ')}`);
|
|
106
|
+
}
|
|
107
|
+
const server = requireId(connectorId, 'connector id');
|
|
108
|
+
const tool = requireId(toolName, 'tool name');
|
|
109
|
+
const policy = editablePolicy(agentId);
|
|
110
|
+
const own = { ...policy.tools[server] };
|
|
111
|
+
if (permission == null) delete own[tool];
|
|
112
|
+
else own[tool] = permission;
|
|
113
|
+
return editor.setAgentConnectorPolicy(
|
|
114
|
+
agentId,
|
|
115
|
+
storedConnectorPolicy({ off: policy.off, tools: { ...policy.tools, [server]: own } })
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** The registered Project at `projectPath` (its path is the policy key). */
|
|
120
|
+
function registeredProject(projectPath) {
|
|
121
|
+
const path = requireId(projectPath, 'project path');
|
|
122
|
+
const project = listProjects().find((entry) => samePath(entry.path, path));
|
|
123
|
+
if (!project) throw new Error(`project not registered: ${path}`);
|
|
124
|
+
return project.path;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function projectPolicies() {
|
|
128
|
+
const policies = readProjectConnectorsFile(projectFile());
|
|
129
|
+
if (policies === DENY_ALL_CONNECTORS) return policies;
|
|
130
|
+
return policies || [];
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** `[{ id, enabled }]`: each installed connector and whether the project allows it. */
|
|
134
|
+
function getProjectConnectors(projectPath) {
|
|
135
|
+
const root = registeredProject(projectPath);
|
|
136
|
+
const policies = projectPolicies();
|
|
137
|
+
if (policies === DENY_ALL_CONNECTORS) return switches(DENY_ALL_CONNECTORS);
|
|
138
|
+
const off = policies.filter((entry) => samePath(entry.root, root)).flatMap((entry) => entry.off);
|
|
139
|
+
return switches({ off, tools: {} });
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Rewrite the project policy file under its lock; `edit` maps root → off list. */
|
|
143
|
+
function updateProjectPolicies(edit) {
|
|
144
|
+
const path = projectFile();
|
|
145
|
+
withFileLockSync(`${path}.lock`, () => {
|
|
146
|
+
const policies = projectPolicies();
|
|
147
|
+
// A file that cannot be read is never overwritten: it may hold switches.
|
|
148
|
+
if (policies === DENY_ALL_CONNECTORS) {
|
|
149
|
+
throw new Error(`${PROJECT_CONNECTORS_FILE} cannot be read; fix or remove it first`);
|
|
150
|
+
}
|
|
151
|
+
const byRoot = new Map(policies.map(({ root, off }) => [root, off]));
|
|
152
|
+
edit(byRoot);
|
|
153
|
+
const projects = {};
|
|
154
|
+
for (const [root, off] of byRoot) if (off.length) projects[root] = { off: [...new Set(off)].sort() };
|
|
155
|
+
writeJsonAtomicSync(path, { projects }, { lock: false });
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Switch one connector on or off for the project; returns its switches. */
|
|
160
|
+
function setProjectConnectorEnabled(projectPath, connectorId, enabled) {
|
|
161
|
+
const id = requireId(connectorId, 'connector id');
|
|
162
|
+
if (typeof enabled !== 'boolean') throw new TypeError('enabled must be a boolean');
|
|
163
|
+
const root = registeredProject(projectPath);
|
|
164
|
+
updateProjectPolicies((byRoot) => {
|
|
165
|
+
const key = [...byRoot.keys()].find((entry) => samePath(entry, root)) ?? root;
|
|
166
|
+
const off = (byRoot.get(key) || []).filter((entry) => entry !== id);
|
|
167
|
+
byRoot.set(key, enabled ? off : [...off, id]);
|
|
168
|
+
});
|
|
169
|
+
return getProjectConnectors(root);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** One-time, idempotent: legacy allow lists become deny lists. Agent lists
|
|
173
|
+
* (agent.json arrays) switch off each configured connector they did not
|
|
174
|
+
* enable; MCP project scopes (`extensionScopes.mcp`, "only in these
|
|
175
|
+
* projects") switch the server off in every other registered Project.
|
|
176
|
+
* Skipped while the configured connector set is not fully known. */
|
|
177
|
+
function migrateConnectorPolicies() {
|
|
178
|
+
const catalog = resolveConfiguredMcpCatalog?.();
|
|
179
|
+
if (!catalog || (catalog.warnings || []).some((warning) => PLUGIN_REGISTRY_WARNING.test(warning?.message || ''))) {
|
|
180
|
+
return { skipped: true, agents: [], scopes: [] };
|
|
181
|
+
}
|
|
182
|
+
const installed = Object.keys(catalog.servers || {});
|
|
183
|
+
const agents = [];
|
|
184
|
+
const agentsDir = join(dataDir(), 'agents');
|
|
185
|
+
let entries = [];
|
|
186
|
+
try {
|
|
187
|
+
entries = readdirSync(agentsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory());
|
|
188
|
+
} catch {
|
|
189
|
+
entries = [];
|
|
190
|
+
}
|
|
191
|
+
for (const entry of entries) {
|
|
192
|
+
const file = join(agentsDir, entry.name, 'agent.json');
|
|
193
|
+
let manifest;
|
|
194
|
+
try {
|
|
195
|
+
manifest = JSON.parse(readFileSync(file, 'utf8'));
|
|
196
|
+
} catch {
|
|
197
|
+
continue; // missing or unreadable: the runtime already denies or allows as before
|
|
198
|
+
}
|
|
199
|
+
if (!Array.isArray(manifest?.connectors)) continue;
|
|
200
|
+
const next = storedConnectorPolicy(
|
|
201
|
+
migrateLegacyConnectorPolicy(parseConnectorPolicy(manifest.connectors), installed)
|
|
202
|
+
);
|
|
203
|
+
if (next) manifest.connectors = next;
|
|
204
|
+
else delete manifest.connectors;
|
|
205
|
+
writeJsonAtomicSync(file, manifest);
|
|
206
|
+
agents.push(entry.name);
|
|
207
|
+
}
|
|
208
|
+
const config = getConfig?.();
|
|
209
|
+
const scoped = Object.entries(extensionScopesFromConfig(config).mcp);
|
|
210
|
+
if (scoped.length) {
|
|
211
|
+
const projects = listProjects();
|
|
212
|
+
updateProjectPolicies((byRoot) => {
|
|
213
|
+
for (const [server, roots] of scoped) {
|
|
214
|
+
for (const { path } of projects) {
|
|
215
|
+
if (cwdWithinProjects(path, roots)) continue;
|
|
216
|
+
const key = [...byRoot.keys()].find((root) => samePath(root, path)) ?? path;
|
|
217
|
+
byRoot.set(key, [...(byRoot.get(key) || []), server]);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
let next = config;
|
|
222
|
+
for (const [server] of scoped) next = withExtensionScope(next, 'mcp', server, null);
|
|
223
|
+
saveConfigAndAdopt(next);
|
|
224
|
+
}
|
|
225
|
+
return { skipped: false, agents, scopes: scoped.map(([server]) => server) };
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return {
|
|
229
|
+
listConnectors,
|
|
230
|
+
listConnectorTools,
|
|
231
|
+
getAgentConnectors,
|
|
232
|
+
setAgentConnectors: editor.setAgentConnectorPolicy,
|
|
233
|
+
setAgentConnectorEnabled,
|
|
234
|
+
setAgentConnectorToolPermission,
|
|
235
|
+
getProjectConnectors,
|
|
236
|
+
setProjectConnectorEnabled,
|
|
237
|
+
migrateConnectorPolicies,
|
|
238
|
+
};
|
|
239
|
+
}
|