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
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { SETUP_EXTENDED_PROPERTIES, SETUP_DESKTOP_ACTIONS } from './settings-contract.mjs';
|
|
2
2
|
import { MEDIA_KINDS } from '../../runtime/media/tool-defs.mjs';
|
|
3
3
|
import { OPENAI_COMPAT_PRESETS } from '../../runtime/agent/orchestrator/providers/openai-compat-presets.mjs';
|
|
4
|
+
import { MIXY_AGENT_ID, agentIdOfHomeSession } from '../../runtime/agent/orchestrator/session/agent-home.mjs';
|
|
5
|
+
import { AGENT_MODE, resolveSessionMode } from '../../runtime/agent/orchestrator/session/agent-mode.mjs';
|
|
6
|
+
import { BOT_AGENT_KIND, WORKFLOW_AGENT_KIND } from '../../runtime/shared/agent-route-config.mjs';
|
|
7
|
+
import { assertAutomationAccess, scheduleCallerScope } from '../services/schedule-access.mjs';
|
|
4
8
|
|
|
5
9
|
const own = (value, key) => Object.hasOwn(value || {}, key);
|
|
6
10
|
const pick = (value, keys) => Object.fromEntries(keys.filter((key) => own(value, key)).map((key) => [key, value[key]]));
|
|
@@ -162,13 +166,20 @@ async function readDefinition(rt, kind, name) {
|
|
|
162
166
|
};
|
|
163
167
|
}
|
|
164
168
|
|
|
165
|
-
|
|
169
|
+
// A created agent's explicit marker: the one given, else a bot when Mixy's
|
|
170
|
+
// agent-mode chat creates it (Mixy creates bots), else a workflow agent.
|
|
171
|
+
function createdAgentKind(input, caller) {
|
|
172
|
+
if (own(input, 'kind')) return input.kind;
|
|
173
|
+
const { mode, agentId } = resolveSessionMode({ session: caller });
|
|
174
|
+
return mode === AGENT_MODE && agentId === MIXY_AGENT_ID ? BOT_AGENT_KIND : WORKFLOW_AGENT_KIND;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async function saveDefinition(rt, args, context = {}) {
|
|
166
178
|
const kind = args.definitionKind;
|
|
167
179
|
const input = args.definition;
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
: ['id', 'name', 'description', 'body'];
|
|
180
|
+
let allowed = ['id', 'name', 'description', 'body'];
|
|
181
|
+
if (kind === 'skill') allowed = ['originalName', 'name', 'description', 'body', 'whenToUse', 'toolDependencies'];
|
|
182
|
+
else if (kind === 'agent') allowed = [...allowed, 'kind'];
|
|
172
183
|
const unexpected = Object.keys(input).find((key) => !allowed.includes(key));
|
|
173
184
|
if (unexpected) throw new Error(`${unexpected} is not a ${kind} definition field`);
|
|
174
185
|
const creating = args.action === 'create_definition';
|
|
@@ -198,11 +209,34 @@ async function saveDefinition(rt, args) {
|
|
|
198
209
|
const agents = await rt.listAgents();
|
|
199
210
|
if (agents.some((agent) => agent.id === input.id)) throw new Error(`agent "${input.id}" already exists`);
|
|
200
211
|
}
|
|
201
|
-
return rt.saveAgentDefinition(
|
|
212
|
+
if (creating) return rt.saveAgentDefinition({ ...next, kind: createdAgentKind(input, context.caller) });
|
|
213
|
+
// The stored kind is kept as it is; an edit naming one is refused by the editor.
|
|
214
|
+
const { kind: _storedKind, ...edit } = { ...pick(current, definitionKeys), ...input };
|
|
215
|
+
return rt.saveAgentDefinition({ ...edit, ...(own(input, 'kind') ? { kind: input.kind } : {}), id: current.id });
|
|
202
216
|
}
|
|
203
217
|
return creating ? rt.addSkill(next) : rt.saveSkill({ ...next, originalName: current.originalName });
|
|
204
218
|
}
|
|
205
219
|
|
|
220
|
+
async function automationRow(rt, kind, name) {
|
|
221
|
+
const status = await rt.getChannelSetup();
|
|
222
|
+
return status[kind === 'schedule' ? 'schedules' : 'webhooks'].find((row) => row.name === name) || null;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** Authorize one automation action for the calling session (`context.caller`,
|
|
226
|
+
* its session record; null when it could not be resolved) — schedule-access.mjs. */
|
|
227
|
+
async function authorizeAutomation(rt, context, { kind, action, current, owner = '' }) {
|
|
228
|
+
const scope = scheduleCallerScope(context.caller);
|
|
229
|
+
const transfer = String(owner ?? '').trim();
|
|
230
|
+
const agents = transfer && scope.kind === 'human' ? await rt.listAgents() : [];
|
|
231
|
+
assertAutomationAccess(scope, {
|
|
232
|
+
kind,
|
|
233
|
+
action,
|
|
234
|
+
current,
|
|
235
|
+
owner: transfer,
|
|
236
|
+
agentIds: (Array.isArray(agents) ? agents : []).map((agent) => agent?.id).filter(Boolean),
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
|
|
206
240
|
export const EXTENDED_SETUP_HANDLERS = Object.freeze({
|
|
207
241
|
set_local_context: (rt, args) => rt.setLocalProviderContext(args.modelId, args.localContextWindow),
|
|
208
242
|
async list_models(rt, args) {
|
|
@@ -238,22 +272,29 @@ export const EXTENDED_SETUP_HANDLERS = Object.freeze({
|
|
|
238
272
|
return {
|
|
239
273
|
...result,
|
|
240
274
|
recovery:
|
|
241
|
-
|
|
275
|
+
args.definitionKind === 'workflow'
|
|
276
|
+
? 'User-authored definition files are deleted. A built-in override may revert to its built-in definition.'
|
|
277
|
+
: 'A custom agent or bot is archived with its chat and its routines are switched off; the user can restore it from Sessions → Archived, or delete it there for good. A built-in override reverts to its built-in definition.',
|
|
242
278
|
};
|
|
243
279
|
},
|
|
244
|
-
async save_automation(rt, args) {
|
|
280
|
+
async save_automation(rt, args, context = {}) {
|
|
245
281
|
const kind = args.automationKind;
|
|
246
282
|
const input = args.entry;
|
|
247
283
|
if (kind === 'webhook' && ['time', 'at', 'timezone', 'days'].some((key) => own(input, key))) {
|
|
248
|
-
throw new Error('Schedule timing
|
|
284
|
+
throw new Error('Schedule fields (timing) are not accepted for webhooks');
|
|
249
285
|
}
|
|
250
286
|
if (kind === 'schedule' && own(input, 'parser')) throw new Error('parser is a webhook-only field');
|
|
251
287
|
let previous = {};
|
|
252
288
|
if (input.overwrite) {
|
|
253
|
-
|
|
254
|
-
previous = status[kind === 'schedule' ? 'schedules' : 'webhooks'].find((row) => row.name === input.name);
|
|
289
|
+
previous = await automationRow(rt, kind, input.name);
|
|
255
290
|
if (!previous) throw new Error(`${kind} "${input.name}" does not exist`);
|
|
256
291
|
}
|
|
292
|
+
await authorizeAutomation(rt, context, {
|
|
293
|
+
kind,
|
|
294
|
+
action: input.overwrite ? 'edit' : 'create',
|
|
295
|
+
current: input.overwrite ? previous : null,
|
|
296
|
+
owner: input.owner,
|
|
297
|
+
});
|
|
257
298
|
const next = { ...pick(previous, entryKeys), ...input };
|
|
258
299
|
if (kind === 'schedule') {
|
|
259
300
|
if (previous.whenAt && !own(input, 'time') && !own(input, 'at')) {
|
|
@@ -263,6 +304,11 @@ export const EXTENDED_SETUP_HANDLERS = Object.freeze({
|
|
|
263
304
|
if (own(input, 'time') && !own(input, 'at')) delete next.at;
|
|
264
305
|
if (own(input, 'at') && !own(input, 'time')) delete next.time;
|
|
265
306
|
}
|
|
307
|
+
// An automation created from an agent's home thread belongs to that agent.
|
|
308
|
+
if (!input.overwrite && !own(input, 'owner')) {
|
|
309
|
+
const homeAgent = agentIdOfHomeSession(context.sessionId);
|
|
310
|
+
if (homeAgent) next.owner = homeAgent;
|
|
311
|
+
}
|
|
266
312
|
const result = kind === 'schedule' ? await rt.saveSchedule(next) : await rt.saveWebhook(next);
|
|
267
313
|
return {
|
|
268
314
|
...publicAutomation(result),
|
|
@@ -275,18 +321,42 @@ export const EXTENDED_SETUP_HANDLERS = Object.freeze({
|
|
|
275
321
|
: {}),
|
|
276
322
|
};
|
|
277
323
|
},
|
|
278
|
-
async delete_automation(rt, args) {
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
|
|
324
|
+
async delete_automation(rt, args, context = {}) {
|
|
325
|
+
const current = await automationRow(rt, args.automationKind, args.name);
|
|
326
|
+
if (!current) throw new Error('Automation entry not found');
|
|
327
|
+
await authorizeAutomation(rt, context, { kind: args.automationKind, action: 'delete', current });
|
|
282
328
|
const result =
|
|
283
329
|
args.automationKind === 'schedule' ? await rt.deleteSchedule(args.name) : await rt.deleteWebhook(args.name);
|
|
284
330
|
return { ...result, recovery: 'The automation record is deleted; recreating it requires its definition.' };
|
|
285
331
|
},
|
|
286
|
-
set_automation_enabled
|
|
287
|
-
args.automationKind
|
|
332
|
+
async set_automation_enabled(rt, args, context = {}) {
|
|
333
|
+
const current = await automationRow(rt, args.automationKind, args.name);
|
|
334
|
+
if (!current) throw new Error('Automation entry not found');
|
|
335
|
+
const action = args.enabled === false ? 'pause' : 'resume';
|
|
336
|
+
await authorizeAutomation(rt, context, { kind: args.automationKind, action, current });
|
|
337
|
+
return args.automationKind === 'schedule'
|
|
288
338
|
? rt.setScheduleEnabled(args.name, args.enabled)
|
|
289
|
-
: rt.setWebhookEnabled(args.name, args.enabled)
|
|
339
|
+
: rt.setWebhookEnabled(args.name, args.enabled);
|
|
340
|
+
},
|
|
341
|
+
// Starts the run and returns at once: the run is its own session, and its
|
|
342
|
+
// result posts into the owning agent's thread when it ends. A webhook
|
|
343
|
+
// re-runs on its latest received payload.
|
|
344
|
+
async run_automation(rt, args, context = {}) {
|
|
345
|
+
const kind = args.automationKind;
|
|
346
|
+
const current = await automationRow(rt, kind, args.name);
|
|
347
|
+
if (!current) throw new Error('Automation entry not found');
|
|
348
|
+
await authorizeAutomation(rt, context, { kind, action: 'run', current });
|
|
349
|
+
if (kind === 'webhook' && current.hasLastPayload !== true) {
|
|
350
|
+
throw new Error(`webhook "${args.name}" has not received a payload yet`);
|
|
351
|
+
}
|
|
352
|
+
const run = kind === 'webhook' ? rt.runWebhookNow(args.name) : rt.runScheduleNow(args.name);
|
|
353
|
+
void Promise.resolve(run).catch(() => {});
|
|
354
|
+
return {
|
|
355
|
+
name: args.name,
|
|
356
|
+
started: true,
|
|
357
|
+
note: "The run is its own session; its result posts into the owning agent's thread when it finishes.",
|
|
358
|
+
};
|
|
359
|
+
},
|
|
290
360
|
async set_developer_option(rt, args) {
|
|
291
361
|
const option = rt
|
|
292
362
|
.getDeveloperSettings()
|
|
@@ -360,9 +430,9 @@ function hookRuleAt(rt, index) {
|
|
|
360
430
|
return publicHookRule(rule);
|
|
361
431
|
}
|
|
362
432
|
|
|
363
|
-
export async function executeExtendedSetupAction(rt, args, requestDesktop) {
|
|
433
|
+
export async function executeExtendedSetupAction(rt, args, requestDesktop, context = {}) {
|
|
364
434
|
if (SETUP_DESKTOP_ACTIONS.includes(args.action)) return requestDesktop(args);
|
|
365
435
|
const handler = EXTENDED_SETUP_HANDLERS[args.action];
|
|
366
436
|
if (!handler) throw new Error(`setup: unhandled action "${args.action}"`);
|
|
367
|
-
return handler(rt, args);
|
|
437
|
+
return handler(rt, args, context);
|
|
368
438
|
}
|
|
@@ -26,6 +26,7 @@ export const SETUP_EXTENDED_ACTION_FIELDS = Object.freeze({
|
|
|
26
26
|
save_automation: 'automationKind entry',
|
|
27
27
|
delete_automation: 'automationKind name',
|
|
28
28
|
set_automation_enabled: 'automationKind name enabled',
|
|
29
|
+
run_automation: 'automationKind name',
|
|
29
30
|
set_webhook_config: 'webhook',
|
|
30
31
|
set_desktop_settings: 'desktop',
|
|
31
32
|
set_appearance: 'appearance',
|
|
@@ -51,6 +52,7 @@ export const SETUP_ACTIVITY_RAIL_PIN_IDS = Object.freeze([
|
|
|
51
52
|
'workflows',
|
|
52
53
|
'projects',
|
|
53
54
|
'extensions',
|
|
55
|
+
'skills',
|
|
54
56
|
'source-control',
|
|
55
57
|
'search',
|
|
56
58
|
'webhooks',
|
|
@@ -155,6 +157,12 @@ export const SETUP_EXTENDED_PROPERTIES = Object.freeze({
|
|
|
155
157
|
name: text,
|
|
156
158
|
description: text,
|
|
157
159
|
body: text,
|
|
160
|
+
kind: {
|
|
161
|
+
type: 'string',
|
|
162
|
+
enum: ['bot', 'agent'],
|
|
163
|
+
description:
|
|
164
|
+
'Agent create only: "bot" (a contact the user chats with) or "agent" (a workflow sub-agent). Omitted: a bot when created from the representative bot\'s chat, else a workflow agent. Fixed after creation.',
|
|
165
|
+
},
|
|
158
166
|
whenToUse: text,
|
|
159
167
|
toolDependencies: {
|
|
160
168
|
type: ['array', 'null'],
|
|
@@ -172,13 +180,7 @@ export const SETUP_EXTENDED_PROPERTIES = Object.freeze({
|
|
|
172
180
|
timezone: text,
|
|
173
181
|
days: { ...text, description: 'Schedule day selector, e.g. weekdays or mon,wed,fri.' },
|
|
174
182
|
parser: { type: 'string', enum: ['github', 'generic', 'stripe', 'sentry'] },
|
|
175
|
-
model: {
|
|
176
|
-
...text,
|
|
177
|
-
description:
|
|
178
|
-
'Required for new schedules; no default-model fallback. Use provider/model[@effort][+fast][+noauto][?parameter=value] (+noauto: Auto reasoning off; absent = on) or an existing preset name. On overwrite, omission preserves the saved model, which must be non-empty.',
|
|
179
|
-
},
|
|
180
183
|
cwd: text,
|
|
181
|
-
workflow: text,
|
|
182
184
|
attachments: {
|
|
183
185
|
type: 'array',
|
|
184
186
|
maxItems: 8,
|
|
@@ -197,6 +199,11 @@ export const SETUP_EXTENDED_PROPERTIES = Object.freeze({
|
|
|
197
199
|
),
|
|
198
200
|
},
|
|
199
201
|
enabled: boolean,
|
|
202
|
+
owner: {
|
|
203
|
+
...text,
|
|
204
|
+
description:
|
|
205
|
+
"The bot id that owns the schedule or webhook; each run is a turn in that bot's chat, where it replies with the result. The bot must exist (no representative bot yet = refused). New entries default to the bot of the calling thread (the representative bot = lead); on overwrite, omission keeps the owner.",
|
|
206
|
+
},
|
|
200
207
|
overwrite: { ...boolean, description: 'Explicitly update an existing entry; omitted fields are preserved.' },
|
|
201
208
|
},
|
|
202
209
|
['name']
|
|
@@ -213,6 +220,7 @@ export const SETUP_EXTENDED_PROPERTIES = Object.freeze({
|
|
|
213
220
|
usagePinned: boolean,
|
|
214
221
|
usageRailShortLong: boolean,
|
|
215
222
|
computerObserveOnly: boolean,
|
|
223
|
+
browserAutoSignIn: boolean,
|
|
216
224
|
notificationVolume: {
|
|
217
225
|
type: 'integer',
|
|
218
226
|
minimum: 0,
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
import { MEDIA_KINDS } from '../../runtime/media/tool-defs.mjs';
|
|
8
8
|
import { INSTRUCTION_FILES_MODES } from '../../runtime/shared/instruction-files-mode.mjs';
|
|
9
9
|
import { WORKTREE_NEW_TASK_DEFAULTS } from '../../runtime/shared/worktrees/settings.mjs';
|
|
10
|
+
import { CONNECTOR_IDS } from '../../runtime/shared/connector-catalog.mjs';
|
|
10
11
|
|
|
11
12
|
/** Built-in `setup` tool: the model's handle on a Mixdog user's persisted
|
|
12
13
|
* configuration. The description is a contract only; how to use each action
|
|
@@ -110,6 +111,7 @@ export const SETUP_ACTION_FIELDS = Object.freeze({
|
|
|
110
111
|
set_plugin_enabled: 'name enabled',
|
|
111
112
|
remove_plugin: 'name',
|
|
112
113
|
enable_plugin_mcp: 'name',
|
|
114
|
+
connect_connector: 'connector',
|
|
113
115
|
set_worktree_settings: 'worktree',
|
|
114
116
|
...SETUP_EXTENDED_ACTION_FIELDS,
|
|
115
117
|
});
|
|
@@ -345,6 +347,12 @@ export const SETUP_TOOL_DEFS = Object.freeze([
|
|
|
345
347
|
description: 'set_disabled_skills: full list of disabled skill names.',
|
|
346
348
|
},
|
|
347
349
|
source: { type: 'string', description: 'add_plugin: Git URL, owner/repo, or local path.' },
|
|
350
|
+
connector: {
|
|
351
|
+
type: 'string',
|
|
352
|
+
enum: [...CONNECTOR_IDS],
|
|
353
|
+
description:
|
|
354
|
+
'connect_connector: catalog service to connect. Shows the user a connect card in this conversation (one-click sign-in or a key sheet in Desktop); it never connects by itself.',
|
|
355
|
+
},
|
|
348
356
|
kind: {
|
|
349
357
|
type: 'string',
|
|
350
358
|
enum: ['skills', 'mcp', 'plugins', ...MEDIA_KINDS],
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Skill surface (status listing, resource load, tool envelope, global skill
|
|
2
2
|
// creation/editing). The runtime facade only wires the mutable cwd and the
|
|
3
3
|
// context module into it.
|
|
4
|
-
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
5
5
|
import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
6
6
|
import { resolvePluginData } from '../runtime/shared/plugin-paths.mjs';
|
|
7
7
|
import {
|
|
@@ -193,6 +193,20 @@ export function createSkillsApi({ contextMod, getCwd, getTools = () => [] }) {
|
|
|
193
193
|
return { originalName, name, filePath };
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
+
function removeGlobalSkill(input = {}) {
|
|
197
|
+
const name = validateSkillName(input.name);
|
|
198
|
+
const resource = contextMod.loadSkillResource?.(name, getCwd());
|
|
199
|
+
if (!resource?.filePath) throw new Error(`skill not found: ${name}`);
|
|
200
|
+
const dir = dirname(resolve(resource.filePath));
|
|
201
|
+
const rel = relative(globalSkillsRoot(), dir);
|
|
202
|
+
if (!rel || rel.startsWith('..') || isAbsolute(rel) || basename(dir) !== name) {
|
|
203
|
+
throw new Error(`only your own skills can be removed: ${name}`);
|
|
204
|
+
}
|
|
205
|
+
rmSync(dir, { recursive: true, force: true });
|
|
206
|
+
invalidateSkills();
|
|
207
|
+
return { name };
|
|
208
|
+
}
|
|
209
|
+
|
|
196
210
|
function invalidateSkills() {
|
|
197
211
|
contextMod.invalidateSkillsCache?.(getCwd());
|
|
198
212
|
}
|
|
@@ -203,6 +217,7 @@ export function createSkillsApi({ contextMod, getCwd, getTools = () => [] }) {
|
|
|
203
217
|
skillToolContent,
|
|
204
218
|
addGlobalSkill,
|
|
205
219
|
saveSkillDocument,
|
|
220
|
+
removeGlobalSkill,
|
|
206
221
|
invalidateSkills,
|
|
207
222
|
};
|
|
208
223
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Refresh the empty Lead session's model-facing tool surface and BP1/BP3
|
|
2
2
|
// layers after workflow or search/memory settings change. Conversation
|
|
3
3
|
// sessions keep their frozen schema; the next new session picks up the
|
|
4
|
-
// updated policy.
|
|
4
|
+
// updated policy. The one exception is a workflow switch made in the session
|
|
5
|
+
// itself (switchSessionWorkflow), which rebuilds that conversation's policy.
|
|
5
6
|
import { sessionHasConversationMessages } from '../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
6
7
|
import { toSessionWorkflowMeta } from '../runtime/agent/orchestrator/runtime-core/workflow.mjs';
|
|
7
8
|
import {
|
|
@@ -21,7 +22,25 @@ import {
|
|
|
21
22
|
} from '../runtime/agent/orchestrator/session/manager/session-tool-surface.mjs';
|
|
22
23
|
import { finalizeSessionToolList } from '../runtime/agent/orchestrator/session/manager/tool-resolution.mjs';
|
|
23
24
|
import { isAgentOwner } from '../runtime/agent/orchestrator/agent-owner.mjs';
|
|
25
|
+
import {
|
|
26
|
+
AGENT_MODE,
|
|
27
|
+
isRoutineSource,
|
|
28
|
+
resolveSessionMode,
|
|
29
|
+
sessionModeOf,
|
|
30
|
+
} from '../runtime/agent/orchestrator/session/agent-mode.mjs';
|
|
24
31
|
import { unusedModelEditToolName } from '../runtime/shared/edit-tool-dialect.mjs';
|
|
32
|
+
import { MIXY_AGENT_ID } from '../runtime/agent/orchestrator/session/agent-home.mjs';
|
|
33
|
+
import {
|
|
34
|
+
refreshSessionBp3Environment,
|
|
35
|
+
withPresentedWorkspaceSlices,
|
|
36
|
+
} from '../runtime/agent/orchestrator/session/manager/prompt-utils.mjs';
|
|
37
|
+
import { stageWorkflowSwitchNotice } from '../runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs';
|
|
38
|
+
import { markToolSurfaceMigrated } from '../runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs';
|
|
39
|
+
import { agentProfileRevision, leadRosterRevision } from '../runtime/agent/orchestrator/context/role-instructions.mjs';
|
|
40
|
+
import { recordTranscriptBoundary } from './model-route/set-route.mjs';
|
|
41
|
+
|
|
42
|
+
const WORKFLOW_SWITCH_BUSY = 'The session is running a turn; wait for it to finish.';
|
|
43
|
+
const AGENT_PROFILE_INTENT = 'agent_profile';
|
|
25
44
|
|
|
26
45
|
function toolNames(list) {
|
|
27
46
|
return (Array.isArray(list) ? list : [])
|
|
@@ -46,16 +65,28 @@ function rewriteSystemHeading(session, heading, nextContent) {
|
|
|
46
65
|
if (target) replaceMessageContent(messages, target, nextContent);
|
|
47
66
|
}
|
|
48
67
|
|
|
49
|
-
function
|
|
68
|
+
function bp3Message(session) {
|
|
50
69
|
const messages = Array.isArray(session.messages) ? session.messages : [];
|
|
51
|
-
|
|
70
|
+
return (
|
|
52
71
|
messages.find((message) => message?.role === 'system' && message.cacheTier === 'tier3') ||
|
|
53
72
|
messages.find(
|
|
54
73
|
(message) =>
|
|
55
74
|
message?.role === 'system' &&
|
|
56
75
|
typeof message.content === 'string' &&
|
|
57
76
|
message.content.startsWith('# Active Workflow:')
|
|
58
|
-
)
|
|
77
|
+
)
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// The BP3 core the session's prompt carries now (split layout: the whole
|
|
82
|
+
// tier3 block; combined: the stored core beside the environment).
|
|
83
|
+
function presentedBp3Core(session) {
|
|
84
|
+
return session.bp3EnvSplit === true ? bp3Message(session)?.content : session.bp3CoreContext;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function rewriteBp3Core(session, nextCore) {
|
|
88
|
+
const messages = Array.isArray(session.messages) ? session.messages : [];
|
|
89
|
+
const bp3 = bp3Message(session);
|
|
59
90
|
if (!bp3 || typeof bp3.content !== 'string') return;
|
|
60
91
|
if (session.bp3EnvSplit === true) {
|
|
61
92
|
// Split layout: the environment lives in its own cacheTier:'env' system
|
|
@@ -69,6 +100,27 @@ function rewriteBp3Core(session, nextCore) {
|
|
|
69
100
|
session.bp3CoreContext = nextCore || '';
|
|
70
101
|
}
|
|
71
102
|
|
|
103
|
+
// A Lead's workflow slices (orchestration, agent and contact catalogs) for its
|
|
104
|
+
// mode, Mixy's with the contacts.
|
|
105
|
+
function leadPartsFor(session, leadPromptParts) {
|
|
106
|
+
return leadPromptParts({
|
|
107
|
+
agentMode: sessionModeOf(session) === AGENT_MODE,
|
|
108
|
+
mixy: resolveSessionMode({ session }).agentId === MIXY_AGENT_ID,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// A conversation keeps its `# Session` block: the legacy combined layout
|
|
113
|
+
// rebuilds the tier3 block from the new core (rooted where it was).
|
|
114
|
+
function rewriteConversationBp3Core(session, nextCore) {
|
|
115
|
+
if (session.bp3EnvSplit !== true && typeof session.bp3CoreContext === 'string') {
|
|
116
|
+
const previous = session.bp3CoreContext;
|
|
117
|
+
session.bp3CoreContext = nextCore;
|
|
118
|
+
if (refreshSessionBp3Environment(session, session.cwd)) return;
|
|
119
|
+
session.bp3CoreContext = previous;
|
|
120
|
+
}
|
|
121
|
+
rewriteBp3Core(session, nextCore);
|
|
122
|
+
}
|
|
123
|
+
|
|
72
124
|
export function createToolPolicyRefresh({
|
|
73
125
|
getSession,
|
|
74
126
|
getRoute,
|
|
@@ -137,15 +189,11 @@ export function createToolPolicyRefresh({
|
|
|
137
189
|
);
|
|
138
190
|
}
|
|
139
191
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
// Older records contain only compiled prompt text; rebuilding would guess
|
|
146
|
-
// away custom instructions. Keep that immutable material for every owner.
|
|
147
|
-
const identity = session.promptIdentity;
|
|
148
|
-
if (!identity) return { appliedToCurrentSession: false, reason: 'missing-prompt-identity' };
|
|
192
|
+
// The policy `config` gives `session`, computed without touching the
|
|
193
|
+
// session, so a turn that starts during the async rebuild cannot lose tools
|
|
194
|
+
// to it. `conversation`: the rebuilt BP3 core keeps the instruction files
|
|
195
|
+
// and core memory the prompt presents now (withPresentedWorkspaceSlices).
|
|
196
|
+
async function stagePolicy(session, identity, config, { conversation = false } = {}) {
|
|
149
197
|
const ownerIsAgent = isAgentOwner(session);
|
|
150
198
|
const schemaAllowedTools = honoredSchemaAllowlist(session.schemaAllowedTools, {
|
|
151
199
|
ownerIsAgent,
|
|
@@ -155,11 +203,13 @@ export function createToolPolicyRefresh({
|
|
|
155
203
|
|
|
156
204
|
const {
|
|
157
205
|
summary: workflow,
|
|
158
|
-
|
|
159
|
-
packContext,
|
|
206
|
+
leadPromptParts,
|
|
207
|
+
packContext: workflowContext,
|
|
160
208
|
orchestrationMode,
|
|
161
|
-
} = activeWorkflowContext(
|
|
162
|
-
const
|
|
209
|
+
} = activeWorkflowContext(config, getDataDir());
|
|
210
|
+
const sessionMode = sessionModeOf(session);
|
|
211
|
+
const agentMode = sessionMode === AGENT_MODE;
|
|
212
|
+
const leadWorkflowParts = ownerIsAgent ? {} : leadPartsFor(session, leadPromptParts);
|
|
163
213
|
const denied = [
|
|
164
214
|
...session.callerDisallowedTools,
|
|
165
215
|
...featureDisallowedTools(),
|
|
@@ -168,8 +218,6 @@ export function createToolPolicyRefresh({
|
|
|
168
218
|
.map((name) => String(name || ''))
|
|
169
219
|
.filter(Boolean);
|
|
170
220
|
|
|
171
|
-
// Stage: everything below is computed without touching the session, so a
|
|
172
|
-
// turn that starts during the async rebuild cannot lose tools to it.
|
|
173
221
|
const baseRules =
|
|
174
222
|
identity.skipAgentRules || toolFreeRole
|
|
175
223
|
? ''
|
|
@@ -179,29 +227,201 @@ export function createToolPolicyRefresh({
|
|
|
179
227
|
provider: getRoute()?.provider,
|
|
180
228
|
model: getRoute()?.model,
|
|
181
229
|
});
|
|
182
|
-
const coreMemoryContext = await leadCoreMemoryContext();
|
|
230
|
+
const coreMemoryContext = conversation ? '' : await leadCoreMemoryContext();
|
|
183
231
|
const { sessionMarkerCore } = composeSystemPrompt({
|
|
184
232
|
...sessionRolePromptFields(identity, {
|
|
185
233
|
ownerIsAgent,
|
|
186
234
|
toolFreeRole,
|
|
187
235
|
delegationFree: delegationDisabled(session, ownerIsAgent),
|
|
236
|
+
sessionMode,
|
|
237
|
+
routine: isRoutineSource(session.sourceType),
|
|
188
238
|
}),
|
|
189
239
|
provider: getRoute()?.provider,
|
|
190
240
|
workflowContext,
|
|
241
|
+
...leadWorkflowParts,
|
|
191
242
|
coreMemoryContext,
|
|
192
|
-
// The rebuilt core keeps (or newly applies) the instruction-files
|
|
193
|
-
|
|
243
|
+
// The rebuilt core keeps (or newly applies) the instruction-files
|
|
244
|
+
// setting; agent mode carries none.
|
|
245
|
+
instructionFilesContext:
|
|
246
|
+
conversation || toolFreeRole || agentMode ? null : loadInstructionFilesContext?.(session) || null,
|
|
194
247
|
});
|
|
248
|
+
return {
|
|
249
|
+
workflow,
|
|
250
|
+
orchestrationMode,
|
|
251
|
+
sessionMode,
|
|
252
|
+
denied,
|
|
253
|
+
schemaAllowedTools,
|
|
254
|
+
ownerIsAgent,
|
|
255
|
+
baseRules,
|
|
256
|
+
core: conversation ? withPresentedWorkspaceSlices(session, sessionMarkerCore) : sessionMarkerCore,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Apply a staged policy synchronously; the BP3 core is the caller's.
|
|
261
|
+
function applyPolicy(session, staged) {
|
|
262
|
+
session.workflow = toSessionWorkflowMeta(staged.workflow);
|
|
263
|
+
session.orchestrationMode = staged.orchestrationMode;
|
|
264
|
+
session.sessionMode = staged.sessionMode;
|
|
265
|
+
applyToolDenials(session, staged.denied, staged.schemaAllowedTools, staged.ownerIsAgent);
|
|
266
|
+
rewriteSystemHeading(session, '# Tool Use', staged.baseRules);
|
|
267
|
+
session.updatedAt = Date.now();
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
async function refreshEmptySessionToolPolicy() {
|
|
271
|
+
invalidatePreSessionToolSurface?.();
|
|
272
|
+
const session = getSession?.();
|
|
273
|
+
if (!session?.id) return { appliedToCurrentSession: true };
|
|
274
|
+
if (!admitsRefresh(session)) return { appliedToCurrentSession: false };
|
|
275
|
+
// Older records contain only compiled prompt text; rebuilding would guess
|
|
276
|
+
// away custom instructions. Keep that immutable material for every owner.
|
|
277
|
+
const identity = session.promptIdentity;
|
|
278
|
+
if (!identity) return { appliedToCurrentSession: false, reason: 'missing-prompt-identity' };
|
|
279
|
+
const staged = await stagePolicy(session, identity, getConfig());
|
|
195
280
|
// Apply: re-check admission after the await, then mutate synchronously.
|
|
196
281
|
if (!admitsRefresh(session)) return { appliedToCurrentSession: false };
|
|
197
|
-
session
|
|
198
|
-
session.
|
|
199
|
-
applyToolDenials(session, denied, schemaAllowedTools, ownerIsAgent);
|
|
200
|
-
rewriteSystemHeading(session, '# Tool Use', baseRules);
|
|
201
|
-
rewriteBp3Core(session, sessionMarkerCore);
|
|
202
|
-
session.updatedAt = Date.now();
|
|
282
|
+
applyPolicy(session, staged);
|
|
283
|
+
rewriteBp3Core(session, staged.core);
|
|
203
284
|
return { appliedToCurrentSession: true };
|
|
204
285
|
}
|
|
205
286
|
|
|
206
|
-
|
|
287
|
+
/**
|
|
288
|
+
* Switch the current coding session's workflow mid-conversation (the
|
|
289
|
+
* composer's workflow selector): its prompt (BP3 core and `# Tool Use`) and
|
|
290
|
+
* tool/delegation surface are rebuilt now for `workflowId` with the current
|
|
291
|
+
* orchestration mode and agents, so its next turn runs on them, and that
|
|
292
|
+
* turn carries a one-time notice (manager/workflow-switch-notice.mjs). The
|
|
293
|
+
* provider prompt cache is rebuilt once. Refused while a turn runs, like a
|
|
294
|
+
* working-folder change. The configured workflow (the default for new
|
|
295
|
+
* sessions) is the caller's and stays as it is.
|
|
296
|
+
*
|
|
297
|
+
* Running work is untouched: agents and workers the session started under
|
|
298
|
+
* the old workflow are separate sessions with their own prompts and tools,
|
|
299
|
+
* so they keep running as they are (unlike a working-folder change, running
|
|
300
|
+
* agents never refuse this); only delegation made from the next turn on
|
|
301
|
+
* uses the new surface.
|
|
302
|
+
*
|
|
303
|
+
* Returns null when the session has no conversation (the caller applies the
|
|
304
|
+
* configured workflow to an empty session as before), else
|
|
305
|
+
* `{ appliedToCurrentSession: true, workflow, workflowSwitch }` where
|
|
306
|
+
* `workflowSwitch` is the transcript boundary (null when unchanged).
|
|
307
|
+
*/
|
|
308
|
+
async function switchSessionWorkflow(workflowId) {
|
|
309
|
+
const session = getSession?.();
|
|
310
|
+
if (!session?.id) return null;
|
|
311
|
+
const conversation = () =>
|
|
312
|
+
sessionHasConversationMessages(session) || sessionHasConversationMessages({ messages: session.liveTurnMessages });
|
|
313
|
+
if (!conversation()) return null;
|
|
314
|
+
if (isAgentOwner(session) || sessionModeOf(session) === AGENT_MODE) {
|
|
315
|
+
throw new Error('Only a coding session has a workflow.');
|
|
316
|
+
}
|
|
317
|
+
const identity = session.promptIdentity;
|
|
318
|
+
if (!identity) throw new Error('This session is too old to switch its workflow; start a new task.');
|
|
319
|
+
const busy = () => getSession?.() !== session || turnInFlight(session);
|
|
320
|
+
if (busy()) throw new Error(WORKFLOW_SWITCH_BUSY);
|
|
321
|
+
const config = getConfig();
|
|
322
|
+
const staged = await stagePolicy(
|
|
323
|
+
session,
|
|
324
|
+
identity,
|
|
325
|
+
{ ...config, workflow: { ...(config?.workflow || {}), active: workflowId } },
|
|
326
|
+
{ conversation: true }
|
|
327
|
+
);
|
|
328
|
+
if (busy()) throw new Error(WORKFLOW_SWITCH_BUSY);
|
|
329
|
+
const before = session.workflow;
|
|
330
|
+
const from = before?.id ? before : null;
|
|
331
|
+
applyPolicy(session, staged);
|
|
332
|
+
rewriteConversationBp3Core(session, staged.core);
|
|
333
|
+
// The request prefix changed: drop provider replay state and the context
|
|
334
|
+
// baseline, and tag the next send's expected cache break.
|
|
335
|
+
markToolSurfaceMigrated(session, 'workflow_switch');
|
|
336
|
+
stageWorkflowSwitchNotice(session, from, session.workflow);
|
|
337
|
+
let workflowSwitch = null;
|
|
338
|
+
if (from?.id !== session.workflow.id) {
|
|
339
|
+
workflowSwitch = {
|
|
340
|
+
fromId: from?.id || '',
|
|
341
|
+
from: from?.name || from?.id || '',
|
|
342
|
+
toId: session.workflow.id,
|
|
343
|
+
to: session.workflow.name,
|
|
344
|
+
at: Date.now(),
|
|
345
|
+
};
|
|
346
|
+
// Two switches can land in the same millisecond (A→B→A): the same
|
|
347
|
+
// switch is a repeat only when its direction matches too.
|
|
348
|
+
recordTranscriptBoundary(
|
|
349
|
+
session,
|
|
350
|
+
'workflowSwitches',
|
|
351
|
+
workflowSwitch,
|
|
352
|
+
(entry) =>
|
|
353
|
+
entry?.at === workflowSwitch.at &&
|
|
354
|
+
entry?.fromId === workflowSwitch.fromId &&
|
|
355
|
+
entry?.toId === workflowSwitch.toId
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
return { appliedToCurrentSession: true, workflow: session.workflow, workflowSwitch };
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// An agent profile edit that met a running turn: the next turn applies it.
|
|
362
|
+
let agentProfilePending = false;
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Bring a Lead session's prompt to the saved bots — its own agent's
|
|
366
|
+
* persona, AGENT.md and name, and the bot roster its catalogs list — after
|
|
367
|
+
* a bot was saved, created, renamed, archived or restored
|
|
368
|
+
* (agent-profile-changes.mjs), on resume, or at the start of the turn after
|
|
369
|
+
* one that ran through the change (`trigger`: 'save' | 'resume' | 'turn').
|
|
370
|
+
* Two stamps (agentProfileRevision, agentRosterRevision) tell whether
|
|
371
|
+
* anything it embeds changed; a delegated worker keeps its prompt. The core
|
|
372
|
+
* is rebuilt like a workflow switch's (the session's own workflow, the
|
|
373
|
+
* workspace slices the model was told) and replaces the stored one, so the
|
|
374
|
+
* next turn sends it with one provider cache break; nothing is re-read per
|
|
375
|
+
* turn. Tools are untouched. Returns true when the prompt changed.
|
|
376
|
+
*/
|
|
377
|
+
async function refreshAgentProfile({ trigger = 'save' } = {}) {
|
|
378
|
+
const session = getSession?.();
|
|
379
|
+
const identity = session?.promptIdentity;
|
|
380
|
+
const agent = identity?.agent;
|
|
381
|
+
if (!session?.id || !agent || isAgentOwner(session)) return false;
|
|
382
|
+
// Only Mixy's own (agent-mode) thread embeds Mixy's profile.
|
|
383
|
+
const revision = agentProfileRevision(agent, { mixy: sessionModeOf(session) === AGENT_MODE });
|
|
384
|
+
const config = getConfig();
|
|
385
|
+
const workflowId = session.workflow?.id;
|
|
386
|
+
const workflowConfig = workflowId
|
|
387
|
+
? { ...config, workflow: { ...(config?.workflow || {}), active: workflowId } }
|
|
388
|
+
: config;
|
|
389
|
+
const roster = leadRosterRevision(
|
|
390
|
+
leadPartsFor(session, activeWorkflowContext(workflowConfig, getDataDir()).leadPromptParts)
|
|
391
|
+
);
|
|
392
|
+
if (session.agentProfileRevision === revision && session.agentRosterRevision === roster) return false;
|
|
393
|
+
// A coding session from before profile stamps keeps its prompt when it
|
|
394
|
+
// is reopened; a saved edit still reaches it.
|
|
395
|
+
if (session.agentProfileRevision === undefined && trigger === 'resume' && sessionModeOf(session) !== AGENT_MODE) {
|
|
396
|
+
return false;
|
|
397
|
+
}
|
|
398
|
+
// At a turn's start its own turn is the one counted; nothing runs yet.
|
|
399
|
+
const busy = () => getSession?.() !== session || (trigger !== 'turn' && turnInFlight(session));
|
|
400
|
+
if (busy()) {
|
|
401
|
+
agentProfilePending = true;
|
|
402
|
+
return false;
|
|
403
|
+
}
|
|
404
|
+
const staged = await stagePolicy(session, identity, workflowConfig, { conversation: true });
|
|
405
|
+
if (busy()) {
|
|
406
|
+
agentProfilePending = true;
|
|
407
|
+
return false;
|
|
408
|
+
}
|
|
409
|
+
session.agentProfileRevision = revision;
|
|
410
|
+
session.agentRosterRevision = roster;
|
|
411
|
+
session.updatedAt = Date.now();
|
|
412
|
+
if (staged.core === presentedBp3Core(session)) return false;
|
|
413
|
+
rewriteConversationBp3Core(session, staged.core);
|
|
414
|
+
// The request prefix changed: one cache break, tagged on the next send.
|
|
415
|
+
markToolSurfaceMigrated(session, AGENT_PROFILE_INTENT);
|
|
416
|
+
return true;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/** Turn start: apply an edit that arrived while the previous turn ran. */
|
|
420
|
+
async function applyPendingAgentProfile() {
|
|
421
|
+
if (!agentProfilePending) return false;
|
|
422
|
+
agentProfilePending = false;
|
|
423
|
+
return refreshAgentProfile({ trigger: 'turn' });
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
return { refreshEmptySessionToolPolicy, switchSessionWorkflow, refreshAgentProfile, applyPendingAgentProfile };
|
|
207
427
|
}
|