@retaw106/mmc-pi 2.2.1 → 2.4.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.
package/dist/web/main.js CHANGED
@@ -381,8 +381,12 @@ function flush() {
381
381
  let currentSize = getCurrentLogSize(logFile);
382
382
  const dataSize = Buffer.byteLength(data);
383
383
  if (currentSize > 0 && currentSize + dataSize > MAX_LOG_FILE_BYTES) {
384
- rotateLogFile(logFile, currentSize);
385
- currentSize = 0;
384
+ flushesSinceSizeCheck = SIZE_CHECK_INTERVAL_FLUSHES;
385
+ currentSize = getCurrentLogSize(logFile);
386
+ if (currentSize > 0 && currentSize + dataSize > MAX_LOG_FILE_BYTES) {
387
+ rotateLogFile(logFile, currentSize);
388
+ currentSize = 0;
389
+ }
386
390
  }
387
391
  fs.appendFileSync(logFile, data, { encoding: "utf8", mode: 384 });
388
392
  buffer = [];
@@ -442,16 +446,21 @@ var init_logger = __esm(() => {
442
446
  });
443
447
 
444
448
  // ../plugin/src/shared/sqlite.ts
445
- import { AsyncLocalStorage } from "node:async_hooks";
449
+ import { AsyncLocalStorage, AsyncResource } from "node:async_hooks";
450
+ function inRootAsyncContext(operation) {
451
+ return resourceRoot.runInAsyncScope(operation);
452
+ }
446
453
  function registerSlowWriteReporter(reporter) {
447
454
  reportSlowPrivilegedWrite = reporter;
448
455
  }
449
- function registerSqliteDiagnosticSink(sink) {
456
+ function registerSqliteDiagnosticSink(sink, host) {
450
457
  sqliteDiagnosticSink = sink;
458
+ if (host)
459
+ sqliteDiagnosticHost = host;
451
460
  }
452
461
  function reportSqliteDiagnostic(message) {
453
462
  try {
454
- sqliteDiagnosticSink?.(`[magic-context] ${message}`);
463
+ sqliteDiagnosticSink?.(`[magic-context] ${message} pid=${process.pid} host=${sqliteDiagnosticHost()}`);
455
464
  } catch {}
456
465
  }
457
466
  function detectSqliteRuntime() {
@@ -473,10 +482,31 @@ function isModuleNotFoundError(error, specifier) {
473
482
  return false;
474
483
  return code === "ERR_MODULE_NOT_FOUND" || code === "ERR_UNKNOWN_BUILTIN_MODULE" || code === "MODULE_NOT_FOUND" || name === "ResolveMessage" || details.includes("module not found") || details.includes("cannot find module") || details.includes("cannot find package") || details.includes("no such built-in module");
475
484
  }
485
+ function isNodeSqliteExperimentalWarning(args) {
486
+ const [warning, options] = args;
487
+ const message = warning instanceof Error ? warning.message : warning;
488
+ const type = typeof options === "string" ? options : options && typeof options === "object" ? options.type : undefined;
489
+ return type === "ExperimentalWarning" && typeof message === "string" && message.startsWith("SQLite is an experimental feature");
490
+ }
491
+ async function importSqliteModuleForRuntime(runtime, specifier, importer) {
492
+ if (runtime !== "Node.js")
493
+ return importer(specifier);
494
+ const originalEmitWarning = process.emitWarning;
495
+ process.emitWarning = function(...args) {
496
+ if (isNodeSqliteExperimentalWarning(args))
497
+ return;
498
+ Reflect.apply(originalEmitWarning, this, args);
499
+ };
500
+ try {
501
+ return await importer(specifier);
502
+ } finally {
503
+ process.emitWarning = originalEmitWarning;
504
+ }
505
+ }
476
506
  async function loadSqliteModule(runtime = detectSqliteRuntime(), importer = importSqliteModule) {
477
507
  const specifier = runtime === "Bun" ? bunSpec : nodeSpec;
478
508
  try {
479
- return await importer(specifier);
509
+ return await importSqliteModuleForRuntime(runtime, specifier, importer);
480
510
  } catch (error) {
481
511
  if (isModuleNotFoundError(error, specifier)) {
482
512
  throw new SqliteRuntimeUnavailableError(runtime, specifier, error);
@@ -484,6 +514,64 @@ async function loadSqliteModule(runtime = detectSqliteRuntime(), importer = impo
484
514
  throw error;
485
515
  }
486
516
  }
517
+ function mayChangeTagIdentity(sql) {
518
+ if (!/\btags\b/i.test(sql) || /^\s*(?:SELECT|EXPLAIN|PRAGMA)\b/i.test(sql))
519
+ return false;
520
+ if (/^\s*WITH\b/i.test(sql) && !/\b(?:INSERT|UPDATE|DELETE|REPLACE)\b/i.test(sql))
521
+ return false;
522
+ if (/;\s*\S/.test(sql) || /\bREPLACE\b/i.test(sql) || /\bON\s+CONFLICT\b/i.test(sql))
523
+ return true;
524
+ const insert = /^\s*INSERT\s+INTO\s+(?:main\.)?["`]?tags["`]?\s*\(([^)]*)\)/i.exec(sql);
525
+ if (insert) {
526
+ const columns = (insert[1] ?? "").split(",").map((column) => column.trim().replace(/["`[\]]/g, "").toLowerCase());
527
+ return columns.includes("id") || columns.includes("rowid");
528
+ }
529
+ const update = /^\s*UPDATE\s+(?:main\.)?["`]?tags["`]?\s+SET\s+([\s\S]*?)\bWHERE\b/i.exec(sql);
530
+ if (update && !/\bSELECT\b/i.test(sql)) {
531
+ const assignments = topLevelCommaSegments(update[1] ?? "");
532
+ if (!assignments)
533
+ return true;
534
+ return !assignments.every((assignment) => {
535
+ const column = /^\s*["`]?(\w+)["`]?\s*=(?!=)/.exec(assignment)?.[1];
536
+ return column !== undefined && TAG_COLUMNS_OUTSIDE_IDENTITY.has(column.toLowerCase());
537
+ });
538
+ }
539
+ return true;
540
+ }
541
+ function topLevelCommaSegments(text) {
542
+ const segments = [];
543
+ let depth = 0;
544
+ let quote = null;
545
+ let start = 0;
546
+ for (let index = 0;index < text.length; index += 1) {
547
+ const char = text[index];
548
+ if (quote) {
549
+ if (char === quote) {
550
+ if (text[index + 1] === quote)
551
+ index += 1;
552
+ else
553
+ quote = null;
554
+ }
555
+ continue;
556
+ }
557
+ if (char === "'" || char === '"' || char === "`")
558
+ quote = char;
559
+ else if (char === "(")
560
+ depth += 1;
561
+ else if (char === ")") {
562
+ depth -= 1;
563
+ if (depth < 0)
564
+ return null;
565
+ } else if (char === "," && depth === 0) {
566
+ segments.push(text.slice(start, index));
567
+ start = index + 1;
568
+ }
569
+ }
570
+ if (quote || depth !== 0)
571
+ return null;
572
+ segments.push(text.slice(start));
573
+ return segments;
574
+ }
487
575
  function installTransactionRouting(db, readonly) {
488
576
  const nativeExec = db.exec.bind(db);
489
577
  Object.defineProperty(db, "exec", {
@@ -494,16 +582,30 @@ function installTransactionRouting(db, readonly) {
494
582
  assertTransformWrite();
495
583
  if (/^\s*BEGIN\s+(?:IMMEDIATE|EXCLUSIVE)(?:\s+TRANSACTION)?\s*;?\s*$/i.test(sql)) {
496
584
  openWriterTransactions.delete(db);
497
- if (transformPassScope.getStore()?.active || backgroundWriterScope.getStore())
585
+ if (transformPassScope.getStore()?.active || backgroundWriterScope.getStore()) {
498
586
  acquireShort(db, () => nativeExec(sql), sql.trim());
499
- else
587
+ } else {
500
588
  nativeExec(sql);
589
+ openWriterTransactions.set(db, {
590
+ site: sql.trim(),
591
+ lane: "background",
592
+ acquireMs: 0,
593
+ attempts: 1,
594
+ acquiredAt: performance.now()
595
+ });
596
+ }
501
597
  return db;
502
598
  }
503
599
  if (WRITER_TRANSACTION_END.test(sql) && openWriterTransactions.has(db))
504
600
  return endWriterTransaction(db, () => nativeExec(sql), sql);
505
- if (!/^\s*(?:SELECT|EXPLAIN|PRAGMA|COMMIT|END|ROLLBACK|SAVEPOINT|RELEASE)\b/i.test(sql))
506
- return withAutocommitTimeout(db, () => nativeExec(sql));
601
+ if (!/^\s*(?:SELECT|EXPLAIN|PRAGMA|COMMIT|END|ROLLBACK|SAVEPOINT|RELEASE)\b/i.test(sql)) {
602
+ try {
603
+ return withAutocommitTimeout(db, () => nativeExec(sql), false);
604
+ } finally {
605
+ if (mayChangeTagIdentity(sql))
606
+ tagIdentityWriteGeneration += 1;
607
+ }
608
+ }
507
609
  return nativeExec(sql);
508
610
  }
509
611
  });
@@ -514,13 +616,23 @@ function installTransactionRouting(db, readonly) {
514
616
  value: (sql) => {
515
617
  const statement = nativePrepare(sql);
516
618
  if (!readonly && !/^\s*(?:SELECT|EXPLAIN|PRAGMA)\b/i.test(sql)) {
619
+ const changesTagIdentity = mayChangeTagIdentity(sql);
517
620
  for (const method of ["run", "get", "all"]) {
518
621
  const execute = statement[method].bind(statement);
519
622
  Object.defineProperty(statement, method, {
520
623
  configurable: true,
521
- value: (...args) => withAutocommitTimeout(db, () => execute(...args))
624
+ value: (...args) => {
625
+ try {
626
+ return withAutocommitTimeout(db, () => execute(...args));
627
+ } finally {
628
+ if (changesTagIdentity)
629
+ tagIdentityWriteGeneration += 1;
630
+ }
631
+ }
522
632
  });
523
633
  }
634
+ if (changesTagIdentity)
635
+ wrapRemainingTagWriteForms(statement);
524
636
  }
525
637
  return statement;
526
638
  }
@@ -568,6 +680,35 @@ function installTransactionRouting(db, readonly) {
568
680
  }
569
681
  });
570
682
  }
683
+ function wrapRemainingTagWriteForms(statement) {
684
+ if (typeof statement.iterate === "function") {
685
+ const iterate = statement.iterate.bind(statement);
686
+ Object.defineProperty(statement, "iterate", {
687
+ configurable: true,
688
+ value: function* (...args) {
689
+ tagIdentityWriteGeneration += 1;
690
+ try {
691
+ yield* iterate(...args);
692
+ } finally {
693
+ tagIdentityWriteGeneration += 1;
694
+ }
695
+ }
696
+ });
697
+ }
698
+ if (typeof statement.values === "function") {
699
+ const values = statement.values.bind(statement);
700
+ Object.defineProperty(statement, "values", {
701
+ configurable: true,
702
+ value: (...args) => {
703
+ try {
704
+ return values(...args);
705
+ } finally {
706
+ tagIdentityWriteGeneration += 1;
707
+ }
708
+ }
709
+ });
710
+ }
711
+ }
571
712
  function trackSqliteConnection(db, filename, options) {
572
713
  const originalClose = db.close.bind(db);
573
714
  const sequence = nextSqliteConnectionSequence++;
@@ -701,25 +842,52 @@ function foregroundWaitLease() {
701
842
  const lease = transformPassScope.getStore();
702
843
  return lease?.active && !admissionScope.getStore() && !backgroundWriterScope.getStore() ? lease : undefined;
703
844
  }
704
- function withAutocommitTimeout(db, operation) {
845
+ function withAutocommitTimeout(db, operation, singleStatement = true) {
705
846
  assertTransformWrite();
706
847
  const lease = foregroundWaitLease();
707
- if (isInTransaction(db) || !lease && !backgroundWriterScope.getStore())
848
+ if (isInTransaction(db))
708
849
  return operation();
709
- const previous = pragmaNumber(db, "busy_timeout");
710
- db.exec(`PRAGMA busy_timeout=${lease ? Math.floor(lease.remainingWaitMs) : SHORT_BUSY_TIMEOUT_MS}`);
850
+ const scoped = lease || backgroundWriterScope.getStore();
851
+ const previous = scoped ? pragmaNumber(db, "busy_timeout") : null;
711
852
  const started = performance.now();
853
+ let completed = false;
854
+ const execute = () => {
855
+ const result = operation();
856
+ completed = true;
857
+ return result;
858
+ };
712
859
  try {
713
- return operation();
860
+ if (!scoped)
861
+ return execute();
862
+ if (singleStatement) {
863
+ db.exec("PRAGMA busy_timeout=0");
864
+ try {
865
+ return execute();
866
+ } catch (error) {
867
+ if (!isTransientSqliteError(error) || isInTransaction(db))
868
+ throw error;
869
+ }
870
+ assertTransformWrite();
871
+ }
872
+ const timeout = Math.floor(Math.min(lease?.remainingWaitMs ?? SHORT_BUSY_TIMEOUT_MS, lease?.guard?.remainingMs() ?? Infinity));
873
+ db.exec(`PRAGMA busy_timeout=${timeout}`);
874
+ const waitStarted = performance.now();
875
+ try {
876
+ return execute();
877
+ } finally {
878
+ if (lease)
879
+ lease.remainingWaitMs = Math.max(0, lease.remainingWaitMs - (performance.now() - waitStarted));
880
+ }
714
881
  } catch (error) {
715
882
  if (lease && isTransientSqliteError(error))
716
883
  throw new SqliteAcquisitionBusyError(error, "autocommit");
717
884
  throw error;
718
885
  } finally {
719
- if (lease)
720
- lease.remainingWaitMs = Math.max(0, lease.remainingWaitMs - (performance.now() - started));
886
+ const elapsed = performance.now() - started;
721
887
  if (previous !== null)
722
888
  db.exec(`PRAGMA busy_timeout=${previous}`);
889
+ if (elapsed >= SLOW_WRITER_LOG_MS)
890
+ reportSqliteDiagnostic(`sqlite writer site=autocommit lane=${lease ? "foreground" : "background"} elapsed_ms=${Math.round(elapsed)} timing=statement_including_acquisition outcome=${completed ? "completed" : "failed"} caller=${writerCaller()}`);
723
891
  }
724
892
  }
725
893
  function acquireShort(db, acquire, site) {
@@ -776,17 +944,22 @@ function endWriterTransaction(db, end, sql) {
776
944
  const holdMs = performance.now() - open.acquiredAt;
777
945
  if (open.acquireMs >= SLOW_WRITER_LOG_MS || holdMs >= SLOW_WRITER_LOG_MS) {
778
946
  const outcome = /^\s*ROLLBACK/i.test(sql) ? "rolled_back" : ended ? "committed" : "failed";
779
- reportSqliteDiagnostic(`sqlite writer site=${open.site} lane=${open.lane} acquire_ms=${Math.round(open.acquireMs)} hold_ms=${Math.round(holdMs)} attempts=${open.attempts} outcome=${outcome}`);
947
+ reportSqliteDiagnostic(`sqlite writer site=${open.site} lane=${open.lane} acquire_ms=${Math.round(open.acquireMs)} hold_ms=${Math.round(holdMs)} attempts=${open.attempts} outcome=${outcome} timing=through_commit_upper_bound caller=${writerCaller()}`);
780
948
  }
781
949
  }
782
950
  }
783
951
  }
952
+ function writerCaller() {
953
+ return new Error().stack?.split(`
954
+ `).find((line) => line.includes(" at ") && !/[/\\]sqlite\.[tj]s[:)]/.test(line) && !/\b(?:writerCaller|endWriterTransaction|withAutocommitTimeout|value)\b/.test(line))?.trim().replace(/\s+/g, "_") ?? "unknown";
955
+ }
784
956
  function isInTransaction(db) {
785
957
  const candidate = db;
786
958
  return candidate.inTransaction === true || candidate.isTransaction === true;
787
959
  }
788
- var reportSlowPrivilegedWrite, sqliteDiagnosticSink, bunSpec, nodeSpec, SqliteRuntimeUnavailableError, detectedRuntime, isBun, sqliteModule, DatabaseImpl, trackedSqliteConnections, nextSqliteConnectionSequence = 1, TrackedDatabase, Database, statementOwners, FIRST_PRUNE_AT = 256, privilegeDepth, transformPassScope, admissionScope, backgroundWriterScope, SqliteAcquisitionBusyError, SHORT_BUSY_TIMEOUT_MS = 25, SLOW_WRITER_LOG_MS = 250, WRITER_TRANSACTION_END, writerAcquisitionScope, openWriterTransactions;
960
+ var resourceRoot, reportSlowPrivilegedWrite, sqliteDiagnosticSink, sqliteDiagnosticHost = () => "unknown", bunSpec, nodeSpec, SqliteRuntimeUnavailableError, detectedRuntime, isBun, sqliteModule, DatabaseImpl, trackedSqliteConnections, nextSqliteConnectionSequence = 1, TAG_COLUMNS_OUTSIDE_IDENTITY, tagIdentityWriteGeneration = 0, TrackedDatabase, Database, statementOwners, FIRST_PRUNE_AT = 256, privilegeDepth, transformPassScope, admissionScope, backgroundWriterScope, SqliteAcquisitionBusyError, SHORT_BUSY_TIMEOUT_MS = 25, SLOW_WRITER_LOG_MS = 100, WRITER_TRANSACTION_END, writerAcquisitionScope, openWriterTransactions, indexCoordinationKey, indexCoordinationHeap, indexCoordinationBuffer, indexCoordinationState;
789
961
  var init_sqlite = __esm(async () => {
962
+ resourceRoot = new AsyncResource("magic-context:root");
790
963
  bunSpec = "bun:" + "sqlite";
791
964
  nodeSpec = "node:" + "sqlite";
792
965
  SqliteRuntimeUnavailableError = class SqliteRuntimeUnavailableError extends Error {
@@ -805,9 +978,22 @@ var init_sqlite = __esm(async () => {
805
978
  sqliteModule = await loadSqliteModule(detectedRuntime);
806
979
  DatabaseImpl = isBun ? sqliteModule.Database : buildNodeSqliteDatabaseClass(sqliteModule.DatabaseSync);
807
980
  trackedSqliteConnections = new Map;
981
+ TAG_COLUMNS_OUTSIDE_IDENTITY = new Set([
982
+ "status",
983
+ "drop_mode",
984
+ "byte_size",
985
+ "input_byte_size",
986
+ "reasoning_byte_size",
987
+ "token_count",
988
+ "input_token_count",
989
+ "caveman_depth",
990
+ "entry_fingerprint",
991
+ "tool_name",
992
+ "harness"
993
+ ]);
808
994
  TrackedDatabase = new Proxy(DatabaseImpl, {
809
995
  construct(target, args) {
810
- const db = Reflect.construct(target, args, target);
996
+ const db = inRootAsyncContext(() => Reflect.construct(target, args, target));
811
997
  return trackSqliteConnection(db, args[0], args[1]);
812
998
  }
813
999
  });
@@ -829,6 +1015,11 @@ var init_sqlite = __esm(async () => {
829
1015
  WRITER_TRANSACTION_END = /^\s*(?:COMMIT|END|ROLLBACK)(?:\s+TRANSACTION)?\s*;?\s*$/i;
830
1016
  writerAcquisitionScope = new AsyncLocalStorage;
831
1017
  openWriterTransactions = new WeakMap;
1018
+ indexCoordinationKey = Symbol.for("magic-context.index-foreground-coordination.v1");
1019
+ indexCoordinationHeap = globalThis;
1020
+ indexCoordinationBuffer = indexCoordinationHeap[indexCoordinationKey] ?? new SharedArrayBuffer(3 * Int32Array.BYTES_PER_ELEMENT);
1021
+ indexCoordinationHeap[indexCoordinationKey] = indexCoordinationBuffer;
1022
+ indexCoordinationState = new Int32Array(indexCoordinationBuffer);
832
1023
  });
833
1024
 
834
1025
  // ../plugin/src/shared/sqlite-helpers.ts
@@ -885,15 +1076,108 @@ var init_migration_v3_perf_schema = __esm(() => {
885
1076
  tagOrderIndexes = new WeakMap;
886
1077
  });
887
1078
 
1079
+ // ../plugin/src/features/magic-context/storage-tag-identity-revision.ts
1080
+ function installTagIdentityRevisionTrigger(db) {
1081
+ db.exec(`DROP TRIGGER IF EXISTS temp.mc_tag_identity_revision_au;
1082
+ DROP TRIGGER IF EXISTS temp.mc_tag_revision_bi;
1083
+ DROP TRIGGER IF EXISTS temp.mc_tag_revision_ai;
1084
+ DROP TRIGGER IF EXISTS temp.mc_tag_revision_au;
1085
+ DROP TRIGGER IF EXISTS temp.mc_tag_revision_ad;
1086
+ DROP TRIGGER IF EXISTS temp.mc_tag_revision_seed_ai;`);
1087
+ db.exec(`CREATE TEMP TRIGGER mc_tag_revision_seed_ai AFTER INSERT ON main.schema_migrations_meta
1088
+ WHEN INSTR(NEW.value, ':') = 0 AND (
1089
+ SUBSTR(NEW.key, 1, ${TAG_REVISION_PREFIX.length}) = '${TAG_REVISION_PREFIX}'
1090
+ OR SUBSTR(NEW.key, 1, ${TAG_IDENTITY_REVISION_PREFIX.length}) = '${TAG_IDENTITY_REVISION_PREFIX}')
1091
+ BEGIN
1092
+ INSERT INTO schema_migrations_meta (key, value) VALUES ('${TAG_REVISION_INCARNATION_KEY}', '1')
1093
+ ON CONFLICT(key) DO UPDATE SET value = CAST(CASE
1094
+ WHEN CAST(value AS INTEGER) < 9223372036854775807 THEN CAST(value AS INTEGER) + 1
1095
+ ELSE NULL END AS TEXT);
1096
+ UPDATE schema_migrations_meta SET value =
1097
+ (SELECT value FROM schema_migrations_meta WHERE key = '${TAG_REVISION_INCARNATION_KEY}')
1098
+ || ':' || CAST(NEW.value AS TEXT) WHERE key = NEW.key;
1099
+ INSERT INTO schema_migrations_meta (key, value)
1100
+ SELECT '${TAG_REVISION_INCARNATION_KEY}', '1'
1101
+ WHERE SUBSTR(NEW.key, 1, ${TAG_REVISION_PREFIX.length}) = '${TAG_REVISION_PREFIX}'
1102
+ AND NOT EXISTS (SELECT 1 FROM schema_migrations_meta
1103
+ WHERE key = '${TAG_IDENTITY_REVISION_PREFIX}' || SUBSTR(NEW.key, ${TAG_REVISION_PREFIX.length + 1}))
1104
+ ON CONFLICT(key) DO UPDATE SET value = CAST(CASE
1105
+ WHEN CAST(value AS INTEGER) < 9223372036854775807 THEN CAST(value AS INTEGER) + 1
1106
+ ELSE NULL END AS TEXT);
1107
+ INSERT INTO schema_migrations_meta (key, value)
1108
+ SELECT '${TAG_IDENTITY_REVISION_PREFIX}' || SUBSTR(NEW.key, ${TAG_REVISION_PREFIX.length + 1}),
1109
+ (SELECT value FROM schema_migrations_meta WHERE key = '${TAG_REVISION_INCARNATION_KEY}') || ':0'
1110
+ WHERE SUBSTR(NEW.key, 1, ${TAG_REVISION_PREFIX.length}) = '${TAG_REVISION_PREFIX}'
1111
+ AND NOT EXISTS (SELECT 1 FROM schema_migrations_meta
1112
+ WHERE key = '${TAG_IDENTITY_REVISION_PREFIX}' || SUBSTR(NEW.key, ${TAG_REVISION_PREFIX.length + 1}));
1113
+ END;`);
1114
+ db.exec(TRIGGER_SQL);
1115
+ db.exec(`CREATE TEMP TRIGGER IF NOT EXISTS mc_tag_revision_bi BEFORE INSERT ON main.tags BEGIN
1116
+ ${BUMP_INSERT_CONFLICTS(TAG_REVISION_PREFIX)};
1117
+ ${BUMP_INSERT_CONFLICTS(TAG_IDENTITY_REVISION_PREFIX)};
1118
+ UPDATE session_meta SET tags_version = tags_version + 1
1119
+ WHERE session_id IN (SELECT session_id FROM (${TAG_INSERT_CONFLICT_ROWS}));
1120
+ END;`);
1121
+ db.exec(`CREATE TEMP TRIGGER IF NOT EXISTS mc_tag_revision_ai AFTER INSERT ON main.tags BEGIN
1122
+ ${BUMP("NEW.session_id", TAG_REVISION_PREFIX)};
1123
+ END;
1124
+ CREATE TEMP TRIGGER IF NOT EXISTS mc_tag_revision_au AFTER UPDATE ON main.tags BEGIN
1125
+ ${BUMP("OLD.session_id", TAG_REVISION_PREFIX)};
1126
+ INSERT INTO schema_migrations_meta (key, value)
1127
+ SELECT '${TAG_REVISION_PREFIX}' || NEW.session_id, '1'
1128
+ WHERE NEW.session_id IS NOT OLD.session_id
1129
+ ON CONFLICT(key) DO UPDATE SET value = ${ADVANCE()};
1130
+ END;
1131
+ CREATE TEMP TRIGGER IF NOT EXISTS mc_tag_revision_ad AFTER DELETE ON main.tags BEGIN
1132
+ ${BUMP("OLD.session_id", TAG_REVISION_PREFIX)};
1133
+ END;`);
1134
+ }
1135
+ var TAG_IDENTITY_REVISION_PREFIX = "tag_identity_revision:", TAG_REVISION_PREFIX = "tag_revision:", TAG_REVISION_INCARNATION_KEY = "tag_revision_incarnation", tagRevisionIncarnationSql = (value) => `CASE WHEN INSTR(${value}, ':') > 0 THEN SUBSTR(${value}, 1, INSTR(${value}, ':') - 1) ELSE '0' END`, tagRevisionCountSql = (value) => `CAST(CASE WHEN INSTR(${value}, ':') > 0 THEN SUBSTR(${value}, INSTR(${value}, ':') + 1) ELSE ${value} END AS INTEGER)`, ADVANCE = (delta = "1") => `CASE
1136
+ WHEN ${tagRevisionCountSql("value")} <= 9223372036854775807 - ${delta}
1137
+ THEN (${tagRevisionIncarnationSql("value")}) || ':' || CAST(${tagRevisionCountSql("value")} + ${delta} AS TEXT)
1138
+ ELSE NULL END`, BUMP = (session, prefix = TAG_IDENTITY_REVISION_PREFIX) => `INSERT INTO schema_migrations_meta (key, value)
1139
+ VALUES ('${prefix}' || ${session}, '1')
1140
+ ON CONFLICT(key) DO UPDATE SET value = ${ADVANCE()}`, TAG_INSERT_CONFLICT_ROWS = `SELECT id, session_id, tag_number FROM tags WHERE id = NEW.id
1141
+ UNION SELECT id, session_id, tag_number FROM tags WHERE session_id = NEW.session_id AND tag_number = NEW.tag_number
1142
+ UNION SELECT id, session_id, tag_number FROM tags
1143
+ WHERE NEW.type = 'tool' AND NEW.tool_owner_message_id IS NOT NULL
1144
+ AND type = 'tool' AND tool_owner_message_id IS NOT NULL
1145
+ AND session_id = NEW.session_id AND message_id = NEW.message_id
1146
+ AND tool_owner_message_id = NEW.tool_owner_message_id`, BUMP_INSERT_CONFLICTS = (prefix) => `INSERT INTO schema_migrations_meta (key, value)
1147
+ SELECT '${prefix}' || session_id, CAST(COUNT(*) AS TEXT)
1148
+ FROM (${TAG_INSERT_CONFLICT_ROWS}) GROUP BY session_id
1149
+ ON CONFLICT(key) DO UPDATE SET value = ${ADVANCE("CAST(excluded.value AS INTEGER)")}`, TRIGGER_SQL;
1150
+ var init_storage_tag_identity_revision = __esm(() => {
1151
+ TRIGGER_SQL = `CREATE TEMP TRIGGER IF NOT EXISTS mc_tag_identity_revision_au
1152
+ AFTER UPDATE OF id, session_id, message_id, tag_number, type, tool_owner_message_id, reasoning_token_count
1153
+ ON main.tags
1154
+ BEGIN
1155
+ ${BUMP("OLD.session_id")};
1156
+ INSERT INTO schema_migrations_meta (key, value)
1157
+ SELECT '${TAG_IDENTITY_REVISION_PREFIX}' || NEW.session_id, '1'
1158
+ WHERE NEW.session_id IS NOT OLD.session_id
1159
+ ON CONFLICT(key) DO UPDATE SET value = ${ADVANCE()};
1160
+ END`;
1161
+ });
1162
+
888
1163
  // ../plugin/src/shared/commit-detection.ts
889
1164
  var HASH_HEX = "[0-9a-f]{7,12}", COMMIT_HASH_TEST_PATTERN;
890
1165
  var init_commit_detection = __esm(() => {
891
1166
  COMMIT_HASH_TEST_PATTERN = new RegExp(`\\b${HASH_HEX}\\b`, "i");
892
1167
  });
1168
+ // ../plugin/src/hooks/magic-context/token-count-exact.ts
1169
+ var textEncoder, textDecoder, mergeCaches;
1170
+ var init_token_count_exact = __esm(() => {
1171
+ textEncoder = new TextEncoder;
1172
+ textDecoder = new TextDecoder("utf-8");
1173
+ mergeCaches = new WeakMap;
1174
+ });
1175
+
893
1176
  // ../plugin/src/hooks/magic-context/read-session-formatting.ts
894
1177
  var promptTokenCounts, PROMPT_TOKEN_COUNT_BYTES;
895
1178
  var init_read_session_formatting = __esm(() => {
896
1179
  init_commit_detection();
1180
+ init_token_count_exact();
897
1181
  promptTokenCounts = new Map;
898
1182
  PROMPT_TOKEN_COUNT_BYTES = 8 * 1024 * 1024;
899
1183
  });
@@ -1379,6 +1663,89 @@ function installV4TemporalDecisions(db) {
1379
1663
  init_logger();
1380
1664
  init_write_transaction_timing();
1381
1665
  init_migration_v3_perf_schema();
1666
+
1667
+ // ../plugin/src/features/magic-context/storage-compartment-history-version.ts
1668
+ function definitions(db) {
1669
+ const hasPrivilegeTable = Boolean(db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='context_privilege_state'").get());
1670
+ const externalUpdate = hasPrivilegeTable ? "CASE WHEN COALESCE((SELECT enabled FROM context_privilege_state WHERE id=1),0)=0 THEN 1 ELSE 0 END" : "1";
1671
+ return [
1672
+ {
1673
+ type: "table",
1674
+ name: "compartment_history_versions",
1675
+ sql: `CREATE TABLE compartment_history_versions (
1676
+ session_id TEXT PRIMARY KEY NOT NULL,
1677
+ generation TEXT NOT NULL DEFAULT (lower(hex(randomblob(16)))),
1678
+ version INTEGER NOT NULL DEFAULT 0 CHECK (version >= 0),
1679
+ rewrite_version INTEGER NOT NULL DEFAULT 0 CHECK (rewrite_version >= 0),
1680
+ seeded INTEGER NOT NULL DEFAULT 0 CHECK (seeded IN (0, 1))
1681
+ )`
1682
+ },
1683
+ {
1684
+ type: "trigger",
1685
+ name: "compartment_history_ai",
1686
+ sql: `CREATE TRIGGER compartment_history_ai AFTER INSERT ON compartments BEGIN
1687
+ INSERT INTO compartment_history_versions(session_id, version) VALUES (NEW.session_id, 1)
1688
+ ON CONFLICT(session_id) DO UPDATE SET version = version + 1;
1689
+ END`
1690
+ },
1691
+ {
1692
+ type: "trigger",
1693
+ name: "compartment_history_ad",
1694
+ sql: `CREATE TRIGGER compartment_history_ad AFTER DELETE ON compartments BEGIN
1695
+ INSERT INTO compartment_history_versions(session_id, version) VALUES (OLD.session_id, 1)
1696
+ ON CONFLICT(session_id) DO UPDATE SET version = version + 1;
1697
+ END`
1698
+ },
1699
+ {
1700
+ type: "trigger",
1701
+ name: "compartment_history_au",
1702
+ sql: `CREATE TRIGGER compartment_history_au AFTER UPDATE ON compartments BEGIN
1703
+ INSERT INTO compartment_history_versions(session_id, version, rewrite_version) VALUES (OLD.session_id, 1, ${externalUpdate})
1704
+ ON CONFLICT(session_id) DO UPDATE SET version = version + 1, rewrite_version = rewrite_version + ${externalUpdate};
1705
+ INSERT INTO compartment_history_versions(session_id, version, rewrite_version)
1706
+ SELECT NEW.session_id, 1, ${externalUpdate} WHERE NEW.session_id != OLD.session_id
1707
+ ON CONFLICT(session_id) DO UPDATE SET version = version + 1, rewrite_version = rewrite_version + ${externalUpdate};
1708
+ END`
1709
+ }
1710
+ ];
1711
+ }
1712
+ function installedDefinitions(db) {
1713
+ const rows = db.prepare(`SELECT type, name, sql FROM sqlite_master
1714
+ WHERE name IN ('compartment_history_versions', 'compartment_history_ai', 'compartment_history_ad', 'compartment_history_au')`).all();
1715
+ return new Map(rows.map((row) => [`${row.type}:${row.name}`, row.sql]));
1716
+ }
1717
+ function matches(expected, installed) {
1718
+ return expected.every((definition) => installed.get(`${definition.type}:${definition.name}`) === definition.sql);
1719
+ }
1720
+ function installCompartmentHistoryVersions(db) {
1721
+ if (!db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='compartments'").get())
1722
+ return;
1723
+ if (matches(definitions(db), installedDefinitions(db)))
1724
+ return;
1725
+ db.transaction(() => {
1726
+ const expected = definitions(db);
1727
+ const installed = installedDefinitions(db);
1728
+ if (matches(expected, installed))
1729
+ return;
1730
+ const table = expected[0];
1731
+ const existingTable = installed.get(`table:${table.name}`);
1732
+ if (existingTable !== undefined && existingTable !== table.sql) {
1733
+ throw new Error("compartment_history_versions schema differs from v5; refusing to replace revision data");
1734
+ }
1735
+ if (existingTable === undefined)
1736
+ db.exec(table.sql);
1737
+ db.exec(`INSERT OR IGNORE INTO compartment_history_versions(session_id, seeded)
1738
+ SELECT DISTINCT session_id, 1 FROM compartments`);
1739
+ for (const trigger of expected.slice(1)) {
1740
+ if (installed.get(`trigger:${trigger.name}`) === trigger.sql)
1741
+ continue;
1742
+ db.exec(`DROP TRIGGER IF EXISTS ${trigger.name}`);
1743
+ db.exec(trigger.sql);
1744
+ }
1745
+ }).immediate();
1746
+ }
1747
+
1748
+ // ../plugin/src/features/magic-context/migrations.ts
1382
1749
  var FORK_MIGRATION_VERSION_FLOOR = 1e4;
1383
1750
  class MigrationLockBusyError extends Error {
1384
1751
  constructor(message) {
@@ -1421,6 +1788,13 @@ var MIGRATIONS = [
1421
1788
  up(db) {
1422
1789
  installV4TemporalDecisions(db);
1423
1790
  }
1791
+ },
1792
+ {
1793
+ version: 5,
1794
+ description: "per-session compartment history revision for shared readers",
1795
+ up(db) {
1796
+ installCompartmentHistoryVersions(db);
1797
+ }
1424
1798
  }
1425
1799
  ];
1426
1800
  var LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
@@ -1562,6 +1936,7 @@ function ensureColumn(db, table, column, definition) {
1562
1936
  }
1563
1937
 
1564
1938
  // ../plugin/src/features/magic-context/storage-db.ts
1939
+ init_storage_tag_identity_revision();
1565
1940
  init_tool_definition_tokens();
1566
1941
 
1567
1942
  // ../plugin/src/features/magic-context/tool-owner-backfill.ts
@@ -1572,13 +1947,13 @@ var LEASE_RENEWAL_MS = 60 * 1000;
1572
1947
 
1573
1948
  // ../plugin/src/features/magic-context/storage-db.ts
1574
1949
  registerSlowWriteReporter(logSlowWriteTransaction);
1575
- registerSqliteDiagnosticSink((message) => log(message));
1950
+ registerSqliteDiagnosticSink((message) => log(message), getHarness);
1576
1951
  var databases = new Map;
1577
1952
  var pendingAsyncOpens = new Map;
1578
1953
  var persistenceByDatabase = new WeakMap;
1579
1954
  var persistenceErrorByDatabase = new WeakMap;
1580
1955
  var pathByDatabase = new WeakMap;
1581
- var LATEST_SUPPORTED_VERSION = 4;
1956
+ var LATEST_SUPPORTED_VERSION = 5;
1582
1957
  var BOOT_SQLITE_BUSY_TIMEOUT_MS = 5000;
1583
1958
  function resolveBootBusyTimeoutMs(value) {
1584
1959
  if (value === undefined)
@@ -3039,6 +3414,8 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
3039
3414
  `);
3040
3415
  installV3PerfSchema(db);
3041
3416
  installV4TemporalDecisions(db);
3417
+ installCompartmentHistoryVersions(db);
3418
+ installTagIdentityRevisionTrigger(db);
3042
3419
  }
3043
3420
  var CHANNEL2_CLAIM_TTL_MS = 10 * 60000;
3044
3421
  var channel2HealStatements = new WeakMap;
@@ -4796,6 +5173,7 @@ var AGENT_STEP_CAPS = {
4796
5173
  [MEMORY_MAINTAINER_A_AGENT]: MEMORY_MAINTAINER_A_STEP_CAP,
4797
5174
  [HIDDEN_HISTORIAN_AGENT]: HISTORIAN_STEP_CAP
4798
5175
  };
5176
+ var DISPOSED_CHILDREN_KEY = Symbol.for("magic-context.v2.disposed-hidden-children");
4799
5177
 
4800
5178
  // ../plugin/src/v2/hidden-child-record.ts
4801
5179
  var HIDDEN_CHILD_ROLE_TITLES = {
@@ -7471,12 +7849,31 @@ function attachPiPartVersion(parts, version) {
7471
7849
  return part;
7472
7850
  });
7473
7851
  }
7474
- function* iterateEntriesToRawMessageRange(entries, afterOrdinal, limit, finalWatermark, synthIdAliases) {
7852
+ var UNREACHABLE_PI_STORE_TYPE = "unavailable";
7853
+ function unreachablePiOrdinalSlot(ordinal) {
7854
+ const slot = { ordinal, id: "", role: "system", parts: [] };
7855
+ Object.defineProperty(slot, "storeType", {
7856
+ value: UNREACHABLE_PI_STORE_TYPE,
7857
+ enumerable: false
7858
+ });
7859
+ return slot;
7860
+ }
7861
+ function* iterateEntriesToRawMessageRange(entries, afterOrdinal, limit, finalWatermark, synthIdAliases, ordinalOffset = 0) {
7475
7862
  let emitted = 0;
7476
7863
  const normalizedAfter = Math.max(0, Math.floor(afterOrdinal));
7477
7864
  const normalizedLimit = Math.max(1, Math.floor(limit));
7478
7865
  const normalizedWatermark = Math.max(normalizedAfter, Math.floor(finalWatermark));
7479
- let nextOrdinal = 1;
7866
+ const prefix = Number.isSafeInteger(ordinalOffset) && ordinalOffset > 0 ? ordinalOffset : 0;
7867
+ const prefixEnd = Math.min(prefix, normalizedWatermark);
7868
+ for (let ordinal = normalizedAfter + 1;ordinal <= prefixEnd; ordinal++) {
7869
+ emitted++;
7870
+ yield unreachablePiOrdinalSlot(ordinal);
7871
+ if (emitted >= normalizedLimit)
7872
+ return;
7873
+ }
7874
+ if (prefix >= normalizedWatermark)
7875
+ return;
7876
+ let nextOrdinal = prefix + 1;
7480
7877
  let heldToolRow = null;
7481
7878
  let orphanToolParts = [];
7482
7879
  const buildOrphanParts = (results) => results.flatMap(({ msg, version }) => attachPiPartVersion(synthesizeToolResultParts(msg), version));
@@ -7591,9 +7988,9 @@ function* iterateEntriesToRawMessageRange(entries, afterOrdinal, limit, finalWat
7591
7988
  yield* appendMessage(`${SYNTH_USER_ID_PREFIX}${orphanFirstId}`, "user", orphanFirstVersion, orphanFirstCreatedAt, () => buildOrphanParts(trailingOrphanResults));
7592
7989
  }
7593
7990
  }
7594
- function convertEntriesToRawMessages(entries) {
7991
+ function convertEntriesToRawMessages(entries, ordinalOffset = 0) {
7595
7992
  return [
7596
- ...iterateEntriesToRawMessageRange(entries, 0, Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER)
7993
+ ...iterateEntriesToRawMessageRange(entries, 0, Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, undefined, ordinalOffset)
7597
7994
  ];
7598
7995
  }
7599
7996
  function buildPiSynthUserIdAlias(entries) {