@effect-agent/storage-cloudflare 0.1.0-beta.46 → 0.1.0-beta.48
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/dist/DoMemoryStore.d.mts +5 -0
- package/dist/DoMemoryStore.mjs +6 -1
- package/dist/DoMemoryStore.mjs.map +1 -1
- package/dist/DoSubmissionLedger.mjs +1 -1
- package/dist/{DoThreadStore-D9ebIYPv.mjs → DoThreadStore-D00TdRAa.mjs} +61 -46
- package/dist/DoThreadStore-D00TdRAa.mjs.map +1 -0
- package/dist/DoThreadStore.mjs +1 -1
- package/dist/MemoryProtocol.mjs +2 -2
- package/dist/MemoryProtocol.mjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/src/DoMemoryStore.ts +5 -0
- package/src/DoThreadStore.ts +15 -10
- package/src/MemoryProtocol.ts +2 -2
- package/src/internal/do-journal.ts +82 -48
- package/dist/DoThreadStore-D9ebIYPv.mjs.map +0 -1
package/dist/DoMemoryStore.d.mts
CHANGED
|
@@ -9,6 +9,8 @@ declare const DoMemoryStorageLimits_base: Schema.Class<DoMemoryStorageLimits, Sc
|
|
|
9
9
|
readonly maxStorageBytes: Schema.Int;
|
|
10
10
|
readonly maxDocuments: Schema.Int;
|
|
11
11
|
readonly maxReceipts: Schema.Int;
|
|
12
|
+
readonly reservedWithdrawalBytes: Schema.optional<Schema.Natural>;
|
|
13
|
+
readonly reservedWithdrawalReceipts: Schema.optional<Schema.Natural>;
|
|
12
14
|
}>, {}>;
|
|
13
15
|
declare class DoMemoryStorageLimits extends DoMemoryStorageLimits_base {}
|
|
14
16
|
declare const defaultDoMemoryStorageLimits: DoMemoryStorageLimits;
|
|
@@ -16,6 +18,9 @@ declare const defaultDoMemoryStorageLimits: DoMemoryStorageLimits;
|
|
|
16
18
|
* Local memory only, without Thread tables. Keep one SQL client per owner and pass the
|
|
17
19
|
* full storage handle: sql-only handles cannot provide atomic receipts and revisions.
|
|
18
20
|
* Byte limits conservatively count encoded rows, not SQLite page/index overhead.
|
|
21
|
+
* Optional withdrawal reserves default to zero and stay within hard byte/receipt limits.
|
|
22
|
+
* Ordinary Put cannot consume them. Deploy exclusively upgraded writers before relying
|
|
23
|
+
* on reserves; the SQL accounting migration preserves older writers and their receipts.
|
|
19
24
|
*/
|
|
20
25
|
declare const doMemoryStoreLayerWithFailpoints: (storage: NonNullable<SqliteClient.SqliteClientConfig["storage"]>, limits?: DoMemoryStorageLimits) => Layer.Layer<import("@effect-agent/core/MemoryStore").MemoryReader | import("@effect-agent/core/MemoryStore").MemoryWriter, import("@effect-agent/thread/SqlMemoryStore").SqliteMemoryInitializationError, MemoryMutationFailpoint>;
|
|
21
26
|
declare const doMemoryStoreLayer: (storage: NonNullable<SqliteClient.SqliteClientConfig["storage"]>, limits?: DoMemoryStorageLimits) => Layer.Layer<import("@effect-agent/core/MemoryStore").MemoryReader | import("@effect-agent/core/MemoryStore").MemoryWriter, import("@effect-agent/thread/SqlMemoryStore").SqliteMemoryInitializationError, never>;
|
package/dist/DoMemoryStore.mjs
CHANGED
|
@@ -26,7 +26,9 @@ var DoMemoryStorageLimits = class extends Schema.Class("@effect-agent/storage-cl
|
|
|
26
26
|
maxReceipts: Schema.Int.check(Schema.isBetween({
|
|
27
27
|
minimum: 1,
|
|
28
28
|
maximum: 1e6
|
|
29
|
-
}))
|
|
29
|
+
})),
|
|
30
|
+
reservedWithdrawalBytes: Schema.optional(Schema.Natural),
|
|
31
|
+
reservedWithdrawalReceipts: Schema.optional(Schema.Natural)
|
|
30
32
|
}) {};
|
|
31
33
|
const defaultDoMemoryStorageLimits = DoMemoryStorageLimits.make({
|
|
32
34
|
maxRowBytes: 19e5,
|
|
@@ -38,6 +40,9 @@ const defaultDoMemoryStorageLimits = DoMemoryStorageLimits.make({
|
|
|
38
40
|
* Local memory only, without Thread tables. Keep one SQL client per owner and pass the
|
|
39
41
|
* full storage handle: sql-only handles cannot provide atomic receipts and revisions.
|
|
40
42
|
* Byte limits conservatively count encoded rows, not SQLite page/index overhead.
|
|
43
|
+
* Optional withdrawal reserves default to zero and stay within hard byte/receipt limits.
|
|
44
|
+
* Ordinary Put cannot consume them. Deploy exclusively upgraded writers before relying
|
|
45
|
+
* on reserves; the SQL accounting migration preserves older writers and their receipts.
|
|
41
46
|
*/
|
|
42
47
|
const doMemoryStoreLayerWithFailpoints = (storage, limits = defaultDoMemoryStorageLimits) => Layer.unwrap(Schema.decodeUnknownEffect(DoMemoryStorageLimits)(limits).pipe(Effect.mapError(() => MemoryStorageError.make({
|
|
43
48
|
operation: "memory storage limits",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DoMemoryStore.mjs","names":[],"sources":["../src/DoMemoryStore.ts"],"sourcesContent":["import { MemoryStorageError, MemoryMutationFailpoint } from \"@effect-agent/core/MemoryStore\";\nimport {\n memoryStoreLayerWithFailpoints,\n SqlMemoryLimits,\n} from \"@effect-agent/thread/SqlMemoryStore\";\nimport { SqliteClient } from \"@effect/sql-sqlite-do\";\nimport { Effect, Layer, Schema } from \"effect\";\n\nexport class DoMemoryStorageLimits extends Schema.Class<DoMemoryStorageLimits>(\n \"@effect-agent/storage-cloudflare/DoMemoryStorageLimits\",\n)({\n maxRowBytes: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 1_900_000 })),\n maxStorageBytes: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 536_870_912 })),\n maxDocuments: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 100_000 })),\n maxReceipts: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 1_000_000 })),\n}) {}\n\nexport const defaultDoMemoryStorageLimits = DoMemoryStorageLimits.make({\n maxRowBytes: 1_900_000,\n maxStorageBytes: 536_870_912,\n maxDocuments: 10_000,\n maxReceipts: 100_000,\n});\n\n/**\n * Local memory only, without Thread tables. Keep one SQL client per owner and pass the\n * full storage handle: sql-only handles cannot provide atomic receipts and revisions.\n * Byte limits conservatively count encoded rows, not SQLite page/index overhead.\n */\nexport const doMemoryStoreLayerWithFailpoints = (\n storage: NonNullable<SqliteClient.SqliteClientConfig[\"storage\"]>,\n limits: DoMemoryStorageLimits = defaultDoMemoryStorageLimits,\n) =>\n Layer.unwrap(\n Schema.decodeUnknownEffect(DoMemoryStorageLimits)(limits).pipe(\n Effect.mapError(() =>\n MemoryStorageError.make({ operation: \"memory storage limits\", reason: \"invalid-input\" }),\n ),\n Effect.map((validated) =>\n memoryStoreLayerWithFailpoints.pipe(\n Layer.provide(Layer.succeed(SqlMemoryLimits, validated)),\n Layer.provide(SqliteClient.layer({ storage })),\n ),\n ),\n ),\n );\n\nexport const doMemoryStoreLayer = (\n storage: NonNullable<SqliteClient.SqliteClientConfig[\"storage\"]>,\n limits: DoMemoryStorageLimits = defaultDoMemoryStorageLimits,\n) =>\n doMemoryStoreLayerWithFailpoints(storage, limits).pipe(\n Layer.provide(MemoryMutationFailpoint.layer),\n );\n"],"mappings":";;;;;;;;;;;;AAQA,IAAa,wBAAb,cAA2C,OAAO,MAChD,wDACF,CAAC,CAAC;CACA,aAAa,OAAO,IAAI,MAAM,OAAO,UAAU;EAAE,SAAS;EAAG,SAAS;CAAU,CAAC,CAAC;CAClF,iBAAiB,OAAO,IAAI,MAAM,OAAO,UAAU;EAAE,SAAS;EAAG,SAAS;CAAY,CAAC,CAAC;CACxF,cAAc,OAAO,IAAI,MAAM,OAAO,UAAU;EAAE,SAAS;EAAG,SAAS;CAAQ,CAAC,CAAC;CACjF,aAAa,OAAO,IAAI,MAAM,OAAO,UAAU;EAAE,SAAS;EAAG,SAAS;CAAU,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"DoMemoryStore.mjs","names":[],"sources":["../src/DoMemoryStore.ts"],"sourcesContent":["import { MemoryStorageError, MemoryMutationFailpoint } from \"@effect-agent/core/MemoryStore\";\nimport {\n memoryStoreLayerWithFailpoints,\n SqlMemoryLimits,\n} from \"@effect-agent/thread/SqlMemoryStore\";\nimport { SqliteClient } from \"@effect/sql-sqlite-do\";\nimport { Effect, Layer, Schema } from \"effect\";\n\nexport class DoMemoryStorageLimits extends Schema.Class<DoMemoryStorageLimits>(\n \"@effect-agent/storage-cloudflare/DoMemoryStorageLimits\",\n)({\n maxRowBytes: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 1_900_000 })),\n maxStorageBytes: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 536_870_912 })),\n maxDocuments: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 100_000 })),\n maxReceipts: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 1_000_000 })),\n reservedWithdrawalBytes: Schema.optional(Schema.Natural),\n reservedWithdrawalReceipts: Schema.optional(Schema.Natural),\n}) {}\n\nexport const defaultDoMemoryStorageLimits = DoMemoryStorageLimits.make({\n maxRowBytes: 1_900_000,\n maxStorageBytes: 536_870_912,\n maxDocuments: 10_000,\n maxReceipts: 100_000,\n});\n\n/**\n * Local memory only, without Thread tables. Keep one SQL client per owner and pass the\n * full storage handle: sql-only handles cannot provide atomic receipts and revisions.\n * Byte limits conservatively count encoded rows, not SQLite page/index overhead.\n * Optional withdrawal reserves default to zero and stay within hard byte/receipt limits.\n * Ordinary Put cannot consume them. Deploy exclusively upgraded writers before relying\n * on reserves; the SQL accounting migration preserves older writers and their receipts.\n */\nexport const doMemoryStoreLayerWithFailpoints = (\n storage: NonNullable<SqliteClient.SqliteClientConfig[\"storage\"]>,\n limits: DoMemoryStorageLimits = defaultDoMemoryStorageLimits,\n) =>\n Layer.unwrap(\n Schema.decodeUnknownEffect(DoMemoryStorageLimits)(limits).pipe(\n Effect.mapError(() =>\n MemoryStorageError.make({ operation: \"memory storage limits\", reason: \"invalid-input\" }),\n ),\n Effect.map((validated) =>\n memoryStoreLayerWithFailpoints.pipe(\n Layer.provide(Layer.succeed(SqlMemoryLimits, validated)),\n Layer.provide(SqliteClient.layer({ storage })),\n ),\n ),\n ),\n );\n\nexport const doMemoryStoreLayer = (\n storage: NonNullable<SqliteClient.SqliteClientConfig[\"storage\"]>,\n limits: DoMemoryStorageLimits = defaultDoMemoryStorageLimits,\n) =>\n doMemoryStoreLayerWithFailpoints(storage, limits).pipe(\n Layer.provide(MemoryMutationFailpoint.layer),\n );\n"],"mappings":";;;;;;;;;;;;AAQA,IAAa,wBAAb,cAA2C,OAAO,MAChD,wDACF,CAAC,CAAC;CACA,aAAa,OAAO,IAAI,MAAM,OAAO,UAAU;EAAE,SAAS;EAAG,SAAS;CAAU,CAAC,CAAC;CAClF,iBAAiB,OAAO,IAAI,MAAM,OAAO,UAAU;EAAE,SAAS;EAAG,SAAS;CAAY,CAAC,CAAC;CACxF,cAAc,OAAO,IAAI,MAAM,OAAO,UAAU;EAAE,SAAS;EAAG,SAAS;CAAQ,CAAC,CAAC;CACjF,aAAa,OAAO,IAAI,MAAM,OAAO,UAAU;EAAE,SAAS;EAAG,SAAS;CAAU,CAAC,CAAC;CAClF,yBAAyB,OAAO,SAAS,OAAO,OAAO;CACvD,4BAA4B,OAAO,SAAS,OAAO,OAAO;AAC5D,CAAC,CAAC,CAAC,CAAC;AAEJ,MAAa,+BAA+B,sBAAsB,KAAK;CACrE,aAAa;CACb,iBAAiB;CACjB,cAAc;CACd,aAAa;AACf,CAAC;;;;;;;;;AAUD,MAAa,oCACX,SACA,SAAgC,iCAEhC,MAAM,OACJ,OAAO,oBAAoB,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC,KACxD,OAAO,eACL,mBAAmB,KAAK;CAAE,WAAW;CAAyB,QAAQ;AAAgB,CAAC,CACzF,GACA,OAAO,KAAK,cACV,+BAA+B,KAC7B,MAAM,QAAQ,MAAM,QAAQ,iBAAiB,SAAS,CAAC,GACvD,MAAM,QAAQ,aAAa,MAAM,EAAE,QAAQ,CAAC,CAAC,CAC/C,CACF,CACF,CACF;AAEF,MAAa,sBACX,SACA,SAAgC,iCAEhC,iCAAiC,SAAS,MAAM,CAAC,CAAC,KAChD,MAAM,QAAQ,wBAAwB,KAAK,CAC7C"}
|
|
@@ -2,7 +2,7 @@ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
|
2
2
|
import { DoStorageConfig } from "./DoStorageConfig.mjs";
|
|
3
3
|
import { DoLedgerError, DoStorageCorruptionError, DoStorageError } from "./DoStorageError.mjs";
|
|
4
4
|
import { DoStorageFailpoint } from "./DoStorageFailpoint.mjs";
|
|
5
|
-
import { i as storageFailpointLayer, o as decodeRows, r as storageConfigLayer, s as initializeDoJournal } from "./DoThreadStore-
|
|
5
|
+
import { i as storageFailpointLayer, o as decodeRows, r as storageConfigLayer, s as initializeDoJournal } from "./DoThreadStore-D00TdRAa.mjs";
|
|
6
6
|
import { SqliteClient } from "@effect/sql-sqlite-do";
|
|
7
7
|
import { Clock, Context, Crypto, DateTime, Effect, Layer, Option, Schema, Stream } from "effect";
|
|
8
8
|
import * as SqlClientService from "effect/unstable/sql/SqlClient";
|
|
@@ -23,6 +23,7 @@ const BoundedStoredText = Schema.String.check(Schema.isMaxLength(2e6));
|
|
|
23
23
|
const BoundedIdentifier = Schema.NonEmptyString.check(Schema.isMaxLength(1024));
|
|
24
24
|
const MAX_RECORDS_PER_THREAD = 65536;
|
|
25
25
|
const MAX_IDENTIFIER_LENGTH = 1024;
|
|
26
|
+
const MAX_READ_PAGE_JSON_BYTES = 4194304;
|
|
26
27
|
const isSqlError = Schema.is(SqlError);
|
|
27
28
|
const storedTextBytes = (value) => new TextEncoder().encode(value).byteLength;
|
|
28
29
|
const chunked = (values, size) => {
|
|
@@ -55,6 +56,10 @@ var RecordRow = class extends Schema.Class("RecordRow")({
|
|
|
55
56
|
record_json: BoundedStoredText,
|
|
56
57
|
sequence: CanonicalSequence
|
|
57
58
|
}) {};
|
|
59
|
+
const ReadPlanRow = Schema.Struct({
|
|
60
|
+
sequence: CanonicalSequence,
|
|
61
|
+
record_json_bytes: Schema.Natural.check(Schema.isLessThanOrEqualTo(MAX_READ_PAGE_JSON_BYTES))
|
|
62
|
+
});
|
|
58
63
|
var CheckpointRow = class extends Schema.Class("CheckpointRow")({
|
|
59
64
|
checkpoint_json: BoundedStoredText,
|
|
60
65
|
thread_id: BoundedIdentifier,
|
|
@@ -94,8 +99,6 @@ var RawCheckpoint = class extends Schema.Class("@effect-agent/storage-cloudflare
|
|
|
94
99
|
throughSequence: CanonicalSequence
|
|
95
100
|
}) {};
|
|
96
101
|
var RawThreadExport = class extends Schema.Class("@effect-agent/storage-cloudflare/RawThreadExport")({
|
|
97
|
-
batches: Schema.Array(BatchRow),
|
|
98
|
-
checkpoints: Schema.Array(CheckpointRow),
|
|
99
102
|
thread: ThreadRow,
|
|
100
103
|
records: Schema.Array(RecordRow)
|
|
101
104
|
}) {};
|
|
@@ -443,20 +446,56 @@ const makeJournal = (sql, failpoint, maxStoredValueBytes) => {
|
|
|
443
446
|
}));
|
|
444
447
|
});
|
|
445
448
|
const read = Effect.fn("DoJournal.read")(function* (request) {
|
|
446
|
-
const
|
|
449
|
+
const planRows = yield* sql`
|
|
447
450
|
SELECT
|
|
448
|
-
thread_id,
|
|
449
451
|
sequence,
|
|
450
|
-
|
|
451
|
-
batch_id,
|
|
452
|
-
record_json
|
|
452
|
+
length(CAST(record_json AS BLOB)) AS record_json_bytes
|
|
453
453
|
FROM effect_agent_canonical_records
|
|
454
454
|
WHERE thread_id = ${request.threadId}
|
|
455
455
|
AND sequence > ${request.fromSequenceExclusive}
|
|
456
456
|
ORDER BY sequence
|
|
457
457
|
LIMIT ${request.limit}
|
|
458
458
|
`.pipe(Effect.mapError(storageError("read canonical records")));
|
|
459
|
-
|
|
459
|
+
const plan = yield* decodeRows(Schema.Array(ReadPlanRow), "effect_agent_canonical_records", `${request.threadId}>${request.fromSequenceExclusive}`, planRows);
|
|
460
|
+
const mismatch = () => DoStorageCorruptionError.make({
|
|
461
|
+
table: "effect_agent_canonical_records",
|
|
462
|
+
rowKey: `${request.threadId}>${request.fromSequenceExclusive}`,
|
|
463
|
+
message: "Canonical read membership, sequence, or payload size changed from its read plan."
|
|
464
|
+
});
|
|
465
|
+
if (plan.length > request.limit) return yield* mismatch();
|
|
466
|
+
const pages = [];
|
|
467
|
+
let page;
|
|
468
|
+
let pageBytes = 0;
|
|
469
|
+
let previousSequence = request.fromSequenceExclusive;
|
|
470
|
+
for (const row of plan) {
|
|
471
|
+
if (row.sequence !== previousSequence + 1) return yield* mismatch();
|
|
472
|
+
previousSequence = row.sequence;
|
|
473
|
+
if (page === void 0 || pageBytes + row.record_json_bytes > MAX_READ_PAGE_JSON_BYTES) {
|
|
474
|
+
page = [row];
|
|
475
|
+
pages.push(page);
|
|
476
|
+
pageBytes = row.record_json_bytes;
|
|
477
|
+
} else {
|
|
478
|
+
page.push(row);
|
|
479
|
+
pageBytes += row.record_json_bytes;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
const readPage = Effect.fn("DoJournal.readPage")(function* (page) {
|
|
483
|
+
const rows = yield* sql`
|
|
484
|
+
SELECT thread_id, sequence, record_id, batch_id, record_json
|
|
485
|
+
FROM effect_agent_canonical_records
|
|
486
|
+
WHERE thread_id = ${request.threadId}
|
|
487
|
+
AND sequence >= ${page[0].sequence}
|
|
488
|
+
AND sequence <= ${page[page.length - 1].sequence}
|
|
489
|
+
ORDER BY sequence
|
|
490
|
+
`.pipe(Effect.mapError(storageError("read canonical records")));
|
|
491
|
+
const decoded = yield* decodeRows(Schema.Array(RecordRow), "effect_agent_canonical_records", `${request.threadId}/${page[0].sequence}`, rows);
|
|
492
|
+
if (decoded.length !== page.length || decoded.some((row, index) => row.thread_id !== request.threadId || row.sequence !== page[index].sequence || storedTextBytes(row.record_json) !== page[index].record_json_bytes)) return yield* mismatch();
|
|
493
|
+
return decoded;
|
|
494
|
+
});
|
|
495
|
+
return {
|
|
496
|
+
count: plan.length,
|
|
497
|
+
records: Stream.fromIterable(pages).pipe(Stream.flatMap((page) => Stream.fromIterableEffect(readPage(page))))
|
|
498
|
+
};
|
|
460
499
|
});
|
|
461
500
|
const exportThread = Effect.fn("DoJournal.exportThread")(function* (threadId) {
|
|
462
501
|
return yield* sql.withTransaction(Effect.gen(function* () {
|
|
@@ -472,19 +511,6 @@ const makeJournal = (sql, failpoint, maxStoredValueBytes) => {
|
|
|
472
511
|
`.pipe(Effect.mapError(storageError("export thread")));
|
|
473
512
|
const thread = yield* decodeSingleRow(Schema.Array(ThreadRow), "effect_agent_threads", threadId, threadRows);
|
|
474
513
|
yield* failpoint("export:after-thread-read");
|
|
475
|
-
const batchRows = yield* sql`
|
|
476
|
-
SELECT
|
|
477
|
-
thread_id,
|
|
478
|
-
batch_id,
|
|
479
|
-
first_sequence,
|
|
480
|
-
last_sequence,
|
|
481
|
-
batch_digest,
|
|
482
|
-
tail_digest,
|
|
483
|
-
batch_json
|
|
484
|
-
FROM effect_agent_canonical_batches
|
|
485
|
-
WHERE thread_id = ${threadId}
|
|
486
|
-
ORDER BY first_sequence
|
|
487
|
-
`.pipe(Effect.mapError(storageError("export canonical batches")));
|
|
488
514
|
const recordRows = yield* sql`
|
|
489
515
|
SELECT
|
|
490
516
|
thread_id,
|
|
@@ -496,21 +522,9 @@ const makeJournal = (sql, failpoint, maxStoredValueBytes) => {
|
|
|
496
522
|
WHERE thread_id = ${threadId}
|
|
497
523
|
ORDER BY sequence
|
|
498
524
|
`.pipe(Effect.mapError(storageError("export canonical records")));
|
|
499
|
-
const checkpointRows = yield* sql`
|
|
500
|
-
SELECT
|
|
501
|
-
thread_id,
|
|
502
|
-
through_sequence,
|
|
503
|
-
tail_digest,
|
|
504
|
-
checkpoint_json
|
|
505
|
-
FROM effect_agent_checkpoints
|
|
506
|
-
WHERE thread_id = ${threadId}
|
|
507
|
-
ORDER BY through_sequence
|
|
508
|
-
`.pipe(Effect.mapError(storageError("export checkpoints")));
|
|
509
525
|
return RawThreadExport.make({
|
|
510
526
|
thread,
|
|
511
|
-
|
|
512
|
-
records: yield* decodeRows(Schema.Array(RecordRow), "effect_agent_canonical_records", threadId, recordRows),
|
|
513
|
-
checkpoints: yield* decodeRows(Schema.Array(CheckpointRow), "effect_agent_checkpoints", threadId, checkpointRows)
|
|
527
|
+
records: yield* decodeRows(Schema.Array(RecordRow), "effect_agent_canonical_records", threadId, recordRows)
|
|
514
528
|
});
|
|
515
529
|
})).pipe(Effect.catchTag("SqlError", (error) => Effect.fail(storageError("export transaction")(error))));
|
|
516
530
|
});
|
|
@@ -928,18 +942,20 @@ const makeServices = Effect.fn("DoThreadStore.makeServices")(function* () {
|
|
|
928
942
|
return result;
|
|
929
943
|
});
|
|
930
944
|
const loadRecords = Effect.fn("DoThreadStore.loadRecords")(function* (request) {
|
|
931
|
-
const
|
|
932
|
-
return
|
|
945
|
+
const result = yield* journal.read(request).pipe(Effect.mapError((error) => storeError("read canonical records", error)));
|
|
946
|
+
return {
|
|
947
|
+
count: result.count,
|
|
948
|
+
records: result.records.pipe(Stream.mapError((error) => storeError("read canonical records", error)), Stream.mapEffect(decodeEnvelope))
|
|
949
|
+
};
|
|
933
950
|
});
|
|
934
951
|
const readEffect = Effect.fn("DoThreadStore.read")(function* (request) {
|
|
935
952
|
const validated = yield* Schema.decodeUnknownEffect(Schema.toType(ThreadRead))(request).pipe(Effect.mapError((error) => schemaStoreError("validate thread read", error)));
|
|
936
953
|
yield* requireThread(journal, validated.threadId);
|
|
937
|
-
|
|
954
|
+
return (yield* loadRecords(RawReadRequest.make({
|
|
938
955
|
threadId: validated.threadId,
|
|
939
956
|
fromSequenceExclusive: validated.afterSequence ?? ZERO_CANONICAL_SEQUENCE,
|
|
940
957
|
limit: validated.limit
|
|
941
|
-
}));
|
|
942
|
-
return Stream.fromIterable(records);
|
|
958
|
+
}))).records;
|
|
943
959
|
});
|
|
944
960
|
const read = (request) => Stream.unwrap(readEffect(request));
|
|
945
961
|
const observeEffect = Effect.fn("DoThreadStore.observe")(function* (request) {
|
|
@@ -949,19 +965,18 @@ const makeServices = Effect.fn("DoThreadStore.makeServices")(function* () {
|
|
|
949
965
|
const cursor = yield* Ref.make(initialSequence);
|
|
950
966
|
const poll = Effect.fn("DoThreadStore.observePoll")(function* () {
|
|
951
967
|
const fromSequenceExclusive = yield* Ref.get(cursor);
|
|
952
|
-
const
|
|
968
|
+
const result = yield* loadRecords(RawReadRequest.make({
|
|
953
969
|
threadId: validated.threadId,
|
|
954
970
|
fromSequenceExclusive,
|
|
955
971
|
limit: 1024
|
|
956
972
|
}));
|
|
957
|
-
if (
|
|
973
|
+
if (result.count === 0) {
|
|
958
974
|
yield* Effect.sleep(config.observationPollInterval);
|
|
959
|
-
return
|
|
975
|
+
return Stream.empty;
|
|
960
976
|
}
|
|
961
|
-
|
|
962
|
-
return records;
|
|
977
|
+
return result.records.pipe(Stream.tap((record) => Ref.set(cursor, record.sequence)));
|
|
963
978
|
});
|
|
964
|
-
return Stream.
|
|
979
|
+
return Stream.fromEffectRepeat(poll()).pipe(Stream.flatten);
|
|
965
980
|
});
|
|
966
981
|
const observe = (request) => Stream.unwrap(observeEffect(request));
|
|
967
982
|
const exportThread = Effect.fn("DoThreadStore.export")(function* (request) {
|
|
@@ -1080,4 +1095,4 @@ const layer = (options) => Layer.unwrap(Effect.map(DoStorageConfig, (config) =>
|
|
|
1080
1095
|
//#endregion
|
|
1081
1096
|
export { threadStoreLayer as a, storageFailpointLayer as i, layer as n, decodeRows as o, storageConfigLayer as r, initializeDoJournal as s, DoThreadStore_exports as t };
|
|
1082
1097
|
|
|
1083
|
-
//# sourceMappingURL=DoThreadStore-
|
|
1098
|
+
//# sourceMappingURL=DoThreadStore-D00TdRAa.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DoThreadStore-D00TdRAa.mjs","names":["SqlClientService"],"sources":["../src/internal/do-journal.ts","../src/DoThreadStore.ts"],"sourcesContent":["import { CanonicalSequence, ProducerEpoch } from \"@effect-agent/thread/Records\";\nimport { SqliteMigrator } from \"@effect/sql-sqlite-do\";\nimport { Effect, Schema, Stream } from \"effect\";\nimport * as SqlClient from \"effect/unstable/sql/SqlClient\";\nimport { SqlError } from \"effect/unstable/sql/SqlError\";\n\nimport {\n type DoStorageFailpointError,\n DoAppendConflict,\n DoCheckpointConflict,\n DoFenceRejected,\n DoStorageCompatibilityError,\n DoStorageCorruptionError,\n DoStorageError,\n DoValueBoundExceeded,\n type DoStorageFailpointLocation,\n} from \"../DoStorageError.ts\";\nimport { CurrentDoStorageVersion, doMigrations } from \"./migrations.ts\";\n\n/**\n * Static schema ceiling for stored text columns. Writes are bounded in BYTES by the\n * configured `maxStoredValueBytes` (always ≤ 2,000,000); UTF-8 byte length is never smaller\n * than UTF-16 string length, so any value that passed the byte bound also passes this\n * decode-side character ceiling.\n */\nconst BoundedStoredText = Schema.String.check(Schema.isMaxLength(2_000_000));\nconst BoundedIdentifier = Schema.NonEmptyString.check(Schema.isMaxLength(1024));\nconst MAX_RECORDS_PER_THREAD = 65_536;\nconst MAX_IDENTIFIER_LENGTH = 1_024;\nconst MAX_READ_PAGE_JSON_BYTES = 4 * 1024 * 1024;\n/** Durable Object SQL storage allows at most 100 bound parameters per statement. */\nconst MAX_BOUND_PARAMETERS = 100;\nconst isSqlError = Schema.is(SqlError);\n\nconst storedTextBytes = (value: string): number => new TextEncoder().encode(value).byteLength;\n\nconst chunked = <A>(values: ReadonlyArray<A>, size: number): Array<ReadonlyArray<A>> => {\n const chunks: Array<ReadonlyArray<A>> = [];\n\n for (let index = 0; index < values.length; index += size) {\n chunks.push(values.slice(index, index + size));\n }\n\n return chunks;\n};\n\nclass DoMetaRow extends Schema.Class<DoMetaRow>(\"DoMetaRow\")({\n value: Schema.NonEmptyString.check(Schema.isMaxLength(128)),\n}) {}\n\nclass DoNameRow extends Schema.Class<DoNameRow>(\"DoNameRow\")({\n name: BoundedIdentifier,\n}) {}\n\nclass ThreadRow extends Schema.Class<ThreadRow>(\"ThreadRow\")({\n thread_id: BoundedIdentifier,\n created_at: Schema.NonEmptyString.check(Schema.isMaxLength(128)),\n producer_epoch: ProducerEpoch,\n tail_digest: BoundedStoredText,\n tail_sequence: CanonicalSequence,\n}) {}\n\nclass BatchRow extends Schema.Class<BatchRow>(\"BatchRow\")({\n batch_digest: BoundedStoredText,\n batch_id: BoundedIdentifier,\n batch_json: BoundedStoredText,\n thread_id: BoundedIdentifier,\n first_sequence: CanonicalSequence,\n last_sequence: CanonicalSequence,\n tail_digest: BoundedStoredText,\n}) {}\n\nclass RecordRow extends Schema.Class<RecordRow>(\"RecordRow\")({\n batch_id: BoundedIdentifier,\n thread_id: BoundedIdentifier,\n record_id: BoundedIdentifier,\n record_json: BoundedStoredText,\n sequence: CanonicalSequence,\n}) {}\n\nconst ReadPlanRow = Schema.Struct({\n sequence: CanonicalSequence,\n record_json_bytes: Schema.Natural.check(Schema.isLessThanOrEqualTo(MAX_READ_PAGE_JSON_BYTES)),\n});\n\ntype ReadPage = [typeof ReadPlanRow.Type, ...Array<typeof ReadPlanRow.Type>];\n\nclass CheckpointRow extends Schema.Class<CheckpointRow>(\"CheckpointRow\")({\n checkpoint_json: BoundedStoredText,\n thread_id: BoundedIdentifier,\n tail_digest: BoundedStoredText,\n through_sequence: CanonicalSequence,\n}) {}\n\nexport class RawRecord extends Schema.Class<RawRecord>(\n \"@effect-agent/storage-cloudflare/RawRecord\",\n)({\n recordId: BoundedIdentifier,\n recordJson: BoundedStoredText,\n}) {}\n\nexport class RawAppendRequest extends Schema.Class<RawAppendRequest>(\n \"@effect-agent/storage-cloudflare/RawAppendRequest\",\n)({\n batchDigest: BoundedStoredText,\n batchId: BoundedIdentifier,\n batchJson: BoundedStoredText,\n threadId: BoundedIdentifier,\n expectedTailDigest: BoundedStoredText,\n expectedTailSequence: CanonicalSequence,\n producerEpoch: ProducerEpoch,\n records: Schema.NonEmptyArray(RawRecord).check(Schema.isMaxLength(256)),\n tailDigest: BoundedStoredText,\n}) {}\n\nexport class RawAppendResult extends Schema.Class<RawAppendResult>(\n \"@effect-agent/storage-cloudflare/RawAppendResult\",\n)({\n firstSequence: CanonicalSequence,\n lastSequence: CanonicalSequence,\n replayed: Schema.Boolean,\n tailDigest: BoundedStoredText,\n}) {}\n\nexport class RawReadRequest extends Schema.Class<RawReadRequest>(\n \"@effect-agent/storage-cloudflare/RawReadRequest\",\n)({\n threadId: BoundedIdentifier,\n fromSequenceExclusive: CanonicalSequence,\n limit: Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(1_024)),\n}) {}\n\nexport class RawCheckpoint extends Schema.Class<RawCheckpoint>(\n \"@effect-agent/storage-cloudflare/RawCheckpoint\",\n)({\n checkpointJson: BoundedStoredText,\n threadId: BoundedIdentifier,\n tailDigest: BoundedStoredText,\n throughSequence: CanonicalSequence,\n}) {}\n\nexport class RawThreadExport extends Schema.Class<RawThreadExport>(\n \"@effect-agent/storage-cloudflare/RawThreadExport\",\n)({\n thread: ThreadRow,\n records: Schema.Array(RecordRow),\n}) {}\n\ntype AppendError =\n | DoAppendConflict\n | DoFenceRejected\n | DoStorageCorruptionError\n | DoStorageError\n | DoStorageFailpointError\n | DoValueBoundExceeded;\n\ntype CheckpointError =\n | DoCheckpointConflict\n | DoStorageCorruptionError\n | DoStorageError\n | DoValueBoundExceeded;\n\ntype DoJournalFailpoint = (\n location: DoStorageFailpointLocation,\n) => Effect.Effect<void, DoStorageFailpointError>;\n\nconst noFailpoint: DoJournalFailpoint = () => Effect.void;\n\nconst storageError =\n (operation: string) =>\n (error: SqlError): DoStorageError =>\n DoStorageError.make({\n cause: error,\n operation,\n message: error.message,\n });\n\n/** Decode raw Durable Object SQLite rows against a Schema, reporting failures as typed corruption. */\nexport const decodeRows = Effect.fn(\n <A, I>(\n schema: Schema.Codec<ReadonlyArray<A>, ReadonlyArray<I>>,\n table: string,\n rowKey: string,\n rows: unknown,\n ): Effect.Effect<ReadonlyArray<A>, DoStorageCorruptionError> =>\n Schema.decodeUnknownEffect(schema)(rows).pipe(\n Effect.mapError((error) =>\n DoStorageCorruptionError.make({\n table,\n rowKey,\n message: String(error),\n }),\n ),\n ),\n);\n\n/** Decode exactly one raw row against a Schema, reporting failures as typed corruption. */\nexport const decodeSingleRow = Effect.fn(\n <A, I>(\n schema: Schema.Codec<ReadonlyArray<A>, ReadonlyArray<I>>,\n table: string,\n rowKey: string,\n rows: unknown,\n ): Effect.Effect<A, DoStorageCorruptionError> =>\n decodeRows(schema, table, rowKey, rows).pipe(\n Effect.flatMap((decoded) =>\n decoded.length === 1\n ? Effect.succeed(decoded[0])\n : Effect.fail(\n DoStorageCorruptionError.make({\n table,\n rowKey,\n message: `Expected exactly one row but found ${decoded.length}.`,\n }),\n ),\n ),\n ),\n);\n\nconst REQUIRED_TABLES = [\n \"effect_agent_abort_intents\",\n \"effect_agent_approval_decisions\",\n \"effect_agent_attempts\",\n \"effect_agent_canonical_batches\",\n \"effect_agent_canonical_records\",\n \"effect_agent_checkpoints\",\n \"effect_agent_child_reservations\",\n \"effect_agent_child_settlements\",\n \"effect_agent_threads\",\n \"effect_agent_meta\",\n \"effect_agent_settlement_reservations\",\n \"effect_agent_submission_ownership\",\n \"effect_agent_submissions\",\n \"effect_agent_unknown_resolutions\",\n] as const;\n\n/**\n * Exact-or-fresh storage gate (DEPLOY-008) over `effect_agent_meta` instead of\n * `PRAGMA user_version` (unverified on Durable Object SQL storage; a meta table is portable\n * regardless). No WAL check (Durable Object storage owns durability and confirms writes\n * through output gates) and no busy timeout (a Durable Object has exactly one writer): the\n * Node machinery those served has no DC analogue and is deliberately absent.\n */\nconst ensureCurrentStorage = Effect.fn(\"DoJournal.ensureCurrentStorage\")(function* (\n sql: SqlClient.SqlClient,\n failpoint: DoJournalFailpoint = noFailpoint,\n maxStoredValueBytes: number,\n) {\n const metaTableRows = yield* sql<Record<string, unknown>>`\n SELECT name\n FROM sqlite_master\n WHERE type = 'table'\n AND name = 'effect_agent_meta'\n `.pipe(Effect.mapError(storageError(\"read storage version table\")));\n\n const metaTables = yield* decodeRows(\n Schema.Array(DoNameRow),\n \"sqlite_master\",\n \"effect_agent_meta\",\n metaTableRows,\n );\n\n if (metaTables.length === 0) {\n const existingRows = yield* sql<Record<string, unknown>>`\n SELECT name\n FROM sqlite_master\n WHERE type = 'table'\n AND name LIKE 'effect_agent_%'\n ORDER BY name\n `.pipe(Effect.mapError(storageError(\"inspect unversioned storage\")));\n\n const existing = yield* decodeRows(\n Schema.Array(DoNameRow),\n \"sqlite_master\",\n \"effect_agent_%\",\n existingRows,\n );\n\n if (existing.length > 0) {\n return yield* DoStorageCompatibilityError.make({\n actualVersion: 0,\n supportedVersion: CurrentDoStorageVersion,\n message:\n \"The Durable Object contains unversioned Effect Agent tables. Reset the development namespace explicitly; refusing to mutate ambiguous stored data.\",\n });\n }\n\n yield* SqliteMigrator.run({ loader: doMigrations }).pipe(\n // SqliteMigrator depends on the generic client supplied by this adapter. The concrete\n // Durable Object client is kept at the outer Layer boundary.\n Effect.provideService(SqlClient.SqlClient, sql),\n Effect.mapError((error) =>\n DoStorageError.make({\n cause: error,\n operation: \"initialize current storage\",\n message: error.message,\n }),\n ),\n );\n } else {\n const versionRows = yield* sql<Record<string, unknown>>`\n SELECT value\n FROM effect_agent_meta\n WHERE key = 'storage_version'\n `.pipe(Effect.mapError(storageError(\"read storage version\")));\n\n const version = yield* decodeSingleRow(\n Schema.Array(DoMetaRow),\n \"effect_agent_meta\",\n \"storage_version\",\n versionRows,\n );\n\n // The storage version must match EXACTLY. Older private-development versions fail\n // closed with reset guidance rather than being migrated, and newer versions fail closed\n // rather than being decoded incorrectly (DEPLOY-008).\n if (version.value !== String(CurrentDoStorageVersion)) {\n const actualVersion = Number.parseInt(version.value, 10);\n\n return yield* DoStorageCompatibilityError.make({\n actualVersion: Number.isSafeInteger(actualVersion) ? actualVersion : -1,\n supportedVersion: CurrentDoStorageVersion,\n message:\n `The Durable Object uses private-development storage version ${version.value}; ` +\n `this build supports exactly version ${CurrentDoStorageVersion}. ` +\n \"Replace the development namespace explicitly; automatic stored-data migrations are not provided during private development.\",\n });\n }\n }\n\n const requiredRows = yield* sql<Record<string, unknown>>`\n SELECT name\n FROM sqlite_master\n WHERE type = 'table'\n AND name IN ${sql.in([...REQUIRED_TABLES])}\n ORDER BY name\n `.pipe(Effect.mapError(storageError(\"verify storage tables\")));\n\n const required = yield* decodeRows(\n Schema.Array(DoNameRow),\n \"sqlite_master\",\n \"required_tables\",\n requiredRows,\n );\n\n if (required.length !== REQUIRED_TABLES.length) {\n return yield* DoStorageCompatibilityError.make({\n actualVersion: CurrentDoStorageVersion,\n supportedVersion: CurrentDoStorageVersion,\n message:\n \"The Durable Object claims the current format but is missing required tables. Reset the corrupt private-development data.\",\n });\n }\n\n return makeJournal(sql, failpoint, maxStoredValueBytes);\n});\n\nconst makeJournal = (\n sql: SqlClient.SqlClient,\n failpoint: DoJournalFailpoint,\n maxStoredValueBytes: number,\n) => {\n /** Typed pre-write refusal for any single value over the configured byte bound. */\n const checkValueBound = (\n operation: string,\n value: string,\n ): Effect.Effect<void, DoValueBoundExceeded> => {\n const actualBytes = storedTextBytes(value);\n\n return actualBytes > maxStoredValueBytes\n ? Effect.fail(\n DoValueBoundExceeded.make({\n actualBytes,\n maxBytes: maxStoredValueBytes,\n operation,\n }),\n )\n : Effect.void;\n };\n\n /**\n * Runs one journal write transaction on the Durable Object storage-backed\n * `withTransaction` (`ctx.storage.transaction()` under the hood). Within one Durable\n * Object there is exactly ONE writer, so the Node `BEGIN IMMEDIATE` + busy-retry +\n * `SqliteWriteContention` machinery has no analogue here and is deliberately absent.\n * Ownership-token and epoch checks still run INSIDE the transaction, so fencing atomicity\n * (DUR-006) is preserved identically.\n *\n * Journal write transactions are always top level: the Durable Object client rejects\n * nested transactions, so new journal operations must not wrap this helper inside another\n * transaction.\n */\n const withWriteTransaction =\n (operation: string) =>\n <A, E>(effect: Effect.Effect<A, E>): Effect.Effect<A, E | DoStorageError> =>\n sql.withTransaction(effect).pipe(\n Effect.mapError((error) => (isSqlError(error) ? storageError(operation)(error) : error)),\n Effect.withSpan(\"DoJournal.withWriteTransaction\", { attributes: { operation } }),\n );\n\n const materialize = Effect.fn(\"DoJournal.materialize\")(function* (\n threadId: string,\n createdAt: string,\n emptyTailDigest: string,\n producerEpoch: ProducerEpoch,\n ): Effect.fn.Return<\n void,\n DoFenceRejected | DoStorageCorruptionError | DoStorageError | DoValueBoundExceeded\n > {\n if (threadId.length > MAX_IDENTIFIER_LENGTH) {\n return yield* DoStorageError.make({\n operation: \"materialize thread\",\n message: \"Thread identity exceeds the Durable Object storage bounds.\",\n });\n }\n yield* checkValueBound(\"materialize thread\", emptyTailDigest);\n yield* withWriteTransaction(\"materialize transaction\")(\n Effect.gen(function* () {\n const existingRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n FROM effect_agent_threads\n WHERE thread_id = ${threadId}\n `.pipe(Effect.mapError(storageError(\"read materialized thread\")));\n\n const existing = yield* decodeRows(\n Schema.Array(ThreadRow),\n \"effect_agent_threads\",\n threadId,\n existingRows,\n );\n\n if (existing.length > 1) {\n return yield* DoStorageCorruptionError.make({\n table: \"effect_agent_threads\",\n rowKey: threadId,\n message: \"A thread primary key returned more than one row.\",\n });\n }\n if (existing.length === 0) {\n yield* sql`\n INSERT INTO effect_agent_threads (\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n ) VALUES (\n ${threadId},\n ${createdAt},\n 0,\n ${emptyTailDigest},\n ${producerEpoch}\n )\n `.pipe(Effect.mapError(storageError(\"materialize thread\")));\n\n return;\n }\n if (producerEpoch < existing[0].producer_epoch) {\n return yield* DoFenceRejected.make({\n producerEpoch,\n actualEpoch: existing[0].producer_epoch,\n message: `Producer epoch ${producerEpoch} is stale; current epoch is ${existing[0].producer_epoch}.`,\n });\n }\n if (producerEpoch > existing[0].producer_epoch) {\n yield* sql`\n UPDATE effect_agent_threads\n SET producer_epoch = ${producerEpoch}\n WHERE thread_id = ${threadId}\n `.pipe(Effect.mapError(storageError(\"advance materialization epoch\")));\n }\n }),\n );\n });\n\n const getThread = Effect.fn(\"DoJournal.getThread\")(function* (threadId: string) {\n const rows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n FROM effect_agent_threads\n WHERE thread_id = ${threadId}\n `.pipe(Effect.mapError(storageError(\"read thread\")));\n\n return yield* decodeRows(Schema.Array(ThreadRow), \"effect_agent_threads\", threadId, rows);\n });\n\n const append = Effect.fn(\"DoJournal.append\")(function* (\n request: RawAppendRequest,\n ): Effect.fn.Return<RawAppendResult, AppendError> {\n if (\n request.threadId.length > MAX_IDENTIFIER_LENGTH ||\n request.batchId.length > MAX_IDENTIFIER_LENGTH ||\n request.records.some((record) => record.recordId.length > MAX_IDENTIFIER_LENGTH)\n ) {\n return yield* DoStorageError.make({\n operation: \"append canonical batch\",\n message: \"Canonical identifiers exceed the Durable Object storage bounds.\",\n });\n }\n // The platform's ~2 MB per-value limit, enforced typed BEFORE any write (plan §1.2).\n yield* checkValueBound(\"append canonical batch\", request.batchJson);\n yield* checkValueBound(\"append canonical batch\", request.batchDigest);\n yield* checkValueBound(\"append canonical batch\", request.tailDigest);\n yield* Effect.forEach(\n request.records,\n (record) => checkValueBound(\"append canonical record\", record.recordJson),\n { discard: true },\n );\n\n return yield* withWriteTransaction(\"append transaction\")(\n Effect.gen(function* () {\n const recordIds = request.records.map((record) => record.recordId);\n\n if (new Set(recordIds).size !== recordIds.length) {\n return yield* DoAppendConflict.make({\n message: `Batch ${request.batchId} contains duplicate canonical record IDs.`,\n reason: \"record-identity\",\n });\n }\n\n const threadRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n FROM effect_agent_threads\n WHERE thread_id = ${request.threadId}\n `.pipe(Effect.mapError(storageError(\"read append tail\")));\n\n const thread = yield* decodeSingleRow(\n Schema.Array(ThreadRow),\n \"effect_agent_threads\",\n request.threadId,\n threadRows,\n );\n\n if (request.producerEpoch !== thread.producer_epoch) {\n return yield* DoFenceRejected.make({\n producerEpoch: request.producerEpoch,\n actualEpoch: thread.producer_epoch,\n message: `Producer epoch ${request.producerEpoch} is not the current epoch ${thread.producer_epoch}.`,\n });\n }\n\n const batchRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n batch_id,\n first_sequence,\n last_sequence,\n batch_digest,\n tail_digest,\n batch_json\n FROM effect_agent_canonical_batches\n WHERE thread_id = ${request.threadId}\n AND batch_id = ${request.batchId}\n `.pipe(Effect.mapError(storageError(\"read idempotent batch\")));\n\n const batches = yield* decodeRows(\n Schema.Array(BatchRow),\n \"effect_agent_canonical_batches\",\n `${request.threadId}/${request.batchId}`,\n batchRows,\n );\n\n if (batches.length > 1) {\n return yield* DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_batches\",\n rowKey: `${request.threadId}/${request.batchId}`,\n message: \"A canonical batch primary key returned more than one row.\",\n });\n }\n if (batches.length === 1) {\n const existing = batches[0];\n\n if (existing.batch_digest !== request.batchDigest) {\n return yield* DoAppendConflict.make({\n message: `Batch ${request.batchId} already exists with different canonical content.`,\n reason: \"batch-digest\",\n });\n }\n\n return RawAppendResult.make({\n firstSequence: existing.first_sequence,\n lastSequence: existing.last_sequence,\n replayed: true,\n tailDigest: existing.tail_digest,\n });\n }\n\n if (\n request.expectedTailSequence !== thread.tail_sequence ||\n request.expectedTailDigest !== thread.tail_digest\n ) {\n return yield* DoAppendConflict.make({\n message:\n `Expected tail ${request.expectedTailSequence}/${request.expectedTailDigest} ` +\n `but found ${thread.tail_sequence}/${thread.tail_digest}.`,\n reason: \"tail\",\n actualTailSequence: thread.tail_sequence,\n actualTailDigest: thread.tail_digest,\n });\n }\n if (thread.tail_sequence + request.records.length > MAX_RECORDS_PER_THREAD) {\n return yield* DoStorageError.make({\n operation: \"append canonical batch\",\n message: `Thread record limit ${MAX_RECORDS_PER_THREAD} would be exceeded.`,\n });\n }\n\n // Chunked to respect the Durable Object platform's 100-bound-parameter statement\n // limit: a batch may carry up to 256 records.\n const existingRecords: Array<RecordRow> = [];\n\n for (const chunk of chunked(recordIds, MAX_BOUND_PARAMETERS - 10)) {\n const existingRecordRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n sequence,\n record_id,\n batch_id,\n record_json\n FROM effect_agent_canonical_records\n WHERE thread_id = ${request.threadId}\n AND record_id IN ${sql.in([...chunk])}\n ORDER BY sequence\n `.pipe(Effect.mapError(storageError(\"check canonical record identities\")));\n\n existingRecords.push(\n ...(yield* decodeRows(\n Schema.Array(RecordRow),\n \"effect_agent_canonical_records\",\n `${request.threadId}/record_ids`,\n existingRecordRows,\n )),\n );\n }\n if (existingRecords.length > 0) {\n return yield* DoAppendConflict.make({\n message: `Canonical record ID ${existingRecords[0].record_id} already exists.`,\n reason: \"record-identity\",\n });\n }\n\n const firstSequence = yield* Schema.decodeUnknownEffect(CanonicalSequence)(\n thread.tail_sequence + 1,\n ).pipe(\n Effect.mapError((error) =>\n DoStorageError.make({\n cause: error,\n operation: \"append canonical batch\",\n message: error.message,\n }),\n ),\n );\n\n const lastSequence = yield* Schema.decodeUnknownEffect(CanonicalSequence)(\n firstSequence + request.records.length - 1,\n ).pipe(\n Effect.mapError((error) =>\n DoStorageError.make({\n cause: error,\n operation: \"append canonical batch\",\n message: error.message,\n }),\n ),\n );\n\n yield* sql`\n INSERT INTO effect_agent_canonical_batches (\n thread_id,\n batch_id,\n first_sequence,\n last_sequence,\n batch_digest,\n tail_digest,\n batch_json\n ) VALUES (\n ${request.threadId},\n ${request.batchId},\n ${firstSequence},\n ${lastSequence},\n ${request.batchDigest},\n ${request.tailDigest},\n ${request.batchJson}\n )\n `.pipe(Effect.mapError(storageError(\"insert canonical batch\")));\n yield* failpoint(\"append:after-batch-insert\");\n\n yield* Effect.forEach(\n request.records,\n (record, index) =>\n Effect.gen(function* () {\n yield* sql`\n INSERT INTO effect_agent_canonical_records (\n thread_id,\n sequence,\n record_id,\n batch_id,\n record_json\n ) VALUES (\n ${request.threadId},\n ${firstSequence + index},\n ${record.recordId},\n ${request.batchId},\n ${record.recordJson}\n )\n `.pipe(Effect.mapError(storageError(\"insert canonical record\")));\n yield* failpoint(\"append:after-record-insert\");\n }),\n { discard: true },\n );\n\n yield* sql`\n UPDATE effect_agent_threads\n SET\n tail_sequence = ${lastSequence},\n tail_digest = ${request.tailDigest},\n producer_epoch = ${request.producerEpoch}\n WHERE thread_id = ${request.threadId}\n `.pipe(Effect.mapError(storageError(\"advance thread tail\")));\n yield* failpoint(\"append:after-tail-update\");\n\n return RawAppendResult.make({\n firstSequence,\n lastSequence,\n replayed: false,\n tailDigest: request.tailDigest,\n });\n }),\n );\n });\n\n const read = Effect.fn(\"DoJournal.read\")(function* (request: RawReadRequest) {\n // Capture membership without retaining payloads. Append-only sequences keep each later\n // payload query inside this snapshot, even when new records arrive during consumption.\n const planRows = yield* sql<Record<string, unknown>>`\n SELECT\n sequence,\n length(CAST(record_json AS BLOB)) AS record_json_bytes\n FROM effect_agent_canonical_records\n WHERE thread_id = ${request.threadId}\n AND sequence > ${request.fromSequenceExclusive}\n ORDER BY sequence\n LIMIT ${request.limit}\n `.pipe(Effect.mapError(storageError(\"read canonical records\")));\n\n const plan = yield* decodeRows(\n Schema.Array(ReadPlanRow),\n \"effect_agent_canonical_records\",\n `${request.threadId}>${request.fromSequenceExclusive}`,\n planRows,\n );\n\n const mismatch = () =>\n DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_records\",\n rowKey: `${request.threadId}>${request.fromSequenceExclusive}`,\n message: \"Canonical read membership, sequence, or payload size changed from its read plan.\",\n });\n\n if (plan.length > request.limit) return yield* mismatch();\n\n const pages: Array<ReadPage> = [];\n let page: ReadPage | undefined;\n let pageBytes = 0;\n let previousSequence = request.fromSequenceExclusive;\n\n for (const row of plan) {\n if (row.sequence !== previousSequence + 1) return yield* mismatch();\n previousSequence = row.sequence;\n if (page === undefined || pageBytes + row.record_json_bytes > MAX_READ_PAGE_JSON_BYTES) {\n page = [row];\n pages.push(page);\n pageBytes = row.record_json_bytes;\n } else {\n page.push(row);\n pageBytes += row.record_json_bytes;\n }\n }\n\n const readPage = Effect.fn(\"DoJournal.readPage\")(function* (page: ReadPage) {\n const rows = yield* sql<Record<string, unknown>>`\n SELECT thread_id, sequence, record_id, batch_id, record_json\n FROM effect_agent_canonical_records\n WHERE thread_id = ${request.threadId}\n AND sequence >= ${page[0].sequence}\n AND sequence <= ${page[page.length - 1].sequence}\n ORDER BY sequence\n `.pipe(Effect.mapError(storageError(\"read canonical records\")));\n\n const decoded = yield* decodeRows(\n Schema.Array(RecordRow),\n \"effect_agent_canonical_records\",\n `${request.threadId}/${page[0].sequence}`,\n rows,\n );\n\n if (\n decoded.length !== page.length ||\n decoded.some(\n (row, index) =>\n row.thread_id !== request.threadId ||\n row.sequence !== page[index].sequence ||\n storedTextBytes(row.record_json) !== page[index].record_json_bytes,\n )\n ) {\n return yield* mismatch();\n }\n\n return decoded;\n });\n\n return {\n count: plan.length,\n records: Stream.fromIterable(pages).pipe(\n Stream.flatMap((page) => Stream.fromIterableEffect(readPage(page))),\n ),\n };\n });\n\n const exportThread = Effect.fn(\"DoJournal.exportThread\")(function* (threadId: string) {\n return yield* sql\n .withTransaction(\n Effect.gen(function* () {\n const threadRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n FROM effect_agent_threads\n WHERE thread_id = ${threadId}\n `.pipe(Effect.mapError(storageError(\"export thread\")));\n\n const thread = yield* decodeSingleRow(\n Schema.Array(ThreadRow),\n \"effect_agent_threads\",\n threadId,\n threadRows,\n );\n\n yield* failpoint(\"export:after-thread-read\");\n\n const recordRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n sequence,\n record_id,\n batch_id,\n record_json\n FROM effect_agent_canonical_records\n WHERE thread_id = ${threadId}\n ORDER BY sequence\n `.pipe(Effect.mapError(storageError(\"export canonical records\")));\n\n return RawThreadExport.make({\n thread,\n records: yield* decodeRows(\n Schema.Array(RecordRow),\n \"effect_agent_canonical_records\",\n threadId,\n recordRows,\n ),\n });\n }),\n )\n .pipe(\n Effect.catchTag(\"SqlError\", (error) =>\n Effect.fail(storageError(\"export transaction\")(error)),\n ),\n );\n });\n\n const saveCheckpoint = Effect.fn(\"DoJournal.saveCheckpoint\")(function* (\n checkpoint: RawCheckpoint,\n ): Effect.fn.Return<void, CheckpointError> {\n if (checkpoint.threadId.length > MAX_IDENTIFIER_LENGTH) {\n return yield* DoStorageError.make({\n operation: \"save checkpoint\",\n message: \"Checkpoint identity exceeds the Durable Object storage bounds.\",\n });\n }\n yield* checkValueBound(\"save checkpoint\", checkpoint.checkpointJson);\n yield* withWriteTransaction(\"checkpoint transaction\")(\n Effect.gen(function* () {\n const threadRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n FROM effect_agent_threads\n WHERE thread_id = ${checkpoint.threadId}\n `.pipe(Effect.mapError(storageError(\"read checkpoint tail\")));\n\n const thread = yield* decodeSingleRow(\n Schema.Array(ThreadRow),\n \"effect_agent_threads\",\n checkpoint.threadId,\n threadRows,\n );\n\n if (checkpoint.throughSequence > thread.tail_sequence) {\n return yield* DoCheckpointConflict.make({\n message:\n `Checkpoint sequence ${checkpoint.throughSequence} is after canonical tail ` +\n `${thread.tail_sequence}.`,\n });\n }\n\n const checkpointRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n through_sequence,\n tail_digest,\n checkpoint_json\n FROM effect_agent_checkpoints\n WHERE thread_id = ${checkpoint.threadId}\n AND through_sequence = ${checkpoint.throughSequence}\n `.pipe(Effect.mapError(storageError(\"read idempotent checkpoint\")));\n\n const existing = yield* decodeRows(\n Schema.Array(CheckpointRow),\n \"effect_agent_checkpoints\",\n `${checkpoint.threadId}/${checkpoint.throughSequence}`,\n checkpointRows,\n );\n\n if (existing.length > 1) {\n return yield* DoStorageCorruptionError.make({\n table: \"effect_agent_checkpoints\",\n rowKey: `${checkpoint.threadId}/${checkpoint.throughSequence}`,\n message: \"A checkpoint primary key returned more than one row.\",\n });\n }\n if (existing.length === 1) {\n if (\n existing[0].tail_digest !== checkpoint.tailDigest ||\n existing[0].checkpoint_json !== checkpoint.checkpointJson\n ) {\n return yield* DoCheckpointConflict.make({\n message: \"A different checkpoint already exists at this canonical sequence.\",\n });\n }\n\n return;\n }\n\n yield* sql`\n INSERT INTO effect_agent_checkpoints (\n thread_id,\n through_sequence,\n tail_digest,\n checkpoint_json\n ) VALUES (\n ${checkpoint.threadId},\n ${checkpoint.throughSequence},\n ${checkpoint.tailDigest},\n ${checkpoint.checkpointJson}\n )\n `.pipe(Effect.mapError(storageError(\"insert checkpoint\")));\n }),\n );\n });\n\n const loadCheckpoint = Effect.fn(\"DoJournal.loadCheckpoint\")(function* (\n threadId: string,\n atOrBeforeSequence: CanonicalSequence,\n ) {\n const rows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n through_sequence,\n tail_digest,\n checkpoint_json\n FROM effect_agent_checkpoints\n WHERE thread_id = ${threadId}\n AND through_sequence <= ${atOrBeforeSequence}\n ORDER BY through_sequence DESC\n LIMIT 1\n `.pipe(Effect.mapError(storageError(\"load checkpoint\")));\n\n return yield* decodeRows(\n Schema.Array(CheckpointRow),\n \"effect_agent_checkpoints\",\n `${threadId}<=${atOrBeforeSequence}`,\n rows,\n );\n });\n\n const getTailDigestAt = Effect.fn(\"DoJournal.getTailDigestAt\")(function* (\n threadId: string,\n sequence: CanonicalSequence,\n ) {\n if (sequence === 0) {\n const threads = yield* getThread(threadId);\n\n return threads.length === 0\n ? []\n : [threads[0].tail_sequence === 0 ? threads[0].tail_digest : undefined].filter(\n (value): value is string => value !== undefined,\n );\n }\n\n const rows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n batch_id,\n first_sequence,\n last_sequence,\n batch_digest,\n tail_digest,\n batch_json\n FROM effect_agent_canonical_batches\n WHERE thread_id = ${threadId}\n AND last_sequence = ${sequence}\n `.pipe(Effect.mapError(storageError(\"read canonical digest at sequence\")));\n\n const batches = yield* decodeRows(\n Schema.Array(BatchRow),\n \"effect_agent_canonical_batches\",\n `${threadId}/${sequence}`,\n rows,\n );\n\n return batches.map((batch) => batch.tail_digest);\n });\n\n const scanStoredPayloads = Effect.fn(\"DoJournal.scanStoredPayloads\")(function* () {\n return yield* sql\n .withTransaction(\n Effect.gen(function* () {\n const threads = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n FROM effect_agent_threads\n ORDER BY thread_id\n `.pipe(Effect.mapError(storageError(\"scan threads\")));\n\n const batches = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n batch_id,\n first_sequence,\n last_sequence,\n batch_digest,\n tail_digest,\n batch_json\n FROM effect_agent_canonical_batches\n ORDER BY thread_id, first_sequence\n `.pipe(Effect.mapError(storageError(\"scan canonical batches\")));\n\n const records = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n sequence,\n record_id,\n batch_id,\n record_json\n FROM effect_agent_canonical_records\n ORDER BY thread_id, sequence\n `.pipe(Effect.mapError(storageError(\"scan canonical records\")));\n\n const checkpoints = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n through_sequence,\n tail_digest,\n checkpoint_json\n FROM effect_agent_checkpoints\n ORDER BY thread_id, through_sequence\n `.pipe(Effect.mapError(storageError(\"scan checkpoints\")));\n\n return {\n threads: yield* decodeRows(\n Schema.Array(ThreadRow),\n \"effect_agent_threads\",\n \"startup_scan\",\n threads,\n ),\n batches: yield* decodeRows(\n Schema.Array(BatchRow),\n \"effect_agent_canonical_batches\",\n \"startup_scan\",\n batches,\n ),\n records: yield* decodeRows(\n Schema.Array(RecordRow),\n \"effect_agent_canonical_records\",\n \"startup_scan\",\n records,\n ),\n checkpoints: yield* decodeRows(\n Schema.Array(CheckpointRow),\n \"effect_agent_checkpoints\",\n \"startup_scan\",\n checkpoints,\n ),\n };\n }),\n )\n .pipe(\n Effect.catchTag(\"SqlError\", (error) =>\n Effect.fail(storageError(\"startup scan transaction\")(error)),\n ),\n );\n });\n\n return {\n append,\n checkValueBound,\n exportThread,\n getThread,\n getTailDigestAt,\n loadCheckpoint,\n materialize,\n read,\n saveCheckpoint,\n scanStoredPayloads,\n withWriteTransaction,\n } as const;\n};\n\nexport type DoJournal = ReturnType<typeof makeJournal>;\n\nexport const initializeDoJournal = ensureCurrentStorage;\n","import { digestCanonicalBatch, EMPTY_TAIL_DIGEST } from \"@effect-agent/thread/Digest\";\nimport {\n CanonicalBatch,\n CanonicalRecord,\n CanonicalRecordEnvelope,\n CanonicalSequence,\n Digest,\n ObservationOffset,\n} from \"@effect-agent/thread/Records\";\nimport { DEFAULT_OWNERSHIP_LEASE_DURATION } from \"@effect-agent/thread/SubmissionLedger\";\nimport {\n AppendConflict,\n AppendResult,\n CheckpointRejected,\n ThreadCheckpoint,\n ThreadExport,\n ThreadExportRequest,\n ThreadMaterialization,\n ThreadNotMaterialized,\n ThreadObservation,\n ThreadRead,\n ThreadStore,\n type ThreadCheckpoints,\n ThreadStoreError,\n ThreadTail,\n ThreadTailRequest,\n FenceRejected,\n FencedAppendRequest,\n LoadCheckpointRequest,\n SaveCheckpointRequest,\n} from \"@effect-agent/thread/ThreadStore\";\nimport { BrowserCrypto } from \"@effect/platform-browser\";\nimport { SqliteClient } from \"@effect/sql-sqlite-do\";\nimport {\n Clock,\n Context,\n Crypto,\n Duration,\n Effect,\n Layer,\n Option,\n Ref,\n Schema,\n Stream,\n} from \"effect\";\nimport * as SqlClientService from \"effect/unstable/sql/SqlClient\";\n\nimport {\n DEFAULT_MAX_STORED_VALUE_BYTES,\n DoStorageConfig,\n DoStorageConfigValue,\n} from \"./DoStorageConfig.ts\";\nimport {\n type DoStorageCompatibilityError,\n DoAppendConflict,\n DoCheckpointConflict,\n DoFenceRejected,\n type DoStorageFailpointLocation,\n DoStorageCorruptionError,\n DoStorageError,\n} from \"./DoStorageError.ts\";\nimport { DoStorageFailpoint, type DoStorageFailpointHandler } from \"./DoStorageFailpoint.ts\";\nimport {\n initializeDoJournal,\n RawAppendRequest,\n RawCheckpoint,\n RawReadRequest,\n type DoJournal,\n} from \"./internal/do-journal.ts\";\n\n/**\n * Convenience-layer construction options. `storage` is the Durable Object's own\n * `ctx.storage` handle, injected as a value (DEPLOY-010: platform bindings enter only\n * through Layers; this package never imports `cloudflare:workers`).\n */\nexport interface DoStorageOptions {\n readonly storage: DurableObjectStorage;\n readonly observationPollInterval?: number | undefined;\n /**\n * Submission ownership lease duration in milliseconds (D5). Defaults to\n * `DEFAULT_OWNERSHIP_LEASE_DURATION` from `@effect-agent/thread`.\n */\n readonly ownershipLeaseDuration?: number | undefined;\n /**\n * Maximum bytes for any single stored value; must stay under the platform's 2 MB\n * per-value limit. Defaults to `DEFAULT_MAX_STORED_VALUE_BYTES`.\n */\n readonly maxStoredValueBytes?: number | undefined;\n /**\n * Re-verify every stored payload and digest chain while opening the store. Defaults to\n * off: per-operation Schema decoding and the digest chain already fail clearly on corrupt\n * rows without scanning the whole database on every open.\n */\n readonly verifyOnOpen?: boolean | undefined;\n readonly failpoint?: DoStorageFailpointHandler | undefined;\n}\n\nexport type DoStorageInitializationError =\n | DoStorageCompatibilityError\n | DoStorageCorruptionError\n | DoStorageError;\n\nconst OffsetText = Schema.String.check(Schema.isMaxLength(4 * 1024));\nconst DO_OFFSET_PREFIX = \"effect-agent-do@1:\";\nconst ZERO_CANONICAL_SEQUENCE = Schema.decodeSync(CanonicalSequence)(0);\nconst isDigest = Schema.is(Digest);\nconst isDoFenceRejected = Schema.is(DoFenceRejected);\nconst isDoAppendConflict = Schema.is(DoAppendConflict);\nconst isDoCheckpointConflict = Schema.is(DoCheckpointConflict);\n\nconst storeError = (operation: string, error: { readonly message: string }) =>\n ThreadStoreError.make({\n cause: error,\n operation,\n message: error.message,\n });\n\nconst schemaStoreError = (operation: string, error: { readonly message: string }) =>\n ThreadStoreError.make({\n cause: error,\n operation,\n message: error.message,\n });\n\nconst makeOffset = Effect.fn(function* (\n threadId: ThreadMaterialization[\"threadId\"],\n sequence: number,\n): Effect.fn.Return<ObservationOffset, ThreadStoreError> {\n return yield* Schema.decodeUnknownEffect(CanonicalSequence)(sequence).pipe(\n Effect.flatMap((validatedSequence) =>\n Schema.decodeUnknownEffect(ObservationOffset)(\n `${DO_OFFSET_PREFIX}${encodeURIComponent(threadId)}:${validatedSequence}`,\n ),\n ),\n Effect.mapError((error) => schemaStoreError(\"encode observation offset\", error)),\n );\n});\n\nconst parseOffset = Effect.fn(function* (\n threadId: ThreadMaterialization[\"threadId\"],\n offset: ObservationOffset | undefined,\n): Effect.fn.Return<CanonicalSequence, ThreadStoreError> {\n if (offset === undefined) return ZERO_CANONICAL_SEQUENCE;\n\n const text = yield* Schema.decodeUnknownEffect(OffsetText)(offset).pipe(\n Effect.mapError((error) => schemaStoreError(\"decode observation offset\", error)),\n );\n\n const threadPrefix = `${DO_OFFSET_PREFIX}${encodeURIComponent(threadId)}:`;\n\n if (!text.startsWith(threadPrefix)) {\n return yield* ThreadStoreError.make({\n operation: \"decode observation offset\",\n message: \"The observation offset belongs to a different adapter, storage version, or Thread.\",\n });\n }\n const sequenceText = text.slice(threadPrefix.length);\n\n if (!/^(0|[1-9][0-9]*)$/.test(sequenceText)) {\n return yield* ThreadStoreError.make({\n operation: \"decode observation offset\",\n message: \"The observation offset is malformed.\",\n });\n }\n\n return yield* Schema.decodeUnknownEffect(CanonicalSequence)(Number(sequenceText)).pipe(\n Effect.mapError((error) => schemaStoreError(\"decode observation offset\", error)),\n );\n});\n\nconst mapFence = (threadId: ThreadMaterialization[\"threadId\"], error: DoFenceRejected) =>\n FenceRejected.make({\n threadId,\n actualEpoch: error.actualEpoch,\n attemptedEpoch: error.producerEpoch,\n });\n\nconst encodeCanonicalRecord = Effect.fn(function* (\n record: CanonicalRecord,\n): Effect.fn.Return<string, ThreadStoreError> {\n return yield* Schema.encodeEffect(Schema.fromJsonString(CanonicalRecord))(record).pipe(\n Effect.mapError((error) => schemaStoreError(\"encode canonical record\", error)),\n );\n});\n\nconst encodeCanonicalBatch = Effect.fn(function* (\n batch: CanonicalBatch,\n): Effect.fn.Return<string, ThreadStoreError> {\n return yield* Schema.encodeEffect(Schema.fromJsonString(CanonicalBatch))(batch).pipe(\n Effect.mapError((error) => schemaStoreError(\"encode canonical batch\", error)),\n );\n});\n\nconst encodeCheckpoint = Effect.fn(function* (\n checkpoint: ThreadCheckpoint,\n): Effect.fn.Return<string, ThreadStoreError> {\n return yield* Schema.encodeEffect(Schema.fromJsonString(ThreadCheckpoint))(checkpoint).pipe(\n Effect.mapError((error) => schemaStoreError(\"encode checkpoint\", error)),\n );\n});\n\nconst decodeEnvelope = Effect.fn(function* (row: {\n readonly batch_id: string;\n readonly thread_id: string;\n readonly record_json: string;\n readonly sequence: CanonicalSequence;\n}) {\n const record = yield* Schema.decodeEffect(Schema.fromJsonString(CanonicalRecord))(\n row.record_json,\n ).pipe(\n Effect.mapError((error) =>\n ThreadStoreError.make({\n operation: \"decode canonical record\",\n message: error.message,\n }),\n ),\n );\n\n const threadId = yield* Schema.decodeUnknownEffect(CanonicalRecordEnvelope.fields.threadId)(\n row.thread_id,\n ).pipe(Effect.mapError((error) => schemaStoreError(\"decode thread identity\", error)));\n\n const offset = yield* makeOffset(threadId, row.sequence);\n\n const batchId = yield* Schema.decodeUnknownEffect(CanonicalRecordEnvelope.fields.batchId)(\n row.batch_id,\n ).pipe(Effect.mapError((error) => schemaStoreError(\"decode batch identity\", error)));\n\n return CanonicalRecordEnvelope.make({\n threadId,\n batchId,\n sequence: row.sequence,\n offset,\n record,\n });\n});\n\nconst decodeCheckpoint = Effect.fn(function* (\n checkpointJson: string,\n): Effect.fn.Return<ThreadCheckpoint, ThreadStoreError> {\n return yield* Schema.decodeEffect(Schema.fromJsonString(ThreadCheckpoint))(checkpointJson).pipe(\n Effect.mapError((error) => schemaStoreError(\"decode checkpoint\", error)),\n );\n});\n\nconst requireThread = Effect.fn(\"DoThreadStore.requireThread\")(function* (\n journal: DoJournal,\n threadId: ThreadMaterialization[\"threadId\"],\n) {\n const rows = yield* journal\n .getThread(threadId)\n .pipe(Effect.mapError((error) => storeError(\"read thread\", error)));\n\n if (rows.length === 0) {\n return yield* ThreadNotMaterialized.make({ threadId });\n }\n\n return rows[0];\n});\n\nconst tailDigestAt = Effect.fn(\"DoThreadStore.tailDigestAt\")(function* (\n journal: DoJournal,\n threadId: ThreadMaterialization[\"threadId\"],\n sequence: CanonicalSequence,\n) {\n if (sequence === 0) return EMPTY_TAIL_DIGEST;\n\n const digests = yield* journal\n .getTailDigestAt(threadId, sequence)\n .pipe(Effect.mapError((error) => storeError(\"read checkpoint digest\", error)));\n\n if (digests.length !== 1) {\n return yield* CheckpointRejected.make({\n threadId,\n reason: \"digest-mismatch\",\n });\n }\n\n return yield* Schema.decodeUnknownEffect(Digest)(digests[0]).pipe(\n Effect.mapError((error) => schemaStoreError(\"decode checkpoint digest\", error)),\n );\n});\n\nconst groupByKey = <A>(\n rows: ReadonlyArray<A>,\n key: (row: A) => string,\n): ReadonlyMap<string, ReadonlyArray<A>> => {\n const grouped = new Map<string, Array<A>>();\n\n for (const row of rows) {\n const existing = grouped.get(key(row));\n\n if (existing === undefined) {\n grouped.set(key(row), [row]);\n } else {\n existing.push(row);\n }\n }\n\n return grouped;\n};\n\n/**\n * Opt-in full integrity audit (`verifyOnOpen`). Every stored payload is decoded, re-encoded,\n * and re-digested against the canonical chain. Routine opens skip this scan: per-operation\n * Schema decoding plus the digest chain already fail clearly on corrupt rows.\n */\nconst decodeStartupPayloads = Effect.fn(\"DoThreadStore.decodeStartupPayloads\")(function* (\n journal: DoJournal,\n crypto: Crypto.Crypto,\n) {\n const stored = yield* journal.scanStoredPayloads();\n\n const batches = yield* Effect.forEach(stored.batches, (batch) =>\n Schema.decodeEffect(Schema.fromJsonString(CanonicalBatch))(batch.batch_json).pipe(\n Effect.map((decoded) => ({ decoded, row: batch })),\n Effect.mapError((error) =>\n DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_batches\",\n rowKey: `${batch.thread_id}/${batch.batch_id}`,\n message: error.message,\n }),\n ),\n ),\n );\n\n const records = yield* Effect.forEach(stored.records, (record) =>\n Schema.decodeEffect(Schema.fromJsonString(CanonicalRecord))(record.record_json).pipe(\n Effect.map((decoded) => ({ decoded, row: record })),\n Effect.mapError((error) =>\n DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_records\",\n rowKey: `${record.thread_id}/${record.sequence}`,\n message: error.message,\n }),\n ),\n ),\n );\n\n const checkpoints = yield* Effect.forEach(stored.checkpoints, (checkpoint) =>\n Schema.decodeEffect(Schema.fromJsonString(ThreadCheckpoint))(checkpoint.checkpoint_json).pipe(\n Effect.map((decoded) => ({ decoded, row: checkpoint })),\n Effect.mapError((error) =>\n DoStorageCorruptionError.make({\n table: \"effect_agent_checkpoints\",\n rowKey: `${checkpoint.thread_id}/${checkpoint.through_sequence}`,\n message: error.message,\n }),\n ),\n ),\n );\n\n const batchesByThread = groupByKey(batches, ({ row }) => row.thread_id);\n const recordsByThread = groupByKey(records, ({ row }) => row.thread_id);\n const checkpointsByThread = groupByKey(checkpoints, ({ row }) => row.thread_id);\n const materializedIds = new Set(stored.threads.map((thread) => thread.thread_id));\n\n for (const thread of stored.threads) {\n const threadBatches = batchesByThread.get(thread.thread_id) ?? [];\n const threadRecords = recordsByThread.get(thread.thread_id) ?? [];\n const threadCheckpoints = checkpointsByThread.get(thread.thread_id) ?? [];\n const recordsByBatch = groupByKey(threadRecords, ({ row }) => row.batch_id);\n let previousDigest = EMPTY_TAIL_DIGEST;\n let expectedSequence = 1;\n const tailDigests = new Map<number, string>([[0, EMPTY_TAIL_DIGEST]]);\n\n for (const { decoded: canonicalBatch, row: batchRow } of threadBatches) {\n const key = `${batchRow.thread_id}/${batchRow.batch_id}`;\n\n if (\n canonicalBatch.batchId !== batchRow.batch_id ||\n batchRow.first_sequence !== expectedSequence ||\n batchRow.last_sequence !== batchRow.first_sequence + canonicalBatch.records.length - 1\n ) {\n return yield* DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_batches\",\n rowKey: key,\n message: \"Canonical batch identity, sequence, or record count is inconsistent.\",\n });\n }\n\n const digest = yield* digestCanonicalBatch(previousDigest, canonicalBatch).pipe(\n Effect.provideService(Crypto.Crypto, crypto),\n Effect.mapError((error) =>\n DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_batches\",\n rowKey: key,\n message: error.message,\n }),\n ),\n );\n\n if (batchRow.batch_digest !== digest || batchRow.tail_digest !== digest) {\n return yield* DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_batches\",\n rowKey: key,\n message: \"Canonical batch digest does not match its decoded content and prior tail.\",\n });\n }\n\n const batchRecords = recordsByBatch.get(batchRow.batch_id) ?? [];\n\n if (batchRecords.length !== canonicalBatch.records.length) {\n return yield* DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_records\",\n rowKey: key,\n message: \"Canonical batch and record-table counts differ.\",\n });\n }\n for (let index = 0; index < canonicalBatch.records.length; index++) {\n const expectedRecord = canonicalBatch.records[index];\n const storedRecord = batchRecords[index];\n\n const expectedJson = yield* Schema.encodeEffect(Schema.fromJsonString(CanonicalRecord))(\n expectedRecord,\n ).pipe(\n Effect.mapError((error) =>\n DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_batches\",\n rowKey: key,\n message: error.message,\n }),\n ),\n );\n\n const storedJson = yield* Schema.encodeEffect(Schema.fromJsonString(CanonicalRecord))(\n storedRecord.decoded,\n ).pipe(\n Effect.mapError((error) =>\n DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_records\",\n rowKey: `${key}/${storedRecord.row.sequence}`,\n message: error.message,\n }),\n ),\n );\n\n if (\n storedRecord.row.sequence !== batchRow.first_sequence + index ||\n storedRecord.row.record_id !== expectedRecord.recordId ||\n expectedJson !== storedJson\n ) {\n return yield* DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_records\",\n rowKey: `${key}/${storedRecord.row.sequence}`,\n message: \"Canonical record identity, sequence, or payload differs from its batch.\",\n });\n }\n }\n\n previousDigest = digest;\n expectedSequence = batchRow.last_sequence + 1;\n tailDigests.set(batchRow.last_sequence, digest);\n }\n\n if (\n threadRecords.length !== thread.tail_sequence ||\n thread.tail_sequence !== expectedSequence - 1 ||\n thread.tail_digest !== previousDigest\n ) {\n return yield* DoStorageCorruptionError.make({\n table: \"effect_agent_threads\",\n rowKey: thread.thread_id,\n message: \"Thread tail does not match its canonical batch chain.\",\n });\n }\n\n for (const checkpoint of threadCheckpoints) {\n if (\n checkpoint.decoded.threadId !== thread.thread_id ||\n checkpoint.decoded.throughSequence !== checkpoint.row.through_sequence ||\n checkpoint.decoded.tailDigest !== checkpoint.row.tail_digest ||\n tailDigests.get(checkpoint.row.through_sequence) !== checkpoint.row.tail_digest\n ) {\n return yield* DoStorageCorruptionError.make({\n table: \"effect_agent_checkpoints\",\n rowKey: `${thread.thread_id}/${checkpoint.row.through_sequence}`,\n message: \"Checkpoint identity or digest is not bound to a canonical batch tail.\",\n });\n }\n }\n }\n\n if (\n batches.some(({ row }) => !materializedIds.has(row.thread_id)) ||\n records.some(({ row }) => !materializedIds.has(row.thread_id)) ||\n checkpoints.some(({ row }) => !materializedIds.has(row.thread_id))\n ) {\n return yield* DoStorageCorruptionError.make({\n table: \"effect_agent_threads\",\n rowKey: \"startup_scan\",\n message: \"Canonical rows exist without a materialized Thread.\",\n });\n }\n});\n\nconst makeServices = Effect.fn(\"DoThreadStore.makeServices\")(function* () {\n const config = yield* DoStorageConfig;\n const failpoint = yield* DoStorageFailpoint;\n const sql = yield* SqlClientService.SqlClient;\n const crypto = yield* Crypto.Crypto;\n const journal = yield* initializeDoJournal(sql, failpoint.hit, config.maxStoredValueBytes);\n\n if (config.verifyOnOpen) {\n yield* decodeStartupPayloads(journal, crypto);\n }\n\n const provideCrypto = <A, E>(effect: Effect.Effect<A, E, Crypto.Crypto>) =>\n Effect.provideService(effect, Crypto.Crypto, crypto);\n\n const hitFailpoint = Effect.fn(\n (location: DoStorageFailpointLocation): Effect.Effect<void, ThreadStoreError> =>\n failpoint\n .hit(location)\n .pipe(Effect.mapError((error) => storeError(`storage failpoint ${location}`, error))),\n );\n\n const materialize: ThreadStore[\"Service\"][\"materialize\"] = Effect.fn(\"DoThreadStore.materialize\")(\n function* (request: ThreadMaterialization) {\n const validated = yield* Schema.decodeUnknownEffect(Schema.toType(ThreadMaterialization))(\n request,\n ).pipe(Effect.mapError((error) => schemaStoreError(\"validate materialization\", error)));\n\n const now = yield* Clock.currentTimeMillis;\n\n yield* hitFailpoint(\"materialize:before\");\n yield* journal\n .materialize(\n validated.threadId,\n new Date(now).toISOString(),\n EMPTY_TAIL_DIGEST,\n validated.producerEpoch,\n )\n .pipe(\n Effect.mapError((error) =>\n error._tag === \"DoFenceRejected\"\n ? mapFence(validated.threadId, error)\n : storeError(\"materialize thread\", error),\n ),\n );\n yield* hitFailpoint(\"materialize:after\");\n },\n );\n\n const append: ThreadStore[\"Service\"][\"append\"] = Effect.fn(\"DoThreadStore.append\")(function* (\n request: FencedAppendRequest,\n ) {\n const validated = yield* Schema.decodeUnknownEffect(Schema.toType(FencedAppendRequest))(\n request,\n ).pipe(Effect.mapError((error) => schemaStoreError(\"validate canonical append\", error)));\n\n yield* requireThread(journal, validated.threadId);\n\n const tailDigest = yield* provideCrypto(\n digestCanonicalBatch(validated.expectedTailDigest, validated.batch),\n ).pipe(Effect.mapError((error) => storeError(\"digest canonical append\", error)));\n\n const batchJson = yield* encodeCanonicalBatch(validated.batch);\n\n const rawRecords = yield* Effect.forEach(validated.batch.records, (record) =>\n encodeCanonicalRecord(record).pipe(\n Effect.map((recordJson) => ({\n recordId: record.recordId,\n recordJson,\n })),\n ),\n );\n\n const rawRequest = yield* Schema.decodeUnknownEffect(RawAppendRequest)({\n threadId: validated.threadId,\n batchId: validated.batch.batchId,\n batchDigest: tailDigest,\n batchJson,\n expectedTailSequence: validated.expectedTailSequence,\n expectedTailDigest: validated.expectedTailDigest,\n producerEpoch: validated.producerEpoch,\n records: rawRecords,\n tailDigest,\n }).pipe(Effect.mapError((error) => schemaStoreError(\"encode canonical append\", error)));\n\n yield* hitFailpoint(\"append:before\");\n\n const result = yield* journal.append(rawRequest).pipe(\n Effect.mapError((error) => {\n if (isDoFenceRejected(error)) {\n return mapFence(validated.threadId, error);\n }\n if (isDoAppendConflict(error)) {\n return error.actualTailSequence !== undefined && isDigest(error.actualTailDigest)\n ? AppendConflict.make({\n threadId: validated.threadId,\n batchId: validated.batch.batchId,\n reason: error.reason,\n actualTailSequence: error.actualTailSequence,\n actualTailDigest: error.actualTailDigest,\n })\n : AppendConflict.make({\n threadId: validated.threadId,\n batchId: validated.batch.batchId,\n reason: error.reason,\n });\n }\n\n return storeError(\"append canonical batch\", error);\n }),\n Effect.flatMap((result) =>\n Schema.decodeUnknownEffect(AppendResult)(result).pipe(\n Effect.mapError((error) => schemaStoreError(\"decode append result\", error)),\n ),\n ),\n );\n\n yield* hitFailpoint(\"append:after\");\n\n return result;\n });\n\n const loadRecords = Effect.fn(\"DoThreadStore.loadRecords\")(function* (request: RawReadRequest) {\n const result = yield* journal\n .read(request)\n .pipe(Effect.mapError((error) => storeError(\"read canonical records\", error)));\n\n return {\n count: result.count,\n records: result.records.pipe(\n Stream.mapError((error) => storeError(\"read canonical records\", error)),\n Stream.mapEffect(decodeEnvelope),\n ),\n };\n });\n\n const readEffect = Effect.fn(\"DoThreadStore.read\")(function* (request: ThreadRead) {\n const validated = yield* Schema.decodeUnknownEffect(Schema.toType(ThreadRead))(request).pipe(\n Effect.mapError((error) => schemaStoreError(\"validate thread read\", error)),\n );\n\n yield* requireThread(journal, validated.threadId);\n\n const result = yield* loadRecords(\n RawReadRequest.make({\n threadId: validated.threadId,\n fromSequenceExclusive: validated.afterSequence ?? ZERO_CANONICAL_SEQUENCE,\n limit: validated.limit,\n }),\n );\n\n return result.records;\n });\n\n const read: ThreadStore[\"Service\"][\"read\"] = (request) => Stream.unwrap(readEffect(request));\n\n const observeEffect = Effect.fn(\"DoThreadStore.observe\")(function* (request: ThreadObservation) {\n const validated = yield* Schema.decodeUnknownEffect(Schema.toType(ThreadObservation))(\n request,\n ).pipe(Effect.mapError((error) => schemaStoreError(\"validate thread observation\", error)));\n\n yield* requireThread(journal, validated.threadId);\n const initialSequence = yield* parseOffset(validated.threadId, validated.afterOffset);\n const cursor = yield* Ref.make(initialSequence);\n\n const poll = Effect.fn(\"DoThreadStore.observePoll\")(function* () {\n const fromSequenceExclusive = yield* Ref.get(cursor);\n\n const result = yield* loadRecords(\n RawReadRequest.make({\n threadId: validated.threadId,\n fromSequenceExclusive,\n limit: 1_024,\n }),\n );\n\n if (result.count === 0) {\n yield* Effect.sleep(config.observationPollInterval);\n\n return Stream.empty;\n }\n\n return result.records.pipe(Stream.tap((record) => Ref.set(cursor, record.sequence)));\n });\n\n return Stream.fromEffectRepeat(poll()).pipe(Stream.flatten);\n });\n\n const observe: ThreadStore[\"Service\"][\"observe\"] = (request) =>\n Stream.unwrap(observeEffect(request));\n\n const exportThread: ThreadStore[\"Service\"][\"export\"] = Effect.fn(\"DoThreadStore.export\")(\n function* (request: ThreadExportRequest) {\n const validated = yield* Schema.decodeUnknownEffect(Schema.toType(ThreadExportRequest))(\n request,\n ).pipe(Effect.mapError((error) => schemaStoreError(\"validate thread export\", error)));\n\n yield* requireThread(journal, validated.threadId);\n\n const exported = yield* journal\n .exportThread(validated.threadId)\n .pipe(Effect.mapError((error) => storeError(\"export thread\", error)));\n\n const records = yield* Effect.forEach(exported.records, decodeEnvelope);\n\n if (records.length > 65_536) {\n return yield* ThreadStoreError.make({\n operation: \"decode thread export\",\n message: \"The thread exceeds the current export record limit.\",\n });\n }\n\n const tailDigest = yield* Schema.decodeUnknownEffect(Digest)(\n exported.thread.tail_digest,\n ).pipe(Effect.mapError((error) => schemaStoreError(\"decode export tail digest\", error)));\n\n return ThreadExport.make({\n format: \"effect-agent/thread@1\",\n threadId: validated.threadId,\n tailSequence: exported.thread.tail_sequence,\n tailDigest,\n records,\n });\n },\n );\n\n const inspectTail: ThreadStore[\"Service\"][\"inspectTail\"] = Effect.fn(\"DoThreadStore.inspectTail\")(\n function* (request: ThreadTailRequest) {\n const validated = yield* Schema.decodeUnknownEffect(Schema.toType(ThreadTailRequest))(\n request,\n ).pipe(Effect.mapError((error) => schemaStoreError(\"validate tail inspection\", error)));\n\n const thread = yield* requireThread(journal, validated.threadId);\n\n const tailDigest = yield* Schema.decodeUnknownEffect(Digest)(thread.tail_digest).pipe(\n Effect.mapError((error) => schemaStoreError(\"decode tail digest\", error)),\n );\n\n return ThreadTail.make({\n threadId: validated.threadId,\n tailSequence: thread.tail_sequence,\n tailDigest,\n producerEpoch: thread.producer_epoch,\n });\n },\n );\n\n const saveCheckpoint: ThreadCheckpoints[\"save\"] = Effect.fn(\"DoThreadStore.saveCheckpoint\")(\n function* (request: SaveCheckpointRequest) {\n const validated = yield* Schema.decodeUnknownEffect(Schema.toType(SaveCheckpointRequest))(\n request,\n ).pipe(Effect.mapError((error) => schemaStoreError(\"validate checkpoint\", error)));\n\n const thread = yield* requireThread(journal, validated.checkpoint.threadId);\n\n if (validated.checkpoint.throughSequence > thread.tail_sequence) {\n return yield* CheckpointRejected.make({\n threadId: validated.checkpoint.threadId,\n reason: \"ahead-of-tail\",\n });\n }\n\n const canonicalDigest = yield* tailDigestAt(\n journal,\n validated.checkpoint.threadId,\n validated.checkpoint.throughSequence,\n );\n\n if (canonicalDigest !== validated.checkpoint.tailDigest) {\n return yield* CheckpointRejected.make({\n threadId: validated.checkpoint.threadId,\n reason: \"digest-mismatch\",\n });\n }\n const checkpointJson = yield* encodeCheckpoint(validated.checkpoint);\n\n const raw = RawCheckpoint.make({\n threadId: validated.checkpoint.threadId,\n throughSequence: validated.checkpoint.throughSequence,\n tailDigest: validated.checkpoint.tailDigest,\n checkpointJson,\n });\n\n yield* hitFailpoint(\"save-checkpoint:before\");\n yield* journal.saveCheckpoint(raw).pipe(\n Effect.mapError((error) =>\n isDoCheckpointConflict(error)\n ? CheckpointRejected.make({\n threadId: validated.checkpoint.threadId,\n reason: \"digest-mismatch\",\n })\n : storeError(\"save checkpoint\", error),\n ),\n );\n yield* hitFailpoint(\"save-checkpoint:after\");\n },\n );\n\n const loadCheckpoint: ThreadCheckpoints[\"load\"] = Effect.fn(\"DoThreadStore.loadCheckpoint\")(\n function* (request: LoadCheckpointRequest) {\n const validated = yield* Schema.decodeUnknownEffect(Schema.toType(LoadCheckpointRequest))(\n request,\n ).pipe(Effect.mapError((error) => schemaStoreError(\"validate checkpoint lookup\", error)));\n\n const thread = yield* requireThread(journal, validated.threadId);\n\n const rows = yield* journal\n .loadCheckpoint(validated.threadId, validated.atOrBeforeSequence ?? thread.tail_sequence)\n .pipe(Effect.mapError((error) => storeError(\"load checkpoint\", error)));\n\n if (rows.length === 0) return Option.none();\n if (rows.length !== 1) {\n return yield* ThreadStoreError.make({\n operation: \"load checkpoint\",\n message: `Expected at most one checkpoint row but found ${rows.length}.`,\n });\n }\n const checkpoint = yield* decodeCheckpoint(rows[0].checkpoint_json);\n\n const canonicalDigest = yield* tailDigestAt(\n journal,\n checkpoint.threadId,\n checkpoint.throughSequence,\n );\n\n if (canonicalDigest !== checkpoint.tailDigest) {\n return yield* CheckpointRejected.make({\n threadId: checkpoint.threadId,\n reason: \"digest-mismatch\",\n });\n }\n\n return Option.some(checkpoint);\n },\n );\n\n const threadStore = ThreadStore.of({\n append,\n export: exportThread,\n inspectTail,\n materialize,\n observe,\n read,\n checkpoints: { save: saveCheckpoint, load: loadCheckpoint },\n });\n\n return Context.make(ThreadStore, threadStore);\n});\n\n/**\n * Durable Object Thread Store implementation with configuration, failpoint, SQL, and\n * Crypto authority kept visible in its input channel.\n */\nexport const threadStoreLayer: Layer.Layer<\n ThreadStore,\n DoStorageInitializationError,\n DoStorageConfig | DoStorageFailpoint | SqlClientService.SqlClient | Crypto.Crypto\n> = Layer.effectContext(makeServices());\n\n/**\n * Validated Durable Object storage configuration Layer with the documented defaults applied.\n * Shared by the ThreadStore and SubmissionLedger convenience layers so their defaults\n * cannot drift.\n */\nexport const storageConfigLayer = (\n options: DoStorageOptions,\n): Layer.Layer<DoStorageConfig, DoStorageError> =>\n Layer.effect(DoStorageConfig)(\n Schema.decodeUnknownEffect(DoStorageConfigValue)({\n observationPollInterval: options.observationPollInterval ?? 25,\n ownershipLeaseDuration:\n options.ownershipLeaseDuration ?? Duration.toMillis(DEFAULT_OWNERSHIP_LEASE_DURATION),\n maxStoredValueBytes: options.maxStoredValueBytes ?? DEFAULT_MAX_STORED_VALUE_BYTES,\n verifyOnOpen: options.verifyOnOpen ?? false,\n }).pipe(\n Effect.mapError((error) =>\n DoStorageError.make({\n cause: error,\n operation: \"configure Durable Object storage\",\n message: error.message,\n }),\n ),\n ),\n );\n\n/** The failpoint Layer selected by convenience options: explicit handler or the no-op default. */\nexport const storageFailpointLayer = (\n options: DoStorageOptions,\n): Layer.Layer<DoStorageFailpoint> =>\n options.failpoint === undefined\n ? DoStorageFailpoint.layer\n : Layer.succeed(DoStorageFailpoint)({ hit: options.failpoint });\n\n/**\n * A composition-root convenience Layer for canonical Threads inside one Durable Object,\n * built over `ctx.storage`. Durable accepted work is served by the separate SubmissionLedger\n * port; point both at the SAME `ctx.storage` so claims fence the same producer epochs\n * (ADR-0011 D7's \"same file\" rule, transposed to one object's private database).\n */\nexport const layer = (\n options: DoStorageOptions,\n): Layer.Layer<ThreadStore, DoStorageInitializationError> =>\n Layer.unwrap(\n Effect.map(DoStorageConfig, (config) =>\n threadStoreLayer.pipe(\n Layer.provide(\n Layer.mergeAll(\n Layer.succeed(DoStorageConfig)(config),\n storageFailpointLayer(options),\n SqliteClient.layer({ storage: options.storage }),\n BrowserCrypto.layer,\n ),\n ),\n ),\n ),\n ).pipe(Layer.provide(storageConfigLayer(options)));\n"],"mappings":"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"}
|
package/dist/DoThreadStore.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "./DoStorageConfig.mjs";
|
|
2
2
|
import "./DoStorageError.mjs";
|
|
3
3
|
import "./DoStorageFailpoint.mjs";
|
|
4
|
-
import { a as threadStoreLayer, i as storageFailpointLayer, n as layer, r as storageConfigLayer } from "./DoThreadStore-
|
|
4
|
+
import { a as threadStoreLayer, i as storageFailpointLayer, n as layer, r as storageConfigLayer } from "./DoThreadStore-D00TdRAa.mjs";
|
|
5
5
|
export { layer, storageConfigLayer, storageFailpointLayer, threadStoreLayer };
|
package/dist/MemoryProtocol.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
2
|
import { MemoryConflict, MemoryDocument, MemoryMutationFailure, MemoryOperationConflict, MemoryStorageError, MemoryWithdrawn, MemoryWrite, MemoryWriter } from "@effect-agent/core/MemoryStore";
|
|
3
|
-
import { Clock, Context, Effect,
|
|
3
|
+
import { Clock, Context, Effect, Schema } from "effect";
|
|
4
4
|
import { Principal } from "@effect-agent/thread/SubmissionLedger";
|
|
5
5
|
import * as MemoryNamespace from "@effect-agent/core/MemoryNamespace";
|
|
6
6
|
import { MemoryLookup, MemoryRecallError, MemoryRecallLimits } from "@effect-agent/core/MemoryReference";
|
|
@@ -109,7 +109,7 @@ const MemoryOwnerResponse = Schema.Union([
|
|
|
109
109
|
var MemoryOwnerAuthorizer = class extends Context.Service()("@effect-agent/storage-cloudflare/MemoryOwnerAuthorizer") {};
|
|
110
110
|
/** Canonical namespace derived from this object's idFromName identity, never its request. */
|
|
111
111
|
var MemoryOwnerIdentity = class extends Context.Service()("@effect-agent/storage-cloudflare/MemoryOwnerIdentity") {};
|
|
112
|
-
const memoryWireBytes = (text) =>
|
|
112
|
+
const memoryWireBytes = (text) => new TextEncoder().encode(text).byteLength;
|
|
113
113
|
const decodeMemoryWire = Effect.fn("decodeMemoryWire")(function* (schema, raw, maxBytes) {
|
|
114
114
|
const text = yield* Schema.decodeUnknownEffect(Schema.String)(raw).pipe(Effect.mapError(() => MemoryRpcError.make({ reason: "protocol" })));
|
|
115
115
|
if (text.length > maxBytes || memoryWireBytes(text) > maxBytes) return yield* MemoryRpcError.make({ reason: "budget" });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MemoryProtocol.mjs","names":[],"sources":["../src/MemoryProtocol.ts"],"sourcesContent":["import * as MemoryNamespace from \"@effect-agent/core/MemoryNamespace\";\nimport {\n MemoryLookup,\n MemoryRecallError,\n MemoryRecallLimits,\n} from \"@effect-agent/core/MemoryReference\";\nimport { MemoryAccess, revalidateMemoryLookup } from \"@effect-agent/core/MemoryRevalidation\";\nimport { type MemoryReader } from \"@effect-agent/core/MemoryStore\";\nimport {\n MemoryConflict,\n MemoryDocument,\n MemoryMutationFailure,\n MemoryOperationConflict,\n MemoryStorageError,\n MemoryWithdrawn,\n MemoryWrite,\n MemoryWriter,\n} from \"@effect-agent/core/MemoryStore\";\nimport {\n MemoryIndexSearch,\n MemoryIndexError,\n SemanticMemoryProfile,\n} from \"@effect-agent/core/SemanticMemoryIndex\";\nimport {\n SemanticMemoryError,\n SemanticCandidateLimits,\n SemanticCandidateResult,\n revalidateSemanticMemoryCandidates,\n} from \"@effect-agent/core/SemanticMemoryRevalidation\";\nimport { Principal } from \"@effect-agent/thread/SubmissionLedger\";\nimport { Clock, Context, Effect, Encoding, Schema } from \"effect\";\n\nexport class MemoryRpcError extends Schema.TaggedError<MemoryRpcError>()(\"MemoryRpcError\", {\n reason: Schema.Literals([\"denied\", \"protocol\", \"budget\", \"timeout\", \"unavailable\"]),\n}) {}\n\nexport class MemoryRpcLimits extends Schema.Class<MemoryRpcLimits>(\n \"@effect-agent/storage-cloudflare/MemoryRpcLimits\",\n)({\n maxRequestBytes: Schema.Int.check(Schema.isBetween({ minimum: 256, maximum: 4_194_304 })),\n maxResponseBytes: Schema.Int.check(Schema.isBetween({ minimum: 256, maximum: 16_777_216 })),\n maxSourceBytes: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 67_108_864 })),\n maxSources: MemoryRecallLimits.fields.maxSources,\n timeoutMillis: MemoryRecallLimits.fields.timeoutMillis,\n}) {}\n\nexport const defaultMemoryRpcLimits = MemoryRpcLimits.make({\n maxRequestBytes: 1_048_576,\n maxResponseBytes: 4_194_304,\n maxSourceBytes: 16_777_216,\n maxSources: 16,\n timeoutMillis: 10_000,\n});\n\nconst RequestFields = {\n version: Schema.Literal(1),\n access: MemoryAccess.Wire,\n /** Host-authenticated identity, never copied from model input. The owner still authorizes it. */\n principal: Principal,\n deadlineMillis: Schema.Finite.check(Schema.isGreaterThanOrEqualTo(0)),\n};\n\nconst RevalidateRequest = Schema.TaggedStruct(\"Revalidate\", {\n ...RequestFields,\n lookup: MemoryLookup,\n limits: MemoryRecallLimits,\n});\n\nconst ChangeRequest = Schema.TaggedStruct(\"Change\", { ...RequestFields, write: MemoryWrite.Wire });\n\nconst SemanticRequest: Schema.TaggedStruct<\n \"RevalidateSemantic\",\n typeof RequestFields & {\n readonly found: typeof MemoryIndexSearch.Wire;\n readonly profile: typeof SemanticMemoryProfile;\n readonly limits: typeof SemanticCandidateLimits;\n }\n> = Schema.TaggedStruct(\"RevalidateSemantic\", {\n ...RequestFields,\n found: MemoryIndexSearch.Wire,\n profile: SemanticMemoryProfile,\n limits: SemanticCandidateLimits,\n});\n\nexport const MemoryOwnerRequest: Schema.Union<\n [typeof RevalidateRequest, typeof ChangeRequest, typeof SemanticRequest]\n> = Schema.Union([RevalidateRequest, ChangeRequest, SemanticRequest]);\n\nexport type MemoryOwnerRequest = typeof MemoryOwnerRequest.Type;\n\nexport const MemoryOwnerFailure = Schema.Union([\n MemoryRpcError,\n MemoryStorageError,\n MemoryRecallError,\n MemoryConflict,\n MemoryWithdrawn,\n MemoryOperationConflict,\n MemoryMutationFailure,\n MemoryIndexError,\n SemanticMemoryError,\n]);\n\nexport type MemoryOwnerFailure = typeof MemoryOwnerFailure.Type;\n\nexport const MemoryOwnerResponse = Schema.Union([\n Schema.TaggedStruct(\"Lookup\", { access: MemoryAccess.Wire, lookup: MemoryLookup }),\n Schema.TaggedStruct(\"Changed\", { access: MemoryAccess.Wire, document: MemoryDocument.Wire }),\n Schema.TaggedStruct(\"Semantic\", { access: MemoryAccess.Wire, result: SemanticCandidateResult }),\n Schema.TaggedStruct(\"Failed\", { failure: MemoryOwnerFailure }),\n]);\n\nexport type MemoryOwnerResponse = typeof MemoryOwnerResponse.Type;\n\n/** Fail-closed application policy. Authorize the namespace, principal, scope, and full command. */\nexport class MemoryOwnerAuthorizer extends Context.Service<\n MemoryOwnerAuthorizer,\n {\n readonly authorize: (request: MemoryOwnerRequest) => Effect.Effect<void, MemoryRpcError>;\n }\n>()(\"@effect-agent/storage-cloudflare/MemoryOwnerAuthorizer\") {}\n\n/** Canonical namespace derived from this object's idFromName identity, never its request. */\nexport class MemoryOwnerIdentity extends Context.Service<\n MemoryOwnerIdentity,\n {\n readonly namespace: MemoryNamespace.Any;\n }\n>()(\"@effect-agent/storage-cloudflare/MemoryOwnerIdentity\") {}\n\nexport const memoryWireBytes = (text: string): number => Encoding.encodeHex(text).length / 2;\n\nexport const decodeMemoryWire = Effect.fn(\"decodeMemoryWire\")(function* <A, I>(\n schema: Schema.Codec<A, I, never>,\n raw: unknown,\n maxBytes: number,\n) {\n const text = yield* Schema.decodeUnknownEffect(Schema.String)(raw).pipe(\n Effect.mapError(() => MemoryRpcError.make({ reason: \"protocol\" })),\n );\n\n if (text.length > maxBytes || memoryWireBytes(text) > maxBytes)\n return yield* MemoryRpcError.make({ reason: \"budget\" });\n\n return yield* Schema.decodeEffect(Schema.fromJsonString(schema))(text).pipe(\n Effect.mapError(() => MemoryRpcError.make({ reason: \"protocol\" })),\n );\n});\n\nexport const encodeMemoryWire = Effect.fn(\"encodeMemoryWire\")(function* <A, I>(\n schema: Schema.Codec<A, I, never, never>,\n value: A,\n maxBytes: number,\n) {\n const encoded = yield* Schema.encodeEffect(Schema.fromJsonString(schema))(value).pipe(\n Effect.mapError(() => MemoryRpcError.make({ reason: \"protocol\" })),\n );\n\n if (encoded.length > maxBytes || memoryWireBytes(encoded) > maxBytes)\n return yield* MemoryRpcError.make({ reason: \"budget\" });\n\n return encoded;\n});\n\n/** One local read per distinct candidate source, with no per-document network calls. */\nexport const handleMemoryOwnerRequest = Effect.fn(\"MemoryOwner.handleRequest\")(function* (\n raw: unknown,\n limits: MemoryRpcLimits = defaultMemoryRpcLimits,\n): Effect.fn.Return<\n string,\n never,\n MemoryOwnerIdentity | MemoryOwnerAuthorizer | MemoryReader | MemoryWriter\n> {\n const result = yield* Effect.gen(function* (): Effect.fn.Return<\n MemoryOwnerResponse,\n MemoryOwnerFailure,\n MemoryOwnerIdentity | MemoryOwnerAuthorizer | MemoryReader | MemoryWriter\n > {\n limits = yield* Schema.decodeUnknownEffect(MemoryRpcLimits)(limits).pipe(\n Effect.mapError(() => MemoryRpcError.make({ reason: \"protocol\" })),\n );\n const request = yield* decodeMemoryWire(MemoryOwnerRequest, raw, limits.maxRequestBytes);\n const { namespace } = yield* MemoryOwnerIdentity;\n\n if (\n !MemoryNamespace.equals(namespace, request.access.namespace) ||\n (request._tag === \"Change\" &&\n !MemoryNamespace.equals(namespace, request.write.key.namespace)) ||\n (request._tag === \"RevalidateSemantic\" &&\n request.found.candidates.some(\n (candidate) => !MemoryNamespace.equals(namespace, candidate.key.namespace),\n ))\n )\n return yield* MemoryRpcError.make({ reason: \"denied\" });\n\n const remaining = Math.min(\n limits.timeoutMillis,\n request.deadlineMillis - (yield* Clock.currentTimeMillis),\n );\n\n if (remaining <= 0) return yield* MemoryRpcError.make({ reason: \"timeout\" });\n\n return yield* Effect.gen(function* (): Effect.fn.Return<\n MemoryOwnerResponse,\n MemoryOwnerFailure,\n MemoryOwnerAuthorizer | MemoryReader | MemoryWriter\n > {\n const authorizer = yield* MemoryOwnerAuthorizer;\n\n yield* authorizer.authorize(request);\n if (request._tag === \"Change\") {\n const writer = yield* MemoryWriter;\n\n return {\n _tag: \"Changed\",\n access: request.access,\n document: yield* writer.change(request.write),\n };\n }\n if (request._tag === \"RevalidateSemantic\") {\n if (\n new Set(request.found.candidates.map((candidate) => candidate.key.id)).size >\n limits.maxSources\n )\n return yield* MemoryRpcError.make({ reason: \"budget\" });\n\n const result = yield* revalidateSemanticMemoryCandidates(\n request.found,\n request.access,\n request.profile,\n {\n ...request.limits,\n maxSourceBytes: Math.min(\n limits.maxSourceBytes,\n request.limits.maxSourceBytes ?? 16_777_216,\n ),\n maxOutputBytes: Math.min(\n limits.maxResponseBytes,\n request.limits.maxOutputBytes ?? 16_777_216,\n ),\n },\n );\n\n return { _tag: \"Semantic\", access: request.access, result };\n }\n\n const count =\n request.lookup._tag === \"Found\"\n ? new Set(request.lookup.passages.map((passage) => passage.source.id)).size\n : 0;\n\n if (count > Math.min(limits.maxSources, request.limits.maxSources))\n return yield* MemoryRpcError.make({ reason: \"budget\" });\n\n const lookup = yield* revalidateMemoryLookup(request.lookup, request.access, {\n maxSourceBytes: limits.maxSourceBytes,\n maxInputBytes: Math.min(limits.maxSourceBytes, request.limits.maxInputBytes ?? 16_777_216),\n });\n\n return { _tag: \"Lookup\", access: request.access, lookup };\n }).pipe(\n Effect.scoped,\n Effect.timeoutOrElse({\n duration: remaining,\n orElse: () => Effect.fail(MemoryRpcError.make({ reason: \"timeout\" })),\n }),\n );\n }).pipe(\n Effect.flatMap((response) =>\n encodeMemoryWire(MemoryOwnerResponse, response, limits.maxResponseBytes),\n ),\n Effect.result,\n );\n\n if (result._tag === \"Success\") return result.success;\n\n return yield* encodeMemoryWire(\n MemoryOwnerResponse,\n {\n _tag: \"Failed\",\n failure: result.failure,\n },\n limits.maxResponseBytes,\n ).pipe(\n Effect.catch(() =>\n Schema.encodeEffect(Schema.fromJsonString(MemoryOwnerResponse))({\n _tag: \"Failed\",\n failure: MemoryRpcError.make({ reason: \"budget\" }),\n }).pipe(Effect.orDie),\n ),\n );\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MemoryProtocol.mjs","names":[],"sources":["../src/MemoryProtocol.ts"],"sourcesContent":["import * as MemoryNamespace from \"@effect-agent/core/MemoryNamespace\";\nimport {\n MemoryLookup,\n MemoryRecallError,\n MemoryRecallLimits,\n} from \"@effect-agent/core/MemoryReference\";\nimport { MemoryAccess, revalidateMemoryLookup } from \"@effect-agent/core/MemoryRevalidation\";\nimport { type MemoryReader } from \"@effect-agent/core/MemoryStore\";\nimport {\n MemoryConflict,\n MemoryDocument,\n MemoryMutationFailure,\n MemoryOperationConflict,\n MemoryStorageError,\n MemoryWithdrawn,\n MemoryWrite,\n MemoryWriter,\n} from \"@effect-agent/core/MemoryStore\";\nimport {\n MemoryIndexSearch,\n MemoryIndexError,\n SemanticMemoryProfile,\n} from \"@effect-agent/core/SemanticMemoryIndex\";\nimport {\n SemanticMemoryError,\n SemanticCandidateLimits,\n SemanticCandidateResult,\n revalidateSemanticMemoryCandidates,\n} from \"@effect-agent/core/SemanticMemoryRevalidation\";\nimport { Principal } from \"@effect-agent/thread/SubmissionLedger\";\nimport { Clock, Context, Effect, Schema } from \"effect\";\n\nexport class MemoryRpcError extends Schema.TaggedError<MemoryRpcError>()(\"MemoryRpcError\", {\n reason: Schema.Literals([\"denied\", \"protocol\", \"budget\", \"timeout\", \"unavailable\"]),\n}) {}\n\nexport class MemoryRpcLimits extends Schema.Class<MemoryRpcLimits>(\n \"@effect-agent/storage-cloudflare/MemoryRpcLimits\",\n)({\n maxRequestBytes: Schema.Int.check(Schema.isBetween({ minimum: 256, maximum: 4_194_304 })),\n maxResponseBytes: Schema.Int.check(Schema.isBetween({ minimum: 256, maximum: 16_777_216 })),\n maxSourceBytes: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 67_108_864 })),\n maxSources: MemoryRecallLimits.fields.maxSources,\n timeoutMillis: MemoryRecallLimits.fields.timeoutMillis,\n}) {}\n\nexport const defaultMemoryRpcLimits = MemoryRpcLimits.make({\n maxRequestBytes: 1_048_576,\n maxResponseBytes: 4_194_304,\n maxSourceBytes: 16_777_216,\n maxSources: 16,\n timeoutMillis: 10_000,\n});\n\nconst RequestFields = {\n version: Schema.Literal(1),\n access: MemoryAccess.Wire,\n /** Host-authenticated identity, never copied from model input. The owner still authorizes it. */\n principal: Principal,\n deadlineMillis: Schema.Finite.check(Schema.isGreaterThanOrEqualTo(0)),\n};\n\nconst RevalidateRequest = Schema.TaggedStruct(\"Revalidate\", {\n ...RequestFields,\n lookup: MemoryLookup,\n limits: MemoryRecallLimits,\n});\n\nconst ChangeRequest = Schema.TaggedStruct(\"Change\", { ...RequestFields, write: MemoryWrite.Wire });\n\nconst SemanticRequest: Schema.TaggedStruct<\n \"RevalidateSemantic\",\n typeof RequestFields & {\n readonly found: typeof MemoryIndexSearch.Wire;\n readonly profile: typeof SemanticMemoryProfile;\n readonly limits: typeof SemanticCandidateLimits;\n }\n> = Schema.TaggedStruct(\"RevalidateSemantic\", {\n ...RequestFields,\n found: MemoryIndexSearch.Wire,\n profile: SemanticMemoryProfile,\n limits: SemanticCandidateLimits,\n});\n\nexport const MemoryOwnerRequest: Schema.Union<\n [typeof RevalidateRequest, typeof ChangeRequest, typeof SemanticRequest]\n> = Schema.Union([RevalidateRequest, ChangeRequest, SemanticRequest]);\n\nexport type MemoryOwnerRequest = typeof MemoryOwnerRequest.Type;\n\nexport const MemoryOwnerFailure = Schema.Union([\n MemoryRpcError,\n MemoryStorageError,\n MemoryRecallError,\n MemoryConflict,\n MemoryWithdrawn,\n MemoryOperationConflict,\n MemoryMutationFailure,\n MemoryIndexError,\n SemanticMemoryError,\n]);\n\nexport type MemoryOwnerFailure = typeof MemoryOwnerFailure.Type;\n\nexport const MemoryOwnerResponse = Schema.Union([\n Schema.TaggedStruct(\"Lookup\", { access: MemoryAccess.Wire, lookup: MemoryLookup }),\n Schema.TaggedStruct(\"Changed\", { access: MemoryAccess.Wire, document: MemoryDocument.Wire }),\n Schema.TaggedStruct(\"Semantic\", { access: MemoryAccess.Wire, result: SemanticCandidateResult }),\n Schema.TaggedStruct(\"Failed\", { failure: MemoryOwnerFailure }),\n]);\n\nexport type MemoryOwnerResponse = typeof MemoryOwnerResponse.Type;\n\n/** Fail-closed application policy. Authorize the namespace, principal, scope, and full command. */\nexport class MemoryOwnerAuthorizer extends Context.Service<\n MemoryOwnerAuthorizer,\n {\n readonly authorize: (request: MemoryOwnerRequest) => Effect.Effect<void, MemoryRpcError>;\n }\n>()(\"@effect-agent/storage-cloudflare/MemoryOwnerAuthorizer\") {}\n\n/** Canonical namespace derived from this object's idFromName identity, never its request. */\nexport class MemoryOwnerIdentity extends Context.Service<\n MemoryOwnerIdentity,\n {\n readonly namespace: MemoryNamespace.Any;\n }\n>()(\"@effect-agent/storage-cloudflare/MemoryOwnerIdentity\") {}\n\nexport const memoryWireBytes = (text: string): number => new TextEncoder().encode(text).byteLength;\n\nexport const decodeMemoryWire = Effect.fn(\"decodeMemoryWire\")(function* <A, I>(\n schema: Schema.Codec<A, I, never>,\n raw: unknown,\n maxBytes: number,\n) {\n const text = yield* Schema.decodeUnknownEffect(Schema.String)(raw).pipe(\n Effect.mapError(() => MemoryRpcError.make({ reason: \"protocol\" })),\n );\n\n if (text.length > maxBytes || memoryWireBytes(text) > maxBytes)\n return yield* MemoryRpcError.make({ reason: \"budget\" });\n\n return yield* Schema.decodeEffect(Schema.fromJsonString(schema))(text).pipe(\n Effect.mapError(() => MemoryRpcError.make({ reason: \"protocol\" })),\n );\n});\n\nexport const encodeMemoryWire = Effect.fn(\"encodeMemoryWire\")(function* <A, I>(\n schema: Schema.Codec<A, I, never, never>,\n value: A,\n maxBytes: number,\n) {\n const encoded = yield* Schema.encodeEffect(Schema.fromJsonString(schema))(value).pipe(\n Effect.mapError(() => MemoryRpcError.make({ reason: \"protocol\" })),\n );\n\n if (encoded.length > maxBytes || memoryWireBytes(encoded) > maxBytes)\n return yield* MemoryRpcError.make({ reason: \"budget\" });\n\n return encoded;\n});\n\n/** One local read per distinct candidate source, with no per-document network calls. */\nexport const handleMemoryOwnerRequest = Effect.fn(\"MemoryOwner.handleRequest\")(function* (\n raw: unknown,\n limits: MemoryRpcLimits = defaultMemoryRpcLimits,\n): Effect.fn.Return<\n string,\n never,\n MemoryOwnerIdentity | MemoryOwnerAuthorizer | MemoryReader | MemoryWriter\n> {\n const result = yield* Effect.gen(function* (): Effect.fn.Return<\n MemoryOwnerResponse,\n MemoryOwnerFailure,\n MemoryOwnerIdentity | MemoryOwnerAuthorizer | MemoryReader | MemoryWriter\n > {\n limits = yield* Schema.decodeUnknownEffect(MemoryRpcLimits)(limits).pipe(\n Effect.mapError(() => MemoryRpcError.make({ reason: \"protocol\" })),\n );\n const request = yield* decodeMemoryWire(MemoryOwnerRequest, raw, limits.maxRequestBytes);\n const { namespace } = yield* MemoryOwnerIdentity;\n\n if (\n !MemoryNamespace.equals(namespace, request.access.namespace) ||\n (request._tag === \"Change\" &&\n !MemoryNamespace.equals(namespace, request.write.key.namespace)) ||\n (request._tag === \"RevalidateSemantic\" &&\n request.found.candidates.some(\n (candidate) => !MemoryNamespace.equals(namespace, candidate.key.namespace),\n ))\n )\n return yield* MemoryRpcError.make({ reason: \"denied\" });\n\n const remaining = Math.min(\n limits.timeoutMillis,\n request.deadlineMillis - (yield* Clock.currentTimeMillis),\n );\n\n if (remaining <= 0) return yield* MemoryRpcError.make({ reason: \"timeout\" });\n\n return yield* Effect.gen(function* (): Effect.fn.Return<\n MemoryOwnerResponse,\n MemoryOwnerFailure,\n MemoryOwnerAuthorizer | MemoryReader | MemoryWriter\n > {\n const authorizer = yield* MemoryOwnerAuthorizer;\n\n yield* authorizer.authorize(request);\n if (request._tag === \"Change\") {\n const writer = yield* MemoryWriter;\n\n return {\n _tag: \"Changed\",\n access: request.access,\n document: yield* writer.change(request.write),\n };\n }\n if (request._tag === \"RevalidateSemantic\") {\n if (\n new Set(request.found.candidates.map((candidate) => candidate.key.id)).size >\n limits.maxSources\n )\n return yield* MemoryRpcError.make({ reason: \"budget\" });\n\n const result = yield* revalidateSemanticMemoryCandidates(\n request.found,\n request.access,\n request.profile,\n {\n ...request.limits,\n maxSourceBytes: Math.min(\n limits.maxSourceBytes,\n request.limits.maxSourceBytes ?? 16_777_216,\n ),\n maxOutputBytes: Math.min(\n limits.maxResponseBytes,\n request.limits.maxOutputBytes ?? 16_777_216,\n ),\n },\n );\n\n return { _tag: \"Semantic\", access: request.access, result };\n }\n\n const count =\n request.lookup._tag === \"Found\"\n ? new Set(request.lookup.passages.map((passage) => passage.source.id)).size\n : 0;\n\n if (count > Math.min(limits.maxSources, request.limits.maxSources))\n return yield* MemoryRpcError.make({ reason: \"budget\" });\n\n const lookup = yield* revalidateMemoryLookup(request.lookup, request.access, {\n maxSourceBytes: limits.maxSourceBytes,\n maxInputBytes: Math.min(limits.maxSourceBytes, request.limits.maxInputBytes ?? 16_777_216),\n });\n\n return { _tag: \"Lookup\", access: request.access, lookup };\n }).pipe(\n Effect.scoped,\n Effect.timeoutOrElse({\n duration: remaining,\n orElse: () => Effect.fail(MemoryRpcError.make({ reason: \"timeout\" })),\n }),\n );\n }).pipe(\n Effect.flatMap((response) =>\n encodeMemoryWire(MemoryOwnerResponse, response, limits.maxResponseBytes),\n ),\n Effect.result,\n );\n\n if (result._tag === \"Success\") return result.success;\n\n return yield* encodeMemoryWire(\n MemoryOwnerResponse,\n {\n _tag: \"Failed\",\n failure: result.failure,\n },\n limits.maxResponseBytes,\n ).pipe(\n Effect.catch(() =>\n Schema.encodeEffect(Schema.fromJsonString(MemoryOwnerResponse))({\n _tag: \"Failed\",\n failure: MemoryRpcError.make({ reason: \"budget\" }),\n }).pipe(Effect.orDie),\n ),\n );\n});\n"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { t as DoStorageConfig_exports } from "./DoStorageConfig.mjs";
|
|
|
4
4
|
import { t as DoStorageError_exports } from "./DoStorageError.mjs";
|
|
5
5
|
import { t as DoStorageFailpoint_exports } from "./DoStorageFailpoint.mjs";
|
|
6
6
|
import { t as DoStorageVersion_exports } from "./DoStorageVersion.mjs";
|
|
7
|
-
import { t as DoThreadStore_exports } from "./DoThreadStore-
|
|
7
|
+
import { t as DoThreadStore_exports } from "./DoThreadStore-D00TdRAa.mjs";
|
|
8
8
|
import { t as DoSubmissionLedger_exports } from "./DoSubmissionLedger.mjs";
|
|
9
9
|
import { t as DoSubscriptionStore_exports } from "./DoSubscriptionStore.mjs";
|
|
10
10
|
import { t as MemoryProtocol_exports } from "./MemoryProtocol.mjs";
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@effect-agent/storage-cloudflare","version":"0.1.0-beta.
|
|
1
|
+
{"name":"@effect-agent/storage-cloudflare","version":"0.1.0-beta.48","dependencies":{"@effect-agent/core":"0.1.0-beta.48","@effect-agent/thread":"0.1.0-beta.48","@effect/platform-browser":"4.0.0-rc.112","@effect/sql-sqlite-do":"4.0.0-rc.112"},"devDependencies":{"@cloudflare/vitest-pool-workers":"0.21.3","@cloudflare/workers-types":"5.20260825.1","@effect-agent/testing":"0.1.0-beta.48","@effect/vitest":"4.0.0-rc.112","effect":"4.0.0-rc.112","typescript":"7.0.2","vite-plus":"0.3.0","vitest":"4.1.11"},"peerDependencies":{"effect":"^4.0.0-rc.112"},"exports":{".":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"./DoMemoryStore":{"types":"./dist/DoMemoryStore.d.mts","default":"./dist/DoMemoryStore.mjs"},"./DoScheduleStore":{"types":"./dist/DoScheduleStore.d.mts","default":"./dist/DoScheduleStore.mjs"},"./DoStorageConfig":{"types":"./dist/DoStorageConfig.d.mts","default":"./dist/DoStorageConfig.mjs"},"./DoStorageError":{"types":"./dist/DoStorageError.d.mts","default":"./dist/DoStorageError.mjs"},"./DoStorageFailpoint":{"types":"./dist/DoStorageFailpoint.d.mts","default":"./dist/DoStorageFailpoint.mjs"},"./DoStorageVersion":{"types":"./dist/DoStorageVersion.d.mts","default":"./dist/DoStorageVersion.mjs"},"./DoSubmissionLedger":{"types":"./dist/DoSubmissionLedger.d.mts","default":"./dist/DoSubmissionLedger.mjs"},"./DoSubscriptionStore":{"types":"./dist/DoSubscriptionStore.d.mts","default":"./dist/DoSubscriptionStore.mjs"},"./DoThreadStore":{"types":"./dist/DoThreadStore.d.mts","default":"./dist/DoThreadStore.mjs"},"./MemoryProtocol":{"types":"./dist/MemoryProtocol.d.mts","default":"./dist/MemoryProtocol.mjs"},"./PortProtocol":{"types":"./dist/PortProtocol.d.mts","default":"./dist/PortProtocol.mjs"},"./PortRouting":{"types":"./dist/PortRouting.d.mts","default":"./dist/PortRouting.mjs"},"./testing/DoStorageFailpointTesting":{"types":"./dist/DoStorageFailpointTesting.d.mts","default":"./dist/DoStorageFailpointTesting.mjs"}},"description":"Durable Object SQLite storage adapters and the routed port protocol for Effect Agent on Cloudflare.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/danieljvdm/effect-agent.git","directory":"packages/storage-cloudflare"},"files":["dist","src"],"type":"module","sideEffects":[],"publishConfig":{"access":"public"},"scripts":{"build":"vp pack","check":"tsc --noEmit -p tsconfig.json"}}
|
package/src/DoMemoryStore.ts
CHANGED
|
@@ -13,6 +13,8 @@ export class DoMemoryStorageLimits extends Schema.Class<DoMemoryStorageLimits>(
|
|
|
13
13
|
maxStorageBytes: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 536_870_912 })),
|
|
14
14
|
maxDocuments: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 100_000 })),
|
|
15
15
|
maxReceipts: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 1_000_000 })),
|
|
16
|
+
reservedWithdrawalBytes: Schema.optional(Schema.Natural),
|
|
17
|
+
reservedWithdrawalReceipts: Schema.optional(Schema.Natural),
|
|
16
18
|
}) {}
|
|
17
19
|
|
|
18
20
|
export const defaultDoMemoryStorageLimits = DoMemoryStorageLimits.make({
|
|
@@ -26,6 +28,9 @@ export const defaultDoMemoryStorageLimits = DoMemoryStorageLimits.make({
|
|
|
26
28
|
* Local memory only, without Thread tables. Keep one SQL client per owner and pass the
|
|
27
29
|
* full storage handle: sql-only handles cannot provide atomic receipts and revisions.
|
|
28
30
|
* Byte limits conservatively count encoded rows, not SQLite page/index overhead.
|
|
31
|
+
* Optional withdrawal reserves default to zero and stay within hard byte/receipt limits.
|
|
32
|
+
* Ordinary Put cannot consume them. Deploy exclusively upgraded writers before relying
|
|
33
|
+
* on reserves; the SQL accounting migration preserves older writers and their receipts.
|
|
29
34
|
*/
|
|
30
35
|
export const doMemoryStoreLayerWithFailpoints = (
|
|
31
36
|
storage: NonNullable<SqliteClient.SqliteClientConfig["storage"]>,
|
package/src/DoThreadStore.ts
CHANGED
|
@@ -616,11 +616,17 @@ const makeServices = Effect.fn("DoThreadStore.makeServices")(function* () {
|
|
|
616
616
|
});
|
|
617
617
|
|
|
618
618
|
const loadRecords = Effect.fn("DoThreadStore.loadRecords")(function* (request: RawReadRequest) {
|
|
619
|
-
const
|
|
619
|
+
const result = yield* journal
|
|
620
620
|
.read(request)
|
|
621
621
|
.pipe(Effect.mapError((error) => storeError("read canonical records", error)));
|
|
622
622
|
|
|
623
|
-
return
|
|
623
|
+
return {
|
|
624
|
+
count: result.count,
|
|
625
|
+
records: result.records.pipe(
|
|
626
|
+
Stream.mapError((error) => storeError("read canonical records", error)),
|
|
627
|
+
Stream.mapEffect(decodeEnvelope),
|
|
628
|
+
),
|
|
629
|
+
};
|
|
624
630
|
});
|
|
625
631
|
|
|
626
632
|
const readEffect = Effect.fn("DoThreadStore.read")(function* (request: ThreadRead) {
|
|
@@ -630,7 +636,7 @@ const makeServices = Effect.fn("DoThreadStore.makeServices")(function* () {
|
|
|
630
636
|
|
|
631
637
|
yield* requireThread(journal, validated.threadId);
|
|
632
638
|
|
|
633
|
-
const
|
|
639
|
+
const result = yield* loadRecords(
|
|
634
640
|
RawReadRequest.make({
|
|
635
641
|
threadId: validated.threadId,
|
|
636
642
|
fromSequenceExclusive: validated.afterSequence ?? ZERO_CANONICAL_SEQUENCE,
|
|
@@ -638,7 +644,7 @@ const makeServices = Effect.fn("DoThreadStore.makeServices")(function* () {
|
|
|
638
644
|
}),
|
|
639
645
|
);
|
|
640
646
|
|
|
641
|
-
return
|
|
647
|
+
return result.records;
|
|
642
648
|
});
|
|
643
649
|
|
|
644
650
|
const read: ThreadStore["Service"]["read"] = (request) => Stream.unwrap(readEffect(request));
|
|
@@ -655,7 +661,7 @@ const makeServices = Effect.fn("DoThreadStore.makeServices")(function* () {
|
|
|
655
661
|
const poll = Effect.fn("DoThreadStore.observePoll")(function* () {
|
|
656
662
|
const fromSequenceExclusive = yield* Ref.get(cursor);
|
|
657
663
|
|
|
658
|
-
const
|
|
664
|
+
const result = yield* loadRecords(
|
|
659
665
|
RawReadRequest.make({
|
|
660
666
|
threadId: validated.threadId,
|
|
661
667
|
fromSequenceExclusive,
|
|
@@ -663,17 +669,16 @@ const makeServices = Effect.fn("DoThreadStore.makeServices")(function* () {
|
|
|
663
669
|
}),
|
|
664
670
|
);
|
|
665
671
|
|
|
666
|
-
if (
|
|
672
|
+
if (result.count === 0) {
|
|
667
673
|
yield* Effect.sleep(config.observationPollInterval);
|
|
668
674
|
|
|
669
|
-
return
|
|
675
|
+
return Stream.empty;
|
|
670
676
|
}
|
|
671
|
-
yield* Ref.set(cursor, records[records.length - 1].sequence);
|
|
672
677
|
|
|
673
|
-
return records;
|
|
678
|
+
return result.records.pipe(Stream.tap((record) => Ref.set(cursor, record.sequence)));
|
|
674
679
|
});
|
|
675
680
|
|
|
676
|
-
return Stream.
|
|
681
|
+
return Stream.fromEffectRepeat(poll()).pipe(Stream.flatten);
|
|
677
682
|
});
|
|
678
683
|
|
|
679
684
|
const observe: ThreadStore["Service"]["observe"] = (request) =>
|
package/src/MemoryProtocol.ts
CHANGED
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
revalidateSemanticMemoryCandidates,
|
|
29
29
|
} from "@effect-agent/core/SemanticMemoryRevalidation";
|
|
30
30
|
import { Principal } from "@effect-agent/thread/SubmissionLedger";
|
|
31
|
-
import { Clock, Context, Effect,
|
|
31
|
+
import { Clock, Context, Effect, Schema } from "effect";
|
|
32
32
|
|
|
33
33
|
export class MemoryRpcError extends Schema.TaggedError<MemoryRpcError>()("MemoryRpcError", {
|
|
34
34
|
reason: Schema.Literals(["denied", "protocol", "budget", "timeout", "unavailable"]),
|
|
@@ -127,7 +127,7 @@ export class MemoryOwnerIdentity extends Context.Service<
|
|
|
127
127
|
}
|
|
128
128
|
>()("@effect-agent/storage-cloudflare/MemoryOwnerIdentity") {}
|
|
129
129
|
|
|
130
|
-
export const memoryWireBytes = (text: string): number =>
|
|
130
|
+
export const memoryWireBytes = (text: string): number => new TextEncoder().encode(text).byteLength;
|
|
131
131
|
|
|
132
132
|
export const decodeMemoryWire = Effect.fn("decodeMemoryWire")(function* <A, I>(
|
|
133
133
|
schema: Schema.Codec<A, I, never>,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CanonicalSequence, ProducerEpoch } from "@effect-agent/thread/Records";
|
|
2
2
|
import { SqliteMigrator } from "@effect/sql-sqlite-do";
|
|
3
|
-
import { Effect, Schema } from "effect";
|
|
3
|
+
import { Effect, Schema, Stream } from "effect";
|
|
4
4
|
import * as SqlClient from "effect/unstable/sql/SqlClient";
|
|
5
5
|
import { SqlError } from "effect/unstable/sql/SqlError";
|
|
6
6
|
|
|
@@ -27,6 +27,7 @@ const BoundedStoredText = Schema.String.check(Schema.isMaxLength(2_000_000));
|
|
|
27
27
|
const BoundedIdentifier = Schema.NonEmptyString.check(Schema.isMaxLength(1024));
|
|
28
28
|
const MAX_RECORDS_PER_THREAD = 65_536;
|
|
29
29
|
const MAX_IDENTIFIER_LENGTH = 1_024;
|
|
30
|
+
const MAX_READ_PAGE_JSON_BYTES = 4 * 1024 * 1024;
|
|
30
31
|
/** Durable Object SQL storage allows at most 100 bound parameters per statement. */
|
|
31
32
|
const MAX_BOUND_PARAMETERS = 100;
|
|
32
33
|
const isSqlError = Schema.is(SqlError);
|
|
@@ -77,6 +78,13 @@ class RecordRow extends Schema.Class<RecordRow>("RecordRow")({
|
|
|
77
78
|
sequence: CanonicalSequence,
|
|
78
79
|
}) {}
|
|
79
80
|
|
|
81
|
+
const ReadPlanRow = Schema.Struct({
|
|
82
|
+
sequence: CanonicalSequence,
|
|
83
|
+
record_json_bytes: Schema.Natural.check(Schema.isLessThanOrEqualTo(MAX_READ_PAGE_JSON_BYTES)),
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
type ReadPage = [typeof ReadPlanRow.Type, ...Array<typeof ReadPlanRow.Type>];
|
|
87
|
+
|
|
80
88
|
class CheckpointRow extends Schema.Class<CheckpointRow>("CheckpointRow")({
|
|
81
89
|
checkpoint_json: BoundedStoredText,
|
|
82
90
|
thread_id: BoundedIdentifier,
|
|
@@ -134,8 +142,6 @@ export class RawCheckpoint extends Schema.Class<RawCheckpoint>(
|
|
|
134
142
|
export class RawThreadExport extends Schema.Class<RawThreadExport>(
|
|
135
143
|
"@effect-agent/storage-cloudflare/RawThreadExport",
|
|
136
144
|
)({
|
|
137
|
-
batches: Schema.Array(BatchRow),
|
|
138
|
-
checkpoints: Schema.Array(CheckpointRow),
|
|
139
145
|
thread: ThreadRow,
|
|
140
146
|
records: Schema.Array(RecordRow),
|
|
141
147
|
}) {}
|
|
@@ -737,13 +743,12 @@ const makeJournal = (
|
|
|
737
743
|
});
|
|
738
744
|
|
|
739
745
|
const read = Effect.fn("DoJournal.read")(function* (request: RawReadRequest) {
|
|
740
|
-
|
|
746
|
+
// Capture membership without retaining payloads. Append-only sequences keep each later
|
|
747
|
+
// payload query inside this snapshot, even when new records arrive during consumption.
|
|
748
|
+
const planRows = yield* sql<Record<string, unknown>>`
|
|
741
749
|
SELECT
|
|
742
|
-
thread_id,
|
|
743
750
|
sequence,
|
|
744
|
-
|
|
745
|
-
batch_id,
|
|
746
|
-
record_json
|
|
751
|
+
length(CAST(record_json AS BLOB)) AS record_json_bytes
|
|
747
752
|
FROM effect_agent_canonical_records
|
|
748
753
|
WHERE thread_id = ${request.threadId}
|
|
749
754
|
AND sequence > ${request.fromSequenceExclusive}
|
|
@@ -751,12 +756,78 @@ const makeJournal = (
|
|
|
751
756
|
LIMIT ${request.limit}
|
|
752
757
|
`.pipe(Effect.mapError(storageError("read canonical records")));
|
|
753
758
|
|
|
754
|
-
|
|
755
|
-
Schema.Array(
|
|
759
|
+
const plan = yield* decodeRows(
|
|
760
|
+
Schema.Array(ReadPlanRow),
|
|
756
761
|
"effect_agent_canonical_records",
|
|
757
762
|
`${request.threadId}>${request.fromSequenceExclusive}`,
|
|
758
|
-
|
|
763
|
+
planRows,
|
|
759
764
|
);
|
|
765
|
+
|
|
766
|
+
const mismatch = () =>
|
|
767
|
+
DoStorageCorruptionError.make({
|
|
768
|
+
table: "effect_agent_canonical_records",
|
|
769
|
+
rowKey: `${request.threadId}>${request.fromSequenceExclusive}`,
|
|
770
|
+
message: "Canonical read membership, sequence, or payload size changed from its read plan.",
|
|
771
|
+
});
|
|
772
|
+
|
|
773
|
+
if (plan.length > request.limit) return yield* mismatch();
|
|
774
|
+
|
|
775
|
+
const pages: Array<ReadPage> = [];
|
|
776
|
+
let page: ReadPage | undefined;
|
|
777
|
+
let pageBytes = 0;
|
|
778
|
+
let previousSequence = request.fromSequenceExclusive;
|
|
779
|
+
|
|
780
|
+
for (const row of plan) {
|
|
781
|
+
if (row.sequence !== previousSequence + 1) return yield* mismatch();
|
|
782
|
+
previousSequence = row.sequence;
|
|
783
|
+
if (page === undefined || pageBytes + row.record_json_bytes > MAX_READ_PAGE_JSON_BYTES) {
|
|
784
|
+
page = [row];
|
|
785
|
+
pages.push(page);
|
|
786
|
+
pageBytes = row.record_json_bytes;
|
|
787
|
+
} else {
|
|
788
|
+
page.push(row);
|
|
789
|
+
pageBytes += row.record_json_bytes;
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
const readPage = Effect.fn("DoJournal.readPage")(function* (page: ReadPage) {
|
|
794
|
+
const rows = yield* sql<Record<string, unknown>>`
|
|
795
|
+
SELECT thread_id, sequence, record_id, batch_id, record_json
|
|
796
|
+
FROM effect_agent_canonical_records
|
|
797
|
+
WHERE thread_id = ${request.threadId}
|
|
798
|
+
AND sequence >= ${page[0].sequence}
|
|
799
|
+
AND sequence <= ${page[page.length - 1].sequence}
|
|
800
|
+
ORDER BY sequence
|
|
801
|
+
`.pipe(Effect.mapError(storageError("read canonical records")));
|
|
802
|
+
|
|
803
|
+
const decoded = yield* decodeRows(
|
|
804
|
+
Schema.Array(RecordRow),
|
|
805
|
+
"effect_agent_canonical_records",
|
|
806
|
+
`${request.threadId}/${page[0].sequence}`,
|
|
807
|
+
rows,
|
|
808
|
+
);
|
|
809
|
+
|
|
810
|
+
if (
|
|
811
|
+
decoded.length !== page.length ||
|
|
812
|
+
decoded.some(
|
|
813
|
+
(row, index) =>
|
|
814
|
+
row.thread_id !== request.threadId ||
|
|
815
|
+
row.sequence !== page[index].sequence ||
|
|
816
|
+
storedTextBytes(row.record_json) !== page[index].record_json_bytes,
|
|
817
|
+
)
|
|
818
|
+
) {
|
|
819
|
+
return yield* mismatch();
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
return decoded;
|
|
823
|
+
});
|
|
824
|
+
|
|
825
|
+
return {
|
|
826
|
+
count: plan.length,
|
|
827
|
+
records: Stream.fromIterable(pages).pipe(
|
|
828
|
+
Stream.flatMap((page) => Stream.fromIterableEffect(readPage(page))),
|
|
829
|
+
),
|
|
830
|
+
};
|
|
760
831
|
});
|
|
761
832
|
|
|
762
833
|
const exportThread = Effect.fn("DoJournal.exportThread")(function* (threadId: string) {
|
|
@@ -783,20 +854,6 @@ const makeJournal = (
|
|
|
783
854
|
|
|
784
855
|
yield* failpoint("export:after-thread-read");
|
|
785
856
|
|
|
786
|
-
const batchRows = yield* sql<Record<string, unknown>>`
|
|
787
|
-
SELECT
|
|
788
|
-
thread_id,
|
|
789
|
-
batch_id,
|
|
790
|
-
first_sequence,
|
|
791
|
-
last_sequence,
|
|
792
|
-
batch_digest,
|
|
793
|
-
tail_digest,
|
|
794
|
-
batch_json
|
|
795
|
-
FROM effect_agent_canonical_batches
|
|
796
|
-
WHERE thread_id = ${threadId}
|
|
797
|
-
ORDER BY first_sequence
|
|
798
|
-
`.pipe(Effect.mapError(storageError("export canonical batches")));
|
|
799
|
-
|
|
800
857
|
const recordRows = yield* sql<Record<string, unknown>>`
|
|
801
858
|
SELECT
|
|
802
859
|
thread_id,
|
|
@@ -809,37 +866,14 @@ const makeJournal = (
|
|
|
809
866
|
ORDER BY sequence
|
|
810
867
|
`.pipe(Effect.mapError(storageError("export canonical records")));
|
|
811
868
|
|
|
812
|
-
const checkpointRows = yield* sql<Record<string, unknown>>`
|
|
813
|
-
SELECT
|
|
814
|
-
thread_id,
|
|
815
|
-
through_sequence,
|
|
816
|
-
tail_digest,
|
|
817
|
-
checkpoint_json
|
|
818
|
-
FROM effect_agent_checkpoints
|
|
819
|
-
WHERE thread_id = ${threadId}
|
|
820
|
-
ORDER BY through_sequence
|
|
821
|
-
`.pipe(Effect.mapError(storageError("export checkpoints")));
|
|
822
|
-
|
|
823
869
|
return RawThreadExport.make({
|
|
824
870
|
thread,
|
|
825
|
-
batches: yield* decodeRows(
|
|
826
|
-
Schema.Array(BatchRow),
|
|
827
|
-
"effect_agent_canonical_batches",
|
|
828
|
-
threadId,
|
|
829
|
-
batchRows,
|
|
830
|
-
),
|
|
831
871
|
records: yield* decodeRows(
|
|
832
872
|
Schema.Array(RecordRow),
|
|
833
873
|
"effect_agent_canonical_records",
|
|
834
874
|
threadId,
|
|
835
875
|
recordRows,
|
|
836
876
|
),
|
|
837
|
-
checkpoints: yield* decodeRows(
|
|
838
|
-
Schema.Array(CheckpointRow),
|
|
839
|
-
"effect_agent_checkpoints",
|
|
840
|
-
threadId,
|
|
841
|
-
checkpointRows,
|
|
842
|
-
),
|
|
843
877
|
});
|
|
844
878
|
}),
|
|
845
879
|
)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DoThreadStore-D9ebIYPv.mjs","names":["SqlClientService"],"sources":["../src/internal/do-journal.ts","../src/DoThreadStore.ts"],"sourcesContent":["import { CanonicalSequence, ProducerEpoch } from \"@effect-agent/thread/Records\";\nimport { SqliteMigrator } from \"@effect/sql-sqlite-do\";\nimport { Effect, Schema } from \"effect\";\nimport * as SqlClient from \"effect/unstable/sql/SqlClient\";\nimport { SqlError } from \"effect/unstable/sql/SqlError\";\n\nimport {\n type DoStorageFailpointError,\n DoAppendConflict,\n DoCheckpointConflict,\n DoFenceRejected,\n DoStorageCompatibilityError,\n DoStorageCorruptionError,\n DoStorageError,\n DoValueBoundExceeded,\n type DoStorageFailpointLocation,\n} from \"../DoStorageError.ts\";\nimport { CurrentDoStorageVersion, doMigrations } from \"./migrations.ts\";\n\n/**\n * Static schema ceiling for stored text columns. Writes are bounded in BYTES by the\n * configured `maxStoredValueBytes` (always ≤ 2,000,000); UTF-8 byte length is never smaller\n * than UTF-16 string length, so any value that passed the byte bound also passes this\n * decode-side character ceiling.\n */\nconst BoundedStoredText = Schema.String.check(Schema.isMaxLength(2_000_000));\nconst BoundedIdentifier = Schema.NonEmptyString.check(Schema.isMaxLength(1024));\nconst MAX_RECORDS_PER_THREAD = 65_536;\nconst MAX_IDENTIFIER_LENGTH = 1_024;\n/** Durable Object SQL storage allows at most 100 bound parameters per statement. */\nconst MAX_BOUND_PARAMETERS = 100;\nconst isSqlError = Schema.is(SqlError);\n\nconst storedTextBytes = (value: string): number => new TextEncoder().encode(value).byteLength;\n\nconst chunked = <A>(values: ReadonlyArray<A>, size: number): Array<ReadonlyArray<A>> => {\n const chunks: Array<ReadonlyArray<A>> = [];\n\n for (let index = 0; index < values.length; index += size) {\n chunks.push(values.slice(index, index + size));\n }\n\n return chunks;\n};\n\nclass DoMetaRow extends Schema.Class<DoMetaRow>(\"DoMetaRow\")({\n value: Schema.NonEmptyString.check(Schema.isMaxLength(128)),\n}) {}\n\nclass DoNameRow extends Schema.Class<DoNameRow>(\"DoNameRow\")({\n name: BoundedIdentifier,\n}) {}\n\nclass ThreadRow extends Schema.Class<ThreadRow>(\"ThreadRow\")({\n thread_id: BoundedIdentifier,\n created_at: Schema.NonEmptyString.check(Schema.isMaxLength(128)),\n producer_epoch: ProducerEpoch,\n tail_digest: BoundedStoredText,\n tail_sequence: CanonicalSequence,\n}) {}\n\nclass BatchRow extends Schema.Class<BatchRow>(\"BatchRow\")({\n batch_digest: BoundedStoredText,\n batch_id: BoundedIdentifier,\n batch_json: BoundedStoredText,\n thread_id: BoundedIdentifier,\n first_sequence: CanonicalSequence,\n last_sequence: CanonicalSequence,\n tail_digest: BoundedStoredText,\n}) {}\n\nclass RecordRow extends Schema.Class<RecordRow>(\"RecordRow\")({\n batch_id: BoundedIdentifier,\n thread_id: BoundedIdentifier,\n record_id: BoundedIdentifier,\n record_json: BoundedStoredText,\n sequence: CanonicalSequence,\n}) {}\n\nclass CheckpointRow extends Schema.Class<CheckpointRow>(\"CheckpointRow\")({\n checkpoint_json: BoundedStoredText,\n thread_id: BoundedIdentifier,\n tail_digest: BoundedStoredText,\n through_sequence: CanonicalSequence,\n}) {}\n\nexport class RawRecord extends Schema.Class<RawRecord>(\n \"@effect-agent/storage-cloudflare/RawRecord\",\n)({\n recordId: BoundedIdentifier,\n recordJson: BoundedStoredText,\n}) {}\n\nexport class RawAppendRequest extends Schema.Class<RawAppendRequest>(\n \"@effect-agent/storage-cloudflare/RawAppendRequest\",\n)({\n batchDigest: BoundedStoredText,\n batchId: BoundedIdentifier,\n batchJson: BoundedStoredText,\n threadId: BoundedIdentifier,\n expectedTailDigest: BoundedStoredText,\n expectedTailSequence: CanonicalSequence,\n producerEpoch: ProducerEpoch,\n records: Schema.NonEmptyArray(RawRecord).check(Schema.isMaxLength(256)),\n tailDigest: BoundedStoredText,\n}) {}\n\nexport class RawAppendResult extends Schema.Class<RawAppendResult>(\n \"@effect-agent/storage-cloudflare/RawAppendResult\",\n)({\n firstSequence: CanonicalSequence,\n lastSequence: CanonicalSequence,\n replayed: Schema.Boolean,\n tailDigest: BoundedStoredText,\n}) {}\n\nexport class RawReadRequest extends Schema.Class<RawReadRequest>(\n \"@effect-agent/storage-cloudflare/RawReadRequest\",\n)({\n threadId: BoundedIdentifier,\n fromSequenceExclusive: CanonicalSequence,\n limit: Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(1_024)),\n}) {}\n\nexport class RawCheckpoint extends Schema.Class<RawCheckpoint>(\n \"@effect-agent/storage-cloudflare/RawCheckpoint\",\n)({\n checkpointJson: BoundedStoredText,\n threadId: BoundedIdentifier,\n tailDigest: BoundedStoredText,\n throughSequence: CanonicalSequence,\n}) {}\n\nexport class RawThreadExport extends Schema.Class<RawThreadExport>(\n \"@effect-agent/storage-cloudflare/RawThreadExport\",\n)({\n batches: Schema.Array(BatchRow),\n checkpoints: Schema.Array(CheckpointRow),\n thread: ThreadRow,\n records: Schema.Array(RecordRow),\n}) {}\n\ntype AppendError =\n | DoAppendConflict\n | DoFenceRejected\n | DoStorageCorruptionError\n | DoStorageError\n | DoStorageFailpointError\n | DoValueBoundExceeded;\n\ntype CheckpointError =\n | DoCheckpointConflict\n | DoStorageCorruptionError\n | DoStorageError\n | DoValueBoundExceeded;\n\ntype DoJournalFailpoint = (\n location: DoStorageFailpointLocation,\n) => Effect.Effect<void, DoStorageFailpointError>;\n\nconst noFailpoint: DoJournalFailpoint = () => Effect.void;\n\nconst storageError =\n (operation: string) =>\n (error: SqlError): DoStorageError =>\n DoStorageError.make({\n cause: error,\n operation,\n message: error.message,\n });\n\n/** Decode raw Durable Object SQLite rows against a Schema, reporting failures as typed corruption. */\nexport const decodeRows = Effect.fn(\n <A, I>(\n schema: Schema.Codec<ReadonlyArray<A>, ReadonlyArray<I>>,\n table: string,\n rowKey: string,\n rows: unknown,\n ): Effect.Effect<ReadonlyArray<A>, DoStorageCorruptionError> =>\n Schema.decodeUnknownEffect(schema)(rows).pipe(\n Effect.mapError((error) =>\n DoStorageCorruptionError.make({\n table,\n rowKey,\n message: String(error),\n }),\n ),\n ),\n);\n\n/** Decode exactly one raw row against a Schema, reporting failures as typed corruption. */\nexport const decodeSingleRow = Effect.fn(\n <A, I>(\n schema: Schema.Codec<ReadonlyArray<A>, ReadonlyArray<I>>,\n table: string,\n rowKey: string,\n rows: unknown,\n ): Effect.Effect<A, DoStorageCorruptionError> =>\n decodeRows(schema, table, rowKey, rows).pipe(\n Effect.flatMap((decoded) =>\n decoded.length === 1\n ? Effect.succeed(decoded[0])\n : Effect.fail(\n DoStorageCorruptionError.make({\n table,\n rowKey,\n message: `Expected exactly one row but found ${decoded.length}.`,\n }),\n ),\n ),\n ),\n);\n\nconst REQUIRED_TABLES = [\n \"effect_agent_abort_intents\",\n \"effect_agent_approval_decisions\",\n \"effect_agent_attempts\",\n \"effect_agent_canonical_batches\",\n \"effect_agent_canonical_records\",\n \"effect_agent_checkpoints\",\n \"effect_agent_child_reservations\",\n \"effect_agent_child_settlements\",\n \"effect_agent_threads\",\n \"effect_agent_meta\",\n \"effect_agent_settlement_reservations\",\n \"effect_agent_submission_ownership\",\n \"effect_agent_submissions\",\n \"effect_agent_unknown_resolutions\",\n] as const;\n\n/**\n * Exact-or-fresh storage gate (DEPLOY-008) over `effect_agent_meta` instead of\n * `PRAGMA user_version` (unverified on Durable Object SQL storage; a meta table is portable\n * regardless). No WAL check (Durable Object storage owns durability and confirms writes\n * through output gates) and no busy timeout (a Durable Object has exactly one writer): the\n * Node machinery those served has no DC analogue and is deliberately absent.\n */\nconst ensureCurrentStorage = Effect.fn(\"DoJournal.ensureCurrentStorage\")(function* (\n sql: SqlClient.SqlClient,\n failpoint: DoJournalFailpoint = noFailpoint,\n maxStoredValueBytes: number,\n) {\n const metaTableRows = yield* sql<Record<string, unknown>>`\n SELECT name\n FROM sqlite_master\n WHERE type = 'table'\n AND name = 'effect_agent_meta'\n `.pipe(Effect.mapError(storageError(\"read storage version table\")));\n\n const metaTables = yield* decodeRows(\n Schema.Array(DoNameRow),\n \"sqlite_master\",\n \"effect_agent_meta\",\n metaTableRows,\n );\n\n if (metaTables.length === 0) {\n const existingRows = yield* sql<Record<string, unknown>>`\n SELECT name\n FROM sqlite_master\n WHERE type = 'table'\n AND name LIKE 'effect_agent_%'\n ORDER BY name\n `.pipe(Effect.mapError(storageError(\"inspect unversioned storage\")));\n\n const existing = yield* decodeRows(\n Schema.Array(DoNameRow),\n \"sqlite_master\",\n \"effect_agent_%\",\n existingRows,\n );\n\n if (existing.length > 0) {\n return yield* DoStorageCompatibilityError.make({\n actualVersion: 0,\n supportedVersion: CurrentDoStorageVersion,\n message:\n \"The Durable Object contains unversioned Effect Agent tables. Reset the development namespace explicitly; refusing to mutate ambiguous stored data.\",\n });\n }\n\n yield* SqliteMigrator.run({ loader: doMigrations }).pipe(\n // SqliteMigrator depends on the generic client supplied by this adapter. The concrete\n // Durable Object client is kept at the outer Layer boundary.\n Effect.provideService(SqlClient.SqlClient, sql),\n Effect.mapError((error) =>\n DoStorageError.make({\n cause: error,\n operation: \"initialize current storage\",\n message: error.message,\n }),\n ),\n );\n } else {\n const versionRows = yield* sql<Record<string, unknown>>`\n SELECT value\n FROM effect_agent_meta\n WHERE key = 'storage_version'\n `.pipe(Effect.mapError(storageError(\"read storage version\")));\n\n const version = yield* decodeSingleRow(\n Schema.Array(DoMetaRow),\n \"effect_agent_meta\",\n \"storage_version\",\n versionRows,\n );\n\n // The storage version must match EXACTLY. Older private-development versions fail\n // closed with reset guidance rather than being migrated, and newer versions fail closed\n // rather than being decoded incorrectly (DEPLOY-008).\n if (version.value !== String(CurrentDoStorageVersion)) {\n const actualVersion = Number.parseInt(version.value, 10);\n\n return yield* DoStorageCompatibilityError.make({\n actualVersion: Number.isSafeInteger(actualVersion) ? actualVersion : -1,\n supportedVersion: CurrentDoStorageVersion,\n message:\n `The Durable Object uses private-development storage version ${version.value}; ` +\n `this build supports exactly version ${CurrentDoStorageVersion}. ` +\n \"Replace the development namespace explicitly; automatic stored-data migrations are not provided during private development.\",\n });\n }\n }\n\n const requiredRows = yield* sql<Record<string, unknown>>`\n SELECT name\n FROM sqlite_master\n WHERE type = 'table'\n AND name IN ${sql.in([...REQUIRED_TABLES])}\n ORDER BY name\n `.pipe(Effect.mapError(storageError(\"verify storage tables\")));\n\n const required = yield* decodeRows(\n Schema.Array(DoNameRow),\n \"sqlite_master\",\n \"required_tables\",\n requiredRows,\n );\n\n if (required.length !== REQUIRED_TABLES.length) {\n return yield* DoStorageCompatibilityError.make({\n actualVersion: CurrentDoStorageVersion,\n supportedVersion: CurrentDoStorageVersion,\n message:\n \"The Durable Object claims the current format but is missing required tables. Reset the corrupt private-development data.\",\n });\n }\n\n return makeJournal(sql, failpoint, maxStoredValueBytes);\n});\n\nconst makeJournal = (\n sql: SqlClient.SqlClient,\n failpoint: DoJournalFailpoint,\n maxStoredValueBytes: number,\n) => {\n /** Typed pre-write refusal for any single value over the configured byte bound. */\n const checkValueBound = (\n operation: string,\n value: string,\n ): Effect.Effect<void, DoValueBoundExceeded> => {\n const actualBytes = storedTextBytes(value);\n\n return actualBytes > maxStoredValueBytes\n ? Effect.fail(\n DoValueBoundExceeded.make({\n actualBytes,\n maxBytes: maxStoredValueBytes,\n operation,\n }),\n )\n : Effect.void;\n };\n\n /**\n * Runs one journal write transaction on the Durable Object storage-backed\n * `withTransaction` (`ctx.storage.transaction()` under the hood). Within one Durable\n * Object there is exactly ONE writer, so the Node `BEGIN IMMEDIATE` + busy-retry +\n * `SqliteWriteContention` machinery has no analogue here and is deliberately absent.\n * Ownership-token and epoch checks still run INSIDE the transaction, so fencing atomicity\n * (DUR-006) is preserved identically.\n *\n * Journal write transactions are always top level: the Durable Object client rejects\n * nested transactions, so new journal operations must not wrap this helper inside another\n * transaction.\n */\n const withWriteTransaction =\n (operation: string) =>\n <A, E>(effect: Effect.Effect<A, E>): Effect.Effect<A, E | DoStorageError> =>\n sql.withTransaction(effect).pipe(\n Effect.mapError((error) => (isSqlError(error) ? storageError(operation)(error) : error)),\n Effect.withSpan(\"DoJournal.withWriteTransaction\", { attributes: { operation } }),\n );\n\n const materialize = Effect.fn(\"DoJournal.materialize\")(function* (\n threadId: string,\n createdAt: string,\n emptyTailDigest: string,\n producerEpoch: ProducerEpoch,\n ): Effect.fn.Return<\n void,\n DoFenceRejected | DoStorageCorruptionError | DoStorageError | DoValueBoundExceeded\n > {\n if (threadId.length > MAX_IDENTIFIER_LENGTH) {\n return yield* DoStorageError.make({\n operation: \"materialize thread\",\n message: \"Thread identity exceeds the Durable Object storage bounds.\",\n });\n }\n yield* checkValueBound(\"materialize thread\", emptyTailDigest);\n yield* withWriteTransaction(\"materialize transaction\")(\n Effect.gen(function* () {\n const existingRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n FROM effect_agent_threads\n WHERE thread_id = ${threadId}\n `.pipe(Effect.mapError(storageError(\"read materialized thread\")));\n\n const existing = yield* decodeRows(\n Schema.Array(ThreadRow),\n \"effect_agent_threads\",\n threadId,\n existingRows,\n );\n\n if (existing.length > 1) {\n return yield* DoStorageCorruptionError.make({\n table: \"effect_agent_threads\",\n rowKey: threadId,\n message: \"A thread primary key returned more than one row.\",\n });\n }\n if (existing.length === 0) {\n yield* sql`\n INSERT INTO effect_agent_threads (\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n ) VALUES (\n ${threadId},\n ${createdAt},\n 0,\n ${emptyTailDigest},\n ${producerEpoch}\n )\n `.pipe(Effect.mapError(storageError(\"materialize thread\")));\n\n return;\n }\n if (producerEpoch < existing[0].producer_epoch) {\n return yield* DoFenceRejected.make({\n producerEpoch,\n actualEpoch: existing[0].producer_epoch,\n message: `Producer epoch ${producerEpoch} is stale; current epoch is ${existing[0].producer_epoch}.`,\n });\n }\n if (producerEpoch > existing[0].producer_epoch) {\n yield* sql`\n UPDATE effect_agent_threads\n SET producer_epoch = ${producerEpoch}\n WHERE thread_id = ${threadId}\n `.pipe(Effect.mapError(storageError(\"advance materialization epoch\")));\n }\n }),\n );\n });\n\n const getThread = Effect.fn(\"DoJournal.getThread\")(function* (threadId: string) {\n const rows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n FROM effect_agent_threads\n WHERE thread_id = ${threadId}\n `.pipe(Effect.mapError(storageError(\"read thread\")));\n\n return yield* decodeRows(Schema.Array(ThreadRow), \"effect_agent_threads\", threadId, rows);\n });\n\n const append = Effect.fn(\"DoJournal.append\")(function* (\n request: RawAppendRequest,\n ): Effect.fn.Return<RawAppendResult, AppendError> {\n if (\n request.threadId.length > MAX_IDENTIFIER_LENGTH ||\n request.batchId.length > MAX_IDENTIFIER_LENGTH ||\n request.records.some((record) => record.recordId.length > MAX_IDENTIFIER_LENGTH)\n ) {\n return yield* DoStorageError.make({\n operation: \"append canonical batch\",\n message: \"Canonical identifiers exceed the Durable Object storage bounds.\",\n });\n }\n // The platform's ~2 MB per-value limit, enforced typed BEFORE any write (plan §1.2).\n yield* checkValueBound(\"append canonical batch\", request.batchJson);\n yield* checkValueBound(\"append canonical batch\", request.batchDigest);\n yield* checkValueBound(\"append canonical batch\", request.tailDigest);\n yield* Effect.forEach(\n request.records,\n (record) => checkValueBound(\"append canonical record\", record.recordJson),\n { discard: true },\n );\n\n return yield* withWriteTransaction(\"append transaction\")(\n Effect.gen(function* () {\n const recordIds = request.records.map((record) => record.recordId);\n\n if (new Set(recordIds).size !== recordIds.length) {\n return yield* DoAppendConflict.make({\n message: `Batch ${request.batchId} contains duplicate canonical record IDs.`,\n reason: \"record-identity\",\n });\n }\n\n const threadRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n FROM effect_agent_threads\n WHERE thread_id = ${request.threadId}\n `.pipe(Effect.mapError(storageError(\"read append tail\")));\n\n const thread = yield* decodeSingleRow(\n Schema.Array(ThreadRow),\n \"effect_agent_threads\",\n request.threadId,\n threadRows,\n );\n\n if (request.producerEpoch !== thread.producer_epoch) {\n return yield* DoFenceRejected.make({\n producerEpoch: request.producerEpoch,\n actualEpoch: thread.producer_epoch,\n message: `Producer epoch ${request.producerEpoch} is not the current epoch ${thread.producer_epoch}.`,\n });\n }\n\n const batchRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n batch_id,\n first_sequence,\n last_sequence,\n batch_digest,\n tail_digest,\n batch_json\n FROM effect_agent_canonical_batches\n WHERE thread_id = ${request.threadId}\n AND batch_id = ${request.batchId}\n `.pipe(Effect.mapError(storageError(\"read idempotent batch\")));\n\n const batches = yield* decodeRows(\n Schema.Array(BatchRow),\n \"effect_agent_canonical_batches\",\n `${request.threadId}/${request.batchId}`,\n batchRows,\n );\n\n if (batches.length > 1) {\n return yield* DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_batches\",\n rowKey: `${request.threadId}/${request.batchId}`,\n message: \"A canonical batch primary key returned more than one row.\",\n });\n }\n if (batches.length === 1) {\n const existing = batches[0];\n\n if (existing.batch_digest !== request.batchDigest) {\n return yield* DoAppendConflict.make({\n message: `Batch ${request.batchId} already exists with different canonical content.`,\n reason: \"batch-digest\",\n });\n }\n\n return RawAppendResult.make({\n firstSequence: existing.first_sequence,\n lastSequence: existing.last_sequence,\n replayed: true,\n tailDigest: existing.tail_digest,\n });\n }\n\n if (\n request.expectedTailSequence !== thread.tail_sequence ||\n request.expectedTailDigest !== thread.tail_digest\n ) {\n return yield* DoAppendConflict.make({\n message:\n `Expected tail ${request.expectedTailSequence}/${request.expectedTailDigest} ` +\n `but found ${thread.tail_sequence}/${thread.tail_digest}.`,\n reason: \"tail\",\n actualTailSequence: thread.tail_sequence,\n actualTailDigest: thread.tail_digest,\n });\n }\n if (thread.tail_sequence + request.records.length > MAX_RECORDS_PER_THREAD) {\n return yield* DoStorageError.make({\n operation: \"append canonical batch\",\n message: `Thread record limit ${MAX_RECORDS_PER_THREAD} would be exceeded.`,\n });\n }\n\n // Chunked to respect the Durable Object platform's 100-bound-parameter statement\n // limit: a batch may carry up to 256 records.\n const existingRecords: Array<RecordRow> = [];\n\n for (const chunk of chunked(recordIds, MAX_BOUND_PARAMETERS - 10)) {\n const existingRecordRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n sequence,\n record_id,\n batch_id,\n record_json\n FROM effect_agent_canonical_records\n WHERE thread_id = ${request.threadId}\n AND record_id IN ${sql.in([...chunk])}\n ORDER BY sequence\n `.pipe(Effect.mapError(storageError(\"check canonical record identities\")));\n\n existingRecords.push(\n ...(yield* decodeRows(\n Schema.Array(RecordRow),\n \"effect_agent_canonical_records\",\n `${request.threadId}/record_ids`,\n existingRecordRows,\n )),\n );\n }\n if (existingRecords.length > 0) {\n return yield* DoAppendConflict.make({\n message: `Canonical record ID ${existingRecords[0].record_id} already exists.`,\n reason: \"record-identity\",\n });\n }\n\n const firstSequence = yield* Schema.decodeUnknownEffect(CanonicalSequence)(\n thread.tail_sequence + 1,\n ).pipe(\n Effect.mapError((error) =>\n DoStorageError.make({\n cause: error,\n operation: \"append canonical batch\",\n message: error.message,\n }),\n ),\n );\n\n const lastSequence = yield* Schema.decodeUnknownEffect(CanonicalSequence)(\n firstSequence + request.records.length - 1,\n ).pipe(\n Effect.mapError((error) =>\n DoStorageError.make({\n cause: error,\n operation: \"append canonical batch\",\n message: error.message,\n }),\n ),\n );\n\n yield* sql`\n INSERT INTO effect_agent_canonical_batches (\n thread_id,\n batch_id,\n first_sequence,\n last_sequence,\n batch_digest,\n tail_digest,\n batch_json\n ) VALUES (\n ${request.threadId},\n ${request.batchId},\n ${firstSequence},\n ${lastSequence},\n ${request.batchDigest},\n ${request.tailDigest},\n ${request.batchJson}\n )\n `.pipe(Effect.mapError(storageError(\"insert canonical batch\")));\n yield* failpoint(\"append:after-batch-insert\");\n\n yield* Effect.forEach(\n request.records,\n (record, index) =>\n Effect.gen(function* () {\n yield* sql`\n INSERT INTO effect_agent_canonical_records (\n thread_id,\n sequence,\n record_id,\n batch_id,\n record_json\n ) VALUES (\n ${request.threadId},\n ${firstSequence + index},\n ${record.recordId},\n ${request.batchId},\n ${record.recordJson}\n )\n `.pipe(Effect.mapError(storageError(\"insert canonical record\")));\n yield* failpoint(\"append:after-record-insert\");\n }),\n { discard: true },\n );\n\n yield* sql`\n UPDATE effect_agent_threads\n SET\n tail_sequence = ${lastSequence},\n tail_digest = ${request.tailDigest},\n producer_epoch = ${request.producerEpoch}\n WHERE thread_id = ${request.threadId}\n `.pipe(Effect.mapError(storageError(\"advance thread tail\")));\n yield* failpoint(\"append:after-tail-update\");\n\n return RawAppendResult.make({\n firstSequence,\n lastSequence,\n replayed: false,\n tailDigest: request.tailDigest,\n });\n }),\n );\n });\n\n const read = Effect.fn(\"DoJournal.read\")(function* (request: RawReadRequest) {\n const rows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n sequence,\n record_id,\n batch_id,\n record_json\n FROM effect_agent_canonical_records\n WHERE thread_id = ${request.threadId}\n AND sequence > ${request.fromSequenceExclusive}\n ORDER BY sequence\n LIMIT ${request.limit}\n `.pipe(Effect.mapError(storageError(\"read canonical records\")));\n\n return yield* decodeRows(\n Schema.Array(RecordRow),\n \"effect_agent_canonical_records\",\n `${request.threadId}>${request.fromSequenceExclusive}`,\n rows,\n );\n });\n\n const exportThread = Effect.fn(\"DoJournal.exportThread\")(function* (threadId: string) {\n return yield* sql\n .withTransaction(\n Effect.gen(function* () {\n const threadRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n FROM effect_agent_threads\n WHERE thread_id = ${threadId}\n `.pipe(Effect.mapError(storageError(\"export thread\")));\n\n const thread = yield* decodeSingleRow(\n Schema.Array(ThreadRow),\n \"effect_agent_threads\",\n threadId,\n threadRows,\n );\n\n yield* failpoint(\"export:after-thread-read\");\n\n const batchRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n batch_id,\n first_sequence,\n last_sequence,\n batch_digest,\n tail_digest,\n batch_json\n FROM effect_agent_canonical_batches\n WHERE thread_id = ${threadId}\n ORDER BY first_sequence\n `.pipe(Effect.mapError(storageError(\"export canonical batches\")));\n\n const recordRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n sequence,\n record_id,\n batch_id,\n record_json\n FROM effect_agent_canonical_records\n WHERE thread_id = ${threadId}\n ORDER BY sequence\n `.pipe(Effect.mapError(storageError(\"export canonical records\")));\n\n const checkpointRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n through_sequence,\n tail_digest,\n checkpoint_json\n FROM effect_agent_checkpoints\n WHERE thread_id = ${threadId}\n ORDER BY through_sequence\n `.pipe(Effect.mapError(storageError(\"export checkpoints\")));\n\n return RawThreadExport.make({\n thread,\n batches: yield* decodeRows(\n Schema.Array(BatchRow),\n \"effect_agent_canonical_batches\",\n threadId,\n batchRows,\n ),\n records: yield* decodeRows(\n Schema.Array(RecordRow),\n \"effect_agent_canonical_records\",\n threadId,\n recordRows,\n ),\n checkpoints: yield* decodeRows(\n Schema.Array(CheckpointRow),\n \"effect_agent_checkpoints\",\n threadId,\n checkpointRows,\n ),\n });\n }),\n )\n .pipe(\n Effect.catchTag(\"SqlError\", (error) =>\n Effect.fail(storageError(\"export transaction\")(error)),\n ),\n );\n });\n\n const saveCheckpoint = Effect.fn(\"DoJournal.saveCheckpoint\")(function* (\n checkpoint: RawCheckpoint,\n ): Effect.fn.Return<void, CheckpointError> {\n if (checkpoint.threadId.length > MAX_IDENTIFIER_LENGTH) {\n return yield* DoStorageError.make({\n operation: \"save checkpoint\",\n message: \"Checkpoint identity exceeds the Durable Object storage bounds.\",\n });\n }\n yield* checkValueBound(\"save checkpoint\", checkpoint.checkpointJson);\n yield* withWriteTransaction(\"checkpoint transaction\")(\n Effect.gen(function* () {\n const threadRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n FROM effect_agent_threads\n WHERE thread_id = ${checkpoint.threadId}\n `.pipe(Effect.mapError(storageError(\"read checkpoint tail\")));\n\n const thread = yield* decodeSingleRow(\n Schema.Array(ThreadRow),\n \"effect_agent_threads\",\n checkpoint.threadId,\n threadRows,\n );\n\n if (checkpoint.throughSequence > thread.tail_sequence) {\n return yield* DoCheckpointConflict.make({\n message:\n `Checkpoint sequence ${checkpoint.throughSequence} is after canonical tail ` +\n `${thread.tail_sequence}.`,\n });\n }\n\n const checkpointRows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n through_sequence,\n tail_digest,\n checkpoint_json\n FROM effect_agent_checkpoints\n WHERE thread_id = ${checkpoint.threadId}\n AND through_sequence = ${checkpoint.throughSequence}\n `.pipe(Effect.mapError(storageError(\"read idempotent checkpoint\")));\n\n const existing = yield* decodeRows(\n Schema.Array(CheckpointRow),\n \"effect_agent_checkpoints\",\n `${checkpoint.threadId}/${checkpoint.throughSequence}`,\n checkpointRows,\n );\n\n if (existing.length > 1) {\n return yield* DoStorageCorruptionError.make({\n table: \"effect_agent_checkpoints\",\n rowKey: `${checkpoint.threadId}/${checkpoint.throughSequence}`,\n message: \"A checkpoint primary key returned more than one row.\",\n });\n }\n if (existing.length === 1) {\n if (\n existing[0].tail_digest !== checkpoint.tailDigest ||\n existing[0].checkpoint_json !== checkpoint.checkpointJson\n ) {\n return yield* DoCheckpointConflict.make({\n message: \"A different checkpoint already exists at this canonical sequence.\",\n });\n }\n\n return;\n }\n\n yield* sql`\n INSERT INTO effect_agent_checkpoints (\n thread_id,\n through_sequence,\n tail_digest,\n checkpoint_json\n ) VALUES (\n ${checkpoint.threadId},\n ${checkpoint.throughSequence},\n ${checkpoint.tailDigest},\n ${checkpoint.checkpointJson}\n )\n `.pipe(Effect.mapError(storageError(\"insert checkpoint\")));\n }),\n );\n });\n\n const loadCheckpoint = Effect.fn(\"DoJournal.loadCheckpoint\")(function* (\n threadId: string,\n atOrBeforeSequence: CanonicalSequence,\n ) {\n const rows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n through_sequence,\n tail_digest,\n checkpoint_json\n FROM effect_agent_checkpoints\n WHERE thread_id = ${threadId}\n AND through_sequence <= ${atOrBeforeSequence}\n ORDER BY through_sequence DESC\n LIMIT 1\n `.pipe(Effect.mapError(storageError(\"load checkpoint\")));\n\n return yield* decodeRows(\n Schema.Array(CheckpointRow),\n \"effect_agent_checkpoints\",\n `${threadId}<=${atOrBeforeSequence}`,\n rows,\n );\n });\n\n const getTailDigestAt = Effect.fn(\"DoJournal.getTailDigestAt\")(function* (\n threadId: string,\n sequence: CanonicalSequence,\n ) {\n if (sequence === 0) {\n const threads = yield* getThread(threadId);\n\n return threads.length === 0\n ? []\n : [threads[0].tail_sequence === 0 ? threads[0].tail_digest : undefined].filter(\n (value): value is string => value !== undefined,\n );\n }\n\n const rows = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n batch_id,\n first_sequence,\n last_sequence,\n batch_digest,\n tail_digest,\n batch_json\n FROM effect_agent_canonical_batches\n WHERE thread_id = ${threadId}\n AND last_sequence = ${sequence}\n `.pipe(Effect.mapError(storageError(\"read canonical digest at sequence\")));\n\n const batches = yield* decodeRows(\n Schema.Array(BatchRow),\n \"effect_agent_canonical_batches\",\n `${threadId}/${sequence}`,\n rows,\n );\n\n return batches.map((batch) => batch.tail_digest);\n });\n\n const scanStoredPayloads = Effect.fn(\"DoJournal.scanStoredPayloads\")(function* () {\n return yield* sql\n .withTransaction(\n Effect.gen(function* () {\n const threads = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n created_at,\n tail_sequence,\n tail_digest,\n producer_epoch\n FROM effect_agent_threads\n ORDER BY thread_id\n `.pipe(Effect.mapError(storageError(\"scan threads\")));\n\n const batches = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n batch_id,\n first_sequence,\n last_sequence,\n batch_digest,\n tail_digest,\n batch_json\n FROM effect_agent_canonical_batches\n ORDER BY thread_id, first_sequence\n `.pipe(Effect.mapError(storageError(\"scan canonical batches\")));\n\n const records = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n sequence,\n record_id,\n batch_id,\n record_json\n FROM effect_agent_canonical_records\n ORDER BY thread_id, sequence\n `.pipe(Effect.mapError(storageError(\"scan canonical records\")));\n\n const checkpoints = yield* sql<Record<string, unknown>>`\n SELECT\n thread_id,\n through_sequence,\n tail_digest,\n checkpoint_json\n FROM effect_agent_checkpoints\n ORDER BY thread_id, through_sequence\n `.pipe(Effect.mapError(storageError(\"scan checkpoints\")));\n\n return {\n threads: yield* decodeRows(\n Schema.Array(ThreadRow),\n \"effect_agent_threads\",\n \"startup_scan\",\n threads,\n ),\n batches: yield* decodeRows(\n Schema.Array(BatchRow),\n \"effect_agent_canonical_batches\",\n \"startup_scan\",\n batches,\n ),\n records: yield* decodeRows(\n Schema.Array(RecordRow),\n \"effect_agent_canonical_records\",\n \"startup_scan\",\n records,\n ),\n checkpoints: yield* decodeRows(\n Schema.Array(CheckpointRow),\n \"effect_agent_checkpoints\",\n \"startup_scan\",\n checkpoints,\n ),\n };\n }),\n )\n .pipe(\n Effect.catchTag(\"SqlError\", (error) =>\n Effect.fail(storageError(\"startup scan transaction\")(error)),\n ),\n );\n });\n\n return {\n append,\n checkValueBound,\n exportThread,\n getThread,\n getTailDigestAt,\n loadCheckpoint,\n materialize,\n read,\n saveCheckpoint,\n scanStoredPayloads,\n withWriteTransaction,\n } as const;\n};\n\nexport type DoJournal = ReturnType<typeof makeJournal>;\n\nexport const initializeDoJournal = ensureCurrentStorage;\n","import { digestCanonicalBatch, EMPTY_TAIL_DIGEST } from \"@effect-agent/thread/Digest\";\nimport {\n CanonicalBatch,\n CanonicalRecord,\n CanonicalRecordEnvelope,\n CanonicalSequence,\n Digest,\n ObservationOffset,\n} from \"@effect-agent/thread/Records\";\nimport { DEFAULT_OWNERSHIP_LEASE_DURATION } from \"@effect-agent/thread/SubmissionLedger\";\nimport {\n AppendConflict,\n AppendResult,\n CheckpointRejected,\n ThreadCheckpoint,\n ThreadExport,\n ThreadExportRequest,\n ThreadMaterialization,\n ThreadNotMaterialized,\n ThreadObservation,\n ThreadRead,\n ThreadStore,\n type ThreadCheckpoints,\n ThreadStoreError,\n ThreadTail,\n ThreadTailRequest,\n FenceRejected,\n FencedAppendRequest,\n LoadCheckpointRequest,\n SaveCheckpointRequest,\n} from \"@effect-agent/thread/ThreadStore\";\nimport { BrowserCrypto } from \"@effect/platform-browser\";\nimport { SqliteClient } from \"@effect/sql-sqlite-do\";\nimport {\n Clock,\n Context,\n Crypto,\n Duration,\n Effect,\n Layer,\n Option,\n Ref,\n Schema,\n Stream,\n} from \"effect\";\nimport * as SqlClientService from \"effect/unstable/sql/SqlClient\";\n\nimport {\n DEFAULT_MAX_STORED_VALUE_BYTES,\n DoStorageConfig,\n DoStorageConfigValue,\n} from \"./DoStorageConfig.ts\";\nimport {\n type DoStorageCompatibilityError,\n DoAppendConflict,\n DoCheckpointConflict,\n DoFenceRejected,\n type DoStorageFailpointLocation,\n DoStorageCorruptionError,\n DoStorageError,\n} from \"./DoStorageError.ts\";\nimport { DoStorageFailpoint, type DoStorageFailpointHandler } from \"./DoStorageFailpoint.ts\";\nimport {\n initializeDoJournal,\n RawAppendRequest,\n RawCheckpoint,\n RawReadRequest,\n type DoJournal,\n} from \"./internal/do-journal.ts\";\n\n/**\n * Convenience-layer construction options. `storage` is the Durable Object's own\n * `ctx.storage` handle, injected as a value (DEPLOY-010: platform bindings enter only\n * through Layers; this package never imports `cloudflare:workers`).\n */\nexport interface DoStorageOptions {\n readonly storage: DurableObjectStorage;\n readonly observationPollInterval?: number | undefined;\n /**\n * Submission ownership lease duration in milliseconds (D5). Defaults to\n * `DEFAULT_OWNERSHIP_LEASE_DURATION` from `@effect-agent/thread`.\n */\n readonly ownershipLeaseDuration?: number | undefined;\n /**\n * Maximum bytes for any single stored value; must stay under the platform's 2 MB\n * per-value limit. Defaults to `DEFAULT_MAX_STORED_VALUE_BYTES`.\n */\n readonly maxStoredValueBytes?: number | undefined;\n /**\n * Re-verify every stored payload and digest chain while opening the store. Defaults to\n * off: per-operation Schema decoding and the digest chain already fail clearly on corrupt\n * rows without scanning the whole database on every open.\n */\n readonly verifyOnOpen?: boolean | undefined;\n readonly failpoint?: DoStorageFailpointHandler | undefined;\n}\n\nexport type DoStorageInitializationError =\n | DoStorageCompatibilityError\n | DoStorageCorruptionError\n | DoStorageError;\n\nconst OffsetText = Schema.String.check(Schema.isMaxLength(4 * 1024));\nconst DO_OFFSET_PREFIX = \"effect-agent-do@1:\";\nconst ZERO_CANONICAL_SEQUENCE = Schema.decodeSync(CanonicalSequence)(0);\nconst isDigest = Schema.is(Digest);\nconst isDoFenceRejected = Schema.is(DoFenceRejected);\nconst isDoAppendConflict = Schema.is(DoAppendConflict);\nconst isDoCheckpointConflict = Schema.is(DoCheckpointConflict);\n\nconst storeError = (operation: string, error: { readonly message: string }) =>\n ThreadStoreError.make({\n cause: error,\n operation,\n message: error.message,\n });\n\nconst schemaStoreError = (operation: string, error: { readonly message: string }) =>\n ThreadStoreError.make({\n cause: error,\n operation,\n message: error.message,\n });\n\nconst makeOffset = Effect.fn(function* (\n threadId: ThreadMaterialization[\"threadId\"],\n sequence: number,\n): Effect.fn.Return<ObservationOffset, ThreadStoreError> {\n return yield* Schema.decodeUnknownEffect(CanonicalSequence)(sequence).pipe(\n Effect.flatMap((validatedSequence) =>\n Schema.decodeUnknownEffect(ObservationOffset)(\n `${DO_OFFSET_PREFIX}${encodeURIComponent(threadId)}:${validatedSequence}`,\n ),\n ),\n Effect.mapError((error) => schemaStoreError(\"encode observation offset\", error)),\n );\n});\n\nconst parseOffset = Effect.fn(function* (\n threadId: ThreadMaterialization[\"threadId\"],\n offset: ObservationOffset | undefined,\n): Effect.fn.Return<CanonicalSequence, ThreadStoreError> {\n if (offset === undefined) return ZERO_CANONICAL_SEQUENCE;\n\n const text = yield* Schema.decodeUnknownEffect(OffsetText)(offset).pipe(\n Effect.mapError((error) => schemaStoreError(\"decode observation offset\", error)),\n );\n\n const threadPrefix = `${DO_OFFSET_PREFIX}${encodeURIComponent(threadId)}:`;\n\n if (!text.startsWith(threadPrefix)) {\n return yield* ThreadStoreError.make({\n operation: \"decode observation offset\",\n message: \"The observation offset belongs to a different adapter, storage version, or Thread.\",\n });\n }\n const sequenceText = text.slice(threadPrefix.length);\n\n if (!/^(0|[1-9][0-9]*)$/.test(sequenceText)) {\n return yield* ThreadStoreError.make({\n operation: \"decode observation offset\",\n message: \"The observation offset is malformed.\",\n });\n }\n\n return yield* Schema.decodeUnknownEffect(CanonicalSequence)(Number(sequenceText)).pipe(\n Effect.mapError((error) => schemaStoreError(\"decode observation offset\", error)),\n );\n});\n\nconst mapFence = (threadId: ThreadMaterialization[\"threadId\"], error: DoFenceRejected) =>\n FenceRejected.make({\n threadId,\n actualEpoch: error.actualEpoch,\n attemptedEpoch: error.producerEpoch,\n });\n\nconst encodeCanonicalRecord = Effect.fn(function* (\n record: CanonicalRecord,\n): Effect.fn.Return<string, ThreadStoreError> {\n return yield* Schema.encodeEffect(Schema.fromJsonString(CanonicalRecord))(record).pipe(\n Effect.mapError((error) => schemaStoreError(\"encode canonical record\", error)),\n );\n});\n\nconst encodeCanonicalBatch = Effect.fn(function* (\n batch: CanonicalBatch,\n): Effect.fn.Return<string, ThreadStoreError> {\n return yield* Schema.encodeEffect(Schema.fromJsonString(CanonicalBatch))(batch).pipe(\n Effect.mapError((error) => schemaStoreError(\"encode canonical batch\", error)),\n );\n});\n\nconst encodeCheckpoint = Effect.fn(function* (\n checkpoint: ThreadCheckpoint,\n): Effect.fn.Return<string, ThreadStoreError> {\n return yield* Schema.encodeEffect(Schema.fromJsonString(ThreadCheckpoint))(checkpoint).pipe(\n Effect.mapError((error) => schemaStoreError(\"encode checkpoint\", error)),\n );\n});\n\nconst decodeEnvelope = Effect.fn(function* (row: {\n readonly batch_id: string;\n readonly thread_id: string;\n readonly record_json: string;\n readonly sequence: CanonicalSequence;\n}) {\n const record = yield* Schema.decodeEffect(Schema.fromJsonString(CanonicalRecord))(\n row.record_json,\n ).pipe(\n Effect.mapError((error) =>\n ThreadStoreError.make({\n operation: \"decode canonical record\",\n message: error.message,\n }),\n ),\n );\n\n const threadId = yield* Schema.decodeUnknownEffect(CanonicalRecordEnvelope.fields.threadId)(\n row.thread_id,\n ).pipe(Effect.mapError((error) => schemaStoreError(\"decode thread identity\", error)));\n\n const offset = yield* makeOffset(threadId, row.sequence);\n\n const batchId = yield* Schema.decodeUnknownEffect(CanonicalRecordEnvelope.fields.batchId)(\n row.batch_id,\n ).pipe(Effect.mapError((error) => schemaStoreError(\"decode batch identity\", error)));\n\n return CanonicalRecordEnvelope.make({\n threadId,\n batchId,\n sequence: row.sequence,\n offset,\n record,\n });\n});\n\nconst decodeCheckpoint = Effect.fn(function* (\n checkpointJson: string,\n): Effect.fn.Return<ThreadCheckpoint, ThreadStoreError> {\n return yield* Schema.decodeEffect(Schema.fromJsonString(ThreadCheckpoint))(checkpointJson).pipe(\n Effect.mapError((error) => schemaStoreError(\"decode checkpoint\", error)),\n );\n});\n\nconst requireThread = Effect.fn(\"DoThreadStore.requireThread\")(function* (\n journal: DoJournal,\n threadId: ThreadMaterialization[\"threadId\"],\n) {\n const rows = yield* journal\n .getThread(threadId)\n .pipe(Effect.mapError((error) => storeError(\"read thread\", error)));\n\n if (rows.length === 0) {\n return yield* ThreadNotMaterialized.make({ threadId });\n }\n\n return rows[0];\n});\n\nconst tailDigestAt = Effect.fn(\"DoThreadStore.tailDigestAt\")(function* (\n journal: DoJournal,\n threadId: ThreadMaterialization[\"threadId\"],\n sequence: CanonicalSequence,\n) {\n if (sequence === 0) return EMPTY_TAIL_DIGEST;\n\n const digests = yield* journal\n .getTailDigestAt(threadId, sequence)\n .pipe(Effect.mapError((error) => storeError(\"read checkpoint digest\", error)));\n\n if (digests.length !== 1) {\n return yield* CheckpointRejected.make({\n threadId,\n reason: \"digest-mismatch\",\n });\n }\n\n return yield* Schema.decodeUnknownEffect(Digest)(digests[0]).pipe(\n Effect.mapError((error) => schemaStoreError(\"decode checkpoint digest\", error)),\n );\n});\n\nconst groupByKey = <A>(\n rows: ReadonlyArray<A>,\n key: (row: A) => string,\n): ReadonlyMap<string, ReadonlyArray<A>> => {\n const grouped = new Map<string, Array<A>>();\n\n for (const row of rows) {\n const existing = grouped.get(key(row));\n\n if (existing === undefined) {\n grouped.set(key(row), [row]);\n } else {\n existing.push(row);\n }\n }\n\n return grouped;\n};\n\n/**\n * Opt-in full integrity audit (`verifyOnOpen`). Every stored payload is decoded, re-encoded,\n * and re-digested against the canonical chain. Routine opens skip this scan: per-operation\n * Schema decoding plus the digest chain already fail clearly on corrupt rows.\n */\nconst decodeStartupPayloads = Effect.fn(\"DoThreadStore.decodeStartupPayloads\")(function* (\n journal: DoJournal,\n crypto: Crypto.Crypto,\n) {\n const stored = yield* journal.scanStoredPayloads();\n\n const batches = yield* Effect.forEach(stored.batches, (batch) =>\n Schema.decodeEffect(Schema.fromJsonString(CanonicalBatch))(batch.batch_json).pipe(\n Effect.map((decoded) => ({ decoded, row: batch })),\n Effect.mapError((error) =>\n DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_batches\",\n rowKey: `${batch.thread_id}/${batch.batch_id}`,\n message: error.message,\n }),\n ),\n ),\n );\n\n const records = yield* Effect.forEach(stored.records, (record) =>\n Schema.decodeEffect(Schema.fromJsonString(CanonicalRecord))(record.record_json).pipe(\n Effect.map((decoded) => ({ decoded, row: record })),\n Effect.mapError((error) =>\n DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_records\",\n rowKey: `${record.thread_id}/${record.sequence}`,\n message: error.message,\n }),\n ),\n ),\n );\n\n const checkpoints = yield* Effect.forEach(stored.checkpoints, (checkpoint) =>\n Schema.decodeEffect(Schema.fromJsonString(ThreadCheckpoint))(checkpoint.checkpoint_json).pipe(\n Effect.map((decoded) => ({ decoded, row: checkpoint })),\n Effect.mapError((error) =>\n DoStorageCorruptionError.make({\n table: \"effect_agent_checkpoints\",\n rowKey: `${checkpoint.thread_id}/${checkpoint.through_sequence}`,\n message: error.message,\n }),\n ),\n ),\n );\n\n const batchesByThread = groupByKey(batches, ({ row }) => row.thread_id);\n const recordsByThread = groupByKey(records, ({ row }) => row.thread_id);\n const checkpointsByThread = groupByKey(checkpoints, ({ row }) => row.thread_id);\n const materializedIds = new Set(stored.threads.map((thread) => thread.thread_id));\n\n for (const thread of stored.threads) {\n const threadBatches = batchesByThread.get(thread.thread_id) ?? [];\n const threadRecords = recordsByThread.get(thread.thread_id) ?? [];\n const threadCheckpoints = checkpointsByThread.get(thread.thread_id) ?? [];\n const recordsByBatch = groupByKey(threadRecords, ({ row }) => row.batch_id);\n let previousDigest = EMPTY_TAIL_DIGEST;\n let expectedSequence = 1;\n const tailDigests = new Map<number, string>([[0, EMPTY_TAIL_DIGEST]]);\n\n for (const { decoded: canonicalBatch, row: batchRow } of threadBatches) {\n const key = `${batchRow.thread_id}/${batchRow.batch_id}`;\n\n if (\n canonicalBatch.batchId !== batchRow.batch_id ||\n batchRow.first_sequence !== expectedSequence ||\n batchRow.last_sequence !== batchRow.first_sequence + canonicalBatch.records.length - 1\n ) {\n return yield* DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_batches\",\n rowKey: key,\n message: \"Canonical batch identity, sequence, or record count is inconsistent.\",\n });\n }\n\n const digest = yield* digestCanonicalBatch(previousDigest, canonicalBatch).pipe(\n Effect.provideService(Crypto.Crypto, crypto),\n Effect.mapError((error) =>\n DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_batches\",\n rowKey: key,\n message: error.message,\n }),\n ),\n );\n\n if (batchRow.batch_digest !== digest || batchRow.tail_digest !== digest) {\n return yield* DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_batches\",\n rowKey: key,\n message: \"Canonical batch digest does not match its decoded content and prior tail.\",\n });\n }\n\n const batchRecords = recordsByBatch.get(batchRow.batch_id) ?? [];\n\n if (batchRecords.length !== canonicalBatch.records.length) {\n return yield* DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_records\",\n rowKey: key,\n message: \"Canonical batch and record-table counts differ.\",\n });\n }\n for (let index = 0; index < canonicalBatch.records.length; index++) {\n const expectedRecord = canonicalBatch.records[index];\n const storedRecord = batchRecords[index];\n\n const expectedJson = yield* Schema.encodeEffect(Schema.fromJsonString(CanonicalRecord))(\n expectedRecord,\n ).pipe(\n Effect.mapError((error) =>\n DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_batches\",\n rowKey: key,\n message: error.message,\n }),\n ),\n );\n\n const storedJson = yield* Schema.encodeEffect(Schema.fromJsonString(CanonicalRecord))(\n storedRecord.decoded,\n ).pipe(\n Effect.mapError((error) =>\n DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_records\",\n rowKey: `${key}/${storedRecord.row.sequence}`,\n message: error.message,\n }),\n ),\n );\n\n if (\n storedRecord.row.sequence !== batchRow.first_sequence + index ||\n storedRecord.row.record_id !== expectedRecord.recordId ||\n expectedJson !== storedJson\n ) {\n return yield* DoStorageCorruptionError.make({\n table: \"effect_agent_canonical_records\",\n rowKey: `${key}/${storedRecord.row.sequence}`,\n message: \"Canonical record identity, sequence, or payload differs from its batch.\",\n });\n }\n }\n\n previousDigest = digest;\n expectedSequence = batchRow.last_sequence + 1;\n tailDigests.set(batchRow.last_sequence, digest);\n }\n\n if (\n threadRecords.length !== thread.tail_sequence ||\n thread.tail_sequence !== expectedSequence - 1 ||\n thread.tail_digest !== previousDigest\n ) {\n return yield* DoStorageCorruptionError.make({\n table: \"effect_agent_threads\",\n rowKey: thread.thread_id,\n message: \"Thread tail does not match its canonical batch chain.\",\n });\n }\n\n for (const checkpoint of threadCheckpoints) {\n if (\n checkpoint.decoded.threadId !== thread.thread_id ||\n checkpoint.decoded.throughSequence !== checkpoint.row.through_sequence ||\n checkpoint.decoded.tailDigest !== checkpoint.row.tail_digest ||\n tailDigests.get(checkpoint.row.through_sequence) !== checkpoint.row.tail_digest\n ) {\n return yield* DoStorageCorruptionError.make({\n table: \"effect_agent_checkpoints\",\n rowKey: `${thread.thread_id}/${checkpoint.row.through_sequence}`,\n message: \"Checkpoint identity or digest is not bound to a canonical batch tail.\",\n });\n }\n }\n }\n\n if (\n batches.some(({ row }) => !materializedIds.has(row.thread_id)) ||\n records.some(({ row }) => !materializedIds.has(row.thread_id)) ||\n checkpoints.some(({ row }) => !materializedIds.has(row.thread_id))\n ) {\n return yield* DoStorageCorruptionError.make({\n table: \"effect_agent_threads\",\n rowKey: \"startup_scan\",\n message: \"Canonical rows exist without a materialized Thread.\",\n });\n }\n});\n\nconst makeServices = Effect.fn(\"DoThreadStore.makeServices\")(function* () {\n const config = yield* DoStorageConfig;\n const failpoint = yield* DoStorageFailpoint;\n const sql = yield* SqlClientService.SqlClient;\n const crypto = yield* Crypto.Crypto;\n const journal = yield* initializeDoJournal(sql, failpoint.hit, config.maxStoredValueBytes);\n\n if (config.verifyOnOpen) {\n yield* decodeStartupPayloads(journal, crypto);\n }\n\n const provideCrypto = <A, E>(effect: Effect.Effect<A, E, Crypto.Crypto>) =>\n Effect.provideService(effect, Crypto.Crypto, crypto);\n\n const hitFailpoint = Effect.fn(\n (location: DoStorageFailpointLocation): Effect.Effect<void, ThreadStoreError> =>\n failpoint\n .hit(location)\n .pipe(Effect.mapError((error) => storeError(`storage failpoint ${location}`, error))),\n );\n\n const materialize: ThreadStore[\"Service\"][\"materialize\"] = Effect.fn(\"DoThreadStore.materialize\")(\n function* (request: ThreadMaterialization) {\n const validated = yield* Schema.decodeUnknownEffect(Schema.toType(ThreadMaterialization))(\n request,\n ).pipe(Effect.mapError((error) => schemaStoreError(\"validate materialization\", error)));\n\n const now = yield* Clock.currentTimeMillis;\n\n yield* hitFailpoint(\"materialize:before\");\n yield* journal\n .materialize(\n validated.threadId,\n new Date(now).toISOString(),\n EMPTY_TAIL_DIGEST,\n validated.producerEpoch,\n )\n .pipe(\n Effect.mapError((error) =>\n error._tag === \"DoFenceRejected\"\n ? mapFence(validated.threadId, error)\n : storeError(\"materialize thread\", error),\n ),\n );\n yield* hitFailpoint(\"materialize:after\");\n },\n );\n\n const append: ThreadStore[\"Service\"][\"append\"] = Effect.fn(\"DoThreadStore.append\")(function* (\n request: FencedAppendRequest,\n ) {\n const validated = yield* Schema.decodeUnknownEffect(Schema.toType(FencedAppendRequest))(\n request,\n ).pipe(Effect.mapError((error) => schemaStoreError(\"validate canonical append\", error)));\n\n yield* requireThread(journal, validated.threadId);\n\n const tailDigest = yield* provideCrypto(\n digestCanonicalBatch(validated.expectedTailDigest, validated.batch),\n ).pipe(Effect.mapError((error) => storeError(\"digest canonical append\", error)));\n\n const batchJson = yield* encodeCanonicalBatch(validated.batch);\n\n const rawRecords = yield* Effect.forEach(validated.batch.records, (record) =>\n encodeCanonicalRecord(record).pipe(\n Effect.map((recordJson) => ({\n recordId: record.recordId,\n recordJson,\n })),\n ),\n );\n\n const rawRequest = yield* Schema.decodeUnknownEffect(RawAppendRequest)({\n threadId: validated.threadId,\n batchId: validated.batch.batchId,\n batchDigest: tailDigest,\n batchJson,\n expectedTailSequence: validated.expectedTailSequence,\n expectedTailDigest: validated.expectedTailDigest,\n producerEpoch: validated.producerEpoch,\n records: rawRecords,\n tailDigest,\n }).pipe(Effect.mapError((error) => schemaStoreError(\"encode canonical append\", error)));\n\n yield* hitFailpoint(\"append:before\");\n\n const result = yield* journal.append(rawRequest).pipe(\n Effect.mapError((error) => {\n if (isDoFenceRejected(error)) {\n return mapFence(validated.threadId, error);\n }\n if (isDoAppendConflict(error)) {\n return error.actualTailSequence !== undefined && isDigest(error.actualTailDigest)\n ? AppendConflict.make({\n threadId: validated.threadId,\n batchId: validated.batch.batchId,\n reason: error.reason,\n actualTailSequence: error.actualTailSequence,\n actualTailDigest: error.actualTailDigest,\n })\n : AppendConflict.make({\n threadId: validated.threadId,\n batchId: validated.batch.batchId,\n reason: error.reason,\n });\n }\n\n return storeError(\"append canonical batch\", error);\n }),\n Effect.flatMap((result) =>\n Schema.decodeUnknownEffect(AppendResult)(result).pipe(\n Effect.mapError((error) => schemaStoreError(\"decode append result\", error)),\n ),\n ),\n );\n\n yield* hitFailpoint(\"append:after\");\n\n return result;\n });\n\n const loadRecords = Effect.fn(\"DoThreadStore.loadRecords\")(function* (request: RawReadRequest) {\n const rows = yield* journal\n .read(request)\n .pipe(Effect.mapError((error) => storeError(\"read canonical records\", error)));\n\n return yield* Effect.forEach(rows, decodeEnvelope);\n });\n\n const readEffect = Effect.fn(\"DoThreadStore.read\")(function* (request: ThreadRead) {\n const validated = yield* Schema.decodeUnknownEffect(Schema.toType(ThreadRead))(request).pipe(\n Effect.mapError((error) => schemaStoreError(\"validate thread read\", error)),\n );\n\n yield* requireThread(journal, validated.threadId);\n\n const records = yield* loadRecords(\n RawReadRequest.make({\n threadId: validated.threadId,\n fromSequenceExclusive: validated.afterSequence ?? ZERO_CANONICAL_SEQUENCE,\n limit: validated.limit,\n }),\n );\n\n return Stream.fromIterable(records);\n });\n\n const read: ThreadStore[\"Service\"][\"read\"] = (request) => Stream.unwrap(readEffect(request));\n\n const observeEffect = Effect.fn(\"DoThreadStore.observe\")(function* (request: ThreadObservation) {\n const validated = yield* Schema.decodeUnknownEffect(Schema.toType(ThreadObservation))(\n request,\n ).pipe(Effect.mapError((error) => schemaStoreError(\"validate thread observation\", error)));\n\n yield* requireThread(journal, validated.threadId);\n const initialSequence = yield* parseOffset(validated.threadId, validated.afterOffset);\n const cursor = yield* Ref.make(initialSequence);\n\n const poll = Effect.fn(\"DoThreadStore.observePoll\")(function* () {\n const fromSequenceExclusive = yield* Ref.get(cursor);\n\n const records = yield* loadRecords(\n RawReadRequest.make({\n threadId: validated.threadId,\n fromSequenceExclusive,\n limit: 1_024,\n }),\n );\n\n if (records.length === 0) {\n yield* Effect.sleep(config.observationPollInterval);\n\n return [];\n }\n yield* Ref.set(cursor, records[records.length - 1].sequence);\n\n return records;\n });\n\n return Stream.fromIterableEffectRepeat(poll());\n });\n\n const observe: ThreadStore[\"Service\"][\"observe\"] = (request) =>\n Stream.unwrap(observeEffect(request));\n\n const exportThread: ThreadStore[\"Service\"][\"export\"] = Effect.fn(\"DoThreadStore.export\")(\n function* (request: ThreadExportRequest) {\n const validated = yield* Schema.decodeUnknownEffect(Schema.toType(ThreadExportRequest))(\n request,\n ).pipe(Effect.mapError((error) => schemaStoreError(\"validate thread export\", error)));\n\n yield* requireThread(journal, validated.threadId);\n\n const exported = yield* journal\n .exportThread(validated.threadId)\n .pipe(Effect.mapError((error) => storeError(\"export thread\", error)));\n\n const records = yield* Effect.forEach(exported.records, decodeEnvelope);\n\n if (records.length > 65_536) {\n return yield* ThreadStoreError.make({\n operation: \"decode thread export\",\n message: \"The thread exceeds the current export record limit.\",\n });\n }\n\n const tailDigest = yield* Schema.decodeUnknownEffect(Digest)(\n exported.thread.tail_digest,\n ).pipe(Effect.mapError((error) => schemaStoreError(\"decode export tail digest\", error)));\n\n return ThreadExport.make({\n format: \"effect-agent/thread@1\",\n threadId: validated.threadId,\n tailSequence: exported.thread.tail_sequence,\n tailDigest,\n records,\n });\n },\n );\n\n const inspectTail: ThreadStore[\"Service\"][\"inspectTail\"] = Effect.fn(\"DoThreadStore.inspectTail\")(\n function* (request: ThreadTailRequest) {\n const validated = yield* Schema.decodeUnknownEffect(Schema.toType(ThreadTailRequest))(\n request,\n ).pipe(Effect.mapError((error) => schemaStoreError(\"validate tail inspection\", error)));\n\n const thread = yield* requireThread(journal, validated.threadId);\n\n const tailDigest = yield* Schema.decodeUnknownEffect(Digest)(thread.tail_digest).pipe(\n Effect.mapError((error) => schemaStoreError(\"decode tail digest\", error)),\n );\n\n return ThreadTail.make({\n threadId: validated.threadId,\n tailSequence: thread.tail_sequence,\n tailDigest,\n producerEpoch: thread.producer_epoch,\n });\n },\n );\n\n const saveCheckpoint: ThreadCheckpoints[\"save\"] = Effect.fn(\"DoThreadStore.saveCheckpoint\")(\n function* (request: SaveCheckpointRequest) {\n const validated = yield* Schema.decodeUnknownEffect(Schema.toType(SaveCheckpointRequest))(\n request,\n ).pipe(Effect.mapError((error) => schemaStoreError(\"validate checkpoint\", error)));\n\n const thread = yield* requireThread(journal, validated.checkpoint.threadId);\n\n if (validated.checkpoint.throughSequence > thread.tail_sequence) {\n return yield* CheckpointRejected.make({\n threadId: validated.checkpoint.threadId,\n reason: \"ahead-of-tail\",\n });\n }\n\n const canonicalDigest = yield* tailDigestAt(\n journal,\n validated.checkpoint.threadId,\n validated.checkpoint.throughSequence,\n );\n\n if (canonicalDigest !== validated.checkpoint.tailDigest) {\n return yield* CheckpointRejected.make({\n threadId: validated.checkpoint.threadId,\n reason: \"digest-mismatch\",\n });\n }\n const checkpointJson = yield* encodeCheckpoint(validated.checkpoint);\n\n const raw = RawCheckpoint.make({\n threadId: validated.checkpoint.threadId,\n throughSequence: validated.checkpoint.throughSequence,\n tailDigest: validated.checkpoint.tailDigest,\n checkpointJson,\n });\n\n yield* hitFailpoint(\"save-checkpoint:before\");\n yield* journal.saveCheckpoint(raw).pipe(\n Effect.mapError((error) =>\n isDoCheckpointConflict(error)\n ? CheckpointRejected.make({\n threadId: validated.checkpoint.threadId,\n reason: \"digest-mismatch\",\n })\n : storeError(\"save checkpoint\", error),\n ),\n );\n yield* hitFailpoint(\"save-checkpoint:after\");\n },\n );\n\n const loadCheckpoint: ThreadCheckpoints[\"load\"] = Effect.fn(\"DoThreadStore.loadCheckpoint\")(\n function* (request: LoadCheckpointRequest) {\n const validated = yield* Schema.decodeUnknownEffect(Schema.toType(LoadCheckpointRequest))(\n request,\n ).pipe(Effect.mapError((error) => schemaStoreError(\"validate checkpoint lookup\", error)));\n\n const thread = yield* requireThread(journal, validated.threadId);\n\n const rows = yield* journal\n .loadCheckpoint(validated.threadId, validated.atOrBeforeSequence ?? thread.tail_sequence)\n .pipe(Effect.mapError((error) => storeError(\"load checkpoint\", error)));\n\n if (rows.length === 0) return Option.none();\n if (rows.length !== 1) {\n return yield* ThreadStoreError.make({\n operation: \"load checkpoint\",\n message: `Expected at most one checkpoint row but found ${rows.length}.`,\n });\n }\n const checkpoint = yield* decodeCheckpoint(rows[0].checkpoint_json);\n\n const canonicalDigest = yield* tailDigestAt(\n journal,\n checkpoint.threadId,\n checkpoint.throughSequence,\n );\n\n if (canonicalDigest !== checkpoint.tailDigest) {\n return yield* CheckpointRejected.make({\n threadId: checkpoint.threadId,\n reason: \"digest-mismatch\",\n });\n }\n\n return Option.some(checkpoint);\n },\n );\n\n const threadStore = ThreadStore.of({\n append,\n export: exportThread,\n inspectTail,\n materialize,\n observe,\n read,\n checkpoints: { save: saveCheckpoint, load: loadCheckpoint },\n });\n\n return Context.make(ThreadStore, threadStore);\n});\n\n/**\n * Durable Object Thread Store implementation with configuration, failpoint, SQL, and\n * Crypto authority kept visible in its input channel.\n */\nexport const threadStoreLayer: Layer.Layer<\n ThreadStore,\n DoStorageInitializationError,\n DoStorageConfig | DoStorageFailpoint | SqlClientService.SqlClient | Crypto.Crypto\n> = Layer.effectContext(makeServices());\n\n/**\n * Validated Durable Object storage configuration Layer with the documented defaults applied.\n * Shared by the ThreadStore and SubmissionLedger convenience layers so their defaults\n * cannot drift.\n */\nexport const storageConfigLayer = (\n options: DoStorageOptions,\n): Layer.Layer<DoStorageConfig, DoStorageError> =>\n Layer.effect(DoStorageConfig)(\n Schema.decodeUnknownEffect(DoStorageConfigValue)({\n observationPollInterval: options.observationPollInterval ?? 25,\n ownershipLeaseDuration:\n options.ownershipLeaseDuration ?? Duration.toMillis(DEFAULT_OWNERSHIP_LEASE_DURATION),\n maxStoredValueBytes: options.maxStoredValueBytes ?? DEFAULT_MAX_STORED_VALUE_BYTES,\n verifyOnOpen: options.verifyOnOpen ?? false,\n }).pipe(\n Effect.mapError((error) =>\n DoStorageError.make({\n cause: error,\n operation: \"configure Durable Object storage\",\n message: error.message,\n }),\n ),\n ),\n );\n\n/** The failpoint Layer selected by convenience options: explicit handler or the no-op default. */\nexport const storageFailpointLayer = (\n options: DoStorageOptions,\n): Layer.Layer<DoStorageFailpoint> =>\n options.failpoint === undefined\n ? DoStorageFailpoint.layer\n : Layer.succeed(DoStorageFailpoint)({ hit: options.failpoint });\n\n/**\n * A composition-root convenience Layer for canonical Threads inside one Durable Object,\n * built over `ctx.storage`. Durable accepted work is served by the separate SubmissionLedger\n * port; point both at the SAME `ctx.storage` so claims fence the same producer epochs\n * (ADR-0011 D7's \"same file\" rule, transposed to one object's private database).\n */\nexport const layer = (\n options: DoStorageOptions,\n): Layer.Layer<ThreadStore, DoStorageInitializationError> =>\n Layer.unwrap(\n Effect.map(DoStorageConfig, (config) =>\n threadStoreLayer.pipe(\n Layer.provide(\n Layer.mergeAll(\n Layer.succeed(DoStorageConfig)(config),\n storageFailpointLayer(options),\n SqliteClient.layer({ storage: options.storage }),\n BrowserCrypto.layer,\n ),\n ),\n ),\n ),\n ).pipe(Layer.provide(storageConfigLayer(options)));\n"],"mappings":"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"}
|