mixdog 1.2.1 → 1.2.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/README.md +18 -0
- package/package.json +2 -1
- package/scripts/gate-local.mjs +19 -3
- package/scripts/model-catalog-audit.mjs +1 -15
- package/scripts/provider-pingpong-live.mjs +509 -0
- package/src/agents/advisor/AGENT.md +1 -1
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/reviewer/AGENT.md +3 -3
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +6 -0
- package/src/defaults/skills/setup/SKILL.md +6 -1
- package/src/defaults/skills/setup/references/actions.md +44 -22
- package/src/defaults/skills/setup/references/surfaces.md +10 -8
- package/src/headless-exec.mjs +15 -8
- package/src/lib/keychain-cjs.cjs +7 -4
- package/src/output-styles/common.md +11 -10
- package/src/repl/slash-commands.mjs +16 -1
- package/src/rules/agent/AGENT.md +5 -5
- package/src/rules/lead/LEAD.md +5 -5
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -4
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +10 -0
- package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
- package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
- package/src/runtime/agent/orchestrator/config.mjs +5 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +36 -7
- package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +49 -10
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +40 -3
- package/src/runtime/agent/orchestrator/mcp/client.mjs +230 -96
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +103 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +150 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +111 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +87 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +95 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-request.mjs +122 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +9 -0
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +229 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +188 -29
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +94 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +98 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-fast-mode.mjs +39 -18
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +55 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +48 -37
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +10 -7
- package/src/runtime/agent/orchestrator/providers/anthropic-midstream-recovery.mjs +18 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +13 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-midstream.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-recovery.mjs +23 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +46 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request.mjs +14 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +102 -45
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +69 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-server-fallback.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +40 -7
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +30 -9
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +88 -21
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +30 -10
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +106 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +10 -61
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +94 -15
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +117 -72
- package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +75 -10
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-guards.mjs +97 -2
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +103 -23
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +43 -2
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +103 -33
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +32 -6
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +27 -3
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +64 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +70 -6
- package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
- package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
- package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +80 -18
- package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +46 -8
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +273 -0
- package/src/runtime/agent/orchestrator/providers/gemini-family.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/gemini-history-signatures.mjs +9 -4
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +180 -0
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +369 -112
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +140 -35
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +70 -24
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +80 -29
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +69 -19
- package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +246 -42
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
- package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +388 -0
- package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
- package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
- package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +48 -22
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +119 -18
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +33 -1
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +4 -9
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +123 -61
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +27 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +37 -7
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +50 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +47 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
- package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +151 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +64 -23
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +79 -33
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +172 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +144 -15
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +193 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +66 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +109 -26
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +27 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +34 -20
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +23 -4
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +37 -28
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +274 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +72 -32
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +43 -15
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-stamps.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +7 -3
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +1 -3
- package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +37 -4
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +12 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +22 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +12 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +76 -33
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +44 -16
- package/src/runtime/agent/orchestrator/providers/openai-retry-policy.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -16
- package/src/runtime/agent/orchestrator/providers/openai-ws-handshake.mjs +16 -8
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -35
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/policy.mjs +25 -14
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
- package/src/runtime/agent/orchestrator/providers/openai-ws-terminal.mjs +18 -11
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +41 -22
- package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +170 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +75 -70
- package/src/runtime/agent/orchestrator/providers/openrouter.mjs +75 -0
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +720 -0
- package/src/runtime/agent/orchestrator/providers/registry.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/retry-backoff.mjs +46 -7
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +123 -219
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +148 -45
- package/src/runtime/agent/orchestrator/providers/retry-midstream.mjs +81 -16
- package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
- package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
- package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +157 -0
- package/src/runtime/agent/orchestrator/providers/wire-route.mjs +512 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +183 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +100 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +21 -0
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
- package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +0 -18
- package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +57 -28
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +19 -16
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +1 -97
- package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
- package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +14 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +176 -71
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +62 -10
- package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +14 -93
- package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +120 -0
- package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
- package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +91 -1
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
- package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +21 -10
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +132 -0
- package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +30 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +67 -20
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +104 -19
- package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +150 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +7 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +30 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +57 -21
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +5 -10
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +208 -14
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +16 -4
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +25 -3
- package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +19 -2
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +18 -7
- package/src/runtime/agent/orchestrator/session/manager.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +168 -29
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/side-question.mjs +192 -0
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +17 -3
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +58 -2
- package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +41 -28
- package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +12 -1
- package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/store/write-guards.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +22 -10
- package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/store.mjs +19 -3
- package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +77 -0
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +20 -1
- package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +12 -15
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +5 -5
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +14 -10
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +49 -34
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
- package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
- package/src/runtime/computer-bridge/action-schema.mjs +44 -21
- package/src/runtime/github/tool.mjs +92 -2
- package/src/runtime/memory/index.mjs +1 -0
- package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
- package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
- package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
- package/src/runtime/memory/lib/pg/process.mjs +65 -50
- package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
- package/src/runtime/memory/lib/pg/supervisor.mjs +124 -16
- package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
- package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
- package/src/runtime/office/README.md +2 -2
- package/src/runtime/office/authoring/html-document-author.mjs +2 -0
- package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-measure.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +2 -0
- package/src/runtime/office/core/office-actions-read.mjs +3 -0
- package/src/runtime/office/core/office-render-preview.mjs +2 -0
- package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
- package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
- package/src/runtime/office/core/office-sessions.mjs +5 -0
- package/src/runtime/office/core/office-transactions.mjs +3 -0
- package/src/runtime/office/core/office-write-ledger.mjs +98 -0
- package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
- package/src/runtime/office/index.mjs +30 -0
- package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
- package/src/runtime/office/pdf/pdf-render.mjs +23 -7
- package/src/runtime/office/pdf/pdf-security.mjs +2 -0
- package/src/runtime/office/portable/portable-opc.mjs +4 -1
- package/src/runtime/office/quality/visual-diff.mjs +2 -0
- package/src/runtime/office/shared/values.mjs +0 -5
- package/src/runtime/shared/background-tasks.mjs +92 -14
- package/src/runtime/shared/bounded-file-read.mjs +13 -0
- package/src/runtime/shared/bounded-line-diff.mjs +182 -0
- package/src/runtime/shared/buffered-appender.mjs +18 -0
- package/src/runtime/shared/config.mjs +78 -18
- package/src/runtime/shared/err-text.mjs +31 -0
- package/src/runtime/shared/error-presentation.mjs +159 -19
- package/src/runtime/shared/file-permissions.d.mts +6 -1
- package/src/runtime/shared/file-permissions.mjs +54 -6
- package/src/runtime/shared/llm/anthropic-betas.mjs +4 -3
- package/src/runtime/shared/llm/anthropic-effort.mjs +129 -134
- package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +50 -14
- package/src/runtime/shared/llm/model-catalog.mjs +53 -40
- package/src/runtime/shared/llm/openai-daybreak.mjs +4 -16
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +11 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +13 -4
- package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
- package/src/runtime/shared/llm/usage-rollup.mjs +0 -1
- package/src/runtime/shared/loopback-listener.mjs +9 -0
- package/src/runtime/shared/model-display.mjs +13 -0
- package/src/runtime/shared/provider-api-key.mjs +2 -0
- package/src/runtime/shared/quota-resume-store.mjs +11 -0
- package/src/runtime/shared/review-diff.mjs +52 -0
- package/src/runtime/shared/session-baseline-store.mjs +960 -0
- package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
- package/src/runtime/shared/session-sidebar-host.mjs +38 -0
- package/src/runtime/shared/slow-span.mjs +114 -0
- package/src/runtime/shared/statusline/statusline-format.mjs +4 -4
- package/src/runtime/shared/statusline/statusline-segments.mjs +28 -4
- package/src/runtime/shared/task-notification-envelope.mjs +2 -2
- package/src/runtime/shared/tool-card-model/card-header.mjs +6 -1
- package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
- package/src/runtime/shared/tool-card-model.mjs +5 -2
- package/src/runtime/shared/tool-output-limit.mjs +4 -0
- package/src/runtime/shared/tool-primitives.mjs +13 -0
- package/src/runtime/shared/tool-result-summary.mjs +8 -1
- package/src/runtime/shared/tool-surface.mjs +18 -3
- package/src/runtime/shared/tool-work-units.mjs +40 -4
- package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
- package/src/runtime/shared/transcript-writer.mjs +10 -2
- package/src/runtime/shared/turn-changes.mjs +670 -274
- package/src/runtime/shared/turn-review-reply.mjs +8 -39
- package/src/runtime/shared/turn-snapshot-store.mjs +94 -2
- package/src/runtime/shared/turn-snapshot.mjs +986 -690
- package/src/runtime/shared/turn-worktree-snapshot.mjs +279 -262
- package/src/runtime/shared/user-data-guard.mjs +262 -49
- package/src/runtime/shared/worktrees/carry.mjs +531 -0
- package/src/runtime/shared/worktrees/contract.mjs +34 -24
- package/src/runtime/shared/worktrees/file-recovery.mjs +68 -0
- package/src/runtime/shared/worktrees/git-head.mjs +205 -0
- package/src/runtime/shared/worktrees/git.mjs +8 -3
- package/src/runtime/shared/worktrees/maintenance.mjs +1 -1
- package/src/runtime/shared/worktrees/manager.mjs +156 -8
- package/src/runtime/shared/worktrees/merge.mjs +31 -21
- package/src/runtime/shared/worktrees/paths.d.mts +6 -0
- package/src/runtime/shared/worktrees/test-support.mjs +19 -4
- package/src/runtime/terminal-bridge/client.mjs +44 -11
- package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
- package/src/runtime/tidy/apply.mjs +47 -2
- package/src/runtime/tidy/run-engines.mjs +11 -5
- package/src/session-runtime/agent-tool-routing.mjs +19 -13
- package/src/session-runtime/boot/apis.mjs +19 -5
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/infrastructure.mjs +12 -1
- package/src/session-runtime/boot/session.mjs +0 -1
- package/src/session-runtime/boot/tools.mjs +4 -1
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +65 -0
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +11 -4
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +115 -18
- package/src/session-runtime/internal-tool-executor.mjs +6 -2
- package/src/session-runtime/lifecycle/cold-heir.mjs +188 -0
- package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
- package/src/session-runtime/lifecycle/session-catalog.mjs +14 -3
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +29 -6
- package/src/session-runtime/lifecycle/teardown.mjs +73 -8
- package/src/session-runtime/lifecycle-api.mjs +1 -0
- package/src/session-runtime/mcp-glue/connect.mjs +46 -14
- package/src/session-runtime/mcp-glue/server-catalog.mjs +20 -3
- package/src/session-runtime/mcp-glue.mjs +3 -0
- package/src/session-runtime/mcp-oauth-login.mjs +174 -0
- package/src/session-runtime/model-route/model-switch-target.mjs +34 -0
- package/src/session-runtime/model-route/set-route.mjs +85 -17
- package/src/session-runtime/model-route/web-search-route.mjs +1 -1
- package/src/session-runtime/native-web-search/routes.mjs +22 -3
- package/src/session-runtime/native-web-search-usage.mjs +51 -0
- package/src/session-runtime/native-web-search.mjs +10 -1
- package/src/session-runtime/new-session-config.mjs +4 -2
- package/src/session-runtime/provider-auth/login.mjs +4 -0
- package/src/session-runtime/provider-models/model-meta.mjs +12 -3
- package/src/session-runtime/quick-model-rows/web-search-rows.mjs +13 -8
- package/src/session-runtime/quick-web-search-models.mjs +13 -38
- package/src/session-runtime/resource-extension-sync.mjs +4 -0
- package/src/session-runtime/resource-mcp-api.mjs +98 -2
- package/src/session-runtime/resource-scope-decorate.mjs +10 -3
- package/src/session-runtime/runtime-review-api.mjs +21 -2
- package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
- package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +13 -1
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +7 -2
- package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
- package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +73 -7
- package/src/session-runtime/services/agent-tool/send-flow.mjs +22 -4
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +2 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +22 -5
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +15 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +8 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -2
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
- package/src/session-runtime/services/agent-tool/worker-index.mjs +46 -7
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +17 -0
- package/src/session-runtime/services/agent-tool.mjs +3 -0
- package/src/session-runtime/services/channel-admin.mjs +19 -3
- package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
- package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
- package/src/session-runtime/services/provider-admin.mjs +81 -15
- package/src/session-runtime/session-transcript-purge.mjs +32 -0
- package/src/session-runtime/session-turn-api.mjs +14 -5
- package/src/session-runtime/settings-builtin-tools-api.mjs +9 -0
- package/src/session-runtime/settings-compaction-api.mjs +1 -0
- package/src/session-runtime/setup-tool/executor.mjs +36 -6
- package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
- package/src/session-runtime/setup-tool/settings-contract.mjs +13 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +13 -4
- package/src/session-runtime/skills-api.mjs +3 -5
- package/src/session-runtime/tool-surface.mjs +5 -1
- package/src/session-runtime/turn/compaction-gate.mjs +25 -0
- package/src/session-runtime/turn/session-ops.mjs +7 -5
- package/src/session-runtime/turn/side-question-ops.mjs +22 -0
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +5 -1
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +8 -3
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +10 -0
- package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
- package/src/session-runtime/turn/turn-run.mjs +25 -9
- package/src/session-runtime/usage-stats-api.mjs +43 -11
- package/src/session-runtime/workspace/project-branches.mjs +7 -5
- package/src/session-runtime/workspace/transition-steps.mjs +129 -31
- package/src/session-runtime/workspace/transitions.mjs +190 -15
- package/src/standalone/daemon-agent-control.mjs +9 -1
- package/src/standalone/daemon-drain-policy.mjs +8 -0
- package/src/standalone/daemon-local-session-bridge.mjs +14 -1
- package/src/standalone/daemon-owner.mjs +17 -4
- package/src/standalone/daemon-pg-stop.mjs +51 -0
- package/src/standalone/daemon-stop-budget.d.mts +2 -0
- package/src/standalone/daemon-stop-budget.mjs +18 -0
- package/src/standalone/daemon-stored-session-views.mjs +2 -0
- package/src/standalone/daemon-telemetry.mjs +74 -0
- package/src/standalone/daemon.mjs +64 -8
- package/src/standalone/desktop-service-registry.mjs +5 -0
- package/src/standalone/local-session-runtime.mjs +70 -19
- package/src/standalone/session-client.mjs +42 -0
- package/src/standalone/session-protocol.mjs +14 -0
- package/src/standalone/session-proxy/projection.mjs +41 -4
- package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
- package/src/standalone/session-runtime-inline-host.mjs +1 -0
- package/src/standalone/session-service/agent-tree/agent-cancel.mjs +33 -2
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +26 -10
- package/src/standalone/session-service/agent-tree.mjs +12 -0
- package/src/standalone/session-service/quota-resume.mjs +8 -0
- package/src/standalone/session-service/retention/busy.mjs +15 -1
- package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
- package/src/standalone/session-service-api.mjs +11 -1
- package/src/standalone/session-service.mjs +1 -0
- package/src/standalone/session-state-patch.d.mts +2 -1
- package/src/standalone/session-state-patch.mjs +41 -1
- package/src/tui/App.jsx +25 -0
- package/src/tui/app/app-view/floating-panel.jsx +26 -1
- package/src/tui/app/app-view.jsx +1 -0
- package/src/tui/app/btw-controller.mjs +118 -0
- package/src/tui/app/create-app-pickers.mjs +6 -0
- package/src/tui/app/extension-pickers/mcp-login.mjs +107 -0
- package/src/tui/app/extension-pickers/mcp-servers-picker.mjs +2 -1
- package/src/tui/app/extension-pickers.mjs +2 -1
- package/src/tui/app/model-options.mjs +11 -16
- package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
- package/src/tui/app/shell-layout/surfaces.mjs +3 -1
- package/src/tui/app/slash-commands.mjs +20 -5
- package/src/tui/app/slash-dispatch/panel-commands.mjs +16 -1
- package/src/tui/app/slash-dispatch/session-commands.mjs +19 -6
- package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
- package/src/tui/app/use-global-key-input.mjs +5 -12
- package/src/tui/app/use-prompt-handlers.mjs +11 -0
- package/src/tui/components/BtwPanel.jsx +53 -0
- package/src/tui/components/QuestionPanel.jsx +275 -0
- package/src/tui/components/StatusLine.jsx +2 -0
- package/src/tui/components/question-panel-model.mjs +156 -0
- package/src/tui/components/status-line/local-line.mjs +5 -2
- package/src/tui/components/status-line/use-statusline-text.mjs +7 -1
- package/src/tui/dist/index.mjs +3221 -1500
- package/src/tui/session/context-state.mjs +4 -2
- package/src/tui/session/quota-resume.mjs +46 -14
- package/src/tui/session/session-api/commands.mjs +43 -24
- package/src/tui/session/session-api/controls.mjs +2 -2
- package/src/tui/session/session-api/extensions.mjs +22 -0
- package/src/tui/session/session-api/integrations.mjs +16 -2
- package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
- package/src/tui/session/session-api/lifecycle.mjs +7 -2
- package/src/tui/session/session-api/routes.mjs +71 -7
- package/src/tui/session/session-api/settings.mjs +11 -14
- package/src/tui/session/session-api.mjs +1 -0
- package/src/tui/session/session-flow/drain.mjs +7 -1
- package/src/tui/session/session-flow/failed-turn-rewind.mjs +10 -4
- package/src/tui/session/tool-approval.mjs +10 -7
- package/src/tui/session/transcript-spill.mjs +14 -7
- package/src/tui/session/turn-stream.mjs +174 -31
- package/src/tui/session/turn.mjs +46 -16
- package/src/tui/statusline-ansi-bridge.mjs +1 -1
- package/src/ui/statusline-agents.mjs +15 -4
- package/src/ui/statusline.mjs +7 -3
- package/src/ui/streaming-markdown-heal.mjs +34 -3
- package/src/vendor/statusline/src/gateway/claude-current.mjs +14 -4
- package/src/workflows/default/WORKFLOW.md +3 -1
- package/src/runtime/memory/lib/memory-session-merge.mjs +0 -32
- package/src/runtime/shared/llm/usage-session-history.mjs +0 -266
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* src/session-runtime/lifecycle/inheritance.mjs - session inheritance
|
|
3
3
|
* (/inherit): fit preflight and the carry of another session's conversation
|
|
4
|
-
* into the freshly created heir
|
|
4
|
+
* into the freshly created heir — the live one (inheritFrom) or a cold sibling
|
|
5
|
+
* persisted without switching (inheritToNewSession), through one carry core.
|
|
5
6
|
*/
|
|
6
7
|
import { hasUserConversationMessage } from '../../runtime/agent/orchestrator/session/manager/prompt-utils.mjs';
|
|
7
8
|
import { stripEffortConfiguration } from '../../runtime/agent/orchestrator/providers/effort-configuration.mjs';
|
|
@@ -14,6 +15,7 @@ import {
|
|
|
14
15
|
inheritanceRouteTarget,
|
|
15
16
|
} from '../inheritance-fit.mjs';
|
|
16
17
|
import { clean } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
18
|
+
import { buildColdHeir, committedSource, persistColdHeir } from './cold-heir.mjs';
|
|
17
19
|
|
|
18
20
|
export function createInheritance(deps, { compactConversation, saveSession }) {
|
|
19
21
|
const { getSession, getRoute, mgr, createCurrentSession, invalidateContextStatusCache, getReservedSessionId } = deps;
|
|
@@ -143,6 +145,44 @@ export function createInheritance(deps, { compactConversation, saveSession }) {
|
|
|
143
145
|
};
|
|
144
146
|
}
|
|
145
147
|
|
|
148
|
+
/**
|
|
149
|
+
* The ONE carry every inheritance path shares: measure the source's
|
|
150
|
+
* conversation on the heir's scale, compact it for the heir when asked to
|
|
151
|
+
* or when it cannot fit, and append it to the (empty) heir with its
|
|
152
|
+
* inheritance boundary. Refusals throw before the heir is touched; the
|
|
153
|
+
* source is never mutated.
|
|
154
|
+
*/
|
|
155
|
+
async function carryConversation(source, target, { compact = false } = {}) {
|
|
156
|
+
// System blocks belong to the session that BUILT them: the target's own
|
|
157
|
+
// prompt was composed for the current model, tool surface, and workflow.
|
|
158
|
+
// Only the conversation itself travels.
|
|
159
|
+
let carried = inheritableMessages(source.messages);
|
|
160
|
+
if (!hasUserConversationMessage(carried)) {
|
|
161
|
+
throw new Error('inheritFrom: the source session has no conversation to carry');
|
|
162
|
+
}
|
|
163
|
+
// Decide BEFORE anything moves, on the heir's own scale. This is the
|
|
164
|
+
// same function inheritancePreflight() answers with, so the surface that
|
|
165
|
+
// offered the carry and the runtime that performs it cannot disagree —
|
|
166
|
+
// and a refusal no longer has to unwind a half-filled transcript.
|
|
167
|
+
const fit = inheritanceFit(carried, target);
|
|
168
|
+
let compacted = false;
|
|
169
|
+
// compact:true summarizes even a conversation that fits; otherwise only
|
|
170
|
+
// one that cannot fit is compacted.
|
|
171
|
+
if (compact || (fit.known && !fit.fits)) {
|
|
172
|
+
const next = await fitConversationForHeir(source, target, carried, fit, { required: compact });
|
|
173
|
+
compacted = next !== carried;
|
|
174
|
+
carried = next;
|
|
175
|
+
}
|
|
176
|
+
target.messages.push(
|
|
177
|
+
...stripEffortConfiguration(inheritedCompatReplayMessages(structuredClone(carried), source.provider))
|
|
178
|
+
);
|
|
179
|
+
target.inheritedFromSessionId = source.id;
|
|
180
|
+
target.updatedAt = Date.now();
|
|
181
|
+
recordInheritanceBoundary(target, source);
|
|
182
|
+
if (!clean(target.title) && clean(source.title)) target.title = source.title;
|
|
183
|
+
return { messages: carried.length, compacted };
|
|
184
|
+
}
|
|
185
|
+
|
|
146
186
|
/**
|
|
147
187
|
* Session inheritance (/inherit): carry another session's conversation
|
|
148
188
|
* into THIS freshly created session, so the transcript continues under a
|
|
@@ -174,41 +214,45 @@ export function createInheritance(deps, { compactConversation, saveSession }) {
|
|
|
174
214
|
}
|
|
175
215
|
const source = mgr.getSession(id);
|
|
176
216
|
if (!source) throw new Error(`inheritFrom: session ${id} was not found`);
|
|
177
|
-
|
|
178
|
-
// prompt was composed for the current model, tool surface, and workflow.
|
|
179
|
-
// Only the conversation itself travels.
|
|
180
|
-
let carried = inheritableMessages(source.messages);
|
|
181
|
-
if (!hasUserConversationMessage(carried)) {
|
|
182
|
-
throw new Error('inheritFrom: the source session has no conversation to carry');
|
|
183
|
-
}
|
|
184
|
-
// Decide BEFORE anything moves, on the heir's own scale. This is the
|
|
185
|
-
// same function inheritancePreflight() answers with, so the surface that
|
|
186
|
-
// offered the carry and the runtime that performs it cannot disagree —
|
|
187
|
-
// and a refusal no longer has to unwind a half-filled transcript.
|
|
188
|
-
const fit = inheritanceFit(carried, target);
|
|
189
|
-
// compact:true summarizes even a conversation that fits; otherwise only
|
|
190
|
-
// one that cannot fit is compacted.
|
|
191
|
-
if (compact || (fit.known && !fit.fits)) {
|
|
192
|
-
carried = await fitConversationForHeir(source, target, carried, fit, { required: compact });
|
|
193
|
-
}
|
|
194
|
-
target.messages.push(
|
|
195
|
-
...stripEffortConfiguration(inheritedCompatReplayMessages(structuredClone(carried), source.provider))
|
|
196
|
-
);
|
|
217
|
+
const { messages } = await carryConversation(source, target, { compact });
|
|
197
218
|
invalidateContextStatusCache();
|
|
198
|
-
target.inheritedFromSessionId = source.id;
|
|
199
|
-
target.updatedAt = Date.now();
|
|
200
|
-
recordInheritanceBoundary(target, source);
|
|
201
|
-
if (!clean(target.title) && clean(source.title)) target.title = source.title;
|
|
202
219
|
saveSession(target, { immediate: true });
|
|
203
220
|
invalidateContextStatusCache();
|
|
204
221
|
return {
|
|
205
222
|
sessionId: target.id,
|
|
206
223
|
sourceSessionId: source.id,
|
|
207
|
-
messages
|
|
224
|
+
messages,
|
|
208
225
|
provider: target.provider,
|
|
209
226
|
model: target.model,
|
|
210
227
|
};
|
|
211
228
|
}
|
|
212
229
|
|
|
213
|
-
|
|
230
|
+
/**
|
|
231
|
+
* Inheritance WITHOUT switching: carry a session's conversation (normally
|
|
232
|
+
* the live one, possibly mid-turn) into a NEW session on the same route,
|
|
233
|
+
* cwd and Project, persisted cold for a later resume. The live session
|
|
234
|
+
* stays the current one and is never mutated; only its committed turns
|
|
235
|
+
* travel. Same carry, compaction and refusals as inheritFrom().
|
|
236
|
+
*/
|
|
237
|
+
async function inheritToNewSession(sourceSessionId, { compact = false, titleSuffix = '' } = {}) {
|
|
238
|
+
const live = getSession();
|
|
239
|
+
const id = clean(sourceSessionId) || clean(live?.id);
|
|
240
|
+
if (!id) throw new TypeError('inheritToNewSession: source session id is required');
|
|
241
|
+
const stored = id === clean(live?.id) ? live : mgr.getSession(id);
|
|
242
|
+
if (!stored) throw new Error(`inheritFrom: session ${id} was not found`);
|
|
243
|
+
const source = committedSource(stored);
|
|
244
|
+
const heir = buildColdHeir(source);
|
|
245
|
+
const { messages, compacted } = await carryConversation(source, heir, { compact: compact === true });
|
|
246
|
+
// A suffixed title ("… (Fork)") tells the copy apart in session lists;
|
|
247
|
+
// locked as a model title so auto-titling keeps it, renames still win.
|
|
248
|
+
if (titleSuffix && clean(heir.title)) {
|
|
249
|
+
heir.title = `${clean(heir.title)}${titleSuffix}`;
|
|
250
|
+
heir.titleLocked = true;
|
|
251
|
+
heir.titleSource = 'ai';
|
|
252
|
+
}
|
|
253
|
+
await persistColdHeir(heir);
|
|
254
|
+
return { sessionId: heir.id, messages, compacted };
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return { inheritancePreflight, inheritFrom, inheritToNewSession };
|
|
214
258
|
}
|
|
@@ -15,6 +15,9 @@ import {
|
|
|
15
15
|
clean,
|
|
16
16
|
} from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
17
17
|
|
|
18
|
+
import { isRealTurnMessage } from '../../runtime/agent/orchestrator/session/compact/user-message-kind.mjs';
|
|
19
|
+
import { realTurnCount as realTurnCountOf } from '../../runtime/agent/orchestrator/session/store-summary-fields.mjs';
|
|
20
|
+
|
|
18
21
|
const VISIBLE_OWNERS = ['cli', 'user', 'mixdog'];
|
|
19
22
|
|
|
20
23
|
function isLeadShaped(s, owner, sourceType) {
|
|
@@ -39,7 +42,9 @@ function previewOf(s) {
|
|
|
39
42
|
const rawPreview = s.preview || '';
|
|
40
43
|
let preview = isSessionPreviewNoise(rawPreview) ? '' : cleanSessionPreview(rawPreview);
|
|
41
44
|
let messageCount = Math.max(0, Number(s.messageCount) || 0);
|
|
45
|
+
let realTurnCount = realTurnCountOf(s);
|
|
42
46
|
if (!preview && Array.isArray(s.messages)) {
|
|
47
|
+
realTurnCount = s.messages.filter(isRealTurnMessage).length;
|
|
43
48
|
const msgs = s.messages;
|
|
44
49
|
const userPreviews = msgs
|
|
45
50
|
.filter((m) => m && m.role === 'user')
|
|
@@ -50,10 +55,10 @@ function previewOf(s) {
|
|
|
50
55
|
preview = userPreviews[0] || '';
|
|
51
56
|
messageCount = msgs.filter((m) => m && (m.role === 'user' || m.role === 'assistant')).length;
|
|
52
57
|
}
|
|
53
|
-
return { preview, messageCount };
|
|
58
|
+
return { preview, messageCount, realTurnCount };
|
|
54
59
|
}
|
|
55
60
|
|
|
56
|
-
function leadSessionRow(s, heartbeatMtimes) {
|
|
61
|
+
export function leadSessionRow(s, heartbeatMtimes) {
|
|
57
62
|
// Durable visibility is the catalog boundary. Apply it before the legacy
|
|
58
63
|
// lead-shape heuristics so an explicitly agent-only child cannot leak just
|
|
59
64
|
// because its owner field looks ordinary.
|
|
@@ -66,10 +71,14 @@ function leadSessionRow(s, heartbeatMtimes) {
|
|
|
66
71
|
// One-shot `mixdog exec` runs are never resumable conversations.
|
|
67
72
|
if (sourceType === 'exec') return null;
|
|
68
73
|
if (!isLeadShaped(s, owner, sourceType)) return null;
|
|
69
|
-
const { preview, messageCount } = previewOf(s);
|
|
74
|
+
const { preview, messageCount, realTurnCount } = previewOf(s);
|
|
70
75
|
if (!preview && messageCount === 0) return null;
|
|
71
76
|
return {
|
|
72
77
|
id: s.id,
|
|
78
|
+
// Durable provenance the desktop uses to tell a real conversation from
|
|
79
|
+
// resume scratch or synthetic-only rows when no title source survives.
|
|
80
|
+
...(realTurnCount === null ? {} : { realTurnCount }),
|
|
81
|
+
...(s.detachedReason ? { detachedReason: s.detachedReason } : {}),
|
|
73
82
|
updatedAt: s.updatedAt,
|
|
74
83
|
// Conversation-activity timestamp for Recent ordering. Without this the
|
|
75
84
|
// desktop falls back to updatedAt, which detach/resume bookkeeping
|
|
@@ -93,6 +102,8 @@ function leadSessionRow(s, heartbeatMtimes) {
|
|
|
93
102
|
// sessions under the sidebar Automations section instead of Recent.
|
|
94
103
|
sourceType: sourceType || null,
|
|
95
104
|
sourceName: clean(s.sourceName || '') || null,
|
|
105
|
+
createdAt: Number(s.createdAt) || 0,
|
|
106
|
+
inheritedFromSessionId: clean(s.inheritedFromSessionId || '') || null,
|
|
96
107
|
};
|
|
97
108
|
}
|
|
98
109
|
|
|
@@ -13,6 +13,8 @@ import { isScratchConversation } from '../shared.mjs';
|
|
|
13
13
|
import { compactionArchiveRange } from '../../../runtime/agent/orchestrator/session/compaction-archive.mjs';
|
|
14
14
|
import { stampCompactionMessageIds } from '../../../runtime/agent/orchestrator/session/compaction-archive-capture.mjs';
|
|
15
15
|
import { boundWorkspaceCwd, restoreWorkspaceAfterResume } from '../../workspace/workspace-state.mjs';
|
|
16
|
+
import { toolExposureMigrationNeeded } from '../../../runtime/agent/orchestrator/runtime-core/tool-exposure.mjs';
|
|
17
|
+
import { markToolSurfaceMigrated } from '../../../runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs';
|
|
16
18
|
|
|
17
19
|
export function resolveResumeCwd(session, currentCwd) {
|
|
18
20
|
// A worktree-bound Lead resumes in its worktree whatever its desktop class;
|
|
@@ -61,10 +63,14 @@ export function createSessionResume(deps, { ingestSessionIntoMemory, closeSurfac
|
|
|
61
63
|
} = deps;
|
|
62
64
|
|
|
63
65
|
function restoreResumedToolSurface(target, targetRoute) {
|
|
66
|
+
// A surface persisted with another tool exposure (e.g. a pre-bridge
|
|
67
|
+
// fixed canonical surface) migrates here; legacy selections never widen it.
|
|
68
|
+
const migrating = toolExposureMigrationNeeded(target, targetRoute.provider);
|
|
64
69
|
applyDeferredToolSurface(target, deferredSurfaceModeForLead(getMode()), getStandaloneTools(), {
|
|
65
70
|
provider: targetRoute.provider,
|
|
66
71
|
model: targetRoute.model,
|
|
67
72
|
});
|
|
73
|
+
if (migrating) markToolSurfaceMigrated(target);
|
|
68
74
|
}
|
|
69
75
|
|
|
70
76
|
// The resumed session's OWN effort wins. resolveRoute always returns an
|
|
@@ -5,7 +5,12 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { clean } from '../../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
7
7
|
import { forgetSessionSearch } from '../../../runtime/session-search/session-search-ingest.mjs';
|
|
8
|
-
import {
|
|
8
|
+
import { leadSessionRow } from '../session-catalog.mjs';
|
|
9
|
+
import { getStoreDir } from '../../../runtime/agent/orchestrator/session/store/paths-heartbeat.mjs';
|
|
10
|
+
import {
|
|
11
|
+
STORED_SESSION_UNREADABLE,
|
|
12
|
+
_storedSessionFromFile,
|
|
13
|
+
} from '../../../runtime/agent/orchestrator/session/store/serialize.mjs';
|
|
9
14
|
import { SESSION_ID_PATTERN } from '../shared.mjs';
|
|
10
15
|
import { replacementSessionCwd } from '../../workspace/workspace-state.mjs';
|
|
11
16
|
|
|
@@ -50,6 +55,15 @@ export function createSessionDelete(deps, { cancelBackgroundTasks }) {
|
|
|
50
55
|
}
|
|
51
56
|
}
|
|
52
57
|
|
|
58
|
+
// Availability is one strict read of the session's own file, filtered like
|
|
59
|
+
// the Lead catalog (an unreadable, foreign, closed or non-Lead record is not
|
|
60
|
+
// deletable). No catalog rebuild, no folder scan.
|
|
61
|
+
function isAvailableLead(sessionId) {
|
|
62
|
+
const stored = _storedSessionFromFile(getStoreDir(), `${sessionId}.json`);
|
|
63
|
+
if (!stored || stored === STORED_SESSION_UNREADABLE || stored.closed === true) return false;
|
|
64
|
+
return leadSessionRow(stored, new Map()) !== null;
|
|
65
|
+
}
|
|
66
|
+
|
|
53
67
|
// The deleted task's worktree: the autoCleanup setting decides (clean and
|
|
54
68
|
// merged → removed; otherwise kept). Off the deletion path; never fails it.
|
|
55
69
|
function releaseDeletedWorktree(sessionId) {
|
|
@@ -61,12 +75,18 @@ export function createSessionDelete(deps, { cancelBackgroundTasks }) {
|
|
|
61
75
|
async function deleteSession(id) {
|
|
62
76
|
const sessionId = clean(id);
|
|
63
77
|
if (!sessionId || !SESSION_ID_PATTERN.test(sessionId)) return false;
|
|
64
|
-
|
|
65
|
-
if (!available) return false;
|
|
78
|
+
if (!isAvailableLead(sessionId)) return false;
|
|
66
79
|
const childIds = ownedAgentSessionIds(sessionId);
|
|
67
80
|
const current = getSession();
|
|
81
|
+
const cleanupReason = 'desktop-session-delete';
|
|
68
82
|
if (current?.id !== sessionId) {
|
|
69
|
-
|
|
83
|
+
// A turn can still be running in a session that is no longer current.
|
|
84
|
+
// Stop its runtime first (controller abort, shells, generation bump) and
|
|
85
|
+
// release its lead row, agents and tasks, so nothing can write it back.
|
|
86
|
+
if (mgr.closeSession(sessionId, cleanupReason, { tombstone: false }) !== true) return false;
|
|
87
|
+
agentTool?.forgetLeadSession?.(sessionId);
|
|
88
|
+
releaseSessionWork(sessionId, cleanupReason);
|
|
89
|
+
const deleted = mgr.deleteSession(sessionId, { fenceWrites: true }) === true;
|
|
70
90
|
if (!deleted) return false;
|
|
71
91
|
void forgetSessionSearch(sessionId);
|
|
72
92
|
// The parent is already irreversibly gone, so child cleanup is
|
|
@@ -74,7 +94,7 @@ export function createSessionDelete(deps, { cancelBackgroundTasks }) {
|
|
|
74
94
|
// because its retained-parent proof disappeared with the parent.
|
|
75
95
|
for (const childId of childIds) {
|
|
76
96
|
try {
|
|
77
|
-
mgr.deleteSession(childId);
|
|
97
|
+
mgr.deleteSession(childId, { fenceWrites: true });
|
|
78
98
|
} catch {}
|
|
79
99
|
}
|
|
80
100
|
void releaseDeletedWorktree(sessionId);
|
|
@@ -83,12 +103,15 @@ export function createSessionDelete(deps, { cancelBackgroundTasks }) {
|
|
|
83
103
|
// Leaving a worktree-bound Lead: the replacement starts in the Project
|
|
84
104
|
// folder, and the worktree can go once nothing runs in it.
|
|
85
105
|
const projectFolder = replacementSessionCwd(current);
|
|
86
|
-
const cleanupReason = 'desktop-session-delete';
|
|
87
106
|
releaseSessionWork(sessionId, cleanupReason);
|
|
88
107
|
// Active sessions retain a tombstone until the normal sweep. Unlinking
|
|
89
108
|
// immediately would let a late provider/save continuation resurrect the
|
|
90
109
|
// deleted conversation after the user has moved to its replacement.
|
|
91
110
|
if (mgr.closeSession(sessionId, cleanupReason, { tombstone: true }) !== true) return false;
|
|
111
|
+
// The unwinding turn's late saves and its idle lead-row upsert must not
|
|
112
|
+
// touch the deleted conversation (an unguarded save would pass the tombstone).
|
|
113
|
+
mgr.fenceSessionWrites?.(sessionId);
|
|
114
|
+
agentTool?.forgetLeadSession?.(sessionId);
|
|
92
115
|
void forgetSessionSearch(sessionId);
|
|
93
116
|
// Active parent deletion uses the same durable tombstone boundary for
|
|
94
117
|
// every linked child. Their files then mature with the parent instead of
|
|
@@ -7,11 +7,13 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { SessionClosedError } from '../../runtime/agent/orchestrator/session/manager/session-errors.mjs';
|
|
9
9
|
import { forgetSessionSaveBaseline } from '../../runtime/agent/orchestrator/session/store/save-worker.mjs';
|
|
10
|
+
import { flushAllIndexWrites } from '../services/agent-tool/index-write-queue.mjs';
|
|
10
11
|
import { unregisterLiveSession } from '../../runtime/shared/staged-update.mjs';
|
|
11
12
|
import { abortRuntime, closeCanonicalSession, closeOwnSession, dispatchSessionEnd } from './teardown/session-close.mjs';
|
|
12
13
|
import { settleAll, settleDetached, startRuntimeStops, startWorkStops } from './teardown/runtime-stops.mjs';
|
|
13
14
|
|
|
14
|
-
const
|
|
15
|
+
const CLOSE_ALL_DEADLINE_MS = 5000;
|
|
16
|
+
const PROCESS_EXIT_REASON =/exit|quit|shutdown|sighup|sigint|sigterm/;
|
|
15
17
|
const WARMUP_TIMER_KEYS = [
|
|
16
18
|
'providerSetupWarmupTimer',
|
|
17
19
|
'providerWarmupTimer',
|
|
@@ -118,6 +120,45 @@ export function createTeardown(deps, { ingestSessionIntoMemory, closeSurfaceSess
|
|
|
118
120
|
} catch {}
|
|
119
121
|
}
|
|
120
122
|
|
|
123
|
+
// Agent closes that have not settled yet (one per close invocation, kept
|
|
124
|
+
// past the bounded wait if it overran).
|
|
125
|
+
const outstandingCloses = new Set();
|
|
126
|
+
|
|
127
|
+
/** Persist every queued index write. A close only ever drains: the shared
|
|
128
|
+
* indexes stay registered (exit hook included) for the closes still to come. */
|
|
129
|
+
async function drainIndexWrites() {
|
|
130
|
+
try {
|
|
131
|
+
await agentTool.flushIndexWrites?.();
|
|
132
|
+
await flushAllIndexWrites();
|
|
133
|
+
} catch {}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// The disposal in progress (if any). New closes wait for it before starting
|
|
137
|
+
// their own closeAll, so no close produces writes while registrations are
|
|
138
|
+
// being released.
|
|
139
|
+
let indexDisposal = null;
|
|
140
|
+
|
|
141
|
+
/** Release this runtime's per-runtime index registrations (exit callbacks,
|
|
142
|
+
* approval writer, store refs) once its drain has completed. Idempotent. A
|
|
143
|
+
* drain that cannot complete tears nothing down: the registrations stay until
|
|
144
|
+
* a later close drains successfully. Exit flushing itself is process-owned. */
|
|
145
|
+
function disposeIndexes(settle) {
|
|
146
|
+
// Assign before disposal runs (deferred), clear on settlement: a synchronous
|
|
147
|
+
// dispose must not clear the slot before it is assigned.
|
|
148
|
+
indexDisposal ??= Promise.resolve()
|
|
149
|
+
.then(async () => {
|
|
150
|
+
if (typeof agentTool.disposeAsync === 'function') await agentTool.disposeAsync({ settle });
|
|
151
|
+
else agentTool.dispose?.({ settle });
|
|
152
|
+
})
|
|
153
|
+
.catch(() => {
|
|
154
|
+
/* drain failed: registrations are kept for a later retry */
|
|
155
|
+
})
|
|
156
|
+
.finally(() => {
|
|
157
|
+
indexDisposal = null;
|
|
158
|
+
});
|
|
159
|
+
return indexDisposal;
|
|
160
|
+
}
|
|
161
|
+
|
|
121
162
|
async function close(reason = 'cli-exit', options = {}) {
|
|
122
163
|
quiesce(reason);
|
|
123
164
|
const scope = teardownScope(reason, options, String(getSession()?.id || ''));
|
|
@@ -160,16 +201,40 @@ export function createTeardown(deps, { ingestSessionIntoMemory, closeSurfaceSess
|
|
|
160
201
|
// memory and must leave workers/rows for the re-materialized owner.
|
|
161
202
|
// Scoped teardown closes only THIS session's workers — the worker index
|
|
162
203
|
// is shared across every Lead in the process.
|
|
204
|
+
let closing = null;
|
|
205
|
+
while (indexDisposal) await indexDisposal;
|
|
163
206
|
if (scope.teardownReapsWork) {
|
|
207
|
+
// Every close runs its OWN scope's closeAll: a scoped close for one Lead
|
|
208
|
+
// never stands in for a process-wide close. Closing produces final index
|
|
209
|
+
// writes (settled rows, tombstones); the deadline only bounds how long
|
|
210
|
+
// teardown waits and does not stop the close.
|
|
211
|
+
const settled = () => {
|
|
212
|
+
outstandingCloses.delete(closing);
|
|
213
|
+
};
|
|
214
|
+
closing = new Promise((resolve) =>
|
|
215
|
+
resolve(agentTool.closeAll(reason, scope.scopedTeardown ? { callerSessionId: scope.closingSessionId } : {}))
|
|
216
|
+
).then(settled, settled);
|
|
217
|
+
outstandingCloses.add(closing);
|
|
164
218
|
try {
|
|
165
|
-
|
|
219
|
+
await withTeardownDeadline(closing, CLOSE_ALL_DEADLINE_MS, false);
|
|
166
220
|
} catch {}
|
|
167
221
|
}
|
|
168
|
-
//
|
|
169
|
-
//
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
222
|
+
// Drain after the closes settle, then release this runtime's index
|
|
223
|
+
// registrations. A close that overran its deadline chains this onto its
|
|
224
|
+
// settlement (teardown may return before then). The live outstanding set is
|
|
225
|
+
// re-checked after every wait and drain, so the single disposal runs only
|
|
226
|
+
// when no close is outstanding; the check and the disposal start share one
|
|
227
|
+
// tick, and closes admitted afterwards wait for it.
|
|
228
|
+
const finish = async () => {
|
|
229
|
+
for (;;) {
|
|
230
|
+
while (outstandingCloses.size > 0) await Promise.allSettled([...outstandingCloses]);
|
|
231
|
+
await drainIndexWrites();
|
|
232
|
+
if (outstandingCloses.size === 0) break;
|
|
233
|
+
}
|
|
234
|
+
await disposeIndexes(scope.teardownReapsWork === true);
|
|
235
|
+
};
|
|
236
|
+
if (outstandingCloses.size > 0) void finish();
|
|
237
|
+
else await finish();
|
|
173
238
|
const { ok, stops } = await inOwnLoopTurn(() => {
|
|
174
239
|
const runtimeStops = startRuntimeStops(deps, reason, scope);
|
|
175
240
|
const closed = closeOwnSession(deps, closeSurfaceSession, reason);
|
|
@@ -178,7 +243,7 @@ export function createTeardown(deps, { ingestSessionIntoMemory, closeSurfaceSess
|
|
|
178
243
|
if (scope.detach) await settleDetached(withTeardownDeadline, stops);
|
|
179
244
|
else await settleAll(withTeardownDeadline, stops);
|
|
180
245
|
// The session went away (idle eviction included): free its save baselines.
|
|
181
|
-
if (scope.closingSessionId) forgetSessionSaveBaseline(scope.closingSessionId);
|
|
246
|
+
if (scope.closingSessionId) forgetSessionSaveBaseline(scope.closingSessionId, { releaseWriteControl: true });
|
|
182
247
|
// Self-update stages in the background and swaps on the next clean launch
|
|
183
248
|
// (see staged-update.mjs) — nothing installs at shutdown. On a real
|
|
184
249
|
// process exit we just drop this session's live-refcount pid file so a
|
|
@@ -24,11 +24,17 @@ export function createMcpConnect({
|
|
|
24
24
|
const fingerprint = (cfg) => JSON.stringify(cfg);
|
|
25
25
|
// Roots advertised by cwd-following servers track this runtime's cwd.
|
|
26
26
|
const syncScopeRoot = () => mcpClient.setMcpScopeRoot?.(getMcpScopeId(), clean(getCurrentCwd?.()));
|
|
27
|
+
// Abort the pending interactive OAuth login of one server's connect.
|
|
28
|
+
const cancelMcpLogin = (name) => mcpClient.cancelMcpLogin?.(clean(name), scopeOptions());
|
|
29
|
+
// Answer it with the redirect URL pasted from the browser.
|
|
30
|
+
const completeMcpLogin = (name, callbackUrl) => mcpClient.completeMcpLogin(clean(name), callbackUrl, scopeOptions());
|
|
27
31
|
|
|
28
32
|
// Connect/disconnect exactly one server in the live registry, leaving all
|
|
29
33
|
// others untouched. Used by the enable/disable toggle so a single-server
|
|
30
|
-
// change never triggers a full disconnectAll()/reconnect freeze.
|
|
31
|
-
|
|
34
|
+
// change never triggers a full disconnectAll()/reconnect freeze. Only an
|
|
35
|
+
// explicit sign-in passes `login` ({ openBrowser }): every other connect is
|
|
36
|
+
// non-interactive and reports a server that needs one as sign-in required.
|
|
37
|
+
async function applyMcpServerConnection(name, enabled, servers = resolveEffectiveMcpServers().servers, login = null) {
|
|
32
38
|
const target = clean(name);
|
|
33
39
|
if (!target) return;
|
|
34
40
|
// Changing this server's state clears any stale failure record for it.
|
|
@@ -46,11 +52,16 @@ export function createMcpConnect({
|
|
|
46
52
|
// between the close and the connect never resurrects the server.
|
|
47
53
|
try {
|
|
48
54
|
ensurePluginServerData(cfg);
|
|
49
|
-
await mcpClient.reconnectSingleMcpServer(
|
|
55
|
+
await mcpClient.reconnectSingleMcpServer(
|
|
56
|
+
getMcpScopeId(),
|
|
57
|
+
target,
|
|
58
|
+
cfg,
|
|
59
|
+
login ? { interactive: true, openBrowser: login.openBrowser } : {}
|
|
60
|
+
);
|
|
50
61
|
} catch (error) {
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
62
|
+
const failure = { name: target, msg: error?.message || String(error) };
|
|
63
|
+
if (error?.authRequired) failure.authRequired = true;
|
|
64
|
+
const failures = Array.isArray(error?.failures) ? error.failures : [failure];
|
|
54
65
|
state.mcpFailures = [...(state.mcpFailures || []), ...failures];
|
|
55
66
|
}
|
|
56
67
|
}
|
|
@@ -72,7 +83,13 @@ export function createMcpConnect({
|
|
|
72
83
|
]);
|
|
73
84
|
}
|
|
74
85
|
|
|
75
|
-
async function connectConfiguredMcp({
|
|
86
|
+
async function connectConfiguredMcp({
|
|
87
|
+
reset = false,
|
|
88
|
+
only = null,
|
|
89
|
+
enabled = true,
|
|
90
|
+
reconcile = false,
|
|
91
|
+
login = null,
|
|
92
|
+
} = {}) {
|
|
76
93
|
if (envFlag('MIXDOG_DISABLE_MCP')) {
|
|
77
94
|
++state.mcpConnectGeneration;
|
|
78
95
|
state.mcpFailures = [];
|
|
@@ -87,6 +104,9 @@ export function createMcpConnect({
|
|
|
87
104
|
// been requested in the meantime. Registering as in-flight makes a later
|
|
88
105
|
// reset serialize behind us instead of interleaving disconnect/connect.
|
|
89
106
|
if (only || reconcile) {
|
|
107
|
+
// A disable/remove must not wait out an interactive login of the
|
|
108
|
+
// connect it queues behind: cancel that login first.
|
|
109
|
+
if (only && enabled === false) cancelMcpLogin(only);
|
|
90
110
|
// Atomically capture the current generation AND the prior in-flight
|
|
91
111
|
// promise in the same synchronous step, then chain our op onto it. No
|
|
92
112
|
// await sits between the capture and the `state.mcpConnectInFlight = run`
|
|
@@ -106,7 +126,7 @@ export function createMcpConnect({
|
|
|
106
126
|
}
|
|
107
127
|
if (gen !== state.mcpConnectGeneration) return;
|
|
108
128
|
if (reconcile) await reconcileServers();
|
|
109
|
-
else await applyMcpServerConnection(only, enabled);
|
|
129
|
+
else await applyMcpServerConnection(only, enabled, undefined, login);
|
|
110
130
|
})();
|
|
111
131
|
state.mcpConnectInFlight = run;
|
|
112
132
|
try {
|
|
@@ -189,23 +209,35 @@ export function createMcpConnect({
|
|
|
189
209
|
budgetMs = Math.min(budgetMs, requestedMaxWaitMs);
|
|
190
210
|
}
|
|
191
211
|
}
|
|
192
|
-
// Swallow the in-flight rejection: failures are already captured in
|
|
193
|
-
// state.mcpFailures, and this gate must never reject the turn.
|
|
194
|
-
const settled = Promise.resolve(inFlight).catch(() => {});
|
|
195
212
|
// Budget disabled (0/off) = no per-server startup timeout, so the connect
|
|
196
213
|
// promise may never settle; never gate the turn on it — fall back to the
|
|
197
214
|
// legacy fire-and-forget behavior (late servers use the deferred path).
|
|
198
215
|
if (!(budgetMs > 0)) return;
|
|
199
216
|
let timer = null;
|
|
217
|
+
let expired = false;
|
|
200
218
|
const budget = new Promise((resolveBudget) => {
|
|
201
|
-
timer = setTimeout(
|
|
219
|
+
timer = setTimeout(() => {
|
|
220
|
+
expired = true;
|
|
221
|
+
resolveBudget();
|
|
222
|
+
}, budgetMs);
|
|
202
223
|
});
|
|
203
224
|
try {
|
|
204
|
-
|
|
225
|
+
// Follow replacement connects (a reconnect queued behind the captured
|
|
226
|
+
// run installs a new in-flight promise) inside ONE fixed deadline.
|
|
227
|
+
// Failures are already captured in state.mcpFailures, so rejections are
|
|
228
|
+
// swallowed: this gate must never reject the turn.
|
|
229
|
+
let current = inFlight;
|
|
230
|
+
while (current && !expired) {
|
|
231
|
+
await Promise.race([Promise.resolve(current).catch(() => {}), budget]);
|
|
232
|
+
if (expired) break;
|
|
233
|
+
// Let a queued reconnect install its promise before re-checking.
|
|
234
|
+
await Promise.race([new Promise((resolveTick) => setImmediate(resolveTick)), budget]);
|
|
235
|
+
current = state.mcpConnectInFlight;
|
|
236
|
+
}
|
|
205
237
|
} finally {
|
|
206
238
|
if (timer) clearTimeout(timer);
|
|
207
239
|
}
|
|
208
240
|
}
|
|
209
241
|
|
|
210
|
-
return { connectConfiguredMcp, awaitInitialMcpConnect };
|
|
242
|
+
return { connectConfiguredMcp, awaitInitialMcpConnect, cancelMcpLogin, completeMcpLogin };
|
|
211
243
|
}
|
|
@@ -5,9 +5,11 @@ import { clean } from '../../runtime/agent/orchestrator/runtime-core/session-tex
|
|
|
5
5
|
import { envFlag } from '../../runtime/shared/env.mjs';
|
|
6
6
|
import { resolveMcpServerCatalog } from './plugin-servers.mjs';
|
|
7
7
|
|
|
8
|
-
function mcpServerStatus(cfg, live, fail) {
|
|
8
|
+
function mcpServerStatus(cfg, live, fail, loginPending) {
|
|
9
9
|
if (cfg?.enabled === false) return 'disabled';
|
|
10
10
|
if (live) return 'connected';
|
|
11
|
+
// Until an interactive sign-in completes the server still needs it.
|
|
12
|
+
if (loginPending || fail?.authRequired) return 'sign-in required';
|
|
11
13
|
return fail ? 'failed' : 'disconnected';
|
|
12
14
|
}
|
|
13
15
|
|
|
@@ -43,6 +45,12 @@ export function createMcpServerCatalog({
|
|
|
43
45
|
* runtime's session cwd. */
|
|
44
46
|
function resolveCatalog() {
|
|
45
47
|
if (envFlag('MIXDOG_DISABLE_MCP')) return EMPTY_CATALOG;
|
|
48
|
+
return resolveConfiguredCatalog();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Every configured server (user config plus plugin declarations, disabled
|
|
52
|
+
* ones included) whether or not this runtime connects MCP at all. */
|
|
53
|
+
function resolveConfiguredCatalog() {
|
|
46
54
|
let plugins = [];
|
|
47
55
|
let registryWarning = null;
|
|
48
56
|
try {
|
|
@@ -115,20 +123,28 @@ export function createMcpServerCatalog({
|
|
|
115
123
|
const fail =
|
|
116
124
|
failures.get(name) || (dead ? { msg: live.error || live.lastError || 'MCP server is not alive' } : undefined);
|
|
117
125
|
const entry = entries[name] || {};
|
|
126
|
+
const loginPending = !(live && !dead) && mcpClient.isMcpLoginPending?.(name, getMcpScopeId()) === true;
|
|
127
|
+
const status = mcpServerStatus(cfg, live && !dead, fail, loginPending);
|
|
128
|
+
// Needing an OAuth sign-in is a state, not an error.
|
|
129
|
+
const authRequired = status === 'sign-in required';
|
|
118
130
|
const row = {
|
|
119
131
|
name,
|
|
120
132
|
configured: true,
|
|
121
133
|
enabled: cfg?.enabled !== false,
|
|
122
134
|
connected: Boolean(live) && !dead,
|
|
123
|
-
status
|
|
135
|
+
status,
|
|
124
136
|
transport: mcpTransportLabel(cfg),
|
|
125
137
|
toolCount: live?.toolCount || 0,
|
|
126
138
|
tools: live?.tools || [],
|
|
127
139
|
capabilities: live?.capabilities || { tools: false, prompts: false, resources: false },
|
|
128
|
-
error: fail?.msg || null,
|
|
140
|
+
error: authRequired ? null : fail?.msg || null,
|
|
129
141
|
warnings: [...(entry.warnings || []), ...(live?.warnings || [])],
|
|
130
142
|
source: sources[name] || 'config',
|
|
131
143
|
};
|
|
144
|
+
if (authRequired) row.authRequired = true;
|
|
145
|
+
const oauth = mcpClient.getMcpServerOAuthState?.(cfg);
|
|
146
|
+
// Why the last sign-in did not complete (already credential-scrubbed).
|
|
147
|
+
if (oauth) row.oauth = authRequired && fail?.msg ? { ...oauth, lastError: fail.msg } : oauth;
|
|
132
148
|
if (entry.owner) {
|
|
133
149
|
row.owner = entry.owner;
|
|
134
150
|
row.pluginEnabled = entry.pluginEnabled;
|
|
@@ -180,6 +196,7 @@ export function createMcpServerCatalog({
|
|
|
180
196
|
return {
|
|
181
197
|
mcpTransportLabel,
|
|
182
198
|
resolveCatalog,
|
|
199
|
+
resolveConfiguredCatalog,
|
|
183
200
|
resolveEffectiveMcpServers,
|
|
184
201
|
pluginServer,
|
|
185
202
|
getMcpServerConfig,
|
|
@@ -37,11 +37,14 @@ export function createMcpGlue({
|
|
|
37
37
|
return {
|
|
38
38
|
mcpStatus: catalog.mcpStatus,
|
|
39
39
|
resolveMcpCatalog: catalog.resolveCatalog,
|
|
40
|
+
resolveConfiguredMcpCatalog: catalog.resolveConfiguredCatalog,
|
|
40
41
|
pluginMcpServer: catalog.pluginServer,
|
|
41
42
|
pluginMcpSummary: catalog.pluginMcpSummary,
|
|
42
43
|
getMcpServerConfig: catalog.getMcpServerConfig,
|
|
43
44
|
connectConfiguredMcp: connect.connectConfiguredMcp,
|
|
44
45
|
awaitInitialMcpConnect: connect.awaitInitialMcpConnect,
|
|
46
|
+
cancelMcpLogin: connect.cancelMcpLogin,
|
|
47
|
+
completeMcpLogin: connect.completeMcpLogin,
|
|
45
48
|
normalizeMcpServerInput,
|
|
46
49
|
};
|
|
47
50
|
}
|