@cortexkit/pi-magic-context 0.49.12 → 0.49.14

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.
Files changed (32) hide show
  1. package/dist/auto-search-worker.js +3 -3
  2. package/dist/chunk-embedding-write-worker.js +87 -0
  3. package/dist/{embedding-backfill-14tqcfrn.js → embedding-backfill-7kj16fh9.js} +5 -4
  4. package/dist/embedding-worker.js +1 -1
  5. package/dist/historian-calibration-extension.js +1 -1
  6. package/dist/{index-gykw2zhn.js → index-0awvkeb5.js} +5 -5
  7. package/dist/index-1mrvw9en.js +225 -0
  8. package/dist/index-1vw4f2pe.js +907 -0
  9. package/dist/{index-zapgkmp7.js → index-65kty5te.js} +37 -48
  10. package/dist/{index-53xdqb3d.js → index-75ah9413.js} +1 -1
  11. package/dist/{index-af9nb5db.js → index-7qc73yk5.js} +60 -3
  12. package/dist/{index-xpsht877.js → index-7wagp5jp.js} +2 -2
  13. package/dist/{index-6hex51s9.js → index-a4pk5yv9.js} +2 -2
  14. package/dist/{index-z5ftst3e.js → index-ccsscaap.js} +3 -3
  15. package/dist/{index-ed9d2ded.js → index-j0n09wtp.js} +4 -1
  16. package/dist/{index-f6e8jsrh.js → index-nwbhe6qv.js} +188 -241
  17. package/dist/{index-xmdkde4v.js → index-y29y2j2w.js} +12 -1
  18. package/dist/index.js +2398 -2068
  19. package/dist/{message-index-bounded-ws37m1nt.js → message-index-bounded-z4d3x9ty.js} +4 -4
  20. package/dist/{message-index-dfs6k35a.js → message-index-dw4z9efj.js} +4 -4
  21. package/dist/migration-worker.js +2 -2
  22. package/dist/{project-embedding-registry-ymvne11v.js → project-embedding-registry-52zwmtbn.js} +4 -3
  23. package/dist/raw-ordinal-warmup-worker.js +3 -3
  24. package/dist/{read-session-chunk-83864b37.js → read-session-chunk-0fsgg2k1.js} +2 -2
  25. package/dist/{search-85e21wb8.js → search-ddbz6v60.js} +12 -11
  26. package/dist/{storage-tags-zmf30zqp.js → storage-tags-3kb5tvgg.js} +3 -1
  27. package/dist/subagent-entry.js +12 -11
  28. package/dist/tag-snapshot-worker-pi.js +235 -0
  29. package/package.json +3 -3
  30. /package/dist/{index-j24916mq.js → index-9jvktm7k.js} +0 -0
  31. /package/dist/{index-69vas84q.js → index-b7p25tm0.js} +0 -0
  32. /package/dist/{index-3cnarwf8.js → index-bet4sd3e.js} +0 -0
@@ -0,0 +1,907 @@
1
+ import {
2
+ tagRevisionIncarnationSql,
3
+ tagRevisionCountSql,
4
+ tagRevisionKey,
5
+ TAG_INSERT_CONFLICT_ROWS
6
+ } from "./index-jrap43gc.js";
7
+ import {
8
+ getTagsBySession2,
9
+ getTagsByNumbers2
10
+ } from "./index-j0n09wtp.js";
11
+ import {
12
+ inRootAsyncContext2,
13
+ getSqliteDatabasePath2
14
+ } from "./index-asrxgdt4.js";
15
+ import {
16
+ createFailClosedBlockingError
17
+ } from "./index-ccsscaap.js";
18
+
19
+ // src/tag-snapshot-worker-client-pi.ts
20
+ import { setImmediate as yieldImmediate } from "node:timers/promises";
21
+ import { Worker } from "node:worker_threads";
22
+
23
+ // src/tag-snapshot-codec-pi.ts
24
+ var encoder = new TextEncoder;
25
+ var decoder = new TextDecoder;
26
+ function encodePiHydrationOperation(operation) {
27
+ return encoder.encode(JSON.stringify(operation, (_key, value) => {
28
+ if (value instanceof Uint8Array)
29
+ return { $piScalar: "bytes", value: Array.from(value) };
30
+ if (typeof value === "number" && (!Number.isFinite(value) || Object.is(value, -0)))
31
+ return {
32
+ $piScalar: "number",
33
+ value: Object.is(value, -0) ? "-0" : String(value)
34
+ };
35
+ if (value === undefined)
36
+ return { $piScalar: "undefined" };
37
+ return value;
38
+ }));
39
+ }
40
+ function decodePiHydrationOperation(bytes) {
41
+ const operation = JSON.parse(decoder.decode(bytes));
42
+ const restore = (value) => {
43
+ for (const key of Object.keys(value)) {
44
+ const scalar = value[key];
45
+ if (!scalar || typeof scalar !== "object")
46
+ continue;
47
+ if (scalar.$piScalar === "bytes")
48
+ value[key] = Uint8Array.from(scalar.value);
49
+ else if (scalar.$piScalar === "undefined")
50
+ value[key] = undefined;
51
+ else if (scalar.$piScalar === "number")
52
+ value[key] = scalar.value === "-0" ? -0 : Number(scalar.value);
53
+ }
54
+ };
55
+ if (operation.type === "row")
56
+ restore(operation.value);
57
+ else if (operation.type === "field")
58
+ restore(operation);
59
+ return operation;
60
+ }
61
+
62
+ // src/tag-snapshot-worker-client-pi.ts
63
+ class PiTagHydrationError extends Error {
64
+ code;
65
+ constructor(message, code = "failed") {
66
+ super(`Pi tag hydration: ${message}`);
67
+ this.code = code;
68
+ this.name = "PiTagHydrationError";
69
+ }
70
+ }
71
+ function createPiHydrationPacketConsumer(request, cached = [], byteLimit) {
72
+ const assembly = createPiTagSnapshotCandidate(cached, byteLimit);
73
+ let sequence = 0;
74
+ let generation;
75
+ let busy = false;
76
+ let rejected = false;
77
+ let stream = "tags";
78
+ let tagsEnded = false;
79
+ let fallbackEnded = false;
80
+ let fragment;
81
+ let fragmentBytes = 0;
82
+ const byteOffsets = new Map;
83
+ let streamRows = 0;
84
+ let maxAssemblyMs = 0;
85
+ let done = false;
86
+ const fail = (message) => {
87
+ rejected = true;
88
+ throw new PiTagHydrationError(message);
89
+ };
90
+ return {
91
+ async consume(message) {
92
+ if (busy || rejected || done)
93
+ return fail("packet after completion or without credit");
94
+ if (message.jobId !== request.jobId || message.sessionId !== request.sessionId || message.connectionEpoch !== request.connectionEpoch || message.sessionEpoch !== request.sessionEpoch || message.sequence !== sequence++)
95
+ return fail("packet sequence or lifetime mismatch");
96
+ if (message.type === "failed") {
97
+ rejected = true;
98
+ if (message.code === "open")
99
+ throw createFailClosedBlockingError({
100
+ kind: "storage_failure",
101
+ cause: `Pi tag hydration: ${message.reason}`
102
+ });
103
+ if (message.code === "schema")
104
+ throw createFailClosedBlockingError({
105
+ kind: "schema_fence",
106
+ persistedVersion: message.persistedVersion ?? 0,
107
+ supportedVersion: message.supportedVersion ?? 0
108
+ }, { cause: new PiTagHydrationError(message.reason, "schema") });
109
+ throw new PiTagHydrationError(message.reason, message.code);
110
+ }
111
+ if (generation && (generation.revision !== message.generation.revision || generation.durable !== message.generation.durable))
112
+ return fail("packet generation mismatch");
113
+ generation ??= message.generation;
114
+ if (message.type === "done") {
115
+ if (!tagsEnded || !fallbackEnded || fragment)
116
+ return fail("completion before both streams ended");
117
+ done = true;
118
+ return assembly.finish();
119
+ }
120
+ if (message.stream !== stream || fallbackEnded)
121
+ return fail("stream order mismatch");
122
+ if (message.type === "end") {
123
+ if (fragment || message.rows !== streamRows)
124
+ return fail("incomplete row or stream count mismatch");
125
+ assembly.end(stream);
126
+ if (stream === "tags") {
127
+ tagsEnded = true;
128
+ stream = "fallback";
129
+ } else
130
+ fallbackEnded = true;
131
+ streamRows = 0;
132
+ return null;
133
+ }
134
+ if (!(message.bytes instanceof ArrayBuffer) || message.bytes.byteLength > 65536 || message.byteLength <= 0 || message.byteLength > message.bytes.byteLength || message.rows > 256)
135
+ return fail("packet exceeds credit limits");
136
+ busy = true;
137
+ let started = performance.now();
138
+ let packetRows = 0;
139
+ const append = (row) => {
140
+ if (stream === "tags")
141
+ assembly.appendTag(row);
142
+ else
143
+ assembly.appendFallback(row);
144
+ streamRows++;
145
+ packetRows++;
146
+ };
147
+ try {
148
+ const bytes = new Uint8Array(message.bytes, 0, message.byteLength);
149
+ const view = new DataView(message.bytes);
150
+ for (let offset = 0;offset < bytes.length; ) {
151
+ if (offset + 4 > bytes.length)
152
+ return fail("truncated frame length");
153
+ const length = view.getUint32(offset);
154
+ offset += 4;
155
+ if (length === 0 || offset + length > bytes.length)
156
+ return fail("truncated frame");
157
+ const operation = decodePiHydrationOperation(bytes.subarray(offset, offset + length));
158
+ offset += length;
159
+ if (operation.type === "row") {
160
+ if (fragment)
161
+ return fail("whole row inside fragments");
162
+ append(operation.value);
163
+ } else if (operation.type === "field") {
164
+ if (!fragment)
165
+ fragmentBytes = 384;
166
+ fragment ??= Object.create(null);
167
+ const value = operation.value;
168
+ fragmentBytes += typeof value === "string" ? 24 + value.length * 2 : value instanceof Uint8Array ? value.length : 8;
169
+ if (assembly.estimatedBytes + fragmentBytes > (byteLimit ?? 128 * 1024 * 1024))
170
+ return fail("candidate memory limit exceeded during field assembly");
171
+ if (operation.append) {
172
+ const prior = fragment[operation.key];
173
+ if (typeof prior === "string" && typeof operation.value === "string")
174
+ fragment[operation.key] = prior + operation.value;
175
+ else if (prior instanceof Uint8Array && operation.value instanceof Uint8Array) {
176
+ const offset = byteOffsets.get(operation.key);
177
+ if (offset === undefined || offset + operation.value.length > prior.length)
178
+ return fail("invalid binary field length");
179
+ prior.set(operation.value, offset);
180
+ byteOffsets.set(operation.key, offset + operation.value.length);
181
+ } else
182
+ return fail("invalid field fragment");
183
+ } else if (value instanceof Uint8Array) {
184
+ const length = operation.totalLength ?? value.length;
185
+ if (length < value.length || length > (byteLimit ?? 128 * 1024 * 1024))
186
+ return fail("binary field memory limit");
187
+ const target = new Uint8Array(length);
188
+ target.set(value);
189
+ fragment[operation.key] = target;
190
+ byteOffsets.set(operation.key, value.length);
191
+ } else
192
+ fragment[operation.key] = value;
193
+ } else if (operation.type === "row-end") {
194
+ if (!fragment)
195
+ return fail("row end without fields");
196
+ append(fragment);
197
+ fragment = undefined;
198
+ byteOffsets.clear();
199
+ } else
200
+ return fail("unknown frame");
201
+ const elapsed = performance.now() - started;
202
+ maxAssemblyMs = Math.max(maxAssemblyMs, elapsed);
203
+ if (elapsed >= 4) {
204
+ await yieldImmediate();
205
+ started = performance.now();
206
+ }
207
+ }
208
+ if (packetRows !== message.rows)
209
+ return fail("packet row count mismatch");
210
+ return null;
211
+ } catch (error) {
212
+ rejected = true;
213
+ throw error;
214
+ } finally {
215
+ busy = false;
216
+ }
217
+ },
218
+ get generation() {
219
+ return generation;
220
+ },
221
+ get maxAssemblyMs() {
222
+ return maxAssemblyMs;
223
+ }
224
+ };
225
+ }
226
+ function startPiTagSnapshotWorker(request, options = {}) {
227
+ const entry = options.entry ?? new URL(import.meta.url.endsWith(".ts") ? "./tag-snapshot-worker-pi.ts" : "./tag-snapshot-worker-pi.js", import.meta.url);
228
+ const started = performance.now();
229
+ const consumer = createPiHydrationPacketConsumer(request, options.cached, options.byteLimit);
230
+ const worker = inRootAsyncContext2(() => new Worker(entry, { workerData: request }));
231
+ let exited = false;
232
+ let settled = false;
233
+ let consumption = Promise.resolve();
234
+ let complete;
235
+ let rejectResult;
236
+ const released = new Promise((resolve) => worker.once("exit", () => {
237
+ exited = true;
238
+ resolve();
239
+ }));
240
+ const result = new Promise((resolve, reject) => {
241
+ rejectResult = reject;
242
+ const consumeMessage = async (message) => {
243
+ if (settled)
244
+ return;
245
+ try {
246
+ const candidate = await consumer.consume(message);
247
+ if (candidate && message.type === "done") {
248
+ complete = {
249
+ candidate,
250
+ generation: message.generation,
251
+ telemetry: {
252
+ maxReadTransactionMs: message.maxReadTransactionMs,
253
+ maxAssemblyMs: consumer.maxAssemblyMs,
254
+ packetCount: message.packetCount,
255
+ packetBytes: message.packetBytes,
256
+ jobMs: performance.now() - started
257
+ }
258
+ };
259
+ } else {
260
+ await options.beforeAck?.(message);
261
+ if (!settled) {
262
+ const bytes = message.type === "packet" ? message.bytes : undefined;
263
+ worker.postMessage({ type: "ack", sequence: message.sequence, bytes }, bytes ? [bytes] : []);
264
+ }
265
+ }
266
+ } catch (error) {
267
+ abort(error instanceof Error ? error : new Error(String(error)));
268
+ }
269
+ };
270
+ worker.on("message", (message) => {
271
+ consumption = consumeMessage(message);
272
+ });
273
+ worker.once("error", (error) => abort(error));
274
+ worker.once("exit", async (code) => {
275
+ await consumption;
276
+ worker.removeAllListeners("message");
277
+ worker.removeAllListeners("error");
278
+ if (settled)
279
+ return;
280
+ settled = true;
281
+ clearTimeout(timer);
282
+ if (code === 0 && complete)
283
+ resolve(complete);
284
+ else
285
+ reject(new PiTagHydrationError(`worker exited with code ${code} before a clean complete result`));
286
+ });
287
+ });
288
+ function abort(error = new PiTagHydrationError("cancelled")) {
289
+ if (settled)
290
+ return;
291
+ settled = true;
292
+ clearTimeout(timer);
293
+ rejectResult(error);
294
+ if (!exited)
295
+ worker.terminate().catch(() => {});
296
+ }
297
+ const timer = inRootAsyncContext2(() => setTimeout(() => abort(new PiTagHydrationError("job deadline exceeded", "deadline")), options.deadlineMs ?? 1e4));
298
+ timer.unref();
299
+ worker.unref();
300
+ result.catch(() => {});
301
+ return { result, released, cancel: abort };
302
+ }
303
+
304
+ // src/tag-snapshot-pi.ts
305
+ function createPiTagSnapshotReader(db) {
306
+ const existing = readers.get(db);
307
+ if (existing)
308
+ return existing;
309
+ db.exec(`
310
+ CREATE TEMP TABLE IF NOT EXISTS pi_tag_revision (revision INTEGER NOT NULL);
311
+ INSERT INTO pi_tag_revision SELECT 0 WHERE NOT EXISTS (SELECT 1 FROM pi_tag_revision);
312
+ CREATE TEMP TABLE IF NOT EXISTS pi_tag_session_revision (session_id TEXT PRIMARY KEY, revision INTEGER NOT NULL);
313
+ CREATE TEMP TABLE IF NOT EXISTS pi_tag_watch (session_id TEXT PRIMARY KEY);
314
+ CREATE TEMP TABLE IF NOT EXISTS pi_tag_changes (session_id TEXT, tag_number INTEGER, PRIMARY KEY (session_id, tag_number));
315
+ CREATE TEMP TABLE IF NOT EXISTS pi_tag_version_own (session_id TEXT PRIMARY KEY, count INTEGER NOT NULL);
316
+ CREATE TEMP TABLE IF NOT EXISTS pi_tag_first_watch (session_id TEXT PRIMARY KEY);
317
+ CREATE TEMP TABLE IF NOT EXISTS pi_tag_first_rows (session_id TEXT, id INTEGER, tag_number INTEGER, PRIMARY KEY(session_id, id));
318
+ CREATE TEMP TABLE IF NOT EXISTS pi_tag_first_allocation (session_id TEXT PRIMARY KEY, incarnation TEXT, seen INTEGER);
319
+ DROP TRIGGER IF EXISTS temp.pi_tag_first_allocation;
320
+ CREATE TEMP TRIGGER pi_tag_first_allocation AFTER UPDATE ON main.schema_migrations_meta
321
+ WHEN SUBSTR(NEW.key, 1, 13) = 'tag_revision:' AND INSTR(OLD.value, ':') = 0
322
+ AND NEW.value = (SELECT value FROM schema_migrations_meta WHERE key = 'tag_revision_incarnation') || ':' || OLD.value
323
+ AND EXISTS (SELECT 1 FROM pi_tag_first_watch WHERE session_id = SUBSTR(NEW.key, 14)) BEGIN
324
+ INSERT INTO pi_tag_first_allocation SELECT SUBSTR(NEW.key, 14), ${tagRevisionIncarnationSql("NEW.value")}, 0
325
+ WHERE NOT EXISTS (SELECT 1 FROM pi_tag_first_allocation WHERE session_id = SUBSTR(NEW.key, 14));
326
+ UPDATE pi_tag_first_allocation SET seen = seen + 1 WHERE session_id = SUBSTR(NEW.key, 14);
327
+ END;
328
+ DROP TRIGGER IF EXISTS temp.pi_tag_version_ai;
329
+ DROP TRIGGER IF EXISTS temp.pi_tag_version_ad;
330
+ DROP TRIGGER IF EXISTS temp.pi_tag_version_au;
331
+ DROP TRIGGER IF EXISTS temp.pi_tag_insert;
332
+ DROP TRIGGER IF EXISTS temp.pi_tag_update;
333
+ DROP TRIGGER IF EXISTS temp.pi_tag_delete;
334
+ DROP TRIGGER IF EXISTS temp.pi_tag_insert_conflicts;
335
+ CREATE TEMP TRIGGER pi_tag_insert_conflicts BEFORE INSERT ON main.tags BEGIN
336
+ UPDATE pi_tag_revision SET revision = revision + (SELECT COUNT(*) FROM (${TAG_INSERT_CONFLICT_ROWS}));
337
+ INSERT INTO pi_tag_session_revision
338
+ SELECT session_id, COUNT(*) FROM (${TAG_INSERT_CONFLICT_ROWS}) GROUP BY session_id
339
+ ON CONFLICT(session_id) DO UPDATE SET revision = revision + excluded.revision;
340
+ INSERT INTO pi_tag_changes
341
+ SELECT session_id, tag_number FROM (${TAG_INSERT_CONFLICT_ROWS}) AS conflicts
342
+ WHERE EXISTS (SELECT 1 FROM pi_tag_watch WHERE session_id = conflicts.session_id)
343
+ AND NOT EXISTS (SELECT 1 FROM pi_tag_changes WHERE session_id = conflicts.session_id AND tag_number = conflicts.tag_number)
344
+ GROUP BY session_id, tag_number;
345
+ END;
346
+ CREATE TEMP TRIGGER IF NOT EXISTS pi_tag_insert AFTER INSERT ON main.tags BEGIN
347
+ INSERT INTO pi_tag_first_rows SELECT NEW.session_id, NEW.id, NEW.tag_number
348
+ WHERE EXISTS (SELECT 1 FROM pi_tag_first_watch WHERE session_id = NEW.session_id)
349
+ AND NOT EXISTS (SELECT 1 FROM pi_tag_first_rows WHERE session_id = NEW.session_id AND id = NEW.id);
350
+ UPDATE pi_tag_revision SET revision = revision + 1;
351
+ INSERT INTO pi_tag_session_revision VALUES (NEW.session_id, 1) ON CONFLICT(session_id) DO UPDATE SET revision = revision + 1;
352
+ INSERT INTO pi_tag_changes SELECT NEW.session_id, NEW.tag_number WHERE EXISTS (SELECT 1 FROM pi_tag_watch WHERE session_id = NEW.session_id) AND NOT EXISTS (SELECT 1 FROM pi_tag_changes WHERE session_id = NEW.session_id AND tag_number = NEW.tag_number);
353
+ END;
354
+ CREATE TEMP TRIGGER IF NOT EXISTS pi_tag_update AFTER UPDATE ON main.tags BEGIN
355
+ UPDATE pi_tag_revision SET revision = revision + 1;
356
+ INSERT INTO pi_tag_session_revision VALUES (OLD.session_id, 1) ON CONFLICT(session_id) DO UPDATE SET revision = revision + 1;
357
+ INSERT INTO pi_tag_session_revision SELECT NEW.session_id, 1 WHERE NEW.session_id IS NOT OLD.session_id ON CONFLICT(session_id) DO UPDATE SET revision = revision + 1;
358
+ INSERT INTO pi_tag_changes SELECT OLD.session_id, OLD.tag_number WHERE EXISTS (SELECT 1 FROM pi_tag_watch WHERE session_id = OLD.session_id) AND NOT EXISTS (SELECT 1 FROM pi_tag_changes WHERE session_id = OLD.session_id AND tag_number = OLD.tag_number);
359
+ INSERT INTO pi_tag_changes SELECT NEW.session_id, NEW.tag_number WHERE EXISTS (SELECT 1 FROM pi_tag_watch WHERE session_id = NEW.session_id) AND NOT EXISTS (SELECT 1 FROM pi_tag_changes WHERE session_id = NEW.session_id AND tag_number = NEW.tag_number);
360
+ END;
361
+ CREATE TEMP TRIGGER IF NOT EXISTS pi_tag_delete AFTER DELETE ON main.tags BEGIN
362
+ UPDATE pi_tag_revision SET revision = revision + 1;
363
+ INSERT INTO pi_tag_session_revision VALUES (OLD.session_id, 1) ON CONFLICT(session_id) DO UPDATE SET revision = revision + 1;
364
+ INSERT INTO pi_tag_changes SELECT OLD.session_id, OLD.tag_number WHERE EXISTS (SELECT 1 FROM pi_tag_watch WHERE session_id = OLD.session_id) AND NOT EXISTS (SELECT 1 FROM pi_tag_changes WHERE session_id = OLD.session_id AND tag_number = OLD.tag_number);
365
+ END;
366
+ CREATE TEMP TRIGGER pi_tag_version_ai AFTER INSERT ON main.tags BEGIN
367
+ INSERT INTO pi_tag_version_own VALUES (NEW.session_id, 1) ON CONFLICT(session_id) DO UPDATE SET count = count + 1;
368
+ END;
369
+ CREATE TEMP TRIGGER pi_tag_version_ad AFTER DELETE ON main.tags BEGIN
370
+ INSERT INTO pi_tag_version_own VALUES (OLD.session_id, 1) ON CONFLICT(session_id) DO UPDATE SET count = count + 1;
371
+ END;
372
+ CREATE TEMP TRIGGER pi_tag_version_au
373
+ AFTER UPDATE OF session_id, message_id, tag_number, type, tool_owner_message_id, status ON main.tags BEGIN
374
+ INSERT INTO pi_tag_version_own VALUES (OLD.session_id, 1) ON CONFLICT(session_id) DO UPDATE SET count = count + 1;
375
+ INSERT INTO pi_tag_version_own SELECT NEW.session_id, 1 WHERE NEW.session_id != OLD.session_id
376
+ ON CONFLICT(session_id) DO UPDATE SET count = count + 1;
377
+ END;
378
+ `);
379
+ const versionStamp = db.prepare(`SELECT
380
+ COALESCE((SELECT tags_version FROM session_meta WHERE session_id = ?), 0) AS durable,
381
+ COALESCE((SELECT count FROM pi_tag_version_own WHERE session_id = ?), 0) AS own`);
382
+ const revision = db.prepare(`WITH stamp AS (SELECT
383
+ COALESCE((SELECT revision FROM pi_tag_session_revision WHERE session_id = ?), 0) AS own,
384
+ COALESCE((SELECT value FROM schema_migrations_meta WHERE key = ?), '0') AS total)
385
+ SELECT CAST(own AS TEXT) AS local,
386
+ (${tagRevisionIncarnationSql("total")}) || ':' || CAST(${tagRevisionCountSql("total")} - own AS TEXT) AS foreign_revision FROM stamp`);
387
+ revisionReaders.set(db, (sessionId) => {
388
+ const transaction = db;
389
+ if (transaction.inTransaction || transaction.isTransaction)
390
+ return null;
391
+ const row = revision.get(sessionId, tagRevisionKey(sessionId));
392
+ return [row.local, row.foreign_revision];
393
+ });
394
+ const changed = db.prepare("SELECT tag_number FROM pi_tag_changes WHERE session_id = ? ORDER BY tag_number");
395
+ const clearChanged = db.prepare("DELETE FROM pi_tag_changes WHERE session_id = ?");
396
+ const watch = db.prepare("INSERT OR IGNORE INTO pi_tag_watch VALUES (?)");
397
+ const unwatch = db.prepare("DELETE FROM pi_tag_watch WHERE session_id = ?");
398
+ const cache = new Map;
399
+ const ownFirstAllocation = db.prepare(`SELECT 1 FROM pi_tag_first_allocation allocation
400
+ WHERE session_id = ? AND seen = 1 AND incarnation || ':0' = ?
401
+ AND EXISTS (SELECT 1 FROM pi_tag_watch WHERE session_id = allocation.session_id)
402
+ AND EXISTS (SELECT 1 FROM pi_tag_first_rows WHERE session_id = allocation.session_id)
403
+ AND NOT EXISTS (SELECT 1 FROM pi_tag_first_rows first_row WHERE first_row.session_id = allocation.session_id
404
+ AND NOT EXISTS (SELECT 1 FROM pi_tag_changes change WHERE change.session_id = first_row.session_id AND change.tag_number IS first_row.tag_number))`);
405
+ const managed = new Set;
406
+ const epoch = ++connectionEpoch;
407
+ const sessionEpochs = new Map;
408
+ let jobId = 0;
409
+ let current;
410
+ let desiredSession;
411
+ let failedUntil = 0;
412
+ let lastFailure;
413
+ const dataVersion = db.prepare("PRAGMA data_version");
414
+ const totalRevision = db.prepare("SELECT COALESCE(value, '0') AS revision, value IS NOT NULL AS present FROM (SELECT 1) LEFT JOIN schema_migrations_meta ON key = ?");
415
+ const assertOutsideTransaction = () => {
416
+ const connection = db;
417
+ if (connection.inTransaction || connection.isTransaction)
418
+ throw new PiTagHydrationError("readiness requested inside a transaction");
419
+ };
420
+ const stamps = (sessionId, id) => {
421
+ assertOutsideTransaction();
422
+ const revision = revisionReaders.get(db)?.(sessionId);
423
+ if (!revision)
424
+ throw new PiTagHydrationError("owner revision unavailable");
425
+ const stamp = versionStamp.get(sessionId, sessionId);
426
+ const total = totalRevision.get(tagRevisionKey(sessionId));
427
+ return {
428
+ connectionEpoch: epoch,
429
+ sessionEpoch: sessionEpochs.get(sessionId) ?? 0,
430
+ jobId: id,
431
+ sessionId,
432
+ localRevision: revision[0],
433
+ foreignRevision: revision[1],
434
+ durableVersion: stamp.durable,
435
+ ownVersion: stamp.own,
436
+ dataVersion: dataVersion.get().data_version,
437
+ totalRevision: total.revision,
438
+ revisionPresent: total.present
439
+ };
440
+ };
441
+ const ready = (sessionId) => {
442
+ assertOutsideTransaction();
443
+ const cached = cache.get(sessionId);
444
+ if (!cached?.fallback)
445
+ return false;
446
+ const revision = revisionReaders.get(db)?.(sessionId);
447
+ if (!revision || cached.foreignRevision !== revision[1])
448
+ return false;
449
+ const stamp = versionStamp.get(sessionId, sessionId);
450
+ return stamp.durable - cached.durableVersion === stamp.own - cached.ownVersion;
451
+ };
452
+ const cancel = (sessionId) => {
453
+ sessionEpochs.set(sessionId, (sessionEpochs.get(sessionId) ?? 0) + 1);
454
+ if (desiredSession === sessionId)
455
+ desiredSession = undefined;
456
+ if (current?.sessionId === sessionId)
457
+ current.cancel();
458
+ };
459
+ const load = (sessionId) => inRootAsyncContext2(async () => {
460
+ managed.add(sessionId);
461
+ if (ready(sessionId))
462
+ return;
463
+ desiredSession = sessionId;
464
+ if (current) {
465
+ if (current.sessionId === sessionId && !current.stale)
466
+ return current.result;
467
+ current.cancel();
468
+ await current.released;
469
+ if (desiredSession !== sessionId)
470
+ throw new PiTagHydrationError("session hydration superseded", "stale");
471
+ return load(sessionId);
472
+ }
473
+ if (performance.now() < failedUntil)
474
+ throw lastFailure;
475
+ watch.run(sessionId);
476
+ const token = stamps(sessionId, ++jobId);
477
+ const previous = cache.get(sessionId);
478
+ const legacyFallbackOnly = previous && previous.foreignRevision === token.foreignRevision && (previous.legacyFallback || token.durableVersion - previous.durableVersion !== token.ownVersion - previous.ownVersion);
479
+ const path = getSqliteDatabasePath2(db);
480
+ const factory = workerFactories.get(db) ?? ((request, cached) => {
481
+ if (!path)
482
+ throw new PiTagHydrationError("read-only hydration requires a file-backed database");
483
+ return startPiTagSnapshotWorker({ ...request, path }, { cached });
484
+ });
485
+ const worker = factory({
486
+ path: path ?? "",
487
+ sessionId,
488
+ connectionEpoch: epoch,
489
+ sessionEpoch: token.sessionEpoch,
490
+ jobId: token.jobId
491
+ }, previous?.tags ?? []);
492
+ const destination = {
493
+ sessionId,
494
+ result: Promise.resolve(),
495
+ released: worker.released,
496
+ cancel: worker.cancel
497
+ };
498
+ current = destination;
499
+ let jobs = activeJobs.get(sessionId);
500
+ if (!jobs) {
501
+ jobs = new Set;
502
+ activeJobs.set(sessionId, jobs);
503
+ }
504
+ const lifetime = {
505
+ cancel,
506
+ released: worker.released,
507
+ get result() {
508
+ return destination.result;
509
+ }
510
+ };
511
+ jobs.add(lifetime);
512
+ destination.result = worker.result.then(({ candidate, generation }) => {
513
+ const live = stamps(sessionId, token.jobId);
514
+ if (current !== destination || desiredSession !== sessionId || !samePiTagSnapshotToken(token, live) || token.totalRevision !== live.totalRevision || generation.revision !== token.totalRevision || generation.durable !== token.durableVersion)
515
+ throw new PiTagHydrationError("owner generation or lifetime changed", "stale");
516
+ const snapshot = {
517
+ firstAllocationPending: !live.revisionPresent && candidate.tags.length === 0 && !db.prepare("SELECT 1 FROM tags WHERE session_id = ? LIMIT 1").get(sessionId),
518
+ revision: legacyFallbackOnly ? previous.revision : live.localRevision,
519
+ foreignRevision: live.foreignRevision,
520
+ tags: legacyFallbackOnly ? previous.tags : candidate.tags,
521
+ active: legacyFallbackOnly ? previous.active : candidate.active,
522
+ fallback: candidate.fallback,
523
+ durableVersion: live.durableVersion,
524
+ ownVersion: live.ownVersion
525
+ };
526
+ if (cache.size >= 100 && !cache.has(sessionId)) {
527
+ const oldest = cache.keys().next().value;
528
+ if (oldest !== undefined) {
529
+ cache.delete(oldest);
530
+ unwatch.run(oldest);
531
+ clearChanged.run(oldest);
532
+ }
533
+ }
534
+ if (!legacyFallbackOnly)
535
+ clearChanged.run(sessionId);
536
+ if (snapshot.firstAllocationPending) {
537
+ db.prepare("DELETE FROM pi_tag_first_allocation WHERE session_id = ?").run(sessionId);
538
+ db.prepare("DELETE FROM pi_tag_first_rows WHERE session_id = ?").run(sessionId);
539
+ db.prepare("INSERT OR IGNORE INTO pi_tag_first_watch VALUES (?)").run(sessionId);
540
+ }
541
+ cache.set(sessionId, snapshot);
542
+ }).catch((error) => {
543
+ if (error instanceof PiTagHydrationError && error.code === "stale")
544
+ destination.stale = true;
545
+ if (current === destination && desiredSession === sessionId && token.sessionEpoch === (sessionEpochs.get(sessionId) ?? 0)) {
546
+ lastFailure = error;
547
+ failedUntil = performance.now() + (error instanceof PiTagHydrationError && error.code === "stale" ? 0 : 500);
548
+ }
549
+ throw error;
550
+ });
551
+ Promise.allSettled([destination.result, worker.released]).then(() => {
552
+ if (current === destination)
553
+ current = undefined;
554
+ jobs.delete(lifetime);
555
+ if (!jobs.size)
556
+ activeJobs.delete(sessionId);
557
+ });
558
+ return destination.result;
559
+ });
560
+ owners.set(db, {
561
+ ready,
562
+ load,
563
+ manage: (sessionId) => managed.add(sessionId),
564
+ cancel
565
+ });
566
+ const fallbackRows = db.prepare(`SELECT ${PI_FALLBACK_ROW_COLUMNS} FROM tags WHERE session_id = ? AND ${PI_FALLBACK_ROW_PREDICATE}`);
567
+ const fallbackRowsByNumbers = db.prepare(`SELECT ${PI_FALLBACK_ROW_COLUMNS} FROM tags WHERE session_id = ?
568
+ AND tag_number IN (SELECT value FROM json_each(?)) AND ${PI_FALLBACK_ROW_PREDICATE}`);
569
+ const sync = (sessionId) => {
570
+ const transaction = db;
571
+ if (transaction.inTransaction || transaction.isTransaction)
572
+ return null;
573
+ const [local, external] = revisionReaders.get(db)?.(sessionId) ?? [
574
+ "0",
575
+ "0:0"
576
+ ];
577
+ const stamp = versionStamp.get(sessionId, sessionId);
578
+ let snapshot = cache.get(sessionId);
579
+ if (snapshot?.firstAllocationPending && snapshot.foreignRevision !== external && snapshot.revision !== local && stamp.durable - snapshot.durableVersion === stamp.own - snapshot.ownVersion && ownFirstAllocation.get(sessionId, external)) {
580
+ snapshot.foreignRevision = external;
581
+ snapshot.firstAllocationPending = false;
582
+ db.prepare("DELETE FROM pi_tag_first_watch WHERE session_id = ?").run(sessionId);
583
+ db.prepare("DELETE FROM pi_tag_first_rows WHERE session_id = ?").run(sessionId);
584
+ }
585
+ if (!snapshot || snapshot.foreignRevision !== external) {
586
+ if (managed.has(sessionId))
587
+ throw new PiTagHydrationError("tag snapshot is not ready; turn not sent, retry");
588
+ const tags = snapshot ? reuseUnchangedRows(snapshot.tags, getTagsBySession2(db, sessionId)) : getTagsBySession2(db, sessionId);
589
+ snapshot = {
590
+ revision: local,
591
+ foreignRevision: external,
592
+ tags,
593
+ active: tags.filter(isActive),
594
+ durableVersion: stamp.durable,
595
+ ownVersion: stamp.own
596
+ };
597
+ if (cache.size >= 100 && !cache.has(sessionId)) {
598
+ const oldest = cache.keys().next().value;
599
+ if (oldest !== undefined) {
600
+ cache.delete(oldest);
601
+ unwatch.run(oldest);
602
+ clearChanged.run(oldest);
603
+ }
604
+ }
605
+ cache.set(sessionId, snapshot);
606
+ for (const tag of snapshot.tags)
607
+ Object.freeze(tag);
608
+ watch.run(sessionId);
609
+ } else if (snapshot.revision !== local) {
610
+ const numbers = changed.all(sessionId).map((row) => row.tag_number);
611
+ if (numbers.length > 0) {
612
+ const dirty = new Set(numbers);
613
+ const replacements = getTagsByNumbers2(db, sessionId, numbers);
614
+ for (const tag of replacements)
615
+ Object.freeze(tag);
616
+ snapshot.tags = mergeChangedRows(snapshot.tags, dirty, replacements);
617
+ snapshot.active = mergeChangedRows(snapshot.active, dirty, replacements.filter(isActive));
618
+ if (!numbers.every(Number.isSafeInteger)) {
619
+ snapshot.fallback = undefined;
620
+ } else if (snapshot.fallback) {
621
+ snapshot.fallback = [
622
+ ...snapshot.fallback.filter((row) => !dirty.has(row.tag_number)),
623
+ ...fallbackRowsByNumbers.all(sessionId, JSON.stringify(numbers))
624
+ ];
625
+ }
626
+ }
627
+ snapshot.revision = local;
628
+ }
629
+ if (stamp.durable - snapshot.durableVersion !== stamp.own - snapshot.ownVersion) {
630
+ snapshot.fallback = undefined;
631
+ snapshot.legacyFallback = true;
632
+ }
633
+ snapshot.durableVersion = stamp.durable;
634
+ snapshot.ownVersion = stamp.own;
635
+ clearChanged.run(sessionId);
636
+ return snapshot;
637
+ };
638
+ const read = (sessionId, borrowed = false) => {
639
+ const snapshot = sync(sessionId);
640
+ if (!snapshot && managed.has(sessionId))
641
+ throw new PiTagHydrationError("managed snapshot read inside a transaction");
642
+ if (!snapshot)
643
+ return getTagsBySession2(db, sessionId);
644
+ return borrowed ? snapshot.tags : snapshot.tags.map((tag) => ({ ...tag }));
645
+ };
646
+ entryReaders.set(db, sync);
647
+ fallbackReaders.set(db, (sessionId) => {
648
+ const snapshot = sync(sessionId);
649
+ if (!snapshot)
650
+ return null;
651
+ if (!snapshot.fallback && managed.has(sessionId))
652
+ throw new PiTagHydrationError("fallback snapshot is not ready; turn not sent, retry");
653
+ snapshot.fallback ??= fallbackRows.all(sessionId);
654
+ return snapshot.fallback;
655
+ });
656
+ readers.set(db, read);
657
+ const close = db.close.bind(db);
658
+ Object.defineProperty(db, "close", {
659
+ configurable: true,
660
+ writable: true,
661
+ value: (...args) => {
662
+ desiredSession = undefined;
663
+ current?.cancel();
664
+ cache.clear();
665
+ entryReaders.delete(db);
666
+ fallbackReaders.delete(db);
667
+ readers.delete(db);
668
+ revisionReaders.delete(db);
669
+ owners.delete(db);
670
+ workerFactories.delete(db);
671
+ return close(...args);
672
+ }
673
+ });
674
+ return read;
675
+ }
676
+ var PI_FALLBACK_ROW_COLUMNS = "id, tag_number, type, message_id, tool_owner_message_id, entry_fingerprint";
677
+ var PI_FALLBACK_ROW_PREDICATE = `((type = 'message' AND message_id LIKE 'pi-msg-%')
678
+ OR (type = 'tool' AND tool_owner_message_id LIKE 'pi-msg-%'))`;
679
+ var isActive = (tag) => tag.status === "active";
680
+ function sameRow(left, right, keys) {
681
+ for (const key of keys)
682
+ if (!Object.is(left[key], right[key]))
683
+ return false;
684
+ return true;
685
+ }
686
+ function samePiTagSnapshotToken(left, right) {
687
+ return left.connectionEpoch === right.connectionEpoch && left.sessionEpoch === right.sessionEpoch && left.jobId === right.jobId && left.sessionId === right.sessionId && left.localRevision === right.localRevision && left.foreignRevision === right.foreignRevision && left.durableVersion === right.durableVersion && left.ownVersion === right.ownVersion && left.dataVersion === right.dataVersion;
688
+ }
689
+ function candidateRowBytes(row, overhead) {
690
+ let bytes = overhead;
691
+ for (const value of Object.values(row)) {
692
+ if (typeof value === "string")
693
+ bytes += 24 + value.length * 2;
694
+ else if (value instanceof Uint8Array)
695
+ bytes += 24 + value.byteLength;
696
+ }
697
+ return bytes;
698
+ }
699
+ function createPiTagSnapshotCandidate(cached = [], byteLimit = 128 * 1024 * 1024) {
700
+ const tags = [];
701
+ const active = [];
702
+ const fallback = [];
703
+ let estimatedBytes = 192;
704
+ let oldIndex = 0;
705
+ let keys;
706
+ let tagsEnded = false;
707
+ let fallbackEnded = false;
708
+ let failed = false;
709
+ const reject = (reason) => {
710
+ failed = true;
711
+ throw new Error(`Pi tag hydration: ${reason}`);
712
+ };
713
+ const admit = (row, overhead) => {
714
+ estimatedBytes += candidateRowBytes(row, overhead);
715
+ if (estimatedBytes > byteLimit)
716
+ reject("candidate memory limit exceeded");
717
+ };
718
+ return {
719
+ get estimatedBytes() {
720
+ return estimatedBytes;
721
+ },
722
+ appendTag(row) {
723
+ if (failed || tagsEnded)
724
+ reject("tag packet after end or failure");
725
+ const previous = tags.at(-1);
726
+ if (previous && (previous.tagNumber > row.tagNumber || previous.tagNumber === row.tagNumber && (previous.id ?? 0) >= (row.id ?? 0)))
727
+ reject("noncanonical tag order");
728
+ admit(row, 384);
729
+ keys ??= Object.keys(row);
730
+ while (oldIndex < cached.length) {
731
+ const old = cached[oldIndex];
732
+ if (!old || old.tagNumber > row.tagNumber || old.tagNumber === row.tagNumber && (old.id ?? 0) >= (row.id ?? 0))
733
+ break;
734
+ oldIndex += 1;
735
+ }
736
+ const old = cached[oldIndex];
737
+ const selected = old && old.id === row.id && sameRow(old, row, keys) ? old : row;
738
+ Object.freeze(selected);
739
+ tags.push(selected);
740
+ if (isActive(selected))
741
+ active.push(selected);
742
+ },
743
+ appendFallback(row) {
744
+ if (failed || fallbackEnded)
745
+ reject("fallback packet after end or failure");
746
+ admit(row, 192);
747
+ fallback.push(Object.freeze(row));
748
+ },
749
+ end(stream) {
750
+ if (failed)
751
+ reject("end after failure");
752
+ if (stream === "tags") {
753
+ if (tagsEnded)
754
+ reject("duplicate tag end");
755
+ tagsEnded = true;
756
+ } else {
757
+ if (fallbackEnded)
758
+ reject("duplicate fallback end");
759
+ fallbackEnded = true;
760
+ }
761
+ },
762
+ finish() {
763
+ if (failed || !tagsEnded || !fallbackEnded)
764
+ throw new Error("Pi tag hydration: incomplete candidate");
765
+ return { tags, active, fallback, estimatedBytes };
766
+ }
767
+ };
768
+ }
769
+ function reuseUnchangedRows(cached, fresh) {
770
+ const first = fresh[0];
771
+ if (!first)
772
+ return fresh;
773
+ const keys = Object.keys(first);
774
+ let index = 0;
775
+ for (let position = 0;position < fresh.length; position += 1) {
776
+ const row = fresh[position];
777
+ if (!row)
778
+ continue;
779
+ while (index < cached.length) {
780
+ const old = cached[index];
781
+ if (!old || old.tagNumber > row.tagNumber || old.tagNumber === row.tagNumber && (old.id ?? 0) >= (row.id ?? 0))
782
+ break;
783
+ index += 1;
784
+ }
785
+ const old = cached[index];
786
+ if (old && old.id === row.id && sameRow(old, row, keys))
787
+ fresh[position] = old;
788
+ }
789
+ return fresh;
790
+ }
791
+ function mergeChangedRows(rows, dirty, replacements) {
792
+ const highest = rows.at(-1)?.tagNumber ?? -1;
793
+ let appendOnly = true;
794
+ for (const number of dirty) {
795
+ if (number <= highest) {
796
+ appendOnly = false;
797
+ break;
798
+ }
799
+ }
800
+ if (appendOnly)
801
+ return [...rows, ...replacements];
802
+ const unchanged = rows.filter((tag) => !dirty.has(tag.tagNumber));
803
+ const merged = [];
804
+ let index = 0;
805
+ for (const tag of unchanged) {
806
+ while (index < replacements.length) {
807
+ const next = replacements[index];
808
+ if (!next)
809
+ break;
810
+ if (next.tagNumber > tag.tagNumber || next.tagNumber === tag.tagNumber && (next.id ?? 0) > (tag.id ?? 0))
811
+ break;
812
+ merged.push(next);
813
+ index += 1;
814
+ }
815
+ merged.push(tag);
816
+ }
817
+ merged.push(...replacements.slice(index));
818
+ return merged;
819
+ }
820
+ var entryReaders = new WeakMap;
821
+ var fallbackReaders = new WeakMap;
822
+ var readers = new WeakMap;
823
+ var revisionReaders = new WeakMap;
824
+ function getPiTagSnapshotView(db, sessionId) {
825
+ return createPiTagSnapshotReader(db)(sessionId, true);
826
+ }
827
+ function getPiActiveTagSnapshotView(db, sessionId, passTags) {
828
+ createPiTagSnapshotReader(db);
829
+ const snapshot = entryReaders.get(db)?.(sessionId);
830
+ if (snapshot && (!passTags || snapshot.tags === passTags))
831
+ return snapshot.active.slice();
832
+ return (passTags ?? getTagsBySession2(db, sessionId)).filter(isActive);
833
+ }
834
+ function readPiFallbackTagRows(db, sessionId) {
835
+ createPiTagSnapshotReader(db);
836
+ return fallbackReaders.get(db)?.(sessionId) ?? null;
837
+ }
838
+ var connectionEpoch = 0;
839
+ var owners = new WeakMap;
840
+ var workerFactories = new WeakMap;
841
+ var activeJobs = new Map;
842
+ var waitDeadlines = new WeakMap;
843
+ function prewarmPiTagSnapshot(db, sessionId) {
844
+ createPiTagSnapshotReader(db);
845
+ owners.get(db)?.load(sessionId).catch(() => {});
846
+ }
847
+ function cancelPiTagSnapshotSession(sessionId) {
848
+ for (const job of activeJobs.get(sessionId) ?? [])
849
+ job.cancel(sessionId);
850
+ }
851
+ async function drainPiTagSnapshotSession(sessionId) {
852
+ await Promise.allSettled([...activeJobs.get(sessionId) ?? []].flatMap((job) => [
853
+ job.result,
854
+ job.released
855
+ ]));
856
+ }
857
+ function assertPiTagSnapshotReady(db, sessionId) {
858
+ createPiTagSnapshotReader(db);
859
+ const owner = owners.get(db);
860
+ owner?.manage(sessionId);
861
+ if (!owner?.ready(sessionId))
862
+ throw new PiTagHydrationError("tag snapshot is not ready; turn not sent, retry");
863
+ }
864
+ function ensurePiTagSnapshotReady(db, sessionId, budget) {
865
+ budget.assert();
866
+ createPiTagSnapshotReader(db);
867
+ const owner = owners.get(db);
868
+ if (!owner)
869
+ throw new PiTagHydrationError("snapshot owner unavailable");
870
+ owner.manage(sessionId);
871
+ if (owner.ready(sessionId))
872
+ return;
873
+ let deadline = waitDeadlines.get(budget);
874
+ if (deadline === undefined) {
875
+ deadline = performance.now() + budget.hydrationAllowance();
876
+ waitDeadlines.set(budget, deadline);
877
+ }
878
+ const end = deadline;
879
+ return (async () => {
880
+ for (let attempt = 0;attempt < 2; attempt++) {
881
+ budget.assert();
882
+ const allowance = Math.min(end - performance.now(), budget.hydrationAllowance());
883
+ if (allowance <= 0)
884
+ throw new PiTagHydrationError("remaining pass budget exhausted waiting for tag snapshot; turn not sent, retry", "deadline");
885
+ let timer;
886
+ try {
887
+ await budget.wait(Promise.race([
888
+ owner.load(sessionId),
889
+ new Promise((_, reject) => {
890
+ timer = setTimeout(() => reject(new PiTagHydrationError("remaining pass budget exhausted waiting for tag snapshot; turn not sent, retry", "deadline")), allowance);
891
+ })
892
+ ]));
893
+ budget.assert();
894
+ assertPiTagSnapshotReady(db, sessionId);
895
+ return;
896
+ } catch (error) {
897
+ budget.assert();
898
+ if (!(error instanceof PiTagHydrationError && error.code === "stale" && attempt === 0))
899
+ throw error;
900
+ } finally {
901
+ clearTimeout(timer);
902
+ }
903
+ }
904
+ })();
905
+ }
906
+
907
+ export { encodePiHydrationOperation, PiTagHydrationError, PI_FALLBACK_ROW_COLUMNS, PI_FALLBACK_ROW_PREDICATE, getPiTagSnapshotView, getPiActiveTagSnapshotView, readPiFallbackTagRows, prewarmPiTagSnapshot, cancelPiTagSnapshotSession, drainPiTagSnapshotSession, assertPiTagSnapshotReady, ensurePiTagSnapshotReady };