mixdog 1.2.2 → 1.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -0
- package/package.json +2 -1
- package/scripts/gate-local.mjs +6 -4
- package/scripts/lib/gate-scheduler.mjs +29 -11
- package/scripts/probe-provider-catalog.mjs +31 -0
- package/scripts/provider-pingpong-live.mjs +599 -0
- package/scripts/session-sweep.mjs +5 -25
- package/src/agents/advisor/AGENT.md +1 -1
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/maintainer/AGENT.md +1 -1
- package/src/agents/maintainer/agent.json +1 -1
- package/src/agents/reviewer/AGENT.md +2 -4
- package/src/agents/security/AGENT.md +1 -2
- package/src/agents/writer/AGENT.md +2 -3
- package/src/defaults/shipped-history.json +11 -1
- package/src/defaults/skills/image/SKILL.md +21 -23
- package/src/defaults/skills/setup/SKILL.md +6 -1
- package/src/defaults/skills/setup/references/actions.md +44 -22
- package/src/defaults/skills/setup/references/surfaces.md +10 -8
- package/src/headless-exec.mjs +15 -8
- package/src/lib/keychain-cjs.cjs +20 -15
- package/src/output-styles/common.md +11 -10
- package/src/rules/agent/AGENT.md +6 -4
- package/src/rules/lead/LEAD.md +7 -9
- package/src/rules/shared/45-destructive.md +4 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +28 -7
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -11
- package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
- package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
- package/src/runtime/agent/orchestrator/config.mjs +5 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +101 -23
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-api-key-fetch.mjs +36 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +24 -17
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +9 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +26 -44
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +31 -15
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +41 -12
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +13 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +131 -9
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +29 -10
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +125 -8
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +12 -62
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +117 -41
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +117 -72
- package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +39 -5
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-native-context.mjs +48 -0
- package/src/runtime/agent/orchestrator/providers/cursor-wire-exec.mjs +144 -34
- package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +28 -4
- package/src/runtime/agent/orchestrator/providers/cursor-wire-request.mjs +8 -4
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +42 -11
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +109 -6
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +17 -4
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +22 -2
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +73 -7
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +75 -6
- package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
- package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
- package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +29 -5
- package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +36 -13
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +101 -11
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/gemini-rest-stream/watchdogs.mjs +16 -5
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +19 -14
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +371 -41
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +97 -49
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +81 -10
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +35 -8
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +253 -42
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
- package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +392 -0
- package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
- package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
- package/src/runtime/agent/orchestrator/providers/lib/request-compression.mjs +86 -0
- package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +50 -22
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +133 -21
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +92 -16
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +13 -13
- package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +133 -62
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +39 -7
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +84 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
- package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +155 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +40 -24
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +63 -25
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +183 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +87 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +51 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +103 -26
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +23 -4
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +11 -6
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +17 -2
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +15 -23
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +64 -52
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +28 -5
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
- package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +72 -24
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +50 -16
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -19
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -36
- package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +18 -9
- package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +181 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +78 -70
- package/src/runtime/agent/orchestrator/providers/openrouter.mjs +74 -0
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +150 -10
- package/src/runtime/agent/orchestrator/providers/registry.mjs +13 -2
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
- package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
- package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +164 -0
- package/src/runtime/agent/orchestrator/providers/wire-route.mjs +522 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
- package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +195 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +104 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +8 -6
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +24 -0
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
- package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +30 -2
- package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +3 -2
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -3
- package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
- package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +16 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge-contract.mjs +6 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +178 -71
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +102 -12
- package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -8
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -2
- package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +24 -0
- package/src/runtime/agent/orchestrator/session/cache/tool-result-reuse.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -3
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +5 -11
- package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +6 -22
- package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +16 -93
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +148 -0
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +0 -6
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +0 -6
- package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/historical-session-closure.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +2 -5
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +89 -1
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
- package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -27
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -10
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +2 -9
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +24 -10
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +135 -0
- package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +31 -4
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +76 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +67 -20
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +10 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +29 -5
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +147 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +7 -5
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +33 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-support.mjs +0 -4
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +23 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +54 -13
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +33 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +11 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +22 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +57 -13
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/failed-turn-rewind.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +6 -120
- package/src/runtime/agent/orchestrator/session/manager/pending-persist-queue.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +231 -16
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +42 -49
- package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +50 -0
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +47 -17
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +26 -4
- package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +36 -35
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +29 -13
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +45 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +4 -10
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/send-instrumentation.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +17 -1
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
- package/src/runtime/agent/orchestrator/session/side-question.mjs +197 -0
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +22 -15
- package/src/runtime/agent/orchestrator/session/store/lifecycle-read.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/listing.mjs +2 -6
- package/src/runtime/agent/orchestrator/session/store/live-cache-eviction.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +46 -37
- package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/load-session.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +44 -37
- package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
- package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +59 -0
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/sweep/stale-sweep.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +27 -21
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +0 -8
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +6 -18
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +33 -106
- package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +4 -2
- package/src/runtime/agent/orchestrator/session/store-agent-worker-pool.mjs +5 -8
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +136 -196
- package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +53 -115
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +10 -1
- package/src/runtime/agent/orchestrator/session/store-summary-locations.mjs +3 -29
- package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +17 -10
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +9 -20
- package/src/runtime/agent/orchestrator/session/store.mjs +22 -19
- package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +12 -12
- package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +38 -14
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +15 -4
- package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +79 -0
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +72 -15
- package/src/runtime/agent/orchestrator/session/turn-failure.mjs +45 -0
- package/src/runtime/agent/orchestrator/stall-policy.mjs +50 -0
- package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +5 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +218 -20
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +160 -39
- package/src/runtime/agent/orchestrator/tools/builtin/git-partial-stage.mjs +7 -5
- package/src/runtime/agent/orchestrator/tools/builtin/grep-formatting.mjs +14 -5
- package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-context-expander.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-output.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-path-fanout.mjs +48 -44
- package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +10 -3
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +247 -49
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +5 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +20 -0
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +101 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +67 -0
- package/src/runtime/agent/orchestrator/tools/lib/process-table-fixture.mjs +50 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +303 -63
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +108 -18
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +77 -11
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +81 -5
- package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
- package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
- package/src/runtime/attachments/store.d.mts +9 -0
- package/src/runtime/attachments/store.mjs +80 -9
- package/src/runtime/browser-bridge/browser-action-contract.d.mts +0 -1
- package/src/runtime/browser-bridge/browser-action-contract.mjs +0 -2
- package/src/runtime/computer-bridge/action-schema.mjs +219 -196
- package/src/runtime/computer-bridge/linux-readiness.d.mts +0 -2
- package/src/runtime/computer-bridge/linux-readiness.mjs +0 -16
- package/src/runtime/effort-judge/judge-client.mjs +21 -4
- package/src/runtime/effort-judge/judge-worker.mjs +4 -1
- package/src/runtime/github/tool.mjs +208 -17
- package/src/runtime/media/adapters/codex-image.mjs +140 -21
- package/src/runtime/media/catalog.mjs +4 -4
- package/src/runtime/media/chatgpt-usage.mjs +55 -0
- package/src/runtime/media/defaults.mjs +37 -0
- package/src/runtime/media/jobs.mjs +12 -2
- package/src/runtime/media/lanes.mjs +12 -0
- package/src/runtime/media/tool-defs.mjs +15 -4
- package/src/runtime/media/tool.mjs +41 -12
- package/src/runtime/media/upstream-error.mjs +72 -6
- package/src/runtime/memory/index.mjs +1 -0
- package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
- package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
- package/src/runtime/memory/lib/ingest/transcript-rows.mjs +1 -0
- package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
- package/src/runtime/memory/lib/pg/process.mjs +36 -33
- package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
- package/src/runtime/memory/lib/pg/supervisor.mjs +112 -4
- package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
- package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
- package/src/runtime/office/README.md +1 -1
- package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
- package/src/runtime/office/authoring/html-browser.mjs +18 -8
- package/src/runtime/office/authoring/html-document-author.mjs +2 -0
- package/src/runtime/office/authoring/pdf-html-runner.mjs +1 -1
- package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
- package/src/runtime/office/authoring/pptx-html-measure.mjs +3 -1
- package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +3 -1
- package/src/runtime/office/core/office-actions-read.mjs +3 -0
- package/src/runtime/office/core/office-render-preview.mjs +2 -0
- package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
- package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
- package/src/runtime/office/core/office-sessions.mjs +5 -0
- package/src/runtime/office/core/office-transactions.mjs +3 -0
- package/src/runtime/office/core/office-write-ledger.mjs +94 -0
- package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
- package/src/runtime/office/index.mjs +29 -0
- package/src/runtime/office/pdf/pdf-analysis.mjs +0 -68
- package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
- package/src/runtime/office/pdf/pdf-render.mjs +23 -7
- package/src/runtime/office/pdf/pdf-security.mjs +2 -0
- package/src/runtime/office/portable/portable-opc.mjs +4 -1
- package/src/runtime/office/quality/visual-diff.mjs +2 -0
- package/src/runtime/session-search/session-search-ingest.mjs +1 -1
- package/src/runtime/shared/agent-reap-state.mjs +13 -0
- package/src/runtime/shared/atomic-file.d.mts +1 -1
- package/src/runtime/shared/background-tasks.mjs +6 -1
- package/src/runtime/shared/bounded-file-read.mjs +13 -0
- package/src/runtime/shared/bounded-line-diff.mjs +191 -0
- package/src/runtime/shared/browser-launch.mjs +15 -0
- package/src/runtime/shared/buffered-appender.mjs +18 -0
- package/src/runtime/shared/config.mjs +78 -18
- package/src/runtime/shared/err-text.mjs +48 -4
- package/src/runtime/shared/file-lock.mjs +6 -5
- package/src/runtime/shared/file-permissions.d.mts +6 -1
- package/src/runtime/shared/file-permissions.mjs +54 -6
- package/src/runtime/shared/llm/anthropic-betas.mjs +1 -2
- package/src/runtime/shared/llm/anthropic-effort.mjs +6 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +1 -0
- package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
- package/src/runtime/shared/loopback-listener.mjs +9 -0
- package/src/runtime/shared/model-route-chain.d.mts +8 -0
- package/src/runtime/shared/model-route-chain.mjs +48 -0
- package/src/runtime/shared/model-route-fallback.mjs +22 -0
- package/src/runtime/shared/pid-liveness.mjs +12 -0
- package/src/runtime/shared/provider-api-key.mjs +8 -0
- package/src/runtime/shared/provider-timeout-phase.mjs +17 -0
- package/src/runtime/shared/quiet-progress.d.mts +35 -0
- package/src/runtime/shared/quiet-progress.mjs +101 -0
- package/src/runtime/shared/quota-resume-store.mjs +32 -1
- package/src/runtime/shared/read-row-numbers.mjs +44 -0
- package/src/runtime/shared/remote-intent.mjs +2 -42
- package/src/runtime/shared/review-diff.mjs +52 -0
- package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
- package/src/runtime/shared/session-sidebar-host.mjs +38 -0
- package/src/runtime/shared/slow-span.mjs +121 -0
- package/src/runtime/shared/statusline/statusline-segments.mjs +52 -6
- package/src/runtime/shared/tool-card-model/card-header.mjs +7 -1
- package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
- package/src/runtime/shared/tool-card-model.mjs +5 -2
- package/src/runtime/shared/tool-output-budget.mjs +2 -0
- package/src/runtime/shared/tool-output-limit.mjs +4 -0
- package/src/runtime/shared/tool-primitives.mjs +13 -0
- package/src/runtime/shared/tool-result-summary.mjs +22 -1
- package/src/runtime/shared/tool-status.mjs +3 -2
- package/src/runtime/shared/tool-surface.mjs +20 -6
- package/src/runtime/shared/tool-work-units.mjs +54 -11
- package/src/runtime/shared/transcript-metadata.mjs +49 -1
- package/src/runtime/shared/transcript-turn-keys.mjs +33 -0
- package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
- package/src/runtime/shared/transcript-writer/transcript-file.mjs +10 -1
- package/src/runtime/shared/transcript-writer.mjs +24 -6
- package/src/runtime/shared/turn-changes.mjs +269 -100
- package/src/runtime/shared/turn-review-reply.mjs +8 -39
- package/src/runtime/shared/turn-snapshot-store.mjs +19 -108
- package/src/runtime/shared/turn-snapshot.mjs +865 -683
- package/src/runtime/shared/turn-worktree-snapshot.mjs +183 -255
- package/src/runtime/shared/user-data-guard.mjs +262 -49
- package/src/runtime/shared/worktrees/activity-gate.mjs +175 -0
- package/src/runtime/shared/worktrees/branch-management.mjs +179 -0
- package/src/runtime/shared/worktrees/carry.mjs +533 -0
- package/src/runtime/shared/worktrees/contract.mjs +60 -0
- package/src/runtime/shared/worktrees/dependencies.mjs +456 -0
- package/src/runtime/shared/worktrees/file-recovery.mjs +84 -0
- package/src/runtime/shared/worktrees/git-head.mjs +214 -0
- package/src/runtime/shared/worktrees/git.mjs +8 -3
- package/src/runtime/shared/worktrees/include.mjs +125 -7
- package/src/runtime/shared/worktrees/lock.mjs +1 -1
- package/src/runtime/shared/worktrees/maintenance.mjs +20 -2
- package/src/runtime/shared/worktrees/manager.mjs +525 -31
- package/src/runtime/shared/worktrees/merge.mjs +31 -21
- package/src/runtime/shared/worktrees/owner.mjs +2 -1
- package/src/runtime/shared/worktrees/paths.d.mts +6 -0
- package/src/runtime/shared/worktrees/preparation-report.mjs +79 -0
- package/src/runtime/shared/worktrees/setup-commands.mjs +232 -0
- package/src/runtime/shared/worktrees/workspace-visibility.mjs +17 -0
- package/src/runtime/terminal-bridge/client.mjs +57 -20
- package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
- package/src/runtime/tidy/apply.mjs +47 -2
- package/src/runtime/tidy/run-engines.mjs +11 -5
- package/src/session-runtime/agent-tool-routing.mjs +19 -13
- package/src/session-runtime/boot/apis.mjs +20 -6
- package/src/session-runtime/boot/config.mjs +2 -0
- package/src/session-runtime/boot/facade.mjs +4 -0
- package/src/session-runtime/boot/infrastructure.mjs +6 -1
- package/src/session-runtime/boot/session.mjs +3 -3
- package/src/session-runtime/boot/tools.mjs +7 -1
- package/src/session-runtime/conversation-import/service.mjs +1 -1
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
- package/src/session-runtime/goal-facade-api.mjs +2 -2
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +91 -0
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +15 -5
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +137 -26
- package/src/session-runtime/internal-tool-executor.mjs +8 -2
- package/src/session-runtime/lifecycle/cold-heir.mjs +187 -0
- package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
- package/src/session-runtime/lifecycle/session-catalog.mjs +25 -18
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +36 -48
- package/src/session-runtime/lifecycle/session-switch.mjs +1 -1
- package/src/session-runtime/lifecycle/shared.mjs +5 -6
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -5
- package/src/session-runtime/lifecycle/teardown.mjs +70 -14
- package/src/session-runtime/lifecycle-api.mjs +1 -0
- package/src/session-runtime/mcp-glue/connect.mjs +17 -5
- package/src/session-runtime/media-api.mjs +8 -0
- package/src/session-runtime/model-route/route-ownership.mjs +60 -0
- package/src/session-runtime/model-route/route-persist.mjs +3 -2
- package/src/session-runtime/model-route/set-route.mjs +116 -36
- package/src/session-runtime/model-route/web-search-route.mjs +7 -2
- package/src/session-runtime/model-route-api.mjs +4 -2
- package/src/session-runtime/native-web-search/routes.mjs +37 -24
- package/src/session-runtime/native-web-search-usage.mjs +51 -0
- package/src/session-runtime/native-web-search.mjs +19 -9
- package/src/session-runtime/new-session-config.mjs +4 -2
- package/src/session-runtime/provider-auth/login.mjs +4 -0
- package/src/session-runtime/provider-auth/setup.mjs +4 -0
- package/src/session-runtime/provider-models/catalog-load.mjs +9 -0
- package/src/session-runtime/provider-models/web-search-catalog.mjs +23 -3
- package/src/session-runtime/provider-models.mjs +1 -0
- package/src/session-runtime/provider-usage.mjs +4 -0
- package/src/session-runtime/resource-scope-decorate.mjs +10 -3
- package/src/session-runtime/route-resolution.mjs +3 -1
- package/src/session-runtime/runtime-core.mjs +4 -0
- package/src/session-runtime/runtime-facade.mjs +6 -0
- package/src/session-runtime/runtime-review-api.mjs +8 -2
- package/src/session-runtime/services/agent-task-status.mjs +2 -0
- package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +0 -3
- package/src/session-runtime/services/agent-tool/close-flow.mjs +6 -7
- package/src/session-runtime/services/agent-tool/execute-send.mjs +2 -2
- package/src/session-runtime/services/agent-tool/execute-spawn.mjs +36 -3
- package/src/session-runtime/services/agent-tool/execute.mjs +9 -1
- package/src/session-runtime/services/agent-tool/helpers.mjs +30 -7
- package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
- package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +7 -2
- package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +6 -3
- package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
- package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
- package/src/session-runtime/services/agent-tool/lead-worker-index/lead-rows.mjs +3 -4
- package/src/session-runtime/services/agent-tool/lead-worker-index/reap-timers.mjs +9 -3
- package/src/session-runtime/services/agent-tool/lead-worker-index/row-settlement.mjs +7 -18
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +82 -13
- package/src/session-runtime/services/agent-tool/model-select.mjs +82 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -6
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +3 -1
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -5
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -4
- package/src/session-runtime/services/agent-tool/spawn-flow.mjs +2 -1
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
- package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +1 -3
- package/src/session-runtime/services/agent-tool/tag-registry/tag-refresh.mjs +1 -3
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +18 -10
- package/src/session-runtime/services/agent-tool/terminal-reaper/scan-admission.mjs +8 -41
- package/src/session-runtime/services/agent-tool/terminal-reaper/stale-rows.mjs +3 -3
- package/src/session-runtime/services/agent-tool/terminal-reaper.mjs +6 -23
- package/src/session-runtime/services/agent-tool/terminal-trace.mjs +0 -1
- package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +32 -20
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -2
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
- package/src/session-runtime/services/agent-tool/worker-index.mjs +74 -15
- package/src/session-runtime/services/agent-tool.mjs +7 -0
- package/src/session-runtime/services/agent-watchdog-registry.mjs +2 -0
- package/src/session-runtime/services/channel-admin.mjs +19 -3
- package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
- package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
- package/src/session-runtime/services/provider-admin.mjs +158 -15
- package/src/session-runtime/session-create/session-options.mjs +7 -5
- package/src/session-runtime/session-create/session-start-hook.mjs +2 -1
- package/src/session-runtime/session-transcript-purge.mjs +32 -0
- package/src/session-runtime/session-transcript.mjs +4 -5
- package/src/session-runtime/session-turn-api.mjs +17 -14
- package/src/session-runtime/settings-builtin-tools-api.mjs +18 -6
- package/src/session-runtime/setup-tool/executor.mjs +57 -9
- package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
- package/src/session-runtime/setup-tool/settings-contract.mjs +18 -3
- package/src/session-runtime/setup-tool/tool-defs.mjs +25 -4
- package/src/session-runtime/skills-api.mjs +3 -5
- package/src/session-runtime/tool-policy-refresh.mjs +83 -32
- package/src/session-runtime/tool-surface.mjs +5 -1
- package/src/session-runtime/turn/agent-ops.mjs +49 -2
- package/src/session-runtime/turn/compaction-gate.mjs +25 -0
- package/src/session-runtime/turn/session-ops.mjs +7 -5
- package/src/session-runtime/turn/side-question-ops.mjs +19 -0
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +7 -1
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +12 -3
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +18 -2
- package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
- package/src/session-runtime/turn/turn-run.mjs +26 -45
- package/src/session-runtime/usage-stats-api.mjs +46 -11
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +16 -1
- package/src/session-runtime/workspace/admission-gate.mjs +44 -15
- package/src/session-runtime/workspace/project-branches.mjs +35 -41
- package/src/session-runtime/workspace/transition-steps.mjs +215 -116
- package/src/session-runtime/workspace/transitions.mjs +428 -73
- package/src/standalone/channel-transport.mjs +3 -4
- package/src/standalone/daemon-agent-control.mjs +9 -1
- package/src/standalone/daemon-desktop-runtime.mjs +32 -1
- package/src/standalone/daemon-local-session-bridge.mjs +14 -1
- package/src/standalone/daemon-owner.mjs +17 -4
- package/src/standalone/daemon-pg-stop.mjs +49 -0
- package/src/standalone/daemon-session-control.mjs +88 -0
- package/src/standalone/daemon-stop-budget.d.mts +2 -0
- package/src/standalone/daemon-stop-budget.mjs +18 -0
- package/src/standalone/daemon-stored-session-views.mjs +25 -3
- package/src/standalone/daemon-telemetry.mjs +19 -0
- package/src/standalone/daemon.mjs +63 -1
- package/src/standalone/desktop-service-registry.mjs +5 -0
- package/src/standalone/local-session-runtime.mjs +80 -30
- package/src/standalone/session-client.mjs +42 -0
- package/src/standalone/session-protocol.mjs +14 -0
- package/src/standalone/session-proxy/projection.mjs +41 -4
- package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
- package/src/standalone/session-runtime-inline-host.mjs +3 -0
- package/src/standalone/session-service/agent-tree/agent-cancel.mjs +91 -49
- package/src/standalone/session-service/agent-tree/agent-child.mjs +19 -1
- package/src/standalone/session-service/agent-tree/agent-registry.mjs +25 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +9 -1
- package/src/standalone/session-service/agent-tree.mjs +28 -2
- package/src/standalone/session-service/entries/session-loads.mjs +16 -5
- package/src/standalone/session-service/entries.mjs +1 -0
- package/src/standalone/session-service/projection/transcript-window.mjs +39 -0
- package/src/standalone/session-service/quota-resume.mjs +28 -13
- package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
- package/src/standalone/session-service/session-calls/session-turns.mjs +17 -6
- package/src/standalone/session-service/session-calls/session-views.mjs +6 -0
- package/src/standalone/session-service-api.mjs +6 -1
- package/src/standalone/session-state-patch.d.mts +2 -1
- package/src/standalone/session-state-patch.mjs +41 -1
- package/src/standalone/session-tool-output.mjs +82 -0
- package/src/tui/App.jsx +25 -0
- package/src/tui/app/app-view/floating-panel.jsx +26 -1
- package/src/tui/app/app-view.jsx +2 -1
- package/src/tui/app/btw-controller.mjs +118 -0
- package/src/tui/app/create-app-pickers.mjs +2 -0
- package/src/tui/app/provider-setup/provider-items.mjs +8 -0
- package/src/tui/app/provider-setup-picker.mjs +15 -3
- package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
- package/src/tui/app/shell-layout/surfaces.mjs +3 -1
- package/src/tui/app/slash-commands.mjs +19 -3
- package/src/tui/app/slash-dispatch/session-commands.mjs +68 -6
- package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
- package/src/tui/app/use-global-key-input.mjs +5 -12
- package/src/tui/app/use-prompt-handlers.mjs +11 -0
- package/src/tui/components/BtwPanel.jsx +53 -0
- package/src/tui/components/QuestionPanel.jsx +275 -0
- package/src/tui/components/Spinner.jsx +4 -0
- package/src/tui/components/SpinnerByline.jsx +21 -2
- package/src/tui/components/question-panel-model.mjs +156 -0
- package/src/tui/components/status-line/local-line.mjs +10 -2
- package/src/tui/dist/index.mjs +2897 -1722
- package/src/tui/session/active-tool-summary.mjs +1 -1
- package/src/tui/session/context-state.mjs +4 -5
- package/src/tui/session/goal-continuation/continuation-queue.mjs +2 -3
- package/src/tui/session/goal-continuation/deadline-delivery.mjs +4 -2
- package/src/tui/session/goal-continuation/session-boundary.mjs +21 -0
- package/src/tui/session/quota-resume.mjs +140 -61
- package/src/tui/session/session-api/commands.mjs +14 -10
- package/src/tui/session/session-api/controls.mjs +14 -2
- package/src/tui/session/session-api/integrations.mjs +9 -2
- package/src/tui/session/session-api/lifecycle/dispose.mjs +3 -9
- package/src/tui/session/session-api/lifecycle/resume.mjs +2 -7
- package/src/tui/session/session-api/lifecycle.mjs +14 -11
- package/src/tui/session/session-api/media.mjs +2 -0
- package/src/tui/session/session-api/routes.mjs +81 -57
- package/src/tui/session/session-api/settings.mjs +9 -3
- package/src/tui/session/session-api/worktree.mjs +3 -2
- package/src/tui/session/session-api.mjs +1 -0
- package/src/tui/session/session-flow/auto-clear.mjs +1 -3
- package/src/tui/session/session-flow/drain.mjs +6 -4
- package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -0
- package/src/tui/session/session-flow/queue/take-entries.mjs +2 -1
- package/src/tui/session/session-flow/queue.mjs +1 -1
- package/src/tui/session/tool-approval.mjs +20 -8
- package/src/tui/session/transcript-spill.mjs +14 -7
- package/src/tui/session/transcript-store/streaming-tail.mjs +1 -1
- package/src/tui/session/tui-steering-persist.mjs +3 -5
- package/src/tui/session/turn-quiet.mjs +53 -0
- package/src/tui/session/turn-stream.mjs +179 -32
- package/src/tui/session/turn.mjs +50 -36
- package/src/tui/session/worktree-setup-notice.mjs +38 -0
- package/src/tui/spinner-meta.mjs +10 -0
- package/src/tui/spinner-verbs.mjs +3 -0
- package/src/ui/statusline.mjs +13 -3
- package/src/workflows/default/WORKFLOW.md +3 -1
- package/src/runtime/agent/orchestrator/providers/model-pricing-rates.mjs +0 -1
- package/src/runtime/agent/orchestrator/session/manager/foreign-pending-messages.mjs +0 -346
- package/src/runtime/agent/orchestrator/session/manager/session-owner-liveness.mjs +0 -117
- package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +0 -246
- package/src/session-runtime/services/agent-tool/terminal-reaper/reap-timers.mjs +0 -142
- package/src/session-runtime/turn/share-ops.mjs +0 -77
- package/src/tui/session/cross-surface-share.mjs +0 -406
- package/src/tui/session/live-share/delta.mjs +0 -153
- package/src/tui/session/live-share/mirror.mjs +0 -106
- package/src/tui/session/live-share/owner.mjs +0 -254
- package/src/tui/session/live-share/retry.mjs +0 -54
- package/src/tui/session/live-share/viewer/frame-router.mjs +0 -32
- package/src/tui/session/live-share/viewer/pipe-client.mjs +0 -108
- package/src/tui/session/live-share/viewer/submit-acks.mjs +0 -65
- package/src/tui/session/live-share/viewer/sync-waiters.mjs +0 -53
- package/src/tui/session/live-share/viewer.mjs +0 -99
- package/src/tui/session/live-share/wire.mjs +0 -44
- package/src/tui/session/live-share.mjs +0 -154
- package/src/tui/session/shared-dir-watch.mjs +0 -69
|
@@ -8,15 +8,25 @@
|
|
|
8
8
|
import { createHash } from 'node:crypto';
|
|
9
9
|
import { lstat, open, realpath, stat } from 'node:fs/promises';
|
|
10
10
|
import { dirname, isAbsolute, relative, resolve } from 'node:path';
|
|
11
|
-
import {
|
|
11
|
+
import { deflateSync } from 'node:zlib';
|
|
12
12
|
import { cleanString as clean } from './clean.mjs';
|
|
13
13
|
import { runGitOffThread } from './git-runner.mjs';
|
|
14
|
+
import { createLineDiffBudget, lineDiffHunks } from './bounded-line-diff.mjs';
|
|
15
|
+
import {
|
|
16
|
+
createReviewPatchBudget,
|
|
17
|
+
filePatchReply,
|
|
18
|
+
PATCH_TOO_LARGE,
|
|
19
|
+
patchOmittedFile,
|
|
20
|
+
REVIEW_FILE_PATCH_MAX_BYTES,
|
|
21
|
+
REVIEW_FILE_PATCH_SHOW_MAX_BYTES,
|
|
22
|
+
REVIEW_PATCH_MAX_BYTES,
|
|
23
|
+
reviewDiffTooLarge,
|
|
24
|
+
} from './review-diff.mjs';
|
|
14
25
|
|
|
15
26
|
/** Largest single-file patch a record keeps replayable. */
|
|
16
27
|
export const TURN_CHANGE_FILE_PATCH_MAX_BYTES = 8 * 1024 * 1024;
|
|
17
28
|
const APPLY_TIMEOUT_MS = 60_000;
|
|
18
29
|
const APPLY_OUTPUT_MAX_BYTES = 4 * 1024 * 1024;
|
|
19
|
-
const TRACKED_DIFF_TIMEOUT_MS = 2_000;
|
|
20
30
|
const STATUSES = new Set(['A', 'M', 'D', 'R']);
|
|
21
31
|
// Characters a patch header cannot carry unquoted; such a path is recorded but
|
|
22
32
|
// never replayed.
|
|
@@ -157,13 +167,15 @@ export function splitPatchSections(buffer) {
|
|
|
157
167
|
});
|
|
158
168
|
}
|
|
159
169
|
|
|
160
|
-
// ── Exact tracker (
|
|
170
|
+
// ── Exact tracker patches (the session's own tool bytes) ────────────────────
|
|
161
171
|
|
|
162
172
|
const utf8Decoder = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
|
|
163
|
-
|
|
173
|
+
/** Text of one change side (bytes or a string): '' when absent, null for
|
|
174
|
+
* binary content (not UTF-8, or holding a NUL byte). */
|
|
175
|
+
export function decodeText(content) {
|
|
164
176
|
if (content == null) return '';
|
|
165
177
|
try {
|
|
166
|
-
const text = utf8Decoder.decode(content);
|
|
178
|
+
const text = typeof content === 'string' ? content : utf8Decoder.decode(content);
|
|
167
179
|
// A NUL byte marks binary content: it gets no text diff.
|
|
168
180
|
return text.includes('\0') ? null : text;
|
|
169
181
|
} catch {
|
|
@@ -171,13 +183,79 @@ function decodeText(content) {
|
|
|
171
183
|
}
|
|
172
184
|
}
|
|
173
185
|
|
|
186
|
+
/** True for bytes that get a binary patch instead of a text diff (not UTF-8,
|
|
187
|
+
* or holding a NUL byte). */
|
|
188
|
+
export function isBinaryChangeContent(content) {
|
|
189
|
+
return content != null && decodeText(content) === null;
|
|
190
|
+
}
|
|
191
|
+
|
|
174
192
|
const headerTab = (path) => (path.includes(' ') ? '\t' : '');
|
|
175
193
|
|
|
194
|
+
/** The object format (`sha1`/`sha256`) `git apply` hashes blobs with in `root`:
|
|
195
|
+
* the repository's own, or sha1 outside any repository. */
|
|
196
|
+
export async function repositoryObjectFormat(root) {
|
|
197
|
+
const result = await runGitOffThread(['rev-parse', '--show-object-format'], {
|
|
198
|
+
cwd: root,
|
|
199
|
+
timeoutMs: APPLY_TIMEOUT_MS,
|
|
200
|
+
maxBytes: APPLY_OUTPUT_MAX_BYTES,
|
|
201
|
+
}).catch(() => null);
|
|
202
|
+
return result?.code === 0 && clean(result.stdout) === 'sha256' ? 'sha256' : 'sha1';
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const BASE85 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~';
|
|
206
|
+
|
|
207
|
+
/** One line of a git binary hunk: a length letter, then 4-byte groups as base85. */
|
|
208
|
+
function base85Line(chunk) {
|
|
209
|
+
let line = String.fromCharCode(chunk.length <= 26 ? 64 + chunk.length : 70 + chunk.length);
|
|
210
|
+
for (let offset = 0; offset < chunk.length; offset += 4) {
|
|
211
|
+
let value = 0;
|
|
212
|
+
for (let index = 0; index < 4; index += 1) value = value * 256 + (chunk[offset + index] ?? 0);
|
|
213
|
+
const group = new Array(5);
|
|
214
|
+
for (let index = 4; index >= 0; index -= 1) {
|
|
215
|
+
group[index] = BASE85[value % 85];
|
|
216
|
+
value = Math.floor(value / 85);
|
|
217
|
+
}
|
|
218
|
+
line += group.join('');
|
|
219
|
+
}
|
|
220
|
+
return line;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function binaryLiteral(bytes) {
|
|
224
|
+
const deflated = deflateSync(bytes);
|
|
225
|
+
let text = `literal ${bytes.length}\n`;
|
|
226
|
+
for (let offset = 0; offset < deflated.length; offset += 52) {
|
|
227
|
+
text += `${base85Line(deflated.subarray(offset, offset + 52))}\n`;
|
|
228
|
+
}
|
|
229
|
+
return `${text}\n`;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/** The `index` line and `GIT binary patch` body of a byte change. Full blob
|
|
233
|
+
* ids make `git apply` verify the file still holds the recorded bytes on
|
|
234
|
+
* either side before it writes, so a binary file changed since is refused. */
|
|
235
|
+
function binaryPatchBody(before, after, status, objectFormat) {
|
|
236
|
+
const empty = Buffer.alloc(0);
|
|
237
|
+
const id = (bytes) => createHash(objectFormat).update(`blob ${bytes.length}\0`).update(bytes).digest('hex');
|
|
238
|
+
const zero = '0'.repeat(objectFormat === 'sha256' ? 64 : 40);
|
|
239
|
+
const oldId = before === null ? zero : id(before);
|
|
240
|
+
const newId = after === null ? zero : id(after);
|
|
241
|
+
return `index ${oldId}..${newId}${status === 'M' ? ' 100644' : ''}\nGIT binary patch\n${binaryLiteral(after ?? empty)}${binaryLiteral(before ?? empty)}`;
|
|
242
|
+
}
|
|
243
|
+
|
|
176
244
|
/**
|
|
177
245
|
* One git-format patch from exact before/after bytes (null = absent). Paths
|
|
178
|
-
* are root-relative.
|
|
246
|
+
* are root-relative. Text diffs as hunks within `budget` (see
|
|
247
|
+
* bounded-line-diff.mjs); binary content (isBinaryChangeContent) as a
|
|
248
|
+
* full-index binary patch hashed in `objectFormat`. Returns the record file
|
|
249
|
+
* without its state.
|
|
179
250
|
*/
|
|
180
|
-
export function trackedChangeFile({
|
|
251
|
+
export function trackedChangeFile({
|
|
252
|
+
oldPath,
|
|
253
|
+
newPath,
|
|
254
|
+
before,
|
|
255
|
+
after,
|
|
256
|
+
objectFormat = 'sha1',
|
|
257
|
+
budget = createLineDiffBudget(),
|
|
258
|
+
}) {
|
|
181
259
|
let status = 'M';
|
|
182
260
|
if (before === null) status = 'A';
|
|
183
261
|
else if (after === null) status = 'D';
|
|
@@ -190,22 +268,16 @@ export function trackedChangeFile({ oldPath, newPath, before, after }) {
|
|
|
190
268
|
const oldText = decodeText(before);
|
|
191
269
|
const newText = decodeText(after);
|
|
192
270
|
if (oldText === null || newText === null) {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
if (oldText !== newText) {
|
|
202
|
-
const result = structuredPatch(`a/${oldPath}`, `b/${newPath}`, oldText, newText, '', '', {
|
|
203
|
-
context: 3,
|
|
204
|
-
timeout: TRACKED_DIFF_TIMEOUT_MS,
|
|
205
|
-
});
|
|
206
|
-
if (!result) return { ...base, revertable: false, reason: 'the diff took too long to compute' };
|
|
207
|
-
hunks = result.hunks;
|
|
271
|
+
let patch = `diff --git a/${status === 'A' ? newPath : oldPath} b/${status === 'D' ? oldPath : newPath}\n`;
|
|
272
|
+
if (status === 'A') patch += 'new file mode 100644\n';
|
|
273
|
+
if (status === 'D') patch += 'deleted file mode 100644\n';
|
|
274
|
+
if (status === 'R') patch += `rename from ${oldPath}\nrename to ${newPath}\n`;
|
|
275
|
+
// A pure rename carries the full-index body too: `git apply` then moves
|
|
276
|
+
// the file only while it still holds the recorded bytes.
|
|
277
|
+
patch += binaryPatchBody(before, after, status, objectFormat);
|
|
278
|
+
return { ...base, binary: true, revertable: true, patch: Buffer.from(patch, 'utf8') };
|
|
208
279
|
}
|
|
280
|
+
const { hunks } = lineDiffHunks(oldText, newText, budget, [before, after]);
|
|
209
281
|
const oldName = status === 'A' ? newPath : oldPath;
|
|
210
282
|
const newName = status === 'D' ? oldPath : newPath;
|
|
211
283
|
let patch = `diff --git a/${oldName} b/${newName}\n`;
|
|
@@ -349,16 +421,17 @@ export function turnChangesReply({ status, checkpointId, record = null, patch =
|
|
|
349
421
|
|
|
350
422
|
export const NET_TEXT_MAX_BYTES = 1024 * 1024;
|
|
351
423
|
/** Budget of the merged session patch, in UTF-8 bytes. */
|
|
352
|
-
export const MERGED_PATCH_MAX_BYTES =
|
|
424
|
+
export const MERGED_PATCH_MAX_BYTES = REVIEW_PATCH_MAX_BYTES;
|
|
353
425
|
const VIEW_PATCH_MAX_BYTES = 256 * 1024;
|
|
354
426
|
|
|
355
427
|
/** Counts and a placeholder-named patch of exact before/after bytes. */
|
|
356
|
-
function measureChange(before, after, renamed) {
|
|
428
|
+
function measureChange(before, after, renamed, budget) {
|
|
357
429
|
const measured = trackedChangeFile({
|
|
358
430
|
oldPath: renamed ? 'mx-old-file' : 'mx-file',
|
|
359
431
|
newPath: renamed ? 'mx-new-file' : 'mx-file',
|
|
360
432
|
before,
|
|
361
433
|
after,
|
|
434
|
+
budget,
|
|
362
435
|
});
|
|
363
436
|
return {
|
|
364
437
|
status: measured.status,
|
|
@@ -384,9 +457,16 @@ function nameMeasuredPatch(text, oldName, newName) {
|
|
|
384
457
|
|
|
385
458
|
/** A git-format patch of exact before/after text under the names a viewer
|
|
386
459
|
* shows (absolute for a file outside the worktree). `before`/`after` are
|
|
387
|
-
* Buffers or null (absent). */
|
|
388
|
-
export function namedChangePatch({
|
|
389
|
-
|
|
460
|
+
* Buffers or null (absent); `budget` the operation's line-diff budget. */
|
|
461
|
+
export function namedChangePatch({
|
|
462
|
+
before,
|
|
463
|
+
after,
|
|
464
|
+
oldName,
|
|
465
|
+
newName,
|
|
466
|
+
maxBytes = VIEW_PATCH_MAX_BYTES,
|
|
467
|
+
budget = createLineDiffBudget(),
|
|
468
|
+
}) {
|
|
469
|
+
const { text, ...measured } = measureChange(before, after, oldName !== newName, budget);
|
|
390
470
|
const patch = nameMeasuredPatch(text, oldName, newName);
|
|
391
471
|
return { ...measured, patch: Buffer.byteLength(patch, 'utf8') > maxBytes ? '' : patch };
|
|
392
472
|
}
|
|
@@ -397,21 +477,39 @@ const absolutePath = (root, path) => (isOutsidePath(path) ? resolve(path) : reso
|
|
|
397
477
|
const patchOf = (file) =>
|
|
398
478
|
changePatchBuffer(file)?.toString('utf8') || (typeof file?.viewPatch === 'string' ? file.viewPatch : '');
|
|
399
479
|
|
|
480
|
+
/** A record file's patch as a review shows it: a binary body becomes the
|
|
481
|
+
* `Binary files … differ` line a diff viewer renders. */
|
|
482
|
+
export function changeDisplayPatch(file) {
|
|
483
|
+
const buffer =
|
|
484
|
+
changePatchBuffer(file) || (typeof file?.viewPatch === 'string' ? Buffer.from(file.viewPatch, 'utf8') : null);
|
|
485
|
+
return splitPatchSections(buffer)
|
|
486
|
+
.map(({ oldPath, newPath, patch }) => {
|
|
487
|
+
const text = patch.toString('utf8');
|
|
488
|
+
const body = text.indexOf('\nGIT binary patch\n');
|
|
489
|
+
if (body < 0) return text;
|
|
490
|
+
const head = text.slice(0, body + 1).replace(/^index .*\n/m, '');
|
|
491
|
+
return `${head}Binary files ${oldPath === null ? '/dev/null' : `a/${oldPath}`} and ${newPath === null ? '/dev/null' : `b/${newPath}`} differ\n`;
|
|
492
|
+
})
|
|
493
|
+
.join('');
|
|
494
|
+
}
|
|
495
|
+
|
|
400
496
|
const insideDirectory = (parent, child) => {
|
|
401
497
|
const rel = relative(parent, child);
|
|
402
498
|
return rel === '' || (!isAbsolute(rel) && rel.split(/[\\/]+/)[0] !== '..');
|
|
403
499
|
};
|
|
404
500
|
|
|
405
|
-
/** At most
|
|
406
|
-
*
|
|
407
|
-
async function readBounded(file) {
|
|
501
|
+
/** At most `maxBytes` of a regular file, read through one handle: undefined
|
|
502
|
+
* when it is larger (checked by size first, never read whole). */
|
|
503
|
+
async function readBounded(file, maxBytes = NET_TEXT_MAX_BYTES) {
|
|
408
504
|
const handle = await open(file, 'r');
|
|
409
505
|
try {
|
|
410
506
|
const info = await handle.stat();
|
|
411
|
-
if (!info.isFile() || info.size >
|
|
412
|
-
|
|
507
|
+
if (!info.isFile() || info.size > maxBytes) return undefined;
|
|
508
|
+
// Sized by the file, one byte over: a file that grew since its stat is
|
|
509
|
+
// not read part-way.
|
|
510
|
+
const buffer = Buffer.alloc(info.size + 1);
|
|
413
511
|
const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);
|
|
414
|
-
return bytesRead >
|
|
512
|
+
return bytesRead > info.size ? undefined : buffer.subarray(0, bytesRead);
|
|
415
513
|
} finally {
|
|
416
514
|
await handle.close();
|
|
417
515
|
}
|
|
@@ -471,13 +569,20 @@ function isUnmeasuredFile(file) {
|
|
|
471
569
|
|
|
472
570
|
/** A legacy record kept no counts or diff for a new file it could not replay
|
|
473
571
|
* (outside the root): measure the file as it is on disk now. Returns the
|
|
474
|
-
* file with its counts and display patch, or the file unchanged.
|
|
475
|
-
|
|
572
|
+
* file with its counts and display patch, or the file unchanged. `budget`:
|
|
573
|
+
* the line-diff budget of the read it is part of. */
|
|
574
|
+
export async function measureLegacyChangeFile(file, root, budget = createLineDiffBudget()) {
|
|
476
575
|
if (!isUnmeasuredFile(file)) return file;
|
|
477
576
|
const text = await currentText(root, file.path);
|
|
478
577
|
if (typeof text !== 'string' || !text) return file;
|
|
479
578
|
const name = slashPath(file.path);
|
|
480
|
-
const named = namedChangePatch({
|
|
579
|
+
const named = namedChangePatch({
|
|
580
|
+
before: null,
|
|
581
|
+
after: Buffer.from(text, 'utf8'),
|
|
582
|
+
oldName: name,
|
|
583
|
+
newName: name,
|
|
584
|
+
budget,
|
|
585
|
+
});
|
|
481
586
|
if (!named.patch) return file;
|
|
482
587
|
return { ...file, additions: named.additions, deletions: named.deletions, viewPatch: named.patch };
|
|
483
588
|
}
|
|
@@ -487,7 +592,10 @@ const DIGEST_MAX_BYTES = 64 * 1024 * 1024;
|
|
|
487
592
|
// Largest measured patch a review keeps cached between polls.
|
|
488
593
|
const CACHED_PATCH_MAX_BYTES = 256 * 1024;
|
|
489
594
|
const READ_CONCURRENCY = 16;
|
|
490
|
-
const
|
|
595
|
+
const CURRENT_READ_MAX_BYTES = REVIEW_FILE_PATCH_SHOW_MAX_BYTES;
|
|
596
|
+
/** A file whose current content is past CURRENT_READ_MAX_BYTES (or cannot be
|
|
597
|
+
* read whole): listed without a patch, explicitly too large. */
|
|
598
|
+
const tooLargeChange = (status) => ({ status, additions: 0, deletions: 0, text: '', patchOmitted: true });
|
|
491
599
|
const UNREADABLE_REASON = 'the file cannot be read safely now';
|
|
492
600
|
const SEVERAL_TURNS_REASON = 'edited in several turns before its session baseline was recorded';
|
|
493
601
|
/** Why a listed file has no exact diff against the session's first state. */
|
|
@@ -534,12 +642,14 @@ async function currentFile({ root, path }) {
|
|
|
534
642
|
|
|
535
643
|
const currentSig = (current) => (current?.state === 'present' ? current.sig : current?.state || '');
|
|
536
644
|
|
|
537
|
-
/** Bytes of a present file up to
|
|
538
|
-
*
|
|
645
|
+
/** Bytes of a present file up to CURRENT_READ_MAX_BYTES — what one file's
|
|
646
|
+
* own patch read may show, so a file past the reply's per-file cap still has
|
|
647
|
+
* its counts and its patch on request; undefined past it or when it cannot
|
|
648
|
+
* be read. */
|
|
539
649
|
async function currentBytes(current) {
|
|
540
|
-
if (current.size >
|
|
650
|
+
if (current.size > CURRENT_READ_MAX_BYTES) return undefined;
|
|
541
651
|
try {
|
|
542
|
-
return await readBounded(current.file);
|
|
652
|
+
return await readBounded(current.file, CURRENT_READ_MAX_BYTES);
|
|
543
653
|
} catch {
|
|
544
654
|
return undefined;
|
|
545
655
|
}
|
|
@@ -600,7 +710,7 @@ const UNVOUCHED_UNCHANGED = Object.freeze({ hidden: true, partial: true });
|
|
|
600
710
|
/** One file (or rename) measured from its first-seen state `entry` to the
|
|
601
711
|
* disk now (`current`); null when the session left it as it found it,
|
|
602
712
|
* UNVOUCHED_UNCHANGED when only a hash says so. */
|
|
603
|
-
async function measureBaseline(entry, current, renamed, readBlob) {
|
|
713
|
+
async function measureBaseline(entry, current, renamed, readBlob, budget) {
|
|
604
714
|
const changed = renamed ? 'R' : 'M';
|
|
605
715
|
if (current.state === 'unsafe') {
|
|
606
716
|
return partialChange(entry.state === 'absent' ? 'A' : changed, UNREADABLE_REASON);
|
|
@@ -609,15 +719,15 @@ async function measureBaseline(entry, current, renamed, readBlob) {
|
|
|
609
719
|
const after = present ? await currentBytes(current) : null;
|
|
610
720
|
if (entry.state === 'absent') {
|
|
611
721
|
if (!present) return null;
|
|
612
|
-
if (after === undefined) return
|
|
613
|
-
return measureChange(null, after, false);
|
|
722
|
+
if (after === undefined) return tooLargeChange('A');
|
|
723
|
+
return measureChange(null, after, false, budget);
|
|
614
724
|
}
|
|
615
725
|
if (present) {
|
|
616
726
|
const same = await sameAsBaseline(entry, current, after);
|
|
617
727
|
const exact = entry.status === 'captured';
|
|
618
728
|
if (same === true && !renamed) return exact ? null : UNVOUCHED_UNCHANGED;
|
|
619
729
|
if (same === true) {
|
|
620
|
-
const moved =
|
|
730
|
+
const moved = measureChange(Buffer.alloc(0), Buffer.alloc(0), true, budget);
|
|
621
731
|
return exact
|
|
622
732
|
? moved
|
|
623
733
|
: { ...moved, partial: true, baseline: entry.status, reason: BASELINE_REASONS[entry.status] };
|
|
@@ -627,14 +737,24 @@ async function measureBaseline(entry, current, renamed, readBlob) {
|
|
|
627
737
|
const before = entry.status === 'captured' ? await readBlob(entry) : undefined;
|
|
628
738
|
if (!before)
|
|
629
739
|
return baselineGap(entry.status === 'captured' ? { ...entry, status: 'evicted' } : entry, present ? changed : 'D');
|
|
630
|
-
if (after === undefined) return
|
|
631
|
-
return measureChange(before, after, renamed);
|
|
740
|
+
if (after === undefined) return tooLargeChange(changed);
|
|
741
|
+
return measureChange(before, after, renamed, budget);
|
|
632
742
|
}
|
|
633
743
|
|
|
634
|
-
/**
|
|
635
|
-
*
|
|
636
|
-
|
|
637
|
-
|
|
744
|
+
/** A list measurement as a reply keeps it: text past the per-file inline cap
|
|
745
|
+
* is dropped at once, its counts kept and the file marked too large. */
|
|
746
|
+
function inlineChange(change) {
|
|
747
|
+
if (Buffer.byteLength(change?.text || '', 'utf8') <= REVIEW_FILE_PATCH_MAX_BYTES) return change;
|
|
748
|
+
return { ...change, text: '', patchOmitted: true };
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
/** Every baseline not `covered` by another source, measured against the disk
|
|
752
|
+
* within the review's line-diff `budget`. A path holding a renamed file pairs
|
|
753
|
+
* with the path it came from when that one is gone. Measurements are reused
|
|
754
|
+
* while the files' stats are unchanged. With `target` (an entry predicate)
|
|
755
|
+
* only the units it matches are measured, with their whole text; every other
|
|
756
|
+
* unit is returned `nameOnly`, for naming. */
|
|
757
|
+
async function baselineChanges(baselines, covered, unvouched, budget, { target = null } = {}) {
|
|
638
758
|
const entries = new Map();
|
|
639
759
|
for (const entry of baselines.files) if (!covered(entry.path)) entries.set(entry.key, entry);
|
|
640
760
|
const list = [...entries.values()];
|
|
@@ -655,6 +775,12 @@ async function baselineChanges(baselines, covered, unvouched) {
|
|
|
655
775
|
for (const entry of list) if (!paired.has(entry.key)) units.push({ key: entry.key, before: entry, after: entry });
|
|
656
776
|
const measured = await mapLimit(units, READ_CONCURRENCY, async (unit) => {
|
|
657
777
|
const renamed = unit.before !== unit.after;
|
|
778
|
+
const named = {
|
|
779
|
+
key: unit.after.key,
|
|
780
|
+
abs: unit.after.path,
|
|
781
|
+
root: unit.after.root,
|
|
782
|
+
...(renamed ? { oldAbs: unit.before.path, oldRoot: unit.before.root } : {}),
|
|
783
|
+
};
|
|
658
784
|
const now = current.get(unit.after.key);
|
|
659
785
|
const sig = [
|
|
660
786
|
unit.before.state,
|
|
@@ -667,22 +793,27 @@ async function baselineChanges(baselines, covered, unvouched) {
|
|
|
667
793
|
currentSig(current.get(unit.before.key)),
|
|
668
794
|
].join('|');
|
|
669
795
|
const cached = baselines.cache?.get(unit.key);
|
|
670
|
-
|
|
796
|
+
if (target && !target(unit.after) && !target(unit.before)) {
|
|
797
|
+
// Not measured: it names a file unless the cache knows it is unchanged.
|
|
798
|
+
const unchanged = cached?.sig === sig && (!cached.change || cached.change.hidden);
|
|
799
|
+
return unchanged ? null : { ...named, nameOnly: true };
|
|
800
|
+
}
|
|
801
|
+
// A file's own patch read measures again what was cached without its text.
|
|
802
|
+
let change = cached?.sig === sig && !(target && cached.stripped) ? cached.change : undefined;
|
|
671
803
|
if (change === undefined) {
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
804
|
+
const whole = await measureBaseline(unit.before, now, renamed, baselines.readBlob, budget);
|
|
805
|
+
const inline = inlineChange(whole);
|
|
806
|
+
// Once the budget is spent a diff may have been cut short to the
|
|
807
|
+
// replacement hunk: such a measurement is not kept, a later review
|
|
808
|
+
// measures it again.
|
|
809
|
+
if (budget.remainingMs > 0 && Buffer.byteLength(inline?.text || '', 'utf8') <= CACHED_PATCH_MAX_BYTES) {
|
|
810
|
+
baselines.cache?.set(unit.key, { sig, change: inline, ...(inline !== whole ? { stripped: true } : {}) });
|
|
675
811
|
}
|
|
812
|
+
change = target ? whole : inline;
|
|
676
813
|
}
|
|
677
814
|
if (change?.hidden) unvouched.add(unit.after.key);
|
|
678
815
|
if (!change || change.hidden) return null;
|
|
679
|
-
return {
|
|
680
|
-
key: unit.after.key,
|
|
681
|
-
abs: unit.after.path,
|
|
682
|
-
root: unit.after.root,
|
|
683
|
-
...(renamed ? { oldAbs: unit.before.path, oldRoot: unit.before.root } : {}),
|
|
684
|
-
change,
|
|
685
|
-
};
|
|
816
|
+
return { ...named, change };
|
|
686
817
|
});
|
|
687
818
|
return measured.filter(Boolean);
|
|
688
819
|
}
|
|
@@ -694,7 +825,7 @@ async function baselineChanges(baselines, covered, unvouched) {
|
|
|
694
825
|
* Also returns the baseline keys such older records touched: those baselines
|
|
695
826
|
* were first seen after an unrecorded edit.
|
|
696
827
|
*/
|
|
697
|
-
async function legacyChanges(records, { kinds, listed, covered, since }) {
|
|
828
|
+
async function legacyChanges(records, { kinds, listed, covered, since, budget }) {
|
|
698
829
|
const groups = new Map();
|
|
699
830
|
const late = new Set();
|
|
700
831
|
for (const record of records) {
|
|
@@ -747,7 +878,7 @@ async function legacyChanges(records, { kinds, listed, covered, since }) {
|
|
|
747
878
|
});
|
|
748
879
|
continue;
|
|
749
880
|
}
|
|
750
|
-
const measured = await measureLegacyChangeFile(file, group.root);
|
|
881
|
+
const measured = await measureLegacyChangeFile(file, group.root, budget);
|
|
751
882
|
const recordPatch = patchOf(measured);
|
|
752
883
|
const counts = (Number(measured.additions) || 0) + (Number(measured.deletions) || 0);
|
|
753
884
|
changes.push({
|
|
@@ -802,10 +933,14 @@ async function missingChanges(refs, { listed, covered }) {
|
|
|
802
933
|
* first state the session itself recorded; otherwise the result is `partial`.
|
|
803
934
|
* A file the user undid is back at its first state and is not listed. Each
|
|
804
935
|
* listed file carries an `id` (its absolute path); two roots sharing a
|
|
805
|
-
* relative name both show their absolute path.
|
|
936
|
+
* relative name both show their absolute path. A file's patch past the
|
|
937
|
+
* per-file cap, or past what the reply's total leaves, is left out
|
|
938
|
+
* (`patchOmitted`, reason PATCH_TOO_LARGE); `diffTooLarge` once nothing fit.
|
|
939
|
+
* `file` (an `id` or listed path) answers that one file's patch instead, up
|
|
940
|
+
* to the file-patch read's cap.
|
|
806
941
|
*/
|
|
807
|
-
export async function sessionChangeReview(base, { baselines = null, records = [] } = {}) {
|
|
808
|
-
const { source = '', reason: unavailableReason, owned, ...kept } = base || {};
|
|
942
|
+
export async function sessionChangeReview(base, { baselines = null, records = [], file: target = '' } = {}) {
|
|
943
|
+
const { source = '', reason: unavailableReason, owned, diffTooLarge: _baseTooLarge, ...kept } = base || {};
|
|
809
944
|
const gitBacked = source === 'git';
|
|
810
945
|
const baseRoot = clean(base?.root);
|
|
811
946
|
const covered = (abs) => gitBacked && Boolean(baseRoot) && insideDirectory(baseRoot, abs);
|
|
@@ -815,12 +950,28 @@ export async function sessionChangeReview(base, { baselines = null, records = []
|
|
|
815
950
|
else if (source === 'absent' || source === 'unavailable') kinds = new Set(['git', 'tracked']);
|
|
816
951
|
// Baselines nothing is listed for, yet whose emptiness cannot be vouched for.
|
|
817
952
|
const unvouched = new Set();
|
|
818
|
-
|
|
953
|
+
// One line-diff budget for the whole review pass.
|
|
954
|
+
const diffBudget = createLineDiffBudget();
|
|
955
|
+
// A file's own patch read measures only the baselines of that file (by
|
|
956
|
+
// `id` or by its name under its root).
|
|
957
|
+
const targetKey = clean(target) ? changePathKey(target) : '';
|
|
958
|
+
const targeted = (entry) =>
|
|
959
|
+
changePathKey(entry.path) === targetKey ||
|
|
960
|
+
(Boolean(entry.root) &&
|
|
961
|
+
insideDirectory(entry.root, entry.path) &&
|
|
962
|
+
changePathKey(relative(entry.root, entry.path)) === targetKey);
|
|
963
|
+
const baselineTarget = targetKey ? targeted : null;
|
|
964
|
+
const baselineUnits = baselines
|
|
965
|
+
? await baselineChanges(baselines, covered, unvouched, diffBudget, { target: baselineTarget })
|
|
966
|
+
: [];
|
|
967
|
+
// Units named but not measured still claim their names (see `show`).
|
|
968
|
+
const measured = baselineUnits.filter((unit) => !unit.nameOnly);
|
|
819
969
|
const legacy = await legacyChanges(Array.isArray(records) ? records : [], {
|
|
820
970
|
kinds,
|
|
821
971
|
listed,
|
|
822
972
|
covered,
|
|
823
973
|
since: Number(baselines?.createdAt) || Number.POSITIVE_INFINITY,
|
|
974
|
+
budget: diffBudget,
|
|
824
975
|
});
|
|
825
976
|
for (const change of legacy.changes) listed.add(change.key);
|
|
826
977
|
// Owned files of the non-Git root, and paths whose first state a clear in
|
|
@@ -846,7 +997,7 @@ export async function sessionChangeReview(base, { baselines = null, records = []
|
|
|
846
997
|
owners.set(key, new Set([...(owners.get(key) || []), changePathKey(abs)]));
|
|
847
998
|
};
|
|
848
999
|
for (const file of baseFiles) if (file?.path) claim(file.path, resolve(baseRoot, file.path));
|
|
849
|
-
for (const change of changes) {
|
|
1000
|
+
for (const change of [...changes, ...baselineUnits.filter((unit) => unit.nameOnly)]) {
|
|
850
1001
|
claim(nameOf(change.abs, change.root), change.abs);
|
|
851
1002
|
if (change.oldAbs) claim(nameOf(change.oldAbs, change.oldRoot), change.oldAbs);
|
|
852
1003
|
}
|
|
@@ -861,11 +1012,6 @@ export async function sessionChangeReview(base, { baselines = null, records = []
|
|
|
861
1012
|
let patch = '';
|
|
862
1013
|
if (change.text) patch = nameMeasuredPatch(change.text, oldName, path);
|
|
863
1014
|
else if (change.recordPatch && change.recordName === path) patch = change.recordPatch;
|
|
864
|
-
let patchOmitted = change.patchOmitted === true;
|
|
865
|
-
if (Buffer.byteLength(patch, 'utf8') > MERGED_PATCH_MAX_BYTES) {
|
|
866
|
-
patch = '';
|
|
867
|
-
patchOmitted = true;
|
|
868
|
-
}
|
|
869
1015
|
return {
|
|
870
1016
|
path,
|
|
871
1017
|
id: slashPath(abs),
|
|
@@ -878,7 +1024,8 @@ export async function sessionChangeReview(base, { baselines = null, records = []
|
|
|
878
1024
|
...(change.reason ? { reason: change.reason } : {}),
|
|
879
1025
|
...(change.baseline ? { baseline: change.baseline } : {}),
|
|
880
1026
|
...(change.unmeasured ? { unmeasured: true } : {}),
|
|
881
|
-
|
|
1027
|
+
// Its patch is past what can be kept or read: listed too large.
|
|
1028
|
+
...(change.patchOmitted === true && !patch ? { patchOmitted: true, reason: PATCH_TOO_LARGE } : {}),
|
|
882
1029
|
patch,
|
|
883
1030
|
};
|
|
884
1031
|
})
|
|
@@ -886,21 +1033,20 @@ export async function sessionChangeReview(base, { baselines = null, records = []
|
|
|
886
1033
|
if (left.path === right.path) return 0;
|
|
887
1034
|
return left.path < right.path ? -1 : 1;
|
|
888
1035
|
});
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
1036
|
+
if (clean(target)) {
|
|
1037
|
+
const key = changePathKey(target);
|
|
1038
|
+
const row = rows.find((entry) => changePathKey(entry.id) === key || changePathKey(entry.path) === key);
|
|
1039
|
+
if (row?.patchOmitted === true && !row.patch) return { ...filePatchReply(row.path, ''), ...patchOmittedFile({}) };
|
|
1040
|
+
return filePatchReply(row?.path || slashPath(target), row?.patch || '');
|
|
1041
|
+
}
|
|
1042
|
+
// The merged response stays bounded: a file past the per-file cap or the
|
|
1043
|
+
// total left is listed with its counts but without its diff.
|
|
1044
|
+
const budget = createReviewPatchBudget(MERGED_PATCH_MAX_BYTES - Buffer.byteLength(basePatch, 'utf8'));
|
|
893
1045
|
const files = [];
|
|
894
1046
|
const patches = [];
|
|
895
1047
|
for (const { patch, ...file } of rows) {
|
|
896
|
-
|
|
897
|
-
if (patch
|
|
898
|
-
budget -= size;
|
|
899
|
-
patches.push(patch);
|
|
900
|
-
} else if (patch) {
|
|
901
|
-
truncated = true;
|
|
902
|
-
file.patchOmitted = true;
|
|
903
|
-
}
|
|
1048
|
+
if (patch && budget.admit(Buffer.byteLength(patch, 'utf8'))) patches.push(patch);
|
|
1049
|
+
else if (patch) Object.assign(file, patchOmittedFile(file));
|
|
904
1050
|
files.push(file);
|
|
905
1051
|
}
|
|
906
1052
|
// A baseline first seen after an older recorded edit (`late`) was not the
|
|
@@ -917,6 +1063,7 @@ export async function sessionChangeReview(base, { baselines = null, records = []
|
|
|
917
1063
|
const all = [...baseFiles, ...files];
|
|
918
1064
|
// An unavailable Git baseline with nothing else to list stays unavailable.
|
|
919
1065
|
if (all.length === 0 && !vouched && kept.supported === false) return { ...kept, reason: unavailableReason };
|
|
1066
|
+
const patch = [basePatch, ...patches].filter(Boolean).join(basePatch.endsWith('\n') || !basePatch ? '' : '\n');
|
|
920
1067
|
return {
|
|
921
1068
|
...kept,
|
|
922
1069
|
supported: true,
|
|
@@ -926,18 +1073,33 @@ export async function sessionChangeReview(base, { baselines = null, records = []
|
|
|
926
1073
|
...(partial ? { partial: true } : {}),
|
|
927
1074
|
...(baselines?.unsaved === true ? { baselinesUnsaved: true } : {}),
|
|
928
1075
|
files: all,
|
|
929
|
-
patch
|
|
930
|
-
patchTruncated:
|
|
1076
|
+
patch,
|
|
1077
|
+
patchTruncated: gitBacked && kept.patchTruncated === true,
|
|
1078
|
+
...(reviewDiffTooLarge(all, patch) ? { diffTooLarge: true } : {}),
|
|
931
1079
|
snapshotKind: kept.snapshotKind || 'session',
|
|
932
1080
|
};
|
|
933
1081
|
}
|
|
934
1082
|
|
|
935
1083
|
// ── Apply ───────────────────────────────────────────────────────────────────
|
|
936
1084
|
|
|
937
|
-
/** Every path a stored patch touches must be exactly the recorded file's.
|
|
1085
|
+
/** Every path a stored patch touches must be exactly the recorded file's.
|
|
1086
|
+
* Several sections are the file's own segments in write order: each starts
|
|
1087
|
+
* where the one before ended (a foreign edit in between stays out of both),
|
|
1088
|
+
* from the recorded old path to its current one. Resolves to the sections. */
|
|
938
1089
|
function assertPatchMatchesFile(file, buffer) {
|
|
939
1090
|
const sections = splitPatchSections(buffer);
|
|
940
|
-
if (sections.length
|
|
1091
|
+
if (sections.length === 0) throw new Error(`${file.path} has a malformed recorded patch`);
|
|
1092
|
+
const mismatch = () => new Error(`${file.path} has a recorded patch for a different path`);
|
|
1093
|
+
if (sections.length > 1) {
|
|
1094
|
+
let at = file.oldPath || file.path;
|
|
1095
|
+
for (const { oldPath, newPath } of sections) {
|
|
1096
|
+
if ([oldPath, newPath].some((path) => path !== null && !safeChangePath(path))) throw mismatch();
|
|
1097
|
+
if ((oldPath ?? newPath) !== at) throw mismatch();
|
|
1098
|
+
at = newPath ?? oldPath;
|
|
1099
|
+
}
|
|
1100
|
+
if (at !== file.path) throw mismatch();
|
|
1101
|
+
return sections;
|
|
1102
|
+
}
|
|
941
1103
|
const { oldPath, newPath } = sections[0];
|
|
942
1104
|
const expectedOld = file.status === 'A' ? null : file.oldPath || file.path;
|
|
943
1105
|
const expectedNew = file.status === 'D' ? null : file.path;
|
|
@@ -945,10 +1107,9 @@ function assertPatchMatchesFile(file, buffer) {
|
|
|
945
1107
|
[oldPath, expectedOld],
|
|
946
1108
|
[newPath, expectedNew],
|
|
947
1109
|
]) {
|
|
948
|
-
if (expected === null ? actual !== null : actual !== expected || !safeChangePath(actual))
|
|
949
|
-
throw new Error(`${file.path} has a recorded patch for a different path`);
|
|
950
|
-
}
|
|
1110
|
+
if (expected === null ? actual !== null : actual !== expected || !safeChangePath(actual)) throw mismatch();
|
|
951
1111
|
}
|
|
1112
|
+
return sections;
|
|
952
1113
|
}
|
|
953
1114
|
|
|
954
1115
|
/** The recorded root must still be the directory (and, for a Git record, the
|
|
@@ -989,13 +1150,21 @@ export async function applyTurnChangeFiles(record, files, { reverse }) {
|
|
|
989
1150
|
}
|
|
990
1151
|
const buffer = changePatchBuffer(file);
|
|
991
1152
|
if (!buffer?.length) throw new Error(`${file.path} has no recorded patch`);
|
|
992
|
-
assertPatchMatchesFile(file, buffer);
|
|
993
|
-
|
|
1153
|
+
const sections = assertPatchMatchesFile(file, buffer);
|
|
1154
|
+
// `git apply` takes a file's sections in input order, each on the result
|
|
1155
|
+
// of the one before: oldest first forward, newest first for an Undo.
|
|
1156
|
+
return Buffer.concat(
|
|
1157
|
+
(reverse ? [...sections].reverse() : sections).map(({ patch }) =>
|
|
1158
|
+
patch.at(-1) === 0x0a ? patch : Buffer.concat([patch, Buffer.from('\n')])
|
|
1159
|
+
)
|
|
1160
|
+
);
|
|
994
1161
|
});
|
|
995
|
-
//
|
|
996
|
-
//
|
|
997
|
-
//
|
|
998
|
-
|
|
1162
|
+
// An older Git record (worktree diff) replays with the repository's own
|
|
1163
|
+
// line-ending conversion, the semantics the shadow snapshot hashed with. A
|
|
1164
|
+
// record of the session's own tool bytes (`counts: 'own'`, any kind) holds
|
|
1165
|
+
// raw bytes, so nothing may convert them.
|
|
1166
|
+
const rawBytes = record.kind !== 'git' || record.counts === 'own';
|
|
1167
|
+
const conversion = rawBytes ? ['-c', 'core.autocrlf=false', '-c', 'core.eol=lf'] : [];
|
|
999
1168
|
const args = [
|
|
1000
1169
|
...conversion,
|
|
1001
1170
|
'-c',
|