mixdog 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -5
- package/package.json +1 -1
- package/scripts/gate-local.mjs +19 -3
- package/scripts/model-catalog-audit.mjs +1 -15
- package/src/agents/reviewer/AGENT.md +3 -3
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +5 -0
- package/src/defaults/skills/pptx/SKILL.md +6 -6
- package/src/defaults/skills/pptx/references/review.md +6 -4
- package/src/defaults/skills/pptx/scripts/source-extract.mjs +1 -1
- package/src/defaults/skills/setup/references/actions.md +13 -3
- package/src/defaults/skills/visualize/SKILL.md +12 -9
- package/src/repl/slash-commands.mjs +16 -1
- package/src/rules/shared/60-verification.md +3 -1
- package/src/rules/shared/70-delivery.md +4 -2
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -4
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +10 -0
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +26 -5
- package/src/runtime/agent/orchestrator/config.mjs +10 -4
- package/src/runtime/agent/orchestrator/context/collect.mjs +2 -1
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +11 -5
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +74 -21
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +122 -15
- package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +54 -11
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +104 -9
- package/src/runtime/agent/orchestrator/mcp/client.mjs +358 -140
- package/src/runtime/agent/orchestrator/mcp/lazy-output-validator.mjs +25 -0
- 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/mcp/plugin-placeholders.mjs +54 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +294 -44
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +94 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +96 -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 +25 -21
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +3 -1
- 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 +73 -35
- 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.mjs +8 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +53 -18
- 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 +30 -14
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +93 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +82 -9
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +337 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-tokens.mjs +159 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +447 -0
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +38 -5
- 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 +102 -23
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +103 -33
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +29 -6
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +18 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -4
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +86 -19
- package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +29 -8
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +191 -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-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 +21 -82
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +71 -12
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +21 -20
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +97 -51
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +68 -19
- package/src/runtime/agent/orchestrator/providers/lib/gemini-model-catalog.mjs +7 -1
- 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-bridge.mjs +1080 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +15 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +35 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +4 -9
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +12 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +6 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +5 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +22 -0
- 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 +6 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +23 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +16 -8
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +94 -13
- 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 +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +6 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +23 -14
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +26 -6
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +42 -25
- 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/terminal-frames.mjs +18 -11
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +1 -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 +2 -3
- 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-oauth-dispatch.mjs +34 -3
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +22 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +5 -9
- package/src/runtime/agent/orchestrator/providers/openai-retry-policy.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-handshake.mjs +16 -8
- 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-terminal.mjs +18 -11
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +35 -24
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +581 -0
- package/src/runtime/agent/orchestrator/providers/registry.mjs +35 -9
- package/src/runtime/agent/orchestrator/providers/retry-backoff.mjs +46 -7
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +118 -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/runtime-core/config-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +15 -55
- package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +15 -2
- package/src/runtime/agent/orchestrator/runtime-core/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 +268 -181
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +21 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +54 -3
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +284 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +270 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/sqlite-gate.mjs +27 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +628 -0
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +184 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +136 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +128 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +127 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +101 -0
- package/src/runtime/agent/orchestrator/session/explicit-skills.mjs +83 -5
- package/src/runtime/agent/orchestrator/session/imported-message.mjs +11 -0
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -4
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +102 -18
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +42 -5
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +14 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +20 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +50 -23
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +22 -14
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +18 -7
- package/src/runtime/agent/orchestrator/session/manager.mjs +0 -1
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +155 -29
- package/src/runtime/agent/orchestrator/session/store/listing.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +6 -0
- 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-catalog.mjs +819 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +22 -12
- package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +158 -0
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +183 -374
- package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +41 -3
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +38 -17
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +12 -15
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +17 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -0
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +5 -5
- package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +6 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +173 -22
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +8 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +5 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +15 -2
- package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +13 -10
- package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +17 -12
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/apply-patch/codex-batch.mjs +4 -4
- package/src/runtime/agent/orchestrator/tools/patch/apply-patch/route.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/read-redirects.mjs +34 -30
- package/src/runtime/agent/orchestrator/tools/patch/sequence/units.mjs +7 -7
- package/src/runtime/agent/orchestrator/tools/patch/sequence.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +4 -0
- package/src/runtime/attachments/store.d.mts +3 -0
- package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +1 -1
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +16 -4
- package/src/runtime/channels/lib/worker-main.mjs +17 -14
- package/src/runtime/computer-bridge/linux-readiness.mjs +0 -2
- package/src/runtime/effort-judge/judge-client.mjs +56 -18
- package/src/runtime/memory/lib/memory.mjs +1 -1
- package/src/runtime/memory/lib/pg/process.mjs +34 -24
- package/src/runtime/memory/lib/pg/supervisor.mjs +16 -13
- package/src/runtime/memory/lib/session-ingest.mjs +2 -2
- package/src/runtime/office/README.md +1 -1
- package/src/runtime/office/shared/values.mjs +0 -5
- package/src/runtime/shared/atomic-file.mjs +25 -4
- package/src/runtime/shared/background-tasks.mjs +92 -14
- package/src/runtime/shared/err-text.mjs +25 -0
- package/src/runtime/shared/error-presentation.mjs +159 -19
- package/src/runtime/shared/extension-scopes.mjs +5 -3
- package/src/runtime/shared/file-lock.mjs +37 -11
- package/src/runtime/shared/llm/anthropic-betas.mjs +4 -3
- package/src/runtime/shared/llm/anthropic-effort.mjs +134 -131
- package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +50 -14
- package/src/runtime/shared/llm/model-catalog.mjs +53 -52
- package/src/runtime/shared/llm/openai-daybreak.mjs +4 -16
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +17 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +13 -4
- package/src/runtime/shared/llm/usage-rollup.mjs +0 -1
- package/src/runtime/shared/model-display.mjs +13 -0
- package/src/runtime/shared/plugin-manifest.mjs +18 -9
- package/src/runtime/shared/pristine-execution-contract.json +9 -2
- package/src/runtime/shared/pristine-execution.mjs +28 -4
- package/src/runtime/shared/provider-accounts.mjs +124 -20
- package/src/runtime/shared/provider-api-key.mjs +12 -0
- package/src/runtime/shared/quota-resume-store.mjs +11 -0
- package/src/runtime/shared/session-baseline-store.mjs +960 -0
- package/src/runtime/shared/shell-display.mjs +9 -3
- package/src/runtime/shared/skill-mentions.d.mts +10 -0
- package/src/runtime/shared/skill-mentions.mjs +133 -0
- package/src/runtime/shared/skill-script-runtime.mjs +264 -0
- package/src/runtime/shared/statusline/statusline-format.mjs +4 -4
- package/src/runtime/shared/task-notification-envelope.mjs +2 -2
- package/src/runtime/shared/tool-primitives.mjs +35 -2
- package/src/runtime/shared/turn-changes.mjs +447 -219
- package/src/runtime/shared/turn-snapshot-store.mjs +182 -1
- package/src/runtime/shared/turn-snapshot.mjs +170 -48
- package/src/runtime/shared/turn-worktree-snapshot.mjs +160 -51
- package/src/runtime/shared/worker-requests.mjs +15 -2
- package/src/runtime/shared/worktrees/contract.mjs +0 -24
- package/src/runtime/shared/worktrees/test-support.mjs +19 -4
- package/src/session-runtime/automation-agents.mjs +8 -2
- package/src/session-runtime/boot/apis.mjs +61 -0
- package/src/session-runtime/boot/config.mjs +5 -2
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/infrastructure.mjs +35 -18
- package/src/session-runtime/conversation-import/discovery.mjs +698 -0
- package/src/session-runtime/conversation-import/service.mjs +369 -0
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +10 -5
- package/src/session-runtime/cwd-plugins/plugin-status.mjs +47 -42
- package/src/session-runtime/lifecycle/session-catalog.mjs +2 -0
- package/src/session-runtime/lifecycle/teardown.mjs +1 -1
- package/src/session-runtime/mcp-glue/connect.mjs +83 -16
- package/src/session-runtime/mcp-glue/plugin-servers.mjs +499 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +135 -33
- package/src/session-runtime/mcp-glue.mjs +25 -2
- 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 +83 -15
- 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/new-session-config.mjs +3 -2
- package/src/session-runtime/notification-bus.mjs +9 -2
- package/src/session-runtime/provider-auth/accounts.mjs +33 -15
- package/src/session-runtime/provider-models/model-meta.mjs +12 -3
- package/src/session-runtime/provider-models/web-search-catalog.mjs +5 -1
- package/src/session-runtime/provider-readiness.mjs +16 -10
- package/src/session-runtime/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 +24 -5
- package/src/session-runtime/resource-mcp-api.mjs +198 -78
- package/src/session-runtime/resource-plugins-api.mjs +29 -41
- package/src/session-runtime/resource-scope-decorate.mjs +6 -8
- package/src/session-runtime/resource-skills-api.mjs +23 -2
- package/src/session-runtime/runtime-review-api.mjs +13 -0
- package/src/session-runtime/schedule-session-run.mjs +1 -1
- 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/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/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-rows.mjs +17 -0
- package/src/session-runtime/services/channel-session-router.mjs +4 -1
- package/src/session-runtime/services/hook-bus/command-handler.mjs +4 -1
- package/src/session-runtime/services/hook-bus/handlers.mjs +7 -3
- package/src/session-runtime/services/provider-admin.mjs +64 -18
- package/src/session-runtime/services/usage-dashboard-model.mjs +3 -0
- package/src/session-runtime/settings-compaction-api.mjs +1 -0
- package/src/session-runtime/setup-tool/executor.mjs +12 -1
- package/src/session-runtime/setup-tool/extended-actions.mjs +1 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +1 -0
- package/src/session-runtime/setup-tool/tool-defs.mjs +7 -1
- package/src/session-runtime/skills-api.mjs +7 -3
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/webhook-session-run.mjs +16 -4
- package/src/skill-script-entry.mjs +36 -0
- package/src/standalone/daemon-drain-policy.mjs +8 -0
- package/src/standalone/daemon-stored-session-views.mjs +11 -3
- package/src/standalone/daemon-telemetry.mjs +55 -0
- package/src/standalone/daemon.mjs +44 -11
- package/src/standalone/session-protocol.mjs +12 -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 +6 -1
- package/src/standalone/session-service-api.mjs +5 -0
- package/src/standalone/session-service.mjs +1 -0
- package/src/tui/App.jsx +9 -1
- package/src/tui/app/app-view/floating-panel.jsx +9 -1
- package/src/tui/app/app-view.jsx +7 -0
- package/src/tui/app/create-app-pickers.mjs +4 -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/plugins-pickers.mjs +35 -16
- package/src/tui/app/extension-pickers.mjs +2 -1
- package/src/tui/app/model-options.mjs +13 -16
- package/src/tui/app/skill-mention-palette.mjs +88 -0
- package/src/tui/app/slash-commands.mjs +7 -2
- package/src/tui/app/slash-dispatch/panel-commands.mjs +16 -1
- package/src/tui/app/slash-palette.mjs +23 -7
- package/src/tui/app/transcript-row-estimate.mjs +11 -3
- package/src/tui/app/use-prompt-draft-flow.mjs +7 -2
- package/src/tui/app/use-prompt-state.mjs +5 -0
- package/src/tui/components/Message.jsx +22 -1
- package/src/tui/components/PromptInput.jsx +21 -3
- package/src/tui/components/SlashCommandPalette.jsx +12 -3
- package/src/tui/components/StatusLine.jsx +2 -0
- package/src/tui/components/TranscriptItem.jsx +9 -1
- package/src/tui/components/prompt-input/key-handler.mjs +21 -8
- 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/components/user-message-skills.mjs +38 -0
- package/src/tui/dist/index.mjs +1323 -214
- package/src/tui/session/queue-helpers.mjs +7 -2
- package/src/tui/session/quota-resume.mjs +46 -14
- package/src/tui/session/session-api/commands.mjs +33 -24
- package/src/tui/session/session-api/extensions.mjs +26 -2
- package/src/tui/session/session-api/integrations.mjs +7 -0
- package/src/tui/session/session-api/lifecycle.mjs +5 -1
- package/src/tui/session/session-api/routes.mjs +71 -7
- package/src/tui/session/session-api/settings.mjs +12 -14
- package/src/tui/session/session-flow/drain.mjs +21 -5
- package/src/tui/session/session-flow/failed-turn-rewind.mjs +10 -4
- package/src/tui/session/tui-steering-persist.mjs +25 -9
- package/src/tui/session/turn.mjs +55 -15
- 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/runtime/effort-judge/previous-human-request.mjs +0 -162
- package/src/runtime/effort-judge/verified-context-input.mjs +0 -10
- package/src/runtime/memory/lib/memory-session-merge.mjs +0 -32
- package/src/runtime/shared/llm/usage-session-history.mjs +0 -266
|
@@ -19,6 +19,15 @@ const READ_RANGE_INDEX_SWEEP_CONCURRENCY = 8;
|
|
|
19
19
|
const READ_RANGE_INDEX_CACHE = new Map();
|
|
20
20
|
const READ_RANGE_INDEX_DRAFTS = new WeakMap();
|
|
21
21
|
const READ_RANGE_INDEX_PERSIST_PENDING = new Map();
|
|
22
|
+
const READ_RANGE_INDEX_INFLIGHT = new Map();
|
|
23
|
+
const READ_RANGE_INDEX_LAST_PERSISTED = new Map();
|
|
24
|
+
// key -> outstanding deletes whose unlink / cancelled write has not settled.
|
|
25
|
+
const READ_RANGE_INDEX_DELETING = new Map();
|
|
26
|
+
let readRangeIndexDeleteSeq = 0;
|
|
27
|
+
const READ_RANGE_INDEX_LAST_PERSISTED_MAX = 256;
|
|
28
|
+
const READ_RANGE_INDEX_WRITE_CONCURRENCY = 2;
|
|
29
|
+
const READ_RANGE_INDEX_WRITE_WAITERS = [];
|
|
30
|
+
let readRangeIndexWritesActive = 0;
|
|
22
31
|
let readRangeIndexDiskSwept = false;
|
|
23
32
|
|
|
24
33
|
let traceReadRangeIndex = () => {};
|
|
@@ -99,7 +108,9 @@ async function computePrefixHashForIndex(fullPath, st, handle = null, prefixBuff
|
|
|
99
108
|
if (!handle) {
|
|
100
109
|
try {
|
|
101
110
|
await fh.close();
|
|
102
|
-
} catch {
|
|
111
|
+
} catch {
|
|
112
|
+
/* close failure after a completed read is irrelevant */
|
|
113
|
+
}
|
|
103
114
|
}
|
|
104
115
|
}
|
|
105
116
|
} catch {
|
|
@@ -123,14 +134,21 @@ async function loadReadRangeIndexFromDisk(fullPath, st, handle, prefixBuffer) {
|
|
|
123
134
|
// No existsSync preflight: a missing file surfaces as an ENOENT from
|
|
124
135
|
// readFile below, caught by the same try/catch — one FS pass, not two.
|
|
125
136
|
if (!file || !st) return null;
|
|
137
|
+
// A delete wins over any disk content: while a cancelled write may still be
|
|
138
|
+
// landing the file is invisible, and a read that straddled a delete is void.
|
|
139
|
+
const key = canonicalCachePath(fullPath);
|
|
140
|
+
const deleteSeq = readRangeIndexDeleteSeq;
|
|
141
|
+
const deleted = () => READ_RANGE_INDEX_DELETING.has(key) || readRangeIndexDeleteSeq !== deleteSeq;
|
|
142
|
+
if (deleted()) return null;
|
|
126
143
|
try {
|
|
127
144
|
const row = JSON.parse(await readFile(file, 'utf-8'));
|
|
128
|
-
if (!readRangeIndexMatches(row, fullPath, st)) return null;
|
|
145
|
+
if (deleted() || !readRangeIndexMatches(row, fullPath, st)) return null;
|
|
129
146
|
// The prefix is an extra check, not proof that later byte offsets survived.
|
|
130
147
|
if (typeof row.prefixHash === 'string' && row.prefixHash) {
|
|
131
148
|
const cur = await computePrefixHashForIndex(fullPath, st, handle, prefixBuffer);
|
|
132
149
|
if (!cur || cur !== row.prefixHash) return null;
|
|
133
150
|
}
|
|
151
|
+
if (deleted()) return null;
|
|
134
152
|
const anchors = new Map([[0, 0]]);
|
|
135
153
|
for (const entry of row.anchors) {
|
|
136
154
|
if (!Array.isArray(entry) || entry.length < 2) continue;
|
|
@@ -161,35 +179,133 @@ function currentReadRangeIndex(index) {
|
|
|
161
179
|
return !!index?.published && READ_RANGE_INDEX_CACHE.get(canonicalCachePath(index.fullPath)) === index;
|
|
162
180
|
}
|
|
163
181
|
|
|
164
|
-
function
|
|
182
|
+
function rememberPersisted(key, text) {
|
|
183
|
+
READ_RANGE_INDEX_LAST_PERSISTED.delete(key);
|
|
184
|
+
READ_RANGE_INDEX_LAST_PERSISTED.set(key, text);
|
|
185
|
+
if (READ_RANGE_INDEX_LAST_PERSISTED.size > READ_RANGE_INDEX_LAST_PERSISTED_MAX) {
|
|
186
|
+
READ_RANGE_INDEX_LAST_PERSISTED.delete(READ_RANGE_INDEX_LAST_PERSISTED.keys().next().value);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// job = { index, row }: row is a pre-serialised evicted row (index no longer cached).
|
|
191
|
+
// Returns false only when a write was needed but failed (e.g. lock contended).
|
|
192
|
+
function persistReadRangeIndexSync(job) {
|
|
193
|
+
const { index, row: evictedRow } = job;
|
|
165
194
|
const file = readRangeIndexFilePath(index?.fullPath);
|
|
166
|
-
if (!file || !currentReadRangeIndex(index)) return;
|
|
195
|
+
if (!file || (!evictedRow && !currentReadRangeIndex(index))) return true;
|
|
167
196
|
try {
|
|
168
|
-
if (!sameFileVersion(index.fileVersion, statSync(index.fullPath))) return;
|
|
169
|
-
const row = serialiseReadRangeIndex(index);
|
|
170
|
-
if (row)
|
|
171
|
-
|
|
197
|
+
if (!sameFileVersion(evictedRow?.fileVersion || index.fileVersion, statSync(index.fullPath))) return true;
|
|
198
|
+
const row = evictedRow || serialiseReadRangeIndex(index);
|
|
199
|
+
if (!row) return true;
|
|
200
|
+
const key = canonicalCachePath(index.fullPath);
|
|
201
|
+
const text = JSON.stringify(row);
|
|
202
|
+
if (READ_RANGE_INDEX_LAST_PERSISTED.get(key) === text) return true;
|
|
203
|
+
writeJsonAtomicSync(file, row, { compact: true, lock: true, fsync: false });
|
|
204
|
+
rememberPersisted(key, text);
|
|
205
|
+
return true;
|
|
206
|
+
} catch {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
172
209
|
}
|
|
173
210
|
|
|
174
|
-
|
|
211
|
+
function acquireReadRangeIndexWriteSlot() {
|
|
212
|
+
if (readRangeIndexWritesActive < READ_RANGE_INDEX_WRITE_CONCURRENCY) {
|
|
213
|
+
readRangeIndexWritesActive += 1;
|
|
214
|
+
return Promise.resolve();
|
|
215
|
+
}
|
|
216
|
+
return new Promise((resolve) => READ_RANGE_INDEX_WRITE_WAITERS.push(resolve));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function releaseReadRangeIndexWriteSlot() {
|
|
220
|
+
const next = READ_RANGE_INDEX_WRITE_WAITERS.shift();
|
|
221
|
+
if (next) next();
|
|
222
|
+
else readRangeIndexWritesActive -= 1;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// One write attempt. `state.epoch` changes when the path is deleted: a write
|
|
226
|
+
// that straddles a delete removes what it just wrote instead of resurrecting it.
|
|
227
|
+
async function persistReadRangeIndexOnce(key, job, state) {
|
|
228
|
+
const { index, row: evictedRow } = job;
|
|
175
229
|
const file = readRangeIndexFilePath(index?.fullPath);
|
|
176
230
|
if (!file || (!evictedRow && !currentReadRangeIndex(index))) return;
|
|
231
|
+
const epoch = state.epoch;
|
|
232
|
+
// Admission precedes every stat/lock so waiting writers hold no file lock.
|
|
233
|
+
await acquireReadRangeIndexWriteSlot();
|
|
177
234
|
try {
|
|
235
|
+
if (state.epoch !== epoch || (!evictedRow && !currentReadRangeIndex(index))) return;
|
|
178
236
|
if (!sameFileVersion(evictedRow?.fileVersion || index.fileVersion, await stat(index.fullPath))) return;
|
|
179
237
|
await mkdir(READ_RANGE_INDEX_DISK_DIR, { recursive: true });
|
|
180
|
-
if (!evictedRow && !currentReadRangeIndex(index)) return;
|
|
238
|
+
if (state.epoch !== epoch || (!evictedRow && !currentReadRangeIndex(index))) return;
|
|
181
239
|
const row = evictedRow || serialiseReadRangeIndex(index);
|
|
182
|
-
if (row)
|
|
183
|
-
|
|
240
|
+
if (!row) return;
|
|
241
|
+
const text = JSON.stringify(row);
|
|
242
|
+
if (READ_RANGE_INDEX_LAST_PERSISTED.get(key) === text) return;
|
|
243
|
+
readRangeIndexPersistStats.concurrent += 1;
|
|
244
|
+
readRangeIndexPersistStats.maxConcurrent = Math.max(
|
|
245
|
+
readRangeIndexPersistStats.maxConcurrent,
|
|
246
|
+
readRangeIndexPersistStats.concurrent
|
|
247
|
+
);
|
|
248
|
+
try {
|
|
249
|
+
await writeJsonAtomicAsync(file, row, { compact: true, lock: true, fsync: false });
|
|
250
|
+
readRangeIndexPersistStats.writes += 1;
|
|
251
|
+
} finally {
|
|
252
|
+
readRangeIndexPersistStats.concurrent -= 1;
|
|
253
|
+
}
|
|
254
|
+
if (state.epoch !== epoch) {
|
|
255
|
+
await unlink(file).catch(() => {});
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
rememberPersisted(key, text);
|
|
259
|
+
} catch {
|
|
260
|
+
/* persisting the index is best-effort */
|
|
261
|
+
} finally {
|
|
262
|
+
releaseReadRangeIndexWriteSlot();
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Single-flight per cache file: a request during an in-flight write only
|
|
267
|
+
// replaces the pending job; one follow-up write persists the latest state.
|
|
268
|
+
function requestReadRangeIndexPersist(key, job) {
|
|
269
|
+
const state = READ_RANGE_INDEX_INFLIGHT.get(key);
|
|
270
|
+
if (state) {
|
|
271
|
+
state.next = job;
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
const fresh = { epoch: 0, next: null, cancelWaiters: [] };
|
|
275
|
+
READ_RANGE_INDEX_INFLIGHT.set(key, fresh);
|
|
276
|
+
const settleCancelled = () => {
|
|
277
|
+
for (const resolve of fresh.cancelWaiters.splice(0)) resolve();
|
|
278
|
+
};
|
|
279
|
+
void (async () => {
|
|
280
|
+
try {
|
|
281
|
+
let cur = job;
|
|
282
|
+
while (cur) {
|
|
283
|
+
await persistReadRangeIndexOnce(key, cur, fresh);
|
|
284
|
+
// A cancelled write has finished (and cleaned up) once Once returns.
|
|
285
|
+
settleCancelled();
|
|
286
|
+
cur = fresh.next;
|
|
287
|
+
fresh.next = null;
|
|
288
|
+
}
|
|
289
|
+
} finally {
|
|
290
|
+
settleCancelled();
|
|
291
|
+
READ_RANGE_INDEX_INFLIGHT.delete(key);
|
|
292
|
+
}
|
|
293
|
+
})();
|
|
184
294
|
}
|
|
185
295
|
|
|
186
296
|
export function scheduleReadRangeIndexPersist(index) {
|
|
187
297
|
if (!READ_RANGE_INDEX_DISK_DIR || !currentReadRangeIndex(index)) return;
|
|
188
298
|
const key = canonicalCachePath(index.fullPath);
|
|
299
|
+
const inflight = READ_RANGE_INDEX_INFLIGHT.get(key);
|
|
300
|
+
if (inflight) {
|
|
301
|
+
inflight.next = { index, row: null };
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
189
304
|
if (READ_RANGE_INDEX_PERSIST_PENDING.has(key)) return;
|
|
190
305
|
const t = setTimeout(() => {
|
|
191
306
|
READ_RANGE_INDEX_PERSIST_PENDING.delete(key);
|
|
192
|
-
|
|
307
|
+
const latest = READ_RANGE_INDEX_CACHE.get(key);
|
|
308
|
+
if (latest) requestReadRangeIndexPersist(key, { index: latest, row: null });
|
|
193
309
|
}, READ_RANGE_INDEX_PERSIST_DEBOUNCE_MS);
|
|
194
310
|
t.unref();
|
|
195
311
|
READ_RANGE_INDEX_PERSIST_PENDING.set(key, t);
|
|
@@ -199,10 +315,19 @@ export function flushReadRangeIndexesSync() {
|
|
|
199
315
|
for (const [key, timer] of READ_RANGE_INDEX_PERSIST_PENDING) {
|
|
200
316
|
try {
|
|
201
317
|
clearTimeout(timer);
|
|
202
|
-
} catch {
|
|
318
|
+
} catch {
|
|
319
|
+
/* a timer that cannot be cleared must not block the flush */
|
|
320
|
+
}
|
|
203
321
|
READ_RANGE_INDEX_PERSIST_PENDING.delete(key);
|
|
204
322
|
const index = READ_RANGE_INDEX_CACHE.get(key);
|
|
205
|
-
if (index) persistReadRangeIndexSync(index);
|
|
323
|
+
if (index) persistReadRangeIndexSync({ index, row: null });
|
|
324
|
+
}
|
|
325
|
+
// Writes queued behind an in-flight one are still pending state at exit.
|
|
326
|
+
for (const state of READ_RANGE_INDEX_INFLIGHT.values()) {
|
|
327
|
+
// Keep the job unless it was durably handled: when the async writer holds
|
|
328
|
+
// the lock, its follow-up still persists it if the process keeps running.
|
|
329
|
+
const job = state.next;
|
|
330
|
+
if (job && persistReadRangeIndexSync(job) && state.next === job) state.next = null;
|
|
206
331
|
}
|
|
207
332
|
}
|
|
208
333
|
|
|
@@ -213,11 +338,32 @@ function dropReadRangeIndexSlot(key) {
|
|
|
213
338
|
}
|
|
214
339
|
|
|
215
340
|
export function deleteReadRangeIndexForPath(fullPath) {
|
|
216
|
-
|
|
341
|
+
const key = canonicalCachePath(fullPath);
|
|
342
|
+
dropReadRangeIndexSlot(key);
|
|
343
|
+
READ_RANGE_INDEX_LAST_PERSISTED.delete(key);
|
|
344
|
+
readRangeIndexDeleteSeq += 1;
|
|
345
|
+
// Disk loads for this path are void until the unlink and any cancelled
|
|
346
|
+
// in-flight write (which removes its own output) have settled.
|
|
347
|
+
READ_RANGE_INDEX_DELETING.set(key, (READ_RANGE_INDEX_DELETING.get(key) || 0) + 1);
|
|
348
|
+
const inflight = READ_RANGE_INDEX_INFLIGHT.get(key);
|
|
349
|
+
let cancelled = Promise.resolve();
|
|
350
|
+
if (inflight) {
|
|
351
|
+
inflight.epoch += 1;
|
|
352
|
+
inflight.next = null;
|
|
353
|
+
cancelled = new Promise((resolve) => inflight.cancelWaiters.push(resolve));
|
|
354
|
+
}
|
|
217
355
|
const file = readRangeIndexFilePath(fullPath);
|
|
218
|
-
|
|
356
|
+
const unlinked = file ? unlink(file).catch(() => {}) : Promise.resolve();
|
|
357
|
+
void Promise.all([unlinked, cancelled]).then(() => {
|
|
358
|
+
const left = (READ_RANGE_INDEX_DELETING.get(key) || 1) - 1;
|
|
359
|
+
if (left > 0) READ_RANGE_INDEX_DELETING.set(key, left);
|
|
360
|
+
else READ_RANGE_INDEX_DELETING.delete(key);
|
|
361
|
+
});
|
|
219
362
|
}
|
|
220
363
|
|
|
364
|
+
// Test observability for write coalescing and the concurrency cap.
|
|
365
|
+
export const readRangeIndexPersistStats = { writes: 0, concurrent: 0, maxConcurrent: 0 };
|
|
366
|
+
|
|
221
367
|
export async function sweepStaleReadRangeIndexes(directory = READ_RANGE_INDEX_DISK_DIR) {
|
|
222
368
|
if (!directory) return;
|
|
223
369
|
let entries;
|
|
@@ -235,8 +381,14 @@ export async function sweepStaleReadRangeIndexes(directory = READ_RANGE_INDEX_DI
|
|
|
235
381
|
const full = join(directory, name);
|
|
236
382
|
try {
|
|
237
383
|
const st = await stat(full);
|
|
238
|
-
if (now - st.mtimeMs > READ_RANGE_INDEX_DISK_STALE_MS)
|
|
239
|
-
|
|
384
|
+
if (now - st.mtimeMs > READ_RANGE_INDEX_DISK_STALE_MS) {
|
|
385
|
+
await unlink(full);
|
|
386
|
+
// A removed file invalidates the unchanged-content skip.
|
|
387
|
+
READ_RANGE_INDEX_LAST_PERSISTED.clear();
|
|
388
|
+
}
|
|
389
|
+
} catch {
|
|
390
|
+
/* best-effort sweep: a file that vanished or cannot be removed is skipped */
|
|
391
|
+
}
|
|
240
392
|
}
|
|
241
393
|
}
|
|
242
394
|
await Promise.all(Array.from({ length: Math.min(READ_RANGE_INDEX_SWEEP_CONCURRENCY, entries.length) }, worker));
|
|
@@ -255,7 +407,7 @@ function refreshReadRangeIndexSlot(key, index) {
|
|
|
255
407
|
// their slot immediately. Disk IO must not delay the foreground lookup.
|
|
256
408
|
const row = serialiseReadRangeIndex(evicted);
|
|
257
409
|
dropReadRangeIndexSlot(oldest);
|
|
258
|
-
if (row)
|
|
410
|
+
if (row) requestReadRangeIndexPersist(oldest, { index: evicted, row });
|
|
259
411
|
}
|
|
260
412
|
return index;
|
|
261
413
|
}
|
|
@@ -346,8 +498,7 @@ export async function publishReadRangeIndex(index, handle, signal = null, before
|
|
|
346
498
|
// result requesting producer certification still owes its terminal stats.
|
|
347
499
|
if (slot && READ_RANGE_INDEX_CACHE.get(key) !== slot && !onValidated) return false;
|
|
348
500
|
try {
|
|
349
|
-
if (!sameFileVersion(version, await handle.stat()) || !sameFileVersion(version, await stat(fullPath)))
|
|
350
|
-
return false;
|
|
501
|
+
if (!sameFileVersion(version, await handle.stat()) || !sameFileVersion(version, await stat(fullPath))) return false;
|
|
351
502
|
} catch {
|
|
352
503
|
return false;
|
|
353
504
|
}
|
|
@@ -108,7 +108,9 @@ async function symlinkTargetGuard(fullPath, filePath, helpers) {
|
|
|
108
108
|
if (typeof isSpecialFileStat === 'function' && isSpecialFileStat(targetStat)) {
|
|
109
109
|
return guardResponse('special', helpers, filePath, realTarget);
|
|
110
110
|
}
|
|
111
|
-
} catch {
|
|
111
|
+
} catch {
|
|
112
|
+
/* vanished target: see above */
|
|
113
|
+
}
|
|
112
114
|
return null;
|
|
113
115
|
}
|
|
114
116
|
|
|
@@ -138,7 +140,9 @@ export async function statReadTarget(fullPath, filePath, options, helpers) {
|
|
|
138
140
|
const error = await symlinkTargetGuard(fullPath, filePath, helpers);
|
|
139
141
|
if (error) return { st, error };
|
|
140
142
|
}
|
|
141
|
-
} catch {
|
|
143
|
+
} catch {
|
|
144
|
+
/* lstat failure is non-fatal: see above */
|
|
145
|
+
}
|
|
142
146
|
return { st };
|
|
143
147
|
}
|
|
144
148
|
|
|
@@ -148,12 +152,12 @@ export async function statReadTarget(fullPath, filePath, options, helpers) {
|
|
|
148
152
|
* recovery mode for an ordinary absence probe. Genuine not-found only —
|
|
149
153
|
* EACCES/EPERM etc. keep failure semantics.
|
|
150
154
|
*/
|
|
151
|
-
export function readNotFoundResponse(err, { fullPath, filePath, workDir }, helpers) {
|
|
155
|
+
export async function readNotFoundResponse(err, { fullPath, filePath, workDir }, helpers) {
|
|
152
156
|
const { findSimilarFile, normalizeErrorMessage, normalizeOutputPath } = helpers;
|
|
153
157
|
const similar = findSimilarFile(fullPath);
|
|
154
158
|
let hint = similar
|
|
155
159
|
? appendNotFoundCwdNote(` Did you mean "${normalizeOutputPath(similar)}"?`, workDir, err?.code)
|
|
156
|
-
: buildNotFoundHint(workDir, fullPath, 'Read', err?.code);
|
|
160
|
+
: await buildNotFoundHint(workDir, fullPath, 'Read', err?.code);
|
|
157
161
|
hint = finalizeReadFamilyEnoentTail(hint, filePath, err?.code);
|
|
158
162
|
const safeMsg = normalizeErrorMessage(err instanceof Error ? err.message : String(err), workDir);
|
|
159
163
|
if (err?.code === 'ENOENT' || err?.code === 'ENOTDIR') return `[path absent] ${safeMsg}${hint}`;
|
|
@@ -30,9 +30,10 @@ async function prefetchRawBody(fullPath, st, helpers, forceFresh = false) {
|
|
|
30
30
|
const cachedRaw = !forceFresh && _rawContentCacheGet ? _rawContentCacheGet(fullPath, st) : null;
|
|
31
31
|
if (cachedRaw) return { buf: cachedRaw, fromCache: true };
|
|
32
32
|
try {
|
|
33
|
-
const buf =
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
const buf =
|
|
34
|
+
!forceFresh && _runRawContentInFlight
|
|
35
|
+
? await _runRawContentInFlight(fullPath, readFile, st)
|
|
36
|
+
: await readFile(fullPath);
|
|
36
37
|
return { buf, fromCache: false };
|
|
37
38
|
} catch {
|
|
38
39
|
return { buf: null, fromCache: false };
|
|
@@ -84,7 +85,7 @@ export async function executeSingleReadTool(args, workDir, readStateScope, optio
|
|
|
84
85
|
let widenNote = '';
|
|
85
86
|
const target = await statReadTarget(fullPath, filePath, options, helpers);
|
|
86
87
|
if (target.error) return target.error;
|
|
87
|
-
if (!target.st) return readNotFoundResponse(target.statErr, { fullPath, filePath, workDir }, helpers);
|
|
88
|
+
if (!target.st) return await readNotFoundResponse(target.statErr, { fullPath, filePath, workDir }, helpers);
|
|
88
89
|
const st = target.st;
|
|
89
90
|
// Reactive widen + window-history bookkeeping (ranged text reads only).
|
|
90
91
|
if (
|
|
@@ -45,7 +45,10 @@ async function scanSourceWindows(path, intervals, signal) {
|
|
|
45
45
|
let parts = [];
|
|
46
46
|
let partBytes = 0;
|
|
47
47
|
const lines = new Map();
|
|
48
|
-
const
|
|
48
|
+
const minChunkBytes = 64 * 1024;
|
|
49
|
+
const maxChunkBytes = 1024 * 1024;
|
|
50
|
+
let chunkBytes = minChunkBytes;
|
|
51
|
+
let buffer = Buffer.allocUnsafe(chunkBytes);
|
|
49
52
|
const deadline = Date.now() + READ_STREAM_TIMEOUT_MS;
|
|
50
53
|
const check = () => {
|
|
51
54
|
signal?.throwIfAborted();
|
|
@@ -70,7 +73,11 @@ async function scanSourceWindows(path, intervals, signal) {
|
|
|
70
73
|
};
|
|
71
74
|
while (interval < intervals.length) {
|
|
72
75
|
check();
|
|
73
|
-
|
|
76
|
+
if (buffer.length < chunkBytes) buffer = Buffer.allocUnsafe(chunkBytes);
|
|
77
|
+
// Consume every byte inside the budget, even when a seeking chunk would
|
|
78
|
+
// cross it. The one-byte EOF probe never becomes usable source text.
|
|
79
|
+
const readBytes = Math.min(chunkBytes, Math.max(1, READ_MAX_SCAN_BYTES - scanned));
|
|
80
|
+
const { bytesRead } = await handle.read(buffer, 0, readBytes, position);
|
|
74
81
|
check();
|
|
75
82
|
if (!bytesRead) {
|
|
76
83
|
if (partBytes) save(Buffer.alloc(0), true);
|
|
@@ -95,6 +102,12 @@ async function scanSourceWindows(path, intervals, signal) {
|
|
|
95
102
|
start = end + 1;
|
|
96
103
|
}
|
|
97
104
|
position += bytesRead;
|
|
105
|
+
// Deep windows still validate coordinates from current bytes. Amortize
|
|
106
|
+
// positional IO while skipping, then return to small reads in a window.
|
|
107
|
+
chunkBytes =
|
|
108
|
+
interval < intervals.length && line < intervals[interval].start
|
|
109
|
+
? Math.min(maxChunkBytes, chunkBytes * 2)
|
|
110
|
+
: minChunkBytes;
|
|
98
111
|
}
|
|
99
112
|
// Publication checks after its async stats, immediately before committing.
|
|
100
113
|
// An unpublished result still owes a final deadline/cancellation check.
|
|
@@ -254,8 +254,8 @@ function absolutePaths(lines, rgCwd) {
|
|
|
254
254
|
return lines.map((line) => (isAbsolute(line) ? line : resolveAgainstCwd(line, rgCwd)));
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
-
function missingGlobRoot(scan, root, rgCwd, err) {
|
|
258
|
-
const hint = buildNotFoundHint(scan.workDir, rgCwd, 'Search', err?.code);
|
|
257
|
+
async function missingGlobRoot(scan, root, rgCwd, err) {
|
|
258
|
+
const hint = await buildNotFoundHint(scan.workDir, rgCwd, 'Search', err?.code);
|
|
259
259
|
return {
|
|
260
260
|
error: `path does not exist: ${normalizeOutputPath(rgCwd)} (${err?.code || 'ENOENT'})${finalizeReadFamilyEnoentTail(hint, root, err?.code)}`,
|
|
261
261
|
paths: [],
|
|
@@ -422,14 +422,14 @@ function globMoreSuffix({ rgWindowIncomplete, remaining, totalBeforeOffset, next
|
|
|
422
422
|
return '';
|
|
423
423
|
}
|
|
424
424
|
|
|
425
|
-
function globEmptyDiagnostic(scan, { totalBeforeOffset }) {
|
|
425
|
+
async function globEmptyDiagnostic(scan, { totalBeforeOffset }) {
|
|
426
426
|
const { patterns, basePath, baseEntries, workDir, statCache, offset } = scan;
|
|
427
427
|
const patternStr = patterns.length === 1 ? JSON.stringify(patterns[0]) : JSON.stringify(patterns);
|
|
428
428
|
const baseLabel = normalizeOutputPath(basePath);
|
|
429
429
|
if (totalBeforeOffset > 0 && offset >= totalBeforeOffset) {
|
|
430
430
|
return `(no entries after offset=${offset}; total=${totalBeforeOffset}) pattern=${patternStr} path=${baseLabel}`;
|
|
431
431
|
}
|
|
432
|
-
const diagnostic = basePathDiagnostic(
|
|
432
|
+
const diagnostic = await basePathDiagnostic(
|
|
433
433
|
baseEntries.map((e) => e.root),
|
|
434
434
|
workDir,
|
|
435
435
|
statCache
|
|
@@ -473,7 +473,7 @@ async function scanGlobGroups(scan) {
|
|
|
473
473
|
const shown = await directAbsoluteMatches({ patterns, headLimit, offset });
|
|
474
474
|
if (shown.length > 0) return patternCapNote + shown.join('\n');
|
|
475
475
|
}
|
|
476
|
-
const out = patternCapNote + renderGlobPage(scan, merged, { capped, remaining, totalBeforeOffset, miss });
|
|
476
|
+
const out = patternCapNote + (await renderGlobPage(scan, merged, { capped, remaining, totalBeforeOffset, miss }));
|
|
477
477
|
settleGlobScanCache(scan, merged, out, remaining);
|
|
478
478
|
reportToolProgress(options, `found ${totalBeforeOffset} files`);
|
|
479
479
|
return out;
|
|
@@ -482,7 +482,7 @@ async function scanGlobGroups(scan) {
|
|
|
482
482
|
// The page body with its more/integrity suffixes. Empty partials are not
|
|
483
483
|
// proof of absence: diagnostics are preserved even when there is no path
|
|
484
484
|
// body, rather than silently dropping the integrity suffix.
|
|
485
|
-
function renderGlobPage(scan, merged, { capped, remaining, totalBeforeOffset, miss }) {
|
|
485
|
+
async function renderGlobPage(scan, merged, { capped, remaining, totalBeforeOffset, miss }) {
|
|
486
486
|
const { offset } = scan;
|
|
487
487
|
const errSuffix = globIntegritySuffix(merged);
|
|
488
488
|
const moreSuffix = globMoreSuffix({
|
|
@@ -492,7 +492,7 @@ function renderGlobPage(scan, merged, { capped, remaining, totalBeforeOffset, mi
|
|
|
492
492
|
nextOffset: offset + capped.length,
|
|
493
493
|
});
|
|
494
494
|
if (capped.length > 0) return `${capped.join('\n')}${moreSuffix}${errSuffix}`;
|
|
495
|
-
const emptyDiag = miss ? globEmptyDiagnostic(scan, { totalBeforeOffset }) : '';
|
|
495
|
+
const emptyDiag = miss ? await globEmptyDiagnostic(scan, { totalBeforeOffset }) : '';
|
|
496
496
|
const emptyBody = (emptyDiag || '(no files found)').replace(
|
|
497
497
|
'(no files found)',
|
|
498
498
|
merged.rgStdoutPartial || merged.rgWindowIncomplete ? '(no files found yet)' : '(no files found)'
|
|
@@ -608,9 +608,12 @@ export async function executeGlobTool(args, workDir, options = {}) {
|
|
|
608
608
|
};
|
|
609
609
|
return await runScopedSearchInFlight(
|
|
610
610
|
cacheKey,
|
|
611
|
-
({ signal: sharedSignal, scopedCacheOutcome }) =>
|
|
612
|
-
|
|
613
|
-
|
|
611
|
+
({ signal: sharedSignal, scopedCacheOutcome }) =>
|
|
612
|
+
scanGlobGroups({
|
|
613
|
+
...scan,
|
|
614
|
+
sharedSignal,
|
|
615
|
+
options: { ...options, scopedCacheOutcome },
|
|
616
|
+
}),
|
|
614
617
|
{ signal: options?.signal || options?.abortSignal || null, scopes },
|
|
615
618
|
options?.scopedCacheOutcome
|
|
616
619
|
);
|
|
@@ -211,7 +211,7 @@ async function runGrepSearch(request, sharedSignal) {
|
|
|
211
211
|
|
|
212
212
|
async function grepMissingPathResult({ workDir, grepResolvedPath, searchPath, executeChildBuiltinTool }, err) {
|
|
213
213
|
const msg = `Error: path does not exist: ${normalizeOutputPath(grepResolvedPath)} (${err?.code || 'ENOENT'})`;
|
|
214
|
-
let hint = buildNotFoundHintBody(workDir, grepResolvedPath, 'Search', err?.code, {});
|
|
214
|
+
let hint = await buildNotFoundHintBody(workDir, grepResolvedPath, 'Search', err?.code, {});
|
|
215
215
|
if (!hint) hint = await _suggestIndexedPaths(grepResolvedPath, executeChildBuiltinTool, workDir);
|
|
216
216
|
return msg + finalizeReadFamilyEnoentTail(appendNotFoundCwdNote(hint, workDir, err?.code), searchPath, err?.code);
|
|
217
217
|
}
|
|
@@ -65,10 +65,10 @@ const ENOENT_ABSENT =
|
|
|
65
65
|
|
|
66
66
|
// Share diagnostic lookup results within one invocation without changing
|
|
67
67
|
// the requested operand or executing a replacement operation.
|
|
68
|
-
function cachedFileByBasename(workDir, missingPath, cache) {
|
|
68
|
+
async function cachedFileByBasename(workDir, missingPath, cache) {
|
|
69
69
|
if (!cache) return findFileByBasename(workDir, missingPath);
|
|
70
70
|
if (!('fileHits' in cache)) cache.fileHits = findFileByBasename(workDir, missingPath);
|
|
71
|
-
return cache.fileHits;
|
|
71
|
+
return await cache.fileHits;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
// A missing ABSOLUTE path that resolves outside the project cannot be
|
|
@@ -180,15 +180,15 @@ export function appendNotFoundCwdNote(hint, workDir, errCode = 'ENOENT') {
|
|
|
180
180
|
return `${hint} (relative paths resolve from ${normalizeOutputPath(workDir)})`;
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
-
export function buildNotFoundHint(workDir, missingPath, actionVerb, errCode = 'ENOENT', cache = null) {
|
|
183
|
+
export async function buildNotFoundHint(workDir, missingPath, actionVerb, errCode = 'ENOENT', cache = null) {
|
|
184
184
|
return appendNotFoundCwdNote(
|
|
185
|
-
buildNotFoundHintBody(workDir, missingPath, actionVerb, errCode, cache),
|
|
185
|
+
await buildNotFoundHintBody(workDir, missingPath, actionVerb, errCode, cache),
|
|
186
186
|
workDir,
|
|
187
187
|
errCode
|
|
188
188
|
);
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
export function buildNotFoundHintBody(workDir, missingPath, actionVerb, errCode = 'ENOENT', cache = null) {
|
|
191
|
+
export async function buildNotFoundHintBody(workDir, missingPath, actionVerb, errCode = 'ENOENT', cache = null) {
|
|
192
192
|
if (!NOT_FOUND_CODES.has(String(errCode || 'ENOENT'))) return '';
|
|
193
193
|
// `C:tmpsmp` shape: a Windows path whose separators were eaten by JSON
|
|
194
194
|
// escaping (`"C:\\tmp\\smp"` written as `"C:\tmp\smp"`). Name the cause —
|
|
@@ -200,12 +200,12 @@ export function buildNotFoundHintBody(workDir, missingPath, actionVerb, errCode
|
|
|
200
200
|
if (missingPathIsOutsideProject(workDir, missingPath)) {
|
|
201
201
|
return outsideProjectNotFoundHint(missingPath, actionVerb);
|
|
202
202
|
}
|
|
203
|
-
const elsewhere = cachedFileByBasename(workDir, missingPath, cache);
|
|
203
|
+
const elsewhere = await cachedFileByBasename(workDir, missingPath, cache);
|
|
204
204
|
if (elsewhere.length) {
|
|
205
205
|
return ` Not found at this path; the same filename exists at: ${elsewhere.map((p) => `"${normalizeOutputPath(p)}"`).join(', ')}. ${actionVerb} that path directly.`;
|
|
206
206
|
}
|
|
207
207
|
if (isDirectoryPathGuess(missingPath)) {
|
|
208
|
-
const dirHits = findDirectoryByBasename(workDir, missingPath, { limit: 5 });
|
|
208
|
+
const dirHits = await findDirectoryByBasename(workDir, missingPath, { limit: 5 });
|
|
209
209
|
if (dirHits.length > 1) {
|
|
210
210
|
return ` Not found at this path; same-named directories exist at: ${dirHits
|
|
211
211
|
.slice(0, 5)
|
|
@@ -268,9 +268,9 @@ export function uncRefusalMessage(toolName, original, resolved) {
|
|
|
268
268
|
return `Error: ${toolName} refuses UNC/SMB path ${JSON.stringify(shown)}; remote share access is blocked to prevent NTLM credential leaks`;
|
|
269
269
|
}
|
|
270
270
|
|
|
271
|
-
export function basePathDiagnostic(basePaths, workDir, statCache = null) {
|
|
272
|
-
|
|
273
|
-
.map((basePath) => {
|
|
271
|
+
export async function basePathDiagnostic(basePaths, workDir, statCache = null) {
|
|
272
|
+
const parts = await Promise.all(
|
|
273
|
+
basePaths.map(async (basePath) => {
|
|
274
274
|
const resolved = resolveSearchScope(basePath, workDir);
|
|
275
275
|
// Reuse the caller's call-scoped stat cache (glob preflight + per-group
|
|
276
276
|
// rg runs already stat'd this same resolved root) instead of re-stating.
|
|
@@ -291,8 +291,13 @@ export function basePathDiagnostic(basePaths, workDir, statCache = null) {
|
|
|
291
291
|
}
|
|
292
292
|
return (
|
|
293
293
|
`${normalizeOutputPath(basePath)}: path does not exist (${err?.code || 'ENOENT'})` +
|
|
294
|
-
finalizeReadFamilyEnoentTail(
|
|
294
|
+
finalizeReadFamilyEnoentTail(
|
|
295
|
+
await buildNotFoundHint(workDir, resolved, 'Search', err?.code),
|
|
296
|
+
basePath,
|
|
297
|
+
err?.code
|
|
298
|
+
)
|
|
295
299
|
);
|
|
296
300
|
})
|
|
297
|
-
|
|
301
|
+
);
|
|
302
|
+
return parts.join('; ');
|
|
298
303
|
}
|
|
@@ -79,10 +79,10 @@ export function resolveAggregateAnchorRoot(name, args, baseCwd, { explicitCwdArg
|
|
|
79
79
|
* One `file` anchor: an error string when it does not exist, otherwise the
|
|
80
80
|
* root it re-homes the call to (null keeps the current cwd).
|
|
81
81
|
*/
|
|
82
|
-
export function resolveFileAnchorRoot(name, args, fileArg, baseCwd) {
|
|
82
|
+
export async function resolveFileAnchorRoot(name, args, fileArg, baseCwd) {
|
|
83
83
|
const abs = _absFrom(baseCwd, fileArg);
|
|
84
84
|
if (!existsSync(abs)) {
|
|
85
|
-
const elsewhere = findFileByBasename(pathResolve(baseCwd), abs);
|
|
85
|
+
const elsewhere = await findFileByBasename(pathResolve(baseCwd), abs);
|
|
86
86
|
const hint = elsewhere.length
|
|
87
87
|
? ` Same filename exists at: ${elsewhere.map((p) => `"${toDisplayPath(p, baseCwd).replace(/\\/g, '/')}"`).join(', ')}. Use that path.`
|
|
88
88
|
: '';
|
|
@@ -345,7 +345,7 @@ async function executeCodeGraphToolRaw(name, rawArgs, cwd, signal = null, option
|
|
|
345
345
|
args = resolved.args;
|
|
346
346
|
}
|
|
347
347
|
if (fileArg && !hasAggregateFileArgs) {
|
|
348
|
-
const anchor = resolveFileAnchorRoot(name, args, fileArg, baseCwd);
|
|
348
|
+
const anchor = await resolveFileAnchorRoot(name, args, fileArg, baseCwd);
|
|
349
349
|
if (anchor.error) return anchor.error;
|
|
350
350
|
if (anchor.root) effectiveCwd = anchor.root;
|
|
351
351
|
}
|
|
@@ -47,7 +47,7 @@ export async function prepareCodexBatch({ patchStr, requestedFormat, basePath, p
|
|
|
47
47
|
let v4aRenamePlan = null;
|
|
48
48
|
if (isV4APatchInput(patchStr, requestedFormat)) {
|
|
49
49
|
try {
|
|
50
|
-
const parsedSections = preParsedV4ASections || rewriteV4AReadRedirects(parseV4APatch(patchStr), basePath);
|
|
50
|
+
const parsedSections = preParsedV4ASections || (await rewriteV4AReadRedirects(parseV4APatch(patchStr), basePath));
|
|
51
51
|
const allSections = coalesceCompatibleV4ASections(parsedSections, basePath);
|
|
52
52
|
v4aRenamePlan = await planV4ARenameSections(allSections, basePath);
|
|
53
53
|
inputPatchStr = await convertV4ASectionsToUnifiedPatch(v4aRenamePlan.remainingSections, basePath, v4aConvertOpts);
|
|
@@ -56,7 +56,7 @@ export async function prepareCodexBatch({ patchStr, requestedFormat, basePath, p
|
|
|
56
56
|
}
|
|
57
57
|
} else if (requestedFormat !== 'unified' && hasUnifiedBareV4AHunk(patchStr)) {
|
|
58
58
|
try {
|
|
59
|
-
const sections = rewriteV4AReadRedirects(parseUnifiedBareV4APatch(patchStr), basePath);
|
|
59
|
+
const sections = await rewriteV4AReadRedirects(parseUnifiedBareV4APatch(patchStr), basePath);
|
|
60
60
|
inputPatchStr = await convertV4ASectionsToUnifiedPatch(sections, basePath, v4aConvertOpts);
|
|
61
61
|
} catch (err) {
|
|
62
62
|
throw new Error(`apply_patch: bare @@ parse failed — ${err?.message || String(err)}`);
|
|
@@ -82,7 +82,7 @@ export async function prepareCodexBatch({ patchStr, requestedFormat, basePath, p
|
|
|
82
82
|
);
|
|
83
83
|
}
|
|
84
84
|
try {
|
|
85
|
-
const sections = rewriteV4AReadRedirects(parseUnifiedCountedAsV4APatch(patchStr), basePath);
|
|
85
|
+
const sections = await rewriteV4AReadRedirects(parseUnifiedCountedAsV4APatch(patchStr), basePath);
|
|
86
86
|
inputPatchStr = await convertV4ASectionsToUnifiedPatch(sections, basePath, v4aConvertOpts);
|
|
87
87
|
parsed = parsePatch(prepareInput(inputPatchStr));
|
|
88
88
|
} catch (fallbackErr) {
|
|
@@ -91,7 +91,7 @@ export async function prepareCodexBatch({ patchStr, requestedFormat, basePath, p
|
|
|
91
91
|
);
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
|
-
parsed = rewriteParsedReadRedirects(parsed, basePath);
|
|
94
|
+
parsed = await rewriteParsedReadRedirects(parsed, basePath);
|
|
95
95
|
if (!Array.isArray(parsed) || parsed.length === 0) {
|
|
96
96
|
return { error: 'Error: patch contained no file sections' };
|
|
97
97
|
}
|
|
@@ -7,11 +7,11 @@ import { pathKey, resolveV4AEntryPath } from '../paths.mjs';
|
|
|
7
7
|
import { rewriteV4AReadRedirects } from '../read-redirects.mjs';
|
|
8
8
|
import { isV4ARenameSection } from '../v4a-convert.mjs';
|
|
9
9
|
|
|
10
|
-
export function selectApplyPatchRoute({ args, patchStr, requestedFormat, basePath }) {
|
|
10
|
+
export async function selectApplyPatchRoute({ args, patchStr, requestedFormat, basePath }) {
|
|
11
11
|
let preParsedV4ASections = null;
|
|
12
12
|
if (isV4APatchInput(patchStr, requestedFormat)) {
|
|
13
13
|
try {
|
|
14
|
-
preParsedV4ASections = rewriteV4AReadRedirects(parseV4APatch(patchStr), basePath);
|
|
14
|
+
preParsedV4ASections = await rewriteV4AReadRedirects(parseV4APatch(patchStr), basePath);
|
|
15
15
|
} catch {
|
|
16
16
|
// The selected execution path reports the authoritative parse error.
|
|
17
17
|
}
|
|
@@ -34,7 +34,7 @@ async function apply_patch(rawArgs, cwd, options = {}) {
|
|
|
34
34
|
}
|
|
35
35
|
const rejectedV4AHunks = [];
|
|
36
36
|
const v4aConvertOpts = { rejectPartial, rejectedHunks: rejectedV4AHunks, fuzzy, dryRun, readStateScope };
|
|
37
|
-
const route = selectApplyPatchRoute({ args, patchStr, requestedFormat, basePath });
|
|
37
|
+
const route = await selectApplyPatchRoute({ args, patchStr, requestedFormat, basePath });
|
|
38
38
|
if (route.useSequence) {
|
|
39
39
|
const seqOut = await applyPatchSequence(patchStr, requestedFormat, basePath, {
|
|
40
40
|
v4aConvertOpts,
|