@code-yeongyu/senpi-agent-core 2026.9.12 → 2026.9.13
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 +4 -0
- package/dist/harness/agent-harness.d.ts +639 -384
- package/dist/harness/agent-harness.d.ts.map +1 -1
- package/dist/harness/agent-harness.js +5 -250
- package/dist/harness/agent-harness.js.map +1 -1
- package/dist/harness/compaction/branch-summarization.d.ts +12 -6
- package/dist/harness/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/harness/compaction/branch-summarization.js +33 -27
- package/dist/harness/compaction/branch-summarization.js.map +1 -1
- package/dist/harness/compaction/compaction.d.ts +30 -8
- package/dist/harness/compaction/compaction.d.ts.map +1 -1
- package/dist/harness/compaction/compaction.js +53 -64
- package/dist/harness/compaction/compaction.js.map +1 -1
- package/dist/harness/config.d.ts +9 -0
- package/dist/harness/config.d.ts.map +1 -0
- package/dist/harness/config.js +35 -0
- package/dist/harness/config.js.map +1 -0
- package/dist/harness/context.d.ts +9 -0
- package/dist/harness/context.d.ts.map +1 -0
- package/dist/harness/context.js +13 -0
- package/dist/harness/context.js.map +1 -0
- package/dist/harness/env/nodejs.d.ts +25 -28
- package/dist/harness/env/nodejs.d.ts.map +1 -1
- package/dist/harness/env/nodejs.js +368 -125
- package/dist/harness/env/nodejs.js.map +1 -1
- package/dist/harness/events.d.ts +20 -38
- package/dist/harness/events.d.ts.map +1 -1
- package/dist/harness/events.js +233 -55
- package/dist/harness/events.js.map +1 -1
- package/dist/harness/execution/assistant.d.ts +42 -0
- package/dist/harness/execution/assistant.d.ts.map +1 -0
- package/dist/harness/execution/assistant.js +82 -0
- package/dist/harness/execution/assistant.js.map +1 -0
- package/dist/harness/execution/effect-gate.d.ts +22 -0
- package/dist/harness/execution/effect-gate.d.ts.map +1 -0
- package/dist/harness/execution/effect-gate.js +48 -0
- package/dist/harness/execution/effect-gate.js.map +1 -0
- package/dist/harness/execution/tools.d.ts +67 -0
- package/dist/harness/execution/tools.d.ts.map +1 -0
- package/dist/harness/execution/tools.js +121 -0
- package/dist/harness/execution/tools.js.map +1 -0
- package/dist/harness/hooks.d.ts +38 -0
- package/dist/harness/hooks.d.ts.map +1 -0
- package/dist/harness/hooks.js +404 -0
- package/dist/harness/hooks.js.map +1 -0
- 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 +3 -2
- 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/result.d.ts +93 -0
- package/dist/harness/result.d.ts.map +1 -1
- package/dist/harness/result.js +39 -0
- package/dist/harness/result.js.map +1 -1
- package/dist/harness/runtime/drive/boundary.d.ts +28 -0
- package/dist/harness/runtime/drive/boundary.d.ts.map +1 -0
- package/dist/harness/runtime/drive/boundary.js +173 -0
- package/dist/harness/runtime/drive/boundary.js.map +1 -0
- package/dist/harness/runtime/drive/checkpoint.d.ts +8 -0
- package/dist/harness/runtime/drive/checkpoint.d.ts.map +1 -0
- package/dist/harness/runtime/drive/checkpoint.js +133 -0
- package/dist/harness/runtime/drive/checkpoint.js.map +1 -0
- package/dist/harness/runtime/drive/deferred.d.ts +15 -0
- package/dist/harness/runtime/drive/deferred.d.ts.map +1 -0
- package/dist/harness/runtime/drive/deferred.js +179 -0
- package/dist/harness/runtime/drive/deferred.js.map +1 -0
- package/dist/harness/runtime/drive/generation.d.ts +8 -0
- package/dist/harness/runtime/drive/generation.d.ts.map +1 -0
- package/dist/harness/runtime/drive/generation.js +205 -0
- package/dist/harness/runtime/drive/generation.js.map +1 -0
- package/dist/harness/runtime/drive/reconcile.d.ts +5 -0
- package/dist/harness/runtime/drive/reconcile.d.ts.map +1 -0
- package/dist/harness/runtime/drive/reconcile.js +140 -0
- package/dist/harness/runtime/drive/reconcile.js.map +1 -0
- package/dist/harness/runtime/drive/recovery.d.ts +8 -0
- package/dist/harness/runtime/drive/recovery.d.ts.map +1 -0
- package/dist/harness/runtime/drive/recovery.js +85 -0
- package/dist/harness/runtime/drive/recovery.js.map +1 -0
- package/dist/harness/runtime/drive/response.d.ts +23 -0
- package/dist/harness/runtime/drive/response.d.ts.map +1 -0
- package/dist/harness/runtime/drive/response.js +394 -0
- package/dist/harness/runtime/drive/response.js.map +1 -0
- package/dist/harness/runtime/drive/retry.d.ts +4 -0
- package/dist/harness/runtime/drive/retry.d.ts.map +1 -0
- package/dist/harness/runtime/drive/retry.js +34 -0
- package/dist/harness/runtime/drive/retry.js.map +1 -0
- package/dist/harness/runtime/drive/structural.d.ts +32 -0
- package/dist/harness/runtime/drive/structural.d.ts.map +1 -0
- package/dist/harness/runtime/drive/structural.js +929 -0
- package/dist/harness/runtime/drive/structural.js.map +1 -0
- package/dist/harness/runtime/drive/terminal.d.ts +7 -0
- package/dist/harness/runtime/drive/terminal.d.ts.map +1 -0
- package/dist/harness/runtime/drive/terminal.js +49 -0
- package/dist/harness/runtime/drive/terminal.js.map +1 -0
- package/dist/harness/runtime/drive/tool-placement.d.ts +14 -0
- package/dist/harness/runtime/drive/tool-placement.d.ts.map +1 -0
- package/dist/harness/runtime/drive/tool-placement.js +244 -0
- package/dist/harness/runtime/drive/tool-placement.js.map +1 -0
- package/dist/harness/runtime/drive/tools.d.ts +6 -0
- package/dist/harness/runtime/drive/tools.d.ts.map +1 -0
- package/dist/harness/runtime/drive/tools.js +449 -0
- package/dist/harness/runtime/drive/tools.js.map +1 -0
- package/dist/harness/runtime/drive.d.ts +6 -0
- package/dist/harness/runtime/drive.d.ts.map +1 -0
- package/dist/harness/runtime/drive.js +93 -0
- package/dist/harness/runtime/drive.js.map +1 -0
- package/dist/harness/runtime/harness.d.ts +59 -0
- package/dist/harness/runtime/harness.d.ts.map +1 -0
- package/dist/harness/runtime/harness.js +302 -0
- package/dist/harness/runtime/harness.js.map +1 -0
- package/dist/harness/runtime/index.d.ts +2 -0
- package/dist/harness/runtime/index.d.ts.map +1 -0
- package/dist/harness/runtime/index.js +2 -0
- package/dist/harness/runtime/index.js.map +1 -0
- package/dist/harness/runtime/lane.d.ts +118 -0
- package/dist/harness/runtime/lane.d.ts.map +1 -0
- package/dist/harness/runtime/lane.js +1559 -0
- package/dist/harness/runtime/lane.js.map +1 -0
- package/dist/harness/runtime/progress.d.ts +15 -0
- package/dist/harness/runtime/progress.d.ts.map +1 -0
- package/dist/harness/runtime/progress.js +66 -0
- package/dist/harness/runtime/progress.js.map +1 -0
- package/dist/harness/runtime/reducer.d.ts +5 -0
- package/dist/harness/runtime/reducer.d.ts.map +1 -0
- package/dist/harness/runtime/reducer.js +240 -0
- package/dist/harness/runtime/reducer.js.map +1 -0
- package/dist/harness/runtime/restore.d.ts +24 -0
- package/dist/harness/runtime/restore.d.ts.map +1 -0
- package/dist/harness/runtime/restore.js +117 -0
- package/dist/harness/runtime/restore.js.map +1 -0
- package/dist/harness/runtime/transcript.d.ts +21 -0
- package/dist/harness/runtime/transcript.d.ts.map +1 -0
- package/dist/harness/runtime/transcript.js +72 -0
- package/dist/harness/runtime/transcript.js.map +1 -0
- package/dist/harness/runtime/types.d.ts +105 -0
- package/dist/harness/runtime/types.d.ts.map +1 -0
- package/dist/harness/runtime/types.js +50 -0
- package/dist/harness/runtime/types.js.map +1 -0
- package/dist/harness/session/commit.d.ts +53 -0
- package/dist/harness/session/commit.d.ts.map +1 -0
- package/dist/harness/session/commit.js +57 -0
- package/dist/harness/session/commit.js.map +1 -0
- package/dist/harness/session/context.d.ts +6 -19
- package/dist/harness/session/context.d.ts.map +1 -1
- package/dist/harness/session/context.js +31 -53
- package/dist/harness/session/context.js.map +1 -1
- package/dist/harness/session/fork-policy.d.ts +21 -0
- package/dist/harness/session/fork-policy.d.ts.map +1 -0
- package/dist/harness/session/fork-policy.js +55 -0
- package/dist/harness/session/fork-policy.js.map +1 -0
- package/dist/harness/session/fork.d.ts +16 -0
- package/dist/harness/session/fork.d.ts.map +1 -0
- package/dist/harness/session/fork.js +79 -0
- package/dist/harness/session/fork.js.map +1 -0
- package/dist/harness/session/in-memory-storage-state.d.ts +39 -0
- package/dist/harness/session/in-memory-storage-state.d.ts.map +1 -0
- package/dist/harness/session/in-memory-storage-state.js +269 -0
- package/dist/harness/session/in-memory-storage-state.js.map +1 -0
- package/dist/harness/session/index.d.ts +9 -5
- package/dist/harness/session/index.d.ts.map +1 -1
- package/dist/harness/session/index.js +7 -4
- package/dist/harness/session/index.js.map +1 -1
- package/dist/harness/session/jsonl/codec.d.ts +19 -8
- package/dist/harness/session/jsonl/codec.d.ts.map +1 -1
- package/dist/harness/session/jsonl/codec.js +34 -219
- package/dist/harness/session/jsonl/codec.js.map +1 -1
- package/dist/harness/session/jsonl/fork.d.ts +38 -0
- package/dist/harness/session/jsonl/fork.d.ts.map +1 -0
- package/dist/harness/session/jsonl/fork.js +266 -0
- package/dist/harness/session/jsonl/fork.js.map +1 -0
- package/dist/harness/session/jsonl/index.d.ts +4 -0
- package/dist/harness/session/jsonl/index.d.ts.map +1 -0
- package/dist/harness/session/jsonl/index.js +4 -0
- package/dist/harness/session/jsonl/index.js.map +1 -0
- package/dist/harness/session/jsonl/io.d.ts +14 -0
- package/dist/harness/session/jsonl/io.d.ts.map +1 -0
- package/dist/harness/session/jsonl/io.js +86 -0
- package/dist/harness/session/jsonl/io.js.map +1 -0
- package/dist/harness/session/jsonl/legacy-v3.d.ts +44 -0
- package/dist/harness/session/jsonl/legacy-v3.d.ts.map +1 -0
- package/dist/harness/session/jsonl/legacy-v3.js +454 -0
- package/dist/harness/session/jsonl/legacy-v3.js.map +1 -0
- package/dist/harness/session/jsonl/repo.d.ts +27 -24
- package/dist/harness/session/jsonl/repo.d.ts.map +1 -1
- package/dist/harness/session/jsonl/repo.js +276 -151
- package/dist/harness/session/jsonl/repo.js.map +1 -1
- package/dist/harness/session/jsonl/storage.d.ts +39 -41
- package/dist/harness/session/jsonl/storage.d.ts.map +1 -1
- package/dist/harness/session/jsonl/storage.js +175 -196
- package/dist/harness/session/jsonl/storage.js.map +1 -1
- package/dist/harness/session/jsonl/types.d.ts +23 -22
- package/dist/harness/session/jsonl/types.d.ts.map +1 -1
- package/dist/harness/session/jsonl/types.js +2 -1
- package/dist/harness/session/jsonl/types.js.map +1 -1
- package/dist/harness/session/memory.d.ts +44 -40
- package/dist/harness/session/memory.d.ts.map +1 -1
- package/dist/harness/session/memory.js +333 -115
- package/dist/harness/session/memory.js.map +1 -1
- package/dist/harness/session/mutation-line.d.ts +8 -0
- package/dist/harness/session/mutation-line.d.ts.map +1 -0
- package/dist/harness/session/mutation-line.js +22 -0
- package/dist/harness/session/mutation-line.js.map +1 -0
- package/dist/harness/session/session.d.ts +78 -51
- package/dist/harness/session/session.d.ts.map +1 -1
- package/dist/harness/session/session.js +327 -207
- package/dist/harness/session/session.js.map +1 -1
- package/dist/harness/session/testing/benchmark/datasets.d.ts +12 -0
- package/dist/harness/session/testing/benchmark/datasets.d.ts.map +1 -0
- package/dist/harness/session/testing/benchmark/datasets.js +24 -0
- package/dist/harness/session/testing/benchmark/datasets.js.map +1 -0
- package/dist/harness/session/testing/benchmark/session-repo.d.ts +42 -0
- package/dist/harness/session/testing/benchmark/session-repo.d.ts.map +1 -0
- package/dist/harness/session/testing/benchmark/session-repo.js +127 -0
- package/dist/harness/session/testing/benchmark/session-repo.js.map +1 -0
- package/dist/harness/session/testing/benchmark/storage.d.ts +25 -0
- package/dist/harness/session/testing/benchmark/storage.d.ts.map +1 -0
- package/dist/harness/session/testing/benchmark/storage.js +114 -0
- package/dist/harness/session/testing/benchmark/storage.js.map +1 -0
- package/dist/harness/session/testing/conformance/session-repo.d.ts +23 -0
- package/dist/harness/session/testing/conformance/session-repo.d.ts.map +1 -0
- package/dist/harness/session/testing/conformance/session-repo.js +809 -0
- package/dist/harness/session/testing/conformance/session-repo.js.map +1 -0
- package/dist/harness/session/testing/conformance/storage.d.ts +4 -0
- package/dist/harness/session/testing/conformance/storage.d.ts.map +1 -0
- package/dist/harness/session/testing/conformance/storage.js +600 -0
- package/dist/harness/session/testing/conformance/storage.js.map +1 -0
- package/dist/harness/session/testing/gating-storage.d.ts +26 -0
- package/dist/harness/session/testing/gating-storage.d.ts.map +1 -0
- package/dist/harness/session/testing/gating-storage.js +103 -0
- package/dist/harness/session/testing/gating-storage.js.map +1 -0
- package/dist/harness/session/testing/index.d.ts +9 -2
- package/dist/harness/session/testing/index.d.ts.map +1 -1
- package/dist/harness/session/testing/index.js +8 -1
- package/dist/harness/session/testing/index.js.map +1 -1
- package/dist/harness/session/testing/instrumented-storage.d.ts +11 -0
- package/dist/harness/session/testing/instrumented-storage.d.ts.map +1 -0
- package/dist/harness/session/testing/instrumented-storage.js +19 -0
- package/dist/harness/session/testing/instrumented-storage.js.map +1 -0
- package/dist/harness/session/testing/storage-decorator.d.ts +20 -0
- package/dist/harness/session/testing/storage-decorator.d.ts.map +1 -0
- package/dist/harness/session/testing/storage-decorator.js +40 -0
- package/dist/harness/session/testing/storage-decorator.js.map +1 -0
- package/dist/harness/session/testing/types.d.ts +5 -7
- 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 +425 -265
- 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/session/values.d.ts +95 -0
- package/dist/harness/session/values.d.ts.map +1 -0
- package/dist/harness/session/values.js +81 -0
- package/dist/harness/session/values.js.map +1 -0
- package/dist/harness/skills.d.ts +3 -2
- package/dist/harness/skills.d.ts.map +1 -1
- package/dist/harness/skills.js +29 -26
- package/dist/harness/skills.js.map +1 -1
- package/dist/harness/telemetry.d.ts +64 -43
- package/dist/harness/telemetry.d.ts.map +1 -1
- package/dist/harness/telemetry.js +45 -26
- 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 +66 -93
- 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 +17 -13
- package/dist/harness/tools/edit.js.map +1 -1
- package/dist/harness/tools/file-mutation-queue.d.ts +2 -1
- 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 +3 -2
- 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 +2 -1
- package/dist/harness/tools/read.d.ts.map +1 -1
- package/dist/harness/tools/read.js +4 -6
- 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 +12 -8
- package/dist/harness/tools/write.js.map +1 -1
- package/dist/harness/types.d.ts +128 -45
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/utils/adaptive-publisher.d.ts +24 -0
- package/dist/harness/utils/adaptive-publisher.d.ts.map +1 -0
- package/dist/harness/utils/adaptive-publisher.js +79 -0
- package/dist/harness/utils/adaptive-publisher.js.map +1 -0
- package/dist/harness/utils/output-capture.d.ts +31 -0
- package/dist/harness/utils/output-capture.d.ts.map +1 -0
- package/dist/harness/utils/output-capture.js +217 -0
- package/dist/harness/utils/output-capture.js.map +1 -0
- package/dist/harness/utils/shell-output.d.ts +19 -5
- package/dist/harness/utils/shell-output.d.ts.map +1 -1
- package/dist/harness/utils/shell-output.js +65 -192
- package/dist/harness/utils/shell-output.js.map +1 -1
- package/dist/harness/utils/truncate.d.ts +1 -0
- 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/harness/utils/usage.d.ts +4 -0
- package/dist/harness/utils/usage.d.ts.map +1 -0
- package/dist/harness/utils/usage.js +33 -0
- package/dist/harness/utils/usage.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -6
- package/dist/index.js.map +1 -1
- package/dist/search/index.d.ts +24 -16
- 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/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +27 -6
- package/dist/harness/reducer.d.ts +0 -100
- package/dist/harness/reducer.d.ts.map +0 -1
- package/dist/harness/reducer.js +0 -420
- package/dist/harness/reducer.js.map +0 -1
- package/dist/harness/session/jsonl/errors.d.ts +0 -9
- package/dist/harness/session/jsonl/errors.d.ts.map +0 -1
- package/dist/harness/session/jsonl/errors.js +0 -18
- package/dist/harness/session/jsonl/errors.js.map +0 -1
- package/dist/harness/session/jsonl.d.ts +0 -3
- package/dist/harness/session/jsonl.d.ts.map +0 -1
- package/dist/harness/session/jsonl.js +0 -2
- package/dist/harness/session/jsonl.js.map +0 -1
- package/dist/harness/session/state.d.ts +0 -65
- package/dist/harness/session/state.d.ts.map +0 -1
- package/dist/harness/session/state.js +0 -320
- package/dist/harness/session/state.js.map +0 -1
- package/dist/harness/session/testing/conformance.d.ts +0 -4
- package/dist/harness/session/testing/conformance.d.ts.map +0 -1
- package/dist/harness/session/testing/conformance.js +0 -762
- package/dist/harness/session/testing/conformance.js.map +0 -1
- package/dist/search/scanning.d.ts +0 -29
- package/dist/search/scanning.d.ts.map +0 -1
- package/dist/search/scanning.js +0 -103
- package/dist/search/scanning.js.map +0 -1
|
@@ -1,762 +0,0 @@
|
|
|
1
|
-
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
2
|
-
if (value !== null && value !== void 0) {
|
|
3
|
-
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
4
|
-
var dispose, inner;
|
|
5
|
-
if (async) {
|
|
6
|
-
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
7
|
-
dispose = value[Symbol.asyncDispose];
|
|
8
|
-
}
|
|
9
|
-
if (dispose === void 0) {
|
|
10
|
-
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
11
|
-
dispose = value[Symbol.dispose];
|
|
12
|
-
if (async) inner = dispose;
|
|
13
|
-
}
|
|
14
|
-
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
15
|
-
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
16
|
-
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
17
|
-
}
|
|
18
|
-
else if (async) {
|
|
19
|
-
env.stack.push({ async: true });
|
|
20
|
-
}
|
|
21
|
-
return value;
|
|
22
|
-
};
|
|
23
|
-
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
24
|
-
return function (env) {
|
|
25
|
-
function fail(e) {
|
|
26
|
-
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
27
|
-
env.hasError = true;
|
|
28
|
-
}
|
|
29
|
-
var r, s = 0;
|
|
30
|
-
function next() {
|
|
31
|
-
while (r = env.stack.pop()) {
|
|
32
|
-
try {
|
|
33
|
-
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
34
|
-
if (r.dispose) {
|
|
35
|
-
var result = r.dispose.call(r.value);
|
|
36
|
-
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
37
|
-
}
|
|
38
|
-
else s |= 1;
|
|
39
|
-
}
|
|
40
|
-
catch (e) {
|
|
41
|
-
fail(e);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
45
|
-
if (env.hasError) throw env.error;
|
|
46
|
-
}
|
|
47
|
-
return next();
|
|
48
|
-
};
|
|
49
|
-
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
50
|
-
var e = new Error(message);
|
|
51
|
-
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
|
-
});
|
|
53
|
-
import { deepStrictEqual, ok, rejects, strictEqual } from "node:assert/strict";
|
|
54
|
-
function createUserMessage(text) {
|
|
55
|
-
return {
|
|
56
|
-
role: "user",
|
|
57
|
-
content: [{ type: "text", text }],
|
|
58
|
-
timestamp: 1,
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
function createAssistantMessage(text) {
|
|
62
|
-
return {
|
|
63
|
-
role: "assistant",
|
|
64
|
-
content: [{ type: "text", text }],
|
|
65
|
-
api: "anthropic-messages",
|
|
66
|
-
provider: "anthropic",
|
|
67
|
-
model: "claude-sonnet-4-5",
|
|
68
|
-
usage: {
|
|
69
|
-
input: 0,
|
|
70
|
-
output: 0,
|
|
71
|
-
cacheRead: 0,
|
|
72
|
-
cacheWrite: 0,
|
|
73
|
-
totalTokens: 0,
|
|
74
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
75
|
-
},
|
|
76
|
-
stopReason: "stop",
|
|
77
|
-
timestamp: 1,
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
function operationStarted(id, { lane, kind }) {
|
|
81
|
-
let intent;
|
|
82
|
-
switch (kind) {
|
|
83
|
-
case "run":
|
|
84
|
-
intent = { kind, originalPrompt: [], initialMessages: [] };
|
|
85
|
-
break;
|
|
86
|
-
case "compaction":
|
|
87
|
-
intent = { kind, resultEntryId: `${id}-result` };
|
|
88
|
-
break;
|
|
89
|
-
case "navigation":
|
|
90
|
-
intent = { kind, targetId: null, summarize: false };
|
|
91
|
-
break;
|
|
92
|
-
}
|
|
93
|
-
return { type: "operation_started", id, lane, sourceLeafId: null, intent };
|
|
94
|
-
}
|
|
95
|
-
async function entryIds(entries) {
|
|
96
|
-
return (await entries).map((entry) => entry.id);
|
|
97
|
-
}
|
|
98
|
-
async function rejectsWithCode(operation, code) {
|
|
99
|
-
await rejects(operation, (error) => typeof error === "object" && error !== null && "code" in error && error.code === code, `Expected SessionError with code ${code}`);
|
|
100
|
-
}
|
|
101
|
-
function createCase(factory, group, name, test) {
|
|
102
|
-
return {
|
|
103
|
-
group,
|
|
104
|
-
name,
|
|
105
|
-
async run() {
|
|
106
|
-
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
107
|
-
try {
|
|
108
|
-
const fixture = __addDisposableResource(env_1, await factory(), true);
|
|
109
|
-
await test(fixture.repository);
|
|
110
|
-
}
|
|
111
|
-
catch (e_1) {
|
|
112
|
-
env_1.error = e_1;
|
|
113
|
-
env_1.hasError = true;
|
|
114
|
-
}
|
|
115
|
-
finally {
|
|
116
|
-
const result_1 = __disposeResources(env_1);
|
|
117
|
-
if (result_1)
|
|
118
|
-
await result_1;
|
|
119
|
-
}
|
|
120
|
-
},
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
/** Creates the session backend conformance cases. Each case creates and disposes its own fixture. */
|
|
124
|
-
export function createSessionBackendConformance(factory) {
|
|
125
|
-
return [
|
|
126
|
-
createCase(factory, "entries and lanes", "assigns parents and one sequence across every mutation", async (repository) => {
|
|
127
|
-
const session = await repository.create({ id: "session" });
|
|
128
|
-
const root = await session.appendEntry({ type: "message", id: "root", message: createUserMessage("root") }, "main");
|
|
129
|
-
await session.createLane("thread", root.id);
|
|
130
|
-
const child = await session.appendEntry({ type: "custom", id: "child", customType: "note", data: { value: 1 } }, "thread");
|
|
131
|
-
const record = await session.appendRecord(operationStarted("run", { lane: "thread", kind: "run" }));
|
|
132
|
-
await session.setName("Example");
|
|
133
|
-
await session.setLabel(root.id, "checkpoint");
|
|
134
|
-
await session.moveLane("main", child.id);
|
|
135
|
-
deepStrictEqual({ parentId: root.parentId, seq: root.seq }, { parentId: null, seq: 1 });
|
|
136
|
-
deepStrictEqual({ parentId: child.parentId, seq: child.seq }, { parentId: "root", seq: 3 });
|
|
137
|
-
strictEqual(record.seq, 4);
|
|
138
|
-
for (const timestamp of [root.timestamp, child.timestamp, record.timestamp]) {
|
|
139
|
-
ok(Number.isSafeInteger(timestamp) && timestamp >= 0, "storage-assigned timestamps must be Unix milliseconds");
|
|
140
|
-
}
|
|
141
|
-
deepStrictEqual((await session.getLog()).map((item) => [item.kind, item.seq]), [
|
|
142
|
-
["entry", 1],
|
|
143
|
-
["lane", 2],
|
|
144
|
-
["entry", 3],
|
|
145
|
-
["record", 4],
|
|
146
|
-
["fact", 5],
|
|
147
|
-
["fact", 6],
|
|
148
|
-
["lane", 7],
|
|
149
|
-
]);
|
|
150
|
-
deepStrictEqual(await session.getLanes(), [
|
|
151
|
-
{ lane: "main", leafId: "child" },
|
|
152
|
-
{ lane: "thread", leafId: "child" },
|
|
153
|
-
]);
|
|
154
|
-
}),
|
|
155
|
-
createCase(factory, "records and log", "commits records and lane moves as separate mutations", async (repository) => {
|
|
156
|
-
const session = await repository.create({ id: "session" });
|
|
157
|
-
const root = await session.appendEntry({ type: "message", id: "root", message: createUserMessage("root") }, "main");
|
|
158
|
-
const finished = await session.appendRecord({
|
|
159
|
-
type: "operation_finished",
|
|
160
|
-
id: "finish",
|
|
161
|
-
lane: "main",
|
|
162
|
-
runId: "run",
|
|
163
|
-
outcome: "completed",
|
|
164
|
-
});
|
|
165
|
-
strictEqual(finished.seq, 2);
|
|
166
|
-
deepStrictEqual(await session.getLanes(), [{ lane: "main", leafId: "root" }]);
|
|
167
|
-
await session.moveLane("main", null);
|
|
168
|
-
deepStrictEqual(await session.getLanes(), [{ lane: "main", leafId: null }]);
|
|
169
|
-
deepStrictEqual(await session.getLog(), [
|
|
170
|
-
{ kind: "entry", seq: 1, entry: root },
|
|
171
|
-
{ kind: "record", seq: 2, record: finished },
|
|
172
|
-
{ kind: "lane", seq: 3, lane: "main", leafId: null },
|
|
173
|
-
]);
|
|
174
|
-
await rejectsWithCode(session.moveLane("main", "missing"), "not_found");
|
|
175
|
-
strictEqual((await session.findRecords()).length, 1);
|
|
176
|
-
deepStrictEqual((await session.getLog()).map((item) => item.seq), [1, 2, 3]);
|
|
177
|
-
}),
|
|
178
|
-
createCase(factory, "entries and lanes", "rejects duplicate ids without changing state", async (repository) => {
|
|
179
|
-
const session = await repository.create({ id: "session" });
|
|
180
|
-
await session.appendEntry({ type: "message", id: "shared", message: createUserMessage("root") }, "main");
|
|
181
|
-
await rejectsWithCode(session.appendRecord(operationStarted("shared", { lane: "main", kind: "run" })), "already_exists");
|
|
182
|
-
await session.appendRecord(operationStarted("run", { lane: "main", kind: "run" }));
|
|
183
|
-
await rejectsWithCode(session.appendEntry({ type: "custom", id: "run", customType: "note" }, "main"), "already_exists");
|
|
184
|
-
deepStrictEqual((await session.getLog()).map((item) => item.seq), [1, 2]);
|
|
185
|
-
}),
|
|
186
|
-
createCase(factory, "entries and lanes", "isolates lanes while sharing the tree", async (repository) => {
|
|
187
|
-
const session = await repository.create({ id: "session" });
|
|
188
|
-
await session.appendEntry({ type: "message", id: "root", message: createUserMessage("root") }, "main");
|
|
189
|
-
await session.createLane("thread", "root");
|
|
190
|
-
await session.appendEntry({ type: "message", id: "main-child", message: createUserMessage("main") }, "main");
|
|
191
|
-
await session.appendEntry({ type: "message", id: "thread-child", message: createUserMessage("thread") }, "thread");
|
|
192
|
-
deepStrictEqual(await session.getLanes(), [
|
|
193
|
-
{ lane: "main", leafId: "main-child" },
|
|
194
|
-
{ lane: "thread", leafId: "thread-child" },
|
|
195
|
-
]);
|
|
196
|
-
deepStrictEqual(await entryIds(session.findEntriesOnBranch({ start: "main-child", order: "oldestFirst" })), [
|
|
197
|
-
"root",
|
|
198
|
-
"main-child",
|
|
199
|
-
]);
|
|
200
|
-
deepStrictEqual(await entryIds(session.findEntriesOnBranch({ start: "thread-child", order: "oldestFirst" })), [
|
|
201
|
-
"root",
|
|
202
|
-
"thread-child",
|
|
203
|
-
]);
|
|
204
|
-
}),
|
|
205
|
-
createCase(factory, "queries and facts", "rejects invalid queries before empty reads", async (repository) => {
|
|
206
|
-
const session = await repository.create({ id: "invalid-queries" });
|
|
207
|
-
await session.createLane("thread", null);
|
|
208
|
-
const thread = session.view("thread");
|
|
209
|
-
await rejectsWithCode(session.findEntries({ limit: 0 }), "invalid_query");
|
|
210
|
-
await rejectsWithCode(session.findEntry({ limit: 0 }), "invalid_query");
|
|
211
|
-
await rejectsWithCode(session.findEntriesOnBranch({ limit: 0 }), "invalid_query");
|
|
212
|
-
await rejectsWithCode(thread.findEntriesOnBranch({ cursor: { afterSeq: -1 } }), "invalid_query");
|
|
213
|
-
await rejectsWithCode(thread.findEntryOnBranch({ limit: 0 }), "invalid_query");
|
|
214
|
-
await rejectsWithCode(session.findRecords({ limit: 0 }), "invalid_query");
|
|
215
|
-
await rejectsWithCode(session.findRecords({ operationKind: "run" }), "invalid_query");
|
|
216
|
-
await rejectsWithCode(session.findRecords({ type: "step_attempt", operationKind: "run" }), "invalid_query");
|
|
217
|
-
await rejectsWithCode(session.findOpenOperations("main", { limit: 0 }), "invalid_query");
|
|
218
|
-
await rejectsWithCode(session.findOpenOperations("main", { limit: -1 }), "invalid_query");
|
|
219
|
-
await rejectsWithCode(session.getLog({ afterSeq: -1 }), "invalid_query");
|
|
220
|
-
}),
|
|
221
|
-
createCase(factory, "queries and facts", "supports bounded filtered and cursor-based queries", async (repository) => {
|
|
222
|
-
const session = await repository.create({ id: "session" });
|
|
223
|
-
await session.appendEntry({ type: "message", id: "root", message: createUserMessage("root") }, "main");
|
|
224
|
-
await session.appendEntry({ type: "custom", id: "old-note", customType: "note", data: 1 }, "main");
|
|
225
|
-
await session.appendEntry({ type: "compaction", id: "compact", summary: "summary", retainedTail: [], tokensBefore: 10 }, "main");
|
|
226
|
-
await session.appendEntry({ type: "custom", id: "new-note", customType: "note", data: 2 }, "main");
|
|
227
|
-
await session.appendEntry({ type: "message", id: "tail", message: createAssistantMessage("tail") }, "main");
|
|
228
|
-
deepStrictEqual(await entryIds(session.findEntries()), ["tail", "new-note", "compact", "old-note", "root"]);
|
|
229
|
-
deepStrictEqual(await entryIds(session.findEntries({ order: "oldestFirst", cursor: { afterSeq: 2 }, limit: 2 })), ["compact", "new-note"]);
|
|
230
|
-
deepStrictEqual(await entryIds(session.findEntries({ customType: "note" })), ["new-note", "old-note"]);
|
|
231
|
-
deepStrictEqual(await entryIds(session.findEntriesOnBranch({ start: "tail", customType: "note", limit: 1 })), ["new-note"]);
|
|
232
|
-
deepStrictEqual(await entryIds(session.findEntriesOnBranch({ start: "tail", stopAtType: "compaction", type: "message" })), ["tail"]);
|
|
233
|
-
deepStrictEqual(await entryIds(session.findEntriesOnBranch({ start: "tail", stopAtId: "tail", type: "custom" })), []);
|
|
234
|
-
deepStrictEqual(await entryIds(session.findEntriesOnBranch({ start: "tail", stopAtType: "custom", order: "oldestFirst" })), ["root", "old-note"]);
|
|
235
|
-
await rejectsWithCode(session.findEntries({ limit: 0 }), "invalid_query");
|
|
236
|
-
await rejectsWithCode(session.findEntriesOnBranch({ start: "missing" }), "not_found");
|
|
237
|
-
}),
|
|
238
|
-
createCase(factory, "records and log", "keeps lane names permanent with their recovery records", async (repository) => {
|
|
239
|
-
const session = await repository.create({ id: "session" });
|
|
240
|
-
await session.createLane("thread", null);
|
|
241
|
-
await session.appendRecord(operationStarted("old-run", { lane: "thread", kind: "run" }));
|
|
242
|
-
await session.appendRecord({
|
|
243
|
-
type: "queue_enqueued",
|
|
244
|
-
id: "old-next-run",
|
|
245
|
-
lane: "thread",
|
|
246
|
-
queue: "nextRun",
|
|
247
|
-
target: { type: "message", id: "queued-message", message: createUserMessage("queued") },
|
|
248
|
-
});
|
|
249
|
-
deepStrictEqual((await session.findRecords({ lane: "thread" })).map((record) => record.id), ["old-next-run", "old-run"]);
|
|
250
|
-
deepStrictEqual((await session.getLog()).flatMap((item) => (item.kind === "record" ? [item.record.id] : [])), ["old-run", "old-next-run"]);
|
|
251
|
-
await rejectsWithCode(session.createLane("thread", null), "already_exists");
|
|
252
|
-
}),
|
|
253
|
-
createCase(factory, "records and log", "persists queue cancellation without consuming its target", async (repository) => {
|
|
254
|
-
const session = await repository.create({ id: "session" });
|
|
255
|
-
const enqueued = await session.appendRecord({
|
|
256
|
-
type: "queue_enqueued",
|
|
257
|
-
id: "enqueue",
|
|
258
|
-
lane: "main",
|
|
259
|
-
queue: "nextRun",
|
|
260
|
-
target: { type: "message", id: "queued-message", message: createUserMessage("queued") },
|
|
261
|
-
});
|
|
262
|
-
const cancelled = await session.appendRecord({
|
|
263
|
-
type: "queue_cancelled",
|
|
264
|
-
id: "cancel",
|
|
265
|
-
lane: "main",
|
|
266
|
-
entryId: "queued-message",
|
|
267
|
-
});
|
|
268
|
-
deepStrictEqual({ seq: cancelled.seq, entryId: cancelled.entryId }, { seq: 2, entryId: "queued-message" });
|
|
269
|
-
strictEqual("runId" in cancelled, false);
|
|
270
|
-
strictEqual(await session.getEntry("queued-message"), undefined);
|
|
271
|
-
const cancellations = await session.findRecords({ type: "queue_cancelled" });
|
|
272
|
-
strictEqual(cancellations[0]?.entryId, "queued-message");
|
|
273
|
-
deepStrictEqual(cancellations, [cancelled]);
|
|
274
|
-
deepStrictEqual(await session.getLog(), [
|
|
275
|
-
{ kind: "record", seq: enqueued.seq, record: enqueued },
|
|
276
|
-
{ kind: "record", seq: cancelled.seq, record: cancelled },
|
|
277
|
-
]);
|
|
278
|
-
}),
|
|
279
|
-
createCase(factory, "records and log", "filters records by lane type run sequence and order", async (repository) => {
|
|
280
|
-
const session = await repository.create({ id: "session" });
|
|
281
|
-
await session.appendRecord(operationStarted("run-1", { lane: "main", kind: "run" }));
|
|
282
|
-
await session.appendRecord({
|
|
283
|
-
type: "step_attempt",
|
|
284
|
-
id: "attempt-1",
|
|
285
|
-
lane: "main",
|
|
286
|
-
runId: "run-1",
|
|
287
|
-
step: "assistant",
|
|
288
|
-
attempt: 1,
|
|
289
|
-
resultEntryId: "assistant-1",
|
|
290
|
-
});
|
|
291
|
-
await session.createLane("thread", null);
|
|
292
|
-
await session.appendRecord(operationStarted("run-2", { lane: "thread", kind: "run" }));
|
|
293
|
-
await session.appendRecord({
|
|
294
|
-
type: "step_attempt",
|
|
295
|
-
id: "attempt-2",
|
|
296
|
-
lane: "thread",
|
|
297
|
-
runId: "run-2",
|
|
298
|
-
step: "assistant",
|
|
299
|
-
attempt: 1,
|
|
300
|
-
resultEntryId: "assistant-2",
|
|
301
|
-
});
|
|
302
|
-
deepStrictEqual((await session.findRecords({ lane: "thread" })).map((record) => record.id), ["attempt-2", "run-2"]);
|
|
303
|
-
deepStrictEqual((await session.findRecords({ type: "step_attempt", order: "oldestFirst" })).map((record) => record.id), ["attempt-1", "attempt-2"]);
|
|
304
|
-
deepStrictEqual((await session.findRecords({ runId: "run-1", afterSeq: 1 })).map((record) => record.id), ["attempt-1"]);
|
|
305
|
-
deepStrictEqual((await session.findRecords({ limit: 1 })).map((record) => record.id), ["attempt-2"]);
|
|
306
|
-
}),
|
|
307
|
-
createCase(factory, "records and log", "filters operation starts by operation kind", async (repository) => {
|
|
308
|
-
const session = await repository.create({ id: "session" });
|
|
309
|
-
await session.appendRecord(operationStarted("run-old", { lane: "main", kind: "run" }));
|
|
310
|
-
await session.appendRecord({
|
|
311
|
-
type: "operation_finished",
|
|
312
|
-
id: "run-old-finished",
|
|
313
|
-
lane: "main",
|
|
314
|
-
runId: "run-old",
|
|
315
|
-
outcome: "completed",
|
|
316
|
-
});
|
|
317
|
-
await session.appendRecord(operationStarted("compaction", { lane: "main", kind: "compaction" }));
|
|
318
|
-
await session.appendRecord({
|
|
319
|
-
type: "operation_finished",
|
|
320
|
-
id: "compaction-finished",
|
|
321
|
-
lane: "main",
|
|
322
|
-
runId: "compaction",
|
|
323
|
-
outcome: "completed",
|
|
324
|
-
});
|
|
325
|
-
await session.appendRecord(operationStarted("navigation", { lane: "main", kind: "navigation" }));
|
|
326
|
-
await session.appendRecord({
|
|
327
|
-
type: "operation_finished",
|
|
328
|
-
id: "navigation-finished",
|
|
329
|
-
lane: "main",
|
|
330
|
-
runId: "navigation",
|
|
331
|
-
outcome: "completed",
|
|
332
|
-
});
|
|
333
|
-
await session.appendRecord(operationStarted("run-new", { lane: "main", kind: "run" }));
|
|
334
|
-
deepStrictEqual((await session.findRecords({
|
|
335
|
-
type: "operation_started",
|
|
336
|
-
operationKind: "run",
|
|
337
|
-
order: "oldestFirst",
|
|
338
|
-
})).map((record) => record.id), ["run-old", "run-new"]);
|
|
339
|
-
deepStrictEqual((await session.findRecords({
|
|
340
|
-
type: "operation_started",
|
|
341
|
-
operationKind: "compaction",
|
|
342
|
-
})).map((record) => record.id), ["compaction"]);
|
|
343
|
-
deepStrictEqual((await session.findRecords({
|
|
344
|
-
type: "operation_started",
|
|
345
|
-
operationKind: "navigation",
|
|
346
|
-
})).map((record) => record.id), ["navigation"]);
|
|
347
|
-
deepStrictEqual((await session.findRecords({
|
|
348
|
-
type: "operation_started",
|
|
349
|
-
operationKind: "run",
|
|
350
|
-
limit: 1,
|
|
351
|
-
})).map((record) => record.id), ["run-new"]);
|
|
352
|
-
}),
|
|
353
|
-
createCase(factory, "records and log", "tracks and enforces one open operation per lane", async (repository) => {
|
|
354
|
-
const session = await repository.create({ id: "session" });
|
|
355
|
-
deepStrictEqual(await session.findOpenOperations("main", { limit: 2 }), []);
|
|
356
|
-
const first = await session.appendRecord(operationStarted("first", { lane: "main", kind: "run" }));
|
|
357
|
-
deepStrictEqual(await session.findOpenOperations("main", { limit: 2 }), [first]);
|
|
358
|
-
await rejectsWithCode(session.appendRecord(operationStarted("second", { lane: "main", kind: "run" })), "storage");
|
|
359
|
-
deepStrictEqual(await session.findOpenOperations("main", { limit: 2 }), [first]);
|
|
360
|
-
await session.appendRecord({
|
|
361
|
-
type: "operation_finished",
|
|
362
|
-
id: "finish-first",
|
|
363
|
-
lane: "main",
|
|
364
|
-
runId: first.id,
|
|
365
|
-
outcome: "completed",
|
|
366
|
-
});
|
|
367
|
-
deepStrictEqual(await session.findOpenOperations("main", { limit: 2 }), []);
|
|
368
|
-
}),
|
|
369
|
-
createCase(factory, "records and log", "does not let an earlier finish close a later start", async (repository) => {
|
|
370
|
-
const session = await repository.create({ id: "session" });
|
|
371
|
-
await session.appendRecord({
|
|
372
|
-
type: "operation_finished",
|
|
373
|
-
id: "finish-before-start",
|
|
374
|
-
lane: "main",
|
|
375
|
-
runId: "run",
|
|
376
|
-
outcome: "completed",
|
|
377
|
-
});
|
|
378
|
-
const started = await session.appendRecord(operationStarted("run", { lane: "main", kind: "run" }));
|
|
379
|
-
deepStrictEqual(await session.findOpenOperations("main", { limit: 2 }), [started]);
|
|
380
|
-
}),
|
|
381
|
-
createCase(factory, "records and log", "scopes open operations by lane and limit", async (repository) => {
|
|
382
|
-
const session = await repository.create({ id: "session" });
|
|
383
|
-
await session.createLane("thread", null);
|
|
384
|
-
const mainRun = await session.appendRecord(operationStarted("main-run", { lane: "main", kind: "run" }));
|
|
385
|
-
const threadNavigation = await session.appendRecord(operationStarted("thread-navigation", { lane: "thread", kind: "navigation" }));
|
|
386
|
-
deepStrictEqual(await session.findOpenOperations("main"), [mainRun]);
|
|
387
|
-
deepStrictEqual(await session.findOpenOperations("main", { limit: 1 }), [mainRun]);
|
|
388
|
-
deepStrictEqual(await session.findOpenOperations("thread", { limit: 2 }), [threadNavigation]);
|
|
389
|
-
}),
|
|
390
|
-
createCase(factory, "validation and immutability", "returns immutable open-operation records", async (repository) => {
|
|
391
|
-
const session = await repository.create({ id: "session" });
|
|
392
|
-
const committed = await session.appendRecord(operationStarted("run", { lane: "main", kind: "run" }));
|
|
393
|
-
const [read] = await session.findOpenOperations("main");
|
|
394
|
-
if (read?.intent.kind !== "run")
|
|
395
|
-
throw new Error("Expected an open run operation");
|
|
396
|
-
read.intent.originalPrompt.push(createUserMessage("mutated"));
|
|
397
|
-
deepStrictEqual(await session.findOpenOperations("main"), [committed]);
|
|
398
|
-
}),
|
|
399
|
-
createCase(factory, "queries and facts", "keeps latest-value facts and computes ledger statistics across lanes", async (repository) => {
|
|
400
|
-
const session = await repository.create({ id: "session" });
|
|
401
|
-
const assistant = createAssistantMessage("answer");
|
|
402
|
-
if (assistant.role !== "assistant")
|
|
403
|
-
throw new Error("Expected assistant message");
|
|
404
|
-
assistant.usage = {
|
|
405
|
-
input: 10,
|
|
406
|
-
output: 5,
|
|
407
|
-
cacheRead: 3,
|
|
408
|
-
cacheWrite: 2,
|
|
409
|
-
totalTokens: 20,
|
|
410
|
-
cost: { input: 1, output: 2, cacheRead: 3, cacheWrite: 4, total: 10 },
|
|
411
|
-
};
|
|
412
|
-
await session.appendEntry({ type: "message", id: "user", message: createUserMessage("question") }, "main");
|
|
413
|
-
await session.appendEntry({ type: "message", id: "assistant", message: assistant }, "main");
|
|
414
|
-
await session.appendRecord({
|
|
415
|
-
type: "usage",
|
|
416
|
-
id: "assistant-usage",
|
|
417
|
-
lane: "main",
|
|
418
|
-
cause: "assistant",
|
|
419
|
-
runId: "run",
|
|
420
|
-
entryId: "assistant",
|
|
421
|
-
attempt: 1,
|
|
422
|
-
stopReason: "stop",
|
|
423
|
-
usage: assistant.usage,
|
|
424
|
-
});
|
|
425
|
-
await session.appendRecord({
|
|
426
|
-
type: "usage",
|
|
427
|
-
id: "deferred-usage",
|
|
428
|
-
lane: "main",
|
|
429
|
-
cause: "deferred_fetch",
|
|
430
|
-
runId: "run",
|
|
431
|
-
entryId: "deferred-result",
|
|
432
|
-
attempt: 1,
|
|
433
|
-
stopReason: "deferred",
|
|
434
|
-
usage: {
|
|
435
|
-
input: 0,
|
|
436
|
-
output: 0,
|
|
437
|
-
cacheRead: 0,
|
|
438
|
-
cacheWrite: 0,
|
|
439
|
-
totalTokens: 0,
|
|
440
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
441
|
-
},
|
|
442
|
-
});
|
|
443
|
-
await session.createLane("thread", "assistant");
|
|
444
|
-
await session.appendRecord({
|
|
445
|
-
type: "usage",
|
|
446
|
-
id: "correction",
|
|
447
|
-
lane: "thread",
|
|
448
|
-
cause: "adjustment",
|
|
449
|
-
details: { reason: "provider correction" },
|
|
450
|
-
usage: {
|
|
451
|
-
input: -2,
|
|
452
|
-
output: 0,
|
|
453
|
-
cacheRead: 0,
|
|
454
|
-
cacheWrite: 0,
|
|
455
|
-
totalTokens: -2,
|
|
456
|
-
cost: { input: -0.5, output: 0, cacheRead: 0, cacheWrite: 0, total: -0.5 },
|
|
457
|
-
},
|
|
458
|
-
});
|
|
459
|
-
await session.setName("First");
|
|
460
|
-
await session.setName("Second");
|
|
461
|
-
await session.setLabel("user", "keep");
|
|
462
|
-
await session.setLabel("user", undefined);
|
|
463
|
-
await rejectsWithCode(session.setLabel("missing", "checkpoint"), "not_found");
|
|
464
|
-
strictEqual(await session.getName(), "Second");
|
|
465
|
-
strictEqual(await session.getLabel("user"), undefined);
|
|
466
|
-
const usageRecords = await session.findRecords({ type: "usage", order: "oldestFirst" });
|
|
467
|
-
deepStrictEqual(usageRecords.map((record) => record.cause), ["assistant", "deferred_fetch", "adjustment"]);
|
|
468
|
-
const deferredUsage = usageRecords.find((record) => record.cause === "deferred_fetch");
|
|
469
|
-
if (deferredUsage?.cause !== "deferred_fetch")
|
|
470
|
-
throw new Error("Expected deferred usage record");
|
|
471
|
-
strictEqual(deferredUsage.stopReason, "deferred");
|
|
472
|
-
deepStrictEqual(await session.getStats(), {
|
|
473
|
-
messageCount: 2,
|
|
474
|
-
cachedTokens: 3,
|
|
475
|
-
uncachedTokens: 10,
|
|
476
|
-
totalTokens: 18,
|
|
477
|
-
costTotal: 9.5,
|
|
478
|
-
});
|
|
479
|
-
}),
|
|
480
|
-
createCase(factory, "queries and facts", "clears session names durably", async (repository) => {
|
|
481
|
-
const session = await repository.create({ id: "session" });
|
|
482
|
-
await session.setName("Temporary");
|
|
483
|
-
await session.setName(undefined);
|
|
484
|
-
strictEqual(await session.getName(), undefined);
|
|
485
|
-
deepStrictEqual(await session.getLog(), [
|
|
486
|
-
{ kind: "fact", seq: 1, fact: "name", name: "Temporary" },
|
|
487
|
-
{ kind: "fact", seq: 2, fact: "name", name: undefined },
|
|
488
|
-
]);
|
|
489
|
-
const metadata = await session.getMetadata();
|
|
490
|
-
const reopened = await repository.open(metadata);
|
|
491
|
-
strictEqual(await reopened.getName(), undefined);
|
|
492
|
-
deepStrictEqual(await reopened.getLog(), [
|
|
493
|
-
{ kind: "fact", seq: 1, fact: "name", name: "Temporary" },
|
|
494
|
-
{ kind: "fact", seq: 2, fact: "name", name: undefined },
|
|
495
|
-
]);
|
|
496
|
-
const fork = await repository.fork(metadata, { id: "fork" });
|
|
497
|
-
strictEqual(await fork.getName(), undefined);
|
|
498
|
-
}),
|
|
499
|
-
createCase(factory, "validation and immutability", "returns immutable copies from reads", async (repository) => {
|
|
500
|
-
const session = await repository.create({ id: "immutable" });
|
|
501
|
-
const metadata = await session.getMetadata();
|
|
502
|
-
const data = { nested: { value: 1 } };
|
|
503
|
-
await session.appendEntry({ type: "custom", id: "custom", customType: "note", data }, "main");
|
|
504
|
-
data.nested.value = 50;
|
|
505
|
-
const read = await session.getEntry("custom");
|
|
506
|
-
if (read?.type !== "custom")
|
|
507
|
-
throw new Error("Expected custom entry");
|
|
508
|
-
read.data.nested.value = 99;
|
|
509
|
-
const readMetadata = await session.getMetadata();
|
|
510
|
-
readMetadata.id = "changed";
|
|
511
|
-
const log = await session.getLog();
|
|
512
|
-
if (log[0]?.kind !== "entry" || log[0].entry.type !== "custom")
|
|
513
|
-
throw new Error("Expected entry log");
|
|
514
|
-
log[0].entry.data.nested.value = 100;
|
|
515
|
-
deepStrictEqual(await session.getMetadata(), metadata);
|
|
516
|
-
deepStrictEqual(await session.getEntry("custom"), {
|
|
517
|
-
type: "custom",
|
|
518
|
-
id: "custom",
|
|
519
|
-
customType: "note",
|
|
520
|
-
data: { nested: { value: 1 } },
|
|
521
|
-
parentId: null,
|
|
522
|
-
seq: 1,
|
|
523
|
-
timestamp: read.timestamp,
|
|
524
|
-
});
|
|
525
|
-
}),
|
|
526
|
-
createCase(factory, "entries and lanes", "validates lane lifecycle and targets", async (repository) => {
|
|
527
|
-
const session = await repository.create({ id: "session" });
|
|
528
|
-
await rejectsWithCode(session.createLane("main", null), "already_exists");
|
|
529
|
-
await rejectsWithCode(session.createLane("thread", "missing"), "not_found");
|
|
530
|
-
await rejectsWithCode(session.moveLane("missing", null), "invalid_lane");
|
|
531
|
-
}),
|
|
532
|
-
createCase(factory, "entries and lanes", "binds lane views without caching leaves", async (repository) => {
|
|
533
|
-
const session = await repository.create({ id: "session" });
|
|
534
|
-
const root = await session.appendMessage(createUserMessage("root"));
|
|
535
|
-
await session.createLane("thread", root);
|
|
536
|
-
const thread = session.view("thread");
|
|
537
|
-
const [mainChild, threadChild] = await Promise.all([
|
|
538
|
-
session.appendMessage(createUserMessage("main")),
|
|
539
|
-
thread.appendMessage(createUserMessage("thread")),
|
|
540
|
-
]);
|
|
541
|
-
strictEqual(await session.getLeafId(), mainChild);
|
|
542
|
-
strictEqual(await thread.getLeafId(), threadChild);
|
|
543
|
-
deepStrictEqual(await entryIds(session.findEntriesOnBranch({ order: "oldestFirst" })), [root, mainChild]);
|
|
544
|
-
deepStrictEqual(await entryIds(thread.findEntriesOnBranch({ order: "oldestFirst" })), [root, threadChild]);
|
|
545
|
-
const empty = await repository.create({ id: "empty" });
|
|
546
|
-
deepStrictEqual(await empty.findEntriesOnBranch(), []);
|
|
547
|
-
}),
|
|
548
|
-
createCase(factory, "entries and lanes", "appends provisioned entries with their existing ids", async (repository) => {
|
|
549
|
-
const session = await repository.create({ id: "session" });
|
|
550
|
-
const entry = await session.appendEntry({ type: "custom", id: "provisioned", customType: "note", data: { value: 1 } }, "main");
|
|
551
|
-
strictEqual(entry.customType, "note");
|
|
552
|
-
deepStrictEqual({ id: entry.id, parentId: entry.parentId, seq: entry.seq }, { id: "provisioned", parentId: null, seq: 1 });
|
|
553
|
-
strictEqual(await session.getLeafId(), "provisioned");
|
|
554
|
-
}),
|
|
555
|
-
createCase(factory, "entries and lanes", "persists tool-result termination decisions", async (repository) => {
|
|
556
|
-
const session = await repository.create({ id: "session" });
|
|
557
|
-
const entry = await session.appendEntry({
|
|
558
|
-
type: "message",
|
|
559
|
-
id: "tool-result",
|
|
560
|
-
message: {
|
|
561
|
-
role: "toolResult",
|
|
562
|
-
toolCallId: "call-1",
|
|
563
|
-
toolName: "example",
|
|
564
|
-
content: [{ type: "text", text: "done" }],
|
|
565
|
-
isError: false,
|
|
566
|
-
timestamp: 1,
|
|
567
|
-
},
|
|
568
|
-
terminate: true,
|
|
569
|
-
}, "main");
|
|
570
|
-
strictEqual(entry.terminate, true);
|
|
571
|
-
const stored = await session.getEntry(entry.id);
|
|
572
|
-
if (stored?.type !== "message")
|
|
573
|
-
throw new Error("Expected message entry");
|
|
574
|
-
strictEqual(stored.terminate, true);
|
|
575
|
-
deepStrictEqual(await session.findEntries(), [entry]);
|
|
576
|
-
deepStrictEqual(await session.getLog(), [{ kind: "entry", seq: entry.seq, entry }]);
|
|
577
|
-
}),
|
|
578
|
-
createCase(factory, "validation and immutability", "rejects non-JSON entries before storage mutation", async (repository) => {
|
|
579
|
-
const session = await repository.create({ id: "session" });
|
|
580
|
-
const cyclic = {};
|
|
581
|
-
cyclic.self = cyclic;
|
|
582
|
-
for (const data of [
|
|
583
|
-
{ value: undefined },
|
|
584
|
-
[undefined],
|
|
585
|
-
{ value: 1n },
|
|
586
|
-
{ value: Number.NaN },
|
|
587
|
-
{ value: new Map() },
|
|
588
|
-
cyclic,
|
|
589
|
-
]) {
|
|
590
|
-
await rejectsWithCode(session.appendCustomEntry("invalid", data), "invalid_payload");
|
|
591
|
-
}
|
|
592
|
-
strictEqual(await session.getLeafId(), null);
|
|
593
|
-
deepStrictEqual(await session.findEntries(), []);
|
|
594
|
-
deepStrictEqual(await session.getLog(), []);
|
|
595
|
-
const validId = await session.appendCustomEntry("valid", { value: 1 });
|
|
596
|
-
strictEqual((await session.getEntry(validId))?.seq, 1);
|
|
597
|
-
}),
|
|
598
|
-
createCase(factory, "validation and immutability", "rejects non-JSON records before storage mutation", async (repository) => {
|
|
599
|
-
const session = await repository.create({ id: "session" });
|
|
600
|
-
for (const [id, value] of [
|
|
601
|
-
["undefined-record", undefined],
|
|
602
|
-
["bigint-record", 1n],
|
|
603
|
-
]) {
|
|
604
|
-
await rejectsWithCode(session.appendRecord({
|
|
605
|
-
type: "tool_started",
|
|
606
|
-
id,
|
|
607
|
-
lane: "main",
|
|
608
|
-
runId: "run",
|
|
609
|
-
assistantEntryId: "assistant",
|
|
610
|
-
toolIndex: 0,
|
|
611
|
-
toolCallId: "call",
|
|
612
|
-
toolName: "example",
|
|
613
|
-
effectiveArgs: { value },
|
|
614
|
-
resultEntryId: "result",
|
|
615
|
-
replay: "never",
|
|
616
|
-
}), "invalid_payload");
|
|
617
|
-
}
|
|
618
|
-
deepStrictEqual(await session.findRecords(), []);
|
|
619
|
-
deepStrictEqual(await session.getLog(), []);
|
|
620
|
-
strictEqual((await session.appendRecord(operationStarted("valid-record", { lane: "main", kind: "run" }))).seq, 1);
|
|
621
|
-
}),
|
|
622
|
-
createCase(factory, "entries and lanes", "linearizes concurrent writes across two lanes", async (repository) => {
|
|
623
|
-
const session = await repository.create({ id: "session" });
|
|
624
|
-
await session.appendEntry({ type: "message", id: "root", message: createUserMessage("root") }, "main");
|
|
625
|
-
await session.createLane("thread", "root");
|
|
626
|
-
const completionOrder = [];
|
|
627
|
-
const writes = [
|
|
628
|
-
session.appendEntry({ type: "custom", id: "main-1", customType: "note" }, "main"),
|
|
629
|
-
session.appendEntry({ type: "custom", id: "thread-1", customType: "note" }, "thread"),
|
|
630
|
-
session.appendEntry({ type: "custom", id: "main-2", customType: "note" }, "main"),
|
|
631
|
-
session.appendEntry({ type: "custom", id: "thread-2", customType: "note" }, "thread"),
|
|
632
|
-
].map((write) => write.then((entry) => {
|
|
633
|
-
completionOrder.push(entry.id);
|
|
634
|
-
return entry;
|
|
635
|
-
}));
|
|
636
|
-
const entries = await Promise.all(writes);
|
|
637
|
-
const commitOrder = [...entries].sort((left, right) => left.seq - right.seq).map((entry) => entry.id);
|
|
638
|
-
strictEqual(new Set(entries.map((entry) => entry.seq)).size, entries.length);
|
|
639
|
-
deepStrictEqual(completionOrder, commitOrder);
|
|
640
|
-
const concurrentIds = new Set(entries.map((entry) => entry.id));
|
|
641
|
-
deepStrictEqual((await session.getLog()).flatMap((item) => item.kind === "entry" && concurrentIds.has(item.entry.id) ? [item.entry.id] : []), commitOrder);
|
|
642
|
-
const sequences = (await session.getLog()).map((item) => item.seq);
|
|
643
|
-
deepStrictEqual(sequences, [...sequences].sort((left, right) => left - right));
|
|
644
|
-
}),
|
|
645
|
-
createCase(factory, "repository and forks", "creates lists and opens sessions", async (repository) => {
|
|
646
|
-
const session = await repository.create({ id: "one" });
|
|
647
|
-
const entryId = await session.appendMessage(createUserMessage("persisted"));
|
|
648
|
-
const metadata = await session.getMetadata();
|
|
649
|
-
const listed = await repository.list();
|
|
650
|
-
strictEqual(listed.length, 1);
|
|
651
|
-
strictEqual(listed[0]?.id, metadata.id);
|
|
652
|
-
strictEqual(listed[0]?.createdAt, metadata.createdAt);
|
|
653
|
-
strictEqual(listed[0]?.parentSessionId, metadata.parentSessionId);
|
|
654
|
-
deepStrictEqual(await entryIds((await repository.open(metadata)).findEntries()), [entryId]);
|
|
655
|
-
await rejectsWithCode(repository.create({ id: "one" }), "already_exists");
|
|
656
|
-
}),
|
|
657
|
-
createCase(factory, "repository and forks", "deletes sessions idempotently", async (repository) => {
|
|
658
|
-
const session = await repository.create({ id: "one" });
|
|
659
|
-
const metadata = await session.getMetadata();
|
|
660
|
-
await repository.delete(metadata);
|
|
661
|
-
await rejectsWithCode(repository.open(metadata), "not_found");
|
|
662
|
-
await repository.delete(metadata);
|
|
663
|
-
}),
|
|
664
|
-
createCase(factory, "repository and forks", "forks one branch with selected facts and no records", async (repository) => {
|
|
665
|
-
const source = await repository.create({ id: "source" });
|
|
666
|
-
const root = await source.appendMessage(createUserMessage("root"));
|
|
667
|
-
const shared = await source.appendMessage(createAssistantMessage("shared"));
|
|
668
|
-
await source.createLane("thread", shared);
|
|
669
|
-
const threadChild = await source.view("thread").appendMessage(createUserMessage("thread"));
|
|
670
|
-
const mainChild = await source.appendMessage(createUserMessage("main"));
|
|
671
|
-
await source.setName("Source");
|
|
672
|
-
await source.setLabel(shared, "copied");
|
|
673
|
-
await source.setLabel(threadChild, "excluded");
|
|
674
|
-
await source.appendRecord(operationStarted("run", { lane: "main", kind: "run" }));
|
|
675
|
-
await source.appendRecord({
|
|
676
|
-
type: "usage",
|
|
677
|
-
id: "source-usage",
|
|
678
|
-
lane: "main",
|
|
679
|
-
cause: "adjustment",
|
|
680
|
-
usage: {
|
|
681
|
-
input: 10,
|
|
682
|
-
output: 5,
|
|
683
|
-
cacheRead: 3,
|
|
684
|
-
cacheWrite: 2,
|
|
685
|
-
totalTokens: 20,
|
|
686
|
-
cost: { input: 1, output: 2, cacheRead: 3, cacheWrite: 4, total: 10 },
|
|
687
|
-
},
|
|
688
|
-
});
|
|
689
|
-
const fork = await repository.fork(await source.getMetadata(), {
|
|
690
|
-
scope: "branch",
|
|
691
|
-
entryId: mainChild,
|
|
692
|
-
position: "at",
|
|
693
|
-
id: "branch-fork",
|
|
694
|
-
});
|
|
695
|
-
deepStrictEqual(await entryIds(fork.findEntries({ order: "oldestFirst" })), [root, shared, mainChild]);
|
|
696
|
-
deepStrictEqual(await fork.getLanes(), [{ lane: "main", leafId: mainChild }]);
|
|
697
|
-
strictEqual(await fork.getName(), "Source");
|
|
698
|
-
strictEqual(await fork.getLabel(shared), "copied");
|
|
699
|
-
strictEqual(await fork.getLabel(threadChild), undefined);
|
|
700
|
-
deepStrictEqual(await fork.findRecords(), []);
|
|
701
|
-
deepStrictEqual(await fork.getStats(), {
|
|
702
|
-
messageCount: 3,
|
|
703
|
-
cachedTokens: 0,
|
|
704
|
-
uncachedTokens: 0,
|
|
705
|
-
totalTokens: 0,
|
|
706
|
-
costTotal: 0,
|
|
707
|
-
});
|
|
708
|
-
await fork.appendMessage(createUserMessage("after fork"));
|
|
709
|
-
strictEqual((await fork.getStats()).messageCount, 4);
|
|
710
|
-
const metadata = await fork.getMetadata();
|
|
711
|
-
deepStrictEqual({ id: metadata.id, parentSessionId: metadata.parentSessionId }, { id: "branch-fork", parentSessionId: "source" });
|
|
712
|
-
}),
|
|
713
|
-
createCase(factory, "repository and forks", "forks a complete tree with lanes and facts", async (repository) => {
|
|
714
|
-
const source = await repository.create({ id: "source" });
|
|
715
|
-
const root = await source.appendMessage(createUserMessage("root"));
|
|
716
|
-
await source.createLane("thread", root);
|
|
717
|
-
const mainChild = await source.appendMessage(createUserMessage("main"));
|
|
718
|
-
const threadChild = await source.view("thread").appendMessage(createUserMessage("thread"));
|
|
719
|
-
await source.setLabel(threadChild, "thread-tip");
|
|
720
|
-
const fork = await repository.fork(await source.getMetadata(), { scope: "tree", id: "tree-fork" });
|
|
721
|
-
deepStrictEqual(await entryIds(fork.findEntries({ order: "oldestFirst" })), [root, mainChild, threadChild]);
|
|
722
|
-
deepStrictEqual(await fork.getLanes(), [
|
|
723
|
-
{ lane: "main", leafId: mainChild },
|
|
724
|
-
{ lane: "thread", leafId: threadChild },
|
|
725
|
-
]);
|
|
726
|
-
strictEqual(await fork.getLabel(threadChild), "thread-tip");
|
|
727
|
-
strictEqual((await fork.getStats()).messageCount, 3);
|
|
728
|
-
deepStrictEqual((await fork.getLog()).filter((item) => item.kind === "lane"), [
|
|
729
|
-
{ kind: "lane", seq: 4, lane: "main", leafId: mainChild },
|
|
730
|
-
{ kind: "lane", seq: 5, lane: "thread", leafId: threadChild },
|
|
731
|
-
]);
|
|
732
|
-
}),
|
|
733
|
-
createCase(factory, "repository and forks", "forks before an entry without modifying the source", async (repository) => {
|
|
734
|
-
const source = await repository.create({ id: "source" });
|
|
735
|
-
const root = await source.appendMessage(createUserMessage("root"));
|
|
736
|
-
const tail = await source.appendMessage(createUserMessage("tail"));
|
|
737
|
-
const fork = await repository.fork(await source.getMetadata(), { entryId: tail, id: "fork" });
|
|
738
|
-
deepStrictEqual(await entryIds(fork.findEntries({ order: "oldestFirst" })), [root]);
|
|
739
|
-
strictEqual(await fork.getLeafId(), root);
|
|
740
|
-
strictEqual(await source.getLeafId(), tail);
|
|
741
|
-
const beforeDefaultTarget = await repository.fork(await source.getMetadata(), {
|
|
742
|
-
position: "before",
|
|
743
|
-
id: "before-default-target",
|
|
744
|
-
});
|
|
745
|
-
deepStrictEqual(await entryIds(beforeDefaultTarget.findEntries({ order: "oldestFirst" })), [root]);
|
|
746
|
-
strictEqual(await beforeDefaultTarget.getLeafId(), root);
|
|
747
|
-
const atDefaultTarget = await repository.fork(await source.getMetadata(), {
|
|
748
|
-
position: "at",
|
|
749
|
-
id: "at-default-target",
|
|
750
|
-
});
|
|
751
|
-
deepStrictEqual(await entryIds(atDefaultTarget.findEntries({ order: "oldestFirst" })), [root, tail]);
|
|
752
|
-
strictEqual(await atDefaultTarget.getLeafId(), tail);
|
|
753
|
-
await rejectsWithCode(repository.fork(await source.getMetadata(), { entryId: "missing" }), "invalid_fork_target");
|
|
754
|
-
}),
|
|
755
|
-
createCase(factory, "repository and forks", "validates the default fork target", async (repository) => {
|
|
756
|
-
const source = await repository.create({ id: "source-with-custom-leaf" });
|
|
757
|
-
await source.appendCustomEntry("not-a-message");
|
|
758
|
-
await rejectsWithCode(repository.fork(await source.getMetadata(), { id: "fork" }), "invalid_fork_target");
|
|
759
|
-
}),
|
|
760
|
-
];
|
|
761
|
-
}
|
|
762
|
-
//# sourceMappingURL=conformance.js.map
|