mixdog 1.4.0 → 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/scripts/build-shipped-history.mjs +115 -33
- package/scripts/check-voice-runtime-inputs.mjs +25 -0
- package/scripts/gate-local.mjs +183 -63
- package/scripts/latest-guard.mjs +21 -9
- package/scripts/lib/gate-scheduler.mjs +138 -32
- package/scripts/lib/gate-timing-reporter.mjs +16 -0
- package/scripts/lib/isolated-test-env.mjs +10 -5
- package/scripts/lib/run-node-tests.mjs +91 -66
- package/scripts/lib/scoped-temp.d.mts +16 -0
- package/scripts/lib/scoped-temp.mjs +124 -0
- package/scripts/lib/stale-temp.mjs +44 -0
- package/scripts/lib/test-failure-records.mjs +14 -1
- package/scripts/lib/test-failure-summary.mjs +16 -4
- package/scripts/lib/test-spawn-ledger.mjs +12 -3
- package/scripts/post-release-check.mjs +1 -6
- package/scripts/pptx-kit-index.mjs +17 -5
- package/scripts/suite-health.mjs +115 -24
- package/scripts/test-data-dir.mjs +10 -7
- package/scripts/test.mjs +9 -14
- package/src/agents/advisor/AGENT.md +4 -4
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/explore/AGENT.md +22 -0
- package/src/agents/explore/agent.json +6 -0
- package/src/app.mjs +4 -0
- package/src/cli.mjs +7 -0
- package/src/defaults/agents.json +7 -0
- package/src/defaults/shipped-history.json +23 -2
- package/src/defaults/skills/browser-use/SKILL.md +10 -5
- package/src/defaults/skills/code-tidy/SKILL.md +71 -102
- package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
- package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
- package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
- package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
- package/src/defaults/skills/computer-use/SKILL.md +16 -4
- package/src/defaults/skills/goal-management/SKILL.md +1 -1
- package/src/defaults/skills/setup/references/actions.md +12 -6
- package/src/defaults/skills/setup/references/surfaces.md +2 -2
- package/src/defaults/skills/setup-guide/SKILL.md +5 -2
- package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
- package/src/defaults/skills/skill-creator/SKILL.md +85 -190
- package/src/defaults/skills/skill-creator/references/design.md +70 -162
- package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
- package/src/defaults/skills/test-suite/SKILL.md +194 -0
- package/src/defaults/skills/test-suite/references/case-management.md +51 -0
- package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
- package/src/defaults/skills/test-suite/references/reliability.md +49 -0
- package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
- package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
- package/src/defaults/skills/visualize/SKILL.md +6 -2
- package/src/lib/rules-builder.cjs +35 -42
- package/src/output-styles/common.md +2 -2
- package/src/output-styles/simple.md +1 -1
- package/src/rules/agent/AGENT.md +5 -4
- package/src/rules/lead/LEAD.md +12 -7
- package/src/rules/shared/10-tool-workflow.md +3 -1
- package/src/rules/shared/20-research.md +3 -6
- package/src/rules/shared/40-editing.md +1 -0
- package/src/rules/shared/45-destructive.md +0 -2
- package/src/rules/shared/50-execution.md +2 -0
- package/src/rules/shared/60-verification.md +10 -9
- package/src/rules/shared/70-delivery.md +8 -9
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -1
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +156 -24
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -0
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
- package/src/runtime/agent/orchestrator/cache-break-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/config.mjs +12 -7
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +8 -8
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +5 -26
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +3 -1
- package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +122 -12
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +5 -3
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +13 -2
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +152 -58
- package/src/runtime/agent/orchestrator/mcp/client.mjs +51 -18
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +88 -54
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +42 -26
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +54 -8
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +37 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +31 -21
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +14 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +1 -10
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
- package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/devin.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +248 -41
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -11
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +45 -6
- package/src/runtime/agent/orchestrator/providers/lib/first-output-window.mjs +58 -0
- package/src/runtime/agent/orchestrator/providers/lib/listen-on.mjs +14 -0
- package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +1 -10
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +14 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +4 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +5 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +13 -3
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +13 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +81 -42
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +160 -31
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +22 -12
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +49 -22
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/registry.mjs +45 -2
- package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +567 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +41 -13
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -6
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +7 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +6 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +14 -5
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
- package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +1 -3
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +102 -12
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -8
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +103 -23
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +160 -36
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +164 -23
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +139 -19
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +38 -7
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +100 -22
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -6
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +33 -3
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +9 -2
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +14 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +23 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +39 -21
- package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +50 -28
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +30 -13
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +63 -6
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +35 -13
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +24 -14
- package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
- package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +10 -6
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +56 -29
- package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +30 -7
- package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +37 -8
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +252 -39
- package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +164 -4
- package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +61 -2
- package/src/runtime/agent/orchestrator/stall-policy.mjs +23 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +46 -20
- package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +67 -31
- package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +25 -13
- package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +6 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +23 -12
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +1 -8
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +96 -20
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/federation.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/isolated-test-env.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
- package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +103 -13
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +34 -10
- package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +28 -4
- package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -2
- package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
- package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
- package/src/runtime/channels/lib/whisper-port.mjs +29 -11
- package/src/runtime/channels/lib/whisper-server.mjs +10 -1
- package/src/runtime/computer-bridge/action-schema.mjs +2 -2
- package/src/runtime/computer-bridge/core-actions.mjs +2 -2
- package/src/runtime/computer-bridge/error-recovery.mjs +5 -4
- package/src/runtime/computer-bridge/linux-action-capabilities.mjs +24 -5
- package/src/runtime/computer-bridge/linux-readiness.d.mts +7 -2
- package/src/runtime/connectors/connector-accounts-mcp.mjs +236 -103
- package/src/runtime/connectors/gmail-app-password.mjs +3 -3
- package/src/runtime/explore/explorer.mjs +93 -0
- package/src/runtime/explore/tool-defs.mjs +35 -0
- package/src/runtime/explore/tool.mjs +123 -0
- package/src/runtime/local-provider/server-process.mjs +2 -1
- package/src/runtime/media/adapters/gemini-video.mjs +4 -1
- package/src/runtime/media/adapters/xai-media.mjs +2 -1
- package/src/runtime/memory/index.mjs +4 -0
- package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
- package/src/runtime/memory/lib/embedding-worker.mjs +10 -3
- package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +1 -7
- package/src/runtime/memory/lib/memory-chunk-quality.mjs +1 -6
- package/src/runtime/office/authoring/pdf-author-action.mjs +1 -6
- package/src/runtime/office/design/design-art-direction.mjs +29 -27
- package/src/runtime/office/pdf/pdf-writer.mjs +6 -1
- package/src/runtime/office/portable/portable-snapshot-docx.mjs +7 -1
- package/src/runtime/office/portable/portable-snapshot-shared.mjs +6 -1
- package/src/runtime/office/quality/assurance-rendered.mjs +9 -2
- package/src/runtime/office/quality/assurance-structure-docx.mjs +4 -2
- package/src/runtime/office/quality/design-review.mjs +1 -5
- package/src/runtime/office/quality/document-brief.mjs +1 -5
- package/src/runtime/office/quality/forced-break-pages.mjs +9 -6
- package/src/runtime/office/quality/quality-pipeline.mjs +1 -1
- package/src/runtime/shared/agent-route-config.mjs +17 -2
- package/src/runtime/shared/atomic-file.mjs +103 -2
- package/src/runtime/shared/background-tasks.mjs +15 -6
- package/src/runtime/shared/bot-owned-work.mjs +56 -0
- package/src/runtime/shared/connector-accounts.mjs +5 -5
- package/src/runtime/shared/connector-catalog.d.mts +11 -4
- package/src/runtime/shared/connector-catalog.mjs +60 -52
- package/src/runtime/shared/custom-provider-keys.mjs +20 -0
- package/src/runtime/shared/defaults-separation.mjs +1 -4
- package/src/runtime/shared/fetch-safe-listen.d.mts +16 -0
- package/src/runtime/shared/fetch-safe-listen.mjs +50 -0
- package/src/runtime/shared/file-has-data.mjs +26 -2
- package/src/runtime/shared/file-lock.mjs +13 -15
- package/src/runtime/shared/git-launch.d.mts +9 -0
- package/src/runtime/shared/git-launch.mjs +213 -0
- package/src/runtime/shared/git-runner-worker.mjs +2 -1
- package/src/runtime/shared/handoff-artifacts.d.mts +2 -1
- package/src/runtime/shared/handoff-artifacts.mjs +18 -8
- package/src/runtime/shared/idle-auto-clear-gate.mjs +29 -7
- package/src/runtime/shared/llm/cost.mjs +11 -2
- package/src/runtime/shared/llm/http-agent.mjs +313 -29
- package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
- package/src/runtime/shared/llm/model-catalog.mjs +46 -6
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
- package/src/runtime/shared/llm/system-proxy.mjs +452 -0
- package/src/runtime/shared/loopback-listener.mjs +25 -2
- package/src/runtime/shared/model-route-chain.d.mts +7 -2
- package/src/runtime/shared/model-route-chain.mjs +22 -4
- package/src/runtime/shared/open-url.mjs +10 -0
- package/src/runtime/shared/provider-accounts.mjs +52 -2
- package/src/runtime/shared/session-activity-signal.mjs +14 -0
- package/src/runtime/shared/session-scratch.mjs +37 -0
- package/src/runtime/shared/staged-install-worker.mjs +5 -0
- package/src/runtime/shared/staged-update.mjs +47 -2
- package/src/runtime/shared/tool-card-model/agent-surface.mjs +1 -3
- package/src/runtime/shared/tool-card-model/card-status.mjs +15 -2
- package/src/runtime/shared/tool-result-summary.mjs +1 -1
- package/src/runtime/shared/tool-surface.mjs +113 -36
- package/src/runtime/shared/tool-work-units.mjs +6 -0
- package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
- package/src/runtime/shared/turn-worktree-snapshot.mjs +414 -54
- package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
- package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
- package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
- package/src/runtime/shared/worktrees/branch-management.mjs +9 -3
- package/src/runtime/shared/worktrees/contract.mjs +4 -1
- package/src/runtime/shared/worktrees/git.mjs +72 -0
- package/src/runtime/shared/worktrees/manager.mjs +285 -168
- package/src/runtime/shared/worktrees/test-support.mjs +6 -10
- package/src/runtime/tidy/install.mjs +95 -15
- package/src/runtime/tidy/languages.mjs +17 -15
- package/src/runtime/tidy/process.mjs +7 -4
- package/src/runtime/tidy/resolve.mjs +19 -16
- package/src/runtime/tidy/runners/biome.mjs +3 -3
- package/src/runtime/tidy/tool.mjs +1 -1
- package/src/runtime/tidy/worktree.mjs +10 -6
- package/src/runtime/visualize-bridge/client.mjs +6 -1
- package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
- package/src/runtime/web-search/index.mjs +1 -1
- package/src/session-runtime/agent-home-delivery.mjs +41 -0
- package/src/session-runtime/agent-task-sessions.mjs +458 -312
- package/src/session-runtime/agent-tool-routing.mjs +8 -41
- package/src/session-runtime/boot/tools.mjs +7 -1
- package/src/session-runtime/bot-status.mjs +107 -101
- package/src/session-runtime/bot-target.mjs +38 -0
- package/src/session-runtime/channel-config-api.mjs +6 -1
- package/src/session-runtime/connector-merge-migration.mjs +18 -15
- package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
- package/src/session-runtime/conversation-import/discovery.mjs +401 -36
- package/src/session-runtime/conversation-import/service.mjs +35 -8
- package/src/session-runtime/handoff-attachments.mjs +82 -31
- package/src/session-runtime/held-requests.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +12 -13
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +1 -0
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -0
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
- package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +145 -112
- package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
- package/src/session-runtime/lifecycle/session-catalog.mjs +9 -1
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -1
- package/src/session-runtime/lifecycle/teardown.mjs +1 -1
- package/src/session-runtime/mcp-glue/server-catalog.mjs +16 -10
- package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
- package/src/session-runtime/mixy-heartbeat.mjs +1 -1
- package/src/session-runtime/model-route/set-route.mjs +11 -2
- package/src/session-runtime/provider-auth/login.mjs +2 -2
- package/src/session-runtime/provider-catalog-cache.mjs +82 -36
- package/src/session-runtime/provider-models/catalog-load.mjs +23 -6
- package/src/session-runtime/provider-models.mjs +4 -2
- package/src/session-runtime/resource-mcp-api.mjs +98 -35
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +44 -31
- package/src/session-runtime/resource-mcp-secrets.mjs +28 -11
- package/src/session-runtime/resource-mcp-servers.mjs +5 -4
- package/src/session-runtime/resource-recall-api.mjs +6 -1
- package/src/session-runtime/runtime-feature-gates.mjs +5 -1
- package/src/session-runtime/services/agent-tool/execute.mjs +14 -9
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +20 -4
- package/src/session-runtime/services/agent-tool/model-select.mjs +48 -7
- package/src/session-runtime/services/agent-tool/render.mjs +71 -17
- package/src/session-runtime/services/agent-tool/send-flow.mjs +10 -2
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +4 -1
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +6 -2
- package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
- package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
- package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
- package/src/session-runtime/services/daemon-candidate.mjs +4 -1
- package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
- package/src/session-runtime/services/plugin-admin.mjs +10 -6
- package/src/session-runtime/services/provider-admin.mjs +283 -11
- package/src/session-runtime/session-turn-api.mjs +2 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +4 -1
- package/src/session-runtime/settings-system-api.mjs +1 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
- package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
- package/src/session-runtime/setup-tool/executor.mjs +6 -2
- package/src/session-runtime/setup-tool/tool-defs.mjs +2 -1
- package/src/session-runtime/tool-policy/policy-stage.mjs +1 -0
- package/src/session-runtime/turn/agent-ops.mjs +23 -0
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +49 -11
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +25 -5
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
- package/src/session-runtime/workspace/activity-guards.mjs +176 -0
- package/src/session-runtime/workspace/session-view.mjs +149 -0
- package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
- package/src/session-runtime/workspace/transition-runner.mjs +188 -0
- package/src/session-runtime/workspace/transitions.mjs +108 -1041
- package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
- package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
- package/src/session-runtime/workspace/worktree-maintenance.mjs +80 -0
- package/src/session-runtime/workspace/worktree-setup.mjs +85 -0
- package/src/session-runtime/workspace/worktree-tool.mjs +73 -56
- package/src/standalone/daemon-desktop-runtime.mjs +2 -0
- package/src/standalone/daemon-session-control.mjs +169 -138
- package/src/standalone/daemon.mjs +7 -0
- package/src/standalone/desktop-service-registry.mjs +9 -0
- package/src/standalone/local-session-runtime.mjs +5 -1
- package/src/standalone/session-client/daemon-unavailable.mjs +3 -0
- package/src/standalone/session-client.mjs +5 -1
- package/src/standalone/session-frame-stream.mjs +83 -11
- package/src/standalone/session-protocol.mjs +4 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
- package/src/standalone/session-service/agent-tree.mjs +45 -9
- package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
- package/src/standalone/session-service/session-calls/session-action.mjs +10 -3
- package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
- package/src/standalone/session-service/stored-reader.mjs +127 -40
- package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
- package/src/tui/App.jsx +154 -164
- package/src/tui/app/app-view/floating-panel.jsx +10 -4
- package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
- package/src/tui/app/clipboard.mjs +21 -10
- package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +1 -3
- package/src/tui/app/model-picker/route-selection.mjs +5 -6
- package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
- package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
- package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
- package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
- package/src/tui/app/provider-setup/oauth-actions.mjs +58 -21
- package/src/tui/app/provider-setup/provider-items.mjs +8 -2
- package/src/tui/app/provider-setup-picker.mjs +29 -18
- package/src/tui/app/shell-layout/row-budgets.mjs +12 -10
- package/src/tui/app/slash-commands.mjs +1 -0
- package/src/tui/app/slash-dispatch/session-commands.mjs +46 -0
- package/src/tui/app/slash-dispatch.mjs +1 -1
- package/src/tui/app/use-btw-panel.mjs +29 -0
- package/src/tui/app/use-context-panel-refresh.mjs +31 -0
- package/src/tui/app/use-model-catalog-cache.mjs +13 -10
- package/src/tui/app/use-mouse-input.mjs +11 -0
- package/src/tui/app/use-onboarding-start.mjs +8 -3
- package/src/tui/app/use-panel-transition.mjs +10 -1
- package/src/tui/app/use-pasted-buffers.mjs +28 -20
- package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
- package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
- package/src/tui/app/use-prompt-queue-history.mjs +3 -2
- package/src/tui/app/use-selection-focus.mjs +11 -2
- package/src/tui/app/use-selection-geometry.mjs +18 -9
- package/src/tui/app/use-selection-paint.mjs +4 -4
- package/src/tui/app/use-selection-stitch.mjs +3 -3
- package/src/tui/app/use-slash-palette.mjs +62 -0
- package/src/tui/app/use-terminal-chrome.mjs +2 -2
- package/src/tui/app/use-transcript-activity.mjs +47 -32
- package/src/tui/app/use-transcript-follow.mjs +12 -4
- package/src/tui/app/use-transcript-scroll.mjs +46 -17
- package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
- package/src/tui/app/use-transcript-window/geometry.mjs +19 -5
- package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
- package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
- package/src/tui/app/use-transcript-window.mjs +21 -11
- package/src/tui/app/use-tui-ready.mjs +18 -0
- package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
- package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
- package/src/tui/components/Picker.jsx +27 -3
- package/src/tui/components/QuestionPanel.jsx +13 -4
- package/src/tui/components/SignInUrl.jsx +68 -0
- package/src/tui/components/TextEntryPanel.jsx +76 -46
- package/src/tui/components/sign-in-url-layout.mjs +24 -0
- package/src/tui/dist/index.mjs +1963 -1361
- package/src/tui/session/goal-turn-state.mjs +6 -2
- package/src/tui/session/session-api/controls.mjs +4 -0
- package/src/tui/session/session-api/extensions.mjs +8 -0
- package/src/tui/session/session-api/intake/abort.mjs +2 -1
- package/src/tui/session/session-api/intake.mjs +2 -0
- package/src/tui/session/session-api/integrations.mjs +2 -2
- package/src/tui/session/session-api/routes-agent-definitions.mjs +1 -0
- package/src/tui/session/session-api/settings.mjs +2 -2
- package/src/tui/session/session-flow/queue/take-entries.mjs +11 -0
- package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
- package/src/tui/session/transcript-spill.mjs +92 -4
- package/src/tui/session/transcript-store.mjs +2 -0
- package/src/ui/statusline-agents.mjs +1 -3
- package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merging the hosted Lead's retained worktree (or the linked checkout it
|
|
3
|
+
* works in) into the project folder's checked-out branch, with the optional
|
|
4
|
+
* cleanup of the merged worktree.
|
|
5
|
+
*/
|
|
6
|
+
import { isWorktreeBound, worktreeError, worktreeRefusal } from '../../runtime/shared/worktrees/contract.mjs';
|
|
7
|
+
import { samePath } from '../../runtime/shared/worktrees/paths.mjs';
|
|
8
|
+
import { mergeConfirmedTarget } from '../../runtime/shared/worktrees/branch-management.mjs';
|
|
9
|
+
import { beginWorkspaceTransition } from './admission-gate.mjs';
|
|
10
|
+
import { assertRetainedFits } from './transition-steps.mjs';
|
|
11
|
+
import { assertRevision, validRevision } from './transition-runner.mjs';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {object} deps The session view, assertLeadIdle, withManagementFolders,
|
|
15
|
+
* the runner's removeWorktree, `backend()` and `worktreeSettings()`.
|
|
16
|
+
*/
|
|
17
|
+
export function createWorkspaceMerge({
|
|
18
|
+
hostedSession,
|
|
19
|
+
currentWorkspace,
|
|
20
|
+
assertLeadIdle,
|
|
21
|
+
inspectProject,
|
|
22
|
+
backend,
|
|
23
|
+
withManagementFolders,
|
|
24
|
+
removeWorktree,
|
|
25
|
+
worktreeSettings,
|
|
26
|
+
newTxId,
|
|
27
|
+
}) {
|
|
28
|
+
/**
|
|
29
|
+
* The merge itself. The retained worktree must belong to this session's
|
|
30
|
+
* Project (same repository and Project folder — a Project switch may have
|
|
31
|
+
* left it behind); its branch, or the branch of the linked checkout the
|
|
32
|
+
* session works in, is merged into the project folder through the shared
|
|
33
|
+
* guarded path (mergeConfirmedTarget): both folders validated and held.
|
|
34
|
+
*/
|
|
35
|
+
async function mergeRetainedWorktree(session, { target, ownTurn, expectedRevision }) {
|
|
36
|
+
const workspace = currentWorkspace(session);
|
|
37
|
+
assertRevision(workspace.revision, expectedRevision);
|
|
38
|
+
const leave = beginWorkspaceTransition(session.id, `merge:${newTxId()}`);
|
|
39
|
+
try {
|
|
40
|
+
await assertLeadIdle(session, { ownTurn: ownTurn === true });
|
|
41
|
+
const project = await inspectProject(workspace.projectPath);
|
|
42
|
+
let branch;
|
|
43
|
+
if (!workspace.worktreeId && !samePath(workspace.cwd, workspace.projectPath)) {
|
|
44
|
+
const source = await inspectProject(workspace.cwd);
|
|
45
|
+
if (!samePath(source.repoCommonDir, project.repoCommonDir)) throw worktreeError('WORKTREE_PROJECT_MISMATCH');
|
|
46
|
+
branch = source.currentBranch;
|
|
47
|
+
} else {
|
|
48
|
+
const backendApi = await backend();
|
|
49
|
+
const entry = workspace.worktreeId
|
|
50
|
+
? await backendApi.findWorktreeContaining(workspace.cwd)
|
|
51
|
+
: await backendApi.getSessionWorktree(session.id);
|
|
52
|
+
if (!entry) throw worktreeError('WORKTREE_MISSING', 'This session has no worktree to merge.');
|
|
53
|
+
assertRetainedFits(entry, project, workspace.projectPath);
|
|
54
|
+
if (!samePath(entry.projectPath, workspace.projectPath)) {
|
|
55
|
+
throw worktreeError('WORKTREE_PROJECT_MISMATCH', undefined, {
|
|
56
|
+
worktreeId: entry.id,
|
|
57
|
+
worktreeProject: entry.projectPath,
|
|
58
|
+
projectPath: workspace.projectPath,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
branch = entry.branch;
|
|
62
|
+
}
|
|
63
|
+
return await mergeConfirmedTarget(
|
|
64
|
+
{ projectPath: workspace.projectPath, branch, target },
|
|
65
|
+
(folders, removing, run) => withManagementFolders(folders, removing, run, { actor: session.id })
|
|
66
|
+
);
|
|
67
|
+
} finally {
|
|
68
|
+
leave();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Merge the retained worktree into the project folder's checked-out branch.
|
|
74
|
+
* `ownTurn` (internal: the Lead's own tool call) tolerates the calling turn.
|
|
75
|
+
*/
|
|
76
|
+
async function mergeWorkspace(
|
|
77
|
+
{ confirmed = false, target = null, cleanup = false, expectedRevision } = {},
|
|
78
|
+
{ ownTurn = false } = {}
|
|
79
|
+
) {
|
|
80
|
+
if (confirmed !== true) {
|
|
81
|
+
throw worktreeError('WORKTREE_CONFIRM_REQUIRED', 'mergeWorkspace requires confirmed: true.');
|
|
82
|
+
}
|
|
83
|
+
const expected = validRevision(expectedRevision);
|
|
84
|
+
const session = hostedSession(null);
|
|
85
|
+
const merged = await mergeRetainedWorktree(session, { target, ownTurn, expectedRevision: expected });
|
|
86
|
+
if (cleanup !== true || merged.merged !== true) return merged;
|
|
87
|
+
// "Merge and clean up": with autoCleanup on, the merged worktree goes now
|
|
88
|
+
// (a dirty one stays, reported); off, nothing is removed automatically.
|
|
89
|
+
// The merge is committed: a failed or refused cleanup (dirty, retained
|
|
90
|
+
// file recovery data, ...) is a cleanup notice, never a merge failure.
|
|
91
|
+
if (worktreeSettings().autoCleanup !== true) {
|
|
92
|
+
return {
|
|
93
|
+
...merged,
|
|
94
|
+
cleanup: { removed: false, reason: 'auto-cleanup-off', message: 'Auto cleanup is off; the worktree is kept.' },
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
// The cleanup never moves a session: while this session still works in the
|
|
98
|
+
// merged folder (or any other session uses it) the removal is refused.
|
|
99
|
+
try {
|
|
100
|
+
if (isWorktreeBound(currentWorkspace(session))) {
|
|
101
|
+
throw worktreeRefusal('folder-in-use', { sessions: [session.id] });
|
|
102
|
+
}
|
|
103
|
+
const entry = await (await backend()).getSessionWorktree(session.id);
|
|
104
|
+
const removed = await withManagementFolders(
|
|
105
|
+
entry ? [entry.path] : [],
|
|
106
|
+
true,
|
|
107
|
+
() => removeWorktree({ force: false }, { ownTurn }),
|
|
108
|
+
{ actor: session.id }
|
|
109
|
+
);
|
|
110
|
+
return { ...merged, cleanup: removed.removed, revision: removed.revision, workspace: removed.workspace };
|
|
111
|
+
} catch (error) {
|
|
112
|
+
// The merge stands: a refused or incomplete cleanup (in use, dirty,
|
|
113
|
+
// unmerged, retained file recovery data, partly removed, …) is
|
|
114
|
+
// reported, never thrown, with the workspace as it is now.
|
|
115
|
+
const workspace = currentWorkspace(session);
|
|
116
|
+
const code = typeof error?.code === 'string' ? error.code : '';
|
|
117
|
+
return {
|
|
118
|
+
...merged,
|
|
119
|
+
cleanup: {
|
|
120
|
+
removed: false,
|
|
121
|
+
reason: code || 'WORKTREE_CLEANUP_FAILED',
|
|
122
|
+
...(code ? { code } : {}),
|
|
123
|
+
message: String(error?.message || error),
|
|
124
|
+
},
|
|
125
|
+
revision: workspace.revision,
|
|
126
|
+
workspace,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return { mergeWorkspace };
|
|
132
|
+
}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pending worktree intent of the hosted Lead: armed at creation (the New
|
|
3
|
+
* task default or an explicit choice) or by "워크트리", and provisioned at
|
|
4
|
+
* the start of the next turn (or at once, for a New Task's first send).
|
|
5
|
+
*/
|
|
6
|
+
import {
|
|
7
|
+
WORKTREE_CARRY_CHOICES,
|
|
8
|
+
isWorktreeBound,
|
|
9
|
+
isWorktreeError,
|
|
10
|
+
worktreeError,
|
|
11
|
+
} from '../../runtime/shared/worktrees/contract.mjs';
|
|
12
|
+
import { sessionHasConversationMessages } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
13
|
+
import { promptContentText } from '../../runtime/agent/orchestrator/session/manager/prompt-utils.mjs';
|
|
14
|
+
import { assertRevision, validName, validRevision } from './transition-runner.mjs';
|
|
15
|
+
import { readSessionWorkspace } from './workspace-state.mjs';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Creation-time intent: `{ mode: 'worktree', name }` asks for a worktree;
|
|
19
|
+
* `{ mode: 'default' }` — an interactive Lead the user starts (TUI launch) —
|
|
20
|
+
* follows the settings `newTaskDefault`; `{ mode: 'branch' }` or no intent
|
|
21
|
+
* runs in the project folder. Desktop tasks carry their choice from the
|
|
22
|
+
* renderer, and agents, schedules, webhooks and resumed sessions pass none,
|
|
23
|
+
* so the default never applies to them.
|
|
24
|
+
*/
|
|
25
|
+
export function creationIntent(worktree, settings) {
|
|
26
|
+
if (worktree?.mode === 'worktree') {
|
|
27
|
+
return { name: worktree.name ?? null, confirmLarge: false, explicit: true, sessionId: null, txId: null };
|
|
28
|
+
}
|
|
29
|
+
return worktree?.mode === 'default' && settings.newTaskDefault === 'worktree'
|
|
30
|
+
? { name: null, confirmLarge: false, explicit: false, sessionId: null, txId: null }
|
|
31
|
+
: null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {object} deps `initial` (creationIntent), the session view, the
|
|
36
|
+
* transition runner, `runPendingSetup` and the host's session hooks.
|
|
37
|
+
*/
|
|
38
|
+
export function createWorktreeIntents({
|
|
39
|
+
initial,
|
|
40
|
+
getSession,
|
|
41
|
+
getReservedSessionId,
|
|
42
|
+
ensureSession,
|
|
43
|
+
currentWorkspace,
|
|
44
|
+
backend,
|
|
45
|
+
transition,
|
|
46
|
+
runTransition,
|
|
47
|
+
runPendingSetup,
|
|
48
|
+
newTxId,
|
|
49
|
+
}) {
|
|
50
|
+
let pendingIntent = initial;
|
|
51
|
+
|
|
52
|
+
/** The pending worktree intent that applies to `session`'s next turn, if any. */
|
|
53
|
+
function intentFor(session) {
|
|
54
|
+
const intent = pendingIntent;
|
|
55
|
+
if (!intent) return null;
|
|
56
|
+
if (isWorktreeBound(readSessionWorkspace(session))) {
|
|
57
|
+
pendingIntent = null;
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
if (intent.sessionId) return intent.sessionId === session.id ? intent : null;
|
|
61
|
+
// A creation-time intent belongs to a new task: never to a resumed
|
|
62
|
+
// conversation this runtime opened instead.
|
|
63
|
+
const started =
|
|
64
|
+
sessionHasConversationMessages(session) || sessionHasConversationMessages({ messages: session.liveTurnMessages });
|
|
65
|
+
return started ? null : intent;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Create and enter the worktree `intent` asks for now: its txId is fixed on
|
|
70
|
+
* first use (`submissionId`, else a fresh one) so a retry reuses the same
|
|
71
|
+
* worktree, and the prompt text names an unnamed one. A settled intent is
|
|
72
|
+
* consumed.
|
|
73
|
+
*/
|
|
74
|
+
async function provisionIntent(session, intent, submissionId, prompt, options) {
|
|
75
|
+
intent.txId ||= String(submissionId || '').trim() || newTxId();
|
|
76
|
+
const result = await transition(
|
|
77
|
+
session,
|
|
78
|
+
{ kind: 'worktree', name: intent.name },
|
|
79
|
+
{ txId: intent.txId, nameHint: promptContentText(prompt), confirmLarge: intent.confirmLarge, ...options }
|
|
80
|
+
);
|
|
81
|
+
if (pendingIntent === intent) pendingIntent = null;
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Turn-start workspace gate, run after the session exists and before the
|
|
87
|
+
* user row, the review snapshot, hooks, the provider and any worker spawn.
|
|
88
|
+
* A session in recovery refuses the turn; a pending worktree intent is
|
|
89
|
+
* provisioned now (txId = the first submission id, reused by retries; an
|
|
90
|
+
* unnamed worktree takes its slug from the first message).
|
|
91
|
+
*/
|
|
92
|
+
async function prepareTurnWorkspace({ submissionId = '', prompt = '', signal, confirmLarge = false } = {}) {
|
|
93
|
+
const session = getSession();
|
|
94
|
+
if (!session?.id) return null;
|
|
95
|
+
const stored = readSessionWorkspace(session);
|
|
96
|
+
if (stored?.transition.state === 'recovery') {
|
|
97
|
+
throw worktreeError(
|
|
98
|
+
'WORKTREE_MISSING',
|
|
99
|
+
'The worktree for this session no longer exists; pick a branch or remove the worktree to continue.',
|
|
100
|
+
{ worktreeId: stored.worktreeId, path: stored.cwd }
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
const intent = intentFor(session);
|
|
104
|
+
let result = null;
|
|
105
|
+
if (intent) {
|
|
106
|
+
try {
|
|
107
|
+
result = await provisionIntent(session, intent, submissionId, prompt, {
|
|
108
|
+
confirmLarge: intent.confirmLarge || confirmLarge === true,
|
|
109
|
+
signal,
|
|
110
|
+
ownTurn: true,
|
|
111
|
+
});
|
|
112
|
+
} catch (error) {
|
|
113
|
+
// The settings default never blocks a task outside a git repository.
|
|
114
|
+
if (!intent.explicit && isWorktreeError(error, 'WORKTREE_UNSUPPORTED_REPO')) {
|
|
115
|
+
if (pendingIntent === intent) pendingIntent = null;
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
await runPendingSetup(session, signal);
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* "워크트리": re-enter the retained worktree now, or arm the lazy creation
|
|
127
|
+
* for the next message (confirmLarge acknowledges WORKTREE_LARGE_REPO_CONFIRM).
|
|
128
|
+
*
|
|
129
|
+
* `provision` (a New Task's first send, before its prompt is submitted)
|
|
130
|
+
* creates and enters the worktree right away instead: `prompt` names it
|
|
131
|
+
* like the lazy path would and `txId` (the submission id) makes a resend
|
|
132
|
+
* reuse it. Typed failures (large repository, disk, busy) therefore reach
|
|
133
|
+
* the sender while its draft is still unsent, and the turn that follows
|
|
134
|
+
* finds the session already bound.
|
|
135
|
+
*
|
|
136
|
+
* A provisioning that creates a new worktree decides the project folder's
|
|
137
|
+
* uncommitted changes (tracked and untracked): none → it proceeds; without
|
|
138
|
+
* `carryChanges` it refuses with WORKTREE_DIRTY_CHOICE (`details.count`);
|
|
139
|
+
* `leave` starts the worktree at HEAD and leaves them; `carry` moves them
|
|
140
|
+
* into it (the result's `changes` reports which). Re-entering a retained
|
|
141
|
+
* worktree never touches them.
|
|
142
|
+
*
|
|
143
|
+
* `ownTurn` (internal: the Lead's own tool call) tolerates the calling turn.
|
|
144
|
+
*/
|
|
145
|
+
async function requestWorktree(
|
|
146
|
+
{
|
|
147
|
+
name = null,
|
|
148
|
+
confirmLarge = false,
|
|
149
|
+
provision = false,
|
|
150
|
+
carryChanges,
|
|
151
|
+
prompt = '',
|
|
152
|
+
txId = '',
|
|
153
|
+
expectedRevision,
|
|
154
|
+
} = {},
|
|
155
|
+
{ ownTurn = false } = {}
|
|
156
|
+
) {
|
|
157
|
+
const nameHint = validName(name);
|
|
158
|
+
const expected = validRevision(expectedRevision);
|
|
159
|
+
if (carryChanges !== undefined && carryChanges !== null && !WORKTREE_CARRY_CHOICES.includes(carryChanges)) {
|
|
160
|
+
throw new TypeError(`carryChanges must be one of ${WORKTREE_CARRY_CHOICES.join(', ')}.`);
|
|
161
|
+
}
|
|
162
|
+
const session = provision === true ? await ensureSession() : getSession();
|
|
163
|
+
// No session yet: the menu it was read from had revision 0.
|
|
164
|
+
const current = session?.id ? currentWorkspace(session) : null;
|
|
165
|
+
assertRevision(current?.revision ?? 0, expected);
|
|
166
|
+
if (current) {
|
|
167
|
+
if (isWorktreeBound(current)) return { revision: current.revision, workspace: current, pending: false };
|
|
168
|
+
if (await (await backend()).getSessionWorktree(session.id)) {
|
|
169
|
+
const entered = await runTransition(
|
|
170
|
+
{ sessionId: session.id },
|
|
171
|
+
{ kind: 'worktree' },
|
|
172
|
+
{ expectedRevision: expected },
|
|
173
|
+
{ ownTurn }
|
|
174
|
+
);
|
|
175
|
+
return { ...entered, pending: false };
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const priorIntent = pendingIntent;
|
|
179
|
+
pendingIntent = {
|
|
180
|
+
name: nameHint ?? pendingIntent?.name ?? null,
|
|
181
|
+
confirmLarge: confirmLarge === true || pendingIntent?.confirmLarge === true,
|
|
182
|
+
explicit: true,
|
|
183
|
+
sessionId: session?.id || getReservedSessionId?.() || null,
|
|
184
|
+
txId: pendingIntent?.txId ?? null,
|
|
185
|
+
};
|
|
186
|
+
if (provision === true) {
|
|
187
|
+
const intent = pendingIntent;
|
|
188
|
+
try {
|
|
189
|
+
return {
|
|
190
|
+
...(await provisionIntent(session, intent, txId, prompt, {
|
|
191
|
+
expectedRevision: expected,
|
|
192
|
+
changes: carryChanges ?? 'ask',
|
|
193
|
+
ownTurn: ownTurn === true,
|
|
194
|
+
})),
|
|
195
|
+
pending: false,
|
|
196
|
+
};
|
|
197
|
+
} catch (error) {
|
|
198
|
+
// A refused move (uncommitted changes to decide, busy, …) is never
|
|
199
|
+
// re-armed for the next turn, where nobody could answer it.
|
|
200
|
+
if (pendingIntent === intent) pendingIntent = priorIntent;
|
|
201
|
+
throw error;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
const workspace = session?.id ? currentWorkspace(session) : null;
|
|
205
|
+
return { revision: workspace?.revision ?? 0, workspace, pending: true };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Run in `branch`'s checkout (see enterProjectBranch); a selected branch
|
|
210
|
+
* settles the session's location, so no worktree intent stays armed.
|
|
211
|
+
* `ownTurn` (internal: the Lead's own tool call) tolerates the calling turn.
|
|
212
|
+
*/
|
|
213
|
+
async function selectBranch(
|
|
214
|
+
{ branch, create = false, expectedRevision, confirmLarge = false, txId = '' } = {},
|
|
215
|
+
{ ownTurn = false } = {}
|
|
216
|
+
) {
|
|
217
|
+
const session = await ensureSession();
|
|
218
|
+
const current = currentWorkspace(session);
|
|
219
|
+
if (current.branch === branch && current.worktreeId) {
|
|
220
|
+
assertRevision(current.revision, validRevision(expectedRevision));
|
|
221
|
+
pendingIntent = null;
|
|
222
|
+
return { revision: current.revision, workspace: current };
|
|
223
|
+
}
|
|
224
|
+
const target = { kind: 'branch', branch, create: create === true };
|
|
225
|
+
const result = await runTransition(
|
|
226
|
+
{ sessionId: session.id },
|
|
227
|
+
target,
|
|
228
|
+
{ expectedRevision, confirmLarge },
|
|
229
|
+
{ ownTurn, txId: String(txId || '').trim() }
|
|
230
|
+
);
|
|
231
|
+
pendingIntent = null;
|
|
232
|
+
return result;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
prepareTurnWorkspace,
|
|
237
|
+
requestWorktree,
|
|
238
|
+
selectBranch,
|
|
239
|
+
/** What the branch menu shows of the armed intent (null: none). */
|
|
240
|
+
pendingWorktree: () => (pendingIntent ? { name: pendingIntent.name } : null),
|
|
241
|
+
};
|
|
242
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The managed-worktree maintenance the hosted runtime offers: the retention
|
|
3
|
+
* list, the manual prune, an orphan's removal and a deleted session's
|
|
4
|
+
* cleanup. Every live session of this process counts as a live owner.
|
|
5
|
+
*/
|
|
6
|
+
import { WORKTREE_SNAPSHOT_KIND, worktreeError } from '../../runtime/shared/worktrees/contract.mjs';
|
|
7
|
+
import * as maintenance from '../../runtime/shared/worktrees/maintenance.mjs';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {object} deps The host's session listings, the `backend()` loader,
|
|
11
|
+
* withManagementFolders, cancelSnapshotCleanups and `worktreeSettings()`.
|
|
12
|
+
*/
|
|
13
|
+
export function createWorktreeMaintenance({
|
|
14
|
+
getSession,
|
|
15
|
+
listLiveSessions,
|
|
16
|
+
listStoredSessionIds,
|
|
17
|
+
backend,
|
|
18
|
+
withManagementFolders,
|
|
19
|
+
cancelSnapshotCleanups,
|
|
20
|
+
worktreeSettings,
|
|
21
|
+
}) {
|
|
22
|
+
/** The maintenance scope here: every live session of this process counts as a live owner. */
|
|
23
|
+
async function maintenanceScope() {
|
|
24
|
+
const liveSessionIds = [
|
|
25
|
+
...new Set([getSession()?.id, ...listLiveSessions().map((candidate) => candidate?.id)].filter(Boolean)),
|
|
26
|
+
];
|
|
27
|
+
return { liveSessionIds, listSessionIds: listStoredSessionIds, manager: await backend() };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Every managed worktree with who retains it (the manual list). Read-only
|
|
32
|
+
* snapshots (no branch) only with `includeSnapshots` (the git tool); the
|
|
33
|
+
* desktop list (DesktopManagedWorktreeRow, a branch per row) never gets them.
|
|
34
|
+
*/
|
|
35
|
+
async function listWorktrees({ includeSnapshots = false } = {}) {
|
|
36
|
+
const rows = await maintenance.listWorktreesWithRetention(await maintenanceScope());
|
|
37
|
+
return includeSnapshots ? rows : rows.filter((row) => row.kind !== WORKTREE_SNAPSHOT_KIND);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** The manual prune: clean, merged worktrees no stored or live session retains. */
|
|
41
|
+
async function pruneWorktrees({ repoCommonDir = null } = {}) {
|
|
42
|
+
return maintenance.pruneWorktrees({ ...(await maintenanceScope()), repoCommonDir });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Remove managed worktree `entryId` whose owner is gone (listed `ownerLive:
|
|
47
|
+
* false, removable: true`), on an explicit request: no owner lane exists to
|
|
48
|
+
* do it. No stored or live session may still use the folder; the manager
|
|
49
|
+
* reads the retention again under the repository lock (an owner that came
|
|
50
|
+
* back refuses) and keeps its guards: dirty or unmerged work needs `force`,
|
|
51
|
+
* other sessions' references and retained recovery data refuse, and only
|
|
52
|
+
* the managed checkout is deleted.
|
|
53
|
+
*/
|
|
54
|
+
async function removeOrphanWorktree({ entryId, force = false } = {}) {
|
|
55
|
+
const row = (await listWorktrees()).find((item) => item.id === entryId);
|
|
56
|
+
if (!row) throw worktreeError('WORKTREE_MISSING', undefined, { entryId });
|
|
57
|
+
const removed = await withManagementFolders([row.path], true, async () => {
|
|
58
|
+
const { liveSessionIds, listSessionIds, manager: backendApi } = await maintenanceScope();
|
|
59
|
+
return backendApi.removeOrphanedWorktree({
|
|
60
|
+
entryId,
|
|
61
|
+
force: force === true,
|
|
62
|
+
liveSessionIds,
|
|
63
|
+
retainedSessionIds: await listSessionIds(),
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
return { removed, entryId, path: row.path };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** After `sessionId` was deleted: autoCleanup removes its clean, merged worktree. */
|
|
70
|
+
async function cleanupDeletedSession(sessionId) {
|
|
71
|
+
// Its snapshots go with it below; no turn cleanup keeps retrying them.
|
|
72
|
+
cancelSnapshotCleanups(sessionId);
|
|
73
|
+
return maintenance.cleanupDeletedSessionWorktree(sessionId, {
|
|
74
|
+
manager: await backend(),
|
|
75
|
+
autoCleanup: worktreeSettings().autoCleanup,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return { listWorktrees, pruneWorktrees, removeOrphanWorktree, cleanupDeletedSession };
|
|
80
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one-time preparation of a session's new worktree at the first turn it
|
|
3
|
+
* runs there (frozen dependency installs), with its progress for viewers and
|
|
4
|
+
* the compact note the agent gets with that turn.
|
|
5
|
+
*/
|
|
6
|
+
import { isWorktreeBound } from '../../runtime/shared/worktrees/contract.mjs';
|
|
7
|
+
import { throwIfAborted } from '../../runtime/shared/worktrees/git.mjs';
|
|
8
|
+
import { worktreePreparationNote } from '../../runtime/shared/worktrees/preparation-report.mjs';
|
|
9
|
+
import { readSessionWorkspace } from './workspace-state.mjs';
|
|
10
|
+
|
|
11
|
+
/** The dependency installs a new worktree folder still needs (dependencies.mjs). */
|
|
12
|
+
export async function defaultPlanWorktreeSetup(input) {
|
|
13
|
+
const { planDependencySetup } = await import('../../runtime/shared/worktrees/dependencies.mjs');
|
|
14
|
+
return planDependencySetup(input);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function defaultRunWorktreeSetup(input) {
|
|
18
|
+
const { runWorktreeSetupCommands } = await import('../../runtime/shared/worktrees/setup-commands.mjs');
|
|
19
|
+
return runWorktreeSetupCommands(input);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** @param {object} deps The `backend()` loader, `newTxId` and the setup planner and runner. */
|
|
23
|
+
export function createWorktreeSetup({ backend, newTxId, planWorktreeSetup, runWorktreeSetup }) {
|
|
24
|
+
const setupListeners = new Set();
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Prepare the session's new worktree, once, under the turn (its admission
|
|
28
|
+
* keeps the folder from being merged or removed; its signal — the Stop
|
|
29
|
+
* button — cancels): the frozen installs the links made at creation did
|
|
30
|
+
* not cover. While an install runs, every onWorktreeSetup listener gets its
|
|
31
|
+
* one-line progress; nothing else reaches the user. The agent gets one
|
|
32
|
+
* compact note with this turn (`session.pendingSetupNotice`): the main
|
|
33
|
+
* checkout, what was copied, linked and installed, what failed (with the
|
|
34
|
+
* output tail) and what was skipped. A failure or timeout is in the note
|
|
35
|
+
* and the turn goes on; a cancel aborts the turn like any other stop. The
|
|
36
|
+
* worktree stays either way. The setup belongs to the worktree it was made
|
|
37
|
+
* for, whichever path made it (a worktree task, a branch selection, `git
|
|
38
|
+
* worktree add`): its registry entry keeps it pending (manager
|
|
39
|
+
* claimWorktreeSetup) until the first turn a session runs there, never in
|
|
40
|
+
* another folder.
|
|
41
|
+
*/
|
|
42
|
+
async function runPendingSetup(session, signal) {
|
|
43
|
+
const here = readSessionWorkspace(session);
|
|
44
|
+
if (!isWorktreeBound(here)) return;
|
|
45
|
+
const claimed = await (await backend()).claimWorktreeSetup(here.worktreeId);
|
|
46
|
+
if (!claimed) return;
|
|
47
|
+
const id = newTxId();
|
|
48
|
+
const report = {
|
|
49
|
+
root: claimed.prepared?.root || here.projectPath,
|
|
50
|
+
prepared: claimed.prepared,
|
|
51
|
+
dependencyNotes: [],
|
|
52
|
+
installs: null,
|
|
53
|
+
notes: [],
|
|
54
|
+
};
|
|
55
|
+
const emit = (event) => {
|
|
56
|
+
for (const listener of setupListeners) {
|
|
57
|
+
try {
|
|
58
|
+
listener({ ...event, id, sessionId: session.id, cwd: here.cwd });
|
|
59
|
+
} catch {
|
|
60
|
+
/* a viewer's failure never stops the setup */
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
try {
|
|
65
|
+
const plan = await planWorktreeSetup({ worktreeDir: here.cwd, mainDir: here.projectPath, signal });
|
|
66
|
+
report.dependencyNotes = plan.notes;
|
|
67
|
+
if (plan.commands.length) {
|
|
68
|
+
report.installs = await runWorktreeSetup({ commands: plan.commands, signal, onProgress: emit });
|
|
69
|
+
}
|
|
70
|
+
} catch (error) {
|
|
71
|
+
if (!signal?.aborted) report.notes.push(`Dependencies could not be prepared: ${error?.message || error}`);
|
|
72
|
+
}
|
|
73
|
+
session.pendingSetupNotice = { revision: Date.now(), content: worktreePreparationNote(report) };
|
|
74
|
+
throwIfAborted(signal);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Subscribe to worktree setup progress; returns the unsubscribe. */
|
|
78
|
+
function onWorktreeSetup(listener) {
|
|
79
|
+
if (typeof listener !== 'function') return () => {};
|
|
80
|
+
setupListeners.add(listener);
|
|
81
|
+
return () => setupListeners.delete(listener);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return { runPendingSetup, onWorktreeSetup };
|
|
85
|
+
}
|