@earendil-works/pi-agent-core 0.84.3 → 0.85.0
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/agent-loop.d.ts.map +1 -1
- package/dist/agent-loop.js +32 -25
- package/dist/agent-loop.js.map +1 -1
- 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 -251
- 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 -26
- 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 -63
- 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 +27 -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 +24 -28
- package/dist/harness/env/nodejs.d.ts.map +1 -1
- package/dist/harness/env/nodejs.js +242 -87
- 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 +240 -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 +49 -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 +406 -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 +40 -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 +170 -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 +37 -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 +311 -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 +101 -0
- package/dist/harness/runtime/lane.d.ts.map +1 -0
- package/dist/harness/runtime/lane.js +1575 -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 +61 -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 -18
- package/dist/harness/session/context.d.ts.map +1 -1
- package/dist/harness/session/context.js +31 -49
- package/dist/harness/session/context.js.map +1 -1
- package/dist/harness/session/fork-policy.d.ts +13 -0
- package/dist/harness/session/fork-policy.d.ts.map +1 -0
- package/dist/harness/session/fork-policy.js +22 -0
- package/dist/harness/session/fork-policy.js.map +1 -0
- package/dist/harness/session/fork.d.ts +18 -0
- package/dist/harness/session/fork.d.ts.map +1 -0
- package/dist/harness/session/fork.js +127 -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 +216 -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 -218
- package/dist/harness/session/jsonl/codec.js.map +1 -1
- 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/legacy-v3.d.ts +18 -0
- package/dist/harness/session/jsonl/legacy-v3.d.ts.map +1 -0
- package/dist/harness/session/jsonl/legacy-v3.js +383 -0
- package/dist/harness/session/jsonl/legacy-v3.js.map +1 -0
- package/dist/harness/session/jsonl/repo.d.ts +26 -19
- package/dist/harness/session/jsonl/repo.d.ts.map +1 -1
- package/dist/harness/session/jsonl/repo.js +266 -156
- 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 +238 -181
- 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 +46 -40
- package/dist/harness/session/memory.d.ts.map +1 -1
- package/dist/harness/session/memory.js +346 -113
- 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 +21 -0
- package/dist/harness/session/mutation-line.js.map +1 -0
- package/dist/harness/session/session.d.ts +78 -46
- package/dist/harness/session/session.d.ts.map +1 -1
- package/dist/harness/session/session.js +343 -209
- 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 +21 -0
- package/dist/harness/session/testing/conformance/session-repo.d.ts.map +1 -0
- package/dist/harness/session/testing/conformance/session-repo.js +590 -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 +100 -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 +16 -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 +41 -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 +424 -259
- package/dist/harness/session/types.d.ts.map +1 -1
- package/dist/harness/session/types.js +7 -8
- 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 +10 -10
- 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 +7 -7
- package/dist/harness/tools/write.js.map +1 -1
- package/dist/harness/types.d.ts +108 -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 +12 -5
- package/dist/harness/utils/shell-output.d.ts.map +1 -1
- package/dist/harness/utils/shell-output.js +64 -174
- 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/proxy.d.ts +2 -0
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +40 -10
- package/dist/proxy.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 +5 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +25 -4
- package/dist/harness/reducer.d.ts +0 -100
- package/dist/harness/reducer.d.ts.map +0 -1
- package/dist/harness/reducer.js +0 -415
- 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 -19
- 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 -319
- 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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/harness/session/session.ts"],"names":[],"mappings":"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","sourcesContent":["import { uuidv7 } from \"@earendil-works/pi-ai\";\nimport type { AgentMessage } from \"../../types.ts\";\nimport type {\n\tBranchBounds,\n\tEntry,\n\tEntryQuery,\n\tIdGenerator,\n\tLanePointer,\n\tLaneRecord,\n\tLogItem,\n\tLogOptions,\n\tNewRecord,\n\tOperationStartedRecord,\n\tProvisionedEntry,\n\tRecordBase,\n\tRecordQuery,\n\tSessionMetadata,\n\tSessionStats,\n\tSessionStorage,\n\tSessionTree,\n} from \"./types.ts\";\nimport { SessionError } from \"./types.ts\";\n\ntype JsonValidationFrame = { value: unknown } | { exit: object };\n\nfunction invalidPayload(reason: string): never {\n\tthrow new SessionError(\"invalid_payload\", `Durable payload ${reason}`);\n}\n\nfunction assertValidLimit(limit: number | undefined): void {\n\tif (limit !== undefined && (!Number.isInteger(limit) || limit <= 0)) {\n\t\tthrow new SessionError(\"invalid_query\", \"limit must be a positive integer\");\n\t}\n}\n\nfunction assertValidCursor(afterSeq: number | undefined): void {\n\tif (afterSeq !== undefined && (!Number.isInteger(afterSeq) || afterSeq < 0)) {\n\t\tthrow new SessionError(\"invalid_query\", \"cursor sequence must be a non-negative integer\");\n\t}\n}\n\nexport function assertJsonSerializable(value: unknown): void {\n\tconst active = new WeakSet<object>();\n\tconst stack: JsonValidationFrame[] = [{ value }];\n\twhile (stack.length > 0) {\n\t\tconst frame = stack.pop()!;\n\t\tif (\"exit\" in frame) {\n\t\t\tactive.delete(frame.exit);\n\t\t\tcontinue;\n\t\t}\n\t\tconst candidate = frame.value;\n\t\tif (candidate === null || typeof candidate === \"string\" || typeof candidate === \"boolean\") {\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof candidate === \"number\") {\n\t\t\tif (!Number.isFinite(candidate)) invalidPayload(\"contains a non-finite number\");\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof candidate !== \"object\") invalidPayload(`contains ${typeof candidate}`);\n\t\tif (active.has(candidate)) invalidPayload(\"contains a cycle\");\n\t\tactive.add(candidate);\n\t\tstack.push({ exit: candidate });\n\n\t\tif (Array.isArray(candidate)) {\n\t\t\tif (Object.getPrototypeOf(candidate) !== Array.prototype) {\n\t\t\t\tinvalidPayload(\"contains a non-standard array\");\n\t\t\t}\n\t\t\tif (\n\t\t\t\tObject.getOwnPropertySymbols(candidate).length > 0 ||\n\t\t\t\tObject.getOwnPropertyNames(candidate).length !== candidate.length + 1\n\t\t\t) {\n\t\t\t\tinvalidPayload(\"contains an array with unsupported properties\");\n\t\t\t}\n\t\t\tfor (let index = candidate.length - 1; index >= 0; index--) {\n\t\t\t\tif (!Object.hasOwn(candidate, index)) invalidPayload(\"contains a sparse array\");\n\t\t\t\tconst descriptor = Object.getOwnPropertyDescriptor(candidate, index)!;\n\t\t\t\tif (!(\"value\" in descriptor)) invalidPayload(\"contains an array accessor\");\n\t\t\t\tstack.push({ value: descriptor.value });\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst prototype = Object.getPrototypeOf(candidate);\n\t\tif (prototype !== Object.prototype && prototype !== null) {\n\t\t\tinvalidPayload(\"contains a non-plain object\");\n\t\t}\n\t\tif (Object.getOwnPropertySymbols(candidate).length > 0) {\n\t\t\tinvalidPayload(\"contains a symbol-keyed property\");\n\t\t}\n\t\tconst keys = Object.keys(candidate);\n\t\tif (Object.getOwnPropertyNames(candidate).length !== keys.length) {\n\t\t\tinvalidPayload(\"contains a non-enumerable property\");\n\t\t}\n\t\tfor (let index = keys.length - 1; index >= 0; index--) {\n\t\t\tconst descriptor = Object.getOwnPropertyDescriptor(candidate, keys[index]!)!;\n\t\t\tif (!(\"value\" in descriptor)) invalidPayload(\"contains an accessor\");\n\t\t\tstack.push({ value: descriptor.value });\n\t\t}\n\t}\n}\n\nexport class Session<TMetadata extends SessionMetadata = SessionMetadata> implements SessionTree {\n\tprivate readonly storage: SessionStorage<TMetadata>;\n\treadonly idGenerator: IdGenerator;\n\n\tconstructor(storage: SessionStorage<TMetadata>, options: { idGenerator?: IdGenerator } = {}) {\n\t\tthis.storage = storage;\n\t\tthis.idGenerator = options.idGenerator ?? { next: () => uuidv7() };\n\t}\n\n\tasync getMetadata(): Promise<TMetadata> {\n\t\treturn this.storage.getMetadata();\n\t}\n\n\tview(lane: string): SessionTree {\n\t\tif (lane === \"main\") return this;\n\t\treturn {\n\t\t\tgetLeafId: () => this.getLeafIdForLane(lane),\n\t\t\tgetEntry: (id) => this.getEntry(id),\n\t\t\tgetStats: () => this.getStats(),\n\t\t\tgetName: () => this.getName(),\n\t\t\tsetName: (name) => this.setName(name),\n\t\t\tgetLabel: (targetId) => this.getLabel(targetId),\n\t\t\tsetLabel: (targetId, label) => this.setLabel(targetId, label),\n\t\t\tfindEntries: (query) => this.queryEntries(query),\n\t\t\tfindEntry: async (query = {}) => (await this.queryEntries(query, 1))[0],\n\t\t\tfindEntriesOnBranch: (query) => this.queryBranchEntries(lane, query),\n\t\t\tfindEntryOnBranch: async (query = {}) => (await this.queryBranchEntries(lane, query, 1))[0],\n\t\t\tappendMessage: (message) => this.appendMessageToLane(lane, message),\n\t\t\tappendCustomEntry: (customType, data) => this.appendCustomEntryToLane(lane, customType, data),\n\t\t};\n\t}\n\n\tasync getLeafId(): Promise<string | null> {\n\t\treturn this.getLeafIdForLane(\"main\");\n\t}\n\n\tasync getEntry(id: string): Promise<Entry | undefined> {\n\t\treturn this.storage.getEntry(id);\n\t}\n\n\tasync getStats(): Promise<SessionStats> {\n\t\treturn this.storage.getStats();\n\t}\n\n\tasync getName(): Promise<string | undefined> {\n\t\treturn this.storage.getName();\n\t}\n\n\tasync setName(name: string | undefined): Promise<void> {\n\t\tawait this.storage.setName(name);\n\t}\n\n\tasync getLabel(targetId: string): Promise<string | undefined> {\n\t\treturn this.storage.getLabel(targetId);\n\t}\n\n\tasync setLabel(targetId: string, label: string | undefined): Promise<void> {\n\t\tawait this.storage.setLabel(targetId, label);\n\t}\n\n\tasync findEntries(query?: EntryQuery): Promise<Entry[]> {\n\t\treturn this.queryEntries(query);\n\t}\n\n\tasync findEntry(query: EntryQuery = {}): Promise<Entry | undefined> {\n\t\treturn (await this.queryEntries(query, 1))[0];\n\t}\n\n\tasync findEntriesOnBranch(query?: EntryQuery & BranchBounds): Promise<Entry[]> {\n\t\treturn this.queryBranchEntries(\"main\", query);\n\t}\n\n\tasync findEntryOnBranch(query: EntryQuery & BranchBounds = {}): Promise<Entry | undefined> {\n\t\treturn (await this.queryBranchEntries(\"main\", query, 1))[0];\n\t}\n\n\tasync appendMessage(message: AgentMessage): Promise<string> {\n\t\treturn this.appendMessageToLane(\"main\", message);\n\t}\n\n\tasync appendCustomEntry(customType: string, data?: unknown): Promise<string> {\n\t\treturn this.appendCustomEntryToLane(\"main\", customType, data);\n\t}\n\n\tasync getLanes(): Promise<LanePointer[]> {\n\t\treturn this.storage.getLanes();\n\t}\n\n\tasync createLane(lane: string, at: string | null): Promise<void> {\n\t\tawait this.storage.createLane(lane, at);\n\t}\n\n\tasync moveLane(lane: string, to: string | null): Promise<void> {\n\t\tawait this.storage.moveLane(lane, to);\n\t}\n\n\tasync appendEntry<TEntry extends Entry>(entry: ProvisionedEntry<TEntry>, lane: string): Promise<TEntry> {\n\t\treturn this.commitEntry(entry, lane);\n\t}\n\n\tasync appendRecord<TNewRecord extends NewRecord>(\n\t\trecord: TNewRecord,\n\t): Promise<TNewRecord & Pick<RecordBase, \"seq\" | \"timestamp\">>;\n\tasync appendRecord(record: NewRecord): Promise<LaneRecord> {\n\t\treturn this.commitRecord(record);\n\t}\n\n\tasync findRecords<K extends LaneRecord[\"type\"]>(\n\t\tquery: RecordQuery & { type: K },\n\t): Promise<Extract<LaneRecord, { type: K }>[]>;\n\tasync findRecords(query?: RecordQuery): Promise<LaneRecord[]>;\n\tasync findRecords(query?: RecordQuery): Promise<LaneRecord[]> {\n\t\treturn this.queryRecords(query);\n\t}\n\n\tasync findOpenOperations(lane: string, options?: { limit?: number }): Promise<OperationStartedRecord[]> {\n\t\tassertValidLimit(options?.limit);\n\t\treturn this.storage.findOpenOperations(lane, options);\n\t}\n\n\tasync getLog(options?: LogOptions): Promise<LogItem[]> {\n\t\treturn this.queryLog(options);\n\t}\n\n\t/** Returns the lane's current leaf, or null when empty. Throws when the lane does not exist. */\n\tprivate async getLeafIdForLane(lane: string): Promise<string | null> {\n\t\tconst pointer = (await this.getLanes()).find((candidate) => candidate.lane === lane);\n\t\tif (!pointer) throw new SessionError(\"invalid_lane\", `Lane not found: ${lane}`);\n\t\treturn pointer.leafId;\n\t}\n\n\tprivate async queryEntries(query: EntryQuery = {}, resultLimit = query.limit): Promise<Entry[]> {\n\t\tassertValidLimit(query.limit);\n\t\tassertValidCursor(query.cursor?.afterSeq);\n\t\treturn this.storage.findEntries(resultLimit === query.limit ? query : { ...query, limit: resultLimit });\n\t}\n\n\t/**\n\t * Queries from `query.start` toward the root, defaulting to the lane's current leaf.\n\t * `resultLimit` lets single-entry queries cap results without changing the caller's query.\n\t */\n\tprivate async queryBranchEntries(\n\t\tdefaultLane: string,\n\t\tquery: EntryQuery & BranchBounds = {},\n\t\tresultLimit = query.limit,\n\t): Promise<Entry[]> {\n\t\tassertValidLimit(query.limit);\n\t\tassertValidCursor(query.cursor?.afterSeq);\n\t\tconst start = query.start ?? (await this.getLeafIdForLane(defaultLane));\n\t\tif (start === null) return [];\n\t\tconst storageQuery = resultLimit === query.limit ? query : { ...query, limit: resultLimit };\n\t\treturn this.storage.findEntriesOnBranch({ ...storageQuery, start });\n\t}\n\n\tprivate async queryRecords(query: RecordQuery = {}): Promise<LaneRecord[]> {\n\t\tassertValidLimit(query.limit);\n\t\tassertValidCursor(query.afterSeq);\n\t\tif (query.operationKind !== undefined && query.type !== \"operation_started\") {\n\t\t\tthrow new SessionError(\"invalid_query\", 'operationKind requires type \"operation_started\"');\n\t\t}\n\t\treturn this.storage.findRecords(query);\n\t}\n\n\tprivate async queryLog(options: LogOptions = {}): Promise<LogItem[]> {\n\t\tassertValidLimit(options.limit);\n\t\tassertValidCursor(options.afterSeq);\n\t\treturn this.storage.getLog(options);\n\t}\n\n\tprivate async appendMessageToLane(lane: string, message: AgentMessage): Promise<string> {\n\t\tconst entry = await this.commitEntry({ type: \"message\", id: this.idGenerator.next(), message }, lane);\n\t\treturn entry.id;\n\t}\n\n\tprivate async appendCustomEntryToLane(lane: string, customType: string, data?: unknown): Promise<string> {\n\t\tconst entry = await this.commitEntry(\n\t\t\tdata === undefined\n\t\t\t\t? { type: \"custom\", id: this.idGenerator.next(), customType }\n\t\t\t\t: { type: \"custom\", id: this.idGenerator.next(), customType, data },\n\t\t\tlane,\n\t\t);\n\t\treturn entry.id;\n\t}\n\n\tprivate async commitEntry<TEntry extends Entry>(entry: ProvisionedEntry<TEntry>, lane: string): Promise<TEntry> {\n\t\tassertJsonSerializable(entry);\n\t\treturn this.storage.appendEntry(entry, lane);\n\t}\n\n\tprivate async commitRecord<TNewRecord extends NewRecord>(\n\t\trecord: TNewRecord,\n\t): Promise<TNewRecord & Pick<RecordBase, \"seq\" | \"timestamp\">> {\n\t\tassertJsonSerializable(record);\n\t\treturn this.storage.appendRecord<LaneRecord>(record) as unknown as Promise<\n\t\t\tTNewRecord & Pick<RecordBase, \"seq\" | \"timestamp\">\n\t\t>;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/harness/session/session.ts"],"names":[],"mappings":"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","sourcesContent":["import { uuidv7 } from \"@earendil-works/pi-ai/utils/uuid\";\nimport type { AgentMessage } from \"../../types.ts\";\nimport type { Context } from \"../context.ts\";\nimport { insertEntry } from \"./commit.ts\";\nimport { MutationLine } from \"./mutation-line.ts\";\nimport type {\n\tBranch,\n\tBranchScan,\n\tCommitResult,\n\tEntry,\n\tEntryQuery,\n\tIdGenerator,\n\tJsonValue,\n\tSession,\n\tSessionMetadata,\n\tSessionMutation,\n\tSessionMutationCallback,\n\tSessionStats,\n\tStorage,\n\tStorageBranchScan,\n\tWrite,\n} from \"./types.ts\";\nimport {\n\tappendList as appendListWrite,\n\tbranchTip,\n\tdeleteList as deleteListWrite,\n\tdeleteValue as deleteValueWrite,\n\tentryLabel,\n\ttype ListElement,\n\ttype ListReadOptions,\n\ttype StoredValue,\n\tsessionName,\n\tsetValue as setValueWrite,\n\ttype Value,\n\ttype ValueList,\n} from \"./values.ts\";\n\nexport interface StorageBackedSessionOptions {\n\tmutationLine?: MutationLine;\n\tidGenerator?: IdGenerator;\n\tonClose?: () => void;\n}\n\n/** Durable session state is internally inconsistent and cannot be safely advanced. */\nexport class SessionInvariantError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"SessionInvariantError\";\n\t}\n}\n\n/** A requested Branch name is invalid. */\nexport class SessionInvalidBranchError extends Error {\n\treadonly branch: string;\n\treadonly reason: string;\n\n\tconstructor(branch: string, reason: string) {\n\t\tsuper(`Invalid branch ${JSON.stringify(branch)}: ${reason}`);\n\t\tthis.name = \"SessionInvalidBranchError\";\n\t\tthis.branch = branch;\n\t\tthis.reason = reason;\n\t}\n}\n\n/** A requested branch already exists. */\nexport class SessionBranchExistsError extends Error {\n\treadonly branch: string;\n\n\tconstructor(branch: string) {\n\t\tsuper(`Branch already exists: ${branch}`);\n\t\tthis.name = \"SessionBranchExistsError\";\n\t\tthis.branch = branch;\n\t}\n}\n\n/** A pending assistant message cannot be persisted as a session entry. */\nexport class SessionPendingAssistantMessageError extends Error {\n\tconstructor() {\n\t\tsuper(\"Cannot persist a pending assistant message\");\n\t\tthis.name = \"SessionPendingAssistantMessageError\";\n\t}\n}\n\n/** A requested session entry target does not exist. */\nexport class SessionUnknownTargetError extends Error {\n\treadonly targetId: string;\n\n\tconstructor(targetId: string) {\n\t\tsuper(`Unknown target: ${targetId}`);\n\t\tthis.name = \"SessionUnknownTargetError\";\n\t\tthis.targetId = targetId;\n\t}\n}\n\nclass StorageBackedSessionMutation implements SessionMutation {\n\tprivate readonly storage: Storage;\n\tprivate readonly release: () => void;\n\tprivate active = true;\n\tprivate commitResult: Promise<CommitResult> | undefined;\n\tprivate endPromise: Promise<void> | undefined;\n\n\tconstructor(storage: Storage, release: () => void) {\n\t\tthis.storage = storage;\n\t\tthis.release = release;\n\t}\n\n\tcommit(writes: Write[], context: Context): Promise<CommitResult> {\n\t\tthis.assertActive();\n\t\tif (this.commitResult !== undefined) return Promise.reject(new Error(\"SessionMutator commit already attempted\"));\n\t\ttry {\n\t\t\tfor (const write of writes) {\n\t\t\t\tif (\n\t\t\t\t\twrite.kind === \"entry\" &&\n\t\t\t\t\twrite.entry.type === \"message\" &&\n\t\t\t\t\twrite.entry.message.role === \"assistant\" &&\n\t\t\t\t\twrite.entry.message.stopReason === \"pending\"\n\t\t\t\t) {\n\t\t\t\t\tthrow new SessionPendingAssistantMessageError();\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.commitResult = this.storage.commit(writes, context);\n\t\t} catch (error) {\n\t\t\tthis.commitResult = Promise.reject(error);\n\t\t}\n\t\treturn this.commitResult;\n\t}\n\n\tend(_context: Context): Promise<void> {\n\t\tif (this.endPromise !== undefined) return this.endPromise;\n\t\tthis.active = false;\n\t\tthis.endPromise = this.settle().finally(this.release);\n\t\treturn this.endPromise;\n\t}\n\n\tgetEntries(ids: string[], context: Context): Promise<Map<string, Entry>> {\n\t\tthis.assertActive();\n\t\treturn this.storage.getEntries(ids, context);\n\t}\n\n\tgetStats(context: Context): Promise<SessionStats> {\n\t\tthis.assertActive();\n\t\treturn this.storage.getStats(context);\n\t}\n\n\tgetValue<T>(address: Value<T>, context: Context): Promise<StoredValue<T> | undefined> {\n\t\tthis.assertActive();\n\t\treturn this.storage.getValue(address, context);\n\t}\n\n\tscanValues<T>(prefix: Value<T>, context: Context): Promise<StoredValue<T>[]> {\n\t\tthis.assertActive();\n\t\treturn this.storage.scanValues(prefix, context);\n\t}\n\n\treadList<T>(\n\t\taddress: ValueList<T>,\n\t\toptions: ListReadOptions | undefined,\n\t\tcontext: Context,\n\t): Promise<ListElement<T>[]> {\n\t\tthis.assertActive();\n\t\treturn this.storage.readList(address, options, context);\n\t}\n\n\tscanBranch(query: StorageBranchScan, context: Context): Promise<Entry[]> {\n\t\tthis.assertActive();\n\t\treturn this.storage.scanBranch(query, context);\n\t}\n\n\tprivate settle(): Promise<void> {\n\t\treturn (\n\t\t\tthis.commitResult?.then(\n\t\t\t\t() => undefined,\n\t\t\t\t() => undefined,\n\t\t\t) ?? Promise.resolve()\n\t\t);\n\t}\n\n\tprivate assertActive(): void {\n\t\tif (!this.active) throw new Error(\"SessionMutator cannot be used outside its mutation callback\");\n\t}\n}\n\nclass StorageBackedBranch implements Branch {\n\treadonly name: string;\n\tprivate readonly session: StorageBackedSession;\n\n\tconstructor(name: string, session: StorageBackedSession) {\n\t\tthis.name = name;\n\t\tthis.session = session;\n\t}\n\n\tgetTipId(context: Context): Promise<string | null> {\n\t\treturn this.session.getBranchTip(this.name, context);\n\t}\n\n\tasync findEntries(query: BranchScan | undefined, context: Context): Promise<Entry[]> {\n\t\tquery ??= {};\n\t\tconst start = query.start ?? (await this.getTipId(context));\n\t\tif (start === null) return [];\n\t\treturn this.session.scanBranch({ ...query, start, order: query.order ?? \"newestFirst\" }, context);\n\t}\n\n\tasync findEntry(query: BranchScan | undefined, context: Context): Promise<Entry | undefined> {\n\t\tquery ??= {};\n\t\treturn (\n\t\t\tawait this.findEntries({ ...query, limit: query.limit === undefined ? 1 : Math.min(query.limit, 1) }, context)\n\t\t)[0];\n\t}\n\n\tappendMessage(message: AgentMessage, context: Context): Promise<string> {\n\t\treturn this.session.appendToBranch(this.name, { type: \"message\", message }, context);\n\t}\n\n\tappendCustomEntry(customType: string, data: JsonValue | undefined, context: Context): Promise<string> {\n\t\treturn this.session.appendToBranch(\n\t\t\tthis.name,\n\t\t\t{ type: \"custom\", customType, ...(data === undefined ? {} : { data }) },\n\t\t\tcontext,\n\t\t);\n\t}\n}\n\n/** Package-internal typed boundary shared by concrete session repositories. */\nexport class StorageBackedSession<TMetadata extends SessionMetadata = SessionMetadata> implements Session<TMetadata> {\n\treadonly metadata: TMetadata;\n\treadonly idGenerator: IdGenerator;\n\tprivate readonly storage: Storage;\n\tprivate readonly mutationLine: MutationLine;\n\tprivate readonly onClose: (() => void) | undefined;\n\tprivate readonly branches = new Map<string, StorageBackedBranch>();\n\tprivate readonly closedError = new Error(\"Session is closed\");\n\tprivate state: \"open\" | \"closing\" | \"closed\" = \"open\";\n\tprivate closePromise: Promise<void> | undefined;\n\n\tconstructor(metadata: TMetadata, storage: Storage, options: StorageBackedSessionOptions = {}) {\n\t\tthis.metadata = metadata;\n\t\tthis.idGenerator = options.idGenerator ?? { next: uuidv7 };\n\t\tthis.storage = storage;\n\t\tthis.mutationLine = options.mutationLine ?? new MutationLine();\n\t\tthis.onClose = options.onClose;\n\t}\n\n\tasync beginMutation(_context: Context): Promise<SessionMutation> {\n\t\tthis.assertOpen();\n\t\tlet grant!: (mutation: SessionMutation) => void;\n\t\tlet rejectGrant!: (error: unknown) => void;\n\t\tconst granted = new Promise<SessionMutation>((resolve, reject) => {\n\t\t\tgrant = resolve;\n\t\t\trejectGrant = reject;\n\t\t});\n\t\tlet release!: () => void;\n\t\tconst finished = new Promise<void>((resolve) => {\n\t\t\trelease = resolve;\n\t\t});\n\t\tconst line = this.mutationLine.run(async () => {\n\t\t\tgrant(new StorageBackedSessionMutation(this.storage, release));\n\t\t\tawait finished;\n\t\t});\n\t\tvoid line.catch(rejectGrant);\n\t\treturn granted;\n\t}\n\n\tasync mutate<T>(mutation: SessionMutationCallback<T>, context: Context): Promise<T> {\n\t\tconst mutator = await this.beginMutation(context);\n\t\ttry {\n\t\t\treturn await mutation(mutator, context);\n\t\t} finally {\n\t\t\tawait mutator.end(context);\n\t\t}\n\t}\n\n\tasync getEntries(ids: string[], context: Context): Promise<Map<string, Entry>> {\n\t\tthis.assertOpen();\n\t\treturn this.storage.getEntries(ids, context);\n\t}\n\n\tasync getEntry(id: string, context: Context): Promise<Entry | undefined> {\n\t\treturn (await this.getEntries([id], context)).get(id);\n\t}\n\n\tasync getValue<T>(address: Value<T>, context: Context): Promise<StoredValue<T> | undefined> {\n\t\tthis.assertOpen();\n\t\treturn this.storage.getValue(address, context);\n\t}\n\n\tasync scanValues<T>(prefix: Value<T>, context: Context): Promise<StoredValue<T>[]> {\n\t\tthis.assertOpen();\n\t\treturn this.storage.scanValues(prefix, context);\n\t}\n\n\tasync readList<T>(\n\t\taddress: ValueList<T>,\n\t\toptions: ListReadOptions | undefined,\n\t\tcontext: Context,\n\t): Promise<ListElement<T>[]> {\n\t\tthis.assertOpen();\n\t\treturn this.storage.readList(address, options, context);\n\t}\n\n\tasync scanBranch(query: StorageBranchScan, context: Context): Promise<Entry[]> {\n\t\tthis.assertOpen();\n\t\treturn this.storage.scanBranch(query, context);\n\t}\n\n\tasync getStats(context: Context): Promise<SessionStats> {\n\t\tthis.assertOpen();\n\t\treturn this.storage.getStats(context);\n\t}\n\n\tasync getName(context: Context): Promise<string | undefined> {\n\t\treturn (await this.getValue(sessionName, context))?.value;\n\t}\n\n\tasync getLabel(targetId: string, context: Context): Promise<string | undefined> {\n\t\treturn (await this.getValue(entryLabel(targetId), context))?.value;\n\t}\n\n\tasync findEntries(query: EntryQuery | undefined, context: Context): Promise<Entry[]> {\n\t\tquery ??= {};\n\t\tthis.assertOpen();\n\t\tconst order = query.order ?? \"desc\";\n\t\tif (query.cursor !== undefined) {\n\t\t\tif (order === \"asc\" && query.cursor.seq === Number.MAX_SAFE_INTEGER) return [];\n\t\t\tif (order === \"desc\" && query.cursor.seq <= 1) return [];\n\t\t}\n\t\treturn this.storage.scanEntries(\n\t\t\t{\n\t\t\t\ttype: query.type,\n\t\t\t\tcustomType: query.customType,\n\t\t\t\torder,\n\t\t\t\tlimit: query.limit,\n\t\t\t\t...(query.cursor === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: order === \"asc\"\n\t\t\t\t\t\t? { fromSeq: query.cursor.seq + 1 }\n\t\t\t\t\t\t: { toSeq: query.cursor.seq - 1 }),\n\t\t\t},\n\t\t\tcontext,\n\t\t);\n\t}\n\n\tasync findEntry(query: EntryQuery | undefined, context: Context): Promise<Entry | undefined> {\n\t\tquery ??= {};\n\t\treturn (\n\t\t\tawait this.findEntries({ ...query, limit: query.limit === undefined ? 1 : Math.min(query.limit, 1) }, context)\n\t\t)[0];\n\t}\n\n\tasync branch(name: string, context: Context): Promise<Branch | undefined> {\n\t\tthis.assertValidBranchName(name);\n\t\tif ((await this.getValue(branchTip(name), context)) === undefined) return undefined;\n\t\treturn this.getOrCreateBranchObject(name);\n\t}\n\n\tasync createBranch(name: string, at: string | null, context: Context): Promise<Branch> {\n\t\tthis.assertOpen();\n\t\tthis.assertValidBranchName(name);\n\t\tawait this.mutate(async (mutator) => {\n\t\t\tif ((await mutator.getValue(branchTip(name), context)) !== undefined) {\n\t\t\t\tthrow new SessionBranchExistsError(name);\n\t\t\t}\n\t\t\tif (at !== null && !(await mutator.getEntries([at], context)).has(at)) {\n\t\t\t\tthrow new SessionUnknownTargetError(at);\n\t\t\t}\n\t\t\tawait mutator.commit([setValueWrite(branchTip(name), at)], context);\n\t\t}, context);\n\t\treturn this.getOrCreateBranchObject(name);\n\t}\n\n\tsetValue<T>(address: Value<T>, next: NoInfer<T>, context: Context): Promise<void> {\n\t\treturn this.mutate(async (mutator) => {\n\t\t\tawait mutator.commit([setValueWrite(address, next)], context);\n\t\t}, context);\n\t}\n\n\tdeleteValue<T>(address: Value<T>, context: Context): Promise<void> {\n\t\treturn this.mutate(async (mutator) => {\n\t\t\tawait mutator.commit([deleteValueWrite(address)], context);\n\t\t}, context);\n\t}\n\n\tappendList<T>(address: ValueList<T>, element: NoInfer<T>, context: Context): Promise<void> {\n\t\treturn this.mutate(async (mutator) => {\n\t\t\tawait mutator.commit([appendListWrite(address, element)], context);\n\t\t}, context);\n\t}\n\n\tdeleteList<T>(address: ValueList<T>, context: Context): Promise<void> {\n\t\treturn this.mutate(async (mutator) => {\n\t\t\tawait mutator.commit([deleteListWrite(address)], context);\n\t\t}, context);\n\t}\n\n\tsetName(name: string | undefined, context: Context): Promise<void> {\n\t\treturn name === undefined ? this.deleteValue(sessionName, context) : this.setValue(sessionName, name, context);\n\t}\n\n\tsetLabel(targetId: string, label: string | undefined, context: Context): Promise<void> {\n\t\tconst address = entryLabel(targetId);\n\t\treturn label === undefined ? this.deleteValue(address, context) : this.setValue(address, label, context);\n\t}\n\n\tclose(context: Context): Promise<void> {\n\t\tif (this.closePromise !== undefined) return this.closePromise;\n\t\tthis.state = \"closing\";\n\t\tthis.closePromise = this.mutationLine\n\t\t\t.seal(this.closedError)\n\t\t\t.then(() => this.storage.close(context))\n\t\t\t.finally(() => {\n\t\t\t\tthis.state = \"closed\";\n\t\t\t\tthis.onClose?.();\n\t\t\t});\n\t\treturn this.closePromise;\n\t}\n\n\tasync getBranchTip(name: string, context: Context): Promise<string | null> {\n\t\tconst stored = await this.getValue(branchTip(name), context);\n\t\tif (stored === undefined) throw new SessionInvariantError(`Unknown branch: ${name}`);\n\t\treturn stored.value;\n\t}\n\n\tasync appendToBranch(\n\t\tname: string,\n\t\tentry: { type: \"message\"; message: AgentMessage } | { type: \"custom\"; customType: string; data?: JsonValue },\n\t\tcontext: Context,\n\t): Promise<string> {\n\t\tthis.assertOpen();\n\t\tif (entry.type === \"message\" && entry.message.role === \"assistant\" && entry.message.stopReason === \"pending\") {\n\t\t\tthrow new SessionPendingAssistantMessageError();\n\t\t}\n\t\tconst id = this.idGenerator.next();\n\t\tawait this.mutate(async (mutator) => {\n\t\t\tconst tip = await mutator.getValue(branchTip(name), context);\n\t\t\tif (tip === undefined) throw new SessionInvariantError(`Unknown branch: ${name}`);\n\t\t\tawait mutator.commit(\n\t\t\t\t[\n\t\t\t\t\tinsertEntry(\n\t\t\t\t\t\tentry.type === \"message\"\n\t\t\t\t\t\t\t? { id, parentId: tip.value, type: \"message\", message: entry.message }\n\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\t\t\tparentId: tip.value,\n\t\t\t\t\t\t\t\t\ttype: \"custom\",\n\t\t\t\t\t\t\t\t\tcustomType: entry.customType,\n\t\t\t\t\t\t\t\t\t...(entry.data === undefined ? {} : { data: entry.data }),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t),\n\t\t\t\t\tsetValueWrite(branchTip(name), id),\n\t\t\t\t],\n\t\t\t\tcontext,\n\t\t\t);\n\t\t}, context);\n\t\treturn id;\n\t}\n\n\tprivate getOrCreateBranchObject(name: string): Branch {\n\t\tlet branch = this.branches.get(name);\n\t\tif (branch === undefined) {\n\t\t\tbranch = new StorageBackedBranch(name, this);\n\t\t\tthis.branches.set(name, branch);\n\t\t}\n\t\treturn branch;\n\t}\n\n\tprivate assertValidBranchName(name: string): void {\n\t\tif (name.length === 0) throw new SessionInvalidBranchError(name, \"branch name must not be empty\");\n\t\tif (name.includes(\"\\u0000\")) {\n\t\t\tthrow new SessionInvalidBranchError(name, \"branch name must not contain \\\\u0000\");\n\t\t}\n\t}\n\n\tprivate assertOpen(): void {\n\t\tif (this.state !== \"open\") throw this.closedError;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface StorageBenchmarkDataset {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
readonly entryCount: number;
|
|
4
|
+
readonly payloadBytes: number;
|
|
5
|
+
readonly lookupIds: readonly string[];
|
|
6
|
+
readonly tipId: string;
|
|
7
|
+
}
|
|
8
|
+
/** Package-internal deterministic id shared by dataset and transaction generation. */
|
|
9
|
+
export declare function storageBenchmarkEntryId(index: number): string;
|
|
10
|
+
/** Deterministic synthetic linear branches shared by all storage measurements. */
|
|
11
|
+
export declare const STORAGE_BENCHMARK_DATASETS: readonly StorageBenchmarkDataset[];
|
|
12
|
+
//# sourceMappingURL=datasets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"datasets.d.ts","sourceRoot":"","sources":["../../../../../src/harness/session/testing/benchmark/datasets.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACvB;AAED,sFAAsF;AACtF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7D;AAgBD,kFAAkF;AAClF,eAAO,MAAM,0BAA0B,EAAE,SAAS,uBAAuB,EAIxE,CAAC","sourcesContent":["export interface StorageBenchmarkDataset {\n\treadonly name: string;\n\treadonly entryCount: number;\n\treadonly payloadBytes: number;\n\treadonly lookupIds: readonly string[];\n\treadonly tipId: string;\n}\n\n/** Package-internal deterministic id shared by dataset and transaction generation. */\nexport function storageBenchmarkEntryId(index: number): string {\n\treturn `benchmark-entry-${index.toString().padStart(8, \"0\")}`;\n}\n\nfunction createDataset(scale: string, entryCount: number): StorageBenchmarkDataset {\n\tconst lookupCount = Math.min(100, entryCount);\n\treturn {\n\t\tname: `synthetic linear branch: ${scale}, 256-byte payloads`,\n\t\tentryCount,\n\t\tpayloadBytes: 256,\n\t\tlookupIds: Array.from({ length: lookupCount }, (_, index) => {\n\t\t\tconst entryIndex = Math.floor((index * (entryCount - 1)) / Math.max(1, lookupCount - 1));\n\t\t\treturn storageBenchmarkEntryId(entryIndex);\n\t\t}),\n\t\ttipId: storageBenchmarkEntryId(entryCount - 1),\n\t};\n}\n\n/** Deterministic synthetic linear branches shared by all storage measurements. */\nexport const STORAGE_BENCHMARK_DATASETS: readonly StorageBenchmarkDataset[] = [\n\tcreateDataset(\"1k entries\", 1_000),\n\tcreateDataset(\"10k entries\", 10_000),\n\tcreateDataset(\"100k entries\", 100_000),\n];\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Package-internal deterministic id shared by dataset and transaction generation. */
|
|
2
|
+
export function storageBenchmarkEntryId(index) {
|
|
3
|
+
return `benchmark-entry-${index.toString().padStart(8, "0")}`;
|
|
4
|
+
}
|
|
5
|
+
function createDataset(scale, entryCount) {
|
|
6
|
+
const lookupCount = Math.min(100, entryCount);
|
|
7
|
+
return {
|
|
8
|
+
name: `synthetic linear branch: ${scale}, 256-byte payloads`,
|
|
9
|
+
entryCount,
|
|
10
|
+
payloadBytes: 256,
|
|
11
|
+
lookupIds: Array.from({ length: lookupCount }, (_, index) => {
|
|
12
|
+
const entryIndex = Math.floor((index * (entryCount - 1)) / Math.max(1, lookupCount - 1));
|
|
13
|
+
return storageBenchmarkEntryId(entryIndex);
|
|
14
|
+
}),
|
|
15
|
+
tipId: storageBenchmarkEntryId(entryCount - 1),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/** Deterministic synthetic linear branches shared by all storage measurements. */
|
|
19
|
+
export const STORAGE_BENCHMARK_DATASETS = [
|
|
20
|
+
createDataset("1k entries", 1_000),
|
|
21
|
+
createDataset("10k entries", 10_000),
|
|
22
|
+
createDataset("100k entries", 100_000),
|
|
23
|
+
];
|
|
24
|
+
//# sourceMappingURL=datasets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"datasets.js","sourceRoot":"","sources":["../../../../../src/harness/session/testing/benchmark/datasets.ts"],"names":[],"mappings":"AAQA,sFAAsF;AACtF,MAAM,UAAU,uBAAuB,CAAC,KAAa,EAAU;IAC9D,OAAO,mBAAmB,KAAK,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AAAA,CAC9D;AAED,SAAS,aAAa,CAAC,KAAa,EAAE,UAAkB,EAA2B;IAClF,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC9C,OAAO;QACN,IAAI,EAAE,4BAA4B,KAAK,qBAAqB;QAC5D,UAAU;QACV,YAAY,EAAE,GAAG;QACjB,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;YAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC;YACzF,OAAO,uBAAuB,CAAC,UAAU,CAAC,CAAC;QAAA,CAC3C,CAAC;QACF,KAAK,EAAE,uBAAuB,CAAC,UAAU,GAAG,CAAC,CAAC;KAC9C,CAAC;AAAA,CACF;AAED,kFAAkF;AAClF,MAAM,CAAC,MAAM,0BAA0B,GAAuC;IAC7E,aAAa,CAAC,YAAY,EAAE,KAAK,CAAC;IAClC,aAAa,CAAC,aAAa,EAAE,MAAM,CAAC;IACpC,aAAa,CAAC,cAAc,EAAE,OAAO,CAAC;CACtC,CAAC","sourcesContent":["export interface StorageBenchmarkDataset {\n\treadonly name: string;\n\treadonly entryCount: number;\n\treadonly payloadBytes: number;\n\treadonly lookupIds: readonly string[];\n\treadonly tipId: string;\n}\n\n/** Package-internal deterministic id shared by dataset and transaction generation. */\nexport function storageBenchmarkEntryId(index: number): string {\n\treturn `benchmark-entry-${index.toString().padStart(8, \"0\")}`;\n}\n\nfunction createDataset(scale: string, entryCount: number): StorageBenchmarkDataset {\n\tconst lookupCount = Math.min(100, entryCount);\n\treturn {\n\t\tname: `synthetic linear branch: ${scale}, 256-byte payloads`,\n\t\tentryCount,\n\t\tpayloadBytes: 256,\n\t\tlookupIds: Array.from({ length: lookupCount }, (_, index) => {\n\t\t\tconst entryIndex = Math.floor((index * (entryCount - 1)) / Math.max(1, lookupCount - 1));\n\t\t\treturn storageBenchmarkEntryId(entryIndex);\n\t\t}),\n\t\ttipId: storageBenchmarkEntryId(entryCount - 1),\n\t};\n}\n\n/** Deterministic synthetic linear branches shared by all storage measurements. */\nexport const STORAGE_BENCHMARK_DATASETS: readonly StorageBenchmarkDataset[] = [\n\tcreateDataset(\"1k entries\", 1_000),\n\tcreateDataset(\"10k entries\", 10_000),\n\tcreateDataset(\"100k entries\", 100_000),\n];\n"]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { SessionMetadata, SessionRepo } from "../../types.ts";
|
|
2
|
+
import { type StorageBenchmarkDataset } from "./datasets.ts";
|
|
3
|
+
export interface SessionRepoCatalogBenchmarkDataset {
|
|
4
|
+
readonly name: string;
|
|
5
|
+
readonly sessionCount: number;
|
|
6
|
+
}
|
|
7
|
+
interface SessionRepoCatalogReadBenchmarkScenario {
|
|
8
|
+
readonly name: string;
|
|
9
|
+
expectedResult(dataset: SessionRepoCatalogBenchmarkDataset): number;
|
|
10
|
+
run(repo: SessionRepo): Promise<number>;
|
|
11
|
+
}
|
|
12
|
+
interface SessionRepoCatalogWriteBenchmarkOperation {
|
|
13
|
+
run(): Promise<number>;
|
|
14
|
+
}
|
|
15
|
+
interface SessionRepoCatalogWriteBenchmarkScenario {
|
|
16
|
+
readonly name: string;
|
|
17
|
+
readonly expectedResult: number;
|
|
18
|
+
prepare(repo: SessionRepo): Promise<SessionRepoCatalogWriteBenchmarkOperation>;
|
|
19
|
+
}
|
|
20
|
+
interface SessionRepoForkWriteBenchmarkScenario {
|
|
21
|
+
readonly name: string;
|
|
22
|
+
expectedResult(dataset: StorageBenchmarkDataset): number;
|
|
23
|
+
run(repo: SessionRepo, source: SessionMetadata, dataset: StorageBenchmarkDataset): Promise<number>;
|
|
24
|
+
}
|
|
25
|
+
/** Package-internal deterministic session id shared by repository benchmark workloads. */
|
|
26
|
+
export declare function sessionRepoBenchmarkSessionId(index: number): string;
|
|
27
|
+
/** Deterministic closed-session catalogs shared by repository measurements. */
|
|
28
|
+
export declare const SESSION_REPO_CATALOG_BENCHMARK_DATASETS: readonly SessionRepoCatalogBenchmarkDataset[];
|
|
29
|
+
/** Seeds one deterministic catalog and returns its durable metadata in creation order. */
|
|
30
|
+
export declare function seedSessionRepoCatalogBenchmark(repo: SessionRepo, dataset: SessionRepoCatalogBenchmarkDataset): Promise<SessionMetadata[]>;
|
|
31
|
+
/** Shared catalog reads. Returning a number ensures each result is consumed. */
|
|
32
|
+
export declare const SESSION_REPO_CATALOG_READ_BENCHMARK_SCENARIOS: readonly SessionRepoCatalogReadBenchmarkScenario[];
|
|
33
|
+
/** Shared catalog writes. Every invocation receives an equivalent independently prepared repository. */
|
|
34
|
+
export declare const SESSION_REPO_CATALOG_WRITE_BENCHMARK_SCENARIOS: readonly SessionRepoCatalogWriteBenchmarkScenario[];
|
|
35
|
+
/** Initial fork timing uses a bounded source because each iteration owns an equivalent seeded repository. */
|
|
36
|
+
export declare const SESSION_REPO_FORK_BENCHMARK_DATASETS: readonly StorageBenchmarkDataset[];
|
|
37
|
+
/** Seeds one deterministic open source session with a linear main branch. */
|
|
38
|
+
export declare function seedSessionRepoForkBenchmark(repo: SessionRepo, dataset: StorageBenchmarkDataset): Promise<SessionMetadata>;
|
|
39
|
+
/** Shared fork writes. Every invocation receives an equivalent source repository. */
|
|
40
|
+
export declare const SESSION_REPO_FORK_WRITE_BENCHMARK_SCENARIOS: readonly SessionRepoForkWriteBenchmarkScenario[];
|
|
41
|
+
export {};
|
|
42
|
+
//# sourceMappingURL=session-repo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-repo.d.ts","sourceRoot":"","sources":["../../../../../src/harness/session/testing/benchmark/session-repo.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAEnE,OAAO,EAA8B,KAAK,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAGzF,MAAM,WAAW,kCAAkC;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC9B;AAED,UAAU,uCAAuC;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,OAAO,EAAE,kCAAkC,GAAG,MAAM,CAAC;IACpE,GAAG,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACxC;AAED,UAAU,yCAAyC;IAClD,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACvB;AAED,UAAU,wCAAwC;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,yCAAyC,CAAC,CAAC;CAC/E;AAED,UAAU,qCAAqC;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,OAAO,EAAE,uBAAuB,GAAG,MAAM,CAAC;IACzD,GAAG,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACnG;AAED,0FAA0F;AAC1F,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnE;AAYD,+EAA+E;AAC/E,eAAO,MAAM,uCAAuC,EAAE,SAAS,kCAAkC,EAIhG,CAAC;AAEF,0FAA0F;AAC1F,wBAAsB,+BAA+B,CACpD,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,kCAAkC,GACzC,OAAO,CAAC,eAAe,EAAE,CAAC,CAQ5B;AAED,gFAAgF;AAChF,eAAO,MAAM,6CAA6C,EAAE,SAAS,uCAAuC,EAU3G,CAAC;AAEF,wGAAwG;AACxG,eAAO,MAAM,8CAA8C,EAAE,SAAS,wCAAwC,EA2C7G,CAAC;AAEF,6GAA6G;AAC7G,eAAO,MAAM,oCAAoC,EAAE,SAAS,uBAAuB,EAGlF,CAAC;AAEF,6EAA6E;AAC7E,wBAAsB,4BAA4B,CACjD,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,uBAAuB,GAC9B,OAAO,CAAC,eAAe,CAAC,CAsB1B;AAED,qFAAqF;AACrF,eAAO,MAAM,2CAA2C,EAAE,SAAS,qCAAqC,EAiBvG,CAAC","sourcesContent":["import { BACKGROUND_CONTEXT } from \"../../../context.ts\";\nimport type { SessionMetadata, SessionRepo } from \"../../types.ts\";\nimport { branchTip, laneConfig, laneState, setValue } from \"../../values.ts\";\nimport { STORAGE_BENCHMARK_DATASETS, type StorageBenchmarkDataset } from \"./datasets.ts\";\nimport { generateStorageBenchmarkSeedTransactions } from \"./storage.ts\";\n\nexport interface SessionRepoCatalogBenchmarkDataset {\n\treadonly name: string;\n\treadonly sessionCount: number;\n}\n\ninterface SessionRepoCatalogReadBenchmarkScenario {\n\treadonly name: string;\n\texpectedResult(dataset: SessionRepoCatalogBenchmarkDataset): number;\n\trun(repo: SessionRepo): Promise<number>;\n}\n\ninterface SessionRepoCatalogWriteBenchmarkOperation {\n\trun(): Promise<number>;\n}\n\ninterface SessionRepoCatalogWriteBenchmarkScenario {\n\treadonly name: string;\n\treadonly expectedResult: number;\n\tprepare(repo: SessionRepo): Promise<SessionRepoCatalogWriteBenchmarkOperation>;\n}\n\ninterface SessionRepoForkWriteBenchmarkScenario {\n\treadonly name: string;\n\texpectedResult(dataset: StorageBenchmarkDataset): number;\n\trun(repo: SessionRepo, source: SessionMetadata, dataset: StorageBenchmarkDataset): Promise<number>;\n}\n\n/** Package-internal deterministic session id shared by repository benchmark workloads. */\nexport function sessionRepoBenchmarkSessionId(index: number): string {\n\treturn `benchmark-session-${index.toString().padStart(8, \"0\")}`;\n}\n\nconst BENCHMARK_SESSION_ID = sessionRepoBenchmarkSessionId(0);\nconst FORK_DESTINATION_SESSION_ID = sessionRepoBenchmarkSessionId(1);\n\nfunction createCatalogDataset(scale: string, sessionCount: number): SessionRepoCatalogBenchmarkDataset {\n\treturn {\n\t\tname: `synthetic catalog: ${scale} closed sessions`,\n\t\tsessionCount,\n\t};\n}\n\n/** Deterministic closed-session catalogs shared by repository measurements. */\nexport const SESSION_REPO_CATALOG_BENCHMARK_DATASETS: readonly SessionRepoCatalogBenchmarkDataset[] = [\n\tcreateCatalogDataset(\"100\", 100),\n\tcreateCatalogDataset(\"1k\", 1_000),\n\tcreateCatalogDataset(\"10k\", 10_000),\n];\n\n/** Seeds one deterministic catalog and returns its durable metadata in creation order. */\nexport async function seedSessionRepoCatalogBenchmark(\n\trepo: SessionRepo,\n\tdataset: SessionRepoCatalogBenchmarkDataset,\n): Promise<SessionMetadata[]> {\n\tconst metadata: SessionMetadata[] = [];\n\tfor (let index = 0; index < dataset.sessionCount; index++) {\n\t\tconst session = await repo.create({ id: sessionRepoBenchmarkSessionId(index) }, BACKGROUND_CONTEXT);\n\t\tmetadata.push(session.metadata);\n\t\tawait session.close(BACKGROUND_CONTEXT);\n\t}\n\treturn metadata;\n}\n\n/** Shared catalog reads. Returning a number ensures each result is consumed. */\nexport const SESSION_REPO_CATALOG_READ_BENCHMARK_SCENARIOS: readonly SessionRepoCatalogReadBenchmarkScenario[] = [\n\t{\n\t\tname: \"list sessions\",\n\t\texpectedResult(dataset) {\n\t\t\treturn dataset.sessionCount;\n\t\t},\n\t\tasync run(repo) {\n\t\t\treturn (await repo.list(undefined, BACKGROUND_CONTEXT)).length;\n\t\t},\n\t},\n];\n\n/** Shared catalog writes. Every invocation receives an equivalent independently prepared repository. */\nexport const SESSION_REPO_CATALOG_WRITE_BENCHMARK_SCENARIOS: readonly SessionRepoCatalogWriteBenchmarkScenario[] = [\n\t{\n\t\tname: \"create empty session\",\n\t\texpectedResult: 1,\n\t\tprepare(repo) {\n\t\t\treturn Promise.resolve({\n\t\t\t\tasync run() {\n\t\t\t\t\tconst session = await repo.create({ id: BENCHMARK_SESSION_ID }, BACKGROUND_CONTEXT);\n\t\t\t\t\treturn session.metadata.id === BENCHMARK_SESSION_ID ? 1 : 0;\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t},\n\t{\n\t\tname: \"open closed empty session\",\n\t\texpectedResult: 1,\n\t\tasync prepare(repo) {\n\t\t\tconst session = await repo.create({ id: BENCHMARK_SESSION_ID }, BACKGROUND_CONTEXT);\n\t\t\tconst { metadata } = session;\n\t\t\tawait session.close(BACKGROUND_CONTEXT);\n\t\t\treturn {\n\t\t\t\tasync run() {\n\t\t\t\t\tconst reopened = await repo.open(metadata, BACKGROUND_CONTEXT);\n\t\t\t\t\treturn reopened.metadata.id === metadata.id ? 1 : 0;\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t},\n\t{\n\t\tname: \"delete closed empty session\",\n\t\texpectedResult: 1,\n\t\tasync prepare(repo) {\n\t\t\tconst session = await repo.create({ id: BENCHMARK_SESSION_ID }, BACKGROUND_CONTEXT);\n\t\t\tconst { metadata } = session;\n\t\t\tawait session.close(BACKGROUND_CONTEXT);\n\t\t\treturn {\n\t\t\t\tasync run() {\n\t\t\t\t\tawait repo.delete(metadata, BACKGROUND_CONTEXT);\n\t\t\t\t\treturn 1;\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t},\n];\n\n/** Initial fork timing uses a bounded source because each iteration owns an equivalent seeded repository. */\nexport const SESSION_REPO_FORK_BENCHMARK_DATASETS: readonly StorageBenchmarkDataset[] = [\n\tSTORAGE_BENCHMARK_DATASETS[0]!,\n\tSTORAGE_BENCHMARK_DATASETS[1]!,\n];\n\n/** Seeds one deterministic open source session with a linear main branch. */\nexport async function seedSessionRepoForkBenchmark(\n\trepo: SessionRepo,\n\tdataset: StorageBenchmarkDataset,\n): Promise<SessionMetadata> {\n\tconst session = await repo.create({ id: BENCHMARK_SESSION_ID }, BACKGROUND_CONTEXT);\n\tfor (const transaction of generateStorageBenchmarkSeedTransactions(dataset)) {\n\t\tawait session.mutate((mutator) => mutator.commit(transaction, BACKGROUND_CONTEXT), BACKGROUND_CONTEXT);\n\t}\n\tawait session.mutate(\n\t\t(mutator) =>\n\t\t\tmutator.commit(\n\t\t\t\t[\n\t\t\t\t\tsetValue(branchTip(\"main\"), dataset.tipId),\n\t\t\t\t\tsetValue(laneConfig(\"main\"), {\n\t\t\t\t\t\tmodel: { provider: \"benchmark\", modelId: \"benchmark\" },\n\t\t\t\t\t\tthinkingLevel: \"off\",\n\t\t\t\t\t\tactiveToolNames: [],\n\t\t\t\t\t}),\n\t\t\t\t\tsetValue(laneState(\"main\"), { currentOperationId: null, lastOperationId: null, inbox: [] }),\n\t\t\t\t],\n\t\t\t\tBACKGROUND_CONTEXT,\n\t\t\t),\n\t\tBACKGROUND_CONTEXT,\n\t);\n\treturn session.metadata;\n}\n\n/** Shared fork writes. Every invocation receives an equivalent source repository. */\nexport const SESSION_REPO_FORK_WRITE_BENCHMARK_SCENARIOS: readonly SessionRepoForkWriteBenchmarkScenario[] = [\n\t{\n\t\tname: \"fork open current branch\",\n\t\texpectedResult(dataset) {\n\t\t\treturn dataset.entryCount;\n\t\t},\n\t\tasync run(repo, source, dataset) {\n\t\t\tconst fork = await repo.fork(\n\t\t\t\tsource,\n\t\t\t\t{ id: FORK_DESTINATION_SESSION_ID, scope: \"branch\", branch: \"main\" },\n\t\t\t\tBACKGROUND_CONTEXT,\n\t\t\t);\n\t\t\treturn fork.metadata.id === FORK_DESTINATION_SESSION_ID && fork.metadata.parentSessionId === source.id\n\t\t\t\t? dataset.entryCount\n\t\t\t\t: 0;\n\t\t},\n\t},\n];\n"]}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { BACKGROUND_CONTEXT } from "../../../context.js";
|
|
2
|
+
import { branchTip, laneConfig, laneState, setValue } from "../../values.js";
|
|
3
|
+
import { STORAGE_BENCHMARK_DATASETS } from "./datasets.js";
|
|
4
|
+
import { generateStorageBenchmarkSeedTransactions } from "./storage.js";
|
|
5
|
+
/** Package-internal deterministic session id shared by repository benchmark workloads. */
|
|
6
|
+
export function sessionRepoBenchmarkSessionId(index) {
|
|
7
|
+
return `benchmark-session-${index.toString().padStart(8, "0")}`;
|
|
8
|
+
}
|
|
9
|
+
const BENCHMARK_SESSION_ID = sessionRepoBenchmarkSessionId(0);
|
|
10
|
+
const FORK_DESTINATION_SESSION_ID = sessionRepoBenchmarkSessionId(1);
|
|
11
|
+
function createCatalogDataset(scale, sessionCount) {
|
|
12
|
+
return {
|
|
13
|
+
name: `synthetic catalog: ${scale} closed sessions`,
|
|
14
|
+
sessionCount,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** Deterministic closed-session catalogs shared by repository measurements. */
|
|
18
|
+
export const SESSION_REPO_CATALOG_BENCHMARK_DATASETS = [
|
|
19
|
+
createCatalogDataset("100", 100),
|
|
20
|
+
createCatalogDataset("1k", 1_000),
|
|
21
|
+
createCatalogDataset("10k", 10_000),
|
|
22
|
+
];
|
|
23
|
+
/** Seeds one deterministic catalog and returns its durable metadata in creation order. */
|
|
24
|
+
export async function seedSessionRepoCatalogBenchmark(repo, dataset) {
|
|
25
|
+
const metadata = [];
|
|
26
|
+
for (let index = 0; index < dataset.sessionCount; index++) {
|
|
27
|
+
const session = await repo.create({ id: sessionRepoBenchmarkSessionId(index) }, BACKGROUND_CONTEXT);
|
|
28
|
+
metadata.push(session.metadata);
|
|
29
|
+
await session.close(BACKGROUND_CONTEXT);
|
|
30
|
+
}
|
|
31
|
+
return metadata;
|
|
32
|
+
}
|
|
33
|
+
/** Shared catalog reads. Returning a number ensures each result is consumed. */
|
|
34
|
+
export const SESSION_REPO_CATALOG_READ_BENCHMARK_SCENARIOS = [
|
|
35
|
+
{
|
|
36
|
+
name: "list sessions",
|
|
37
|
+
expectedResult(dataset) {
|
|
38
|
+
return dataset.sessionCount;
|
|
39
|
+
},
|
|
40
|
+
async run(repo) {
|
|
41
|
+
return (await repo.list(undefined, BACKGROUND_CONTEXT)).length;
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
/** Shared catalog writes. Every invocation receives an equivalent independently prepared repository. */
|
|
46
|
+
export const SESSION_REPO_CATALOG_WRITE_BENCHMARK_SCENARIOS = [
|
|
47
|
+
{
|
|
48
|
+
name: "create empty session",
|
|
49
|
+
expectedResult: 1,
|
|
50
|
+
prepare(repo) {
|
|
51
|
+
return Promise.resolve({
|
|
52
|
+
async run() {
|
|
53
|
+
const session = await repo.create({ id: BENCHMARK_SESSION_ID }, BACKGROUND_CONTEXT);
|
|
54
|
+
return session.metadata.id === BENCHMARK_SESSION_ID ? 1 : 0;
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: "open closed empty session",
|
|
61
|
+
expectedResult: 1,
|
|
62
|
+
async prepare(repo) {
|
|
63
|
+
const session = await repo.create({ id: BENCHMARK_SESSION_ID }, BACKGROUND_CONTEXT);
|
|
64
|
+
const { metadata } = session;
|
|
65
|
+
await session.close(BACKGROUND_CONTEXT);
|
|
66
|
+
return {
|
|
67
|
+
async run() {
|
|
68
|
+
const reopened = await repo.open(metadata, BACKGROUND_CONTEXT);
|
|
69
|
+
return reopened.metadata.id === metadata.id ? 1 : 0;
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "delete closed empty session",
|
|
76
|
+
expectedResult: 1,
|
|
77
|
+
async prepare(repo) {
|
|
78
|
+
const session = await repo.create({ id: BENCHMARK_SESSION_ID }, BACKGROUND_CONTEXT);
|
|
79
|
+
const { metadata } = session;
|
|
80
|
+
await session.close(BACKGROUND_CONTEXT);
|
|
81
|
+
return {
|
|
82
|
+
async run() {
|
|
83
|
+
await repo.delete(metadata, BACKGROUND_CONTEXT);
|
|
84
|
+
return 1;
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
];
|
|
90
|
+
/** Initial fork timing uses a bounded source because each iteration owns an equivalent seeded repository. */
|
|
91
|
+
export const SESSION_REPO_FORK_BENCHMARK_DATASETS = [
|
|
92
|
+
STORAGE_BENCHMARK_DATASETS[0],
|
|
93
|
+
STORAGE_BENCHMARK_DATASETS[1],
|
|
94
|
+
];
|
|
95
|
+
/** Seeds one deterministic open source session with a linear main branch. */
|
|
96
|
+
export async function seedSessionRepoForkBenchmark(repo, dataset) {
|
|
97
|
+
const session = await repo.create({ id: BENCHMARK_SESSION_ID }, BACKGROUND_CONTEXT);
|
|
98
|
+
for (const transaction of generateStorageBenchmarkSeedTransactions(dataset)) {
|
|
99
|
+
await session.mutate((mutator) => mutator.commit(transaction, BACKGROUND_CONTEXT), BACKGROUND_CONTEXT);
|
|
100
|
+
}
|
|
101
|
+
await session.mutate((mutator) => mutator.commit([
|
|
102
|
+
setValue(branchTip("main"), dataset.tipId),
|
|
103
|
+
setValue(laneConfig("main"), {
|
|
104
|
+
model: { provider: "benchmark", modelId: "benchmark" },
|
|
105
|
+
thinkingLevel: "off",
|
|
106
|
+
activeToolNames: [],
|
|
107
|
+
}),
|
|
108
|
+
setValue(laneState("main"), { currentOperationId: null, lastOperationId: null, inbox: [] }),
|
|
109
|
+
], BACKGROUND_CONTEXT), BACKGROUND_CONTEXT);
|
|
110
|
+
return session.metadata;
|
|
111
|
+
}
|
|
112
|
+
/** Shared fork writes. Every invocation receives an equivalent source repository. */
|
|
113
|
+
export const SESSION_REPO_FORK_WRITE_BENCHMARK_SCENARIOS = [
|
|
114
|
+
{
|
|
115
|
+
name: "fork open current branch",
|
|
116
|
+
expectedResult(dataset) {
|
|
117
|
+
return dataset.entryCount;
|
|
118
|
+
},
|
|
119
|
+
async run(repo, source, dataset) {
|
|
120
|
+
const fork = await repo.fork(source, { id: FORK_DESTINATION_SESSION_ID, scope: "branch", branch: "main" }, BACKGROUND_CONTEXT);
|
|
121
|
+
return fork.metadata.id === FORK_DESTINATION_SESSION_ID && fork.metadata.parentSessionId === source.id
|
|
122
|
+
? dataset.entryCount
|
|
123
|
+
: 0;
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
];
|
|
127
|
+
//# sourceMappingURL=session-repo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-repo.js","sourceRoot":"","sources":["../../../../../src/harness/session/testing/benchmark/session-repo.ts"],"names":[],"mappings":"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","sourcesContent":["import { BACKGROUND_CONTEXT } from \"../../../context.ts\";\nimport type { SessionMetadata, SessionRepo } from \"../../types.ts\";\nimport { branchTip, laneConfig, laneState, setValue } from \"../../values.ts\";\nimport { STORAGE_BENCHMARK_DATASETS, type StorageBenchmarkDataset } from \"./datasets.ts\";\nimport { generateStorageBenchmarkSeedTransactions } from \"./storage.ts\";\n\nexport interface SessionRepoCatalogBenchmarkDataset {\n\treadonly name: string;\n\treadonly sessionCount: number;\n}\n\ninterface SessionRepoCatalogReadBenchmarkScenario {\n\treadonly name: string;\n\texpectedResult(dataset: SessionRepoCatalogBenchmarkDataset): number;\n\trun(repo: SessionRepo): Promise<number>;\n}\n\ninterface SessionRepoCatalogWriteBenchmarkOperation {\n\trun(): Promise<number>;\n}\n\ninterface SessionRepoCatalogWriteBenchmarkScenario {\n\treadonly name: string;\n\treadonly expectedResult: number;\n\tprepare(repo: SessionRepo): Promise<SessionRepoCatalogWriteBenchmarkOperation>;\n}\n\ninterface SessionRepoForkWriteBenchmarkScenario {\n\treadonly name: string;\n\texpectedResult(dataset: StorageBenchmarkDataset): number;\n\trun(repo: SessionRepo, source: SessionMetadata, dataset: StorageBenchmarkDataset): Promise<number>;\n}\n\n/** Package-internal deterministic session id shared by repository benchmark workloads. */\nexport function sessionRepoBenchmarkSessionId(index: number): string {\n\treturn `benchmark-session-${index.toString().padStart(8, \"0\")}`;\n}\n\nconst BENCHMARK_SESSION_ID = sessionRepoBenchmarkSessionId(0);\nconst FORK_DESTINATION_SESSION_ID = sessionRepoBenchmarkSessionId(1);\n\nfunction createCatalogDataset(scale: string, sessionCount: number): SessionRepoCatalogBenchmarkDataset {\n\treturn {\n\t\tname: `synthetic catalog: ${scale} closed sessions`,\n\t\tsessionCount,\n\t};\n}\n\n/** Deterministic closed-session catalogs shared by repository measurements. */\nexport const SESSION_REPO_CATALOG_BENCHMARK_DATASETS: readonly SessionRepoCatalogBenchmarkDataset[] = [\n\tcreateCatalogDataset(\"100\", 100),\n\tcreateCatalogDataset(\"1k\", 1_000),\n\tcreateCatalogDataset(\"10k\", 10_000),\n];\n\n/** Seeds one deterministic catalog and returns its durable metadata in creation order. */\nexport async function seedSessionRepoCatalogBenchmark(\n\trepo: SessionRepo,\n\tdataset: SessionRepoCatalogBenchmarkDataset,\n): Promise<SessionMetadata[]> {\n\tconst metadata: SessionMetadata[] = [];\n\tfor (let index = 0; index < dataset.sessionCount; index++) {\n\t\tconst session = await repo.create({ id: sessionRepoBenchmarkSessionId(index) }, BACKGROUND_CONTEXT);\n\t\tmetadata.push(session.metadata);\n\t\tawait session.close(BACKGROUND_CONTEXT);\n\t}\n\treturn metadata;\n}\n\n/** Shared catalog reads. Returning a number ensures each result is consumed. */\nexport const SESSION_REPO_CATALOG_READ_BENCHMARK_SCENARIOS: readonly SessionRepoCatalogReadBenchmarkScenario[] = [\n\t{\n\t\tname: \"list sessions\",\n\t\texpectedResult(dataset) {\n\t\t\treturn dataset.sessionCount;\n\t\t},\n\t\tasync run(repo) {\n\t\t\treturn (await repo.list(undefined, BACKGROUND_CONTEXT)).length;\n\t\t},\n\t},\n];\n\n/** Shared catalog writes. Every invocation receives an equivalent independently prepared repository. */\nexport const SESSION_REPO_CATALOG_WRITE_BENCHMARK_SCENARIOS: readonly SessionRepoCatalogWriteBenchmarkScenario[] = [\n\t{\n\t\tname: \"create empty session\",\n\t\texpectedResult: 1,\n\t\tprepare(repo) {\n\t\t\treturn Promise.resolve({\n\t\t\t\tasync run() {\n\t\t\t\t\tconst session = await repo.create({ id: BENCHMARK_SESSION_ID }, BACKGROUND_CONTEXT);\n\t\t\t\t\treturn session.metadata.id === BENCHMARK_SESSION_ID ? 1 : 0;\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t},\n\t{\n\t\tname: \"open closed empty session\",\n\t\texpectedResult: 1,\n\t\tasync prepare(repo) {\n\t\t\tconst session = await repo.create({ id: BENCHMARK_SESSION_ID }, BACKGROUND_CONTEXT);\n\t\t\tconst { metadata } = session;\n\t\t\tawait session.close(BACKGROUND_CONTEXT);\n\t\t\treturn {\n\t\t\t\tasync run() {\n\t\t\t\t\tconst reopened = await repo.open(metadata, BACKGROUND_CONTEXT);\n\t\t\t\t\treturn reopened.metadata.id === metadata.id ? 1 : 0;\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t},\n\t{\n\t\tname: \"delete closed empty session\",\n\t\texpectedResult: 1,\n\t\tasync prepare(repo) {\n\t\t\tconst session = await repo.create({ id: BENCHMARK_SESSION_ID }, BACKGROUND_CONTEXT);\n\t\t\tconst { metadata } = session;\n\t\t\tawait session.close(BACKGROUND_CONTEXT);\n\t\t\treturn {\n\t\t\t\tasync run() {\n\t\t\t\t\tawait repo.delete(metadata, BACKGROUND_CONTEXT);\n\t\t\t\t\treturn 1;\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t},\n];\n\n/** Initial fork timing uses a bounded source because each iteration owns an equivalent seeded repository. */\nexport const SESSION_REPO_FORK_BENCHMARK_DATASETS: readonly StorageBenchmarkDataset[] = [\n\tSTORAGE_BENCHMARK_DATASETS[0]!,\n\tSTORAGE_BENCHMARK_DATASETS[1]!,\n];\n\n/** Seeds one deterministic open source session with a linear main branch. */\nexport async function seedSessionRepoForkBenchmark(\n\trepo: SessionRepo,\n\tdataset: StorageBenchmarkDataset,\n): Promise<SessionMetadata> {\n\tconst session = await repo.create({ id: BENCHMARK_SESSION_ID }, BACKGROUND_CONTEXT);\n\tfor (const transaction of generateStorageBenchmarkSeedTransactions(dataset)) {\n\t\tawait session.mutate((mutator) => mutator.commit(transaction, BACKGROUND_CONTEXT), BACKGROUND_CONTEXT);\n\t}\n\tawait session.mutate(\n\t\t(mutator) =>\n\t\t\tmutator.commit(\n\t\t\t\t[\n\t\t\t\t\tsetValue(branchTip(\"main\"), dataset.tipId),\n\t\t\t\t\tsetValue(laneConfig(\"main\"), {\n\t\t\t\t\t\tmodel: { provider: \"benchmark\", modelId: \"benchmark\" },\n\t\t\t\t\t\tthinkingLevel: \"off\",\n\t\t\t\t\t\tactiveToolNames: [],\n\t\t\t\t\t}),\n\t\t\t\t\tsetValue(laneState(\"main\"), { currentOperationId: null, lastOperationId: null, inbox: [] }),\n\t\t\t\t],\n\t\t\t\tBACKGROUND_CONTEXT,\n\t\t\t),\n\t\tBACKGROUND_CONTEXT,\n\t);\n\treturn session.metadata;\n}\n\n/** Shared fork writes. Every invocation receives an equivalent source repository. */\nexport const SESSION_REPO_FORK_WRITE_BENCHMARK_SCENARIOS: readonly SessionRepoForkWriteBenchmarkScenario[] = [\n\t{\n\t\tname: \"fork open current branch\",\n\t\texpectedResult(dataset) {\n\t\t\treturn dataset.entryCount;\n\t\t},\n\t\tasync run(repo, source, dataset) {\n\t\t\tconst fork = await repo.fork(\n\t\t\t\tsource,\n\t\t\t\t{ id: FORK_DESTINATION_SESSION_ID, scope: \"branch\", branch: \"main\" },\n\t\t\t\tBACKGROUND_CONTEXT,\n\t\t\t);\n\t\t\treturn fork.metadata.id === FORK_DESTINATION_SESSION_ID && fork.metadata.parentSessionId === source.id\n\t\t\t\t? dataset.entryCount\n\t\t\t\t: 0;\n\t\t},\n\t},\n];\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Storage, Write } from "../../types.ts";
|
|
2
|
+
import { type StorageBenchmarkDataset } from "./datasets.ts";
|
|
3
|
+
/** Generates deterministic seed transactions without claiming a production data distribution. */
|
|
4
|
+
export declare function generateStorageBenchmarkSeedTransactions(dataset: StorageBenchmarkDataset): Generator<Write[]>;
|
|
5
|
+
/** Seeds one deterministic synthetic linear branch. */
|
|
6
|
+
export declare function seedStorageBenchmark(storage: Storage, dataset: StorageBenchmarkDataset): Promise<void>;
|
|
7
|
+
/** A steady-state read operation run against a pre-seeded fixture. */
|
|
8
|
+
interface StorageReadBenchmarkScenario {
|
|
9
|
+
readonly name: string;
|
|
10
|
+
expectedResult(dataset: StorageBenchmarkDataset): number;
|
|
11
|
+
run(storage: Storage, dataset: StorageBenchmarkDataset): Promise<number>;
|
|
12
|
+
}
|
|
13
|
+
/** A write operation run once against each independently prepared fixture. */
|
|
14
|
+
interface StorageWriteBenchmarkScenario {
|
|
15
|
+
readonly name: string;
|
|
16
|
+
readonly writeCount: number;
|
|
17
|
+
prepare?(storage: Storage): Promise<void>;
|
|
18
|
+
run(storage: Storage): Promise<number>;
|
|
19
|
+
}
|
|
20
|
+
/** Shared read scenarios. Returning a number ensures each result is consumed. */
|
|
21
|
+
export declare const STORAGE_READ_BENCHMARK_SCENARIOS: readonly StorageReadBenchmarkScenario[];
|
|
22
|
+
/** Shared writes. Every invocation receives equivalent pre-benchmark state. */
|
|
23
|
+
export declare const STORAGE_WRITE_BENCHMARK_SCENARIOS: readonly StorageWriteBenchmarkScenario[];
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../../../src/harness/session/testing/benchmark/storage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAA0B,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE7E,OAAO,EAA8B,KAAK,uBAAuB,EAA2B,MAAM,eAAe,CAAC;AA2BlH,iGAAiG;AACjG,wBAAiB,wCAAwC,CAAC,OAAO,EAAE,uBAAuB,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,CAQ9G;AAED,uDAAuD;AACvD,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAG5G;AAED,sEAAsE;AACtE,UAAU,4BAA4B;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,OAAO,EAAE,uBAAuB,GAAG,MAAM,CAAC;IACzD,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACzE;AAED,8EAA8E;AAC9E,UAAU,6BAA6B;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACvC;AAuBD,iFAAiF;AACjF,eAAO,MAAM,gCAAgC,EAAE,SAAS,4BAA4B,EA6BnF,CAAC;AAEF,+EAA+E;AAC/E,eAAO,MAAM,iCAAiC,EAAE,SAAS,6BAA6B,EAyBrF,CAAC","sourcesContent":["import { BACKGROUND_CONTEXT } from \"../../../context.ts\";\nimport { insertEntry, insertUsage } from \"../../commit.ts\";\nimport type { MessageEntry, NewEntry, Storage, Write } from \"../../types.ts\";\nimport { branchTip, setValue } from \"../../values.ts\";\nimport { STORAGE_BENCHMARK_DATASETS, type StorageBenchmarkDataset, storageBenchmarkEntryId } from \"./datasets.ts\";\n\nconst MESSAGE_TIMESTAMP = 1_650_000_000_000;\nconst SEED_BATCH_SIZE = 250;\nconst WRITE_BASELINE_DATASET = STORAGE_BENCHMARK_DATASETS[0]!;\n\nfunction createEntry(index: number, payloadBytes: number): NewEntry<MessageEntry> {\n\tconst id = storageBenchmarkEntryId(index);\n\tconst prefix = `${id}:`;\n\treturn {\n\t\tid,\n\t\tparentId: index === 0 ? null : storageBenchmarkEntryId(index - 1),\n\t\ttype: \"message\",\n\t\tmessage: {\n\t\t\trole: \"user\",\n\t\t\tcontent: [{ type: \"text\", text: prefix + \"x\".repeat(Math.max(0, payloadBytes - prefix.length)) }],\n\t\t\ttimestamp: MESSAGE_TIMESTAMP,\n\t\t},\n\t};\n}\n\nfunction createStorageBenchmarkTransaction(startIndex: number, entryCount: number, payloadBytes: number): Write[] {\n\treturn Array.from({ length: entryCount }, (_, offset) =>\n\t\tinsertEntry(createEntry(startIndex + offset, payloadBytes)),\n\t);\n}\n\n/** Generates deterministic seed transactions without claiming a production data distribution. */\nexport function* generateStorageBenchmarkSeedTransactions(dataset: StorageBenchmarkDataset): Generator<Write[]> {\n\tfor (let startIndex = 0; startIndex < dataset.entryCount; startIndex += SEED_BATCH_SIZE) {\n\t\tyield createStorageBenchmarkTransaction(\n\t\t\tstartIndex,\n\t\t\tMath.min(SEED_BATCH_SIZE, dataset.entryCount - startIndex),\n\t\t\tdataset.payloadBytes,\n\t\t);\n\t}\n}\n\n/** Seeds one deterministic synthetic linear branch. */\nexport async function seedStorageBenchmark(storage: Storage, dataset: StorageBenchmarkDataset): Promise<void> {\n\tfor (const transaction of generateStorageBenchmarkSeedTransactions(dataset))\n\t\tawait storage.commit(transaction, BACKGROUND_CONTEXT);\n}\n\n/** A steady-state read operation run against a pre-seeded fixture. */\ninterface StorageReadBenchmarkScenario {\n\treadonly name: string;\n\texpectedResult(dataset: StorageBenchmarkDataset): number;\n\trun(storage: Storage, dataset: StorageBenchmarkDataset): Promise<number>;\n}\n\n/** A write operation run once against each independently prepared fixture. */\ninterface StorageWriteBenchmarkScenario {\n\treadonly name: string;\n\treadonly writeCount: number;\n\tprepare?(storage: Storage): Promise<void>;\n\trun(storage: Storage): Promise<number>;\n}\n\nconst singleEntryTransaction = createStorageBenchmarkTransaction(0, 1, 256);\nconst hundredEntryTransaction = createStorageBenchmarkTransaction(0, 100, 256);\nconst appendedEntryId = storageBenchmarkEntryId(WRITE_BASELINE_DATASET.entryCount);\nconst mixedAppendTransaction: Write[] = [\n\t...createStorageBenchmarkTransaction(WRITE_BASELINE_DATASET.entryCount, 1, WRITE_BASELINE_DATASET.payloadBytes),\n\tsetValue(branchTip(\"main\"), appendedEntryId),\n\tinsertUsage({\n\t\tid: \"benchmark-usage\",\n\t\tentryId: appendedEntryId,\n\t\tadjustment: false,\n\t\tusage: {\n\t\t\tinput: 1_000,\n\t\t\toutput: 250,\n\t\t\tcacheRead: 500,\n\t\t\tcacheWrite: 0,\n\t\t\ttotalTokens: 1_250,\n\t\t\tcost: { input: 0.001, output: 0.001, cacheRead: 0.0001, cacheWrite: 0, total: 0.0021 },\n\t\t},\n\t}),\n];\n\n/** Shared read scenarios. Returning a number ensures each result is consumed. */\nexport const STORAGE_READ_BENCHMARK_SCENARIOS: readonly StorageReadBenchmarkScenario[] = [\n\t{\n\t\tname: \"get 100 distributed entries\",\n\t\texpectedResult(dataset) {\n\t\t\treturn dataset.lookupIds.length;\n\t\t},\n\t\tasync run(storage, dataset) {\n\t\t\treturn (await storage.getEntries([...dataset.lookupIds], BACKGROUND_CONTEXT)).size;\n\t\t},\n\t},\n\t{\n\t\tname: \"scan latest 50 entries\",\n\t\texpectedResult(dataset) {\n\t\t\treturn Math.min(50, dataset.entryCount);\n\t\t},\n\t\tasync run(storage) {\n\t\t\treturn (await storage.scanEntries({ order: \"desc\", limit: 50 }, BACKGROUND_CONTEXT)).length;\n\t\t},\n\t},\n\t{\n\t\tname: \"scan full branch structure\",\n\t\texpectedResult(dataset) {\n\t\t\treturn dataset.entryCount;\n\t\t},\n\t\tasync run(storage, dataset) {\n\t\t\treturn (await storage.scanBranchStructure({ start: dataset.tipId, order: \"newestFirst\" }, BACKGROUND_CONTEXT))\n\t\t\t\t.length;\n\t\t},\n\t},\n];\n\n/** Shared writes. Every invocation receives equivalent pre-benchmark state. */\nexport const STORAGE_WRITE_BENCHMARK_SCENARIOS: readonly StorageWriteBenchmarkScenario[] = [\n\t{\n\t\tname: \"commit one message entry\",\n\t\twriteCount: 1,\n\t\tasync run(storage) {\n\t\t\treturn (await storage.commit(singleEntryTransaction, BACKGROUND_CONTEXT)).seqs.length;\n\t\t},\n\t},\n\t{\n\t\tname: \"commit 100 message entries\",\n\t\twriteCount: 100,\n\t\tasync run(storage) {\n\t\t\treturn (await storage.commit(hundredEntryTransaction, BACKGROUND_CONTEXT)).seqs.length;\n\t\t},\n\t},\n\t{\n\t\tname: `commit mixed append (${WRITE_BASELINE_DATASET.name})`,\n\t\twriteCount: 3,\n\t\tprepare(storage) {\n\t\t\treturn seedStorageBenchmark(storage, WRITE_BASELINE_DATASET);\n\t\t},\n\t\tasync run(storage) {\n\t\t\treturn (await storage.commit(mixedAppendTransaction, BACKGROUND_CONTEXT)).seqs.length;\n\t\t},\n\t},\n];\n"]}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { BACKGROUND_CONTEXT } from "../../../context.js";
|
|
2
|
+
import { insertEntry, insertUsage } from "../../commit.js";
|
|
3
|
+
import { branchTip, setValue } from "../../values.js";
|
|
4
|
+
import { STORAGE_BENCHMARK_DATASETS, storageBenchmarkEntryId } from "./datasets.js";
|
|
5
|
+
const MESSAGE_TIMESTAMP = 1_650_000_000_000;
|
|
6
|
+
const SEED_BATCH_SIZE = 250;
|
|
7
|
+
const WRITE_BASELINE_DATASET = STORAGE_BENCHMARK_DATASETS[0];
|
|
8
|
+
function createEntry(index, payloadBytes) {
|
|
9
|
+
const id = storageBenchmarkEntryId(index);
|
|
10
|
+
const prefix = `${id}:`;
|
|
11
|
+
return {
|
|
12
|
+
id,
|
|
13
|
+
parentId: index === 0 ? null : storageBenchmarkEntryId(index - 1),
|
|
14
|
+
type: "message",
|
|
15
|
+
message: {
|
|
16
|
+
role: "user",
|
|
17
|
+
content: [{ type: "text", text: prefix + "x".repeat(Math.max(0, payloadBytes - prefix.length)) }],
|
|
18
|
+
timestamp: MESSAGE_TIMESTAMP,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function createStorageBenchmarkTransaction(startIndex, entryCount, payloadBytes) {
|
|
23
|
+
return Array.from({ length: entryCount }, (_, offset) => insertEntry(createEntry(startIndex + offset, payloadBytes)));
|
|
24
|
+
}
|
|
25
|
+
/** Generates deterministic seed transactions without claiming a production data distribution. */
|
|
26
|
+
export function* generateStorageBenchmarkSeedTransactions(dataset) {
|
|
27
|
+
for (let startIndex = 0; startIndex < dataset.entryCount; startIndex += SEED_BATCH_SIZE) {
|
|
28
|
+
yield createStorageBenchmarkTransaction(startIndex, Math.min(SEED_BATCH_SIZE, dataset.entryCount - startIndex), dataset.payloadBytes);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** Seeds one deterministic synthetic linear branch. */
|
|
32
|
+
export async function seedStorageBenchmark(storage, dataset) {
|
|
33
|
+
for (const transaction of generateStorageBenchmarkSeedTransactions(dataset))
|
|
34
|
+
await storage.commit(transaction, BACKGROUND_CONTEXT);
|
|
35
|
+
}
|
|
36
|
+
const singleEntryTransaction = createStorageBenchmarkTransaction(0, 1, 256);
|
|
37
|
+
const hundredEntryTransaction = createStorageBenchmarkTransaction(0, 100, 256);
|
|
38
|
+
const appendedEntryId = storageBenchmarkEntryId(WRITE_BASELINE_DATASET.entryCount);
|
|
39
|
+
const mixedAppendTransaction = [
|
|
40
|
+
...createStorageBenchmarkTransaction(WRITE_BASELINE_DATASET.entryCount, 1, WRITE_BASELINE_DATASET.payloadBytes),
|
|
41
|
+
setValue(branchTip("main"), appendedEntryId),
|
|
42
|
+
insertUsage({
|
|
43
|
+
id: "benchmark-usage",
|
|
44
|
+
entryId: appendedEntryId,
|
|
45
|
+
adjustment: false,
|
|
46
|
+
usage: {
|
|
47
|
+
input: 1_000,
|
|
48
|
+
output: 250,
|
|
49
|
+
cacheRead: 500,
|
|
50
|
+
cacheWrite: 0,
|
|
51
|
+
totalTokens: 1_250,
|
|
52
|
+
cost: { input: 0.001, output: 0.001, cacheRead: 0.0001, cacheWrite: 0, total: 0.0021 },
|
|
53
|
+
},
|
|
54
|
+
}),
|
|
55
|
+
];
|
|
56
|
+
/** Shared read scenarios. Returning a number ensures each result is consumed. */
|
|
57
|
+
export const STORAGE_READ_BENCHMARK_SCENARIOS = [
|
|
58
|
+
{
|
|
59
|
+
name: "get 100 distributed entries",
|
|
60
|
+
expectedResult(dataset) {
|
|
61
|
+
return dataset.lookupIds.length;
|
|
62
|
+
},
|
|
63
|
+
async run(storage, dataset) {
|
|
64
|
+
return (await storage.getEntries([...dataset.lookupIds], BACKGROUND_CONTEXT)).size;
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: "scan latest 50 entries",
|
|
69
|
+
expectedResult(dataset) {
|
|
70
|
+
return Math.min(50, dataset.entryCount);
|
|
71
|
+
},
|
|
72
|
+
async run(storage) {
|
|
73
|
+
return (await storage.scanEntries({ order: "desc", limit: 50 }, BACKGROUND_CONTEXT)).length;
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: "scan full branch structure",
|
|
78
|
+
expectedResult(dataset) {
|
|
79
|
+
return dataset.entryCount;
|
|
80
|
+
},
|
|
81
|
+
async run(storage, dataset) {
|
|
82
|
+
return (await storage.scanBranchStructure({ start: dataset.tipId, order: "newestFirst" }, BACKGROUND_CONTEXT))
|
|
83
|
+
.length;
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
];
|
|
87
|
+
/** Shared writes. Every invocation receives equivalent pre-benchmark state. */
|
|
88
|
+
export const STORAGE_WRITE_BENCHMARK_SCENARIOS = [
|
|
89
|
+
{
|
|
90
|
+
name: "commit one message entry",
|
|
91
|
+
writeCount: 1,
|
|
92
|
+
async run(storage) {
|
|
93
|
+
return (await storage.commit(singleEntryTransaction, BACKGROUND_CONTEXT)).seqs.length;
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: "commit 100 message entries",
|
|
98
|
+
writeCount: 100,
|
|
99
|
+
async run(storage) {
|
|
100
|
+
return (await storage.commit(hundredEntryTransaction, BACKGROUND_CONTEXT)).seqs.length;
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: `commit mixed append (${WRITE_BASELINE_DATASET.name})`,
|
|
105
|
+
writeCount: 3,
|
|
106
|
+
prepare(storage) {
|
|
107
|
+
return seedStorageBenchmark(storage, WRITE_BASELINE_DATASET);
|
|
108
|
+
},
|
|
109
|
+
async run(storage) {
|
|
110
|
+
return (await storage.commit(mixedAppendTransaction, BACKGROUND_CONTEXT)).seqs.length;
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
];
|
|
114
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../../../src/harness/session/testing/benchmark/storage.ts"],"names":[],"mappings":"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","sourcesContent":["import { BACKGROUND_CONTEXT } from \"../../../context.ts\";\nimport { insertEntry, insertUsage } from \"../../commit.ts\";\nimport type { MessageEntry, NewEntry, Storage, Write } from \"../../types.ts\";\nimport { branchTip, setValue } from \"../../values.ts\";\nimport { STORAGE_BENCHMARK_DATASETS, type StorageBenchmarkDataset, storageBenchmarkEntryId } from \"./datasets.ts\";\n\nconst MESSAGE_TIMESTAMP = 1_650_000_000_000;\nconst SEED_BATCH_SIZE = 250;\nconst WRITE_BASELINE_DATASET = STORAGE_BENCHMARK_DATASETS[0]!;\n\nfunction createEntry(index: number, payloadBytes: number): NewEntry<MessageEntry> {\n\tconst id = storageBenchmarkEntryId(index);\n\tconst prefix = `${id}:`;\n\treturn {\n\t\tid,\n\t\tparentId: index === 0 ? null : storageBenchmarkEntryId(index - 1),\n\t\ttype: \"message\",\n\t\tmessage: {\n\t\t\trole: \"user\",\n\t\t\tcontent: [{ type: \"text\", text: prefix + \"x\".repeat(Math.max(0, payloadBytes - prefix.length)) }],\n\t\t\ttimestamp: MESSAGE_TIMESTAMP,\n\t\t},\n\t};\n}\n\nfunction createStorageBenchmarkTransaction(startIndex: number, entryCount: number, payloadBytes: number): Write[] {\n\treturn Array.from({ length: entryCount }, (_, offset) =>\n\t\tinsertEntry(createEntry(startIndex + offset, payloadBytes)),\n\t);\n}\n\n/** Generates deterministic seed transactions without claiming a production data distribution. */\nexport function* generateStorageBenchmarkSeedTransactions(dataset: StorageBenchmarkDataset): Generator<Write[]> {\n\tfor (let startIndex = 0; startIndex < dataset.entryCount; startIndex += SEED_BATCH_SIZE) {\n\t\tyield createStorageBenchmarkTransaction(\n\t\t\tstartIndex,\n\t\t\tMath.min(SEED_BATCH_SIZE, dataset.entryCount - startIndex),\n\t\t\tdataset.payloadBytes,\n\t\t);\n\t}\n}\n\n/** Seeds one deterministic synthetic linear branch. */\nexport async function seedStorageBenchmark(storage: Storage, dataset: StorageBenchmarkDataset): Promise<void> {\n\tfor (const transaction of generateStorageBenchmarkSeedTransactions(dataset))\n\t\tawait storage.commit(transaction, BACKGROUND_CONTEXT);\n}\n\n/** A steady-state read operation run against a pre-seeded fixture. */\ninterface StorageReadBenchmarkScenario {\n\treadonly name: string;\n\texpectedResult(dataset: StorageBenchmarkDataset): number;\n\trun(storage: Storage, dataset: StorageBenchmarkDataset): Promise<number>;\n}\n\n/** A write operation run once against each independently prepared fixture. */\ninterface StorageWriteBenchmarkScenario {\n\treadonly name: string;\n\treadonly writeCount: number;\n\tprepare?(storage: Storage): Promise<void>;\n\trun(storage: Storage): Promise<number>;\n}\n\nconst singleEntryTransaction = createStorageBenchmarkTransaction(0, 1, 256);\nconst hundredEntryTransaction = createStorageBenchmarkTransaction(0, 100, 256);\nconst appendedEntryId = storageBenchmarkEntryId(WRITE_BASELINE_DATASET.entryCount);\nconst mixedAppendTransaction: Write[] = [\n\t...createStorageBenchmarkTransaction(WRITE_BASELINE_DATASET.entryCount, 1, WRITE_BASELINE_DATASET.payloadBytes),\n\tsetValue(branchTip(\"main\"), appendedEntryId),\n\tinsertUsage({\n\t\tid: \"benchmark-usage\",\n\t\tentryId: appendedEntryId,\n\t\tadjustment: false,\n\t\tusage: {\n\t\t\tinput: 1_000,\n\t\t\toutput: 250,\n\t\t\tcacheRead: 500,\n\t\t\tcacheWrite: 0,\n\t\t\ttotalTokens: 1_250,\n\t\t\tcost: { input: 0.001, output: 0.001, cacheRead: 0.0001, cacheWrite: 0, total: 0.0021 },\n\t\t},\n\t}),\n];\n\n/** Shared read scenarios. Returning a number ensures each result is consumed. */\nexport const STORAGE_READ_BENCHMARK_SCENARIOS: readonly StorageReadBenchmarkScenario[] = [\n\t{\n\t\tname: \"get 100 distributed entries\",\n\t\texpectedResult(dataset) {\n\t\t\treturn dataset.lookupIds.length;\n\t\t},\n\t\tasync run(storage, dataset) {\n\t\t\treturn (await storage.getEntries([...dataset.lookupIds], BACKGROUND_CONTEXT)).size;\n\t\t},\n\t},\n\t{\n\t\tname: \"scan latest 50 entries\",\n\t\texpectedResult(dataset) {\n\t\t\treturn Math.min(50, dataset.entryCount);\n\t\t},\n\t\tasync run(storage) {\n\t\t\treturn (await storage.scanEntries({ order: \"desc\", limit: 50 }, BACKGROUND_CONTEXT)).length;\n\t\t},\n\t},\n\t{\n\t\tname: \"scan full branch structure\",\n\t\texpectedResult(dataset) {\n\t\t\treturn dataset.entryCount;\n\t\t},\n\t\tasync run(storage, dataset) {\n\t\t\treturn (await storage.scanBranchStructure({ start: dataset.tipId, order: \"newestFirst\" }, BACKGROUND_CONTEXT))\n\t\t\t\t.length;\n\t\t},\n\t},\n];\n\n/** Shared writes. Every invocation receives equivalent pre-benchmark state. */\nexport const STORAGE_WRITE_BENCHMARK_SCENARIOS: readonly StorageWriteBenchmarkScenario[] = [\n\t{\n\t\tname: \"commit one message entry\",\n\t\twriteCount: 1,\n\t\tasync run(storage) {\n\t\t\treturn (await storage.commit(singleEntryTransaction, BACKGROUND_CONTEXT)).seqs.length;\n\t\t},\n\t},\n\t{\n\t\tname: \"commit 100 message entries\",\n\t\twriteCount: 100,\n\t\tasync run(storage) {\n\t\t\treturn (await storage.commit(hundredEntryTransaction, BACKGROUND_CONTEXT)).seqs.length;\n\t\t},\n\t},\n\t{\n\t\tname: `commit mixed append (${WRITE_BASELINE_DATASET.name})`,\n\t\twriteCount: 3,\n\t\tprepare(storage) {\n\t\t\treturn seedStorageBenchmark(storage, WRITE_BASELINE_DATASET);\n\t\t},\n\t\tasync run(storage) {\n\t\t\treturn (await storage.commit(mixedAppendTransaction, BACKGROUND_CONTEXT)).seqs.length;\n\t\t},\n\t},\n];\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { SessionMetadata, SessionRepo } from "../../types.ts";
|
|
2
|
+
import type { ConformanceCase } from "../types.ts";
|
|
3
|
+
/** Creates lifecycle cases for repositories that support creation, discovery, open, and deletion. */
|
|
4
|
+
export declare function createSessionRepoLifecycleConformance<TMetadata extends SessionMetadata>(backendFactory: () => Promise<Pick<SessionRepo<TMetadata>, "create" | "open" | "list" | "delete">>, onClose?: () => void | Promise<void>): readonly ConformanceCase[];
|
|
5
|
+
/** Creates exclusive-open cases for repositories that own active session handles. */
|
|
6
|
+
export declare function createSessionRepoOwnershipConformance<TMetadata extends SessionMetadata>(backendFactory: () => Promise<Pick<SessionRepo<TMetadata>, "create" | "open">>, onClose?: () => void | Promise<void>): readonly ConformanceCase[];
|
|
7
|
+
/** Creates message cases for repositories that support session creation. */
|
|
8
|
+
export declare function createSessionRepoMessageConformance<TMetadata extends SessionMetadata>(backendFactory: () => Promise<Pick<SessionRepo<TMetadata>, "create">>, onClose?: () => void | Promise<void>): readonly ConformanceCase[];
|
|
9
|
+
/** Creates fork-content cases that do not require concurrent repository coordination. */
|
|
10
|
+
export declare function createSessionRepoForkBehaviorConformance<TMetadata extends SessionMetadata>(backendFactory: () => Promise<Pick<SessionRepo<TMetadata>, "create" | "list" | "fork">>, onClose?: () => void | Promise<void>): readonly ConformanceCase[];
|
|
11
|
+
/** Creates fork cases that require destination reservation across create and fork. */
|
|
12
|
+
export declare function createSessionRepoForkDestinationReservationConformance<TMetadata extends SessionMetadata>(backendFactory: () => Promise<Pick<SessionRepo<TMetadata>, "create" | "fork">>, onClose?: () => void | Promise<void>): readonly ConformanceCase[];
|
|
13
|
+
/** Creates fork cases that require a snapshot boundary on an active source storage queue. */
|
|
14
|
+
export declare function createSessionRepoForkSourceSnapshotConformance<TMetadata extends SessionMetadata>(backendFactory: () => Promise<Pick<SessionRepo<TMetadata>, "create" | "fork">>, onClose?: () => void | Promise<void>): readonly ConformanceCase[];
|
|
15
|
+
/** Creates every fork coordination case. */
|
|
16
|
+
export declare function createSessionRepoForkCoordinationConformance<TMetadata extends SessionMetadata>(backendFactory: () => Promise<Pick<SessionRepo<TMetadata>, "create" | "fork">>, onClose?: () => void | Promise<void>): readonly ConformanceCase[];
|
|
17
|
+
/** Creates every fork conformance case. */
|
|
18
|
+
export declare function createSessionRepoForkConformance<TMetadata extends SessionMetadata>(backendFactory: () => Promise<Pick<SessionRepo<TMetadata>, "create" | "list" | "fork">>, onClose?: () => void | Promise<void>): readonly ConformanceCase[];
|
|
19
|
+
/** Creates every SessionRepo conformance case. */
|
|
20
|
+
export declare function createSessionRepoConformance<TMetadata extends SessionMetadata>(factory: () => Promise<SessionRepo<TMetadata>>, onClose?: () => void | Promise<void>): readonly ConformanceCase[];
|
|
21
|
+
//# sourceMappingURL=session-repo.d.ts.map
|