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
|
@@ -367,6 +367,7 @@ function oauthAuthFields(p, auth) {
|
|
|
367
367
|
status: auth.status || (authenticated ? 'Set' : 'Not Set'),
|
|
368
368
|
detail: auth.detail || p.desc,
|
|
369
369
|
expiresAt: auth.expiresAt || null,
|
|
370
|
+
plan: auth.plan || null,
|
|
370
371
|
usable: auth.usable === true || (auth.usable == null && authenticated),
|
|
371
372
|
refreshable: auth.refreshable === true,
|
|
372
373
|
reauthRequired: auth.reauthRequired === true,
|
|
@@ -958,8 +959,8 @@ async function withTimeout(run, ms, label) {
|
|
|
958
959
|
}
|
|
959
960
|
}
|
|
960
961
|
|
|
961
|
-
function existingCustomEntry(
|
|
962
|
-
const entry =
|
|
962
|
+
function existingCustomEntry(config, id) {
|
|
963
|
+
const entry = config.providers?.[id];
|
|
963
964
|
if (!isCustomProviderId(id) || !isCustomProviderConfig(entry)) throw new Error(`unknown custom provider "${id}"`);
|
|
964
965
|
return entry;
|
|
965
966
|
}
|
|
@@ -1021,16 +1022,15 @@ function withStoredSettings(input, entry) {
|
|
|
1021
1022
|
return out;
|
|
1022
1023
|
}
|
|
1023
1024
|
|
|
1024
|
-
// Validated, secret-free config for `input
|
|
1025
|
-
//
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1025
|
+
// Validated, secret-free config for `input` over one config snapshot (the
|
|
1026
|
+
// stored entry supplies an edit's omitted settings); the key (typed, else
|
|
1027
|
+
// stored for an existing provider) is resolved separately and never enters
|
|
1028
|
+
// the config. Synchronous, so a caller can merge and commit one snapshot.
|
|
1029
|
+
function customInputAt(snapshot, input, normalizeCustomProviderConfig, options) {
|
|
1029
1030
|
const id = input.id === undefined ? null : input.id;
|
|
1030
|
-
|
|
1031
|
-
const
|
|
1032
|
-
const
|
|
1033
|
-
const typed = typeof input.apiKey === 'string' ? input.apiKey.trim() : '';
|
|
1031
|
+
const merged = id ? withStoredSettings(input, existingCustomEntry(snapshot, id)) : input;
|
|
1032
|
+
const config = normalizeCustomProviderConfig(merged, options);
|
|
1033
|
+
const typed = typeof merged.apiKey === 'string' ? merged.apiKey.trim() : '';
|
|
1034
1034
|
const keyless = config.auth === 'none';
|
|
1035
1035
|
const envName = keyless ? '' : config.apiKeyEnv || '';
|
|
1036
1036
|
let apiKey = '';
|
|
@@ -1039,36 +1039,71 @@ async function resolveCustomInput(cfgMod, rawInput, options) {
|
|
|
1039
1039
|
return { id, config, typed: keyless || envName ? '' : typed, apiKey, keyless, envName };
|
|
1040
1040
|
}
|
|
1041
1041
|
|
|
1042
|
+
async function resolveCustomInput(cfgMod, rawInput, options) {
|
|
1043
|
+
const input = inputObject(rawInput);
|
|
1044
|
+
validateCustomTransportFields(input);
|
|
1045
|
+
const { normalizeCustomProviderConfig } = await loadCustomProviderModule();
|
|
1046
|
+
return customInputAt(cfgMod.loadConfig(), input, normalizeCustomProviderConfig, options);
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
function requireCustomKey({ apiKey, keyless, envName }) {
|
|
1050
|
+
if (!keyless && !envName && !apiKey) throw new Error('API key is required');
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
// One key transaction per provider, from reading the rollback key to the
|
|
1054
|
+
// config commit or rollback: a failed save restores the key the preceding
|
|
1055
|
+
// save committed and never one a newer save wrote. Settings-only saves and
|
|
1056
|
+
// other providers never wait.
|
|
1057
|
+
const customKeySaves = new Map();
|
|
1058
|
+
|
|
1059
|
+
function serializeCustomKeySave(id, run) {
|
|
1060
|
+
const result = (customKeySaves.get(id) || Promise.resolve()).then(run);
|
|
1061
|
+
const settled = result.then(
|
|
1062
|
+
() => {},
|
|
1063
|
+
() => {}
|
|
1064
|
+
);
|
|
1065
|
+
customKeySaves.set(id, settled);
|
|
1066
|
+
settled.then(() => {
|
|
1067
|
+
if (customKeySaves.get(id) === settled) customKeySaves.delete(id);
|
|
1068
|
+
});
|
|
1069
|
+
return result;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1042
1072
|
export async function saveCustomProvider(cfgMod, rawInput) {
|
|
1043
1073
|
requireLocalProviderManagement();
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
apiKey,
|
|
1049
|
-
keyless,
|
|
1050
|
-
envName,
|
|
1051
|
-
} = await resolveCustomInput(cfgMod, rawInput, { requireModels: false });
|
|
1052
|
-
if (!keyless && !envName && !apiKey) throw new Error('API key is required');
|
|
1074
|
+
// Early verdict: an invalid save never touches the keychain.
|
|
1075
|
+
const resolved = await resolveCustomInput(cfgMod, rawInput, { requireModels: false });
|
|
1076
|
+
requireCustomKey(resolved);
|
|
1077
|
+
const { id: existingId, typed } = resolved;
|
|
1053
1078
|
const id = existingId || `custom-${randomUUID()}`;
|
|
1054
|
-
const
|
|
1055
|
-
const
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1079
|
+
const { normalizeCustomProviderConfig } = await loadCustomProviderModule();
|
|
1080
|
+
const commit = async () => {
|
|
1081
|
+
const account = SECRET_ACCOUNTS.agentApiKey(id);
|
|
1082
|
+
const previousKey = typed && existingId ? getAgentApiKey(id) : null;
|
|
1083
|
+
if (typed) await saveSecretAsync(account, typed);
|
|
1084
|
+
let entry;
|
|
1085
|
+
try {
|
|
1086
|
+
// Synchronous from here: omitted settings come from the config this
|
|
1087
|
+
// save commits over, so an edit that landed during the awaits above (a
|
|
1088
|
+
// model's visibility, a peer save, a removal) is never reverted.
|
|
1089
|
+
const current = cfgMod.loadConfig();
|
|
1090
|
+
const latest = customInputAt(current, rawInput, normalizeCustomProviderConfig, { requireModels: false });
|
|
1091
|
+
requireCustomKey(latest);
|
|
1092
|
+
entry = { ...latest.config, type: 'custom', enabled: latest.config.enabled !== false };
|
|
1093
|
+
cfgMod.saveConfig(
|
|
1094
|
+
{ ...current, providers: { ...(current.providers || {}), [id]: entry } },
|
|
1095
|
+
{ baseConfig: current }
|
|
1096
|
+
);
|
|
1097
|
+
} catch (error) {
|
|
1098
|
+
if (typed) {
|
|
1099
|
+
if (previousKey) await saveSecretAsync(account, previousKey);
|
|
1100
|
+
else await deleteSecretAsync(account);
|
|
1101
|
+
}
|
|
1102
|
+
throw error;
|
|
1068
1103
|
}
|
|
1069
|
-
|
|
1070
|
-
}
|
|
1071
|
-
return
|
|
1104
|
+
return customProviderRow(id, entry);
|
|
1105
|
+
};
|
|
1106
|
+
return typed ? serializeCustomKeySave(id, commit) : commit();
|
|
1072
1107
|
}
|
|
1073
1108
|
|
|
1074
1109
|
const MODEL_PATCH_KEYS = new Set(['manual', 'hidden', 'name', 'contextWindow', 'maxOutputTokens', 'reasoning']);
|
|
@@ -1104,7 +1139,7 @@ export async function updateCustomProviderModel(cfgMod, rawId, rawModelId, patch
|
|
|
1104
1139
|
// Everything below is synchronous: the provider is read, patched and saved
|
|
1105
1140
|
// without yielding, so a concurrent update can never be overwritten by a
|
|
1106
1141
|
// provider object read before the await above.
|
|
1107
|
-
const entry = existingCustomEntry(cfgMod, id);
|
|
1142
|
+
const entry = existingCustomEntry(cfgMod.loadConfig(), id);
|
|
1108
1143
|
const current = normalizeCustomProviderConfig(entry, { requireModels: false });
|
|
1109
1144
|
const overrides = new Map(Object.entries(current.modelOverrides || {}));
|
|
1110
1145
|
if (patch === null) {
|
|
@@ -1241,7 +1276,7 @@ function withoutProviderReferences(config, id) {
|
|
|
1241
1276
|
export async function removeCustomProvider(cfgMod, rawId) {
|
|
1242
1277
|
requireLocalProviderManagement();
|
|
1243
1278
|
const id = String(rawId || '').trim();
|
|
1244
|
-
existingCustomEntry(cfgMod, id);
|
|
1279
|
+
existingCustomEntry(cfgMod.loadConfig(), id);
|
|
1245
1280
|
// Secret first: a real keychain failure (locked, permission) leaves the
|
|
1246
1281
|
// provider registered so the removal can be retried. A missing secret
|
|
1247
1282
|
// (keyless provider) is not an error.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// Who may manage automations (schedules and webhooks) from a chat, by the
|
|
2
|
+
// calling session's provenance. Enforced by every setup automation action
|
|
3
|
+
// (setup-tool/extended-actions.mjs), the chat-facing door of channel-admin:
|
|
4
|
+
// - the human's own sessions (an ordinary Lead session, Mixy's home) manage
|
|
5
|
+
// every automation and may move one to an agent that exists;
|
|
6
|
+
// - another agent's home thread manages only the automations it owns and can
|
|
7
|
+
// never give one away;
|
|
8
|
+
// - a headless run (schedule, webhook, delegated agent, or a session that
|
|
9
|
+
// cannot be resolved) manages none — nor does it change any other setting
|
|
10
|
+
// (setup-tool/executor.mjs refuses every mutating setup action for it).
|
|
11
|
+
// - a group-room member session is no background run, but it speaks for the
|
|
12
|
+
// room, not for the user: it creates or changes no agent, automation or
|
|
13
|
+
// other setting either.
|
|
14
|
+
// The app's own panels call channel-admin directly and act for the human.
|
|
15
|
+
import { MIXY_AGENT_ID, agentIdOfHomeSession } from '../../runtime/agent/orchestrator/session/agent-home.mjs';
|
|
16
|
+
import { roomMemberOfSession } from '../../runtime/agent/orchestrator/session/agent-room.mjs';
|
|
17
|
+
import { mixyDisplayName } from '../../runtime/agent/orchestrator/session/mixy-name.mjs';
|
|
18
|
+
import { isAgentOwner } from '../../runtime/agent/orchestrator/agent-owner.mjs';
|
|
19
|
+
|
|
20
|
+
const INTERACTIVE_SOURCE_TYPES = new Set(['', 'lead', 'cli']);
|
|
21
|
+
|
|
22
|
+
/** `{ kind: 'human' | 'agent' | 'room-member' | 'headless', agentId? }` of a session record. */
|
|
23
|
+
export function scheduleCallerScope(session) {
|
|
24
|
+
const id = String(session?.id || '');
|
|
25
|
+
const member = roomMemberOfSession(id);
|
|
26
|
+
if (member) return { kind: 'room-member', agentId: member.agentId };
|
|
27
|
+
const homeAgent = agentIdOfHomeSession(id);
|
|
28
|
+
if (homeAgent) return homeAgent === MIXY_AGENT_ID ? { kind: 'human' } : { kind: 'agent', agentId: homeAgent };
|
|
29
|
+
const headless =
|
|
30
|
+
!id ||
|
|
31
|
+
isAgentOwner(session) ||
|
|
32
|
+
Boolean(session.parentSessionId) ||
|
|
33
|
+
Boolean(session.ownerSessionId && session.ownerSessionId !== id) ||
|
|
34
|
+
!INTERACTIVE_SOURCE_TYPES.has(String(session.sourceType || '').toLowerCase());
|
|
35
|
+
return headless ? { kind: 'headless' } : { kind: 'human' };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Throws unless `scope` may `action` the `kind` ('schedule' | 'webhook')
|
|
39
|
+
* automation `current` (null when creating) with `owner` the requested owner
|
|
40
|
+
* ('' keeps the saved one). `agentIds` are the agents a transfer may name;
|
|
41
|
+
* Mixy always counts. */
|
|
42
|
+
export function assertAutomationAccess(
|
|
43
|
+
scope,
|
|
44
|
+
{ kind = 'schedule', action, current = null, owner = '', agentIds = [] }
|
|
45
|
+
) {
|
|
46
|
+
if (scope?.kind === 'room-member') throw new Error(`A group-room member cannot ${action} ${kind}s`);
|
|
47
|
+
if (scope?.kind !== 'human' && scope?.kind !== 'agent') {
|
|
48
|
+
throw new Error(`A background run cannot ${action} ${kind}s`);
|
|
49
|
+
}
|
|
50
|
+
const requested = String(owner ?? '').trim();
|
|
51
|
+
const saved = current ? current.owner || MIXY_AGENT_ID : '';
|
|
52
|
+
if (scope.kind === 'agent') {
|
|
53
|
+
if (current && saved !== scope.agentId) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
`${kind === 'webhook' ? 'Webhook' : 'Schedule'} "${current.name}" belongs to another agent; this thread manages only its own ${kind}s`
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
if (requested && requested !== scope.agentId) throw new Error(`This thread cannot give a ${kind} to another agent`);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (requested && requested !== saved && requested !== MIXY_AGENT_ID && !agentIds.includes(requested)) {
|
|
62
|
+
throw new Error(`Agent "${requested}" does not exist`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Throws unless `caller` (scope `scope`) is Mixy — its home thread or an
|
|
67
|
+
* ordinary Lead session acting as 'lead': only Mixy creates, edits or
|
|
68
|
+
* deletes agent definitions from a chat. The app's own panels call the agent
|
|
69
|
+
* editor directly and act for the human. */
|
|
70
|
+
export function assertAgentEditorAccess(scope, caller, action) {
|
|
71
|
+
const acting = String(caller?.agent || '').trim();
|
|
72
|
+
if (scope?.kind === 'human' && (!acting || acting === MIXY_AGENT_ID)) return;
|
|
73
|
+
const name = mixyDisplayName();
|
|
74
|
+
throw new Error(
|
|
75
|
+
`Only ${name} (the representative agent) can create, edit or delete agents (setup ${action}); ask the user to do it with ${name} or in the Agents settings`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Throws when an agent's home thread changes another agent's settings. */
|
|
80
|
+
export function assertOwnAgentSettings(scope, agentId, action) {
|
|
81
|
+
if (scope?.kind === 'agent' && String(agentId || '').trim() !== scope.agentId) {
|
|
82
|
+
throw new Error(`This thread manages only its own agent's settings (setup ${action})`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Throws when `scope` is a headless run: it reads settings, never changes them. */
|
|
87
|
+
export function assertInteractiveCaller(scope, action) {
|
|
88
|
+
if (scope?.kind === 'human' || scope?.kind === 'agent') return;
|
|
89
|
+
if (scope?.kind === 'room-member') throw new Error(`A group-room member cannot change settings (setup ${action})`);
|
|
90
|
+
throw new Error(`A background run cannot change settings (setup ${action})`);
|
|
91
|
+
}
|
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
// the current runtime state: route, tool spec, ownership/lane, workflow pack,
|
|
3
3
|
// memory context and compaction.
|
|
4
4
|
import { normalizeCompactionConfig } from '../../runtime/agent/orchestrator/runtime-core/config-helpers.mjs';
|
|
5
|
-
import { hasOwn } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
5
|
+
import { clean, hasOwn } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
6
6
|
import { toolSpecForMode } from '../../runtime/agent/orchestrator/runtime-core/effort.mjs';
|
|
7
|
-
import { pluginDataDir } from '../runtime-paths.mjs';
|
|
7
|
+
import { STANDALONE_ROOT, pluginDataDir } from '../runtime-paths.mjs';
|
|
8
|
+
import { readAgentFrontmatterPermission } from '../services/agent-tool/helpers.mjs';
|
|
8
9
|
import { LEAD_DISALLOWED_TOOLS } from '../../runtime/agent/orchestrator/runtime-core/tool-defs.mjs';
|
|
9
10
|
import { HEADLESS_TOOL_PROFILE } from '../../runtime/agent/orchestrator/runtime-core/tool-profile.mjs';
|
|
11
|
+
import { AGENT_MODE, resolveSessionMode } from '../../runtime/agent/orchestrator/session/agent-mode.mjs';
|
|
12
|
+
import { MIXY_AGENT_ID } from '../../runtime/agent/orchestrator/session/agent-home.mjs';
|
|
10
13
|
|
|
11
14
|
// Ownership and permission fields an agent-owned session inherits from its profile.
|
|
12
15
|
function agentOwnedSessionFields(sessionProfile) {
|
|
@@ -31,14 +34,30 @@ export function sessionOptions(deps, coreMemoryContext) {
|
|
|
31
34
|
// Load the active WORKFLOW.md pack once for both summary + context block.
|
|
32
35
|
const {
|
|
33
36
|
summary: workflow,
|
|
34
|
-
|
|
37
|
+
leadPromptParts,
|
|
35
38
|
packContext,
|
|
36
39
|
orchestrationMode,
|
|
37
40
|
} = activeWorkflowContext(rt.config, dataDir);
|
|
38
41
|
const sessionProfile = rt.sessionProfile && typeof rt.sessionProfile === 'object' ? rt.sessionProfile : null;
|
|
39
42
|
const agentOwned = sessionProfile?.owner === 'agent' || sessionProfile?.visibility === 'agent-only';
|
|
40
|
-
// Agent
|
|
41
|
-
const
|
|
43
|
+
// Agent or coding mode, from the one resolver (agent-mode.mjs).
|
|
44
|
+
const { mode: sessionMode, agentId: actingAgent } = resolveSessionMode({
|
|
45
|
+
sessionId: rt.reservedSessionId,
|
|
46
|
+
profile: sessionProfile,
|
|
47
|
+
});
|
|
48
|
+
// An agent's home thread: a user conversation that runs AS that agent (its
|
|
49
|
+
// AGENT.md role and permission); route comes with the create call.
|
|
50
|
+
const homeAgent = agentOwned ? '' : clean(sessionProfile?.homeAgent);
|
|
51
|
+
const homePermission = homeAgent ? readAgentFrontmatterPermission(homeAgent, dataDir, STANDALONE_ROOT) : null;
|
|
52
|
+
// A coding task session an agent created (session create): the user's own
|
|
53
|
+
// Lead, tagged with its origin; `sourceName` lets the Agents list file it.
|
|
54
|
+
const taskOrigin = agentOwned ? null : sessionProfile?.taskOrigin || null;
|
|
55
|
+
// Every session leads BP3 with the Active Workflow block; a Lead adds its
|
|
56
|
+
// orchestration and catalog slices (coding, agent mode or Mixy's).
|
|
57
|
+
const workflowContext = packContext;
|
|
58
|
+
const leadWorkflowParts = agentOwned
|
|
59
|
+
? undefined
|
|
60
|
+
: leadPromptParts({ agentMode: sessionMode === AGENT_MODE, mixy: actingAgent === MIXY_AGENT_ID });
|
|
42
61
|
const callerDisallowedTools = [
|
|
43
62
|
...(agentOwned ? [] : LEAD_DISALLOWED_TOOLS),
|
|
44
63
|
...(!agentOwned && rt.disallowDelegation ? ['agent'] : []),
|
|
@@ -51,7 +70,8 @@ export function sessionOptions(deps, coreMemoryContext) {
|
|
|
51
70
|
tools: toolSpecForMode(rt.mode),
|
|
52
71
|
...(Array.isArray(schemaAllowedTools) ? { schemaAllowedTools } : {}),
|
|
53
72
|
owner: agentOwned ? 'agent' : 'cli',
|
|
54
|
-
agent: agentOwned ? sessionProfile?.agent || 'worker' : 'lead',
|
|
73
|
+
agent: agentOwned ? sessionProfile?.agent || 'worker' : homeAgent || 'lead',
|
|
74
|
+
...(homePermission ? { permission: homePermission } : {}),
|
|
55
75
|
lane: agentOwned ? 'agent' : 'cli',
|
|
56
76
|
// One-shot `mixdog exec` runs carry their own source so session catalogs
|
|
57
77
|
// can keep them out of the user's resumable list.
|
|
@@ -60,7 +80,12 @@ export function sessionOptions(deps, coreMemoryContext) {
|
|
|
60
80
|
: rt.toolProfile === HEADLESS_TOOL_PROFILE
|
|
61
81
|
? 'exec'
|
|
62
82
|
: 'lead',
|
|
63
|
-
sourceName: agentOwned
|
|
83
|
+
sourceName: agentOwned
|
|
84
|
+
? sessionProfile?.sourceName || sessionProfile?.agent || 'agent'
|
|
85
|
+
: taskOrigin
|
|
86
|
+
? `agent:${taskOrigin.agentId}`
|
|
87
|
+
: 'main',
|
|
88
|
+
...(taskOrigin ? { taskOrigin } : {}),
|
|
64
89
|
...(rt.approvalMode ? { approvalMode: rt.approvalMode } : {}),
|
|
65
90
|
clientHostPid: sessionProfile?.clientHostPid || process.pid,
|
|
66
91
|
mcpScopeId: rt.mcpScopeId,
|
|
@@ -71,6 +96,8 @@ export function sessionOptions(deps, coreMemoryContext) {
|
|
|
71
96
|
coreMemoryContext,
|
|
72
97
|
workflow,
|
|
73
98
|
workflowContext,
|
|
99
|
+
...(leadWorkflowParts ? { leadWorkflowParts } : {}),
|
|
100
|
+
sessionMode,
|
|
74
101
|
orchestrationMode,
|
|
75
102
|
fast: rt.route.fast === true,
|
|
76
103
|
autoEffort: rt.route.autoEffort !== false,
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
// facade's hookCommonPayload / currentCwd accessor + the session itself. All
|
|
6
6
|
// properties are non-enumerable/configurable/writable so the loop/manager can
|
|
7
7
|
// read them by name without changing session enumeration.
|
|
8
|
+
import { roomMemberOfSession } from '../runtime/agent/orchestrator/session/agent-room.mjs';
|
|
9
|
+
import { roomMemberToolDecision } from './room-member-gate.mjs';
|
|
8
10
|
|
|
9
11
|
export function attachSessionHooks(session, { hooks, hookCommonPayload, getCwd }) {
|
|
10
12
|
const identity = (input) => ({
|
|
@@ -26,20 +28,26 @@ export function attachSessionHooks(session, { hooks, hookCommonPayload, getCwd }
|
|
|
26
28
|
// rejection cannot escape the tool loop or the compaction flow.
|
|
27
29
|
const dispatcher = (event, payload) => (input) => hooks.dispatch(event, hookCommonPayload(payload(input)));
|
|
28
30
|
|
|
29
|
-
// PreToolUse bridge.
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
// PreToolUse bridge. A group-room member's mutating calls always ask the
|
|
32
|
+
// user (room-member-gate.mjs), whatever the hooks decided short of a deny.
|
|
33
|
+
define('beforeToolHook', async (input, options = {}) => {
|
|
34
|
+
const name = input?.name || input?.tool_name;
|
|
35
|
+
const args = input?.args || input?.tool_input;
|
|
36
|
+
const cwd = input?.cwd || getCwd();
|
|
37
|
+
const decision = await hooks.beforeTool(
|
|
32
38
|
hookCommonPayload({
|
|
33
39
|
...input,
|
|
34
40
|
session_id: input?.sessionId || input?.session_id || session?.id,
|
|
35
|
-
tool_name:
|
|
36
|
-
tool_input:
|
|
41
|
+
tool_name: name,
|
|
42
|
+
tool_input: args,
|
|
37
43
|
tool_use_id: input?.toolCallId || input?.tool_use_id,
|
|
38
|
-
cwd
|
|
44
|
+
cwd,
|
|
39
45
|
}),
|
|
40
46
|
options
|
|
41
|
-
)
|
|
42
|
-
|
|
47
|
+
);
|
|
48
|
+
if (!roomMemberOfSession(session?.id)) return decision;
|
|
49
|
+
return roomMemberToolDecision({ name, args, cwd }, decision);
|
|
50
|
+
});
|
|
43
51
|
// PostToolUse: bridge runtime tool completions to the standard hook bus.
|
|
44
52
|
define('afterToolHook', dispatcher('PostToolUse', toolPayload));
|
|
45
53
|
// PostToolUseFailure: dispatched by loop.mjs only when a tool execution
|
|
@@ -9,6 +9,12 @@ import { INSTRUCTION_FILES_MODES } from '../../runtime/shared/instruction-files-
|
|
|
9
9
|
import { MEDIA_KINDS } from '../../runtime/media/tool-defs.mjs';
|
|
10
10
|
import { SETUP_DESKTOP_DOMAINS, SETUP_HANDOFFS } from './settings-contract.mjs';
|
|
11
11
|
import { executeExtendedSetupAction, publicAutomation, publicHookRule, validateMcpInput } from './extended-actions.mjs';
|
|
12
|
+
import {
|
|
13
|
+
assertAgentEditorAccess,
|
|
14
|
+
assertInteractiveCaller,
|
|
15
|
+
assertOwnAgentSettings,
|
|
16
|
+
scheduleCallerScope,
|
|
17
|
+
} from '../services/schedule-access.mjs';
|
|
12
18
|
import { SETUP_DESKTOP_UNCLAIMED, createSetupUiRequests } from './ui-requests.mjs';
|
|
13
19
|
import {
|
|
14
20
|
SETUP_ACTIONS,
|
|
@@ -20,8 +26,11 @@ import {
|
|
|
20
26
|
} from './tool-defs.mjs';
|
|
21
27
|
import { schemaValueError } from '../../runtime/shared/schema-value-error.mjs';
|
|
22
28
|
import { clean } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
29
|
+
import { CONNECTOR_IDS, connectorById } from '../../runtime/shared/connector-catalog.mjs';
|
|
23
30
|
import profileConfig from '../../runtime/shared/profile-config.cjs';
|
|
24
31
|
|
|
32
|
+
const AGENT_DEFINITION_ACTIONS = new Set(['create_definition', 'save_definition', 'delete_definition']);
|
|
33
|
+
|
|
25
34
|
const PROFILE_VALUE_IDS = Object.freeze({
|
|
26
35
|
language: profileConfig.PROFILE_LANGUAGES.map((entry) => entry.id),
|
|
27
36
|
experienceLevel: ['', ...profileConfig.PROFILE_EXPERIENCE_LEVELS.map((entry) => entry.id)],
|
|
@@ -35,6 +44,7 @@ const ACTION_APPLIES_TO = {
|
|
|
35
44
|
save_automation: 'the automation worker; scheduled runs follow the saved timing',
|
|
36
45
|
delete_automation: 'future automation runs',
|
|
37
46
|
set_automation_enabled: 'future automation runs',
|
|
47
|
+
run_automation: "one run now; its result posts into the owning agent's thread",
|
|
38
48
|
set_webhook_config: 'the webhook worker after configuration reload',
|
|
39
49
|
add_hook_rule: 'subsequent tool calls; no restart required',
|
|
40
50
|
set_hook_rule_enabled: 'subsequent tool calls; no restart required',
|
|
@@ -55,9 +65,10 @@ const OPEN_TARGET_HINTS = Object.freeze({
|
|
|
55
65
|
autoclear: 'Desktop: Settings → Context · TUI: /autoclear',
|
|
56
66
|
memory:
|
|
57
67
|
'Desktop: Extensions → Plugin → Built-in (Memory); core memories under Projects → project → Memories · TUI: /memory',
|
|
58
|
-
mcp: 'Desktop: Extensions →
|
|
59
|
-
skills: 'Desktop:
|
|
60
|
-
plugins:
|
|
68
|
+
mcp: 'Desktop: Extensions → Connectors tab · TUI: /mcp',
|
|
69
|
+
skills: 'Desktop: Skills (activity rail) · TUI: /skills',
|
|
70
|
+
plugins:
|
|
71
|
+
'Desktop: Extensions → Extensions tab (plugins that bring MCP servers: Connectors tab → Custom connectors) · TUI: /plugins',
|
|
61
72
|
update: 'Desktop: Settings → System → Update · TUI: /update',
|
|
62
73
|
usage: 'Desktop: /usage in the composer · TUI: /usage',
|
|
63
74
|
doctor: 'Desktop: Settings → System → Doctor, or /doctor in the composer · TUI: /doctor',
|
|
@@ -133,6 +144,7 @@ function publicProviderRows(setup) {
|
|
|
133
144
|
pick(row, {
|
|
134
145
|
reauthRequired: row.reauthRequired === true,
|
|
135
146
|
expiresAt: row.expiresAt || null,
|
|
147
|
+
plan: row.plan || null,
|
|
136
148
|
})
|
|
137
149
|
),
|
|
138
150
|
local: (setup?.local || []).map((row) =>
|
|
@@ -167,6 +179,7 @@ function configuredProviderRows(rows, accountCount) {
|
|
|
167
179
|
kind,
|
|
168
180
|
authenticated: row.authenticated,
|
|
169
181
|
status: row.status,
|
|
182
|
+
...(kind === 'oauth' ? { plan: row.plan || null } : {}),
|
|
170
183
|
...(row.reauthRequired ? { reauthRequired: true } : {}),
|
|
171
184
|
...accounts,
|
|
172
185
|
});
|
|
@@ -364,6 +377,17 @@ const SETUP_STATUS_READERS = {
|
|
|
364
377
|
// schema, the per-action field list and the route/object-argument minimums.
|
|
365
378
|
function validateSetupInput(args) {
|
|
366
379
|
const action = requireEnum(args?.action, SETUP_ACTIONS, 'action');
|
|
380
|
+
// Old callers still ask to connect GitHub: it is the signed-in GitHub CLI, not a catalog connector.
|
|
381
|
+
if (
|
|
382
|
+
action === 'connect_connector' &&
|
|
383
|
+
String(args.connector ?? '')
|
|
384
|
+
.trim()
|
|
385
|
+
.toLowerCase() === 'github'
|
|
386
|
+
) {
|
|
387
|
+
throw new Error(
|
|
388
|
+
'GitHub uses the signed-in GitHub CLI; no connector needed. Use the github tool or Settings → Git.'
|
|
389
|
+
);
|
|
390
|
+
}
|
|
367
391
|
const validationError = schemaValueError({ ...args, action }, SETUP_TOOL_DEFS[0].inputSchema, 'setup');
|
|
368
392
|
if (validationError) throw new Error(`[tool-input-validation] ${validationError}`);
|
|
369
393
|
const fields = SETUP_ACTION_FIELDS[action].split(' ').filter(Boolean);
|
|
@@ -627,6 +651,25 @@ const SETUP_ACTION_HANDLERS = {
|
|
|
627
651
|
remove_plugin: async (rt, args) => ({
|
|
628
652
|
plugin: (await rt.removePlugin(requireText(args.name, 'name')))?.plugin || null,
|
|
629
653
|
}),
|
|
654
|
+
// The chat path of the one-click connect: the attached Desktop renders this
|
|
655
|
+
// call as a connect card (agent-chat connector card) that runs the same flow
|
|
656
|
+
// as Extensions → 커넥터. Nothing is connected here.
|
|
657
|
+
connect_connector: async (rt, args) => {
|
|
658
|
+
const entry = connectorById(requireText(args.connector, 'connector'));
|
|
659
|
+
if (!entry || entry.ownKey) throw new Error(`connector must be one of ${CONNECTOR_IDS.join(', ')}`);
|
|
660
|
+
const server = (rt.mcpStatus?.()?.servers || []).find((row) => row.connector === entry.id) || null;
|
|
661
|
+
const connected = server?.connected === true;
|
|
662
|
+
return {
|
|
663
|
+
connector: entry.id,
|
|
664
|
+
name: entry.name,
|
|
665
|
+
backend: entry.backend.kind,
|
|
666
|
+
...(server ? { server: server.name } : {}),
|
|
667
|
+
connected,
|
|
668
|
+
note: connected
|
|
669
|
+
? `${entry.name} is already connected.`
|
|
670
|
+
: `A connect card for ${entry.name} is shown in this conversation; the user presses it (Desktop: Extensions → 커넥터). Check status mcp afterwards.`,
|
|
671
|
+
};
|
|
672
|
+
},
|
|
630
673
|
enable_plugin_mcp: async (rt, args) => {
|
|
631
674
|
const name = requireText(args.name, 'name');
|
|
632
675
|
const plugin = ((await rt.pluginsStatus())?.plugins || []).find((row) => row.name === name || row.id === name);
|
|
@@ -645,6 +688,7 @@ const READ_ONLY_SETUP_ACTIONS = new Set([
|
|
|
645
688
|
'open',
|
|
646
689
|
'list_models',
|
|
647
690
|
'get_mcp_server',
|
|
691
|
+
'connect_connector',
|
|
648
692
|
'read_definition',
|
|
649
693
|
'search_local_models',
|
|
650
694
|
'inspect_hf_model',
|
|
@@ -656,6 +700,7 @@ const BACKGROUND_SETUP_ACTIONS = new Set([
|
|
|
656
700
|
'maintain_local_model',
|
|
657
701
|
'cancel_local_installation',
|
|
658
702
|
'reconnect_mcp',
|
|
703
|
+
'run_automation',
|
|
659
704
|
]);
|
|
660
705
|
|
|
661
706
|
function setupMutationReceipt(action, result) {
|
|
@@ -671,7 +716,16 @@ function setupMutationReceipt(action, result) {
|
|
|
671
716
|
);
|
|
672
717
|
}
|
|
673
718
|
|
|
674
|
-
|
|
719
|
+
/** `getCallerSession(id)` returns the calling session's record (null when it
|
|
720
|
+
* cannot be resolved): automation actions authorize by its provenance. */
|
|
721
|
+
export function createSetupToolExecutor({
|
|
722
|
+
getApi,
|
|
723
|
+
getConfig,
|
|
724
|
+
notifySessionUi,
|
|
725
|
+
getSessionId,
|
|
726
|
+
getCallerSession,
|
|
727
|
+
flushSettings,
|
|
728
|
+
}) {
|
|
675
729
|
const desktop = createSetupUiRequests({ notifySessionUi, getSessionId });
|
|
676
730
|
const api = () => {
|
|
677
731
|
const facade = getApi?.();
|
|
@@ -701,12 +755,31 @@ export function createSetupToolExecutor({ getApi, getConfig, notifySessionUi, ge
|
|
|
701
755
|
};
|
|
702
756
|
}
|
|
703
757
|
|
|
704
|
-
async function execute(args, { signal }) {
|
|
758
|
+
async function execute(args, { signal, callerSessionId }) {
|
|
705
759
|
signal?.throwIfAborted();
|
|
706
760
|
const requestDesktop = (request) => desktop.request(request, { signal });
|
|
707
761
|
const action = validateSetupInput(args);
|
|
762
|
+
// The session that made this call, not just the runtime's own Lead.
|
|
763
|
+
const sessionId = clean(callerSessionId) || clean(getSessionId?.());
|
|
764
|
+
const caller = (sessionId && getCallerSession?.(sessionId)) || null;
|
|
765
|
+
// A headless run (schedule, webhook, delegated agent) only reads settings:
|
|
766
|
+
// it never creates agents, definitions or automations, nor changes any
|
|
767
|
+
// other setting. Hosts without session provenance (no getCallerSession)
|
|
768
|
+
// skip this gate; automation actions still refuse an unknown caller.
|
|
769
|
+
if (getCallerSession && !READ_ONLY_SETUP_ACTIONS.has(action)) {
|
|
770
|
+
const scope = scheduleCallerScope(caller);
|
|
771
|
+
assertInteractiveCaller(scope, action);
|
|
772
|
+
// Agent definitions (contacts) change only from Mixy; another agent's
|
|
773
|
+
// home changes only its own agent settings.
|
|
774
|
+
if (AGENT_DEFINITION_ACTIONS.has(action) && args.definitionKind === 'agent') {
|
|
775
|
+
assertAgentEditorAccess(scope, caller, action);
|
|
776
|
+
}
|
|
777
|
+
if (action === 'set_agent_route') assertOwnAgentSettings(scope, args.agent, action);
|
|
778
|
+
}
|
|
708
779
|
const rt = action === 'status' || action === 'open' ? null : api();
|
|
709
|
-
if (!Object.hasOwn(SETUP_ACTION_HANDLERS, action))
|
|
780
|
+
if (!Object.hasOwn(SETUP_ACTION_HANDLERS, action)) {
|
|
781
|
+
return executeExtendedSetupAction(rt, args, requestDesktop, { sessionId, caller });
|
|
782
|
+
}
|
|
710
783
|
return SETUP_ACTION_HANDLERS[action](rt, args, { requestDesktop, readStatus, openSurface });
|
|
711
784
|
}
|
|
712
785
|
|