@ferricstore/ferricstore 0.12.0 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/langgraph.cjs +395 -125
- package/dist/langgraph.cjs.map +1 -1
- package/dist/langgraph.d.cts +17 -7
- package/dist/langgraph.d.ts +17 -7
- package/dist/langgraph.js +396 -126
- package/dist/langgraph.js.map +1 -1
- package/dist/openai-agents.cjs +161 -24
- package/dist/openai-agents.cjs.map +1 -1
- package/dist/openai-agents.d.cts +10 -4
- package/dist/openai-agents.d.ts +10 -4
- package/dist/openai-agents.js +161 -24
- package/dist/openai-agents.js.map +1 -1
- package/docs/agent-api/assets/hierarchy.js +1 -0
- package/docs/agent-api/assets/highlight.css +92 -0
- package/docs/agent-api/assets/icons.js +18 -0
- package/docs/agent-api/assets/icons.svg +1 -0
- package/docs/agent-api/assets/main.js +60 -0
- package/docs/agent-api/assets/navigation.js +1 -0
- package/docs/agent-api/assets/search.js +1 -0
- package/docs/agent-api/assets/style.css +1648 -0
- package/docs/agent-api/classes/langgraph.FerricStoreSaver.html +297 -0
- package/docs/agent-api/classes/langgraph.FerricStoreStore.html +298 -0
- package/docs/agent-api/classes/langgraph.LangGraphFlow.html +190 -0
- package/docs/agent-api/classes/langgraph.LangGraphFlowContext.html +158 -0
- package/docs/agent-api/classes/langgraph.LangGraphFlowRun.html +133 -0
- package/docs/agent-api/classes/openai-agents.FerricStoreSession.html +241 -0
- package/docs/agent-api/hierarchy.html +44 -0
- package/docs/agent-api/index.html +142 -0
- package/docs/agent-api/interfaces/langgraph.FerricFlowHandlerContext.html +94 -0
- package/docs/agent-api/interfaces/langgraph.FerricStoreCommandClient.html +77 -0
- package/docs/agent-api/interfaces/langgraph.FerricStoreLockOptions.html +81 -0
- package/docs/agent-api/interfaces/langgraph.FerricStoreSaverOptions.html +106 -0
- package/docs/agent-api/interfaces/langgraph.FerricStoreStoreOptions.html +98 -0
- package/docs/agent-api/interfaces/langgraph.InvokableLangGraph.html +83 -0
- package/docs/agent-api/interfaces/langgraph.LangGraphFlowOptions.html +116 -0
- package/docs/agent-api/interfaces/openai-agents.FerricStoreSessionOptions.html +114 -0
- package/docs/agent-api/interfaces/openai-agents.Session.html +208 -0
- package/docs/agent-api/interfaces/openai-agents.SessionHistoryRewriteAwareSession.html +230 -0
- package/docs/agent-api/interfaces/openai-agents.SessionHistoryTransactionAwareSession.html +237 -0
- package/docs/agent-api/modules/langgraph.html +44 -0
- package/docs/agent-api/modules/openai-agents.html +44 -0
- package/docs/agent-api/modules.html +35 -0
- package/docs/agent-api/types/langgraph.LangGraphChannelVersions.html +33 -0
- package/docs/agent-api/types/langgraph.LangGraphInvocationConfig.html +33 -0
- package/docs/agent-api/types/langgraph.LangGraphOutcomeMapper.html +50 -0
- package/docs/agent-api/types/langgraph.LangGraphPendingWrite.html +33 -0
- package/docs/agent-api/types/openai-agents.AgentInputItem.html +35 -0
- package/docs/agent-frameworks.md +25 -8
- package/docs/api/index.html +4 -1
- package/docs/api/media/agent-frameworks.md +25 -8
- package/package.json +3 -3
package/dist/openai-agents.cjs
CHANGED
|
@@ -128,14 +128,44 @@ function integerResponse(value, name) {
|
|
|
128
128
|
if (!Number.isSafeInteger(parsed)) throw new TypeError(`FerricStore returned an invalid ${name}`);
|
|
129
129
|
return parsed;
|
|
130
130
|
}
|
|
131
|
+
async function readAtomicValue(client, key, name) {
|
|
132
|
+
const value = await client.command("GET", key);
|
|
133
|
+
if (value == null) return void 0;
|
|
134
|
+
if (typeof value === "string") return Buffer.from(value, "utf8");
|
|
135
|
+
if (Buffer.isBuffer(value) || value instanceof Uint8Array) return Buffer.from(value);
|
|
136
|
+
throw new TypeError(`FerricStore returned a non-binary ${name}`);
|
|
137
|
+
}
|
|
138
|
+
async function compareAndSetAtomicValue(client, key, expected, value) {
|
|
139
|
+
if (expected == null) {
|
|
140
|
+
const response2 = await client.command("SET", key, value, "NX");
|
|
141
|
+
if (response2 == null || response2 === false) return false;
|
|
142
|
+
if (response2 === true) return true;
|
|
143
|
+
return textResponse(response2, "SET NX response").toUpperCase() === "OK";
|
|
144
|
+
}
|
|
145
|
+
const response = await client.command("CAS", key, expected, value);
|
|
146
|
+
if (response == null || response === false) return false;
|
|
147
|
+
if (response === true) return true;
|
|
148
|
+
return integerResponse(response, "CAS response") === 1;
|
|
149
|
+
}
|
|
131
150
|
async function withMutationLocks(client, keys, operation, options = {}) {
|
|
132
151
|
const orderedKeys = [...new Set(keys)].sort();
|
|
133
|
-
if (orderedKeys.length === 0)
|
|
152
|
+
if (orderedKeys.length === 0) {
|
|
153
|
+
const signal = new AbortController().signal;
|
|
154
|
+
return await operation({
|
|
155
|
+
signal,
|
|
156
|
+
assertOwned: () => void 0,
|
|
157
|
+
publish: async (...args) => await additiveCommand(client, args),
|
|
158
|
+
compareAndSet: async (key, expected, value) => await compareAndSetAtomicValue(client, key, expected, value)
|
|
159
|
+
});
|
|
160
|
+
}
|
|
134
161
|
const normalized = {
|
|
135
162
|
lockRetryMs: positiveInteger(options.lockRetryMs, DEFAULT_LOCK_OPTIONS.lockRetryMs, "lockRetryMs"),
|
|
136
163
|
lockTtlMs: positiveInteger(options.lockTtlMs, DEFAULT_LOCK_OPTIONS.lockTtlMs, "lockTtlMs"),
|
|
137
164
|
lockWaitMs: nonNegativeInteger(options.lockWaitMs, DEFAULT_LOCK_OPTIONS.lockWaitMs, "lockWaitMs")
|
|
138
165
|
};
|
|
166
|
+
if (normalized.lockRetryMs >= normalized.lockTtlMs) {
|
|
167
|
+
throw new TypeError("lockRetryMs must be less than lockTtlMs");
|
|
168
|
+
}
|
|
139
169
|
const owner = (0, import_node_crypto.randomUUID)();
|
|
140
170
|
const acquired = [];
|
|
141
171
|
const deadline = performance.now() + normalized.lockWaitMs;
|
|
@@ -144,29 +174,81 @@ async function withMutationLocks(client, keys, operation, options = {}) {
|
|
|
144
174
|
let releaseError;
|
|
145
175
|
let result;
|
|
146
176
|
let operationCompleted = false;
|
|
177
|
+
let conditionalCommitCompleted = false;
|
|
147
178
|
const heartbeatAbort = new AbortController();
|
|
179
|
+
const ownershipAbort = new AbortController();
|
|
180
|
+
const lastExtended = /* @__PURE__ */ new Map();
|
|
181
|
+
const loseOwnership = (error) => {
|
|
182
|
+
const normalizedError = errorObject(error);
|
|
183
|
+
heartbeatError ??= normalizedError;
|
|
184
|
+
if (!ownershipAbort.signal.aborted) ownershipAbort.abort(normalizedError);
|
|
185
|
+
return normalizedError;
|
|
186
|
+
};
|
|
187
|
+
const assertOwned = () => {
|
|
188
|
+
if (heartbeatError != null) throw errorObject(heartbeatError);
|
|
189
|
+
if (ownershipAbort.signal.aborted) throw errorObject(ownershipAbort.signal.reason);
|
|
190
|
+
};
|
|
191
|
+
const renewOwned = async () => {
|
|
192
|
+
assertOwned();
|
|
193
|
+
for (const key of acquired) {
|
|
194
|
+
try {
|
|
195
|
+
const response = await client.command("EXTEND", key, owner, normalized.lockTtlMs);
|
|
196
|
+
if (integerResponse(response, "EXTEND response") !== 1) {
|
|
197
|
+
throw new Error(`lost FerricStore lock ${JSON.stringify(key)} while mutating data`);
|
|
198
|
+
}
|
|
199
|
+
lastExtended.set(key, performance.now());
|
|
200
|
+
} catch (error) {
|
|
201
|
+
throw loseOwnership(new Error(
|
|
202
|
+
`could not validate FerricStore lock ${JSON.stringify(key)} before mutating data`,
|
|
203
|
+
{ cause: error }
|
|
204
|
+
));
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
assertOwned();
|
|
208
|
+
};
|
|
209
|
+
const lease = {
|
|
210
|
+
signal: ownershipAbort.signal,
|
|
211
|
+
assertOwned,
|
|
212
|
+
publish: async (...args) => {
|
|
213
|
+
await renewOwned();
|
|
214
|
+
const response = await additiveCommand(client, args);
|
|
215
|
+
assertOwned();
|
|
216
|
+
return response;
|
|
217
|
+
},
|
|
218
|
+
compareAndSet: async (key, expected, value) => {
|
|
219
|
+
await renewOwned();
|
|
220
|
+
const committed = await compareAndSetAtomicValue(client, key, expected, value);
|
|
221
|
+
if (committed) conditionalCommitCompleted = true;
|
|
222
|
+
else assertOwned();
|
|
223
|
+
return committed;
|
|
224
|
+
}
|
|
225
|
+
};
|
|
148
226
|
try {
|
|
149
227
|
for (const key of orderedKeys) {
|
|
150
228
|
while (!await tryAcquireLock(client, key, owner, normalized.lockTtlMs)) {
|
|
151
229
|
if (performance.now() >= deadline) {
|
|
152
230
|
throw new Error(`timed out acquiring FerricStore lock ${JSON.stringify(key)}`);
|
|
153
231
|
}
|
|
232
|
+
await extendAcquiredLocks(client, acquired, owner, normalized.lockTtlMs);
|
|
154
233
|
await (0, import_promises.setTimeout)(normalized.lockRetryMs);
|
|
155
234
|
}
|
|
156
235
|
acquired.push(key);
|
|
157
236
|
}
|
|
237
|
+
await extendAcquiredLocks(client, acquired, owner, normalized.lockTtlMs);
|
|
238
|
+
for (const key of acquired) lastExtended.set(key, performance.now());
|
|
158
239
|
const heartbeat = renewLocks(
|
|
159
240
|
client,
|
|
160
241
|
acquired,
|
|
161
242
|
owner,
|
|
162
243
|
normalized.lockTtlMs,
|
|
244
|
+
lastExtended,
|
|
163
245
|
heartbeatAbort.signal,
|
|
164
246
|
(error) => {
|
|
165
|
-
|
|
247
|
+
loseOwnership(error);
|
|
166
248
|
}
|
|
167
249
|
);
|
|
168
250
|
try {
|
|
169
|
-
result = await operation();
|
|
251
|
+
result = await operation(lease);
|
|
170
252
|
operationCompleted = true;
|
|
171
253
|
} catch (error) {
|
|
172
254
|
primaryError = error;
|
|
@@ -187,11 +269,32 @@ async function withMutationLocks(client, keys, operation, options = {}) {
|
|
|
187
269
|
}
|
|
188
270
|
}
|
|
189
271
|
if (primaryError != null) throw errorObject(primaryError);
|
|
190
|
-
if (heartbeatError != null) throw errorObject(heartbeatError);
|
|
191
|
-
if (releaseError != null
|
|
272
|
+
if (heartbeatError != null && !conditionalCommitCompleted) throw errorObject(heartbeatError);
|
|
273
|
+
if (releaseError != null && !(heartbeatError != null && conditionalCommitCompleted)) {
|
|
274
|
+
throw errorObject(releaseError);
|
|
275
|
+
}
|
|
192
276
|
if (!operationCompleted) throw new Error("FerricStore mutation did not complete");
|
|
193
277
|
return result;
|
|
194
278
|
}
|
|
279
|
+
async function additiveCommand(client, args) {
|
|
280
|
+
const rawName = args[0];
|
|
281
|
+
const name = typeof rawName === "string" ? rawName.toUpperCase() : Buffer.isBuffer(rawName) || rawName instanceof Uint8Array ? Buffer.from(rawName).toString("utf8").toUpperCase() : "";
|
|
282
|
+
if (name !== "SADD" && name !== "ZADD") {
|
|
283
|
+
throw new TypeError("FerricStore mutation leases only publish add-only SADD or ZADD indexes");
|
|
284
|
+
}
|
|
285
|
+
if (name === "ZADD" && (args.length < 4 || args.length % 2 !== 0 || args.slice(2).some((value, index) => index % 2 === 0 && Number(value) !== 0))) {
|
|
286
|
+
throw new TypeError("FerricStore mutation leases only publish zero-score ZADD indexes");
|
|
287
|
+
}
|
|
288
|
+
return await client.command(...args);
|
|
289
|
+
}
|
|
290
|
+
async function extendAcquiredLocks(client, keys, owner, ttlMs) {
|
|
291
|
+
for (const key of keys) {
|
|
292
|
+
const response = await client.command("EXTEND", key, owner, ttlMs);
|
|
293
|
+
if (integerResponse(response, "EXTEND response") !== 1) {
|
|
294
|
+
throw new Error(`lost FerricStore lock ${JSON.stringify(key)} before mutating data`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
195
298
|
async function tryAcquireLock(client, key, owner, ttlMs) {
|
|
196
299
|
try {
|
|
197
300
|
const response = await client.command("LOCK", key, owner, ttlMs);
|
|
@@ -201,10 +304,9 @@ async function tryAcquireLock(client, key, owner, ttlMs) {
|
|
|
201
304
|
throw error;
|
|
202
305
|
}
|
|
203
306
|
}
|
|
204
|
-
async function renewLocks(client, keys, owner, ttlMs, signal, onError) {
|
|
205
|
-
const intervalMs = Math.max(Math.floor(ttlMs / 3),
|
|
206
|
-
const retryMs = Math.min(Math.max(Math.floor(intervalMs / 10),
|
|
207
|
-
const lastExtended = new Map(keys.map((key) => [key, performance.now()]));
|
|
307
|
+
async function renewLocks(client, keys, owner, ttlMs, lastExtended, signal, onError) {
|
|
308
|
+
const intervalMs = Math.max(Math.floor(ttlMs / 3), 1);
|
|
309
|
+
const retryMs = Math.min(Math.max(Math.floor(intervalMs / 10), 1), 1e3);
|
|
208
310
|
let waitMs = intervalMs;
|
|
209
311
|
while (!signal.aborted) {
|
|
210
312
|
try {
|
|
@@ -242,7 +344,7 @@ function errorObject(value) {
|
|
|
242
344
|
// src/agent-persistence/snapshot.ts
|
|
243
345
|
var import_node_crypto2 = require("crypto");
|
|
244
346
|
function encodeSnapshot(value) {
|
|
245
|
-
return
|
|
347
|
+
return encodeSnapshotWith(value, defaultKeyComparator);
|
|
246
348
|
}
|
|
247
349
|
function decodeSnapshot(value, name) {
|
|
248
350
|
const bytes = typeof value === "string" ? Buffer.from(value, "utf8") : Buffer.from(asBytes(value, name));
|
|
@@ -257,13 +359,22 @@ function decodeSnapshot(value, name) {
|
|
|
257
359
|
function snapshotDigest(value) {
|
|
258
360
|
return (0, import_node_crypto2.createHash)("sha256").update(encodeSnapshot(value)).digest("hex");
|
|
259
361
|
}
|
|
362
|
+
function legacySnapshotDigest(value, locale) {
|
|
363
|
+
return (0, import_node_crypto2.createHash)("sha256").update(encodeSnapshotWith(value, (left, right) => left.localeCompare(right, locale))).digest("hex");
|
|
364
|
+
}
|
|
260
365
|
function cloneSnapshot(value) {
|
|
261
366
|
return decodeSnapshot(encodeSnapshot(value), "snapshot");
|
|
262
367
|
}
|
|
263
368
|
function snapshotsEqual(left, right) {
|
|
264
369
|
return encodeSnapshot(left).equals(encodeSnapshot(right));
|
|
265
370
|
}
|
|
266
|
-
function
|
|
371
|
+
function encodeSnapshotWith(value, compareKeys) {
|
|
372
|
+
return Buffer.from(JSON.stringify(snapshot(value, /* @__PURE__ */ new WeakSet(), compareKeys)), "utf8");
|
|
373
|
+
}
|
|
374
|
+
function defaultKeyComparator(left, right) {
|
|
375
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
376
|
+
}
|
|
377
|
+
function snapshot(value, ancestors, compareKeys) {
|
|
267
378
|
if (value === null) return ["null"];
|
|
268
379
|
if (value === void 0) return ["undefined"];
|
|
269
380
|
if (typeof value === "string") return ["string", value];
|
|
@@ -297,7 +408,7 @@ function snapshot(value, ancestors) {
|
|
|
297
408
|
if (descriptor == null || !descriptor.enumerable || !("value" in descriptor)) {
|
|
298
409
|
throw new TypeError("session history contains an unsupported array item");
|
|
299
410
|
}
|
|
300
|
-
items.push(snapshot(descriptor.value, ancestors));
|
|
411
|
+
items.push(snapshot(descriptor.value, ancestors, compareKeys));
|
|
301
412
|
}
|
|
302
413
|
return ["array", items];
|
|
303
414
|
}
|
|
@@ -310,12 +421,12 @@ function snapshot(value, ancestors) {
|
|
|
310
421
|
throw new TypeError("session history contains a symbol property");
|
|
311
422
|
}
|
|
312
423
|
const entries = [];
|
|
313
|
-
for (const key of keys.sort(
|
|
424
|
+
for (const key of keys.sort(compareKeys)) {
|
|
314
425
|
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
315
426
|
if (descriptor == null || !descriptor.enumerable || !("value" in descriptor)) {
|
|
316
427
|
throw new TypeError("session history contains an unsupported property");
|
|
317
428
|
}
|
|
318
|
-
entries.push([key, snapshot(descriptor.value, ancestors)]);
|
|
429
|
+
entries.push([key, snapshot(descriptor.value, ancestors, compareKeys)]);
|
|
319
430
|
}
|
|
320
431
|
return ["object", entries];
|
|
321
432
|
} finally {
|
|
@@ -386,13 +497,16 @@ function isArrayIndex(key, length) {
|
|
|
386
497
|
// src/openai-agents.ts
|
|
387
498
|
var SESSION_FORMAT_VERSION = 1;
|
|
388
499
|
var SESSION_STATE_FIELD = "state";
|
|
500
|
+
var RECEIPT_DIGEST_VERSION = "v2:";
|
|
389
501
|
var FerricStoreSession = class {
|
|
390
502
|
client;
|
|
391
503
|
sessionId;
|
|
392
504
|
keyPrefix;
|
|
393
505
|
initialItems;
|
|
394
506
|
lockOptions;
|
|
507
|
+
legacyReceiptLocales;
|
|
395
508
|
sessionKey;
|
|
509
|
+
stateKey;
|
|
396
510
|
lockKey;
|
|
397
511
|
constructor(client, options = {}) {
|
|
398
512
|
this.client = client;
|
|
@@ -407,8 +521,17 @@ var FerricStoreSession = class {
|
|
|
407
521
|
lockTtlMs: options.lockTtlMs,
|
|
408
522
|
lockWaitMs: options.lockWaitMs
|
|
409
523
|
};
|
|
524
|
+
if (options.legacyReceiptLocales != null && !Array.isArray(options.legacyReceiptLocales)) {
|
|
525
|
+
throw new TypeError("legacyReceiptLocales must be an array");
|
|
526
|
+
}
|
|
527
|
+
try {
|
|
528
|
+
this.legacyReceiptLocales = Intl.getCanonicalLocales(options.legacyReceiptLocales ?? []);
|
|
529
|
+
} catch (error) {
|
|
530
|
+
throw new TypeError("legacyReceiptLocales contains an invalid locale", { cause: error });
|
|
531
|
+
}
|
|
410
532
|
const digest = (0, import_node_crypto3.createHash)("sha256").update(this.sessionId, "utf8").digest("hex");
|
|
411
533
|
this.sessionKey = `${this.keyPrefix}:{oais:${digest}}:session`;
|
|
534
|
+
this.stateKey = `${this.sessionKey}:atomic-state`;
|
|
412
535
|
this.lockKey = `${this.keyPrefix}:{oais:${digest}}:mutation-lock`;
|
|
413
536
|
}
|
|
414
537
|
async getSessionId() {
|
|
@@ -479,15 +602,21 @@ var FerricStoreSession = class {
|
|
|
479
602
|
}
|
|
480
603
|
async applyHistoryTransaction(args) {
|
|
481
604
|
const { operationId, transaction } = snapshotTransactionArgs(args);
|
|
482
|
-
const digest = snapshotDigest(transaction)
|
|
605
|
+
const digest = `${RECEIPT_DIGEST_VERSION}${snapshotDigest(transaction)}`;
|
|
606
|
+
const legacyDigests = /* @__PURE__ */ new Set([
|
|
607
|
+
snapshotDigest(transaction),
|
|
608
|
+
legacySnapshotDigest(transaction),
|
|
609
|
+
...this.legacyReceiptLocales.map((locale) => legacySnapshotDigest(transaction, locale))
|
|
610
|
+
]);
|
|
483
611
|
await this.mutate(async (state) => {
|
|
484
612
|
const existing = Object.getOwnPropertyDescriptor(state.operations, operationId)?.value;
|
|
485
613
|
if (existing != null) {
|
|
486
614
|
if (typeof existing !== "string") throw new Error("corrupt session history operation receipt");
|
|
487
|
-
if (existing
|
|
615
|
+
if (existing === digest) return state;
|
|
616
|
+
if (!legacyDigests.has(existing)) {
|
|
488
617
|
throw new Error("session history operation was already applied with a different transaction");
|
|
489
618
|
}
|
|
490
|
-
return state;
|
|
619
|
+
return { ...state, operations: { ...state.operations, [operationId]: digest } };
|
|
491
620
|
}
|
|
492
621
|
let items;
|
|
493
622
|
if (transaction.type === "append_items") {
|
|
@@ -508,20 +637,28 @@ var FerricStoreSession = class {
|
|
|
508
637
|
});
|
|
509
638
|
}
|
|
510
639
|
async mutate(operation) {
|
|
511
|
-
await withMutationLocks(this.client, [this.lockKey], async () => {
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
640
|
+
await withMutationLocks(this.client, [this.lockKey], async (lease) => {
|
|
641
|
+
for (let attempt = 0; attempt < 8; attempt += 1) {
|
|
642
|
+
lease.assertOwned();
|
|
643
|
+
const snapshot2 = await this.readMutationState();
|
|
644
|
+
const next = await operation(snapshot2.state);
|
|
645
|
+
if (await lease.compareAndSet(this.stateKey, snapshot2.expected, encodeSnapshot(next))) return;
|
|
646
|
+
}
|
|
647
|
+
throw new Error("concurrent FerricStore OpenAI Agents session mutation did not converge");
|
|
515
648
|
}, this.lockOptions);
|
|
516
649
|
}
|
|
517
650
|
async readState() {
|
|
518
|
-
|
|
519
|
-
|
|
651
|
+
return (await this.readMutationState()).state;
|
|
652
|
+
}
|
|
653
|
+
async readMutationState() {
|
|
654
|
+
const expected = await readAtomicValue(this.client, this.stateKey, "OpenAI Agents atomic session state");
|
|
655
|
+
const value = expected ?? await this.client.command("HGET", this.sessionKey, SESSION_STATE_FIELD);
|
|
656
|
+
if (value == null) return { expected, state: this.emptyState() };
|
|
520
657
|
const state = decodeSnapshot(value, "OpenAI Agents session state");
|
|
521
658
|
if (state == null || typeof state !== "object" || state.formatVersion !== SESSION_FORMAT_VERSION || state.sessionId !== this.sessionId || !Array.isArray(state.items) || state.operations == null || typeof state.operations !== "object" || Array.isArray(state.operations) || Object.values(state.operations).some((digest) => typeof digest !== "string")) {
|
|
522
659
|
throw new Error("unsupported or corrupt FerricStore OpenAI Agents session state");
|
|
523
660
|
}
|
|
524
|
-
return state;
|
|
661
|
+
return { expected, state };
|
|
525
662
|
}
|
|
526
663
|
emptyState() {
|
|
527
664
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/openai-agents.ts","../src/agent-persistence/durability.ts","../src/errors.ts","../src/agent-persistence/snapshot.ts"],"sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\n\nimport type {\n AgentInputItem,\n Session,\n SessionHistoryRewriteArgs,\n SessionHistoryRewriteAwareSession,\n SessionHistoryTransaction,\n SessionHistoryTransactionArgs,\n SessionHistoryTransactionAwareSession\n} from \"@openai/agents\";\n\nimport {\n normalizeKeyPrefix,\n type FerricStoreCommandClient,\n type FerricStoreLockOptions,\n withMutationLocks\n} from \"./agent-persistence/durability.js\";\nimport {\n cloneSnapshot,\n decodeSnapshot,\n encodeSnapshot,\n snapshotDigest,\n snapshotsEqual\n} from \"./agent-persistence/snapshot.js\";\n\nconst SESSION_FORMAT_VERSION = 1;\nconst SESSION_STATE_FIELD = \"state\";\n\ninterface StoredSessionState {\n readonly formatVersion: typeof SESSION_FORMAT_VERSION;\n readonly items: AgentInputItem[];\n readonly operations: Record<string, string>;\n readonly sessionId: string;\n}\n\nexport interface FerricStoreSessionOptions extends FerricStoreLockOptions {\n /** Existing conversation identifier. A random UUID is created when omitted. */\n sessionId?: string;\n /** Items used only when this session has not yet been persisted. */\n initialItems?: AgentInputItem[];\n /** FerricStore key prefix. Defaults to `openai:agents:session`. */\n keyPrefix?: string;\n}\n\n/**\n * Durable OpenAI Agents SDK conversation history backed by FerricStore.\n *\n * Every mutation is serialized by an ownership-checked, renewable FerricStore\n * lock. History transactions and their operation receipts are persisted in one\n * atomic hash-field write, implementing the SDK's retry-safe transaction\n * capability in addition to its base Session contract.\n */\nexport class FerricStoreSession implements\n Session,\n SessionHistoryRewriteAwareSession,\n SessionHistoryTransactionAwareSession {\n readonly client: FerricStoreCommandClient;\n readonly sessionId: string;\n readonly keyPrefix: string;\n private readonly initialItems: AgentInputItem[];\n private readonly lockOptions: FerricStoreLockOptions;\n private readonly sessionKey: string;\n private readonly lockKey: string;\n\n constructor(client: FerricStoreCommandClient, options: FerricStoreSessionOptions = {}) {\n this.client = client;\n this.sessionId = options.sessionId ?? randomUUID();\n if (typeof this.sessionId !== \"string\" || this.sessionId.trim().length === 0) {\n throw new TypeError(\"sessionId must be a non-empty string\");\n }\n this.keyPrefix = normalizeKeyPrefix(options.keyPrefix ?? \"openai:agents:session\", \"openai:agents:session\");\n this.initialItems = snapshotItems(options.initialItems ?? [], \"initialItems\");\n this.lockOptions = {\n lockRetryMs: options.lockRetryMs,\n lockTtlMs: options.lockTtlMs,\n lockWaitMs: options.lockWaitMs\n };\n const digest = createHash(\"sha256\").update(this.sessionId, \"utf8\").digest(\"hex\");\n this.sessionKey = `${this.keyPrefix}:{oais:${digest}}:session`;\n this.lockKey = `${this.keyPrefix}:{oais:${digest}}:mutation-lock`;\n }\n\n async getSessionId(): Promise<string> {\n await this.mutate(async (state) => state);\n return this.sessionId;\n }\n\n async getItems(limit?: number): Promise<AgentInputItem[]> {\n if (limit != null && limit <= 0) return [];\n if (limit != null && !Number.isSafeInteger(limit)) {\n throw new TypeError(\"limit must be a safe integer\");\n }\n const state = await this.readState();\n const items = limit == null ? state.items : state.items.slice(Math.max(state.items.length - limit, 0));\n return cloneSnapshot(items);\n }\n\n async addItems(items: AgentInputItem[]): Promise<void> {\n if (items.length === 0) return;\n const additions = snapshotItems(items, \"items\");\n await this.mutate(async (state) => ({\n ...state,\n items: [...state.items, ...additions]\n }));\n }\n\n async replaceHistoryWithCompaction(items: AgentInputItem[]): Promise<void> {\n const replacement = snapshotItems(items, \"items\");\n await this.mutate(async (state) => ({ ...state, items: replacement }));\n }\n\n async popItem(): Promise<AgentInputItem | undefined> {\n let popped: AgentInputItem | undefined;\n await this.mutate(async (state) => {\n popped = state.items.at(-1);\n return popped == null ? state : { ...state, items: state.items.slice(0, -1) };\n });\n return popped == null ? undefined : cloneSnapshot(popped);\n }\n\n async clearSession(): Promise<void> {\n await this.mutate(async (state) => ({ ...state, items: [], operations: {} }));\n }\n\n async applyHistoryMutations(args: SessionHistoryRewriteArgs): Promise<void> {\n if (args == null || !Array.isArray(args.mutations)) {\n throw new TypeError(\"session history mutations are invalid\");\n }\n if (args.mutations.length === 0) return;\n const mutations = cloneSnapshot(args.mutations);\n await this.mutate(async (state) => {\n let items = cloneSnapshot(state.items);\n for (const mutation of mutations) {\n if (mutation.type !== \"replace_function_call\") {\n throw new TypeError(\"unsupported session history mutation\");\n }\n const replacement = snapshotItem(mutation.replacement, \"mutation replacement\");\n let keptReplacement = false;\n const next: AgentInputItem[] = [];\n for (const item of items) {\n if (item.type === \"function_call\" && item.callId === mutation.callId) {\n if (!keptReplacement) {\n next.push(replacement);\n keptReplacement = true;\n }\n } else {\n next.push(item);\n }\n }\n items = next;\n }\n return { ...state, items };\n });\n }\n\n async applyHistoryTransaction(args: SessionHistoryTransactionArgs): Promise<void> {\n const { operationId, transaction } = snapshotTransactionArgs(args);\n const digest = snapshotDigest(transaction);\n await this.mutate(async (state) => {\n const existing = Object.getOwnPropertyDescriptor(state.operations, operationId)?.value as unknown;\n if (existing != null) {\n if (typeof existing !== \"string\") throw new Error(\"corrupt session history operation receipt\");\n if (existing !== digest) {\n throw new Error(\"session history operation was already applied with a different transaction\");\n }\n return state;\n }\n\n let items: AgentInputItem[];\n if (transaction.type === \"append_items\") {\n items = [...state.items, ...transaction.items];\n } else {\n const suffixStart = state.items.length - transaction.expectedSuffix.length;\n const actualSuffix = suffixStart < 0 ? [] : state.items.slice(suffixStart);\n if (suffixStart < 0 || !snapshotsEqual(actualSuffix, transaction.expectedSuffix)) {\n throw new Error(\"session history suffix no longer matches the transaction precondition\");\n }\n items = [...state.items.slice(0, suffixStart), ...transaction.replacement];\n }\n return {\n ...state,\n items,\n operations: { ...state.operations, [operationId]: digest }\n };\n });\n }\n\n private async mutate(\n operation: (state: StoredSessionState) => Promise<StoredSessionState>\n ): Promise<void> {\n await withMutationLocks(this.client, [this.lockKey], async () => {\n const current = await this.readState();\n const next = await operation(current);\n await this.client.command(\"HSET\", this.sessionKey, SESSION_STATE_FIELD, encodeSnapshot(next));\n }, this.lockOptions);\n }\n\n private async readState(): Promise<StoredSessionState> {\n const value = await this.client.command(\"HGET\", this.sessionKey, SESSION_STATE_FIELD);\n if (value == null) return this.emptyState();\n const state = decodeSnapshot<StoredSessionState>(value, \"OpenAI Agents session state\");\n if (\n state == null ||\n typeof state !== \"object\" ||\n state.formatVersion !== SESSION_FORMAT_VERSION ||\n state.sessionId !== this.sessionId ||\n !Array.isArray(state.items) ||\n state.operations == null ||\n typeof state.operations !== \"object\" ||\n Array.isArray(state.operations) ||\n Object.values(state.operations).some((digest) => typeof digest !== \"string\")\n ) {\n throw new Error(\"unsupported or corrupt FerricStore OpenAI Agents session state\");\n }\n return state;\n }\n\n private emptyState(): StoredSessionState {\n return {\n formatVersion: SESSION_FORMAT_VERSION,\n items: cloneSnapshot(this.initialItems),\n operations: {},\n sessionId: this.sessionId\n };\n }\n}\n\nfunction snapshotTransactionArgs(args: SessionHistoryTransactionArgs): {\n operationId: string;\n transaction: SessionHistoryTransaction;\n} {\n if (args == null || typeof args !== \"object\") throw new TypeError(\"session history transaction is invalid\");\n if (typeof args.operationId !== \"string\" || args.operationId.trim().length === 0) {\n throw new TypeError(\"session history transaction operationId must be a non-empty string\");\n }\n const transaction = cloneSnapshot(args.transaction);\n if (transaction == null || typeof transaction !== \"object\") {\n throw new TypeError(\"session history transaction must be an object\");\n }\n if (transaction.type === \"append_items\") {\n if (!Array.isArray(transaction.items)) throw new TypeError(\"session history append items are invalid\");\n return {\n operationId: args.operationId,\n transaction: { type: \"append_items\", items: snapshotItems(transaction.items, \"transaction items\") }\n };\n }\n if (transaction.type === \"replace_suffix\") {\n if (!Array.isArray(transaction.expectedSuffix) || !Array.isArray(transaction.replacement)) {\n throw new TypeError(\"session history suffix transaction is invalid\");\n }\n return {\n operationId: args.operationId,\n transaction: {\n type: \"replace_suffix\",\n expectedSuffix: snapshotItems(transaction.expectedSuffix, \"transaction expectedSuffix\"),\n replacement: snapshotItems(transaction.replacement, \"transaction replacement\")\n }\n };\n }\n throw new TypeError(\"unsupported session history transaction type\");\n}\n\nfunction snapshotItems(items: AgentInputItem[], name: string): AgentInputItem[] {\n if (!Array.isArray(items)) throw new TypeError(`${name} must be an array`);\n return items.map((item) => snapshotItem(item, name));\n}\n\nfunction snapshotItem(item: AgentInputItem, name: string): AgentInputItem {\n if (item == null || typeof item !== \"object\" || Array.isArray(item)) {\n throw new TypeError(`${name} contains an invalid agent item`);\n }\n return cloneSnapshot(item);\n}\n\nexport type {\n AgentInputItem,\n Session,\n SessionHistoryRewriteAwareSession,\n SessionHistoryTransactionAwareSession\n} from \"@openai/agents\";\n","import { randomUUID } from \"node:crypto\";\nimport { setTimeout as delay } from \"node:timers/promises\";\n\nimport { LockHeldError } from \"../errors.js\";\nimport type { Command, CommandArgument } from \"../internal.js\";\n\nexport interface FerricStoreCommandClient {\n command(...args: CommandArgument[]): Promise<unknown>;\n pipeline?(commands: readonly Command[]): Promise<unknown[]>;\n}\n\nexport interface FerricStoreLockOptions {\n /** Lease duration for adapter mutation locks. Defaults to five minutes. */\n lockTtlMs?: number;\n /** Maximum time to wait for a contended mutation lock. Defaults to 30 seconds. */\n lockWaitMs?: number;\n /** Delay between lock acquisition attempts. Defaults to 10 milliseconds. */\n lockRetryMs?: number;\n}\n\ninterface RequiredLockOptions {\n readonly lockRetryMs: number;\n readonly lockTtlMs: number;\n readonly lockWaitMs: number;\n}\n\nconst DEFAULT_LOCK_OPTIONS: RequiredLockOptions = {\n lockRetryMs: 10,\n lockTtlMs: 300_000,\n lockWaitMs: 30_000\n};\n\nexport function normalizeKeyPrefix(value: string, defaultValue: string): string {\n const prefix = value.length === 0 ? defaultValue : value;\n if (prefix.includes(\"\\0\")) throw new TypeError(\"keyPrefix must not contain NUL bytes\");\n const normalized = prefix.replace(/:+$/u, \"\");\n if (normalized.length === 0) throw new TypeError(\"keyPrefix must contain a character other than ':'\");\n return normalized;\n}\n\nexport function positiveInteger(value: number | undefined, fallback: number, name: string): number {\n const normalized = value ?? fallback;\n if (!Number.isSafeInteger(normalized) || normalized <= 0) {\n throw new TypeError(`${name} must be a positive safe integer`);\n }\n return normalized;\n}\n\nexport function nonNegativeInteger(value: number | undefined, fallback: number, name: string): number {\n const normalized = value ?? fallback;\n if (!Number.isSafeInteger(normalized) || normalized < 0) {\n throw new TypeError(`${name} must be a non-negative safe integer`);\n }\n return normalized;\n}\n\nexport function textResponse(value: unknown, name: string): string {\n if (typeof value === \"string\") return value;\n if (Buffer.isBuffer(value) || value instanceof Uint8Array) return Buffer.from(value).toString(\"utf8\");\n throw new TypeError(`FerricStore returned an invalid ${name}`);\n}\n\nexport function arrayResponse(value: unknown, name: string): unknown[] {\n if (!Array.isArray(value)) throw new TypeError(`FerricStore returned an invalid ${name}`);\n return value;\n}\n\nexport function integerResponse(value: unknown, name: string): number {\n const parsed = typeof value === \"number\" ? value : Number(textResponse(value, name));\n if (!Number.isSafeInteger(parsed)) throw new TypeError(`FerricStore returned an invalid ${name}`);\n return parsed;\n}\n\nexport async function executeCommands(\n client: FerricStoreCommandClient,\n commands: readonly Command[]\n): Promise<unknown[]> {\n if (commands.length === 0) return [];\n if (client.pipeline != null) return await client.pipeline(commands);\n return await Promise.all(commands.map(async (command) => await client.command(...command)));\n}\n\nexport async function withMutationLocks<T>(\n client: FerricStoreCommandClient,\n keys: readonly string[],\n operation: () => Promise<T>,\n options: FerricStoreLockOptions = {}\n): Promise<T> {\n const orderedKeys = [...new Set(keys)].sort();\n if (orderedKeys.length === 0) return await operation();\n\n const normalized: RequiredLockOptions = {\n lockRetryMs: positiveInteger(options.lockRetryMs, DEFAULT_LOCK_OPTIONS.lockRetryMs, \"lockRetryMs\"),\n lockTtlMs: positiveInteger(options.lockTtlMs, DEFAULT_LOCK_OPTIONS.lockTtlMs, \"lockTtlMs\"),\n lockWaitMs: nonNegativeInteger(options.lockWaitMs, DEFAULT_LOCK_OPTIONS.lockWaitMs, \"lockWaitMs\")\n };\n const owner = randomUUID();\n const acquired: string[] = [];\n const deadline = performance.now() + normalized.lockWaitMs;\n let primaryError: unknown;\n let heartbeatError: unknown;\n let releaseError: unknown;\n let result: T | undefined;\n let operationCompleted = false;\n const heartbeatAbort = new AbortController();\n\n try {\n for (const key of orderedKeys) {\n while (!(await tryAcquireLock(client, key, owner, normalized.lockTtlMs))) {\n if (performance.now() >= deadline) {\n throw new Error(`timed out acquiring FerricStore lock ${JSON.stringify(key)}`);\n }\n await delay(normalized.lockRetryMs);\n }\n acquired.push(key);\n }\n\n const heartbeat = renewLocks(\n client,\n acquired,\n owner,\n normalized.lockTtlMs,\n heartbeatAbort.signal,\n (error) => {\n heartbeatError ??= error;\n }\n );\n try {\n result = await operation();\n operationCompleted = true;\n } catch (error) {\n primaryError = error;\n } finally {\n heartbeatAbort.abort();\n await heartbeat;\n }\n } catch (error) {\n primaryError ??= error;\n } finally {\n heartbeatAbort.abort();\n for (const key of acquired.reverse()) {\n try {\n await client.command(\"UNLOCK\", key, owner);\n } catch (error) {\n releaseError ??= error;\n }\n }\n }\n if (primaryError != null) throw errorObject(primaryError);\n if (heartbeatError != null) throw errorObject(heartbeatError);\n if (releaseError != null) throw errorObject(releaseError);\n if (!operationCompleted) throw new Error(\"FerricStore mutation did not complete\");\n return result as T;\n}\n\nasync function tryAcquireLock(\n client: FerricStoreCommandClient,\n key: string,\n owner: string,\n ttlMs: number\n): Promise<boolean> {\n try {\n const response = await client.command(\"LOCK\", key, owner, ttlMs);\n return response === true || response === \"OK\" || Buffer.isBuffer(response) && response.equals(Buffer.from(\"OK\"));\n } catch (error) {\n if (error instanceof LockHeldError) return false;\n throw error;\n }\n}\n\nasync function renewLocks(\n client: FerricStoreCommandClient,\n keys: readonly string[],\n owner: string,\n ttlMs: number,\n signal: AbortSignal,\n onError: (error: unknown) => void\n): Promise<void> {\n const intervalMs = Math.max(Math.floor(ttlMs / 3), 10);\n const retryMs = Math.min(Math.max(Math.floor(intervalMs / 10), 10), 1_000);\n const lastExtended = new Map(keys.map((key) => [key, performance.now()]));\n let waitMs = intervalMs;\n while (!signal.aborted) {\n try {\n await delay(waitMs, undefined, { signal });\n } catch (error) {\n if (signal.aborted) return;\n onError(error);\n return;\n }\n const now = performance.now();\n let retry = false;\n for (const key of keys) {\n try {\n const response = await client.command(\"EXTEND\", key, owner, ttlMs);\n if (integerResponse(response, \"EXTEND response\") !== 1) {\n onError(new Error(`lost FerricStore lock ${JSON.stringify(key)} while mutating data`));\n return;\n }\n lastExtended.set(key, now);\n } catch (error) {\n if (now - (lastExtended.get(key) ?? 0) >= ttlMs) {\n onError(new Error(`lost FerricStore lock ${JSON.stringify(key)} while mutating data`, { cause: error }));\n return;\n }\n retry = true;\n }\n }\n waitMs = retry ? retryMs : intervalMs;\n }\n}\n\nfunction errorObject(value: unknown): Error {\n return value instanceof Error ? value : new Error(\"FerricStore mutation failed\", { cause: value });\n}\n","export class FerricStoreError extends Error {\n readonly code: string = \"ferricstore_error\";\n readonly raw: unknown;\n readonly retryable: boolean | undefined;\n readonly safeToRetry: boolean | undefined;\n readonly retryAfterMs: number | undefined;\n\n constructor(message: string, options: {\n raw?: unknown;\n cause?: unknown;\n retryable?: boolean;\n safeToRetry?: boolean;\n retryAfterMs?: number;\n } = {}) {\n super(message, { cause: options.cause });\n this.name = new.target.name;\n this.raw = options.raw;\n this.retryable = options.retryable ?? structuredBooleanField(options.raw, \"retryable\");\n this.safeToRetry = options.safeToRetry ?? structuredBooleanField(options.raw, \"safe_to_retry\");\n this.retryAfterMs = options.retryAfterMs ?? structuredIntegerField(options.raw, \"retry_after_ms\");\n }\n}\n\nexport class HTTPTransportError extends FerricStoreError {\n override readonly code = \"http_transport\";\n readonly statusCode: number | undefined;\n\n constructor(message: string, options: ConstructorParameters<typeof FerricStoreError>[1] & {\n statusCode?: number;\n } = {}) {\n super(message, options);\n this.statusCode = options.statusCode;\n }\n}\n\nexport type RequestDisposition = \"unsent\" | \"possibly_sent\";\n/** @deprecated Use RequestDisposition; retained for source compatibility. */\nexport type ConnectionRequestDisposition = RequestDisposition;\n\n/** Connection closure annotated with whether the current request may have reached the server. */\nexport class ConnectionClosedError extends FerricStoreError {\n override readonly code = \"connection_closed\";\n readonly requestDisposition: RequestDisposition;\n\n constructor(\n requestDisposition: RequestDisposition,\n options: { raw?: unknown; cause?: unknown; message?: string } = {}\n ) {\n super(\n options.message ?? (requestDisposition === \"unsent\"\n ? \"FerricStore connection is closed\"\n : \"FerricStore connection closed\"),\n options\n );\n this.requestDisposition = requestDisposition;\n }\n}\n\n/** Request timeout annotated with whether the request may have reached the server. */\nexport class RequestTimeoutError extends FerricStoreError {\n override readonly code = \"request_timeout\";\n readonly requestDisposition: RequestDisposition;\n readonly timeoutMs: number;\n\n constructor(\n timeoutMs: number,\n requestDisposition: RequestDisposition,\n options: { raw?: unknown; cause?: unknown } = {}\n ) {\n super(`FerricStore request timed out after ${timeoutMs}ms`, options);\n this.requestDisposition = requestDisposition;\n this.timeoutMs = timeoutMs;\n }\n}\n\nexport class FlowNotFoundError extends FerricStoreError {\n override readonly code = \"flow_not_found\";\n}\n\nexport class FlowWrongStateError extends FerricStoreError {\n override readonly code = \"flow_wrong_state\";\n}\n\nexport class StaleLeaseError extends FerricStoreError {\n override readonly code = \"stale_lease\";\n}\n\n/** FLOW.POLICY.SET expected_generation did not match the stored generation. */\nexport class StalePolicyGenerationError extends FerricStoreError {\n override readonly code = \"stale_policy_generation\";\n}\n\nexport class FlowAlreadyExistsError extends FerricStoreError {\n override readonly code = \"flow_already_exists\";\n}\n\nexport class LockHeldError extends FerricStoreError {\n override readonly code = \"lock_held\";\n}\n\nexport class LockNotOwnedError extends FerricStoreError {\n override readonly code = \"lock_not_owned\";\n}\n\nexport class InvalidCommandError extends FerricStoreError {\n override readonly code = \"invalid_command\";\n}\n\nexport class OverloadedError extends FerricStoreError {\n override readonly code = \"overloaded\";\n readonly reason: string | undefined;\n\n constructor(\n message: string,\n options: {\n raw?: unknown;\n cause?: unknown;\n retryAfterMs?: number;\n reason?: string;\n retryable?: boolean;\n safeToRetry?: boolean;\n } = {}\n ) {\n const local = options.raw == null;\n super(message, {\n ...options,\n retryable: options.retryable ?? (local ? true : undefined),\n safeToRetry: options.safeToRetry ?? (local ? true : undefined)\n });\n this.reason = options.reason;\n }\n}\n\n/** The contacted endpoint cannot serve this route and topology should be refreshed. */\nexport class RerouteError extends FerricStoreError {\n override readonly code = \"reroute\";\n}\n\nconst OVERLOAD_CODES = new Set([\n \"backpressure\",\n \"busy\",\n \"flow_control_window_exhausted\",\n \"lane_queue_full\",\n \"overloaded\"\n]);\n\nexport function classifyServerError(\n message: string,\n raw?: unknown,\n cause?: unknown,\n status?: number | string\n): FerricStoreError {\n const lower = message.toLowerCase();\n const structuredCode = structuredStringField(raw, \"code\");\n const code = structuredCode?.toLowerCase();\n const retry = {\n retryable: structuredBooleanField(raw, \"retryable\"),\n safeToRetry: structuredBooleanField(raw, \"safe_to_retry\"),\n retryAfterMs: structuredIntegerField(raw, \"retry_after_ms\") ?? intField(lower, \"retry_after_ms\")\n };\n\n if (isRerouteStatus(status) || code === \"reroute\") {\n return new RerouteError(message, { cause, raw, ...definedRetryMetadata(retry) });\n }\n if (isBusyStatus(status) || isOverloadCode(structuredCode) || overloadMessage(lower)) {\n return new OverloadedError(message, {\n cause,\n raw,\n ...definedRetryMetadata(retry),\n reason: structuredStringField(raw, \"reason\") ?? structuredCode ?? stringField(lower, \"reason\"),\n retryAfterMs: retry.retryAfterMs\n });\n }\n if (code === \"flow_already_exists\" || (lower.includes(\"flow\") && lower.includes(\"already exists\"))) {\n return new FlowAlreadyExistsError(message, { cause, raw });\n }\n if (lower.includes(\"flow wrong state\") || code === \"flow_wrong_state\") {\n return new FlowWrongStateError(message, { cause, raw });\n }\n if (\n code === \"stale_lease\"\n || code === \"stale_flow_lease\"\n || lower.includes(\"stale flow lease\")\n || lower.includes(\"stale lease\")\n || lower.includes(\"stale token\")\n ) {\n return new StaleLeaseError(message, { cause, raw });\n }\n if (\n code === \"stale_generation\"\n || code === \"stale_policy_generation\"\n || code === \"stale_flow_policy_generation\"\n || lower.includes(\"stale flow policy generation\")\n || lower.includes(\"stale policy generation\")\n ) {\n return new StalePolicyGenerationError(message, { cause, raw });\n }\n if (\n code === \"flow_not_found\"\n || (lower.includes(\"flow\") && (lower.includes(\"not found\") || lower.includes(\"does not exist\")))\n ) {\n return new FlowNotFoundError(message, { cause, raw });\n }\n if (code === \"lock_held\" || lower.includes(\"lock is held\") || lower.includes(\"held by another owner\")) {\n return new LockHeldError(message, { cause, raw });\n }\n if (code === \"lock_not_owned\" || lower.includes(\"not the lock owner\") || lower.includes(\"caller is not the lock owner\")) {\n return new LockNotOwnedError(message, { cause, raw });\n }\n if (code === \"invalid_command\" || lower.includes(\"wrong number of arguments\") || lower.includes(\"syntax error\")) {\n return new InvalidCommandError(message, { cause, raw });\n }\n\n return new FerricStoreError(message, { cause, raw, ...definedRetryMetadata(retry) });\n}\n\nexport function mapException(error: unknown): unknown {\n if (error instanceof FerricStoreError) {\n return error;\n }\n\n if (!(error instanceof Error)) {\n return error;\n }\n\n const message = error.message;\n const serverLike =\n error.name === \"ResponseError\" ||\n message.startsWith(\"ERR \") ||\n message.startsWith(\"WRONGTYPE \") ||\n message.startsWith(\"DISTLOCK \");\n\n if (!serverLike) {\n return error;\n }\n\n return classifyServerError(message, error, error);\n}\n\nfunction intField(message: string, name: string): number | undefined {\n const match = new RegExp(`\\\\b${name}=([0-9]+)\\\\b`).exec(message);\n return match?.[1] == null ? undefined : nonNegativeSafeIntegerText(match[1]);\n}\n\nfunction isBusyStatus(status: number | string | undefined): boolean {\n return status === 4 || (typeof status === \"string\" && (status === \"4\" || status.toLowerCase() === \"busy\"));\n}\n\nfunction isRerouteStatus(status: number | string | undefined): boolean {\n return status === 5 || (typeof status === \"string\" && (status === \"5\" || status.toLowerCase() === \"reroute\"));\n}\n\nfunction isOverloadCode(code: string | undefined): boolean {\n return code != null && OVERLOAD_CODES.has(code.toLowerCase());\n}\n\nfunction overloadMessage(message: string): boolean {\n return /\\boverloaded\\b/u.test(message) || /(?:^|\\s)busy(?:\\s|:|$)/u.test(message);\n}\n\nfunction structuredIntegerField(raw: unknown, name: string): number | undefined {\n const value = structuredField(raw, name);\n if (typeof value === \"number\") {\n return Number.isSafeInteger(value) && value >= 0 ? value : undefined;\n }\n if (typeof value === \"bigint\") {\n return value >= 0n && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : undefined;\n }\n const text = binaryText(value);\n return text == null ? undefined : nonNegativeSafeIntegerText(text);\n}\n\nfunction structuredBooleanField(raw: unknown, name: string): boolean | undefined {\n const value = structuredField(raw, name);\n if (typeof value === \"boolean\") return value;\n const text = binaryText(value)?.toLowerCase();\n if (text === \"true\" || text === \"1\") return true;\n if (text === \"false\" || text === \"0\") return false;\n return undefined;\n}\n\nfunction definedRetryMetadata(metadata: {\n readonly retryable?: boolean;\n readonly safeToRetry?: boolean;\n readonly retryAfterMs?: number;\n}): { retryable?: boolean; safeToRetry?: boolean; retryAfterMs?: number } {\n return {\n ...(metadata.retryable == null ? {} : { retryable: metadata.retryable }),\n ...(metadata.safeToRetry == null ? {} : { safeToRetry: metadata.safeToRetry }),\n ...(metadata.retryAfterMs == null ? {} : { retryAfterMs: metadata.retryAfterMs })\n };\n}\n\nfunction nonNegativeSafeIntegerText(value: string): number | undefined {\n if (!/^[0-9]+$/u.test(value)) return undefined;\n const parsed = Number.parseInt(value, 10);\n return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : undefined;\n}\n\nfunction structuredStringField(raw: unknown, name: string): string | undefined {\n return binaryText(structuredField(raw, name));\n}\n\nfunction structuredField(raw: unknown, name: string): unknown {\n if (raw instanceof Map) {\n if (raw.has(name)) return raw.get(name);\n for (const [key, value] of raw.entries()) {\n if (binaryText(key) === name) return value;\n }\n return undefined;\n }\n if (typeof raw === \"object\" && raw != null && Object.hasOwn(raw, name)) {\n return (raw as Record<string, unknown>)[name];\n }\n return undefined;\n}\n\nfunction binaryText(value: unknown): string | undefined {\n if (typeof value === \"string\") return value;\n if (Buffer.isBuffer(value) || value instanceof Uint8Array) return Buffer.from(value).toString(\"utf8\");\n return undefined;\n}\n\nfunction stringField(message: string, name: string): string | undefined {\n const match = new RegExp(`\\\\b${name}=([a-z0-9_:-]+)\\\\b`).exec(message);\n return match?.[1];\n}\n","import { createHash } from \"node:crypto\";\n\ntype EncodedSnapshot =\n | [\"array\", EncodedSnapshot[]]\n | [\"binary\", string]\n | [\"boolean\", boolean]\n | [\"null\"]\n | [\"number\", number | \"NaN\" | \"+Infinity\" | \"-Infinity\" | \"-0\"]\n | [\"object\", [string, EncodedSnapshot][]]\n | [\"string\", string]\n | [\"undefined\"];\n\nexport function encodeSnapshot(value: unknown): Buffer {\n return Buffer.from(JSON.stringify(snapshot(value, new WeakSet())), \"utf8\");\n}\n\nexport function decodeSnapshot<T>(value: unknown, name: string): T {\n const bytes = typeof value === \"string\" ? Buffer.from(value, \"utf8\") : Buffer.from(asBytes(value, name));\n let encoded: unknown;\n try {\n encoded = JSON.parse(bytes.toString(\"utf8\"));\n } catch (error) {\n throw new Error(`FerricStore returned an invalid ${name}`, { cause: error });\n }\n return restore(encoded, name) as T;\n}\n\nexport function snapshotDigest(value: unknown): string {\n return createHash(\"sha256\").update(encodeSnapshot(value)).digest(\"hex\");\n}\n\nexport function cloneSnapshot<T>(value: T): T {\n return decodeSnapshot<T>(encodeSnapshot(value), \"snapshot\");\n}\n\nexport function snapshotsEqual(left: unknown, right: unknown): boolean {\n return encodeSnapshot(left).equals(encodeSnapshot(right));\n}\n\nfunction snapshot(value: unknown, ancestors: WeakSet<object>): EncodedSnapshot {\n if (value === null) return [\"null\"];\n if (value === undefined) return [\"undefined\"];\n if (typeof value === \"string\") return [\"string\", value];\n if (typeof value === \"boolean\") return [\"boolean\", value];\n if (typeof value === \"number\") {\n if (Object.is(value, -0)) return [\"number\", \"-0\"];\n if (Number.isNaN(value)) return [\"number\", \"NaN\"];\n if (value === Infinity) return [\"number\", \"+Infinity\"];\n if (value === -Infinity) return [\"number\", \"-Infinity\"];\n return [\"number\", value];\n }\n if (typeof value !== \"object\") throw new TypeError(\"session history contains unsupported data\");\n if (value instanceof Uint8Array) {\n const keys = Reflect.ownKeys(value);\n if (\n keys.length !== value.length ||\n keys.some((key) => typeof key !== \"string\" || !isArrayIndex(key, value.length))\n ) {\n throw new TypeError(\"session history binary data contains custom properties\");\n }\n return [\"binary\", Buffer.from(value).toString(\"base64\")];\n }\n if (ancestors.has(value)) throw new TypeError(\"session history contains cyclic data\");\n ancestors.add(value);\n try {\n if (Array.isArray(value)) {\n const keys = Reflect.ownKeys(value);\n if (\n keys.length !== value.length + 1 ||\n keys.some((key) => typeof key !== \"string\" || key !== \"length\" && !isArrayIndex(key, value.length))\n ) {\n throw new TypeError(\"session history contains a sparse or customized array\");\n }\n const items: EncodedSnapshot[] = [];\n for (let index = 0; index < value.length; index += 1) {\n const descriptor = Object.getOwnPropertyDescriptor(value, String(index));\n if (descriptor == null || !descriptor.enumerable || !(\"value\" in descriptor)) {\n throw new TypeError(\"session history contains an unsupported array item\");\n }\n items.push(snapshot(descriptor.value as unknown, ancestors));\n }\n return [\"array\", items];\n }\n const prototype: unknown = Object.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) {\n throw new TypeError(\"session history contains an unsupported object\");\n }\n const keys = Reflect.ownKeys(value);\n if (keys.some((key) => typeof key !== \"string\")) {\n throw new TypeError(\"session history contains a symbol property\");\n }\n const entries: [string, EncodedSnapshot][] = [];\n for (const key of (keys as string[]).sort((left, right) => left.localeCompare(right))) {\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n if (descriptor == null || !descriptor.enumerable || !(\"value\" in descriptor)) {\n throw new TypeError(\"session history contains an unsupported property\");\n }\n entries.push([key, snapshot(descriptor.value as unknown, ancestors)]);\n }\n return [\"object\", entries];\n } finally {\n ancestors.delete(value);\n }\n}\n\nfunction restore(value: unknown, name: string): unknown {\n if (!Array.isArray(value) || typeof value[0] !== \"string\") throw new TypeError(`invalid ${name}`);\n switch (value[0]) {\n case \"null\": return null;\n case \"undefined\": return undefined;\n case \"string\": return requireValueType(value[1], \"string\", name);\n case \"boolean\": return requireValueType(value[1], \"boolean\", name);\n case \"binary\": return Buffer.from(requireValueType(value[1], \"string\", name), \"base64\");\n case \"number\": return restoreNumber(value[1], name);\n case \"array\": {\n if (!Array.isArray(value[1])) throw new TypeError(`invalid ${name}`);\n return value[1].map((item) => restore(item, name));\n }\n case \"object\": {\n if (!Array.isArray(value[1])) throw new TypeError(`invalid ${name}`);\n const result: Record<string, unknown> = {};\n for (const entry of value[1]) {\n if (!Array.isArray(entry) || entry.length !== 2 || typeof entry[0] !== \"string\") {\n throw new TypeError(`invalid ${name}`);\n }\n Object.defineProperty(result, entry[0], {\n configurable: true,\n enumerable: true,\n value: restore(entry[1], name),\n writable: true\n });\n }\n return result;\n }\n default: throw new TypeError(`invalid ${name}`);\n }\n}\n\nfunction restoreNumber(value: unknown, name: string): number {\n if (typeof value === \"number\") return value;\n if (value === \"NaN\") return Number.NaN;\n if (value === \"+Infinity\") return Infinity;\n if (value === \"-Infinity\") return -Infinity;\n if (value === \"-0\") return -0;\n throw new TypeError(`invalid ${name}`);\n}\n\nfunction requireValueType<T extends \"boolean\" | \"string\">(\n value: unknown,\n type: T,\n name: string\n): T extends \"string\" ? string : boolean {\n if (typeof value !== type) throw new TypeError(`invalid ${name}`);\n return value as T extends \"string\" ? string : boolean;\n}\n\nfunction asBytes(value: unknown, name: string): Uint8Array {\n if (Buffer.isBuffer(value) || value instanceof Uint8Array) return value;\n throw new TypeError(`FerricStore returned a non-binary ${name}`);\n}\n\nfunction isArrayIndex(key: string, length: number): boolean {\n if (!/^(?:0|[1-9]\\d*)$/u.test(key)) return false;\n const index = Number(key);\n return Number.isSafeInteger(index) && index >= 0 && index < length;\n}\n"],"mappings":"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","names":["import_node_crypto","delay","import_node_crypto","keys"]}
|
|
1
|
+
{"version":3,"sources":["../src/openai-agents.ts","../src/agent-persistence/durability.ts","../src/errors.ts","../src/agent-persistence/snapshot.ts"],"sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\n\nimport type {\n AgentInputItem,\n Session,\n SessionHistoryRewriteArgs,\n SessionHistoryRewriteAwareSession,\n SessionHistoryTransaction,\n SessionHistoryTransactionArgs,\n SessionHistoryTransactionAwareSession\n} from \"@openai/agents\";\n\nimport {\n normalizeKeyPrefix,\n readAtomicValue,\n type FerricStoreCommandClient,\n type FerricStoreLockOptions,\n withMutationLocks\n} from \"./agent-persistence/durability.js\";\nimport {\n cloneSnapshot,\n decodeSnapshot,\n encodeSnapshot,\n legacySnapshotDigest,\n snapshotDigest,\n snapshotsEqual\n} from \"./agent-persistence/snapshot.js\";\n\nconst SESSION_FORMAT_VERSION = 1;\nconst SESSION_STATE_FIELD = \"state\";\nconst RECEIPT_DIGEST_VERSION = \"v2:\";\n\ninterface StoredSessionState {\n readonly formatVersion: typeof SESSION_FORMAT_VERSION;\n readonly items: AgentInputItem[];\n readonly operations: Record<string, string>;\n readonly sessionId: string;\n}\n\nexport interface FerricStoreSessionOptions extends FerricStoreLockOptions {\n /** Existing conversation identifier. A random UUID is created when omitted. */\n sessionId?: string;\n /** Items used only when this session has not yet been persisted. */\n initialItems?: AgentInputItem[];\n /** FerricStore key prefix. Defaults to `openai:agents:session`. */\n keyPrefix?: string;\n /** Previous worker locales to accept when migrating unversioned operation receipts. */\n legacyReceiptLocales?: string[];\n}\n\n/**\n * Durable OpenAI Agents SDK conversation history backed by FerricStore.\n *\n * Renewable locks reduce contention, while compare-and-swap makes every state\n * commit safe even if a writer's lease expires in flight. History transactions\n * and their operation receipts are persisted in one atomic value, implementing\n * the SDK's retry-safe transaction capability in addition to its base Session\n * contract.\n */\nexport class FerricStoreSession implements\n Session,\n SessionHistoryRewriteAwareSession,\n SessionHistoryTransactionAwareSession {\n readonly client: FerricStoreCommandClient;\n readonly sessionId: string;\n readonly keyPrefix: string;\n private readonly initialItems: AgentInputItem[];\n private readonly lockOptions: FerricStoreLockOptions;\n private readonly legacyReceiptLocales: readonly string[];\n private readonly sessionKey: string;\n private readonly stateKey: string;\n private readonly lockKey: string;\n\n constructor(client: FerricStoreCommandClient, options: FerricStoreSessionOptions = {}) {\n this.client = client;\n this.sessionId = options.sessionId ?? randomUUID();\n if (typeof this.sessionId !== \"string\" || this.sessionId.trim().length === 0) {\n throw new TypeError(\"sessionId must be a non-empty string\");\n }\n this.keyPrefix = normalizeKeyPrefix(options.keyPrefix ?? \"openai:agents:session\", \"openai:agents:session\");\n this.initialItems = snapshotItems(options.initialItems ?? [], \"initialItems\");\n this.lockOptions = {\n lockRetryMs: options.lockRetryMs,\n lockTtlMs: options.lockTtlMs,\n lockWaitMs: options.lockWaitMs\n };\n if (options.legacyReceiptLocales != null && !Array.isArray(options.legacyReceiptLocales)) {\n throw new TypeError(\"legacyReceiptLocales must be an array\");\n }\n try {\n this.legacyReceiptLocales = Intl.getCanonicalLocales(options.legacyReceiptLocales ?? []);\n } catch (error) {\n throw new TypeError(\"legacyReceiptLocales contains an invalid locale\", { cause: error });\n }\n const digest = createHash(\"sha256\").update(this.sessionId, \"utf8\").digest(\"hex\");\n this.sessionKey = `${this.keyPrefix}:{oais:${digest}}:session`;\n this.stateKey = `${this.sessionKey}:atomic-state`;\n this.lockKey = `${this.keyPrefix}:{oais:${digest}}:mutation-lock`;\n }\n\n async getSessionId(): Promise<string> {\n await this.mutate(async (state) => state);\n return this.sessionId;\n }\n\n async getItems(limit?: number): Promise<AgentInputItem[]> {\n if (limit != null && limit <= 0) return [];\n if (limit != null && !Number.isSafeInteger(limit)) {\n throw new TypeError(\"limit must be a safe integer\");\n }\n const state = await this.readState();\n const items = limit == null ? state.items : state.items.slice(Math.max(state.items.length - limit, 0));\n return cloneSnapshot(items);\n }\n\n async addItems(items: AgentInputItem[]): Promise<void> {\n if (items.length === 0) return;\n const additions = snapshotItems(items, \"items\");\n await this.mutate(async (state) => ({\n ...state,\n items: [...state.items, ...additions]\n }));\n }\n\n async replaceHistoryWithCompaction(items: AgentInputItem[]): Promise<void> {\n const replacement = snapshotItems(items, \"items\");\n await this.mutate(async (state) => ({ ...state, items: replacement }));\n }\n\n async popItem(): Promise<AgentInputItem | undefined> {\n let popped: AgentInputItem | undefined;\n await this.mutate(async (state) => {\n popped = state.items.at(-1);\n return popped == null ? state : { ...state, items: state.items.slice(0, -1) };\n });\n return popped == null ? undefined : cloneSnapshot(popped);\n }\n\n async clearSession(): Promise<void> {\n await this.mutate(async (state) => ({ ...state, items: [], operations: {} }));\n }\n\n async applyHistoryMutations(args: SessionHistoryRewriteArgs): Promise<void> {\n if (args == null || !Array.isArray(args.mutations)) {\n throw new TypeError(\"session history mutations are invalid\");\n }\n if (args.mutations.length === 0) return;\n const mutations = cloneSnapshot(args.mutations);\n await this.mutate(async (state) => {\n let items = cloneSnapshot(state.items);\n for (const mutation of mutations) {\n if (mutation.type !== \"replace_function_call\") {\n throw new TypeError(\"unsupported session history mutation\");\n }\n const replacement = snapshotItem(mutation.replacement, \"mutation replacement\");\n let keptReplacement = false;\n const next: AgentInputItem[] = [];\n for (const item of items) {\n if (item.type === \"function_call\" && item.callId === mutation.callId) {\n if (!keptReplacement) {\n next.push(replacement);\n keptReplacement = true;\n }\n } else {\n next.push(item);\n }\n }\n items = next;\n }\n return { ...state, items };\n });\n }\n\n async applyHistoryTransaction(args: SessionHistoryTransactionArgs): Promise<void> {\n const { operationId, transaction } = snapshotTransactionArgs(args);\n const digest = `${RECEIPT_DIGEST_VERSION}${snapshotDigest(transaction)}`;\n const legacyDigests = new Set([\n snapshotDigest(transaction),\n legacySnapshotDigest(transaction),\n ...this.legacyReceiptLocales.map((locale) => legacySnapshotDigest(transaction, locale))\n ]);\n await this.mutate(async (state) => {\n const existing = Object.getOwnPropertyDescriptor(state.operations, operationId)?.value as unknown;\n if (existing != null) {\n if (typeof existing !== \"string\") throw new Error(\"corrupt session history operation receipt\");\n if (existing === digest) return state;\n if (!legacyDigests.has(existing)) {\n throw new Error(\"session history operation was already applied with a different transaction\");\n }\n return { ...state, operations: { ...state.operations, [operationId]: digest } };\n }\n\n let items: AgentInputItem[];\n if (transaction.type === \"append_items\") {\n items = [...state.items, ...transaction.items];\n } else {\n const suffixStart = state.items.length - transaction.expectedSuffix.length;\n const actualSuffix = suffixStart < 0 ? [] : state.items.slice(suffixStart);\n if (suffixStart < 0 || !snapshotsEqual(actualSuffix, transaction.expectedSuffix)) {\n throw new Error(\"session history suffix no longer matches the transaction precondition\");\n }\n items = [...state.items.slice(0, suffixStart), ...transaction.replacement];\n }\n return {\n ...state,\n items,\n operations: { ...state.operations, [operationId]: digest }\n };\n });\n }\n\n private async mutate(\n operation: (state: StoredSessionState) => Promise<StoredSessionState>\n ): Promise<void> {\n await withMutationLocks(this.client, [this.lockKey], async (lease) => {\n for (let attempt = 0; attempt < 8; attempt += 1) {\n lease.assertOwned();\n const snapshot = await this.readMutationState();\n const next = await operation(snapshot.state);\n if (await lease.compareAndSet(this.stateKey, snapshot.expected, encodeSnapshot(next))) return;\n }\n throw new Error(\"concurrent FerricStore OpenAI Agents session mutation did not converge\");\n }, this.lockOptions);\n }\n\n private async readState(): Promise<StoredSessionState> {\n return (await this.readMutationState()).state;\n }\n\n private async readMutationState(): Promise<{ expected: Buffer | undefined; state: StoredSessionState }> {\n const expected = await readAtomicValue(this.client, this.stateKey, \"OpenAI Agents atomic session state\");\n const value = expected ?? await this.client.command(\"HGET\", this.sessionKey, SESSION_STATE_FIELD);\n if (value == null) return { expected, state: this.emptyState() };\n const state = decodeSnapshot<StoredSessionState>(value, \"OpenAI Agents session state\");\n if (\n state == null ||\n typeof state !== \"object\" ||\n state.formatVersion !== SESSION_FORMAT_VERSION ||\n state.sessionId !== this.sessionId ||\n !Array.isArray(state.items) ||\n state.operations == null ||\n typeof state.operations !== \"object\" ||\n Array.isArray(state.operations) ||\n Object.values(state.operations).some((digest) => typeof digest !== \"string\")\n ) {\n throw new Error(\"unsupported or corrupt FerricStore OpenAI Agents session state\");\n }\n return { expected, state };\n }\n\n private emptyState(): StoredSessionState {\n return {\n formatVersion: SESSION_FORMAT_VERSION,\n items: cloneSnapshot(this.initialItems),\n operations: {},\n sessionId: this.sessionId\n };\n }\n}\n\nfunction snapshotTransactionArgs(args: SessionHistoryTransactionArgs): {\n operationId: string;\n transaction: SessionHistoryTransaction;\n} {\n if (args == null || typeof args !== \"object\") throw new TypeError(\"session history transaction is invalid\");\n if (typeof args.operationId !== \"string\" || args.operationId.trim().length === 0) {\n throw new TypeError(\"session history transaction operationId must be a non-empty string\");\n }\n const transaction = cloneSnapshot(args.transaction);\n if (transaction == null || typeof transaction !== \"object\") {\n throw new TypeError(\"session history transaction must be an object\");\n }\n if (transaction.type === \"append_items\") {\n if (!Array.isArray(transaction.items)) throw new TypeError(\"session history append items are invalid\");\n return {\n operationId: args.operationId,\n transaction: { type: \"append_items\", items: snapshotItems(transaction.items, \"transaction items\") }\n };\n }\n if (transaction.type === \"replace_suffix\") {\n if (!Array.isArray(transaction.expectedSuffix) || !Array.isArray(transaction.replacement)) {\n throw new TypeError(\"session history suffix transaction is invalid\");\n }\n return {\n operationId: args.operationId,\n transaction: {\n type: \"replace_suffix\",\n expectedSuffix: snapshotItems(transaction.expectedSuffix, \"transaction expectedSuffix\"),\n replacement: snapshotItems(transaction.replacement, \"transaction replacement\")\n }\n };\n }\n throw new TypeError(\"unsupported session history transaction type\");\n}\n\nfunction snapshotItems(items: AgentInputItem[], name: string): AgentInputItem[] {\n if (!Array.isArray(items)) throw new TypeError(`${name} must be an array`);\n return items.map((item) => snapshotItem(item, name));\n}\n\nfunction snapshotItem(item: AgentInputItem, name: string): AgentInputItem {\n if (item == null || typeof item !== \"object\" || Array.isArray(item)) {\n throw new TypeError(`${name} contains an invalid agent item`);\n }\n return cloneSnapshot(item);\n}\n\nexport type {\n AgentInputItem,\n Session,\n SessionHistoryRewriteAwareSession,\n SessionHistoryTransactionAwareSession\n} from \"@openai/agents\";\n","import { randomUUID } from \"node:crypto\";\nimport { setTimeout as delay } from \"node:timers/promises\";\n\nimport { LockHeldError } from \"../errors.js\";\nimport type { Command, CommandArgument } from \"../internal.js\";\n\nexport interface FerricStoreCommandClient {\n command(...args: CommandArgument[]): Promise<unknown>;\n pipeline?(commands: readonly Command[]): Promise<unknown[]>;\n}\n\nexport interface FerricStoreLockOptions {\n /** Lease duration for adapter mutation locks. Defaults to five minutes. */\n lockTtlMs?: number;\n /** Maximum time to wait for a contended mutation lock. Defaults to 30 seconds. */\n lockWaitMs?: number;\n /** Delay between lock acquisition attempts. Defaults to 10 milliseconds. */\n lockRetryMs?: number;\n}\n\nexport interface FerricStoreMutationLease {\n /** Aborted as soon as lock ownership is known to have been lost. */\n readonly signal: AbortSignal;\n /** Throw when this mutation no longer owns every requested lock. */\n assertOwned(): void;\n /** Publish an idempotent, add-only discovery entry before its CAS record. */\n publish(...args: CommandArgument[]): Promise<unknown>;\n /** Atomically replace a value only when its last-read bytes are still current. */\n compareAndSet(key: string, expected: Buffer | undefined, value: Buffer): Promise<boolean>;\n}\n\ninterface RequiredLockOptions {\n readonly lockRetryMs: number;\n readonly lockTtlMs: number;\n readonly lockWaitMs: number;\n}\n\nconst DEFAULT_LOCK_OPTIONS: RequiredLockOptions = {\n lockRetryMs: 10,\n lockTtlMs: 300_000,\n lockWaitMs: 30_000\n};\n\nexport function normalizeKeyPrefix(value: string, defaultValue: string): string {\n const prefix = value.length === 0 ? defaultValue : value;\n if (prefix.includes(\"\\0\")) throw new TypeError(\"keyPrefix must not contain NUL bytes\");\n const normalized = prefix.replace(/:+$/u, \"\");\n if (normalized.length === 0) throw new TypeError(\"keyPrefix must contain a character other than ':'\");\n return normalized;\n}\n\nexport function positiveInteger(value: number | undefined, fallback: number, name: string): number {\n const normalized = value ?? fallback;\n if (!Number.isSafeInteger(normalized) || normalized <= 0) {\n throw new TypeError(`${name} must be a positive safe integer`);\n }\n return normalized;\n}\n\nexport function nonNegativeInteger(value: number | undefined, fallback: number, name: string): number {\n const normalized = value ?? fallback;\n if (!Number.isSafeInteger(normalized) || normalized < 0) {\n throw new TypeError(`${name} must be a non-negative safe integer`);\n }\n return normalized;\n}\n\nexport function textResponse(value: unknown, name: string): string {\n if (typeof value === \"string\") return value;\n if (Buffer.isBuffer(value) || value instanceof Uint8Array) return Buffer.from(value).toString(\"utf8\");\n throw new TypeError(`FerricStore returned an invalid ${name}`);\n}\n\nexport function arrayResponse(value: unknown, name: string): unknown[] {\n if (!Array.isArray(value)) throw new TypeError(`FerricStore returned an invalid ${name}`);\n return value;\n}\n\nexport function integerResponse(value: unknown, name: string): number {\n const parsed = typeof value === \"number\" ? value : Number(textResponse(value, name));\n if (!Number.isSafeInteger(parsed)) throw new TypeError(`FerricStore returned an invalid ${name}`);\n return parsed;\n}\n\nexport async function executeCommands(\n client: FerricStoreCommandClient,\n commands: readonly Command[]\n): Promise<unknown[]> {\n if (commands.length === 0) return [];\n if (client.pipeline != null) return await client.pipeline(commands);\n return await Promise.all(commands.map(async (command) => await client.command(...command)));\n}\n\nexport async function readAtomicValue(\n client: FerricStoreCommandClient,\n key: string,\n name: string\n): Promise<Buffer | undefined> {\n const value = await client.command(\"GET\", key);\n if (value == null) return undefined;\n if (typeof value === \"string\") return Buffer.from(value, \"utf8\");\n if (Buffer.isBuffer(value) || value instanceof Uint8Array) return Buffer.from(value);\n throw new TypeError(`FerricStore returned a non-binary ${name}`);\n}\n\nexport async function compareAndSetAtomicValue(\n client: FerricStoreCommandClient,\n key: string,\n expected: Buffer | undefined,\n value: Buffer\n): Promise<boolean> {\n if (expected == null) {\n const response = await client.command(\"SET\", key, value, \"NX\");\n if (response == null || response === false) return false;\n if (response === true) return true;\n return textResponse(response, \"SET NX response\").toUpperCase() === \"OK\";\n }\n const response = await client.command(\"CAS\", key, expected, value);\n if (response == null || response === false) return false;\n if (response === true) return true;\n return integerResponse(response, \"CAS response\") === 1;\n}\n\nexport async function withMutationLocks<T>(\n client: FerricStoreCommandClient,\n keys: readonly string[],\n operation: (lease: FerricStoreMutationLease) => Promise<T>,\n options: FerricStoreLockOptions = {}\n): Promise<T> {\n const orderedKeys = [...new Set(keys)].sort();\n if (orderedKeys.length === 0) {\n const signal = new AbortController().signal;\n return await operation({\n signal,\n assertOwned: () => undefined,\n publish: async (...args) => await additiveCommand(client, args),\n compareAndSet: async (key, expected, value) =>\n await compareAndSetAtomicValue(client, key, expected, value)\n });\n }\n\n const normalized: RequiredLockOptions = {\n lockRetryMs: positiveInteger(options.lockRetryMs, DEFAULT_LOCK_OPTIONS.lockRetryMs, \"lockRetryMs\"),\n lockTtlMs: positiveInteger(options.lockTtlMs, DEFAULT_LOCK_OPTIONS.lockTtlMs, \"lockTtlMs\"),\n lockWaitMs: nonNegativeInteger(options.lockWaitMs, DEFAULT_LOCK_OPTIONS.lockWaitMs, \"lockWaitMs\")\n };\n if (normalized.lockRetryMs >= normalized.lockTtlMs) {\n throw new TypeError(\"lockRetryMs must be less than lockTtlMs\");\n }\n const owner = randomUUID();\n const acquired: string[] = [];\n const deadline = performance.now() + normalized.lockWaitMs;\n let primaryError: unknown;\n let heartbeatError: unknown;\n let releaseError: unknown;\n let result: T | undefined;\n let operationCompleted = false;\n let conditionalCommitCompleted = false;\n const heartbeatAbort = new AbortController();\n const ownershipAbort = new AbortController();\n const lastExtended = new Map<string, number>();\n const loseOwnership = (error: unknown): Error => {\n const normalizedError = errorObject(error);\n heartbeatError ??= normalizedError;\n if (!ownershipAbort.signal.aborted) ownershipAbort.abort(normalizedError);\n return normalizedError;\n };\n const assertOwned = (): void => {\n if (heartbeatError != null) throw errorObject(heartbeatError);\n if (ownershipAbort.signal.aborted) throw errorObject(ownershipAbort.signal.reason);\n };\n const renewOwned = async (): Promise<void> => {\n assertOwned();\n for (const key of acquired) {\n try {\n const response = await client.command(\"EXTEND\", key, owner, normalized.lockTtlMs);\n if (integerResponse(response, \"EXTEND response\") !== 1) {\n throw new Error(`lost FerricStore lock ${JSON.stringify(key)} while mutating data`);\n }\n lastExtended.set(key, performance.now());\n } catch (error) {\n throw loseOwnership(new Error(\n `could not validate FerricStore lock ${JSON.stringify(key)} before mutating data`,\n { cause: error }\n ));\n }\n }\n assertOwned();\n };\n const lease: FerricStoreMutationLease = {\n signal: ownershipAbort.signal,\n assertOwned,\n publish: async (...args) => {\n await renewOwned();\n const response = await additiveCommand(client, args);\n assertOwned();\n return response;\n },\n compareAndSet: async (key, expected, value) => {\n await renewOwned();\n const committed = await compareAndSetAtomicValue(client, key, expected, value);\n if (committed) conditionalCommitCompleted = true;\n else assertOwned();\n return committed;\n }\n };\n\n try {\n for (const key of orderedKeys) {\n while (!(await tryAcquireLock(client, key, owner, normalized.lockTtlMs))) {\n if (performance.now() >= deadline) {\n throw new Error(`timed out acquiring FerricStore lock ${JSON.stringify(key)}`);\n }\n await extendAcquiredLocks(client, acquired, owner, normalized.lockTtlMs);\n await delay(normalized.lockRetryMs);\n }\n acquired.push(key);\n }\n await extendAcquiredLocks(client, acquired, owner, normalized.lockTtlMs);\n for (const key of acquired) lastExtended.set(key, performance.now());\n\n const heartbeat = renewLocks(\n client,\n acquired,\n owner,\n normalized.lockTtlMs,\n lastExtended,\n heartbeatAbort.signal,\n (error) => {\n loseOwnership(error);\n }\n );\n try {\n result = await operation(lease);\n operationCompleted = true;\n } catch (error) {\n primaryError = error;\n } finally {\n heartbeatAbort.abort();\n await heartbeat;\n }\n } catch (error) {\n primaryError ??= error;\n } finally {\n heartbeatAbort.abort();\n for (const key of acquired.reverse()) {\n try {\n await client.command(\"UNLOCK\", key, owner);\n } catch (error) {\n releaseError ??= error;\n }\n }\n }\n if (primaryError != null) throw errorObject(primaryError);\n if (heartbeatError != null && !conditionalCommitCompleted) throw errorObject(heartbeatError);\n if (releaseError != null && !(heartbeatError != null && conditionalCommitCompleted)) {\n throw errorObject(releaseError);\n }\n if (!operationCompleted) throw new Error(\"FerricStore mutation did not complete\");\n return result as T;\n}\n\nasync function additiveCommand(\n client: FerricStoreCommandClient,\n args: readonly CommandArgument[]\n): Promise<unknown> {\n const rawName = args[0];\n const name = typeof rawName === \"string\"\n ? rawName.toUpperCase()\n : Buffer.isBuffer(rawName) || rawName instanceof Uint8Array\n ? Buffer.from(rawName).toString(\"utf8\").toUpperCase()\n : \"\";\n if (name !== \"SADD\" && name !== \"ZADD\") {\n throw new TypeError(\"FerricStore mutation leases only publish add-only SADD or ZADD indexes\");\n }\n if (name === \"ZADD\" && (\n args.length < 4 ||\n args.length % 2 !== 0 ||\n args.slice(2).some((value, index) => index % 2 === 0 && Number(value) !== 0)\n )) {\n throw new TypeError(\"FerricStore mutation leases only publish zero-score ZADD indexes\");\n }\n return await client.command(...args);\n}\n\nasync function extendAcquiredLocks(\n client: FerricStoreCommandClient,\n keys: readonly string[],\n owner: string,\n ttlMs: number\n): Promise<void> {\n for (const key of keys) {\n const response = await client.command(\"EXTEND\", key, owner, ttlMs);\n if (integerResponse(response, \"EXTEND response\") !== 1) {\n throw new Error(`lost FerricStore lock ${JSON.stringify(key)} before mutating data`);\n }\n }\n}\n\nasync function tryAcquireLock(\n client: FerricStoreCommandClient,\n key: string,\n owner: string,\n ttlMs: number\n): Promise<boolean> {\n try {\n const response = await client.command(\"LOCK\", key, owner, ttlMs);\n return response === true || response === \"OK\" || Buffer.isBuffer(response) && response.equals(Buffer.from(\"OK\"));\n } catch (error) {\n if (error instanceof LockHeldError) return false;\n throw error;\n }\n}\n\nasync function renewLocks(\n client: FerricStoreCommandClient,\n keys: readonly string[],\n owner: string,\n ttlMs: number,\n lastExtended: Map<string, number>,\n signal: AbortSignal,\n onError: (error: unknown) => void\n): Promise<void> {\n const intervalMs = Math.max(Math.floor(ttlMs / 3), 1);\n const retryMs = Math.min(Math.max(Math.floor(intervalMs / 10), 1), 1_000);\n let waitMs = intervalMs;\n while (!signal.aborted) {\n try {\n await delay(waitMs, undefined, { signal });\n } catch (error) {\n if (signal.aborted) return;\n onError(error);\n return;\n }\n const now = performance.now();\n let retry = false;\n for (const key of keys) {\n try {\n const response = await client.command(\"EXTEND\", key, owner, ttlMs);\n if (integerResponse(response, \"EXTEND response\") !== 1) {\n onError(new Error(`lost FerricStore lock ${JSON.stringify(key)} while mutating data`));\n return;\n }\n lastExtended.set(key, now);\n } catch (error) {\n if (now - (lastExtended.get(key) ?? 0) >= ttlMs) {\n onError(new Error(`lost FerricStore lock ${JSON.stringify(key)} while mutating data`, { cause: error }));\n return;\n }\n retry = true;\n }\n }\n waitMs = retry ? retryMs : intervalMs;\n }\n}\n\nfunction errorObject(value: unknown): Error {\n return value instanceof Error ? value : new Error(\"FerricStore mutation failed\", { cause: value });\n}\n","export class FerricStoreError extends Error {\n readonly code: string = \"ferricstore_error\";\n readonly raw: unknown;\n readonly retryable: boolean | undefined;\n readonly safeToRetry: boolean | undefined;\n readonly retryAfterMs: number | undefined;\n\n constructor(message: string, options: {\n raw?: unknown;\n cause?: unknown;\n retryable?: boolean;\n safeToRetry?: boolean;\n retryAfterMs?: number;\n } = {}) {\n super(message, { cause: options.cause });\n this.name = new.target.name;\n this.raw = options.raw;\n this.retryable = options.retryable ?? structuredBooleanField(options.raw, \"retryable\");\n this.safeToRetry = options.safeToRetry ?? structuredBooleanField(options.raw, \"safe_to_retry\");\n this.retryAfterMs = options.retryAfterMs ?? structuredIntegerField(options.raw, \"retry_after_ms\");\n }\n}\n\nexport class HTTPTransportError extends FerricStoreError {\n override readonly code = \"http_transport\";\n readonly statusCode: number | undefined;\n\n constructor(message: string, options: ConstructorParameters<typeof FerricStoreError>[1] & {\n statusCode?: number;\n } = {}) {\n super(message, options);\n this.statusCode = options.statusCode;\n }\n}\n\nexport type RequestDisposition = \"unsent\" | \"possibly_sent\";\n/** @deprecated Use RequestDisposition; retained for source compatibility. */\nexport type ConnectionRequestDisposition = RequestDisposition;\n\n/** Connection closure annotated with whether the current request may have reached the server. */\nexport class ConnectionClosedError extends FerricStoreError {\n override readonly code = \"connection_closed\";\n readonly requestDisposition: RequestDisposition;\n\n constructor(\n requestDisposition: RequestDisposition,\n options: { raw?: unknown; cause?: unknown; message?: string } = {}\n ) {\n super(\n options.message ?? (requestDisposition === \"unsent\"\n ? \"FerricStore connection is closed\"\n : \"FerricStore connection closed\"),\n options\n );\n this.requestDisposition = requestDisposition;\n }\n}\n\n/** Request timeout annotated with whether the request may have reached the server. */\nexport class RequestTimeoutError extends FerricStoreError {\n override readonly code = \"request_timeout\";\n readonly requestDisposition: RequestDisposition;\n readonly timeoutMs: number;\n\n constructor(\n timeoutMs: number,\n requestDisposition: RequestDisposition,\n options: { raw?: unknown; cause?: unknown } = {}\n ) {\n super(`FerricStore request timed out after ${timeoutMs}ms`, options);\n this.requestDisposition = requestDisposition;\n this.timeoutMs = timeoutMs;\n }\n}\n\nexport class FlowNotFoundError extends FerricStoreError {\n override readonly code = \"flow_not_found\";\n}\n\nexport class FlowWrongStateError extends FerricStoreError {\n override readonly code = \"flow_wrong_state\";\n}\n\nexport class StaleLeaseError extends FerricStoreError {\n override readonly code = \"stale_lease\";\n}\n\n/** FLOW.POLICY.SET expected_generation did not match the stored generation. */\nexport class StalePolicyGenerationError extends FerricStoreError {\n override readonly code = \"stale_policy_generation\";\n}\n\nexport class FlowAlreadyExistsError extends FerricStoreError {\n override readonly code = \"flow_already_exists\";\n}\n\nexport class LockHeldError extends FerricStoreError {\n override readonly code = \"lock_held\";\n}\n\nexport class LockNotOwnedError extends FerricStoreError {\n override readonly code = \"lock_not_owned\";\n}\n\nexport class InvalidCommandError extends FerricStoreError {\n override readonly code = \"invalid_command\";\n}\n\nexport class OverloadedError extends FerricStoreError {\n override readonly code = \"overloaded\";\n readonly reason: string | undefined;\n\n constructor(\n message: string,\n options: {\n raw?: unknown;\n cause?: unknown;\n retryAfterMs?: number;\n reason?: string;\n retryable?: boolean;\n safeToRetry?: boolean;\n } = {}\n ) {\n const local = options.raw == null;\n super(message, {\n ...options,\n retryable: options.retryable ?? (local ? true : undefined),\n safeToRetry: options.safeToRetry ?? (local ? true : undefined)\n });\n this.reason = options.reason;\n }\n}\n\n/** The contacted endpoint cannot serve this route and topology should be refreshed. */\nexport class RerouteError extends FerricStoreError {\n override readonly code = \"reroute\";\n}\n\nconst OVERLOAD_CODES = new Set([\n \"backpressure\",\n \"busy\",\n \"flow_control_window_exhausted\",\n \"lane_queue_full\",\n \"overloaded\"\n]);\n\nexport function classifyServerError(\n message: string,\n raw?: unknown,\n cause?: unknown,\n status?: number | string\n): FerricStoreError {\n const lower = message.toLowerCase();\n const structuredCode = structuredStringField(raw, \"code\");\n const code = structuredCode?.toLowerCase();\n const retry = {\n retryable: structuredBooleanField(raw, \"retryable\"),\n safeToRetry: structuredBooleanField(raw, \"safe_to_retry\"),\n retryAfterMs: structuredIntegerField(raw, \"retry_after_ms\") ?? intField(lower, \"retry_after_ms\")\n };\n\n if (isRerouteStatus(status) || code === \"reroute\") {\n return new RerouteError(message, { cause, raw, ...definedRetryMetadata(retry) });\n }\n if (isBusyStatus(status) || isOverloadCode(structuredCode) || overloadMessage(lower)) {\n return new OverloadedError(message, {\n cause,\n raw,\n ...definedRetryMetadata(retry),\n reason: structuredStringField(raw, \"reason\") ?? structuredCode ?? stringField(lower, \"reason\"),\n retryAfterMs: retry.retryAfterMs\n });\n }\n if (code === \"flow_already_exists\" || (lower.includes(\"flow\") && lower.includes(\"already exists\"))) {\n return new FlowAlreadyExistsError(message, { cause, raw });\n }\n if (lower.includes(\"flow wrong state\") || code === \"flow_wrong_state\") {\n return new FlowWrongStateError(message, { cause, raw });\n }\n if (\n code === \"stale_lease\"\n || code === \"stale_flow_lease\"\n || lower.includes(\"stale flow lease\")\n || lower.includes(\"stale lease\")\n || lower.includes(\"stale token\")\n ) {\n return new StaleLeaseError(message, { cause, raw });\n }\n if (\n code === \"stale_generation\"\n || code === \"stale_policy_generation\"\n || code === \"stale_flow_policy_generation\"\n || lower.includes(\"stale flow policy generation\")\n || lower.includes(\"stale policy generation\")\n ) {\n return new StalePolicyGenerationError(message, { cause, raw });\n }\n if (\n code === \"flow_not_found\"\n || (lower.includes(\"flow\") && (lower.includes(\"not found\") || lower.includes(\"does not exist\")))\n ) {\n return new FlowNotFoundError(message, { cause, raw });\n }\n if (code === \"lock_held\" || lower.includes(\"lock is held\") || lower.includes(\"held by another owner\")) {\n return new LockHeldError(message, { cause, raw });\n }\n if (code === \"lock_not_owned\" || lower.includes(\"not the lock owner\") || lower.includes(\"caller is not the lock owner\")) {\n return new LockNotOwnedError(message, { cause, raw });\n }\n if (code === \"invalid_command\" || lower.includes(\"wrong number of arguments\") || lower.includes(\"syntax error\")) {\n return new InvalidCommandError(message, { cause, raw });\n }\n\n return new FerricStoreError(message, { cause, raw, ...definedRetryMetadata(retry) });\n}\n\nexport function mapException(error: unknown): unknown {\n if (error instanceof FerricStoreError) {\n return error;\n }\n\n if (!(error instanceof Error)) {\n return error;\n }\n\n const message = error.message;\n const serverLike =\n error.name === \"ResponseError\" ||\n message.startsWith(\"ERR \") ||\n message.startsWith(\"WRONGTYPE \") ||\n message.startsWith(\"DISTLOCK \");\n\n if (!serverLike) {\n return error;\n }\n\n return classifyServerError(message, error, error);\n}\n\nfunction intField(message: string, name: string): number | undefined {\n const match = new RegExp(`\\\\b${name}=([0-9]+)\\\\b`).exec(message);\n return match?.[1] == null ? undefined : nonNegativeSafeIntegerText(match[1]);\n}\n\nfunction isBusyStatus(status: number | string | undefined): boolean {\n return status === 4 || (typeof status === \"string\" && (status === \"4\" || status.toLowerCase() === \"busy\"));\n}\n\nfunction isRerouteStatus(status: number | string | undefined): boolean {\n return status === 5 || (typeof status === \"string\" && (status === \"5\" || status.toLowerCase() === \"reroute\"));\n}\n\nfunction isOverloadCode(code: string | undefined): boolean {\n return code != null && OVERLOAD_CODES.has(code.toLowerCase());\n}\n\nfunction overloadMessage(message: string): boolean {\n return /\\boverloaded\\b/u.test(message) || /(?:^|\\s)busy(?:\\s|:|$)/u.test(message);\n}\n\nfunction structuredIntegerField(raw: unknown, name: string): number | undefined {\n const value = structuredField(raw, name);\n if (typeof value === \"number\") {\n return Number.isSafeInteger(value) && value >= 0 ? value : undefined;\n }\n if (typeof value === \"bigint\") {\n return value >= 0n && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : undefined;\n }\n const text = binaryText(value);\n return text == null ? undefined : nonNegativeSafeIntegerText(text);\n}\n\nfunction structuredBooleanField(raw: unknown, name: string): boolean | undefined {\n const value = structuredField(raw, name);\n if (typeof value === \"boolean\") return value;\n const text = binaryText(value)?.toLowerCase();\n if (text === \"true\" || text === \"1\") return true;\n if (text === \"false\" || text === \"0\") return false;\n return undefined;\n}\n\nfunction definedRetryMetadata(metadata: {\n readonly retryable?: boolean;\n readonly safeToRetry?: boolean;\n readonly retryAfterMs?: number;\n}): { retryable?: boolean; safeToRetry?: boolean; retryAfterMs?: number } {\n return {\n ...(metadata.retryable == null ? {} : { retryable: metadata.retryable }),\n ...(metadata.safeToRetry == null ? {} : { safeToRetry: metadata.safeToRetry }),\n ...(metadata.retryAfterMs == null ? {} : { retryAfterMs: metadata.retryAfterMs })\n };\n}\n\nfunction nonNegativeSafeIntegerText(value: string): number | undefined {\n if (!/^[0-9]+$/u.test(value)) return undefined;\n const parsed = Number.parseInt(value, 10);\n return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : undefined;\n}\n\nfunction structuredStringField(raw: unknown, name: string): string | undefined {\n return binaryText(structuredField(raw, name));\n}\n\nfunction structuredField(raw: unknown, name: string): unknown {\n if (raw instanceof Map) {\n if (raw.has(name)) return raw.get(name);\n for (const [key, value] of raw.entries()) {\n if (binaryText(key) === name) return value;\n }\n return undefined;\n }\n if (typeof raw === \"object\" && raw != null && Object.hasOwn(raw, name)) {\n return (raw as Record<string, unknown>)[name];\n }\n return undefined;\n}\n\nfunction binaryText(value: unknown): string | undefined {\n if (typeof value === \"string\") return value;\n if (Buffer.isBuffer(value) || value instanceof Uint8Array) return Buffer.from(value).toString(\"utf8\");\n return undefined;\n}\n\nfunction stringField(message: string, name: string): string | undefined {\n const match = new RegExp(`\\\\b${name}=([a-z0-9_:-]+)\\\\b`).exec(message);\n return match?.[1];\n}\n","import { createHash } from \"node:crypto\";\n\ntype EncodedSnapshot =\n | [\"array\", EncodedSnapshot[]]\n | [\"binary\", string]\n | [\"boolean\", boolean]\n | [\"null\"]\n | [\"number\", number | \"NaN\" | \"+Infinity\" | \"-Infinity\" | \"-0\"]\n | [\"object\", [string, EncodedSnapshot][]]\n | [\"string\", string]\n | [\"undefined\"];\n\nexport function encodeSnapshot(value: unknown): Buffer {\n return encodeSnapshotWith(value, defaultKeyComparator);\n}\n\nexport function decodeSnapshot<T>(value: unknown, name: string): T {\n const bytes = typeof value === \"string\" ? Buffer.from(value, \"utf8\") : Buffer.from(asBytes(value, name));\n let encoded: unknown;\n try {\n encoded = JSON.parse(bytes.toString(\"utf8\"));\n } catch (error) {\n throw new Error(`FerricStore returned an invalid ${name}`, { cause: error });\n }\n return restore(encoded, name) as T;\n}\n\nexport function snapshotDigest(value: unknown): string {\n return createHash(\"sha256\").update(encodeSnapshot(value)).digest(\"hex\");\n}\n\n/** @internal Compatibility digest for receipts written before deterministic key ordering. */\nexport function legacySnapshotDigest(value: unknown, locale?: string): string {\n return createHash(\"sha256\")\n .update(encodeSnapshotWith(value, (left, right) => left.localeCompare(right, locale)))\n .digest(\"hex\");\n}\n\nexport function cloneSnapshot<T>(value: T): T {\n return decodeSnapshot<T>(encodeSnapshot(value), \"snapshot\");\n}\n\nexport function snapshotsEqual(left: unknown, right: unknown): boolean {\n return encodeSnapshot(left).equals(encodeSnapshot(right));\n}\n\nfunction encodeSnapshotWith(value: unknown, compareKeys: (left: string, right: string) => number): Buffer {\n return Buffer.from(JSON.stringify(snapshot(value, new WeakSet(), compareKeys)), \"utf8\");\n}\n\nfunction defaultKeyComparator(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\nfunction snapshot(\n value: unknown,\n ancestors: WeakSet<object>,\n compareKeys: (left: string, right: string) => number\n): EncodedSnapshot {\n if (value === null) return [\"null\"];\n if (value === undefined) return [\"undefined\"];\n if (typeof value === \"string\") return [\"string\", value];\n if (typeof value === \"boolean\") return [\"boolean\", value];\n if (typeof value === \"number\") {\n if (Object.is(value, -0)) return [\"number\", \"-0\"];\n if (Number.isNaN(value)) return [\"number\", \"NaN\"];\n if (value === Infinity) return [\"number\", \"+Infinity\"];\n if (value === -Infinity) return [\"number\", \"-Infinity\"];\n return [\"number\", value];\n }\n if (typeof value !== \"object\") throw new TypeError(\"session history contains unsupported data\");\n if (value instanceof Uint8Array) {\n const keys = Reflect.ownKeys(value);\n if (\n keys.length !== value.length ||\n keys.some((key) => typeof key !== \"string\" || !isArrayIndex(key, value.length))\n ) {\n throw new TypeError(\"session history binary data contains custom properties\");\n }\n return [\"binary\", Buffer.from(value).toString(\"base64\")];\n }\n if (ancestors.has(value)) throw new TypeError(\"session history contains cyclic data\");\n ancestors.add(value);\n try {\n if (Array.isArray(value)) {\n const keys = Reflect.ownKeys(value);\n if (\n keys.length !== value.length + 1 ||\n keys.some((key) => typeof key !== \"string\" || key !== \"length\" && !isArrayIndex(key, value.length))\n ) {\n throw new TypeError(\"session history contains a sparse or customized array\");\n }\n const items: EncodedSnapshot[] = [];\n for (let index = 0; index < value.length; index += 1) {\n const descriptor = Object.getOwnPropertyDescriptor(value, String(index));\n if (descriptor == null || !descriptor.enumerable || !(\"value\" in descriptor)) {\n throw new TypeError(\"session history contains an unsupported array item\");\n }\n items.push(snapshot(descriptor.value as unknown, ancestors, compareKeys));\n }\n return [\"array\", items];\n }\n const prototype: unknown = Object.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) {\n throw new TypeError(\"session history contains an unsupported object\");\n }\n const keys = Reflect.ownKeys(value);\n if (keys.some((key) => typeof key !== \"string\")) {\n throw new TypeError(\"session history contains a symbol property\");\n }\n const entries: [string, EncodedSnapshot][] = [];\n for (const key of (keys as string[]).sort(compareKeys)) {\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n if (descriptor == null || !descriptor.enumerable || !(\"value\" in descriptor)) {\n throw new TypeError(\"session history contains an unsupported property\");\n }\n entries.push([key, snapshot(descriptor.value as unknown, ancestors, compareKeys)]);\n }\n return [\"object\", entries];\n } finally {\n ancestors.delete(value);\n }\n}\n\nfunction restore(value: unknown, name: string): unknown {\n if (!Array.isArray(value) || typeof value[0] !== \"string\") throw new TypeError(`invalid ${name}`);\n switch (value[0]) {\n case \"null\": return null;\n case \"undefined\": return undefined;\n case \"string\": return requireValueType(value[1], \"string\", name);\n case \"boolean\": return requireValueType(value[1], \"boolean\", name);\n case \"binary\": return Buffer.from(requireValueType(value[1], \"string\", name), \"base64\");\n case \"number\": return restoreNumber(value[1], name);\n case \"array\": {\n if (!Array.isArray(value[1])) throw new TypeError(`invalid ${name}`);\n return value[1].map((item) => restore(item, name));\n }\n case \"object\": {\n if (!Array.isArray(value[1])) throw new TypeError(`invalid ${name}`);\n const result: Record<string, unknown> = {};\n for (const entry of value[1]) {\n if (!Array.isArray(entry) || entry.length !== 2 || typeof entry[0] !== \"string\") {\n throw new TypeError(`invalid ${name}`);\n }\n Object.defineProperty(result, entry[0], {\n configurable: true,\n enumerable: true,\n value: restore(entry[1], name),\n writable: true\n });\n }\n return result;\n }\n default: throw new TypeError(`invalid ${name}`);\n }\n}\n\nfunction restoreNumber(value: unknown, name: string): number {\n if (typeof value === \"number\") return value;\n if (value === \"NaN\") return Number.NaN;\n if (value === \"+Infinity\") return Infinity;\n if (value === \"-Infinity\") return -Infinity;\n if (value === \"-0\") return -0;\n throw new TypeError(`invalid ${name}`);\n}\n\nfunction requireValueType<T extends \"boolean\" | \"string\">(\n value: unknown,\n type: T,\n name: string\n): T extends \"string\" ? string : boolean {\n if (typeof value !== type) throw new TypeError(`invalid ${name}`);\n return value as T extends \"string\" ? string : boolean;\n}\n\nfunction asBytes(value: unknown, name: string): Uint8Array {\n if (Buffer.isBuffer(value) || value instanceof Uint8Array) return value;\n throw new TypeError(`FerricStore returned a non-binary ${name}`);\n}\n\nfunction isArrayIndex(key: string, length: number): boolean {\n if (!/^(?:0|[1-9]\\d*)$/u.test(key)) return false;\n const index = Number(key);\n return Number.isSafeInteger(index) && index >= 0 && index < length;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,sBAAuC;;;ACAvC,yBAA2B;AAC3B,sBAAoC;;;ACD7B,IAAM,mBAAN,cAA+B,MAAM;AAAA,EACjC,OAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,UAMzB,CAAC,GAAG;AACN,UAAM,SAAS,EAAE,OAAO,QAAQ,MAAM,CAAC;AACvC,SAAK,OAAO,WAAW;AACvB,SAAK,MAAM,QAAQ;AACnB,SAAK,YAAY,QAAQ,aAAa,uBAAuB,QAAQ,KAAK,WAAW;AACrF,SAAK,cAAc,QAAQ,eAAe,uBAAuB,QAAQ,KAAK,eAAe;AAC7F,SAAK,eAAe,QAAQ,gBAAgB,uBAAuB,QAAQ,KAAK,gBAAgB;AAAA,EAClG;AACF;AA2EO,IAAM,gBAAN,cAA4B,iBAAiB;AAAA,EAChC,OAAO;AAC3B;AAkKA,SAAS,uBAAuB,KAAc,MAAkC;AAC9E,QAAM,QAAQ,gBAAgB,KAAK,IAAI;AACvC,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,OAAO,cAAc,KAAK,KAAK,SAAS,IAAI,QAAQ;AAAA,EAC7D;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,SAAS,MAAM,SAAS,OAAO,OAAO,gBAAgB,IAAI,OAAO,KAAK,IAAI;AAAA,EACnF;AACA,QAAM,OAAO,WAAW,KAAK;AAC7B,SAAO,QAAQ,OAAO,SAAY,2BAA2B,IAAI;AACnE;AAEA,SAAS,uBAAuB,KAAc,MAAmC;AAC/E,QAAM,QAAQ,gBAAgB,KAAK,IAAI;AACvC,MAAI,OAAO,UAAU,UAAW,QAAO;AACvC,QAAM,OAAO,WAAW,KAAK,GAAG,YAAY;AAC5C,MAAI,SAAS,UAAU,SAAS,IAAK,QAAO;AAC5C,MAAI,SAAS,WAAW,SAAS,IAAK,QAAO;AAC7C,SAAO;AACT;AAcA,SAAS,2BAA2B,OAAmC;AACrE,MAAI,CAAC,YAAY,KAAK,KAAK,EAAG,QAAO;AACrC,QAAM,SAAS,OAAO,SAAS,OAAO,EAAE;AACxC,SAAO,OAAO,cAAc,MAAM,KAAK,UAAU,IAAI,SAAS;AAChE;AAMA,SAAS,gBAAgB,KAAc,MAAuB;AAC5D,MAAI,eAAe,KAAK;AACtB,QAAI,IAAI,IAAI,IAAI,EAAG,QAAO,IAAI,IAAI,IAAI;AACtC,eAAW,CAAC,KAAK,KAAK,KAAK,IAAI,QAAQ,GAAG;AACxC,UAAI,WAAW,GAAG,MAAM,KAAM,QAAO;AAAA,IACvC;AACA,WAAO;AAAA,EACT;AACA,MAAI,OAAO,QAAQ,YAAY,OAAO,QAAQ,OAAO,OAAO,KAAK,IAAI,GAAG;AACtE,WAAQ,IAAgC,IAAI;AAAA,EAC9C;AACA,SAAO;AACT;AAEA,SAAS,WAAW,OAAoC;AACtD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,OAAO,SAAS,KAAK,KAAK,iBAAiB,WAAY,QAAO,OAAO,KAAK,KAAK,EAAE,SAAS,MAAM;AACpG,SAAO;AACT;;;AD5RA,IAAM,uBAA4C;AAAA,EAChD,aAAa;AAAA,EACb,WAAW;AAAA,EACX,YAAY;AACd;AAEO,SAAS,mBAAmB,OAAe,cAA8B;AAC9E,QAAM,SAAS,MAAM,WAAW,IAAI,eAAe;AACnD,MAAI,OAAO,SAAS,IAAI,EAAG,OAAM,IAAI,UAAU,sCAAsC;AACrF,QAAM,aAAa,OAAO,QAAQ,QAAQ,EAAE;AAC5C,MAAI,WAAW,WAAW,EAAG,OAAM,IAAI,UAAU,mDAAmD;AACpG,SAAO;AACT;AAEO,SAAS,gBAAgB,OAA2B,UAAkB,MAAsB;AACjG,QAAM,aAAa,SAAS;AAC5B,MAAI,CAAC,OAAO,cAAc,UAAU,KAAK,cAAc,GAAG;AACxD,UAAM,IAAI,UAAU,GAAG,IAAI,kCAAkC;AAAA,EAC/D;AACA,SAAO;AACT;AAEO,SAAS,mBAAmB,OAA2B,UAAkB,MAAsB;AACpG,QAAM,aAAa,SAAS;AAC5B,MAAI,CAAC,OAAO,cAAc,UAAU,KAAK,aAAa,GAAG;AACvD,UAAM,IAAI,UAAU,GAAG,IAAI,sCAAsC;AAAA,EACnE;AACA,SAAO;AACT;AAEO,SAAS,aAAa,OAAgB,MAAsB;AACjE,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,OAAO,SAAS,KAAK,KAAK,iBAAiB,WAAY,QAAO,OAAO,KAAK,KAAK,EAAE,SAAS,MAAM;AACpG,QAAM,IAAI,UAAU,mCAAmC,IAAI,EAAE;AAC/D;AAOO,SAAS,gBAAgB,OAAgB,MAAsB;AACpE,QAAM,SAAS,OAAO,UAAU,WAAW,QAAQ,OAAO,aAAa,OAAO,IAAI,CAAC;AACnF,MAAI,CAAC,OAAO,cAAc,MAAM,EAAG,OAAM,IAAI,UAAU,mCAAmC,IAAI,EAAE;AAChG,SAAO;AACT;AAWA,eAAsB,gBACpB,QACA,KACA,MAC6B;AAC7B,QAAM,QAAQ,MAAM,OAAO,QAAQ,OAAO,GAAG;AAC7C,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,OAAO,UAAU,SAAU,QAAO,OAAO,KAAK,OAAO,MAAM;AAC/D,MAAI,OAAO,SAAS,KAAK,KAAK,iBAAiB,WAAY,QAAO,OAAO,KAAK,KAAK;AACnF,QAAM,IAAI,UAAU,qCAAqC,IAAI,EAAE;AACjE;AAEA,eAAsB,yBACpB,QACA,KACA,UACA,OACkB;AAClB,MAAI,YAAY,MAAM;AACpB,UAAMC,YAAW,MAAM,OAAO,QAAQ,OAAO,KAAK,OAAO,IAAI;AAC7D,QAAIA,aAAY,QAAQA,cAAa,MAAO,QAAO;AACnD,QAAIA,cAAa,KAAM,QAAO;AAC9B,WAAO,aAAaA,WAAU,iBAAiB,EAAE,YAAY,MAAM;AAAA,EACrE;AACA,QAAM,WAAW,MAAM,OAAO,QAAQ,OAAO,KAAK,UAAU,KAAK;AACjE,MAAI,YAAY,QAAQ,aAAa,MAAO,QAAO;AACnD,MAAI,aAAa,KAAM,QAAO;AAC9B,SAAO,gBAAgB,UAAU,cAAc,MAAM;AACvD;AAEA,eAAsB,kBACpB,QACA,MACA,WACA,UAAkC,CAAC,GACvB;AACZ,QAAM,cAAc,CAAC,GAAG,IAAI,IAAI,IAAI,CAAC,EAAE,KAAK;AAC5C,MAAI,YAAY,WAAW,GAAG;AAC5B,UAAM,SAAS,IAAI,gBAAgB,EAAE;AACrC,WAAO,MAAM,UAAU;AAAA,MACrB;AAAA,MACA,aAAa,MAAM;AAAA,MACnB,SAAS,UAAU,SAAS,MAAM,gBAAgB,QAAQ,IAAI;AAAA,MAC9D,eAAe,OAAO,KAAK,UAAU,UACnC,MAAM,yBAAyB,QAAQ,KAAK,UAAU,KAAK;AAAA,IAC/D,CAAC;AAAA,EACH;AAEA,QAAM,aAAkC;AAAA,IACtC,aAAa,gBAAgB,QAAQ,aAAa,qBAAqB,aAAa,aAAa;AAAA,IACjG,WAAW,gBAAgB,QAAQ,WAAW,qBAAqB,WAAW,WAAW;AAAA,IACzF,YAAY,mBAAmB,QAAQ,YAAY,qBAAqB,YAAY,YAAY;AAAA,EAClG;AACA,MAAI,WAAW,eAAe,WAAW,WAAW;AAClD,UAAM,IAAI,UAAU,yCAAyC;AAAA,EAC/D;AACA,QAAM,YAAQ,+BAAW;AACzB,QAAM,WAAqB,CAAC;AAC5B,QAAM,WAAW,YAAY,IAAI,IAAI,WAAW;AAChD,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI,qBAAqB;AACzB,MAAI,6BAA6B;AACjC,QAAM,iBAAiB,IAAI,gBAAgB;AAC3C,QAAM,iBAAiB,IAAI,gBAAgB;AAC3C,QAAM,eAAe,oBAAI,IAAoB;AAC7C,QAAM,gBAAgB,CAAC,UAA0B;AAC/C,UAAM,kBAAkB,YAAY,KAAK;AACzC,uBAAmB;AACnB,QAAI,CAAC,eAAe,OAAO,QAAS,gBAAe,MAAM,eAAe;AACxE,WAAO;AAAA,EACT;AACA,QAAM,cAAc,MAAY;AAC9B,QAAI,kBAAkB,KAAM,OAAM,YAAY,cAAc;AAC5D,QAAI,eAAe,OAAO,QAAS,OAAM,YAAY,eAAe,OAAO,MAAM;AAAA,EACnF;AACA,QAAM,aAAa,YAA2B;AAC5C,gBAAY;AACZ,eAAW,OAAO,UAAU;AAC1B,UAAI;AACF,cAAM,WAAW,MAAM,OAAO,QAAQ,UAAU,KAAK,OAAO,WAAW,SAAS;AAChF,YAAI,gBAAgB,UAAU,iBAAiB,MAAM,GAAG;AACtD,gBAAM,IAAI,MAAM,yBAAyB,KAAK,UAAU,GAAG,CAAC,sBAAsB;AAAA,QACpF;AACA,qBAAa,IAAI,KAAK,YAAY,IAAI,CAAC;AAAA,MACzC,SAAS,OAAO;AACd,cAAM,cAAc,IAAI;AAAA,UACtB,uCAAuC,KAAK,UAAU,GAAG,CAAC;AAAA,UAC1D,EAAE,OAAO,MAAM;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF;AACA,gBAAY;AAAA,EACd;AACA,QAAM,QAAkC;AAAA,IACtC,QAAQ,eAAe;AAAA,IACvB;AAAA,IACA,SAAS,UAAU,SAAS;AAC1B,YAAM,WAAW;AACjB,YAAM,WAAW,MAAM,gBAAgB,QAAQ,IAAI;AACnD,kBAAY;AACZ,aAAO;AAAA,IACT;AAAA,IACA,eAAe,OAAO,KAAK,UAAU,UAAU;AAC7C,YAAM,WAAW;AACjB,YAAM,YAAY,MAAM,yBAAyB,QAAQ,KAAK,UAAU,KAAK;AAC7E,UAAI,UAAW,8BAA6B;AAAA,UACvC,aAAY;AACjB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI;AACF,eAAW,OAAO,aAAa;AAC7B,aAAO,CAAE,MAAM,eAAe,QAAQ,KAAK,OAAO,WAAW,SAAS,GAAI;AACxE,YAAI,YAAY,IAAI,KAAK,UAAU;AACjC,gBAAM,IAAI,MAAM,wCAAwC,KAAK,UAAU,GAAG,CAAC,EAAE;AAAA,QAC/E;AACA,cAAM,oBAAoB,QAAQ,UAAU,OAAO,WAAW,SAAS;AACvE,kBAAM,gBAAAC,YAAM,WAAW,WAAW;AAAA,MACpC;AACA,eAAS,KAAK,GAAG;AAAA,IACnB;AACA,UAAM,oBAAoB,QAAQ,UAAU,OAAO,WAAW,SAAS;AACvE,eAAW,OAAO,SAAU,cAAa,IAAI,KAAK,YAAY,IAAI,CAAC;AAEnE,UAAM,YAAY;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MACX;AAAA,MACA,eAAe;AAAA,MACf,CAAC,UAAU;AACT,sBAAc,KAAK;AAAA,MACrB;AAAA,IACF;AACA,QAAI;AACF,eAAS,MAAM,UAAU,KAAK;AAC9B,2BAAqB;AAAA,IACvB,SAAS,OAAO;AACd,qBAAe;AAAA,IACjB,UAAE;AACA,qBAAe,MAAM;AACrB,YAAM;AAAA,IACR;AAAA,EACF,SAAS,OAAO;AACd,qBAAiB;AAAA,EACnB,UAAE;AACA,mBAAe,MAAM;AACrB,eAAW,OAAO,SAAS,QAAQ,GAAG;AACpC,UAAI;AACF,cAAM,OAAO,QAAQ,UAAU,KAAK,KAAK;AAAA,MAC3C,SAAS,OAAO;AACd,yBAAiB;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AACA,MAAI,gBAAgB,KAAM,OAAM,YAAY,YAAY;AACxD,MAAI,kBAAkB,QAAQ,CAAC,2BAA4B,OAAM,YAAY,cAAc;AAC3F,MAAI,gBAAgB,QAAQ,EAAE,kBAAkB,QAAQ,6BAA6B;AACnF,UAAM,YAAY,YAAY;AAAA,EAChC;AACA,MAAI,CAAC,mBAAoB,OAAM,IAAI,MAAM,uCAAuC;AAChF,SAAO;AACT;AAEA,eAAe,gBACb,QACA,MACkB;AAClB,QAAM,UAAU,KAAK,CAAC;AACtB,QAAM,OAAO,OAAO,YAAY,WAC5B,QAAQ,YAAY,IACpB,OAAO,SAAS,OAAO,KAAK,mBAAmB,aAC7C,OAAO,KAAK,OAAO,EAAE,SAAS,MAAM,EAAE,YAAY,IAClD;AACN,MAAI,SAAS,UAAU,SAAS,QAAQ;AACtC,UAAM,IAAI,UAAU,wEAAwE;AAAA,EAC9F;AACA,MAAI,SAAS,WACX,KAAK,SAAS,KACd,KAAK,SAAS,MAAM,KACpB,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC,OAAO,UAAU,QAAQ,MAAM,KAAK,OAAO,KAAK,MAAM,CAAC,IAC1E;AACD,UAAM,IAAI,UAAU,kEAAkE;AAAA,EACxF;AACA,SAAO,MAAM,OAAO,QAAQ,GAAG,IAAI;AACrC;AAEA,eAAe,oBACb,QACA,MACA,OACA,OACe;AACf,aAAW,OAAO,MAAM;AACtB,UAAM,WAAW,MAAM,OAAO,QAAQ,UAAU,KAAK,OAAO,KAAK;AACjE,QAAI,gBAAgB,UAAU,iBAAiB,MAAM,GAAG;AACtD,YAAM,IAAI,MAAM,yBAAyB,KAAK,UAAU,GAAG,CAAC,uBAAuB;AAAA,IACrF;AAAA,EACF;AACF;AAEA,eAAe,eACb,QACA,KACA,OACA,OACkB;AAClB,MAAI;AACF,UAAM,WAAW,MAAM,OAAO,QAAQ,QAAQ,KAAK,OAAO,KAAK;AAC/D,WAAO,aAAa,QAAQ,aAAa,QAAQ,OAAO,SAAS,QAAQ,KAAK,SAAS,OAAO,OAAO,KAAK,IAAI,CAAC;AAAA,EACjH,SAAS,OAAO;AACd,QAAI,iBAAiB,cAAe,QAAO;AAC3C,UAAM;AAAA,EACR;AACF;AAEA,eAAe,WACb,QACA,MACA,OACA,OACA,cACA,QACA,SACe;AACf,QAAM,aAAa,KAAK,IAAI,KAAK,MAAM,QAAQ,CAAC,GAAG,CAAC;AACpD,QAAM,UAAU,KAAK,IAAI,KAAK,IAAI,KAAK,MAAM,aAAa,EAAE,GAAG,CAAC,GAAG,GAAK;AACxE,MAAI,SAAS;AACb,SAAO,CAAC,OAAO,SAAS;AACtB,QAAI;AACF,gBAAM,gBAAAA,YAAM,QAAQ,QAAW,EAAE,OAAO,CAAC;AAAA,IAC3C,SAAS,OAAO;AACd,UAAI,OAAO,QAAS;AACpB,cAAQ,KAAK;AACb;AAAA,IACF;AACA,UAAM,MAAM,YAAY,IAAI;AAC5B,QAAI,QAAQ;AACZ,eAAW,OAAO,MAAM;AACtB,UAAI;AACF,cAAM,WAAW,MAAM,OAAO,QAAQ,UAAU,KAAK,OAAO,KAAK;AACjE,YAAI,gBAAgB,UAAU,iBAAiB,MAAM,GAAG;AACtD,kBAAQ,IAAI,MAAM,yBAAyB,KAAK,UAAU,GAAG,CAAC,sBAAsB,CAAC;AACrF;AAAA,QACF;AACA,qBAAa,IAAI,KAAK,GAAG;AAAA,MAC3B,SAAS,OAAO;AACd,YAAI,OAAO,aAAa,IAAI,GAAG,KAAK,MAAM,OAAO;AAC/C,kBAAQ,IAAI,MAAM,yBAAyB,KAAK,UAAU,GAAG,CAAC,wBAAwB,EAAE,OAAO,MAAM,CAAC,CAAC;AACvG;AAAA,QACF;AACA,gBAAQ;AAAA,MACV;AAAA,IACF;AACA,aAAS,QAAQ,UAAU;AAAA,EAC7B;AACF;AAEA,SAAS,YAAY,OAAuB;AAC1C,SAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,+BAA+B,EAAE,OAAO,MAAM,CAAC;AACnG;;;AEtWA,IAAAC,sBAA2B;AAYpB,SAAS,eAAe,OAAwB;AACrD,SAAO,mBAAmB,OAAO,oBAAoB;AACvD;AAEO,SAAS,eAAkB,OAAgB,MAAiB;AACjE,QAAM,QAAQ,OAAO,UAAU,WAAW,OAAO,KAAK,OAAO,MAAM,IAAI,OAAO,KAAK,QAAQ,OAAO,IAAI,CAAC;AACvG,MAAI;AACJ,MAAI;AACF,cAAU,KAAK,MAAM,MAAM,SAAS,MAAM,CAAC;AAAA,EAC7C,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,mCAAmC,IAAI,IAAI,EAAE,OAAO,MAAM,CAAC;AAAA,EAC7E;AACA,SAAO,QAAQ,SAAS,IAAI;AAC9B;AAEO,SAAS,eAAe,OAAwB;AACrD,aAAO,gCAAW,QAAQ,EAAE,OAAO,eAAe,KAAK,CAAC,EAAE,OAAO,KAAK;AACxE;AAGO,SAAS,qBAAqB,OAAgB,QAAyB;AAC5E,aAAO,gCAAW,QAAQ,EACvB,OAAO,mBAAmB,OAAO,CAAC,MAAM,UAAU,KAAK,cAAc,OAAO,MAAM,CAAC,CAAC,EACpF,OAAO,KAAK;AACjB;AAEO,SAAS,cAAiB,OAAa;AAC5C,SAAO,eAAkB,eAAe,KAAK,GAAG,UAAU;AAC5D;AAEO,SAAS,eAAe,MAAe,OAAyB;AACrE,SAAO,eAAe,IAAI,EAAE,OAAO,eAAe,KAAK,CAAC;AAC1D;AAEA,SAAS,mBAAmB,OAAgB,aAA8D;AACxG,SAAO,OAAO,KAAK,KAAK,UAAU,SAAS,OAAO,oBAAI,QAAQ,GAAG,WAAW,CAAC,GAAG,MAAM;AACxF;AAEA,SAAS,qBAAqB,MAAc,OAAuB;AACjE,SAAO,OAAO,QAAQ,KAAK,OAAO,QAAQ,IAAI;AAChD;AAEA,SAAS,SACP,OACA,WACA,aACiB;AACjB,MAAI,UAAU,KAAM,QAAO,CAAC,MAAM;AAClC,MAAI,UAAU,OAAW,QAAO,CAAC,WAAW;AAC5C,MAAI,OAAO,UAAU,SAAU,QAAO,CAAC,UAAU,KAAK;AACtD,MAAI,OAAO,UAAU,UAAW,QAAO,CAAC,WAAW,KAAK;AACxD,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,OAAO,GAAG,OAAO,EAAE,EAAG,QAAO,CAAC,UAAU,IAAI;AAChD,QAAI,OAAO,MAAM,KAAK,EAAG,QAAO,CAAC,UAAU,KAAK;AAChD,QAAI,UAAU,SAAU,QAAO,CAAC,UAAU,WAAW;AACrD,QAAI,UAAU,UAAW,QAAO,CAAC,UAAU,WAAW;AACtD,WAAO,CAAC,UAAU,KAAK;AAAA,EACzB;AACA,MAAI,OAAO,UAAU,SAAU,OAAM,IAAI,UAAU,2CAA2C;AAC9F,MAAI,iBAAiB,YAAY;AAC/B,UAAM,OAAO,QAAQ,QAAQ,KAAK;AAClC,QACE,KAAK,WAAW,MAAM,UACtB,KAAK,KAAK,CAAC,QAAQ,OAAO,QAAQ,YAAY,CAAC,aAAa,KAAK,MAAM,MAAM,CAAC,GAC9E;AACA,YAAM,IAAI,UAAU,wDAAwD;AAAA,IAC9E;AACA,WAAO,CAAC,UAAU,OAAO,KAAK,KAAK,EAAE,SAAS,QAAQ,CAAC;AAAA,EACzD;AACA,MAAI,UAAU,IAAI,KAAK,EAAG,OAAM,IAAI,UAAU,sCAAsC;AACpF,YAAU,IAAI,KAAK;AACnB,MAAI;AACF,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,YAAMC,QAAO,QAAQ,QAAQ,KAAK;AAClC,UACEA,MAAK,WAAW,MAAM,SAAS,KAC/BA,MAAK,KAAK,CAAC,QAAQ,OAAO,QAAQ,YAAY,QAAQ,YAAY,CAAC,aAAa,KAAK,MAAM,MAAM,CAAC,GAClG;AACA,cAAM,IAAI,UAAU,uDAAuD;AAAA,MAC7E;AACA,YAAM,QAA2B,CAAC;AAClC,eAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,cAAM,aAAa,OAAO,yBAAyB,OAAO,OAAO,KAAK,CAAC;AACvE,YAAI,cAAc,QAAQ,CAAC,WAAW,cAAc,EAAE,WAAW,aAAa;AAC5E,gBAAM,IAAI,UAAU,oDAAoD;AAAA,QAC1E;AACA,cAAM,KAAK,SAAS,WAAW,OAAkB,WAAW,WAAW,CAAC;AAAA,MAC1E;AACA,aAAO,CAAC,SAAS,KAAK;AAAA,IACxB;AACA,UAAM,YAAqB,OAAO,eAAe,KAAK;AACtD,QAAI,cAAc,OAAO,aAAa,cAAc,MAAM;AACxD,YAAM,IAAI,UAAU,gDAAgD;AAAA,IACtE;AACA,UAAM,OAAO,QAAQ,QAAQ,KAAK;AAClC,QAAI,KAAK,KAAK,CAAC,QAAQ,OAAO,QAAQ,QAAQ,GAAG;AAC/C,YAAM,IAAI,UAAU,4CAA4C;AAAA,IAClE;AACA,UAAM,UAAuC,CAAC;AAC9C,eAAW,OAAQ,KAAkB,KAAK,WAAW,GAAG;AACtD,YAAM,aAAa,OAAO,yBAAyB,OAAO,GAAG;AAC7D,UAAI,cAAc,QAAQ,CAAC,WAAW,cAAc,EAAE,WAAW,aAAa;AAC5E,cAAM,IAAI,UAAU,kDAAkD;AAAA,MACxE;AACA,cAAQ,KAAK,CAAC,KAAK,SAAS,WAAW,OAAkB,WAAW,WAAW,CAAC,CAAC;AAAA,IACnF;AACA,WAAO,CAAC,UAAU,OAAO;AAAA,EAC3B,UAAE;AACA,cAAU,OAAO,KAAK;AAAA,EACxB;AACF;AAEA,SAAS,QAAQ,OAAgB,MAAuB;AACtD,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,OAAO,MAAM,CAAC,MAAM,SAAU,OAAM,IAAI,UAAU,WAAW,IAAI,EAAE;AAChG,UAAQ,MAAM,CAAC,GAAG;AAAA,IAChB,KAAK;AAAQ,aAAO;AAAA,IACpB,KAAK;AAAa,aAAO;AAAA,IACzB,KAAK;AAAU,aAAO,iBAAiB,MAAM,CAAC,GAAG,UAAU,IAAI;AAAA,IAC/D,KAAK;AAAW,aAAO,iBAAiB,MAAM,CAAC,GAAG,WAAW,IAAI;AAAA,IACjE,KAAK;AAAU,aAAO,OAAO,KAAK,iBAAiB,MAAM,CAAC,GAAG,UAAU,IAAI,GAAG,QAAQ;AAAA,IACtF,KAAK;AAAU,aAAO,cAAc,MAAM,CAAC,GAAG,IAAI;AAAA,IAClD,KAAK,SAAS;AACZ,UAAI,CAAC,MAAM,QAAQ,MAAM,CAAC,CAAC,EAAG,OAAM,IAAI,UAAU,WAAW,IAAI,EAAE;AACnE,aAAO,MAAM,CAAC,EAAE,IAAI,CAAC,SAAS,QAAQ,MAAM,IAAI,CAAC;AAAA,IACnD;AAAA,IACA,KAAK,UAAU;AACb,UAAI,CAAC,MAAM,QAAQ,MAAM,CAAC,CAAC,EAAG,OAAM,IAAI,UAAU,WAAW,IAAI,EAAE;AACnE,YAAM,SAAkC,CAAC;AACzC,iBAAW,SAAS,MAAM,CAAC,GAAG;AAC5B,YAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW,KAAK,OAAO,MAAM,CAAC,MAAM,UAAU;AAC/E,gBAAM,IAAI,UAAU,WAAW,IAAI,EAAE;AAAA,QACvC;AACA,eAAO,eAAe,QAAQ,MAAM,CAAC,GAAG;AAAA,UACtC,cAAc;AAAA,UACd,YAAY;AAAA,UACZ,OAAO,QAAQ,MAAM,CAAC,GAAG,IAAI;AAAA,UAC7B,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AACA,aAAO;AAAA,IACT;AAAA,IACA;AAAS,YAAM,IAAI,UAAU,WAAW,IAAI,EAAE;AAAA,EAChD;AACF;AAEA,SAAS,cAAc,OAAgB,MAAsB;AAC3D,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,UAAU,MAAO,QAAO,OAAO;AACnC,MAAI,UAAU,YAAa,QAAO;AAClC,MAAI,UAAU,YAAa,QAAO;AAClC,MAAI,UAAU,KAAM,QAAO;AAC3B,QAAM,IAAI,UAAU,WAAW,IAAI,EAAE;AACvC;AAEA,SAAS,iBACP,OACA,MACA,MACuC;AACvC,MAAI,OAAO,UAAU,KAAM,OAAM,IAAI,UAAU,WAAW,IAAI,EAAE;AAChE,SAAO;AACT;AAEA,SAAS,QAAQ,OAAgB,MAA0B;AACzD,MAAI,OAAO,SAAS,KAAK,KAAK,iBAAiB,WAAY,QAAO;AAClE,QAAM,IAAI,UAAU,qCAAqC,IAAI,EAAE;AACjE;AAEA,SAAS,aAAa,KAAa,QAAyB;AAC1D,MAAI,CAAC,oBAAoB,KAAK,GAAG,EAAG,QAAO;AAC3C,QAAM,QAAQ,OAAO,GAAG;AACxB,SAAO,OAAO,cAAc,KAAK,KAAK,SAAS,KAAK,QAAQ;AAC9D;;;AH5JA,IAAM,yBAAyB;AAC/B,IAAM,sBAAsB;AAC5B,IAAM,yBAAyB;AA6BxB,IAAM,qBAAN,MAGiC;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACQ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,QAAkC,UAAqC,CAAC,GAAG;AACrF,SAAK,SAAS;AACd,SAAK,YAAY,QAAQ,iBAAa,gCAAW;AACjD,QAAI,OAAO,KAAK,cAAc,YAAY,KAAK,UAAU,KAAK,EAAE,WAAW,GAAG;AAC5E,YAAM,IAAI,UAAU,sCAAsC;AAAA,IAC5D;AACA,SAAK,YAAY,mBAAmB,QAAQ,aAAa,yBAAyB,uBAAuB;AACzG,SAAK,eAAe,cAAc,QAAQ,gBAAgB,CAAC,GAAG,cAAc;AAC5E,SAAK,cAAc;AAAA,MACjB,aAAa,QAAQ;AAAA,MACrB,WAAW,QAAQ;AAAA,MACnB,YAAY,QAAQ;AAAA,IACtB;AACA,QAAI,QAAQ,wBAAwB,QAAQ,CAAC,MAAM,QAAQ,QAAQ,oBAAoB,GAAG;AACxF,YAAM,IAAI,UAAU,uCAAuC;AAAA,IAC7D;AACA,QAAI;AACF,WAAK,uBAAuB,KAAK,oBAAoB,QAAQ,wBAAwB,CAAC,CAAC;AAAA,IACzF,SAAS,OAAO;AACd,YAAM,IAAI,UAAU,mDAAmD,EAAE,OAAO,MAAM,CAAC;AAAA,IACzF;AACA,UAAM,aAAS,gCAAW,QAAQ,EAAE,OAAO,KAAK,WAAW,MAAM,EAAE,OAAO,KAAK;AAC/E,SAAK,aAAa,GAAG,KAAK,SAAS,UAAU,MAAM;AACnD,SAAK,WAAW,GAAG,KAAK,UAAU;AAClC,SAAK,UAAU,GAAG,KAAK,SAAS,UAAU,MAAM;AAAA,EAClD;AAAA,EAEA,MAAM,eAAgC;AACpC,UAAM,KAAK,OAAO,OAAO,UAAU,KAAK;AACxC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,SAAS,OAA2C;AACxD,QAAI,SAAS,QAAQ,SAAS,EAAG,QAAO,CAAC;AACzC,QAAI,SAAS,QAAQ,CAAC,OAAO,cAAc,KAAK,GAAG;AACjD,YAAM,IAAI,UAAU,8BAA8B;AAAA,IACpD;AACA,UAAM,QAAQ,MAAM,KAAK,UAAU;AACnC,UAAM,QAAQ,SAAS,OAAO,MAAM,QAAQ,MAAM,MAAM,MAAM,KAAK,IAAI,MAAM,MAAM,SAAS,OAAO,CAAC,CAAC;AACrG,WAAO,cAAc,KAAK;AAAA,EAC5B;AAAA,EAEA,MAAM,SAAS,OAAwC;AACrD,QAAI,MAAM,WAAW,EAAG;AACxB,UAAM,YAAY,cAAc,OAAO,OAAO;AAC9C,UAAM,KAAK,OAAO,OAAO,WAAW;AAAA,MAClC,GAAG;AAAA,MACH,OAAO,CAAC,GAAG,MAAM,OAAO,GAAG,SAAS;AAAA,IACtC,EAAE;AAAA,EACJ;AAAA,EAEA,MAAM,6BAA6B,OAAwC;AACzE,UAAM,cAAc,cAAc,OAAO,OAAO;AAChD,UAAM,KAAK,OAAO,OAAO,WAAW,EAAE,GAAG,OAAO,OAAO,YAAY,EAAE;AAAA,EACvE;AAAA,EAEA,MAAM,UAA+C;AACnD,QAAI;AACJ,UAAM,KAAK,OAAO,OAAO,UAAU;AACjC,eAAS,MAAM,MAAM,GAAG,EAAE;AAC1B,aAAO,UAAU,OAAO,QAAQ,EAAE,GAAG,OAAO,OAAO,MAAM,MAAM,MAAM,GAAG,EAAE,EAAE;AAAA,IAC9E,CAAC;AACD,WAAO,UAAU,OAAO,SAAY,cAAc,MAAM;AAAA,EAC1D;AAAA,EAEA,MAAM,eAA8B;AAClC,UAAM,KAAK,OAAO,OAAO,WAAW,EAAE,GAAG,OAAO,OAAO,CAAC,GAAG,YAAY,CAAC,EAAE,EAAE;AAAA,EAC9E;AAAA,EAEA,MAAM,sBAAsB,MAAgD;AAC1E,QAAI,QAAQ,QAAQ,CAAC,MAAM,QAAQ,KAAK,SAAS,GAAG;AAClD,YAAM,IAAI,UAAU,uCAAuC;AAAA,IAC7D;AACA,QAAI,KAAK,UAAU,WAAW,EAAG;AACjC,UAAM,YAAY,cAAc,KAAK,SAAS;AAC9C,UAAM,KAAK,OAAO,OAAO,UAAU;AACjC,UAAI,QAAQ,cAAc,MAAM,KAAK;AACrC,iBAAW,YAAY,WAAW;AAChC,YAAI,SAAS,SAAS,yBAAyB;AAC7C,gBAAM,IAAI,UAAU,sCAAsC;AAAA,QAC5D;AACA,cAAM,cAAc,aAAa,SAAS,aAAa,sBAAsB;AAC7E,YAAI,kBAAkB;AACtB,cAAM,OAAyB,CAAC;AAChC,mBAAW,QAAQ,OAAO;AACxB,cAAI,KAAK,SAAS,mBAAmB,KAAK,WAAW,SAAS,QAAQ;AACpE,gBAAI,CAAC,iBAAiB;AACpB,mBAAK,KAAK,WAAW;AACrB,gCAAkB;AAAA,YACpB;AAAA,UACF,OAAO;AACL,iBAAK,KAAK,IAAI;AAAA,UAChB;AAAA,QACF;AACA,gBAAQ;AAAA,MACV;AACA,aAAO,EAAE,GAAG,OAAO,MAAM;AAAA,IAC3B,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,wBAAwB,MAAoD;AAChF,UAAM,EAAE,aAAa,YAAY,IAAI,wBAAwB,IAAI;AACjE,UAAM,SAAS,GAAG,sBAAsB,GAAG,eAAe,WAAW,CAAC;AACtE,UAAM,gBAAgB,oBAAI,IAAI;AAAA,MAC5B,eAAe,WAAW;AAAA,MAC1B,qBAAqB,WAAW;AAAA,MAChC,GAAG,KAAK,qBAAqB,IAAI,CAAC,WAAW,qBAAqB,aAAa,MAAM,CAAC;AAAA,IACxF,CAAC;AACD,UAAM,KAAK,OAAO,OAAO,UAAU;AACjC,YAAM,WAAW,OAAO,yBAAyB,MAAM,YAAY,WAAW,GAAG;AACjF,UAAI,YAAY,MAAM;AACpB,YAAI,OAAO,aAAa,SAAU,OAAM,IAAI,MAAM,2CAA2C;AAC7F,YAAI,aAAa,OAAQ,QAAO;AAChC,YAAI,CAAC,cAAc,IAAI,QAAQ,GAAG;AAChC,gBAAM,IAAI,MAAM,4EAA4E;AAAA,QAC9F;AACA,eAAO,EAAE,GAAG,OAAO,YAAY,EAAE,GAAG,MAAM,YAAY,CAAC,WAAW,GAAG,OAAO,EAAE;AAAA,MAChF;AAEA,UAAI;AACJ,UAAI,YAAY,SAAS,gBAAgB;AACvC,gBAAQ,CAAC,GAAG,MAAM,OAAO,GAAG,YAAY,KAAK;AAAA,MAC/C,OAAO;AACL,cAAM,cAAc,MAAM,MAAM,SAAS,YAAY,eAAe;AACpE,cAAM,eAAe,cAAc,IAAI,CAAC,IAAI,MAAM,MAAM,MAAM,WAAW;AACzE,YAAI,cAAc,KAAK,CAAC,eAAe,cAAc,YAAY,cAAc,GAAG;AAChF,gBAAM,IAAI,MAAM,uEAAuE;AAAA,QACzF;AACA,gBAAQ,CAAC,GAAG,MAAM,MAAM,MAAM,GAAG,WAAW,GAAG,GAAG,YAAY,WAAW;AAAA,MAC3E;AACA,aAAO;AAAA,QACL,GAAG;AAAA,QACH;AAAA,QACA,YAAY,EAAE,GAAG,MAAM,YAAY,CAAC,WAAW,GAAG,OAAO;AAAA,MAC3D;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,OACZ,WACe;AACf,UAAM,kBAAkB,KAAK,QAAQ,CAAC,KAAK,OAAO,GAAG,OAAO,UAAU;AACpE,eAAS,UAAU,GAAG,UAAU,GAAG,WAAW,GAAG;AAC/C,cAAM,YAAY;AAClB,cAAMC,YAAW,MAAM,KAAK,kBAAkB;AAC9C,cAAM,OAAO,MAAM,UAAUA,UAAS,KAAK;AAC3C,YAAI,MAAM,MAAM,cAAc,KAAK,UAAUA,UAAS,UAAU,eAAe,IAAI,CAAC,EAAG;AAAA,MACzF;AACA,YAAM,IAAI,MAAM,wEAAwE;AAAA,IAC1F,GAAG,KAAK,WAAW;AAAA,EACrB;AAAA,EAEA,MAAc,YAAyC;AACrD,YAAQ,MAAM,KAAK,kBAAkB,GAAG;AAAA,EAC1C;AAAA,EAEA,MAAc,oBAA0F;AACtG,UAAM,WAAW,MAAM,gBAAgB,KAAK,QAAQ,KAAK,UAAU,oCAAoC;AACvG,UAAM,QAAQ,YAAY,MAAM,KAAK,OAAO,QAAQ,QAAQ,KAAK,YAAY,mBAAmB;AAChG,QAAI,SAAS,KAAM,QAAO,EAAE,UAAU,OAAO,KAAK,WAAW,EAAE;AAC/D,UAAM,QAAQ,eAAmC,OAAO,6BAA6B;AACrF,QACE,SAAS,QACT,OAAO,UAAU,YACjB,MAAM,kBAAkB,0BACxB,MAAM,cAAc,KAAK,aACzB,CAAC,MAAM,QAAQ,MAAM,KAAK,KAC1B,MAAM,cAAc,QACpB,OAAO,MAAM,eAAe,YAC5B,MAAM,QAAQ,MAAM,UAAU,KAC9B,OAAO,OAAO,MAAM,UAAU,EAAE,KAAK,CAAC,WAAW,OAAO,WAAW,QAAQ,GAC3E;AACA,YAAM,IAAI,MAAM,gEAAgE;AAAA,IAClF;AACA,WAAO,EAAE,UAAU,MAAM;AAAA,EAC3B;AAAA,EAEQ,aAAiC;AACvC,WAAO;AAAA,MACL,eAAe;AAAA,MACf,OAAO,cAAc,KAAK,YAAY;AAAA,MACtC,YAAY,CAAC;AAAA,MACb,WAAW,KAAK;AAAA,IAClB;AAAA,EACF;AACF;AAEA,SAAS,wBAAwB,MAG/B;AACA,MAAI,QAAQ,QAAQ,OAAO,SAAS,SAAU,OAAM,IAAI,UAAU,wCAAwC;AAC1G,MAAI,OAAO,KAAK,gBAAgB,YAAY,KAAK,YAAY,KAAK,EAAE,WAAW,GAAG;AAChF,UAAM,IAAI,UAAU,oEAAoE;AAAA,EAC1F;AACA,QAAM,cAAc,cAAc,KAAK,WAAW;AAClD,MAAI,eAAe,QAAQ,OAAO,gBAAgB,UAAU;AAC1D,UAAM,IAAI,UAAU,+CAA+C;AAAA,EACrE;AACA,MAAI,YAAY,SAAS,gBAAgB;AACvC,QAAI,CAAC,MAAM,QAAQ,YAAY,KAAK,EAAG,OAAM,IAAI,UAAU,0CAA0C;AACrG,WAAO;AAAA,MACL,aAAa,KAAK;AAAA,MAClB,aAAa,EAAE,MAAM,gBAAgB,OAAO,cAAc,YAAY,OAAO,mBAAmB,EAAE;AAAA,IACpG;AAAA,EACF;AACA,MAAI,YAAY,SAAS,kBAAkB;AACzC,QAAI,CAAC,MAAM,QAAQ,YAAY,cAAc,KAAK,CAAC,MAAM,QAAQ,YAAY,WAAW,GAAG;AACzF,YAAM,IAAI,UAAU,+CAA+C;AAAA,IACrE;AACA,WAAO;AAAA,MACL,aAAa,KAAK;AAAA,MAClB,aAAa;AAAA,QACX,MAAM;AAAA,QACN,gBAAgB,cAAc,YAAY,gBAAgB,4BAA4B;AAAA,QACtF,aAAa,cAAc,YAAY,aAAa,yBAAyB;AAAA,MAC/E;AAAA,IACF;AAAA,EACF;AACA,QAAM,IAAI,UAAU,8CAA8C;AACpE;AAEA,SAAS,cAAc,OAAyB,MAAgC;AAC9E,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,OAAM,IAAI,UAAU,GAAG,IAAI,mBAAmB;AACzE,SAAO,MAAM,IAAI,CAAC,SAAS,aAAa,MAAM,IAAI,CAAC;AACrD;AAEA,SAAS,aAAa,MAAsB,MAA8B;AACxE,MAAI,QAAQ,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,IAAI,GAAG;AACnE,UAAM,IAAI,UAAU,GAAG,IAAI,iCAAiC;AAAA,EAC9D;AACA,SAAO,cAAc,IAAI;AAC3B;","names":["import_node_crypto","response","delay","import_node_crypto","keys","snapshot"]}
|