@effect-agent/storage-sqlite 0.1.0-beta.49 → 0.1.0-beta.51

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.
@@ -15,8 +15,12 @@ import {
15
15
  AbortIntentRequest,
16
16
  AdmissionAdmitted,
17
17
  AdmissionConflict,
18
+ AdmissionFence,
19
+ AdmissionGroup,
20
+ AdmissionPolicyError,
18
21
  AdmissionNotAdmitted,
19
22
  AdmissionRequest,
23
+ SubmissionAdmissionFence,
20
24
  AdmissionResult,
21
25
  ApprovalConflict,
22
26
  ApprovalDecisionCommand,
@@ -139,6 +143,8 @@ class SubmissionRow extends Schema.Class<SubmissionRow>("SubmissionRow")({
139
143
  unknown_tool_call_ids_json: Schema.NullOr(BoundedStoredText),
140
144
  parent_submission_id: Schema.NullOr(BoundedIdentifier),
141
145
  parent_tool_call_id: Schema.NullOr(BoundedIdentifier),
146
+ admission_group: Schema.NullOr(AdmissionGroup),
147
+ admission_fence_json: Schema.NullOr(BoundedStoredText),
142
148
  }) {}
143
149
 
144
150
  class ChildReservationRow extends Schema.Class<ChildReservationRow>("ChildReservationRow")({
@@ -242,7 +248,9 @@ const SUBMISSION_COLUMNS = `
242
248
  unknown_reason,
243
249
  unknown_tool_call_ids_json,
244
250
  parent_submission_id,
245
- parent_tool_call_id
251
+ parent_tool_call_id,
252
+ admission_group,
253
+ admission_fence_json
246
254
  `;
247
255
 
248
256
  const CHILD_RESERVATION_COLUMNS = `
@@ -336,6 +344,7 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
336
344
  const failpoint = yield* SqliteStorageFailpoint;
337
345
  const sql = yield* SqlClientService.SqlClient;
338
346
  const crypto = yield* Crypto.Crypto;
347
+ const admissionFence = yield* SubmissionAdmissionFence;
339
348
  const journal = yield* initializeSqliteJournal();
340
349
 
341
350
  const hitFailpoint = (
@@ -354,6 +363,7 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
354
363
  A,
355
364
  E extends
356
365
  | AdmissionConflict
366
+ | AdmissionPolicyError
357
367
  | ApprovalConflict
358
368
  | ChildReservationConflict
359
369
  | JoinedToHost
@@ -558,6 +568,14 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
558
568
  receiptId: row.receipt_id,
559
569
  state: row.state,
560
570
  createdAt: row.created_at,
571
+ ...(row.admission_group === null ? {} : { admissionGroup: row.admission_group }),
572
+ ...(row.admission_fence_json === null
573
+ ? {}
574
+ : {
575
+ admissionFence: yield* parseStoredJsonText(row.admission_fence_json).pipe(
576
+ Effect.mapError(internalFailure(operation)),
577
+ ),
578
+ }),
561
579
  ...(row.settled_outcome === null ? {} : { settledOutcome: row.settled_outcome }),
562
580
  ...(row.ready_at === null ? {} : { readyAt: row.ready_at }),
563
581
  ...(row.parent_submission_id === null || row.parent_tool_call_id === null
@@ -1017,6 +1035,28 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
1017
1035
  });
1018
1036
  }
1019
1037
 
1038
+ const retainedFence =
1039
+ existing[0].admission_fence_json === null
1040
+ ? undefined
1041
+ : yield* Schema.decodeEffect(Schema.fromJsonString(AdmissionFence))(
1042
+ existing[0].admission_fence_json,
1043
+ ).pipe(Effect.mapError(internalFailure(operation)));
1044
+
1045
+ if (
1046
+ (existing[0].admission_group ?? undefined) !== validated.admissionGroup ||
1047
+ !Schema.toEquivalence(Schema.optional(AdmissionFence))(
1048
+ retainedFence,
1049
+ validated.admissionFence,
1050
+ )
1051
+ )
1052
+ return yield* AdmissionConflict.make({
1053
+ threadId: validated.threadId,
1054
+ principal: validated.principal,
1055
+ idempotencyKey: validated.idempotencyKey,
1056
+ existingInputDigest: existing[0].input_digest,
1057
+ attemptedInputDigest: validated.inputDigest,
1058
+ });
1059
+
1020
1060
  return yield* decodeAdmissionResult({
1021
1061
  submissionId: existing[0].submission_id,
1022
1062
  receiptId: existing[0].receipt_id,
@@ -1026,6 +1066,20 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
1026
1066
  }).pipe(Effect.mapError(internalFailure(operation)));
1027
1067
  }
1028
1068
 
1069
+ yield* admissionFence.check(validated);
1070
+ if (validated.admissionGroup !== undefined) {
1071
+ const occupied = yield* sql<Record<string, unknown>>`
1072
+ SELECT submission_id FROM effect_agent_submissions
1073
+ WHERE thread_id=${validated.threadId} AND admission_group=${validated.admissionGroup} AND state<>'settled' LIMIT 1
1074
+ `.pipe(Effect.mapError(sqlFailure(operation)));
1075
+
1076
+ if (occupied.length > 0)
1077
+ return yield* AdmissionPolicyError.make({
1078
+ reason: "occupied",
1079
+ code: "admission-group",
1080
+ });
1081
+ }
1082
+
1029
1083
  const maxRows = yield* sql<Record<string, unknown>>`
1030
1084
  SELECT COALESCE(MAX(queue_sequence), 0) AS max_queue_sequence
1031
1085
  FROM effect_agent_submissions
@@ -1061,7 +1115,9 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
1061
1115
  state,
1062
1116
  created_at,
1063
1117
  parent_submission_id,
1064
- parent_tool_call_id
1118
+ parent_tool_call_id,
1119
+ admission_group,
1120
+ admission_fence_json
1065
1121
  ) VALUES (
1066
1122
  ${mintedSubmissionId},
1067
1123
  ${validated.threadId},
@@ -1077,7 +1133,9 @@ const makeServices = Effect.fn("SqliteSubmissionLedger.makeServices")(function*
1077
1133
  'admitted',
1078
1134
  ${now.iso},
1079
1135
  ${validated.parentLinkage?.parentSubmissionId ?? null},
1080
- ${validated.parentLinkage?.parentToolCallId ?? null}
1136
+ ${validated.parentLinkage?.parentToolCallId ?? null},
1137
+ ${validated.admissionGroup ?? null},
1138
+ ${validated.admissionFence === undefined ? null : JSON.stringify(validated.admissionFence)}
1081
1139
  )
1082
1140
  `.pipe(Effect.mapError(sqlFailure(operation)));
1083
1141