mixdog 1.1.2 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -5
- package/package.json +2 -1
- package/scripts/lib/run-node-tests.mjs +9 -0
- package/scripts/prune-desktop-runtime.mjs +3 -0
- package/scripts/test-direct.mjs +4 -2
- package/src/defaults/shipped-history.json +10 -0
- package/src/defaults/skills/pptx/SKILL.md +6 -6
- package/src/defaults/skills/pptx/references/review.md +6 -4
- package/src/defaults/skills/pptx/scripts/source-extract.mjs +1 -1
- package/src/defaults/skills/setup/references/actions.md +18 -5
- package/src/defaults/skills/visualize/SKILL.md +160 -0
- package/src/defaults/skills/visualize/references/craft.md +88 -0
- package/src/headless-command.mjs +56 -3
- package/src/headless-exec.mjs +17 -1
- package/src/help.mjs +2 -0
- package/src/rules/shared/60-verification.md +3 -1
- package/src/rules/shared/70-delivery.md +4 -2
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +1 -0
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +2 -0
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +26 -5
- package/src/runtime/agent/orchestrator/config-presets.mjs +2 -0
- package/src/runtime/agent/orchestrator/config-providers-merge.mjs +17 -11
- package/src/runtime/agent/orchestrator/config-storage.mjs +1 -0
- package/src/runtime/agent/orchestrator/config.mjs +19 -5
- package/src/runtime/agent/orchestrator/context/collect.mjs +2 -1
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +11 -5
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +74 -21
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +133 -15
- package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +55 -8
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +86 -8
- package/src/runtime/agent/orchestrator/mcp/client.mjs +474 -164
- package/src/runtime/agent/orchestrator/mcp/lazy-output-validator.mjs +25 -0
- package/src/runtime/agent/orchestrator/mcp/plugin-placeholders.mjs +54 -0
- package/src/runtime/agent/orchestrator/mcp/reconnect-singleflight.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +108 -17
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +15 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +32 -12
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +337 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-tokens.mjs +159 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +444 -0
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-normalization.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -4
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +21 -6
- package/src/runtime/agent/orchestrator/providers/effort-rejection.mjs +244 -0
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +41 -28
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/lib/gemini-model-catalog.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +8 -40
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-tokens.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +51 -12
- package/src/runtime/agent/orchestrator/providers/model-cache.mjs +37 -2
- package/src/runtime/agent/orchestrator/providers/model-proxy-bridge.mjs +1080 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +82 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +556 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +251 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth-tokens.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +69 -102
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +15 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +6 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +15 -4
- package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog-store.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +4 -4
- package/src/runtime/agent/orchestrator/providers/registry.mjs +47 -7
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +10 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +36 -3
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -11
- package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +15 -55
- package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +15 -2
- package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +16 -1
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +278 -84
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +21 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +54 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +10 -3
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/cache/prefetch-cache.mjs +9 -5
- package/src/runtime/agent/orchestrator/session/cache/read-cache.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +284 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +268 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/sqlite-gate.mjs +27 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +628 -0
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +10 -3
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +24 -13
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +362 -0
- package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +253 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +184 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +136 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +128 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +127 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +101 -0
- package/src/runtime/agent/orchestrator/session/explicit-skills.mjs +83 -5
- package/src/runtime/agent/orchestrator/session/imported-message.mjs +11 -0
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/continuation.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/diagnostic.mjs +1 -7
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/refusal.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +7 -4
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +21 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +15 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +22 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +9 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +9 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +37 -16
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +17 -4
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +90 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +22 -12
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +32 -3
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +27 -0
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +0 -1
- package/src/runtime/agent/orchestrator/session/message-ids.mjs +123 -0
- package/src/runtime/agent/orchestrator/session/message-ids.test-support.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +33 -22
- package/src/runtime/agent/orchestrator/session/store/listing.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +10 -3
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +11 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +817 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +36 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +23 -12
- package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +158 -0
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +202 -374
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +20 -3
- package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +48 -9
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +161 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +17 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -0
- package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +52 -2
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +32 -22
- package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +10 -3
- package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +6 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-cache-policy.mjs +8 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +203 -33
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +32 -35
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +8 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +11 -12
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +9 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +83 -68
- package/src/runtime/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +8 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +20 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +16 -7
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +137 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +11 -10
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +21 -11
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +12 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +13 -10
- package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +17 -12
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +56 -13
- package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +58 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/trusted-roots.mjs +25 -1
- package/src/runtime/agent/orchestrator/tools/patch/apply-patch/codex-batch.mjs +4 -4
- package/src/runtime/agent/orchestrator/tools/patch/apply-patch/route.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/read-redirects.mjs +34 -30
- package/src/runtime/agent/orchestrator/tools/patch/sequence/units.mjs +7 -7
- package/src/runtime/agent/orchestrator/tools/patch/sequence.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +78 -5
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +4 -0
- package/src/runtime/attachments/store.d.mts +3 -0
- package/src/runtime/attachments/store.mjs +38 -0
- package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +1 -1
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +16 -4
- package/src/runtime/channels/lib/worker-main.mjs +17 -14
- package/src/runtime/computer-bridge/linux-readiness.mjs +0 -2
- package/src/runtime/effort-judge/judge-client.mjs +56 -18
- package/src/runtime/memory/lib/memory.mjs +1 -1
- package/src/runtime/memory/lib/session-ingest.mjs +2 -2
- package/src/runtime/shared/atomic-file.mjs +33 -6
- package/src/runtime/shared/best-effort-stderr.mjs +8 -0
- package/src/runtime/shared/code-graph-state.mjs +12 -0
- package/src/runtime/shared/defaults-separation.mjs +2 -0
- package/src/runtime/shared/extension-scopes.mjs +5 -3
- package/src/runtime/shared/file-lock.mjs +37 -11
- package/src/runtime/shared/git-runner-worker.mjs +3 -2
- package/src/runtime/shared/git-runner.mjs +4 -3
- package/src/runtime/shared/llm/anthropic-effort.mjs +14 -0
- package/src/runtime/shared/llm/default-context-window.mjs +6 -0
- package/src/runtime/shared/llm/model-catalog-projection.mjs +5 -4
- package/src/runtime/shared/llm/model-catalog.mjs +240 -130
- package/src/runtime/shared/llm/provider-catalog-cache.mjs +36 -28
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +162 -0
- package/src/runtime/shared/llm/provider-seed-rosters.mjs +130 -0
- package/src/runtime/shared/model-proxy-mode.d.mts +3 -0
- package/src/runtime/shared/model-proxy-mode.mjs +19 -0
- package/src/runtime/shared/plugin-manifest.mjs +18 -9
- package/src/runtime/shared/pristine-execution-contract.json +9 -2
- package/src/runtime/shared/pristine-execution.mjs +28 -4
- package/src/runtime/shared/provider-accounts.mjs +125 -21
- package/src/runtime/shared/provider-api-key.mjs +33 -1
- package/src/runtime/shared/schedule-model-ref.mjs +11 -2
- package/src/runtime/shared/session-usage-totals.mjs +19 -0
- package/src/runtime/shared/sharp-electron-linux.mjs +25 -0
- package/src/runtime/shared/shell-display.mjs +9 -3
- package/src/runtime/shared/singleton-owner.mjs +36 -6
- package/src/runtime/shared/skill-mentions.d.mts +10 -0
- package/src/runtime/shared/skill-mentions.mjs +133 -0
- package/src/runtime/shared/skill-script-runtime.mjs +264 -0
- package/src/runtime/shared/statusline/statusline-segments.mjs +68 -14
- package/src/runtime/shared/tool-primitives.mjs +35 -2
- package/src/runtime/shared/tool-surface.mjs +7 -0
- package/src/runtime/shared/tool-work-units.mjs +14 -0
- package/src/runtime/shared/transcript-metadata.mjs +17 -1
- package/src/runtime/shared/turn-changes.mjs +791 -0
- package/src/runtime/shared/turn-snapshot-store.mjs +346 -12
- package/src/runtime/shared/turn-snapshot.mjs +690 -81
- package/src/runtime/shared/turn-worktree-snapshot.mjs +185 -15
- package/src/runtime/shared/worker-requests.mjs +15 -2
- package/src/runtime/shared/worktrees/cache-cleanups.mjs +52 -0
- package/src/runtime/shared/worktrees/contract.mjs +551 -0
- package/src/runtime/shared/worktrees/disk.mjs +57 -0
- package/src/runtime/shared/worktrees/git.mjs +247 -0
- package/src/runtime/shared/worktrees/include.mjs +480 -0
- package/src/runtime/shared/worktrees/lock.mjs +46 -0
- package/src/runtime/shared/worktrees/maintenance.mjs +96 -0
- package/src/runtime/shared/worktrees/manager.mjs +1215 -0
- package/src/runtime/shared/worktrees/merge.mjs +182 -0
- package/src/runtime/shared/worktrees/owner.mjs +46 -0
- package/src/runtime/shared/worktrees/paths.mjs +62 -0
- package/src/runtime/shared/worktrees/registry.mjs +110 -0
- package/src/runtime/shared/worktrees/settings.mjs +84 -0
- package/src/runtime/shared/worktrees/slug.mjs +62 -0
- package/src/runtime/shared/worktrees/test-support.mjs +96 -0
- package/src/runtime/visualize-bridge/client.mjs +181 -0
- package/src/runtime/visualize-bridge/tool-defs.mjs +97 -0
- package/src/session-runtime/automation-agents.mjs +8 -2
- package/src/session-runtime/boot/apis.mjs +90 -0
- package/src/session-runtime/boot/config.mjs +7 -2
- package/src/session-runtime/boot/facade.mjs +21 -0
- package/src/session-runtime/boot/infrastructure.mjs +30 -18
- package/src/session-runtime/boot/session.mjs +1 -0
- package/src/session-runtime/boot/tools.mjs +4 -0
- package/src/session-runtime/config-lifecycle.mjs +10 -1
- package/src/session-runtime/conversation-import/discovery.mjs +698 -0
- package/src/session-runtime/conversation-import/service.mjs +369 -0
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +21 -6
- package/src/session-runtime/cwd-plugins/plugin-status.mjs +47 -42
- package/src/session-runtime/global-extensions.mjs +2 -2
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +27 -2
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +32 -1
- package/src/session-runtime/internal-tool-executor.mjs +9 -1
- package/src/session-runtime/lifecycle/session-catalog.mjs +8 -1
- package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +5 -0
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +21 -3
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +16 -0
- package/src/session-runtime/mcp-glue/connect.mjs +68 -16
- package/src/session-runtime/mcp-glue/plugin-servers.mjs +499 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +122 -33
- package/src/session-runtime/mcp-glue/server-input.mjs +29 -0
- package/src/session-runtime/mcp-glue.mjs +22 -2
- package/src/session-runtime/model-route/route-persist.mjs +3 -0
- package/src/session-runtime/model-route/set-route.mjs +15 -2
- package/src/session-runtime/new-session-config.mjs +3 -2
- package/src/session-runtime/notification-bus.mjs +18 -3
- package/src/session-runtime/provider-auth/accounts.mjs +33 -15
- package/src/session-runtime/provider-models/row-hydration.mjs +2 -0
- package/src/session-runtime/provider-models/web-search-catalog.mjs +5 -1
- package/src/session-runtime/provider-readiness.mjs +16 -10
- package/src/session-runtime/resource-extension-sync.mjs +45 -7
- package/src/session-runtime/resource-mcp-api.mjs +121 -84
- package/src/session-runtime/resource-plugins-api.mjs +29 -41
- package/src/session-runtime/resource-scope-decorate.mjs +6 -8
- package/src/session-runtime/resource-skills-api.mjs +23 -2
- package/src/session-runtime/route-resolution.mjs +10 -1
- package/src/session-runtime/route-state.mjs +16 -2
- package/src/session-runtime/runtime-core.mjs +5 -0
- package/src/session-runtime/runtime-facade.mjs +8 -0
- package/src/session-runtime/runtime-review-api.mjs +9 -0
- package/src/session-runtime/schedule-session-run.mjs +1 -1
- package/src/session-runtime/services/agent-tool/helpers.mjs +5 -0
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +3 -0
- package/src/session-runtime/services/agent-tool/job-views/job-lookup.mjs +1 -0
- package/src/session-runtime/services/agent-tool/job-views/spawn-meta.mjs +1 -0
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +15 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +1 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +10 -2
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -7
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +2 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -0
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +1 -0
- package/src/session-runtime/services/agent-tool.mjs +1 -0
- package/src/session-runtime/services/channel-session-router.mjs +4 -1
- package/src/session-runtime/services/daemon-candidate.mjs +3 -2
- package/src/session-runtime/services/daemon-crash-capture/spawn-capture.mjs +55 -0
- package/src/session-runtime/services/hook-bus/command-handler.mjs +4 -1
- package/src/session-runtime/services/hook-bus/handlers.mjs +7 -3
- package/src/session-runtime/services/provider-admin.mjs +64 -18
- package/src/session-runtime/services/usage-dashboard-model.mjs +3 -0
- package/src/session-runtime/session-create/session-options.mjs +10 -1
- package/src/session-runtime/session-turn-api.mjs +1 -0
- package/src/session-runtime/settings-api.mjs +4 -2
- package/src/session-runtime/settings-builtin-tools-api.mjs +9 -2
- package/src/session-runtime/settings-worktree-api.mjs +17 -0
- package/src/session-runtime/setup-tool/executor.mjs +23 -5
- package/src/session-runtime/setup-tool/extended-actions.mjs +1 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +4 -1
- package/src/session-runtime/setup-tool/tool-defs.mjs +38 -4
- package/src/session-runtime/skills-api.mjs +7 -3
- package/src/session-runtime/turn/agent-ops.mjs +12 -1
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +14 -3
- package/src/session-runtime/turn/turn-run/snapshot-tracker.mjs +20 -15
- package/src/session-runtime/turn/turn-run/turn-open.mjs +4 -5
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +29 -1
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +6 -1
- package/src/session-runtime/turn/turn-run.mjs +6 -7
- package/src/session-runtime/webhook-session-run.mjs +16 -4
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +15 -3
- package/src/session-runtime/workspace/admission-gate.mjs +197 -0
- package/src/session-runtime/workspace/project-branches.mjs +136 -0
- package/src/session-runtime/workspace/transition-steps.mjs +364 -0
- package/src/session-runtime/workspace/transitions.mjs +651 -0
- package/src/session-runtime/workspace/workspace-state.mjs +112 -0
- package/src/skill-script-entry.mjs +36 -0
- package/src/standalone/channel-transport/http-routes.mjs +17 -0
- package/src/standalone/channel-transport.mjs +13 -1
- package/src/standalone/daemon-desktop-runtime.mjs +1 -0
- package/src/standalone/daemon-owner.mjs +372 -0
- package/src/standalone/daemon-stored-session-views.mjs +15 -4
- package/src/standalone/daemon.mjs +179 -8
- package/src/standalone/desktop-service-registry.mjs +20 -0
- package/src/standalone/local-session-runtime.mjs +11 -0
- package/src/standalone/session-client/attachment-calls.mjs +3 -1
- package/src/standalone/session-client/daemon-unavailable.mjs +62 -0
- package/src/standalone/session-client/lease-heartbeat.mjs +47 -0
- package/src/standalone/session-client.mjs +104 -13
- package/src/standalone/session-protocol.mjs +21 -0
- package/src/standalone/session-proxy.mjs +3 -0
- package/src/standalone/session-service/agent-tree/agent-child.mjs +4 -0
- package/src/standalone/session-service/agent-tree/agent-rehydrate.mjs +1 -0
- package/src/standalone/session-service/entries/lifecycle.mjs +6 -0
- package/src/standalone/session-service/projection/revisions.mjs +2 -0
- package/src/standalone/session-service/projection/transcript-window.mjs +149 -19
- package/src/standalone/session-service/projection/workspace.mjs +14 -0
- package/src/standalone/session-service/session-calls/session-action.mjs +17 -4
- package/src/standalone/session-transport/call-route.mjs +13 -0
- package/src/standalone/session-transport/client-registry/client-grace.mjs +45 -3
- package/src/standalone/session-transport/client-registry/registration-replays.mjs +1 -0
- package/src/standalone/session-transport/client-registry.mjs +20 -3
- package/src/standalone/session-transport/routes.mjs +79 -2
- package/src/standalone/session-transport/stack.mjs +2 -0
- package/src/standalone/session-transport.mjs +24 -1
- package/src/tui/App.jsx +9 -1
- package/src/tui/app/app-view/floating-panel.jsx +9 -1
- package/src/tui/app/app-view.jsx +6 -0
- package/src/tui/app/extension-pickers/plugins-pickers.mjs +35 -16
- package/src/tui/app/message-selector.mjs +2 -1
- package/src/tui/app/model-options.mjs +37 -5
- package/src/tui/app/model-picker/provider-models-list.mjs +2 -2
- package/src/tui/app/model-picker.mjs +4 -2
- package/src/tui/app/skill-mention-palette.mjs +88 -0
- package/src/tui/app/slash-palette.mjs +23 -7
- package/src/tui/app/transcript-row-estimate.mjs +11 -3
- package/src/tui/app/use-prompt-draft-flow.mjs +7 -2
- package/src/tui/app/use-prompt-state.mjs +5 -0
- package/src/tui/components/Message.jsx +22 -1
- package/src/tui/components/PromptInput.jsx +21 -3
- package/src/tui/components/SlashCommandPalette.jsx +12 -3
- package/src/tui/components/TranscriptItem.jsx +9 -1
- package/src/tui/components/prompt-input/key-handler.mjs +21 -8
- package/src/tui/components/user-message-skills.mjs +38 -0
- package/src/tui/dist/index.mjs +839 -207
- package/src/tui/index.jsx +10 -2
- package/src/tui/session/compaction-view.mjs +147 -0
- package/src/tui/session/context-state.mjs +6 -0
- package/src/tui/session/initial-state.mjs +3 -0
- package/src/tui/session/queue-helpers.mjs +7 -2
- package/src/tui/session/quota-resume.mjs +2 -1
- package/src/tui/session/session-api/commands.mjs +10 -2
- package/src/tui/session/session-api/controls.mjs +4 -0
- package/src/tui/session/session-api/extensions.mjs +4 -2
- package/src/tui/session/session-api/intake/rewind.mjs +2 -1
- package/src/tui/session/session-api/integrations.mjs +17 -0
- package/src/tui/session/session-api/lifecycle/dispose.mjs +6 -1
- package/src/tui/session/session-api/lifecycle/inheritance.mjs +2 -0
- package/src/tui/session/session-api/lifecycle/resume.mjs +3 -0
- package/src/tui/session/session-api/routes.mjs +10 -1
- package/src/tui/session/session-api/settings.mjs +9 -0
- package/src/tui/session/session-api/worktree.mjs +60 -0
- package/src/tui/session/session-api.mjs +2 -0
- package/src/tui/session/session-flow/auto-clear.mjs +31 -12
- package/src/tui/session/session-flow/drain.mjs +27 -3
- package/src/tui/session/session-flow/session-reset.mjs +4 -3
- package/src/tui/session/session-flow.mjs +2 -0
- package/src/tui/session/transcript-intake.mjs +14 -5
- package/src/tui/session/tui-steering-persist.mjs +25 -9
- package/src/tui/session/turn-stream.mjs +32 -4
- package/src/tui/session/turn-tool-cards.mjs +10 -2
- package/src/tui/session/turn.mjs +56 -10
- package/src/runtime/effort-judge/previous-human-request.mjs +0 -162
- package/src/runtime/effort-judge/verified-context-input.mjs +0 -10
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import { existsSync, realpathSync } from 'node:fs';
|
|
2
|
+
import { existsSync, lstatSync, realpathSync } from 'node:fs';
|
|
3
3
|
import { access, copyFile, lstat, mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
|
|
4
|
-
import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
4
|
+
import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
5
5
|
import { PATCH_EDIT_MAX_BYTES } from './bounded-file-read.mjs';
|
|
6
6
|
import { cleanString as clean } from './clean.mjs';
|
|
7
7
|
import { runGitOffThread } from './git-runner.mjs';
|
|
8
8
|
import { resolvePluginData } from './plugin-paths.mjs';
|
|
9
|
+
import { normalizeChangeStatus, splitPatchSections } from './turn-changes.mjs';
|
|
9
10
|
|
|
10
11
|
const COMMAND_TIMEOUT_MS = 30_000;
|
|
11
12
|
const COMMAND_MAX_BYTES = 8 * 1024 * 1024;
|
|
12
13
|
const PATCH_MAX_BYTES = 2 * 1024 * 1024;
|
|
14
|
+
// The complete (replay-safe) patch a sealing turn records; per-file and
|
|
15
|
+
// per-session bounds are applied on top of this by the change record.
|
|
16
|
+
const FREEZE_PATCH_MAX_BYTES = 64 * 1024 * 1024;
|
|
13
17
|
const MAX_UNTRACKED_FILE_BYTES = 2 * 1024 * 1024;
|
|
14
18
|
// Largest tool-supplied baseline kept for `hash-object`: the apply_patch edit
|
|
15
19
|
// limit. (2–64 MiB explicit untracked edits keep their exact revert.)
|
|
@@ -40,8 +44,26 @@ function pathKey(value) {
|
|
|
40
44
|
|
|
41
45
|
/** `resolve` plus symlinks of the nearest existing ancestor: git reports the
|
|
42
46
|
* worktree root canonically (macOS /var -> /private/var), callers may not. */
|
|
43
|
-
function canonicalPath(value) {
|
|
47
|
+
function canonicalPath(value, dirs = null) {
|
|
44
48
|
const full = resolve(value);
|
|
49
|
+
if (dirs) {
|
|
50
|
+
// Same result as the walk below without repeating it per file: the parent
|
|
51
|
+
// directory is canonicalized once per call; the final component only
|
|
52
|
+
// matters when it is itself a link (or its state is unknown).
|
|
53
|
+
const parent = dirname(full);
|
|
54
|
+
if (parent !== full) {
|
|
55
|
+
let canonicalParent = dirs.get(parent);
|
|
56
|
+
if (canonicalParent === undefined) {
|
|
57
|
+
canonicalParent = canonicalPath(parent);
|
|
58
|
+
dirs.set(parent, canonicalParent);
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
if (!lstatSync(full).isSymbolicLink()) return join(canonicalParent, basename(full));
|
|
62
|
+
} catch (error) {
|
|
63
|
+
if (error?.code === 'ENOENT' || error?.code === 'ENOTDIR') return join(canonicalParent, basename(full));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
45
67
|
let head = full;
|
|
46
68
|
while (!existsSync(head)) {
|
|
47
69
|
const parent = dirname(head);
|
|
@@ -70,9 +92,16 @@ function commandError(args, stderr, code) {
|
|
|
70
92
|
// call that would otherwise stall the event loop each time.
|
|
71
93
|
async function runGit(
|
|
72
94
|
args,
|
|
73
|
-
{
|
|
95
|
+
{
|
|
96
|
+
cwd,
|
|
97
|
+
input = '',
|
|
98
|
+
timeoutMs = COMMAND_TIMEOUT_MS,
|
|
99
|
+
maxBytes = COMMAND_MAX_BYTES,
|
|
100
|
+
allowFailure = false,
|
|
101
|
+
stdoutEncoding = 'utf8',
|
|
102
|
+
} = {}
|
|
74
103
|
) {
|
|
75
|
-
const result = await runGitOffThread(args, { cwd, input, timeoutMs, maxBytes });
|
|
104
|
+
const result = await runGitOffThread(args, { cwd, input, timeoutMs, maxBytes, stdoutEncoding });
|
|
76
105
|
if (result.code !== 0 && !allowFailure) throw commandError(args, result.stderr, result.code);
|
|
77
106
|
return result;
|
|
78
107
|
}
|
|
@@ -94,11 +123,14 @@ async function repositoryRoot(worktree) {
|
|
|
94
123
|
return root ? resolve(root) : null;
|
|
95
124
|
}
|
|
96
125
|
|
|
126
|
+
function shadowDirForKey(key) {
|
|
127
|
+
return join(snapshotRoot(), createHash('sha256').update(key).digest('hex').slice(0, 24));
|
|
128
|
+
}
|
|
129
|
+
|
|
97
130
|
function stateForRoot(root) {
|
|
98
131
|
const key = pathKey(root);
|
|
99
132
|
let state = states.get(key);
|
|
100
|
-
const
|
|
101
|
-
const gitDir = join(snapshotRoot(), hash);
|
|
133
|
+
const gitDir = shadowDirForKey(key);
|
|
102
134
|
if (state && state.gitDir === gitDir) return state;
|
|
103
135
|
state = {
|
|
104
136
|
root,
|
|
@@ -112,6 +144,11 @@ function stateForRoot(root) {
|
|
|
112
144
|
// Bumped by every reported write under `root`; a capture records the
|
|
113
145
|
// value it started from.
|
|
114
146
|
changeStamp: 0,
|
|
147
|
+
// Set by forgetTurnWorktreeRoot(): the shadow repository must never be
|
|
148
|
+
// recreated for this state. A later snapshot of the same path gets a new one.
|
|
149
|
+
forgotten: false,
|
|
150
|
+
gcTimer: null,
|
|
151
|
+
gcRun: null,
|
|
115
152
|
};
|
|
116
153
|
states.set(key, state);
|
|
117
154
|
return state;
|
|
@@ -120,8 +157,10 @@ function stateForRoot(root) {
|
|
|
120
157
|
/** Report written paths (or `null`: anything may have changed). The next
|
|
121
158
|
* review poll of an affected worktree captures instead of reusing. */
|
|
122
159
|
export function noteTurnWorktreeChange(paths = null) {
|
|
160
|
+
if (states.size === 0) return;
|
|
123
161
|
const list = Array.isArray(paths) ? paths.filter((value) => clean(value)) : [];
|
|
124
|
-
const
|
|
162
|
+
const dirs = new Map();
|
|
163
|
+
const keys = list.map((value) => pathKey(canonicalPath(value, dirs)));
|
|
125
164
|
for (const state of states.values()) {
|
|
126
165
|
const root = pathKey(state.root);
|
|
127
166
|
if (keys.length === 0 || keys.some((key) => key === root || key.startsWith(`${root}/`))) {
|
|
@@ -156,7 +195,19 @@ async function sourceLineEndingArgs(root) {
|
|
|
156
195
|
return [...values].flatMap(([key, value]) => ['-c', `${key}=${value}`]);
|
|
157
196
|
}
|
|
158
197
|
|
|
198
|
+
// A forgotten root's shadow repository is gone for good. Every git command and
|
|
199
|
+
// every file write on it goes through shadowArgs/ensureState, so refusing there
|
|
200
|
+
// keeps a snapshot object that outlived forgetTurnWorktreeRoot() from
|
|
201
|
+
// recreating the directory.
|
|
202
|
+
function assertStateLive(state) {
|
|
203
|
+
if (!state.forgotten) return;
|
|
204
|
+
const error = new Error(`turn worktree snapshot for ${state.root} was removed`);
|
|
205
|
+
error.code = 'TURN_WORKTREE_SNAPSHOT_REMOVED';
|
|
206
|
+
throw error;
|
|
207
|
+
}
|
|
208
|
+
|
|
159
209
|
function shadowArgs(state, args) {
|
|
210
|
+
assertStateLive(state);
|
|
160
211
|
return [
|
|
161
212
|
...state.lineEndingArgs,
|
|
162
213
|
// A conversion warning must never fail the snapshot `add`.
|
|
@@ -239,6 +290,7 @@ async function refreshSourceTracked(state, { force = false } = {}) {
|
|
|
239
290
|
}
|
|
240
291
|
|
|
241
292
|
async function ensureState(state) {
|
|
293
|
+
assertStateLive(state);
|
|
242
294
|
if (state.initialized && (await exists(join(state.gitDir, 'config')))) return;
|
|
243
295
|
await mkdir(dirname(state.gitDir), { recursive: true });
|
|
244
296
|
if (!(await exists(join(state.gitDir, 'config')))) {
|
|
@@ -643,24 +695,141 @@ async function diffTreesUnlocked(state, baselineTree, currentTree, paths = null,
|
|
|
643
695
|
return { patch, files, patchTruncated, currentTree, ...(omitPatch ? { patchOmitted: true } : {}) };
|
|
644
696
|
}
|
|
645
697
|
|
|
698
|
+
/**
|
|
699
|
+
* Freeze the snapshot's last captured net diff into replayable per-file
|
|
700
|
+
* patches: one complete `--binary --full-index` diff (independent of the
|
|
701
|
+
* bounded display patch), split back into its `diff --git` sections. `paths`
|
|
702
|
+
* scopes a contended worktree to the session-owned files. Callers refresh the
|
|
703
|
+
* snapshot first; this never captures. Files whose bytes cannot be replayed
|
|
704
|
+
* (an uncaptured baseline, a type change, an over-limit diff) stay in the
|
|
705
|
+
* record as non-revertable with a reason.
|
|
706
|
+
*/
|
|
707
|
+
export async function freezeTurnWorktreeChanges(snapshot, paths = null) {
|
|
708
|
+
if (!snapshot?.state || !snapshot.baselineTree) return null;
|
|
709
|
+
const scope = Array.isArray(paths) ? [...new Set(paths.filter(Boolean))] : null;
|
|
710
|
+
if (scope && scope.length === 0) return { root: snapshot.root, files: [] };
|
|
711
|
+
return await withStateLock(snapshot.state, async () => {
|
|
712
|
+
const { state, baselineTree, currentTree } = snapshot;
|
|
713
|
+
let review = { files: [], patch: '', patchTruncated: false };
|
|
714
|
+
let sections = [];
|
|
715
|
+
let unavailable = '';
|
|
716
|
+
if (currentTree && currentTree !== baselineTree) {
|
|
717
|
+
review = await diffTreesUnlocked(state, baselineTree, currentTree, scope, { omitPatch: true });
|
|
718
|
+
const args = [
|
|
719
|
+
'diff',
|
|
720
|
+
'--binary',
|
|
721
|
+
'--full-index',
|
|
722
|
+
'--no-color',
|
|
723
|
+
'--no-ext-diff',
|
|
724
|
+
'--no-textconv',
|
|
725
|
+
'--src-prefix=a/',
|
|
726
|
+
'--dst-prefix=b/',
|
|
727
|
+
'--find-renames',
|
|
728
|
+
baselineTree,
|
|
729
|
+
currentTree,
|
|
730
|
+
'--',
|
|
731
|
+
...(scope || ['.']),
|
|
732
|
+
];
|
|
733
|
+
try {
|
|
734
|
+
const result = await runGit(shadowArgs(state, args), {
|
|
735
|
+
cwd: state.root,
|
|
736
|
+
maxBytes: FREEZE_PATCH_MAX_BYTES,
|
|
737
|
+
stdoutEncoding: 'base64',
|
|
738
|
+
});
|
|
739
|
+
sections = splitPatchSections(Buffer.from(result.stdout, 'base64'));
|
|
740
|
+
} catch (error) {
|
|
741
|
+
if (error?.code !== 'EMAXBUFFER') throw error;
|
|
742
|
+
unavailable = 'the turn changed too much to keep its patches for undo';
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
const listed = withOmittedBaselines({ ...snapshot, scopePaths: scope }, { ...review, patchOmitted: true });
|
|
746
|
+
const byPath = new Map();
|
|
747
|
+
for (const section of sections) {
|
|
748
|
+
const key = pathKey(section.newPath ?? section.oldPath ?? '');
|
|
749
|
+
// A type change diffs as a delete plus an add of one path: not one patch.
|
|
750
|
+
byPath.set(key, byPath.has(key) ? null : section.patch);
|
|
751
|
+
}
|
|
752
|
+
const files = (listed.files || []).map((file) => {
|
|
753
|
+
const entry = {
|
|
754
|
+
path: file.path,
|
|
755
|
+
...(file.oldPath ? { oldPath: file.oldPath } : {}),
|
|
756
|
+
status: normalizeChangeStatus(file.status),
|
|
757
|
+
additions: Number(file.additions) || 0,
|
|
758
|
+
deletions: Number(file.deletions) || 0,
|
|
759
|
+
...(file.binary ? { binary: true } : {}),
|
|
760
|
+
};
|
|
761
|
+
if (entry.status !== 'R') delete entry.oldPath;
|
|
762
|
+
if (file.omitted === true) {
|
|
763
|
+
return { ...entry, revertable: false, reason: 'binary/large file content was not captured' };
|
|
764
|
+
}
|
|
765
|
+
if (file.status === 'T') return { ...entry, revertable: false, reason: 'the file type changed' };
|
|
766
|
+
const patch = byPath.get(pathKey(file.path));
|
|
767
|
+
if (!patch) return { ...entry, revertable: false, reason: unavailable || 'no replayable patch was recorded' };
|
|
768
|
+
return { ...entry, revertable: true, patch };
|
|
769
|
+
});
|
|
770
|
+
return { root: snapshot.root, files };
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
|
|
646
774
|
// One maintenance pass per shadow repository per process, off the turn's
|
|
647
775
|
// critical path. `--auto` does nothing until the repository actually needs it,
|
|
648
776
|
// so the common case costs a process spawn and nothing else.
|
|
649
777
|
const maintainedShadowRepositories = new Set();
|
|
650
778
|
|
|
651
779
|
function scheduleShadowGc(state) {
|
|
652
|
-
if (maintainedShadowRepositories.has(state.gitDir)) return;
|
|
780
|
+
if (state.forgotten || maintainedShadowRepositories.has(state.gitDir)) return;
|
|
653
781
|
maintainedShadowRepositories.add(state.gitDir);
|
|
654
782
|
const timer = setTimeout(() => {
|
|
783
|
+
state.gcTimer = null;
|
|
655
784
|
// Deliberately outside the state lock: collection can run for minutes and
|
|
656
785
|
// git serializes itself through gc.lock, so a clash just retries later.
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
786
|
+
// forgetTurnWorktreeRoot() waits for `gcRun` before deleting the repository.
|
|
787
|
+
state.gcRun = Promise.resolve()
|
|
788
|
+
.then(() =>
|
|
789
|
+
runGit(shadowArgs(state, ['gc', '--auto', `--prune=${SHADOW_GC_PRUNE}`, '--quiet']), {
|
|
790
|
+
cwd: state.root,
|
|
791
|
+
allowFailure: true,
|
|
792
|
+
timeoutMs: 300_000,
|
|
793
|
+
})
|
|
794
|
+
)
|
|
795
|
+
.catch(() => {});
|
|
662
796
|
}, 60_000);
|
|
663
797
|
timer.unref?.();
|
|
798
|
+
state.gcTimer = timer;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
async function removeShadowDir(gitDir, removed, kept) {
|
|
802
|
+
if (!(await exists(gitDir))) return;
|
|
803
|
+
await rm(gitDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 }).catch(() => {});
|
|
804
|
+
((await exists(gitDir)) ? kept : removed).push(gitDir);
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
/** Drop every trace of one worktree root: serialize behind its pending capture
|
|
808
|
+
* work, remove its shadow repository and in-memory state, and refuse any write
|
|
809
|
+
* a snapshot object that still holds the old state attempts afterwards.
|
|
810
|
+
* Only the exact root is touched. Returns `{ removed, kept }` shadow paths;
|
|
811
|
+
* `kept` lists a shadow repository that could not be deleted. */
|
|
812
|
+
export async function forgetTurnWorktreeRoot(root) {
|
|
813
|
+
const text = clean(root);
|
|
814
|
+
const removed = [];
|
|
815
|
+
const kept = [];
|
|
816
|
+
if (!text) return { removed, kept };
|
|
817
|
+
const keys = new Set([pathKey(resolve(text)), pathKey(canonicalPath(text))]);
|
|
818
|
+
const gitDirs = new Set([...keys].map(shadowDirForKey));
|
|
819
|
+
for (const [key, state] of [...states]) {
|
|
820
|
+
if (!keys.has(key) && !keys.has(pathKey(state.root))) continue;
|
|
821
|
+
gitDirs.add(state.gitDir);
|
|
822
|
+
await withStateLock(state, async () => {
|
|
823
|
+
state.forgotten = true;
|
|
824
|
+
if (states.get(key) === state) states.delete(key);
|
|
825
|
+
if (state.gcTimer) clearTimeout(state.gcTimer);
|
|
826
|
+
state.gcTimer = null;
|
|
827
|
+
await state.gcRun;
|
|
828
|
+
maintainedShadowRepositories.delete(state.gitDir);
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
for (const gitDir of gitDirs) await removeShadowDir(gitDir, removed, kept);
|
|
832
|
+
return { removed, kept };
|
|
664
833
|
}
|
|
665
834
|
|
|
666
835
|
export async function createTurnWorktreeSnapshot(worktree) {
|
|
@@ -847,7 +1016,8 @@ async function revertPathsUnlocked(snapshot, targets) {
|
|
|
847
1016
|
await diffTreesUnlocked(snapshot.state, snapshot.baselineTree, currentTree, snapshot.scopePaths)
|
|
848
1017
|
)
|
|
849
1018
|
);
|
|
850
|
-
|
|
1019
|
+
// The absolute paths now back at their baseline bytes.
|
|
1020
|
+
return targets.map((target) => resolve(snapshot.root, target));
|
|
851
1021
|
}
|
|
852
1022
|
|
|
853
1023
|
export async function revertTurnWorktreeFile(snapshot, value) {
|
|
@@ -14,8 +14,11 @@ import { parentPort, Worker } from 'node:worker_threads';
|
|
|
14
14
|
* worker is detached before it is terminated, so no request is ever sent to
|
|
15
15
|
* (or lost with) a worker that is shutting down.
|
|
16
16
|
* `request.running()` reports whether a worker thread is currently attached.
|
|
17
|
+
*
|
|
18
|
+
* `onEvent` (optional): receives what the worker sends with postWorkerEvent
|
|
19
|
+
* (messages that answer no request).
|
|
17
20
|
*/
|
|
18
|
-
export function createWorkerRequestClient(url, { idleExitMs = 0, ...workerOptions } = {}) {
|
|
21
|
+
export function createWorkerRequestClient(url, { idleExitMs = 0, onEvent = null, ...workerOptions } = {}) {
|
|
19
22
|
let worker = null;
|
|
20
23
|
let nextRequestId = 0;
|
|
21
24
|
// Requests belong to the worker they were posted to: a replacement worker
|
|
@@ -50,7 +53,12 @@ export function createWorkerRequestClient(url, { idleExitMs = 0, ...workerOption
|
|
|
50
53
|
owned.clear();
|
|
51
54
|
for (const entry of entries) entry.reject(error);
|
|
52
55
|
};
|
|
53
|
-
created.on('message', (
|
|
56
|
+
created.on('message', (message) => {
|
|
57
|
+
if (message && Object.hasOwn(message, 'event')) {
|
|
58
|
+
onEvent?.(message.event);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const { id, result, error } = message;
|
|
54
62
|
const entry = owned.get(id);
|
|
55
63
|
if (!entry) return;
|
|
56
64
|
owned.delete(id);
|
|
@@ -109,6 +117,11 @@ export function createWorkerRequestClient(url, { idleExitMs = 0, ...workerOption
|
|
|
109
117
|
return request;
|
|
110
118
|
}
|
|
111
119
|
|
|
120
|
+
/** Worker side: send `event` to the client's `onEvent`, outside any request. */
|
|
121
|
+
export function postWorkerEvent(event) {
|
|
122
|
+
parentPort.postMessage({ event });
|
|
123
|
+
}
|
|
124
|
+
|
|
112
125
|
/** Worker side: answer every request with `handler(payload)` (sync or async). */
|
|
113
126
|
export function serveWorkerRequests(handler) {
|
|
114
127
|
parentPort.on('message', ({ id, payload }) => {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Root cleanups for Mixdog's path-keyed caches: when a managed worktree is
|
|
3
|
+
* removed these drop everything the runtime cached under that exact root, so
|
|
4
|
+
* the removal leaves no turn snapshots, snapshot-store scopes or code-graph
|
|
5
|
+
* state behind. Each returns `{ removed, kept }` and never touches other roots.
|
|
6
|
+
* Modules load lazily: registering costs nothing until a worktree is removed.
|
|
7
|
+
*/
|
|
8
|
+
import { registerRootCleanup } from './contract.mjs';
|
|
9
|
+
|
|
10
|
+
const merge = (target, part) => {
|
|
11
|
+
target.removed.push(...part.removed);
|
|
12
|
+
target.kept.push(...part.kept);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/** @type {Record<string, (root: string) => Promise<{removed: string[], kept: string[]}>>} */
|
|
16
|
+
export const WORKTREE_CACHE_CLEANUPS = Object.freeze({
|
|
17
|
+
'turn-worktree-snapshots': async (root) => {
|
|
18
|
+
const { forgetTurnWorktreeRoot } = await import('../turn-worktree-snapshot.mjs');
|
|
19
|
+
return await forgetTurnWorktreeRoot(root);
|
|
20
|
+
},
|
|
21
|
+
'turn-snapshot-store': async (root) => {
|
|
22
|
+
const { forgetTurnSnapshotRoot } = await import('../turn-snapshot-store.mjs');
|
|
23
|
+
return await forgetTurnSnapshotRoot(root);
|
|
24
|
+
},
|
|
25
|
+
'code-graph': async (root) => {
|
|
26
|
+
const [state, disk, trusted] = await Promise.all([
|
|
27
|
+
import('../code-graph-state.mjs'),
|
|
28
|
+
import('../../agent/orchestrator/tools/code-graph/disk-cache.mjs'),
|
|
29
|
+
import('../../agent/orchestrator/tools/code-graph/trusted-roots.mjs'),
|
|
30
|
+
]);
|
|
31
|
+
const result = { removed: state.forgetCodeGraphStateRoot(root).map((name) => `${name}:${root}`), kept: [] };
|
|
32
|
+
merge(result, disk.forgetDiskCodeGraphRoot(root));
|
|
33
|
+
merge(result, trusted.forgetTrustedCodeGraphRoot(root));
|
|
34
|
+
return result;
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const registrations = new WeakSet();
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Register every cache cleanup once per registry function. Idempotent: calling
|
|
42
|
+
* it again (or from several hosts) neither throws nor registers duplicates.
|
|
43
|
+
* @param {typeof registerRootCleanup} [register] Defaults to the process registry.
|
|
44
|
+
* @returns {string[]} Cleanup names.
|
|
45
|
+
*/
|
|
46
|
+
export function registerWorktreeCacheCleanups(register = registerRootCleanup) {
|
|
47
|
+
if (!registrations.has(register)) {
|
|
48
|
+
registrations.add(register);
|
|
49
|
+
for (const [name, cleanup] of Object.entries(WORKTREE_CACHE_CLEANUPS)) register(name, cleanup);
|
|
50
|
+
}
|
|
51
|
+
return Object.keys(WORKTREE_CACHE_CLEANUPS);
|
|
52
|
+
}
|