@code-yeongyu/senpi-agent-core 2026.9.12-3 → 2026.9.12
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 +0 -4
- package/dist/harness/agent-harness.d.ts +384 -639
- package/dist/harness/agent-harness.d.ts.map +1 -1
- package/dist/harness/agent-harness.js +250 -5
- package/dist/harness/agent-harness.js.map +1 -1
- package/dist/harness/compaction/branch-summarization.d.ts +6 -12
- package/dist/harness/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/harness/compaction/branch-summarization.js +27 -33
- package/dist/harness/compaction/branch-summarization.js.map +1 -1
- package/dist/harness/compaction/compaction.d.ts +8 -30
- package/dist/harness/compaction/compaction.d.ts.map +1 -1
- package/dist/harness/compaction/compaction.js +64 -53
- package/dist/harness/compaction/compaction.js.map +1 -1
- package/dist/harness/env/nodejs.d.ts +28 -25
- package/dist/harness/env/nodejs.d.ts.map +1 -1
- package/dist/harness/env/nodejs.js +125 -368
- package/dist/harness/env/nodejs.js.map +1 -1
- package/dist/harness/events.d.ts +38 -20
- package/dist/harness/events.d.ts.map +1 -1
- package/dist/harness/events.js +55 -233
- package/dist/harness/events.js.map +1 -1
- package/dist/harness/messages.d.ts +2 -2
- package/dist/harness/messages.d.ts.map +1 -1
- package/dist/harness/messages.js.map +1 -1
- package/dist/harness/prompt-templates.d.ts +2 -3
- package/dist/harness/prompt-templates.d.ts.map +1 -1
- package/dist/harness/prompt-templates.js +17 -17
- package/dist/harness/prompt-templates.js.map +1 -1
- package/dist/harness/reducer.d.ts +100 -0
- package/dist/harness/reducer.d.ts.map +1 -0
- package/dist/harness/reducer.js +420 -0
- package/dist/harness/reducer.js.map +1 -0
- package/dist/harness/result.d.ts +0 -93
- package/dist/harness/result.d.ts.map +1 -1
- package/dist/harness/result.js +0 -39
- package/dist/harness/result.js.map +1 -1
- package/dist/harness/session/context.d.ts +19 -6
- package/dist/harness/session/context.d.ts.map +1 -1
- package/dist/harness/session/context.js +53 -31
- package/dist/harness/session/context.js.map +1 -1
- package/dist/harness/session/index.d.ts +5 -9
- package/dist/harness/session/index.d.ts.map +1 -1
- package/dist/harness/session/index.js +4 -7
- package/dist/harness/session/index.js.map +1 -1
- package/dist/harness/session/jsonl/codec.d.ts +8 -19
- package/dist/harness/session/jsonl/codec.d.ts.map +1 -1
- package/dist/harness/session/jsonl/codec.js +219 -34
- package/dist/harness/session/jsonl/codec.js.map +1 -1
- package/dist/harness/session/jsonl/errors.d.ts +9 -0
- package/dist/harness/session/jsonl/errors.d.ts.map +1 -0
- package/dist/harness/session/jsonl/errors.js +18 -0
- package/dist/harness/session/jsonl/errors.js.map +1 -0
- package/dist/harness/session/jsonl/repo.d.ts +24 -27
- package/dist/harness/session/jsonl/repo.d.ts.map +1 -1
- package/dist/harness/session/jsonl/repo.js +151 -276
- package/dist/harness/session/jsonl/repo.js.map +1 -1
- package/dist/harness/session/jsonl/storage.d.ts +41 -39
- package/dist/harness/session/jsonl/storage.d.ts.map +1 -1
- package/dist/harness/session/jsonl/storage.js +196 -175
- package/dist/harness/session/jsonl/storage.js.map +1 -1
- package/dist/harness/session/jsonl/types.d.ts +22 -23
- package/dist/harness/session/jsonl/types.d.ts.map +1 -1
- package/dist/harness/session/jsonl/types.js +1 -2
- package/dist/harness/session/jsonl/types.js.map +1 -1
- package/dist/harness/session/jsonl.d.ts +3 -0
- package/dist/harness/session/jsonl.d.ts.map +1 -0
- package/dist/harness/session/jsonl.js +2 -0
- package/dist/harness/session/jsonl.js.map +1 -0
- package/dist/harness/session/memory.d.ts +40 -44
- package/dist/harness/session/memory.d.ts.map +1 -1
- package/dist/harness/session/memory.js +115 -333
- package/dist/harness/session/memory.js.map +1 -1
- package/dist/harness/session/session.d.ts +51 -78
- package/dist/harness/session/session.d.ts.map +1 -1
- package/dist/harness/session/session.js +207 -327
- package/dist/harness/session/session.js.map +1 -1
- package/dist/harness/session/state.d.ts +65 -0
- package/dist/harness/session/state.d.ts.map +1 -0
- package/dist/harness/session/state.js +320 -0
- package/dist/harness/session/state.js.map +1 -0
- package/dist/harness/session/testing/conformance.d.ts +4 -0
- package/dist/harness/session/testing/conformance.d.ts.map +1 -0
- package/dist/harness/session/testing/conformance.js +762 -0
- package/dist/harness/session/testing/conformance.js.map +1 -0
- package/dist/harness/session/testing/index.d.ts +2 -9
- package/dist/harness/session/testing/index.d.ts.map +1 -1
- package/dist/harness/session/testing/index.js +1 -8
- package/dist/harness/session/testing/index.js.map +1 -1
- package/dist/harness/session/testing/types.d.ts +7 -5
- package/dist/harness/session/testing/types.d.ts.map +1 -1
- package/dist/harness/session/testing/types.js.map +1 -1
- package/dist/harness/session/types.d.ts +265 -425
- package/dist/harness/session/types.d.ts.map +1 -1
- package/dist/harness/session/types.js +7 -7
- package/dist/harness/session/types.js.map +1 -1
- package/dist/harness/skills.d.ts +2 -3
- package/dist/harness/skills.d.ts.map +1 -1
- package/dist/harness/skills.js +26 -29
- package/dist/harness/skills.js.map +1 -1
- package/dist/harness/telemetry.d.ts +43 -64
- package/dist/harness/telemetry.d.ts.map +1 -1
- package/dist/harness/telemetry.js +26 -45
- package/dist/harness/telemetry.js.map +1 -1
- package/dist/harness/tools/bash.d.ts +4 -4
- package/dist/harness/tools/bash.d.ts.map +1 -1
- package/dist/harness/tools/bash.js +93 -66
- package/dist/harness/tools/bash.js.map +1 -1
- package/dist/harness/tools/edit.d.ts.map +1 -1
- package/dist/harness/tools/edit.js +13 -17
- package/dist/harness/tools/edit.js.map +1 -1
- package/dist/harness/tools/file-mutation-queue.d.ts +1 -2
- package/dist/harness/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/harness/tools/file-mutation-queue.js +5 -5
- package/dist/harness/tools/file-mutation-queue.js.map +1 -1
- package/dist/harness/tools/path-utils.d.ts +2 -3
- package/dist/harness/tools/path-utils.d.ts.map +1 -1
- package/dist/harness/tools/path-utils.js +5 -5
- package/dist/harness/tools/path-utils.js.map +1 -1
- package/dist/harness/tools/read.d.ts +1 -2
- package/dist/harness/tools/read.d.ts.map +1 -1
- package/dist/harness/tools/read.js +6 -4
- package/dist/harness/tools/read.js.map +1 -1
- package/dist/harness/tools/write.d.ts.map +1 -1
- package/dist/harness/tools/write.js +8 -12
- package/dist/harness/tools/write.js.map +1 -1
- package/dist/harness/types.d.ts +45 -128
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/utils/shell-output.d.ts +5 -19
- package/dist/harness/utils/shell-output.d.ts.map +1 -1
- package/dist/harness/utils/shell-output.js +192 -65
- package/dist/harness/utils/shell-output.js.map +1 -1
- package/dist/harness/utils/truncate.d.ts +0 -1
- package/dist/harness/utils/truncate.d.ts.map +1 -1
- package/dist/harness/utils/truncate.js +1 -1
- package/dist/harness/utils/truncate.js.map +1 -1
- package/dist/index.d.ts +1 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/search/index.d.ts +16 -24
- package/dist/search/index.d.ts.map +1 -1
- package/dist/search/index.js +1 -1
- package/dist/search/index.js.map +1 -1
- package/dist/search/scanning.d.ts +29 -0
- package/dist/search/scanning.d.ts.map +1 -0
- package/dist/search/scanning.js +103 -0
- package/dist/search/scanning.js.map +1 -0
- package/dist/types.d.ts +0 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +6 -27
- package/dist/harness/config.d.ts +0 -9
- package/dist/harness/config.d.ts.map +0 -1
- package/dist/harness/config.js +0 -35
- package/dist/harness/config.js.map +0 -1
- package/dist/harness/context.d.ts +0 -9
- package/dist/harness/context.d.ts.map +0 -1
- package/dist/harness/context.js +0 -13
- package/dist/harness/context.js.map +0 -1
- package/dist/harness/execution/assistant.d.ts +0 -42
- package/dist/harness/execution/assistant.d.ts.map +0 -1
- package/dist/harness/execution/assistant.js +0 -82
- package/dist/harness/execution/assistant.js.map +0 -1
- package/dist/harness/execution/effect-gate.d.ts +0 -22
- package/dist/harness/execution/effect-gate.d.ts.map +0 -1
- package/dist/harness/execution/effect-gate.js +0 -48
- package/dist/harness/execution/effect-gate.js.map +0 -1
- package/dist/harness/execution/tools.d.ts +0 -67
- package/dist/harness/execution/tools.d.ts.map +0 -1
- package/dist/harness/execution/tools.js +0 -121
- package/dist/harness/execution/tools.js.map +0 -1
- package/dist/harness/hooks.d.ts +0 -38
- package/dist/harness/hooks.d.ts.map +0 -1
- package/dist/harness/hooks.js +0 -404
- package/dist/harness/hooks.js.map +0 -1
- package/dist/harness/runtime/drive/boundary.d.ts +0 -28
- package/dist/harness/runtime/drive/boundary.d.ts.map +0 -1
- package/dist/harness/runtime/drive/boundary.js +0 -173
- package/dist/harness/runtime/drive/boundary.js.map +0 -1
- package/dist/harness/runtime/drive/checkpoint.d.ts +0 -8
- package/dist/harness/runtime/drive/checkpoint.d.ts.map +0 -1
- package/dist/harness/runtime/drive/checkpoint.js +0 -133
- package/dist/harness/runtime/drive/checkpoint.js.map +0 -1
- package/dist/harness/runtime/drive/deferred.d.ts +0 -15
- package/dist/harness/runtime/drive/deferred.d.ts.map +0 -1
- package/dist/harness/runtime/drive/deferred.js +0 -179
- package/dist/harness/runtime/drive/deferred.js.map +0 -1
- package/dist/harness/runtime/drive/generation.d.ts +0 -8
- package/dist/harness/runtime/drive/generation.d.ts.map +0 -1
- package/dist/harness/runtime/drive/generation.js +0 -205
- package/dist/harness/runtime/drive/generation.js.map +0 -1
- package/dist/harness/runtime/drive/reconcile.d.ts +0 -5
- package/dist/harness/runtime/drive/reconcile.d.ts.map +0 -1
- package/dist/harness/runtime/drive/reconcile.js +0 -140
- package/dist/harness/runtime/drive/reconcile.js.map +0 -1
- package/dist/harness/runtime/drive/recovery.d.ts +0 -8
- package/dist/harness/runtime/drive/recovery.d.ts.map +0 -1
- package/dist/harness/runtime/drive/recovery.js +0 -85
- package/dist/harness/runtime/drive/recovery.js.map +0 -1
- package/dist/harness/runtime/drive/response.d.ts +0 -23
- package/dist/harness/runtime/drive/response.d.ts.map +0 -1
- package/dist/harness/runtime/drive/response.js +0 -394
- package/dist/harness/runtime/drive/response.js.map +0 -1
- package/dist/harness/runtime/drive/retry.d.ts +0 -4
- package/dist/harness/runtime/drive/retry.d.ts.map +0 -1
- package/dist/harness/runtime/drive/retry.js +0 -34
- package/dist/harness/runtime/drive/retry.js.map +0 -1
- package/dist/harness/runtime/drive/structural.d.ts +0 -32
- package/dist/harness/runtime/drive/structural.d.ts.map +0 -1
- package/dist/harness/runtime/drive/structural.js +0 -929
- package/dist/harness/runtime/drive/structural.js.map +0 -1
- package/dist/harness/runtime/drive/terminal.d.ts +0 -7
- package/dist/harness/runtime/drive/terminal.d.ts.map +0 -1
- package/dist/harness/runtime/drive/terminal.js +0 -49
- package/dist/harness/runtime/drive/terminal.js.map +0 -1
- package/dist/harness/runtime/drive/tool-placement.d.ts +0 -14
- package/dist/harness/runtime/drive/tool-placement.d.ts.map +0 -1
- package/dist/harness/runtime/drive/tool-placement.js +0 -244
- package/dist/harness/runtime/drive/tool-placement.js.map +0 -1
- package/dist/harness/runtime/drive/tools.d.ts +0 -6
- package/dist/harness/runtime/drive/tools.d.ts.map +0 -1
- package/dist/harness/runtime/drive/tools.js +0 -449
- package/dist/harness/runtime/drive/tools.js.map +0 -1
- package/dist/harness/runtime/drive.d.ts +0 -6
- package/dist/harness/runtime/drive.d.ts.map +0 -1
- package/dist/harness/runtime/drive.js +0 -93
- package/dist/harness/runtime/drive.js.map +0 -1
- package/dist/harness/runtime/harness.d.ts +0 -59
- package/dist/harness/runtime/harness.d.ts.map +0 -1
- package/dist/harness/runtime/harness.js +0 -302
- package/dist/harness/runtime/harness.js.map +0 -1
- package/dist/harness/runtime/index.d.ts +0 -2
- package/dist/harness/runtime/index.d.ts.map +0 -1
- package/dist/harness/runtime/index.js +0 -2
- package/dist/harness/runtime/index.js.map +0 -1
- package/dist/harness/runtime/lane.d.ts +0 -118
- package/dist/harness/runtime/lane.d.ts.map +0 -1
- package/dist/harness/runtime/lane.js +0 -1559
- package/dist/harness/runtime/lane.js.map +0 -1
- package/dist/harness/runtime/progress.d.ts +0 -15
- package/dist/harness/runtime/progress.d.ts.map +0 -1
- package/dist/harness/runtime/progress.js +0 -66
- package/dist/harness/runtime/progress.js.map +0 -1
- package/dist/harness/runtime/reducer.d.ts +0 -5
- package/dist/harness/runtime/reducer.d.ts.map +0 -1
- package/dist/harness/runtime/reducer.js +0 -240
- package/dist/harness/runtime/reducer.js.map +0 -1
- package/dist/harness/runtime/restore.d.ts +0 -24
- package/dist/harness/runtime/restore.d.ts.map +0 -1
- package/dist/harness/runtime/restore.js +0 -117
- package/dist/harness/runtime/restore.js.map +0 -1
- package/dist/harness/runtime/transcript.d.ts +0 -21
- package/dist/harness/runtime/transcript.d.ts.map +0 -1
- package/dist/harness/runtime/transcript.js +0 -72
- package/dist/harness/runtime/transcript.js.map +0 -1
- package/dist/harness/runtime/types.d.ts +0 -105
- package/dist/harness/runtime/types.d.ts.map +0 -1
- package/dist/harness/runtime/types.js +0 -50
- package/dist/harness/runtime/types.js.map +0 -1
- package/dist/harness/session/commit.d.ts +0 -53
- package/dist/harness/session/commit.d.ts.map +0 -1
- package/dist/harness/session/commit.js +0 -57
- package/dist/harness/session/commit.js.map +0 -1
- package/dist/harness/session/fork-policy.d.ts +0 -21
- package/dist/harness/session/fork-policy.d.ts.map +0 -1
- package/dist/harness/session/fork-policy.js +0 -55
- package/dist/harness/session/fork-policy.js.map +0 -1
- package/dist/harness/session/fork.d.ts +0 -16
- package/dist/harness/session/fork.d.ts.map +0 -1
- package/dist/harness/session/fork.js +0 -79
- package/dist/harness/session/fork.js.map +0 -1
- package/dist/harness/session/in-memory-storage-state.d.ts +0 -39
- package/dist/harness/session/in-memory-storage-state.d.ts.map +0 -1
- package/dist/harness/session/in-memory-storage-state.js +0 -269
- package/dist/harness/session/in-memory-storage-state.js.map +0 -1
- package/dist/harness/session/jsonl/fork.d.ts +0 -38
- package/dist/harness/session/jsonl/fork.d.ts.map +0 -1
- package/dist/harness/session/jsonl/fork.js +0 -266
- package/dist/harness/session/jsonl/fork.js.map +0 -1
- package/dist/harness/session/jsonl/index.d.ts +0 -4
- package/dist/harness/session/jsonl/index.d.ts.map +0 -1
- package/dist/harness/session/jsonl/index.js +0 -4
- package/dist/harness/session/jsonl/index.js.map +0 -1
- package/dist/harness/session/jsonl/io.d.ts +0 -14
- package/dist/harness/session/jsonl/io.d.ts.map +0 -1
- package/dist/harness/session/jsonl/io.js +0 -86
- package/dist/harness/session/jsonl/io.js.map +0 -1
- package/dist/harness/session/jsonl/legacy-v3.d.ts +0 -44
- package/dist/harness/session/jsonl/legacy-v3.d.ts.map +0 -1
- package/dist/harness/session/jsonl/legacy-v3.js +0 -454
- package/dist/harness/session/jsonl/legacy-v3.js.map +0 -1
- package/dist/harness/session/mutation-line.d.ts +0 -8
- package/dist/harness/session/mutation-line.d.ts.map +0 -1
- package/dist/harness/session/mutation-line.js +0 -22
- package/dist/harness/session/mutation-line.js.map +0 -1
- package/dist/harness/session/testing/benchmark/datasets.d.ts +0 -12
- package/dist/harness/session/testing/benchmark/datasets.d.ts.map +0 -1
- package/dist/harness/session/testing/benchmark/datasets.js +0 -24
- package/dist/harness/session/testing/benchmark/datasets.js.map +0 -1
- package/dist/harness/session/testing/benchmark/session-repo.d.ts +0 -42
- package/dist/harness/session/testing/benchmark/session-repo.d.ts.map +0 -1
- package/dist/harness/session/testing/benchmark/session-repo.js +0 -127
- package/dist/harness/session/testing/benchmark/session-repo.js.map +0 -1
- package/dist/harness/session/testing/benchmark/storage.d.ts +0 -25
- package/dist/harness/session/testing/benchmark/storage.d.ts.map +0 -1
- package/dist/harness/session/testing/benchmark/storage.js +0 -114
- package/dist/harness/session/testing/benchmark/storage.js.map +0 -1
- package/dist/harness/session/testing/conformance/session-repo.d.ts +0 -23
- package/dist/harness/session/testing/conformance/session-repo.d.ts.map +0 -1
- package/dist/harness/session/testing/conformance/session-repo.js +0 -809
- package/dist/harness/session/testing/conformance/session-repo.js.map +0 -1
- package/dist/harness/session/testing/conformance/storage.d.ts +0 -4
- package/dist/harness/session/testing/conformance/storage.d.ts.map +0 -1
- package/dist/harness/session/testing/conformance/storage.js +0 -600
- package/dist/harness/session/testing/conformance/storage.js.map +0 -1
- package/dist/harness/session/testing/gating-storage.d.ts +0 -26
- package/dist/harness/session/testing/gating-storage.d.ts.map +0 -1
- package/dist/harness/session/testing/gating-storage.js +0 -103
- package/dist/harness/session/testing/gating-storage.js.map +0 -1
- package/dist/harness/session/testing/instrumented-storage.d.ts +0 -11
- package/dist/harness/session/testing/instrumented-storage.d.ts.map +0 -1
- package/dist/harness/session/testing/instrumented-storage.js +0 -19
- package/dist/harness/session/testing/instrumented-storage.js.map +0 -1
- package/dist/harness/session/testing/storage-decorator.d.ts +0 -20
- package/dist/harness/session/testing/storage-decorator.d.ts.map +0 -1
- package/dist/harness/session/testing/storage-decorator.js +0 -40
- package/dist/harness/session/testing/storage-decorator.js.map +0 -1
- package/dist/harness/session/values.d.ts +0 -95
- package/dist/harness/session/values.d.ts.map +0 -1
- package/dist/harness/session/values.js +0 -81
- package/dist/harness/session/values.js.map +0 -1
- package/dist/harness/utils/adaptive-publisher.d.ts +0 -24
- package/dist/harness/utils/adaptive-publisher.d.ts.map +0 -1
- package/dist/harness/utils/adaptive-publisher.js +0 -79
- package/dist/harness/utils/adaptive-publisher.js.map +0 -1
- package/dist/harness/utils/output-capture.d.ts +0 -31
- package/dist/harness/utils/output-capture.d.ts.map +0 -1
- package/dist/harness/utils/output-capture.js +0 -217
- package/dist/harness/utils/output-capture.js.map +0 -1
- package/dist/harness/utils/usage.d.ts +0 -4
- package/dist/harness/utils/usage.d.ts.map +0 -1
- package/dist/harness/utils/usage.js +0 -33
- package/dist/harness/utils/usage.js.map +0 -1
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
import { addUsage, emptyUsage } from "../utils/usage.js";
|
|
2
|
-
import { prepareStorageCommit, validateCommittedWrites, } from "./commit.js";
|
|
3
|
-
import { projectForkCurrentStateWrite, selectBranchFork } from "./fork-policy.js";
|
|
4
|
-
import { branchTip, laneConfig, laneState, list, resolveListReadOptions, value, } from "./values.js";
|
|
5
|
-
function physicalKey(namespace, key) {
|
|
6
|
-
return `${namespace}\u0000${key}`;
|
|
7
|
-
}
|
|
8
|
-
function compareKeys(left, right) {
|
|
9
|
-
const leftCodePoints = Array.from(left, (character) => character.codePointAt(0));
|
|
10
|
-
const rightCodePoints = Array.from(right, (character) => character.codePointAt(0));
|
|
11
|
-
const length = Math.min(leftCodePoints.length, rightCodePoints.length);
|
|
12
|
-
for (let index = 0; index < length; index++) {
|
|
13
|
-
const difference = leftCodePoints[index] - rightCodePoints[index];
|
|
14
|
-
if (difference !== 0)
|
|
15
|
-
return difference;
|
|
16
|
-
}
|
|
17
|
-
return leftCodePoints.length - rightCodePoints.length;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Complete materialized session state for MemoryStorage and JsonlStorage.
|
|
21
|
-
*
|
|
22
|
-
* This is intentionally unsuitable for database backends and long-running sessions that may not fit in memory.
|
|
23
|
-
* Those backends should query indexed durable state and update durable aggregates within each commit transaction.
|
|
24
|
-
*/
|
|
25
|
-
export class InMemoryStorageState {
|
|
26
|
-
constructor() {
|
|
27
|
-
this.entries = new Map();
|
|
28
|
-
this.entriesBySeq = [];
|
|
29
|
-
this.scalarValues = new Map();
|
|
30
|
-
this.listValues = new Map();
|
|
31
|
-
this.usage = new Map();
|
|
32
|
-
this.stats = { messageCount: 0, usage: emptyUsage() };
|
|
33
|
-
this.nextSeq = 1;
|
|
34
|
-
}
|
|
35
|
-
prepareCommit(writes, timestamp) {
|
|
36
|
-
const prepared = prepareStorageCommit(writes, this.nextSeq, timestamp);
|
|
37
|
-
this.validateCommitted(prepared.writes);
|
|
38
|
-
return prepared;
|
|
39
|
-
}
|
|
40
|
-
validateCommitted(writes) {
|
|
41
|
-
validateCommittedWrites(writes, this.nextSeq, {
|
|
42
|
-
hasEntryOrUsageId: (id) => this.entries.has(id) || this.usage.has(id),
|
|
43
|
-
hasEntryId: (id) => this.entries.has(id),
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
/** Apply writes already accepted by validateCommitted() and return the post-apply totals. */
|
|
47
|
-
applyValidated(writes) {
|
|
48
|
-
for (const write of writes) {
|
|
49
|
-
switch (write.kind) {
|
|
50
|
-
case "entry": {
|
|
51
|
-
const { kind: _kind, ...entry } = write;
|
|
52
|
-
this.entries.set(entry.id, entry);
|
|
53
|
-
this.entriesBySeq.push(entry);
|
|
54
|
-
if (entry.type === "message")
|
|
55
|
-
this.stats = { ...this.stats, messageCount: this.stats.messageCount + 1 };
|
|
56
|
-
break;
|
|
57
|
-
}
|
|
58
|
-
case "usage": {
|
|
59
|
-
const { kind: _kind, ...row } = write;
|
|
60
|
-
this.usage.set(row.id, row);
|
|
61
|
-
this.stats = { ...this.stats, usage: addUsage(this.stats.usage, row.usage) };
|
|
62
|
-
break;
|
|
63
|
-
}
|
|
64
|
-
case "value":
|
|
65
|
-
if (write.op === "delete")
|
|
66
|
-
this.scalarValues.delete(physicalKey(write.namespace, write.key));
|
|
67
|
-
else
|
|
68
|
-
this.applyValueSetOrListAppend(write);
|
|
69
|
-
break;
|
|
70
|
-
case "list":
|
|
71
|
-
if (write.op === "delete")
|
|
72
|
-
this.listValues.delete(physicalKey(write.namespace, write.key));
|
|
73
|
-
else
|
|
74
|
-
this.applyValueSetOrListAppend(write);
|
|
75
|
-
break;
|
|
76
|
-
}
|
|
77
|
-
this.nextSeq = write.seq + 1;
|
|
78
|
-
}
|
|
79
|
-
return this.stats;
|
|
80
|
-
}
|
|
81
|
-
createFork(options) {
|
|
82
|
-
const plan = this.selectForkPlan(options);
|
|
83
|
-
const isEntryCopied = (entryId) => {
|
|
84
|
-
if (plan.scope === "tree")
|
|
85
|
-
return true;
|
|
86
|
-
return plan.entryIds.has(entryId);
|
|
87
|
-
};
|
|
88
|
-
const destination = new InMemoryStorageState();
|
|
89
|
-
let messageCount = 0;
|
|
90
|
-
for (const entry of this.entriesBySeq) {
|
|
91
|
-
if (!isEntryCopied(entry.id))
|
|
92
|
-
continue;
|
|
93
|
-
destination.entries.set(entry.id, entry);
|
|
94
|
-
destination.entriesBySeq.push(entry);
|
|
95
|
-
if (entry.type === "message")
|
|
96
|
-
messageCount++;
|
|
97
|
-
}
|
|
98
|
-
destination.stats = { ...destination.stats, messageCount };
|
|
99
|
-
for (const stored of this.scalarValues.values()) {
|
|
100
|
-
const projected = projectForkCurrentStateWrite({
|
|
101
|
-
kind: "value",
|
|
102
|
-
op: "set",
|
|
103
|
-
seq: stored.seq,
|
|
104
|
-
namespace: stored.address.namespace,
|
|
105
|
-
key: stored.address.key,
|
|
106
|
-
value: stored.value,
|
|
107
|
-
}, plan, isEntryCopied);
|
|
108
|
-
if (projected !== undefined)
|
|
109
|
-
destination.applyValueSetOrListAppend(projected);
|
|
110
|
-
}
|
|
111
|
-
for (const stored of this.listValues.values()) {
|
|
112
|
-
for (const element of stored.elements) {
|
|
113
|
-
const projected = projectForkCurrentStateWrite({
|
|
114
|
-
kind: "list",
|
|
115
|
-
op: "append",
|
|
116
|
-
seq: element.seq,
|
|
117
|
-
namespace: stored.address.namespace,
|
|
118
|
-
key: stored.address.key,
|
|
119
|
-
value: element.value,
|
|
120
|
-
}, plan, isEntryCopied);
|
|
121
|
-
if (projected !== undefined)
|
|
122
|
-
destination.applyValueSetOrListAppend(projected);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
destination.nextSeq = this.nextSeq;
|
|
126
|
-
return destination;
|
|
127
|
-
}
|
|
128
|
-
selectForkPlan(options) {
|
|
129
|
-
if (options.scope === "tree")
|
|
130
|
-
return { scope: "tree" };
|
|
131
|
-
const entryIds = new Set();
|
|
132
|
-
const plan = selectBranchFork(options, {
|
|
133
|
-
tip: this.getValue(branchTip(options.branch))?.value,
|
|
134
|
-
getParent: (entryId) => this.entries.get(entryId)?.parentId,
|
|
135
|
-
selectEntry: (entryId) => entryIds.add(entryId),
|
|
136
|
-
});
|
|
137
|
-
if (this.getValue(laneConfig(options.branch)) === undefined ||
|
|
138
|
-
this.getValue(laneState(options.branch)) === undefined) {
|
|
139
|
-
throw new Error(`Source branch ${JSON.stringify(options.branch)} is not a configured AgentLane`);
|
|
140
|
-
}
|
|
141
|
-
return { ...plan, entryIds };
|
|
142
|
-
}
|
|
143
|
-
applyValueSetOrListAppend(write) {
|
|
144
|
-
const key = physicalKey(write.namespace, write.key);
|
|
145
|
-
if (write.kind === "value") {
|
|
146
|
-
this.scalarValues.set(key, {
|
|
147
|
-
address: value(write.namespace, write.key),
|
|
148
|
-
value: write.value,
|
|
149
|
-
seq: write.seq,
|
|
150
|
-
});
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
const element = { seq: write.seq, value: write.value };
|
|
154
|
-
const stored = this.listValues.get(key);
|
|
155
|
-
if (stored === undefined) {
|
|
156
|
-
this.listValues.set(key, {
|
|
157
|
-
address: list(write.namespace, write.key),
|
|
158
|
-
elements: [element],
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
else {
|
|
162
|
-
stored.elements.push(element);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
advanceNextSeq(nextSeq) {
|
|
166
|
-
if (!Number.isSafeInteger(nextSeq) || nextSeq < 1) {
|
|
167
|
-
throw new Error(`Invalid storage sequence high-water mark: ${nextSeq}`);
|
|
168
|
-
}
|
|
169
|
-
this.nextSeq = Math.max(this.nextSeq, nextSeq);
|
|
170
|
-
}
|
|
171
|
-
getEntries(ids) {
|
|
172
|
-
const found = new Map();
|
|
173
|
-
for (const id of ids) {
|
|
174
|
-
const entry = this.entries.get(id);
|
|
175
|
-
if (entry !== undefined)
|
|
176
|
-
found.set(id, entry);
|
|
177
|
-
}
|
|
178
|
-
return found;
|
|
179
|
-
}
|
|
180
|
-
getValue(address) {
|
|
181
|
-
return this.scalarValues.get(physicalKey(address.namespace, address.key));
|
|
182
|
-
}
|
|
183
|
-
scanValues(prefix) {
|
|
184
|
-
return [...this.scalarValues.values()]
|
|
185
|
-
.filter((stored) => stored.address.namespace === prefix.namespace && stored.address.key.startsWith(prefix.key))
|
|
186
|
-
.sort((left, right) => compareKeys(left.address.key, right.address.key));
|
|
187
|
-
}
|
|
188
|
-
readList(address, options) {
|
|
189
|
-
const resolved = resolveListReadOptions(options);
|
|
190
|
-
const elements = this.listValues.get(physicalKey(address.namespace, address.key))?.elements ?? [];
|
|
191
|
-
const filtered = elements.filter((element) => {
|
|
192
|
-
if (resolved.cursor === undefined)
|
|
193
|
-
return true;
|
|
194
|
-
return resolved.order === "asc" ? element.seq > resolved.cursor.seq : element.seq < resolved.cursor.seq;
|
|
195
|
-
});
|
|
196
|
-
const ordered = resolved.order === "asc" ? filtered : [...filtered].reverse();
|
|
197
|
-
return ordered.slice(0, resolved.limit);
|
|
198
|
-
}
|
|
199
|
-
scanBranch(query) {
|
|
200
|
-
const start = this.entries.get(query.start);
|
|
201
|
-
if (start === undefined)
|
|
202
|
-
throw new Error(`Unknown branch start: ${query.start}`);
|
|
203
|
-
const path = [];
|
|
204
|
-
let entry = start;
|
|
205
|
-
while (entry !== undefined) {
|
|
206
|
-
path.push(entry);
|
|
207
|
-
if (entry.parentId === null)
|
|
208
|
-
break;
|
|
209
|
-
entry = this.entries.get(entry.parentId);
|
|
210
|
-
if (entry === undefined)
|
|
211
|
-
throw new Error("Corrupt branch: missing parent");
|
|
212
|
-
}
|
|
213
|
-
if (query.order === "oldestFirst")
|
|
214
|
-
path.reverse();
|
|
215
|
-
const stopped = [];
|
|
216
|
-
for (const candidate of path) {
|
|
217
|
-
stopped.push(candidate);
|
|
218
|
-
if (candidate.id === query.stopAtId || candidate.type === query.stopAtType)
|
|
219
|
-
break;
|
|
220
|
-
}
|
|
221
|
-
const filtered = stopped
|
|
222
|
-
.filter((candidate) => query.type === undefined || candidate.type === query.type)
|
|
223
|
-
.filter((candidate) => query.customType === undefined || candidate.customType === query.customType)
|
|
224
|
-
.filter((candidate) => query.cursor === undefined ||
|
|
225
|
-
(query.order === "oldestFirst" ? candidate.seq > query.cursor.seq : candidate.seq < query.cursor.seq));
|
|
226
|
-
return query.limit === undefined ? filtered : filtered.slice(0, Math.max(0, query.limit));
|
|
227
|
-
}
|
|
228
|
-
scanBranchStructure(query) {
|
|
229
|
-
return this.scanBranch(query).map((entry) => ({
|
|
230
|
-
id: entry.id,
|
|
231
|
-
parentId: entry.parentId,
|
|
232
|
-
seq: entry.seq,
|
|
233
|
-
timestamp: entry.timestamp,
|
|
234
|
-
type: entry.type,
|
|
235
|
-
...(entry.customType === undefined ? {} : { customType: entry.customType }),
|
|
236
|
-
}));
|
|
237
|
-
}
|
|
238
|
-
scanEntries(query) {
|
|
239
|
-
const limit = query.limit === undefined ? Number.POSITIVE_INFINITY : Math.max(0, Math.trunc(query.limit));
|
|
240
|
-
const entries = [];
|
|
241
|
-
const descending = query.order === "desc";
|
|
242
|
-
let index = descending ? this.entriesBySeq.length - 1 : 0;
|
|
243
|
-
while (index >= 0 && index < this.entriesBySeq.length && entries.length < limit) {
|
|
244
|
-
const entry = this.entriesBySeq[index];
|
|
245
|
-
if ((query.type === undefined || entry.type === query.type) &&
|
|
246
|
-
(query.customType === undefined || entry.customType === query.customType) &&
|
|
247
|
-
(query.fromSeq === undefined || entry.seq >= query.fromSeq) &&
|
|
248
|
-
(query.toSeq === undefined || entry.seq <= query.toSeq)) {
|
|
249
|
-
entries.push(entry);
|
|
250
|
-
}
|
|
251
|
-
index += descending ? -1 : 1;
|
|
252
|
-
}
|
|
253
|
-
return entries;
|
|
254
|
-
}
|
|
255
|
-
scanUsage(query) {
|
|
256
|
-
const rows = [...this.usage.values()]
|
|
257
|
-
.filter((row) => query.fromSeq === undefined || row.seq >= query.fromSeq)
|
|
258
|
-
.filter((row) => query.toSeq === undefined || row.seq <= query.toSeq)
|
|
259
|
-
.sort((left, right) => (query.order === "desc" ? right.seq - left.seq : left.seq - right.seq));
|
|
260
|
-
return query.limit === undefined ? rows : rows.slice(0, Math.max(0, query.limit));
|
|
261
|
-
}
|
|
262
|
-
getStats() {
|
|
263
|
-
return this.stats;
|
|
264
|
-
}
|
|
265
|
-
getNextSeq() {
|
|
266
|
-
return this.nextSeq;
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
//# sourceMappingURL=in-memory-storage-state.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"in-memory-storage-state.js","sourceRoot":"","sources":["../../../src/harness/session/in-memory-storage-state.ts"],"names":[],"mappings":"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","sourcesContent":["import { addUsage, emptyUsage } from \"../utils/usage.ts\";\nimport {\n\ttype CommittedListAppendWrite,\n\ttype CommittedValueSetWrite,\n\ttype CommittedWrite,\n\ttype PreparedCommit,\n\tprepareStorageCommit,\n\tvalidateCommittedWrites,\n} from \"./commit.ts\";\nimport { projectForkCurrentStateWrite, selectBranchFork } from \"./fork-policy.ts\";\n\nexport type {\n\tCommittedEntryWrite,\n\tCommittedListAppendWrite,\n\tCommittedListDeleteWrite,\n\tCommittedUsageWrite,\n\tCommittedValueDeleteWrite,\n\tCommittedValueSetWrite,\n\tCommittedWrite,\n\tPreparedCommit,\n} from \"./commit.ts\";\n\nimport type {\n\tEntry,\n\tEntryScan,\n\tEntryStructure,\n\tForkOptions,\n\tSessionStats,\n\tStorageBranchScan,\n\tUsageRow,\n\tUsageScan,\n\tWrite,\n} from \"./types.ts\";\nimport {\n\tbranchTip,\n\ttype ListElement,\n\ttype ListReadOptions,\n\tlaneConfig,\n\tlaneState,\n\tlist,\n\tresolveListReadOptions,\n\ttype StoredValue,\n\ttype Value,\n\ttype ValueList,\n\tvalue,\n} from \"./values.ts\";\n\ninterface StoredListSnapshot {\n\taddress: ValueList<unknown>;\n\telements: ListElement<unknown>[];\n}\n\ntype MemoryForkPlan =\n\t| { scope: \"tree\" }\n\t| { scope: \"branch\"; branch: string; destinationTip: string | null; entryIds: Set<string> };\n\nfunction physicalKey(namespace: string, key: string): string {\n\treturn `${namespace}\\u0000${key}`;\n}\n\nfunction compareKeys(left: string, right: string): number {\n\tconst leftCodePoints = Array.from(left, (character) => character.codePointAt(0)!);\n\tconst rightCodePoints = Array.from(right, (character) => character.codePointAt(0)!);\n\tconst length = Math.min(leftCodePoints.length, rightCodePoints.length);\n\tfor (let index = 0; index < length; index++) {\n\t\tconst difference = leftCodePoints[index]! - rightCodePoints[index]!;\n\t\tif (difference !== 0) return difference;\n\t}\n\treturn leftCodePoints.length - rightCodePoints.length;\n}\n\n/**\n * Complete materialized session state for MemoryStorage and JsonlStorage.\n *\n * This is intentionally unsuitable for database backends and long-running sessions that may not fit in memory.\n * Those backends should query indexed durable state and update durable aggregates within each commit transaction.\n */\nexport class InMemoryStorageState {\n\tprivate readonly entries: Map<string, Entry>;\n\tprivate readonly entriesBySeq: Entry[];\n\tprivate readonly scalarValues: Map<string, StoredValue<unknown>>;\n\tprivate readonly listValues: Map<string, StoredListSnapshot>;\n\tprivate readonly usage: Map<string, UsageRow>;\n\tprivate stats: SessionStats;\n\tprivate nextSeq: number;\n\n\tconstructor() {\n\t\tthis.entries = new Map();\n\t\tthis.entriesBySeq = [];\n\t\tthis.scalarValues = new Map();\n\t\tthis.listValues = new Map();\n\t\tthis.usage = new Map();\n\t\tthis.stats = { messageCount: 0, usage: emptyUsage() };\n\t\tthis.nextSeq = 1;\n\t}\n\n\tprepareCommit(writes: Write[], timestamp: number): PreparedCommit {\n\t\tconst prepared = prepareStorageCommit(writes, this.nextSeq, timestamp);\n\t\tthis.validateCommitted(prepared.writes);\n\t\treturn prepared;\n\t}\n\n\tvalidateCommitted(writes: readonly CommittedWrite[]): void {\n\t\tvalidateCommittedWrites(writes, this.nextSeq, {\n\t\t\thasEntryOrUsageId: (id) => this.entries.has(id) || this.usage.has(id),\n\t\t\thasEntryId: (id) => this.entries.has(id),\n\t\t});\n\t}\n\n\t/** Apply writes already accepted by validateCommitted() and return the post-apply totals. */\n\tapplyValidated(writes: readonly CommittedWrite[]): SessionStats {\n\t\tfor (const write of writes) {\n\t\t\tswitch (write.kind) {\n\t\t\t\tcase \"entry\": {\n\t\t\t\t\tconst { kind: _kind, ...entry } = write;\n\t\t\t\t\tthis.entries.set(entry.id, entry);\n\t\t\t\t\tthis.entriesBySeq.push(entry);\n\t\t\t\t\tif (entry.type === \"message\") this.stats = { ...this.stats, messageCount: this.stats.messageCount + 1 };\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"usage\": {\n\t\t\t\t\tconst { kind: _kind, ...row } = write;\n\t\t\t\t\tthis.usage.set(row.id, row);\n\t\t\t\t\tthis.stats = { ...this.stats, usage: addUsage(this.stats.usage, row.usage) };\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"value\":\n\t\t\t\t\tif (write.op === \"delete\") this.scalarValues.delete(physicalKey(write.namespace, write.key));\n\t\t\t\t\telse this.applyValueSetOrListAppend(write);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"list\":\n\t\t\t\t\tif (write.op === \"delete\") this.listValues.delete(physicalKey(write.namespace, write.key));\n\t\t\t\t\telse this.applyValueSetOrListAppend(write);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tthis.nextSeq = write.seq + 1;\n\t\t}\n\t\treturn this.stats;\n\t}\n\n\tcreateFork(options: ForkOptions): InMemoryStorageState {\n\t\tconst plan = this.selectForkPlan(options);\n\n\t\tconst isEntryCopied = (entryId: string): boolean => {\n\t\t\tif (plan.scope === \"tree\") return true;\n\t\t\treturn plan.entryIds.has(entryId);\n\t\t};\n\t\tconst destination = new InMemoryStorageState();\n\t\tlet messageCount = 0;\n\t\tfor (const entry of this.entriesBySeq) {\n\t\t\tif (!isEntryCopied(entry.id)) continue;\n\t\t\tdestination.entries.set(entry.id, entry);\n\t\t\tdestination.entriesBySeq.push(entry);\n\t\t\tif (entry.type === \"message\") messageCount++;\n\t\t}\n\t\tdestination.stats = { ...destination.stats, messageCount };\n\n\t\tfor (const stored of this.scalarValues.values()) {\n\t\t\tconst projected = projectForkCurrentStateWrite(\n\t\t\t\t{\n\t\t\t\t\tkind: \"value\",\n\t\t\t\t\top: \"set\",\n\t\t\t\t\tseq: stored.seq,\n\t\t\t\t\tnamespace: stored.address.namespace,\n\t\t\t\t\tkey: stored.address.key,\n\t\t\t\t\tvalue: stored.value,\n\t\t\t\t},\n\t\t\t\tplan,\n\t\t\t\tisEntryCopied,\n\t\t\t);\n\t\t\tif (projected !== undefined) destination.applyValueSetOrListAppend(projected);\n\t\t}\n\n\t\tfor (const stored of this.listValues.values()) {\n\t\t\tfor (const element of stored.elements) {\n\t\t\t\tconst projected = projectForkCurrentStateWrite(\n\t\t\t\t\t{\n\t\t\t\t\t\tkind: \"list\",\n\t\t\t\t\t\top: \"append\",\n\t\t\t\t\t\tseq: element.seq,\n\t\t\t\t\t\tnamespace: stored.address.namespace,\n\t\t\t\t\t\tkey: stored.address.key,\n\t\t\t\t\t\tvalue: element.value,\n\t\t\t\t\t},\n\t\t\t\t\tplan,\n\t\t\t\t\tisEntryCopied,\n\t\t\t\t);\n\t\t\t\tif (projected !== undefined) destination.applyValueSetOrListAppend(projected);\n\t\t\t}\n\t\t}\n\t\tdestination.nextSeq = this.nextSeq;\n\t\treturn destination;\n\t}\n\n\tprivate selectForkPlan(options: ForkOptions): MemoryForkPlan {\n\t\tif (options.scope === \"tree\") return { scope: \"tree\" };\n\n\t\tconst entryIds = new Set<string>();\n\t\tconst plan = selectBranchFork(options, {\n\t\t\ttip: this.getValue(branchTip(options.branch))?.value,\n\t\t\tgetParent: (entryId) => this.entries.get(entryId)?.parentId,\n\t\t\tselectEntry: (entryId) => entryIds.add(entryId),\n\t\t});\n\t\tif (\n\t\t\tthis.getValue(laneConfig(options.branch)) === undefined ||\n\t\t\tthis.getValue(laneState(options.branch)) === undefined\n\t\t) {\n\t\t\tthrow new Error(`Source branch ${JSON.stringify(options.branch)} is not a configured AgentLane`);\n\t\t}\n\t\treturn { ...plan, entryIds };\n\t}\n\n\tprivate applyValueSetOrListAppend(write: CommittedValueSetWrite | CommittedListAppendWrite): void {\n\t\tconst key = physicalKey(write.namespace, write.key);\n\t\tif (write.kind === \"value\") {\n\t\t\tthis.scalarValues.set(key, {\n\t\t\t\taddress: value<unknown>(write.namespace, write.key),\n\t\t\t\tvalue: write.value,\n\t\t\t\tseq: write.seq,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tconst element = { seq: write.seq, value: write.value };\n\t\tconst stored = this.listValues.get(key);\n\t\tif (stored === undefined) {\n\t\t\tthis.listValues.set(key, {\n\t\t\t\taddress: list<unknown>(write.namespace, write.key),\n\t\t\t\telements: [element],\n\t\t\t});\n\t\t} else {\n\t\t\tstored.elements.push(element);\n\t\t}\n\t}\n\n\tadvanceNextSeq(nextSeq: number): void {\n\t\tif (!Number.isSafeInteger(nextSeq) || nextSeq < 1) {\n\t\t\tthrow new Error(`Invalid storage sequence high-water mark: ${nextSeq}`);\n\t\t}\n\t\tthis.nextSeq = Math.max(this.nextSeq, nextSeq);\n\t}\n\n\tgetEntries(ids: readonly string[]): Map<string, Entry> {\n\t\tconst found = new Map<string, Entry>();\n\t\tfor (const id of ids) {\n\t\t\tconst entry = this.entries.get(id);\n\t\t\tif (entry !== undefined) found.set(id, entry);\n\t\t}\n\t\treturn found;\n\t}\n\n\tgetValue<T>(address: Value<T>): StoredValue<T> | undefined {\n\t\treturn this.scalarValues.get(physicalKey(address.namespace, address.key)) as StoredValue<T> | undefined;\n\t}\n\n\tscanValues<T>(prefix: Value<T>): StoredValue<T>[] {\n\t\treturn [...this.scalarValues.values()]\n\t\t\t.filter((stored) => stored.address.namespace === prefix.namespace && stored.address.key.startsWith(prefix.key))\n\t\t\t.sort((left, right) => compareKeys(left.address.key, right.address.key)) as StoredValue<T>[];\n\t}\n\n\treadList<T>(address: ValueList<T>, options?: ListReadOptions): ListElement<T>[] {\n\t\tconst resolved = resolveListReadOptions(options);\n\t\tconst elements = this.listValues.get(physicalKey(address.namespace, address.key))?.elements ?? [];\n\t\tconst filtered = elements.filter((element) => {\n\t\t\tif (resolved.cursor === undefined) return true;\n\t\t\treturn resolved.order === \"asc\" ? element.seq > resolved.cursor.seq : element.seq < resolved.cursor.seq;\n\t\t});\n\t\tconst ordered = resolved.order === \"asc\" ? filtered : [...filtered].reverse();\n\t\treturn ordered.slice(0, resolved.limit) as ListElement<T>[];\n\t}\n\n\tscanBranch(query: StorageBranchScan): Entry[] {\n\t\tconst start = this.entries.get(query.start);\n\t\tif (start === undefined) throw new Error(`Unknown branch start: ${query.start}`);\n\n\t\tconst path: Entry[] = [];\n\t\tlet entry: Entry | undefined = start;\n\t\twhile (entry !== undefined) {\n\t\t\tpath.push(entry);\n\t\t\tif (entry.parentId === null) break;\n\t\t\tentry = this.entries.get(entry.parentId);\n\t\t\tif (entry === undefined) throw new Error(\"Corrupt branch: missing parent\");\n\t\t}\n\t\tif (query.order === \"oldestFirst\") path.reverse();\n\n\t\tconst stopped: Entry[] = [];\n\t\tfor (const candidate of path) {\n\t\t\tstopped.push(candidate);\n\t\t\tif (candidate.id === query.stopAtId || candidate.type === query.stopAtType) break;\n\t\t}\n\t\tconst filtered = stopped\n\t\t\t.filter((candidate) => query.type === undefined || candidate.type === query.type)\n\t\t\t.filter((candidate) => query.customType === undefined || candidate.customType === query.customType)\n\t\t\t.filter(\n\t\t\t\t(candidate) =>\n\t\t\t\t\tquery.cursor === undefined ||\n\t\t\t\t\t(query.order === \"oldestFirst\" ? candidate.seq > query.cursor.seq : candidate.seq < query.cursor.seq),\n\t\t\t);\n\t\treturn query.limit === undefined ? filtered : filtered.slice(0, Math.max(0, query.limit));\n\t}\n\n\tscanBranchStructure(query: StorageBranchScan): EntryStructure[] {\n\t\treturn this.scanBranch(query).map((entry) => ({\n\t\t\tid: entry.id,\n\t\t\tparentId: entry.parentId,\n\t\t\tseq: entry.seq,\n\t\t\ttimestamp: entry.timestamp,\n\t\t\ttype: entry.type,\n\t\t\t...(entry.customType === undefined ? {} : { customType: entry.customType }),\n\t\t}));\n\t}\n\n\tscanEntries(query: EntryScan): Entry[] {\n\t\tconst limit = query.limit === undefined ? Number.POSITIVE_INFINITY : Math.max(0, Math.trunc(query.limit));\n\t\tconst entries: Entry[] = [];\n\t\tconst descending = query.order === \"desc\";\n\t\tlet index = descending ? this.entriesBySeq.length - 1 : 0;\n\t\twhile (index >= 0 && index < this.entriesBySeq.length && entries.length < limit) {\n\t\t\tconst entry = this.entriesBySeq[index]!;\n\t\t\tif (\n\t\t\t\t(query.type === undefined || entry.type === query.type) &&\n\t\t\t\t(query.customType === undefined || entry.customType === query.customType) &&\n\t\t\t\t(query.fromSeq === undefined || entry.seq >= query.fromSeq) &&\n\t\t\t\t(query.toSeq === undefined || entry.seq <= query.toSeq)\n\t\t\t) {\n\t\t\t\tentries.push(entry);\n\t\t\t}\n\t\t\tindex += descending ? -1 : 1;\n\t\t}\n\t\treturn entries;\n\t}\n\n\tscanUsage(query: UsageScan): UsageRow[] {\n\t\tconst rows = [...this.usage.values()]\n\t\t\t.filter((row) => query.fromSeq === undefined || row.seq >= query.fromSeq)\n\t\t\t.filter((row) => query.toSeq === undefined || row.seq <= query.toSeq)\n\t\t\t.sort((left, right) => (query.order === \"desc\" ? right.seq - left.seq : left.seq - right.seq));\n\t\treturn query.limit === undefined ? rows : rows.slice(0, Math.max(0, query.limit));\n\t}\n\n\tgetStats(): SessionStats {\n\t\treturn this.stats;\n\t}\n\n\tgetNextSeq(): number {\n\t\treturn this.nextSeq;\n\t}\n}\n"]}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { Context } from "../../context.ts";
|
|
2
|
-
import type { FileSystem } from "../../types.ts";
|
|
3
|
-
import type { ForkOptions } from "../types.ts";
|
|
4
|
-
import type { LegacyV3Source } from "./legacy-v3.ts";
|
|
5
|
-
import { type JsonlStorageHeader } from "./types.ts";
|
|
6
|
-
interface JsonlForkSourceMetadata {
|
|
7
|
-
id: string;
|
|
8
|
-
cwd: string;
|
|
9
|
-
path: string;
|
|
10
|
-
}
|
|
11
|
-
/** Prepared fork input: format-4 file metadata or an already-normalized legacy source. */
|
|
12
|
-
export type JsonlForkInput = {
|
|
13
|
-
kind: "open";
|
|
14
|
-
metadata: JsonlForkSourceMetadata;
|
|
15
|
-
nextSeq: number;
|
|
16
|
-
} | {
|
|
17
|
-
kind: "closed";
|
|
18
|
-
metadata: JsonlForkSourceMetadata;
|
|
19
|
-
} | {
|
|
20
|
-
kind: "legacy-v3";
|
|
21
|
-
normalized: LegacyV3Source;
|
|
22
|
-
};
|
|
23
|
-
/**
|
|
24
|
-
* Index the source, validate the requested fork, and stream selected entries and current state
|
|
25
|
-
* into an atomically published format-4 destination without modifying the source.
|
|
26
|
-
* Preserve copied sequences and the source's nextSeq while excluding usage and open-operation state.
|
|
27
|
-
* Source files must not be replaced or edited between passes; later append-only writes are excluded
|
|
28
|
-
* by the captured sequence boundary or legacy record count. Does not open the destination Session.
|
|
29
|
-
*/
|
|
30
|
-
export declare function runJsonlFork(options: {
|
|
31
|
-
input: JsonlForkInput;
|
|
32
|
-
fileSystem: FileSystem;
|
|
33
|
-
destinationPath: string;
|
|
34
|
-
destinationHeader: Omit<JsonlStorageHeader, "nextSeq">;
|
|
35
|
-
fork: ForkOptions;
|
|
36
|
-
}, context: Context): Promise<void>;
|
|
37
|
-
export {};
|
|
38
|
-
//# sourceMappingURL=fork.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fork.d.ts","sourceRoot":"","sources":["../../../../src/harness/session/jsonl/fork.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAkB,MAAM,gBAAgB,CAAC;AAQjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAyB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAE5E,UAAU,uBAAuB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACb;AA4LD,0FAA0F;AAC1F,MAAM,MAAM,cAAc,GACvB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,uBAAuB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACpE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,uBAAuB,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,UAAU,EAAE,cAAc,CAAA;CAAE,CAAC;AA6ErD;;;;;;GAMG;AACH,wBAAsB,YAAY,CACjC,OAAO,EAAE;IACR,KAAK,EAAE,cAAc,CAAC;IACtB,UAAU,EAAE,UAAU,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC;IACvD,IAAI,EAAE,WAAW,CAAC;CAClB,EACD,OAAO,EAAE,OAAO,GACd,OAAO,CAAC,IAAI,CAAC,CAwBf"}
|
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
import { projectForkCurrentStateWrite, selectBranchFork } from "../fork-policy.js";
|
|
2
|
-
import { fileValue, parseJsonlTransaction, publishJsonl, readJsonlHeader } from "./io.js";
|
|
3
|
-
import { JSONL_STORAGE_VERSION } from "./types.js";
|
|
4
|
-
function physicalKey(namespace, key) {
|
|
5
|
-
return `${namespace}\u0000${key}`;
|
|
6
|
-
}
|
|
7
|
-
async function readJsonlForkHeader(reader, source, context) {
|
|
8
|
-
const parsed = await readJsonlHeader(reader, source.path, context);
|
|
9
|
-
if (parsed.format !== "v4") {
|
|
10
|
-
throw new Error(`Invalid JSONL storage ${source.path}: expected format 4 header`);
|
|
11
|
-
}
|
|
12
|
-
const header = parsed.header;
|
|
13
|
-
if (header.id !== source.id || header.cwd !== source.cwd) {
|
|
14
|
-
throw new Error(`Session identity does not match header: ${source.id}`);
|
|
15
|
-
}
|
|
16
|
-
if (header.storageVersion !== JSONL_STORAGE_VERSION) {
|
|
17
|
-
throw new Error(`Session ${source.id} uses unsupported storage version ${header.storageVersion}`);
|
|
18
|
-
}
|
|
19
|
-
return header;
|
|
20
|
-
}
|
|
21
|
-
function reachesForkBoundary(writes, stopBeforeSeq) {
|
|
22
|
-
if (stopBeforeSeq === undefined || writes.length === 0)
|
|
23
|
-
return false;
|
|
24
|
-
const first = writes[0];
|
|
25
|
-
const last = writes.at(-1);
|
|
26
|
-
if (first.seq >= stopBeforeSeq)
|
|
27
|
-
return true;
|
|
28
|
-
if (last.seq >= stopBeforeSeq) {
|
|
29
|
-
throw new Error(`JSONL transaction crosses fork sequence boundary ${stopBeforeSeq}`);
|
|
30
|
-
}
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
/** Read complete transactions after the header, never splitting a transaction at the sequence boundary. */
|
|
34
|
-
async function* readJsonlForkTransactions(reader, path, stopBeforeSeq, context) {
|
|
35
|
-
while (true) {
|
|
36
|
-
const line = fileValue(await reader.readLine(context), `Failed to read JSONL fork source ${path}`);
|
|
37
|
-
if (line === undefined || !line.terminated)
|
|
38
|
-
break;
|
|
39
|
-
const writes = parseJsonlTransaction(line.text);
|
|
40
|
-
if (reachesForkBoundary(writes, stopBeforeSeq))
|
|
41
|
-
break;
|
|
42
|
-
yield writes;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
class JsonlForkIndex {
|
|
46
|
-
constructor() {
|
|
47
|
-
this.currentScalarSeqs = new Map();
|
|
48
|
-
this.branchTips = new Map();
|
|
49
|
-
this.firstSurvivingListSeqs = new Map();
|
|
50
|
-
this.entryParents = new Map();
|
|
51
|
-
this.copiedEntryIds = new Set();
|
|
52
|
-
this.laneConfigs = new Set();
|
|
53
|
-
this.laneStates = new Set();
|
|
54
|
-
}
|
|
55
|
-
applyEntry(id, parentId) {
|
|
56
|
-
this.entryParents.set(id, parentId);
|
|
57
|
-
}
|
|
58
|
-
applyWrites(writes) {
|
|
59
|
-
for (const write of writes) {
|
|
60
|
-
switch (write.kind) {
|
|
61
|
-
case "entry":
|
|
62
|
-
this.applyEntry(write.id, write.parentId);
|
|
63
|
-
break;
|
|
64
|
-
case "value": {
|
|
65
|
-
const key = physicalKey(write.namespace, write.key);
|
|
66
|
-
if (write.op === "delete") {
|
|
67
|
-
this.currentScalarSeqs.delete(key);
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
this.currentScalarSeqs.set(key, write.seq);
|
|
71
|
-
}
|
|
72
|
-
this.applyLaneValue(write);
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
case "list": {
|
|
76
|
-
const key = physicalKey(write.namespace, write.key);
|
|
77
|
-
if (write.op === "delete")
|
|
78
|
-
this.firstSurvivingListSeqs.delete(key);
|
|
79
|
-
else if (!this.firstSurvivingListSeqs.has(key))
|
|
80
|
-
this.firstSurvivingListSeqs.set(key, write.seq);
|
|
81
|
-
break;
|
|
82
|
-
}
|
|
83
|
-
case "usage":
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
applyLaneValue(write) {
|
|
89
|
-
const present = write.op === "set";
|
|
90
|
-
switch (write.namespace) {
|
|
91
|
-
case "pi.branch.tip":
|
|
92
|
-
if (present)
|
|
93
|
-
this.branchTips.set(write.key, write.value);
|
|
94
|
-
else
|
|
95
|
-
this.branchTips.delete(write.key);
|
|
96
|
-
break;
|
|
97
|
-
case "pi.lane.config":
|
|
98
|
-
if (present)
|
|
99
|
-
this.laneConfigs.add(write.key);
|
|
100
|
-
else
|
|
101
|
-
this.laneConfigs.delete(write.key);
|
|
102
|
-
break;
|
|
103
|
-
case "pi.lane.state":
|
|
104
|
-
if (present)
|
|
105
|
-
this.laneStates.add(write.key);
|
|
106
|
-
else
|
|
107
|
-
this.laneStates.delete(write.key);
|
|
108
|
-
break;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
getBranchTip(branch) {
|
|
112
|
-
return this.branchTips.get(branch);
|
|
113
|
-
}
|
|
114
|
-
hasCompleteLane(branch) {
|
|
115
|
-
return this.laneConfigs.has(branch) && this.laneStates.has(branch);
|
|
116
|
-
}
|
|
117
|
-
getCurrentScalarSeq(namespace, key) {
|
|
118
|
-
return this.currentScalarSeqs.get(physicalKey(namespace, key));
|
|
119
|
-
}
|
|
120
|
-
isSurvivingListElement(namespace, key, seq) {
|
|
121
|
-
const firstSeq = this.firstSurvivingListSeqs.get(physicalKey(namespace, key));
|
|
122
|
-
return firstSeq !== undefined && seq >= firstSeq;
|
|
123
|
-
}
|
|
124
|
-
getParent(entryId) {
|
|
125
|
-
return this.entryParents.get(entryId);
|
|
126
|
-
}
|
|
127
|
-
selectEntry(entryId) {
|
|
128
|
-
this.copiedEntryIds.add(entryId);
|
|
129
|
-
}
|
|
130
|
-
isEntrySelected(entryId) {
|
|
131
|
-
return this.copiedEntryIds.has(entryId);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Validate the source lanes and return the fork plan.
|
|
136
|
-
*
|
|
137
|
-
* Branch scope updates JsonlForkIndex's selected entries via index.selectEntry(): it selects the
|
|
138
|
-
* destination tip and its ancestors after validating entryId and applying "at"/"before". The plan
|
|
139
|
-
* records the branch name and destination tip; the copy pass uses the index to filter entries and labels.
|
|
140
|
-
*
|
|
141
|
-
* Tree scope leaves the index's selected entries unchanged because the copy pass keeps every entry.
|
|
142
|
-
* Both formats use the same indexed metadata; this function performs no file I/O.
|
|
143
|
-
*/
|
|
144
|
-
function selectJsonlFork(index, options) {
|
|
145
|
-
if (options.scope === "tree")
|
|
146
|
-
return { scope: "tree" };
|
|
147
|
-
const plan = selectBranchFork(options, {
|
|
148
|
-
tip: index.getBranchTip(options.branch),
|
|
149
|
-
getParent: (entryId) => index.getParent(entryId),
|
|
150
|
-
selectEntry: (entryId) => index.selectEntry(entryId),
|
|
151
|
-
});
|
|
152
|
-
if (!index.hasCompleteLane(options.branch)) {
|
|
153
|
-
throw new Error(`Source branch ${JSON.stringify(options.branch)} is not a configured AgentLane`);
|
|
154
|
-
}
|
|
155
|
-
return plan;
|
|
156
|
-
}
|
|
157
|
-
function projectJsonlForkWrite(write, index, plan, isEntryCopied) {
|
|
158
|
-
switch (write.kind) {
|
|
159
|
-
case "entry":
|
|
160
|
-
return isEntryCopied(write.id) ? write : undefined;
|
|
161
|
-
case "value":
|
|
162
|
-
if (write.op !== "set")
|
|
163
|
-
return undefined;
|
|
164
|
-
if (index.getCurrentScalarSeq(write.namespace, write.key) !== write.seq)
|
|
165
|
-
return undefined;
|
|
166
|
-
return projectForkCurrentStateWrite(write, plan, isEntryCopied);
|
|
167
|
-
case "list":
|
|
168
|
-
if (write.op !== "append")
|
|
169
|
-
return undefined;
|
|
170
|
-
if (!index.isSurvivingListElement(write.namespace, write.key, write.seq))
|
|
171
|
-
return undefined;
|
|
172
|
-
return projectForkCurrentStateWrite(write, plan, isEntryCopied);
|
|
173
|
-
case "usage":
|
|
174
|
-
return undefined;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Build the index used to select branch ancestry and identify current scalar/list writes.
|
|
179
|
-
* Retains entry parent links, current-row sequences, and lane inventory, not entry payloads.
|
|
180
|
-
* Returns the index and the source's nextSeq high-water mark; no destination writes occur here.
|
|
181
|
-
*
|
|
182
|
-
* V3: LegacyV3Source already scanned the file and assigned normalized IDs/sequences. Copy its
|
|
183
|
-
* in-memory entry structures and derived values without reopening the file or calling writes(),
|
|
184
|
-
* which would unnecessarily parse payloads and reconstruct compaction tails before fork selection.
|
|
185
|
-
*
|
|
186
|
-
* V4: Open the source file and fold complete transactions into the index. For an open source,
|
|
187
|
-
* stop at the captured commit-queue sequence boundary. For a closed source, scan to EOF or a torn
|
|
188
|
-
* final line and derive nextSeq from the header and highest complete write sequence.
|
|
189
|
-
* The later copy pass reopens the source file in both formats and emits only selected writes.
|
|
190
|
-
*/
|
|
191
|
-
async function indexForkInput(input, fileSystem, context) {
|
|
192
|
-
const index = new JsonlForkIndex();
|
|
193
|
-
if (input.kind === "legacy-v3") {
|
|
194
|
-
for (const entry of input.normalized.entryStructures())
|
|
195
|
-
index.applyEntry(entry.id, entry.parentId);
|
|
196
|
-
index.applyWrites(input.normalized.values);
|
|
197
|
-
return { index, nextSeq: input.normalized.nextSeq };
|
|
198
|
-
}
|
|
199
|
-
const reader = fileValue(await fileSystem.openTextLineReader(input.metadata.path, context), `Failed to open JSONL fork source ${input.metadata.path}`);
|
|
200
|
-
try {
|
|
201
|
-
const header = await readJsonlForkHeader(reader, input.metadata, context);
|
|
202
|
-
const stopBeforeSeq = input.kind === "open" ? input.nextSeq : undefined;
|
|
203
|
-
let highestCompleteSeq = 0;
|
|
204
|
-
for await (const writes of readJsonlForkTransactions(reader, input.metadata.path, stopBeforeSeq, context)) {
|
|
205
|
-
index.applyWrites(writes);
|
|
206
|
-
if (writes.length !== 0)
|
|
207
|
-
highestCompleteSeq = writes.at(-1).seq;
|
|
208
|
-
}
|
|
209
|
-
return {
|
|
210
|
-
index,
|
|
211
|
-
nextSeq: input.kind === "open" ? input.nextSeq : Math.max(header.nextSeq ?? 1, highestCompleteSeq + 1),
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
finally {
|
|
215
|
-
await reader.close(context);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
/** Yield source writes; the caller owns final projection and filtering. */
|
|
219
|
-
async function* streamForkWrites(input, fileSystem, stopBeforeSeq, isEntryCopied, context) {
|
|
220
|
-
if (input.kind === "legacy-v3") {
|
|
221
|
-
// V3 filters early to avoid rereading messages and reconstructing unselected compaction tails.
|
|
222
|
-
// V4 already stores complete payloads, so it streams all captured writes below.
|
|
223
|
-
// Both formats still pass through projectJsonlForkWrite() for final filtering and transformation.
|
|
224
|
-
yield* input.normalized.writes(context, isEntryCopied);
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
const reader = fileValue(await fileSystem.openTextLineReader(input.metadata.path, context), `Failed to open JSONL fork source ${input.metadata.path}`);
|
|
228
|
-
try {
|
|
229
|
-
await readJsonlForkHeader(reader, input.metadata, context);
|
|
230
|
-
for await (const writes of readJsonlForkTransactions(reader, input.metadata.path, stopBeforeSeq, context)) {
|
|
231
|
-
yield* writes;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
finally {
|
|
235
|
-
await reader.close(context);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
/**
|
|
239
|
-
* Index the source, validate the requested fork, and stream selected entries and current state
|
|
240
|
-
* into an atomically published format-4 destination without modifying the source.
|
|
241
|
-
* Preserve copied sequences and the source's nextSeq while excluding usage and open-operation state.
|
|
242
|
-
* Source files must not be replaced or edited between passes; later append-only writes are excluded
|
|
243
|
-
* by the captured sequence boundary or legacy record count. Does not open the destination Session.
|
|
244
|
-
*/
|
|
245
|
-
export async function runJsonlFork(options, context) {
|
|
246
|
-
const { index, nextSeq } = await indexForkInput(options.input, options.fileSystem, context);
|
|
247
|
-
let fork = options.fork;
|
|
248
|
-
if (options.input.kind === "legacy-v3" && fork.scope === "branch" && fork.entryId !== undefined) {
|
|
249
|
-
fork = { ...fork, entryId: options.input.normalized.translateForkEntryId(fork.entryId) };
|
|
250
|
-
}
|
|
251
|
-
const plan = selectJsonlFork(index, fork);
|
|
252
|
-
const isEntryCopied = (entryId) => {
|
|
253
|
-
if (plan.scope === "tree")
|
|
254
|
-
return true;
|
|
255
|
-
return index.isEntrySelected(entryId);
|
|
256
|
-
};
|
|
257
|
-
await publishJsonl(options.fileSystem, options.destinationPath, { ...options.destinationHeader, nextSeq }, context, async (append) => {
|
|
258
|
-
const sourceWrites = streamForkWrites(options.input, options.fileSystem, nextSeq, isEntryCopied, context);
|
|
259
|
-
for await (const write of sourceWrites) {
|
|
260
|
-
const projected = projectJsonlForkWrite(write, index, plan, isEntryCopied);
|
|
261
|
-
if (projected !== undefined)
|
|
262
|
-
await append([projected]);
|
|
263
|
-
}
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
//# sourceMappingURL=fork.js.map
|