mixdog 1.3.5 → 1.4.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/NOTICE.md +2 -2
- package/README.md +2 -2
- package/package.json +2 -11
- package/scripts/check-voice-runtime-inputs.mjs +25 -0
- package/scripts/daemon-stub.mjs +1 -1
- package/scripts/gate-local.mjs +16 -5
- package/scripts/latest-guard.mjs +21 -9
- package/scripts/lib/isolated-test-env.mjs +10 -5
- package/scripts/lib/run-node-tests.mjs +37 -37
- package/scripts/lib/scoped-temp.d.mts +16 -0
- package/scripts/lib/scoped-temp.mjs +123 -0
- package/scripts/lib/stale-temp.mjs +44 -0
- package/scripts/native-release-status.mjs +2 -2
- package/scripts/post-release-check.mjs +1 -6
- package/scripts/pptx-kit-index.mjs +17 -4
- package/scripts/recall-history-cases.json +1 -1
- package/scripts/suite-health.mjs +20 -2
- package/scripts/test-data-dir.mjs +10 -7
- package/scripts/test.mjs +7 -11
- package/src/agents/reviewer/AGENT.md +7 -11
- package/src/agents/reviewer/agent.json +1 -1
- package/src/app.mjs +4 -0
- package/src/defaults/shipped-history.json +22 -1
- package/src/defaults/skills/browser-use/SKILL.md +62 -12
- 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 +35 -9
- package/src/defaults/skills/setup/SKILL.md +22 -0
- package/src/defaults/skills/setup/references/actions.md +39 -5
- package/src/defaults/skills/setup/references/surfaces.md +11 -2
- package/src/defaults/skills/visualize/SKILL.md +2 -1
- package/src/lib/rules-builder.cjs +39 -20
- package/src/output-styles/common.md +2 -2
- package/src/output-styles/simple.md +1 -1
- package/src/rules/agent/AGENT.md +11 -10
- package/src/rules/lead/LEAD.md +23 -20
- package/src/rules/shared/05-tool-calls.md +5 -6
- package/src/rules/shared/10-tool-workflow.md +4 -0
- package/src/rules/shared/45-destructive.md +0 -2
- package/src/rules/shared/50-execution.md +2 -0
- package/src/rules/shared/60-verification.md +7 -5
- package/src/rules/shared/70-delivery.md +7 -9
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -6
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
- 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/cache-break-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/config.mjs +17 -1
- package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +73 -68
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +57 -2
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +176 -72
- package/src/runtime/agent/orchestrator/mcp/client.mjs +19 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +192 -133
- package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +42 -6
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +7 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -2
- 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-request/initial-status.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +159 -69
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +70 -33
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +123 -102
- package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +1 -10
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +25 -13
- package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/devin.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +210 -20
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -11
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +45 -6
- package/src/runtime/agent/orchestrator/providers/lib/first-output-window.mjs +58 -0
- package/src/runtime/agent/orchestrator/providers/lib/listen-on.mjs +14 -0
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +17 -3
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -10
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +1 -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 +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +14 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +4 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +5 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +13 -3
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +13 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +81 -42
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +136 -5
- 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/openai-ws-stream/event-switch.mjs +20 -12
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +48 -22
- 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 +38 -0
- 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/runtime-core/ask-user-tool-defs.mjs +49 -16
- 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 +7 -6
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +9 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +3 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +1 -3
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +798 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -8
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +103 -23
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +280 -45
- 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/context-utils.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +163 -22
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +132 -17
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +38 -7
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +90 -22
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +0 -2
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +51 -25
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +37 -3
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +31 -3
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +20 -3
- 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 +5 -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 +49 -21
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +12 -3
- 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-execute.mjs +133 -90
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +3 -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 +24 -14
- 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 +130 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +27 -9
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +81 -8
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +27 -8
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +12 -5
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +9 -4
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +21 -5
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +24 -9
- package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
- package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +150 -0
- package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +36 -9
- 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-delete.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/store/session-persistence-events.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +8 -6
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +81 -22
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +92 -3
- package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
- 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/transcript-restore/restore.mjs +79 -3
- 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/stall-policy.mjs +23 -0
- 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/invocation-plan.mjs +2 -2
- 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/spawn-env.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +31 -6
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +110 -26
- package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +31 -5
- package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +22 -8
- package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +6 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +23 -12
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +1 -8
- package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/federation.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/isolated-test-env.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +26 -4
- 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/scheduler.mjs +33 -147
- package/src/runtime/channels/lib/schedules-db.mjs +34 -11
- package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
- package/src/runtime/channels/lib/tool-dispatch.mjs +1 -2
- package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
- package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
- package/src/runtime/channels/lib/whisper-port.mjs +10 -1
- 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 +10 -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 +28 -2
- package/src/runtime/computer-bridge/linux-action-capabilities.mjs +24 -5
- package/src/runtime/computer-bridge/linux-readiness.d.mts +7 -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/local-provider/server-process.mjs +2 -1
- package/src/runtime/media/adapters/gemini-video.mjs +4 -1
- package/src/runtime/media/adapters/xai-media.mjs +2 -1
- package/src/runtime/memory/lib/embedding-worker.mjs +6 -3
- package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +1 -7
- package/src/runtime/memory/lib/memory-chunk-quality.mjs +1 -6
- 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/authoring/pdf-author-action.mjs +1 -6
- package/src/runtime/office/design/design-art-direction.mjs +29 -27
- package/src/runtime/office/pdf/pdf-writer.mjs +6 -1
- package/src/runtime/office/portable/portable-snapshot-docx.mjs +7 -1
- package/src/runtime/office/portable/portable-snapshot-shared.mjs +6 -1
- package/src/runtime/office/quality/assurance-rendered.mjs +9 -2
- package/src/runtime/office/quality/assurance-structure-docx.mjs +3 -1
- package/src/runtime/office/quality/design-review.mjs +1 -5
- package/src/runtime/office/quality/document-brief.mjs +1 -5
- package/src/runtime/office/quality/forced-break-pages.mjs +9 -6
- package/src/runtime/office/quality/quality-pipeline.mjs +1 -1
- 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-owned-work.mjs +56 -0
- package/src/runtime/shared/bounded-download.mjs +8 -3
- package/src/runtime/shared/config.mjs +2 -13
- package/src/runtime/shared/connector-accounts.mjs +20 -10
- package/src/runtime/shared/connector-catalog.d.mts +29 -0
- package/src/runtime/shared/connector-catalog.mjs +150 -0
- package/src/runtime/shared/connector-triggers.mjs +22 -19
- package/src/runtime/shared/defaults-separation.mjs +2 -17
- package/src/runtime/shared/delegated-approval-host.mjs +103 -11
- package/src/runtime/shared/err-text.mjs +24 -15
- package/src/runtime/shared/fetch-safe-listen.d.mts +16 -0
- package/src/runtime/shared/fetch-safe-listen.mjs +50 -0
- 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/handoff-artifacts.d.mts +2 -1
- package/src/runtime/shared/handoff-artifacts.mjs +18 -8
- 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 +126 -0
- package/src/runtime/shared/llm/cost.mjs +5 -1
- package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
- package/src/runtime/shared/loopback-listener.mjs +25 -2
- package/src/runtime/shared/mixy-presence.mjs +22 -0
- package/src/runtime/shared/model-route-chain.d.mts +7 -2
- package/src/runtime/shared/model-route-chain.mjs +22 -4
- package/src/runtime/shared/open-url.mjs +10 -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 +7 -1
- 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 +10 -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 +48 -1
- package/src/runtime/shared/session-scratch.mjs +37 -0
- 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-card-model/agent-surface.mjs +1 -3
- package/src/runtime/shared/tool-card-model/card-status.mjs +15 -2
- package/src/runtime/shared/tool-result-summary.mjs +2 -15
- package/src/runtime/shared/tool-surface.mjs +3 -0
- package/src/runtime/shared/tool-work-units.mjs +2 -0
- package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
- package/src/runtime/shared/worktrees/contract.mjs +4 -1
- package/src/runtime/shared/worktrees/git.mjs +15 -0
- package/src/runtime/shared/worktrees/manager.mjs +87 -38
- package/src/runtime/shared/worktrees/test-support.mjs +14 -13
- package/src/runtime/terminal-bridge/client.mjs +10 -1
- package/src/runtime/visualize-bridge/client.mjs +29 -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 +489 -185
- package/src/session-runtime/agent-task-sessions.mjs +467 -229
- package/src/session-runtime/agent-tool-routing.mjs +8 -41
- package/src/session-runtime/boot/apis.mjs +9 -0
- 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 +11 -2
- package/src/session-runtime/bot-status.mjs +12 -6
- package/src/session-runtime/bot-target.mjs +38 -0
- package/src/session-runtime/channel-config-api.mjs +6 -1
- package/src/session-runtime/config-lifecycle.mjs +6 -0
- package/src/session-runtime/connector-merge-migration.mjs +305 -0
- package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
- package/src/session-runtime/conversation-import/discovery.mjs +271 -25
- package/src/session-runtime/conversation-import/service.mjs +26 -5
- package/src/session-runtime/handoff-attachments.mjs +82 -31
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +144 -41
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -0
- package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +8 -2
- package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
- package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
- package/src/session-runtime/lifecycle/session-catalog.mjs +12 -2
- 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 +55 -3
- package/src/session-runtime/mcp-oauth-login.mjs +5 -3
- package/src/session-runtime/mixy-heartbeat.mjs +153 -33
- package/src/session-runtime/model-route/set-route.mjs +11 -2
- 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 +2 -1
- package/src/session-runtime/prewarm/channel-start.mjs +3 -7
- package/src/session-runtime/provider-catalog-cache.mjs +82 -36
- package/src/session-runtime/provider-models/catalog-load.mjs +23 -6
- package/src/session-runtime/provider-models.mjs +4 -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/resource-recall-api.mjs +6 -1
- package/src/session-runtime/routine-owner.mjs +40 -9
- package/src/session-runtime/runtime-feature-gates.mjs +5 -1
- package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
- package/src/session-runtime/services/agent-tool/execute.mjs +14 -9
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +20 -4
- package/src/session-runtime/services/agent-tool/model-select.mjs +48 -7
- package/src/session-runtime/services/agent-tool/render.mjs +71 -17
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +13 -4
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
- package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
- 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 +7 -13
- package/src/session-runtime/services/channel-session-router.mjs +4 -2
- package/src/session-runtime/services/provider-admin.mjs +2 -1
- package/src/session-runtime/services/seeds.mjs +0 -28
- package/src/session-runtime/session-compaction-sync.mjs +27 -0
- package/src/session-runtime/session-create/session-options.mjs +1 -0
- 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 +13 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
- package/src/session-runtime/setup-tool/executor.mjs +145 -22
- package/src/session-runtime/setup-tool/extended-actions.mjs +8 -3
- package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +4 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +64 -5
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
- package/src/session-runtime/tool-policy/policy-stage.mjs +17 -2
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +15 -4
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
- package/src/session-runtime/workspace/transitions.mjs +25 -0
- package/src/session-runtime/workspace/worktree-tool.mjs +26 -9
- 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 +142 -190
- package/src/standalone/daemon.mjs +26 -3
- package/src/standalone/session-client.mjs +7 -3
- package/src/standalone/session-protocol.mjs +5 -0
- package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
- 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 +30 -2
- package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
- package/src/standalone/session-tool-output.mjs +15 -7
- package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
- package/src/tui/app/app-view/floating-panel.jsx +7 -4
- package/src/tui/app/model-options.mjs +3 -28
- package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +1 -3
- package/src/tui/app/model-picker/route-selection.mjs +5 -6
- package/src/tui/app/provider-setup/oauth-actions.mjs +38 -20
- package/src/tui/app/provider-setup/provider-items.mjs +8 -2
- package/src/tui/app/provider-setup-picker.mjs +9 -5
- package/src/tui/components/QuestionPanel.jsx +13 -4
- package/src/tui/dist/index.mjs +133 -92
- 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 +7 -1
- package/src/tui/session/queue-helpers.mjs +3 -42
- 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 +17 -1
- 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 +16 -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 +19 -2
- package/src/tui/session/turn.mjs +1 -0
- package/src/ui/statusline-agents.mjs +1 -3
- 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
|
@@ -5,55 +5,22 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { clean } from '../runtime/shared/clean.mjs';
|
|
8
|
-
|
|
9
|
-
const lower = (value) => clean(value).toLowerCase();
|
|
10
|
-
|
|
11
|
-
// A pinned model named by its catalog display name ("GPT-6.1-Sol") is not a
|
|
12
|
-
// wire id. Canonicalize it only on an unambiguous EXACT match: the id itself,
|
|
13
|
-
// or a display name / label, case-insensitively, within the requested provider
|
|
14
|
-
// (or across providers when none is given and exactly one row matches).
|
|
15
|
-
// Anything else — no match, several matches, an empty or partial catalog —
|
|
16
|
-
// returns the args unchanged: the catalog never refuses a model and never
|
|
17
|
-
// substitutes a near one.
|
|
18
|
-
export function canonicalizePinnedModel(args, rows) {
|
|
19
|
-
const model = clean(args?.model);
|
|
20
|
-
if (!model || !Array.isArray(rows)) return args;
|
|
21
|
-
const provider = lower(args.provider);
|
|
22
|
-
const pool = rows.filter((row) => row && (!provider || lower(row.provider) === provider));
|
|
23
|
-
const wanted = model.toLowerCase();
|
|
24
|
-
const exactId = pool.filter((row) => row.id === model);
|
|
25
|
-
// A partial catalog may lack the real id a display name collides with, so
|
|
26
|
-
// only an exact id can pass there; aliases wait for a complete catalog.
|
|
27
|
-
const partial = pool.some((row) => row.catalogPartial === true);
|
|
28
|
-
const hits = exactId.length
|
|
29
|
-
? exactId
|
|
30
|
-
: partial
|
|
31
|
-
? []
|
|
32
|
-
: pool.filter((row) => lower(row.id) === wanted || lower(row.display) === wanted || lower(row.label) === wanted);
|
|
33
|
-
const distinct = [...new Map(hits.map((row) => [`${row.provider}\n${row.id}`, row])).values()];
|
|
34
|
-
if (distinct.length !== 1) return args;
|
|
35
|
-
const [hit] = distinct;
|
|
36
|
-
if (hit.id === model && hit.provider === args.provider) return args;
|
|
37
|
-
return { ...args, provider: hit.provider, model: hit.id };
|
|
38
|
-
}
|
|
8
|
+
import { resolveRequestedModel } from './services/agent-tool/model-select.mjs';
|
|
39
9
|
|
|
40
10
|
// `listProviderModels` is this runtime's provider catalog. The agent control
|
|
41
11
|
// behind `executeAgentControl` (the daemon's canonical agent) has none, so a
|
|
42
|
-
//
|
|
43
|
-
//
|
|
12
|
+
// pinned model is resolved here, by the same rule the in-process agent tool
|
|
13
|
+
// applies (exact id, display name, then every query word; ambiguous or
|
|
14
|
+
// unknown names fail with candidates), and forwarded as the exact route.
|
|
44
15
|
export function createRoutedAgentTool({ rt, agentTool, executeAgentControl = null, listProviderModels = null }) {
|
|
45
16
|
const routedAgentTool = {
|
|
46
17
|
...agentTool,
|
|
47
18
|
async execute(args, context = {}) {
|
|
48
19
|
if (typeof executeAgentControl !== 'function') return agentTool.execute(args, context);
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
} catch {
|
|
54
|
-
routedArgs = args;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
20
|
+
const routedArgs =
|
|
21
|
+
typeof listProviderModels === 'function' && clean(args?.model) && (clean(args.type) || 'spawn') === 'spawn'
|
|
22
|
+
? await resolveRequestedModel(args, listProviderModels)
|
|
23
|
+
: args;
|
|
57
24
|
return executeAgentControl(routedArgs, context);
|
|
58
25
|
},
|
|
59
26
|
closeAll(reason, scope = {}) {
|
|
@@ -107,8 +107,17 @@ export function wireApis(boot) {
|
|
|
107
107
|
try {
|
|
108
108
|
boot.resourceApi.migratePluginMcpCopies();
|
|
109
109
|
} catch (error) {
|
|
110
|
+
console.warn(`[mcp] adopting plugin MCP copies failed: ${error?.message || error}`);
|
|
110
111
|
bootProfile('plugin-mcp:adopt-failed', { error: error?.message || String(error) });
|
|
111
112
|
}
|
|
113
|
+
// One server per multi-account connector: `gmail`, `gmail-2`… merge into
|
|
114
|
+
// `gmail` holding the accounts (their sign-ins and app passwords stay).
|
|
115
|
+
try {
|
|
116
|
+
boot.resourceApi.migrateConnectorAccounts();
|
|
117
|
+
} catch (error) {
|
|
118
|
+
console.warn(`[connectors] merging connector accounts failed: ${error?.message || error}`);
|
|
119
|
+
bootProfile('connector-accounts:merge-failed', { error: error?.message || String(error) });
|
|
120
|
+
}
|
|
112
121
|
}
|
|
113
122
|
boot.disposeGlobalExtensionSubscription = () => {
|
|
114
123
|
boot.disposeConfigSync?.();
|
|
@@ -20,6 +20,7 @@ import { listProjectsStrict } from '../../runtime/shared/projects.mjs';
|
|
|
20
20
|
import { isWithin } from '../../runtime/shared/worktrees/paths.mjs';
|
|
21
21
|
import { standaloneDataDir } from '../runtime-paths.mjs';
|
|
22
22
|
import { SessionAddressError, isAdmissionOpen, ownerLifecycle } from '../session-address.mjs';
|
|
23
|
+
import { syncSessionCompaction, usesInjectedConfig } from '../session-compaction-sync.mjs';
|
|
23
24
|
import { dataDirOf } from './shared.mjs';
|
|
24
25
|
|
|
25
26
|
export function wireInfrastructure(boot) {
|
|
@@ -187,6 +188,9 @@ export function sessionAdopter(boot) {
|
|
|
187
188
|
}
|
|
188
189
|
}
|
|
189
190
|
rt.session = v;
|
|
191
|
+
// A resumed or swapped-in session keeps the compaction it was saved with
|
|
192
|
+
// unless it follows the current global settings (not on an injected config).
|
|
193
|
+
if (v?.id && !usesInjectedConfig(boot.params)) syncSessionCompaction(v, rt.config);
|
|
190
194
|
// The PreToolUse/PostToolUse bridge is a non-enumerable property that
|
|
191
195
|
// neither the store nor a resumed record carries: every session installed
|
|
192
196
|
// here (create, resume, route swap, clear, the manager's copy) gets it, so
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
} from '../model-recency.mjs';
|
|
32
32
|
import { createNativeWebSearch } from '../native-web-search.mjs';
|
|
33
33
|
import { createConfigLifecycle } from '../config-lifecycle.mjs';
|
|
34
|
+
import { usesInjectedConfig } from '../session-compaction-sync.mjs';
|
|
34
35
|
import { createQuickModelRows } from '../quick-model-rows.mjs';
|
|
35
36
|
import { createProviderModels } from '../provider-models.mjs';
|
|
36
37
|
import { createProviderUsage } from '../provider-usage.mjs';
|
|
@@ -66,6 +67,8 @@ function wireConfigLifecycle(boot) {
|
|
|
66
67
|
rt.configHasSecrets = next;
|
|
67
68
|
},
|
|
68
69
|
getRoute: () => rt.route,
|
|
70
|
+
getSession: () => rt.session,
|
|
71
|
+
fixedSessionCompaction: usesInjectedConfig(boot.params),
|
|
69
72
|
setRouteState: (next) => {
|
|
70
73
|
rt.route = next;
|
|
71
74
|
},
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
channelNotificationSessionId,
|
|
10
10
|
} from '../../runtime/shared/channel-notification-routing.mjs';
|
|
11
11
|
import { CHANNEL_NOTIFICATION_METHOD } from '../services/channel-session-router.mjs';
|
|
12
|
+
import { PROMPT_ORIGIN_CHANNEL } from '../../runtime/agent/orchestrator/session/manager/pending-message-entry.mjs';
|
|
12
13
|
import { envFlag } from '../../runtime/shared/env.mjs';
|
|
13
14
|
// Desktop-app bridges: tiny fs/fetch clients, so a static import adds no
|
|
14
15
|
// meaningful boot cost. The tools themselves are gated per session by the
|
|
@@ -21,7 +22,10 @@ import { TOOL_DEFS as OFFICE_TOOL_DEFS } from '../../runtime/office/tool-defs.mj
|
|
|
21
22
|
import { TOOL_DEFS as MEDIA_TOOL_DEFS } from '../../runtime/media/tool-defs.mjs';
|
|
22
23
|
import { TOOL_DEFS as TIDY_TOOL_DEFS } from '../../runtime/tidy/tool-defs.mjs';
|
|
23
24
|
import { TOOL_DEFS as VISUALIZE_BRIDGE_TOOL_DEFS } from '../../runtime/visualize-bridge/tool-defs.mjs';
|
|
24
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
ASK_USER_TOOL_DEFS,
|
|
27
|
+
HANDOFF_USER_TOOL_DEFS,
|
|
28
|
+
} from '../../runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs';
|
|
25
29
|
import { REACTION_TOOL_DEFS } from '../../runtime/agent/orchestrator/runtime-core/reaction-tool-defs.mjs';
|
|
26
30
|
import { SETUP_TOOL_DEFS } from '../setup-tool/tool-defs.mjs';
|
|
27
31
|
import { createSetupToolExecutor } from '../setup-tool/executor.mjs';
|
|
@@ -144,7 +148,9 @@ function wireChannels(boot) {
|
|
|
144
148
|
const meta = p.meta && typeof p.meta === 'object' ? p.meta : {};
|
|
145
149
|
const content = channelNotificationModelContent(p);
|
|
146
150
|
if (!content) return;
|
|
147
|
-
notifySession(channelNotificationSessionId(rt.session, rt.reservedSessionId), content, meta
|
|
151
|
+
notifySession(channelNotificationSessionId(rt.session, rt.reservedSessionId), content, meta, {
|
|
152
|
+
origin: PROMPT_ORIGIN_CHANNEL,
|
|
153
|
+
});
|
|
148
154
|
},
|
|
149
155
|
});
|
|
150
156
|
bootProfile('channels:worker-ready', { ms: (performance.now() - channelsStartedAt).toFixed(1) });
|
|
@@ -168,6 +174,7 @@ function wireToolSurface(boot) {
|
|
|
168
174
|
visualizeToolDefs: VISUALIZE_BRIDGE_TOOL_DEFS,
|
|
169
175
|
setupToolDefs: SETUP_TOOL_DEFS,
|
|
170
176
|
askUserToolDefs: ASK_USER_TOOL_DEFS,
|
|
177
|
+
handoffUserToolDefs: HANDOFF_USER_TOOL_DEFS,
|
|
171
178
|
reactionToolDefs: REACTION_TOOL_DEFS,
|
|
172
179
|
goalTools: goalRuntime.tools,
|
|
173
180
|
agentTools: agentTool.tools,
|
|
@@ -234,6 +241,8 @@ function wireInternalTools(boot) {
|
|
|
234
241
|
getCallerSession: (sessionId) =>
|
|
235
242
|
sessionId === rt.session?.id ? rt.session : boot.mgr?.getSession?.(sessionId) || null,
|
|
236
243
|
flushSettings: () => boot.flushAllConfigSavesAsync({ requireSaved: true }),
|
|
244
|
+
// Another session's route and quota actions (daemon-session-control.mjs); null without a daemon.
|
|
245
|
+
executeSessionControl: boot.params.executeSessionControl || null,
|
|
237
246
|
});
|
|
238
247
|
const disposeInternalTools = internalTools.setInternalToolsProvider({
|
|
239
248
|
scopeId: rt.mcpScopeId,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `session bots`: the state of the user's bots, read on demand (never injected
|
|
3
3
|
* into a turn). One line per bot: its home chat (`sess_home_<id>`), the last
|
|
4
|
-
* activity there and its latest line, whether it works now (its chat, or
|
|
5
|
-
*
|
|
4
|
+
* activity there and its latest line, whether it works now (its chat, or work
|
|
5
|
+
* it sent running in a task session; a turn the user typed there is the
|
|
6
|
+
* user's), approvals waiting on the user, its routines and what
|
|
6
7
|
* needs attention. With one bot (`session_id`: its id or chat id): its
|
|
7
8
|
* routines, its held requests and its recent sessions.
|
|
8
9
|
*
|
|
@@ -143,7 +144,7 @@ function span(ms) {
|
|
|
143
144
|
const ago = (at, now) => `${span(now - at)} ago`;
|
|
144
145
|
const until = (at, now) => (at <= now ? 'due now' : `in ${span(at - now)}`);
|
|
145
146
|
|
|
146
|
-
async function defaultListBots() {
|
|
147
|
+
export async function defaultListBots() {
|
|
147
148
|
const [{ workflowHelpers }, { getPluginData, loadConfig }, { isAgentDisabled, isContactAgentId }] = await Promise.all(
|
|
148
149
|
[
|
|
149
150
|
import('./boot/shared.mjs'),
|
|
@@ -264,7 +265,12 @@ export function createBotStatus({
|
|
|
264
265
|
const homeId = agentHomeSessionId(bot.id);
|
|
265
266
|
const owned = ctx.owned.get(bot.id) || [];
|
|
266
267
|
const home = ctx.rows.get(homeId) || null;
|
|
267
|
-
//
|
|
268
|
+
// Work this bot sent that is running now: a session working with the bot's
|
|
269
|
+
// send in flight (`handedBy`, bot-owned-work.mjs). A turn the user typed
|
|
270
|
+
// in the bot's task session is the user's, not the bot working.
|
|
271
|
+
const sentWork = (row) => isWorking(row) && row.handedBy?.includes(bot.id) === true;
|
|
272
|
+
// Running task sessions: a turn whose report is still owed, or the bot's
|
|
273
|
+
// work running now.
|
|
268
274
|
const tasks = new Map();
|
|
269
275
|
const addTask = (id, title, at) => {
|
|
270
276
|
const known = tasks.get(id);
|
|
@@ -276,7 +282,7 @@ export function createBotStatus({
|
|
|
276
282
|
addTask(watch.taskSessionId, watch.title, Number(watch.at) || 0);
|
|
277
283
|
}
|
|
278
284
|
for (const row of owned) {
|
|
279
|
-
if (row.id === homeId || roomMemberOfSession(row.id) || !
|
|
285
|
+
if (row.id === homeId || roomMemberOfSession(row.id) || !sentWork(row)) continue;
|
|
280
286
|
addTask(row.id, row.title, Number(row.createdAt) || 0);
|
|
281
287
|
}
|
|
282
288
|
const running = [...tasks.values()].sort((left, right) => left.at - right.at || (left.id < right.id ? -1 : 1));
|
|
@@ -302,7 +308,7 @@ export function createBotStatus({
|
|
|
302
308
|
approvals,
|
|
303
309
|
routines,
|
|
304
310
|
flags,
|
|
305
|
-
working: isWorking(home) || running.some((task) =>
|
|
311
|
+
working: isWorking(home) || running.some((task) => sentWork(ctx.rows.get(task.id))),
|
|
306
312
|
lastAt: activityOf(home),
|
|
307
313
|
};
|
|
308
314
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// A bot id as the `session_id` of read, send and status: a bot's chat is a
|
|
2
|
+
// session of its own (`sess_home_<id>`), but the schema also lets a model name
|
|
3
|
+
// the bot (`bots` takes either), so the id resolves to that home chat — before
|
|
4
|
+
// any check of the target, so the bot-chain, hop and task-origin checks see
|
|
5
|
+
// the chat they would for `sess_home_<id>`. A minted session id always has an
|
|
6
|
+
// underscore, a normalized bot id never does (agent-home.mjs), so only ids
|
|
7
|
+
// shaped like a bot id are looked up.
|
|
8
|
+
import { MIXY_AGENT_ID, agentHomeSessionId } from '../runtime/agent/orchestrator/session/agent-home.mjs';
|
|
9
|
+
import { defaultListBots, quotedText } from './bot-status.mjs';
|
|
10
|
+
|
|
11
|
+
const MAX_NAMED_BOTS = 30;
|
|
12
|
+
/** The actions whose `session_id` may be a bot id. */
|
|
13
|
+
export const BOT_TARGET_ACTIONS = new Set(['read', 'send', 'status']);
|
|
14
|
+
|
|
15
|
+
/** The ids of the bots a send can reach: Mixy and every contact agent. */
|
|
16
|
+
async function botIds(listBots) {
|
|
17
|
+
return [MIXY_AGENT_ID, ...(await listBots()).map((bot) => bot.id)];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** `target`'s home chat when it is a known bot id, else `target` unchanged. */
|
|
21
|
+
export async function resolveBotTarget(target, listBots = defaultListBots) {
|
|
22
|
+
const home = agentHomeSessionId(target);
|
|
23
|
+
return home && (await botIds(listBots)).includes(target) ? home : target;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Whether `target` is shaped like a bot id (so, with no session, a mistyped one). */
|
|
27
|
+
export const isBotShaped = (target) => agentHomeSessionId(target) !== '';
|
|
28
|
+
|
|
29
|
+
/** The error for a bot-shaped `target` that is neither a known bot nor a session. */
|
|
30
|
+
export async function unknownBotError(target, listBots = defaultListBots, cause) {
|
|
31
|
+
const ids = await botIds(listBots);
|
|
32
|
+
const named = ids.slice(0, MAX_NAMED_BOTS).join(', ');
|
|
33
|
+
const more = ids.length > MAX_NAMED_BOTS ? `, … (${ids.length - MAX_NAMED_BOTS} more)` : '';
|
|
34
|
+
return new Error(
|
|
35
|
+
`session: "${quotedText(target, 64)}" is neither a session nor a known bot id; bot ids: ${named}${more}; session action=list finds session ids`,
|
|
36
|
+
cause ? { cause } : undefined
|
|
37
|
+
);
|
|
38
|
+
}
|
|
@@ -12,7 +12,12 @@ import {
|
|
|
12
12
|
testWebhook,
|
|
13
13
|
withScheduleRenameReserved,
|
|
14
14
|
} from './services/channel-admin.mjs';
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
getSchedule,
|
|
17
|
+
markScheduleFailure,
|
|
18
|
+
markScheduleSkipped,
|
|
19
|
+
markScheduleSuccess,
|
|
20
|
+
} from '../runtime/channels/lib/schedules-db.mjs';
|
|
16
21
|
import { scheduleRenameUncertainError } from '../runtime/channels/lib/schedule-errors.mjs';
|
|
17
22
|
import { loadEndpointConfig, readEndpointLastPayload } from '../runtime/channels/lib/webhooks-db.mjs';
|
|
18
23
|
import { webhookEventSummary, webhookRunPrompt } from '../runtime/channels/lib/webhook/session-dispatch.mjs';
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
stripStoredRouteDefaults,
|
|
18
18
|
withDefaultPresets,
|
|
19
19
|
} from '../runtime/agent/orchestrator/config-presets.mjs';
|
|
20
|
+
import { syncSessionCompaction } from './session-compaction-sync.mjs';
|
|
20
21
|
import { createConfigWriters } from './config-lifecycle/config-writers.mjs';
|
|
21
22
|
import { createLeadRouteSync } from './config-lifecycle/lead-route-sync.mjs';
|
|
22
23
|
import { createOutputStyleStatusCache } from './config-lifecycle/output-style-cache.mjs';
|
|
@@ -134,6 +135,10 @@ export function createConfigLifecycle({
|
|
|
134
135
|
getConfigHasSecrets,
|
|
135
136
|
setConfigHasSecrets,
|
|
136
137
|
getRoute,
|
|
138
|
+
// The live session follows the reloaded global compaction settings, unless
|
|
139
|
+
// the runtime runs on an injected (headless) config.
|
|
140
|
+
getSession,
|
|
141
|
+
fixedSessionCompaction = false,
|
|
137
142
|
// Main route sync on reload (both optional: a lifecycle without them never syncs)
|
|
138
143
|
setRouteState,
|
|
139
144
|
resolveRoute,
|
|
@@ -222,6 +227,7 @@ export function createConfigLifecycle({
|
|
|
222
227
|
const adopted = adoptConfig(next, { hasSecrets: true });
|
|
223
228
|
configSaveBaseline = structuredClone(adopted);
|
|
224
229
|
leadRoute.syncEmptyMainRoute(adopted);
|
|
230
|
+
if (!fixedSessionCompaction) syncSessionCompaction(getSession?.(), adopted);
|
|
225
231
|
return adopted;
|
|
226
232
|
}
|
|
227
233
|
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
// After the multi-account connector merge (connector-catalog.mjs
|
|
2
|
+
// mergeConnectorAccountServers) `gmail-2`, `google-calendar-2`… are accounts of
|
|
3
|
+
// one server, no longer servers. Every store of ours that keys a setting by
|
|
4
|
+
// MCP server name must name the surviving server instead:
|
|
5
|
+
// agents/<id>/agent.json, bots/<id>/agent.json connectors.off / connectors.tools
|
|
6
|
+
// (a legacy allow list too)
|
|
7
|
+
// <data>/project-connectors.json projects.<root>.off
|
|
8
|
+
// <data>/hooks.json, <data>/hooks/hooks.json mcp_tool `server`, tool matchers
|
|
9
|
+
// (extension scopes are the config's and are dropped by migrateConnectorAccounts;
|
|
10
|
+
// an approval's "always allow" is the agent's connectors.tools; agent routes
|
|
11
|
+
// name models, not servers.) Project and plugin hook files are the user's or
|
|
12
|
+
// the plugin's own and are never rewritten here.
|
|
13
|
+
//
|
|
14
|
+
// Rule: the merged connector is OFF for an agent/project only when EVERY
|
|
15
|
+
// merged server was off (the same rule as the merged server's `enabled`: one
|
|
16
|
+
// working account keeps the connector usable). Per-tool permissions move to
|
|
17
|
+
// the surviving name; where two merged servers disagree on a tool the MORE
|
|
18
|
+
// PERMISSIVE permission wins, as "on beats off" does at server level. Entries
|
|
19
|
+
// of a server that was off are dormant and are dropped when the connector
|
|
20
|
+
// stays on, so they never become live. A setting that names no merged-away
|
|
21
|
+
// server is never touched, which makes every run after the first a no-op.
|
|
22
|
+
//
|
|
23
|
+
// The merge is saved to the config once, so the rename mapping outlives it:
|
|
24
|
+
// `<data>/connector-merge-pending.json` ({ merged: [{ name, from }] }) is
|
|
25
|
+
// written before any store is touched and deleted only when every store
|
|
26
|
+
// migrated. A store that fails (unreadable, malformed, not writable) is
|
|
27
|
+
// reported and the others still go on; the next start retries them all.
|
|
28
|
+
//
|
|
29
|
+
// Hooks: only tool identifiers are rewritten — an `mcp_tool` handler's
|
|
30
|
+
// `server`, and a matcher / tool-name field (or the tool part of an `if`
|
|
31
|
+
// before its `(`) that is an `mcp__<server>__…` identifier or an
|
|
32
|
+
// alternative of a pattern. Argument conditions such as `Bash(mcp__x__*)`
|
|
33
|
+
// and any other data are never touched.
|
|
34
|
+
import { readdirSync, readFileSync, rmSync } from 'node:fs';
|
|
35
|
+
import { join } from 'node:path';
|
|
36
|
+
import { normalizeRules, standardConfigReport } from './services/hook-bus/config.mjs';
|
|
37
|
+
import {
|
|
38
|
+
PERMISSION_RANK,
|
|
39
|
+
PROJECT_CONNECTORS_FILE,
|
|
40
|
+
connectorEnabled,
|
|
41
|
+
parseConnectorPolicy,
|
|
42
|
+
storedConnectorPolicy,
|
|
43
|
+
} from '../runtime/agent/orchestrator/mcp/agent-connectors.mjs';
|
|
44
|
+
import { parseJsonText, withFileLockSync, writeJsonAtomicSync } from '../runtime/shared/atomic-file.mjs';
|
|
45
|
+
|
|
46
|
+
const unique = (list) => [...new Set(list)].sort();
|
|
47
|
+
|
|
48
|
+
/** The policy `{ off, tools }` (or a legacy `{ allow, off, tools }`) with every
|
|
49
|
+
* merged-away server of `merged` mapped onto its surviving one; null when it
|
|
50
|
+
* names none. `merged` is mergeConnectorAccountServers' `merged`. */
|
|
51
|
+
function mapMergedConnectorPolicy(policy, merged) {
|
|
52
|
+
let current = policy;
|
|
53
|
+
for (const { name, from } of merged) {
|
|
54
|
+
const gone = from.filter((server) => server !== name);
|
|
55
|
+
const named = (server) =>
|
|
56
|
+
current.off.includes(server) || current.allow?.includes(server) || Object.hasOwn(current.tools, server);
|
|
57
|
+
if (!gone.some(named)) continue;
|
|
58
|
+
const live = from.filter((server) => connectorEnabled(current, server));
|
|
59
|
+
const on = live.length > 0;
|
|
60
|
+
const off = current.off.filter((server) => !from.includes(server));
|
|
61
|
+
const allow = current.allow?.filter((server) => !from.includes(server));
|
|
62
|
+
if (allow && on) allow.push(name);
|
|
63
|
+
if (!allow && !on) off.push(name);
|
|
64
|
+
const tools = { ...current.tools };
|
|
65
|
+
for (const server of from) delete tools[server];
|
|
66
|
+
const moved = {};
|
|
67
|
+
for (const server of on ? live : from) {
|
|
68
|
+
for (const [tool, permission] of Object.entries(current.tools[server] || {})) {
|
|
69
|
+
if (!(tool in moved) || PERMISSION_RANK[permission] > PERMISSION_RANK[moved[tool]]) moved[tool] = permission;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (Object.keys(moved).length) tools[name] = moved;
|
|
73
|
+
current = { ...(allow ? { allow: unique(allow) } : {}), off: unique(off), tools };
|
|
74
|
+
}
|
|
75
|
+
return current === policy ? null : current;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** A mapped policy as the value the agent.json `connectors` field stores
|
|
79
|
+
* (undefined: the field goes). */
|
|
80
|
+
function storedValue(policy) {
|
|
81
|
+
if (!policy.allow) return storedConnectorPolicy(policy) ?? undefined;
|
|
82
|
+
const ids = unique([...policy.allow, ...Object.keys(policy.tools)]);
|
|
83
|
+
return ids.map((id) => ({
|
|
84
|
+
id,
|
|
85
|
+
enabled: policy.allow.includes(id),
|
|
86
|
+
...(policy.tools[id] ? { tools: policy.tools[id] } : {}),
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export const PENDING_MERGE_FILE = 'connector-merge-pending.json';
|
|
91
|
+
|
|
92
|
+
const warn = (file, error) => process.stderr.write(`[connectors] ${file} not migrated (${error?.message || error})\n`);
|
|
93
|
+
|
|
94
|
+
/** The JSON at `file`; null when it does not exist. Any other failure throws. */
|
|
95
|
+
function readJsonFile(file) {
|
|
96
|
+
try {
|
|
97
|
+
return parseJsonText(readFileSync(file, 'utf8'));
|
|
98
|
+
} catch (error) {
|
|
99
|
+
if (error?.code === 'ENOENT' || error?.code === 'ENOTDIR') return null;
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const isRecord = (value) => Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
105
|
+
|
|
106
|
+
/** Runs `step` for one store; a failure is reported and returned, never thrown. */
|
|
107
|
+
function attempt(file, step, outcome) {
|
|
108
|
+
try {
|
|
109
|
+
step();
|
|
110
|
+
} catch (error) {
|
|
111
|
+
warn(file, error);
|
|
112
|
+
outcome.failed.push(file);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function migrateAgentFiles(dataDir, merged, outcome, readdir) {
|
|
117
|
+
for (const store of ['agents', 'bots']) {
|
|
118
|
+
const dir = join(dataDir, store);
|
|
119
|
+
let entries;
|
|
120
|
+
try {
|
|
121
|
+
entries = readdir(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory());
|
|
122
|
+
} catch (error) {
|
|
123
|
+
// A store that does not exist has nothing to migrate; any other failure
|
|
124
|
+
// leaves its agents unprocessed, so the mapping must stay pending.
|
|
125
|
+
if (error?.code !== 'ENOENT') {
|
|
126
|
+
warn(dir, error);
|
|
127
|
+
outcome.failed.push(dir);
|
|
128
|
+
}
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
for (const entry of entries) {
|
|
132
|
+
const file = join(dataDir, store, entry.name, 'agent.json');
|
|
133
|
+
attempt(
|
|
134
|
+
file,
|
|
135
|
+
() => {
|
|
136
|
+
const manifest = readJsonFile(file);
|
|
137
|
+
if (!isRecord(manifest) || manifest.connectors == null) return;
|
|
138
|
+
const next = mapMergedConnectorPolicy(parseConnectorPolicy(manifest.connectors), merged);
|
|
139
|
+
if (!next) return;
|
|
140
|
+
const value = storedValue(next);
|
|
141
|
+
if (value) manifest.connectors = value;
|
|
142
|
+
else delete manifest.connectors;
|
|
143
|
+
writeJsonAtomicSync(file, manifest, { backup: true });
|
|
144
|
+
outcome.agents.push(`${store}/${entry.name}`);
|
|
145
|
+
},
|
|
146
|
+
outcome
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function migrateProjectFile(dataDir, merged, outcome) {
|
|
153
|
+
const file = join(dataDir, PROJECT_CONNECTORS_FILE);
|
|
154
|
+
attempt(
|
|
155
|
+
file,
|
|
156
|
+
() => {
|
|
157
|
+
withFileLockSync(`${file}.lock`, () => {
|
|
158
|
+
const document = readJsonFile(file);
|
|
159
|
+
const projects = document?.projects;
|
|
160
|
+
if (!isRecord(projects)) return;
|
|
161
|
+
const changed = [];
|
|
162
|
+
for (const [root, entry] of Object.entries(projects)) {
|
|
163
|
+
if (!isRecord(entry) || !Array.isArray(entry.off)) continue;
|
|
164
|
+
const next = mapMergedConnectorPolicy({ off: entry.off.map(String), tools: {} }, merged);
|
|
165
|
+
if (!next) continue;
|
|
166
|
+
if (next.off.length) projects[root] = { ...entry, off: next.off };
|
|
167
|
+
else delete projects[root];
|
|
168
|
+
changed.push(root);
|
|
169
|
+
}
|
|
170
|
+
if (!changed.length) return;
|
|
171
|
+
writeJsonAtomicSync(file, document, { lock: false, backup: true });
|
|
172
|
+
outcome.projects.push(...changed);
|
|
173
|
+
});
|
|
174
|
+
},
|
|
175
|
+
outcome
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
180
|
+
|
|
181
|
+
/** A tool identifier or pattern (`mcp__a__x`, `^mcp__a__.*$`, `Bash|mcp__a__x`)
|
|
182
|
+
* with each `mcp__<merged-away>` alternative renamed. */
|
|
183
|
+
function renameToolPattern(value, renames) {
|
|
184
|
+
let next = value;
|
|
185
|
+
for (const [gone, name] of renames) {
|
|
186
|
+
const identifier = new RegExp(`(^|\\|)(\\^?)mcp__${escapeRegExp(gone)}(?=__|(?![A-Za-z0-9_-]))`, 'g');
|
|
187
|
+
next = next.replace(identifier, (_all, lead, anchor) => `${lead}${anchor}mcp__${name}`);
|
|
188
|
+
}
|
|
189
|
+
return next;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** A condition `Tool(arguments)`: only the tool part is an identifier. */
|
|
193
|
+
function renameCondition(value, renames) {
|
|
194
|
+
const open = value.indexOf('(');
|
|
195
|
+
return open < 0
|
|
196
|
+
? renameToolPattern(value, renames)
|
|
197
|
+
: renameToolPattern(value.slice(0, open), renames) + value.slice(open);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** Renames in the hook structures of `document` (in place); true when any changed. */
|
|
201
|
+
function renameInHooks(document, renames) {
|
|
202
|
+
let changed = false;
|
|
203
|
+
const set = (owner, key, rename) => {
|
|
204
|
+
if (typeof owner[key] !== 'string') return;
|
|
205
|
+
const next = rename(owner[key], renames);
|
|
206
|
+
if (next === owner[key]) return;
|
|
207
|
+
owner[key] = next;
|
|
208
|
+
changed = true;
|
|
209
|
+
};
|
|
210
|
+
const handler = (hook) => {
|
|
211
|
+
if (!isRecord(hook)) return;
|
|
212
|
+
if (hook.type === 'mcp_tool') {
|
|
213
|
+
if (typeof hook.server === 'string' && renames.has(hook.server.trim())) {
|
|
214
|
+
hook.server = renames.get(hook.server.trim());
|
|
215
|
+
changed = true;
|
|
216
|
+
}
|
|
217
|
+
set(hook, 'tool', renameToolPattern);
|
|
218
|
+
}
|
|
219
|
+
set(hook, 'if', renameCondition);
|
|
220
|
+
};
|
|
221
|
+
if (standardConfigReport(document).standard) {
|
|
222
|
+
for (const groups of Object.values(document.hooks)) {
|
|
223
|
+
for (const group of Array.isArray(groups) ? groups : []) {
|
|
224
|
+
if (!isRecord(group)) continue;
|
|
225
|
+
set(group, 'matcher', renameToolPattern);
|
|
226
|
+
set(group, 'if', renameCondition);
|
|
227
|
+
for (const hook of Array.isArray(group.hooks) ? group.hooks : []) handler(hook);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
} else {
|
|
231
|
+
for (const rule of normalizeRules(document)) {
|
|
232
|
+
if (!isRecord(rule)) continue;
|
|
233
|
+
set(rule, 'tool', renameToolPattern);
|
|
234
|
+
set(rule, 'name', renameToolPattern);
|
|
235
|
+
set(rule, 'if', renameCondition);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return changed;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function migrateHookFiles(dataDir, merged, outcome) {
|
|
242
|
+
const renames = new Map(
|
|
243
|
+
merged.flatMap(({ name, from }) => from.filter((server) => server !== name).map((gone) => [gone, name]))
|
|
244
|
+
);
|
|
245
|
+
for (const file of [join(dataDir, 'hooks.json'), join(dataDir, 'hooks', 'hooks.json')]) {
|
|
246
|
+
attempt(
|
|
247
|
+
file,
|
|
248
|
+
() => {
|
|
249
|
+
const document = readJsonFile(file);
|
|
250
|
+
if (!isRecord(document) && !Array.isArray(document)) return;
|
|
251
|
+
if (!renameInHooks(document, renames)) return;
|
|
252
|
+
writeJsonAtomicSync(file, document, { backup: true });
|
|
253
|
+
outcome.hooks.push(file);
|
|
254
|
+
},
|
|
255
|
+
outcome
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const validGroup = (group) =>
|
|
261
|
+
isRecord(group) &&
|
|
262
|
+
typeof group.name === 'string' &&
|
|
263
|
+
Array.isArray(group.from) &&
|
|
264
|
+
group.from.every((n) => typeof n === 'string');
|
|
265
|
+
|
|
266
|
+
/** Maps every per-server setting of `dataDir` onto the surviving servers of
|
|
267
|
+
* `merged` (this start's merge, [] to only retry) plus any still pending from
|
|
268
|
+
* an earlier start. Returns what it rewrote and the files that failed:
|
|
269
|
+
* `{ agents, projects, hooks, failed, unrecorded? }`. The pending record is
|
|
270
|
+
* removed only when `failed` is empty; `unrecorded` says it could not be
|
|
271
|
+
* written, so the caller must not save the merge. `readdir` lists the agent
|
|
272
|
+
* and bot directories. */
|
|
273
|
+
export function migrateMergedConnectorServers(dataDir, merged, { readdir = readdirSync } = {}) {
|
|
274
|
+
const outcome = { agents: [], projects: [], hooks: [], failed: [] };
|
|
275
|
+
if (!dataDir) return outcome;
|
|
276
|
+
const pendingFile = join(dataDir, PENDING_MERGE_FILE);
|
|
277
|
+
let pending = [];
|
|
278
|
+
try {
|
|
279
|
+
const stored = readJsonFile(pendingFile)?.merged;
|
|
280
|
+
pending = Array.isArray(stored) ? stored.filter(validGroup).map(({ name, from }) => ({ name, from })) : [];
|
|
281
|
+
} catch (error) {
|
|
282
|
+
warn(pendingFile, error);
|
|
283
|
+
}
|
|
284
|
+
const groups = [...pending];
|
|
285
|
+
for (const { name, from } of merged) {
|
|
286
|
+
if (!groups.some((group) => group.name === name && JSON.stringify(group.from) === JSON.stringify(from))) {
|
|
287
|
+
groups.push({ name, from });
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
if (!groups.length) return outcome;
|
|
291
|
+
if (groups.length !== pending.length) {
|
|
292
|
+
try {
|
|
293
|
+
writeJsonAtomicSync(pendingFile, { merged: groups }, { backup: false });
|
|
294
|
+
} catch (error) {
|
|
295
|
+
warn(pendingFile, error);
|
|
296
|
+
// Nothing records the mapping: a failed store must keep the merge unsaved.
|
|
297
|
+
outcome.unrecorded = true;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
migrateAgentFiles(dataDir, groups, outcome, readdir);
|
|
301
|
+
migrateProjectFile(dataDir, groups, outcome);
|
|
302
|
+
migrateHookFiles(dataDir, groups, outcome);
|
|
303
|
+
if (!outcome.failed.length) rmSync(pendingFile, { force: true });
|
|
304
|
+
return outcome;
|
|
305
|
+
}
|