@effect-agent/storage-sqlite 0.1.0-beta.39 → 0.1.0-beta.40

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/index.mjs CHANGED
@@ -1,9 +1,10 @@
1
1
  import { t as SqliteStorageFailpoint } from "./sqlite-storage-failpoint-DIwWk5dw.mjs";
2
- import { AbortCommand, AbortIntent, AcceptedEvent, AdmissionAdmitted, AdmissionConflict, AdmissionNotAdmitted, AdmissionRequest, AdmissionResult, AppendConflict, AppendResult, ApprovalConflict, ApprovalDecision, ApprovalDecisionCommand, ApprovalDecisionIntent, AttachChildToReservationRequest, BeginChildBudgetReleaseRequest, CanonicalBatch, CanonicalRecord, CanonicalRecordEnvelope, CanonicalSequence, CheckpointRejected, ChildAttachmentSnapshot, ChildBudgetReservationRequest, ChildBudgetReservationSnapshot, ChildReservationConflict, ChildReservationStatus, ChildSettledNotification, Claim, ClaimJoiningRequest, ClaimRequest, DEFAULT_OWNERSHIP_LEASE_DURATION, DefinitionDigests, DeliveryChange, Digest, EMPTY_TAIL_DIGEST, FenceRejected, FencedAppendRequest, InputAppliedMarker, JoinSnapshot, JoinedToHost, JoiningClaim, LedgerCapabilities, LedgerError, LoadCheckpointRequest, MarkInputAppliedRequest, MarkJoinedRequest, MarkReadyRequest, MarkUnknownRequest, ObservationOffset, OwnershipLost, OwnershipRenewal, OwnershipSnapshot, ParentLinkage, PersistedJson, ProducerEpoch, QueueSequence, RecordEnvelope, RecoverySnapshot, RecoverySnapshotRequest, ReleaseChildBudgetRequest, ReleaseOwnershipRequest, RenewOwnershipRequest, ReservedChildBudget, ReservedSettlement, RevertJoiningRequest, SaveCheckpointRequest, ScheduleCapacityError, ScheduleChange, ScheduleConflict, ScheduleDueCursor, ScheduleFailpoint, ScheduleId, ScheduleInstant, ScheduleKey, ScheduleNotFound, ScheduleOwner, SchedulePageRequest, ScheduleRecord, ScheduleStorageError, ScheduleStore, Settlement, SettlementConflict, SettlementFinalization, SettlementOutcome, SettlementReservation, SettlementReservationSnapshot, SourcePartition, SubmissionLedger, SubmissionLookup, SubmissionLookupByKey, SubmissionSnapshot, SubmissionState, SubscriptionDelivery, SubscriptionDeliveryKey, SubscriptionError, SubscriptionFailpoint, SubscriptionKey, SubscriptionLimits, SubscriptionName, SubscriptionRecord, SubscriptionScanCursors, SubscriptionStore, SuspendRequest, SuspensionReason, SuspensionSnapshot, ThreadCheckpoint, ThreadExport, ThreadExportRequest, ThreadMaterialization, ThreadNotMaterialized, ThreadObservation, ThreadRead, ThreadStore, ThreadStoreError, ThreadTail, ThreadTailRequest, UnknownResolution, UnknownResolutionCommand, UnknownResolutionConflict, UnknownResolutionIntent, applyScheduleChange, applySubscriptionDeliveryChange, defaultSchedulingLimits, digestCanonicalBatch, sameAcceptedEventIdentity, sameSourcePartition, scheduleDeadline, scheduleUsesCapacity, settlementFailureFromRecord, submissionAbortRecordId, subscriptionCanSelect, subscriptionDeliveryCanSelect, subscriptionDeliveryKeyString } from "@effect-agent/thread";
2
+ import { AbortCommand, AbortIntent, AcceptedEvent, ActivityBusy, ActivityClaim, ActivityClaimRequest, ActivityMutationFailpoint, ActivityOwnershipLost, ActivityProcessorKey, ActivityProcessorStore, ActivityProgress, ActivityStoreError, ActivityWorkConflict, AdmissionAdmitted, AdmissionConflict, AdmissionNotAdmitted, AdmissionRequest, AdmissionResult, AppendConflict, AppendResult, ApprovalConflict, ApprovalDecision, ApprovalDecisionCommand, ApprovalDecisionIntent, AttachChildToReservationRequest, BeginChildBudgetReleaseRequest, CanonicalBatch, CanonicalRecord, CanonicalRecordEnvelope, CanonicalSequence, CheckpointRejected, ChildAttachmentSnapshot, ChildBudgetReservationRequest, ChildBudgetReservationSnapshot, ChildReservationConflict, ChildReservationStatus, ChildSettledNotification, Claim, ClaimJoiningRequest, ClaimRequest, DEFAULT_OWNERSHIP_LEASE_DURATION, DefinitionDigests, DeliveryChange, Digest, EMPTY_TAIL_DIGEST, FenceRejected, FencedAppendRequest, InputAppliedMarker, JoinSnapshot, JoinedToHost, JoiningClaim, LedgerCapabilities, LedgerError, LoadCheckpointRequest, MarkInputAppliedRequest, MarkJoinedRequest, MarkReadyRequest, MarkUnknownRequest, ObservationOffset, OwnershipLost, OwnershipRenewal, OwnershipSnapshot, ParentLinkage, PersistedJson, PreparedActivity, ProducerEpoch, QueueSequence, RecordEnvelope, RecoverySnapshot, RecoverySnapshotRequest, ReleaseChildBudgetRequest, ReleaseOwnershipRequest, RenewOwnershipRequest, ReservedChildBudget, ReservedSettlement, RevertJoiningRequest, SaveCheckpointRequest, ScheduleCapacityError, ScheduleChange, ScheduleConflict, ScheduleDueCursor, ScheduleFailpoint, ScheduleId, ScheduleInstant, ScheduleKey, ScheduleNotFound, ScheduleOwner, SchedulePageRequest, ScheduleRecord, ScheduleStorageError, ScheduleStore, Settlement, SettlementConflict, SettlementFinalization, SettlementOutcome, SettlementReservation, SettlementReservationSnapshot, SourcePartition, SubmissionLedger, SubmissionLookup, SubmissionLookupByKey, SubmissionSnapshot, SubmissionState, SubscriptionDelivery, SubscriptionDeliveryKey, SubscriptionError, SubscriptionFailpoint, SubscriptionKey, SubscriptionLimits, SubscriptionName, SubscriptionRecord, SubscriptionScanCursors, SubscriptionStore, SuspendRequest, SuspensionReason, SuspensionSnapshot, ThreadCheckpoint, ThreadExport, ThreadExportRequest, ThreadMaterialization, ThreadNotMaterialized, ThreadObservation, ThreadRead, ThreadStore, ThreadStoreError, ThreadTail, ThreadTailRequest, UnknownResolution, UnknownResolutionCommand, UnknownResolutionConflict, UnknownResolutionIntent, applyScheduleChange, applySubscriptionDeliveryChange, defaultSchedulingLimits, digestCanonicalBatch, sameAcceptedEventIdentity, sameSourcePartition, scheduleDeadline, scheduleUsesCapacity, settlementFailureFromRecord, submissionAbortRecordId, subscriptionCanSelect, subscriptionDeliveryCanSelect, subscriptionDeliveryKeyString } from "@effect-agent/thread";
3
3
  import { Clock, Context, Crypto, DateTime, Duration, Effect, Exit, Layer, Option, Ref, Result, Schema, Stream } from "effect";
4
4
  import { SqliteClient, SqliteMigrator } from "@effect/sql-sqlite-node";
5
5
  import * as SqlClient from "effect/unstable/sql/SqlClient";
6
6
  import { NodeCrypto } from "@effect/platform-node";
7
+ import { MemoryDocument, MemoryKey, MemoryMutationFailpoint, MemoryNamespaceAddress, MemoryOperationConflict, MemoryReader, MemoryStorageError, MemoryWrite, MemoryWriter, applyMemoryWrite } from "@effect-agent/core";
7
8
  //#region src/errors.ts
8
9
  /** The SQLite file uses a private-development format this adapter cannot read. */
9
10
  var SqliteStorageCompatibilityError = class extends Schema.TaggedError()("SqliteStorageCompatibilityError", {
@@ -132,10 +133,10 @@ var SqliteStorageFailpointError = class extends Schema.TaggedError()("SqliteStor
132
133
  //#endregion
133
134
  //#region src/migrations.ts
134
135
  const CurrentSqliteStorageVersion = 7;
135
- const sqliteMigrations = SqliteMigrator.fromRecord({
136
- "1_current_persistent_thread_foundation": Effect.gen(function* () {
137
- const sql = yield* SqlClient.SqlClient;
138
- yield* sql`
136
+ /** Initialize empty storage with the complete current schema. */
137
+ const sqliteMigrations = SqliteMigrator.fromRecord({ "1_current_thread_storage": Effect.gen(function* () {
138
+ const sql = yield* SqlClient.SqlClient;
139
+ yield* sql`
139
140
  CREATE TABLE effect_agent_threads (
140
141
  thread_id TEXT PRIMARY KEY NOT NULL,
141
142
  created_at TEXT NOT NULL,
@@ -144,7 +145,7 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
144
145
  producer_epoch INTEGER NOT NULL
145
146
  )
146
147
  `.withoutTransform;
147
- yield* sql`
148
+ yield* sql`
148
149
  CREATE TABLE effect_agent_canonical_batches (
149
150
  thread_id TEXT NOT NULL,
150
151
  batch_id TEXT NOT NULL,
@@ -159,7 +160,7 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
159
160
  ON DELETE RESTRICT
160
161
  )
161
162
  `.withoutTransform;
162
- yield* sql`
163
+ yield* sql`
163
164
  CREATE TABLE effect_agent_canonical_records (
164
165
  thread_id TEXT NOT NULL,
165
166
  sequence INTEGER NOT NULL,
@@ -173,11 +174,11 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
173
174
  ON DELETE RESTRICT
174
175
  )
175
176
  `.withoutTransform;
176
- yield* sql`
177
+ yield* sql`
177
178
  CREATE INDEX effect_agent_canonical_records_batch
178
179
  ON effect_agent_canonical_records (thread_id, batch_id, sequence)
179
180
  `.withoutTransform;
180
- yield* sql`
181
+ yield* sql`
181
182
  CREATE TABLE effect_agent_checkpoints (
182
183
  thread_id TEXT NOT NULL,
183
184
  through_sequence INTEGER NOT NULL,
@@ -189,11 +190,7 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
189
190
  ON DELETE RESTRICT
190
191
  )
191
192
  `.withoutTransform;
192
- yield* sql`PRAGMA user_version = 1`.withoutTransform;
193
- }),
194
- "2_durable_submission_ledger": Effect.gen(function* () {
195
- const sql = yield* SqlClient.SqlClient;
196
- yield* sql`
193
+ yield* sql`
197
194
  CREATE TABLE effect_agent_submissions (
198
195
  submission_id TEXT PRIMARY KEY NOT NULL,
199
196
  thread_id TEXT NOT NULL,
@@ -212,11 +209,18 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
212
209
  ready_at TEXT,
213
210
  input_applied_record_id TEXT,
214
211
  input_applied_sequence INTEGER,
212
+ joined_host_submission_id TEXT,
213
+ suspended_reason_json TEXT,
214
+ suspended_at TEXT,
215
+ unknown_reason TEXT,
216
+ unknown_tool_call_ids_json TEXT,
217
+ parent_submission_id TEXT,
218
+ parent_tool_call_id TEXT,
215
219
  UNIQUE (thread_id, principal, idempotency_key),
216
220
  UNIQUE (thread_id, queue_sequence)
217
221
  )
218
222
  `.withoutTransform;
219
- yield* sql`
223
+ yield* sql`
220
224
  CREATE TABLE effect_agent_submission_ownership (
221
225
  submission_id TEXT PRIMARY KEY NOT NULL,
222
226
  attempt_id TEXT NOT NULL,
@@ -229,7 +233,7 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
229
233
  ON DELETE RESTRICT
230
234
  )
231
235
  `.withoutTransform;
232
- yield* sql`
236
+ yield* sql`
233
237
  CREATE TABLE effect_agent_attempts (
234
238
  attempt_id TEXT PRIMARY KEY NOT NULL,
235
239
  submission_id TEXT NOT NULL,
@@ -242,7 +246,7 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
242
246
  ON DELETE RESTRICT
243
247
  )
244
248
  `.withoutTransform;
245
- yield* sql`
249
+ yield* sql`
246
250
  CREATE TABLE effect_agent_settlement_reservations (
247
251
  submission_id TEXT PRIMARY KEY NOT NULL,
248
252
  settlement_id TEXT NOT NULL,
@@ -257,7 +261,7 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
257
261
  ON DELETE RESTRICT
258
262
  )
259
263
  `.withoutTransform;
260
- yield* sql`
264
+ yield* sql`
261
265
  CREATE TABLE effect_agent_abort_intents (
262
266
  submission_id TEXT PRIMARY KEY NOT NULL,
263
267
  author TEXT NOT NULL,
@@ -269,35 +273,11 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
269
273
  ON DELETE RESTRICT
270
274
  )
271
275
  `.withoutTransform;
272
- yield* sql`PRAGMA user_version = 2`.withoutTransform;
273
- }),
274
- "3_durable_tools_and_joined_input": Effect.gen(function* () {
275
- const sql = yield* SqlClient.SqlClient;
276
- yield* sql`
277
- ALTER TABLE effect_agent_submissions
278
- ADD COLUMN joined_host_submission_id TEXT
279
- `.withoutTransform;
280
- yield* sql`
281
- ALTER TABLE effect_agent_submissions
282
- ADD COLUMN suspended_reason_json TEXT
283
- `.withoutTransform;
284
- yield* sql`
285
- ALTER TABLE effect_agent_submissions
286
- ADD COLUMN suspended_at TEXT
287
- `.withoutTransform;
288
- yield* sql`
289
- ALTER TABLE effect_agent_submissions
290
- ADD COLUMN unknown_reason TEXT
291
- `.withoutTransform;
292
- yield* sql`
293
- ALTER TABLE effect_agent_submissions
294
- ADD COLUMN unknown_tool_call_ids_json TEXT
295
- `.withoutTransform;
296
- yield* sql`
276
+ yield* sql`
297
277
  CREATE INDEX effect_agent_submissions_joined_host
298
278
  ON effect_agent_submissions (joined_host_submission_id)
299
279
  `.withoutTransform;
300
- yield* sql`
280
+ yield* sql`
301
281
  CREATE TABLE effect_agent_approval_decisions (
302
282
  submission_id TEXT NOT NULL,
303
283
  tool_call_id TEXT NOT NULL,
@@ -311,7 +291,7 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
311
291
  ON DELETE RESTRICT
312
292
  )
313
293
  `.withoutTransform;
314
- yield* sql`
294
+ yield* sql`
315
295
  CREATE TABLE effect_agent_unknown_resolutions (
316
296
  submission_id TEXT NOT NULL,
317
297
  tool_call_id TEXT NOT NULL,
@@ -325,23 +305,11 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
325
305
  ON DELETE RESTRICT
326
306
  )
327
307
  `.withoutTransform;
328
- yield* sql`PRAGMA user_version = 3`.withoutTransform;
329
- }),
330
- "4_durable_subagents": Effect.gen(function* () {
331
- const sql = yield* SqlClient.SqlClient;
332
- yield* sql`
333
- ALTER TABLE effect_agent_submissions
334
- ADD COLUMN parent_submission_id TEXT
335
- `.withoutTransform;
336
- yield* sql`
337
- ALTER TABLE effect_agent_submissions
338
- ADD COLUMN parent_tool_call_id TEXT
339
- `.withoutTransform;
340
- yield* sql`
308
+ yield* sql`
341
309
  CREATE INDEX effect_agent_submissions_parent
342
310
  ON effect_agent_submissions (parent_submission_id)
343
311
  `.withoutTransform;
344
- yield* sql`
312
+ yield* sql`
345
313
  CREATE TABLE effect_agent_child_reservations (
346
314
  reservation_id TEXT PRIMARY KEY NOT NULL,
347
315
  parent_submission_id TEXT NOT NULL,
@@ -360,11 +328,7 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
360
328
  ON DELETE RESTRICT
361
329
  )
362
330
  `.withoutTransform;
363
- yield* sql`PRAGMA user_version = 4`.withoutTransform;
364
- }),
365
- "5_durable_schedules": Effect.gen(function* () {
366
- const sql = yield* SqlClient.SqlClient;
367
- yield* sql`
331
+ yield* sql`
368
332
  CREATE TABLE effect_agent_schedules (
369
333
  tenant_id TEXT NOT NULL,
370
334
  owner_id TEXT NOT NULL,
@@ -374,21 +338,17 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
374
338
  PRIMARY KEY (tenant_id, owner_id, schedule_id)
375
339
  )
376
340
  `.withoutTransform;
377
- yield* sql`
341
+ yield* sql`
378
342
  CREATE INDEX effect_agent_schedules_deadline
379
343
  ON effect_agent_schedules (deadline_at_millis, tenant_id, owner_id, schedule_id)
380
344
  WHERE deadline_at_millis IS NOT NULL
381
345
  `.withoutTransform;
382
- yield* sql`
346
+ yield* sql`
383
347
  CREATE INDEX effect_agent_schedules_owner_deadline
384
348
  ON effect_agent_schedules (tenant_id, owner_id, deadline_at_millis, schedule_id)
385
349
  WHERE deadline_at_millis IS NOT NULL
386
350
  `.withoutTransform;
387
- yield* sql`PRAGMA user_version = 5`.withoutTransform;
388
- }),
389
- "6_durable_subscriptions": Effect.gen(function* () {
390
- const sql = yield* SqlClient.SqlClient;
391
- yield* sql`
351
+ yield* sql`
392
352
  CREATE TABLE effect_agent_subscription_sequences (
393
353
  tenant_id TEXT NOT NULL,
394
354
  source_address TEXT NOT NULL,
@@ -399,7 +359,7 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
399
359
  PRIMARY KEY (tenant_id, source_address)
400
360
  )
401
361
  `.withoutTransform;
402
- yield* sql`
362
+ yield* sql`
403
363
  CREATE TABLE effect_agent_subscriptions (
404
364
  tenant_id TEXT NOT NULL,
405
365
  source_address TEXT NOT NULL,
@@ -417,10 +377,10 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
417
377
  UNIQUE (tenant_id, source_address, ordinal)
418
378
  )
419
379
  `.withoutTransform;
420
- yield* sql`CREATE INDEX effect_agent_subscriptions_owner ON effect_agent_subscriptions (tenant_id, source_address, owner_id, ordinal)`.withoutTransform;
421
- yield* sql`CREATE INDEX effect_agent_subscriptions_candidates ON effect_agent_subscriptions (tenant_id, source_address, source_name, source_version, matching_key, ordinal)`.withoutTransform;
422
- yield* sql`CREATE INDEX effect_agent_subscriptions_recovery ON effect_agent_subscriptions (tenant_id, source_address, recovery_at_millis, ordinal) WHERE recovery_at_millis IS NOT NULL`.withoutTransform;
423
- yield* sql`
380
+ yield* sql`CREATE INDEX effect_agent_subscriptions_owner ON effect_agent_subscriptions (tenant_id, source_address, owner_id, ordinal)`.withoutTransform;
381
+ yield* sql`CREATE INDEX effect_agent_subscriptions_candidates ON effect_agent_subscriptions (tenant_id, source_address, source_name, source_version, matching_key, ordinal)`.withoutTransform;
382
+ yield* sql`CREATE INDEX effect_agent_subscriptions_recovery ON effect_agent_subscriptions (tenant_id, source_address, recovery_at_millis, ordinal) WHERE recovery_at_millis IS NOT NULL`.withoutTransform;
383
+ yield* sql`
424
384
  CREATE TABLE effect_agent_subscription_events (
425
385
  tenant_id TEXT NOT NULL,
426
386
  source_address TEXT NOT NULL,
@@ -437,8 +397,8 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
437
397
  PRIMARY KEY (tenant_id, source_address, event_id)
438
398
  )
439
399
  `.withoutTransform;
440
- yield* sql`CREATE INDEX effect_agent_subscription_events_pending ON effect_agent_subscription_events (tenant_id, source_address, routing_complete, next_attempt_at_millis, event_id)`.withoutTransform;
441
- yield* sql`
400
+ yield* sql`CREATE INDEX effect_agent_subscription_events_pending ON effect_agent_subscription_events (tenant_id, source_address, routing_complete, next_attempt_at_millis, event_id)`.withoutTransform;
401
+ yield* sql`
442
402
  CREATE TABLE effect_agent_subscription_deliveries (
443
403
  tenant_id TEXT NOT NULL,
444
404
  source_address TEXT NOT NULL,
@@ -453,14 +413,308 @@ const sqliteMigrations = SqliteMigrator.fromRecord({
453
413
  UNIQUE (tenant_id, source_address, delivery_key)
454
414
  )
455
415
  `.withoutTransform;
456
- yield* sql`CREATE INDEX effect_agent_subscription_deliveries_pending ON effect_agent_subscription_deliveries (tenant_id, source_address, state, next_attempt_at_millis, delivery_key)`.withoutTransform;
457
- yield* sql`CREATE INDEX effect_agent_subscription_deliveries_registration ON effect_agent_subscription_deliveries (tenant_id, source_address, owner_id, subscription_id, delivery_key)`.withoutTransform;
458
- yield* sql`PRAGMA user_version = 6`.withoutTransform;
459
- }),
460
- "7_thread_terminology_cutover": Effect.gen(function* () {
461
- yield* (yield* SqlClient.SqlClient)`PRAGMA user_version = 7`.withoutTransform;
462
- })
416
+ yield* sql`CREATE INDEX effect_agent_subscription_deliveries_pending ON effect_agent_subscription_deliveries (tenant_id, source_address, state, next_attempt_at_millis, delivery_key)`.withoutTransform;
417
+ yield* sql`CREATE INDEX effect_agent_subscription_deliveries_registration ON effect_agent_subscription_deliveries (tenant_id, source_address, owner_id, subscription_id, delivery_key)`.withoutTransform;
418
+ yield* sql`PRAGMA user_version = 7`.withoutTransform;
419
+ }) });
420
+ //#endregion
421
+ //#region src/sqlite-activity-store.ts
422
+ const STORAGE_VERSION$1 = 1;
423
+ const METADATA_COMPONENT$1 = "activity";
424
+ const STATE_TABLE = "effect_agent_activity_processor_state_v1";
425
+ const StoredJson$2 = Schema.String.check(Schema.isMaxLength(16777216));
426
+ const sameKey = Schema.toEquivalence(ActivityProcessorKey);
427
+ const sameWork = Schema.toEquivalence(PreparedActivity);
428
+ var ActivityMetadataRow = class extends Schema.Class("@effect-agent/storage-sqlite/ActivityMetadataRow")({ version: Schema.Int }) {};
429
+ var ActivityTableRow = class extends Schema.Class("@effect-agent/storage-sqlite/ActivityTableRow")({ name: Schema.NonEmptyString }) {};
430
+ var ActivityStateRow = class extends Schema.Class("@effect-agent/storage-sqlite/ActivityStateRow")({
431
+ processor_id: ActivityProcessorKey.fields.processorId,
432
+ processor_version: ActivityProcessorKey.fields.processorVersion,
433
+ thread_id: ActivityProcessorKey.fields.threadId,
434
+ format_version: Schema.Int,
435
+ through_sequence: ActivityProgress.fields.throughSequence,
436
+ epoch: ActivityProgress.fields.epoch,
437
+ owner: ActivityProgress.fields.owner,
438
+ lease_expires_at: ActivityProgress.fields.leaseExpiresAt,
439
+ progress_json: StoredJson$2
440
+ }) {};
441
+ var ActivityChangeCountRow = class extends Schema.Class("@effect-agent/storage-sqlite/ActivityChangeCountRow")({ changed: Schema.Int }) {};
442
+ const StoredVersionHeader$1 = Schema.Struct({ version: Schema.Int });
443
+ const storeError$1 = (operation, reason = "unavailable") => ActivityStoreError.make({
444
+ operation,
445
+ reason
446
+ });
447
+ const query$1 = (effect, operation) => effect.pipe(Effect.mapError(() => storeError$1(operation)));
448
+ const decodeRows$4 = Effect.fn("SqliteActivityStore.decodeRows")(function* (schema, rows, operation) {
449
+ return yield* Schema.decodeUnknownEffect(Schema.Array(schema))(rows).pipe(Effect.mapError(() => storeError$1(operation, "corrupt")));
450
+ });
451
+ const decodeInput$2 = Effect.fn("SqliteActivityStore.decodeInput")(function* (schema, value, operation) {
452
+ return yield* Schema.decodeUnknownEffect(schema)(value).pipe(Effect.mapError(() => storeError$1(operation, "invalid-input")));
463
453
  });
454
+ const encodeProgress = Effect.fn("SqliteActivityStore.encodeProgress")(function* (progress, operation) {
455
+ return yield* Schema.encodeEffect(Schema.fromJsonString(ActivityProgress))(progress).pipe(Effect.mapError(() => storeError$1(operation, "corrupt")), Effect.flatMap((encoded) => Schema.decodeEffect(StoredJson$2)(encoded).pipe(Effect.mapError(() => storeError$1(operation, "invalid-input")))));
456
+ });
457
+ const decodeProgress = Effect.fn("SqliteActivityStore.decodeProgress")(function* (value, operation) {
458
+ if ((yield* Schema.decodeEffect(Schema.fromJsonString(StoredVersionHeader$1))(value).pipe(Effect.mapError(() => storeError$1(operation, "corrupt")))).version !== STORAGE_VERSION$1) return yield* storeError$1(operation, "incompatible");
459
+ const progress = yield* Schema.decodeEffect(Schema.fromJsonString(ActivityProgress))(value).pipe(Effect.mapError(() => storeError$1(operation, "corrupt")));
460
+ if ((yield* encodeProgress(progress, operation)) !== value) return yield* storeError$1(operation, "corrupt");
461
+ return progress;
462
+ });
463
+ const validateProgress = Effect.fn("SqliteActivityStore.validateProgress")(function* (progress, operation) {
464
+ if (progress.epoch < 1 || progress.owner === null && progress.leaseExpiresAt !== 0 || progress.pending !== null && (!sameKey(progress.pending.key, progress.key) || progress.pending.sequence !== progress.throughSequence + 1)) return yield* storeError$1(operation, "corrupt");
465
+ return progress;
466
+ });
467
+ const makeClaim = (progress) => progress.owner === null ? null : ActivityClaim.make({
468
+ key: progress.key,
469
+ owner: progress.owner,
470
+ epoch: progress.epoch,
471
+ throughSequence: progress.throughSequence,
472
+ leaseExpiresAt: progress.leaseExpiresAt,
473
+ pending: progress.pending
474
+ });
475
+ const ownershipLost = (claim) => ActivityOwnershipLost.make({
476
+ key: claim.key,
477
+ owner: claim.owner,
478
+ epoch: claim.epoch
479
+ });
480
+ const makeActivityStore = Effect.fn("SqliteActivityStore.make")(function* () {
481
+ const sql = yield* SqlClient.SqlClient;
482
+ const failpoint = yield* ActivityMutationFailpoint;
483
+ yield* failpoint.hit("activity:initialize:before");
484
+ yield* sql.withTransaction(Effect.gen(function* () {
485
+ yield* sql`
486
+ CREATE TABLE IF NOT EXISTS effect_agent_activity_metadata (
487
+ component TEXT PRIMARY KEY NOT NULL,
488
+ version INTEGER NOT NULL
489
+ )
490
+ `;
491
+ const metadataRows = yield* sql`
492
+ SELECT version FROM effect_agent_activity_metadata
493
+ WHERE component = ${METADATA_COMPONENT$1}
494
+ `;
495
+ const metadata = yield* decodeRows$4(ActivityMetadataRow, metadataRows, "decode activity schema version");
496
+ if (metadata.length > 1) return yield* storeError$1("decode activity schema version", "corrupt");
497
+ const currentVersion = metadata[0]?.version;
498
+ if (currentVersion !== void 0 && currentVersion !== STORAGE_VERSION$1) return yield* storeError$1("initialize activity schema", "incompatible");
499
+ if (currentVersion === void 0) {
500
+ const tableRows = yield* sql`
501
+ SELECT name FROM sqlite_master
502
+ WHERE type = 'table' AND name = ${STATE_TABLE}
503
+ `;
504
+ if ((yield* decodeRows$4(ActivityTableRow, tableRows, "inspect activity schema")).length > 0) return yield* storeError$1("initialize activity schema", "incompatible");
505
+ yield* sql`
506
+ CREATE TABLE effect_agent_activity_processor_state_v1 (
507
+ processor_id TEXT NOT NULL,
508
+ processor_version TEXT NOT NULL,
509
+ thread_id TEXT NOT NULL,
510
+ format_version INTEGER NOT NULL,
511
+ through_sequence INTEGER NOT NULL,
512
+ epoch INTEGER NOT NULL,
513
+ owner TEXT,
514
+ lease_expires_at REAL NOT NULL,
515
+ progress_json TEXT NOT NULL,
516
+ PRIMARY KEY (processor_id, processor_version, thread_id)
517
+ )
518
+ `;
519
+ yield* sql`
520
+ INSERT INTO effect_agent_activity_metadata (component, version)
521
+ VALUES (${METADATA_COMPONENT$1}, ${STORAGE_VERSION$1})
522
+ `;
523
+ }
524
+ yield* sql`
525
+ SELECT processor_id, processor_version, thread_id, format_version,
526
+ through_sequence, epoch, owner, lease_expires_at, progress_json
527
+ FROM effect_agent_activity_processor_state_v1
528
+ LIMIT 0
529
+ `;
530
+ })).pipe(Effect.catchTag("SqlError", () => Effect.fail(storeError$1("initialize activity schema"))));
531
+ yield* failpoint.hit("activity:initialize:after");
532
+ const readProgress = Effect.fn("SqliteActivityStore.readProgress")(function* (key, operation) {
533
+ const rawRows = yield* query$1(sql`
534
+ SELECT processor_id, processor_version, thread_id, format_version,
535
+ through_sequence, epoch, owner, lease_expires_at, progress_json
536
+ FROM effect_agent_activity_processor_state_v1
537
+ WHERE processor_id = ${key.processorId}
538
+ AND processor_version = ${key.processorVersion}
539
+ AND thread_id = ${key.threadId}
540
+ `, operation);
541
+ const rows = yield* decodeRows$4(ActivityStateRow, rawRows, operation);
542
+ if (rows.length === 0) return null;
543
+ if (rows.length !== 1) return yield* storeError$1(operation, "corrupt");
544
+ const row = rows[0];
545
+ if (row.format_version !== STORAGE_VERSION$1) return yield* storeError$1(operation, "incompatible");
546
+ const progress = yield* decodeProgress(row.progress_json, operation);
547
+ yield* validateProgress(progress, operation);
548
+ if (!sameKey(progress.key, key) || row.processor_id !== key.processorId || row.processor_version !== key.processorVersion || row.thread_id !== key.threadId || row.through_sequence !== progress.throughSequence || row.epoch !== progress.epoch || row.owner !== progress.owner || row.lease_expires_at !== progress.leaseExpiresAt) return yield* storeError$1(operation, "corrupt");
549
+ return progress;
550
+ });
551
+ const checkChanged = Effect.fn("SqliteActivityStore.checkChanged")(function* (operation) {
552
+ const rawRows = yield* query$1(sql`SELECT changes() AS changed`, operation);
553
+ const rows = yield* decodeRows$4(ActivityChangeCountRow, rawRows, operation);
554
+ if (rows.length !== 1 || rows[0].changed !== 1) return yield* storeError$1(operation, "corrupt");
555
+ });
556
+ const insertProgress = Effect.fn("SqliteActivityStore.insertProgress")(function* (progress, operation) {
557
+ const progressJson = yield* encodeProgress(progress, operation);
558
+ yield* sql`
559
+ INSERT INTO effect_agent_activity_processor_state_v1 (
560
+ processor_id, processor_version, thread_id, format_version, through_sequence,
561
+ epoch, owner, lease_expires_at, progress_json
562
+ ) VALUES (
563
+ ${progress.key.processorId}, ${progress.key.processorVersion}, ${progress.key.threadId},
564
+ ${STORAGE_VERSION$1}, ${progress.throughSequence}, ${progress.epoch}, ${progress.owner},
565
+ ${progress.leaseExpiresAt}, ${progressJson}
566
+ )
567
+ `;
568
+ yield* checkChanged(operation);
569
+ });
570
+ const updateProgress = Effect.fn("SqliteActivityStore.updateProgress")(function* (current, next, operation) {
571
+ const progressJson = yield* encodeProgress(next, operation);
572
+ yield* sql`
573
+ UPDATE effect_agent_activity_processor_state_v1
574
+ SET format_version = ${STORAGE_VERSION$1},
575
+ through_sequence = ${next.throughSequence},
576
+ epoch = ${next.epoch},
577
+ owner = ${next.owner},
578
+ lease_expires_at = ${next.leaseExpiresAt},
579
+ progress_json = ${progressJson}
580
+ WHERE processor_id = ${current.key.processorId}
581
+ AND processor_version = ${current.key.processorVersion}
582
+ AND thread_id = ${current.key.threadId}
583
+ AND through_sequence = ${current.throughSequence}
584
+ AND epoch = ${current.epoch}
585
+ `;
586
+ yield* checkChanged(operation);
587
+ });
588
+ const requireLive = Effect.fn("SqliteActivityStore.requireLive")(function* (progress, claim, requireSequence) {
589
+ const now = yield* Clock.currentTimeMillis;
590
+ if (progress === null || !sameKey(progress.key, claim.key) || progress.owner !== claim.owner || progress.epoch !== claim.epoch || progress.leaseExpiresAt <= now || requireSequence && progress.throughSequence !== claim.throughSequence) return yield* ownershipLost(claim);
591
+ return progress;
592
+ });
593
+ const inspect = Effect.fn("SqliteActivityStore.inspect")(function* (key) {
594
+ const decodedKey = yield* decodeInput$2(ActivityProcessorKey, key, "inspect activity progress");
595
+ return yield* readProgress(decodedKey, "inspect activity progress");
596
+ });
597
+ const claim = Effect.fn("SqliteActivityStore.claim")(function* (request) {
598
+ const operation = "claim activity progress";
599
+ const decoded = yield* decodeInput$2(ActivityClaimRequest, request, operation);
600
+ yield* failpoint.hit("activity:claim:before");
601
+ const claimed = yield* sql.withTransaction(Effect.gen(function* () {
602
+ const current = yield* readProgress(decoded.key, operation);
603
+ const now = yield* Clock.currentTimeMillis;
604
+ if (current !== null && current.owner !== null && current.leaseExpiresAt > now) return yield* ActivityBusy.make({
605
+ key: decoded.key,
606
+ leaseExpiresAt: current.leaseExpiresAt
607
+ });
608
+ const next = yield* Schema.decodeUnknownEffect(ActivityProgress)({
609
+ version: STORAGE_VERSION$1,
610
+ key: decoded.key,
611
+ throughSequence: current?.throughSequence ?? 0,
612
+ epoch: (current?.epoch ?? 0) + 1,
613
+ owner: decoded.owner,
614
+ leaseExpiresAt: now + decoded.leaseMillis,
615
+ pending: current?.pending ?? null,
616
+ advancedAt: current?.advancedAt ?? null
617
+ }).pipe(Effect.mapError(() => storeError$1(operation, "corrupt")));
618
+ if (current === null) yield* insertProgress(next, operation);
619
+ else yield* updateProgress(current, next, operation);
620
+ yield* failpoint.hit("activity:claim:after-state");
621
+ const result = makeClaim(next);
622
+ if (result === null) return yield* storeError$1(operation, "corrupt");
623
+ return result;
624
+ })).pipe(Effect.catchTag("SqlError", () => Effect.fail(storeError$1(operation))));
625
+ yield* failpoint.hit("activity:claim:after");
626
+ return claimed;
627
+ });
628
+ const prepare = Effect.fn("SqliteActivityStore.prepare")(function* (request) {
629
+ const operation = "prepare activity output";
630
+ const claim = yield* decodeInput$2(ActivityClaim, request.claim, operation);
631
+ const work = yield* decodeInput$2(PreparedActivity, request.work, operation);
632
+ yield* failpoint.hit("activity:prepare:before");
633
+ const result = yield* sql.withTransaction(Effect.gen(function* () {
634
+ const current = yield* requireLive(yield* readProgress(claim.key, operation), claim, true);
635
+ if (current.pending !== null) {
636
+ if (sameWork(current.pending, work)) return {
637
+ work: current.pending,
638
+ changed: false
639
+ };
640
+ return yield* ActivityWorkConflict.make({
641
+ key: claim.key,
642
+ workId: work.workId
643
+ });
644
+ }
645
+ if (!sameKey(work.key, claim.key) || work.sequence !== current.throughSequence + 1) return yield* ActivityWorkConflict.make({
646
+ key: claim.key,
647
+ workId: work.workId
648
+ });
649
+ const next = ActivityProgress.make({
650
+ ...current,
651
+ pending: work
652
+ });
653
+ yield* updateProgress(current, next, operation);
654
+ yield* failpoint.hit("activity:prepare:after-state");
655
+ return {
656
+ work,
657
+ changed: true
658
+ };
659
+ })).pipe(Effect.catchTag("SqlError", () => Effect.fail(storeError$1(operation))));
660
+ if (result.changed) yield* failpoint.hit("activity:prepare:after");
661
+ return result.work;
662
+ });
663
+ const advance = Effect.fn("SqliteActivityStore.advance")(function* (request) {
664
+ const operation = "advance activity progress";
665
+ const claim = yield* decodeInput$2(ActivityClaim, request.claim, operation);
666
+ const workId = yield* decodeInput$2(Digest, request.workId, operation);
667
+ yield* failpoint.hit("activity:advance:before");
668
+ const nextClaim = yield* sql.withTransaction(Effect.gen(function* () {
669
+ const current = yield* requireLive(yield* readProgress(claim.key, operation), claim, true);
670
+ if (current.pending === null || current.pending.workId !== workId) return yield* ActivityWorkConflict.make({
671
+ key: claim.key,
672
+ workId
673
+ });
674
+ const next = ActivityProgress.make({
675
+ ...current,
676
+ throughSequence: current.pending.sequence,
677
+ pending: null,
678
+ advancedAt: yield* Clock.currentTimeMillis
679
+ });
680
+ yield* updateProgress(current, next, operation);
681
+ yield* failpoint.hit("activity:advance:after-state");
682
+ const result = makeClaim(next);
683
+ if (result === null) return yield* storeError$1(operation, "corrupt");
684
+ return result;
685
+ })).pipe(Effect.catchTag("SqlError", () => Effect.fail(storeError$1(operation))));
686
+ yield* failpoint.hit("activity:advance:after");
687
+ return nextClaim;
688
+ });
689
+ const release = Effect.fn("SqliteActivityStore.release")(function* (claim) {
690
+ const operation = "release activity claim";
691
+ const decoded = yield* decodeInput$2(ActivityClaim, claim, operation);
692
+ yield* failpoint.hit("activity:release:before");
693
+ yield* sql.withTransaction(Effect.gen(function* () {
694
+ const current = yield* readProgress(decoded.key, operation);
695
+ if (current === null || current.owner !== decoded.owner || current.epoch !== decoded.epoch) return yield* ownershipLost(decoded);
696
+ const next = ActivityProgress.make({
697
+ ...current,
698
+ owner: null,
699
+ leaseExpiresAt: 0
700
+ });
701
+ yield* updateProgress(current, next, operation);
702
+ yield* failpoint.hit("activity:release:after-state");
703
+ })).pipe(Effect.catchTag("SqlError", () => Effect.fail(storeError$1(operation))));
704
+ yield* failpoint.hit("activity:release:after");
705
+ });
706
+ return ActivityProcessorStore.of({
707
+ inspect,
708
+ claim,
709
+ prepare,
710
+ advance,
711
+ release
712
+ });
713
+ });
714
+ /** SQLite activity progress with mutation failpoints kept injectable for recovery tests. */
715
+ const activityProcessorStoreLayerWithFailpoints = Layer.effect(ActivityProcessorStore, makeActivityStore());
716
+ /** SQLite activity progress with the production no-op mutation failpoint. */
717
+ const activityProcessorStoreLayer = activityProcessorStoreLayerWithFailpoints.pipe(Layer.provide(ActivityMutationFailpoint.layer));
464
718
  //#endregion
465
719
  //#region src/sqlite-storage-config.ts
466
720
  const ObservationPollInterval = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));
@@ -493,11 +747,11 @@ var SqliteStorageConfigValue = class extends Schema.Class("@effect-agent/storage
493
747
  var SqliteStorageConfig = class extends Context.Service()("@effect-agent/storage-sqlite/SqliteStorageConfig") {};
494
748
  //#endregion
495
749
  //#region src/sqlite-journal.ts
496
- const BoundedStoredText$1 = Schema.String.check(Schema.isMaxLength(16 * 1024 * 1024));
750
+ const BoundedStoredText$1 = Schema.String.check(Schema.isMaxLength(16777216));
497
751
  const BoundedIdentifier$1 = Schema.NonEmptyString.check(Schema.isMaxLength(1024));
498
752
  const NonNegativeInt = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));
499
753
  const MAX_RECORDS_PER_THREAD = 65536;
500
- const MAX_STORED_TEXT_BYTES = 16 * 1024 * 1024;
754
+ const MAX_STORED_TEXT_BYTES = 16777216;
501
755
  const MAX_IDENTIFIER_LENGTH = 1024;
502
756
  const storedTextBytes = (value) => new TextEncoder().encode(value).byteLength;
503
757
  var SqliteVersionRow = class extends Schema.Class("SqliteVersionRow")({ user_version: NonNegativeInt }) {};
@@ -570,19 +824,19 @@ var RawThreadExport = class extends Schema.Class("@effect-agent/storage-sqlite/R
570
824
  thread: ThreadRow,
571
825
  records: Schema.Array(RecordRow)
572
826
  }) {};
573
- const storageError = (operation) => (error) => SqliteStorageError.make({
827
+ const storageError$1 = (operation) => (error) => SqliteStorageError.make({
574
828
  cause: error,
575
829
  operation,
576
830
  message: error.message
577
831
  });
578
832
  /** Decode raw SQLite rows against a Schema, reporting failures as typed corruption. */
579
- const decodeRows$2 = Effect.fn("SqliteJournal.decodeRows")((schema, table, rowKey, rows) => Schema.decodeUnknownEffect(schema)(rows).pipe(Effect.mapError((error) => SqliteStorageCorruptionError.make({
833
+ const decodeRows$3 = Effect.fn("SqliteJournal.decodeRows")((schema, table, rowKey, rows) => Schema.decodeUnknownEffect(schema)(rows).pipe(Effect.mapError((error) => SqliteStorageCorruptionError.make({
580
834
  table,
581
835
  rowKey,
582
836
  message: String(error)
583
837
  }))));
584
838
  /** Decode exactly one raw SQLite row against a Schema, reporting failures as typed corruption. */
585
- const decodeSingleRow = Effect.fn("SqliteJournal.decodeSingleRow")((schema, table, rowKey, rows) => decodeRows$2(schema, table, rowKey, rows).pipe(Effect.flatMap((decoded) => decoded.length === 1 ? Effect.succeed(decoded[0]) : Effect.fail(SqliteStorageCorruptionError.make({
839
+ const decodeSingleRow = Effect.fn("SqliteJournal.decodeSingleRow")((schema, table, rowKey, rows) => decodeRows$3(schema, table, rowKey, rows).pipe(Effect.flatMap((decoded) => decoded.length === 1 ? Effect.succeed(decoded[0]) : Effect.fail(SqliteStorageCorruptionError.make({
586
840
  table,
587
841
  rowKey,
588
842
  message: `Expected exactly one row but found ${decoded.length}.`
@@ -591,16 +845,16 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
591
845
  const sql = yield* SqlClient.SqlClient;
592
846
  const { hit: failpoint } = yield* SqliteStorageFailpoint;
593
847
  const { busyTimeout } = yield* SqliteStorageConfig;
594
- yield* sql`PRAGMA foreign_keys = ON`.pipe(Effect.mapError(storageError("enable foreign keys")));
595
- yield* sql.unsafe(`PRAGMA busy_timeout = ${busyTimeout}`).pipe(Effect.mapError(storageError("configure busy timeout")));
596
- const journalModeRows = yield* sql`PRAGMA journal_mode`.pipe(Effect.mapError(storageError("read journal mode")));
848
+ yield* sql`PRAGMA foreign_keys = ON`.pipe(Effect.mapError(storageError$1("enable foreign keys")));
849
+ yield* sql.unsafe(`PRAGMA busy_timeout = ${busyTimeout}`).pipe(Effect.mapError(storageError$1("configure busy timeout")));
850
+ const journalModeRows = yield* sql`PRAGMA journal_mode`.pipe(Effect.mapError(storageError$1("read journal mode")));
597
851
  const journalMode = yield* decodeSingleRow(Schema.Array(SqliteJournalModeRow), "pragma_journal_mode", "singleton", journalModeRows);
598
852
  if (journalMode.journal_mode.toLowerCase() !== "wal") return yield* SqliteStorageCompatibilityError.make({
599
853
  actualVersion: 0,
600
854
  supportedVersion: 7,
601
855
  message: `SQLite WAL mode is required; the database reported ${journalMode.journal_mode}.`
602
856
  });
603
- const versionRows = yield* sql`PRAGMA user_version`.pipe(Effect.mapError(storageError("read storage version")));
857
+ const versionRows = yield* sql`PRAGMA user_version`.pipe(Effect.mapError(storageError$1("read storage version")));
604
858
  const version = yield* decodeSingleRow(Schema.Array(SqliteVersionRow), "pragma_user_version", "singleton", versionRows);
605
859
  if (version.user_version !== 0 && version.user_version !== 7) return yield* SqliteStorageCompatibilityError.make({
606
860
  actualVersion: version.user_version,
@@ -614,8 +868,8 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
614
868
  WHERE type = 'table'
615
869
  AND name LIKE 'effect_agent_%'
616
870
  ORDER BY name
617
- `.pipe(Effect.mapError(storageError("inspect unversioned storage")));
618
- if ((yield* decodeRows$2(Schema.Array(SqliteNameRow), "sqlite_master", "effect_agent_%", existingRows)).length > 0) return yield* SqliteStorageCompatibilityError.make({
871
+ `.pipe(Effect.mapError(storageError$1("inspect unversioned storage")));
872
+ if ((yield* decodeRows$3(Schema.Array(SqliteNameRow), "sqlite_master", "effect_agent_%", existingRows)).length > 0) return yield* SqliteStorageCompatibilityError.make({
619
873
  actualVersion: 0,
620
874
  supportedVersion: 7,
621
875
  message: "The SQLite file contains unversioned Effect Agent tables. Reset it explicitly; refusing to mutate ambiguous stored data."
@@ -645,8 +899,8 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
645
899
  'effect_agent_schedules'
646
900
  )
647
901
  ORDER BY name
648
- `.pipe(Effect.mapError(storageError("verify storage tables")));
649
- if ((yield* decodeRows$2(Schema.Array(SqliteNameRow), "sqlite_master", "required_tables", requiredRows)).length !== 12) return yield* SqliteStorageCompatibilityError.make({
902
+ `.pipe(Effect.mapError(storageError$1("verify storage tables")));
903
+ if ((yield* decodeRows$3(Schema.Array(SqliteNameRow), "sqlite_master", "required_tables", requiredRows)).length !== 12) return yield* SqliteStorageCompatibilityError.make({
650
904
  actualVersion: 7,
651
905
  supportedVersion: 7,
652
906
  message: "The SQLite file claims the current format but is missing required tables. Reset the corrupt private-development data."
@@ -655,7 +909,7 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
655
909
  cause: error,
656
910
  operation,
657
911
  message: `Another producer holds the SQLite write lock; ${operation} is safe to retry.`
658
- }) : storageError(operation)(error);
912
+ }) : storageError$1(operation)(error);
659
913
  /**
660
914
  * Runs one journal write transaction under `BEGIN IMMEDIATE`. SQLite's deferred `BEGIN`
661
915
  * would let a read-then-write transaction start as a reader and fail with
@@ -688,11 +942,11 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
688
942
  * `BEGIN` is reported directly because there is no transaction to roll back.
689
943
  */
690
944
  const withReadTransaction = (operation) => (effect) => Effect.uninterruptibleMask((restore) => Effect.scoped(Effect.gen(function* () {
691
- const connection = yield* sql.reserve.pipe(Effect.mapError(storageError(operation)));
692
- yield* connection.executeUnprepared("BEGIN", [], void 0).pipe(Effect.mapError(storageError(operation)));
945
+ const connection = yield* sql.reserve.pipe(Effect.mapError(storageError$1(operation)));
946
+ yield* connection.executeUnprepared("BEGIN", [], void 0).pipe(Effect.mapError(storageError$1(operation)));
693
947
  const exit = yield* restore(Effect.provideService(effect, sql.transactionService, [connection, 0])).pipe(Effect.exit);
694
948
  if (Exit.isSuccess(exit)) {
695
- yield* connection.executeUnprepared("COMMIT", [], void 0).pipe(Effect.mapError(storageError(operation)));
949
+ yield* connection.executeUnprepared("COMMIT", [], void 0).pipe(Effect.mapError(storageError$1(operation)));
696
950
  return exit.value;
697
951
  }
698
952
  yield* Effect.orDie(connection.executeUnprepared("ROLLBACK", [], void 0));
@@ -713,8 +967,8 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
713
967
  producer_epoch
714
968
  FROM effect_agent_threads
715
969
  WHERE thread_id = ${threadId}
716
- `.pipe(Effect.mapError(storageError("read materialized thread")));
717
- const existing = yield* decodeRows$2(Schema.Array(ThreadRow), "effect_agent_threads", threadId, existingRows);
970
+ `.pipe(Effect.mapError(storageError$1("read materialized thread")));
971
+ const existing = yield* decodeRows$3(Schema.Array(ThreadRow), "effect_agent_threads", threadId, existingRows);
718
972
  if (existing.length > 1) return yield* SqliteStorageCorruptionError.make({
719
973
  table: "effect_agent_threads",
720
974
  rowKey: threadId,
@@ -735,7 +989,7 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
735
989
  ${emptyTailDigest},
736
990
  ${producerEpoch}
737
991
  )
738
- `.pipe(Effect.mapError(storageError("materialize thread")));
992
+ `.pipe(Effect.mapError(storageError$1("materialize thread")));
739
993
  return;
740
994
  }
741
995
  if (producerEpoch < existing[0].producer_epoch) return yield* SqliteFenceRejected.make({
@@ -747,7 +1001,7 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
747
1001
  UPDATE effect_agent_threads
748
1002
  SET producer_epoch = ${producerEpoch}
749
1003
  WHERE thread_id = ${threadId}
750
- `.pipe(Effect.mapError(storageError("advance materialization epoch")));
1004
+ `.pipe(Effect.mapError(storageError$1("advance materialization epoch")));
751
1005
  }));
752
1006
  });
753
1007
  const getThread = Effect.fn("SqliteJournal.getThread")(function* (threadId) {
@@ -760,8 +1014,8 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
760
1014
  producer_epoch
761
1015
  FROM effect_agent_threads
762
1016
  WHERE thread_id = ${threadId}
763
- `.pipe(Effect.mapError(storageError("read thread")));
764
- return yield* decodeRows$2(Schema.Array(ThreadRow), "effect_agent_threads", threadId, rows);
1017
+ `.pipe(Effect.mapError(storageError$1("read thread")));
1018
+ return yield* decodeRows$3(Schema.Array(ThreadRow), "effect_agent_threads", threadId, rows);
765
1019
  });
766
1020
  const append = Effect.fn("SqliteJournal.append")(function* (request) {
767
1021
  if (request.threadId.length > MAX_IDENTIFIER_LENGTH || request.batchId.length > MAX_IDENTIFIER_LENGTH || storedTextBytes(request.batchJson) > MAX_STORED_TEXT_BYTES || storedTextBytes(request.batchDigest) > MAX_STORED_TEXT_BYTES || storedTextBytes(request.tailDigest) > MAX_STORED_TEXT_BYTES || request.records.some((record) => record.recordId.length > MAX_IDENTIFIER_LENGTH || storedTextBytes(record.recordJson) > MAX_STORED_TEXT_BYTES)) return yield* SqliteStorageError.make({
@@ -783,7 +1037,7 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
783
1037
  producer_epoch
784
1038
  FROM effect_agent_threads
785
1039
  WHERE thread_id = ${request.threadId}
786
- `.pipe(Effect.mapError(storageError("read append tail")));
1040
+ `.pipe(Effect.mapError(storageError$1("read append tail")));
787
1041
  const thread = yield* decodeSingleRow(Schema.Array(ThreadRow), "effect_agent_threads", request.threadId, threadRows);
788
1042
  if (request.producerEpoch !== thread.producer_epoch) return yield* SqliteFenceRejected.make({
789
1043
  producerEpoch: request.producerEpoch,
@@ -802,8 +1056,8 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
802
1056
  FROM effect_agent_canonical_batches
803
1057
  WHERE thread_id = ${request.threadId}
804
1058
  AND batch_id = ${request.batchId}
805
- `.pipe(Effect.mapError(storageError("read idempotent batch")));
806
- const batches = yield* decodeRows$2(Schema.Array(BatchRow), "effect_agent_canonical_batches", `${request.threadId}/${request.batchId}`, batchRows);
1059
+ `.pipe(Effect.mapError(storageError$1("read idempotent batch")));
1060
+ const batches = yield* decodeRows$3(Schema.Array(BatchRow), "effect_agent_canonical_batches", `${request.threadId}/${request.batchId}`, batchRows);
807
1061
  if (batches.length > 1) return yield* SqliteStorageCorruptionError.make({
808
1062
  table: "effect_agent_canonical_batches",
809
1063
  rowKey: `${request.threadId}/${request.batchId}`,
@@ -843,8 +1097,8 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
843
1097
  WHERE thread_id = ${request.threadId}
844
1098
  AND record_id IN ${sql.in(recordIds)}
845
1099
  ORDER BY sequence
846
- `.pipe(Effect.mapError(storageError("check canonical record identities")));
847
- const existingRecords = yield* decodeRows$2(Schema.Array(RecordRow), "effect_agent_canonical_records", `${request.threadId}/record_ids`, existingRecordRows);
1100
+ `.pipe(Effect.mapError(storageError$1("check canonical record identities")));
1101
+ const existingRecords = yield* decodeRows$3(Schema.Array(RecordRow), "effect_agent_canonical_records", `${request.threadId}/record_ids`, existingRecordRows);
848
1102
  if (existingRecords.length > 0) return yield* SqliteAppendConflict.make({
849
1103
  message: `Canonical record ID ${existingRecords[0].record_id} already exists.`,
850
1104
  reason: "record-identity"
@@ -877,7 +1131,7 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
877
1131
  ${request.tailDigest},
878
1132
  ${request.batchJson}
879
1133
  )
880
- `.pipe(Effect.mapError(storageError("insert canonical batch")));
1134
+ `.pipe(Effect.mapError(storageError$1("insert canonical batch")));
881
1135
  yield* failpoint("append:after-batch-insert");
882
1136
  yield* Effect.forEach(request.records, (record, index) => Effect.gen(function* () {
883
1137
  yield* sql`
@@ -894,7 +1148,7 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
894
1148
  ${request.batchId},
895
1149
  ${record.recordJson}
896
1150
  )
897
- `.pipe(Effect.mapError(storageError("insert canonical record")));
1151
+ `.pipe(Effect.mapError(storageError$1("insert canonical record")));
898
1152
  yield* failpoint("append:after-record-insert");
899
1153
  }), { discard: true });
900
1154
  yield* sql`
@@ -904,7 +1158,7 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
904
1158
  tail_digest = ${request.tailDigest},
905
1159
  producer_epoch = ${request.producerEpoch}
906
1160
  WHERE thread_id = ${request.threadId}
907
- `.pipe(Effect.mapError(storageError("advance thread tail")));
1161
+ `.pipe(Effect.mapError(storageError$1("advance thread tail")));
908
1162
  yield* failpoint("append:after-tail-update");
909
1163
  return RawAppendResult.make({
910
1164
  firstSequence,
@@ -927,8 +1181,8 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
927
1181
  AND sequence > ${request.fromSequenceExclusive}
928
1182
  ORDER BY sequence
929
1183
  LIMIT ${request.limit}
930
- `.pipe(Effect.mapError(storageError("read canonical records")));
931
- return yield* decodeRows$2(Schema.Array(RecordRow), "effect_agent_canonical_records", `${request.threadId}>${request.fromSequenceExclusive}`, rows);
1184
+ `.pipe(Effect.mapError(storageError$1("read canonical records")));
1185
+ return yield* decodeRows$3(Schema.Array(RecordRow), "effect_agent_canonical_records", `${request.threadId}>${request.fromSequenceExclusive}`, rows);
932
1186
  });
933
1187
  const exportThread = Effect.fn("SqliteJournal.exportThread")(function* (threadId) {
934
1188
  return yield* withReadTransaction("export transaction")(Effect.gen(function* () {
@@ -941,7 +1195,7 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
941
1195
  producer_epoch
942
1196
  FROM effect_agent_threads
943
1197
  WHERE thread_id = ${threadId}
944
- `.pipe(Effect.mapError(storageError("export thread")));
1198
+ `.pipe(Effect.mapError(storageError$1("export thread")));
945
1199
  const thread = yield* decodeSingleRow(Schema.Array(ThreadRow), "effect_agent_threads", threadId, threadRows);
946
1200
  yield* failpoint("export:after-thread-read");
947
1201
  const batchRows = yield* sql`
@@ -956,7 +1210,7 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
956
1210
  FROM effect_agent_canonical_batches
957
1211
  WHERE thread_id = ${threadId}
958
1212
  ORDER BY first_sequence
959
- `.pipe(Effect.mapError(storageError("export canonical batches")));
1213
+ `.pipe(Effect.mapError(storageError$1("export canonical batches")));
960
1214
  const recordRows = yield* sql`
961
1215
  SELECT
962
1216
  thread_id,
@@ -967,7 +1221,7 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
967
1221
  FROM effect_agent_canonical_records
968
1222
  WHERE thread_id = ${threadId}
969
1223
  ORDER BY sequence
970
- `.pipe(Effect.mapError(storageError("export canonical records")));
1224
+ `.pipe(Effect.mapError(storageError$1("export canonical records")));
971
1225
  const checkpointRows = yield* sql`
972
1226
  SELECT
973
1227
  thread_id,
@@ -977,12 +1231,12 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
977
1231
  FROM effect_agent_checkpoints
978
1232
  WHERE thread_id = ${threadId}
979
1233
  ORDER BY through_sequence
980
- `.pipe(Effect.mapError(storageError("export checkpoints")));
1234
+ `.pipe(Effect.mapError(storageError$1("export checkpoints")));
981
1235
  return RawThreadExport.make({
982
1236
  thread,
983
- batches: yield* decodeRows$2(Schema.Array(BatchRow), "effect_agent_canonical_batches", threadId, batchRows),
984
- records: yield* decodeRows$2(Schema.Array(RecordRow), "effect_agent_canonical_records", threadId, recordRows),
985
- checkpoints: yield* decodeRows$2(Schema.Array(CheckpointRow), "effect_agent_checkpoints", threadId, checkpointRows)
1237
+ batches: yield* decodeRows$3(Schema.Array(BatchRow), "effect_agent_canonical_batches", threadId, batchRows),
1238
+ records: yield* decodeRows$3(Schema.Array(RecordRow), "effect_agent_canonical_records", threadId, recordRows),
1239
+ checkpoints: yield* decodeRows$3(Schema.Array(CheckpointRow), "effect_agent_checkpoints", threadId, checkpointRows)
986
1240
  });
987
1241
  }));
988
1242
  });
@@ -1001,7 +1255,7 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
1001
1255
  producer_epoch
1002
1256
  FROM effect_agent_threads
1003
1257
  WHERE thread_id = ${checkpoint.threadId}
1004
- `.pipe(Effect.mapError(storageError("read checkpoint tail")));
1258
+ `.pipe(Effect.mapError(storageError$1("read checkpoint tail")));
1005
1259
  const thread = yield* decodeSingleRow(Schema.Array(ThreadRow), "effect_agent_threads", checkpoint.threadId, threadRows);
1006
1260
  if (checkpoint.throughSequence > thread.tail_sequence) return yield* SqliteCheckpointConflict.make({ message: `Checkpoint sequence ${checkpoint.throughSequence} is after canonical tail ${thread.tail_sequence}.` });
1007
1261
  const checkpointRows = yield* sql`
@@ -1013,8 +1267,8 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
1013
1267
  FROM effect_agent_checkpoints
1014
1268
  WHERE thread_id = ${checkpoint.threadId}
1015
1269
  AND through_sequence = ${checkpoint.throughSequence}
1016
- `.pipe(Effect.mapError(storageError("read idempotent checkpoint")));
1017
- const existing = yield* decodeRows$2(Schema.Array(CheckpointRow), "effect_agent_checkpoints", `${checkpoint.threadId}/${checkpoint.throughSequence}`, checkpointRows);
1270
+ `.pipe(Effect.mapError(storageError$1("read idempotent checkpoint")));
1271
+ const existing = yield* decodeRows$3(Schema.Array(CheckpointRow), "effect_agent_checkpoints", `${checkpoint.threadId}/${checkpoint.throughSequence}`, checkpointRows);
1018
1272
  if (existing.length > 1) return yield* SqliteStorageCorruptionError.make({
1019
1273
  table: "effect_agent_checkpoints",
1020
1274
  rowKey: `${checkpoint.threadId}/${checkpoint.throughSequence}`,
@@ -1036,7 +1290,7 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
1036
1290
  ${checkpoint.tailDigest},
1037
1291
  ${checkpoint.checkpointJson}
1038
1292
  )
1039
- `.pipe(Effect.mapError(storageError("insert checkpoint")));
1293
+ `.pipe(Effect.mapError(storageError$1("insert checkpoint")));
1040
1294
  }));
1041
1295
  });
1042
1296
  const loadCheckpoint = Effect.fn("SqliteJournal.loadCheckpoint")(function* (threadId, atOrBeforeSequence) {
@@ -1051,8 +1305,8 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
1051
1305
  AND through_sequence <= ${atOrBeforeSequence}
1052
1306
  ORDER BY through_sequence DESC
1053
1307
  LIMIT 1
1054
- `.pipe(Effect.mapError(storageError("load checkpoint")));
1055
- return yield* decodeRows$2(Schema.Array(CheckpointRow), "effect_agent_checkpoints", `${threadId}<=${atOrBeforeSequence}`, rows);
1308
+ `.pipe(Effect.mapError(storageError$1("load checkpoint")));
1309
+ return yield* decodeRows$3(Schema.Array(CheckpointRow), "effect_agent_checkpoints", `${threadId}<=${atOrBeforeSequence}`, rows);
1056
1310
  });
1057
1311
  return {
1058
1312
  append,
@@ -1075,8 +1329,8 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
1075
1329
  FROM effect_agent_canonical_batches
1076
1330
  WHERE thread_id = ${threadId}
1077
1331
  AND last_sequence = ${sequence}
1078
- `.pipe(Effect.mapError(storageError("read canonical digest at sequence")));
1079
- return (yield* decodeRows$2(Schema.Array(BatchRow), "effect_agent_canonical_batches", `${threadId}/${sequence}`, rows)).map((batch) => batch.tail_digest);
1332
+ `.pipe(Effect.mapError(storageError$1("read canonical digest at sequence")));
1333
+ return (yield* decodeRows$3(Schema.Array(BatchRow), "effect_agent_canonical_batches", `${threadId}/${sequence}`, rows)).map((batch) => batch.tail_digest);
1080
1334
  }),
1081
1335
  loadCheckpoint,
1082
1336
  materialize,
@@ -1093,7 +1347,7 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
1093
1347
  producer_epoch
1094
1348
  FROM effect_agent_threads
1095
1349
  ORDER BY thread_id
1096
- `.pipe(Effect.mapError(storageError("scan threads")));
1350
+ `.pipe(Effect.mapError(storageError$1("scan threads")));
1097
1351
  const batches = yield* sql`
1098
1352
  SELECT
1099
1353
  thread_id,
@@ -1105,7 +1359,7 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
1105
1359
  batch_json
1106
1360
  FROM effect_agent_canonical_batches
1107
1361
  ORDER BY thread_id, first_sequence
1108
- `.pipe(Effect.mapError(storageError("scan canonical batches")));
1362
+ `.pipe(Effect.mapError(storageError$1("scan canonical batches")));
1109
1363
  const records = yield* sql`
1110
1364
  SELECT
1111
1365
  thread_id,
@@ -1115,7 +1369,7 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
1115
1369
  record_json
1116
1370
  FROM effect_agent_canonical_records
1117
1371
  ORDER BY thread_id, sequence
1118
- `.pipe(Effect.mapError(storageError("scan canonical records")));
1372
+ `.pipe(Effect.mapError(storageError$1("scan canonical records")));
1119
1373
  const checkpoints = yield* sql`
1120
1374
  SELECT
1121
1375
  thread_id,
@@ -1124,12 +1378,12 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
1124
1378
  checkpoint_json
1125
1379
  FROM effect_agent_checkpoints
1126
1380
  ORDER BY thread_id, through_sequence
1127
- `.pipe(Effect.mapError(storageError("scan checkpoints")));
1381
+ `.pipe(Effect.mapError(storageError$1("scan checkpoints")));
1128
1382
  return {
1129
- threads: yield* decodeRows$2(Schema.Array(ThreadRow), "effect_agent_threads", "startup_scan", threads),
1130
- batches: yield* decodeRows$2(Schema.Array(BatchRow), "effect_agent_canonical_batches", "startup_scan", batches),
1131
- records: yield* decodeRows$2(Schema.Array(RecordRow), "effect_agent_canonical_records", "startup_scan", records),
1132
- checkpoints: yield* decodeRows$2(Schema.Array(CheckpointRow), "effect_agent_checkpoints", "startup_scan", checkpoints)
1383
+ threads: yield* decodeRows$3(Schema.Array(ThreadRow), "effect_agent_threads", "startup_scan", threads),
1384
+ batches: yield* decodeRows$3(Schema.Array(BatchRow), "effect_agent_canonical_batches", "startup_scan", batches),
1385
+ records: yield* decodeRows$3(Schema.Array(RecordRow), "effect_agent_canonical_records", "startup_scan", records),
1386
+ checkpoints: yield* decodeRows$3(Schema.Array(CheckpointRow), "effect_agent_checkpoints", "startup_scan", checkpoints)
1133
1387
  };
1134
1388
  }));
1135
1389
  }),
@@ -1138,7 +1392,7 @@ const initializeSqliteJournal = Effect.fn("SqliteJournal.initialize")(function*
1138
1392
  });
1139
1393
  //#endregion
1140
1394
  //#region src/sqlite-thread-store.ts
1141
- const OffsetText = Schema.String.check(Schema.isMaxLength(4 * 1024));
1395
+ const OffsetText = Schema.String.check(Schema.isMaxLength(4096));
1142
1396
  const SQLITE_OFFSET_PREFIX = "effect-agent-sqlite@1:";
1143
1397
  const ZERO_CANONICAL_SEQUENCE = Schema.decodeSync(CanonicalSequence)(0);
1144
1398
  const isDigest = Schema.is(Digest);
@@ -1541,7 +1795,7 @@ const layer = (options) => Layer.unwrap(Effect.map(SqliteStorageConfig, (config)
1541
1795
  const observationOffsetAt = makeOffset;
1542
1796
  //#endregion
1543
1797
  //#region src/sqlite-ledger.ts
1544
- const BoundedStoredText = Schema.String.check(Schema.isMaxLength(16 * 1024 * 1024));
1798
+ const BoundedStoredText = Schema.String.check(Schema.isMaxLength(16777216));
1545
1799
  const BoundedIdentifier = Schema.NonEmptyString.check(Schema.isMaxLength(1024));
1546
1800
  const BoundedTimestamp = Schema.NonEmptyString.check(Schema.isMaxLength(128));
1547
1801
  const SCAN_PAGE_SIZE = 256;
@@ -1750,7 +2004,7 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
1750
2004
  iso: new Date(millis).toISOString()
1751
2005
  }));
1752
2006
  const timestampMillis = (operation, rowKey) => (timestamp) => decodeUtcInstant(timestamp).pipe(Effect.map(DateTime.toEpochMillis), Effect.mapError((error) => corruptionFailure(operation, "effect_agent_submission_ownership", rowKey, error.message)));
1753
- const decodeSubmissionRows = (operation, rowKey, rows) => decodeRows$2(Schema.Array(SubmissionRow), "effect_agent_submissions", rowKey, rows).pipe(Effect.mapError(internalFailure(operation)));
2007
+ const decodeSubmissionRows = (operation, rowKey, rows) => decodeRows$3(Schema.Array(SubmissionRow), "effect_agent_submissions", rowKey, rows).pipe(Effect.mapError(internalFailure(operation)));
1754
2008
  const readSubmission = Effect.fn("SqliteSubmissionLedger.readSubmission")(function* (operation, submissionId) {
1755
2009
  const rows = yield* sql`
1756
2010
  SELECT ${sql.literal(SUBMISSION_COLUMNS)}
@@ -1781,7 +2035,7 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
1781
2035
  FROM effect_agent_submission_ownership
1782
2036
  WHERE submission_id = ${submissionId}
1783
2037
  `.pipe(Effect.mapError(sqlFailure(operation)));
1784
- const decoded = yield* decodeRows$2(Schema.Array(OwnershipRow), "effect_agent_submission_ownership", submissionId, rows).pipe(Effect.mapError(internalFailure(operation)));
2038
+ const decoded = yield* decodeRows$3(Schema.Array(OwnershipRow), "effect_agent_submission_ownership", submissionId, rows).pipe(Effect.mapError(internalFailure(operation)));
1785
2039
  if (decoded.length > 1) return yield* corruptionFailure(operation, "effect_agent_submission_ownership", submissionId, "An ownership primary key returned more than one row.");
1786
2040
  return decoded.length === 0 ? Option.none() : Option.some(decoded[0]);
1787
2041
  });
@@ -1846,7 +2100,7 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
1846
2100
  FROM effect_agent_settlement_reservations
1847
2101
  WHERE submission_id = ${submissionId}
1848
2102
  `.pipe(Effect.mapError(sqlFailure(operation)));
1849
- const decoded = yield* decodeRows$2(Schema.Array(ReservationRow), "effect_agent_settlement_reservations", submissionId, rows).pipe(Effect.mapError(internalFailure(operation)));
2103
+ const decoded = yield* decodeRows$3(Schema.Array(ReservationRow), "effect_agent_settlement_reservations", submissionId, rows).pipe(Effect.mapError(internalFailure(operation)));
1850
2104
  if (decoded.length > 1) return yield* corruptionFailure(operation, "effect_agent_settlement_reservations", submissionId, "A settlement reservation primary key returned more than one row.");
1851
2105
  return decoded.length === 0 ? Option.none() : Option.some(decoded[0]);
1852
2106
  });
@@ -1861,11 +2115,11 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
1861
2115
  FROM effect_agent_abort_intents
1862
2116
  WHERE submission_id = ${submissionId}
1863
2117
  `.pipe(Effect.mapError(sqlFailure(operation)));
1864
- const decoded = yield* decodeRows$2(Schema.Array(AbortIntentRow), "effect_agent_abort_intents", submissionId, rows).pipe(Effect.mapError(internalFailure(operation)));
2118
+ const decoded = yield* decodeRows$3(Schema.Array(AbortIntentRow), "effect_agent_abort_intents", submissionId, rows).pipe(Effect.mapError(internalFailure(operation)));
1865
2119
  if (decoded.length > 1) return yield* corruptionFailure(operation, "effect_agent_abort_intents", submissionId, "An abort intent primary key returned more than one row.");
1866
2120
  return decoded.length === 0 ? Option.none() : Option.some(decoded[0]);
1867
2121
  });
1868
- const decodeChildReservationRows = (operation, rowKey, rows) => decodeRows$2(Schema.Array(ChildReservationRow), "effect_agent_child_reservations", rowKey, rows).pipe(Effect.mapError(internalFailure(operation)));
2122
+ const decodeChildReservationRows = (operation, rowKey, rows) => decodeRows$3(Schema.Array(ChildReservationRow), "effect_agent_child_reservations", rowKey, rows).pipe(Effect.mapError(internalFailure(operation)));
1869
2123
  const readChildReservation = Effect.fn("SqliteSubmissionLedger.readChildReservation")(function* (operation, reservationId) {
1870
2124
  const rows = yield* sql`
1871
2125
  SELECT ${sql.literal(CHILD_RESERVATION_COLUMNS)}
@@ -1918,7 +2172,7 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
1918
2172
  WHERE submission_id = ${submissionId}
1919
2173
  ORDER BY tool_call_id ASC
1920
2174
  `.pipe(Effect.mapError(sqlFailure(operation)));
1921
- return yield* decodeRows$2(Schema.Array(ApprovalDecisionRow), "effect_agent_approval_decisions", submissionId, rows).pipe(Effect.mapError(internalFailure(operation)));
2175
+ return yield* decodeRows$3(Schema.Array(ApprovalDecisionRow), "effect_agent_approval_decisions", submissionId, rows).pipe(Effect.mapError(internalFailure(operation)));
1922
2176
  });
1923
2177
  const approvalIntentFromRow = Effect.fn("SqliteSubmissionLedger.approvalIntentFromRow")(function* (operation, row) {
1924
2178
  return yield* decodeApprovalDecisionIntent({
@@ -1943,7 +2197,7 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
1943
2197
  WHERE submission_id = ${submissionId}
1944
2198
  ORDER BY tool_call_id ASC
1945
2199
  `.pipe(Effect.mapError(sqlFailure(operation)));
1946
- return yield* decodeRows$2(Schema.Array(UnknownResolutionRow), "effect_agent_unknown_resolutions", submissionId, rows).pipe(Effect.mapError(internalFailure(operation)));
2200
+ return yield* decodeRows$3(Schema.Array(UnknownResolutionRow), "effect_agent_unknown_resolutions", submissionId, rows).pipe(Effect.mapError(internalFailure(operation)));
1947
2201
  });
1948
2202
  const unknownResolutionIntentFromRow = Effect.fn("SqliteSubmissionLedger.unknownResolutionIntentFromRow")(function* (operation, row) {
1949
2203
  const resolution = yield* parseStoredJsonText(row.resolution_json).pipe(Effect.mapError((error) => corruptionFailure(operation, "effect_agent_unknown_resolutions", `${row.submission_id}/${row.tool_call_id}`, error.message)));
@@ -1974,7 +2228,7 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
1974
2228
  WHERE thread_id = ${threadId}
1975
2229
  AND record_id = ${recordId}
1976
2230
  `.pipe(Effect.mapError(sqlFailure(operation)));
1977
- return (yield* decodeRows$2(Schema.Array(CanonicalRecordIdRow), "effect_agent_canonical_records", `${threadId}/${recordId}`, rows).pipe(Effect.mapError(internalFailure(operation)))).length === 0 ? void 0 : recordId;
2231
+ return (yield* decodeRows$3(Schema.Array(CanonicalRecordIdRow), "effect_agent_canonical_records", `${threadId}/${recordId}`, rows).pipe(Effect.mapError(internalFailure(operation)))).length === 0 ? void 0 : recordId;
1978
2232
  });
1979
2233
  const abortIntentFromRow = Effect.fn("SqliteSubmissionLedger.abortIntentFromRow")(function* (operation, submission, submissionId, row) {
1980
2234
  const canonicalRecordId = yield* canonicalAbortRecordId(operation, submission.thread_id, submissionId);
@@ -2028,7 +2282,7 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
2028
2282
  FROM effect_agent_submissions
2029
2283
  WHERE thread_id = ${validated.threadId}
2030
2284
  `.pipe(Effect.mapError(sqlFailure(operation)));
2031
- const decodedMax = yield* decodeRows$2(Schema.Array(MaxQueueSequenceRow), "effect_agent_submissions", validated.threadId, maxRows).pipe(Effect.mapError(internalFailure(operation)));
2285
+ const decodedMax = yield* decodeRows$3(Schema.Array(MaxQueueSequenceRow), "effect_agent_submissions", validated.threadId, maxRows).pipe(Effect.mapError(internalFailure(operation)));
2032
2286
  const queueSequence = yield* decodeQueueSequence((decodedMax[0]?.max_queue_sequence ?? 0) + 1).pipe(Effect.mapError(internalFailure(operation)));
2033
2287
  const now = yield* currentInstant;
2034
2288
  yield* sql`
@@ -2395,7 +2649,8 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
2395
2649
  submissionId: validated.submissionId,
2396
2650
  existingOutcome: reservation.value.outcome
2397
2651
  });
2398
- const settlementFailure = settlementFailureFromRecord(yield* decodeRecordEnvelopeText(reservation.value.record_json).pipe(Effect.mapError((error) => corruptionFailure(operation, "effect_agent_settlement_reservations", validated.submissionId, error.message))));
2652
+ const reservationRecord = yield* decodeRecordEnvelopeText(reservation.value.record_json).pipe(Effect.mapError((error) => corruptionFailure(operation, "effect_agent_settlement_reservations", validated.submissionId, error.message)));
2653
+ const settlementFailure = settlementFailureFromRecord(reservationRecord);
2399
2654
  if (reservation.value.outcome === "failed" !== (settlementFailure !== void 0)) return yield* corruptionFailure(operation, "effect_agent_settlement_reservations", validated.submissionId, "The reserved outcome and canonical failure diagnostic disagree.");
2400
2655
  const submission = yield* requireSubmission(operation, validated.submissionId);
2401
2656
  if (submission.state === "settled") {
@@ -3175,8 +3430,308 @@ const submissionLedgerLayer = Layer.effectContext(makeServices());
3175
3430
  */
3176
3431
  const ledgerLayer = (options) => Layer.unwrap(Effect.map(SqliteStorageConfig, (config) => submissionLedgerLayer.pipe(Layer.provide(Layer.mergeAll(Layer.succeed(SqliteStorageConfig)(config), storageFailpointLayer(options), SqliteClient.layer({ filename: options.filename }), NodeCrypto.layer))))).pipe(Layer.provide(storageConfigLayer(options)));
3177
3432
  //#endregion
3433
+ //#region src/sqlite-memory-store.ts
3434
+ const STORAGE_VERSION = 2;
3435
+ const METADATA_COMPONENT = "memory";
3436
+ const DOCUMENT_TABLE = "effect_agent_memory_documents_v1";
3437
+ const RECEIPT_TABLE = "effect_agent_memory_receipts_v1";
3438
+ const StoredJson$1 = Schema.String.check(Schema.isMaxLength(16777216));
3439
+ const EncodedMemoryChange = Schema.Struct({
3440
+ commandJson: StoredJson$1,
3441
+ documentJson: StoredJson$1,
3442
+ resultJson: StoredJson$1
3443
+ });
3444
+ const equivalentContent = Schema.toEquivalence(MemoryWrite.Wire.members[0].fields.content);
3445
+ const equivalentScopes = Schema.toEquivalence(MemoryWrite.Wire.members[0].fields.scopes);
3446
+ var MemoryMetadataRow = class extends Schema.Class("@effect-agent/storage-sqlite/MemoryMetadataRow")({ version: Schema.Int }) {};
3447
+ var MemoryTableRow = class extends Schema.Class("@effect-agent/storage-sqlite/MemoryTableRow")({ name: Schema.NonEmptyString }) {};
3448
+ var MemoryDocumentRow = class extends Schema.Class("@effect-agent/storage-sqlite/MemoryDocumentRow")({
3449
+ namespace: MemoryNamespaceAddress,
3450
+ source_id: MemoryKey.Wire.fields.id,
3451
+ format_version: Schema.Int,
3452
+ generation: Schema.Int,
3453
+ revision: Schema.NonEmptyString,
3454
+ document_json: StoredJson$1
3455
+ }) {};
3456
+ var MemoryReceiptRow = class extends Schema.Class("@effect-agent/storage-sqlite/MemoryReceiptRow")({
3457
+ namespace: MemoryNamespaceAddress,
3458
+ operation_id: MemoryWrite.Wire.members[0].fields.operationId,
3459
+ source_id: MemoryKey.Wire.fields.id,
3460
+ format_version: Schema.Int,
3461
+ command_json: StoredJson$1,
3462
+ result_json: StoredJson$1
3463
+ }) {};
3464
+ var MemoryChangeCountRow = class extends Schema.Class("@effect-agent/storage-sqlite/MemoryChangeCountRow")({ changed: Schema.Int }) {};
3465
+ var StoredMemoryCommand = class extends Schema.Class("@effect-agent/storage-sqlite/StoredMemoryCommand")({
3466
+ version: Schema.Literal(STORAGE_VERSION),
3467
+ value: MemoryWrite.Wire
3468
+ }) {};
3469
+ var StoredMemoryResult = class extends Schema.Class("@effect-agent/storage-sqlite/StoredMemoryResult")({
3470
+ version: Schema.Literal(STORAGE_VERSION),
3471
+ value: MemoryDocument.Wire
3472
+ }) {};
3473
+ const StoredVersionHeader = Schema.Struct({ version: Schema.Int });
3474
+ const storageError = (operation, reason = "unavailable") => MemoryStorageError.make({
3475
+ operation,
3476
+ reason
3477
+ });
3478
+ const query = (effect, operation) => effect.pipe(Effect.mapError(() => storageError(operation)));
3479
+ const decodeRows$2 = Effect.fn("SqliteMemoryStore.decodeRows")(function* (schema, rows, operation) {
3480
+ return yield* Schema.decodeUnknownEffect(Schema.Array(schema))(rows).pipe(Effect.mapError(() => storageError(operation, "corrupt")));
3481
+ });
3482
+ const decodeInput$1 = Effect.fn("SqliteMemoryStore.decodeInput")(function* (schema, value, operation) {
3483
+ return yield* Schema.decodeUnknownEffect(schema)(value).pipe(Effect.mapError(() => storageError(operation, "invalid-input")));
3484
+ });
3485
+ const encodeJson = Effect.fn("SqliteMemoryStore.encodeJson")(function* (schema, value, operation) {
3486
+ return yield* Schema.encodeEffect(Schema.fromJsonString(schema))(value).pipe(Effect.mapError(() => storageError(operation, "corrupt")));
3487
+ });
3488
+ const validateEncodedChange = Effect.fn("SqliteMemoryStore.validateEncodedChange")(function* (encoded, operation) {
3489
+ yield* Schema.decodeEffect(EncodedMemoryChange)(encoded).pipe(Effect.mapError(() => storageError(operation, "invalid-input")));
3490
+ });
3491
+ const decodeVersionedJson = Effect.fn("SqliteMemoryStore.decodeVersionedJson")(function* (schema, value, operation) {
3492
+ if ((yield* Schema.decodeEffect(Schema.fromJsonString(StoredVersionHeader))(value).pipe(Effect.mapError(() => storageError(operation, "corrupt")))).version !== STORAGE_VERSION) return yield* storageError(operation, "incompatible");
3493
+ const decoded = yield* Schema.decodeEffect(Schema.fromJsonString(schema))(value).pipe(Effect.mapError(() => storageError(operation, "corrupt")));
3494
+ if ((yield* encodeJson(schema, decoded, operation)) !== value) return yield* storageError(operation, "corrupt");
3495
+ return decoded;
3496
+ });
3497
+ const validateDocument = Effect.fn("SqliteMemoryStore.validateDocument")(function* (document, key, operation) {
3498
+ if (document.key.namespace.address !== key.namespace.address || document.key.id !== key.id || document.source.id !== key.id || document.source.revision !== String(document.generation) || document.generation === 1 !== (document.predecessor === null) || document.predecessor !== null && (document.predecessor.id !== key.id || document.predecessor.revision !== String(document.generation - 1))) return yield* storageError(operation, "corrupt");
3499
+ return document;
3500
+ });
3501
+ const validateReceiptResult = Effect.fn("SqliteMemoryStore.validateReceiptResult")(function* (command, result, operation) {
3502
+ if ((result.predecessor?.revision ?? null) !== command.expectedRevision) return yield* storageError(operation, "corrupt");
3503
+ if (command._tag === "Put") {
3504
+ if (result._tag !== "ActiveMemoryDocument" || result.source.locator !== command.locator) return yield* storageError(operation, "corrupt");
3505
+ if (!equivalentContent(command.content, result.content) || !equivalentScopes(command.scopes, result.scopes)) return yield* storageError(operation, "corrupt");
3506
+ return;
3507
+ }
3508
+ if (result._tag !== "WithdrawnMemoryDocument" || result.reason !== command.reason || result.predecessor === null || result.source.locator !== result.predecessor.locator) return yield* storageError(operation, "corrupt");
3509
+ });
3510
+ const initializeMemorySchema = Effect.fn("SqliteMemoryStore.initialize")(function* () {
3511
+ const sql = yield* SqlClient.SqlClient;
3512
+ const failpoint = yield* MemoryMutationFailpoint;
3513
+ yield* failpoint.hit("memory:initialize:before");
3514
+ yield* sql.withTransaction(Effect.gen(function* () {
3515
+ yield* sql`
3516
+ CREATE TABLE IF NOT EXISTS effect_agent_memory_metadata (
3517
+ component TEXT PRIMARY KEY NOT NULL,
3518
+ version INTEGER NOT NULL
3519
+ )
3520
+ `;
3521
+ const metadataRows = yield* sql`
3522
+ SELECT version
3523
+ FROM effect_agent_memory_metadata
3524
+ WHERE component = ${METADATA_COMPONENT}
3525
+ `;
3526
+ const metadata = yield* decodeRows$2(MemoryMetadataRow, metadataRows, "decode memory schema version");
3527
+ if (metadata.length > 1) return yield* storageError("decode memory schema version", "corrupt");
3528
+ const currentVersion = metadata[0]?.version;
3529
+ if (currentVersion !== void 0 && currentVersion !== STORAGE_VERSION) return yield* storageError("initialize memory schema", "incompatible");
3530
+ if (currentVersion === void 0) {
3531
+ const tableRows = yield* sql`
3532
+ SELECT name
3533
+ FROM sqlite_master
3534
+ WHERE type = 'table' AND name IN (${DOCUMENT_TABLE}, ${RECEIPT_TABLE})
3535
+ `;
3536
+ if ((yield* decodeRows$2(MemoryTableRow, tableRows, "inspect memory schema")).length > 0) return yield* storageError("initialize memory schema", "incompatible");
3537
+ yield* sql`
3538
+ CREATE TABLE effect_agent_memory_documents_v1 (
3539
+ namespace TEXT NOT NULL,
3540
+ source_id TEXT NOT NULL,
3541
+ format_version INTEGER NOT NULL,
3542
+ generation INTEGER NOT NULL,
3543
+ revision TEXT NOT NULL,
3544
+ document_json TEXT NOT NULL,
3545
+ PRIMARY KEY (namespace, source_id)
3546
+ )
3547
+ `;
3548
+ yield* sql`
3549
+ CREATE TABLE effect_agent_memory_receipts_v1 (
3550
+ namespace TEXT NOT NULL,
3551
+ operation_id TEXT NOT NULL,
3552
+ source_id TEXT NOT NULL,
3553
+ format_version INTEGER NOT NULL,
3554
+ command_json TEXT NOT NULL,
3555
+ result_json TEXT NOT NULL,
3556
+ PRIMARY KEY (namespace, operation_id)
3557
+ )
3558
+ `;
3559
+ yield* sql`
3560
+ INSERT INTO effect_agent_memory_metadata (component, version)
3561
+ VALUES (${METADATA_COMPONENT}, ${STORAGE_VERSION})
3562
+ `;
3563
+ }
3564
+ yield* sql`
3565
+ SELECT namespace, source_id, format_version, generation, revision, document_json
3566
+ FROM effect_agent_memory_documents_v1
3567
+ LIMIT 0
3568
+ `;
3569
+ yield* sql`
3570
+ SELECT namespace, operation_id, source_id, format_version, command_json, result_json
3571
+ FROM effect_agent_memory_receipts_v1
3572
+ LIMIT 0
3573
+ `;
3574
+ })).pipe(Effect.catchTag("SqlError", () => Effect.fail(storageError("initialize memory schema"))));
3575
+ yield* failpoint.hit("memory:initialize:after");
3576
+ });
3577
+ const makeMemoryReader = Effect.fn("SqliteMemoryStore.makeReader")(function* () {
3578
+ const sql = yield* SqlClient.SqlClient;
3579
+ const readDocument = Effect.fn("SqliteMemoryStore.readDocument")(function* (key, operation) {
3580
+ const rawRows = yield* query(sql`
3581
+ SELECT namespace, source_id, format_version, generation, revision, document_json
3582
+ FROM effect_agent_memory_documents_v1
3583
+ WHERE namespace = ${key.namespace.address} AND source_id = ${key.id}
3584
+ `, operation);
3585
+ const rows = yield* decodeRows$2(MemoryDocumentRow, rawRows, operation);
3586
+ if (rows.length === 0) return null;
3587
+ if (rows.length !== 1) return yield* storageError(operation, "corrupt");
3588
+ const row = rows[0];
3589
+ if (row.format_version !== STORAGE_VERSION) return yield* storageError(operation, "incompatible");
3590
+ const document = (yield* decodeVersionedJson(StoredMemoryResult, row.document_json, operation)).value;
3591
+ yield* validateDocument(document, key, operation);
3592
+ if (row.namespace !== key.namespace.address || row.source_id !== key.id || row.generation !== document.generation || row.revision !== document.source.revision) return yield* storageError(operation, "corrupt");
3593
+ return document;
3594
+ });
3595
+ return {
3596
+ get: Effect.fn("SqliteMemoryStore.get")(function* (key) {
3597
+ const decodedKey = yield* decodeInput$1(MemoryKey.Wire, key, "get memory document");
3598
+ return yield* readDocument(decodedKey, "get memory document");
3599
+ }),
3600
+ readDocument
3601
+ };
3602
+ });
3603
+ const makeMemoryServices = Effect.fn("SqliteMemoryStore.make")(function* () {
3604
+ const sql = yield* SqlClient.SqlClient;
3605
+ const failpoint = yield* MemoryMutationFailpoint;
3606
+ yield* initializeMemorySchema();
3607
+ const { get, readDocument } = yield* makeMemoryReader();
3608
+ const readReceipt = Effect.fn("SqliteMemoryStore.readReceipt")(function* (write, operation) {
3609
+ const rawRows = yield* query(sql`
3610
+ SELECT namespace, operation_id, source_id, format_version, command_json, result_json
3611
+ FROM effect_agent_memory_receipts_v1
3612
+ WHERE namespace = ${write.key.namespace.address} AND operation_id = ${write.operationId}
3613
+ `, operation);
3614
+ const rows = yield* decodeRows$2(MemoryReceiptRow, rawRows, operation);
3615
+ if (rows.length === 0) return null;
3616
+ if (rows.length !== 1) return yield* storageError(operation, "corrupt");
3617
+ const row = rows[0];
3618
+ if (row.format_version !== STORAGE_VERSION) return yield* storageError(operation, "incompatible");
3619
+ const command = yield* decodeVersionedJson(StoredMemoryCommand, row.command_json, `${operation} command`);
3620
+ const result = yield* decodeVersionedJson(StoredMemoryResult, row.result_json, `${operation} result`);
3621
+ if (row.namespace !== command.value.key.namespace.address || row.operation_id !== command.value.operationId || row.source_id !== command.value.key.id || result.value.key.namespace.address !== command.value.key.namespace.address || result.value.key.id !== command.value.key.id) return yield* storageError(operation, "corrupt");
3622
+ yield* validateDocument(result.value, command.value.key, operation);
3623
+ yield* validateReceiptResult(command.value, result.value, operation);
3624
+ return {
3625
+ commandJson: row.command_json,
3626
+ result: result.value
3627
+ };
3628
+ });
3629
+ const change = Effect.fn("SqliteMemoryStore.change")(function* (write) {
3630
+ const operation = "change memory document";
3631
+ const decodedWrite = yield* decodeInput$1(MemoryWrite.Wire, write, operation);
3632
+ const commandJson = yield* encodeJson(StoredMemoryCommand, StoredMemoryCommand.make({
3633
+ version: STORAGE_VERSION,
3634
+ value: decodedWrite
3635
+ }), "encode memory command");
3636
+ yield* failpoint.hit("memory:change:before");
3637
+ const transactionResult = yield* sql.withTransaction(Effect.gen(function* () {
3638
+ const receipt = yield* readReceipt(decodedWrite, operation);
3639
+ if (receipt !== null) {
3640
+ if (receipt.commandJson !== commandJson) return yield* MemoryOperationConflict.make({
3641
+ key: decodedWrite.key,
3642
+ operationId: decodedWrite.operationId
3643
+ });
3644
+ return {
3645
+ document: receipt.result,
3646
+ changed: false
3647
+ };
3648
+ }
3649
+ const current = yield* readDocument(decodedWrite.key, operation);
3650
+ const modifiedAt = yield* Clock.currentTimeMillis;
3651
+ const next = yield* applyMemoryWrite(current, decodedWrite, modifiedAt);
3652
+ const resultJson = yield* encodeJson(StoredMemoryResult, StoredMemoryResult.make({
3653
+ version: STORAGE_VERSION,
3654
+ value: next
3655
+ }), "encode memory result");
3656
+ const documentJson = resultJson;
3657
+ yield* validateEncodedChange({
3658
+ commandJson,
3659
+ documentJson,
3660
+ resultJson
3661
+ }, operation);
3662
+ if (current === null) yield* sql`
3663
+ INSERT INTO effect_agent_memory_documents_v1 (
3664
+ namespace, source_id, format_version, generation, revision, document_json
3665
+ ) VALUES (
3666
+ ${next.key.namespace.address}, ${next.key.id}, ${STORAGE_VERSION},
3667
+ ${next.generation}, ${next.source.revision}, ${documentJson}
3668
+ )
3669
+ `;
3670
+ else yield* sql`
3671
+ UPDATE effect_agent_memory_documents_v1
3672
+ SET format_version = ${STORAGE_VERSION},
3673
+ generation = ${next.generation},
3674
+ revision = ${next.source.revision},
3675
+ document_json = ${documentJson}
3676
+ WHERE namespace = ${next.key.namespace.address}
3677
+ AND source_id = ${next.key.id}
3678
+ AND generation = ${current.generation}
3679
+ AND revision = ${current.source.revision}
3680
+ `;
3681
+ const changedRows = yield* sql`
3682
+ SELECT changes() AS changed
3683
+ `;
3684
+ const changed = yield* decodeRows$2(MemoryChangeCountRow, changedRows, operation);
3685
+ if (changed.length !== 1 || changed[0].changed !== 1) return yield* storageError(operation, "corrupt");
3686
+ yield* failpoint.hit("memory:change:after-state");
3687
+ yield* sql`
3688
+ INSERT INTO effect_agent_memory_receipts_v1 (
3689
+ namespace, operation_id, source_id, format_version, command_json, result_json
3690
+ ) VALUES (
3691
+ ${decodedWrite.key.namespace.address}, ${decodedWrite.operationId}, ${decodedWrite.key.id},
3692
+ ${STORAGE_VERSION}, ${commandJson}, ${resultJson}
3693
+ )
3694
+ `;
3695
+ yield* failpoint.hit("memory:change:after-receipt");
3696
+ return {
3697
+ document: next,
3698
+ changed: true
3699
+ };
3700
+ })).pipe(Effect.catchTag("SqlError", () => Effect.fail(storageError(operation))));
3701
+ if (transactionResult.changed) yield* failpoint.hit("memory:change:after");
3702
+ return transactionResult.document;
3703
+ });
3704
+ return Context.make(MemoryReader, MemoryReader.fromAdapter({ get })).pipe(Context.add(MemoryWriter, MemoryWriter.fromAdapter({ change })));
3705
+ });
3706
+ /** SQLite memory ports with the mutation failpoint kept injectable for recovery tests. */
3707
+ const memoryStoreLayerWithFailpoints = Layer.effectContext(makeMemoryServices());
3708
+ /** SQLite memory reader and writer with the production no-op mutation failpoint. */
3709
+ const memoryStoreLayer = memoryStoreLayerWithFailpoints.pipe(Layer.provide(MemoryMutationFailpoint.layer));
3710
+ /** Reads an existing memory schema without writes, transactions, or mutation failpoints. */
3711
+ const memoryReaderLayer = Layer.effect(MemoryReader, Effect.gen(function* () {
3712
+ const sql = yield* SqlClient.SqlClient;
3713
+ const operation = "open memory reader";
3714
+ const tables = yield* query(sql`
3715
+ SELECT name FROM sqlite_master
3716
+ WHERE type = 'table' AND name IN (
3717
+ 'effect_agent_memory_metadata', ${DOCUMENT_TABLE}, ${RECEIPT_TABLE}
3718
+ )
3719
+ `, operation).pipe(Effect.flatMap((rows) => decodeRows$2(MemoryTableRow, rows, operation)));
3720
+ if (tables.length !== 3) return yield* storageError(operation, tables.length === 0 ? "unavailable" : "incompatible");
3721
+ const metadata = yield* query(sql`
3722
+ SELECT version FROM effect_agent_memory_metadata WHERE component = ${METADATA_COMPONENT}
3723
+ `, operation).pipe(Effect.flatMap((rows) => decodeRows$2(MemoryMetadataRow, rows, operation)));
3724
+ if (metadata.length !== 1 || metadata[0].version !== STORAGE_VERSION) return yield* storageError(operation, "incompatible");
3725
+ yield* query(sql`
3726
+ SELECT namespace, source_id, format_version, generation, revision, document_json
3727
+ FROM effect_agent_memory_documents_v1 LIMIT 0
3728
+ `, operation);
3729
+ const { get } = yield* makeMemoryReader();
3730
+ return MemoryReader.fromAdapter({ get });
3731
+ }));
3732
+ //#endregion
3178
3733
  //#region src/sqlite-schedule-store.ts
3179
- const StoredScheduleJson = Schema.String.check(Schema.isMaxLength(16 * 1024 * 1024));
3734
+ const StoredScheduleJson = Schema.String.check(Schema.isMaxLength(16777216));
3180
3735
  const StoredDeadline = Schema.NullOr(ScheduleInstant);
3181
3736
  var ScheduleRow = class extends Schema.Class("@effect-agent/storage-sqlite/ScheduleRow")({
3182
3737
  tenant_id: ScheduleOwner.fields.tenantId,
@@ -3421,7 +3976,7 @@ const makeScheduleStore = Effect.gen(function* () {
3421
3976
  const scheduleStoreLayer = Layer.effect(ScheduleStore)(makeScheduleStore);
3422
3977
  //#endregion
3423
3978
  //#region src/sqlite-subscription-store.ts
3424
- const StoredJson = Schema.String.check(Schema.isMaxLength(16 * 1024 * 1024));
3979
+ const StoredJson = Schema.String.check(Schema.isMaxLength(16777216));
3425
3980
  const CountRow = Schema.Struct({ count: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)) });
3426
3981
  const SequenceRow = Schema.Struct({ sequence: Schema.Natural });
3427
3982
  const ScanRow = Schema.Struct({
@@ -3814,7 +4369,8 @@ const makeSubscriptionStore = Effect.fn("SqliteSubscriptionStore.make")(function
3814
4369
  return false;
3815
4370
  }
3816
4371
  yield* failpoint.hit("subscription:catch-up:before");
3817
- if (!subscriptionCanSelect(record, accepted, Math.max(nowMillis, yield* Clock.currentTimeMillis), true)) return yield* error("conflict", "catch-up-eligibility");
4372
+ const effectiveNowMillis = Math.max(nowMillis, yield* Clock.currentTimeMillis);
4373
+ if (!subscriptionCanSelect(record, accepted, effectiveNowMillis, true)) return yield* error("conflict", "catch-up-eligibility");
3818
4374
  if ((yield* count(sql`SELECT COUNT(*) AS count FROM effect_agent_subscription_deliveries WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address}`, "count deliveries")) >= limits.maxDeliveries) return yield* error("capacity", "deliveries");
3819
4375
  if ((yield* count(sql`SELECT COUNT(*) AS count FROM effect_agent_subscription_deliveries WHERE tenant_id=${partition.tenantId} AND source_address=${partition.address} AND owner_id=${record.key.ownerId}`, "count owner deliveries")) >= limits.maxDeliveriesPerOwner) return yield* error("capacity", "owner-deliveries");
3820
4376
  yield* insertDelivery(delivery);
@@ -4004,6 +4560,6 @@ const makeSubscriptionStore = Effect.fn("SqliteSubscriptionStore.make")(function
4004
4560
  });
4005
4561
  const subscriptionStoreLayer = (partition) => Layer.effect(SubscriptionStore, makeSubscriptionStore(partition));
4006
4562
  //#endregion
4007
- export { CurrentSqliteStorageVersion, SqliteAppendConflict, SqliteCheckpointConflict, SqliteFenceRejected, SqliteLedgerError, SqliteStorageCompatibilityError, SqliteStorageConfig, SqliteStorageConfigValue, SqliteStorageCorruptionError, SqliteStorageError, SqliteStorageFailpoint, SqliteStorageFailpointError, SqliteStorageFailpointLocation, SqliteWriteContention, layer, ledgerLayer, observationOffsetAt, scheduleStoreLayer, storageConfigLayer, storageFailpointLayer, submissionLedgerLayer, subscriptionStoreLayer, threadStoreLayer };
4563
+ export { CurrentSqliteStorageVersion, SqliteAppendConflict, SqliteCheckpointConflict, SqliteFenceRejected, SqliteLedgerError, SqliteStorageCompatibilityError, SqliteStorageConfig, SqliteStorageConfigValue, SqliteStorageCorruptionError, SqliteStorageError, SqliteStorageFailpoint, SqliteStorageFailpointError, SqliteStorageFailpointLocation, SqliteWriteContention, activityProcessorStoreLayer, activityProcessorStoreLayerWithFailpoints, layer, ledgerLayer, memoryReaderLayer, memoryStoreLayer, memoryStoreLayerWithFailpoints, observationOffsetAt, scheduleStoreLayer, storageConfigLayer, storageFailpointLayer, submissionLedgerLayer, subscriptionStoreLayer, threadStoreLayer };
4008
4564
 
4009
4565
  //# sourceMappingURL=index.mjs.map