mixdog 1.2.4 → 1.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/scripts/lib/gate-scheduler.mjs +2 -2
- package/scripts/lib/run-node-tests.mjs +5 -14
- package/scripts/mobile-release.mjs +5 -4
- package/scripts/provider-pingpong-live.mjs +9 -9
- package/src/agents/advisor/AGENT.md +4 -4
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/reviewer/AGENT.md +2 -3
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +11 -0
- package/src/defaults/skills/browser-use/SKILL.md +2 -1
- package/src/defaults/skills/computer-use/SKILL.md +3 -1
- package/src/defaults/skills/visualize/SKILL.md +3 -2
- package/src/lib/rules-builder.cjs +1 -1
- package/src/output-styles/common.md +22 -5
- package/src/output-styles/detailed.md +7 -5
- package/src/output-styles/minimal.md +7 -3
- package/src/output-styles/simple.md +2 -3
- package/src/rules/agent/AGENT.md +3 -1
- package/src/rules/lead/LEAD.md +10 -7
- package/src/rules/shared/10-tool-workflow.md +2 -1
- package/src/rules/shared/60-verification.md +4 -5
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -1
- package/src/runtime/agent/orchestrator/config.mjs +6 -0
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +1 -1
- package/src/runtime/agent/orchestrator/internal-agents.mjs +10 -0
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +53 -60
- package/src/runtime/agent/orchestrator/mcp/client.mjs +7 -4
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +2 -3
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +40 -19
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/catalog-deadline.mjs +163 -0
- package/src/runtime/agent/orchestrator/providers/catalog-failures.mjs +34 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +38 -14
- package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +100 -26
- package/src/runtime/agent/orchestrator/providers/lib/send-callbacks.mjs +24 -0
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +13 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +49 -4
- package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +0 -7
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +11 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +45 -16
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-connect.mjs +196 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +74 -9
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +14 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-login.mjs +194 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-tokens.mjs +353 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +293 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +33 -100
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +23 -14
- package/src/runtime/agent/orchestrator/providers/registry.mjs +41 -27
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +2 -3
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +3 -8
- package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +15 -3
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +74 -13
- package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +102 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +8 -2
- package/src/runtime/agent/orchestrator/session/compact/summary.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/lifecycle-scan.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +39 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +9 -19
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +2 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +10 -7
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +62 -22
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +23 -1
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +81 -34
- package/src/runtime/agent/orchestrator/session/manager.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/request-fork.mjs +47 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/side-question.mjs +5 -43
- package/src/runtime/agent/orchestrator/session/store/fs-probe.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +73 -6
- package/src/runtime/agent/orchestrator/session/store/load-session.mjs +40 -0
- package/src/runtime/agent/orchestrator/session/store/save-fault.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-header.mjs +36 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +255 -32
- package/src/runtime/agent/orchestrator/session/store-record-strict-scan.mjs +306 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +70 -21
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +46 -30
- package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +144 -45
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +32 -13
- package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +364 -38
- package/src/runtime/agent/orchestrator/session/store.mjs +9 -2
- package/src/runtime/agent/orchestrator/session/task-wait-control.mjs +43 -12
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +23 -6
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +12 -6
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +13 -7
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/bashism-rewrite.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/benign-exit.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +40 -7
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +37 -34
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +0 -4
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -0
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +29 -27
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/find-files-tool.mjs +28 -11
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-policy.mjs +12 -3
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +203 -101
- package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +90 -41
- package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +17 -1
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-delivery.mjs +199 -0
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +165 -39
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +25 -13
- package/src/runtime/agent/orchestrator/tools/builtin/read-batch.mjs +7 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +19 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-line-collector.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +25 -7
- package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-render.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +12 -5
- package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +61 -22
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +32 -8
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +193 -19
- package/src/runtime/agent/orchestrator/tools/builtin/shell-direct-exe.mjs +57 -7
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +119 -32
- package/src/runtime/agent/orchestrator/tools/builtin/shell-lossless-compact.mjs +26 -1
- package/src/runtime/agent/orchestrator/tools/builtin/shell-output.mjs +13 -28
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +90 -11
- package/src/runtime/agent/orchestrator/tools/builtin/wait-budgets.mjs +23 -0
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +54 -10
- package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +22 -28
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +11 -7
- package/src/runtime/agent/orchestrator/tools/destructive-warning.mjs +126 -9
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +15 -6
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +40 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promotion-results.mjs +13 -3
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +35 -4
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +7 -2
- package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +39 -23
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
- package/src/runtime/attachments/office-extract.mjs +11 -9
- package/src/runtime/memory/lib/embedding-tokenizer.mjs +32 -18
- package/src/runtime/memory/lib/runtime-fetcher.mjs +1 -1
- package/src/runtime/memory/lib/tool-call-handler.mjs +7 -5
- package/src/runtime/office/authoring/pptx-script-normalize.mjs +11 -8
- package/src/runtime/office/core/tabular.mjs +1 -1
- package/src/runtime/office/design/library/design-template-inspect.mjs +7 -4
- package/src/runtime/office/portable/docx-formatting.mjs +1 -1
- package/src/runtime/office/portable/docx-runs.mjs +1 -1
- package/src/runtime/office/portable/docx-tracked-edits.mjs +2 -2
- package/src/runtime/office/portable/portable-docx-edits.mjs +11 -10
- package/src/runtime/office/portable/portable-docx-operations.mjs +21 -17
- package/src/runtime/office/portable/portable-docx-parts.mjs +15 -9
- package/src/runtime/office/portable/portable-docx-styles.mjs +4 -1
- package/src/runtime/office/portable/portable-docx-xml.mjs +9 -9
- package/src/runtime/office/portable/portable-opc.mjs +27 -13
- package/src/runtime/office/portable/portable-pivot.mjs +3 -3
- package/src/runtime/office/portable/portable-pptx-chart.mjs +3 -3
- package/src/runtime/office/portable/portable-pptx-charts.mjs +24 -18
- package/src/runtime/office/portable/portable-pptx-core.mjs +5 -5
- package/src/runtime/office/portable/portable-pptx-deck.mjs +8 -4
- package/src/runtime/office/portable/portable-pptx-package.mjs +7 -4
- package/src/runtime/office/portable/portable-pptx-shapes.mjs +18 -9
- package/src/runtime/office/portable/portable-sheet-parts.mjs +9 -3
- package/src/runtime/office/portable/portable-sheet-xml.mjs +5 -5
- package/src/runtime/office/portable/portable-xlsx-charts.mjs +4 -1
- package/src/runtime/office/portable/portable-xlsx-drawings.mjs +10 -6
- package/src/runtime/office/portable/portable-xlsx-operations.mjs +8 -5
- package/src/runtime/office/portable/portable-xlsx-pivot-ops.mjs +1 -1
- package/src/runtime/office/portable/portable-xlsx-reference-shift.mjs +11 -7
- package/src/runtime/office/portable/portable-xlsx-sheet-edits.mjs +6 -3
- package/src/runtime/office/portable/portable-xml.mjs +1 -1
- package/src/runtime/shared/atomic-file.mjs +22 -13
- package/src/runtime/shared/background-tasks.mjs +60 -20
- package/src/runtime/shared/child-spawn-gate.mjs +26 -16
- package/src/runtime/shared/config.mjs +0 -10
- package/src/runtime/shared/file-lock.mjs +7 -1
- package/src/runtime/shared/file-permissions-worker.mjs +38 -0
- package/src/runtime/shared/file-permissions.d.mts +19 -4
- package/src/runtime/shared/file-permissions.mjs +310 -4
- package/src/runtime/shared/git-runner-worker.mjs +6 -78
- package/src/runtime/shared/llm/http-agent.mjs +7 -3
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +10 -0
- package/src/runtime/shared/llm/usage-accounting.mjs +2 -0
- package/src/runtime/shared/llm/usage-ledger-import.mjs +32 -3
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +12 -5
- package/src/runtime/shared/llm/usage-ledger-worker.mjs +1 -1
- package/src/runtime/shared/llm/usage-ledger.mjs +20 -5
- package/src/runtime/shared/memory-snapshot.mjs +5 -1
- package/src/runtime/shared/notify-trace.mjs +8 -1
- package/src/runtime/shared/pristine-execution-contract.json +5 -1
- package/src/runtime/shared/process-runner-worker.mjs +7 -0
- package/src/runtime/shared/process-runner.mjs +38 -0
- package/src/runtime/shared/provider-accounts.mjs +2 -1
- package/src/runtime/shared/provider-api-key.mjs +0 -1
- package/src/runtime/shared/read-row-numbers.mjs +1 -1
- package/src/runtime/shared/resource-admission.mjs +60 -18
- package/src/runtime/shared/run-child.mjs +84 -0
- package/src/runtime/shared/session-activity-signal.mjs +23 -0
- package/src/runtime/shared/shell-output-summary.mjs +23 -0
- package/src/runtime/shared/singleton-owner.mjs +126 -42
- package/src/runtime/shared/tool-output-limit.mjs +4 -2
- package/src/runtime/shared/tool-output-marker.mjs +58 -0
- package/src/runtime/shared/user-data-guard.mjs +28 -9
- package/src/runtime/shared/worktrees/activity-gate.mjs +33 -8
- package/src/runtime/shared/worktrees/git-head.mjs +20 -2
- package/src/runtime/shared/worktrees/lock.mjs +3 -2
- package/src/runtime/terminal-bridge/tool-defs.mjs +1 -1
- package/src/runtime/tidy/runners/biome.mjs +3 -1
- package/src/runtime/tidy/shadow.mjs +2 -1
- package/src/runtime/web-search/index.mjs +5 -7
- package/src/runtime/web-search/lib/formatter.mjs +42 -6
- package/src/runtime/web-search/tool-defs.mjs +6 -1
- package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +4 -3
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +7 -4
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +3 -3
- package/src/session-runtime/lifecycle/shared.mjs +19 -2
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +2 -0
- package/src/session-runtime/lifecycle/teardown.mjs +5 -2
- package/src/session-runtime/lifecycle-api.mjs +3 -1
- package/src/session-runtime/provider-auth/login.mjs +10 -6
- package/src/session-runtime/provider-auth/setup.mjs +19 -2
- package/src/session-runtime/provider-catalog-cache.mjs +101 -25
- package/src/session-runtime/provider-models/catalog-load.mjs +14 -3
- package/src/session-runtime/provider-models/row-hydration.mjs +4 -0
- package/src/session-runtime/provider-models.mjs +76 -10
- package/src/session-runtime/provider-readiness.mjs +4 -0
- package/src/session-runtime/services/agent-tool/close-flow.mjs +2 -1
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +10 -2
- package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +13 -4
- package/src/session-runtime/services/agent-tool/notify.mjs +15 -4
- package/src/session-runtime/services/agent-tool/restart-notify.mjs +134 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -1
- package/src/session-runtime/services/agent-tool/spawn-flow/deferred-spawn.mjs +2 -1
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +4 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -1
- package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +8 -3
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +3 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +4 -0
- package/src/session-runtime/services/agent-tool/worker-index.mjs +44 -10
- package/src/session-runtime/services/agent-tool.mjs +20 -0
- package/src/session-runtime/services/provider-admin.mjs +92 -20
- package/src/session-runtime/services/usage-dashboard-model.mjs +2 -2
- package/src/session-runtime/services/usage-dashboard.mjs +27 -69
- package/src/session-runtime/turn/session-ops.mjs +2 -2
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/usage-stats-api.mjs +6 -1
- package/src/standalone/channel-transport/http-routes.mjs +10 -9
- package/src/standalone/daemon-desktop-runtime.mjs +20 -7
- package/src/standalone/daemon-owner.mjs +117 -25
- package/src/standalone/daemon.mjs +43 -13
- package/src/standalone/desktop-service-registry.mjs +32 -5
- package/src/standalone/session-call-cache.mjs +6 -0
- package/src/standalone/session-protocol.mjs +1 -1
- package/src/standalone/session-service/retention/busy.mjs +7 -2
- package/src/standalone/session-transport/routes.mjs +7 -6
- package/src/tui/app/model-options.mjs +39 -2
- package/src/tui/app/model-picker.mjs +16 -2
- package/src/tui/app/provider-setup-picker.mjs +1 -2
- package/src/tui/dist/index.mjs +436 -123
- package/src/tui/session/notice-text.mjs +0 -1
- package/src/tui/session/session-api/intake/submission.mjs +7 -13
- package/src/tui/session/session-api/integrations.mjs +1 -5
- package/src/tui/session/session-flow/drain.mjs +8 -0
- package/src/tui/session/session-flow/steering.mjs +46 -0
- package/src/tui/session/session-flow.mjs +2 -0
- package/src/tui/session/turn-stream.mjs +33 -0
- package/src/tui/session/turn.mjs +30 -3
- package/src/ui/statusline.mjs +1 -6
- package/src/ui/streaming-markdown-heal.mjs +94 -25
- package/src/vendor/statusline/bin/statusline-route.mjs +0 -1
- package/src/vendor/statusline/src/gateway/route-meta.mjs +0 -1
- package/src/workflows/default/WORKFLOW.md +9 -13
|
@@ -49,6 +49,17 @@ function sameFileStat(left, right) {
|
|
|
49
49
|
);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
// The file at `fileStat` provably still holds the bytes read under `known`.
|
|
53
|
+
const settledSameFile = (known, fileStat, now) =>
|
|
54
|
+
sameFileStat(known, fileStat) && now - Math.max(fileStat.mtimeMs, fileStat.ctimeMs) > SETTLED_FILE_AGE_MS;
|
|
55
|
+
|
|
56
|
+
/** Content identity of a record's text. UTF-16 preserves exact JavaScript
|
|
57
|
+
* code units, including lone surrogates that UTF-8 would collapse into the
|
|
58
|
+
* same replacement character. */
|
|
59
|
+
export function transcriptTextHash(text) {
|
|
60
|
+
return createHash('sha256').update(text, 'utf16le').digest('hex');
|
|
61
|
+
}
|
|
62
|
+
|
|
52
63
|
let stampSequence = 0;
|
|
53
64
|
const stampEpoch = `${process.pid}:${Date.now().toString(36)}`;
|
|
54
65
|
|
|
@@ -72,6 +83,9 @@ export function createStoredTranscriptCache({
|
|
|
72
83
|
const entries = new Map();
|
|
73
84
|
/** key -> { text, fingerprint, promise } for reads still parsing. */
|
|
74
85
|
const inFlight = new Map();
|
|
86
|
+
/** key -> { fingerprint, fileStat, promise } for reads not yet answered,
|
|
87
|
+
* from before their body is loaded. */
|
|
88
|
+
const reading = new Map();
|
|
75
89
|
/** Keys evicted for space (insertion order = age), bounded. */
|
|
76
90
|
const ghosts = new Set();
|
|
77
91
|
let retainedBytes = 0;
|
|
@@ -143,59 +157,135 @@ export function createStoredTranscriptCache({
|
|
|
143
157
|
}
|
|
144
158
|
};
|
|
145
159
|
|
|
160
|
+
// The cached entry, when it still holds content identified by `digest`.
|
|
161
|
+
const entryWithContent = (key, fingerprint, digest) => {
|
|
162
|
+
const entry = entries.get(key);
|
|
163
|
+
return entry &&
|
|
164
|
+
entry.fingerprint === fingerprint &&
|
|
165
|
+
entry.textChars === digest.textChars &&
|
|
166
|
+
entry.textHash === digest.textHash
|
|
167
|
+
? entry
|
|
168
|
+
: null;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// `project(known)` reads, digests and projects the record elsewhere (a
|
|
172
|
+
// worker thread) in one step: `{ textChars, textHash, value }`, or
|
|
173
|
+
// `{ textChars, textHash, same: true }` without a projection when the
|
|
174
|
+
// content is the `known` digest of the cached entry; null when the record
|
|
175
|
+
// cannot be read. Undefined when it could not answer at all.
|
|
176
|
+
async function readProjected({ key, group, fingerprint, fileStat, project, now }) {
|
|
177
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
178
|
+
const cached = entries.get(key);
|
|
179
|
+
const known =
|
|
180
|
+
attempt === 0 && cached?.fingerprint === fingerprint
|
|
181
|
+
? { textChars: cached.textChars, textHash: cached.textHash }
|
|
182
|
+
: null;
|
|
183
|
+
// A newer read of this key, clear or forget replaces or drops the
|
|
184
|
+
// record; only a still-current answer may then be remembered.
|
|
185
|
+
const record = { text: null, fingerprint, promise: null };
|
|
186
|
+
inFlight.set(key, record);
|
|
187
|
+
let answer;
|
|
188
|
+
try {
|
|
189
|
+
answer = await project(known);
|
|
190
|
+
} catch {
|
|
191
|
+
answer = undefined;
|
|
192
|
+
}
|
|
193
|
+
const current = inFlight.get(key) === record;
|
|
194
|
+
if (current) inFlight.delete(key);
|
|
195
|
+
if (answer === undefined) return undefined;
|
|
196
|
+
if (answer === null || typeof answer !== 'object') return { value: null, hit: false, read: true };
|
|
197
|
+
if (answer.same === true) {
|
|
198
|
+
const entry = entryWithContent(key, fingerprint, answer);
|
|
199
|
+
// Evicted meanwhile: project it after all.
|
|
200
|
+
if (!entry) continue;
|
|
201
|
+
entry.fileStat = fileStat;
|
|
202
|
+
touch(key, entry, now);
|
|
203
|
+
return { value: entry.value, hit: true, read: true };
|
|
204
|
+
}
|
|
205
|
+
const value = answer.value ?? null;
|
|
206
|
+
if (current && value && typeof value === 'object') {
|
|
207
|
+
remember(key, group, answer.textChars, answer.textHash, fingerprint, fileStat, value, now);
|
|
208
|
+
}
|
|
209
|
+
return { value, hit: false, read: true };
|
|
210
|
+
}
|
|
211
|
+
return undefined;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
async function readFresh({ key, group, fingerprint, fileStat, loadText, produce, project, now }) {
|
|
215
|
+
if (typeof project === 'function') {
|
|
216
|
+
const answered = await readProjected({ key, group, fingerprint, fileStat, project, now });
|
|
217
|
+
if (answered !== undefined) return answered;
|
|
218
|
+
// It could not answer (worker unavailable): load and produce here.
|
|
219
|
+
}
|
|
220
|
+
const cached = entries.get(key);
|
|
221
|
+
// `loadText` may answer asynchronously (a large record is read without
|
|
222
|
+
// blocking the loop); a plain string is unchanged.
|
|
223
|
+
let text = loadText();
|
|
224
|
+
if (typeof text?.then === 'function') text = await text;
|
|
225
|
+
if (typeof text !== 'string') return { value: null, hit: false, read: true };
|
|
226
|
+
const textHash = transcriptTextHash(text);
|
|
227
|
+
if (cached && entryWithContent(key, fingerprint, { textChars: text.length, textHash }) === cached) {
|
|
228
|
+
cached.fileStat = fileStat;
|
|
229
|
+
touch(key, cached, now);
|
|
230
|
+
return { value: cached.value, hit: true, read: true };
|
|
231
|
+
}
|
|
232
|
+
const pending = inFlight.get(key);
|
|
233
|
+
if (pending && pending.fingerprint === fingerprint && pending.text === text) {
|
|
234
|
+
return { value: await pending.promise, hit: true, read: true };
|
|
235
|
+
}
|
|
236
|
+
const record = { text, fingerprint, promise: null };
|
|
237
|
+
const promise = (async () => {
|
|
238
|
+
const value = await produce(text);
|
|
239
|
+
if (inFlight.get(key) === record && value && typeof value === 'object') {
|
|
240
|
+
remember(key, group, text.length, textHash, fingerprint, fileStat, value, now);
|
|
241
|
+
}
|
|
242
|
+
return value;
|
|
243
|
+
})();
|
|
244
|
+
record.promise = promise;
|
|
245
|
+
inFlight.set(key, record);
|
|
246
|
+
try {
|
|
247
|
+
return { value: await promise, hit: false, read: true };
|
|
248
|
+
} finally {
|
|
249
|
+
if (inFlight.get(key) === record) inFlight.delete(key);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
146
253
|
return {
|
|
147
254
|
/** The cached projection for this exact content, or a fresh one from
|
|
148
|
-
* `
|
|
149
|
-
*
|
|
255
|
+
* `project` (when given and able to answer) or `produce`. `loadText` /
|
|
256
|
+
* `project` run only when stat alone cannot vouch for the entry.
|
|
257
|
+
* Concurrent callers with the same content share one parse; callers of
|
|
258
|
+
* one unchanged, settled file share one read before it is even loaded.
|
|
150
259
|
* Entries naming the same `group` replace each other. */
|
|
151
|
-
async read({
|
|
260
|
+
async read({
|
|
261
|
+
key,
|
|
262
|
+
group = null,
|
|
263
|
+
fingerprint,
|
|
264
|
+
fileStat = null,
|
|
265
|
+
loadText,
|
|
266
|
+
produce,
|
|
267
|
+
project = null,
|
|
268
|
+
now = Date.now(),
|
|
269
|
+
}) {
|
|
152
270
|
trimIdle(now);
|
|
153
271
|
const cached = entries.get(key);
|
|
154
|
-
if (
|
|
155
|
-
cached &&
|
|
156
|
-
cached.fingerprint === fingerprint &&
|
|
157
|
-
sameFileStat(cached.fileStat, fileStat) &&
|
|
158
|
-
now - Math.max(fileStat.mtimeMs, fileStat.ctimeMs) > SETTLED_FILE_AGE_MS
|
|
159
|
-
) {
|
|
272
|
+
if (cached && cached.fingerprint === fingerprint && settledSameFile(cached.fileStat, fileStat, now)) {
|
|
160
273
|
touch(key, cached, now);
|
|
161
274
|
return { value: cached.value, hit: true, read: false };
|
|
162
275
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
// UTF-16 preserves exact JavaScript code units, including lone surrogates
|
|
169
|
-
// that UTF-8 would collapse into the same replacement character.
|
|
170
|
-
const textHash = createHash('sha256').update(text, 'utf16le').digest('hex');
|
|
171
|
-
if (
|
|
172
|
-
cached &&
|
|
173
|
-
cached.fingerprint === fingerprint &&
|
|
174
|
-
cached.textChars === text.length &&
|
|
175
|
-
cached.textHash === textHash
|
|
176
|
-
) {
|
|
177
|
-
cached.fileStat = fileStat;
|
|
178
|
-
touch(key, cached, now);
|
|
179
|
-
return { value: cached.value, hit: true, read: true };
|
|
180
|
-
}
|
|
181
|
-
const pending = inFlight.get(key);
|
|
182
|
-
if (pending && pending.fingerprint === fingerprint && pending.text === text) {
|
|
183
|
-
return { value: await pending.promise, hit: true, read: true };
|
|
276
|
+
const joined = reading.get(key);
|
|
277
|
+
if (joined && joined.fingerprint === fingerprint && settledSameFile(joined.fileStat, fileStat, now)) {
|
|
278
|
+
const { value } = await joined.promise;
|
|
279
|
+
// A read that found nothing is not shared: this caller learns why itself.
|
|
280
|
+
if (value) return { value, hit: true, read: false };
|
|
184
281
|
}
|
|
185
|
-
const record = {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
if (inFlight.get(key) === record && value && typeof value === 'object') {
|
|
189
|
-
remember(key, group, text.length, textHash, fingerprint, fileStat, value, now);
|
|
190
|
-
}
|
|
191
|
-
return value;
|
|
192
|
-
})();
|
|
193
|
-
record.promise = promise;
|
|
194
|
-
inFlight.set(key, record);
|
|
282
|
+
const record = { fingerprint, fileStat, promise: null };
|
|
283
|
+
record.promise = readFresh({ key, group, fingerprint, fileStat, loadText, produce, project, now });
|
|
284
|
+
reading.set(key, record);
|
|
195
285
|
try {
|
|
196
|
-
return
|
|
286
|
+
return await record.promise;
|
|
197
287
|
} finally {
|
|
198
|
-
if (
|
|
288
|
+
if (reading.get(key) === record) reading.delete(key);
|
|
199
289
|
}
|
|
200
290
|
},
|
|
201
291
|
/** The last view of these projections left: they turn idle now and stay
|
|
@@ -207,8 +297,10 @@ export function createStoredTranscriptCache({
|
|
|
207
297
|
trimIdle(now);
|
|
208
298
|
},
|
|
209
299
|
forget(keyPrefix) {
|
|
210
|
-
for (const
|
|
211
|
-
|
|
300
|
+
for (const pending of [inFlight, reading]) {
|
|
301
|
+
for (const key of pending.keys()) {
|
|
302
|
+
if (key.startsWith(keyPrefix)) pending.delete(key);
|
|
303
|
+
}
|
|
212
304
|
}
|
|
213
305
|
for (const key of [...entries.keys()]) {
|
|
214
306
|
if (key.startsWith(keyPrefix)) drop(key);
|
|
@@ -220,11 +312,18 @@ export function createStoredTranscriptCache({
|
|
|
220
312
|
clear() {
|
|
221
313
|
entries.clear();
|
|
222
314
|
inFlight.clear();
|
|
315
|
+
reading.clear();
|
|
223
316
|
ghosts.clear();
|
|
224
317
|
retainedBytes = 0;
|
|
225
318
|
},
|
|
226
319
|
stats() {
|
|
227
|
-
return {
|
|
320
|
+
return {
|
|
321
|
+
entries: entries.size,
|
|
322
|
+
retainedBytes,
|
|
323
|
+
inFlight: inFlight.size,
|
|
324
|
+
reading: reading.size,
|
|
325
|
+
ghosts: ghosts.size,
|
|
326
|
+
};
|
|
228
327
|
},
|
|
229
328
|
};
|
|
230
329
|
}
|
|
@@ -19,6 +19,14 @@ import { dataDir } from './store-summary-locations.mjs';
|
|
|
19
19
|
/** The parse/recovery/projection body of a stored transcript read. Runs once
|
|
20
20
|
* per distinct content; its result is shared read-only through the cache. */
|
|
21
21
|
export async function projectStoredTranscript(sessionId, doc, options) {
|
|
22
|
+
return windowStoredTranscript(sessionId, await prepareStoredTranscriptBase(sessionId, doc, options), options);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** The window-independent half of a projection: recovery, the prepared
|
|
26
|
+
* session and its whole-transcript context gauge. Every transcript window of
|
|
27
|
+
* the same content is cut from one base (windowStoredTranscript), which
|
|
28
|
+
* never mutates it. */
|
|
29
|
+
export async function prepareStoredTranscriptBase(sessionId, doc, options) {
|
|
22
30
|
let session = doc;
|
|
23
31
|
if (!options.checkpointAbsent) {
|
|
24
32
|
const { projectTurnCheckpointMessages, readTurnCheckpoint } = await import('./manager/turn-checkpoint.mjs');
|
|
@@ -37,7 +45,7 @@ export async function projectStoredTranscript(sessionId, doc, options) {
|
|
|
37
45
|
if (session?.activeTurnCheckpoint) projectCheckpoint();
|
|
38
46
|
}
|
|
39
47
|
}
|
|
40
|
-
const {
|
|
48
|
+
const { sessionContextSnapshotProjection } = await import('./transcript-restore/restore.mjs');
|
|
41
49
|
let preparedContextProjection = null;
|
|
42
50
|
try {
|
|
43
51
|
const [{ prepareSessionProjection }, { createContextStatus }, { primeContextEstimates }] = await Promise.all([
|
|
@@ -81,6 +89,28 @@ export async function projectStoredTranscript(sessionId, doc, options) {
|
|
|
81
89
|
rawAutoCompactTokenLimit && (!displayContextWindow || rawAutoCompactTokenLimit < displayContextWindow)
|
|
82
90
|
? rawAutoCompactTokenLimit
|
|
83
91
|
: 0;
|
|
92
|
+
return {
|
|
93
|
+
session,
|
|
94
|
+
messages,
|
|
95
|
+
contextFields: preparedContextProjection
|
|
96
|
+
? {
|
|
97
|
+
...preparedContextProjection,
|
|
98
|
+
preparedContextProjection: true,
|
|
99
|
+
}
|
|
100
|
+
: {
|
|
101
|
+
stats: measuredStats,
|
|
102
|
+
contextWindow: contextWindow || null,
|
|
103
|
+
rawContextWindow: rawContextWindow || null,
|
|
104
|
+
displayContextWindow: displayContextWindow || null,
|
|
105
|
+
autoCompactTokenLimit: autoCompactTokenLimit || null,
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** One transcript window (`options.itemLimit`, default whole) of a base. */
|
|
111
|
+
export async function windowStoredTranscript(sessionId, base, options) {
|
|
112
|
+
const { session, messages, contextFields } = base;
|
|
113
|
+
const { restoreTranscriptItems } = await import('./transcript-restore/restore.mjs');
|
|
84
114
|
// Restoring one item past a finite limit proves whether older history exists
|
|
85
115
|
// without projecting it; restore ids are message-positional, so the kept
|
|
86
116
|
// tail is identical either way.
|
|
@@ -115,17 +145,6 @@ export async function projectStoredTranscript(sessionId, doc, options) {
|
|
|
115
145
|
cwd: session.cwd || '',
|
|
116
146
|
desktopSession: desktopSession(session.desktopSession, session.cwd),
|
|
117
147
|
workflow: session.workflow || null,
|
|
118
|
-
...
|
|
119
|
-
? {
|
|
120
|
-
...preparedContextProjection,
|
|
121
|
-
preparedContextProjection: true,
|
|
122
|
-
}
|
|
123
|
-
: {
|
|
124
|
-
stats: measuredStats,
|
|
125
|
-
contextWindow: contextWindow || null,
|
|
126
|
-
rawContextWindow: rawContextWindow || null,
|
|
127
|
-
displayContextWindow: displayContextWindow || null,
|
|
128
|
-
autoCompactTokenLimit: autoCompactTokenLimit || null,
|
|
129
|
-
}),
|
|
148
|
+
...contextFields,
|
|
130
149
|
};
|
|
131
150
|
}
|