mixdog 1.2.1 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -0
- package/package.json +2 -1
- package/scripts/gate-local.mjs +19 -3
- package/scripts/model-catalog-audit.mjs +1 -15
- package/scripts/provider-pingpong-live.mjs +509 -0
- package/src/agents/advisor/AGENT.md +1 -1
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/reviewer/AGENT.md +3 -3
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +6 -0
- package/src/defaults/skills/setup/SKILL.md +6 -1
- package/src/defaults/skills/setup/references/actions.md +44 -22
- package/src/defaults/skills/setup/references/surfaces.md +10 -8
- package/src/headless-exec.mjs +15 -8
- package/src/lib/keychain-cjs.cjs +7 -4
- package/src/output-styles/common.md +11 -10
- package/src/repl/slash-commands.mjs +16 -1
- package/src/rules/agent/AGENT.md +5 -5
- package/src/rules/lead/LEAD.md +5 -5
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -4
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +10 -0
- package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
- package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
- package/src/runtime/agent/orchestrator/config.mjs +5 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +36 -7
- package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +49 -10
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +40 -3
- package/src/runtime/agent/orchestrator/mcp/client.mjs +230 -96
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +103 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +150 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +111 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +87 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +95 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-request.mjs +122 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +9 -0
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +229 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +188 -29
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +94 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +98 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-fast-mode.mjs +39 -18
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +55 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +48 -37
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +10 -7
- package/src/runtime/agent/orchestrator/providers/anthropic-midstream-recovery.mjs +18 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +13 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-midstream.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-recovery.mjs +23 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +46 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request.mjs +14 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +102 -45
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +69 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-server-fallback.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +40 -7
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +30 -9
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +88 -21
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +30 -10
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +106 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +10 -61
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +94 -15
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +117 -72
- package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +75 -10
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-guards.mjs +97 -2
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +103 -23
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +43 -2
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +103 -33
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +32 -6
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +27 -3
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +64 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +70 -6
- package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
- package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
- package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +80 -18
- package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +46 -8
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +273 -0
- package/src/runtime/agent/orchestrator/providers/gemini-family.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/gemini-history-signatures.mjs +9 -4
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +180 -0
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +369 -112
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +140 -35
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +70 -24
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +80 -29
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +69 -19
- package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +246 -42
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
- package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +388 -0
- package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
- package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
- package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +48 -22
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +119 -18
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +33 -1
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +4 -9
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +123 -61
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +27 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +37 -7
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +50 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +47 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
- package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +151 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +64 -23
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +79 -33
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +172 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +144 -15
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +193 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +66 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +109 -26
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +27 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +34 -20
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +23 -4
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +37 -28
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +274 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +72 -32
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +43 -15
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-stamps.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +7 -3
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +1 -3
- package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +37 -4
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +12 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +22 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +12 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +76 -33
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +44 -16
- package/src/runtime/agent/orchestrator/providers/openai-retry-policy.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -16
- package/src/runtime/agent/orchestrator/providers/openai-ws-handshake.mjs +16 -8
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -35
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/policy.mjs +25 -14
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
- package/src/runtime/agent/orchestrator/providers/openai-ws-terminal.mjs +18 -11
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +41 -22
- package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +170 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +75 -70
- package/src/runtime/agent/orchestrator/providers/openrouter.mjs +75 -0
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +720 -0
- package/src/runtime/agent/orchestrator/providers/registry.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/retry-backoff.mjs +46 -7
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +123 -219
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +148 -45
- package/src/runtime/agent/orchestrator/providers/retry-midstream.mjs +81 -16
- package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
- package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
- package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +157 -0
- package/src/runtime/agent/orchestrator/providers/wire-route.mjs +512 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +183 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +100 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +21 -0
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
- package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +0 -18
- package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +57 -28
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +19 -16
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +1 -97
- package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
- package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +14 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +176 -71
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +62 -10
- package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +14 -93
- package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +120 -0
- package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
- package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +91 -1
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
- package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +21 -10
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +132 -0
- package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +30 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +67 -20
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +104 -19
- package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +150 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +7 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +30 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +57 -21
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +5 -10
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +208 -14
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +16 -4
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +25 -3
- package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +19 -2
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +18 -7
- package/src/runtime/agent/orchestrator/session/manager.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +168 -29
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/side-question.mjs +192 -0
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +17 -3
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +58 -2
- package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +41 -28
- package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +12 -1
- package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/store/write-guards.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +22 -10
- package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/store.mjs +19 -3
- package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +77 -0
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +20 -1
- package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +12 -15
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +5 -5
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +14 -10
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +49 -34
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
- package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
- package/src/runtime/computer-bridge/action-schema.mjs +44 -21
- package/src/runtime/github/tool.mjs +92 -2
- package/src/runtime/memory/index.mjs +1 -0
- package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
- package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
- package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
- package/src/runtime/memory/lib/pg/process.mjs +65 -50
- package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
- package/src/runtime/memory/lib/pg/supervisor.mjs +124 -16
- package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
- package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
- package/src/runtime/office/README.md +2 -2
- package/src/runtime/office/authoring/html-document-author.mjs +2 -0
- package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-measure.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +2 -0
- package/src/runtime/office/core/office-actions-read.mjs +3 -0
- package/src/runtime/office/core/office-render-preview.mjs +2 -0
- package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
- package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
- package/src/runtime/office/core/office-sessions.mjs +5 -0
- package/src/runtime/office/core/office-transactions.mjs +3 -0
- package/src/runtime/office/core/office-write-ledger.mjs +98 -0
- package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
- package/src/runtime/office/index.mjs +30 -0
- package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
- package/src/runtime/office/pdf/pdf-render.mjs +23 -7
- package/src/runtime/office/pdf/pdf-security.mjs +2 -0
- package/src/runtime/office/portable/portable-opc.mjs +4 -1
- package/src/runtime/office/quality/visual-diff.mjs +2 -0
- package/src/runtime/office/shared/values.mjs +0 -5
- package/src/runtime/shared/background-tasks.mjs +92 -14
- package/src/runtime/shared/bounded-file-read.mjs +13 -0
- package/src/runtime/shared/bounded-line-diff.mjs +182 -0
- package/src/runtime/shared/buffered-appender.mjs +18 -0
- package/src/runtime/shared/config.mjs +78 -18
- package/src/runtime/shared/err-text.mjs +31 -0
- package/src/runtime/shared/error-presentation.mjs +159 -19
- package/src/runtime/shared/file-permissions.d.mts +6 -1
- package/src/runtime/shared/file-permissions.mjs +54 -6
- package/src/runtime/shared/llm/anthropic-betas.mjs +4 -3
- package/src/runtime/shared/llm/anthropic-effort.mjs +129 -134
- package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +50 -14
- package/src/runtime/shared/llm/model-catalog.mjs +53 -40
- package/src/runtime/shared/llm/openai-daybreak.mjs +4 -16
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +11 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +13 -4
- package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
- package/src/runtime/shared/llm/usage-rollup.mjs +0 -1
- package/src/runtime/shared/loopback-listener.mjs +9 -0
- package/src/runtime/shared/model-display.mjs +13 -0
- package/src/runtime/shared/provider-api-key.mjs +2 -0
- package/src/runtime/shared/quota-resume-store.mjs +11 -0
- package/src/runtime/shared/review-diff.mjs +52 -0
- package/src/runtime/shared/session-baseline-store.mjs +960 -0
- package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
- package/src/runtime/shared/session-sidebar-host.mjs +38 -0
- package/src/runtime/shared/slow-span.mjs +114 -0
- package/src/runtime/shared/statusline/statusline-format.mjs +4 -4
- package/src/runtime/shared/statusline/statusline-segments.mjs +28 -4
- package/src/runtime/shared/task-notification-envelope.mjs +2 -2
- package/src/runtime/shared/tool-card-model/card-header.mjs +6 -1
- package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
- package/src/runtime/shared/tool-card-model.mjs +5 -2
- package/src/runtime/shared/tool-output-limit.mjs +4 -0
- package/src/runtime/shared/tool-primitives.mjs +13 -0
- package/src/runtime/shared/tool-result-summary.mjs +8 -1
- package/src/runtime/shared/tool-surface.mjs +18 -3
- package/src/runtime/shared/tool-work-units.mjs +40 -4
- package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
- package/src/runtime/shared/transcript-writer.mjs +10 -2
- package/src/runtime/shared/turn-changes.mjs +670 -274
- package/src/runtime/shared/turn-review-reply.mjs +8 -39
- package/src/runtime/shared/turn-snapshot-store.mjs +94 -2
- package/src/runtime/shared/turn-snapshot.mjs +986 -690
- package/src/runtime/shared/turn-worktree-snapshot.mjs +279 -262
- package/src/runtime/shared/user-data-guard.mjs +262 -49
- package/src/runtime/shared/worktrees/carry.mjs +531 -0
- package/src/runtime/shared/worktrees/contract.mjs +34 -24
- package/src/runtime/shared/worktrees/file-recovery.mjs +68 -0
- package/src/runtime/shared/worktrees/git-head.mjs +205 -0
- package/src/runtime/shared/worktrees/git.mjs +8 -3
- package/src/runtime/shared/worktrees/maintenance.mjs +1 -1
- package/src/runtime/shared/worktrees/manager.mjs +156 -8
- package/src/runtime/shared/worktrees/merge.mjs +31 -21
- package/src/runtime/shared/worktrees/paths.d.mts +6 -0
- package/src/runtime/shared/worktrees/test-support.mjs +19 -4
- package/src/runtime/terminal-bridge/client.mjs +44 -11
- package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
- package/src/runtime/tidy/apply.mjs +47 -2
- package/src/runtime/tidy/run-engines.mjs +11 -5
- package/src/session-runtime/agent-tool-routing.mjs +19 -13
- package/src/session-runtime/boot/apis.mjs +19 -5
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/infrastructure.mjs +12 -1
- package/src/session-runtime/boot/session.mjs +0 -1
- package/src/session-runtime/boot/tools.mjs +4 -1
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +65 -0
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +11 -4
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +115 -18
- package/src/session-runtime/internal-tool-executor.mjs +6 -2
- package/src/session-runtime/lifecycle/cold-heir.mjs +188 -0
- package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
- package/src/session-runtime/lifecycle/session-catalog.mjs +14 -3
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +29 -6
- package/src/session-runtime/lifecycle/teardown.mjs +73 -8
- package/src/session-runtime/lifecycle-api.mjs +1 -0
- package/src/session-runtime/mcp-glue/connect.mjs +46 -14
- package/src/session-runtime/mcp-glue/server-catalog.mjs +20 -3
- package/src/session-runtime/mcp-glue.mjs +3 -0
- package/src/session-runtime/mcp-oauth-login.mjs +174 -0
- package/src/session-runtime/model-route/model-switch-target.mjs +34 -0
- package/src/session-runtime/model-route/set-route.mjs +85 -17
- package/src/session-runtime/model-route/web-search-route.mjs +1 -1
- package/src/session-runtime/native-web-search/routes.mjs +22 -3
- package/src/session-runtime/native-web-search-usage.mjs +51 -0
- package/src/session-runtime/native-web-search.mjs +10 -1
- package/src/session-runtime/new-session-config.mjs +4 -2
- package/src/session-runtime/provider-auth/login.mjs +4 -0
- package/src/session-runtime/provider-models/model-meta.mjs +12 -3
- package/src/session-runtime/quick-model-rows/web-search-rows.mjs +13 -8
- package/src/session-runtime/quick-web-search-models.mjs +13 -38
- package/src/session-runtime/resource-extension-sync.mjs +4 -0
- package/src/session-runtime/resource-mcp-api.mjs +98 -2
- package/src/session-runtime/resource-scope-decorate.mjs +10 -3
- package/src/session-runtime/runtime-review-api.mjs +21 -2
- package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
- package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +13 -1
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +7 -2
- package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
- package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +73 -7
- package/src/session-runtime/services/agent-tool/send-flow.mjs +22 -4
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +2 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +22 -5
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +15 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +8 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -2
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
- package/src/session-runtime/services/agent-tool/worker-index.mjs +46 -7
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +17 -0
- package/src/session-runtime/services/agent-tool.mjs +3 -0
- package/src/session-runtime/services/channel-admin.mjs +19 -3
- package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
- package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
- package/src/session-runtime/services/provider-admin.mjs +81 -15
- package/src/session-runtime/session-transcript-purge.mjs +32 -0
- package/src/session-runtime/session-turn-api.mjs +14 -5
- package/src/session-runtime/settings-builtin-tools-api.mjs +9 -0
- package/src/session-runtime/settings-compaction-api.mjs +1 -0
- package/src/session-runtime/setup-tool/executor.mjs +36 -6
- package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
- package/src/session-runtime/setup-tool/settings-contract.mjs +13 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +13 -4
- package/src/session-runtime/skills-api.mjs +3 -5
- package/src/session-runtime/tool-surface.mjs +5 -1
- package/src/session-runtime/turn/compaction-gate.mjs +25 -0
- package/src/session-runtime/turn/session-ops.mjs +7 -5
- package/src/session-runtime/turn/side-question-ops.mjs +22 -0
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +5 -1
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +8 -3
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +10 -0
- package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
- package/src/session-runtime/turn/turn-run.mjs +25 -9
- package/src/session-runtime/usage-stats-api.mjs +43 -11
- package/src/session-runtime/workspace/project-branches.mjs +7 -5
- package/src/session-runtime/workspace/transition-steps.mjs +129 -31
- package/src/session-runtime/workspace/transitions.mjs +190 -15
- package/src/standalone/daemon-agent-control.mjs +9 -1
- package/src/standalone/daemon-drain-policy.mjs +8 -0
- package/src/standalone/daemon-local-session-bridge.mjs +14 -1
- package/src/standalone/daemon-owner.mjs +17 -4
- package/src/standalone/daemon-pg-stop.mjs +51 -0
- package/src/standalone/daemon-stop-budget.d.mts +2 -0
- package/src/standalone/daemon-stop-budget.mjs +18 -0
- package/src/standalone/daemon-stored-session-views.mjs +2 -0
- package/src/standalone/daemon-telemetry.mjs +74 -0
- package/src/standalone/daemon.mjs +64 -8
- package/src/standalone/desktop-service-registry.mjs +5 -0
- package/src/standalone/local-session-runtime.mjs +70 -19
- package/src/standalone/session-client.mjs +42 -0
- package/src/standalone/session-protocol.mjs +14 -0
- package/src/standalone/session-proxy/projection.mjs +41 -4
- package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
- package/src/standalone/session-runtime-inline-host.mjs +1 -0
- package/src/standalone/session-service/agent-tree/agent-cancel.mjs +33 -2
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +26 -10
- package/src/standalone/session-service/agent-tree.mjs +12 -0
- package/src/standalone/session-service/quota-resume.mjs +8 -0
- package/src/standalone/session-service/retention/busy.mjs +15 -1
- package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
- package/src/standalone/session-service-api.mjs +11 -1
- package/src/standalone/session-service.mjs +1 -0
- package/src/standalone/session-state-patch.d.mts +2 -1
- package/src/standalone/session-state-patch.mjs +41 -1
- package/src/tui/App.jsx +25 -0
- package/src/tui/app/app-view/floating-panel.jsx +26 -1
- package/src/tui/app/app-view.jsx +1 -0
- package/src/tui/app/btw-controller.mjs +118 -0
- package/src/tui/app/create-app-pickers.mjs +6 -0
- package/src/tui/app/extension-pickers/mcp-login.mjs +107 -0
- package/src/tui/app/extension-pickers/mcp-servers-picker.mjs +2 -1
- package/src/tui/app/extension-pickers.mjs +2 -1
- package/src/tui/app/model-options.mjs +11 -16
- package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
- package/src/tui/app/shell-layout/surfaces.mjs +3 -1
- package/src/tui/app/slash-commands.mjs +20 -5
- package/src/tui/app/slash-dispatch/panel-commands.mjs +16 -1
- package/src/tui/app/slash-dispatch/session-commands.mjs +19 -6
- package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
- package/src/tui/app/use-global-key-input.mjs +5 -12
- package/src/tui/app/use-prompt-handlers.mjs +11 -0
- package/src/tui/components/BtwPanel.jsx +53 -0
- package/src/tui/components/QuestionPanel.jsx +275 -0
- package/src/tui/components/StatusLine.jsx +2 -0
- package/src/tui/components/question-panel-model.mjs +156 -0
- package/src/tui/components/status-line/local-line.mjs +5 -2
- package/src/tui/components/status-line/use-statusline-text.mjs +7 -1
- package/src/tui/dist/index.mjs +3221 -1500
- package/src/tui/session/context-state.mjs +4 -2
- package/src/tui/session/quota-resume.mjs +46 -14
- package/src/tui/session/session-api/commands.mjs +43 -24
- package/src/tui/session/session-api/controls.mjs +2 -2
- package/src/tui/session/session-api/extensions.mjs +22 -0
- package/src/tui/session/session-api/integrations.mjs +16 -2
- package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
- package/src/tui/session/session-api/lifecycle.mjs +7 -2
- package/src/tui/session/session-api/routes.mjs +71 -7
- package/src/tui/session/session-api/settings.mjs +11 -14
- package/src/tui/session/session-api.mjs +1 -0
- package/src/tui/session/session-flow/drain.mjs +7 -1
- package/src/tui/session/session-flow/failed-turn-rewind.mjs +10 -4
- package/src/tui/session/tool-approval.mjs +10 -7
- package/src/tui/session/transcript-spill.mjs +14 -7
- package/src/tui/session/turn-stream.mjs +174 -31
- package/src/tui/session/turn.mjs +46 -16
- package/src/tui/statusline-ansi-bridge.mjs +1 -1
- package/src/ui/statusline-agents.mjs +15 -4
- package/src/ui/statusline.mjs +7 -3
- package/src/ui/streaming-markdown-heal.mjs +34 -3
- package/src/vendor/statusline/src/gateway/claude-current.mjs +14 -4
- package/src/workflows/default/WORKFLOW.md +3 -1
- package/src/runtime/memory/lib/memory-session-merge.mjs +0 -32
- package/src/runtime/shared/llm/usage-session-history.mjs +0 -266
|
@@ -15,23 +15,49 @@ import {
|
|
|
15
15
|
rm as rmP,
|
|
16
16
|
stat as statP,
|
|
17
17
|
} from 'node:fs/promises';
|
|
18
|
-
import { dirname, join } from 'node:path';
|
|
18
|
+
import { basename, dirname, join, resolve } from 'node:path';
|
|
19
19
|
import { homedir } from 'node:os';
|
|
20
|
-
import { createHash } from 'node:crypto';
|
|
20
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
21
21
|
import { isPlainObject } from './object.mjs';
|
|
22
|
+
import { mixdogHome } from './plugin-paths.mjs';
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
// The root follows the isolated home (MIXDOG_HOME, then the legacy
|
|
25
|
+
// MIXDOG_CONFIG_DIR), so a dev profile keeps its backups inside its own
|
|
26
|
+
// profile; the installed app resolves to ~/.mixdog/backups/user-data.
|
|
27
27
|
function getBackupRoot() {
|
|
28
|
-
return
|
|
28
|
+
return (
|
|
29
|
+
process.env.MIXDOG_USER_DATA_BACKUP_ROOT ||
|
|
30
|
+
join(process.env.MIXDOG_HOME || process.env.MIXDOG_CONFIG_DIR || mixdogHome(), 'backups', 'user-data')
|
|
31
|
+
);
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
const USER_DATA_FILES = ['mixdog-config.json'];
|
|
32
35
|
|
|
33
36
|
const USER_DATA_DIRS = ['schedules', 'webhooks', 'workflows'];
|
|
34
37
|
|
|
38
|
+
// Written into every backup; a backup without one (legacy, or interrupted
|
|
39
|
+
// mid-copy) is never restored.
|
|
40
|
+
const BACKUP_MANIFEST = 'backup.json';
|
|
41
|
+
|
|
42
|
+
// Lives INSIDE the data dir: deleting or recreating the profile drops it, so a
|
|
43
|
+
// recreated profile at the same path is fresh. Its instanceId ties backups to
|
|
44
|
+
// this incarnation of the data dir.
|
|
45
|
+
const INIT_MARKER = '.mixdog-user-data.json';
|
|
46
|
+
|
|
47
|
+
const SCOPE_PREFIX = 'scope-';
|
|
48
|
+
|
|
49
|
+
function normalizeDataDir(dataDir) {
|
|
50
|
+
const full = resolve(String(dataDir));
|
|
51
|
+
return process.platform === 'win32' ? full.toLowerCase() : full;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Per-data-dir backup folder. The `scope-` prefix sorts after the timestamped
|
|
55
|
+
// legacy entries, so an older build pruning the root as one ring keeps it.
|
|
56
|
+
function scopeDirFor(dataDir) {
|
|
57
|
+
const id = createHash('sha256').update(normalizeDataDir(dataDir)).digest('hex').slice(0, 16);
|
|
58
|
+
return join(getBackupRoot(), `${SCOPE_PREFIX}${id}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
35
61
|
function stamp() {
|
|
36
62
|
return new Date().toISOString().replace(/[:.]/g, '-');
|
|
37
63
|
}
|
|
@@ -44,16 +70,105 @@ function safeReason(reason) {
|
|
|
44
70
|
);
|
|
45
71
|
}
|
|
46
72
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
.
|
|
52
|
-
|
|
73
|
+
/** instanceId of this data dir's init marker; null when absent or unreadable. */
|
|
74
|
+
function readInitInstanceId(dataDir) {
|
|
75
|
+
if (!dataDir) return null;
|
|
76
|
+
try {
|
|
77
|
+
const marker = JSON.parse(readFileSync(join(dataDir, INIT_MARKER), 'utf8'));
|
|
78
|
+
return typeof marker?.instanceId === 'string' && marker.instanceId ? marker.instanceId : null;
|
|
79
|
+
} catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
53
82
|
}
|
|
54
83
|
|
|
55
84
|
export function hasUserDataInitMarker(dataDir) {
|
|
56
|
-
return
|
|
85
|
+
return readInitInstanceId(dataDir) != null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Older builds kept one unscoped ring plus `.initialized-<hash>.json` markers
|
|
89
|
+
// under MIXDOG_CONFIG_DIR (or ~/.mixdog), ignoring MIXDOG_HOME.
|
|
90
|
+
function legacyBackupRoots() {
|
|
91
|
+
const legacy =
|
|
92
|
+
process.env.MIXDOG_USER_DATA_BACKUP_ROOT ||
|
|
93
|
+
join(process.env.MIXDOG_CONFIG_DIR || join(homedir(), '.mixdog'), 'backups', 'user-data');
|
|
94
|
+
const current = getBackupRoot();
|
|
95
|
+
return normalizeDataDir(legacy) === normalizeDataDir(current) ? [current] : [current, legacy];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function manifestDataDirMatches(backupDir, dataDirKey) {
|
|
99
|
+
try {
|
|
100
|
+
const manifest = JSON.parse(readFileSync(join(backupDir, BACKUP_MANIFEST), 'utf8'));
|
|
101
|
+
return typeof manifest?.dataDir === 'string' && normalizeDataDir(manifest.dataDir) === dataDirKey;
|
|
102
|
+
} catch {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function legacyMarkersFor(root, dataDir, dataDirKey) {
|
|
108
|
+
const hashed = new Set(
|
|
109
|
+
[String(dataDir), resolve(String(dataDir))].map(
|
|
110
|
+
(value) => `.initialized-${createHash('sha256').update(value).digest('hex').slice(0, 16)}.json`
|
|
111
|
+
)
|
|
112
|
+
);
|
|
113
|
+
let names = [];
|
|
114
|
+
try {
|
|
115
|
+
names = readdirSync(root).filter((name) => name.startsWith('.initialized-') && name.endsWith('.json'));
|
|
116
|
+
} catch {
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
119
|
+
return names
|
|
120
|
+
.filter((name) => {
|
|
121
|
+
if (hashed.has(name)) return true;
|
|
122
|
+
try {
|
|
123
|
+
const marker = JSON.parse(readFileSync(join(root, name), 'utf8'));
|
|
124
|
+
return typeof marker?.dataDir === 'string' && normalizeDataDir(marker.dataDir) === dataDirKey;
|
|
125
|
+
} catch {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
.map((name) => join(root, name));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Evidence that a data dir without the in-dir marker was initialized by an
|
|
134
|
+
* older build: a legacy marker for it, or an unscoped backup whose manifest
|
|
135
|
+
* names it. Null when there is none, or when the data dir was already migrated
|
|
136
|
+
* (scoped backups exist), so a recreated profile stays fresh.
|
|
137
|
+
*/
|
|
138
|
+
export function findLegacyUserDataEvidence(dataDir, { fresh = false } = {}) {
|
|
139
|
+
if (!dataDir || hasUserDataInitMarker(dataDir)) return null;
|
|
140
|
+
const key = normalizeDataDir(dataDir);
|
|
141
|
+
const roots = legacyBackupRoots().join('\n');
|
|
142
|
+
const hit = legacyEvidenceCache.get(key);
|
|
143
|
+
if (!fresh && hit && hit.roots === roots) return hit.evidence;
|
|
144
|
+
const evidence = scanLegacyUserDataEvidence(dataDir, key);
|
|
145
|
+
legacyEvidenceCache.set(key, { roots, evidence });
|
|
146
|
+
return evidence;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Per-process legacy-evidence lookup for plain reads (a fresh install with a
|
|
150
|
+
// missing config would otherwise rescan the legacy root on every read). RMW
|
|
151
|
+
// writes always rescan; this process's own backups invalidate it.
|
|
152
|
+
const legacyEvidenceCache = new Map();
|
|
153
|
+
|
|
154
|
+
function scanLegacyUserDataEvidence(dataDir, key) {
|
|
155
|
+
if (backupDirsNewestFirst(scopeDirFor(dataDir)).length > 0) return null;
|
|
156
|
+
const markers = [];
|
|
157
|
+
const backups = [];
|
|
158
|
+
for (const root of legacyBackupRoots()) {
|
|
159
|
+
markers.push(...legacyMarkersFor(root, dataDir, key));
|
|
160
|
+
for (const name of backupDirsNewestFirst(root)) {
|
|
161
|
+
if (name.startsWith(SCOPE_PREFIX)) continue;
|
|
162
|
+
if (manifestDataDirMatches(join(root, name), key)) backups.push(join(root, name));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
backups.sort((x, y) => basename(y).localeCompare(basename(x)));
|
|
166
|
+
return markers.length || backups.length ? { markers, backups, roots: legacyBackupRoots() } : null;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** A missing config is a loss to recover (not a fresh install). */
|
|
170
|
+
export function isUserDataRecoveryExpected(dataDir, options) {
|
|
171
|
+
return hasUserDataInitMarker(dataDir) || findLegacyUserDataEvidence(dataDir, options) != null;
|
|
57
172
|
}
|
|
58
173
|
|
|
59
174
|
/** Skip single-section wipe remnants (e.g. `{ search: … }` only). */
|
|
@@ -64,10 +179,10 @@ function isStructurallyCompleteMixdogConfigBackup(parsed) {
|
|
|
64
179
|
return true;
|
|
65
180
|
}
|
|
66
181
|
|
|
67
|
-
/** Backup directory names
|
|
68
|
-
function backupDirsNewestFirst() {
|
|
182
|
+
/** Backup directory names in `dir`, newest first; empty when unreadable. */
|
|
183
|
+
function backupDirsNewestFirst(dir) {
|
|
69
184
|
try {
|
|
70
|
-
return readdirSync(
|
|
185
|
+
return readdirSync(dir, { withFileTypes: true })
|
|
71
186
|
.filter((entry) => entry.isDirectory())
|
|
72
187
|
.map((entry) => entry.name)
|
|
73
188
|
.sort()
|
|
@@ -78,16 +193,71 @@ function backupDirsNewestFirst() {
|
|
|
78
193
|
}
|
|
79
194
|
|
|
80
195
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
196
|
+
* A backup is restorable only when its manifest names this data dir and this
|
|
197
|
+
* incarnation of it. Legacy unscoped backups carry no manifest, so they stay
|
|
198
|
+
* on disk but never match.
|
|
83
199
|
*/
|
|
84
|
-
|
|
200
|
+
function readRestorableConfig(backupDir, dataDirKey, instanceId) {
|
|
201
|
+
try {
|
|
202
|
+
const manifest = JSON.parse(readFileSync(join(backupDir, BACKUP_MANIFEST), 'utf8'));
|
|
203
|
+
if (typeof manifest?.dataDir !== 'string' || normalizeDataDir(manifest.dataDir) !== dataDirKey) return null;
|
|
204
|
+
if (manifest.instanceId !== instanceId) return null;
|
|
205
|
+
const parsed = JSON.parse(readFileSync(join(backupDir, 'mixdog-config.json'), 'utf8'));
|
|
206
|
+
return isStructurallyCompleteMixdogConfigBackup(parsed) ? parsed : null;
|
|
207
|
+
} catch {
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function findRestorableConfig(dataDir, instanceId) {
|
|
213
|
+
const key = normalizeDataDir(dataDir);
|
|
214
|
+
const scopeDir = scopeDirFor(dataDir);
|
|
215
|
+
for (const name of backupDirsNewestFirst(scopeDir)) {
|
|
216
|
+
const parsed = readRestorableConfig(join(scopeDir, name), key, instanceId);
|
|
217
|
+
if (parsed) return parsed;
|
|
218
|
+
}
|
|
85
219
|
const root = getBackupRoot();
|
|
86
|
-
for (const name of backupDirsNewestFirst()) {
|
|
87
|
-
|
|
88
|
-
|
|
220
|
+
for (const name of backupDirsNewestFirst(root)) {
|
|
221
|
+
if (name.startsWith(SCOPE_PREFIX)) continue;
|
|
222
|
+
const parsed = readRestorableConfig(join(root, name), key, instanceId);
|
|
223
|
+
if (parsed) return parsed;
|
|
224
|
+
}
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Per-process restore lookup, keyed by data dir. A hit is reused while the
|
|
229
|
+
// backup root and the marker's instanceId are unchanged; this process's own
|
|
230
|
+
// backups invalidate it.
|
|
231
|
+
const restoreLookupCache = new Map();
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Newest structurally complete mixdog-config.json backed up from THIS data
|
|
235
|
+
* dir (skips degenerate single-section snapshots from a prior failed RMW).
|
|
236
|
+
* Never another data dir's config, and nothing for an uninitialized one.
|
|
237
|
+
*/
|
|
238
|
+
export function loadLatestMixdogConfigFromBackup(dataDir, options) {
|
|
239
|
+
const instanceId = readInitInstanceId(dataDir);
|
|
240
|
+
if (!instanceId) return loadLegacyMixdogConfigFromBackup(dataDir, options);
|
|
241
|
+
const key = normalizeDataDir(dataDir);
|
|
242
|
+
const root = getBackupRoot();
|
|
243
|
+
let hit = restoreLookupCache.get(key);
|
|
244
|
+
if (!hit || hit.root !== root || hit.instanceId !== instanceId) {
|
|
245
|
+
hit = { root, instanceId, config: findRestorableConfig(dataDir, instanceId) };
|
|
246
|
+
restoreLookupCache.set(key, hit);
|
|
247
|
+
}
|
|
248
|
+
return hit.config ? structuredClone(hit.config) : null;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Upgraded data dir without the in-dir marker: only an unscoped backup whose
|
|
253
|
+
* manifest names this data dir is verifiable (legacy backups predate
|
|
254
|
+
* instanceIds); manifest-less legacy backups are never restored.
|
|
255
|
+
*/
|
|
256
|
+
function loadLegacyMixdogConfigFromBackup(dataDir, options) {
|
|
257
|
+
const evidence = findLegacyUserDataEvidence(dataDir, options);
|
|
258
|
+
for (const backupDir of evidence?.backups || []) {
|
|
89
259
|
try {
|
|
90
|
-
const parsed = JSON.parse(readFileSync(
|
|
260
|
+
const parsed = JSON.parse(readFileSync(join(backupDir, 'mixdog-config.json'), 'utf8'));
|
|
91
261
|
if (isStructurallyCompleteMixdogConfigBackup(parsed)) return parsed;
|
|
92
262
|
} catch {}
|
|
93
263
|
}
|
|
@@ -108,38 +278,83 @@ function copyTree(src, dst, copied) {
|
|
|
108
278
|
copied.push(dst);
|
|
109
279
|
}
|
|
110
280
|
|
|
111
|
-
|
|
112
|
-
|
|
281
|
+
/** Prune one data dir's scope only; other scopes and legacy entries stay. */
|
|
282
|
+
function pruneBackups(scopeDir, keep = 40) {
|
|
283
|
+
for (const name of backupDirsNewestFirst(scopeDir).slice(keep)) {
|
|
113
284
|
try {
|
|
114
|
-
rmSync(join(
|
|
285
|
+
rmSync(join(scopeDir, name), { recursive: true, force: true });
|
|
115
286
|
} catch {}
|
|
116
287
|
}
|
|
117
288
|
}
|
|
118
289
|
|
|
290
|
+
/**
|
|
291
|
+
* Create the data dir's init marker unless one exists; returns its instanceId
|
|
292
|
+
* (null when the data dir is gone or unwritable). Never creates the data dir.
|
|
293
|
+
*/
|
|
119
294
|
export function markUserDataInitialized(dataDir) {
|
|
295
|
+
const existing = readInitInstanceId(dataDir);
|
|
296
|
+
if (existing || !dataDir || !existsSync(dataDir)) return existing;
|
|
120
297
|
try {
|
|
121
|
-
mkdirSync(getBackupRoot(), { recursive: true });
|
|
122
298
|
writeFileSync(
|
|
123
|
-
|
|
299
|
+
join(dataDir, INIT_MARKER),
|
|
124
300
|
`${JSON.stringify(
|
|
125
|
-
{
|
|
126
|
-
dataDir,
|
|
127
|
-
updatedAt: new Date().toISOString(),
|
|
128
|
-
},
|
|
301
|
+
{ instanceId: randomUUID(), dataDir: resolve(dataDir), createdAt: new Date().toISOString() },
|
|
129
302
|
null,
|
|
130
303
|
2
|
|
131
304
|
)}\n`,
|
|
132
|
-
'
|
|
305
|
+
// An unreadable marker is replaced; a concurrent creator's valid one wins.
|
|
306
|
+
{ encoding: 'utf8', flag: existsSync(join(dataDir, INIT_MARKER)) ? 'w' : 'wx' }
|
|
133
307
|
);
|
|
134
308
|
} catch {}
|
|
309
|
+
return readInitInstanceId(dataDir);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const ensuredDataDirs = new Set();
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Called when a readable config is observed. A data dir that predates the
|
|
316
|
+
* in-dir marker (an upgraded install) gets its marker together with a first
|
|
317
|
+
* scoped snapshot, so a later loss of the config stays recoverable. Once per
|
|
318
|
+
* data dir per process.
|
|
319
|
+
*/
|
|
320
|
+
export function ensureUserDataInitialized(dataDir) {
|
|
321
|
+
if (!dataDir) return;
|
|
322
|
+
const key = normalizeDataDir(dataDir);
|
|
323
|
+
if (ensuredDataDirs.has(key)) return;
|
|
324
|
+
ensuredDataDirs.add(key);
|
|
325
|
+
if (!hasUserDataInitMarker(dataDir)) backupUserData(dataDir, 'initial-snapshot');
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function skipBackups() {
|
|
329
|
+
return process.env.MIXDOG_SKIP_USER_DATA_BACKUP === '1' || process.env.MIXDOG_SKIP_USER_DATA_BACKUP === 'true';
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function backupTarget(dataDir, reason) {
|
|
333
|
+
const scopeDir = scopeDirFor(dataDir);
|
|
334
|
+
return { scopeDir, backupDir: join(scopeDir, `${stamp()}-${safeReason(reason)}`) };
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Mark first so the manifest carries this incarnation's instanceId; the
|
|
338
|
+
// manifest goes last, so an interrupted copy is never restorable.
|
|
339
|
+
function finishBackup(dataDir, backupDir, reason) {
|
|
340
|
+
const instanceId = markUserDataInitialized(dataDir);
|
|
341
|
+
writeFileSync(
|
|
342
|
+
join(backupDir, BACKUP_MANIFEST),
|
|
343
|
+
`${JSON.stringify(
|
|
344
|
+
{ dataDir: resolve(dataDir), instanceId, reason, createdAt: new Date().toISOString() },
|
|
345
|
+
null,
|
|
346
|
+
2
|
|
347
|
+
)}\n`,
|
|
348
|
+
'utf8'
|
|
349
|
+
);
|
|
350
|
+
restoreLookupCache.delete(normalizeDataDir(dataDir));
|
|
351
|
+
legacyEvidenceCache.delete(normalizeDataDir(dataDir));
|
|
135
352
|
}
|
|
136
353
|
|
|
137
354
|
export function backupUserData(dataDir, reason = 'snapshot') {
|
|
138
|
-
if (
|
|
139
|
-
return { dir: null, copied: [] };
|
|
140
|
-
}
|
|
355
|
+
if (skipBackups()) return { dir: null, copied: [] };
|
|
141
356
|
if (!dataDir || !existsSync(dataDir)) return { dir: null, copied: [] };
|
|
142
|
-
const backupDir =
|
|
357
|
+
const { scopeDir, backupDir } = backupTarget(dataDir, reason);
|
|
143
358
|
const copied = [];
|
|
144
359
|
for (const rel of USER_DATA_FILES) {
|
|
145
360
|
const src = join(dataDir, rel);
|
|
@@ -150,8 +365,8 @@ export function backupUserData(dataDir, reason = 'snapshot') {
|
|
|
150
365
|
if (existsSync(src)) copyTree(src, join(backupDir, rel), copied);
|
|
151
366
|
}
|
|
152
367
|
if (copied.length > 0) {
|
|
153
|
-
|
|
154
|
-
pruneBackups();
|
|
368
|
+
finishBackup(dataDir, backupDir, reason);
|
|
369
|
+
pruneBackups(scopeDir);
|
|
155
370
|
if (process.env.MIXDOG_SETUP_QUIET !== '1') {
|
|
156
371
|
process.stderr.write(`[user-data-backup] ${reason}: copied ${copied.length} file(s) to ${backupDir}\n`);
|
|
157
372
|
}
|
|
@@ -177,10 +392,10 @@ async function copyTreeAsync(src, dst, copied) {
|
|
|
177
392
|
copied.push(dst);
|
|
178
393
|
}
|
|
179
394
|
|
|
180
|
-
async function pruneBackupsAsync(keep = 40) {
|
|
395
|
+
async function pruneBackupsAsync(scopeDir, keep = 40) {
|
|
181
396
|
let entries = [];
|
|
182
397
|
try {
|
|
183
|
-
entries = (await readdirP(
|
|
398
|
+
entries = (await readdirP(scopeDir, { withFileTypes: true }))
|
|
184
399
|
.filter((entry) => entry.isDirectory())
|
|
185
400
|
.map((entry) => entry.name)
|
|
186
401
|
.sort()
|
|
@@ -190,17 +405,15 @@ async function pruneBackupsAsync(keep = 40) {
|
|
|
190
405
|
}
|
|
191
406
|
for (const name of entries.slice(keep)) {
|
|
192
407
|
try {
|
|
193
|
-
await rmP(join(
|
|
408
|
+
await rmP(join(scopeDir, name), { recursive: true, force: true });
|
|
194
409
|
} catch {}
|
|
195
410
|
}
|
|
196
411
|
}
|
|
197
412
|
|
|
198
413
|
export async function backupUserDataAsync(dataDir, reason = 'snapshot') {
|
|
199
|
-
if (
|
|
200
|
-
return { dir: null, copied: [] };
|
|
201
|
-
}
|
|
414
|
+
if (skipBackups()) return { dir: null, copied: [] };
|
|
202
415
|
if (!dataDir || !existsSync(dataDir)) return { dir: null, copied: [] };
|
|
203
|
-
const backupDir =
|
|
416
|
+
const { scopeDir, backupDir } = backupTarget(dataDir, reason);
|
|
204
417
|
const copied = [];
|
|
205
418
|
for (const rel of USER_DATA_FILES) {
|
|
206
419
|
const src = join(dataDir, rel);
|
|
@@ -211,8 +424,8 @@ export async function backupUserDataAsync(dataDir, reason = 'snapshot') {
|
|
|
211
424
|
if (existsSync(src)) await copyTreeAsync(src, join(backupDir, rel), copied);
|
|
212
425
|
}
|
|
213
426
|
if (copied.length > 0) {
|
|
214
|
-
|
|
215
|
-
await pruneBackupsAsync();
|
|
427
|
+
finishBackup(dataDir, backupDir, reason);
|
|
428
|
+
await pruneBackupsAsync(scopeDir);
|
|
216
429
|
if (process.env.MIXDOG_SETUP_QUIET !== '1') {
|
|
217
430
|
process.stderr.write(`[user-data-backup] ${reason}: copied ${copied.length} file(s) to ${backupDir}\n`);
|
|
218
431
|
}
|