mixdog 1.3.4 → 1.4.0
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/oh-my-pi-MIT.txt +23 -0
- package/NOTICE.md +17 -2
- package/README.md +11 -0
- package/package.json +3 -11
- package/scripts/daemon-stub.mjs +1 -1
- package/scripts/embed-google-oauth-client.mjs +49 -0
- package/scripts/gate-local.mjs +4 -2
- package/scripts/lib/test-spawn-ledger.mjs +46 -1
- package/scripts/native-release-status.mjs +2 -2
- package/scripts/recall-history-cases.json +1 -1
- package/scripts/suite-health.mjs +10 -1
- package/scripts/test.mjs +12 -11
- package/src/agents/reviewer/AGENT.md +7 -11
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +25 -1
- package/src/defaults/skills/browser-use/SKILL.md +77 -17
- package/src/defaults/skills/code-tidy/SKILL.md +142 -270
- package/src/defaults/skills/code-tidy/references/agent-cleanup.md +4 -4
- package/src/defaults/skills/code-tidy/references/cleanup-report.md +31 -76
- package/src/defaults/skills/code-tidy/references/dead-code.md +6 -12
- package/src/defaults/skills/computer-use/SKILL.md +33 -9
- package/src/defaults/skills/setup/SKILL.md +29 -2
- package/src/defaults/skills/setup/references/actions.md +117 -28
- package/src/defaults/skills/setup/references/surfaces.md +77 -35
- package/src/defaults/skills/setup-guide/SKILL.md +3 -3
- package/src/defaults/skills/visualize/SKILL.md +2 -1
- package/src/lib/keychain-cjs.cjs +359 -29
- package/src/lib/rules-builder.cjs +10 -8
- package/src/rules/agent/AGENT.md +6 -6
- package/src/rules/agent-mode/AGENT_MODE.md +10 -2
- package/src/rules/agent-mode/MIXY.md +12 -0
- package/src/rules/lead/LEAD.md +18 -20
- package/src/rules/shared/05-tool-calls.md +5 -6
- package/src/rules/shared/10-tool-workflow.md +2 -0
- package/src/rules/shared/60-verification.md +7 -5
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
- package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +193 -0
- package/src/runtime/agent/orchestrator/agent-runtime/title-completion.mjs +3 -1
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -1
- package/src/runtime/agent/orchestrator/config.mjs +34 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +72 -67
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +54 -1
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +177 -73
- package/src/runtime/agent/orchestrator/mcp/client.mjs +25 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +31 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +16 -3
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +42 -7
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +21 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +23 -0
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +11 -1
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +230 -137
- package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +64 -7
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +18 -5
- package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +14 -14
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +160 -69
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +64 -33
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +52 -8
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +22 -6
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +15 -4
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +17 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +142 -104
- package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-normalization.mjs +10 -4
- package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +10 -217
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +22 -6
- package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +409 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-families.mjs +187 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-identity.mjs +342 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-models.mjs +541 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-protobuf.mjs +305 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-request.mjs +558 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-schema.mjs +880 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-session.mjs +190 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-tool-args.mjs +351 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +560 -0
- package/src/runtime/agent/orchestrator/providers/devin.mjs +491 -0
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/gemini-output-limit.mjs +46 -0
- package/src/runtime/agent/orchestrator/providers/gemini-reasoning-relay.mjs +30 -0
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +7 -11
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +61 -22
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +71 -4
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +25 -2
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +96 -5
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +17 -3
- package/src/runtime/agent/orchestrator/providers/lib/tail-reminder-split.mjs +23 -5
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -10
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +8 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +11 -3
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +19 -1
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +39 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +6 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -9
- package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +22 -3
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +43 -5
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +6 -3
- package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/provider-availability.mjs +19 -0
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +65 -1
- package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +38 -12
- package/src/runtime/agent/orchestrator/providers/registry.mjs +43 -3
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +39 -7
- package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/wire-protobuf-codec.mjs +368 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +12 -7
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/compaction-config-keys.mjs +62 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +37 -16
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +100 -23
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/reaction-tool-defs.mjs +133 -0
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +23 -5
- package/src/runtime/agent/orchestrator/runtime-core/tool-profile.mjs +35 -10
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +57 -10
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +9 -6
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +18 -0
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +0 -3
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +10 -4
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +792 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +148 -25
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +475 -58
- package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +42 -17
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +47 -9
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +14 -2
- package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +18 -22
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +32 -3
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +51 -3
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +17 -3
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/after-hook.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +14 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +23 -5
- package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +60 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +19 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +133 -90
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +14 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +31 -4
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +30 -18
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +23 -13
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +129 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +20 -2
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +7 -2
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +18 -5
- package/src/runtime/agent/orchestrator/session/message-ids.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/message-reactions.mjs +89 -0
- package/src/runtime/agent/orchestrator/session/message-reactions.test-support.mjs +75 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +19 -8
- package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
- package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +127 -0
- package/src/runtime/agent/orchestrator/session/routine-result.d.mts +0 -2
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +47 -11
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +20 -2
- package/src/runtime/agent/orchestrator/session/sensitive-projection.mjs +100 -0
- package/src/runtime/agent/orchestrator/session/sensitive-values.mjs +257 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +20 -7
- package/src/runtime/agent/orchestrator/session/side-question.mjs +18 -0
- package/src/runtime/agent/orchestrator/session/skill-update-notice.mjs +60 -0
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/save-delta.mjs +9 -5
- package/src/runtime/agent/orchestrator/session/store/serialize.mjs +9 -8
- package/src/runtime/agent/orchestrator/session/store/session-persistence-events.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-header-cache.mjs +85 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +133 -18
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +12 -2
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -14
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +84 -3
- package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
- package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/thinking-binding.mjs +108 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-batch.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +25 -2
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +9 -7
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-text.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/turn-failure.mjs +5 -1
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +5 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +12 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +240 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/shell-cwd.mjs +38 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +25 -5
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +65 -7
- package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +36 -13
- package/src/runtime/browser-bridge/action-schema.mjs +13 -2
- package/src/runtime/browser-bridge/client.mjs +73 -8
- package/src/runtime/browser-bridge/input-fields.mjs +8 -9
- package/src/runtime/browser-bridge/mail-links.mjs +107 -0
- package/src/runtime/browser-bridge/tool-defs.mjs +1 -1
- package/src/runtime/channels/lib/config.mjs +6 -61
- package/src/runtime/channels/lib/crash-log.mjs +1 -1
- package/src/runtime/channels/lib/event-pipeline.mjs +4 -19
- package/src/runtime/channels/lib/event-queue.mjs +3 -18
- package/src/runtime/channels/lib/owned-runtime/automation-services.mjs +2 -2
- package/src/runtime/channels/lib/owned-runtime/automation-start.mjs +3 -4
- package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +4 -59
- package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +33 -115
- package/src/runtime/channels/lib/owned-runtime/owned-stop.mjs +5 -22
- package/src/runtime/channels/lib/owned-runtime/state.mjs +2 -8
- package/src/runtime/channels/lib/owned-runtime.mjs +6 -23
- package/src/runtime/channels/lib/parent-bridge.mjs +2 -2
- package/src/runtime/channels/lib/runtime-paths.mjs +4 -43
- package/src/runtime/channels/lib/schedule-errors.mjs +51 -0
- package/src/runtime/channels/lib/scheduler.mjs +135 -154
- package/src/runtime/channels/lib/schedules-db.mjs +83 -11
- package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
- package/src/runtime/channels/lib/tool-dispatch.mjs +14 -2
- package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
- package/src/runtime/channels/lib/worker-bootstrap.mjs +0 -1
- package/src/runtime/channels/lib/worker-ipc.mjs +0 -1
- package/src/runtime/channels/lib/worker-main.mjs +19 -34
- package/src/runtime/computer-bridge/action-schema.mjs +42 -1
- package/src/runtime/computer-bridge/actions.mjs +9 -1
- package/src/runtime/computer-bridge/client.mjs +180 -8
- package/src/runtime/computer-bridge/core-actions.mjs +2 -2
- package/src/runtime/computer-bridge/error-recovery.mjs +27 -2
- package/src/runtime/computer-bridge/linux-readiness.mjs +65 -23
- package/src/runtime/computer-bridge/pending-continuation.mjs +1 -1
- package/src/runtime/connectors/connector-accounts-mcp.mjs +230 -0
- package/src/runtime/connectors/gmail-app-password.mjs +172 -39
- package/src/runtime/connectors/google-mcp.mjs +10 -12
- package/src/runtime/memory/lib/pg/adapter.mjs +77 -70
- package/src/runtime/memory/lib/pg/supervisor.mjs +24 -12
- package/src/runtime/memory/lib/runtime-fetcher.mjs +23 -5
- package/src/runtime/office/com/com-adapter.mjs +17 -1
- package/src/runtime/office/com/office-com-host.ps1 +51 -1
- package/src/runtime/office/pdf/cfb-fixture.mjs +328 -0
- package/src/runtime/office/pdf/cfb-protection.mjs +311 -0
- package/src/runtime/office/pdf/document-preview.mjs +326 -8
- package/src/runtime/office/pdf/ooxml-crypto.mjs +469 -0
- package/src/runtime/office/pdf/ooxml-key-worker.mjs +14 -0
- package/src/runtime/office/portable/portable-soffice.mjs +45 -5
- package/src/runtime/session-search/session-search-db.mjs +73 -9
- package/src/runtime/session-search/session-search-ingest.mjs +110 -20
- package/src/runtime/shared/abort-race.mjs +89 -0
- package/src/runtime/shared/agent-avatar.d.mts +0 -1
- package/src/runtime/shared/agent-kind.mjs +4 -3
- package/src/runtime/shared/bot-hops.mjs +62 -2
- package/src/runtime/shared/bounded-download.mjs +8 -3
- package/src/runtime/shared/config.mjs +51 -35
- package/src/runtime/shared/connector-accounts.mjs +20 -10
- package/src/runtime/shared/connector-catalog.d.mts +33 -2
- package/src/runtime/shared/connector-catalog.mjs +166 -8
- package/src/runtime/shared/connector-triggers.mjs +22 -19
- package/src/runtime/shared/defaults-separation.mjs +2 -14
- package/src/runtime/shared/delegated-approval-host.mjs +103 -11
- package/src/runtime/shared/developer-options.mjs +32 -1
- package/src/runtime/shared/err-text.mjs +24 -15
- package/src/runtime/shared/file-permissions.d.mts +0 -8
- package/src/runtime/shared/file-permissions.mjs +0 -11
- package/src/runtime/shared/git-direct.test-support.mjs +19 -0
- package/src/runtime/shared/google-oauth-client.generated.json +4 -0
- package/src/runtime/shared/google-oauth-client.mjs +34 -9
- package/src/runtime/shared/heartbeat-interval.d.mts +4 -0
- package/src/runtime/shared/heartbeat-interval.mjs +19 -0
- package/src/runtime/shared/idle-auto-clear-gate.mjs +104 -0
- package/src/runtime/shared/llm/anthropic-betas.mjs +7 -0
- package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +12 -0
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +1 -0
- package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
- package/src/runtime/shared/llm/well-formed.mjs +66 -0
- package/src/runtime/shared/mixy-presence.mjs +22 -0
- package/src/runtime/shared/orchestration.d.mts +2 -0
- package/src/runtime/shared/pg-schema-db.mjs +27 -16
- package/src/runtime/shared/profile-config.cjs +1 -1
- package/src/runtime/shared/prompt-origin.d.mts +4 -0
- package/src/runtime/shared/prompt-origin.mjs +21 -0
- package/src/runtime/shared/provider-accounts.mjs +231 -59
- package/src/runtime/shared/provider-api-key.mjs +19 -8
- package/src/runtime/shared/provider-display-name.mjs +29 -0
- package/src/runtime/shared/provider-timeout-phase.mjs +2 -0
- package/src/runtime/shared/routine-trigger.d.mts +2 -0
- package/src/runtime/shared/routine-trigger.mjs +52 -0
- package/src/runtime/shared/sensitive-path-rules.d.mts +2 -10
- package/src/runtime/shared/sensitive-path-rules.mjs +19 -41
- package/src/runtime/shared/session-activity-signal.mjs +34 -1
- package/src/runtime/shared/session-sidebar-host.d.mts +1 -1
- package/src/runtime/shared/session-sidebar-host.mjs +7 -3
- package/src/runtime/shared/session-turn-prelude.mjs +18 -0
- package/src/runtime/shared/tool-execution-contract.mjs +2 -0
- package/src/runtime/shared/tool-result-summary.mjs +1 -14
- package/src/runtime/shared/transcript-metadata.mjs +38 -0
- package/src/runtime/shared/user-data-guard.mjs +30 -2
- package/src/runtime/shared/worktrees/activity-gate.mjs +12 -5
- package/src/runtime/shared/worktrees/test-support.mjs +9 -4
- package/src/runtime/terminal-bridge/client.mjs +10 -1
- package/src/runtime/visualize-bridge/client.mjs +27 -8
- package/src/runtime/visualize-bridge/tool-defs.mjs +22 -8
- package/src/runtime/visualize-bridge/tool-meta.d.mts +5 -0
- package/src/runtime/visualize-bridge/tool-meta.mjs +22 -0
- package/src/runtime/web-search/lib/fetch-pipeline.mjs +2 -2
- package/src/session-runtime/agent-home-delivery.mjs +486 -179
- package/src/session-runtime/agent-room-delivery.mjs +28 -1
- package/src/session-runtime/agent-task-sessions.mjs +561 -199
- package/src/session-runtime/boot/apis.mjs +9 -0
- package/src/session-runtime/boot/begin.mjs +3 -2
- package/src/session-runtime/boot/infrastructure.mjs +4 -0
- package/src/session-runtime/boot/providers.mjs +3 -0
- package/src/session-runtime/boot/tools.mjs +8 -1
- package/src/session-runtime/bot-chain.mjs +32 -0
- package/src/session-runtime/bot-status.mjs +7 -4
- package/src/session-runtime/channel-config-api.mjs +63 -17
- package/src/session-runtime/config-lifecycle.mjs +6 -0
- package/src/session-runtime/connector-merge-migration.mjs +305 -0
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +132 -28
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +2 -0
- package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +45 -0
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +72 -5
- package/src/session-runtime/internal-tool-executor.mjs +4 -0
- package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
- package/src/session-runtime/lifecycle/session-catalog.mjs +3 -1
- package/src/session-runtime/lifecycle/teardown/runtime-stops.mjs +50 -4
- package/src/session-runtime/lifecycle/teardown.mjs +23 -5
- package/src/session-runtime/mcp-glue/server-catalog.mjs +61 -3
- package/src/session-runtime/mcp-oauth-login.mjs +5 -3
- package/src/session-runtime/mixy-heartbeat.mjs +927 -0
- package/src/session-runtime/model-route/route-tuning.mjs +10 -6
- package/src/session-runtime/notification-bus.mjs +31 -117
- package/src/session-runtime/notification-completion-queue.mjs +54 -0
- package/src/session-runtime/notification-listeners.mjs +76 -0
- package/src/session-runtime/owned-automation-run.mjs +35 -13
- package/src/session-runtime/prewarm/channel-start.mjs +3 -7
- package/src/session-runtime/provider-auth/login.mjs +7 -0
- package/src/session-runtime/provider-models/row-hydration.mjs +13 -2
- package/src/session-runtime/resource-mcp-api.mjs +143 -224
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +163 -0
- package/src/session-runtime/resource-mcp-oauth-api.mjs +217 -0
- package/src/session-runtime/resource-mcp-secrets.mjs +82 -0
- package/src/session-runtime/resource-mcp-servers.mjs +78 -0
- package/src/session-runtime/resource-mcp-store.mjs +49 -0
- package/src/session-runtime/routine-home-turn.mjs +33 -6
- package/src/session-runtime/routine-owner.mjs +40 -9
- package/src/session-runtime/schedule-session-run.mjs +7 -3
- package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +8 -12
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +7 -2
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
- package/src/session-runtime/services/agent-tool/worker-index/awaiting-user-sync.mjs +51 -0
- package/src/session-runtime/services/agent-tool/worker-index/disposal.mjs +55 -0
- package/src/session-runtime/services/agent-tool/worker-index/released-store.mjs +123 -0
- package/src/session-runtime/services/agent-tool/worker-index/restart-settlement.mjs +112 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-reads.mjs +36 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +17 -4
- package/src/session-runtime/services/agent-tool/worker-index/row-writes.mjs +58 -0
- package/src/session-runtime/services/agent-tool/worker-index.mjs +41 -241
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +3 -0
- package/src/session-runtime/services/channel-admin.mjs +73 -31
- package/src/session-runtime/services/channel-session-router.mjs +4 -2
- package/src/session-runtime/services/channel-worker.mjs +1 -1
- package/src/session-runtime/services/provider-admin.mjs +128 -25
- package/src/session-runtime/services/schedule-access.mjs +14 -0
- package/src/session-runtime/services/seeds.mjs +0 -28
- package/src/session-runtime/services/usage-dashboard-model.mjs +1 -0
- package/src/session-runtime/session-compaction-sync.mjs +27 -0
- package/src/session-runtime/session-create/session-options.mjs +8 -4
- package/src/session-runtime/settings-builtin-tools-api.mjs +11 -0
- package/src/session-runtime/settings-compaction-api.mjs +2 -40
- package/src/session-runtime/settings-system-api.mjs +28 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
- package/src/session-runtime/setup-tool/executor.mjs +187 -29
- package/src/session-runtime/setup-tool/extended-actions.mjs +33 -2
- package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +68 -6
- package/src/session-runtime/setup-tool/tool-defs.mjs +92 -6
- package/src/session-runtime/task-session-route.mjs +99 -0
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
- package/src/session-runtime/tool-policy/policy-stage.mjs +21 -4
- package/src/session-runtime/tool-policy/surface-helpers.mjs +2 -3
- package/src/session-runtime/tool-surface.mjs +4 -0
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +98 -21
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +6 -1
- package/src/session-runtime/workspace/transitions.mjs +10 -2
- package/src/standalone/channel-transport/client-registry/client-records.mjs +65 -0
- package/src/standalone/channel-transport/client-registry/client-registration.mjs +118 -0
- package/src/standalone/channel-transport/client-registry.mjs +24 -163
- package/src/standalone/channel-transport.mjs +1 -1
- package/src/standalone/daemon-channels-loader.mjs +10 -8
- package/src/standalone/daemon-session-control/list-page.mjs +72 -0
- package/src/standalone/daemon-session-control/request.mjs +51 -0
- package/src/standalone/daemon-session-control/room-host.mjs +57 -0
- package/src/standalone/daemon-session-control/route-control.mjs +48 -0
- package/src/standalone/daemon-session-control/send-turn.mjs +60 -0
- package/src/standalone/daemon-session-control/worktree-control.mjs +40 -0
- package/src/standalone/daemon-session-control.mjs +161 -157
- package/src/standalone/daemon.mjs +33 -2
- package/src/standalone/session-client.mjs +7 -3
- package/src/standalone/session-protocol.mjs +10 -0
- package/src/standalone/session-service/agent-tree/agent-cancel.mjs +6 -2
- package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
- package/src/standalone/session-service/quota-resume.mjs +3 -0
- package/src/standalone/session-service/retention/busy.mjs +65 -1
- package/src/standalone/session-service/session-calls/session-action.mjs +23 -2
- package/src/standalone/session-service/session-calls/session-turns.mjs +6 -0
- package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
- package/src/standalone/session-service.mjs +13 -0
- package/src/standalone/session-tool-output.mjs +21 -10
- package/src/tui/app/model-options.mjs +4 -27
- package/src/tui/dist/index.mjs +81 -65
- package/src/tui/session/agent-job-feed/model-notification.mjs +3 -0
- package/src/tui/session/initial-state.mjs +3 -0
- package/src/tui/session/notice-surface.mjs +23 -1
- package/src/tui/session/queue-helpers.mjs +3 -42
- package/src/tui/session/session-api/integrations.mjs +1 -0
- package/src/tui/session/session-api/lifecycle.mjs +8 -0
- package/src/tui/session/session-api/routes-agent-definitions.mjs +14 -2
- package/src/tui/session/session-api/routes-write.mjs +5 -1
- package/src/tui/session/session-api/routes.mjs +1 -0
- package/src/tui/session/session-api/settings.mjs +30 -2
- package/src/tui/session/session-flow/auto-clear.mjs +4 -33
- package/src/tui/session/session-flow/drain-closed-queue.mjs +38 -0
- package/src/tui/session/session-flow/drain-enqueue.mjs +86 -0
- package/src/tui/session/session-flow/drain-retry.mjs +35 -0
- package/src/tui/session/session-flow/drain.mjs +118 -149
- package/src/tui/session/session-flow/queue/entry-shape.mjs +5 -0
- package/src/tui/session/session-flow/queue/take-entries.mjs +5 -2
- package/src/tui/session/tool-approval-delegation.mjs +64 -0
- package/src/tui/session/tool-approval-request.mjs +39 -0
- package/src/tui/session/tool-approval-settle.mjs +62 -0
- package/src/tui/session/tool-approval.mjs +69 -115
- package/src/tui/session/tui-steering-persist.mjs +8 -1
- package/src/tui/session/turn-stream.mjs +36 -3
- package/src/tui/session/turn.mjs +23 -2
- package/src/vendor/statusline/bin/statusline-route.mjs +1 -219
- package/src/vendor/statusline/src/gateway/route-meta.mjs +35 -13
- package/scripts/code-graph-description-contract.mjs +0 -188
- package/src/runtime/channels/lib/owned-runtime/ownership-refresh.mjs +0 -36
|
@@ -7,11 +7,16 @@ import { builtinFeatureActive } from '../../runtime/agent/orchestrator/runtime-c
|
|
|
7
7
|
import { ORCHESTRATION_MODES } from '../../runtime/shared/orchestration.mjs';
|
|
8
8
|
import { AUTO_EFFORT_BASES } from '../../runtime/agent/orchestrator/providers/auto-effort.mjs';
|
|
9
9
|
import { INSTRUCTION_FILES_MODES } from '../../runtime/shared/instruction-files-mode.mjs';
|
|
10
|
+
import {
|
|
11
|
+
normalizeHeartbeatIntervalMinutes,
|
|
12
|
+
requireHeartbeatIntervalMinutes,
|
|
13
|
+
} from '../../runtime/shared/heartbeat-interval.mjs';
|
|
10
14
|
import { MEDIA_KINDS } from '../../runtime/media/tool-defs.mjs';
|
|
11
15
|
import { SETUP_DESKTOP_DOMAINS, SETUP_HANDOFFS } from './settings-contract.mjs';
|
|
12
16
|
import { executeExtendedSetupAction, publicAutomation, publicHookRule, validateMcpInput } from './extended-actions.mjs';
|
|
13
17
|
import {
|
|
14
18
|
assertAgentEditorAccess,
|
|
19
|
+
assertHeartbeatSetupAction,
|
|
15
20
|
assertInteractiveCaller,
|
|
16
21
|
assertOwnAgentSettings,
|
|
17
22
|
scheduleCallerScope,
|
|
@@ -29,8 +34,32 @@ import { schemaValueError } from '../../runtime/shared/schema-value-error.mjs';
|
|
|
29
34
|
import { clean } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
30
35
|
import { CONNECTOR_IDS, connectorById } from '../../runtime/shared/connector-catalog.mjs';
|
|
31
36
|
import profileConfig from '../../runtime/shared/profile-config.cjs';
|
|
37
|
+
import { SESSION_ROUTE_HANDLERS, routePositionsStatus } from './session-route-actions.mjs';
|
|
38
|
+
import { AGENT_SETTINGS_HANDLERS } from './agent-settings-actions.mjs';
|
|
39
|
+
import {
|
|
40
|
+
routeFallbackPosition,
|
|
41
|
+
sessionChainSource,
|
|
42
|
+
sessionRoutePrimary,
|
|
43
|
+
} from '../../runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs';
|
|
44
|
+
import { sameRouteModel } from '../../runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs';
|
|
45
|
+
|
|
46
|
+
const AGENT_DEFINITION_ACTIONS = new Set([
|
|
47
|
+
'create_definition',
|
|
48
|
+
'save_definition',
|
|
49
|
+
'delete_definition',
|
|
50
|
+
'restore_definition',
|
|
51
|
+
]);
|
|
52
|
+
// Actions on one agent's own settings: another agent's thread changes only its own.
|
|
53
|
+
const OWN_AGENT_ACTIONS = new Set([
|
|
54
|
+
'set_agent_route',
|
|
55
|
+
'set_agent_permission',
|
|
56
|
+
'set_agent_connector',
|
|
57
|
+
'set_agent_connector_tool',
|
|
58
|
+
]);
|
|
32
59
|
|
|
33
|
-
|
|
60
|
+
// How a fallback chain edit reaches sessions that already run (route-fallback-chain.mjs).
|
|
61
|
+
const CHAIN_APPLIES =
|
|
62
|
+
'a changed fallback chain reaches running sessions on that route from their next fallback hop ([] stops further hops at once; the turn ends with the provider error)';
|
|
34
63
|
|
|
35
64
|
const PROFILE_VALUE_IDS = Object.freeze({
|
|
36
65
|
language: profileConfig.PROFILE_LANGUAGES.map((entry) => entry.id),
|
|
@@ -38,12 +67,32 @@ const PROFILE_VALUE_IDS = Object.freeze({
|
|
|
38
67
|
});
|
|
39
68
|
|
|
40
69
|
const ACTION_APPLIES_TO = {
|
|
41
|
-
|
|
42
|
-
|
|
70
|
+
set_route: `new sessions (an established conversation keeps its model); ${CHAIN_APPLIES}: Lead conversations and agents that inherit Main`,
|
|
71
|
+
set_agent_route: `the bot's chats from their next turn (a running turn finishes on the old model); ${CHAIN_APPLIES}: its chats and sub-agents; an agent switched on or off reaches open conversations from their next turn as an agent list reminder`,
|
|
72
|
+
reset_route_fallback:
|
|
73
|
+
'each listed session from its next turn (a running turn finishes on its fallback model): it returns to its primary and its chain starts over',
|
|
74
|
+
continue_in_model: 'that session now; its stopped turn is not resent',
|
|
75
|
+
schedule_quota_resume: "that session's stopped turn, resent at the provider's reset time",
|
|
76
|
+
cancel_quota_resume: 'that session: its pending resume is dropped; the turn stays stopped',
|
|
77
|
+
set_cache_warming_enabled: 'the next prompt-cache warm of every session; no restart required',
|
|
78
|
+
set_agent_permission: "that agent's next action of the kind, in every session",
|
|
79
|
+
set_agent_connector: "that agent's next connector tool call, in every session",
|
|
80
|
+
set_agent_connector_tool: "that agent's next call of the tool, in every session",
|
|
81
|
+
set_project_connector: 'the next connector tool call of sessions in that Project',
|
|
82
|
+
restore_definition: 'now: the bot and its chat return; its routines stay off',
|
|
83
|
+
set_bot_order: 'the Bots page and the Sessions bot section on every device',
|
|
43
84
|
set_orchestration_mode:
|
|
44
85
|
"new sessions and an empty current one (the default mode); a conversation keeps its own mode until it is switched with the composer's mode selector",
|
|
45
86
|
set_recap_enabled: 'background Memory cycles; no restart required',
|
|
46
87
|
set_auto_update: 'subsequent automatic update checks',
|
|
88
|
+
set_ai_session_titles: 'titles generated from now on; existing titles are unchanged',
|
|
89
|
+
set_quota_auto_resume: 'subsequent usage-limit stops; turning it off cancels pending resumes',
|
|
90
|
+
set_model_preferences: 'the /model picker and model management lists',
|
|
91
|
+
set_heartbeat_enabled: "Mixy's next heartbeat check; no restart required",
|
|
92
|
+
set_heartbeat_interval:
|
|
93
|
+
"Mixy's heartbeat from the next tick: the next check is due the new interval after the last one; no restart required",
|
|
94
|
+
set_reactions_enabled:
|
|
95
|
+
"bots' chats; while off a reaction is refused at once and new chats are not offered the tool; reactions already left stay visible",
|
|
47
96
|
set_worktree_settings: 'new tasks and worktrees created afterwards; existing worktrees are unchanged',
|
|
48
97
|
set_system_shell: 'subsequent shell calls',
|
|
49
98
|
save_automation: 'the automation worker; scheduled runs follow the saved timing',
|
|
@@ -54,7 +103,7 @@ const ACTION_APPLIES_TO = {
|
|
|
54
103
|
add_hook_rule: 'subsequent tool calls; no restart required',
|
|
55
104
|
set_hook_rule_enabled: 'subsequent tool calls; no restart required',
|
|
56
105
|
delete_hook_rule: 'subsequent tool calls; no restart required',
|
|
57
|
-
set_media_default: 'media generations that
|
|
106
|
+
set_media_default: 'media generations that name no lane/model; lane "" returns the kind to Auto',
|
|
58
107
|
};
|
|
59
108
|
|
|
60
109
|
const OPEN_TARGET_HINTS = Object.freeze({
|
|
@@ -65,11 +114,11 @@ const OPEN_TARGET_HINTS = Object.freeze({
|
|
|
65
114
|
workflow: 'Desktop: Workflows · TUI: /workflow',
|
|
66
115
|
agents: 'Desktop: Workflows → Agents · TUI: /agents',
|
|
67
116
|
outputstyle: 'Desktop: Settings → Output style · TUI: /OutputStyle',
|
|
68
|
-
theme: 'Desktop: Settings →
|
|
117
|
+
theme: 'Desktop: Settings → Theme · TUI: /theme',
|
|
69
118
|
profile: 'Desktop: Settings → General → Profile · TUI: /profile',
|
|
70
119
|
autoclear: 'Desktop: Settings → Context · TUI: /autoclear',
|
|
71
120
|
memory:
|
|
72
|
-
'Desktop: Extensions
|
|
121
|
+
'Desktop: Extensions tab → Built-in (Memory); core memories under Projects → project → Memories · TUI: /memory',
|
|
73
122
|
mcp: 'Desktop: Extensions → Connectors tab · TUI: /mcp',
|
|
74
123
|
skills: 'Desktop: Skills (activity rail) · TUI: /skills',
|
|
75
124
|
plugins:
|
|
@@ -79,7 +128,7 @@ const OPEN_TARGET_HINTS = Object.freeze({
|
|
|
79
128
|
doctor: 'Desktop: Settings → System → Doctor, or /doctor in the composer · TUI: /doctor',
|
|
80
129
|
context: 'Desktop: /context in the composer · TUI: /context',
|
|
81
130
|
developer: 'Desktop: Settings → Developer options · TUI: /setting → Developer',
|
|
82
|
-
voice: 'Desktop: Extensions
|
|
131
|
+
voice: 'Desktop: Extensions tab → Built-in (Voice) · TUI: /setting → Voice',
|
|
83
132
|
connection: 'Desktop only: Settings → Connection',
|
|
84
133
|
});
|
|
85
134
|
|
|
@@ -117,6 +166,31 @@ function routeInput(source) {
|
|
|
117
166
|
return next;
|
|
118
167
|
}
|
|
119
168
|
|
|
169
|
+
/** A fallback chain edit's receipt: whether the calling conversation now
|
|
170
|
+
* follows the saved chain, and the position it reads it from. `owner` is
|
|
171
|
+
* whose route was edited: `{ kind: 'lead' }` (set_route) or `{ kind: 'bot',
|
|
172
|
+
* agent }` (set_agent_route); only a caller whose chain comes from that
|
|
173
|
+
* route's settings follows it. */
|
|
174
|
+
function chainReceipt(route, { caller, getConfig }, owner) {
|
|
175
|
+
if (!Object.hasOwn(route, 'fallbacks') || !caller?.agent) return {};
|
|
176
|
+
const config = getConfig();
|
|
177
|
+
const position = routeFallbackPosition(caller, config);
|
|
178
|
+
// Settings-sourced and still on that route's primary: a conversation left on
|
|
179
|
+
// a previous model follows no chain, whatever the saved one is.
|
|
180
|
+
const source = sessionChainSource(caller, config);
|
|
181
|
+
const followsEdited =
|
|
182
|
+
position.chainFrom === 'settings' &&
|
|
183
|
+
sameRouteModel(source, sessionRoutePrimary(caller)) &&
|
|
184
|
+
position.kind === owner.kind &&
|
|
185
|
+
(owner.kind !== 'bot' || position.agent === owner.agent);
|
|
186
|
+
const saved = route.fallbacks.map((entry) => `${entry.provider}/${entry.model}`);
|
|
187
|
+
const followed = position.fallbacks.map((entry) => `${entry.provider}/${entry.model}`);
|
|
188
|
+
return {
|
|
189
|
+
appliedToCurrentSession: followsEdited && saved.join('\n') === followed.join('\n'),
|
|
190
|
+
currentSession: position,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
120
194
|
function apiKeySource(row) {
|
|
121
195
|
if (row.env) return `env:${row.envName}`;
|
|
122
196
|
return row.stored ? 'keychain' : 'none';
|
|
@@ -225,6 +299,18 @@ function mcpRows(status) {
|
|
|
225
299
|
error: server.error || null,
|
|
226
300
|
...(server.warnings?.length ? { warnings: server.warnings } : {}),
|
|
227
301
|
scope: Array.isArray(server.scope) ? server.scope : null,
|
|
302
|
+
...(server.connector ? { connector: server.connector } : {}),
|
|
303
|
+
// A multi-account connector's accounts: remove_mcp_server / sign-in take an account's name.
|
|
304
|
+
...(Array.isArray(server.accounts)
|
|
305
|
+
? {
|
|
306
|
+
accounts: server.accounts.map((account) => ({
|
|
307
|
+
name: account.name,
|
|
308
|
+
email: account.email || '',
|
|
309
|
+
...(account.authRequired ? { authRequired: true } : {}),
|
|
310
|
+
...(account.error ? { error: account.error } : {}),
|
|
311
|
+
})),
|
|
312
|
+
}
|
|
313
|
+
: {}),
|
|
228
314
|
})),
|
|
229
315
|
...(status?.warnings?.length ? { warnings: status.warnings } : {}),
|
|
230
316
|
...(status?.declarationErrors?.length ? { declarationErrors: status.declarationErrors } : {}),
|
|
@@ -277,16 +363,26 @@ async function featureStatus(rt, getConfig) {
|
|
|
277
363
|
browser: { active: builtinFeatureActive(config, 'browser') },
|
|
278
364
|
computer: { active: builtinFeatureActive(config, 'computer') },
|
|
279
365
|
terminal: { active: builtinFeatureActive(config, 'terminal') },
|
|
366
|
+
heartbeat: {
|
|
367
|
+
enabled: config?.heartbeat !== false,
|
|
368
|
+
intervalMinutes: normalizeHeartbeatIntervalMinutes(config?.heartbeatIntervalMinutes),
|
|
369
|
+
},
|
|
370
|
+
reactions: { enabled: config?.reactions !== false },
|
|
280
371
|
voice: rt.getVoiceStatus ? voiceFeatureStatus(await rt.getVoiceStatus()) : null,
|
|
281
372
|
};
|
|
282
373
|
}
|
|
283
374
|
|
|
284
375
|
async function mediaDefaults(rt) {
|
|
285
|
-
const rows = await Promise.all(
|
|
376
|
+
const [pins, ...rows] = await Promise.all([
|
|
377
|
+
rt.getMediaPins(),
|
|
378
|
+
...MEDIA_KINDS.map((kind) => rt.getMediaDefault(kind)),
|
|
379
|
+
]);
|
|
380
|
+
const fieldsOf = (row, fields) => (row ? Object.fromEntries(fields.map((field) => [field, row[field]])) : null);
|
|
286
381
|
return {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
382
|
+
// The default generator (Settings → Built-in → Media generation); null = Auto.
|
|
383
|
+
pinned: Object.fromEntries(MEDIA_KINDS.map((kind) => [kind, fieldsOf(pins[kind], ['lane', 'model', 'account'])])),
|
|
384
|
+
// The last generator used; applies only to a kind that is on Auto.
|
|
385
|
+
remembered: Object.fromEntries(MEDIA_KINDS.map((kind, i) => [kind, fieldsOf(rows[i], ['lane', 'model'])])),
|
|
290
386
|
};
|
|
291
387
|
}
|
|
292
388
|
|
|
@@ -324,11 +420,24 @@ const SETUP_STATUS_READERS = {
|
|
|
324
420
|
features: await featureStatus(rt, getConfig),
|
|
325
421
|
onboarding: rt.getOnboardingStatus?.() || null,
|
|
326
422
|
}),
|
|
327
|
-
model: (rt
|
|
328
|
-
|
|
423
|
+
model: (rt, { getConfig, caller }) => ({
|
|
424
|
+
route: {
|
|
425
|
+
...mainRoute(rt),
|
|
426
|
+
autoEffort: rt.autoEffort !== false,
|
|
427
|
+
// The Lead preset (workflow-lead) holds the Lead route's fallback chain, as the Workflows page reads it.
|
|
428
|
+
fallbacks: (rt.listPresets?.() || []).find((preset) => preset?.id === 'workflow-lead')?.fallbacks || [],
|
|
429
|
+
},
|
|
430
|
+
effortOptions: rt.effortOptions || [],
|
|
431
|
+
// Where this conversation and the other Lead conversations are on their chain.
|
|
432
|
+
...routePositionsStatus({ caller, config: getConfig(), keep: (row) => row.kind === 'lead' }),
|
|
433
|
+
}),
|
|
434
|
+
agents: (rt, { getConfig, caller }) => ({
|
|
329
435
|
agents: rt.listAgents?.() || [],
|
|
330
436
|
orchestrationMode: rt.getOrchestrationMode(),
|
|
331
437
|
orchestrationModes: ORCHESTRATION_MODES,
|
|
438
|
+
...(rt.getBotOrder ? { botOrder: rt.getBotOrder().order } : {}),
|
|
439
|
+
// Bot chats and sub-agents on their fallback chains.
|
|
440
|
+
sessions: routePositionsStatus({ caller, config: getConfig(), keep: (row) => row.kind !== 'lead' }).sessions,
|
|
332
441
|
}),
|
|
333
442
|
workflow: (rt) => ({ workflows: rt.listWorkflows?.() || [] }),
|
|
334
443
|
websearch: (rt) => ({
|
|
@@ -347,19 +456,27 @@ const SETUP_STATUS_READERS = {
|
|
|
347
456
|
};
|
|
348
457
|
},
|
|
349
458
|
autoclear: (rt) => rt.getAutoClear?.() || {},
|
|
350
|
-
compaction: (rt) =>
|
|
459
|
+
compaction: (rt) => ({
|
|
460
|
+
...(rt.getCompactionSettings?.() || {}),
|
|
461
|
+
...(rt.getSessionTitleSettings?.() || {}),
|
|
462
|
+
...(rt.getCacheWarmingSettings ? { promptCacheWarming: rt.getCacheWarmingSettings().enabled } : {}),
|
|
463
|
+
}),
|
|
351
464
|
memory: (rt) => ({ ...(rt.getToolModuleSettings?.()?.memory || {}), recap: rt.getRecapSettings?.() || null }),
|
|
352
465
|
'local-provider': (rt) => rt.getToolModuleSettings().localProvider,
|
|
353
466
|
features: (rt, { getConfig }) => featureStatus(rt, getConfig),
|
|
354
467
|
shell: (rt) => rt.getSystemShell?.() || {},
|
|
355
468
|
providers: async (rt, { detail }) => {
|
|
356
469
|
const rows = publicProviderRows(await rt.getProviderSetup?.({}));
|
|
470
|
+
const quotaResume = rt.getQuotaAutoResume ? { quotaAutoResume: rt.getQuotaAutoResume() } : {};
|
|
357
471
|
// Client mode: the desktop owns accounts, so the server roster is never read.
|
|
358
472
|
if (rows.managedByClient) {
|
|
359
|
-
if (detail) return rows;
|
|
360
|
-
return { managedByClient: true, unavailable: rows.unavailable, ...configuredProviderRows(rows) };
|
|
473
|
+
if (detail) return { ...rows, ...quotaResume };
|
|
474
|
+
return { managedByClient: true, unavailable: rows.unavailable, ...configuredProviderRows(rows), ...quotaResume };
|
|
361
475
|
}
|
|
362
|
-
if (!detail)
|
|
476
|
+
if (!detail) {
|
|
477
|
+
return { ...configuredProviderRows(rows, (id) => rt.getProviderAccounts(id).accounts.length), ...quotaResume };
|
|
478
|
+
}
|
|
479
|
+
Object.assign(rows, quotaResume);
|
|
363
480
|
rows.oauth = rows.oauth.map((row) =>
|
|
364
481
|
row.authenticated ? { ...row, accounts: publicAccounts(rt.getProviderAccounts(row.id)) } : row
|
|
365
482
|
);
|
|
@@ -473,22 +590,28 @@ const SETUP_INSTALLABLE_FEATURES = [
|
|
|
473
590
|
// Action handlers: (rt, args, { requestDesktop, readStatus, openSurface }).
|
|
474
591
|
// `rt` is null for `status` and `open`, which never touch the facade.
|
|
475
592
|
const SETUP_ACTION_HANDLERS = {
|
|
476
|
-
status: async (_rt, args, { readStatus, requestDesktop }) => {
|
|
593
|
+
status: async (_rt, args, { readStatus, requestDesktop, caller }) => {
|
|
477
594
|
const domain = clean(args.domain) || 'summary';
|
|
478
595
|
requireEnum(domain, SETUP_STATUS_DOMAINS, 'domain');
|
|
479
|
-
return { domain, ...(await readStatus(domain, requestDesktop, args.detail === true)) };
|
|
596
|
+
return { domain, ...(await readStatus(domain, requestDesktop, args.detail === true, caller)) };
|
|
480
597
|
},
|
|
481
598
|
open: (_rt, args, { openSurface }) => openSurface(args.target),
|
|
482
|
-
set_route: async (rt, args) => {
|
|
599
|
+
set_route: async (rt, args, context) => {
|
|
483
600
|
const route = routeInput(args.route);
|
|
484
601
|
const next = await rt.setRoute(route, { keepMainModel: false });
|
|
485
|
-
return { route: next,
|
|
602
|
+
return { route: next, ...chainReceipt(args.route, context, { kind: 'lead' }) };
|
|
486
603
|
},
|
|
487
|
-
set_agent_route: async (rt, args) => {
|
|
604
|
+
set_agent_route: async (rt, args, context) => {
|
|
488
605
|
const agent = requireText(args.agent, 'agent');
|
|
489
606
|
const route = routeInput(args.route);
|
|
490
|
-
return {
|
|
607
|
+
return {
|
|
608
|
+
agent,
|
|
609
|
+
route: await rt.setAgentRoute(agent, route),
|
|
610
|
+
...chainReceipt(args.route, context, { kind: 'bot', agent }),
|
|
611
|
+
};
|
|
491
612
|
},
|
|
613
|
+
...SESSION_ROUTE_HANDLERS,
|
|
614
|
+
...AGENT_SETTINGS_HANDLERS,
|
|
492
615
|
set_web_search_route: async (rt, args) => ({ route: await rt.setWebSearchRoute(routeInput(args.route)) }),
|
|
493
616
|
set_workflow: (rt, args) => rt.setWorkflow(requireText(args.workflow, 'workflow')),
|
|
494
617
|
set_output_style: async (rt, args) => {
|
|
@@ -597,6 +720,20 @@ const SETUP_ACTION_HANDLERS = {
|
|
|
597
720
|
rt.deleteLocalProviderModel(requireText(args.confirmationToken, 'confirmationToken')),
|
|
598
721
|
set_system_shell: (rt, args) => rt.setSystemShell({ command: clean(args.command) }),
|
|
599
722
|
set_auto_update: (rt, args) => rt.setAutoUpdate(requireBoolean(args.enabled)),
|
|
723
|
+
set_ai_session_titles: (rt, args) => rt.setAiSessionTitles(requireBoolean(args.enabled)),
|
|
724
|
+
set_quota_auto_resume: async (rt, args) => ({
|
|
725
|
+
quotaAutoResume: await rt.setQuotaAutoResume(requireBoolean(args.enabled)),
|
|
726
|
+
}),
|
|
727
|
+
set_model_preferences: async (rt, args) => {
|
|
728
|
+
const change = { model: requireText(args.model, 'model') };
|
|
729
|
+
for (const key of ['hidden', 'favorite'])
|
|
730
|
+
if (Object.hasOwn(args, key)) change[key] = requireBoolean(args[key], key);
|
|
731
|
+
if (Object.keys(change).length === 1) throw new Error('hidden or favorite is required');
|
|
732
|
+
return rt.setModelPreferences(requireText(args.provider, 'provider'), [change]);
|
|
733
|
+
},
|
|
734
|
+
set_heartbeat_enabled: (rt, args) => rt.setHeartbeatEnabled(requireBoolean(args.enabled)),
|
|
735
|
+
set_heartbeat_interval: (rt, args) => rt.setHeartbeatInterval(requireHeartbeatIntervalMinutes(args.minutes)),
|
|
736
|
+
set_reactions_enabled: (rt, args) => rt.setReactionsEnabled(requireBoolean(args.enabled)),
|
|
600
737
|
set_worktree_settings: (rt, args) => rt.setWorktreeSettings(args.worktree),
|
|
601
738
|
forget_provider_auth: async (rt, args) => {
|
|
602
739
|
const name = requireText(args.name, 'name');
|
|
@@ -666,7 +803,7 @@ const SETUP_ACTION_HANDLERS = {
|
|
|
666
803
|
// as Extensions → 커넥터. Nothing is connected here.
|
|
667
804
|
connect_connector: async (rt, args) => {
|
|
668
805
|
const entry = connectorById(requireText(args.connector, 'connector'));
|
|
669
|
-
if (!entry
|
|
806
|
+
if (!entry) throw new Error(`connector must be one of ${CONNECTOR_IDS.join(', ')}`);
|
|
670
807
|
const server = (rt.mcpStatus?.()?.servers || []).find((row) => row.connector === entry.id) || null;
|
|
671
808
|
const connected = server?.connected === true;
|
|
672
809
|
return {
|
|
@@ -703,6 +840,8 @@ const READ_ONLY_SETUP_ACTIONS = new Set([
|
|
|
703
840
|
'search_local_models',
|
|
704
841
|
'inspect_hf_model',
|
|
705
842
|
'local_model_details',
|
|
843
|
+
'read_agent_settings',
|
|
844
|
+
'read_project_connectors',
|
|
706
845
|
]);
|
|
707
846
|
// Actions that start or steer work rather than saving a setting.
|
|
708
847
|
const BACKGROUND_SETUP_ACTIONS = new Set([
|
|
@@ -711,6 +850,10 @@ const BACKGROUND_SETUP_ACTIONS = new Set([
|
|
|
711
850
|
'cancel_local_installation',
|
|
712
851
|
'reconnect_mcp',
|
|
713
852
|
'run_automation',
|
|
853
|
+
'reset_route_fallback',
|
|
854
|
+
'continue_in_model',
|
|
855
|
+
'schedule_quota_resume',
|
|
856
|
+
'cancel_quota_resume',
|
|
714
857
|
]);
|
|
715
858
|
|
|
716
859
|
function setupMutationReceipt(action, result) {
|
|
@@ -735,6 +878,7 @@ export function createSetupToolExecutor({
|
|
|
735
878
|
getSessionId,
|
|
736
879
|
getCallerSession,
|
|
737
880
|
flushSettings,
|
|
881
|
+
executeSessionControl = null,
|
|
738
882
|
}) {
|
|
739
883
|
const desktop = createSetupUiRequests({ notifySessionUi, getSessionId });
|
|
740
884
|
const api = () => {
|
|
@@ -743,11 +887,11 @@ export function createSetupToolExecutor({
|
|
|
743
887
|
return facade;
|
|
744
888
|
};
|
|
745
889
|
|
|
746
|
-
async function readStatus(domain, requestDesktop, detail) {
|
|
890
|
+
async function readStatus(domain, requestDesktop, detail, caller = null) {
|
|
747
891
|
const rt = api();
|
|
748
892
|
if (SETUP_DESKTOP_DOMAINS.includes(domain)) return requestDesktop({ action: 'status', domain });
|
|
749
893
|
if (!Object.hasOwn(SETUP_STATUS_READERS, domain)) throw new Error(`setup: unknown status domain "${domain}"`);
|
|
750
|
-
return SETUP_STATUS_READERS[domain](rt, { domain, detail, getConfig: () => getConfig?.() || {} });
|
|
894
|
+
return SETUP_STATUS_READERS[domain](rt, { domain, detail, caller, getConfig: () => getConfig?.() || {} });
|
|
751
895
|
}
|
|
752
896
|
|
|
753
897
|
function openSurface(target) {
|
|
@@ -776,21 +920,35 @@ export function createSetupToolExecutor({
|
|
|
776
920
|
// it never creates agents, definitions or automations, nor changes any
|
|
777
921
|
// other setting. Hosts without session provenance (no getCallerSession)
|
|
778
922
|
// skip this gate; automation actions still refuse an unknown caller.
|
|
923
|
+
let scope = null;
|
|
779
924
|
if (getCallerSession && !READ_ONLY_SETUP_ACTIONS.has(action)) {
|
|
780
|
-
|
|
925
|
+
scope = scheduleCallerScope(caller);
|
|
781
926
|
assertInteractiveCaller(scope, action);
|
|
782
927
|
// Agent definitions (contacts) change only from Mixy; another agent's
|
|
783
928
|
// home changes only its own agent settings.
|
|
784
929
|
if (AGENT_DEFINITION_ACTIONS.has(action) && args.definitionKind === 'agent') {
|
|
785
930
|
assertAgentEditorAccess(scope, caller, action);
|
|
786
931
|
}
|
|
787
|
-
if (action
|
|
932
|
+
if (OWN_AGENT_ACTIONS.has(action)) assertOwnAgentSettings(scope, args.agent, action);
|
|
788
933
|
}
|
|
934
|
+
// Mixy's heartbeat session takes only its two routine actions, reads included.
|
|
935
|
+
assertHeartbeatSetupAction(sessionId, action, args);
|
|
789
936
|
const rt = action === 'status' || action === 'open' ? null : api();
|
|
790
937
|
if (!Object.hasOwn(SETUP_ACTION_HANDLERS, action)) {
|
|
791
938
|
return executeExtendedSetupAction(rt, args, requestDesktop, { sessionId, caller });
|
|
792
939
|
}
|
|
793
|
-
return SETUP_ACTION_HANDLERS[action](rt, args, {
|
|
940
|
+
return SETUP_ACTION_HANDLERS[action](rt, args, {
|
|
941
|
+
requestDesktop,
|
|
942
|
+
readStatus,
|
|
943
|
+
openSurface,
|
|
944
|
+
sessionId,
|
|
945
|
+
caller,
|
|
946
|
+
// The session-scoped actions authorize each target against it (session-route-actions.mjs).
|
|
947
|
+
scope,
|
|
948
|
+
getSession: getCallerSession,
|
|
949
|
+
getConfig: () => getConfig?.() || {},
|
|
950
|
+
executeSessionControl,
|
|
951
|
+
});
|
|
794
952
|
}
|
|
795
953
|
|
|
796
954
|
return {
|
|
@@ -33,9 +33,16 @@ function compactModelRow(row) {
|
|
|
33
33
|
efforts: (row.effortOptions || []).map((option) => option.value),
|
|
34
34
|
...(row.fastCapable === true ? { fast: true } : {}),
|
|
35
35
|
...(row.supportsVision === true ? { vision: true } : {}),
|
|
36
|
+
...modelPreferenceFields(row),
|
|
36
37
|
};
|
|
37
38
|
}
|
|
38
39
|
|
|
40
|
+
/** The model-management choices, only when set (savedHidden is an explicit /model visibility choice). */
|
|
41
|
+
const modelPreferenceFields = (row) => ({
|
|
42
|
+
...(typeof row.savedHidden === 'boolean' ? { hidden: row.savedHidden } : {}),
|
|
43
|
+
...(row.favorite === true ? { favorite: true } : {}),
|
|
44
|
+
});
|
|
45
|
+
|
|
39
46
|
const isPresent = (value) =>
|
|
40
47
|
value != null && value !== '' && value !== false && !(typeof value === 'object' && !Object.keys(value).length);
|
|
41
48
|
|
|
@@ -64,7 +71,10 @@ function modelDetail(row) {
|
|
|
64
71
|
defaultModelParameters: row.defaultModelParameters,
|
|
65
72
|
supportsMaxMode: row.supportsMaxMode,
|
|
66
73
|
};
|
|
67
|
-
return
|
|
74
|
+
return {
|
|
75
|
+
...Object.fromEntries(Object.entries(detail).filter(([, value]) => isPresent(value))),
|
|
76
|
+
...modelPreferenceFields(row),
|
|
77
|
+
};
|
|
68
78
|
}
|
|
69
79
|
|
|
70
80
|
function findModel(rows, id, provider) {
|
|
@@ -283,6 +293,7 @@ export const EXTENDED_SETUP_HANDLERS = Object.freeze({
|
|
|
283
293
|
if (kind === 'webhook' && ['time', 'at', 'timezone', 'days'].some((key) => own(input, key))) {
|
|
284
294
|
throw new Error('Schedule fields (timing) are not accepted for webhooks');
|
|
285
295
|
}
|
|
296
|
+
if (kind === 'webhook' && own(input, 'newName')) throw new Error('newName (rename) is schedule-only');
|
|
286
297
|
if (kind === 'schedule' && own(input, 'parser')) throw new Error('parser is a webhook-only field');
|
|
287
298
|
let previous = {};
|
|
288
299
|
if (input.overwrite) {
|
|
@@ -363,6 +374,12 @@ export const EXTENDED_SETUP_HANDLERS = Object.freeze({
|
|
|
363
374
|
.sections.flatMap((section) => section.options)
|
|
364
375
|
.find((row) => row.id === args.name);
|
|
365
376
|
if (!option) throw new Error(`Unknown developer option "${args.name}"; read status developer`);
|
|
377
|
+
// An agent must never remove its own approval cards: only the person turns this on.
|
|
378
|
+
if (args.enabled && option.id === 'allowAllActions') {
|
|
379
|
+
throw new Error(
|
|
380
|
+
`"${option.label}" cannot be turned on by an agent; only the person can turn it on in Settings → Developer options.`
|
|
381
|
+
);
|
|
382
|
+
}
|
|
366
383
|
if (args.enabled && option.warning && !args.riskAccepted) {
|
|
367
384
|
throw new Error(
|
|
368
385
|
`Enabling ${option.label} requires riskAccepted:true after the user explicitly accepts: ${option.warning}`
|
|
@@ -401,6 +418,11 @@ export const EXTENDED_SETUP_HANDLERS = Object.freeze({
|
|
|
401
418
|
},
|
|
402
419
|
async set_media_default(rt, args) {
|
|
403
420
|
if (!MEDIA_KINDS.includes(args.kind)) throw new Error(`kind must be one of ${MEDIA_KINDS.join(', ')}`);
|
|
421
|
+
// A blank lane returns the kind to Auto, as the Settings control does.
|
|
422
|
+
if (!String(args.lane).trim()) {
|
|
423
|
+
if (own(args, 'model') || own(args, 'accountId')) throw new Error('model and accountId need a lane');
|
|
424
|
+
return { kind: args.kind, media: await rt.setMediaPin({ kind: args.kind, lane: '' }) };
|
|
425
|
+
}
|
|
404
426
|
const lane = (await rt.listMediaLanes()).find((row) => row.id === args.lane);
|
|
405
427
|
if (!lane) throw new Error(`Unknown media lane "${args.lane}"; list lanes with the media tool`);
|
|
406
428
|
if (!lane.authenticated) throw new Error(`${lane.label} is not signed in; open providers first`);
|
|
@@ -409,7 +431,16 @@ export const EXTENDED_SETUP_HANDLERS = Object.freeze({
|
|
|
409
431
|
if (own(args, 'model') && !spec.models.some((model) => model.id === args.model)) {
|
|
410
432
|
throw new Error(`model "${args.model}" is not available on ${lane.id}/${args.kind}`);
|
|
411
433
|
}
|
|
412
|
-
|
|
434
|
+
if (own(args, 'accountId')) {
|
|
435
|
+
if (lane.authType !== 'oauth') throw new Error(`${lane.id} signs in with an API key; it has no accounts`);
|
|
436
|
+
if (!rt.getProviderAccounts(lane.authProvider).accounts.some((row) => row.id === args.accountId)) {
|
|
437
|
+
throw new Error(
|
|
438
|
+
`Unknown ${lane.authProvider} account "${args.accountId}"; list accounts with status providers`
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
const pin = await rt.setMediaPin({ kind: args.kind, lane: args.lane, model: args.model, account: args.accountId });
|
|
443
|
+
return { kind: args.kind, media: pin };
|
|
413
444
|
},
|
|
414
445
|
});
|
|
415
446
|
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/** Setup actions that act on one running session rather than a setting: its
|
|
2
|
+
* fallback position (read in status model/agents), a return to its primary
|
|
3
|
+
* route, and its quota card's actions. The caller's own session changes
|
|
4
|
+
* through its runtime; another session through the daemon's configure lane
|
|
5
|
+
* (daemon-session-control/route-control.mjs), the lane the model picker and
|
|
6
|
+
* quota card use. */
|
|
7
|
+
import {
|
|
8
|
+
liveRouteFallbackPositions,
|
|
9
|
+
routeFallbackHopped,
|
|
10
|
+
routeFallbackPosition,
|
|
11
|
+
routeLeaf,
|
|
12
|
+
sessionChainSource,
|
|
13
|
+
sessionRoutePrimary,
|
|
14
|
+
} from '../../runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs';
|
|
15
|
+
import { sameRouteModel } from '../../runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs';
|
|
16
|
+
import { resolveSessionMode } from '../../runtime/agent/orchestrator/session/agent-mode.mjs';
|
|
17
|
+
import { agentHomeSessionId } from '../../runtime/agent/orchestrator/session/agent-home.mjs';
|
|
18
|
+
import { _liveSessions } from '../../runtime/agent/orchestrator/session/store/live-state.mjs';
|
|
19
|
+
import { assertOwnAgentSettings } from '../services/schedule-access.mjs';
|
|
20
|
+
import { clean } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
21
|
+
|
|
22
|
+
const modelOf = (route) => ({ provider: route?.provider || '', model: route?.model || '' });
|
|
23
|
+
|
|
24
|
+
/** The calling session's fallback position, and those of the other sessions
|
|
25
|
+
* held here that `keep` selects (status model: Leads; status agents: bots and agents). */
|
|
26
|
+
export function routePositionsStatus({ caller, config, keep }) {
|
|
27
|
+
return {
|
|
28
|
+
...(caller?.agent ? { session: routeFallbackPosition(caller, config) } : {}),
|
|
29
|
+
sessions: liveRouteFallbackPositions(config, (row) => row.sessionId !== caller?.id && keep(row)),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** The route a reset returns `session` to: the one it left at its first hop,
|
|
34
|
+
* else its settings' route when that is still its primary. */
|
|
35
|
+
function primaryRoute(session, config) {
|
|
36
|
+
if (session.routeFallbackPrimary?.provider) return routeLeaf(session.routeFallbackPrimary);
|
|
37
|
+
const primary = sessionRoutePrimary(session);
|
|
38
|
+
const source = sessionChainSource(session, config);
|
|
39
|
+
return source && sameRouteModel(source, primary) ? routeLeaf(source) : routeLeaf(primary);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const actingAgentOf = (session) => resolveSessionMode({ session }).agentId || clean(session?.agent);
|
|
43
|
+
|
|
44
|
+
function createSessionTargets(ctx) {
|
|
45
|
+
const { sessionId: callerId, caller, getSession, scope, executeSessionControl } = ctx;
|
|
46
|
+
const load = (id) => (id === callerId ? caller : getSession?.(id)) || null;
|
|
47
|
+
// A bot's thread acts only on its own sessions; the human's on any.
|
|
48
|
+
const assertTarget = (session, action) => {
|
|
49
|
+
if (scope) assertOwnAgentSettings(scope, actingAgentOf(session), action);
|
|
50
|
+
};
|
|
51
|
+
const target = (id, action, { other = false } = {}) => {
|
|
52
|
+
const sessionId = clean(id) || callerId;
|
|
53
|
+
if (!sessionId) throw new Error('sessionId is required');
|
|
54
|
+
if (other && sessionId === callerId) {
|
|
55
|
+
throw new Error(`${action} applies to another session: this one is running the setup call`);
|
|
56
|
+
}
|
|
57
|
+
const session = load(sessionId);
|
|
58
|
+
if (!session || session.closed === true) throw new Error(`session ${sessionId} not found`);
|
|
59
|
+
assertTarget(session, action);
|
|
60
|
+
return session;
|
|
61
|
+
};
|
|
62
|
+
const control = async (session, method, input) => {
|
|
63
|
+
if (typeof executeSessionControl !== 'function') {
|
|
64
|
+
throw new Error('Another session is reachable only through the Mixdog app or daemon; none hosts this runtime');
|
|
65
|
+
}
|
|
66
|
+
return executeSessionControl(
|
|
67
|
+
{ action: 'route', session_id: session.id, method, ...(input ? { input } : {}) },
|
|
68
|
+
{ callerSessionId: callerId }
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
return { load, target, control, assertTarget };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const SESSION_ROUTE_HANDLERS = {
|
|
75
|
+
async reset_route_fallback(rt, args, ctx) {
|
|
76
|
+
if (Object.hasOwn(args, 'sessionId') && Object.hasOwn(args, 'agent')) {
|
|
77
|
+
throw new Error('Pass sessionId or agent, not both');
|
|
78
|
+
}
|
|
79
|
+
const config = ctx.getConfig();
|
|
80
|
+
const sessions = createSessionTargets(ctx);
|
|
81
|
+
let targets;
|
|
82
|
+
if (Object.hasOwn(args, 'agent')) {
|
|
83
|
+
const agent = clean(args.agent);
|
|
84
|
+
if (!agent) throw new Error('agent is required');
|
|
85
|
+
if (ctx.scope) assertOwnAgentSettings(ctx.scope, agent, 'reset_route_fallback');
|
|
86
|
+
// Its chats held here (home, room seats) and its home thread from disk.
|
|
87
|
+
const byId = new Map();
|
|
88
|
+
for (const session of _liveSessions.values()) {
|
|
89
|
+
if (session?.id && session.closed !== true && resolveSessionMode({ session }).agentId === agent) {
|
|
90
|
+
byId.set(session.id, session);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const home = agentHomeSessionId(agent);
|
|
94
|
+
if (home && !byId.has(home)) {
|
|
95
|
+
const stored = sessions.load(home);
|
|
96
|
+
if (stored && stored.closed !== true) byId.set(home, stored);
|
|
97
|
+
}
|
|
98
|
+
targets = [...byId.values()];
|
|
99
|
+
} else {
|
|
100
|
+
targets = [sessions.target(args.sessionId, 'reset_route_fallback')];
|
|
101
|
+
}
|
|
102
|
+
const reset = [];
|
|
103
|
+
const unchanged = [];
|
|
104
|
+
for (const session of targets) {
|
|
105
|
+
if (!routeFallbackHopped(session)) {
|
|
106
|
+
unchanged.push({ sessionId: session.id, current: modelOf(session) });
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const route = primaryRoute(session, config);
|
|
110
|
+
// The session's own model pick, from its next turn: the switch restarts
|
|
111
|
+
// its chain (fallback index and failures cleared).
|
|
112
|
+
if (session.id === ctx.sessionId) {
|
|
113
|
+
await rt.setRoute(route, { sessionOnly: true, switchEstablished: true, deferUntilNextTurn: true });
|
|
114
|
+
} else {
|
|
115
|
+
await sessions.control(session, 'setRoute', route);
|
|
116
|
+
}
|
|
117
|
+
reset.push({ sessionId: session.id, from: modelOf(session), to: modelOf(route) });
|
|
118
|
+
}
|
|
119
|
+
return { scope: 'session', reset, ...(unchanged.length ? { alreadyOnPrimary: unchanged } : {}) };
|
|
120
|
+
},
|
|
121
|
+
async continue_in_model(_rt, args, ctx) {
|
|
122
|
+
const sessions = createSessionTargets(ctx);
|
|
123
|
+
const session = sessions.target(args.sessionId, 'continue_in_model', { other: true });
|
|
124
|
+
const route = routeLeaf(args.route);
|
|
125
|
+
const continued = (await sessions.control(session, 'continueSessionInModel', route)) !== false;
|
|
126
|
+
return {
|
|
127
|
+
scope: 'session',
|
|
128
|
+
sessionId: session.id,
|
|
129
|
+
continued,
|
|
130
|
+
route: modelOf(route),
|
|
131
|
+
note: 'The stopped turn is not resent: the user resumes it from that conversation (Resume, or a new message).',
|
|
132
|
+
};
|
|
133
|
+
},
|
|
134
|
+
async schedule_quota_resume(_rt, args, ctx) {
|
|
135
|
+
const sessions = createSessionTargets(ctx);
|
|
136
|
+
const session = sessions.target(args.sessionId, 'schedule_quota_resume', { other: true });
|
|
137
|
+
return {
|
|
138
|
+
scope: 'session',
|
|
139
|
+
sessionId: session.id,
|
|
140
|
+
scheduled: (await sessions.control(session, 'scheduleQuotaResume')) === true,
|
|
141
|
+
};
|
|
142
|
+
},
|
|
143
|
+
async cancel_quota_resume(_rt, args, ctx) {
|
|
144
|
+
const sessions = createSessionTargets(ctx);
|
|
145
|
+
const session = sessions.target(args.sessionId, 'cancel_quota_resume', { other: true });
|
|
146
|
+
return {
|
|
147
|
+
scope: 'session',
|
|
148
|
+
sessionId: session.id,
|
|
149
|
+
cancelled: (await sessions.control(session, 'cancelQuotaResume')) === true,
|
|
150
|
+
};
|
|
151
|
+
},
|
|
152
|
+
};
|