mixdog 1.2.2 → 1.2.4
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 +6 -4
- package/scripts/lib/gate-scheduler.mjs +29 -11
- package/scripts/probe-provider-catalog.mjs +31 -0
- package/scripts/provider-pingpong-live.mjs +599 -0
- package/scripts/session-sweep.mjs +5 -25
- package/src/agents/advisor/AGENT.md +1 -1
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/maintainer/AGENT.md +1 -1
- package/src/agents/maintainer/agent.json +1 -1
- package/src/agents/reviewer/AGENT.md +2 -4
- package/src/agents/security/AGENT.md +1 -2
- package/src/agents/writer/AGENT.md +2 -3
- package/src/defaults/shipped-history.json +11 -1
- package/src/defaults/skills/image/SKILL.md +21 -23
- 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 +20 -15
- package/src/output-styles/common.md +11 -10
- package/src/rules/agent/AGENT.md +6 -4
- package/src/rules/lead/LEAD.md +7 -9
- package/src/rules/shared/45-destructive.md +4 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +28 -7
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -11
- 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/child-tree.mjs +101 -23
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-api-key-fetch.mjs +36 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +24 -17
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +9 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +26 -44
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +31 -15
- 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 +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +41 -12
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +13 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +131 -9
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +29 -10
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +125 -8
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +12 -62
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +117 -41
- 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 +39 -5
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-native-context.mjs +48 -0
- package/src/runtime/agent/orchestrator/providers/cursor-wire-exec.mjs +144 -34
- package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +28 -4
- package/src/runtime/agent/orchestrator/providers/cursor-wire-request.mjs +8 -4
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +42 -11
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +109 -6
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +17 -4
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +22 -2
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +73 -7
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +75 -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 +29 -5
- package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +36 -13
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +101 -11
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/gemini-rest-stream/watchdogs.mjs +16 -5
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +19 -14
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +371 -41
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +97 -49
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +81 -10
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +35 -8
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +1 -0
- 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 +253 -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 +392 -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/request-compression.mjs +86 -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 +50 -22
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +133 -21
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +7 -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 +92 -16
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +13 -13
- package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +133 -62
- 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 +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +39 -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 +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +84 -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 +155 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +40 -24
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +63 -25
- 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 +183 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +87 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +51 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +103 -26
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +23 -4
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +11 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +17 -2
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +15 -23
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +64 -52
- 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 +28 -5
- 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 +4 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +72 -24
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +50 -16
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -19
- 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 -36
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
- 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.mjs +18 -9
- package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +181 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +78 -70
- package/src/runtime/agent/orchestrator/providers/openrouter.mjs +74 -0
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +150 -10
- package/src/runtime/agent/orchestrator/providers/registry.mjs +13 -2
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +7 -1
- 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 +164 -0
- package/src/runtime/agent/orchestrator/providers/wire-route.mjs +522 -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 +195 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +104 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +8 -6
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +24 -0
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
- package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +30 -2
- package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +3 -2
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -3
- 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 +16 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge-contract.mjs +6 -0
- 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 +178 -71
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +102 -12
- package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -8
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -2
- package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +24 -0
- package/src/runtime/agent/orchestrator/session/cache/tool-result-reuse.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -3
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +5 -11
- package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +6 -22
- package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +16 -93
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +148 -0
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
- 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/conversation-import/claude.mjs +0 -6
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +0 -6
- package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/historical-session-closure.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +2 -5
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +89 -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 -27
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -10
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +2 -9
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +24 -10
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +135 -0
- package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +31 -4
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +76 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +67 -20
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +10 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +6 -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 +29 -5
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +147 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +7 -5
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +33 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-support.mjs +0 -4
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +23 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +54 -13
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +33 -0
- 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 +11 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +22 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +57 -13
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/failed-turn-rewind.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +6 -120
- package/src/runtime/agent/orchestrator/session/manager/pending-persist-queue.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +231 -16
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +42 -49
- package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +50 -0
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +47 -17
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +26 -4
- package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +36 -35
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +29 -13
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +45 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +4 -10
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/send-instrumentation.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +17 -1
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/side-question.mjs +197 -0
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +22 -15
- package/src/runtime/agent/orchestrator/session/store/lifecycle-read.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/listing.mjs +2 -6
- package/src/runtime/agent/orchestrator/session/store/live-cache-eviction.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +46 -37
- package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/load-session.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +44 -37
- package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
- package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +59 -0
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/sweep/stale-sweep.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +27 -21
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +0 -8
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +6 -18
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +33 -106
- package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +4 -2
- package/src/runtime/agent/orchestrator/session/store-agent-worker-pool.mjs +5 -8
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +136 -196
- package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +53 -115
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +10 -1
- package/src/runtime/agent/orchestrator/session/store-summary-locations.mjs +3 -29
- package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +17 -10
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +9 -20
- package/src/runtime/agent/orchestrator/session/store.mjs +22 -19
- package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +12 -12
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +38 -14
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +15 -4
- 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 +79 -0
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +72 -15
- package/src/runtime/agent/orchestrator/session/turn-failure.mjs +45 -0
- package/src/runtime/agent/orchestrator/stall-policy.mjs +50 -0
- package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +5 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +218 -20
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +160 -39
- package/src/runtime/agent/orchestrator/tools/builtin/git-partial-stage.mjs +7 -5
- package/src/runtime/agent/orchestrator/tools/builtin/grep-formatting.mjs +14 -5
- package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-context-expander.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-output.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-path-fanout.mjs +48 -44
- package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +10 -3
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +247 -49
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +5 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +20 -0
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +101 -2
- 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/code-graph-prewarm-worker.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +67 -0
- package/src/runtime/agent/orchestrator/tools/lib/process-table-fixture.mjs +50 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +303 -63
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +108 -18
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +77 -11
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +81 -5
- 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/attachments/store.d.mts +9 -0
- package/src/runtime/attachments/store.mjs +80 -9
- package/src/runtime/browser-bridge/browser-action-contract.d.mts +0 -1
- package/src/runtime/browser-bridge/browser-action-contract.mjs +0 -2
- package/src/runtime/computer-bridge/action-schema.mjs +219 -196
- package/src/runtime/computer-bridge/linux-readiness.d.mts +0 -2
- package/src/runtime/computer-bridge/linux-readiness.mjs +0 -16
- package/src/runtime/effort-judge/judge-client.mjs +21 -4
- package/src/runtime/effort-judge/judge-worker.mjs +4 -1
- package/src/runtime/github/tool.mjs +208 -17
- package/src/runtime/media/adapters/codex-image.mjs +140 -21
- package/src/runtime/media/catalog.mjs +4 -4
- package/src/runtime/media/chatgpt-usage.mjs +55 -0
- package/src/runtime/media/defaults.mjs +37 -0
- package/src/runtime/media/jobs.mjs +12 -2
- package/src/runtime/media/lanes.mjs +12 -0
- package/src/runtime/media/tool-defs.mjs +15 -4
- package/src/runtime/media/tool.mjs +41 -12
- package/src/runtime/media/upstream-error.mjs +72 -6
- 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/ingest/transcript-rows.mjs +1 -0
- package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
- package/src/runtime/memory/lib/pg/process.mjs +36 -33
- package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
- package/src/runtime/memory/lib/pg/supervisor.mjs +112 -4
- 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 +1 -1
- package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
- package/src/runtime/office/authoring/html-browser.mjs +18 -8
- package/src/runtime/office/authoring/html-document-author.mjs +2 -0
- package/src/runtime/office/authoring/pdf-html-runner.mjs +1 -1
- package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-measure.mjs +3 -1
- package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +3 -1
- 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 +94 -0
- package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
- package/src/runtime/office/index.mjs +29 -0
- package/src/runtime/office/pdf/pdf-analysis.mjs +0 -68
- 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/session-search/session-search-ingest.mjs +1 -1
- package/src/runtime/shared/agent-reap-state.mjs +13 -0
- package/src/runtime/shared/atomic-file.d.mts +1 -1
- package/src/runtime/shared/background-tasks.mjs +6 -1
- package/src/runtime/shared/bounded-file-read.mjs +13 -0
- package/src/runtime/shared/bounded-line-diff.mjs +191 -0
- package/src/runtime/shared/browser-launch.mjs +15 -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 +48 -4
- package/src/runtime/shared/file-lock.mjs +6 -5
- 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 +1 -2
- package/src/runtime/shared/llm/anthropic-effort.mjs +6 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +1 -0
- 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/loopback-listener.mjs +9 -0
- package/src/runtime/shared/model-route-chain.d.mts +8 -0
- package/src/runtime/shared/model-route-chain.mjs +48 -0
- package/src/runtime/shared/model-route-fallback.mjs +22 -0
- package/src/runtime/shared/pid-liveness.mjs +12 -0
- package/src/runtime/shared/provider-api-key.mjs +8 -0
- package/src/runtime/shared/provider-timeout-phase.mjs +17 -0
- package/src/runtime/shared/quiet-progress.d.mts +35 -0
- package/src/runtime/shared/quiet-progress.mjs +101 -0
- package/src/runtime/shared/quota-resume-store.mjs +32 -1
- package/src/runtime/shared/read-row-numbers.mjs +44 -0
- package/src/runtime/shared/remote-intent.mjs +2 -42
- package/src/runtime/shared/review-diff.mjs +52 -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 +121 -0
- package/src/runtime/shared/statusline/statusline-segments.mjs +52 -6
- package/src/runtime/shared/tool-card-model/card-header.mjs +7 -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-budget.mjs +2 -0
- 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 +22 -1
- package/src/runtime/shared/tool-status.mjs +3 -2
- package/src/runtime/shared/tool-surface.mjs +20 -6
- package/src/runtime/shared/tool-work-units.mjs +54 -11
- package/src/runtime/shared/transcript-metadata.mjs +49 -1
- package/src/runtime/shared/transcript-turn-keys.mjs +33 -0
- package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
- package/src/runtime/shared/transcript-writer/transcript-file.mjs +10 -1
- package/src/runtime/shared/transcript-writer.mjs +24 -6
- package/src/runtime/shared/turn-changes.mjs +269 -100
- package/src/runtime/shared/turn-review-reply.mjs +8 -39
- package/src/runtime/shared/turn-snapshot-store.mjs +19 -108
- package/src/runtime/shared/turn-snapshot.mjs +865 -683
- package/src/runtime/shared/turn-worktree-snapshot.mjs +183 -255
- package/src/runtime/shared/user-data-guard.mjs +262 -49
- package/src/runtime/shared/worktrees/activity-gate.mjs +175 -0
- package/src/runtime/shared/worktrees/branch-management.mjs +179 -0
- package/src/runtime/shared/worktrees/carry.mjs +533 -0
- package/src/runtime/shared/worktrees/contract.mjs +60 -0
- package/src/runtime/shared/worktrees/dependencies.mjs +456 -0
- package/src/runtime/shared/worktrees/file-recovery.mjs +84 -0
- package/src/runtime/shared/worktrees/git-head.mjs +214 -0
- package/src/runtime/shared/worktrees/git.mjs +8 -3
- package/src/runtime/shared/worktrees/include.mjs +125 -7
- package/src/runtime/shared/worktrees/lock.mjs +1 -1
- package/src/runtime/shared/worktrees/maintenance.mjs +20 -2
- package/src/runtime/shared/worktrees/manager.mjs +525 -31
- package/src/runtime/shared/worktrees/merge.mjs +31 -21
- package/src/runtime/shared/worktrees/owner.mjs +2 -1
- package/src/runtime/shared/worktrees/paths.d.mts +6 -0
- package/src/runtime/shared/worktrees/preparation-report.mjs +79 -0
- package/src/runtime/shared/worktrees/setup-commands.mjs +232 -0
- package/src/runtime/shared/worktrees/workspace-visibility.mjs +17 -0
- package/src/runtime/terminal-bridge/client.mjs +57 -20
- 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 +20 -6
- package/src/session-runtime/boot/config.mjs +2 -0
- package/src/session-runtime/boot/facade.mjs +4 -0
- package/src/session-runtime/boot/infrastructure.mjs +6 -1
- package/src/session-runtime/boot/session.mjs +3 -3
- package/src/session-runtime/boot/tools.mjs +7 -1
- package/src/session-runtime/conversation-import/service.mjs +1 -1
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
- package/src/session-runtime/goal-facade-api.mjs +2 -2
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +91 -0
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +15 -5
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +137 -26
- package/src/session-runtime/internal-tool-executor.mjs +8 -2
- package/src/session-runtime/lifecycle/cold-heir.mjs +187 -0
- package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
- package/src/session-runtime/lifecycle/session-catalog.mjs +25 -18
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +36 -48
- package/src/session-runtime/lifecycle/session-switch.mjs +1 -1
- package/src/session-runtime/lifecycle/shared.mjs +5 -6
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -5
- package/src/session-runtime/lifecycle/teardown.mjs +70 -14
- package/src/session-runtime/lifecycle-api.mjs +1 -0
- package/src/session-runtime/mcp-glue/connect.mjs +17 -5
- package/src/session-runtime/media-api.mjs +8 -0
- package/src/session-runtime/model-route/route-ownership.mjs +60 -0
- package/src/session-runtime/model-route/route-persist.mjs +3 -2
- package/src/session-runtime/model-route/set-route.mjs +116 -36
- package/src/session-runtime/model-route/web-search-route.mjs +7 -2
- package/src/session-runtime/model-route-api.mjs +4 -2
- package/src/session-runtime/native-web-search/routes.mjs +37 -24
- package/src/session-runtime/native-web-search-usage.mjs +51 -0
- package/src/session-runtime/native-web-search.mjs +19 -9
- 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-auth/setup.mjs +4 -0
- package/src/session-runtime/provider-models/catalog-load.mjs +9 -0
- package/src/session-runtime/provider-models/web-search-catalog.mjs +23 -3
- package/src/session-runtime/provider-models.mjs +1 -0
- package/src/session-runtime/provider-usage.mjs +4 -0
- package/src/session-runtime/resource-scope-decorate.mjs +10 -3
- package/src/session-runtime/route-resolution.mjs +3 -1
- package/src/session-runtime/runtime-core.mjs +4 -0
- package/src/session-runtime/runtime-facade.mjs +6 -0
- package/src/session-runtime/runtime-review-api.mjs +8 -2
- package/src/session-runtime/services/agent-task-status.mjs +2 -0
- package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +0 -3
- package/src/session-runtime/services/agent-tool/close-flow.mjs +6 -7
- package/src/session-runtime/services/agent-tool/execute-send.mjs +2 -2
- package/src/session-runtime/services/agent-tool/execute-spawn.mjs +36 -3
- package/src/session-runtime/services/agent-tool/execute.mjs +9 -1
- package/src/session-runtime/services/agent-tool/helpers.mjs +30 -7
- package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
- package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +7 -2
- package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +6 -3
- 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/lead-rows.mjs +3 -4
- package/src/session-runtime/services/agent-tool/lead-worker-index/reap-timers.mjs +9 -3
- package/src/session-runtime/services/agent-tool/lead-worker-index/row-settlement.mjs +7 -18
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +82 -13
- package/src/session-runtime/services/agent-tool/model-select.mjs +82 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -6
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +3 -1
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -5
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -4
- package/src/session-runtime/services/agent-tool/spawn-flow.mjs +2 -1
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
- package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +1 -3
- package/src/session-runtime/services/agent-tool/tag-registry/tag-refresh.mjs +1 -3
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +18 -10
- package/src/session-runtime/services/agent-tool/terminal-reaper/scan-admission.mjs +8 -41
- package/src/session-runtime/services/agent-tool/terminal-reaper/stale-rows.mjs +3 -3
- package/src/session-runtime/services/agent-tool/terminal-reaper.mjs +6 -23
- package/src/session-runtime/services/agent-tool/terminal-trace.mjs +0 -1
- package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +32 -20
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -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 +74 -15
- package/src/session-runtime/services/agent-tool.mjs +7 -0
- package/src/session-runtime/services/agent-watchdog-registry.mjs +2 -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 +158 -15
- package/src/session-runtime/session-create/session-options.mjs +7 -5
- package/src/session-runtime/session-create/session-start-hook.mjs +2 -1
- package/src/session-runtime/session-transcript-purge.mjs +32 -0
- package/src/session-runtime/session-transcript.mjs +4 -5
- package/src/session-runtime/session-turn-api.mjs +17 -14
- package/src/session-runtime/settings-builtin-tools-api.mjs +18 -6
- package/src/session-runtime/setup-tool/executor.mjs +57 -9
- package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
- package/src/session-runtime/setup-tool/settings-contract.mjs +18 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +25 -4
- package/src/session-runtime/skills-api.mjs +3 -5
- package/src/session-runtime/tool-policy-refresh.mjs +83 -32
- package/src/session-runtime/tool-surface.mjs +5 -1
- package/src/session-runtime/turn/agent-ops.mjs +49 -2
- 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 +19 -0
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +7 -1
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +12 -3
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +18 -2
- package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
- package/src/session-runtime/turn/turn-run.mjs +26 -45
- package/src/session-runtime/usage-stats-api.mjs +46 -11
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +16 -1
- package/src/session-runtime/workspace/admission-gate.mjs +44 -15
- package/src/session-runtime/workspace/project-branches.mjs +35 -41
- package/src/session-runtime/workspace/transition-steps.mjs +215 -116
- package/src/session-runtime/workspace/transitions.mjs +428 -73
- package/src/standalone/channel-transport.mjs +3 -4
- package/src/standalone/daemon-agent-control.mjs +9 -1
- package/src/standalone/daemon-desktop-runtime.mjs +32 -1
- 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 +49 -0
- package/src/standalone/daemon-session-control.mjs +88 -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 +25 -3
- package/src/standalone/daemon-telemetry.mjs +19 -0
- package/src/standalone/daemon.mjs +63 -1
- package/src/standalone/desktop-service-registry.mjs +5 -0
- package/src/standalone/local-session-runtime.mjs +80 -30
- 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 +3 -0
- package/src/standalone/session-service/agent-tree/agent-cancel.mjs +91 -49
- package/src/standalone/session-service/agent-tree/agent-child.mjs +19 -1
- package/src/standalone/session-service/agent-tree/agent-registry.mjs +25 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +9 -1
- package/src/standalone/session-service/agent-tree.mjs +28 -2
- package/src/standalone/session-service/entries/session-loads.mjs +16 -5
- package/src/standalone/session-service/entries.mjs +1 -0
- package/src/standalone/session-service/projection/transcript-window.mjs +39 -0
- package/src/standalone/session-service/quota-resume.mjs +28 -13
- package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
- package/src/standalone/session-service/session-calls/session-turns.mjs +17 -6
- package/src/standalone/session-service/session-calls/session-views.mjs +6 -0
- package/src/standalone/session-service-api.mjs +6 -1
- package/src/standalone/session-state-patch.d.mts +2 -1
- package/src/standalone/session-state-patch.mjs +41 -1
- package/src/standalone/session-tool-output.mjs +82 -0
- 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 +2 -1
- package/src/tui/app/btw-controller.mjs +118 -0
- package/src/tui/app/create-app-pickers.mjs +2 -0
- package/src/tui/app/provider-setup/provider-items.mjs +8 -0
- package/src/tui/app/provider-setup-picker.mjs +15 -3
- 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 +19 -3
- package/src/tui/app/slash-dispatch/session-commands.mjs +68 -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/Spinner.jsx +4 -0
- package/src/tui/components/SpinnerByline.jsx +21 -2
- package/src/tui/components/question-panel-model.mjs +156 -0
- package/src/tui/components/status-line/local-line.mjs +10 -2
- package/src/tui/dist/index.mjs +2897 -1722
- package/src/tui/session/active-tool-summary.mjs +1 -1
- package/src/tui/session/context-state.mjs +4 -5
- package/src/tui/session/goal-continuation/continuation-queue.mjs +2 -3
- package/src/tui/session/goal-continuation/deadline-delivery.mjs +4 -2
- package/src/tui/session/goal-continuation/session-boundary.mjs +21 -0
- package/src/tui/session/quota-resume.mjs +140 -61
- package/src/tui/session/session-api/commands.mjs +14 -10
- package/src/tui/session/session-api/controls.mjs +14 -2
- package/src/tui/session/session-api/integrations.mjs +9 -2
- package/src/tui/session/session-api/lifecycle/dispose.mjs +3 -9
- package/src/tui/session/session-api/lifecycle/resume.mjs +2 -7
- package/src/tui/session/session-api/lifecycle.mjs +14 -11
- package/src/tui/session/session-api/media.mjs +2 -0
- package/src/tui/session/session-api/routes.mjs +81 -57
- package/src/tui/session/session-api/settings.mjs +9 -3
- package/src/tui/session/session-api/worktree.mjs +3 -2
- package/src/tui/session/session-api.mjs +1 -0
- package/src/tui/session/session-flow/auto-clear.mjs +1 -3
- package/src/tui/session/session-flow/drain.mjs +6 -4
- package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -0
- package/src/tui/session/session-flow/queue/take-entries.mjs +2 -1
- package/src/tui/session/session-flow/queue.mjs +1 -1
- package/src/tui/session/tool-approval.mjs +20 -8
- package/src/tui/session/transcript-spill.mjs +14 -7
- package/src/tui/session/transcript-store/streaming-tail.mjs +1 -1
- package/src/tui/session/tui-steering-persist.mjs +3 -5
- package/src/tui/session/turn-quiet.mjs +53 -0
- package/src/tui/session/turn-stream.mjs +179 -32
- package/src/tui/session/turn.mjs +50 -36
- package/src/tui/session/worktree-setup-notice.mjs +38 -0
- package/src/tui/spinner-meta.mjs +10 -0
- package/src/tui/spinner-verbs.mjs +3 -0
- package/src/ui/statusline.mjs +13 -3
- package/src/workflows/default/WORKFLOW.md +3 -1
- package/src/runtime/agent/orchestrator/providers/model-pricing-rates.mjs +0 -1
- package/src/runtime/agent/orchestrator/session/manager/foreign-pending-messages.mjs +0 -346
- package/src/runtime/agent/orchestrator/session/manager/session-owner-liveness.mjs +0 -117
- package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +0 -246
- package/src/session-runtime/services/agent-tool/terminal-reaper/reap-timers.mjs +0 -142
- package/src/session-runtime/turn/share-ops.mjs +0 -77
- package/src/tui/session/cross-surface-share.mjs +0 -406
- package/src/tui/session/live-share/delta.mjs +0 -153
- package/src/tui/session/live-share/mirror.mjs +0 -106
- package/src/tui/session/live-share/owner.mjs +0 -254
- package/src/tui/session/live-share/retry.mjs +0 -54
- package/src/tui/session/live-share/viewer/frame-router.mjs +0 -32
- package/src/tui/session/live-share/viewer/pipe-client.mjs +0 -108
- package/src/tui/session/live-share/viewer/submit-acks.mjs +0 -65
- package/src/tui/session/live-share/viewer/sync-waiters.mjs +0 -53
- package/src/tui/session/live-share/viewer.mjs +0 -99
- package/src/tui/session/live-share/wire.mjs +0 -44
- package/src/tui/session/live-share.mjs +0 -154
- package/src/tui/session/shared-dir-watch.mjs +0 -69
|
@@ -1,29 +1,47 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The Lead session workspace transition authority. Every workspace change of
|
|
3
3
|
* the Lead this runtime hosts — entering its retained worktree (created lazily
|
|
4
|
-
* on the first message of a worktree task),
|
|
5
|
-
* branch
|
|
4
|
+
* on the first message of a worktree task), selecting a branch (it runs where
|
|
5
|
+
* that branch is checked out — the project folder, a linked checkout, or a
|
|
6
|
+
* managed worktree made for it — and no existing folder is switched),
|
|
7
|
+
* removing the worktree — goes through applyWorkspaceTransition: one
|
|
6
8
|
* serialized, revisioned commit that retargets the runtime cwd (and the turn's
|
|
7
9
|
* cwd override), stores the durable `workspace` record, re-roots the prompt
|
|
8
|
-
* context of the Lead and its idle workers, and persists
|
|
9
|
-
* WorktreeErrors and leave the
|
|
10
|
+
* context of the Lead and its idle workers, and persists, awaiting each save
|
|
11
|
+
* before it reports success. Failures are typed WorktreeErrors and leave the
|
|
12
|
+
* previous workspace intact.
|
|
10
13
|
*
|
|
11
14
|
* Git and registry work is delegated to the managed-worktree backend
|
|
12
15
|
* (runtime/shared/worktrees/manager.mjs), loaded on first use.
|
|
13
16
|
*/
|
|
14
17
|
import { randomUUID } from 'node:crypto';
|
|
18
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
15
19
|
import {
|
|
20
|
+
WORKTREE_CARRY_CHOICES,
|
|
16
21
|
branchMenuEntries,
|
|
17
22
|
isWorktreeBound,
|
|
18
23
|
isWorktreeError,
|
|
19
24
|
normalizeSessionWorkspace,
|
|
20
25
|
worktreeError,
|
|
21
26
|
worktreeNameError,
|
|
27
|
+
worktreeRefusal,
|
|
22
28
|
} from '../../runtime/shared/worktrees/contract.mjs';
|
|
23
29
|
import { normalizeWorktreeSettings } from '../../runtime/shared/worktrees/settings.mjs';
|
|
24
30
|
import * as maintenance from '../../runtime/shared/worktrees/maintenance.mjs';
|
|
25
31
|
import { inspectRepo, throwIfAborted } from '../../runtime/shared/worktrees/git.mjs';
|
|
32
|
+
import { worktreePreparationNote } from '../../runtime/shared/worktrees/preparation-report.mjs';
|
|
26
33
|
import { isWithin, samePath } from '../../runtime/shared/worktrees/paths.mjs';
|
|
34
|
+
import { readGitHead } from '../../runtime/shared/worktrees/git-head.mjs';
|
|
35
|
+
import {
|
|
36
|
+
holdWorkspaceActivity,
|
|
37
|
+
isExternalCheckout,
|
|
38
|
+
releaseAll,
|
|
39
|
+
} from '../../runtime/shared/worktrees/activity-gate.mjs';
|
|
40
|
+
import { mergeConfirmedTarget } from '../../runtime/shared/worktrees/branch-management.mjs';
|
|
41
|
+
import {
|
|
42
|
+
clearReadDedupSession,
|
|
43
|
+
resetReadStateAfterCompaction,
|
|
44
|
+
} from '../../runtime/agent/orchestrator/session/cache/read-cache.mjs';
|
|
27
45
|
import { sessionHasConversationMessages } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
28
46
|
import { buildWorkspacePromptContext } from '../../runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs';
|
|
29
47
|
import {
|
|
@@ -33,7 +51,7 @@ import {
|
|
|
33
51
|
import { AGENT_OWNER } from '../../runtime/agent/orchestrator/agent-owner.mjs';
|
|
34
52
|
import { _liveSessions } from '../../runtime/agent/orchestrator/session/store/live-state.mjs';
|
|
35
53
|
import { admitTurn, beginWorkspaceTransition, holdCheckoutFolder } from './admission-gate.mjs';
|
|
36
|
-
import {
|
|
54
|
+
import { createProjectBranchOps } from './project-branches.mjs';
|
|
37
55
|
import { assertRetainedFits, createTransitionSteps, undoAll } from './transition-steps.mjs';
|
|
38
56
|
import { readSessionWorkspace } from './workspace-state.mjs';
|
|
39
57
|
|
|
@@ -53,18 +71,39 @@ async function defaultOwnShellJobCount(sessionIds) {
|
|
|
53
71
|
|
|
54
72
|
const lower = (value) => String(value || '').toLowerCase();
|
|
55
73
|
|
|
74
|
+
const WORKTREE_BOUND_SWITCH =
|
|
75
|
+
'The session works in a managed worktree; exit the worktree first (switch to a project-folder branch, or merge or remove the worktree) before moving it to another project.';
|
|
76
|
+
|
|
56
77
|
/** The registered Project (projects.json) at `path`, or null. */
|
|
57
78
|
async function defaultRegisteredProject(path) {
|
|
58
79
|
const { listProjectsStrict } = await import('../../runtime/shared/projects.mjs');
|
|
59
80
|
return listProjectsStrict().find((entry) => samePath(entry.path, path))?.path ?? null;
|
|
60
81
|
}
|
|
61
82
|
|
|
83
|
+
/** The dependency installs a new worktree folder still needs (dependencies.mjs). */
|
|
84
|
+
async function defaultPlanWorktreeSetup(input) {
|
|
85
|
+
const { planDependencySetup } = await import('../../runtime/shared/worktrees/dependencies.mjs');
|
|
86
|
+
return planDependencySetup(input);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function defaultRunWorktreeSetup(input) {
|
|
90
|
+
const { runWorktreeSetupCommands } = await import('../../runtime/shared/worktrees/setup-commands.mjs');
|
|
91
|
+
return runWorktreeSetupCommands(input);
|
|
92
|
+
}
|
|
93
|
+
|
|
62
94
|
/**
|
|
63
95
|
* Re-root one session's prompt at `cwd`: environment facts and instruction
|
|
64
96
|
* files for every session, project memory for the Lead only (workers never
|
|
65
|
-
* carried it).
|
|
97
|
+
* carried it). A session with a conversation keeps its system prompt (cache
|
|
98
|
+
* intact) and gets a tail notice instead (refreshSessionWorkspaceContext);
|
|
99
|
+
* `move` ({ from, changes }: the session left the project folder `from` for
|
|
100
|
+
* a worktree) adds the uncommitted-changes and path lines to that notice.
|
|
66
101
|
*/
|
|
67
|
-
export async function refreshWorkspacePrompt(session, cwd, { loadCoreMemoryContext } = {}) {
|
|
102
|
+
export async function refreshWorkspacePrompt(session, cwd, { loadCoreMemoryContext, move = null } = {}) {
|
|
103
|
+
// A new checkout invalidates observed-file snapshots as well as read/search
|
|
104
|
+
// results. Conversation text remains historical evidence, not a file cache.
|
|
105
|
+
clearReadDedupSession(session?.id);
|
|
106
|
+
resetReadStateAfterCompaction(session?.id);
|
|
68
107
|
const { environmentContext, instructionFilesContext } = buildWorkspacePromptContext(session, cwd);
|
|
69
108
|
const coreMemoryContext =
|
|
70
109
|
session?.owner === AGENT_OWNER || typeof loadCoreMemoryContext !== 'function'
|
|
@@ -75,6 +114,7 @@ export async function refreshWorkspacePrompt(session, cwd, { loadCoreMemoryConte
|
|
|
75
114
|
environmentContext,
|
|
76
115
|
coreMemoryContext,
|
|
77
116
|
instructionFilesContext,
|
|
117
|
+
...(move ? { move } : {}),
|
|
78
118
|
});
|
|
79
119
|
}
|
|
80
120
|
|
|
@@ -137,9 +177,10 @@ const TRANSITION_STATE = { worktree: 'provisioning', branch: 'switching', 'remov
|
|
|
137
177
|
* @param {object} deps
|
|
138
178
|
* @param {() => any} deps.getSession The Lead session this runtime hosts.
|
|
139
179
|
* @param {() => string} deps.getCurrentCwd
|
|
140
|
-
* @param {(cwd: string) => unknown} deps.applyResolvedCwd Retargets rt cwd, session.cwd and the cwd override.
|
|
141
|
-
* @param {(
|
|
142
|
-
* @param {(session: any
|
|
180
|
+
* @param {(cwd: string, options?: { persistProjectSelection?: boolean }) => unknown} deps.applyResolvedCwd Retargets rt cwd, session.cwd and the cwd override (and, persisting, the Project selection).
|
|
181
|
+
* @param {(desktopSession: any) => unknown} [deps.setDesktopSession] Restores the runtime's desktop metadata on a rollback.
|
|
182
|
+
* @param {(session: any) => Promise<unknown>|unknown} deps.persistSession Durable save: resolves once the session is on disk, rejects (throws) when it is not.
|
|
183
|
+
* @param {(session: any, cwd: string, move?: { from: string, changes: 'carried'|'left'|null }|null) => Promise<unknown>} deps.refreshWorkspaceContext
|
|
143
184
|
* @param {() => number} deps.getActiveTurnCount
|
|
144
185
|
* @param {() => { agentWorkers?: any[], agentJobs?: any[] }} deps.agentStatusState
|
|
145
186
|
* @param {(sessionId: string, cwd: string) => unknown} [deps.updateLeadWorkerCwd] Moves the Lead's pool row (lead-workers.json).
|
|
@@ -149,6 +190,7 @@ export function createWorkspaceTransitions({
|
|
|
149
190
|
getReservedSessionId = () => null,
|
|
150
191
|
getCurrentCwd,
|
|
151
192
|
getDesktopSession = () => null,
|
|
193
|
+
setDesktopSession = () => {},
|
|
152
194
|
getConfig = () => null,
|
|
153
195
|
createCurrentSession = null,
|
|
154
196
|
applyResolvedCwd,
|
|
@@ -167,11 +209,24 @@ export function createWorkspaceTransitions({
|
|
|
167
209
|
inspectProject = inspectRepo,
|
|
168
210
|
findRegisteredProject = defaultRegisteredProject,
|
|
169
211
|
listStoredSessionIds = maintenance.storedSessionIds,
|
|
212
|
+
listWorkspaceConsumers = maintenance.storedWorkspaceConsumers,
|
|
213
|
+
listWorkspaceJobs = async () => {
|
|
214
|
+
const { listShellJobRecords } = await import(
|
|
215
|
+
'../../runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs'
|
|
216
|
+
);
|
|
217
|
+
return listShellJobRecords({ strict: true });
|
|
218
|
+
},
|
|
170
219
|
runtimeToken = randomUUID(),
|
|
171
220
|
newTxId = randomUUID,
|
|
221
|
+
planWorktreeSetup = defaultPlanWorktreeSetup,
|
|
222
|
+
runWorktreeSetup = defaultRunWorktreeSetup,
|
|
172
223
|
}) {
|
|
173
224
|
const worktreeSettings = () => normalizeWorktreeSettings(getConfig?.()?.worktree);
|
|
174
225
|
let pendingIntent = creationIntent(initialIntent, worktreeSettings());
|
|
226
|
+
// The new worktree whose dependencies have not been prepared yet, bound to
|
|
227
|
+
// that worktree (worktreeId + cwd): it runs only while the session is there.
|
|
228
|
+
let pendingSetup = null;
|
|
229
|
+
const setupListeners = new Set();
|
|
175
230
|
let managerPromise = null;
|
|
176
231
|
const backend = () => {
|
|
177
232
|
if (manager) return Promise.resolve(manager);
|
|
@@ -207,6 +262,37 @@ export function createWorkspaceTransitions({
|
|
|
207
262
|
return normalizeSessionWorkspace({ projectPath, cwd: getCurrentCwd() || projectPath, revision: 0 });
|
|
208
263
|
}
|
|
209
264
|
|
|
265
|
+
let liveWorkspace = null;
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* The workspace the session publishes: a worktree-bound record as stored; a
|
|
269
|
+
* project-folder session (never moved, back from a worktree, or carrying a
|
|
270
|
+
* transition stub) with the folder's checked-out branch / detached commit and
|
|
271
|
+
* repoCommonDir read straight from HEAD — no git process. Null outside a git
|
|
272
|
+
* repository for a session without a record. Identity-stable while equal.
|
|
273
|
+
*/
|
|
274
|
+
function getLiveWorkspace() {
|
|
275
|
+
const session = getSession();
|
|
276
|
+
const stored = readSessionWorkspace(session);
|
|
277
|
+
if (isWorktreeBound(stored)) return session.workspace;
|
|
278
|
+
let base;
|
|
279
|
+
try {
|
|
280
|
+
base = stored ?? currentWorkspace(session);
|
|
281
|
+
} catch {
|
|
282
|
+
return session?.workspace ?? null;
|
|
283
|
+
}
|
|
284
|
+
const head = readGitHead(base.cwd);
|
|
285
|
+
if (!head) return session?.workspace ?? null;
|
|
286
|
+
const next = {
|
|
287
|
+
...base,
|
|
288
|
+
repoCommonDir: head.repoCommonDir,
|
|
289
|
+
branch: head.branch,
|
|
290
|
+
baseCommit: head.branch ? base.baseCommit : head.commit,
|
|
291
|
+
};
|
|
292
|
+
if (!liveWorkspace || !isDeepStrictEqual(liveWorkspace, next)) liveWorkspace = next;
|
|
293
|
+
return liveWorkspace;
|
|
294
|
+
}
|
|
295
|
+
|
|
210
296
|
function isSessionActive(session) {
|
|
211
297
|
const runtime = sessionManager?.getSessionRuntime?.(session.id);
|
|
212
298
|
if (runtime?.controller?.signal && !runtime.controller.signal.aborted) return true;
|
|
@@ -223,8 +309,11 @@ export function createWorkspaceTransitions({
|
|
|
223
309
|
(candidate.ownerSessionId === session.id || candidate.parentSessionId === session.id)
|
|
224
310
|
);
|
|
225
311
|
|
|
226
|
-
/**
|
|
227
|
-
|
|
312
|
+
/**
|
|
313
|
+
* WORKTREE_BUSY_JOBS while this Lead has a turn, workers or background
|
|
314
|
+
* shells running (`shellJobs: false` tolerates background shells).
|
|
315
|
+
*/
|
|
316
|
+
async function assertLeadIdle(session, { ownTurn = false, shellJobs: checkShellJobs = true } = {}) {
|
|
228
317
|
if (!ownTurn && getActiveTurnCount() > 0) {
|
|
229
318
|
throw worktreeError('WORKTREE_BUSY_JOBS', 'The session is running a turn; wait for it to finish.', {
|
|
230
319
|
reason: 'turn',
|
|
@@ -240,6 +329,7 @@ export function createWorkspaceTransitions({
|
|
|
240
329
|
if (busyWorkers || busyJobs) {
|
|
241
330
|
throw worktreeError('WORKTREE_BUSY_JOBS', undefined, { reason: 'workers', workers: busyWorkers, jobs: busyJobs });
|
|
242
331
|
}
|
|
332
|
+
if (!checkShellJobs) return;
|
|
243
333
|
const ids = new Set([session.id, ...workers.map((row) => row?.sessionId).filter(Boolean)]);
|
|
244
334
|
for (const worker of workersOf(session)) ids.add(worker.id);
|
|
245
335
|
const shellJobs = await countOwnShellJobs([...ids]);
|
|
@@ -253,25 +343,19 @@ export function createWorkspaceTransitions({
|
|
|
253
343
|
* wait (admission gate). `sessionId` null: a session-less (draft) change.
|
|
254
344
|
* @returns {() => void}
|
|
255
345
|
*/
|
|
256
|
-
function holdProjectFolder(sessionId, folder) {
|
|
346
|
+
function holdProjectFolder(sessionId, folder, { hold = true } = {}) {
|
|
257
347
|
const users = listLiveSessions().filter(
|
|
258
348
|
(candidate) =>
|
|
259
349
|
candidate?.id &&
|
|
260
350
|
candidate.id !== sessionId &&
|
|
261
351
|
candidate.closed !== true &&
|
|
262
|
-
candidate.remoteAttached !== true &&
|
|
263
352
|
(!sessionId || (candidate.ownerSessionId !== sessionId && candidate.parentSessionId !== sessionId)) &&
|
|
264
353
|
typeof candidate.cwd === 'string' &&
|
|
265
354
|
isWithin(folder, candidate.cwd) &&
|
|
266
355
|
isSessionActive(candidate)
|
|
267
356
|
);
|
|
268
|
-
if (users.length) {
|
|
269
|
-
|
|
270
|
-
reason: 'folder-in-use',
|
|
271
|
-
sessions: users.map((candidate) => candidate.id),
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
return holdCheckoutFolder(sessionId, folder);
|
|
357
|
+
if (users.length) throw worktreeRefusal('folder-in-use', { sessions: users.map((candidate) => candidate.id) });
|
|
358
|
+
return holdCheckoutFolder(sessionId, folder, { hold });
|
|
275
359
|
}
|
|
276
360
|
|
|
277
361
|
/** Run `fn` holding the checkout `folder` (holdProjectFolder); released when it settles. */
|
|
@@ -284,11 +368,81 @@ export function createWorkspaceTransitions({
|
|
|
284
368
|
}
|
|
285
369
|
}
|
|
286
370
|
|
|
371
|
+
/**
|
|
372
|
+
* Before a carry clears the shared checkout `folder` (held by the caller,
|
|
373
|
+
* so no new turn starts there): WORKTREE_BUSY_JOBS while any other session
|
|
374
|
+
* working in it — idle or not, this Lead's workers included — owns a
|
|
375
|
+
* running background shell (holdProjectFolder already refused running
|
|
376
|
+
* turns and agents there, assertLeadIdle this Lead's own). Processes
|
|
377
|
+
* outside Mixdog (editors, watchers) cannot be excluded.
|
|
378
|
+
*/
|
|
379
|
+
async function assertCheckoutQuiet(session, folder) {
|
|
380
|
+
const sharing = listLiveSessions()
|
|
381
|
+
.filter(
|
|
382
|
+
(candidate) =>
|
|
383
|
+
candidate?.id &&
|
|
384
|
+
candidate.id !== session.id &&
|
|
385
|
+
candidate.closed !== true &&
|
|
386
|
+
typeof candidate.cwd === 'string' &&
|
|
387
|
+
isWithin(folder, candidate.cwd)
|
|
388
|
+
)
|
|
389
|
+
.map((candidate) => candidate.id);
|
|
390
|
+
if (!sharing.length) return;
|
|
391
|
+
const shellJobs = await countOwnShellJobs(sharing);
|
|
392
|
+
if (shellJobs > 0) throw worktreeRefusal('folder-shell-jobs', { shellJobs });
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* The shared admission of every merge and folder cleanup (manageProjectBranch):
|
|
397
|
+
* refuses while a session or worker runs in an affected folder, or a
|
|
398
|
+
* background command does; `removing` refuses while any session still uses
|
|
399
|
+
* one. Then holds the folders — Mixdog checkouts only; an external checkout
|
|
400
|
+
* is never lock-blocked — so new Mixdog work there waits until `run`
|
|
401
|
+
* settles. `actor`: the session acting on its own checkout, whose own turn
|
|
402
|
+
* and workers its caller already checked (assertLeadIdle).
|
|
403
|
+
*/
|
|
404
|
+
async function withManagementFolders(folders, removing, run, { actor = null } = {}) {
|
|
405
|
+
const release = [];
|
|
406
|
+
try {
|
|
407
|
+
for (const folder of [...new Set(folders)].sort()) {
|
|
408
|
+
release.push(holdProjectFolder(actor, folder, { hold: !isExternalCheckout(folder) }));
|
|
409
|
+
}
|
|
410
|
+
release.push(holdWorkspaceActivity(folders, { sessionId: actor }));
|
|
411
|
+
const stored = await listWorkspaceConsumers();
|
|
412
|
+
const consumers = new Map(stored.map((session) => [session.id, session]));
|
|
413
|
+
for (const session of listLiveSessions()) if (session?.closed !== true) consumers.set(session.id, session);
|
|
414
|
+
const affected = [...consumers.values()].filter((session) =>
|
|
415
|
+
folders.some((folder) => session.cwd && isWithin(folder, session.cwd))
|
|
416
|
+
);
|
|
417
|
+
const blocking = removing
|
|
418
|
+
? affected
|
|
419
|
+
: affected.filter(
|
|
420
|
+
(session) =>
|
|
421
|
+
!(actor && [session.id, session.ownerSessionId, session.parentSessionId].includes(actor)) &&
|
|
422
|
+
isSessionActive(session)
|
|
423
|
+
);
|
|
424
|
+
if (blocking.length) throw worktreeRefusal('folder-in-use', { sessions: blocking.map((session) => session.id) });
|
|
425
|
+
const jobs = await listWorkspaceJobs();
|
|
426
|
+
if (jobs.some((job) => !job.terminal && folders.some((folder) => isWithin(folder, job.cwd)))) {
|
|
427
|
+
throw worktreeRefusal('folder-shell-jobs');
|
|
428
|
+
}
|
|
429
|
+
if ((await countOwnShellJobs(affected.map((session) => session.id))) > 0) {
|
|
430
|
+
throw worktreeRefusal('folder-shell-jobs');
|
|
431
|
+
}
|
|
432
|
+
return await run([...consumers.keys()]);
|
|
433
|
+
} finally {
|
|
434
|
+
releaseAll(release);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
287
438
|
const steps = createTransitionSteps({
|
|
439
|
+
assertCheckoutQuiet,
|
|
288
440
|
backend,
|
|
289
441
|
inspectProject,
|
|
290
442
|
runtimeToken,
|
|
291
443
|
getCurrentCwd,
|
|
444
|
+
getDesktopSession,
|
|
445
|
+
setDesktopSession,
|
|
292
446
|
applyResolvedCwd,
|
|
293
447
|
persistSession,
|
|
294
448
|
refreshWorkspaceContext,
|
|
@@ -302,6 +456,7 @@ export function createWorkspaceTransitions({
|
|
|
302
456
|
inspectProject,
|
|
303
457
|
findRegisteredProject,
|
|
304
458
|
withProjectFolder,
|
|
459
|
+
withManagementFolders,
|
|
305
460
|
});
|
|
306
461
|
|
|
307
462
|
async function transition(session, target, options = {}) {
|
|
@@ -326,21 +481,48 @@ export function createWorkspaceTransitions({
|
|
|
326
481
|
await assertLeadIdle(session, { ownTurn: options.ownTurn === true });
|
|
327
482
|
const run = { signal: options.signal, txId, journal };
|
|
328
483
|
if (target.kind === 'worktree') {
|
|
329
|
-
|
|
484
|
+
const { created, ...entered } = await steps.enterWorktree(session, previous, {
|
|
330
485
|
...run,
|
|
331
486
|
name: target.name,
|
|
332
487
|
nameHint: options.nameHint,
|
|
333
488
|
confirmLarge: options.confirmLarge,
|
|
489
|
+
changes: options.changes,
|
|
334
490
|
});
|
|
491
|
+
// A new checkout gets its dependencies prepared at the start of the
|
|
492
|
+
// session's next turn there (prepareTurnWorkspace).
|
|
493
|
+
if (created) {
|
|
494
|
+
pendingSetup = {
|
|
495
|
+
...created,
|
|
496
|
+
sessionId: session.id,
|
|
497
|
+
worktreeId: entered.workspace.worktreeId,
|
|
498
|
+
cwd: entered.workspace.cwd,
|
|
499
|
+
mainDir: previous.projectPath,
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
return entered;
|
|
335
503
|
}
|
|
336
504
|
if (target.kind === 'branch') {
|
|
337
|
-
|
|
505
|
+
const { created, ...entered } = await steps.enterProjectBranch(session, previous, {
|
|
338
506
|
...run,
|
|
339
507
|
branch: target.branch,
|
|
340
508
|
create: target.create,
|
|
509
|
+
confirmLarge: options.confirmLarge,
|
|
341
510
|
});
|
|
511
|
+
if (created && entered.workspace?.worktreeId) {
|
|
512
|
+
pendingSetup = {
|
|
513
|
+
...created,
|
|
514
|
+
sessionId: session.id,
|
|
515
|
+
worktreeId: entered.workspace.worktreeId,
|
|
516
|
+
cwd: entered.workspace.cwd,
|
|
517
|
+
mainDir: previous.projectPath,
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
return entered;
|
|
342
521
|
}
|
|
343
|
-
|
|
522
|
+
const removed = await steps.removeRetainedWorktree(session, previous, { ...run, force: target.force });
|
|
523
|
+
// The session's retained worktree is gone: its pending setup goes with it.
|
|
524
|
+
if (pendingSetup?.sessionId === session.id) pendingSetup = null;
|
|
525
|
+
return removed;
|
|
344
526
|
} catch (error) {
|
|
345
527
|
// Whatever already moved (cwd, record, prompts, worker roots, lease)
|
|
346
528
|
// goes back exactly; the previous workspace stays authoritative.
|
|
@@ -414,21 +596,77 @@ export function createWorkspaceTransitions({
|
|
|
414
596
|
);
|
|
415
597
|
}
|
|
416
598
|
const intent = intentFor(session);
|
|
417
|
-
|
|
599
|
+
let result = null;
|
|
600
|
+
if (intent) {
|
|
601
|
+
try {
|
|
602
|
+
result = await provisionIntent(session, intent, submissionId, prompt, {
|
|
603
|
+
confirmLarge: intent.confirmLarge || confirmLarge === true,
|
|
604
|
+
signal,
|
|
605
|
+
ownTurn: true,
|
|
606
|
+
});
|
|
607
|
+
} catch (error) {
|
|
608
|
+
// The settings default never blocks a task outside a git repository.
|
|
609
|
+
if (!intent.explicit && isWorktreeError(error, 'WORKTREE_UNSUPPORTED_REPO')) {
|
|
610
|
+
if (pendingIntent === intent) pendingIntent = null;
|
|
611
|
+
return null;
|
|
612
|
+
}
|
|
613
|
+
throw error;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
await runPendingSetup(session, signal);
|
|
617
|
+
return result;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* Prepare the session's new worktree, once, under the turn (its admission
|
|
622
|
+
* keeps the folder from being merged or removed; its signal — the Stop
|
|
623
|
+
* button — cancels): the frozen installs the links made at creation did
|
|
624
|
+
* not cover. While an install runs, every onWorktreeSetup listener gets its
|
|
625
|
+
* one-line progress; nothing else reaches the user. The agent gets one
|
|
626
|
+
* compact note with this turn (`session.pendingSetupNotice`): the main
|
|
627
|
+
* checkout, what was copied, linked and installed, what failed (with the
|
|
628
|
+
* output tail) and what was skipped. A failure or timeout is in the note
|
|
629
|
+
* and the turn goes on; a cancel aborts the turn like any other stop. The
|
|
630
|
+
* worktree stays either way. The setup belongs to the worktree it was made
|
|
631
|
+
* for: while the session works elsewhere (it returned to a project-folder
|
|
632
|
+
* branch before its first turn there) it is deferred, never run in another
|
|
633
|
+
* folder, and runs on the first turn after the session re-enters it.
|
|
634
|
+
*/
|
|
635
|
+
async function runPendingSetup(session, signal) {
|
|
636
|
+
const pending = pendingSetup;
|
|
637
|
+
if (!pending || pending.sessionId !== session.id) return;
|
|
638
|
+
const here = readSessionWorkspace(session);
|
|
639
|
+
if (!isWorktreeBound(here) || here.worktreeId !== pending.worktreeId || !samePath(here.cwd, pending.cwd)) return;
|
|
640
|
+
pendingSetup = null;
|
|
641
|
+
const id = newTxId();
|
|
642
|
+
const report = { root: pending.root, prepared: pending.prepared, dependencyNotes: [], installs: null, notes: [] };
|
|
643
|
+
const emit = (event) => {
|
|
644
|
+
for (const listener of setupListeners) {
|
|
645
|
+
try {
|
|
646
|
+
listener({ ...event, id, sessionId: session.id, cwd: pending.cwd });
|
|
647
|
+
} catch {
|
|
648
|
+
/* a viewer's failure never stops the setup */
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
};
|
|
418
652
|
try {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
});
|
|
424
|
-
} catch (error) {
|
|
425
|
-
// The settings default never blocks a task outside a git repository.
|
|
426
|
-
if (!intent.explicit && isWorktreeError(error, 'WORKTREE_UNSUPPORTED_REPO')) {
|
|
427
|
-
if (pendingIntent === intent) pendingIntent = null;
|
|
428
|
-
return null;
|
|
653
|
+
const plan = await planWorktreeSetup({ worktreeDir: pending.cwd, mainDir: pending.mainDir, signal });
|
|
654
|
+
report.dependencyNotes = plan.notes;
|
|
655
|
+
if (plan.commands.length) {
|
|
656
|
+
report.installs = await runWorktreeSetup({ commands: plan.commands, signal, onProgress: emit });
|
|
429
657
|
}
|
|
430
|
-
|
|
658
|
+
} catch (error) {
|
|
659
|
+
if (!signal?.aborted) report.notes.push(`Dependencies could not be prepared: ${error?.message || error}`);
|
|
431
660
|
}
|
|
661
|
+
session.pendingSetupNotice = { revision: Date.now(), content: worktreePreparationNote(report) };
|
|
662
|
+
throwIfAborted(signal);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/** Subscribe to worktree setup progress; returns the unsubscribe. */
|
|
666
|
+
function onWorktreeSetup(listener) {
|
|
667
|
+
if (typeof listener !== 'function') return () => {};
|
|
668
|
+
setupListeners.add(listener);
|
|
669
|
+
return () => setupListeners.delete(listener);
|
|
432
670
|
}
|
|
433
671
|
|
|
434
672
|
async function getBranchMenu() {
|
|
@@ -440,15 +678,30 @@ export function createWorkspaceTransitions({
|
|
|
440
678
|
projectPath: workspace.projectPath,
|
|
441
679
|
sessionId: session?.id || null,
|
|
442
680
|
});
|
|
443
|
-
|
|
681
|
+
const selectedEntry = workspace.worktreeId ? await (await backend()).findWorktreeContaining(workspace.cwd) : null;
|
|
682
|
+
// A session outside a managed worktree (the project folder — never moved,
|
|
683
|
+
// or back from a worktree — or a linked checkout of the selected branch)
|
|
444
684
|
// is on whatever that folder has checked out now.
|
|
445
|
-
|
|
685
|
+
// Its repository is the project's (a never-moved session has no stored
|
|
686
|
+
// record), and a detached checkout shows branch null with the commit in
|
|
687
|
+
// baseCommit — never mistaken for "not a repository".
|
|
688
|
+
let view = workspace;
|
|
689
|
+
if (!isWorktreeBound(workspace)) {
|
|
690
|
+
const project = await inspectProject(workspace.cwd);
|
|
691
|
+
const checkedOut = project.currentBranch ?? null;
|
|
692
|
+
view = {
|
|
693
|
+
...workspace,
|
|
694
|
+
repoCommonDir: project.repoCommonDir ?? workspace.repoCommonDir,
|
|
695
|
+
branch: checkedOut,
|
|
696
|
+
baseCommit: checkedOut ? workspace.baseCommit : (project.headCommit ?? null),
|
|
697
|
+
};
|
|
698
|
+
}
|
|
446
699
|
return {
|
|
447
|
-
workspace:
|
|
700
|
+
workspace: view,
|
|
448
701
|
pendingWorktree: pendingIntent ? { name: pendingIntent.name } : null,
|
|
449
702
|
branches: branchMenuEntries(menu.branches, menu.occupancy),
|
|
450
703
|
occupancy: menu.occupancy,
|
|
451
|
-
retainedWorktree: menu.retainedWorktree ?? null,
|
|
704
|
+
retainedWorktree: selectedEntry ?? menu.retainedWorktree ?? null,
|
|
452
705
|
// Creation notes of the retained worktree (submodules, include entries).
|
|
453
706
|
warnings: Array.isArray(menu.retainedWorktree?.warnings) ? [...menu.retainedWorktree.warnings] : [],
|
|
454
707
|
};
|
|
@@ -487,11 +740,13 @@ export function createWorkspaceTransitions({
|
|
|
487
740
|
|
|
488
741
|
async function selectBranch({ branch, create = false, expectedRevision, confirmLarge = false } = {}) {
|
|
489
742
|
const session = await ensureSession();
|
|
490
|
-
const
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
743
|
+
const current = currentWorkspace(session);
|
|
744
|
+
if (current.branch === branch && current.worktreeId) {
|
|
745
|
+
assertRevision(current.revision, validRevision(expectedRevision));
|
|
746
|
+
pendingIntent = null;
|
|
747
|
+
return { revision: current.revision, workspace: current };
|
|
748
|
+
}
|
|
749
|
+
const target = { kind: 'branch', branch, create: create === true };
|
|
495
750
|
const result = await applyWorkspaceTransition({ sessionId: session.id }, target, {
|
|
496
751
|
expectedRevision,
|
|
497
752
|
confirmLarge,
|
|
@@ -510,17 +765,28 @@ export function createWorkspaceTransitions({
|
|
|
510
765
|
* reuse it. Typed failures (large repository, disk, busy) therefore reach
|
|
511
766
|
* the sender while its draft is still unsent, and the turn that follows
|
|
512
767
|
* finds the session already bound.
|
|
768
|
+
*
|
|
769
|
+
* A provisioning that creates a new worktree decides the project folder's
|
|
770
|
+
* uncommitted changes (tracked and untracked): none → it proceeds; without
|
|
771
|
+
* `carryChanges` it refuses with WORKTREE_DIRTY_CHOICE (`details.count`);
|
|
772
|
+
* `leave` starts the worktree at HEAD and leaves them; `carry` moves them
|
|
773
|
+
* into it (the result's `changes` reports which). Re-entering a retained
|
|
774
|
+
* worktree never touches them.
|
|
513
775
|
*/
|
|
514
776
|
async function requestWorktree({
|
|
515
777
|
name = null,
|
|
516
778
|
confirmLarge = false,
|
|
517
779
|
provision = false,
|
|
780
|
+
carryChanges,
|
|
518
781
|
prompt = '',
|
|
519
782
|
txId = '',
|
|
520
783
|
expectedRevision,
|
|
521
784
|
} = {}) {
|
|
522
785
|
const nameHint = validName(name);
|
|
523
786
|
const expected = validRevision(expectedRevision);
|
|
787
|
+
if (carryChanges !== undefined && carryChanges !== null && !WORKTREE_CARRY_CHOICES.includes(carryChanges)) {
|
|
788
|
+
throw new TypeError(`carryChanges must be one of ${WORKTREE_CARRY_CHOICES.join(', ')}.`);
|
|
789
|
+
}
|
|
524
790
|
const session = provision === true ? await ensureSession() : getSession();
|
|
525
791
|
// No session yet: the menu it was read from had revision 0.
|
|
526
792
|
const current = session?.id ? currentWorkspace(session) : null;
|
|
@@ -536,6 +802,7 @@ export function createWorkspaceTransitions({
|
|
|
536
802
|
return { ...entered, pending: false };
|
|
537
803
|
}
|
|
538
804
|
}
|
|
805
|
+
const priorIntent = pendingIntent;
|
|
539
806
|
pendingIntent = {
|
|
540
807
|
name: nameHint ?? pendingIntent?.name ?? null,
|
|
541
808
|
confirmLarge: confirmLarge === true || pendingIntent?.confirmLarge === true,
|
|
@@ -544,10 +811,21 @@ export function createWorkspaceTransitions({
|
|
|
544
811
|
txId: pendingIntent?.txId ?? null,
|
|
545
812
|
};
|
|
546
813
|
if (provision === true) {
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
814
|
+
const intent = pendingIntent;
|
|
815
|
+
try {
|
|
816
|
+
return {
|
|
817
|
+
...(await provisionIntent(session, intent, txId, prompt, {
|
|
818
|
+
expectedRevision: expected,
|
|
819
|
+
changes: carryChanges ?? 'ask',
|
|
820
|
+
})),
|
|
821
|
+
pending: false,
|
|
822
|
+
};
|
|
823
|
+
} catch (error) {
|
|
824
|
+
// A refused move (uncommitted changes to decide, busy, …) is never
|
|
825
|
+
// re-armed for the next turn, where nobody could answer it.
|
|
826
|
+
if (pendingIntent === intent) pendingIntent = priorIntent;
|
|
827
|
+
throw error;
|
|
828
|
+
}
|
|
551
829
|
}
|
|
552
830
|
const workspace = session?.id ? currentWorkspace(session) : null;
|
|
553
831
|
return { revision: workspace?.revision ?? 0, workspace, pending: true };
|
|
@@ -570,23 +848,54 @@ export function createWorkspaceTransitions({
|
|
|
570
848
|
if (cleanup !== true || merged.merged !== true) return merged;
|
|
571
849
|
// "Merge and clean up": with autoCleanup on, the merged worktree goes now
|
|
572
850
|
// (a dirty one stays, reported); off, nothing is removed automatically.
|
|
851
|
+
// The merge is committed: a failed or refused cleanup (dirty, retained
|
|
852
|
+
// file recovery data, ...) is a cleanup notice, never a merge failure.
|
|
573
853
|
if (worktreeSettings().autoCleanup !== true) {
|
|
574
|
-
return {
|
|
854
|
+
return {
|
|
855
|
+
...merged,
|
|
856
|
+
cleanup: { removed: false, reason: 'auto-cleanup-off', message: 'Auto cleanup is off; the worktree is kept.' },
|
|
857
|
+
};
|
|
575
858
|
}
|
|
859
|
+
// The cleanup never moves a session: while this session still works in the
|
|
860
|
+
// merged folder (or any other session uses it) the removal is refused.
|
|
576
861
|
try {
|
|
577
|
-
|
|
862
|
+
if (isWorktreeBound(currentWorkspace(session))) {
|
|
863
|
+
throw worktreeRefusal('folder-in-use', { sessions: [session.id] });
|
|
864
|
+
}
|
|
865
|
+
const entry = await (await backend()).getSessionWorktree(session.id);
|
|
866
|
+
const removed = await withManagementFolders(
|
|
867
|
+
entry ? [entry.path] : [],
|
|
868
|
+
true,
|
|
869
|
+
() => removeWorktree({ force: false }, { ownTurn }),
|
|
870
|
+
{ actor: session.id }
|
|
871
|
+
);
|
|
578
872
|
return { ...merged, cleanup: removed.removed, revision: removed.revision, workspace: removed.workspace };
|
|
579
873
|
} catch (error) {
|
|
580
|
-
|
|
581
|
-
|
|
874
|
+
// The merge stands: a refused or incomplete cleanup (in use, dirty,
|
|
875
|
+
// unmerged, retained file recovery data, partly removed, …) is
|
|
876
|
+
// reported, never thrown, with the workspace as it is now.
|
|
877
|
+
const workspace = currentWorkspace(session);
|
|
878
|
+
const code = typeof error?.code === 'string' ? error.code : '';
|
|
879
|
+
return {
|
|
880
|
+
...merged,
|
|
881
|
+
cleanup: {
|
|
882
|
+
removed: false,
|
|
883
|
+
reason: code || 'WORKTREE_CLEANUP_FAILED',
|
|
884
|
+
...(code ? { code } : {}),
|
|
885
|
+
message: String(error?.message || error),
|
|
886
|
+
},
|
|
887
|
+
revision: workspace.revision,
|
|
888
|
+
workspace,
|
|
889
|
+
};
|
|
582
890
|
}
|
|
583
891
|
}
|
|
584
892
|
|
|
585
893
|
/**
|
|
586
894
|
* The merge itself. The retained worktree must belong to this session's
|
|
587
895
|
* Project (same repository and Project folder — a Project switch may have
|
|
588
|
-
* left it behind)
|
|
589
|
-
*
|
|
896
|
+
* left it behind); its branch, or the branch of the linked checkout the
|
|
897
|
+
* session works in, is merged into the project folder through the shared
|
|
898
|
+
* guarded path (mergeConfirmedTarget): both folders validated and held.
|
|
590
899
|
*/
|
|
591
900
|
async function mergeRetainedWorktree(session, { target, ownTurn, expectedRevision }) {
|
|
592
901
|
const workspace = currentWorkspace(session);
|
|
@@ -594,32 +903,72 @@ export function createWorkspaceTransitions({
|
|
|
594
903
|
const leave = beginWorkspaceTransition(session.id, `merge:${newTxId()}`);
|
|
595
904
|
try {
|
|
596
905
|
await assertLeadIdle(session, { ownTurn: ownTurn === true });
|
|
597
|
-
const backendApi = await backend();
|
|
598
|
-
const entry = await backendApi.getSessionWorktree(session.id);
|
|
599
|
-
if (!entry) throw worktreeError('WORKTREE_MISSING', 'This session has no worktree to merge.');
|
|
600
906
|
const project = await inspectProject(workspace.projectPath);
|
|
601
|
-
|
|
602
|
-
if (!samePath(
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
907
|
+
let branch;
|
|
908
|
+
if (!workspace.worktreeId && !samePath(workspace.cwd, workspace.projectPath)) {
|
|
909
|
+
const source = await inspectProject(workspace.cwd);
|
|
910
|
+
if (!samePath(source.repoCommonDir, project.repoCommonDir)) throw worktreeError('WORKTREE_PROJECT_MISMATCH');
|
|
911
|
+
branch = source.currentBranch;
|
|
912
|
+
} else {
|
|
913
|
+
const backendApi = await backend();
|
|
914
|
+
const entry = workspace.worktreeId
|
|
915
|
+
? await backendApi.findWorktreeContaining(workspace.cwd)
|
|
916
|
+
: await backendApi.getSessionWorktree(session.id);
|
|
917
|
+
if (!entry) throw worktreeError('WORKTREE_MISSING', 'This session has no worktree to merge.');
|
|
918
|
+
assertRetainedFits(entry, project, workspace.projectPath);
|
|
919
|
+
if (!samePath(entry.projectPath, workspace.projectPath)) {
|
|
920
|
+
throw worktreeError('WORKTREE_PROJECT_MISMATCH', undefined, {
|
|
921
|
+
worktreeId: entry.id,
|
|
922
|
+
worktreeProject: entry.projectPath,
|
|
923
|
+
projectPath: workspace.projectPath,
|
|
924
|
+
});
|
|
925
|
+
}
|
|
926
|
+
branch = entry.branch;
|
|
608
927
|
}
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
entryId: entry.id,
|
|
613
|
-
target: project.currentBranch,
|
|
614
|
-
confirmed: true,
|
|
615
|
-
projectPath: entry.projectPath,
|
|
616
|
-
})
|
|
928
|
+
return await mergeConfirmedTarget(
|
|
929
|
+
{ projectPath: workspace.projectPath, branch, target },
|
|
930
|
+
(folders, removing, run) => withManagementFolders(folders, removing, run, { actor: session.id })
|
|
617
931
|
);
|
|
618
932
|
} finally {
|
|
619
933
|
leave();
|
|
620
934
|
}
|
|
621
935
|
}
|
|
622
936
|
|
|
937
|
+
/**
|
|
938
|
+
* Move the hosted Lead to another Project folder (session set-project, the
|
|
939
|
+
* desktop/remote setCwd): the one authority for a Project switch, admitted
|
|
940
|
+
* like a workspace transition. Refused while a turn runs (`ownTurn`: the
|
|
941
|
+
* Lead's own tool call tolerates its calling turn), while workers run, and
|
|
942
|
+
* while the session works in a managed worktree. Serialized with turns and
|
|
943
|
+
* other workspace changes; the prompt refresh of the Lead and its idle
|
|
944
|
+
* workers completes (or rolls the switch back) before it resolves. Without
|
|
945
|
+
* a session (a draft) only the runtime cwd and the selection move.
|
|
946
|
+
* `classifyByMembership` (the desktop/remote move): a folder outside every
|
|
947
|
+
* registered Project is classified as a task (cwd-apply).
|
|
948
|
+
* @returns {Promise<string>} the runtime cwd after the switch
|
|
949
|
+
*/
|
|
950
|
+
async function switchProject(cwd, { ownTurn = false, classifyByMembership = false } = {}) {
|
|
951
|
+
const selection = { classifyByMembership: classifyByMembership === true };
|
|
952
|
+
const session = getSession();
|
|
953
|
+
if (!session?.id) {
|
|
954
|
+
applyResolvedCwd(cwd, { persistProjectSelection: true, ...selection });
|
|
955
|
+
return getCurrentCwd();
|
|
956
|
+
}
|
|
957
|
+
const leave = beginWorkspaceTransition(session.id, `project:${newTxId()}`);
|
|
958
|
+
const journal = [];
|
|
959
|
+
try {
|
|
960
|
+
await assertLeadIdle(session, { ownTurn: ownTurn === true, shellJobs: false });
|
|
961
|
+
if (isWorktreeBound(readSessionWorkspace(session))) throw new Error(WORKTREE_BOUND_SWITCH);
|
|
962
|
+
await steps.switchProject(session, cwd, journal, selection);
|
|
963
|
+
return getCurrentCwd();
|
|
964
|
+
} catch (error) {
|
|
965
|
+
await undoAll(journal, error);
|
|
966
|
+
throw error;
|
|
967
|
+
} finally {
|
|
968
|
+
leave();
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
|
|
623
972
|
async function removeWorktree({ force = false, expectedRevision } = {}, { ownTurn = false } = {}) {
|
|
624
973
|
const expected = validRevision(expectedRevision);
|
|
625
974
|
const session = hostedSession(null);
|
|
@@ -636,16 +985,22 @@ export function createWorkspaceTransitions({
|
|
|
636
985
|
admitTurnWorkspace,
|
|
637
986
|
/** The durable workspace record of the hosted session (null: project folder, never moved). */
|
|
638
987
|
getWorkspace: () => getSession()?.workspace ?? null,
|
|
988
|
+
/** What the session snapshot publishes (see getLiveWorkspace). */
|
|
989
|
+
getLiveWorkspace,
|
|
639
990
|
getBranchMenu,
|
|
640
991
|
getProjectBranchMenu: projectBranches.getProjectBranchMenu,
|
|
641
992
|
selectBranch,
|
|
642
993
|
selectProjectBranch: projectBranches.selectProjectBranch,
|
|
643
994
|
mergeProjectBranch: projectBranches.mergeProjectBranch,
|
|
995
|
+
inspectProjectBranch: projectBranches.inspectProjectBranch,
|
|
996
|
+
manageProjectBranch: projectBranches.manageProjectBranch,
|
|
644
997
|
requestWorktree,
|
|
645
998
|
mergeWorkspace,
|
|
646
999
|
removeWorktree,
|
|
1000
|
+
switchProject,
|
|
647
1001
|
listWorktrees,
|
|
648
1002
|
pruneWorktrees,
|
|
649
1003
|
cleanupDeletedSession,
|
|
1004
|
+
onWorktreeSetup,
|
|
650
1005
|
};
|
|
651
1006
|
}
|