@cortexkit/pi-magic-context 0.47.0 → 0.49.0

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 (60) hide show
  1. package/dist/auto-search-worker.js +27 -22
  2. package/dist/embedding-activity-ew6dshfd.js +10 -0
  3. package/dist/embedding-backfill-b71dvfs8.js +20 -0
  4. package/dist/embedding-cache-7rp4gqzr.js +16 -0
  5. package/dist/embedding-worker.js +11 -8
  6. package/dist/harness-9872e0ym.js +10 -0
  7. package/dist/historian-calibration-extension.js +30 -4
  8. package/dist/index-041ex0cj.js +519 -0
  9. package/dist/index-0h2mkab2.js +17 -0
  10. package/dist/{index-2p1e8706.js → index-0vrkp1jq.js} +3 -3
  11. package/dist/index-135e8hvg.js +43 -0
  12. package/dist/{index-vgcemg0n.js → index-1evzceyw.js} +151 -2452
  13. package/dist/index-21v1kfs7.js +2309 -0
  14. package/dist/{index-n3g5mwa8.js → index-290tzwp1.js} +3 -3
  15. package/dist/{index-0qejsd7f.js → index-3cgbv47m.js} +289 -45
  16. package/dist/{index-xpbh1ypk.js → index-3mgf68pn.js} +38 -741
  17. package/dist/index-3rea6zd9.js +2396 -0
  18. package/dist/index-674f6qs2.js +16 -0
  19. package/dist/index-8976mezv.js +209 -0
  20. package/dist/index-904reqtg.js +152 -0
  21. package/dist/index-9p40dgkm.js +22 -0
  22. package/dist/index-9x1f96r8.js +11 -0
  23. package/dist/index-bejpsj10.js +1060 -0
  24. package/dist/{index-spk5vrhy.js → index-bgmv2kaf.js} +1 -16
  25. package/dist/{index-k3ezsjng.js → index-ehybv5nr.js} +14657 -13951
  26. package/dist/index-fapenpch.js +13 -0
  27. package/dist/index-hwqb3s7f.js +3804 -0
  28. package/dist/index-kjd1fj55.js +3106 -0
  29. package/dist/{index-td885aah.js → index-mcgehvgw.js} +181 -230
  30. package/dist/index-r024r8da.js +171 -0
  31. package/dist/{index-266qrgss.js → index-r56xgha8.js} +301 -27
  32. package/dist/{index-kztsbkqq.js → index-t7xfqtg6.js} +171 -168
  33. package/dist/index-vakawmbc.js +1262 -0
  34. package/dist/{index-7n8gb6j3.js → index-x3dcnxh0.js} +34 -33
  35. package/dist/index-xjqheg7a.js +931 -0
  36. package/dist/index-yarjn32j.js +3026 -0
  37. package/dist/index-yhzhdp3m.js +143 -0
  38. package/dist/index-yzcjxnt2.js +787 -0
  39. package/dist/{index-w76x3af7.js → index-zh1jw8qp.js} +107 -4
  40. package/dist/index.js +4926 -2437
  41. package/dist/logger-j6tecd1h.js +19 -0
  42. package/dist/message-index-bounded-qz5dz2se.js +120 -0
  43. package/dist/{message-time-backfill-d3db2etr.js → message-time-backfill-05ppypkz.js} +7 -6
  44. package/dist/migration-worker.js +20 -14
  45. package/dist/project-embedding-registry-ky7wrkr1.js +85 -0
  46. package/dist/raw-ordinal-warmup-worker.js +60 -0
  47. package/dist/{read-session-chunk-atxsyfqv.js → read-session-chunk-24sd89tf.js} +14 -6
  48. package/dist/read-session-raw-npx3920c.js +57 -0
  49. package/dist/{safe-notification-target-6cn3z99t.js → safe-notification-target-vn9kpmv4.js} +3 -2
  50. package/dist/search-jbh28nwy.js +40 -0
  51. package/dist/sqlite-3yye76ht.js +44 -0
  52. package/dist/sqlite-context-pragmas-gcgch6qz.js +6 -0
  53. package/dist/storage-memory-1z20y55x.js +71 -0
  54. package/dist/storage-tags-kjnsqbdb.js +127 -0
  55. package/dist/subagent-entry.js +35 -17
  56. package/dist/transformers-node-wasm.js +18415 -18415
  57. package/package.json +3 -3
  58. package/dist/index-7s8vw2y0.js +0 -5207
  59. package/dist/index-qaa5j277.js +0 -8544
  60. /package/dist/{index-en1k8h8m.js → index-5prbx026.js} +0 -0
@@ -1,6 +1,54 @@
1
1
  import {
2
- sessionLog
3
- } from "./index-7n8gb6j3.js";
2
+ sessionLog2
3
+ } from "./index-x3dcnxh0.js";
4
+
5
+ // ../plugin/src/shared/stable-json.ts
6
+ function stableStringify(value, seen = new WeakSet) {
7
+ const pieces = [];
8
+ writeStable(value, seen, pieces);
9
+ return pieces.join("");
10
+ }
11
+ function writeStable(value, seen, pieces) {
12
+ if (value === undefined) {
13
+ pieces.push("undefined");
14
+ return;
15
+ }
16
+ if (value === null || typeof value !== "object") {
17
+ pieces.push(JSON.stringify(value) ?? String(value));
18
+ return;
19
+ }
20
+ if (seen.has(value)) {
21
+ pieces.push('"[Circular]"');
22
+ return;
23
+ }
24
+ seen.add(value);
25
+ if (Array.isArray(value)) {
26
+ pieces.push("[");
27
+ for (let index = 0;index < value.length; index += 1) {
28
+ if (index > 0)
29
+ pieces.push(",");
30
+ if (index in value)
31
+ writeStable(value[index], seen, pieces);
32
+ }
33
+ pieces.push("]");
34
+ return;
35
+ }
36
+ const entries = Object.entries(value).sort(([a], [b]) => {
37
+ if (a < b)
38
+ return -1;
39
+ if (a > b)
40
+ return 1;
41
+ return 0;
42
+ });
43
+ pieces.push("{");
44
+ entries.forEach(([key, child], index) => {
45
+ if (index > 0)
46
+ pieces.push(",");
47
+ pieces.push(JSON.stringify(key), ":");
48
+ writeStable(child, seen, pieces);
49
+ });
50
+ pieces.push("}");
51
+ }
4
52
 
5
53
  // ../plugin/src/shared/sqlite-helpers.ts
6
54
  function closeQuietly(db) {
@@ -19,28 +67,6 @@ function isKnownAutocommit(db) {
19
67
  }
20
68
  }
21
69
 
22
- // ../plugin/src/shared/stable-json.ts
23
- function stableStringify(value, seen = new WeakSet) {
24
- if (value === undefined)
25
- return "undefined";
26
- if (value === null || typeof value !== "object")
27
- return JSON.stringify(value) ?? String(value);
28
- if (seen.has(value))
29
- return '"[Circular]"';
30
- seen.add(value);
31
- if (Array.isArray(value)) {
32
- return `[${value.map((item) => stableStringify(item, seen)).join(",")}]`;
33
- }
34
- const entries = Object.entries(value).sort(([a], [b]) => {
35
- if (a < b)
36
- return -1;
37
- if (a > b)
38
- return 1;
39
- return 0;
40
- });
41
- return `{${entries.map(([key, child]) => `${JSON.stringify(key)}:${stableStringify(child, seen)}`).join(",")}}`;
42
- }
43
-
44
70
  // ../plugin/src/features/magic-context/storage-schema-helpers.ts
45
71
  var columnCaches = new WeakMap;
46
72
  function readColumnNames(db, table) {
@@ -313,11 +339,11 @@ function installV95PerfSchema(db, verifyExistingMap = false, allowCreateMap = tr
313
339
  try {
314
340
  entries = JSON.parse(row.entries);
315
341
  } catch {
316
- sessionLog(row.session_id, "v95 temporal metadata: malformed JSON skipped; original blob retained");
342
+ sessionLog2(row.session_id, "v95 temporal metadata: malformed JSON skipped; original blob retained");
317
343
  continue;
318
344
  }
319
345
  if (!Array.isArray(entries)) {
320
- sessionLog(row.session_id, "v95 temporal metadata: non-array JSON skipped; original blob retained");
346
+ sessionLog2(row.session_id, "v95 temporal metadata: non-array JSON skipped; original blob retained");
321
347
  continue;
322
348
  }
323
349
  const kept = [];
@@ -364,213 +390,138 @@ function installV95PerfSchema(db, verifyExistingMap = false, allowCreateMap = tr
364
390
  }
365
391
  }
366
392
  var tagOrderIndexes = new WeakMap;
367
-
368
- // ../plugin/src/shared/opencode-db-path.ts
369
- import { existsSync, readdirSync, statSync } from "node:fs";
370
- import { homedir } from "node:os";
371
- import { isAbsolute, join, resolve } from "node:path";
372
- var cachedResolution = null;
373
- var lastReadFailure = null;
374
- var claimedDiagnostics = new Set;
375
- function openCodeDataDir(env = process.env, dataHome) {
376
- return join(dataHome ?? env.XDG_DATA_HOME ?? join(homedir(), ".local", "share"), "opencode");
377
- }
378
- function environmentKey(dataDir, hostGeneration, channel, env) {
379
- return [
380
- hostGeneration,
381
- dataDir,
382
- env.OPENCODE_DB ?? "",
383
- env.OPENCODE_DISABLE_CHANNEL_DB ?? "",
384
- channel ?? env.OPENCODE_CHANNEL ?? ""
385
- ].join("\x00");
386
- }
387
- function channelPath(dataDir, channel) {
388
- return ["latest", "beta", "prod"].includes(channel) ? join(dataDir, "opencode.db") : join(dataDir, `opencode-${channel}.db`);
389
- }
390
- function discoveredCandidateNames(dataDir) {
391
- const names = ["opencode.db", "opencode-local.db", "opencode-dev.db"];
392
- try {
393
- const discovered = readdirSync(dataDir, { withFileTypes: true }).filter((entry) => /^opencode-.+\.db$/.test(entry.name) && !names.includes(entry.name)).map((entry) => entry.name).sort();
394
- names.push(...discovered);
395
- } catch {}
396
- return names;
397
- }
398
- function discoverOpenCodeDb(dataDir) {
399
- const candidates = discoveredCandidateNames(dataDir).map((name, order) => {
400
- const path = join(dataDir, name);
401
- try {
402
- const metadata = statSync(path);
403
- return metadata.isFile() ? { path, order, mtimeMs: metadata.mtimeMs } : null;
404
- } catch {
405
- return null;
406
- }
407
- });
408
- const existing = candidates.filter((candidate) => candidate !== null).sort((left, right) => right.mtimeMs - left.mtimeMs || left.order - right.order)[0];
409
- if (!existing) {
410
- return { path: join(dataDir, "opencode.db"), source: "default", channel: null };
411
- }
412
- const name = existing.path.slice(dataDir.length + 1);
413
- const channel = name === "opencode.db" ? null : name.slice("opencode-".length, -".db".length) || null;
414
- return { path: existing.path, source: "discovered", channel };
415
- }
416
- function resolveV1Fresh(dataDir, env = process.env) {
417
- const explicit = env.OPENCODE_DB;
418
- if (explicit !== undefined && explicit.length > 0) {
419
- if (explicit === ":memory:") {
420
- return { path: explicit, source: "OPENCODE_DB", channel: null };
421
- }
422
- return {
423
- path: isAbsolute(explicit) ? explicit : join(dataDir, explicit),
424
- source: "OPENCODE_DB",
425
- channel: null
426
- };
427
- }
428
- const disableChannelDb = env.OPENCODE_DISABLE_CHANNEL_DB;
429
- if (disableChannelDb === "1" || disableChannelDb === "true") {
430
- return { path: join(dataDir, "opencode.db"), source: "default", channel: null };
431
- }
432
- const channel = env.OPENCODE_CHANNEL;
433
- if (channel !== undefined && channel.length > 0) {
434
- return { path: channelPath(dataDir, channel), source: "channel", channel };
435
- }
436
- return discoverOpenCodeDb(dataDir);
437
- }
438
- function sourceOpenCodeDatabaseFilename(hostGeneration, channel, env = process.env) {
439
- if (hostGeneration === "v1") {
440
- const explicit = env.OPENCODE_DB;
441
- if (explicit !== undefined && explicit.length > 0)
442
- return explicit;
443
- if (env.OPENCODE_DISABLE_CHANNEL_DB === "1" || env.OPENCODE_DISABLE_CHANNEL_DB === "true") {
444
- return "opencode.db";
445
- }
446
- return ["latest", "beta", "prod"].includes(channel) ? "opencode.db" : `opencode-${channel}.db`;
447
- }
448
- return env.OPENCODE_DB ?? (["latest", "dev", "beta", "next", "prod"].includes(channel) || env.OPENCODE_DISABLE_CHANNEL_DB === "1" || env.OPENCODE_DISABLE_CHANNEL_DB === "true" ? "opencode.db" : `opencode-${channel.replace(/[^a-zA-Z0-9._-]/g, "")}.db`);
449
- }
450
- function resolveV2Fresh(dataDir, channel, env) {
451
- const filename = sourceOpenCodeDatabaseFilename("v2", channel, env);
452
- const explicit = env.OPENCODE_DB !== undefined;
453
- return {
454
- path: filename === ":memory:" ? filename : resolve(dataDir, filename),
455
- source: explicit ? "OPENCODE_DB" : env.OPENCODE_CHANNEL ? "channel" : "default",
456
- channel: explicit ? null : channel
457
- };
458
- }
459
- function resolveOpenCodeDbPath(hostGeneration = "v1", options = {}) {
460
- const env = options.env ?? process.env;
461
- const dataDir = openCodeDataDir(env, options.dataHome);
462
- const channel = options.channel ?? env.OPENCODE_CHANNEL;
463
- const key = environmentKey(dataDir, hostGeneration, channel, env);
464
- if (cachedResolution?.key === key && (!cachedResolution.existed || existsSync(cachedResolution.resolution.path))) {
465
- if (cachedResolution.existed)
466
- return cachedResolution.resolution;
467
- }
468
- const resolution = hostGeneration === "v2" ? resolveV2Fresh(dataDir, channel ?? "latest", env) : resolveV1Fresh(dataDir, env);
469
- cachedResolution = {
470
- key,
471
- resolution,
472
- existed: resolution.path !== ":memory:" && existsSync(resolution.path)
473
- };
474
- return resolution;
475
- }
476
- function schemaTableNames(db, schema = "main") {
477
- const rows = db.prepare(`SELECT name FROM ${schema}.sqlite_master WHERE type = 'table' AND name IN ('message', 'part', 'session', 'project', 'session_message', 'session_v2')`).all();
478
- return new Set(rows.flatMap((row) => typeof row.name === "string" ? [row.name] : []));
479
- }
480
- function hasV1MessageTables(db, schema = "main") {
481
- const tables = schemaTableNames(db, schema);
482
- return tables.has("message") && tables.has("part");
483
- }
484
- function detectOpenCodeStoreGeneration(db, schema = "main") {
485
- const tables = schemaTableNames(db, schema);
486
- const hasV1Messages = tables.has("message") && tables.has("part");
487
- if (hasV1Messages)
488
- return "v1";
489
- if (tables.has("session_message"))
490
- return "v2";
491
- if (tables.has("session") || tables.has("project"))
492
- return "v1";
493
- return "unknown";
494
- }
495
- function hasMigratedV2Schema(tables) {
496
- return tables.has("session_message") && tables.has("session_v2");
497
- }
498
- function isOpenCodeV2Store(db, schema = "main") {
499
- return detectOpenCodeStoreGeneration(db, schema) === "v2" || hasMigratedV2Schema(schemaTableNames(db, schema));
500
- }
501
- function assertOpenCodeStoreGeneration(db, expected, path, schema = "main") {
502
- const actual = detectOpenCodeStoreGeneration(db, schema);
503
- if (actual === expected)
504
- return;
505
- if (expected === "v2" && isOpenCodeV2Store(db, schema))
506
- return;
507
- if (actual === "unknown")
508
- return;
509
- throw new Error(`OpenCode store generation mismatch at ${path}: expected ${expected}, found ${actual}; refusing generation-specific database access`);
510
- }
511
- function openCodeDbPathExists(resolution = resolveOpenCodeDbPath()) {
512
- return resolution.path !== ":memory:" && existsSync(resolution.path);
513
- }
514
- function getOpenCodeDbProbeDescriptions(resolution = resolveOpenCodeDbPath()) {
515
- if (resolution.source === "OPENCODE_DB")
516
- return [resolution.path];
517
- if (resolution.source === "channel" || process.env.OPENCODE_DISABLE_CHANNEL_DB === "1" || process.env.OPENCODE_DISABLE_CHANNEL_DB === "true") {
518
- return [resolution.path];
393
+ function tagOrderConstraintIndex(db) {
394
+ const version = db.prepare("PRAGMA schema_version").get().schema_version;
395
+ const cacheable = isKnownAutocommit(db);
396
+ if (!cacheable)
397
+ tagOrderIndexes.delete(db);
398
+ const cached = tagOrderIndexes.get(db);
399
+ if (cached?.schemaVersion === version)
400
+ return cached.name;
401
+ const candidates = db.prepare("PRAGMA index_list(tags)").all();
402
+ for (const candidate of candidates) {
403
+ if (!candidate.unique || candidate.origin !== "u")
404
+ continue;
405
+ const quoted = `"${candidate.name.replaceAll('"', '""')}"`;
406
+ const columns = db.prepare(`PRAGMA index_info(${quoted})`).all();
407
+ if (columns.length !== 2 || columns[0]?.name !== "session_id" || columns[1]?.name !== "tag_number")
408
+ continue;
409
+ if (cacheable)
410
+ tagOrderIndexes.set(db, { schemaVersion: version, name: quoted });
411
+ return quoted;
519
412
  }
520
- const dataDir = openCodeDataDir();
521
- return [
522
- join(dataDir, "opencode.db"),
523
- join(dataDir, "opencode-local.db"),
524
- join(dataDir, "opencode-dev.db"),
525
- join(dataDir, "opencode-<channel>.db")
526
- ];
527
- }
528
- function recordOpenCodeDbReadFailure(resolution, error) {
529
- const message = error instanceof Error ? error.message : String(error);
530
- lastReadFailure = { ...resolution, message };
531
- return lastReadFailure;
532
- }
533
- function clearOpenCodeDbReadFailure(path) {
534
- if (path === undefined || lastReadFailure?.path === path)
535
- lastReadFailure = null;
536
- }
537
- function claimOpenCodeDbDiagnosticOnce(surface, resolution) {
538
- const key = `${surface}\x00${resolution.path}\x00${resolution.source}`;
539
- if (claimedDiagnostics.has(key))
540
- return false;
541
- claimedDiagnostics.add(key);
542
- return true;
413
+ throw new Error("tags lacks its UNIQUE(session_id, tag_number) ordering constraint");
543
414
  }
544
415
 
545
- // ../plugin/src/features/magic-context/tool-definition-tokens.ts
546
- var measurements = new Map;
547
- var fingerprints = new Map;
548
- var persistenceDb = null;
549
- var cachedInsertStmt = null;
550
- function keyFor(providerID, modelID, agentName) {
551
- const agent = agentName && agentName.length > 0 ? agentName : "default";
552
- return `${providerID}/${modelID}/${agent}`;
553
- }
554
- function setDatabase(db) {
555
- persistenceDb = db;
556
- cachedInsertStmt = null;
557
- }
558
- function loadToolDefinitionMeasurements(db) {
559
- let rows = [];
560
- try {
561
- rows = db.prepare("SELECT provider_id, model_id, agent_name, tool_id, token_count FROM tool_definition_measurements").all();
562
- } catch {
563
- return;
564
- }
565
- for (const row of rows) {
566
- const key = keyFor(row.provider_id, row.model_id, row.agent_name);
567
- let inner = measurements.get(key);
568
- if (!inner) {
569
- inner = new Map;
570
- measurements.set(key, inner);
571
- }
572
- inner.set(row.tool_id, row.token_count);
416
+ // ../plugin/src/features/magic-context/storage-tag-identity-revision.ts
417
+ var TAG_IDENTITY_REVISION_PREFIX = "tag_identity_revision:";
418
+ var TAG_REVISION_PREFIX = "tag_revision:";
419
+ var TAG_TOMBSTONE_OWNER_PREFIX = "tag_revision_owner:";
420
+ var TAG_REVISION_INCARNATION_KEY = "tag_revision_incarnation";
421
+ var tagRevisionIncarnationSql = (value) => `CASE WHEN INSTR(${value}, ':') > 0 THEN SUBSTR(${value}, 1, INSTR(${value}, ':') - 1) ELSE '0' END`;
422
+ var tagRevisionCountSql = (value) => `CAST(CASE WHEN INSTR(${value}, ':') > 0 THEN SUBSTR(${value}, INSTR(${value}, ':') + 1) ELSE ${value} END AS INTEGER)`;
423
+ var ADVANCE = (delta = "1") => `CASE
424
+ WHEN ${tagRevisionCountSql("value")} <= 9223372036854775807 - ${delta}
425
+ THEN (${tagRevisionIncarnationSql("value")}) || ':' || CAST(${tagRevisionCountSql("value")} + ${delta} AS TEXT)
426
+ ELSE NULL END`;
427
+ function tagTombstoneOwnerRange(sessionId) {
428
+ const stem = `${TAG_TOMBSTONE_OWNER_PREFIX}${JSON.stringify(sessionId)}`;
429
+ return [`${stem}:`, `${stem};`];
430
+ }
431
+ function tagTombstoneOwnerKey(sessionId, harness) {
432
+ return `${tagTombstoneOwnerRange(sessionId)[0]}${harness}`;
433
+ }
434
+ function tagRevisionKey(sessionId) {
435
+ return `${TAG_REVISION_PREFIX}${sessionId}`;
436
+ }
437
+ function tagIdentityRevisionKey(sessionId) {
438
+ return `${TAG_IDENTITY_REVISION_PREFIX}${sessionId}`;
439
+ }
440
+ var BUMP = (session, prefix = TAG_IDENTITY_REVISION_PREFIX) => `INSERT INTO schema_migrations_meta (key, value)
441
+ VALUES ('${prefix}' || ${session}, '1')
442
+ ON CONFLICT(key) DO UPDATE SET value = ${ADVANCE()}`;
443
+ var TAG_INSERT_CONFLICT_ROWS = `SELECT id, session_id, tag_number FROM tags WHERE id = NEW.id
444
+ UNION SELECT id, session_id, tag_number FROM tags WHERE session_id = NEW.session_id AND tag_number = NEW.tag_number
445
+ UNION SELECT id, session_id, tag_number FROM tags
446
+ WHERE NEW.type = 'tool' AND NEW.tool_owner_message_id IS NOT NULL
447
+ AND type = 'tool' AND tool_owner_message_id IS NOT NULL
448
+ AND session_id = NEW.session_id AND message_id = NEW.message_id
449
+ AND tool_owner_message_id = NEW.tool_owner_message_id`;
450
+ var BUMP_INSERT_CONFLICTS = (prefix) => `INSERT INTO schema_migrations_meta (key, value)
451
+ SELECT '${prefix}' || session_id, CAST(COUNT(*) AS TEXT)
452
+ FROM (${TAG_INSERT_CONFLICT_ROWS}) GROUP BY session_id
453
+ ON CONFLICT(key) DO UPDATE SET value = ${ADVANCE("CAST(excluded.value AS INTEGER)")}`;
454
+ var TRIGGER_SQL = `CREATE TEMP TRIGGER IF NOT EXISTS mc_tag_identity_revision_au
455
+ AFTER UPDATE OF id, session_id, message_id, tag_number, type, tool_owner_message_id, reasoning_token_count
456
+ ON main.tags
457
+ BEGIN
458
+ ${BUMP("OLD.session_id")};
459
+ INSERT INTO schema_migrations_meta (key, value)
460
+ SELECT '${TAG_IDENTITY_REVISION_PREFIX}' || NEW.session_id, '1'
461
+ WHERE NEW.session_id IS NOT OLD.session_id
462
+ ON CONFLICT(key) DO UPDATE SET value = ${ADVANCE()};
463
+ END`;
464
+ function installTagIdentityRevisionTrigger(db) {
465
+ db.exec(`DROP TRIGGER IF EXISTS temp.mc_tag_identity_revision_au;
466
+ DROP TRIGGER IF EXISTS temp.mc_tag_revision_bi;
467
+ DROP TRIGGER IF EXISTS temp.mc_tag_revision_ai;
468
+ DROP TRIGGER IF EXISTS temp.mc_tag_revision_au;
469
+ DROP TRIGGER IF EXISTS temp.mc_tag_revision_ad;
470
+ DROP TRIGGER IF EXISTS temp.mc_tag_revision_seed_ai;`);
471
+ db.exec(`CREATE TEMP TRIGGER mc_tag_revision_seed_ai AFTER INSERT ON main.schema_migrations_meta
472
+ WHEN INSTR(NEW.value, ':') = 0 AND (
473
+ SUBSTR(NEW.key, 1, ${TAG_REVISION_PREFIX.length}) = '${TAG_REVISION_PREFIX}'
474
+ OR SUBSTR(NEW.key, 1, ${TAG_IDENTITY_REVISION_PREFIX.length}) = '${TAG_IDENTITY_REVISION_PREFIX}')
475
+ BEGIN
476
+ INSERT INTO schema_migrations_meta (key, value) VALUES ('${TAG_REVISION_INCARNATION_KEY}', '1')
477
+ ON CONFLICT(key) DO UPDATE SET value = CAST(CASE
478
+ WHEN CAST(value AS INTEGER) < 9223372036854775807 THEN CAST(value AS INTEGER) + 1
479
+ ELSE NULL END AS TEXT);
480
+ UPDATE schema_migrations_meta SET value =
481
+ (SELECT value FROM schema_migrations_meta WHERE key = '${TAG_REVISION_INCARNATION_KEY}')
482
+ || ':' || CAST(NEW.value AS TEXT) WHERE key = NEW.key;
483
+ INSERT INTO schema_migrations_meta (key, value)
484
+ SELECT '${TAG_REVISION_INCARNATION_KEY}', '1'
485
+ WHERE SUBSTR(NEW.key, 1, ${TAG_REVISION_PREFIX.length}) = '${TAG_REVISION_PREFIX}'
486
+ AND NOT EXISTS (SELECT 1 FROM schema_migrations_meta
487
+ WHERE key = '${TAG_IDENTITY_REVISION_PREFIX}' || SUBSTR(NEW.key, ${TAG_REVISION_PREFIX.length + 1}))
488
+ ON CONFLICT(key) DO UPDATE SET value = CAST(CASE
489
+ WHEN CAST(value AS INTEGER) < 9223372036854775807 THEN CAST(value AS INTEGER) + 1
490
+ ELSE NULL END AS TEXT);
491
+ INSERT INTO schema_migrations_meta (key, value)
492
+ SELECT '${TAG_IDENTITY_REVISION_PREFIX}' || SUBSTR(NEW.key, ${TAG_REVISION_PREFIX.length + 1}),
493
+ (SELECT value FROM schema_migrations_meta WHERE key = '${TAG_REVISION_INCARNATION_KEY}') || ':0'
494
+ WHERE SUBSTR(NEW.key, 1, ${TAG_REVISION_PREFIX.length}) = '${TAG_REVISION_PREFIX}'
495
+ AND NOT EXISTS (SELECT 1 FROM schema_migrations_meta
496
+ WHERE key = '${TAG_IDENTITY_REVISION_PREFIX}' || SUBSTR(NEW.key, ${TAG_REVISION_PREFIX.length + 1}));
497
+ END;`);
498
+ db.exec(TRIGGER_SQL);
499
+ db.exec(`CREATE TEMP TRIGGER IF NOT EXISTS mc_tag_revision_bi BEFORE INSERT ON main.tags BEGIN
500
+ ${BUMP_INSERT_CONFLICTS(TAG_REVISION_PREFIX)};
501
+ ${BUMP_INSERT_CONFLICTS(TAG_IDENTITY_REVISION_PREFIX)};
502
+ UPDATE session_meta SET tags_version = tags_version + 1
503
+ WHERE session_id IN (SELECT session_id FROM (${TAG_INSERT_CONFLICT_ROWS}));
504
+ END;`);
505
+ db.exec(`CREATE TEMP TRIGGER IF NOT EXISTS mc_tag_revision_ai AFTER INSERT ON main.tags BEGIN
506
+ ${BUMP("NEW.session_id", TAG_REVISION_PREFIX)};
507
+ END;
508
+ CREATE TEMP TRIGGER IF NOT EXISTS mc_tag_revision_au AFTER UPDATE ON main.tags BEGIN
509
+ ${BUMP("OLD.session_id", TAG_REVISION_PREFIX)};
510
+ INSERT INTO schema_migrations_meta (key, value)
511
+ SELECT '${TAG_REVISION_PREFIX}' || NEW.session_id, '1'
512
+ WHERE NEW.session_id IS NOT OLD.session_id
513
+ ON CONFLICT(key) DO UPDATE SET value = ${ADVANCE()};
514
+ END;
515
+ CREATE TEMP TRIGGER IF NOT EXISTS mc_tag_revision_ad AFTER DELETE ON main.tags BEGIN
516
+ ${BUMP("OLD.session_id", TAG_REVISION_PREFIX)};
517
+ END;`);
518
+ }
519
+ function deleteTagIdentityRevisions(db, sessionIds) {
520
+ const statement = db.prepare(`INSERT INTO schema_migrations_meta (key, value) VALUES (?, '1')
521
+ ON CONFLICT(key) DO UPDATE SET value = ${ADVANCE()}`);
522
+ for (const sessionId of sessionIds) {
523
+ statement.run(tagIdentityRevisionKey(sessionId));
573
524
  }
574
525
  }
575
526
 
576
- export { stableStringify, closeQuietly, isKnownAutocommit, getTableColumnNames, ensureColumn, healAllNullColumns, observeTemporalDecisions, freezeTemporalDecisions, installV95PerfSchema, resolveOpenCodeDbPath, hasV1MessageTables, assertOpenCodeStoreGeneration, openCodeDbPathExists, getOpenCodeDbProbeDescriptions, recordOpenCodeDbReadFailure, clearOpenCodeDbReadFailure, claimOpenCodeDbDiagnosticOnce, setDatabase, loadToolDefinitionMeasurements };
527
+ export { stableStringify, closeQuietly, isKnownAutocommit, getTableColumnNames, ensureColumn, healAllNullColumns, observeTemporalDecisions, freezeTemporalDecisions, installV95PerfSchema, tagOrderConstraintIndex, TAG_TOMBSTONE_OWNER_PREFIX, tagRevisionIncarnationSql, tagRevisionCountSql, tagTombstoneOwnerRange, tagTombstoneOwnerKey, tagRevisionKey, tagIdentityRevisionKey, TAG_INSERT_CONFLICT_ROWS, installTagIdentityRevisionTrigger, deleteTagIdentityRevisions };
@@ -0,0 +1,171 @@
1
+ import {
2
+ withSqliteBackgroundWriter2,
3
+ withoutSqliteTransformPass2
4
+ } from "./index-3cgbv47m.js";
5
+ import {
6
+ logSlowWriteTransaction
7
+ } from "./index-0vrkp1jq.js";
8
+
9
+ // ../plugin/src/features/magic-context/message-fts-rowid-map.ts
10
+ import { createHash } from "node:crypto";
11
+ var MESSAGE_FTS_ROWID_MAP_BACKFILL_BATCH_SIZE = 100;
12
+ var BACKFILL_STATE_ID = 1;
13
+ var EMPTY_INDEX_CONTENT_HASH = createHash("sha256").update("").digest("hex");
14
+ var upsertMapStatements = new WeakMap;
15
+ var rangeReadyStatements = new WeakMap;
16
+ var updateTimeStatements = new WeakMap;
17
+ var activeBackfills = new WeakMap;
18
+ function getUpsertMapStatement(db) {
19
+ let statement = upsertMapStatements.get(db);
20
+ if (!statement) {
21
+ statement = db.prepare(`INSERT INTO message_fts_rowid_map
22
+ (session_id, message_ordinal, fts_rowid, message_time_ms)
23
+ VALUES (?, ?, ?, ?)
24
+ ON CONFLICT(session_id, message_ordinal) DO UPDATE SET
25
+ fts_rowid = excluded.fts_rowid,
26
+ message_time_ms = COALESCE(
27
+ excluded.message_time_ms,
28
+ message_fts_rowid_map.message_time_ms
29
+ )`);
30
+ upsertMapStatements.set(db, statement);
31
+ }
32
+ return statement;
33
+ }
34
+ function getBackfillState(db) {
35
+ const row = db.prepare(`SELECT watermark_rowid AS watermarkRowid, completed
36
+ FROM message_fts_rowid_map_backfill_state
37
+ WHERE id = ?`).get(BACKFILL_STATE_ID);
38
+ return {
39
+ processed: 0,
40
+ watermarkRowid: typeof row?.watermarkRowid === "number" && Number.isSafeInteger(row.watermarkRowid) ? row.watermarkRowid : 0,
41
+ completed: row?.completed === 1
42
+ };
43
+ }
44
+ function recordMessageFtsRowid(db, sessionId, messageOrdinal, ftsRowid, messageTimeMs = null) {
45
+ const numericRowid = Number(ftsRowid);
46
+ if (!Number.isSafeInteger(numericRowid) || numericRowid <= 0) {
47
+ throw new Error(`invalid message FTS rowid: ${String(ftsRowid)}`);
48
+ }
49
+ const normalizedTime = typeof messageTimeMs === "number" && Number.isSafeInteger(messageTimeMs) && messageTimeMs >= 0 ? messageTimeMs : null;
50
+ getUpsertMapStatement(db).run(sessionId, messageOrdinal, numericRowid, normalizedTime);
51
+ }
52
+ function recordIndexedMessageTime(db, sessionId, messageOrdinal, messageTimeMs) {
53
+ if (typeof messageTimeMs !== "number" || !Number.isSafeInteger(messageTimeMs) || messageTimeMs < 0) {
54
+ return;
55
+ }
56
+ let statement = updateTimeStatements.get(db);
57
+ if (!statement) {
58
+ statement = db.prepare(`UPDATE message_fts_rowid_map
59
+ SET message_time_ms = ?
60
+ WHERE session_id = ? AND message_ordinal = ?
61
+ AND message_time_ms IS NULL`);
62
+ updateTimeStatements.set(db, statement);
63
+ }
64
+ statement.run(messageTimeMs, sessionId, messageOrdinal);
65
+ }
66
+ function backfillMessageFtsRowidMapBatch(db, batchSize = MESSAGE_FTS_ROWID_MAP_BACKFILL_BATCH_SIZE) {
67
+ const boundedBatchSize = Number.isFinite(batchSize) ? Math.min(MESSAGE_FTS_ROWID_MAP_BACKFILL_BATCH_SIZE, Math.max(1, Math.floor(batchSize))) : MESSAGE_FTS_ROWID_MAP_BACKFILL_BATCH_SIZE;
68
+ let progress = {
69
+ processed: 0,
70
+ watermarkRowid: 0,
71
+ completed: false
72
+ };
73
+ let transactionStartedAt = 0;
74
+ db.transaction(() => {
75
+ transactionStartedAt = performance.now();
76
+ db.prepare(`INSERT OR IGNORE INTO message_fts_rowid_map_backfill_state
77
+ (id, watermark_rowid, completed) VALUES (?, 0, 0)`).run(BACKFILL_STATE_ID);
78
+ const state = getBackfillState(db);
79
+ if (state.completed) {
80
+ progress = state;
81
+ return;
82
+ }
83
+ const rows = db.prepare(`SELECT rowid AS ftsRowid,
84
+ session_id AS sessionId, message_ordinal AS messageOrdinal
85
+ FROM message_history_fts WHERE rowid > ? ORDER BY rowid ASC LIMIT ?`).all(state.watermarkRowid, boundedBatchSize);
86
+ let watermarkRowid = state.watermarkRowid;
87
+ for (const row of rows) {
88
+ const ftsRowid = Number(row.ftsRowid);
89
+ const messageOrdinal = Number(row.messageOrdinal);
90
+ if (Number.isSafeInteger(ftsRowid) && ftsRowid > watermarkRowid) {
91
+ watermarkRowid = ftsRowid;
92
+ }
93
+ if (typeof row.sessionId === "string" && Number.isSafeInteger(messageOrdinal) && messageOrdinal >= 0 && Number.isSafeInteger(ftsRowid) && ftsRowid > 0) {
94
+ recordMessageFtsRowid(db, row.sessionId, messageOrdinal, ftsRowid);
95
+ }
96
+ }
97
+ const completed = rows.length < boundedBatchSize;
98
+ db.prepare(`UPDATE message_fts_rowid_map_backfill_state
99
+ SET watermark_rowid = ?, completed = ?, updated_at = ?
100
+ WHERE id = ?`).run(watermarkRowid, completed ? 1 : 0, Date.now(), BACKFILL_STATE_ID);
101
+ progress = {
102
+ processed: rows.length,
103
+ watermarkRowid,
104
+ completed
105
+ };
106
+ }).immediate();
107
+ logSlowWriteTransaction("message_fts_rowid_backfill", transactionStartedAt);
108
+ return progress;
109
+ }
110
+ async function runMessageFtsRowidMapBackfill(db) {
111
+ await new Promise((resolve) => setTimeout(resolve, 0));
112
+ for (;; ) {
113
+ const progress = backfillMessageFtsRowidMapBatch(db);
114
+ if (progress.completed)
115
+ return;
116
+ await new Promise((resolve) => setTimeout(resolve, 0));
117
+ }
118
+ }
119
+ function startMessageFtsRowidMapBackfill(db) {
120
+ const active = activeBackfills.get(db);
121
+ if (active)
122
+ return active;
123
+ const run = withoutSqliteTransformPass2(() => withSqliteBackgroundWriter2(() => runMessageFtsRowidMapBackfill(db))).finally(() => {
124
+ activeBackfills.delete(db);
125
+ });
126
+ activeBackfills.set(db, run);
127
+ return run;
128
+ }
129
+ function messageFtsOrdinalRangeIsMapped(db, sessionId, startOrdinal, endOrdinal) {
130
+ if (endOrdinal < startOrdinal)
131
+ return true;
132
+ if (getBackfillState(db).completed)
133
+ return true;
134
+ let statement = rangeReadyStatements.get(db);
135
+ if (!statement) {
136
+ statement = db.prepare(`SELECT COUNT(DISTINCT source.message_ordinal) AS sourceOrdinalCount,
137
+ COUNT(DISTINCT CASE
138
+ WHEN source.role IN ('user', 'assistant')
139
+ AND source.normalized_content_hash != ?
140
+ THEN source.message_ordinal
141
+ END) AS expectedMapCount,
142
+ COUNT(DISTINCT CASE
143
+ WHEN source.role IN ('user', 'assistant')
144
+ AND source.normalized_content_hash != ?
145
+ AND map.fts_rowid IS NOT NULL
146
+ THEN source.message_ordinal
147
+ END) AS mappedCount
148
+ FROM message_history_source AS source
149
+ LEFT JOIN message_fts_rowid_map AS map
150
+ ON map.session_id = source.session_id
151
+ AND map.message_ordinal = source.message_ordinal
152
+ WHERE source.session_id = ?
153
+ AND source.message_ordinal BETWEEN ? AND ?`);
154
+ rangeReadyStatements.set(db, statement);
155
+ }
156
+ const row = statement.get(EMPTY_INDEX_CONTENT_HASH, EMPTY_INDEX_CONTENT_HASH, sessionId, startOrdinal, endOrdinal);
157
+ const ordinalCount = endOrdinal - startOrdinal + 1;
158
+ return row?.sourceOrdinalCount === ordinalCount && row.expectedMapCount === row.mappedCount;
159
+ }
160
+ function deleteUnmappedMessageFtsRows(db, sessionIds) {
161
+ if (sessionIds.length === 0)
162
+ return;
163
+ const state = getBackfillState(db);
164
+ if (state.completed)
165
+ return;
166
+ const placeholders = sessionIds.map(() => "?").join(", ");
167
+ db.prepare(`DELETE FROM message_history_fts
168
+ WHERE rowid > ? AND session_id IN (${placeholders})`).run(state.watermarkRowid, ...sessionIds);
169
+ }
170
+
171
+ export { recordMessageFtsRowid, recordIndexedMessageTime, startMessageFtsRowidMapBackfill, messageFtsOrdinalRangeIsMapped, deleteUnmappedMessageFtsRows };