mixdog 1.4.2 → 1.4.3
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/package.json +2 -2
- package/scripts/build-shipped-history.mjs +15 -5
- package/scripts/gate-local.mjs +65 -19
- package/scripts/graph-parity.mjs +8 -3
- package/scripts/lib/gate-scheduler.mjs +2 -1
- package/scripts/lib/run-node-tests.mjs +17 -5
- package/scripts/lib/test-failure-summary.mjs +1 -8
- package/scripts/lib/test-spawn-ledger.mjs +33 -2
- package/scripts/post-release-check.mjs +26 -16
- package/scripts/provider-pingpong-live.mjs +1 -1
- package/scripts/prune-embedding-runtime.mjs +3 -1
- package/scripts/release-paths.mjs +7 -1
- package/src/defaults/shipped-history.json +20 -0
- package/src/defaults/skills/setup/SKILL.md +2 -2
- package/src/defaults/skills/setup/references/actions.md +16 -3
- package/src/defaults/skills/setup/references/surfaces.md +3 -0
- package/src/defaults/skills/setup-guide/SKILL.md +6 -1
- package/src/lib/instruction-text.cjs +36 -0
- package/src/lib/rules-builder.cjs +34 -20
- package/src/orchestration/balanced.md +23 -0
- package/src/orchestration/focused.md +22 -0
- package/src/orchestration/none.md +5 -0
- package/src/orchestration/swarm.md +24 -0
- package/src/rules/agent-mode/AGENT_MODE.md +3 -1
- package/src/rules/agent-mode/MIXY.md +2 -2
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +3 -3
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +0 -1
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +4 -2
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +0 -9
- package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +2 -2
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +67 -0
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +1 -0
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +4 -4
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -1
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +199 -46
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +3 -5
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +9 -3
- package/src/runtime/agent/orchestrator/mcp/client.mjs +3 -5
- package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +1 -1
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +8 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +1 -1
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +14 -0
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-stop.mjs +3 -3
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +4 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2784 -2872
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +5 -8
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +288 -300
- package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +10 -30
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +30 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +0 -11
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +8 -0
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +17 -3
- package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +47 -27
- package/src/runtime/agent/orchestrator/runtime-core/goal-deadlines.mjs +141 -10
- package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +26 -63
- package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +28 -3
- package/src/runtime/agent/orchestrator/runtime-core/goal-runtime.mjs +36 -11
- package/src/runtime/agent/orchestrator/runtime-core/goal-state.mjs +88 -56
- package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +51 -32
- package/src/runtime/agent/orchestrator/runtime-core/goal-text.mjs +45 -145
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +15 -98
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +32 -99
- package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +23 -78
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +69 -48
- package/src/runtime/agent/orchestrator/runtime-core/todo-list.mjs +367 -0
- package/src/runtime/agent/orchestrator/runtime-core/todo-tool-defs.mjs +47 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-availability.mjs +155 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +9 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +119 -35
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +28 -22
- package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +30 -0
- package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -12
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +7 -3
- package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +1 -2
- package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/image-strip-recovery.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +11 -1
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +8 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/todo-check.mjs +196 -0
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +116 -50
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +8 -1
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +5 -6
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/loop/turn-report.mjs +35 -0
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +57 -26
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +9 -7
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +21 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +27 -11
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-open.mjs +37 -34
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +25 -15
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +79 -24
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +12 -1
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +9 -1
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-path.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/prompt-settings.mjs +598 -0
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +19 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +19 -10
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +31 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lock.mjs +31 -0
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +42 -6
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +11 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +8 -9
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +339 -88
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +135 -11
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +377 -104
- package/src/runtime/agent/orchestrator/session/manager/turn-durability.mjs +144 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +8 -1
- package/src/runtime/agent/orchestrator/session/save-session-worker.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +23 -2
- package/src/runtime/agent/orchestrator/session/store/sweep/sub-agent-retention.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/store/transcript-durability.mjs +88 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/store-summary-log.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +14 -5
- package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/store.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +9 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/agent-envelope.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +2 -2
- package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -5
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +21 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/worktree-add-guard.mjs +77 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +0 -1
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +7 -3
- package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +27 -9
- package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +0 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +0 -10
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +1 -2
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +1 -24
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary/child-kill.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +1 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/modes/calls.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/modes/symbols.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +4 -5
- package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +3 -4
- package/src/runtime/agent/orchestrator/tools/code-graph.mjs +4 -22
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +0 -4
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +0 -1
- package/src/runtime/attachments/attachment-reference.mjs +1 -1
- package/src/runtime/attachments/pdf-extract.mjs +1 -1
- package/src/runtime/attachments/store.d.mts +1 -0
- package/src/runtime/attachments/store.mjs +2 -2
- package/src/runtime/channels/lib/config-reload-watch.mjs +42 -0
- package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +29 -9
- package/src/runtime/channels/lib/scheduler.mjs +33 -0
- package/src/runtime/channels/lib/schedules-db.mjs +11 -4
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +4 -1
- package/src/runtime/channels/lib/webhooks-db.mjs +9 -3
- package/src/runtime/channels/lib/whisper-server.mjs +12 -12
- package/src/runtime/channels/lib/worker-main.mjs +9 -31
- package/src/runtime/computer-bridge/linux-readiness.mjs +10 -14
- package/src/runtime/connectors/connector-accounts-mcp.mjs +169 -33
- package/src/runtime/connectors/gmail-app-password.mjs +2 -2
- package/src/runtime/connectors/google-mcp.mjs +1 -1
- package/src/runtime/effort-judge/judge-client.mjs +2 -2
- package/src/runtime/effort-judge/judge-input.mjs +4 -4
- package/src/runtime/explore/explorer.mjs +0 -5
- package/src/runtime/explore/tool.mjs +3 -3
- package/src/runtime/local-provider/hardware.mjs +1 -1
- package/src/runtime/media/adapters/codex-image.mjs +3 -3
- package/src/runtime/media/adapters/gemini-video.mjs +1 -1
- package/src/runtime/media/media-usage.mjs +1 -1
- package/src/runtime/media/store.mjs +1 -1
- package/src/runtime/memory/index.mjs +11 -1
- package/src/runtime/memory/lib/embedding-reindex.mjs +27 -0
- package/src/runtime/memory/lib/memory-embed.mjs +83 -14
- package/src/runtime/memory/lib/memory-process-lock.mjs +159 -36
- package/src/runtime/memory/lib/memory-text-utils.mjs +6 -1
- package/src/runtime/memory/lib/memory.mjs +17 -0
- package/src/runtime/memory/lib/pg/process.mjs +1 -1
- package/src/runtime/memory/lib/pg/supervisor.mjs +16 -96
- package/src/runtime/memory/lib/recall-hybrid/hybrid-sql.mjs +12 -3
- package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
- package/src/runtime/office/authoring/pptx-author-action.mjs +1 -1
- package/src/runtime/office/authoring/xlsx-html-build.mjs +1 -1
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
- package/src/runtime/office/capabilities.mjs +1 -1
- package/src/runtime/office/core/office-core.mjs +1 -1
- package/src/runtime/office/design/content-model.mjs +3 -3
- package/src/runtime/office/design/docx/design-docx/section.mjs +6 -6
- package/src/runtime/office/design/xlsx/design-xlsx-components.mjs +1 -1
- package/src/runtime/office/design/xlsx/design-xlsx.mjs +1 -1
- package/src/runtime/office/pdf/ocr-engine.mjs +1 -1
- package/src/runtime/office/pdf/pdf-writer.mjs +4 -4
- package/src/runtime/office/portable/portable-docx-operations.mjs +2 -2
- package/src/runtime/office/portable/portable-soffice.mjs +8 -6
- package/src/runtime/office/portable/xlsx-contract.mjs +1 -1
- package/src/runtime/shared/atomic-file.d.mts +8 -0
- package/src/runtime/shared/background-tasks.mjs +22 -4
- package/src/runtime/shared/background-wait.mjs +66 -0
- package/src/runtime/shared/child-guardian.mjs +17 -7
- package/src/runtime/shared/config.mjs +313 -16
- package/src/runtime/shared/connector-catalog.d.mts +4 -5
- package/src/runtime/shared/connector-catalog.mjs +11 -1
- package/src/runtime/shared/file-lock.mjs +8 -3
- package/src/runtime/shared/git-runner.mjs +7 -2
- package/src/runtime/shared/idle-gc.mjs +30 -7
- package/src/runtime/shared/llm/http-agent.mjs +8 -5
- package/src/runtime/shared/llm/system-proxy.mjs +2 -1
- package/src/runtime/shared/llm/usage-ledger-quota.mjs +31 -12
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +84 -8
- package/src/runtime/shared/llm/usage-ledger.mjs +3 -0
- package/src/runtime/shared/llm/usage-rollup.mjs +48 -0
- package/src/runtime/shared/maintenance-schedule.mjs +109 -0
- package/src/runtime/shared/process-runner.mjs +8 -4
- package/src/runtime/shared/routine-trigger.d.mts +13 -0
- package/src/runtime/shared/routine-trigger.mjs +34 -0
- package/src/runtime/shared/run-child.d.mts +2 -1
- package/src/runtime/shared/run-child.mjs +70 -18
- package/src/runtime/shared/session-scratch.mjs +14 -2
- package/src/runtime/shared/shipped-definitions.mjs +7 -1
- package/src/runtime/shared/tool-card-model.golden.json +3 -12
- package/src/runtime/shared/tool-execution-contract.mjs +2 -0
- package/src/runtime/shared/tool-work-units.mjs +31 -6
- package/src/runtime/shared/turn-snapshot.mjs +26 -4
- package/src/runtime/shared/turn-worktree-snapshot.mjs +6 -11
- package/src/runtime/shared/worker-requests.mjs +17 -3
- package/src/runtime/shared/worktrees/branch-management.mjs +1 -5
- package/src/runtime/shared/worktrees/contract.mjs +16 -6
- package/src/runtime/shared/worktrees/dependencies.mjs +127 -89
- package/src/runtime/shared/worktrees/disk.mjs +79 -2
- package/src/runtime/shared/worktrees/git.mjs +44 -11
- package/src/runtime/shared/worktrees/include.mjs +6 -4
- package/src/runtime/shared/worktrees/maintenance.mjs +422 -30
- package/src/runtime/shared/worktrees/manager.mjs +772 -75
- package/src/runtime/shared/worktrees/settings.mjs +33 -7
- package/src/runtime/shared/worktrees/test-support.mjs +5 -1
- package/src/runtime/shared/worktrees/worker-snapshots.mjs +82 -0
- package/src/runtime/tidy/process.mjs +2 -1
- package/src/runtime/web-search/index.mjs +3 -22
- package/src/runtime/web-search/lib/web-tools.mjs +2 -2
- package/src/runtime/web-search/tool-defs.mjs +17 -26
- package/src/session-runtime/agent-profile-changes.mjs +55 -4
- package/src/session-runtime/boot/apis.mjs +27 -4
- package/src/session-runtime/boot/begin.mjs +2 -0
- package/src/session-runtime/boot/config.mjs +10 -1
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/providers.mjs +70 -3
- package/src/session-runtime/boot/session.mjs +2 -0
- package/src/session-runtime/boot/tools.mjs +69 -25
- package/src/session-runtime/channel-config-api.mjs +1 -0
- package/src/session-runtime/config-change-effects.mjs +179 -0
- package/src/session-runtime/config-lifecycle/config-writers.mjs +1 -0
- package/src/session-runtime/config-lifecycle.mjs +160 -24
- package/src/session-runtime/conversation-import/discovery.mjs +86 -7
- package/src/session-runtime/conversation-import/service.mjs +3 -2
- package/src/session-runtime/goal-facade-api.mjs +49 -3
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +3 -0
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -2
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +3 -11
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +18 -4
- package/src/session-runtime/internal-tool-executor.mjs +12 -19
- package/src/session-runtime/lifecycle/cold-heir.mjs +7 -0
- package/src/session-runtime/lifecycle/memory-ingest.mjs +3 -3
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +53 -5
- package/src/session-runtime/lifecycle/session-switch.mjs +13 -2
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +4 -4
- package/src/session-runtime/lifecycle-api.mjs +1 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +14 -3
- package/src/session-runtime/mcp-glue/server-connection.mjs +34 -8
- package/src/session-runtime/model-route/set-route.mjs +40 -7
- package/src/session-runtime/native-web-search/routes.mjs +3 -3
- package/src/session-runtime/provider-auth/refresh.mjs +6 -3
- package/src/session-runtime/provider-auth/setup.mjs +1 -1
- package/src/session-runtime/provider-readiness.mjs +53 -4
- package/src/session-runtime/resource-api.mjs +1 -1
- package/src/session-runtime/resource-extension-sync.mjs +4 -8
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +5 -1
- package/src/session-runtime/resource-mcp-secrets.mjs +3 -3
- package/src/session-runtime/resource-plugins-api.mjs +4 -0
- package/src/session-runtime/routine-executor.mjs +152 -0
- package/src/session-runtime/routine-home-turn.mjs +46 -5
- package/src/session-runtime/runtime-facade.mjs +5 -0
- package/src/session-runtime/runtime-feature-gates.mjs +2 -11
- package/src/session-runtime/schedule-session-run.mjs +1 -0
- package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +6 -1
- package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +7 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +110 -6
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +12 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +5 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +24 -6
- package/src/session-runtime/services/agent-tool.mjs +51 -1
- package/src/session-runtime/services/channel-admin.mjs +18 -0
- package/src/session-runtime/services/hook-bus/command-handler.mjs +7 -11
- package/src/session-runtime/services/plugin-admin.mjs +4 -0
- package/src/session-runtime/services/seeds.mjs +7 -0
- package/src/session-runtime/services/usage-stats-model.mjs +32 -11
- package/src/session-runtime/session-create/materialize.mjs +4 -2
- package/src/session-runtime/session-create/session-options.mjs +2 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +1 -9
- package/src/session-runtime/setup-tool/connector-widen-approval.mjs +1 -1
- package/src/session-runtime/setup-tool/executor.mjs +8 -1
- package/src/session-runtime/setup-tool/extended-actions.mjs +2 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +28 -0
- package/src/session-runtime/setup-tool/tool-defs.mjs +26 -1
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +40 -43
- package/src/session-runtime/tool-policy/mode-switch.mjs +1 -1
- package/src/session-runtime/tool-policy/policy-stage.mjs +106 -8
- package/src/session-runtime/tool-policy/workflow-overlay.mjs +2 -1
- package/src/session-runtime/tool-policy-refresh.mjs +182 -5
- package/src/session-runtime/tool-surface.mjs +38 -1
- package/src/session-runtime/turn/agent-ops.mjs +10 -2
- package/src/session-runtime/turn/session-ops.mjs +2 -0
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +5 -0
- package/src/session-runtime/turn/turn-run.mjs +1 -1
- package/src/session-runtime/webhook-session-run.mjs +2 -0
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +1 -4
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +3 -10
- package/src/session-runtime/workflow-agents-api/instruction-files.mjs +165 -0
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +5 -4
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +2 -3
- package/src/session-runtime/workflow-agents-api.mjs +2 -0
- package/src/session-runtime/workspace/project-branches.mjs +1 -1
- package/src/session-runtime/workspace/session-view.mjs +1 -1
- package/src/session-runtime/workspace/transitions.mjs +20 -4
- package/src/session-runtime/workspace/worktree-maintenance.mjs +126 -6
- package/src/session-runtime/workspace/worktree-setup.mjs +13 -1
- package/src/session-runtime/workspace/worktree-tool.mjs +16 -0
- package/src/standalone/daemon-agent-control.mjs +25 -8
- package/src/standalone/daemon-desktop-runtime.mjs +6 -2
- package/src/standalone/daemon-lag-profiler.mjs +7 -7
- package/src/standalone/daemon.mjs +54 -2
- package/src/standalone/local-session-runtime.mjs +16 -0
- package/src/standalone/session-client/daemon-unavailable.mjs +1 -1
- package/src/standalone/session-protocol.mjs +11 -0
- package/src/standalone/session-service/agent-route-follow.mjs +23 -20
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +18 -6
- package/src/standalone/session-service/quota-resume.mjs +9 -0
- package/src/standalone/session-service/session-calls/session-action.mjs +51 -1
- package/src/standalone/session-service/session-calls/session-turns.mjs +37 -18
- package/src/standalone/session-service/session-calls/turn-gate.mjs +34 -0
- package/src/standalone/session-service/session-calls.mjs +2 -1
- package/src/tui/App.jsx +8 -0
- package/src/tui/app/clipboard.mjs +1 -1
- package/src/tui/app/create-app-pickers.mjs +2 -0
- package/src/tui/app/doctor.mjs +2 -2
- package/src/tui/app/panel-signature.mjs +1 -1
- package/src/tui/app/settings-picker.mjs +53 -8
- package/src/tui/app/shell-layout/row-budgets.mjs +2 -2
- package/src/tui/app/slash-commands.mjs +1 -1
- package/src/tui/app/slash-dispatch/route-commands.mjs +1 -1
- package/src/tui/app/slash-dispatch/session-commands.mjs +1 -1
- package/src/tui/app/use-prompt-queue-history.mjs +2 -2
- package/src/tui/app/use-transcript-activity.mjs +1 -1
- package/src/tui/app/use-transcript-window/geometry.mjs +1 -1
- package/src/tui/components/prompt-input/escape-policy.d.mts +0 -1
- package/src/tui/components/prompt-input/escape-policy.mjs +1 -1
- package/src/tui/components/question-panel-model.mjs +4 -4
- package/src/tui/components/tool-execution/standard-card.jsx +3 -4
- package/src/tui/components/user-message-skills.mjs +1 -1
- package/src/tui/dist/index.mjs +309 -30
- package/src/tui/markdown/render-ansi.mjs +1 -1
- package/src/tui/session/agent-job-feed/notification-router.mjs +10 -0
- package/src/tui/session/agent-job-feed.mjs +2 -0
- package/src/tui/session/context-state.mjs +3 -0
- package/src/tui/session/quota-resume.mjs +1 -1
- package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
- package/src/tui/session/session-api/lifecycle/session-reset.mjs +7 -0
- package/src/tui/session/session-api/routes-agent-definitions.mjs +5 -0
- package/src/tui/session/session-api/worktree.mjs +13 -1
- package/src/tui/session/session-flow/drain.mjs +11 -14
- package/src/tui/session/tool-card-results/grouped-result.mjs +2 -2
- package/src/tui/session/turn-quiet.mjs +1 -1
- package/src/tui/session/turn.mjs +3 -0
- package/src/tui/session/worktree-setup-notice.mjs +1 -1
- package/src/tui/spinner-meta.mjs +3 -3
- package/src/tui/spinner-verbs.mjs +2 -2
- package/src/defaults/skills/goal-management/SKILL.md +0 -169
- package/src/runtime/agent/orchestrator/runtime-core/goal-tasks.mjs +0 -156
- package/src/session-runtime/goal-tasks.mjs +0 -1
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* to channel tools.
|
|
7
7
|
*/
|
|
8
8
|
import { clean } from '../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
9
|
+
import { settingDisabledIn } from '../runtime/agent/orchestrator/runtime-core/tool-availability.mjs';
|
|
9
10
|
import { createAskUserToolHandlers } from './internal-tool-executor/ask-user-tool.mjs';
|
|
10
11
|
import { createBridgeToolHandlers } from './internal-tool-executor/bridge-tools.mjs';
|
|
11
12
|
import { createFeatureToolHandlers } from './internal-tool-executor/feature-tools.mjs';
|
|
@@ -19,11 +20,7 @@ export function createInternalToolExecutor({
|
|
|
19
20
|
goalRuntime,
|
|
20
21
|
agentTool,
|
|
21
22
|
setupTool,
|
|
22
|
-
|
|
23
|
-
memoryToolsEnabled,
|
|
24
|
-
officeToolsEnabled,
|
|
25
|
-
mediaToolEnabled,
|
|
26
|
-
tidyToolEnabled = () => true,
|
|
23
|
+
featureDisallowedTools = () => [],
|
|
27
24
|
getWebSearchModule,
|
|
28
25
|
getMemoryModule,
|
|
29
26
|
getCodeGraphModule,
|
|
@@ -42,7 +39,7 @@ export function createInternalToolExecutor({
|
|
|
42
39
|
...createBridgeToolHandlers({ rt }),
|
|
43
40
|
...createAskUserToolHandlers({ rt }),
|
|
44
41
|
...createReactionToolHandlers({ rt }),
|
|
45
|
-
...createFeatureToolHandlers({ rt, setupTool
|
|
42
|
+
...createFeatureToolHandlers({ rt, setupTool }),
|
|
46
43
|
...createKnowledgeToolHandlers({
|
|
47
44
|
rt,
|
|
48
45
|
getWebSearchModule,
|
|
@@ -67,24 +64,20 @@ export function createInternalToolExecutor({
|
|
|
67
64
|
}),
|
|
68
65
|
};
|
|
69
66
|
|
|
70
|
-
//
|
|
71
|
-
//
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
throw new Error('web search is disabled in settings; start a new session to refresh the tool list');
|
|
75
|
-
}
|
|
76
|
-
if ((name === 'memory' || name === 'recall') && !memoryToolsEnabled()) {
|
|
77
|
-
throw new Error(
|
|
78
|
-
'memory tools are disabled in settings; background memory and manual core memory remain available'
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
};
|
|
67
|
+
// A model call of a tool a setting turned off is refused at dispatch
|
|
68
|
+
// (tool-exec/dispatch.mjs settingDisabledTool, built-ins such as git
|
|
69
|
+
// included); a model-tool call reaching this executor directly takes the
|
|
70
|
+
// same check against this runtime's live gate list.
|
|
82
71
|
|
|
83
72
|
return async (name, args, callerCtx = {}) => {
|
|
84
73
|
const callerCwd = clean(callerCtx?.callerCwd) || rt.currentCwd;
|
|
85
74
|
// The Reactions setting gates the tool whoever calls it, not only the model.
|
|
86
75
|
if (name === 'react' && rt.config?.reactions === false) throw new Error('reactions are turned off in settings');
|
|
87
|
-
|
|
76
|
+
const disabled =
|
|
77
|
+
callerCtx?.invocationSource === 'model-tool' ? settingDisabledIn(name, featureDisallowedTools()) : null;
|
|
78
|
+
if (disabled) {
|
|
79
|
+
throw new Error(`${disabled} is disabled in settings by the user; do not retry unless the user turns it back on`);
|
|
80
|
+
}
|
|
88
81
|
if (Object.hasOwn(handlers, name)) return handlers[name](args, { name, callerCtx, callerCwd });
|
|
89
82
|
if (channels.isChannelTool(name)) {
|
|
90
83
|
return await channels.execute(name, args || {});
|
|
@@ -35,9 +35,16 @@ const SOURCE_RUNTIME_FIELDS = [
|
|
|
35
35
|
'toolApprovalHook',
|
|
36
36
|
'_providerPrefixGuardState',
|
|
37
37
|
'activeTurnCheckpoint',
|
|
38
|
+
// The source's durable transcript identity (store/transcript-durability.mjs).
|
|
39
|
+
'transcriptEpoch',
|
|
40
|
+
'turnCoverage',
|
|
38
41
|
'deferredInitialRefreshPending',
|
|
39
42
|
'pendingGoalReminder',
|
|
40
43
|
'goalReminderRevision',
|
|
44
|
+
'goalStalledNotice',
|
|
45
|
+
// The source's own step list and its reminder cycle.
|
|
46
|
+
'todo',
|
|
47
|
+
'todoCheck',
|
|
41
48
|
'pendingCacheBreakIntent',
|
|
42
49
|
'contextPressureUnanchoredAfterRestart',
|
|
43
50
|
'contextPressureUnanchoredReason',
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
const INGEST_DEADLINE_MS = 2500;
|
|
6
6
|
|
|
7
|
-
// Sessions that never compacted
|
|
8
|
-
//
|
|
9
|
-
//
|
|
7
|
+
// Sessions that never compacted have no session-sourced rows unless ingested
|
|
8
|
+
// here, and recall could not reconstruct the most recent conversations
|
|
9
|
+
// without them. Deadline-capped: the row inserts are fast
|
|
10
10
|
// and committed even if the bounded wait elapses during the trailing
|
|
11
11
|
// embedding flush (the raw-embedding backlog sweep embeds them later). Never
|
|
12
12
|
// loads the memory runtime just for this — a null module promise means
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
import { SESSION_ID_PATTERN, closeManagedSession } from '../shared.mjs';
|
|
15
15
|
import { replacementSessionCwd } from '../../workspace/workspace-state.mjs';
|
|
16
16
|
import { isHistoricalAutomaticClosure } from '../../../runtime/agent/orchestrator/session/historical-session-closure.mjs';
|
|
17
|
+
import { readSessionSidebarState } from '../../../runtime/shared/session-sidebar-host.mjs';
|
|
17
18
|
|
|
18
19
|
export function createSessionDelete(deps, { cancelBackgroundTasks }) {
|
|
19
20
|
const {
|
|
@@ -38,12 +39,13 @@ export function createSessionDelete(deps, { cancelBackgroundTasks }) {
|
|
|
38
39
|
// Availability is one strict read of the session's own file, filtered like
|
|
39
40
|
// the session catalog (an unreadable, foreign, closed or non-catalogued
|
|
40
41
|
// record is not deletable). No catalog rebuild, no folder scan.
|
|
41
|
-
function
|
|
42
|
+
function availableRecord(sessionId) {
|
|
42
43
|
const stored = _storedSessionFromFile(getStoreDir(), `${sessionId}.json`);
|
|
43
|
-
if (!stored || stored === STORED_SESSION_UNREADABLE) return
|
|
44
|
-
if (stored.closed === true && !isHistoricalAutomaticClosure(stored)) return
|
|
45
|
-
return leadSessionRow(stored) !== null;
|
|
44
|
+
if (!stored || stored === STORED_SESSION_UNREADABLE) return null;
|
|
45
|
+
if (stored.closed === true && !isHistoricalAutomaticClosure(stored)) return null;
|
|
46
|
+
return leadSessionRow(stored) !== null ? stored : null;
|
|
46
47
|
}
|
|
48
|
+
const isAvailableSession = (sessionId) => availableRecord(sessionId) !== null;
|
|
47
49
|
|
|
48
50
|
// The deleted task's worktree: the autoCleanup setting decides (clean and
|
|
49
51
|
// merged → removed; otherwise kept). Off the deletion path; never fails it.
|
|
@@ -102,5 +104,51 @@ export function createSessionDelete(deps, { cancelBackgroundTasks }) {
|
|
|
102
104
|
return true;
|
|
103
105
|
}
|
|
104
106
|
|
|
105
|
-
|
|
107
|
+
/**
|
|
108
|
+
* The desktop's auto-delete of an archived session: only one that is still
|
|
109
|
+
* archived, not a favorite, idle (no turn running, waiting for its ask lock
|
|
110
|
+
* or queued) and unchanged since the caller looked (`expected.lastUsedAt`,
|
|
111
|
+
* which every turn moves). It holds the session's ask lock, which every
|
|
112
|
+
* turn takes, and runs its last checks, the close and the delete in one
|
|
113
|
+
* synchronous stretch, so no turn can start in between. A refusal closes
|
|
114
|
+
* and deletes nothing: `{ deleted: false, reason }`. `isHostedBusy` (the
|
|
115
|
+
* session service) reports queued input in a runtime hosting the session.
|
|
116
|
+
*/
|
|
117
|
+
async function deleteSessionIfIdle(id, expected = {}, { isHostedBusy = null } = {}) {
|
|
118
|
+
const sessionId = clean(id);
|
|
119
|
+
const refuse = (reason) => ({ deleted: false, reason });
|
|
120
|
+
if (!sessionId || !SESSION_ID_PATTERN.test(sessionId)) return refuse('invalid');
|
|
121
|
+
if (typeof isHostedBusy !== 'function') return refuse('unguarded');
|
|
122
|
+
if (getSession()?.id === sessionId) return refuse('current');
|
|
123
|
+
const unlock = mgr.tryAcquireSessionLock(sessionId);
|
|
124
|
+
if (!unlock) return refuse('busy');
|
|
125
|
+
try {
|
|
126
|
+
// The archive and favorite flags are the desktop's.
|
|
127
|
+
const sidebar = await readSessionSidebarState();
|
|
128
|
+
if (!sidebar || !Object.hasOwn(sidebar.archived ?? {}, sessionId)) return refuse('not-archived');
|
|
129
|
+
if (Object.hasOwn(sidebar.favorites ?? {}, sessionId)) return refuse('favorite');
|
|
130
|
+
// From here to the delete: synchronous.
|
|
131
|
+
if (mgr.sessionLockContended(sessionId)) return refuse('turn-waiting');
|
|
132
|
+
if (mgr.isSessionTurnInFlight(sessionId) || mgr.hasUnsettledTurn(sessionId)) return refuse('busy');
|
|
133
|
+
if (mgr.hasPendingMessages(sessionId) || isHostedBusy(sessionId)) return refuse('queued');
|
|
134
|
+
const stored = availableRecord(sessionId);
|
|
135
|
+
if (!stored) return refuse('missing');
|
|
136
|
+
if ((Number(stored.lastUsedAt) || 0) !== (Number(expected?.lastUsedAt) || 0)) return refuse('changed');
|
|
137
|
+
const reason = 'desktop-auto-delete';
|
|
138
|
+
// The blocking close: its barrier lands before this stretch yields.
|
|
139
|
+
if (closeManagedSession(mgr, sessionId, reason, { tombstone: false }, false) !== true) {
|
|
140
|
+
return refuse('close-failed');
|
|
141
|
+
}
|
|
142
|
+
agentTool?.forgetLeadSession?.(sessionId);
|
|
143
|
+
releaseSessionWork(sessionId, reason);
|
|
144
|
+
if (mgr.deleteSession(sessionId, { fenceWrites: true }) !== true) return refuse('delete-failed');
|
|
145
|
+
void forgetSessionSearch(sessionId);
|
|
146
|
+
void releaseDeletedWorktree(sessionId);
|
|
147
|
+
return { deleted: true };
|
|
148
|
+
} finally {
|
|
149
|
+
unlock();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return { releaseSessionWork, deleteSession, deleteSessionIfIdle };
|
|
106
154
|
}
|
|
@@ -15,7 +15,9 @@ export { resolveResumeCwd } from './session-switch/resume.mjs';
|
|
|
15
15
|
|
|
16
16
|
export function createSessionSwitching(deps, { ingestSessionIntoMemory, closeSurfaceSession, cancelBackgroundTasks }) {
|
|
17
17
|
const { mgr, getMode } = deps;
|
|
18
|
-
const { releaseSessionWork, deleteSession } = createSessionDelete(deps, {
|
|
18
|
+
const { releaseSessionWork, deleteSession, deleteSessionIfIdle } = createSessionDelete(deps, {
|
|
19
|
+
cancelBackgroundTasks,
|
|
20
|
+
});
|
|
19
21
|
const { switchContext, newSession } = createContextSwitch(deps, {
|
|
20
22
|
ingestSessionIntoMemory,
|
|
21
23
|
closeSurfaceSession,
|
|
@@ -41,5 +43,14 @@ export function createSessionSwitching(deps, { ingestSessionIntoMemory, closeSur
|
|
|
41
43
|
return mgr.prefetchSession?.(id, toolSpecForMode(getMode())) === true;
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
return {
|
|
46
|
+
return {
|
|
47
|
+
listSessions,
|
|
48
|
+
sessionStoreDir,
|
|
49
|
+
deleteSession,
|
|
50
|
+
deleteSessionIfIdle,
|
|
51
|
+
switchContext,
|
|
52
|
+
newSession,
|
|
53
|
+
prefetchSession,
|
|
54
|
+
resume,
|
|
55
|
+
};
|
|
45
56
|
}
|
|
@@ -35,10 +35,10 @@ export async function dispatchSessionEnd(deps, reason) {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
// Runtime stop/exit (TUI Ctrl-C, process exit)
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
// tombstone
|
|
38
|
+
// Runtime stop/exit (TUI Ctrl-C, process exit) must not tombstone a session
|
|
39
|
+
// you were mid-conversation in: it would vanish from the Resume list the
|
|
40
|
+
// instant you quit and be hard-deleted by the 24h tombstone sweep. Only
|
|
41
|
+
// tombstone truly-empty scratch sessions.
|
|
42
42
|
export function closeOwnSession(deps, closeSurfaceSession, reason) {
|
|
43
43
|
const {
|
|
44
44
|
getSession,
|
|
@@ -38,6 +38,7 @@ export function createLifecycleApi(deps) {
|
|
|
38
38
|
listSessions: switching.listSessions,
|
|
39
39
|
sessionStoreDir: switching.sessionStoreDir,
|
|
40
40
|
deleteSession: switching.deleteSession,
|
|
41
|
+
deleteSessionIfIdle: switching.deleteSessionIfIdle,
|
|
41
42
|
switchContext: switching.switchContext,
|
|
42
43
|
newSession: switching.newSession,
|
|
43
44
|
prefetchSession: switching.prefetchSession,
|
|
@@ -4,12 +4,16 @@
|
|
|
4
4
|
import { clean } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
5
5
|
import {
|
|
6
6
|
connectorAccountEnabled,
|
|
7
|
+
connectorAccountId,
|
|
7
8
|
connectorAccountServer,
|
|
8
9
|
connectorAccountsOf,
|
|
9
10
|
connectorOfServer,
|
|
10
11
|
gmailAppPasswordAccount,
|
|
11
12
|
} from '../../runtime/shared/connector-catalog.mjs';
|
|
12
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
connectorAccountHealth,
|
|
15
|
+
connectorAccountInUseRecord,
|
|
16
|
+
} from '../../runtime/connectors/connector-accounts-mcp.mjs';
|
|
13
17
|
import { googleOAuthClient } from '../../runtime/shared/google-oauth-client.mjs';
|
|
14
18
|
import { envFlag } from '../../runtime/shared/env.mjs';
|
|
15
19
|
import { resolveMcpServerCatalog } from './plugin-servers.mjs';
|
|
@@ -158,8 +162,15 @@ export function createMcpServerCatalog({
|
|
|
158
162
|
const stored = entry.owner ? [] : connectorAccountsOf(cfg);
|
|
159
163
|
// The connector's last-used account (none when that one was removed),
|
|
160
164
|
// else its topmost switched-on one.
|
|
161
|
-
|
|
162
|
-
|
|
165
|
+
// A record names an account only while that account is still it (a new
|
|
166
|
+
// account given a removed one's name is not).
|
|
167
|
+
const record = stored.length ? connectorAccountInUseRecord(connectorOfServer(cfg)) : null;
|
|
168
|
+
const recorded = record
|
|
169
|
+
? stored.find(
|
|
170
|
+
(account) => account.name === record.name && record.id && connectorAccountId(cfg, account) === record.id
|
|
171
|
+
)?.name
|
|
172
|
+
: '';
|
|
173
|
+
const inUse = record ? recorded : stored.find(connectorAccountEnabled)?.name;
|
|
163
174
|
const accounts = stored.map((account) =>
|
|
164
175
|
accountRow(connectorAccountServer(cfg, account), connectorAccountEnabled(account), account.name === inUse)
|
|
165
176
|
);
|
|
@@ -18,20 +18,23 @@ export function createServerConnection({
|
|
|
18
18
|
// change never triggers a full disconnectAll()/reconnect freeze. Only an
|
|
19
19
|
// explicit sign-in passes `login` ({ openBrowser }): every other connect is
|
|
20
20
|
// non-interactive and reports a server that needs one as sign-in required.
|
|
21
|
+
// Answers the connect's failure (recorded in state.mcpFailures), null once
|
|
22
|
+
// it connected or disconnected. The server's fingerprint is recorded only
|
|
23
|
+
// once it connected, so one that failed is connected again by the next
|
|
24
|
+
// reconcile although its config is unchanged.
|
|
21
25
|
async function applyMcpServerConnection(name, enabled, servers = resolveEffectiveMcpServers().servers, login = null) {
|
|
22
26
|
const target = clean(name);
|
|
23
|
-
if (!target) return;
|
|
27
|
+
if (!target) return null;
|
|
24
28
|
// Changing this server's state clears any stale failure record for it.
|
|
25
29
|
if (Array.isArray(state.mcpFailures)) {
|
|
26
30
|
state.mcpFailures = state.mcpFailures.filter((row) => row.name !== target);
|
|
27
31
|
}
|
|
28
32
|
const cfg = servers[target];
|
|
33
|
+
applied().delete(target);
|
|
29
34
|
if (enabled === false || !cfg || cfg.enabled === false) {
|
|
30
|
-
applied().delete(target);
|
|
31
35
|
await mcpClient.disconnectMcpServer?.(target, scopeOptions());
|
|
32
|
-
return;
|
|
36
|
+
return null;
|
|
33
37
|
}
|
|
34
|
-
applied().set(target, fingerprint(cfg));
|
|
35
38
|
// Close-then-connect as one generation-guarded op: a shutdown landing
|
|
36
39
|
// between the close and the connect never resurrects the server.
|
|
37
40
|
try {
|
|
@@ -42,29 +45,52 @@ export function createServerConnection({
|
|
|
42
45
|
cfg,
|
|
43
46
|
login ? { interactive: true, openBrowser: login.openBrowser } : {}
|
|
44
47
|
);
|
|
48
|
+
applied().set(target, fingerprint(cfg));
|
|
49
|
+
return null;
|
|
45
50
|
} catch (error) {
|
|
46
51
|
const failure = { name: target, msg: error?.message || String(error) };
|
|
47
52
|
if (error?.authRequired) failure.authRequired = true;
|
|
48
53
|
const failures = Array.isArray(error?.failures) ? error.failures : [failure];
|
|
49
54
|
state.mcpFailures = [...(state.mcpFailures || []), ...failures];
|
|
55
|
+
return failure;
|
|
50
56
|
}
|
|
51
57
|
}
|
|
52
58
|
|
|
53
59
|
// Bring the registry in line with the effective set: drop servers that are
|
|
54
60
|
// gone or disabled, (re)connect servers that are new or whose resolved
|
|
55
|
-
// config changed; untouched servers keep their connection.
|
|
61
|
+
// config changed; untouched servers keep their connection. A server whose
|
|
62
|
+
// last connect failed is retried too (one the full connect recorded as
|
|
63
|
+
// connected included): reconcile also runs when a sign-in or a stored
|
|
64
|
+
// credential changed (possibly in another process), which leaves its
|
|
65
|
+
// config, and so its fingerprint, as it was; so is a connection the client
|
|
66
|
+
// reports dead. Answers the failures of this run that are not a needed
|
|
67
|
+
// sign-in (that waits on the user, whose sign-in reconciles again); they
|
|
68
|
+
// stay in the status, which the change step checks to retry them.
|
|
56
69
|
async function reconcileServers() {
|
|
57
70
|
syncScopeRoot();
|
|
58
71
|
const { servers } = resolveEffectiveMcpServers();
|
|
59
72
|
const known = applied();
|
|
60
|
-
const
|
|
73
|
+
const dead = (mcpClient.getMcpServerStatus?.(getMcpScopeId()) || [])
|
|
74
|
+
.filter((row) => row.alive === false || row.connected === false)
|
|
75
|
+
.map((row) => row.name);
|
|
76
|
+
const failed = new Set([
|
|
77
|
+
...(Array.isArray(state.mcpFailures) ? state.mcpFailures : []).map((row) => row.name),
|
|
78
|
+
...dead,
|
|
79
|
+
]);
|
|
80
|
+
const drops = [...new Set([...known.keys(), ...failed])].filter(
|
|
81
|
+
(name) => !servers[name] || servers[name].enabled === false
|
|
82
|
+
);
|
|
61
83
|
const connects = Object.entries(servers)
|
|
62
|
-
.filter(([name, cfg]) => cfg?.enabled !== false && known.get(name) !== fingerprint(cfg))
|
|
84
|
+
.filter(([name, cfg]) => cfg?.enabled !== false && (known.get(name) !== fingerprint(cfg) || failed.has(name)))
|
|
63
85
|
.map(([name]) => name);
|
|
64
|
-
await Promise.allSettled([
|
|
86
|
+
const results = await Promise.allSettled([
|
|
65
87
|
...drops.map((name) => applyMcpServerConnection(name, false, servers)),
|
|
66
88
|
...connects.map((name) => applyMcpServerConnection(name, true, servers)),
|
|
67
89
|
]);
|
|
90
|
+
return results.flatMap((one) => {
|
|
91
|
+
if (one.status === 'rejected') return [{ msg: one.reason?.message || String(one.reason) }];
|
|
92
|
+
return one.value && !one.value.authRequired ? [one.value] : [];
|
|
93
|
+
});
|
|
68
94
|
}
|
|
69
95
|
|
|
70
96
|
return { applyMcpServerConnection, reconcileServers };
|
|
@@ -136,6 +136,23 @@ function refreshSessionFallbacks(deps, session) {
|
|
|
136
136
|
deps.mgr.updateSessionRoute?.(session.id, fields, { session });
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
+
/** The route fields a model pick held for the next turn keeps on its session. */
|
|
140
|
+
function heldRoutePick(route) {
|
|
141
|
+
const pick = {
|
|
142
|
+
provider: route.provider,
|
|
143
|
+
model: route.model,
|
|
144
|
+
...(route.preset ? { preset: route.preset } : {}),
|
|
145
|
+
...(route.effort !== undefined ? { effort: route.effort } : {}),
|
|
146
|
+
fast: route.fast === true,
|
|
147
|
+
...(route.autoEffort === false ? { autoEffort: false } : {}),
|
|
148
|
+
...(route.modelParameters ? { modelParameters: route.modelParameters } : {}),
|
|
149
|
+
...(route.contextPercent !== undefined ? { contextPercent: route.contextPercent } : {}),
|
|
150
|
+
...(route.contextTokens ? { contextTokens: route.contextTokens } : {}),
|
|
151
|
+
...(route.selectedContextWindow ? { selectedContextWindow: route.selectedContextWindow } : {}),
|
|
152
|
+
};
|
|
153
|
+
return pick;
|
|
154
|
+
}
|
|
155
|
+
|
|
139
156
|
/** Rewrite the addressed empty session to the route it was asked to run on. */
|
|
140
157
|
function updateSessionInPlace(deps, session, updateOptions) {
|
|
141
158
|
const { getRoute, getSession, setSession, mgr, statusRoutes } = deps;
|
|
@@ -386,9 +403,16 @@ export function createSetRoute(deps, persist) {
|
|
|
386
403
|
const session = getSession();
|
|
387
404
|
if (options.deferUntilNextTurn === true) {
|
|
388
405
|
pending = session?.id ? { generation: lease.token } : null;
|
|
406
|
+
// Held on the session too (saved like a pending workflow switch), so a
|
|
407
|
+
// restart before the next turn still applies it.
|
|
408
|
+
if (session?.id) {
|
|
409
|
+
session.pendingRoute = heldRoutePick(getRoute());
|
|
410
|
+
deps.persistSession?.(session);
|
|
411
|
+
}
|
|
389
412
|
return getRoute();
|
|
390
413
|
}
|
|
391
414
|
pending = null;
|
|
415
|
+
if (session?.pendingRoute) delete session.pendingRoute;
|
|
392
416
|
// A session the user has already talked in or compacted keeps its route
|
|
393
417
|
// unless the selection was addressed to it. A current session with no
|
|
394
418
|
// model reply, no compaction summary and no in-flight first turn — empty,
|
|
@@ -436,21 +460,30 @@ export function createSetRoute(deps, persist) {
|
|
|
436
460
|
return getRoute();
|
|
437
461
|
}
|
|
438
462
|
setRoute.applyPendingRoute = () => {
|
|
439
|
-
|
|
440
|
-
const
|
|
441
|
-
if (
|
|
463
|
+
const session = getSession();
|
|
464
|
+
const held = session?.pendingRoute;
|
|
465
|
+
if (session && held) delete session.pendingRoute;
|
|
466
|
+
if (pending) {
|
|
467
|
+
const selection = pending;
|
|
442
468
|
pending = null;
|
|
469
|
+
if (selection.generation !== getSessionGeneration()) return null;
|
|
470
|
+
// The live route is the latest selection: effort/Fast tuned after the
|
|
471
|
+
// deferred model choice replace it.
|
|
472
|
+
} else if (held?.provider && held.model) {
|
|
473
|
+
// Held by an earlier process (a restart in between): the saved pick
|
|
474
|
+
// becomes the live route again.
|
|
475
|
+
deps.setRouteState(deps.resolveRoute(deps.getConfig(), held));
|
|
476
|
+
} else {
|
|
443
477
|
return null;
|
|
444
478
|
}
|
|
445
|
-
|
|
446
|
-
// deferred model choice replace it, so no snapshot is kept.
|
|
447
|
-
const modelSwitch = switchSessionInPlace(deps, getSession());
|
|
479
|
+
const modelSwitch = switchSessionInPlace(deps, session);
|
|
448
480
|
invalidateContextStatusCache();
|
|
449
|
-
pending = null;
|
|
450
481
|
return modelSwitch;
|
|
451
482
|
};
|
|
452
483
|
setRoute.clearPendingRoute = () => {
|
|
453
484
|
pending = null;
|
|
485
|
+
const session = getSession();
|
|
486
|
+
if (session?.pendingRoute) delete session.pendingRoute;
|
|
454
487
|
};
|
|
455
488
|
return setRoute;
|
|
456
489
|
}
|
|
@@ -46,9 +46,9 @@ export function createWebSearchRouteCandidates({
|
|
|
46
46
|
await awaitKeychainPrewarm();
|
|
47
47
|
const cfg = ensureFullConfig();
|
|
48
48
|
// An unset webSearchRoute IS the default ("follow the Main Model") — the
|
|
49
|
-
// sidebar
|
|
50
|
-
//
|
|
51
|
-
//
|
|
49
|
+
// sidebar presents it that way. Materialize it here instead of treating a
|
|
50
|
+
// missing key as "not configured", which would fail the search before the
|
|
51
|
+
// Main Model is consulted.
|
|
52
52
|
const webSearchRoute = webSearchRouteOrDefault(cfg.webSearchRoute, getWebSearchRoute());
|
|
53
53
|
setWebSearchRoute(webSearchRoute);
|
|
54
54
|
const candidates = [];
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { resetProviderAdmissionCooldowns } from '../../runtime/agent/orchestrator/providers/admission-scheduler.mjs';
|
|
4
4
|
|
|
5
5
|
export function createAuthRefresh({
|
|
6
|
-
|
|
6
|
+
applyConfigChange,
|
|
7
7
|
invalidateProviderCaches,
|
|
8
8
|
warmProviderModelCache,
|
|
9
9
|
refreshProviderCatalogs,
|
|
@@ -42,14 +42,17 @@ export function createAuthRefresh({
|
|
|
42
42
|
warmProviderModelCache();
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
// The change step (reload + effects keyed by the config/secret change) runs
|
|
46
|
+
// here at once rather than on the notification that follows, so this
|
|
47
|
+
// runtime's notification finds the change already applied.
|
|
45
48
|
function afterCredentialChange() {
|
|
46
|
-
|
|
49
|
+
applyConfigChange();
|
|
47
50
|
adoptCredentials();
|
|
48
51
|
}
|
|
49
52
|
|
|
50
53
|
/** Usage-dashboard credentials affect no admission lane or catalog. */
|
|
51
54
|
function afterUsageAuthChange() {
|
|
52
|
-
|
|
55
|
+
applyConfigChange();
|
|
53
56
|
invalidateProviderCaches();
|
|
54
57
|
}
|
|
55
58
|
|
|
@@ -48,7 +48,7 @@ export function createSetupApi({
|
|
|
48
48
|
return cachedProviderSetup({ force: force || options?.recheckKeychain === true });
|
|
49
49
|
}
|
|
50
50
|
// An unforced read never blocks: the authoritative setup waits on the OS
|
|
51
|
-
// keychain, which can take seconds on a cold start and
|
|
51
|
+
// keychain, which can take seconds on a cold start and would stall the
|
|
52
52
|
// whole settings sweep behind it. Serve
|
|
53
53
|
// the no-secrets snapshot until the real one is cached — flagged, so the
|
|
54
54
|
// caller shows "checking" instead of a wrong "not connected" — and let the
|
|
@@ -51,6 +51,13 @@ export function createProviderReadiness({ rt, keychain, getReg, getWarmProviderM
|
|
|
51
51
|
const providerModelCaches = { ...emptyModelCaches(), providerModelsLoadSeq: 0 };
|
|
52
52
|
const providerUsageCaches = emptyUsageCaches();
|
|
53
53
|
const providerInitPromises = new Map();
|
|
54
|
+
// Whether this runtime has started its providers: a rebuild after a change
|
|
55
|
+
// follows it, a failed initialization (whose gate is dropped) included.
|
|
56
|
+
let providersStarted = false;
|
|
57
|
+
// Advances whenever the init gates are cleared (a provider config or
|
|
58
|
+
// credential change): an initialization registered before it is superseded
|
|
59
|
+
// and never writes the shared registry.
|
|
60
|
+
let providerInitGeneration = 0;
|
|
54
61
|
|
|
55
62
|
function invalidateProviderCaches(options = {}) {
|
|
56
63
|
// Auth/account/config changes alter what providers list: the process-wide
|
|
@@ -59,7 +66,10 @@ export function createProviderReadiness({ rt, keychain, getReg, getWarmProviderM
|
|
|
59
66
|
Object.assign(providerModelCaches, emptyModelCaches());
|
|
60
67
|
providerModelCaches.providerModelsLoadSeq += 1;
|
|
61
68
|
Object.assign(providerUsageCaches, emptyUsageCaches());
|
|
62
|
-
if (options.preserveProviderInit !== true)
|
|
69
|
+
if (options.preserveProviderInit !== true) {
|
|
70
|
+
providerInitPromises.clear();
|
|
71
|
+
providerInitGeneration += 1;
|
|
72
|
+
}
|
|
63
73
|
modelMetaByRoute.clear();
|
|
64
74
|
}
|
|
65
75
|
|
|
@@ -67,19 +77,44 @@ export function createProviderReadiness({ rt, keychain, getReg, getWarmProviderM
|
|
|
67
77
|
// absent (provider setup, init gates) is stale.
|
|
68
78
|
keychain.onKeychainRecovered?.(() => invalidateProviderCaches());
|
|
69
79
|
|
|
70
|
-
|
|
80
|
+
// The one edit a caller makes to the provider config it passes is turning a
|
|
81
|
+
// route's provider on (ensureProviderEnabled); those providers, judged
|
|
82
|
+
// against the runtime's config when the request was made.
|
|
83
|
+
function forcedProviders(requested, base) {
|
|
84
|
+
return Object.keys(requested || {}).filter(
|
|
85
|
+
(name) => requested[name]?.enabled === true && base?.[name]?.enabled !== true
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Waits for the keychain, then initializes the registry with
|
|
90
|
+
// `providerConfig` unless a change superseded it meanwhile: a superseded
|
|
91
|
+
// request is replayed on the latest config (with the providers it turned on),
|
|
92
|
+
// so the latest config always wins.
|
|
93
|
+
async function initializeProviders(providerConfig) {
|
|
94
|
+
const generation = providerInitGeneration;
|
|
95
|
+
const forced = forcedProviders(providerConfig, rt.config.providers);
|
|
71
96
|
await awaitKeychainPrewarm();
|
|
72
97
|
if (rt.closeRequested) throw new Error('runtime is closing');
|
|
98
|
+
if (generation === providerInitGeneration) return getReg().initProviders(providerConfig);
|
|
99
|
+
const latest = { ...(rt.config.providers || {}) };
|
|
100
|
+
for (const name of forced) latest[name] = { ...(latest[name] || {}), enabled: true };
|
|
101
|
+
return ensureProvidersReady(latest);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function ensureProvidersReady(providerConfig = rt.config.providers || {}) {
|
|
105
|
+
if (rt.closeRequested) throw new Error('runtime is closing');
|
|
106
|
+
providersStarted = true;
|
|
73
107
|
const initKey = providerInitCacheKey(providerConfig);
|
|
74
108
|
// Provider initialization is idempotent for one normalized config. Keep
|
|
75
109
|
// the fulfilled promise, not only the in-flight one: session resume used
|
|
76
110
|
// to rerun registry/keychain setup on every click even though neither the
|
|
77
111
|
// provider config nor the registry had changed. Auth/config mutations call
|
|
78
112
|
// invalidateProviderCaches(), which clears this gate and preserves the
|
|
79
|
-
// existing refresh semantics.
|
|
113
|
+
// existing refresh semantics. Registered before any await, so a change
|
|
114
|
+
// applied while it waits on the keychain sees (and supersedes) it.
|
|
80
115
|
let providerInitPromise = providerInitPromises.get(initKey);
|
|
81
116
|
if (!providerInitPromise) {
|
|
82
|
-
providerInitPromise =
|
|
117
|
+
providerInitPromise = initializeProviders(providerConfig);
|
|
83
118
|
providerInitPromises.set(initKey, providerInitPromise);
|
|
84
119
|
}
|
|
85
120
|
let result;
|
|
@@ -125,9 +160,23 @@ export function createProviderReadiness({ rt, keychain, getReg, getWarmProviderM
|
|
|
125
160
|
return result;
|
|
126
161
|
}
|
|
127
162
|
|
|
163
|
+
// Provider config or secrets changed: drop everything keyed to the old ones
|
|
164
|
+
// and, when this runtime had initialized providers, rebuild the shared
|
|
165
|
+
// registry from its reloaded config now, so no runtime's stale copy is the
|
|
166
|
+
// last one to have initialized it. Rejects when that rebuild failed.
|
|
167
|
+
function reinitProviders() {
|
|
168
|
+
invalidateProviderCaches();
|
|
169
|
+
if (!providersStarted || rt.closeRequested) return Promise.resolve();
|
|
170
|
+
return ensureProvidersReady().catch((error) => {
|
|
171
|
+
bootProfile('providers:reinit-failed', { error: error?.message || String(error) });
|
|
172
|
+
throw error;
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
128
176
|
return {
|
|
129
177
|
awaitKeychainPrewarm,
|
|
130
178
|
invalidateProviderCaches,
|
|
179
|
+
reinitProviders,
|
|
131
180
|
ensureProvidersReady,
|
|
132
181
|
modelMetaByRoute,
|
|
133
182
|
providerModelCaches,
|
|
@@ -31,7 +31,7 @@ export function createResourceApi(deps) {
|
|
|
31
31
|
throw new Error(`extension scope kind must be one of ${EXTENSION_SCOPE_KINDS.join(', ')}`);
|
|
32
32
|
}
|
|
33
33
|
// A connector is on in every project unless a project switches it off
|
|
34
|
-
// (setProjectConnectorEnabled); "only in this project"
|
|
34
|
+
// (setProjectConnectorEnabled); there is no "only in this project" scope.
|
|
35
35
|
if (scopeKind === 'mcp') {
|
|
36
36
|
throw new Error('MCP servers are switched off per project in Project settings (setProjectConnectorEnabled)');
|
|
37
37
|
}
|
|
@@ -7,7 +7,6 @@ export function createExtensionSync({
|
|
|
7
7
|
connectConfiguredMcp,
|
|
8
8
|
cancelMcpLogin,
|
|
9
9
|
invalidatePreSessionToolSurface,
|
|
10
|
-
refreshEmptySessionToolPolicy,
|
|
11
10
|
reloadFullConfig,
|
|
12
11
|
invalidateSkills,
|
|
13
12
|
}) {
|
|
@@ -19,14 +18,11 @@ export function createExtensionSync({
|
|
|
19
18
|
// session.
|
|
20
19
|
const mcpToggleChains = new Map(); // name -> { desired, running }
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
// The invalidation moves the surface generation: an empty session rebuilds
|
|
22
|
+
// at its next turn start (reconcileTurnSettings); MCP has its own
|
|
23
|
+
// first-turn/late-tool reconciliation against the live connection registry.
|
|
24
|
+
async function refreshSurface() {
|
|
23
25
|
invalidatePreSessionToolSurface();
|
|
24
|
-
// Existing conversations retain their stable prompt/session identity.
|
|
25
|
-
// Empty sessions can safely rebuild their policy in place; MCP has its own
|
|
26
|
-
// first-turn/late-tool reconciliation against the live connection registry.
|
|
27
|
-
if ((kind === 'skills' || kind === 'plugins') && typeof refreshEmptySessionToolPolicy === 'function') {
|
|
28
|
-
await refreshEmptySessionToolPolicy();
|
|
29
|
-
}
|
|
30
26
|
}
|
|
31
27
|
|
|
32
28
|
// Apply per-server MCP changes in order, then reconcile: a configured server
|
|
@@ -80,7 +80,9 @@ export function createConnectorAccountEdits({
|
|
|
80
80
|
throw nameTakenError(servers, name);
|
|
81
81
|
}
|
|
82
82
|
const accountName = serverName ? freeName(servers, name) : name;
|
|
83
|
-
|
|
83
|
+
// A fresh identity: a conversation that used a removed account of this
|
|
84
|
+
// name never takes this one for it (connector-accounts-mcp.mjs).
|
|
85
|
+
const account = { ...connectorAccountEntry(accountName, accountCfg), id: randomUUID() };
|
|
84
86
|
// A sign-in is stored per exact URL: another account signing in at the
|
|
85
87
|
// same URL gets its own key, so the two never share tokens.
|
|
86
88
|
const asServer = connectorAccountServer({ connector }, account);
|
|
@@ -141,6 +143,8 @@ export function createConnectorAccountEdits({
|
|
|
141
143
|
entry.name === account.name
|
|
142
144
|
? {
|
|
143
145
|
...connectorAccountEntry(account.name, next),
|
|
146
|
+
// An edit keeps the account's identity.
|
|
147
|
+
...(entry.id ? { id: entry.id } : {}),
|
|
144
148
|
...(connectorAccountEnabled(entry) ? {} : { enabled: false }),
|
|
145
149
|
}
|
|
146
150
|
: entry
|