@cortexkit/pi-magic-context 0.32.1 → 0.32.3

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/index.js CHANGED
@@ -351,7 +351,7 @@ var require_dist2 = __commonJS((exports, module) => {
351
351
  throw c;
352
352
  };
353
353
  if (typeof __filename < "u" ? _scriptName = __filename : f && (_scriptName = self.location.href), ba) {
354
- var fs3 = __require("fs");
354
+ var fs5 = __require("fs");
355
355
  1 < process.argv.length && (t = process.argv[1].replace(/\\/g, "/")), process.argv.slice(2), w = (b, c) => {
356
356
  throw process.exitCode = b, c;
357
357
  };
@@ -16055,6 +16055,22 @@ function storedPathBelongsToIdentity(storedProjectPath, projectIdentity) {
16055
16055
  return storedProjectPath === projectIdentity || normalizeStoredProjectPath(storedProjectPath) === projectIdentity;
16056
16056
  }
16057
16057
 
16058
+ // ../plugin/src/plugin/boot-quiet.ts
16059
+ var BOOT_QUIET_MS = 120000;
16060
+ var bootQuietUntilMs = 0;
16061
+ function beginBootQuietPeriod(now = Date.now()) {
16062
+ if (bootQuietUntilMs === 0)
16063
+ bootQuietUntilMs = now + BOOT_QUIET_MS;
16064
+ }
16065
+ function bootQuietRemainingMs(now = Date.now()) {
16066
+ return Math.max(0, bootQuietUntilMs - now);
16067
+ }
16068
+ function scheduleAfterBootQuiet(task, additionalDelayMs = 0) {
16069
+ const timer = setTimeout(task, bootQuietRemainingMs() + Math.max(0, additionalDelayMs));
16070
+ timer.unref?.();
16071
+ return timer;
16072
+ }
16073
+
16058
16074
  // ../plugin/src/features/magic-context/message-index-async.ts
16059
16075
  init_logger();
16060
16076
 
@@ -149799,11 +149815,13 @@ function scheduleReconciliation(db, sessionId, readMessages) {
149799
149815
  return;
149800
149816
  }
149801
149817
  reconciliationScheduledSessions.add(sessionId);
149802
- defer(() => {
149803
- reconcileSessionIndex(db, sessionId, readMessages).catch((error) => {
149804
- logIndexingError(sessionId, "reconciliation", error);
149805
- }).finally(() => {
149806
- reconciliationScheduledSessions.delete(sessionId);
149818
+ scheduleAfterBootQuiet(() => {
149819
+ defer(() => {
149820
+ reconcileSessionIndex(db, sessionId, readMessages).catch((error) => {
149821
+ logIndexingError(sessionId, "reconciliation", error);
149822
+ }).finally(() => {
149823
+ reconciliationScheduledSessions.delete(sessionId);
149824
+ });
149807
149825
  });
149808
149826
  });
149809
149827
  }
@@ -151242,6 +151260,22 @@ function bumpEpochsForWorkspaceMemberSet(db, identities, now = Date.now()) {
151242
151260
  }
151243
151261
 
151244
151262
  // ../plugin/src/features/magic-context/migrations.ts
151263
+ var MIGRATION_LOCK_RETRY_DELAYS_MS = [1000, 2000, 4000, 8000, 15000];
151264
+
151265
+ class MigrationLockBusyError extends Error {
151266
+ constructor(message) {
151267
+ super(message);
151268
+ this.name = "MigrationLockBusyError";
151269
+ }
151270
+ }
151271
+ function isSqliteLockError(error) {
151272
+ if (!error || typeof error !== "object")
151273
+ return false;
151274
+ const candidate = error;
151275
+ if (candidate.code === "SQLITE_BUSY" || candidate.code === "SQLITE_LOCKED")
151276
+ return true;
151277
+ return typeof candidate.message === "string" && /database is locked|sqlite_(busy|locked)/i.test(candidate.message);
151278
+ }
151245
151279
  function tableExists2(db, name2) {
151246
151280
  return Boolean(db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name = ?").get(name2));
151247
151281
  }
@@ -152601,6 +152635,80 @@ var MIGRATIONS = [
152601
152635
  ensureColumn(db, "session_meta", "emergency_recovery_origin", "TEXT DEFAULT ''");
152602
152636
  }
152603
152637
  }
152638
+ },
152639
+ {
152640
+ version: 53,
152641
+ description: "add Synapse batch, shadow, and measurement storage",
152642
+ up(db) {
152643
+ db.exec(`
152644
+ CREATE TABLE IF NOT EXISTS embedding_registrations (
152645
+ project_path TEXT PRIMARY KEY,
152646
+ provider_identity TEXT NOT NULL DEFAULT '',
152647
+ model_id TEXT NOT NULL DEFAULT '',
152648
+ chunk_model_id TEXT NOT NULL DEFAULT '',
152649
+ fingerprint TEXT NOT NULL DEFAULT '',
152650
+ table_epoch INTEGER NOT NULL DEFAULT 0,
152651
+ dims INTEGER NOT NULL DEFAULT 0,
152652
+ provenance_json TEXT NOT NULL DEFAULT '{}',
152653
+ generation INTEGER NOT NULL DEFAULT 0,
152654
+ updated_at INTEGER NOT NULL DEFAULT 0
152655
+ );
152656
+ CREATE TABLE IF NOT EXISTS synapse_batch_ledger (
152657
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
152658
+ session_id TEXT NOT NULL,
152659
+ project_path TEXT NOT NULL DEFAULT '',
152660
+ scope TEXT NOT NULL DEFAULT '',
152661
+ manifest_json TEXT NOT NULL DEFAULT '{}',
152662
+ request_key TEXT NOT NULL DEFAULT '',
152663
+ job_id TEXT,
152664
+ cursor TEXT,
152665
+ status TEXT NOT NULL DEFAULT 'pending',
152666
+ created_at INTEGER NOT NULL DEFAULT 0,
152667
+ updated_at INTEGER NOT NULL DEFAULT 0,
152668
+ UNIQUE(session_id, request_key)
152669
+ );
152670
+ CREATE INDEX IF NOT EXISTS idx_synapse_batch_ledger_session
152671
+ ON synapse_batch_ledger(session_id, updated_at);
152672
+ CREATE TABLE IF NOT EXISTS shadow_embedding_registrations (
152673
+ project_path TEXT NOT NULL,
152674
+ scope TEXT NOT NULL CHECK(scope IN ('memory', 'commit', 'chunk')),
152675
+ model_id TEXT NOT NULL,
152676
+ generation INTEGER NOT NULL DEFAULT 0,
152677
+ fingerprint TEXT NOT NULL DEFAULT '',
152678
+ table_epoch INTEGER NOT NULL DEFAULT 0,
152679
+ dims INTEGER NOT NULL DEFAULT 0,
152680
+ provenance_json TEXT NOT NULL DEFAULT '{}',
152681
+ updated_at INTEGER NOT NULL DEFAULT 0,
152682
+ PRIMARY KEY(project_path, scope, model_id)
152683
+ );
152684
+ CREATE TABLE IF NOT EXISTS embedding_measurement_corpus (
152685
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
152686
+ session_id TEXT NOT NULL,
152687
+ project_path TEXT NOT NULL DEFAULT '',
152688
+ dedup_key TEXT NOT NULL DEFAULT '',
152689
+ cohort_key TEXT NOT NULL DEFAULT '',
152690
+ query_text_hash TEXT NOT NULL DEFAULT '',
152691
+ primary_result_ids_json TEXT NOT NULL DEFAULT '[]',
152692
+ shadow_result_ids_json TEXT NOT NULL DEFAULT '[]',
152693
+ primary_latency_ms INTEGER,
152694
+ shadow_latency_ms INTEGER,
152695
+ primary_failed INTEGER NOT NULL DEFAULT 0,
152696
+ shadow_failed INTEGER NOT NULL DEFAULT 0,
152697
+ primary_model_id TEXT NOT NULL DEFAULT '',
152698
+ shadow_model_id TEXT NOT NULL DEFAULT '',
152699
+ primary_fingerprint TEXT NOT NULL DEFAULT '',
152700
+ shadow_fingerprint TEXT NOT NULL DEFAULT '',
152701
+ primary_epoch INTEGER NOT NULL DEFAULT 0,
152702
+ shadow_epoch INTEGER NOT NULL DEFAULT 0,
152703
+ corpus_hash TEXT NOT NULL DEFAULT '',
152704
+ coverage_json TEXT NOT NULL DEFAULT '{}',
152705
+ created_at INTEGER NOT NULL DEFAULT 0,
152706
+ UNIQUE(dedup_key, cohort_key)
152707
+ );
152708
+ CREATE INDEX IF NOT EXISTS idx_embedding_measurement_session
152709
+ ON embedding_measurement_corpus(session_id, created_at);
152710
+ `);
152711
+ }
152604
152712
  }
152605
152713
  ];
152606
152714
  var LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
@@ -152629,7 +152737,14 @@ function isSiblingMigrationConflict(db, error, version) {
152629
152737
  return confirmed != null;
152630
152738
  }
152631
152739
  function runMigrations(db) {
152632
- ensureMigrationsTable(db);
152740
+ try {
152741
+ ensureMigrationsTable(db);
152742
+ } catch (error) {
152743
+ if (isSqliteLockError(error)) {
152744
+ throw new MigrationLockBusyError(`failed to prepare migration lock: ${error instanceof Error ? error.message : String(error)}`);
152745
+ }
152746
+ throw error;
152747
+ }
152633
152748
  let loggedPlan = false;
152634
152749
  while (true) {
152635
152750
  let migration;
@@ -152653,6 +152768,9 @@ function runMigrations(db) {
152653
152768
  break;
152654
152769
  log(`[migrations] applied v${migration.version}: ${migration.description}`);
152655
152770
  } catch (error) {
152771
+ if (!migration && isSqliteLockError(error)) {
152772
+ throw new MigrationLockBusyError(`failed to acquire migration write lock: ${error instanceof Error ? error.message : String(error)}`);
152773
+ }
152656
152774
  if (migration && isSiblingMigrationConflict(db, error, migration.version)) {
152657
152775
  log(`[migrations] v${migration.version} already applied by sibling instance — resuming with re-read version`);
152658
152776
  const reReadVersion = getCurrentVersion(db);
@@ -152670,6 +152788,26 @@ function runMigrations(db) {
152670
152788
  log(`[migrations] schema version now: ${MIGRATIONS[MIGRATIONS.length - 1].version}`);
152671
152789
  }
152672
152790
  }
152791
+ async function runMigrationsWithRetry(db, options = {}) {
152792
+ const retryDelaysMs = options.retryDelaysMs ?? MIGRATION_LOCK_RETRY_DELAYS_MS;
152793
+ const sleep = options.sleep ?? ((delayMs) => new Promise((resolve) => setTimeout(resolve, delayMs)));
152794
+ const totalAttempts = retryDelaysMs.length + 1;
152795
+ for (let attempt = 1;attempt <= totalAttempts; attempt += 1) {
152796
+ log(`[migrations] migration lock check attempt ${attempt}/${totalAttempts}`);
152797
+ try {
152798
+ runMigrations(db);
152799
+ return;
152800
+ } catch (error) {
152801
+ if (!(error instanceof MigrationLockBusyError))
152802
+ throw error;
152803
+ const delayMs = retryDelaysMs[attempt - 1];
152804
+ if (delayMs === undefined)
152805
+ throw error;
152806
+ log(`[migrations] migration write lock is busy; retrying attempt ${attempt + 1}/${totalAttempts} in ${delayMs}ms`);
152807
+ await sleep(delayMs);
152808
+ }
152809
+ }
152810
+ }
152673
152811
  // ../plugin/src/features/magic-context/project-docs-hash.ts
152674
152812
  import { createHash as createHash3 } from "node:crypto";
152675
152813
  import { lstatSync, readFileSync as readFileSync3, statSync as statSync3 } from "node:fs";
@@ -152814,14 +152952,19 @@ function countRows(db, table, sessionId) {
152814
152952
  const row = db.prepare(`SELECT COUNT(*) AS count FROM ${table} WHERE session_id = ?`).get(sessionId);
152815
152953
  return typeof row?.count === "number" ? row.count : 0;
152816
152954
  }
152817
- function filterIdBlob(raw, includeMessageId) {
152955
+ function mapMessageId(filter, messageId) {
152956
+ if (messageId === null)
152957
+ return null;
152958
+ return filter.mapMessageId?.(messageId) ?? messageId;
152959
+ }
152960
+ function filterIdBlob(raw, filter) {
152818
152961
  if (!raw)
152819
152962
  return "";
152820
152963
  try {
152821
152964
  const value = JSON.parse(raw);
152822
152965
  if (!Array.isArray(value))
152823
152966
  return "";
152824
- const filtered = value.filter((id) => typeof id === "string" && includeMessageId(id));
152967
+ const filtered = value.filter((id) => typeof id === "string" && filter.includeMessageId(id)).map((id) => mapMessageId(filter, id));
152825
152968
  return filtered.length > 0 ? JSON.stringify(filtered) : "";
152826
152969
  } catch {
152827
152970
  return "";
@@ -152858,16 +153001,16 @@ function copySessionStateForClone(db, sourceSessionId, destinationSessionId, fil
152858
153001
  const endMessage = filter.resolveBoundaryOrdinal(row.end_message_id);
152859
153002
  if (startMessage === undefined || endMessage === undefined)
152860
153003
  continue;
152861
- insertCompartment.run(destinationSessionId, row.sequence, startMessage, endMessage, row.start_message_id, row.end_message_id, row.title, row.content, row.p1, row.p2, row.p3, row.p4, row.importance, row.episode_type, row.legacy, row.created_at, row.harness);
153004
+ insertCompartment.run(destinationSessionId, row.sequence, startMessage, endMessage, mapMessageId(filter, row.start_message_id), mapMessageId(filter, row.end_message_id), row.title, row.content, row.p1, row.p2, row.p3, row.p4, row.importance, row.episode_type, row.legacy, row.created_at, row.harness);
152862
153005
  copiedCompartments.push({
152863
153006
  sequence: row.sequence,
152864
153007
  startMessage,
152865
153008
  endMessage,
152866
- startMessageId: row.start_message_id,
152867
- endMessageId: row.end_message_id
153009
+ startMessageId: mapMessageId(filter, row.start_message_id) ?? row.start_message_id,
153010
+ endMessageId: mapMessageId(filter, row.end_message_id) ?? row.end_message_id
152868
153011
  });
152869
153012
  }
152870
- const sourceTags = db.prepare(`SELECT message_id, type, status, byte_size, tag_number, harness,
153013
+ const sourceTags = db.prepare(`SELECT id, message_id, type, status, byte_size, tag_number, harness,
152871
153014
  entry_fingerprint, token_count, input_token_count,
152872
153015
  reasoning_token_count, reasoning_byte_size, drop_mode, tool_name,
152873
153016
  input_byte_size, caveman_depth, tool_owner_message_id
@@ -152879,6 +153022,7 @@ function copySessionStateForClone(db, sourceSessionId, destinationSessionId, fil
152879
153022
  caveman_depth, tool_owner_message_id)
152880
153023
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
152881
153024
  const copiedTagNumbers = [];
153025
+ const copiedTagIds = new Map;
152882
153026
  for (const row of sourceTags) {
152883
153027
  if (!filter.includeTag({
152884
153028
  messageId: row.message_id,
@@ -152888,19 +153032,39 @@ function copySessionStateForClone(db, sourceSessionId, destinationSessionId, fil
152888
153032
  })) {
152889
153033
  continue;
152890
153034
  }
152891
- insertTag.run(destinationSessionId, row.message_id, row.type, row.status, row.byte_size, row.tag_number, row.harness, row.entry_fingerprint, row.token_count, row.input_token_count, row.reasoning_token_count, row.reasoning_byte_size, row.drop_mode, row.tool_name, row.input_byte_size, row.caveman_depth, row.tool_owner_message_id);
153035
+ const insertResult = insertTag.run(destinationSessionId, mapMessageId(filter, row.message_id), row.type, row.status, row.byte_size, row.tag_number, row.harness, row.entry_fingerprint, row.token_count, row.input_token_count, row.reasoning_token_count, row.reasoning_byte_size, row.drop_mode, row.tool_name, row.input_byte_size, row.caveman_depth, mapMessageId(filter, row.tool_owner_message_id));
153036
+ const insertedTagId = Number(insertResult.lastInsertRowid);
153037
+ if (!Number.isSafeInteger(insertedTagId) || insertedTagId <= 0) {
153038
+ throw new Error(`failed to obtain destination tag id for tag ${row.tag_number}`);
153039
+ }
153040
+ const sourceTagId = filter.mapTagId ? row.id : row.tag_number;
153041
+ const destinationTagId = filter.mapTagId ? filter.mapTagId(sourceTagId, insertedTagId) : sourceTagId;
153042
+ copiedTagIds.set(sourceTagId, destinationTagId);
152892
153043
  copiedTagNumbers.push(row.tag_number);
152893
153044
  }
152894
153045
  if (copiedTagNumbers.length > 0) {
152895
- const placeholders2 = copiedTagNumbers.map(() => "?").join(", ");
152896
- db.prepare(`INSERT INTO source_contents (tag_id, session_id, content, created_at, harness)
152897
- SELECT tag_id, ?, content, created_at, harness
152898
- FROM source_contents
152899
- WHERE session_id = ? AND tag_id IN (${placeholders2})`).run(destinationSessionId, sourceSessionId, ...copiedTagNumbers);
152900
- db.prepare(`INSERT INTO pending_ops (session_id, tag_id, operation, queued_at, harness)
152901
- SELECT ?, tag_id, operation, queued_at, harness
152902
- FROM pending_ops
152903
- WHERE session_id = ? AND tag_id IN (${placeholders2})`).run(destinationSessionId, sourceSessionId, ...copiedTagNumbers);
153046
+ const sourceTagIds = [...copiedTagIds.keys()];
153047
+ const placeholders2 = sourceTagIds.map(() => "?").join(", ");
153048
+ const sourceContents = db.prepare(`SELECT tag_id, content, created_at, harness
153049
+ FROM source_contents
153050
+ WHERE session_id = ? AND tag_id IN (${placeholders2})`).all(sourceSessionId, ...sourceTagIds);
153051
+ const insertSourceContent = db.prepare("INSERT INTO source_contents (tag_id, session_id, content, created_at, harness) VALUES (?, ?, ?, ?, ?)");
153052
+ for (const row of sourceContents) {
153053
+ const destinationTagId = copiedTagIds.get(row.tag_id);
153054
+ if (destinationTagId === undefined)
153055
+ continue;
153056
+ insertSourceContent.run(destinationTagId, destinationSessionId, row.content, row.created_at, row.harness);
153057
+ }
153058
+ const pendingOps = db.prepare(`SELECT tag_id, operation, queued_at, harness
153059
+ FROM pending_ops
153060
+ WHERE session_id = ? AND tag_id IN (${placeholders2})`).all(sourceSessionId, ...sourceTagIds);
153061
+ const insertPendingOp = db.prepare("INSERT INTO pending_ops (session_id, tag_id, operation, queued_at, harness) VALUES (?, ?, ?, ?, ?)");
153062
+ for (const row of pendingOps) {
153063
+ const destinationTagId = copiedTagIds.get(row.tag_id);
153064
+ if (destinationTagId === undefined)
153065
+ continue;
153066
+ insertPendingOp.run(destinationSessionId, destinationTagId, row.operation, row.queued_at, row.harness);
153067
+ }
152904
153068
  }
152905
153069
  const meta = db.prepare(`SELECT cleared_reasoning_through_tag, tool_reclaim_watermark,
152906
153070
  pi_stable_id_scheme, stripped_placeholder_ids,
@@ -152936,7 +153100,7 @@ function copySessionStateForClone(db, sourceSessionId, destinationSessionId, fil
152936
153100
  todo_synthetic_anchor_message_id = excluded.todo_synthetic_anchor_message_id,
152937
153101
  todo_synthetic_state_json = excluded.todo_synthetic_state_json,
152938
153102
  cached_m0_bytes = NULL,
152939
- cached_m1_bytes = NULL`).run(destinationSessionId, getHarness(), maxCopiedTag, clampWatermark(meta?.cleared_reasoning_through_tag ?? null, maxCopiedTag), clampWatermark(meta?.tool_reclaim_watermark ?? null, maxCopiedTag), typeof meta?.pi_stable_id_scheme === "number" && Number.isFinite(meta.pi_stable_id_scheme) ? meta.pi_stable_id_scheme : null, filterIdBlob(meta?.stripped_placeholder_ids ?? null, filter.includeMessageId), filterIdBlob(meta?.stale_reduce_stripped_ids ?? null, filter.includeMessageId), filterIdBlob(meta?.processed_image_stripped_ids ?? null, filter.includeMessageId), pendingMarker, migrateTodo ? meta?.last_todo_state ?? "" : "", migrateTodo ? meta?.todo_synthetic_call_id ?? "" : "", migrateTodo ? todoAnchor : "", migrateTodo ? meta?.todo_synthetic_state_json ?? "" : "");
153103
+ cached_m1_bytes = NULL`).run(destinationSessionId, getHarness(), maxCopiedTag, clampWatermark(meta?.cleared_reasoning_through_tag ?? null, maxCopiedTag), clampWatermark(meta?.tool_reclaim_watermark ?? null, maxCopiedTag), typeof meta?.pi_stable_id_scheme === "number" && Number.isFinite(meta.pi_stable_id_scheme) ? meta.pi_stable_id_scheme : null, filterIdBlob(meta?.stripped_placeholder_ids ?? null, filter), filterIdBlob(meta?.stale_reduce_stripped_ids ?? null, filter), filterIdBlob(meta?.processed_image_stripped_ids ?? null, filter), pendingMarker, migrateTodo ? meta?.last_todo_state ?? "" : "", migrateTodo ? meta?.todo_synthetic_call_id ?? "" : "", migrateTodo ? mapMessageId(filter, todoAnchor) ?? "" : "", migrateTodo ? meta?.todo_synthetic_state_json ?? "" : "");
152940
153104
  const pendingOpsRow = db.prepare("SELECT COUNT(*) AS count FROM pending_ops WHERE session_id = ?").get(destinationSessionId);
152941
153105
  return {
152942
153106
  kind: "migrated",
@@ -152949,8 +153113,8 @@ function copySessionStateForClone(db, sourceSessionId, destinationSessionId, fil
152949
153113
  }
152950
153114
  // ../plugin/src/features/magic-context/storage-db.ts
152951
153115
  import { chmodSync, copyFileSync, cpSync, existsSync as existsSync7, mkdirSync as mkdirSync4, mkdtempSync } from "node:fs";
152952
- init_data_path();
152953
153116
  import { dirname as dirname3, join as join5 } from "node:path";
153117
+ init_data_path();
152954
153118
 
152955
153119
  // ../plugin/src/shared/error-message.ts
152956
153120
  function getErrorMessage(error) {
@@ -153342,11 +153506,12 @@ function backfillToolOwnersInChunks(db, result) {
153342
153506
 
153343
153507
  // ../plugin/src/features/magic-context/storage-db.ts
153344
153508
  var databases = new Map;
153509
+ var pendingAsyncOpens = new Map;
153345
153510
  var persistenceByDatabase = new WeakMap;
153346
153511
  var persistenceErrorByDatabase = new WeakMap;
153347
153512
  var pathByDatabase = new WeakMap;
153348
153513
  var lastSchemaFenceRejection = null;
153349
- var LATEST_SUPPORTED_VERSION = 52;
153514
+ var LATEST_SUPPORTED_VERSION = 53;
153350
153515
  var PERMISSIONS_ENFORCEABLE = process.platform !== "win32";
153351
153516
  function ensureSecureStorageDir(dir) {
153352
153517
  mkdirSync4(dir, { recursive: true, mode: 448 });
@@ -153476,6 +153641,34 @@ function runSqliteOptimize(db) {
153476
153641
  db.exec("PRAGMA optimize");
153477
153642
  } catch {}
153478
153643
  }
153644
+ function finishDatabaseOpen(db, dbPath, explicitDbPath, latestSupportedVersion) {
153645
+ if (!enforceSchemaFence(db, dbPath, latestSupportedVersion)) {
153646
+ closeQuietly(db);
153647
+ return null;
153648
+ }
153649
+ healWedgedChannel2Claims(db);
153650
+ if (!explicitDbPath) {
153651
+ const runBackfill = () => {
153652
+ try {
153653
+ runToolOwnerBackfill(db);
153654
+ } catch (error) {
153655
+ log(`[magic-context] tool-owner backfill failed (continuing with lazy adoption fallback): ${getErrorMessage(error)}`);
153656
+ }
153657
+ };
153658
+ if (bootQuietRemainingMs() > 0)
153659
+ scheduleAfterBootQuiet(runBackfill);
153660
+ else
153661
+ runBackfill();
153662
+ }
153663
+ setDatabase(db);
153664
+ loadToolDefinitionMeasurements(db);
153665
+ restrictDatabaseFilePermissions(dbPath);
153666
+ databases.set(dbPath, db);
153667
+ pathByDatabase.set(db, dbPath);
153668
+ persistenceByDatabase.set(db, true);
153669
+ persistenceErrorByDatabase.delete(db);
153670
+ return db;
153671
+ }
153479
153672
  function initializeDatabase(db) {
153480
153673
  db.exec("PRAGMA busy_timeout=5000");
153481
153674
  db.exec("PRAGMA foreign_keys=ON");
@@ -153733,6 +153926,76 @@ function initializeDatabase(db) {
153733
153926
  PRIMARY KEY(project_path, scope, model_id)
153734
153927
  );
153735
153928
 
153929
+ CREATE TABLE IF NOT EXISTS embedding_registrations (
153930
+ project_path TEXT PRIMARY KEY,
153931
+ provider_identity TEXT NOT NULL DEFAULT '',
153932
+ model_id TEXT NOT NULL DEFAULT '',
153933
+ chunk_model_id TEXT NOT NULL DEFAULT '',
153934
+ fingerprint TEXT NOT NULL DEFAULT '',
153935
+ table_epoch INTEGER NOT NULL DEFAULT 0,
153936
+ dims INTEGER NOT NULL DEFAULT 0,
153937
+ provenance_json TEXT NOT NULL DEFAULT '{}',
153938
+ generation INTEGER NOT NULL DEFAULT 0,
153939
+ updated_at INTEGER NOT NULL DEFAULT 0
153940
+ );
153941
+
153942
+ CREATE TABLE IF NOT EXISTS synapse_batch_ledger (
153943
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
153944
+ session_id TEXT NOT NULL,
153945
+ project_path TEXT NOT NULL DEFAULT '',
153946
+ scope TEXT NOT NULL DEFAULT '',
153947
+ manifest_json TEXT NOT NULL DEFAULT '{}',
153948
+ request_key TEXT NOT NULL DEFAULT '',
153949
+ job_id TEXT,
153950
+ cursor TEXT,
153951
+ status TEXT NOT NULL DEFAULT 'pending',
153952
+ created_at INTEGER NOT NULL DEFAULT 0,
153953
+ updated_at INTEGER NOT NULL DEFAULT 0,
153954
+ UNIQUE(session_id, request_key)
153955
+ );
153956
+ CREATE INDEX IF NOT EXISTS idx_synapse_batch_ledger_session
153957
+ ON synapse_batch_ledger(session_id, updated_at);
153958
+
153959
+ CREATE TABLE IF NOT EXISTS shadow_embedding_registrations (
153960
+ project_path TEXT NOT NULL,
153961
+ scope TEXT NOT NULL CHECK(scope IN ('memory', 'commit', 'chunk')),
153962
+ model_id TEXT NOT NULL,
153963
+ generation INTEGER NOT NULL DEFAULT 0,
153964
+ fingerprint TEXT NOT NULL DEFAULT '',
153965
+ table_epoch INTEGER NOT NULL DEFAULT 0,
153966
+ dims INTEGER NOT NULL DEFAULT 0,
153967
+ provenance_json TEXT NOT NULL DEFAULT '{}',
153968
+ updated_at INTEGER NOT NULL DEFAULT 0,
153969
+ PRIMARY KEY(project_path, scope, model_id)
153970
+ );
153971
+
153972
+ CREATE TABLE IF NOT EXISTS embedding_measurement_corpus (
153973
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
153974
+ session_id TEXT NOT NULL,
153975
+ project_path TEXT NOT NULL DEFAULT '',
153976
+ dedup_key TEXT NOT NULL DEFAULT '',
153977
+ cohort_key TEXT NOT NULL DEFAULT '',
153978
+ query_text_hash TEXT NOT NULL DEFAULT '',
153979
+ primary_result_ids_json TEXT NOT NULL DEFAULT '[]',
153980
+ shadow_result_ids_json TEXT NOT NULL DEFAULT '[]',
153981
+ primary_latency_ms INTEGER,
153982
+ shadow_latency_ms INTEGER,
153983
+ primary_failed INTEGER NOT NULL DEFAULT 0,
153984
+ shadow_failed INTEGER NOT NULL DEFAULT 0,
153985
+ primary_model_id TEXT NOT NULL DEFAULT '',
153986
+ shadow_model_id TEXT NOT NULL DEFAULT '',
153987
+ primary_fingerprint TEXT NOT NULL DEFAULT '',
153988
+ shadow_fingerprint TEXT NOT NULL DEFAULT '',
153989
+ primary_epoch INTEGER NOT NULL DEFAULT 0,
153990
+ shadow_epoch INTEGER NOT NULL DEFAULT 0,
153991
+ corpus_hash TEXT NOT NULL DEFAULT '',
153992
+ coverage_json TEXT NOT NULL DEFAULT '{}',
153993
+ created_at INTEGER NOT NULL DEFAULT 0,
153994
+ UNIQUE(dedup_key, cohort_key)
153995
+ );
153996
+ CREATE INDEX IF NOT EXISTS idx_embedding_measurement_session
153997
+ ON embedding_measurement_corpus(session_id, created_at);
153998
+
153736
153999
  CREATE TABLE IF NOT EXISTS memory_verifications (
153737
154000
  memory_id INTEGER NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
153738
154001
  file_path TEXT NOT NULL,
@@ -154473,32 +154736,90 @@ function openDatabase(dbPathOrOptions) {
154473
154736
  }
154474
154737
  initializeDatabase(db);
154475
154738
  runMigrations(db);
154476
- if (!enforceSchemaFence(db, dbPath, latestSupportedVersion)) {
154477
- closeQuietly(db);
154478
- return null;
154479
- }
154480
- healWedgedChannel2Claims(db);
154481
- if (!explicitDbPath) {
154482
- try {
154483
- runToolOwnerBackfill(db);
154484
- } catch (error) {
154485
- log(`[magic-context] tool-owner backfill failed (continuing with lazy adoption fallback): ${getErrorMessage(error)}`);
154486
- }
154487
- }
154488
- setDatabase(db);
154489
- loadToolDefinitionMeasurements(db);
154490
- restrictDatabaseFilePermissions(dbPath);
154491
- databases.set(dbPath, db);
154492
- pathByDatabase.set(db, dbPath);
154493
- persistenceByDatabase.set(db, true);
154494
- persistenceErrorByDatabase.delete(db);
154495
- return db;
154739
+ return finishDatabaseOpen(db, dbPath, explicitDbPath, latestSupportedVersion);
154496
154740
  } catch (error) {
154497
154741
  const detail = getErrorMessage(error);
154498
154742
  log(`[magic-context] storage fatal: failed to open ${dbPath}: ${detail}`);
154499
154743
  throw new Error(`[magic-context] storage unavailable: ${detail}. Magic Context is disabled for this run; check log for details.`);
154500
154744
  }
154501
154745
  }
154746
+ async function openDatabaseAsync(dbPathOrOptions) {
154747
+ const options = typeof dbPathOrOptions === "string" ? { dbPath: dbPathOrOptions } : dbPathOrOptions;
154748
+ const explicitDbPath = options?.dbPath !== undefined;
154749
+ const { dbDir, dbPath } = resolveDatabasePath(options?.dbPath);
154750
+ const latestSupportedVersion = getRuntimeLatestSupportedVersion(options);
154751
+ const existing = databases.get(dbPath);
154752
+ if (existing) {
154753
+ if (!enforceSchemaFence(existing, dbPath, latestSupportedVersion))
154754
+ return null;
154755
+ if (!persistenceByDatabase.has(existing))
154756
+ persistenceByDatabase.set(existing, true);
154757
+ healWedgedChannel2Claims(existing);
154758
+ return existing;
154759
+ }
154760
+ const pending = pendingAsyncOpens.get(dbPath);
154761
+ if (pending)
154762
+ return pending;
154763
+ const opening = (async () => {
154764
+ let db;
154765
+ try {
154766
+ if (!explicitDbPath)
154767
+ migrateLegacyStorageIfNeeded(dbPath, dbDir);
154768
+ ensureSecureStorageDir(dbDir);
154769
+ db = new Database(dbPath);
154770
+ if (!enforceSchemaFence(db, dbPath, latestSupportedVersion)) {
154771
+ closeQuietly(db);
154772
+ return null;
154773
+ }
154774
+ initializeDatabase(db);
154775
+ await runMigrationsWithRetry(db);
154776
+ return finishDatabaseOpen(db, dbPath, explicitDbPath, latestSupportedVersion);
154777
+ } catch (error) {
154778
+ if (db)
154779
+ closeQuietly(db);
154780
+ const detail = getErrorMessage(error);
154781
+ log(`[magic-context] storage fatal: failed to open ${dbPath}: ${detail}`);
154782
+ throw new Error(`[magic-context] storage unavailable: ${detail}. Magic Context is disabled for this run; check log for details.`);
154783
+ }
154784
+ })();
154785
+ pendingAsyncOpens.set(dbPath, opening);
154786
+ try {
154787
+ return await opening;
154788
+ } finally {
154789
+ if (pendingAsyncOpens.get(dbPath) === opening)
154790
+ pendingAsyncOpens.delete(dbPath);
154791
+ }
154792
+ }
154793
+ // ../plugin/src/features/magic-context/storage-embedding-measurements.ts
154794
+ import { createHash as createHash4 } from "node:crypto";
154795
+ function normalizedQueryHash(query) {
154796
+ const normalized = query.trim().replace(/\s+/g, " ").toLowerCase();
154797
+ return createHash4("sha256").update(normalized).digest("hex");
154798
+ }
154799
+ function recordEmbeddingMeasurement(db, input) {
154800
+ const queryTextHash = normalizedQueryHash(input.queryText);
154801
+ const dedupKey = queryTextHash;
154802
+ const result = db.prepare(`INSERT OR IGNORE INTO embedding_measurement_corpus
154803
+ (session_id, project_path, dedup_key, cohort_key, query_text_hash,
154804
+ primary_result_ids_json, shadow_result_ids_json, primary_latency_ms, shadow_latency_ms,
154805
+ primary_failed, shadow_failed, primary_model_id, shadow_model_id,
154806
+ primary_fingerprint, shadow_fingerprint, primary_epoch, shadow_epoch,
154807
+ corpus_hash, coverage_json, created_at)
154808
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(input.sessionId, input.projectPath, dedupKey, input.cohortKey, queryTextHash, JSON.stringify(input.primaryResultIds.slice(0, 10)), JSON.stringify(input.shadowResultIds.slice(0, 10)), input.primaryLatencyMs, input.shadowLatencyMs, input.primaryFailed ? 1 : 0, input.shadowFailed ? 1 : 0, input.primaryModelId, input.shadowModelId, input.primaryFingerprint, input.shadowFingerprint, input.primaryEpoch, input.shadowEpoch, input.corpusHash, JSON.stringify(input.coverage), Date.now());
154809
+ return result.changes > 0;
154810
+ }
154811
+ function beginSynapseBatchLedger(db, input) {
154812
+ const now = Date.now();
154813
+ db.prepare(`INSERT INTO synapse_batch_ledger
154814
+ (session_id, project_path, scope, manifest_json, request_key, status, created_at, updated_at)
154815
+ VALUES (?, ?, ?, ?, ?, 'pending', ?, ?)
154816
+ ON CONFLICT(session_id, request_key) DO UPDATE SET
154817
+ manifest_json = excluded.manifest_json,
154818
+ updated_at = excluded.updated_at`).run(input.sessionId, input.projectPath, input.scope, JSON.stringify(input.manifest), input.requestKey, now, now);
154819
+ }
154820
+ function finishSynapseBatchLedger(db, sessionId, requestKey, status) {
154821
+ db.prepare("UPDATE synapse_batch_ledger SET status = ?, updated_at = ? WHERE session_id = ? AND request_key = ?").run(status, Date.now(), sessionId, requestKey);
154822
+ }
154502
154823
  // ../plugin/src/features/magic-context/storage-m0-mutation-log.ts
154503
154824
  var M0_MUTATION_TYPES = new Set([
154504
154825
  "compartment_delete",
@@ -154658,6 +154979,7 @@ function getMaxMemoryMutationIdForProjects(db, projectPaths) {
154658
154979
  }
154659
154980
  // ../plugin/src/features/magic-context/storage-meta-persisted.ts
154660
154981
  init_logger();
154982
+ var emergencyRecoveryArmedSessions = new Set;
154661
154983
  var CAS_RETRY_LIMIT = 5;
154662
154984
  var AUTO_SEARCH_NO_HINT_REASONS = new Set([
154663
154985
  "below-threshold",
@@ -155379,6 +155701,7 @@ function getOverflowState(db, sessionId, modelKey) {
155379
155701
  };
155380
155702
  }
155381
155703
  function recordOverflowDetected(db, sessionId, reportedLimit, modelKey, origin = "provider_overflow") {
155704
+ emergencyRecoveryArmedSessions.add(sessionId);
155382
155705
  db.transaction(() => {
155383
155706
  ensureSessionMetaRow(db, sessionId);
155384
155707
  if (typeof reportedLimit === "number" && reportedLimit > 0) {
@@ -155397,6 +155720,7 @@ function clearEmergencyRecovery(db, sessionId) {
155397
155720
  db.prepare("UPDATE session_meta SET needs_emergency_recovery = 0, emergency_recovery_origin = '' WHERE session_id = ?").run(sessionId);
155398
155721
  }
155399
155722
  })();
155723
+ emergencyRecoveryArmedSessions.delete(sessionId);
155400
155724
  }
155401
155725
  function clearDetectedContextLimit(db, sessionId) {
155402
155726
  db.transaction(() => {
@@ -156902,7 +157226,7 @@ var ERROR_CLASSES = new Set([
156902
157226
  ]);
156903
157227
  // ../plugin/src/features/magic-context/v22-deferred-backfill.ts
156904
157228
  init_logger();
156905
- import { createHash as createHash4 } from "node:crypto";
157229
+ import { createHash as createHash5 } from "node:crypto";
156906
157230
  import { realpathSync as realpathSync2 } from "node:fs";
156907
157231
  import path5 from "node:path";
156908
157232
 
@@ -156964,7 +157288,7 @@ function computeLegacyRustDirIdentity(rawProjectPath) {
156964
157288
  } catch {
156965
157289
  canonical = path5.isAbsolute(rawProjectPath) ? rawProjectPath : path5.join(process.cwd(), rawProjectPath);
156966
157290
  }
156967
- return `dir:${createHash4("sha256").update(canonical, "utf8").digest("hex")}`;
157291
+ return `dir:${createHash5("sha256").update(canonical, "utf8").digest("hex")}`;
156968
157292
  }
156969
157293
  function upsertRekeyMap(db, oldProjectPath, newProjectPath, rekeyedAt) {
156970
157294
  db.prepare(`INSERT INTO v22_identity_rekey_map (old_project_path, new_project_path, rekeyed_at)
@@ -157456,7 +157780,7 @@ function clearNoteNudgeTriggerOnly(db, sessionId) {
157456
157780
  }
157457
157781
 
157458
157782
  // ../plugin/src/hooks/magic-context/todo-view.ts
157459
- import { createHash as createHash5 } from "node:crypto";
157783
+ import { createHash as createHash6 } from "node:crypto";
157460
157784
  var TODO_STATUS_PENDING = "pending";
157461
157785
  var TODO_STATUS_IN_PROGRESS = "in_progress";
157462
157786
  var TODO_STATUS_COMPLETED = "completed";
@@ -157524,7 +157848,7 @@ function buildSyntheticTodoPart(stateJson) {
157524
157848
  };
157525
157849
  }
157526
157850
  function computeSyntheticCallId(stateJson) {
157527
- const hash = createHash5("sha256").update(stateJson).digest("hex").slice(0, 16);
157851
+ const hash = createHash6("sha256").update(stateJson).digest("hex").slice(0, 16);
157528
157852
  return `${SYNTHETIC_CALL_ID_PREFIX}${hash}`;
157529
157853
  }
157530
157854
  function parseTodoState(stateJson) {
@@ -159225,26 +159549,32 @@ init_logger();
159225
159549
  // ../plugin/src/features/magic-context/compaction-marker.ts
159226
159550
  init_data_path();
159227
159551
  init_logger();
159552
+ import { createHash as createHash7 } from "node:crypto";
159228
159553
  import { existsSync as existsSync10 } from "node:fs";
159229
159554
  import { join as join9 } from "node:path";
159230
159555
  var BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
159231
- function randomBase62(length) {
159232
- const chars = [];
159233
- for (let i = 0;i < length; i++) {
159234
- chars.push(BASE62_CHARS[Math.floor(Math.random() * BASE62_CHARS.length)]);
159556
+ var ID_PREFIX_HEX_LENGTH = 12;
159557
+ var ID_SUFFIX_LENGTH = 14;
159558
+ var ID_PREFIX_MASK = (1n << BigInt(ID_PREFIX_HEX_LENGTH * 4)) - 1n;
159559
+ function deterministicBase62(seed, length) {
159560
+ let value = BigInt(`0x${createHash7("sha256").update(seed).digest("hex")}`);
159561
+ const chars = Array(length);
159562
+ for (let index = length - 1;index >= 0; index -= 1) {
159563
+ chars[index] = BASE62_CHARS[Number(value % 62n)];
159564
+ value /= 62n;
159235
159565
  }
159236
159566
  return chars.join("");
159237
159567
  }
159238
- function generateId(prefix, timestampMs, counter = 0n) {
159239
- const encoded = BigInt(timestampMs) * 0x1000n + counter;
159240
- const hex = encoded.toString(16).padStart(14, "0");
159241
- return `${prefix}_${hex}${randomBase62(14)}`;
159568
+ function generateId(prefix, timestampMs, counter, identity) {
159569
+ const encoded = BigInt(Math.max(0, Math.floor(timestampMs))) * 0x1000n + counter & ID_PREFIX_MASK;
159570
+ const hex = encoded.toString(16).padStart(ID_PREFIX_HEX_LENGTH, "0");
159571
+ return `${prefix}_${hex}${deterministicBase62(`${prefix}\x00${identity}`, ID_SUFFIX_LENGTH)}`;
159242
159572
  }
159243
- function generateMessageId(timestampMs, counter = 0n) {
159244
- return generateId("msg", timestampMs, counter);
159573
+ function generateMessageId(timestampMs, counter = 0n, identity = "") {
159574
+ return generateId("msg", timestampMs, counter, identity);
159245
159575
  }
159246
- function generatePartId(timestampMs, counter = 0n) {
159247
- return generateId("prt", timestampMs, counter);
159576
+ function generatePartId(timestampMs, counter = 0n, identity = "") {
159577
+ return generateId("prt", timestampMs, counter, identity);
159248
159578
  }
159249
159579
  function getOpenCodeDbPath2() {
159250
159580
  return join9(getDataDir(), "opencode", "opencode.db");
@@ -159349,6 +159679,38 @@ function compareOpenCodeMessagesByCanonicalOrder(sessionId, leftMessageId, right
159349
159679
  return 1;
159350
159680
  return 0;
159351
159681
  }
159682
+ function removeLegacyMarkerLineageRows(db, args) {
159683
+ const legacySummaries = db.prepare(`SELECT m.id
159684
+ FROM message m
159685
+ WHERE m.session_id = ?
159686
+ AND m.id <> ?
159687
+ AND COALESCE(json_extract(m.data, '$.summary'), 0) = 1
159688
+ AND COALESCE(json_extract(m.data, '$.finish'), '') = 'stop'
159689
+ AND COALESCE(json_extract(m.data, '$.parentID'), '') = ?
159690
+ AND EXISTS (
159691
+ SELECT 1
159692
+ FROM part p
159693
+ WHERE p.session_id = m.session_id
159694
+ AND p.message_id = m.id
159695
+ AND COALESCE(json_extract(p.data, '$.type'), '') = 'text'
159696
+ AND COALESCE(json_extract(p.data, '$.text'), '') = ?
159697
+ )`).all(args.sessionId, args.summaryMessageId, args.boundaryMessageId, args.summaryText);
159698
+ const legacySummaryIds = legacySummaries.flatMap((row) => typeof row.id === "string" ? [row.id] : []);
159699
+ if (legacySummaryIds.length === 0)
159700
+ return;
159701
+ const deleteSummaryParts = db.prepare("DELETE FROM part WHERE session_id = ? AND message_id = ?");
159702
+ const deleteSummary = db.prepare("DELETE FROM message WHERE session_id = ? AND id = ?");
159703
+ for (const summaryMessageId of legacySummaryIds) {
159704
+ deleteSummaryParts.run(args.sessionId, summaryMessageId);
159705
+ deleteSummary.run(args.sessionId, summaryMessageId);
159706
+ }
159707
+ db.prepare(`DELETE FROM part
159708
+ WHERE session_id = ?
159709
+ AND message_id = ?
159710
+ AND id <> ?
159711
+ AND COALESCE(json_extract(data, '$.type'), '') = 'compaction'
159712
+ AND COALESCE(json_extract(data, '$.auto'), 0) = 1`).run(args.sessionId, args.boundaryMessageId, args.compactionPartId);
159713
+ }
159352
159714
  function injectCompactionMarker(args) {
159353
159715
  const db = getWritableOpenCodeDb();
159354
159716
  if (!isOpenCodeSchemaCompatible(db, getOpenCodeDbPath2())) {
@@ -159360,9 +159722,10 @@ function injectCompactionMarker(args) {
159360
159722
  return null;
159361
159723
  }
159362
159724
  const boundaryTime = boundary.timeCreated;
159363
- const summaryMsgId = generateMessageId(boundaryTime + 1, 1n);
159364
- const compactionPartId = generatePartId(boundaryTime, 1n);
159365
- const summaryPartId = generatePartId(boundaryTime + 1, 2n);
159725
+ const markerIdentity = `${args.sessionId}\x00${args.endMessageId}`;
159726
+ const summaryMsgId = generateMessageId(boundaryTime + 1, 1n, `${markerIdentity}\x00summary-message`);
159727
+ const compactionPartId = generatePartId(boundaryTime, 1n, `${markerIdentity}\x00compaction-part`);
159728
+ const summaryPartId = generatePartId(boundaryTime + 1, 2n, `${markerIdentity}\x00summary-part`);
159366
159729
  const summaryMsgData = JSON.stringify({
159367
159730
  role: "assistant",
159368
159731
  parentID: boundary.id,
@@ -159379,9 +159742,36 @@ function injectCompactionMarker(args) {
159379
159742
  });
159380
159743
  try {
159381
159744
  db.transaction(() => {
159382
- db.prepare("INSERT INTO part (id, message_id, session_id, time_created, time_updated, data) VALUES (?, ?, ?, ?, ?, ?)").run(compactionPartId, boundary.id, args.sessionId, boundaryTime, boundaryTime, '{"type":"compaction","auto":true}');
159383
- db.prepare("INSERT INTO message (id, session_id, time_created, time_updated, data) VALUES (?, ?, ?, ?, ?)").run(summaryMsgId, args.sessionId, boundaryTime + 1, boundaryTime + 1, summaryMsgData);
159384
- db.prepare("INSERT INTO part (id, message_id, session_id, time_created, time_updated, data) VALUES (?, ?, ?, ?, ?, ?)").run(summaryPartId, summaryMsgId, args.sessionId, boundaryTime + 1, boundaryTime + 1, JSON.stringify({ type: "text", text: args.summaryText }));
159745
+ removeLegacyMarkerLineageRows(db, {
159746
+ sessionId: args.sessionId,
159747
+ boundaryMessageId: boundary.id,
159748
+ summaryText: args.summaryText,
159749
+ summaryMessageId: summaryMsgId,
159750
+ compactionPartId
159751
+ });
159752
+ db.prepare(`INSERT INTO part (id, message_id, session_id, time_created, time_updated, data)
159753
+ VALUES (?, ?, ?, ?, ?, ?)
159754
+ ON CONFLICT(id) DO UPDATE SET
159755
+ message_id = excluded.message_id,
159756
+ session_id = excluded.session_id,
159757
+ time_created = excluded.time_created,
159758
+ time_updated = excluded.time_updated,
159759
+ data = excluded.data`).run(compactionPartId, boundary.id, args.sessionId, boundaryTime, boundaryTime, '{"type":"compaction","auto":true}');
159760
+ db.prepare(`INSERT INTO message (id, session_id, time_created, time_updated, data)
159761
+ VALUES (?, ?, ?, ?, ?)
159762
+ ON CONFLICT(id) DO UPDATE SET
159763
+ session_id = excluded.session_id,
159764
+ time_created = excluded.time_created,
159765
+ time_updated = excluded.time_updated,
159766
+ data = excluded.data`).run(summaryMsgId, args.sessionId, boundaryTime + 1, boundaryTime + 1, summaryMsgData);
159767
+ db.prepare(`INSERT INTO part (id, message_id, session_id, time_created, time_updated, data)
159768
+ VALUES (?, ?, ?, ?, ?, ?)
159769
+ ON CONFLICT(id) DO UPDATE SET
159770
+ message_id = excluded.message_id,
159771
+ session_id = excluded.session_id,
159772
+ time_created = excluded.time_created,
159773
+ time_updated = excluded.time_updated,
159774
+ data = excluded.data`).run(summaryPartId, summaryMsgId, args.sessionId, boundaryTime + 1, boundaryTime + 1, JSON.stringify({ type: "text", text: args.summaryText }));
159385
159775
  })();
159386
159776
  log(`[magic-context] compaction-marker: injected boundary at user msg ${boundary.id} (ordinal ~${args.endOrdinal}), summary msg ${summaryMsgId}`);
159387
159777
  return {
@@ -159428,7 +159818,7 @@ function openOpenCodeDb() {
159428
159818
  }
159429
159819
 
159430
159820
  // ../plugin/src/features/magic-context/dreamer/task-executor.ts
159431
- import { createHash as createHash10 } from "node:crypto";
159821
+ import { createHash as createHash13 } from "node:crypto";
159432
159822
  import { existsSync as existsSync15 } from "node:fs";
159433
159823
 
159434
159824
  // ../plugin/src/agents/dreamer.ts
@@ -159819,6 +160209,9 @@ function parseFields(json) {
159819
160209
  } catch {}
159820
160210
  return {};
159821
160211
  }
160212
+ // ../plugin/src/config/schema/magic-context.ts
160213
+ import { homedir as homedir3 } from "node:os";
160214
+
159822
160215
  // ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
159823
160216
  var exports_external = {};
159824
160217
  __export(exports_external, {
@@ -174342,8 +174735,18 @@ var HistorianConfigSchema = AgentOverrideConfigSchema.extend({
174342
174735
  thinking_level: PiThinkingLevelSchema.describe("Pi only: explicit thinking level passed as --thinking <level> to Pi historian subagent invocations. Required when using reasoning models (e.g. github-copilot/gpt-5.4) because Pi's default thinking-level resolution can pick a value the provider rejects. OpenCode users set variant instead. Valid: off | minimal | low | medium | high | xhigh"),
174343
174736
  disallowed_tools: exports_external.array(exports_external.enum(["*", "read", "aft_outline", "aft_zoom", "aft_search"])).default([]).describe(`OpenCode only. Tools to REMOVE from the historian's default allow-list [read, aft_outline, aft_zoom, aft_search]. Applies to both historian and historian-editor agents. Use ["*"] to strip all tool definitions from the model request — this prevents weak instruction-following models (e.g. mistral-small-latest) from entering tool-calling loops. Individual tool names remove just that tool. Note: a user-supplied historian.permission override can re-allow a tool that disallowed_tools removed — disallowed_tools sets the baseline, permission overrides take precedence. (default: [])`)
174344
174737
  }).optional();
174738
+ var EmbeddingFallbackProviderSchema = exports_external.enum(["local", "openai-compatible", "off"]);
174739
+ function expandConfigPath(value) {
174740
+ const trimmed = value.trim();
174741
+ if (trimmed === "~")
174742
+ return homedir3();
174743
+ if (trimmed.startsWith("~/"))
174744
+ return `${homedir3()}/${trimmed.slice(2)}`;
174745
+ return trimmed;
174746
+ }
174345
174747
  var BaseEmbeddingConfigSchema = exports_external.object({
174346
- provider: exports_external.enum(["local", "openai-compatible", "off"]).default("local").describe("Embedding provider. 'local' uses Xenova/all-MiniLM-L6-v2, 'openai-compatible' requires endpoint and model, 'off' disables embeddings."),
174748
+ provider: exports_external.enum(["local", "openai-compatible", "off", "synapse"]).default("local").describe("Embedding provider. 'local' uses Xenova/all-MiniLM-L6-v2, 'openai-compatible' requires endpoint and model, 'synapse' uses the certified local Synapse lane with an explicit fallback provider, and 'off' disables embeddings."),
174749
+ fallback_provider: EmbeddingFallbackProviderSchema.optional().describe("Fallback provider for the Synapse lane. Required when provider is 'synapse'; local, openai-compatible, and off are valid."),
174347
174750
  model: exports_external.string().optional().describe("Embedding model name. Required for openai-compatible, ignored for local."),
174348
174751
  endpoint: exports_external.string().optional().describe("API endpoint URL. Required when provider is openai-compatible."),
174349
174752
  api_key: exports_external.string().optional().describe("API key for remote embedding provider (optional)"),
@@ -174352,14 +174755,15 @@ var BaseEmbeddingConfigSchema = exports_external.object({
174352
174755
  truncate: exports_external.string().optional().describe("Optional truncate mode sent in the embedding request body (e.g. NVIDIA NIM accepts 'NONE' | 'START' | 'END'). Omitted from the request when unset."),
174353
174756
  max_input_tokens: exports_external.number().int().positive().optional().describe("Optional maximum input tokens for chunk embeddings. Defaults conservatively to 512 when omitted.")
174354
174757
  }).superRefine((data, ctx) => {
174355
- if (data.provider === "openai-compatible" && !data.endpoint?.trim()) {
174758
+ const validationProvider = data.provider === "synapse" ? data.fallback_provider : data.provider;
174759
+ if (validationProvider === "openai-compatible" && !data.endpoint?.trim()) {
174356
174760
  ctx.addIssue({
174357
174761
  code: "custom",
174358
174762
  path: ["endpoint"],
174359
174763
  message: "endpoint is required when embedding.provider is openai-compatible"
174360
174764
  });
174361
174765
  }
174362
- if (data.provider === "openai-compatible" && !data.model?.trim()) {
174766
+ if (validationProvider === "openai-compatible" && !data.model?.trim()) {
174363
174767
  ctx.addIssue({
174364
174768
  code: "custom",
174365
174769
  path: ["model"],
@@ -174368,6 +174772,25 @@ var BaseEmbeddingConfigSchema = exports_external.object({
174368
174772
  }
174369
174773
  });
174370
174774
  var EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data) => {
174775
+ if (data.provider === "synapse") {
174776
+ const model = data.model?.trim();
174777
+ const endpoint = data.endpoint?.trim();
174778
+ const apiKey = data.api_key?.trim();
174779
+ const inputType = data.input_type?.trim();
174780
+ const queryInputType = data.query_input_type?.trim();
174781
+ const truncate = data.truncate?.trim();
174782
+ return {
174783
+ provider: "synapse",
174784
+ ...data.fallback_provider ? { fallback_provider: data.fallback_provider } : {},
174785
+ ...model ? { model } : {},
174786
+ ...endpoint ? { endpoint } : {},
174787
+ ...apiKey ? { api_key: apiKey } : {},
174788
+ ...inputType ? { input_type: inputType } : {},
174789
+ ...queryInputType ? { query_input_type: queryInputType } : {},
174790
+ ...truncate ? { truncate } : {},
174791
+ ...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}
174792
+ };
174793
+ }
174371
174794
  if (data.provider === "local") {
174372
174795
  return {
174373
174796
  provider: "local",
@@ -174395,6 +174818,7 @@ var EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data) => {
174395
174818
  });
174396
174819
  var MagicContextConfigSchema = exports_external.object({
174397
174820
  enabled: exports_external.boolean().default(true).describe("Enable magic context (default: true)"),
174821
+ transform_mode: exports_external.enum(["ts", "rust"]).default("ts").describe('Experimental: routes the entire Magic Context runtime for the project through the ck-mc Rust module over subc (requires user-level `subc` config); "ts" is the current TypeScript pipeline.'),
174398
174822
  auto_update: exports_external.boolean().optional().describe("Enable automatic npm self-update checks for the OpenCode plugin. Security: USER-only in config loader, so hostile project configs cannot suppress updates."),
174399
174823
  language: exports_external.string().trim().toLowerCase().refine((s) => isValidLanguageCode(s), 'language must be a 2-letter ISO 639-1 code (e.g. "tr", "es", "de")').optional().describe("Output language for Magic Context's generated content and guidance, as a " + '2-letter ISO 639-1 code (e.g. "tr", "es", "de", "ja", "pt"). When set, the ' + "historian, dreamer, sidekick, and the agent-guidance block instruct the model to " + "write its PROSE in this language while keeping all structural tokens (XML tags, " + "the five memory category names, code identifiers, file paths) in English. " + "USER-LEVEL ONLY (ignored in project config for security). Unset = today's " + "behavior (model mirrors the conversation; English scaffolding). Changing it " + "triggers one cache re-materialization; existing compartments/memories keep their " + "original language until naturally rewritten."),
174400
174824
  historian: HistorianConfigSchema.describe("Historian agent configuration (model, fallback_models, variant, temperature, maxTokens, permission, two_pass, etc.)"),
@@ -174431,6 +174855,12 @@ var MagicContextConfigSchema = exports_external.object({
174431
174855
  provider: "local",
174432
174856
  model: DEFAULT_LOCAL_EMBEDDING_MODEL
174433
174857
  }).describe("Embedding provider configuration"),
174858
+ subc: exports_external.object({
174859
+ connection_file: exports_external.string().trim().min(1).transform(expandConfigPath).describe("Path to the owner-only subc connection file.")
174860
+ }).optional().describe("User-only Synapse daemon connection settings."),
174861
+ shadow_embedding: exports_external.object({
174862
+ enabled: exports_external.boolean().default(false).describe("Developer-only Synapse shadow embedding lane switch.")
174863
+ }).default({ enabled: false }).describe("Developer-only Synapse shadow embedding lane."),
174434
174864
  temporal_awareness: exports_external.boolean().default(true).describe('Inject wall-clock gap markers (<!-- +Xm -->) between user messages where > 5 min elapsed since the previous message, and add compact date ranges to compartment headings. Gives the agent a sense of session pacing and "how long ago" across multi-day sessions. Graduated from experimental.temporal_awareness; default: true (set false to opt out).'),
174435
174865
  keep_subagents: exports_external.boolean().default(false).describe("Debug: keep the child sessions Magic Context spawns for its own subagents (historian, dreamer, sidekick, memory-migration) instead of deleting them on success. Useful for short-term inspection/data collection — their full transcript (prompt, tool calls, token usage, output) stays in the host session store. Kept sessions accumulate until manually cleared; leave false for normal use. Requires a restart to take effect."),
174436
174866
  shadow_transform: exports_external.object({
@@ -174480,7 +174910,7 @@ var MagicContextConfigSchema = exports_external.object({
174480
174910
  init_logger();
174481
174911
 
174482
174912
  // ../plugin/src/features/magic-context/compartment-chunk-embedding.ts
174483
- import { createHash as createHash6 } from "node:crypto";
174913
+ import { createHash as createHash8 } from "node:crypto";
174484
174914
  init_logger();
174485
174915
 
174486
174916
  // ../plugin/src/features/magic-context/recursive-text-splitter.ts
@@ -174692,7 +175122,7 @@ function parseCanonicalLineRange(line) {
174692
175122
  return { start, end };
174693
175123
  }
174694
175124
  function hashChunkText(text) {
174695
- return createHash6("sha256").update(text).digest("hex");
175125
+ return createHash8("sha256").update(text).digest("hex");
174696
175126
  }
174697
175127
  function vectorBlob2(vector) {
174698
175128
  return new Uint8Array(vector.buffer, vector.byteOffset, vector.byteLength);
@@ -175084,14 +175514,2634 @@ function cosineSimilarity(a, b) {
175084
175514
  return denominator === 0 ? 0 : dotProduct / denominator;
175085
175515
  }
175086
175516
 
175517
+ // ../plugin/src/features/magic-context/memory/embedding-synapse.ts
175518
+ import { createHash as createHash9 } from "node:crypto";
175519
+
175520
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/client.js
175521
+ import { promises as fs4 } from "node:fs";
175522
+ import { debuglog } from "node:util";
175523
+
175524
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/auth.js
175525
+ import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
175526
+ var NONCE_LEN = 32;
175527
+ var MAX_AUTH_MESSAGE_LEN = 4096;
175528
+ var SERVER_PROOF_DOMAIN = "subc-server-v1";
175529
+ var CLIENT_AUTH_DOMAIN = "subc-client-v1";
175530
+ var DEFAULT_CLIENT_ROLE = "client";
175531
+
175532
+ class AuthError extends Error {
175533
+ }
175534
+ function computeProof(key, domain2, clientNonce, serverNonce, daemonId) {
175535
+ const mac3 = createHmac("sha256", Buffer.from(key));
175536
+ mac3.update(Buffer.from(domain2, "utf8"));
175537
+ mac3.update(Buffer.from(clientNonce));
175538
+ mac3.update(Buffer.from(serverNonce));
175539
+ mac3.update(Buffer.from(daemonId));
175540
+ return new Uint8Array(mac3.digest());
175541
+ }
175542
+ function constantTimeEq(a, b) {
175543
+ if (a.length !== b.length)
175544
+ return false;
175545
+ return timingSafeEqual(Buffer.from(a), Buffer.from(b));
175546
+ }
175547
+ async function writeMessage(sock, value, deadlineMs) {
175548
+ const json2 = Buffer.from(JSON.stringify(value), "utf8");
175549
+ if (json2.length > MAX_AUTH_MESSAGE_LEN) {
175550
+ throw new AuthError(`auth message too large: ${json2.length} > ${MAX_AUTH_MESSAGE_LEN}`);
175551
+ }
175552
+ const lenPrefix = new Uint8Array(4);
175553
+ new DataView(lenPrefix.buffer).setUint32(0, json2.length, true);
175554
+ await sock.write(lenPrefix, deadlineMs);
175555
+ await sock.write(json2, deadlineMs);
175556
+ }
175557
+ async function readMessage(sock, deadlineMs) {
175558
+ const lenBytes = await sock.readExact(4, deadlineMs);
175559
+ const len = new DataView(lenBytes.buffer, lenBytes.byteOffset, 4).getUint32(0, true);
175560
+ if (len > MAX_AUTH_MESSAGE_LEN) {
175561
+ throw new AuthError(`auth message too large: ${len} > ${MAX_AUTH_MESSAGE_LEN}`);
175562
+ }
175563
+ const body = len === 0 ? new Uint8Array(0) : await sock.readExact(len, deadlineMs);
175564
+ try {
175565
+ return JSON.parse(Buffer.from(body).toString("utf8"));
175566
+ } catch (err) {
175567
+ throw new AuthError(`auth message JSON decode failed: ${String(err)}`);
175568
+ }
175569
+ }
175570
+ async function authenticateClient(sock, conn, deadlineMs) {
175571
+ const clientNonce = new Uint8Array(randomBytes(NONCE_LEN));
175572
+ await writeMessage(sock, { client_nonce: Array.from(clientNonce), role: DEFAULT_CLIENT_ROLE }, deadlineMs);
175573
+ const proof = await readMessage(sock, deadlineMs);
175574
+ const serverNonce = Uint8Array.from(proof.server_nonce);
175575
+ const daemonId = Uint8Array.from(proof.daemon_id);
175576
+ const serverProof = Uint8Array.from(proof.server_proof);
175577
+ const expected = computeProof(conn.key, SERVER_PROOF_DOMAIN, clientNonce, serverNonce, daemonId);
175578
+ if (!constantTimeEq(expected, serverProof)) {
175579
+ throw new AuthError("server proof mismatch — wrong key or impostor daemon");
175580
+ }
175581
+ if (!constantTimeEq(daemonId, conn.daemonId)) {
175582
+ throw new AuthError("daemon id mismatch — connection file points at a different daemon");
175583
+ }
175584
+ const clientAuth = computeProof(conn.key, CLIENT_AUTH_DOMAIN, clientNonce, serverNonce, daemonId);
175585
+ await writeMessage(sock, { client_auth: Array.from(clientAuth) }, deadlineMs);
175586
+ }
175587
+
175588
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/connection-file.js
175589
+ import { promises as fs3 } from "node:fs";
175590
+ var SCHEMA_VERSION = 1;
175591
+ var MIN_KEY_LEN = 32;
175592
+ var DAEMON_ID_LEN = 16;
175593
+
175594
+ class ConnectionFileError extends Error {
175595
+ }
175596
+ function toBytes(value, field) {
175597
+ if (!Array.isArray(value) || value.some((n) => typeof n !== "number")) {
175598
+ throw new ConnectionFileError(`connection file field '${field}' must be a JSON array of bytes`);
175599
+ }
175600
+ return Uint8Array.from(value);
175601
+ }
175602
+ function validate(info) {
175603
+ if (info.schema !== SCHEMA_VERSION) {
175604
+ throw new ConnectionFileError(`unsupported connection file schema ${info.schema}; expected ${SCHEMA_VERSION}`);
175605
+ }
175606
+ if (info.endpoints.length === 0) {
175607
+ throw new ConnectionFileError("connection file must include at least one endpoint");
175608
+ }
175609
+ if (info.key.length < MIN_KEY_LEN) {
175610
+ throw new ConnectionFileError(`connection file key is too short: ${info.key.length} bytes, need at least ${MIN_KEY_LEN}`);
175611
+ }
175612
+ if (info.daemonId.length !== DAEMON_ID_LEN) {
175613
+ throw new ConnectionFileError(`connection file daemon_id must be ${DAEMON_ID_LEN} bytes, got ${info.daemonId.length}`);
175614
+ }
175615
+ }
175616
+ async function verifyOwnerOnly(path7) {
175617
+ if (process.platform === "win32")
175618
+ return;
175619
+ const stat = await fs3.stat(path7);
175620
+ const mode = stat.mode & 511;
175621
+ if ((mode & 63) !== 0) {
175622
+ throw new ConnectionFileError(`connection file ${path7} has insecure permissions 0o${mode.toString(8)}; expected owner-only 0600`);
175623
+ }
175624
+ }
175625
+ async function readConnectionFile(path7) {
175626
+ await verifyOwnerOnly(path7);
175627
+ const raw = await fs3.readFile(path7, "utf8");
175628
+ let parsed;
175629
+ try {
175630
+ parsed = JSON.parse(raw);
175631
+ } catch (err) {
175632
+ throw new ConnectionFileError(`connection file JSON read failed for ${path7}: ${String(err)}`);
175633
+ }
175634
+ const endpointsRaw = parsed.endpoints;
175635
+ if (!Array.isArray(endpointsRaw)) {
175636
+ throw new ConnectionFileError("connection file 'endpoints' must be an array");
175637
+ }
175638
+ const endpoints = endpointsRaw.map((e) => {
175639
+ const ep = e;
175640
+ if (typeof ep.host !== "string" || typeof ep.port !== "number") {
175641
+ throw new ConnectionFileError("connection file endpoint must be { host: string, port: number }");
175642
+ }
175643
+ return { host: ep.host, port: ep.port };
175644
+ });
175645
+ const info = {
175646
+ schema: parsed.schema,
175647
+ endpoints,
175648
+ key: toBytes(parsed.key, "key"),
175649
+ daemonId: toBytes(parsed.daemon_id, "daemon_id"),
175650
+ pid: parsed.pid,
175651
+ daemonVer: parsed.daemon_ver ?? ""
175652
+ };
175653
+ validate(info);
175654
+ return info;
175655
+ }
175656
+
175657
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/envelope.js
175658
+ var PROTOCOL_VERSION = 2;
175659
+ var HEADER_LEN = 21;
175660
+ var FROZEN_PREFIX_LEN = 5;
175661
+ var MAX_FRAME_BODY_LEN = 64 * 1024 * 1024;
175662
+ var FrameType;
175663
+ (function(FrameType2) {
175664
+ FrameType2[FrameType2["Request"] = 0] = "Request";
175665
+ FrameType2[FrameType2["Response"] = 1] = "Response";
175666
+ FrameType2[FrameType2["Push"] = 2] = "Push";
175667
+ FrameType2[FrameType2["StreamData"] = 3] = "StreamData";
175668
+ FrameType2[FrameType2["StreamEnd"] = 4] = "StreamEnd";
175669
+ FrameType2[FrameType2["Error"] = 5] = "Error";
175670
+ FrameType2[FrameType2["Cancel"] = 6] = "Cancel";
175671
+ FrameType2[FrameType2["Ping"] = 7] = "Ping";
175672
+ FrameType2[FrameType2["Pong"] = 8] = "Pong";
175673
+ FrameType2[FrameType2["Hello"] = 9] = "Hello";
175674
+ FrameType2[FrameType2["HelloAck"] = 10] = "HelloAck";
175675
+ FrameType2[FrameType2["Goodbye"] = 11] = "Goodbye";
175676
+ })(FrameType || (FrameType = {}));
175677
+ var FRAME_TYPE_MAX = FrameType.Goodbye;
175678
+ function isPureHeader(ty) {
175679
+ return ty === FrameType.Cancel || ty === FrameType.Ping || ty === FrameType.Pong || ty === FrameType.Goodbye;
175680
+ }
175681
+ var Priority;
175682
+ (function(Priority2) {
175683
+ Priority2[Priority2["Passive"] = 0] = "Passive";
175684
+ Priority2[Priority2["Interactive"] = 1] = "Interactive";
175685
+ Priority2[Priority2["Background"] = 2] = "Background";
175686
+ })(Priority || (Priority = {}));
175687
+ var AdmissionClass;
175688
+ (function(AdmissionClass2) {
175689
+ AdmissionClass2[AdmissionClass2["Normal"] = 0] = "Normal";
175690
+ AdmissionClass2[AdmissionClass2["Expedite"] = 1] = "Expedite";
175691
+ AdmissionClass2[AdmissionClass2["Sheddable"] = 2] = "Sheddable";
175692
+ })(AdmissionClass || (AdmissionClass = {}));
175693
+ var FLAG_BINARY = 1;
175694
+ var FLAG_PRIORITY_MASK = 6;
175695
+ var FLAG_PRIORITY_SHIFT = 1;
175696
+ var FLAG_LAST = 8;
175697
+ var FLAG_ADMISSION_MASK = 48;
175698
+ var FLAG_ADMISSION_SHIFT = 4;
175699
+ var FLAG_RESERVED_MASK = 192;
175700
+ function buildFlags(binary, priority, last, admissionClass = AdmissionClass.Normal) {
175701
+ let flags = 0;
175702
+ if (binary)
175703
+ flags |= FLAG_BINARY;
175704
+ flags |= priority << FLAG_PRIORITY_SHIFT;
175705
+ if (last)
175706
+ flags |= FLAG_LAST;
175707
+ flags |= admissionClass << FLAG_ADMISSION_SHIFT;
175708
+ return flags;
175709
+ }
175710
+ function encodeHeader(header) {
175711
+ const buffer2 = new Uint8Array(HEADER_LEN);
175712
+ const view = new DataView(buffer2.buffer);
175713
+ view.setUint32(0, header.len, true);
175714
+ buffer2[4] = header.ver;
175715
+ buffer2[5] = header.ty;
175716
+ buffer2[6] = header.flags;
175717
+ view.setUint16(7, header.channel, true);
175718
+ view.setUint32(9, header.epoch, true);
175719
+ view.setBigUint64(13, header.corr, true);
175720
+ return buffer2;
175721
+ }
175722
+
175723
+ class DecodeError extends Error {
175724
+ code;
175725
+ constructor(message, code) {
175726
+ super(message);
175727
+ this.code = code;
175728
+ this.name = "DecodeError";
175729
+ }
175730
+ }
175731
+ function decodeHeader(bytes) {
175732
+ if (bytes.length < FROZEN_PREFIX_LEN) {
175733
+ throw new DecodeError(`header shorter than frozen prefix: have ${bytes.length} bytes`, "too_short_for_prefix");
175734
+ }
175735
+ const ver = bytes[4];
175736
+ if (ver !== PROTOCOL_VERSION)
175737
+ throw new DecodeError(`unsupported envelope version ${ver}`, "unsupported_version");
175738
+ if (bytes.length < HEADER_LEN) {
175739
+ throw new DecodeError(`header too short for version: have ${bytes.length} bytes, need ${HEADER_LEN}`, "too_short_for_header");
175740
+ }
175741
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
175742
+ const len = view.getUint32(0, true);
175743
+ const typeByte = bytes[5];
175744
+ if (typeByte > FRAME_TYPE_MAX)
175745
+ throw new DecodeError(`unknown frame type byte ${typeByte}`, "unknown_frame_type");
175746
+ const ty = typeByte;
175747
+ const flags = bytes[6];
175748
+ if ((flags & FLAG_RESERVED_MASK) !== 0) {
175749
+ throw new DecodeError(`reserved flag bits set in flags 0b${flags.toString(2).padStart(8, "0")}`, "reserved_flag_bits");
175750
+ }
175751
+ if ((flags & FLAG_PRIORITY_MASK) >> FLAG_PRIORITY_SHIFT === 3) {
175752
+ throw new DecodeError(`reserved priority bits set in flags 0b${flags.toString(2).padStart(8, "0")}`, "reserved_priority_bits");
175753
+ }
175754
+ const admission = (flags & FLAG_ADMISSION_MASK) >> FLAG_ADMISSION_SHIFT;
175755
+ if (admission === 3) {
175756
+ throw new DecodeError(`reserved admission class set in flags 0b${flags.toString(2).padStart(8, "0")}`, "reserved_admission_class");
175757
+ }
175758
+ if (admission === AdmissionClass.Sheddable && ty !== FrameType.Push && ty !== FrameType.StreamData) {
175759
+ throw new DecodeError(`SHEDDABLE admission class is illegal on ${FrameType[ty]} in flags 0b${flags.toString(2).padStart(8, "0")}`, "sheddable_illegal_frame_type");
175760
+ }
175761
+ const channel = view.getUint16(7, true);
175762
+ const epoch = view.getUint32(9, true);
175763
+ if (channel === 0 && epoch !== 0) {
175764
+ throw new DecodeError(`control channel carried nonzero epoch ${epoch}`, "nonzero_epoch_on_control_channel");
175765
+ }
175766
+ if (isPureHeader(ty) && len !== 0) {
175767
+ throw new DecodeError(`pure-header frame ${FrameType[ty]} declared non-zero body length ${len}`, "pure_header_frame_with_body");
175768
+ }
175769
+ return { len, ver, ty, flags, channel, epoch, corr: view.getBigUint64(13, true) };
175770
+ }
175771
+ function buildFrame(ty, flags, channel, epoch, corr, body) {
175772
+ return buildFrameWithVersion(PROTOCOL_VERSION, ty, flags, channel, epoch, corr, body);
175773
+ }
175774
+ function buildFrameWithVersion(ver, ty, flags, channel, epoch, corr, body) {
175775
+ if (body.length > MAX_FRAME_BODY_LEN) {
175776
+ throw new DecodeError(`frame body ${body.length} exceeds max ${MAX_FRAME_BODY_LEN}`, "frame_body_too_large");
175777
+ }
175778
+ const header = { len: body.length, ver, ty, flags, channel, epoch, corr };
175779
+ decodeHeader(encodeHeader(header));
175780
+ return { header, body };
175781
+ }
175782
+ function encodeFrame(frame) {
175783
+ if (frame.header.len !== frame.body.length) {
175784
+ throw new DecodeError(`frame header length ${frame.header.len} does not match body length ${frame.body.length}`, "frame_length_mismatch");
175785
+ }
175786
+ const header = encodeHeader(frame.header);
175787
+ const output = new Uint8Array(header.length + frame.body.length);
175788
+ output.set(header, 0);
175789
+ output.set(frame.body, header.length);
175790
+ return output;
175791
+ }
175792
+
175793
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/route-handle.js
175794
+ var connectionToken = new WeakMap;
175795
+
175796
+ class RouteHandle {
175797
+ channel;
175798
+ epoch;
175799
+ constructor(channel, epoch, token) {
175800
+ if (!Number.isInteger(channel) || channel <= 0 || channel > 65535) {
175801
+ throw new RangeError(`route channel must be an integer in 1..65535, got ${channel}`);
175802
+ }
175803
+ if (!Number.isInteger(epoch) || epoch <= 0 || epoch > 4294967295) {
175804
+ throw new RangeError(`route epoch must be an integer in 1..4294967295, got ${epoch}`);
175805
+ }
175806
+ this.channel = channel;
175807
+ this.epoch = epoch;
175808
+ connectionToken.set(this, token);
175809
+ Object.freeze(this);
175810
+ }
175811
+ static create(channel, epoch, token) {
175812
+ return new RouteHandle(channel, epoch, token);
175813
+ }
175814
+ }
175815
+ function createRouteHandle(channel, epoch, token) {
175816
+ const factory = RouteHandle;
175817
+ return factory.create(channel, epoch, token);
175818
+ }
175819
+
175820
+ class StaleRouteHandleError extends Error {
175821
+ handle;
175822
+ code = "stale_route_handle";
175823
+ constructor(handle) {
175824
+ super(`route handle (${handle.channel}, ${handle.epoch}) is not live on the current connection`);
175825
+ this.handle = handle;
175826
+ this.name = "StaleRouteHandleError";
175827
+ }
175828
+ }
175829
+ function newConnectionToken() {
175830
+ return Object.freeze({});
175831
+ }
175832
+ function belongsToConnection(handle, token) {
175833
+ return connectionToken.get(handle) === token;
175834
+ }
175835
+ function sameRouteHandle(left, right) {
175836
+ return left === right;
175837
+ }
175838
+
175839
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/socket.js
175840
+ import net from "node:net";
175841
+ class SocketClosedError extends Error {
175842
+ }
175843
+
175844
+ class SocketTimeoutError extends Error {
175845
+ }
175846
+
175847
+ class SocketWriteNotQueuedError extends Error {
175848
+ cause;
175849
+ constructor(message, cause) {
175850
+ super(message);
175851
+ this.cause = cause;
175852
+ }
175853
+ }
175854
+
175855
+ class SocketWriteQueuedError extends Error {
175856
+ cause;
175857
+ constructor(message, cause) {
175858
+ super(message);
175859
+ this.cause = cause;
175860
+ }
175861
+ }
175862
+
175863
+ class SubcSocket {
175864
+ sock;
175865
+ chunks = [];
175866
+ buffered = 0;
175867
+ waiter = null;
175868
+ closedErr = null;
175869
+ bufferedBytes() {
175870
+ return this.buffered;
175871
+ }
175872
+ constructor(sock) {
175873
+ this.sock = sock;
175874
+ sock.on("data", (chunk) => {
175875
+ this.chunks.push(chunk);
175876
+ this.buffered += chunk.length;
175877
+ this.tryServe();
175878
+ });
175879
+ const fail = (err) => {
175880
+ if (!this.closedErr)
175881
+ this.closedErr = err;
175882
+ this.tryServe();
175883
+ };
175884
+ sock.on("error", (err) => fail(err instanceof Error ? err : new Error(String(err))));
175885
+ sock.on("end", () => fail(new SocketClosedError("subc closed the connection")));
175886
+ sock.on("close", () => fail(new SocketClosedError("subc connection closed")));
175887
+ }
175888
+ localPort() {
175889
+ return this.sock.localPort ?? null;
175890
+ }
175891
+ static connect(host, port, deadlineMs) {
175892
+ return new Promise((resolve, reject) => {
175893
+ const sock = net.connect({ host, port });
175894
+ sock.setNoDelay(true);
175895
+ const timer = setTimeout(() => {
175896
+ sock.destroy();
175897
+ reject(new SocketTimeoutError(`timed out connecting to ${host}:${port}`));
175898
+ }, Math.max(0, deadlineMs - Date.now()));
175899
+ sock.once("connect", () => {
175900
+ clearTimeout(timer);
175901
+ resolve(new SubcSocket(sock));
175902
+ });
175903
+ sock.once("error", (err) => {
175904
+ clearTimeout(timer);
175905
+ reject(err);
175906
+ });
175907
+ });
175908
+ }
175909
+ async readFrame(headerDeadlineMs, bodyDeadline, onHeader) {
175910
+ const prefix = await this.readExact(FROZEN_PREFIX_LEN, headerDeadlineMs);
175911
+ const version2 = prefix[4];
175912
+ if (version2 !== PROTOCOL_VERSION)
175913
+ throw new DecodeError(`unsupported envelope version ${version2}`, "unsupported_version");
175914
+ const remainder = await this.readExact(HEADER_LEN - FROZEN_PREFIX_LEN, headerDeadlineMs);
175915
+ const headerBytes = new Uint8Array(HEADER_LEN);
175916
+ headerBytes.set(prefix);
175917
+ headerBytes.set(remainder, FROZEN_PREFIX_LEN);
175918
+ const header = decodeHeader(headerBytes);
175919
+ if (header.len > MAX_FRAME_BODY_LEN) {
175920
+ throw new DecodeError(`frame body ${header.len} exceeds max ${MAX_FRAME_BODY_LEN}`, "frame_body_too_large");
175921
+ }
175922
+ onHeader?.();
175923
+ const bodyDeadlineMs = typeof bodyDeadline === "number" ? bodyDeadline : Date.now() + bodyDeadline.afterHeaderMs;
175924
+ const body = header.len === 0 ? new Uint8Array(0) : await this.readExact(header.len, bodyDeadlineMs);
175925
+ return { header, body };
175926
+ }
175927
+ readExact(n, deadlineMs) {
175928
+ if (this.waiter) {
175929
+ return Promise.reject(new Error("concurrent readExact is not supported"));
175930
+ }
175931
+ if (n === 0)
175932
+ return Promise.resolve(new Uint8Array(0));
175933
+ return new Promise((resolve, reject) => {
175934
+ let timer = null;
175935
+ if (Number.isFinite(deadlineMs)) {
175936
+ const remaining = deadlineMs - Date.now();
175937
+ if (remaining <= 0) {
175938
+ reject(new SocketTimeoutError(`timed out waiting for ${n} bytes`));
175939
+ return;
175940
+ }
175941
+ timer = setTimeout(() => {
175942
+ this.waiter = null;
175943
+ reject(new SocketTimeoutError(`timed out waiting for ${n} bytes`));
175944
+ }, remaining);
175945
+ }
175946
+ this.waiter = { need: n, resolve, reject, timer };
175947
+ this.tryServe();
175948
+ });
175949
+ }
175950
+ async write(bytes, deadlineMs) {
175951
+ try {
175952
+ await this.writeTracked(bytes, deadlineMs).completed;
175953
+ } catch (err) {
175954
+ if (err instanceof SocketWriteNotQueuedError || err instanceof SocketWriteQueuedError) {
175955
+ throw err.cause ?? err;
175956
+ }
175957
+ throw err;
175958
+ }
175959
+ }
175960
+ writeTracked(bytes, deadlineMs) {
175961
+ if (this.closedErr) {
175962
+ return {
175963
+ queued: false,
175964
+ completed: Promise.reject(new SocketWriteNotQueuedError("subc socket was closed before bytes could be queued", this.closedErr))
175965
+ };
175966
+ }
175967
+ let queued = false;
175968
+ let settled = false;
175969
+ let timer = null;
175970
+ const completed = new Promise((resolve, reject) => {
175971
+ const settle = (run) => {
175972
+ if (settled)
175973
+ return;
175974
+ settled = true;
175975
+ if (timer)
175976
+ clearTimeout(timer);
175977
+ run();
175978
+ };
175979
+ const remaining = deadlineMs - Date.now();
175980
+ if (remaining <= 0) {
175981
+ settle(() => reject(new SocketWriteNotQueuedError("timed out before bytes could be queued to subc", new SocketTimeoutError("timed out writing to subc"))));
175982
+ return;
175983
+ }
175984
+ timer = setTimeout(() => {
175985
+ const timeout = new SocketTimeoutError("timed out writing to subc");
175986
+ settle(() => reject(queued ? new SocketWriteQueuedError("timed out after bytes were handed to the subc socket", timeout) : new SocketWriteNotQueuedError("timed out before bytes could be queued to subc", timeout)));
175987
+ }, remaining);
175988
+ try {
175989
+ this.sock.write(Buffer.from(bytes), (err) => {
175990
+ settle(() => {
175991
+ if (err) {
175992
+ reject(new SocketWriteQueuedError("subc socket reported a write error after bytes were handed to the socket", err instanceof Error ? err : new Error(String(err))));
175993
+ } else {
175994
+ resolve();
175995
+ }
175996
+ });
175997
+ });
175998
+ queued = true;
175999
+ } catch (err) {
176000
+ settle(() => reject(new SocketWriteNotQueuedError("subc socket write threw before bytes could be queued", err instanceof Error ? err : new Error(String(err)))));
176001
+ }
176002
+ });
176003
+ return { queued, completed };
176004
+ }
176005
+ close() {
176006
+ this.sock.destroy();
176007
+ }
176008
+ tryServe() {
176009
+ const w = this.waiter;
176010
+ if (!w)
176011
+ return;
176012
+ if (this.buffered >= w.need) {
176013
+ const out = this.take(w.need);
176014
+ this.waiter = null;
176015
+ if (w.timer)
176016
+ clearTimeout(w.timer);
176017
+ w.resolve(out);
176018
+ return;
176019
+ }
176020
+ if (this.closedErr) {
176021
+ this.waiter = null;
176022
+ if (w.timer)
176023
+ clearTimeout(w.timer);
176024
+ w.reject(this.closedErr);
176025
+ }
176026
+ }
176027
+ take(n) {
176028
+ const out = Buffer.allocUnsafe(n);
176029
+ let off = 0;
176030
+ while (off < n) {
176031
+ const head = this.chunks[0];
176032
+ const want = n - off;
176033
+ if (head.length <= want) {
176034
+ head.copy(out, off);
176035
+ off += head.length;
176036
+ this.chunks.shift();
176037
+ } else {
176038
+ head.copy(out, off, 0, want);
176039
+ this.chunks[0] = head.subarray(want);
176040
+ off += want;
176041
+ }
176042
+ }
176043
+ this.buffered -= n;
176044
+ return out;
176045
+ }
176046
+ }
176047
+
176048
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/client.js
176049
+ var debug = debuglog("subc-client");
176050
+ var DEFAULT_HANDSHAKE_TIMEOUT_MS = 1e4;
176051
+ var DEFAULT_REQUEST_TIMEOUT_MS = 30000;
176052
+ var TIMEOUT_ARBITRATION_GRACE_MS = 50;
176053
+ var REQUEST_DEADLINE_MARKER = "request_deadline";
176054
+ var DEADLINE_NO_DROP_CODE = "deadline_exceeded_no_drop_observed";
176055
+ var ROUTE_OPEN_RETRY_DEADLINE_MS = 30000;
176056
+ var BODY_READ_TIMEOUT_MS = 30000;
176057
+ var EMPTY_BODY = new Uint8Array(0);
176058
+ var DEFAULT_MANAGED_TARGET_KIND = "management_surface";
176059
+ var SUBC_MODULE_ID_ENV = "SUBC_MODULE_ID";
176060
+ var SUBC_LAUNCH_NONCE_ENV = "SUBC_LAUNCH_NONCE";
176061
+ var DEFAULT_RECONNECT_BACKOFF = {
176062
+ baseMs: 100,
176063
+ capMs: 2000,
176064
+ maxAttempts: 6
176065
+ };
176066
+
176067
+ class SubcCallError extends Error {
176068
+ kind;
176069
+ code;
176070
+ cause;
176071
+ constructor(kind, message, code, cause) {
176072
+ super(message);
176073
+ this.kind = kind;
176074
+ this.code = code;
176075
+ this.cause = cause;
176076
+ this.name = "SubcCallError";
176077
+ }
176078
+ }
176079
+
176080
+ class SubcError extends Error {
176081
+ code;
176082
+ constructor(message, code) {
176083
+ super(message);
176084
+ this.code = code;
176085
+ }
176086
+ }
176087
+
176088
+ class SubcClient {
176089
+ sock;
176090
+ currentConn;
176091
+ opts;
176092
+ nextCorr = 1n;
176093
+ pending = new Map;
176094
+ lateResponses = new Map;
176095
+ routes = new Map;
176096
+ liveRoutes = new Map;
176097
+ connectionToken = newConnectionToken();
176098
+ ingressEpochDropCount = 0;
176099
+ closedErr = null;
176100
+ closeStarted = false;
176101
+ reconnecting = null;
176102
+ generation = 1;
176103
+ readerActive = false;
176104
+ constructor(sock, currentConn, opts) {
176105
+ this.sock = sock;
176106
+ this.currentConn = currentConn;
176107
+ this.opts = opts;
176108
+ this.readLoop(sock, this.generation);
176109
+ }
176110
+ get conn() {
176111
+ return this.currentConn;
176112
+ }
176113
+ static async connect(opts) {
176114
+ const normalized = normalizeConnectOptions(opts);
176115
+ const opened = await SubcClient.openConnection(normalized);
176116
+ return new SubcClient(opened.sock, opened.conn, normalized);
176117
+ }
176118
+ async catalogList(moduleId) {
176119
+ const body = this.encode(moduleId === undefined ? { op: "catalog.list" } : { op: "catalog.list", module_id: moduleId });
176120
+ const reply = await this.controlRpc(body);
176121
+ const parsed = this.parseJson(reply);
176122
+ return parsed.modules ?? [];
176123
+ }
176124
+ async routeOpen(target, identity, opts = {}) {
176125
+ const consumerIdentity = routeOpenConsumerIdentity(opts);
176126
+ const consumerCapabilities = opts.consumerCapabilities;
176127
+ const body = this.encode({
176128
+ op: "route.open",
176129
+ target,
176130
+ identity,
176131
+ ...consumerIdentity ? { consumer_identity: consumerIdentity } : {},
176132
+ ...consumerCapabilities !== undefined ? { consumer_capabilities: consumerCapabilities } : {}
176133
+ });
176134
+ let installed = null;
176135
+ const install = (frame) => {
176136
+ if (frame.header.ty !== FrameType.Response)
176137
+ return true;
176138
+ const parsed = this.parseJson(frame);
176139
+ if (typeof parsed.route_channel !== "number" || typeof parsed.route_epoch !== "number") {
176140
+ throw new SubcError(`route.open returned no route handle: ${JSON.stringify(parsed)}`);
176141
+ }
176142
+ installed = this.installRoute(parsed.route_channel, parsed.route_epoch);
176143
+ return true;
176144
+ };
176145
+ const closeLateRoute = (frame) => {
176146
+ if (frame.header.ty !== FrameType.Response)
176147
+ return;
176148
+ try {
176149
+ const parsed = this.parseJson(frame);
176150
+ if (typeof parsed.route_channel !== "number" || typeof parsed.route_epoch !== "number")
176151
+ return;
176152
+ const lateHandle = this.installRoute(parsed.route_channel, parsed.route_epoch);
176153
+ this.failHandle(lateHandle, new SubcError("late route.open was closed", "route_closed"));
176154
+ this.liveRoutes.delete(lateHandle.channel);
176155
+ this.sendRouteGoodbye(lateHandle, true);
176156
+ } catch {
176157
+ this.closeConnectionAfterCleanupFailure();
176158
+ }
176159
+ };
176160
+ await this.controlRpc(body, install, closeLateRoute);
176161
+ if (!installed)
176162
+ throw new SubcError("route.open response was not installed");
176163
+ return installed;
176164
+ }
176165
+ async request(handle, body, opts = {}) {
176166
+ this.assertLiveHandle(handle);
176167
+ const bytes = body instanceof Uint8Array ? body : this.encode(body);
176168
+ const priority = opts.priority ?? Priority.Interactive;
176169
+ const admission = opts.admissionClass ?? AdmissionClass.Normal;
176170
+ const reply = await this.send(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress);
176171
+ return this.parseJson(reply);
176172
+ }
176173
+ async call(moduleId, method, params, opts = {}) {
176174
+ const body = params === undefined ? { method } : { method, params };
176175
+ let retriedUnknownChannel = false;
176176
+ for (;; ) {
176177
+ const routeHandle = await this.cachedRouteHandle(moduleId, opts);
176178
+ try {
176179
+ return await this.managedRequest(routeHandle, body, opts);
176180
+ } catch (err) {
176181
+ if (!(err instanceof SubcCallError))
176182
+ throw this.terminalCallError("managed call failed", err);
176183
+ if (err.code === "unknown_channel" && !retriedUnknownChannel && !this.closeStarted) {
176184
+ retriedUnknownChannel = true;
176185
+ this.evictRouteHandle(routeHandle);
176186
+ continue;
176187
+ }
176188
+ if (err.kind === "not_sent") {
176189
+ try {
176190
+ await this.reconnectAfterDrop(err);
176191
+ } catch (reconnectErr) {
176192
+ throw this.notSentRecoveryError("managed call was not sent", reconnectErr);
176193
+ }
176194
+ continue;
176195
+ }
176196
+ if (err.kind === "outcome_unknown" && err.code !== DEADLINE_NO_DROP_CODE) {
176197
+ this.scheduleReconnectAfterDrop(err);
176198
+ }
176199
+ throw err;
176200
+ }
176201
+ }
176202
+ }
176203
+ subscribe(handle, body, onEvent, opts = {}) {
176204
+ this.assertLiveHandle(handle);
176205
+ const bytes = body instanceof Uint8Array ? body : this.encode(body);
176206
+ const priority = opts.priority ?? Priority.Interactive;
176207
+ const admission = opts.admissionClass ?? AdmissionClass.Normal;
176208
+ const corr = this.allocateCorr();
176209
+ const key = pendingKey(handle, corr);
176210
+ const closed = new Promise((resolve, reject) => {
176211
+ if (this.closedErr) {
176212
+ reject(this.closedErr);
176213
+ return;
176214
+ }
176215
+ this.pending.set(key, {
176216
+ handle,
176217
+ resolve: () => resolve(),
176218
+ reject,
176219
+ onProgress: onEvent,
176220
+ timer: null,
176221
+ subscription: true
176222
+ });
176223
+ const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), handle.channel, handle.epoch, corr, bytes);
176224
+ this.sock.write(encodeFrame(frame), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS).catch((err) => {
176225
+ const pending = this.pending.get(key);
176226
+ if (pending)
176227
+ this.rejectPending(key, pending, err instanceof Error ? err : new SubcError(String(err)));
176228
+ });
176229
+ });
176230
+ let cancelled = false;
176231
+ const unsubscribe = () => {
176232
+ if (cancelled)
176233
+ return;
176234
+ cancelled = true;
176235
+ this.cancel(handle, corr, priority);
176236
+ };
176237
+ return { unsubscribe, closed };
176238
+ }
176239
+ cancel(handle, corr, priority = Priority.Interactive) {
176240
+ this.assertLiveHandle(handle);
176241
+ const cancel = buildFrame(FrameType.Cancel, buildFlags(false, priority, false), handle.channel, handle.epoch, corr, EMPTY_BODY);
176242
+ this.sock.write(encodeFrame(cancel), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS).catch(() => {
176243
+ return;
176244
+ });
176245
+ }
176246
+ async routePoll(handle, kind) {
176247
+ this.assertLiveHandle(handle);
176248
+ const body = this.encode({
176249
+ op: "route.poll",
176250
+ route_channel: handle.channel,
176251
+ route_epoch: handle.epoch,
176252
+ kind
176253
+ });
176254
+ const reply = await this.controlRpc(body, (frame) => {
176255
+ if (frame.header.ty !== FrameType.Response)
176256
+ return true;
176257
+ const parsed = this.parseJson(frame);
176258
+ return parsed.route_channel === handle.channel && parsed.route_epoch === handle.epoch;
176259
+ });
176260
+ return this.parseJson(reply);
176261
+ }
176262
+ async closeRoute(handle, opts = {}) {
176263
+ this.assertLiveHandle(handle);
176264
+ for (const [key, cached2] of this.routes) {
176265
+ if (cached2.handle && sameRouteHandle(cached2.handle, handle)) {
176266
+ cached2.closed = true;
176267
+ cached2.handle = null;
176268
+ this.routes.delete(key);
176269
+ }
176270
+ }
176271
+ if (opts.drain)
176272
+ await this.drainUnaryOnHandle(handle);
176273
+ this.failHandle(handle, new SubcError("route closed by closeRoute", "route_closed"));
176274
+ if (this.liveRoutes.get(handle.channel) === handle)
176275
+ this.liveRoutes.delete(handle.channel);
176276
+ this.sendRouteGoodbye(handle);
176277
+ }
176278
+ async closeManagedRoute(target, identity, opts = {}) {
176279
+ const key = routeCacheKey(target, identity, routeOpenConsumerIdentity(opts));
176280
+ const cached2 = this.routes.get(key);
176281
+ if (!cached2)
176282
+ return;
176283
+ cached2.closed = true;
176284
+ this.routes.delete(key);
176285
+ const handle = cached2.handle;
176286
+ cached2.handle = null;
176287
+ if (handle)
176288
+ await this.closeRoute(handle, opts);
176289
+ }
176290
+ async closeRouteChannel(handle, opts = {}) {
176291
+ await this.closeRoute(handle, opts);
176292
+ }
176293
+ close() {
176294
+ this.closeStarted = true;
176295
+ this.fail(new SubcError("client closed"));
176296
+ this.sock.close();
176297
+ }
176298
+ drainUnaryOnHandle(handle) {
176299
+ const waiters = [];
176300
+ for (const pending of this.pending.values()) {
176301
+ if (pending.handle === handle && !pending.subscription) {
176302
+ waiters.push(new Promise((resolve) => {
176303
+ const previous = pending.onSettle;
176304
+ pending.onSettle = () => {
176305
+ previous?.();
176306
+ resolve();
176307
+ };
176308
+ }));
176309
+ }
176310
+ }
176311
+ return Promise.all(waiters).then(() => {
176312
+ return;
176313
+ });
176314
+ }
176315
+ sendRouteGoodbye(handle, closeOnQueueFailure = false) {
176316
+ this.assertLiveConnection(handle);
176317
+ if (this.closedErr) {
176318
+ if (closeOnQueueFailure)
176319
+ this.closeConnectionAfterCleanupFailure();
176320
+ return;
176321
+ }
176322
+ const goodbye = buildFrame(FrameType.Goodbye, buildFlags(false, Priority.Interactive, false), handle.channel, handle.epoch, 0n, EMPTY_BODY);
176323
+ const write = this.sock.writeTracked(encodeFrame(goodbye), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS);
176324
+ if (!write.queued && closeOnQueueFailure)
176325
+ this.closeConnectionAfterCleanupFailure();
176326
+ write.completed.catch(() => {
176327
+ if (closeOnQueueFailure && !write.queued)
176328
+ this.closeConnectionAfterCleanupFailure();
176329
+ });
176330
+ }
176331
+ static async openConnection(opts) {
176332
+ const conn = await readConnectionFile(opts.connectionFile);
176333
+ const deadline = Date.now() + (opts.handshakeTimeoutMs ?? DEFAULT_HANDSHAKE_TIMEOUT_MS);
176334
+ const endpoint = conn.endpoints[0];
176335
+ const sock = await SubcSocket.connect(endpoint.host, endpoint.port, deadline);
176336
+ try {
176337
+ await authenticateClient(sock, conn, deadline);
176338
+ } catch (err) {
176339
+ sock.close();
176340
+ throw err;
176341
+ }
176342
+ return { sock, conn };
176343
+ }
176344
+ async controlRpc(body, acceptFrame, onLateResponse) {
176345
+ return this.send(null, body, Priority.Interactive, AdmissionClass.Normal, undefined, undefined, acceptFrame, onLateResponse);
176346
+ }
176347
+ send(handle, body, priority, admission, timeoutMs, onProgress, acceptFrame, onLateResponse) {
176348
+ if (handle)
176349
+ this.assertLiveHandle(handle);
176350
+ if (this.closedErr)
176351
+ return Promise.reject(this.closedErr);
176352
+ let corr;
176353
+ try {
176354
+ corr = this.allocateCorr();
176355
+ } catch (error51) {
176356
+ return Promise.reject(error51);
176357
+ }
176358
+ const key = pendingKey(handle, corr);
176359
+ const channel = handle?.channel ?? 0;
176360
+ const epoch = handle?.epoch ?? 0;
176361
+ const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), channel, epoch, corr, body);
176362
+ return new Promise((resolve, reject) => {
176363
+ const ms = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
176364
+ const pending = {
176365
+ handle,
176366
+ resolve,
176367
+ reject,
176368
+ onProgress,
176369
+ timer: null,
176370
+ acceptFrame,
176371
+ onLateResponse
176372
+ };
176373
+ pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, channel, corr, ms), ms);
176374
+ this.pending.set(key, pending);
176375
+ this.sock.write(encodeFrame(frame), Date.now() + ms).catch((error51) => {
176376
+ const current = this.pending.get(key);
176377
+ if (current)
176378
+ this.rejectPending(key, current, error51 instanceof Error ? error51 : new SubcError(String(error51)));
176379
+ });
176380
+ });
176381
+ }
176382
+ arbitrateTimeout(key, pending, channel, corr, ms) {
176383
+ const settleAsTimeout = () => {
176384
+ if (pending.onLateResponse)
176385
+ this.lateResponses.set(key, pending.onLateResponse);
176386
+ this.rejectPending(key, pending, new SubcError(this.timeoutMessage(channel, corr, ms), REQUEST_DEADLINE_MARKER));
176387
+ };
176388
+ const graceDeadline = Date.now() + this.opts.timeoutArbitrationGraceMs;
176389
+ const arbitrate = () => {
176390
+ if (this.pending.get(key) !== pending)
176391
+ return;
176392
+ const readerDraining = this.readerActive || this.sock.bufferedBytes() > 0;
176393
+ if (readerDraining && Date.now() < graceDeadline) {
176394
+ setImmediate(arbitrate);
176395
+ return;
176396
+ }
176397
+ settleAsTimeout();
176398
+ };
176399
+ setImmediate(arbitrate);
176400
+ }
176401
+ async managedRequest(handle, body, opts) {
176402
+ const bytes = body instanceof Uint8Array ? body : this.encode(body);
176403
+ const priority = opts.priority ?? Priority.Interactive;
176404
+ const admission = opts.admissionClass ?? AdmissionClass.Normal;
176405
+ try {
176406
+ const reply = await this.sendManaged(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress);
176407
+ return this.parseJson(reply);
176408
+ } catch (error51) {
176409
+ if (error51 instanceof SubcCallError)
176410
+ throw error51;
176411
+ throw this.terminalCallError("managed call failed", error51);
176412
+ }
176413
+ }
176414
+ sendManaged(handle, body, priority, admission, timeoutMs, onProgress) {
176415
+ try {
176416
+ this.assertLiveHandle(handle);
176417
+ } catch (error51) {
176418
+ return Promise.reject(this.notSentCallError("request used a stale route handle", error51));
176419
+ }
176420
+ if (this.closedErr) {
176421
+ return Promise.reject(this.notSentCallError("request was not sent because the subc connection was already closed", this.closedErr));
176422
+ }
176423
+ let corr;
176424
+ try {
176425
+ corr = this.allocateCorr();
176426
+ } catch (error51) {
176427
+ return Promise.reject(this.notSentCallError("request correlation allocator was exhausted", error51));
176428
+ }
176429
+ const key = pendingKey(handle, corr);
176430
+ const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), handle.channel, handle.epoch, corr, body);
176431
+ let handedToSocket = false;
176432
+ const classifyFailure = (error51) => {
176433
+ if (!handedToSocket)
176434
+ return this.notSentCallError("request bytes were not queued to the subc socket", error51);
176435
+ if (error51 instanceof SubcError && error51.code === REQUEST_DEADLINE_MARKER) {
176436
+ return new SubcCallError("outcome_unknown", `managed call deadline exceeded after request bytes were queued to the local socket; no terminal response was observed; outcome unknown${causeMessage(error51)}`, DEADLINE_NO_DROP_CODE, error51);
176437
+ }
176438
+ return this.outcomeUnknownCallError("connection dropped before the managed call returned a response", error51);
176439
+ };
176440
+ return new Promise((resolve, reject) => {
176441
+ const ms = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
176442
+ const pending = {
176443
+ handle,
176444
+ resolve,
176445
+ reject,
176446
+ onProgress,
176447
+ timer: null,
176448
+ classifyFailure
176449
+ };
176450
+ pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, handle.channel, corr, ms), ms);
176451
+ this.pending.set(key, pending);
176452
+ const write = this.sock.writeTracked(encodeFrame(frame), Date.now() + ms);
176453
+ handedToSocket = write.queued;
176454
+ write.completed.catch((error51) => {
176455
+ const current = this.pending.get(key);
176456
+ if (current)
176457
+ this.rejectPending(key, current, error51 instanceof Error ? error51 : new SubcError(String(error51)));
176458
+ });
176459
+ });
176460
+ }
176461
+ async cachedRouteHandle(moduleId, opts) {
176462
+ const identity = opts.identity ?? this.opts.identity;
176463
+ if (!identity) {
176464
+ throw new SubcCallError("terminal", "managed call requires a BindIdentity in SubcClient.connect({ identity }) or call(..., { identity })", "missing_identity");
176465
+ }
176466
+ const target = { kind: opts.targetKind ?? this.opts.targetKind, module_id: moduleId };
176467
+ const consumerIdentity = routeOpenConsumerIdentity(opts);
176468
+ const key = routeCacheKey(target, identity, consumerIdentity);
176469
+ let cached2 = this.routes.get(key);
176470
+ if (!cached2) {
176471
+ cached2 = {
176472
+ key,
176473
+ moduleId,
176474
+ target,
176475
+ identity,
176476
+ consumerIdentity,
176477
+ handle: null,
176478
+ opening: null
176479
+ };
176480
+ this.routes.set(key, cached2);
176481
+ }
176482
+ if (cached2.handle && this.isLiveHandle(cached2.handle))
176483
+ return cached2.handle;
176484
+ if (!cached2.opening) {
176485
+ cached2.opening = this.openCachedRoute(cached2).finally(() => {
176486
+ cached2.opening = null;
176487
+ });
176488
+ }
176489
+ return cached2.opening;
176490
+ }
176491
+ async openCachedRoute(cached2) {
176492
+ const routeRetryDeadline = Date.now() + ROUTE_OPEN_RETRY_DEADLINE_MS;
176493
+ let routeRetryDelay = this.opts.reconnectBackoff.baseMs;
176494
+ let routeRetryAttempt = 0;
176495
+ for (;; ) {
176496
+ if (cached2.closed)
176497
+ throw this.routeClosedDuringOpen();
176498
+ try {
176499
+ await this.ensureConnectedForManaged();
176500
+ } catch (error51) {
176501
+ throw this.notSentRecoveryError("route.open could not run because reconnect failed", error51);
176502
+ }
176503
+ if (cached2.handle && this.isLiveHandle(cached2.handle))
176504
+ return cached2.handle;
176505
+ try {
176506
+ const handle = await this.routeOpen(cached2.target, cached2.identity, {
176507
+ consumerIdentity: cached2.consumerIdentity ?? null
176508
+ });
176509
+ if (cached2.closed) {
176510
+ this.liveRoutes.delete(handle.channel);
176511
+ this.sendRouteGoodbye(handle);
176512
+ throw this.routeClosedDuringOpen();
176513
+ }
176514
+ cached2.handle = handle;
176515
+ return handle;
176516
+ } catch (error51) {
176517
+ if (error51 instanceof SubcCallError && error51.code === "route_closed")
176518
+ throw error51;
176519
+ if (!this.closeStarted && isConsumerReconnectTransient(error51)) {
176520
+ try {
176521
+ await this.reconnectAfterDrop(error51);
176522
+ } catch (reconnectError) {
176523
+ throw this.notSentRecoveryError("route.open was not sent and reconnect failed", reconnectError);
176524
+ }
176525
+ continue;
176526
+ }
176527
+ if (!this.closeStarted && error51 instanceof SubcError && isRetryableRouteOpenCode(error51.code)) {
176528
+ routeRetryAttempt += 1;
176529
+ if (routeRetryAttempt < this.opts.reconnectBackoff.maxAttempts && Date.now() < routeRetryDeadline) {
176530
+ await this.opts.sleep(routeRetryDelay);
176531
+ routeRetryDelay = Math.min(routeRetryDelay * 2, this.opts.reconnectBackoff.capMs);
176532
+ continue;
176533
+ }
176534
+ throw this.notSentCallError(`route.open failed for module ${cached2.moduleId}: ${error51.code} (retry budget exhausted)`, error51);
176535
+ }
176536
+ throw this.terminalCallError(`route.open failed for module ${cached2.moduleId}`, error51);
176537
+ }
176538
+ }
176539
+ }
176540
+ async ensureConnectedForManaged() {
176541
+ if (this.closeStarted)
176542
+ throw new SubcError("client closed");
176543
+ if (this.reconnecting)
176544
+ await this.reconnecting;
176545
+ if (this.closedErr)
176546
+ await this.reconnectAfterDrop(this.closedErr);
176547
+ }
176548
+ scheduleReconnectAfterDrop(err) {
176549
+ if (this.closeStarted || this.reconnecting)
176550
+ return;
176551
+ this.reconnectAfterDrop(err).catch(() => {});
176552
+ }
176553
+ reconnectAfterDrop(trigger) {
176554
+ if (this.closeStarted)
176555
+ return Promise.reject(new SubcError("client closed"));
176556
+ if (this.reconnecting)
176557
+ return this.reconnecting;
176558
+ const promise2 = this.reconnectWithRetry(trigger).finally(() => {
176559
+ if (this.reconnecting === promise2)
176560
+ this.reconnecting = null;
176561
+ });
176562
+ this.reconnecting = promise2;
176563
+ return promise2;
176564
+ }
176565
+ async reconnectWithRetry(_trigger) {
176566
+ let attempt = 0;
176567
+ let delay = this.opts.reconnectBackoff.baseMs;
176568
+ for (;; ) {
176569
+ if (this.closeStarted)
176570
+ throw new SubcError("client closed");
176571
+ attempt += 1;
176572
+ try {
176573
+ const opened = await SubcClient.openConnection(this.opts);
176574
+ if (this.closeStarted) {
176575
+ opened.sock.close();
176576
+ throw new SubcError("client closed");
176577
+ }
176578
+ this.replaceConnection(opened);
176579
+ await this.reopenCachedRoutes();
176580
+ return;
176581
+ } catch (err) {
176582
+ if (!isConsumerReconnectTransient(err) || attempt >= this.opts.reconnectBackoff.maxAttempts) {
176583
+ if (err instanceof AuthError && attempt > 1) {
176584
+ throw new AuthError(`reconnect gave up after ${attempt} attempts: ${err.message} — the connection file and the daemon's key disagree persistently ` + `(daemon restarting in a loop, split connection-file paths, or a genuinely foreign daemon on this port); ` + `check the daemon, then restart this host app`);
176585
+ }
176586
+ throw err;
176587
+ }
176588
+ await this.opts.sleep(delay);
176589
+ delay = Math.min(delay * 2, this.opts.reconnectBackoff.capMs);
176590
+ }
176591
+ }
176592
+ }
176593
+ replaceConnection(opened) {
176594
+ this.sock.close();
176595
+ this.sock = opened.sock;
176596
+ this.currentConn = opened.conn;
176597
+ this.closedErr = null;
176598
+ this.generation += 1;
176599
+ this.connectionToken = newConnectionToken();
176600
+ this.liveRoutes.clear();
176601
+ this.lateResponses.clear();
176602
+ this.nextCorr = 1n;
176603
+ this.readLoop(opened.sock, this.generation);
176604
+ }
176605
+ async reopenCachedRoutes() {
176606
+ for (const cached2 of this.routes.values())
176607
+ cached2.handle = null;
176608
+ for (const cached2 of this.routes.values()) {
176609
+ if (cached2.closed)
176610
+ continue;
176611
+ const handle = await this.routeOpen(cached2.target, cached2.identity, {
176612
+ consumerIdentity: cached2.consumerIdentity ?? null
176613
+ });
176614
+ if (cached2.closed) {
176615
+ this.liveRoutes.delete(handle.channel);
176616
+ this.sendRouteGoodbye(handle);
176617
+ continue;
176618
+ }
176619
+ cached2.handle = handle;
176620
+ }
176621
+ }
176622
+ timeoutMessage(channel, corr, ms) {
176623
+ const port = this.sock.localPort();
176624
+ const where = port === null ? "channel" : `local_port=${port} channel`;
176625
+ return `request on ${where} ${channel} corr ${corr} timed out after ${ms}ms`;
176626
+ }
176627
+ routeClosedDuringOpen() {
176628
+ return new SubcCallError("not_sent", "route was closed before route.open completed", "route_closed");
176629
+ }
176630
+ async readLoop(sock, generation) {
176631
+ try {
176632
+ for (;; ) {
176633
+ this.readerActive = false;
176634
+ const frame = await sock.readFrame(Number.POSITIVE_INFINITY, { afterHeaderMs: BODY_READ_TIMEOUT_MS }, () => {
176635
+ this.readerActive = true;
176636
+ });
176637
+ try {
176638
+ if (this.sock === sock && this.generation === generation)
176639
+ this.dispatch(frame);
176640
+ } finally {
176641
+ this.readerActive = false;
176642
+ }
176643
+ }
176644
+ } catch (error51) {
176645
+ if (this.sock === sock && this.generation === generation) {
176646
+ this.fail(error51 instanceof Error ? error51 : new SubcError(String(error51)));
176647
+ }
176648
+ }
176649
+ }
176650
+ dispatch(frame) {
176651
+ let handle = null;
176652
+ if (frame.header.channel !== 0) {
176653
+ handle = this.liveRoutes.get(frame.header.channel) ?? null;
176654
+ if (!handle || handle.epoch !== frame.header.epoch) {
176655
+ this.ingressEpochDropCount += 1;
176656
+ return;
176657
+ }
176658
+ }
176659
+ const key = pendingKey(handle, frame.header.corr);
176660
+ const pending = this.pending.get(key);
176661
+ if (pending) {
176662
+ if (pending.acceptFrame && !pending.acceptFrame(frame))
176663
+ return;
176664
+ switch (frame.header.ty) {
176665
+ case FrameType.Push:
176666
+ case FrameType.StreamData:
176667
+ pending.onProgress?.(frame.body);
176668
+ return;
176669
+ case FrameType.Response:
176670
+ case FrameType.StreamEnd:
176671
+ this.settle(key, pending, () => pending.resolve(frame));
176672
+ return;
176673
+ case FrameType.Error:
176674
+ this.settle(key, pending, () => pending.reject(this.errorFromFrame(frame)));
176675
+ return;
176676
+ default:
176677
+ return;
176678
+ }
176679
+ }
176680
+ const late = this.lateResponses.get(key);
176681
+ if (late && (frame.header.ty === FrameType.Response || frame.header.ty === FrameType.Error)) {
176682
+ this.lateResponses.delete(key);
176683
+ late(frame);
176684
+ return;
176685
+ }
176686
+ if (frame.header.ty === FrameType.Goodbye && handle) {
176687
+ this.failHandle(handle, new SubcError("route closed by subc (GOODBYE)"));
176688
+ if (this.liveRoutes.get(handle.channel) === handle)
176689
+ this.liveRoutes.delete(handle.channel);
176690
+ this.evictRouteHandle(handle);
176691
+ return;
176692
+ }
176693
+ if (frame.header.ty === FrameType.Response || frame.header.ty === FrameType.Error || frame.header.ty === FrameType.StreamEnd) {
176694
+ debug("dropped terminal frame with no waiter: type=%d channel=%d epoch=%d corr=%s port=%s", frame.header.ty, frame.header.channel, frame.header.epoch, frame.header.corr, this.sock.localPort() ?? "?");
176695
+ }
176696
+ }
176697
+ settle(key, pending, run) {
176698
+ if (this.pending.get(key) !== pending)
176699
+ return false;
176700
+ this.pending.delete(key);
176701
+ if (pending.timer)
176702
+ clearTimeout(pending.timer);
176703
+ run();
176704
+ pending.onSettle?.();
176705
+ return true;
176706
+ }
176707
+ rejectPending(key, pending, err) {
176708
+ this.settle(key, pending, () => pending.reject(pending.classifyFailure?.(err) ?? err));
176709
+ }
176710
+ errorFromFrame(frame) {
176711
+ try {
176712
+ const parsed = JSON.parse(Buffer.from(frame.body).toString("utf8"));
176713
+ return new SubcError(parsed.message ?? "subc error", parsed.code);
176714
+ } catch {
176715
+ return new SubcError(Buffer.from(frame.body).toString("utf8") || "subc error");
176716
+ }
176717
+ }
176718
+ evictRouteHandle(handle) {
176719
+ for (const cached2 of this.routes.values()) {
176720
+ if (cached2.handle && sameRouteHandle(cached2.handle, handle))
176721
+ cached2.handle = null;
176722
+ }
176723
+ }
176724
+ failHandle(handle, error51) {
176725
+ for (const [key, pending] of this.pending) {
176726
+ if (pending.handle && sameRouteHandle(pending.handle, handle))
176727
+ this.rejectPending(key, pending, error51);
176728
+ }
176729
+ }
176730
+ fail(err) {
176731
+ if (!this.closedErr)
176732
+ this.closedErr = err;
176733
+ for (const [key, pending] of this.pending) {
176734
+ this.rejectPending(key, pending, err);
176735
+ }
176736
+ }
176737
+ notSentCallError(message, cause) {
176738
+ return new SubcCallError("not_sent", `${message}${causeMessage(cause)}`, errorCode(cause), cause);
176739
+ }
176740
+ outcomeUnknownCallError(message, cause) {
176741
+ return new SubcCallError("outcome_unknown", `${message}${causeMessage(cause)}`, errorCode(cause), cause);
176742
+ }
176743
+ terminalCallError(message, cause) {
176744
+ if (cause instanceof SubcCallError)
176745
+ return cause;
176746
+ return new SubcCallError("terminal", `${message}${causeMessage(cause)}`, errorCode(cause), cause);
176747
+ }
176748
+ notSentRecoveryError(message, cause) {
176749
+ if (cause instanceof SubcCallError)
176750
+ return cause;
176751
+ if (isConsumerReconnectTransient(cause))
176752
+ return this.notSentCallError(message, cause);
176753
+ return this.terminalCallError(message, cause);
176754
+ }
176755
+ get droppedIngressFrames() {
176756
+ return this.ingressEpochDropCount;
176757
+ }
176758
+ installRoute(channel, epoch) {
176759
+ const handle = createRouteHandle(channel, epoch, this.connectionToken);
176760
+ this.liveRoutes.set(channel, handle);
176761
+ return handle;
176762
+ }
176763
+ isLiveHandle(handle) {
176764
+ return belongsToConnection(handle, this.connectionToken) && this.liveRoutes.get(handle.channel) === handle;
176765
+ }
176766
+ assertLiveConnection(handle) {
176767
+ if (!belongsToConnection(handle, this.connectionToken))
176768
+ throw new StaleRouteHandleError(handle);
176769
+ }
176770
+ assertLiveHandle(handle) {
176771
+ if (!this.isLiveHandle(handle))
176772
+ throw new StaleRouteHandleError(handle);
176773
+ }
176774
+ allocateCorr() {
176775
+ const maximum = 0xffffffffffffffffn;
176776
+ if (this.nextCorr > maximum) {
176777
+ const error51 = new SubcError("channel-0 correlation id allocator exhausted", "corr_exhausted");
176778
+ this.fail(error51);
176779
+ this.sock.close();
176780
+ this.scheduleReconnectAfterDrop(error51);
176781
+ throw error51;
176782
+ }
176783
+ const corr = this.nextCorr;
176784
+ this.nextCorr += 1n;
176785
+ return corr;
176786
+ }
176787
+ closeConnectionAfterCleanupFailure() {
176788
+ const error51 = new SubcError("late route cleanup could not be queued", "late_route_cleanup_failed");
176789
+ this.fail(error51);
176790
+ this.sock.close();
176791
+ this.scheduleReconnectAfterDrop(error51);
176792
+ }
176793
+ encode(value) {
176794
+ return new Uint8Array(Buffer.from(JSON.stringify(value), "utf8"));
176795
+ }
176796
+ parseJson(frame) {
176797
+ return JSON.parse(Buffer.from(frame.body).toString("utf8"));
176798
+ }
176799
+ }
176800
+ function isConsumerReconnectTransient(err) {
176801
+ if (err instanceof SocketClosedError || err instanceof SocketTimeoutError)
176802
+ return true;
176803
+ if (err instanceof SocketWriteNotQueuedError || err instanceof SocketWriteQueuedError)
176804
+ return true;
176805
+ if (err instanceof SubcCallError)
176806
+ return err.kind === "not_sent" || err.kind === "outcome_unknown";
176807
+ if (err instanceof AuthError)
176808
+ return true;
176809
+ if (err instanceof SubcError || err instanceof ConnectionFileError)
176810
+ return false;
176811
+ const code = errorCode(err);
176812
+ return code === "ECONNREFUSED" || code === "ECONNRESET" || code === "EPIPE" || code === "ETIMEDOUT" || code === "ENOENT";
176813
+ }
176814
+ function isRetryableRouteOpenCode(code) {
176815
+ return code === "unknown_module" || code === "module_reloading" || code === "target_unavailable" || code === "module_timeout";
176816
+ }
176817
+ async function connectionFileExists(path7) {
176818
+ try {
176819
+ await fs4.access(path7);
176820
+ return true;
176821
+ } catch {
176822
+ return false;
176823
+ }
176824
+ }
176825
+ function normalizeConnectOptions(opts) {
176826
+ return {
176827
+ connectionFile: opts.connectionFile,
176828
+ handshakeTimeoutMs: opts.handshakeTimeoutMs,
176829
+ identity: opts.identity,
176830
+ targetKind: opts.targetKind ?? DEFAULT_MANAGED_TARGET_KIND,
176831
+ reconnectBackoff: opts.reconnectBackoff ?? DEFAULT_RECONNECT_BACKOFF,
176832
+ sleep: opts.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms))),
176833
+ timeoutArbitrationGraceMs: opts.timeoutArbitrationGraceMs ?? TIMEOUT_ARBITRATION_GRACE_MS
176834
+ };
176835
+ }
176836
+ function routeCacheKey(target, identity, consumerIdentity) {
176837
+ const consumerPart = consumerIdentity ? `${consumerIdentity.module_id}\x00${consumerIdentity.launch_nonce}` : "";
176838
+ return `${target.kind}\x00${target.module_id}\x00${identity.project_root}\x00${identity.harness}\x00${identity.session}\x00${consumerPart}`;
176839
+ }
176840
+ function routeOpenConsumerIdentity(opts = {}) {
176841
+ if (opts.consumerIdentity !== undefined)
176842
+ return opts.consumerIdentity ?? undefined;
176843
+ const moduleId = process.env[SUBC_MODULE_ID_ENV];
176844
+ const launchNonce = process.env[SUBC_LAUNCH_NONCE_ENV];
176845
+ if (!moduleId || !launchNonce)
176846
+ return;
176847
+ return { module_id: moduleId, launch_nonce: launchNonce };
176848
+ }
176849
+ function errorCode(err) {
176850
+ if (typeof err === "object" && err !== null && "code" in err) {
176851
+ const code = err.code;
176852
+ if (typeof code === "string")
176853
+ return code;
176854
+ }
176855
+ return;
176856
+ }
176857
+ function causeMessage(cause) {
176858
+ if (cause === undefined)
176859
+ return "";
176860
+ return `: ${cause instanceof Error ? cause.message : String(cause)}`;
176861
+ }
176862
+ function pendingKey(handle, corr) {
176863
+ return handle ? `${handle.channel}:${handle.epoch}:${corr}` : `0:0:${corr}`;
176864
+ }
176865
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/provider.js
176866
+ import { Buffer as Buffer4 } from "node:buffer";
176867
+ var DEFAULT_HANDSHAKE_TIMEOUT_MS2 = 1e4;
176868
+ var BODY_READ_TIMEOUT_MS2 = 30000;
176869
+ var WRITE_TIMEOUT_MS = 30000;
176870
+ var DEFAULT_RESTORED_DEBOUNCE_MS = 250;
176871
+ var DEFAULT_PROVIDER_HANDLER_CAPACITY = 64;
176872
+ var HEALTH_CHECK_OP = "health.check";
176873
+ var HELLO_CORR = 1n;
176874
+
176875
+ class AsyncPermitPool {
176876
+ available;
176877
+ waiters = [];
176878
+ constructor(capacity) {
176879
+ if (!Number.isInteger(capacity) || capacity <= 0) {
176880
+ throw new SubcProviderError("provider handler capacity must be a positive integer", "invalid_handler_capacity");
176881
+ }
176882
+ this.available = capacity;
176883
+ }
176884
+ async acquire() {
176885
+ if (this.available > 0) {
176886
+ this.available -= 1;
176887
+ return this.releaseOnce();
176888
+ }
176889
+ await new Promise((resolve) => {
176890
+ this.waiters.push(resolve);
176891
+ });
176892
+ return this.releaseOnce();
176893
+ }
176894
+ releaseOnce() {
176895
+ let released = false;
176896
+ return () => {
176897
+ if (released)
176898
+ return;
176899
+ released = true;
176900
+ const next = this.waiters.shift();
176901
+ if (next) {
176902
+ next();
176903
+ } else {
176904
+ this.available += 1;
176905
+ }
176906
+ };
176907
+ }
176908
+ }
176909
+
176910
+ class SubcProviderError extends Error {
176911
+ code;
176912
+ constructor(message, code) {
176913
+ super(message);
176914
+ this.code = code;
176915
+ }
176916
+ }
176917
+ class SubcProvider {
176918
+ sock;
176919
+ currentConn;
176920
+ opts;
176921
+ closed;
176922
+ resolveClosed = () => {
176923
+ return;
176924
+ };
176925
+ closeStarted = false;
176926
+ closedErr = null;
176927
+ inflight = new Map;
176928
+ pending = new Map;
176929
+ liveRoutes = new Map;
176930
+ connectionToken = newConnectionToken();
176931
+ nextCorr = 1n;
176932
+ ingressEpochDropCount = 0;
176933
+ requestGate = new AsyncPermitPool(DEFAULT_PROVIDER_HANDLER_CAPACITY);
176934
+ reconnecting = null;
176935
+ generation = 1;
176936
+ connectionEpoch = 1;
176937
+ stateQueue = [];
176938
+ drainingStateQueue = false;
176939
+ restoredDebounceToken = 0;
176940
+ storage;
176941
+ constructor(sock, currentConn, opts, storage) {
176942
+ this.sock = sock;
176943
+ this.currentConn = currentConn;
176944
+ this.opts = opts;
176945
+ this.storage = storage;
176946
+ this.closed = new Promise((resolve) => {
176947
+ this.resolveClosed = resolve;
176948
+ });
176949
+ this.readLoop(sock, this.generation);
176950
+ this.enqueueConnectionState({ state: "connected", epoch: this.connectionEpoch });
176951
+ }
176952
+ get droppedIngressFrames() {
176953
+ return this.ingressEpochDropCount;
176954
+ }
176955
+ get conn() {
176956
+ return this.currentConn;
176957
+ }
176958
+ currentEpoch() {
176959
+ return this.connectionEpoch;
176960
+ }
176961
+ async request(handle, body, opts = {}) {
176962
+ this.assertLiveHandle(handle);
176963
+ const corr = this.allocateCorr();
176964
+ const key = routeKey(handle, corr);
176965
+ const timeoutMs = opts.timeoutMs ?? WRITE_TIMEOUT_MS;
176966
+ const frame = buildFrame(FrameType.Request, buildFlags(false, opts.priority ?? Priority.Interactive, false, opts.admissionClass ?? AdmissionClass.Normal), handle.channel, handle.epoch, corr, body);
176967
+ return await new Promise((resolve, reject) => {
176968
+ const timer = setTimeout(() => {
176969
+ if (this.pending.delete(key))
176970
+ reject(new SubcProviderError("reverse request timed out", "request_timeout"));
176971
+ }, timeoutMs);
176972
+ this.pending.set(key, {
176973
+ resolve: (response) => resolve(response.body),
176974
+ reject,
176975
+ timer
176976
+ });
176977
+ this.sendOn(this.sock, this.generation, frame).catch((error51) => {
176978
+ const pending = this.pending.get(key);
176979
+ if (!pending)
176980
+ return;
176981
+ this.pending.delete(key);
176982
+ clearTimeout(pending.timer);
176983
+ reject(error51 instanceof Error ? error51 : new SubcProviderError(String(error51)));
176984
+ });
176985
+ });
176986
+ }
176987
+ async push(handle, body, opts = {}) {
176988
+ this.assertLiveHandle(handle);
176989
+ await this.sendOn(this.sock, this.generation, buildFrame(FrameType.Push, buildFlags(false, opts.priority ?? Priority.Interactive, false, opts.admissionClass ?? AdmissionClass.Normal), handle.channel, handle.epoch, 0n, body));
176990
+ }
176991
+ cancel(handle, corr) {
176992
+ this.assertLiveHandle(handle);
176993
+ this.sendOn(this.sock, this.generation, buildFrame(FrameType.Cancel, controlFlags(), handle.channel, handle.epoch, corr, new Uint8Array(0)));
176994
+ }
176995
+ closeRoute(handle) {
176996
+ this.assertLiveHandle(handle);
176997
+ this.liveRoutes.delete(handle.channel);
176998
+ this.abortHandle(handle);
176999
+ this.sendOn(this.sock, this.generation, buildFrame(FrameType.Goodbye, controlFlags(), handle.channel, handle.epoch, 0n, new Uint8Array(0)));
177000
+ }
177001
+ static async connect(opts) {
177002
+ if (opts.manifest.protocol_ver !== PROTOCOL_VERSION) {
177003
+ throw new SubcProviderError(`manifest protocol_ver ${opts.manifest.protocol_ver} does not match client protocol ${PROTOCOL_VERSION}`, "invalid_manifest");
177004
+ }
177005
+ const normalized = normalizeProviderConnectOptions(opts);
177006
+ const opened = await SubcProvider.openConnection(normalized);
177007
+ return new SubcProvider(opened.sock, opened.conn, normalized, opened.ack.storage);
177008
+ }
177009
+ async close() {
177010
+ if (!this.closeStarted) {
177011
+ this.closeStarted = true;
177012
+ this.cancelRestoredDebounce();
177013
+ const sock = this.sock;
177014
+ try {
177015
+ await sendFrame(sock, buildFrame(FrameType.Goodbye, controlFlags(), 0, 0, 0n, new Uint8Array(0)));
177016
+ } catch {} finally {
177017
+ sock.close();
177018
+ this.finishClosed();
177019
+ }
177020
+ }
177021
+ await this.closed;
177022
+ }
177023
+ static async openConnection(opts) {
177024
+ const conn = await readConnectionFile(opts.connectionFile);
177025
+ const deadline = Date.now() + (opts.handshakeTimeoutMs ?? DEFAULT_HANDSHAKE_TIMEOUT_MS2);
177026
+ const endpoint = conn.endpoints[0];
177027
+ const sock = await SubcSocket.connect(endpoint.host, endpoint.port, deadline);
177028
+ try {
177029
+ await authenticateClient(sock, conn, deadline);
177030
+ await sendFrame(sock, buildHelloFrame(opts));
177031
+ const ack = await expectHelloAck(sock, deadline);
177032
+ return { sock, conn, ack };
177033
+ } catch (err) {
177034
+ sock.close();
177035
+ throw err;
177036
+ }
177037
+ }
177038
+ async readLoop(sock, generation) {
177039
+ try {
177040
+ for (;; ) {
177041
+ const frame = await sock.readFrame(Number.POSITIVE_INFINITY, { afterHeaderMs: BODY_READ_TIMEOUT_MS2 });
177042
+ const keepGoing = await this.dispatch(frame, sock, generation);
177043
+ if (!keepGoing) {
177044
+ if (this.sock === sock && this.generation === generation)
177045
+ this.closeStarted = true;
177046
+ break;
177047
+ }
177048
+ }
177049
+ } catch (error51) {
177050
+ if (this.sock === sock && this.generation === generation && !this.closeStarted) {
177051
+ this.handleUnexpectedDrop(sock, generation, error51 instanceof Error ? error51 : new SubcProviderError(String(error51)));
177052
+ return;
177053
+ }
177054
+ } finally {
177055
+ if (this.sock === sock && this.generation === generation) {
177056
+ sock.close();
177057
+ if (this.closeStarted)
177058
+ this.finishClosed();
177059
+ }
177060
+ }
177061
+ }
177062
+ async dispatch(frame, sock, generation) {
177063
+ let handle = null;
177064
+ if (frame.header.channel !== 0) {
177065
+ handle = this.liveRoutes.get(frame.header.channel) ?? null;
177066
+ if (!handle || handle.epoch !== frame.header.epoch) {
177067
+ this.ingressEpochDropCount += 1;
177068
+ return true;
177069
+ }
177070
+ }
177071
+ if (handle) {
177072
+ const pendingKey2 = routeKey(handle, frame.header.corr);
177073
+ const pending = this.pending.get(pendingKey2);
177074
+ if (pending) {
177075
+ if (frame.header.ty === FrameType.Push || frame.header.ty === FrameType.StreamData)
177076
+ return true;
177077
+ if (frame.header.ty === FrameType.Response || frame.header.ty === FrameType.StreamEnd) {
177078
+ this.pending.delete(pendingKey2);
177079
+ clearTimeout(pending.timer);
177080
+ pending.resolve(frame);
177081
+ return true;
177082
+ }
177083
+ if (frame.header.ty === FrameType.Error) {
177084
+ this.pending.delete(pendingKey2);
177085
+ clearTimeout(pending.timer);
177086
+ pending.reject(providerErrorFromFrame(frame));
177087
+ return true;
177088
+ }
177089
+ }
177090
+ }
177091
+ switch (frame.header.ty) {
177092
+ case FrameType.Ping:
177093
+ if (frame.header.channel === 0) {
177094
+ await this.sendOn(sock, generation, buildFrameWithVersion(frame.header.ver, FrameType.Pong, frame.header.flags, 0, 0, frame.header.corr, new Uint8Array(0)));
177095
+ }
177096
+ return true;
177097
+ case FrameType.Goodbye:
177098
+ if (!handle)
177099
+ return false;
177100
+ this.liveRoutes.delete(handle.channel);
177101
+ this.abortHandle(handle);
177102
+ await this.opts.onRouteGone?.(handle);
177103
+ return true;
177104
+ case FrameType.Cancel:
177105
+ if (handle)
177106
+ this.inflight.get(routeKey(handle, frame.header.corr))?.abort();
177107
+ return true;
177108
+ case FrameType.Request:
177109
+ if (frame.header.channel === 0) {
177110
+ await this.handleControlRequest(frame, sock, generation);
177111
+ } else if (handle) {
177112
+ this.handleDataRequest(frame, handle, sock, generation).catch((error51) => {
177113
+ if (!this.closeStarted && this.sock === sock && this.generation === generation) {
177114
+ console.warn("SubcProvider handler failed after its request was dispatched", error51);
177115
+ }
177116
+ });
177117
+ }
177118
+ return true;
177119
+ default:
177120
+ return true;
177121
+ }
177122
+ }
177123
+ abortHandle(handle) {
177124
+ const prefix = `${handle.channel}:${handle.epoch}:`;
177125
+ for (const [key, controller] of this.inflight) {
177126
+ if (key.startsWith(prefix))
177127
+ controller.abort();
177128
+ }
177129
+ for (const [key, pending] of this.pending) {
177130
+ if (!key.startsWith(prefix))
177131
+ continue;
177132
+ this.pending.delete(key);
177133
+ clearTimeout(pending.timer);
177134
+ pending.reject(new StaleRouteHandleError(handle));
177135
+ }
177136
+ }
177137
+ abortGeneration(_generation) {
177138
+ this.abortAllInflight();
177139
+ for (const [key, pending] of this.pending) {
177140
+ this.pending.delete(key);
177141
+ clearTimeout(pending.timer);
177142
+ pending.reject(new SubcProviderError("provider connection dropped", "connection_dropped"));
177143
+ }
177144
+ this.liveRoutes.clear();
177145
+ }
177146
+ abortAllInflight() {
177147
+ for (const controller of this.inflight.values())
177148
+ controller.abort();
177149
+ }
177150
+ async handleControlRequest(frame, sock, generation) {
177151
+ const request = parseJson(frame.body);
177152
+ if (request.op === HEALTH_CHECK_OP) {
177153
+ this.handleHealthRequest(frame, sock, generation).catch((error51) => {
177154
+ if (!this.closeStarted && this.sock === sock && this.generation === generation) {
177155
+ console.warn("SubcProvider health handler failed after its request was dispatched", error51);
177156
+ }
177157
+ });
177158
+ return;
177159
+ }
177160
+ if (request.op !== "route.bind") {
177161
+ throw new SubcProviderError(`unsupported module control request ${request.op ?? "<missing op>"}`);
177162
+ }
177163
+ const tentative = createRouteHandle(numberField(request.route_channel, "route_channel"), numberField(request.epoch, "epoch"), this.connectionToken);
177164
+ const bindRequest = {
177165
+ handle: tentative,
177166
+ target: request.target,
177167
+ identity: request.identity,
177168
+ principal: request.principal,
177169
+ consumer_capabilities: request.consumer_capabilities
177170
+ };
177171
+ let decision;
177172
+ try {
177173
+ decision = await this.opts.onBind?.(bindRequest);
177174
+ } catch (error51) {
177175
+ try {
177176
+ await this.sendError(frame, "route_rejected", error51 instanceof Error ? error51.message : String(error51), controlFlags(), sock, generation);
177177
+ } finally {
177178
+ await this.opts.onRouteGone?.(tentative);
177179
+ }
177180
+ return;
177181
+ }
177182
+ const rejection = bindRejection(decision);
177183
+ if (rejection) {
177184
+ try {
177185
+ await this.sendError(frame, rejection.code, rejection.message, controlFlags(), sock, generation);
177186
+ } finally {
177187
+ await this.opts.onRouteGone?.(tentative);
177188
+ }
177189
+ return;
177190
+ }
177191
+ try {
177192
+ await this.sendOn(sock, generation, buildFrameWithVersion(frame.header.ver, FrameType.Response, controlFlags(), 0, 0, frame.header.corr, encodeJson({ op: "route.bind" })));
177193
+ } catch (error51) {
177194
+ await this.opts.onRouteGone?.(tentative);
177195
+ throw error51;
177196
+ }
177197
+ if (this.sock !== sock || this.generation !== generation || this.closeStarted || this.closedErr) {
177198
+ await this.opts.onRouteGone?.(tentative);
177199
+ return;
177200
+ }
177201
+ this.liveRoutes.set(tentative.channel, tentative);
177202
+ await this.opts.onBound?.(tentative);
177203
+ }
177204
+ async handleDataRequest(frame, handle, sock, generation) {
177205
+ const { corr, ver } = frame.header;
177206
+ const key = routeKey(handle, corr);
177207
+ const controller = new AbortController;
177208
+ this.inflight.set(key, controller);
177209
+ const context = {
177210
+ handle,
177211
+ signal: controller.signal,
177212
+ currentEpoch: () => this.connectionEpoch,
177213
+ emit: async (eventBody, options = {}) => {
177214
+ this.assertLiveHandle(handle);
177215
+ if (controller.signal.aborted)
177216
+ return;
177217
+ await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.StreamData, buildFlags(false, options.priority ?? Priority.Interactive, false, options.admissionClass ?? AdmissionClass.Normal), handle.channel, handle.epoch, corr, eventBody));
177218
+ }
177219
+ };
177220
+ const releasePermit = await (this.requestGate ?? new AsyncPermitPool(DEFAULT_PROVIDER_HANDLER_CAPACITY)).acquire();
177221
+ const dataFlags = buildFlags(false, Priority.Interactive, false);
177222
+ try {
177223
+ const body = await this.opts.handler(handle, frame.body, context);
177224
+ if (controller.signal.aborted)
177225
+ return;
177226
+ this.assertLiveHandle(handle);
177227
+ if (body === undefined) {
177228
+ await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.StreamEnd, dataFlags, handle.channel, handle.epoch, corr, new Uint8Array(0)));
177229
+ } else if (body instanceof Uint8Array) {
177230
+ await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.Response, dataFlags, handle.channel, handle.epoch, corr, body));
177231
+ } else {
177232
+ throw new SubcProviderError("provider handler must return a Uint8Array or void", "invalid_handler_response");
177233
+ }
177234
+ } catch (error51) {
177235
+ if (error51 instanceof StaleRouteHandleError || controller.signal.aborted)
177236
+ return;
177237
+ await this.sendError(frame, error51 instanceof SubcProviderError && error51.code ? error51.code : "handler_error", error51 instanceof Error ? error51.message : String(error51), dataFlags, sock, generation);
177238
+ } finally {
177239
+ releasePermit();
177240
+ if (this.inflight.get(key) === controller)
177241
+ this.inflight.delete(key);
177242
+ }
177243
+ }
177244
+ async handleHealthRequest(frame, sock, generation) {
177245
+ const { corr, ver } = frame.header;
177246
+ const key = `control:${generation}:${corr}`;
177247
+ const controller = new AbortController;
177248
+ this.inflight.set(key, controller);
177249
+ const releasePermit = await (this.requestGate ?? new AsyncPermitPool(DEFAULT_PROVIDER_HANDLER_CAPACITY)).acquire();
177250
+ try {
177251
+ if (controller.signal.aborted)
177252
+ return;
177253
+ const report = await this.opts.health();
177254
+ await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.Response, controlFlags(), 0, 0, corr, encodeJson({
177255
+ op: HEALTH_CHECK_OP,
177256
+ status: report.status,
177257
+ ...report.detail === undefined ? {} : { detail: report.detail },
177258
+ ...report.metrics === undefined ? {} : { metrics: report.metrics }
177259
+ })));
177260
+ } catch (error51) {
177261
+ await this.sendError(frame, error51 instanceof SubcProviderError && error51.code ? error51.code : "health_error", error51 instanceof Error ? error51.message : String(error51), controlFlags(), sock, generation);
177262
+ } finally {
177263
+ releasePermit();
177264
+ if (this.inflight.get(key) === controller)
177265
+ this.inflight.delete(key);
177266
+ }
177267
+ }
177268
+ async sendError(frame, code, message, flags, sock, generation) {
177269
+ await this.sendOn(sock, generation, buildFrameWithVersion(frame.header.ver, FrameType.Error, flags, frame.header.channel, frame.header.epoch, frame.header.corr, encodeJson({ code, message })));
177270
+ }
177271
+ async sendOn(sock, generation, frame) {
177272
+ if (this.sock !== sock || this.generation !== generation || this.closeStarted || this.closedErr)
177273
+ return;
177274
+ await sendFrame(sock, frame);
177275
+ }
177276
+ handleUnexpectedDrop(sock, generation, cause) {
177277
+ this.cancelRestoredDebounce();
177278
+ this.abortGeneration(generation);
177279
+ this.generation += 1;
177280
+ sock.close();
177281
+ this.enqueueConnectionState({ state: "down", cause });
177282
+ this.scheduleReconnectAfterDrop(cause);
177283
+ }
177284
+ scheduleReconnectAfterDrop(trigger) {
177285
+ if (this.closeStarted || this.reconnecting)
177286
+ return;
177287
+ const promise2 = this.reconnectWithRetry(trigger).catch((err) => {
177288
+ if (!this.closeStarted)
177289
+ this.failFatal(err instanceof Error ? err : new SubcProviderError(String(err)));
177290
+ }).finally(() => {
177291
+ if (this.reconnecting === promise2)
177292
+ this.reconnecting = null;
177293
+ });
177294
+ this.reconnecting = promise2;
177295
+ }
177296
+ async reconnectWithRetry(_trigger) {
177297
+ let attempt = 0;
177298
+ let delay = this.opts.reconnectBackoff.baseMs;
177299
+ for (;; ) {
177300
+ if (this.closeStarted)
177301
+ throw new SubcProviderError("provider closed");
177302
+ attempt += 1;
177303
+ this.enqueueConnectionState({ state: "reconnecting", attempt });
177304
+ try {
177305
+ const opened = await SubcProvider.openConnection(this.opts);
177306
+ if (this.closeStarted) {
177307
+ opened.sock.close();
177308
+ throw new SubcProviderError("provider closed");
177309
+ }
177310
+ this.replaceConnection(opened);
177311
+ return;
177312
+ } catch (err) {
177313
+ if (this.closeStarted)
177314
+ throw err;
177315
+ if (!isProviderReconnectTransient(err))
177316
+ throw err;
177317
+ await this.opts.sleep(delay);
177318
+ delay = Math.min(delay * 2, this.opts.reconnectBackoff.capMs);
177319
+ }
177320
+ }
177321
+ }
177322
+ replaceConnection(opened) {
177323
+ this.sock.close();
177324
+ this.sock = opened.sock;
177325
+ this.currentConn = opened.conn;
177326
+ this.storage = opened.ack.storage;
177327
+ this.closedErr = null;
177328
+ this.connectionEpoch += 1;
177329
+ this.connectionToken = newConnectionToken();
177330
+ this.liveRoutes.clear();
177331
+ this.nextCorr = 1n;
177332
+ const generation = this.generation;
177333
+ this.readLoop(opened.sock, generation);
177334
+ this.scheduleRestored(generation, this.connectionEpoch);
177335
+ }
177336
+ scheduleRestored(generation, epoch) {
177337
+ if (!this.opts.onConnectionState)
177338
+ return;
177339
+ const token = ++this.restoredDebounceToken;
177340
+ this.opts.sleep(this.opts.restoredDebounceMs).then(() => {
177341
+ if (token === this.restoredDebounceToken && !this.closeStarted && this.sock && this.generation === generation && this.connectionEpoch === epoch) {
177342
+ this.enqueueConnectionState({ state: "restored", epoch });
177343
+ }
177344
+ }).catch((err) => {
177345
+ if (token === this.restoredDebounceToken && !this.closeStarted) {
177346
+ console.warn("SubcProvider restored debounce timer failed", err);
177347
+ }
177348
+ });
177349
+ }
177350
+ cancelRestoredDebounce() {
177351
+ this.restoredDebounceToken += 1;
177352
+ }
177353
+ enqueueConnectionState(event) {
177354
+ if (!this.opts.onConnectionState)
177355
+ return;
177356
+ this.stateQueue.push(event);
177357
+ if (!this.drainingStateQueue)
177358
+ this.drainConnectionStateQueue();
177359
+ }
177360
+ async drainConnectionStateQueue() {
177361
+ if (this.drainingStateQueue)
177362
+ return;
177363
+ this.drainingStateQueue = true;
177364
+ try {
177365
+ while (this.stateQueue.length > 0) {
177366
+ const event = this.stateQueue[0];
177367
+ try {
177368
+ await this.opts.onConnectionState?.(event);
177369
+ this.stateQueue.shift();
177370
+ } catch (err) {
177371
+ if (event.state === "restored") {
177372
+ console.warn("SubcProvider restored callback failed; retrying delivery", err);
177373
+ await pauseBeforeStateRetry();
177374
+ continue;
177375
+ }
177376
+ console.warn("SubcProvider connection-state callback failed", err);
177377
+ this.stateQueue.shift();
177378
+ }
177379
+ }
177380
+ } finally {
177381
+ this.drainingStateQueue = false;
177382
+ if (this.stateQueue.length > 0)
177383
+ this.drainConnectionStateQueue();
177384
+ }
177385
+ }
177386
+ isLiveHandle(handle) {
177387
+ return belongsToConnection(handle, this.connectionToken) && this.liveRoutes.get(handle.channel) === handle;
177388
+ }
177389
+ assertLiveHandle(handle) {
177390
+ if (!this.isLiveHandle(handle))
177391
+ throw new StaleRouteHandleError(handle);
177392
+ }
177393
+ allocateCorr() {
177394
+ const maximum = 0xffffffffffffffffn;
177395
+ if (this.nextCorr > maximum) {
177396
+ const error51 = new SubcProviderError("channel-0 correlation id allocator exhausted", "corr_exhausted");
177397
+ this.handleUnexpectedDrop(this.sock, this.generation, error51);
177398
+ throw error51;
177399
+ }
177400
+ const corr = this.nextCorr;
177401
+ this.nextCorr += 1n;
177402
+ return corr;
177403
+ }
177404
+ failFatal(err) {
177405
+ if (!this.closedErr)
177406
+ this.closedErr = err;
177407
+ this.closeStarted = true;
177408
+ this.cancelRestoredDebounce();
177409
+ this.abortAllInflight();
177410
+ this.sock.close();
177411
+ this.finishClosed();
177412
+ }
177413
+ finishClosed() {
177414
+ this.resolveClosed();
177415
+ }
177416
+ }
177417
+ function routeKey(handle, corr) {
177418
+ return `${handle.channel}:${handle.epoch}:${corr}`;
177419
+ }
177420
+ function providerErrorFromFrame(frame) {
177421
+ try {
177422
+ const body = parseJson(frame.body);
177423
+ return new SubcProviderError(body.message ?? "subc error", body.code);
177424
+ } catch {
177425
+ return new SubcProviderError(Buffer4.from(frame.body).toString("utf8") || "subc error");
177426
+ }
177427
+ }
177428
+ function launchNonce(opts) {
177429
+ const nonce = opts.launchNonce ?? process.env[SUBC_LAUNCH_NONCE_ENV2];
177430
+ return nonce && nonce.length > 0 ? nonce : undefined;
177431
+ }
177432
+ var SUBC_LAUNCH_NONCE_ENV2 = "SUBC_LAUNCH_NONCE";
177433
+ function normalizeProviderConnectOptions(opts) {
177434
+ return {
177435
+ connectionFile: opts.connectionFile,
177436
+ manifest: opts.manifest,
177437
+ handler: opts.handler,
177438
+ health: opts.health ?? (() => ({ status: "ok" })),
177439
+ handshakeTimeoutMs: opts.handshakeTimeoutMs,
177440
+ controlOps: opts.controlOps,
177441
+ onBind: opts.onBind,
177442
+ onBound: opts.onBound,
177443
+ onRouteGone: opts.onRouteGone,
177444
+ reconnectBackoff: opts.reconnectBackoff ?? DEFAULT_RECONNECT_BACKOFF,
177445
+ sleep: opts.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms))),
177446
+ restoredDebounceMs: opts.restoredDebounceMs ?? DEFAULT_RESTORED_DEBOUNCE_MS,
177447
+ onConnectionState: opts.onConnectionState,
177448
+ launchNonce: opts.launchNonce
177449
+ };
177450
+ }
177451
+ function normalizedControlOps(controlOps) {
177452
+ if (controlOps === null)
177453
+ return null;
177454
+ const merged = new Set(controlOps ?? []);
177455
+ merged.add(HEALTH_CHECK_OP);
177456
+ return [...merged];
177457
+ }
177458
+ function buildHelloFrame(opts) {
177459
+ const nonce = launchNonce(opts);
177460
+ return buildFrame(FrameType.Hello, controlFlags(), 0, 0, HELLO_CORR, encodeJson({
177461
+ manifest: normalizeManifest(opts.manifest),
177462
+ protocol_ver: PROTOCOL_VERSION,
177463
+ control_ops: normalizedControlOps(opts.controlOps),
177464
+ ...nonce ? { launch_nonce: nonce } : {}
177465
+ }));
177466
+ }
177467
+ function isProviderReconnectTransient(err) {
177468
+ if (err instanceof SubcProviderError)
177469
+ return err.code === "duplicate_module_id";
177470
+ if (err instanceof SocketClosedError || err instanceof SocketTimeoutError)
177471
+ return true;
177472
+ if (err instanceof SocketWriteNotQueuedError || err instanceof SocketWriteQueuedError)
177473
+ return true;
177474
+ if (err instanceof AuthError)
177475
+ return true;
177476
+ if (err instanceof ConnectionFileError)
177477
+ return false;
177478
+ const code = errorCode2(err);
177479
+ return code === "ECONNREFUSED" || code === "ECONNRESET" || code === "EPIPE" || code === "ETIMEDOUT" || code === "ENOENT";
177480
+ }
177481
+ function errorCode2(err) {
177482
+ if (typeof err === "object" && err !== null && "code" in err) {
177483
+ const code = err.code;
177484
+ if (typeof code === "string")
177485
+ return code;
177486
+ }
177487
+ return;
177488
+ }
177489
+ async function pauseBeforeStateRetry() {
177490
+ await new Promise((resolve) => setTimeout(resolve, 0));
177491
+ }
177492
+ function controlFlags() {
177493
+ return buildFlags(false, Priority.Passive, false);
177494
+ }
177495
+ async function sendFrame(sock, frame) {
177496
+ await sock.write(encodeFrame(frame), Date.now() + WRITE_TIMEOUT_MS);
177497
+ }
177498
+ async function expectHelloAck(sock, deadline) {
177499
+ const frame = await sock.readFrame(deadline, deadline);
177500
+ switch (frame.header.ty) {
177501
+ case FrameType.HelloAck: {
177502
+ const ack = parseJson(frame.body);
177503
+ if (ack.negotiated_ver !== PROTOCOL_VERSION) {
177504
+ throw new SubcProviderError(`subc negotiated protocol ${ack.negotiated_ver}; expected exactly ${PROTOCOL_VERSION}`, "unsupported_version");
177505
+ }
177506
+ return ack;
177507
+ }
177508
+ case FrameType.Error: {
177509
+ const error51 = parseJson(frame.body);
177510
+ throw new SubcProviderError(`subc rejected HELLO: ${error51.code ?? "unknown"} — ${error51.message ?? "subc error"}`, error51.code);
177511
+ }
177512
+ default:
177513
+ throw new SubcProviderError(`unexpected frame ${FrameType[frame.header.ty]} awaiting HELLO_ACK`);
177514
+ }
177515
+ }
177516
+ function encodeJson(value) {
177517
+ return new Uint8Array(Buffer4.from(JSON.stringify(value), "utf8"));
177518
+ }
177519
+ function parseJson(bytes) {
177520
+ return JSON.parse(Buffer4.from(bytes).toString("utf8"));
177521
+ }
177522
+ function numberField(value, field) {
177523
+ if (typeof value !== "number" || !Number.isInteger(value)) {
177524
+ throw new SubcProviderError(`route.bind ${field} must be an integer`);
177525
+ }
177526
+ return value;
177527
+ }
177528
+ function bindRejection(decision) {
177529
+ if (decision === undefined || decision === true)
177530
+ return null;
177531
+ if (decision === false) {
177532
+ return { code: "route_rejected", message: "route.bind rejected by provider" };
177533
+ }
177534
+ if (decision.accept)
177535
+ return null;
177536
+ return {
177537
+ code: decision.code ?? "route_rejected",
177538
+ message: decision.message ?? "route.bind rejected by provider"
177539
+ };
177540
+ }
177541
+ function normalizeManifest(manifest) {
177542
+ return {
177543
+ module_id: manifest.module_id,
177544
+ module_version: manifest.module_version,
177545
+ protocol_ver: manifest.protocol_ver,
177546
+ trust_tier: manifest.trust_tier,
177547
+ provides: manifest.provides.map(normalizeProviderRole),
177548
+ consumes: manifest.consumes.map(normalizeConsumerRole),
177549
+ scheduled_tasks: manifest.scheduled_tasks.map(normalizeScheduledTask),
177550
+ bindings: {
177551
+ storage: {
177552
+ kind: manifest.bindings.storage.kind,
177553
+ scope: manifest.bindings.storage.scope,
177554
+ owns_schema: manifest.bindings.storage.owns_schema
177555
+ },
177556
+ vault_grants: manifest.bindings.vault_grants.map((grant) => ({
177557
+ secret: grant.secret,
177558
+ reason: grant.reason
177559
+ })),
177560
+ identity: {
177561
+ requires: [...manifest.bindings.identity.requires],
177562
+ optional: [...manifest.bindings.identity.optional]
177563
+ }
177564
+ }
177565
+ };
177566
+ }
177567
+ function normalizeProviderRole(role) {
177568
+ switch (role.role) {
177569
+ case "tool_provider":
177570
+ return {
177571
+ role: "tool_provider",
177572
+ tools: role.tools.map((tool) => ({
177573
+ name: tool.name,
177574
+ ...tool.description === undefined ? {} : { description: tool.description },
177575
+ execution_mode: tool.execution_mode,
177576
+ schema: tool.schema
177577
+ })),
177578
+ identity_scope: [...role.identity_scope],
177579
+ concurrency: role.concurrency,
177580
+ emits_push: role.emits_push,
177581
+ sub_supervises: role.sub_supervises
177582
+ };
177583
+ case "pipeline_stage":
177584
+ return {
177585
+ role: "pipeline_stage",
177586
+ stage: role.stage,
177587
+ applies_to: {
177588
+ provider: role.applies_to.provider,
177589
+ model: role.applies_to.model
177590
+ },
177591
+ interface: role.interface,
177592
+ declares_frozen_floor: role.declares_frozen_floor,
177593
+ needs_signals: [...role.needs_signals],
177594
+ conformance_class: role.conformance_class
177595
+ };
177596
+ case "management_surface":
177597
+ return {
177598
+ role: "management_surface",
177599
+ operations: role.operations.map((operation) => ({
177600
+ name: operation.name,
177601
+ kind: operation.kind
177602
+ })),
177603
+ config_schema: role.config_schema,
177604
+ observability: role.observability.map((surface) => ({
177605
+ name: surface.name,
177606
+ kind: surface.kind
177607
+ })),
177608
+ identity_scope: [...role.identity_scope]
177609
+ };
177610
+ case "internal_service":
177611
+ return {
177612
+ role: "internal_service",
177613
+ service_id: role.service_id,
177614
+ transport: role.transport,
177615
+ agent_facing: role.agent_facing,
177616
+ operations: [...role.operations]
177617
+ };
177618
+ }
177619
+ }
177620
+ function normalizeConsumerRole(role) {
177621
+ switch (role.role) {
177622
+ case "tool_client":
177623
+ return { role: "tool_client", of: [...role.of] };
177624
+ case "llm_client":
177625
+ return { role: "llm_client", via: role.via, auth: role.auth };
177626
+ case "service_client":
177627
+ return { role: "service_client", of: [...role.of] };
177628
+ }
177629
+ }
177630
+ function normalizeScheduledTask(task) {
177631
+ return {
177632
+ task_id: task.task_id,
177633
+ eligibility: {
177634
+ cooldown: task.eligibility.cooldown,
177635
+ window: task.eligibility.window
177636
+ },
177637
+ lease_scope: task.lease_scope,
177638
+ renews_during_calls: task.renews_during_calls,
177639
+ toolset: [...task.toolset],
177640
+ model_policy: {
177641
+ tier: task.model_policy.tier,
177642
+ fallback_chain: [...task.model_policy.fallback_chain]
177643
+ },
177644
+ step_cap: task.step_cap,
177645
+ circuit_breaker: {
177646
+ identical_failures: task.circuit_breaker.identical_failures
177647
+ }
177648
+ };
177649
+ }
177650
+ // ../plugin/src/features/magic-context/memory/embedding-synapse.ts
177651
+ init_logger();
177652
+ var SYNAPSE_DEFAULT_MODEL = "gte-modernbert-base-f16";
177653
+ var SYNAPSE_MAX_INPUT_TOKENS = 8192;
177654
+ var SYNAPSE_DEFAULT_QUERY_TIMEOUT_MS = 3000;
177655
+ var SYNAPSE_DEFAULT_BATCH_TIMEOUT_MS = 120000;
177656
+
177657
+ class SynapseEmbeddingError extends Error {
177658
+ code;
177659
+ retryAfterMs;
177660
+ permanent;
177661
+ constructor(code, message, options) {
177662
+ super(message, options?.cause === undefined ? undefined : { cause: options.cause });
177663
+ this.name = "SynapseEmbeddingError";
177664
+ this.code = code;
177665
+ this.permanent = options?.permanent ?? isPermanentSynapseCode(code);
177666
+ this.retryAfterMs = options?.retryAfterMs ?? (this.permanent ? undefined : 100);
177667
+ }
177668
+ }
177669
+ function isPermanentSynapseCode(code) {
177670
+ return code === "artifact_invalid" || code === "substitution_rejected" || code === "not_certified" || code === "probe_required" || code === "idempotency_conflict" || code === "schema_violation";
177671
+ }
177672
+ function asRecord(value) {
177673
+ return value !== null && typeof value === "object" ? value : null;
177674
+ }
177675
+ function responseBody(value) {
177676
+ const record2 = asRecord(value);
177677
+ const result = asRecord(record2?.result);
177678
+ return result ? { ...record2, ...result } : record2 ?? {};
177679
+ }
177680
+ function readRetryAfter(value) {
177681
+ const record2 = asRecord(value);
177682
+ const candidate = record2?.retry_after_ms ?? record2?.retryAfterMs;
177683
+ if (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0)
177684
+ return;
177685
+ return Math.ceil(candidate);
177686
+ }
177687
+ function readErrorCode(value) {
177688
+ const record2 = asRecord(value);
177689
+ if (typeof record2?.code === "string")
177690
+ return record2.code;
177691
+ if (value instanceof Error && "code" in value && typeof value.code === "string") {
177692
+ return value.code;
177693
+ }
177694
+ return;
177695
+ }
177696
+ function classifyError(value) {
177697
+ if (value instanceof SynapseEmbeddingError)
177698
+ return value;
177699
+ const code = readErrorCode(value) ?? (value instanceof Error ? value.name : "transport");
177700
+ const normalized = code.toLowerCase();
177701
+ let mapped = "transport";
177702
+ if (normalized.includes("queue_full"))
177703
+ mapped = "queue_full";
177704
+ else if (normalized.includes("model_loading"))
177705
+ mapped = "model_loading";
177706
+ else if (normalized.includes("timeout") || normalized.includes("deadline"))
177707
+ mapped = "timeout";
177708
+ else if (normalized.includes("artifact_invalid"))
177709
+ mapped = "artifact_invalid";
177710
+ else if (normalized.includes("substitution"))
177711
+ mapped = "substitution_rejected";
177712
+ else if (normalized.includes("not_certified"))
177713
+ mapped = "not_certified";
177714
+ else if (normalized.includes("probe_required"))
177715
+ mapped = "probe_required";
177716
+ else if (normalized.includes("idempotency_conflict"))
177717
+ mapped = "idempotency_conflict";
177718
+ else if (normalized.includes("schema"))
177719
+ mapped = "schema_violation";
177720
+ else if (normalized.includes("module_restarted") || normalized.includes("module restarted"))
177721
+ mapped = "module_restarted";
177722
+ const message = value instanceof Error ? value.message : String(value);
177723
+ return new SynapseEmbeddingError(mapped, message, {
177724
+ retryAfterMs: readRetryAfter(value) ?? (isPermanentSynapseCode(mapped) ? undefined : 100),
177725
+ cause: value
177726
+ });
177727
+ }
177728
+ function wait(ms) {
177729
+ return new Promise((resolve) => setTimeout(resolve, ms));
177730
+ }
177731
+ function sha256(value) {
177732
+ return createHash9("sha256").update(value).digest("hex");
177733
+ }
177734
+ function stableJson(value) {
177735
+ if (Array.isArray(value))
177736
+ return `[${value.map(stableJson).join(",")}]`;
177737
+ if (value && typeof value === "object") {
177738
+ return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => `${JSON.stringify(key)}:${stableJson(entry)}`).join(",")}}`;
177739
+ }
177740
+ return JSON.stringify(value);
177741
+ }
177742
+ function getSynapseLaneIdentity(model, fingerprint) {
177743
+ return `synapse:v1:${sha256(stableJson({ model, fingerprint }))}`;
177744
+ }
177745
+ function getSynapseBatchRequestKey(args) {
177746
+ return sha256(stableJson({
177747
+ op: "embed.batch",
177748
+ model: args.model,
177749
+ required_fingerprint: args.fingerprint,
177750
+ required_epoch: args.tableEpoch,
177751
+ allow_equivalent: false,
177752
+ accept_declared: false,
177753
+ ids: args.items.map((item) => item.id),
177754
+ content_sha256: args.items.map((item) => item.contentSha256)
177755
+ }));
177756
+ }
177757
+ function hashContent(text) {
177758
+ return sha256(text);
177759
+ }
177760
+ function extractCatalogEntries(value) {
177761
+ const body = responseBody(value);
177762
+ const raw = Array.isArray(body.models) ? body.models : Array.isArray(body.entries) ? body.entries : Array.isArray(value) ? value : [];
177763
+ const envelopeEpoch = typeof body.table_epoch === "number" && Number.isInteger(body.table_epoch) ? body.table_epoch : undefined;
177764
+ return raw.flatMap((entry) => {
177765
+ const record2 = asRecord(entry);
177766
+ if (!record2)
177767
+ return [];
177768
+ const model = typeof record2.model === "string" && record2.model.length > 0 ? record2.model : typeof record2.model_id === "string" ? record2.model_id : "";
177769
+ const fingerprint = typeof record2.fingerprint === "string" && record2.fingerprint.length > 0 ? record2.fingerprint : Array.isArray(record2.fingerprints) && typeof record2.fingerprints[0] === "string" ? record2.fingerprints[0] : "";
177770
+ const entryEpoch = record2.table_epoch ?? record2.tableEpoch;
177771
+ const tableEpoch = typeof entryEpoch === "number" && Number.isInteger(entryEpoch) ? entryEpoch : envelopeEpoch;
177772
+ const dims = record2.dims ?? record2.dimensions;
177773
+ if (model.length === 0 || fingerprint.length === 0 || typeof tableEpoch !== "number" || !Number.isInteger(tableEpoch)) {
177774
+ return [];
177775
+ }
177776
+ const recommendedBatch = record2.recommended_batch ?? record2.recommendedBatch;
177777
+ const state = typeof record2.state === "string" ? record2.state : undefined;
177778
+ return [
177779
+ {
177780
+ model,
177781
+ fingerprint,
177782
+ table_epoch: tableEpoch,
177783
+ ...typeof dims === "number" && Number.isInteger(dims) && dims > 0 ? { dims } : {},
177784
+ ...typeof recommendedBatch === "number" && recommendedBatch > 0 ? { recommended_batch: Math.floor(recommendedBatch) } : {},
177785
+ ...record2.provenance !== undefined ? { provenance: record2.provenance } : {},
177786
+ ...typeof record2.certified === "boolean" ? { certified: record2.certified } : {},
177787
+ ...typeof record2.status === "string" ? { status: record2.status } : state ? { status: state } : {}
177788
+ }
177789
+ ];
177790
+ });
177791
+ }
177792
+ function extractVector(value) {
177793
+ const body = responseBody(value);
177794
+ const fromVectors = Array.isArray(body.vectors) ? asRecord(body.vectors[0])?.vector : undefined;
177795
+ const raw = fromVectors ?? body.vector ?? body.embedding;
177796
+ if (!Array.isArray(raw) || raw.some((item) => typeof item !== "number" || !Number.isFinite(item))) {
177797
+ return null;
177798
+ }
177799
+ return { vector: Float32Array.from(raw), metadata: body };
177800
+ }
177801
+ function extractBatchItems(value) {
177802
+ const body = responseBody(value);
177803
+ const raw = Array.isArray(body.vectors) ? body.vectors : Array.isArray(body.items) ? body.items : Array.isArray(body.results) ? body.results : [];
177804
+ return raw.flatMap((item) => {
177805
+ const record2 = asRecord(item);
177806
+ return record2 ? [record2] : [];
177807
+ });
177808
+ }
177809
+ var sharedClient = null;
177810
+ var sharedClientFile = null;
177811
+ var sharedClientPromise = null;
177812
+ var factoryClients = new WeakMap;
177813
+ async function getSharedClient(options) {
177814
+ if (options.clientFactory) {
177815
+ let promise2 = factoryClients.get(options.clientFactory);
177816
+ if (!promise2) {
177817
+ promise2 = options.clientFactory();
177818
+ factoryClients.set(options.clientFactory, promise2);
177819
+ }
177820
+ return promise2;
177821
+ }
177822
+ if (sharedClient && sharedClientFile === options.connectionFile)
177823
+ return sharedClient;
177824
+ if (sharedClientPromise && sharedClientFile === options.connectionFile)
177825
+ return sharedClientPromise;
177826
+ sharedClientFile = options.connectionFile;
177827
+ sharedClientPromise = SubcClient.connect({ connectionFile: options.connectionFile }).then((client) => {
177828
+ sharedClient = client;
177829
+ return client;
177830
+ });
177831
+ return sharedClientPromise;
177832
+ }
177833
+
177834
+ class SynapseEmbeddingProvider {
177835
+ modelId;
177836
+ maxInputTokens = SYNAPSE_MAX_INPUT_TOKENS;
177837
+ metadata;
177838
+ options;
177839
+ client = null;
177840
+ initialized = false;
177841
+ initializing = null;
177842
+ permanentFailure = false;
177843
+ batchLimit = 16;
177844
+ constructor(options) {
177845
+ this.options = options;
177846
+ const model = options.model || SYNAPSE_DEFAULT_MODEL;
177847
+ const fingerprint = options.fingerprint ?? "";
177848
+ this.metadata = fingerprint && Number.isInteger(options.tableEpoch) && Number.isInteger(options.dims) && (options.dims ?? 0) > 0 ? {
177849
+ model,
177850
+ fingerprint,
177851
+ table_epoch: options.tableEpoch,
177852
+ dims: options.dims,
177853
+ ...options.recommendedBatch ? { recommended_batch: Math.max(1, Math.floor(options.recommendedBatch)) } : {},
177854
+ ...options.provenance !== undefined ? { provenance: options.provenance } : {},
177855
+ laneIdentity: getSynapseLaneIdentity(model, fingerprint)
177856
+ } : null;
177857
+ this.modelId = this.metadata?.laneIdentity ?? "synapse:v1:pending";
177858
+ this.batchLimit = this.metadata?.recommended_batch ?? 16;
177859
+ }
177860
+ static async discover(options) {
177861
+ const provider = new SynapseEmbeddingProvider(options);
177862
+ if (!await provider.initialize() || !provider.metadata) {
177863
+ throw new SynapseEmbeddingError("not_certified", "Synapse lane is not ready");
177864
+ }
177865
+ return provider.metadata;
177866
+ }
177867
+ async initialize() {
177868
+ if (this.initialized)
177869
+ return true;
177870
+ if (this.permanentFailure)
177871
+ return false;
177872
+ if (this.initializing)
177873
+ return this.initializing;
177874
+ this.initializing = (async () => {
177875
+ try {
177876
+ if (!this.options.clientFactory && !await connectionFileExists(this.options.connectionFile)) {
177877
+ throw new SynapseEmbeddingError("transport", `Synapse connection file is unavailable: ${this.options.connectionFile}`);
177878
+ }
177879
+ this.client = await getSharedClient(this.options);
177880
+ if (!this.metadata) {
177881
+ const discovered = await this.callWithRetry("models.list", {}, this.options.queryTimeoutMs ?? SYNAPSE_DEFAULT_QUERY_TIMEOUT_MS, false);
177882
+ const entries = extractCatalogEntries(discovered);
177883
+ const requested = this.options.model?.trim() || SYNAPSE_DEFAULT_MODEL;
177884
+ const entry = entries.find((candidate) => candidate.model === requested);
177885
+ if (!entry) {
177886
+ throw new SynapseEmbeddingError("artifact_invalid", `Synapse models.list did not return requested model ${requested}`);
177887
+ }
177888
+ if (entry.certified === false || entry.status === "not_certified") {
177889
+ throw new SynapseEmbeddingError("not_certified", `Synapse model ${entry.model} is not certified`);
177890
+ }
177891
+ const metadata = {
177892
+ ...entry,
177893
+ laneIdentity: getSynapseLaneIdentity(entry.model, entry.fingerprint)
177894
+ };
177895
+ this.metadata = metadata;
177896
+ this.modelId = metadata.laneIdentity;
177897
+ this.batchLimit = metadata.recommended_batch ?? this.batchLimit;
177898
+ }
177899
+ this.initialized = true;
177900
+ return true;
177901
+ } catch (error51) {
177902
+ const classified = classifyError(error51);
177903
+ if (classified.permanent) {
177904
+ this.permanentFailure = true;
177905
+ log(`[magic-context] Synapse lane disabled: ${classified.code}: ${classified.message}`);
177906
+ } else {
177907
+ log(`[magic-context] Synapse lane unavailable: ${classified.message}`);
177908
+ }
177909
+ this.initialized = false;
177910
+ return false;
177911
+ } finally {
177912
+ this.initializing = null;
177913
+ }
177914
+ })();
177915
+ return this.initializing;
177916
+ }
177917
+ async embed(text, signal) {
177918
+ if (!await this.initialize() || signal?.aborted || !this.metadata)
177919
+ return null;
177920
+ try {
177921
+ const value = await this.callWithRetry("embed.query", this.requestConstraints({
177922
+ text,
177923
+ deadline_ms: this.options.queryTimeoutMs ?? SYNAPSE_DEFAULT_QUERY_TIMEOUT_MS
177924
+ }), this.options.queryTimeoutMs ?? SYNAPSE_DEFAULT_QUERY_TIMEOUT_MS, true, signal);
177925
+ const extracted = extractVector(value);
177926
+ if (!extracted)
177927
+ throw new SynapseEmbeddingError("schema_violation", "Synapse query returned no vector");
177928
+ this.validateResponse(extracted.metadata, extracted.vector.length);
177929
+ return extracted.vector;
177930
+ } catch (error51) {
177931
+ this.logCallFailure(error51, "embed.query");
177932
+ return null;
177933
+ }
177934
+ }
177935
+ async embedBatch(texts, signal) {
177936
+ if (texts.length === 0)
177937
+ return [];
177938
+ const items = texts.map((text, index) => ({
177939
+ id: `item:${index}`,
177940
+ text,
177941
+ contentSha256: hashContent(text)
177942
+ }));
177943
+ const map2 = await this.embedItems(items, signal);
177944
+ return items.map((item) => map2.get(item.id) ?? null);
177945
+ }
177946
+ async embedItems(items, signal) {
177947
+ const output = new Map;
177948
+ if (items.length === 0 || !await this.initialize() || !this.metadata || signal?.aborted) {
177949
+ return output;
177950
+ }
177951
+ for (let start = 0;start < items.length; start += this.batchLimit) {
177952
+ if (signal?.aborted || this.permanentFailure)
177953
+ break;
177954
+ const page = items.slice(start, start + this.batchLimit);
177955
+ try {
177956
+ const requestKey = this.requestKey(page);
177957
+ let body = {};
177958
+ let restarted = false;
177959
+ for (;; ) {
177960
+ try {
177961
+ body = await this.callWithRetry("embed.batch", this.batchRequest(page, requestKey), this.options.batchTimeoutMs ?? SYNAPSE_DEFAULT_BATCH_TIMEOUT_MS, true, signal);
177962
+ const first = responseBody(body);
177963
+ const jobId = typeof first.job_id === "string" ? first.job_id : null;
177964
+ if (jobId)
177965
+ body = await this.pollBatch(jobId, requestKey, signal);
177966
+ break;
177967
+ } catch (error51) {
177968
+ const classified = classifyError(error51);
177969
+ if (classified.code !== "module_restarted" || restarted)
177970
+ throw classified;
177971
+ restarted = true;
177972
+ }
177973
+ }
177974
+ const batchEnvelope = responseBody(body);
177975
+ for (const item of extractBatchItems(body)) {
177976
+ const id = typeof item.id === "string" ? item.id : "";
177977
+ const vector = item.vector ?? item.embedding;
177978
+ if (!id || !Array.isArray(vector)) {
177979
+ throw new SynapseEmbeddingError("schema_violation", "Synapse batch item is malformed");
177980
+ }
177981
+ const expected = page.find((candidate) => candidate.id === id);
177982
+ if (!expected) {
177983
+ throw new SynapseEmbeddingError("schema_violation", `Synapse returned unknown item ${id}`);
177984
+ }
177985
+ if (typeof item.content_sha256 === "string" && item.content_sha256 !== expected.contentSha256) {
177986
+ throw new SynapseEmbeddingError("artifact_invalid", `Synapse content hash mismatch for item ${id}`);
177987
+ }
177988
+ const vectorArray = Float32Array.from(vector);
177989
+ this.validateResponse({ ...batchEnvelope, ...item }, vectorArray.length);
177990
+ output.set(id, vectorArray);
177991
+ }
177992
+ } catch (error51) {
177993
+ const classified = classifyError(error51);
177994
+ this.logCallFailure(classified, "embed.batch");
177995
+ if (classified.code === "idempotency_conflict")
177996
+ throw classified;
177997
+ if (classified.permanent) {
177998
+ this.permanentFailure = true;
177999
+ this.initialized = false;
178000
+ break;
178001
+ }
178002
+ }
178003
+ }
178004
+ return output;
178005
+ }
178006
+ async dispose() {
178007
+ this.initialized = false;
178008
+ this.client = null;
178009
+ }
178010
+ isLoaded() {
178011
+ return this.initialized;
178012
+ }
178013
+ requestConstraints(extra) {
178014
+ const metadata = this.metadata;
178015
+ if (!metadata)
178016
+ return extra;
178017
+ return {
178018
+ ...extra,
178019
+ model: metadata.model,
178020
+ required_fingerprint: metadata.fingerprint,
178021
+ required_epoch: metadata.table_epoch,
178022
+ allow_equivalent: false,
178023
+ accept_declared: false
178024
+ };
178025
+ }
178026
+ batchRequest(items, requestKey) {
178027
+ return this.requestConstraints({
178028
+ items: items.map((item) => ({
178029
+ id: item.id,
178030
+ text: item.text,
178031
+ content_sha256: item.contentSha256
178032
+ })),
178033
+ request_key: requestKey
178034
+ });
178035
+ }
178036
+ requestKey(items) {
178037
+ if (!this.metadata)
178038
+ throw new SynapseEmbeddingError("transport", "Synapse metadata is unavailable");
178039
+ return getSynapseBatchRequestKey({
178040
+ model: this.metadata.model,
178041
+ fingerprint: this.metadata.fingerprint,
178042
+ tableEpoch: this.metadata.table_epoch,
178043
+ items
178044
+ });
178045
+ }
178046
+ async pollBatch(jobId, requestKey, signal) {
178047
+ let cursor = null;
178048
+ const allItems = [];
178049
+ for (;; ) {
178050
+ if (signal?.aborted)
178051
+ return {};
178052
+ const body = await this.callWithRetry("embed.result", this.requestConstraints({
178053
+ job_id: jobId,
178054
+ cursor,
178055
+ request_key: requestKey
178056
+ }), this.options.batchTimeoutMs ?? SYNAPSE_DEFAULT_BATCH_TIMEOUT_MS, true, signal);
178057
+ const parsed = responseBody(body);
178058
+ const items = extractBatchItems(body);
178059
+ allItems.push(...items);
178060
+ const nextCursor = parsed.next_cursor ?? parsed.cursor;
178061
+ const done = parsed.done === true || parsed.complete === true || nextCursor === undefined || nextCursor === null;
178062
+ if (done)
178063
+ return { ...parsed, items: allItems };
178064
+ cursor = nextCursor;
178065
+ }
178066
+ }
178067
+ async callWithRetry(method, params, timeoutMs, retryEmbeddings, signal) {
178068
+ let attempt = 0;
178069
+ for (;; ) {
178070
+ if (signal?.aborted)
178071
+ throw new SynapseEmbeddingError("transport", "Synapse request aborted");
178072
+ try {
178073
+ if (!this.client)
178074
+ throw new SynapseEmbeddingError("transport", "Synapse client is unavailable");
178075
+ return await this.client.call(this.options.moduleId ?? "synapse", method, params, {
178076
+ timeoutMs,
178077
+ targetKind: "management_surface",
178078
+ identity: {
178079
+ project_root: this.options.projectRoot,
178080
+ harness: getHarness(),
178081
+ session: this.options.session
178082
+ }
178083
+ });
178084
+ } catch (error51) {
178085
+ const classified = classifyError(error51);
178086
+ if (classified.code === "idempotency_conflict")
178087
+ throw classified;
178088
+ const outcomeUnknown = error51 instanceof SubcCallError && error51.kind === "outcome_unknown";
178089
+ const retryable = !classified.permanent && (retryEmbeddings || !outcomeUnknown);
178090
+ if (!retryable || attempt >= 3)
178091
+ throw classified;
178092
+ const delay = classified.retryAfterMs ?? Math.min(2000, 100 * 2 ** attempt);
178093
+ attempt += 1;
178094
+ await wait(delay);
178095
+ }
178096
+ }
178097
+ }
178098
+ validateResponse(body, dims) {
178099
+ const metadata = this.metadata;
178100
+ if (!metadata) {
178101
+ throw new SynapseEmbeddingError("artifact_invalid", "Synapse lane metadata missing");
178102
+ }
178103
+ if (metadata.dims === undefined) {
178104
+ const envelopeDims = body.dims;
178105
+ if (typeof envelopeDims === "number" && envelopeDims !== dims) {
178106
+ throw new SynapseEmbeddingError("artifact_invalid", `Synapse envelope declares ${envelopeDims} dimensions but the vector has ${dims}`);
178107
+ }
178108
+ metadata.dims = dims;
178109
+ }
178110
+ if (dims !== metadata.dims) {
178111
+ throw new SynapseEmbeddingError("artifact_invalid", `Synapse returned ${dims} dimensions, expected ${metadata.dims}`);
178112
+ }
178113
+ const fingerprint = body.fingerprint ?? body.served_fingerprint;
178114
+ if (typeof fingerprint !== "string") {
178115
+ throw new SynapseEmbeddingError("artifact_invalid", "Synapse response omitted the served fingerprint");
178116
+ }
178117
+ if (fingerprint !== metadata.fingerprint) {
178118
+ throw new SynapseEmbeddingError("substitution_rejected", `Synapse fingerprint changed from ${metadata.fingerprint} to ${fingerprint}`);
178119
+ }
178120
+ const epoch = body.table_epoch ?? body.tableEpoch;
178121
+ if (typeof epoch !== "number") {
178122
+ throw new SynapseEmbeddingError("artifact_invalid", "Synapse response omitted the served table epoch");
178123
+ }
178124
+ if (epoch !== metadata.table_epoch) {
178125
+ throw new SynapseEmbeddingError("substitution_rejected", `Synapse table epoch changed from ${metadata.table_epoch} to ${epoch}`);
178126
+ }
178127
+ }
178128
+ logCallFailure(error51, operation) {
178129
+ const classified = classifyError(error51);
178130
+ if (classified.permanent)
178131
+ this.permanentFailure = true;
178132
+ const suffix = classified.retryAfterMs === undefined ? "" : ` retry_after_ms=${classified.retryAfterMs}`;
178133
+ log(`[magic-context] Synapse ${operation} failed: ${classified.code}${suffix}: ${classified.message}`);
178134
+ }
178135
+ }
178136
+
175087
178137
  // ../plugin/src/features/magic-context/memory/normalize-hash.ts
175088
- import { createHash as createHash7 } from "node:crypto";
178138
+ import { createHash as createHash10 } from "node:crypto";
175089
178139
  function normalizeMemoryContent(content) {
175090
178140
  return content.toLowerCase().replace(/\s+/g, " ").trim();
175091
178141
  }
175092
178142
  function computeNormalizedHash(content) {
175093
178143
  const normalized = normalizeMemoryContent(content);
175094
- return createHash7("md5").update(normalized).digest("hex");
178144
+ return createHash10("md5").update(normalized).digest("hex");
175095
178145
  }
175096
178146
 
175097
178147
  // ../plugin/src/features/magic-context/memory/embedding-identity.ts
@@ -175102,6 +178152,15 @@ function getEmbeddingProviderIdentity(config2) {
175102
178152
  if (config2.provider === "off") {
175103
178153
  return "embedding-provider:off";
175104
178154
  }
178155
+ if (config2.provider === "synapse") {
178156
+ const resolved = config2;
178157
+ if (!resolved.model || !resolved.synapse_fingerprint)
178158
+ return "synapse:v1:pending";
178159
+ return getSynapseLaneIdentity(resolved.model, resolved.synapse_fingerprint);
178160
+ }
178161
+ if (config2.provider !== "local" && config2.provider !== "openai-compatible") {
178162
+ throw new Error("Unknown embedding provider");
178163
+ }
175105
178164
  const truncate = config2.provider === "openai-compatible" ? config2.truncate?.trim() : undefined;
175106
178165
  const identityInput = config2.provider === "openai-compatible" ? {
175107
178166
  provider: "openai-compatible",
@@ -175891,7 +178950,7 @@ function getMemoryEmbedCoverage(db, projectPath, modelId) {
175891
178950
  }
175892
178951
 
175893
178952
  // ../plugin/src/features/magic-context/project-embedding-registry.ts
175894
- import { createHash as createHash8, randomUUID as randomUUID2 } from "node:crypto";
178953
+ import { createHash as createHash11, randomUUID as randomUUID2 } from "node:crypto";
175895
178954
  init_logger();
175896
178955
 
175897
178956
  // ../plugin/src/features/magic-context/git-commits/storage-git-commit-embeddings.ts
@@ -176282,6 +179341,12 @@ var EMBED_SLICE_RETRY_BASE_MS = 250;
176282
179341
  var EMBED_SLOW_FAILURE_NO_RETRY_MS = 1e4;
176283
179342
  var MAX_CONSECUTIVE_FAILED_BATCHES = 3;
176284
179343
  var projectRegistrations = new Map;
179344
+ var shadowRegistrations = new Map;
179345
+ var shadowQueue = [];
179346
+ var shadowWorker = null;
179347
+ var SHADOW_MAX_ITEMS_PER_TICK = 64;
179348
+ var SHADOW_MAX_BYTES_PER_TICK = 512 * 1024;
179349
+ var SHADOW_MAX_WALL_CLOCK_MS = 2000;
176285
179350
  var loadUnembeddedMemoriesStatements = new WeakMap;
176286
179351
  var upsertActiveIdentityStatements = new WeakMap;
176287
179352
  var backfillActiveIdentityStatements = new Map;
@@ -176293,6 +179358,35 @@ function markProjectLoadUntrusted(projectIdentity) {
176293
179358
  untrustedLoadProjects.add(projectIdentity);
176294
179359
  }
176295
179360
  var testProviderFactory = null;
179361
+ function synapseConfigFields(config2) {
179362
+ const raw = config2;
179363
+ return {
179364
+ ...typeof raw.model === "string" ? { model: raw.model } : {},
179365
+ ...typeof raw.synapse_fingerprint === "string" ? { fingerprint: raw.synapse_fingerprint } : {},
179366
+ ...typeof raw.synapse_table_epoch === "number" ? { tableEpoch: raw.synapse_table_epoch } : {},
179367
+ ...typeof raw.synapse_dims === "number" ? { dims: raw.synapse_dims } : {},
179368
+ ...raw.synapse_provenance !== undefined ? { provenance: raw.synapse_provenance } : {}
179369
+ };
179370
+ }
179371
+ function persistPrimaryDescriptor(db, registration) {
179372
+ const descriptorTable = db.prepare("SELECT 1 AS present FROM sqlite_master WHERE type = 'table' AND name = 'embedding_registrations'").get();
179373
+ if (!descriptorTable)
179374
+ return;
179375
+ const fields = synapseConfigFields(registration.config);
179376
+ db.prepare(`INSERT INTO embedding_registrations
179377
+ (project_path, provider_identity, model_id, chunk_model_id, fingerprint, table_epoch, dims, provenance_json, generation, updated_at)
179378
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
179379
+ ON CONFLICT(project_path) DO UPDATE SET
179380
+ provider_identity = excluded.provider_identity,
179381
+ model_id = excluded.model_id,
179382
+ chunk_model_id = excluded.chunk_model_id,
179383
+ fingerprint = excluded.fingerprint,
179384
+ table_epoch = excluded.table_epoch,
179385
+ dims = excluded.dims,
179386
+ provenance_json = excluded.provenance_json,
179387
+ generation = excluded.generation,
179388
+ updated_at = excluded.updated_at`).run(registration.projectIdentity, registration.providerIdentity, registration.modelId, registration.chunkModelId, fields.fingerprint ?? "", fields.tableEpoch ?? 0, fields.dims ?? 0, JSON.stringify(fields.provenance ?? {}), registration.generation, Date.now());
179389
+ }
176296
179390
  function resolveEmbeddingConfig(config2) {
176297
179391
  if (!config2 || config2.provider === "local") {
176298
179392
  return {
@@ -176321,9 +179415,26 @@ function resolveEmbeddingConfig(config2) {
176321
179415
  } : {}
176322
179416
  };
176323
179417
  }
176324
- return { provider: "off" };
179418
+ if (config2.provider === "off") {
179419
+ return { provider: "off" };
179420
+ }
179421
+ if (config2.provider === "synapse") {
179422
+ const synapse = config2;
179423
+ return {
179424
+ provider: "synapse",
179425
+ model: synapse.model?.trim() || "gte-modernbert-base-f16",
179426
+ max_input_tokens: SYNAPSE_MAX_INPUT_TOKENS,
179427
+ ...synapse.synapse_connection_file ? { synapse_connection_file: synapse.synapse_connection_file } : {},
179428
+ ...synapse.synapse_fingerprint ? { synapse_fingerprint: synapse.synapse_fingerprint } : {},
179429
+ ...typeof synapse.synapse_table_epoch === "number" ? { synapse_table_epoch: synapse.synapse_table_epoch } : {},
179430
+ ...typeof synapse.synapse_dims === "number" ? { synapse_dims: synapse.synapse_dims } : {},
179431
+ ...typeof synapse.synapse_recommended_batch === "number" ? { synapse_recommended_batch: synapse.synapse_recommended_batch } : {},
179432
+ ...synapse.synapse_provenance !== undefined ? { synapse_provenance: synapse.synapse_provenance } : {}
179433
+ };
179434
+ }
179435
+ throw new Error("Unknown embedding provider");
176325
179436
  }
176326
- function createProvider(config2) {
179437
+ function createProvider(config2, context) {
176327
179438
  if (testProviderFactory) {
176328
179439
  return testProviderFactory(config2);
176329
179440
  }
@@ -176341,7 +179452,24 @@ function createProvider(config2) {
176341
179452
  maxInputTokens: config2.max_input_tokens
176342
179453
  });
176343
179454
  }
176344
- return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
179455
+ if (config2.provider === "local") {
179456
+ return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
179457
+ }
179458
+ if (config2.provider === "synapse") {
179459
+ const synapse = config2;
179460
+ return new SynapseEmbeddingProvider({
179461
+ connectionFile: synapse.synapse_connection_file ?? "",
179462
+ projectRoot: context?.projectRoot ?? "",
179463
+ session: context?.session ?? "embedding",
179464
+ model: synapse.model,
179465
+ fingerprint: synapse.synapse_fingerprint,
179466
+ tableEpoch: synapse.synapse_table_epoch,
179467
+ dims: synapse.synapse_dims,
179468
+ recommendedBatch: synapse.synapse_recommended_batch,
179469
+ provenance: synapse.synapse_provenance
179470
+ });
179471
+ }
179472
+ throw new Error("Unknown embedding provider");
176345
179473
  }
176346
179474
  function stableStringify2(value) {
176347
179475
  if (Array.isArray(value)) {
@@ -176354,7 +179482,10 @@ function stableStringify2(value) {
176354
179482
  return JSON.stringify(value);
176355
179483
  }
176356
179484
  function sha256Prefix(value, length = 16) {
176357
- return createHash8("sha256").update(value).digest("hex").slice(0, length);
179485
+ return createHash11("sha256").update(value).digest("hex").slice(0, length);
179486
+ }
179487
+ function contentSha256(value) {
179488
+ return createHash11("sha256").update(value).digest("hex");
176358
179489
  }
176359
179490
  function getRuntimeFingerprint(config2) {
176360
179491
  if (config2.provider === "off") {
@@ -176381,6 +179512,7 @@ function snapshotFor(registration) {
176381
179512
  const providerIsOn = registration.providerIdentity !== OFF_PROVIDER_IDENTITY;
176382
179513
  const enabled = !registration.observationMode && providerIsOn && registration.features.memoryEnabled;
176383
179514
  const gitCommitEnabled = !registration.observationMode && providerIsOn && registration.features.gitCommitEnabled;
179515
+ const configuredModel = "model" in registration.config && typeof registration.config.model === "string" ? registration.config.model.trim() : "";
176384
179516
  return {
176385
179517
  projectIdentity: registration.projectIdentity,
176386
179518
  sourceDirectory: registration.sourceDirectory,
@@ -176392,7 +179524,7 @@ function snapshotFor(registration) {
176392
179524
  gitCommitEnabled,
176393
179525
  modelId: registration.observationMode || !providerIsOn ? "off" : registration.modelId,
176394
179526
  chunkModelId: registration.observationMode || !providerIsOn ? "off" : registration.chunkModelId,
176395
- model: registration.observationMode || !providerIsOn ? "off" : ("model" in registration.config) && registration.config.model.trim() ? registration.config.model.trim() : registration.modelId,
179527
+ model: registration.observationMode || !providerIsOn ? "off" : configuredModel ? configuredModel : registration.modelId,
176396
179528
  provider: registration.observationMode || !providerIsOn ? "off" : registration.config.provider ?? "local"
176397
179529
  };
176398
179530
  }
@@ -176499,9 +179631,9 @@ function getDeleteActiveIdentityStatement(db) {
176499
179631
  }
176500
179632
  return stmt;
176501
179633
  }
176502
- function staleModelsForScope(db, projectIdentity, scope, currentModelId, cutoff) {
179634
+ function staleModelsForScope(db, projectIdentity, scope, currentModelId, cutoff, protectedModelIds = new Set([currentModelId])) {
176503
179635
  const rows = getStaleIdentityStatement(db, scope).all(projectIdentity, scope, currentModelId, cutoff);
176504
- return rows.map((row) => row.modelId).filter((modelId) => typeof modelId === "string");
179636
+ return rows.map((row) => row.modelId).filter((modelId) => typeof modelId === "string" && !protectedModelIds.has(modelId));
176505
179637
  }
176506
179638
  function deleteStaleEmbeddingBatch(db, scope, projectIdentity, modelId, limit) {
176507
179639
  if (scope === "memory") {
@@ -176566,6 +179698,12 @@ function sweepStaleEmbeddingIdentitiesForProject(db, projectIdentity, now = Date
176566
179698
  return result;
176567
179699
  const cutoff = now - EMBEDDING_IDENTITY_GC_GRACE_MS;
176568
179700
  const deleteTracking = getDeleteActiveIdentityStatement(db);
179701
+ const shadow = shadowRegistrations.get(projectIdentity);
179702
+ const protectedModels = {
179703
+ memory: new Set([snapshot.modelId, ...shadow ? [shadow.modelId] : []]),
179704
+ commit: new Set([snapshot.modelId, ...shadow ? [shadow.modelId] : []]),
179705
+ chunk: new Set([snapshot.chunkModelId, ...shadow ? [shadow.chunkModelId] : []])
179706
+ };
176569
179707
  const scopes = [
176570
179708
  {
176571
179709
  scope: "memory",
@@ -176589,7 +179727,7 @@ function sweepStaleEmbeddingIdentitiesForProject(db, projectIdentity, now = Date
176589
179727
  for (const { scope, enabled, currentModelId } of scopes) {
176590
179728
  if (!enabled || remainingBudget === 0)
176591
179729
  continue;
176592
- for (const modelId of staleModelsForScope(db, projectIdentity, scope, currentModelId, cutoff)) {
179730
+ for (const modelId of staleModelsForScope(db, projectIdentity, scope, currentModelId, cutoff, protectedModels[scope])) {
176593
179731
  if (remainingBudget === 0)
176594
179732
  break;
176595
179733
  const deleted = deleteStaleEmbeddingBatch(db, scope, projectIdentity, modelId, remainingBudget);
@@ -176643,11 +179781,206 @@ function registerProjectEmbedding(db, projectIdentity, config2, features, source
176643
179781
  observationMode: false
176644
179782
  };
176645
179783
  projectRegistrations.set(projectIdentity, registration);
179784
+ persistPrimaryDescriptor(db, registration);
176646
179785
  if (!canReuseProvider) {
176647
179786
  disposeProvider(prior?.provider ?? null);
176648
179787
  }
176649
179788
  return snapshotFor(registration);
176650
179789
  }
179790
+ function startShadowWorker() {
179791
+ if (shadowWorker)
179792
+ return;
179793
+ shadowWorker = runShadowWorker().finally(() => {
179794
+ shadowWorker = null;
179795
+ if (shadowQueue.length > 0)
179796
+ startShadowWorker();
179797
+ });
179798
+ }
179799
+ function getShadowEmbeddingMeasurementCohort(projectIdentity) {
179800
+ const registration = shadowRegistrations.get(projectIdentity);
179801
+ if (!registration)
179802
+ return null;
179803
+ const fields = synapseConfigFields(registration.config);
179804
+ return {
179805
+ modelId: registration.modelId,
179806
+ chunkModelId: registration.chunkModelId,
179807
+ fingerprint: fields.fingerprint ?? "",
179808
+ epoch: fields.tableEpoch ?? 0,
179809
+ dims: fields.dims ?? 0
179810
+ };
179811
+ }
179812
+ function getPrimaryEmbeddingMeasurementCohort(projectIdentity) {
179813
+ const registration = projectRegistrations.get(projectIdentity);
179814
+ if (!registration)
179815
+ return null;
179816
+ const fields = synapseConfigFields(registration.config);
179817
+ return {
179818
+ modelId: registration.modelId,
179819
+ chunkModelId: registration.chunkModelId,
179820
+ fingerprint: fields.fingerprint ?? "",
179821
+ epoch: fields.tableEpoch ?? 0,
179822
+ dims: fields.dims ?? 0
179823
+ };
179824
+ }
179825
+ async function embedShadowTextForProject(projectIdentity, text, signal) {
179826
+ const registration = shadowRegistrations.get(projectIdentity);
179827
+ if (!registration)
179828
+ return null;
179829
+ try {
179830
+ return await registration.provider.embed(text, signal, "query");
179831
+ } catch (error51) {
179832
+ log("[magic-context] Synapse shadow query failed:", error51);
179833
+ return null;
179834
+ }
179835
+ }
179836
+ function enqueueShadowEmbeddingItems(projectIdentity, scope, ids) {
179837
+ if (ids.length === 0 || !shadowRegistrations.has(projectIdentity))
179838
+ return;
179839
+ shadowQueue.push({ projectIdentity, scope, ids: [...ids] });
179840
+ startShadowWorker();
179841
+ }
179842
+ async function embedShadowItems(registration, items, db, scope) {
179843
+ const raw = registration.config;
179844
+ const fingerprint = typeof raw.synapse_fingerprint === "string" ? raw.synapse_fingerprint : "";
179845
+ const tableEpoch = typeof raw.synapse_table_epoch === "number" ? raw.synapse_table_epoch : 0;
179846
+ const requestKey = getSynapseBatchRequestKey({
179847
+ model: typeof raw.model === "string" ? raw.model : SYNAPSE_DEFAULT_MODEL,
179848
+ fingerprint,
179849
+ tableEpoch,
179850
+ items
179851
+ });
179852
+ beginSynapseBatchLedger(db, {
179853
+ sessionId: `shadow:${registration.projectIdentity}`,
179854
+ projectPath: registration.projectIdentity,
179855
+ scope,
179856
+ manifest: items.map(({ id, contentSha256: contentSha2562 }) => ({ id, contentSha256: contentSha2562 })),
179857
+ requestKey
179858
+ });
179859
+ try {
179860
+ if (registration.provider.embedItems) {
179861
+ const vectors2 = await registration.provider.embedItems(items);
179862
+ finishSynapseBatchLedger(db, `shadow:${registration.projectIdentity}`, requestKey, vectors2.size === items.length ? "complete" : "partial");
179863
+ return vectors2;
179864
+ }
179865
+ const positional = await registration.provider.embedBatch(items.map((item) => item.text));
179866
+ const vectors = new Map(items.flatMap((item, index) => {
179867
+ const vector = positional[index];
179868
+ return vector ? [[item.id, vector]] : [];
179869
+ }));
179870
+ finishSynapseBatchLedger(db, `shadow:${registration.projectIdentity}`, requestKey, vectors.size === items.length ? "complete" : "partial");
179871
+ return vectors;
179872
+ } catch (error51) {
179873
+ finishSynapseBatchLedger(db, `shadow:${registration.projectIdentity}`, requestKey, "failed");
179874
+ throw error51;
179875
+ }
179876
+ }
179877
+ async function processShadowQueueItem(item) {
179878
+ const registration = shadowRegistrations.get(item.projectIdentity);
179879
+ if (!registration)
179880
+ return;
179881
+ const boundedIds = item.ids.slice(0, SHADOW_MAX_ITEMS_PER_TICK);
179882
+ if (item.scope === "memory") {
179883
+ const db2 = dbForShadowQueue.get(item.projectIdentity);
179884
+ if (!db2)
179885
+ return;
179886
+ const placeholders4 = boundedIds.map(() => "?").join(",");
179887
+ const rows = db2.prepare(`SELECT id, content, normalized_hash FROM memories
179888
+ WHERE project_path = ? AND id IN (${placeholders4}) AND status = 'active'`).all(item.projectIdentity, ...boundedIds.map((id) => Number(id)));
179889
+ const vectors2 = await embedShadowItems(registration, rows.map((row) => ({
179890
+ id: `memory:${row.id}`,
179891
+ text: row.content,
179892
+ contentSha256: contentSha256(row.content)
179893
+ })), db2, "memory");
179894
+ db2.transaction(() => {
179895
+ for (const row of rows) {
179896
+ const vector = vectors2.get(`memory:${row.id}`);
179897
+ if (vector)
179898
+ saveEmbeddingIfHashMatches(db2, row.id, vector, registration.modelId, row.normalized_hash);
179899
+ }
179900
+ })();
179901
+ return;
179902
+ }
179903
+ if (item.scope === "commit") {
179904
+ const db2 = dbForShadowQueue.get(item.projectIdentity);
179905
+ if (!db2)
179906
+ return;
179907
+ const placeholders4 = boundedIds.map(() => "?").join(",");
179908
+ const rows = db2.prepare(`SELECT sha, message FROM git_commits WHERE project_path = ? AND sha IN (${placeholders4})`).all(item.projectIdentity, ...boundedIds);
179909
+ const vectors2 = await embedShadowItems(registration, rows.map((row) => ({
179910
+ id: `commit:${row.sha}`,
179911
+ text: row.message,
179912
+ contentSha256: contentSha256(row.message)
179913
+ })), db2, "commit");
179914
+ db2.transaction(() => {
179915
+ for (const row of rows) {
179916
+ const vector = vectors2.get(`commit:${row.sha}`);
179917
+ if (vector)
179918
+ saveCommitEmbedding(db2, row.sha, vector, registration.modelId);
179919
+ }
179920
+ })();
179921
+ return;
179922
+ }
179923
+ const db = dbForShadowQueue.get(item.projectIdentity);
179924
+ if (!db)
179925
+ return;
179926
+ const placeholders3 = boundedIds.map(() => "?").join(",");
179927
+ const candidates = db.prepare(`SELECT id, session_id, start_message, end_message
179928
+ FROM compartments WHERE id IN (${placeholders3})`).all(...boundedIds.map((id) => Number(id)));
179929
+ const prepared = candidates.flatMap((candidate) => {
179930
+ const text = buildCanonicalChunkTextFromFts(db, candidate.session_id, candidate.start_message, candidate.end_message) || buildCompartmentSummaryFallbackText(db, candidate.id);
179931
+ if (!text)
179932
+ return [];
179933
+ const windows = chunkCanonicalText(text, candidate.start_message, candidate.end_message, SYNAPSE_MAX_INPUT_TOKENS);
179934
+ return windows.length > 0 ? [{ candidate, windows }] : [];
179935
+ });
179936
+ const items = prepared.flatMap((item2) => item2.windows.map((window) => ({
179937
+ id: `chunk:${item2.candidate.id}:${window.windowIndex}`,
179938
+ text: window.text,
179939
+ contentSha256: contentSha256(window.text)
179940
+ })));
179941
+ const vectors = await embedShadowItems(registration, items, db, "chunk");
179942
+ for (const item2 of prepared) {
179943
+ const rows = item2.windows.flatMap((window) => {
179944
+ const vector = vectors.get(`chunk:${item2.candidate.id}:${window.windowIndex}`);
179945
+ return vector ? [
179946
+ {
179947
+ compartmentId: item2.candidate.id,
179948
+ sessionId: item2.candidate.session_id,
179949
+ projectPath: registration.projectIdentity,
179950
+ window,
179951
+ modelId: registration.chunkModelId,
179952
+ vector
179953
+ }
179954
+ ] : [];
179955
+ });
179956
+ if (rows.length === item2.windows.length)
179957
+ replaceCompartmentChunkEmbeddings(db, rows);
179958
+ }
179959
+ }
179960
+ var dbForShadowQueue = new Map;
179961
+ async function runShadowWorker() {
179962
+ const startedAt = Date.now();
179963
+ let processed = 0;
179964
+ let processedBytes = 0;
179965
+ while (shadowQueue.length > 0 && processed < SHADOW_MAX_ITEMS_PER_TICK && Date.now() - startedAt < SHADOW_MAX_WALL_CLOCK_MS) {
179966
+ const item = shadowQueue.shift();
179967
+ if (!item)
179968
+ break;
179969
+ const itemBytes = item.ids.reduce((total, id) => total + id.length, 0);
179970
+ if (processed > 0 && processedBytes + itemBytes > SHADOW_MAX_BYTES_PER_TICK) {
179971
+ shadowQueue.unshift(item);
179972
+ break;
179973
+ }
179974
+ try {
179975
+ await processShadowQueueItem(item);
179976
+ } catch (error51) {
179977
+ log("[magic-context] Synapse shadow write failed:", error51);
179978
+ }
179979
+ processed += item.ids.length;
179980
+ processedBytes += itemBytes;
179981
+ await new Promise((resolve) => setTimeout(resolve, 0));
179982
+ }
179983
+ }
176651
179984
  function registerProjectInObservationMode(db, projectIdentity, sourceDirectory, failedConfig, failureSummary) {
176652
179985
  const prior = projectRegistrations.get(projectIdentity);
176653
179986
  const runtimeFingerprint = `observation:${sha256Prefix(failureSummary)}`;
@@ -176689,7 +180022,10 @@ function getOrCreateProjectProvider(registration) {
176689
180022
  if (registration.provider) {
176690
180023
  return registration.provider;
176691
180024
  }
176692
- const provider = createProvider(registration.config);
180025
+ const provider = createProvider(registration.config, {
180026
+ projectRoot: registration.sourceDirectory,
180027
+ session: `project:${registration.projectIdentity}`
180028
+ });
176693
180029
  registration.provider = provider;
176694
180030
  return provider;
176695
180031
  }
@@ -176709,7 +180045,7 @@ async function embedTextForProject(projectIdentity, text, signal, purpose = "pas
176709
180045
  if (!current || current.generation !== generation || current.runtimeFingerprint !== registration.runtimeFingerprint) {
176710
180046
  return null;
176711
180047
  }
176712
- return { vector, modelId, generation };
180048
+ return { vector, modelId, chunkModelId: registration.chunkModelId, generation };
176713
180049
  }
176714
180050
  async function embedBatchForProject(projectIdentity, texts, signal, purpose = "passage") {
176715
180051
  if (texts.length === 0) {
@@ -176734,31 +180070,81 @@ async function embedBatchForProject(projectIdentity, texts, signal, purpose = "p
176734
180070
  }
176735
180071
  return { vectors, modelId, generation };
176736
180072
  }
176737
- async function embedTextsWindowBounded(projectIdentity, texts, signal) {
176738
- if (texts.length <= MAX_WINDOWS_PER_EMBED_CALL) {
176739
- return embedBatchForProject(projectIdentity, texts, signal);
180073
+ async function embedItemsForProject(projectIdentity, items, signal, db, sessionId = projectIdentity) {
180074
+ const registration = projectRegistrations.get(projectIdentity);
180075
+ if (!registration || registration.observationMode || items.length === 0)
180076
+ return null;
180077
+ const generation = registration.generation;
180078
+ const modelId = registration.modelId;
180079
+ const runtimeFingerprint = registration.runtimeFingerprint;
180080
+ const provider = getOrCreateProjectProvider(registration);
180081
+ if (!provider)
180082
+ return null;
180083
+ const rawConfig = registration.config;
180084
+ const fingerprint = typeof rawConfig.synapse_fingerprint === "string" ? rawConfig.synapse_fingerprint : "";
180085
+ const tableEpoch = typeof rawConfig.synapse_table_epoch === "number" ? rawConfig.synapse_table_epoch : undefined;
180086
+ const isSynapse = registration.providerIdentity.startsWith("synapse:v1:") && fingerprint && tableEpoch !== undefined;
180087
+ const ledgerKey = isSynapse ? getSynapseBatchRequestKey({
180088
+ model: typeof rawConfig.model === "string" ? rawConfig.model : registration.modelId,
180089
+ fingerprint,
180090
+ tableEpoch,
180091
+ items
180092
+ }) : null;
180093
+ if (db && ledgerKey) {
180094
+ beginSynapseBatchLedger(db, {
180095
+ sessionId,
180096
+ projectPath: projectIdentity,
180097
+ scope: items[0].id.split(":", 1)[0],
180098
+ manifest: items.map(({ id, contentSha256: contentSha2562 }) => ({ id, contentSha256: contentSha2562 })),
180099
+ requestKey: ledgerKey
180100
+ });
180101
+ }
180102
+ let vectors;
180103
+ try {
180104
+ if (provider.embedItems) {
180105
+ vectors = await provider.embedItems(items, signal);
180106
+ } else {
180107
+ const positional = await provider.embedBatch(items.map((item) => item.text), signal, "passage");
180108
+ vectors = new Map(items.flatMap((item, index) => {
180109
+ const vector = positional[index];
180110
+ return vector ? [[item.id, vector]] : [];
180111
+ }));
180112
+ }
180113
+ } catch (error51) {
180114
+ if (db && ledgerKey)
180115
+ finishSynapseBatchLedger(db, sessionId, ledgerKey, "failed");
180116
+ throw error51;
180117
+ }
180118
+ if (db && ledgerKey) {
180119
+ finishSynapseBatchLedger(db, sessionId, ledgerKey, vectors.size === items.length ? "complete" : "partial");
180120
+ }
180121
+ const current = projectRegistrations.get(projectIdentity);
180122
+ if (!current || current.generation !== generation || current.runtimeFingerprint !== runtimeFingerprint) {
180123
+ return null;
180124
+ }
180125
+ return { vectors, modelId, generation };
180126
+ }
180127
+ async function embedItemsWindowBounded(projectIdentity, items, signal, db) {
180128
+ if (items.length <= MAX_WINDOWS_PER_EMBED_CALL) {
180129
+ return embedItemsForProject(projectIdentity, items, signal, db, projectIdentity);
176740
180130
  }
176741
- const vectors = [];
180131
+ const vectors = new Map;
176742
180132
  let modelId = null;
176743
180133
  let generation = null;
176744
- for (let start = 0;start < texts.length; start += MAX_WINDOWS_PER_EMBED_CALL) {
176745
- if (signal?.aborted)
176746
- return null;
176747
- const sub = texts.slice(start, start + MAX_WINDOWS_PER_EMBED_CALL);
176748
- const result = await embedBatchForProject(projectIdentity, sub, signal);
180134
+ for (let start = 0;start < items.length; start += MAX_WINDOWS_PER_EMBED_CALL) {
180135
+ const result = await embedItemsForProject(projectIdentity, items.slice(start, start + MAX_WINDOWS_PER_EMBED_CALL), signal, db, projectIdentity);
176749
180136
  if (!result)
176750
180137
  return null;
176751
180138
  if (modelId === null) {
176752
180139
  modelId = result.modelId;
176753
180140
  generation = result.generation;
176754
- } else if (result.modelId !== modelId || result.generation !== generation) {
180141
+ } else if (modelId !== result.modelId || generation !== result.generation) {
176755
180142
  return null;
176756
180143
  }
176757
- vectors.push(...result.vectors);
180144
+ for (const [id, vector] of result.vectors)
180145
+ vectors.set(id, vector);
176758
180146
  }
176759
- if (modelId === null || generation === null)
176760
- return null;
176761
- return { vectors, modelId, generation };
180147
+ return modelId === null || generation === null ? null : { vectors, modelId, generation };
176762
180148
  }
176763
180149
  function isUnembeddedMemoryRow(row) {
176764
180150
  if (row === null || typeof row !== "object")
@@ -176783,13 +180169,17 @@ async function embedUnembeddedMemoriesForProject(db, projectIdentity, batchSize
176783
180169
  if (memories.length === 0)
176784
180170
  return 0;
176785
180171
  try {
176786
- const result = await embedBatchForProject(projectIdentity, memories.map((memory) => memory.content));
180172
+ const result = await embedItemsForProject(projectIdentity, memories.map((memory) => ({
180173
+ id: `memory:${memory.id}`,
180174
+ text: memory.content,
180175
+ contentSha256: contentSha256(memory.content)
180176
+ })), undefined, db, projectIdentity);
176787
180177
  if (!result)
176788
180178
  return 0;
176789
180179
  let embeddedCount = 0;
176790
180180
  db.transaction(() => {
176791
- for (const [index, memory] of memories.entries()) {
176792
- const embedding = result.vectors[index];
180181
+ for (const memory of memories) {
180182
+ const embedding = result.vectors.get(`memory:${memory.id}`);
176793
180183
  if (!embedding)
176794
180184
  continue;
176795
180185
  if (saveEmbeddingIfHashMatches(db, memory.id, embedding, result.modelId, memory.normalized_hash)) {
@@ -176797,6 +180187,7 @@ async function embedUnembeddedMemoriesForProject(db, projectIdentity, batchSize
176797
180187
  }
176798
180188
  }
176799
180189
  })();
180190
+ enqueueShadowEmbeddingItems(projectIdentity, "memory", memories.filter((memory) => result.vectors.has(`memory:${memory.id}`)).map((memory) => String(memory.id)));
176800
180191
  return embeddedCount;
176801
180192
  } catch (error51) {
176802
180193
  log("[magic-context] failed to proactively embed missing memories:", error51);
@@ -176810,19 +180201,24 @@ async function embedCommitBatch(db, projectIdentity, batchSize) {
176810
180201
  const commits = loadUnembeddedCommits(db, projectIdentity, snapshot.modelId, Math.max(1, Math.floor(batchSize)));
176811
180202
  if (commits.length === 0)
176812
180203
  return 0;
176813
- const result = await embedBatchForProject(projectIdentity, commits.map((commit) => commit.message));
180204
+ const result = await embedItemsForProject(projectIdentity, commits.map((commit) => ({
180205
+ id: `commit:${commit.sha}`,
180206
+ text: commit.message,
180207
+ contentSha256: contentSha256(commit.message)
180208
+ })), undefined, db, projectIdentity);
176814
180209
  if (!result)
176815
180210
  return 0;
176816
180211
  let embeddedCount = 0;
176817
180212
  db.transaction(() => {
176818
- for (const [index, commit] of commits.entries()) {
176819
- const embedding = result.vectors[index];
180213
+ for (const commit of commits) {
180214
+ const embedding = result.vectors.get(`commit:${commit.sha}`);
176820
180215
  if (!embedding)
176821
180216
  continue;
176822
180217
  saveCommitEmbedding(db, commit.sha, embedding, result.modelId);
176823
180218
  embeddedCount += 1;
176824
180219
  }
176825
180220
  })();
180221
+ enqueueShadowEmbeddingItems(projectIdentity, "commit", commits.filter((commit) => result.vectors.has(`commit:${commit.sha}`)).map((commit) => commit.sha));
176826
180222
  return embeddedCount;
176827
180223
  }
176828
180224
  async function drainCommitBacklogForProject(db, projectIdentity, deadline) {
@@ -176895,9 +180291,11 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
176895
180291
  windowCount += item.windows.length;
176896
180292
  i += 1;
176897
180293
  } while (i < prepared.length && windowCount + prepared[i].windows.length <= MAX_WINDOWS_PER_EMBED_CALL);
176898
- const texts = [];
176899
- for (const item of slice)
176900
- texts.push(...item.windows.map((w) => w.text));
180294
+ const items = slice.flatMap((item) => item.windows.map((window) => ({
180295
+ id: `chunk:${item.candidate.id}:${window.windowIndex}`,
180296
+ text: window.text,
180297
+ contentSha256: contentSha256(window.text)
180298
+ })));
176901
180299
  const persistedIds = new Set;
176902
180300
  for (let attempt = 0;attempt < EMBED_SLICE_RETRY_ATTEMPTS; attempt++) {
176903
180301
  if (signal?.aborted)
@@ -176905,19 +180303,17 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
176905
180303
  let result = null;
176906
180304
  const attemptStart = Date.now();
176907
180305
  try {
176908
- result = await embedTextsWindowBounded(projectIdentity, texts, signal);
180306
+ result = await embedItemsWindowBounded(projectIdentity, items, signal, db);
176909
180307
  } catch (error51) {
176910
180308
  log("[magic-context] failed to proactively embed compartment chunks:", error51);
176911
180309
  }
176912
180310
  if (signal?.aborted)
176913
180311
  break;
176914
180312
  if (result) {
176915
- let offset = 0;
176916
180313
  for (const item of slice) {
176917
- const vectors = result.vectors.slice(offset, offset + item.windows.length);
176918
- offset += item.windows.length;
176919
180314
  if (persistedIds.has(item.candidate.id))
176920
180315
  continue;
180316
+ const vectors = item.windows.map((window) => result.vectors.get(`chunk:${item.candidate.id}:${window.windowIndex}`));
176921
180317
  if (vectors.length !== item.windows.length || vectors.some((v) => !v)) {
176922
180318
  continue;
176923
180319
  }
@@ -176931,6 +180327,9 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
176931
180327
  }));
176932
180328
  replaceCompartmentChunkEmbeddings(db, rows);
176933
180329
  persistedIds.add(item.candidate.id);
180330
+ enqueueShadowEmbeddingItems(projectIdentity, "chunk", [
180331
+ String(item.candidate.id)
180332
+ ]);
176934
180333
  }
176935
180334
  }
176936
180335
  if (persistedIds.size === slice.length)
@@ -177099,7 +180498,24 @@ function createProvider2(config2) {
177099
180498
  maxInputTokens: config2.max_input_tokens
177100
180499
  });
177101
180500
  }
177102
- return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
180501
+ if (config2.provider === "local") {
180502
+ return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
180503
+ }
180504
+ if (config2.provider === "synapse") {
180505
+ const synapse = config2;
180506
+ return new SynapseEmbeddingProvider({
180507
+ connectionFile: synapse.synapse_connection_file ?? "",
180508
+ projectRoot: "",
180509
+ session: "embedding",
180510
+ model: synapse.model,
180511
+ fingerprint: synapse.synapse_fingerprint,
180512
+ tableEpoch: synapse.synapse_table_epoch,
180513
+ dims: synapse.synapse_dims,
180514
+ recommendedBatch: synapse.synapse_recommended_batch,
180515
+ provenance: synapse.synapse_provenance
180516
+ });
180517
+ }
180518
+ throw new Error("Unknown embedding provider");
177103
180519
  }
177104
180520
  function getOrCreateProvider() {
177105
180521
  if (provider) {
@@ -178991,7 +182407,7 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
178991
182407
  init_logger();
178992
182408
 
178993
182409
  // ../plugin/src/shared/redaction.ts
178994
- import { homedir as homedir3, userInfo } from "node:os";
182410
+ import { homedir as homedir4, userInfo } from "node:os";
178995
182411
  function escapeRegex3(value) {
178996
182412
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
178997
182413
  }
@@ -179040,7 +182456,7 @@ var SECRET_QUALIFIERS = new Set([
179040
182456
  "azure"
179041
182457
  ]);
179042
182458
  function sanitizePathString(value) {
179043
- const home = homedir3();
182459
+ const home = homedir4();
179044
182460
  const username = userInfo().username;
179045
182461
  let sanitized = value;
179046
182462
  if (home) {
@@ -180036,7 +183452,7 @@ function throwIfAborted2(signal) {
180036
183452
  }
180037
183453
 
180038
183454
  // ../plugin/src/features/magic-context/smart-notes/compiler.ts
180039
- import { createHash as createHash9 } from "node:crypto";
183455
+ import { createHash as createHash12 } from "node:crypto";
180040
183456
  init_logger();
180041
183457
 
180042
183458
  // ../plugin/src/features/magic-context/smart-notes/compiler-prompt.ts
@@ -180347,7 +183763,7 @@ Remember: output only the JSON object described by the system prompt.`;
180347
183763
  });
180348
183764
  const response = run.validated;
180349
183765
  const compiledCheck = normalizeCompiledCheck(response.compiled_check);
180350
- const manifest = normalizeManifest(response.manifest);
183766
+ const manifest = normalizeManifest2(response.manifest);
180351
183767
  const checkCron = normalizeCron(response.check_cron);
180352
183768
  for (const warning of manifestAdvisoryWarnings(compiledCheck, manifest)) {
180353
183769
  log(`[dreamer] smart note #${args.note.id}: manifest advisory — ${warning}`);
@@ -180426,7 +183842,7 @@ function normalizeCompiledCheck(source) {
180426
183842
  }
180427
183843
  return code;
180428
183844
  }
180429
- function normalizeManifest(manifest) {
183845
+ function normalizeManifest2(manifest) {
180430
183846
  const capabilities = Array.isArray(manifest.capabilities) ? unique(manifest.capabilities.slice(0, MAX_MANIFEST_ENTRIES).filter((cap) => ["readFile", "gitHeadSha", "gitTag", "gitLog", "httpGet"].includes(String(cap)))) : [];
180431
183847
  return {
180432
183848
  capabilities,
@@ -180470,7 +183886,7 @@ function manifestAdvisoryWarnings(code, manifest) {
180470
183886
  return warnings;
180471
183887
  }
180472
183888
  function hashCheck(surfaceCondition, compiledCheck, manifest, checkCron) {
180473
- return createHash9("sha256").update(surfaceCondition ?? "").update("\x00").update(compiledCheck).update("\x00").update(JSON.stringify(manifest)).update("\x00").update(checkCron).digest("hex");
183889
+ return createHash12("sha256").update(surfaceCondition ?? "").update("\x00").update(compiledCheck).update("\x00").update(JSON.stringify(manifest)).update("\x00").update(checkCron).digest("hex");
180474
183890
  }
180475
183891
  function extractJsonObject(output) {
180476
183892
  const fenced = output.match(/```(?:json)?\s*([\s\S]*?)```/i);
@@ -182405,7 +185821,7 @@ function normalizeOpenCodeRows(db, sessionId, rows) {
182405
185821
  const partsByMessageId = new Map;
182406
185822
  for (const row of partRows) {
182407
185823
  const parts = partsByMessageId.get(row.message_id) ?? [];
182408
- const parsed = parseJson(row.data);
185824
+ const parsed = parseJson2(row.data);
182409
185825
  if (parsed !== null)
182410
185826
  parts.push(parsed);
182411
185827
  partsByMessageId.set(row.message_id, parts);
@@ -182516,7 +185932,7 @@ function stringifyToolOutput(value) {
182516
185932
  return String(value);
182517
185933
  }
182518
185934
  }
182519
- function parseJson(value) {
185935
+ function parseJson2(value) {
182520
185936
  try {
182521
185937
  return JSON.parse(value);
182522
185938
  } catch {
@@ -182524,7 +185940,7 @@ function parseJson(value) {
182524
185940
  }
182525
185941
  }
182526
185942
  function parseJsonRecord2(value) {
182527
- const parsed = parseJson(value);
185943
+ const parsed = parseJson2(value);
182528
185944
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
182529
185945
  return null;
182530
185946
  return parsed;
@@ -183282,7 +186698,7 @@ function parseFrictionGateVerdict(verdict) {
183282
186698
  }
183283
186699
  function computeRetrospectiveWindowKey(flagged) {
183284
186700
  const anchors = flagged.map((message) => `${message.sessionId}:${message.ts}`).sort().join("|");
183285
- return createHash10("sha256").update(anchors).digest("hex").slice(0, 32);
186701
+ return createHash13("sha256").update(anchors).digest("hex").slice(0, 32);
183286
186702
  }
183287
186703
  function renderFrictionWindow(messages, flaggedOrdinals, radius = 2) {
183288
186704
  const flagged = new Set(flaggedOrdinals);
@@ -184136,18 +187552,23 @@ async function embedUnembeddedCommits(db, projectPath) {
184136
187552
  break;
184137
187553
  let embeddedThisBatch = 0;
184138
187554
  try {
184139
- const result = await embedBatchForProject(projectPath, rows.map((row) => row.message));
187555
+ const result = await embedItemsForProject(projectPath, rows.map((row) => ({
187556
+ id: `commit:${row.sha}`,
187557
+ text: row.message,
187558
+ contentSha256: contentSha256(row.message)
187559
+ })), undefined, db, projectPath);
184140
187560
  if (!result)
184141
187561
  break;
184142
187562
  db.transaction(() => {
184143
- for (const [index, row] of rows.entries()) {
184144
- const embedding2 = result.vectors[index];
187563
+ for (const row of rows) {
187564
+ const embedding2 = result.vectors.get(`commit:${row.sha}`);
184145
187565
  if (!embedding2)
184146
187566
  continue;
184147
187567
  saveCommitEmbedding(db, row.sha, embedding2, result.modelId);
184148
187568
  embeddedThisBatch += 1;
184149
187569
  }
184150
187570
  })();
187571
+ enqueueShadowEmbeddingItems(projectPath, "commit", rows.filter((row) => result.vectors.has(`commit:${row.sha}`)).map((row) => row.sha));
184151
187572
  } catch (error51) {
184152
187573
  log(`[git-commits] embed batch failed for ${projectPath}: ${error51 instanceof Error ? error51.message : String(error51)}`);
184153
187574
  break;
@@ -184303,7 +187724,11 @@ function searchGitCommitsSync(db, projectPath, query, options) {
184303
187724
  init_logger();
184304
187725
  var DREAM_TIMER_INTERVAL_MS = 15 * 60 * 1000;
184305
187726
  var GIT_COMMIT_BACKLOG_DRAIN_MAX_MS = 5 * 60 * 1000;
187727
+ var BOOT_PROJECT_JITTER_SLOT_MS = 1000;
184306
187728
  var activeTimer = null;
187729
+ var startupTimers = new Map;
187730
+ var startupJitters = new Map;
187731
+ var nextStartupJitterSlot = 0;
184307
187732
  function directoryStillExists(directory) {
184308
187733
  try {
184309
187734
  return statSync6(directory).isDirectory();
@@ -184327,39 +187752,53 @@ function openTimerDatabaseOrNull(context) {
184327
187752
  }
184328
187753
  var registeredProjects = new Map;
184329
187754
  async function startDreamScheduleTimer(args) {
187755
+ beginBootQuietPeriod();
184330
187756
  const db = openTimerDatabaseOrNull("schedule timer registration");
184331
187757
  if (!db)
184332
187758
  return;
184333
- await args.ensureRegistered(args.directory, db);
184334
- const snapshot = getProjectEmbeddingSnapshot(args.projectIdentity);
184335
187759
  const dreamingEnabled = Boolean(args.dreamerConfig && args.dreamerConfig.disable !== true);
184336
- const embeddingSweepEnabled = snapshot?.enabled ?? false;
184337
- const commitIndexingEnabled = snapshot?.gitCommitEnabled ?? false;
187760
+ const embeddingSweepEnabled = args.memoryEnabled === true;
187761
+ const commitIndexingEnabled = args.gitCommitIndexing?.enabled === true;
184338
187762
  if (!dreamingEnabled && !embeddingSweepEnabled && !commitIndexingEnabled) {
184339
187763
  return;
184340
187764
  }
184341
- const isNewRegistration = !registeredProjects.has(args.directory);
187765
+ const previousRegistration = registeredProjects.get(args.directory);
187766
+ const isNewRegistration = previousRegistration === undefined;
187767
+ if (previousRegistration && previousRegistration !== args) {
187768
+ const pendingStartup = startupTimers.get(args.directory);
187769
+ if (pendingStartup) {
187770
+ clearTimeout(pendingStartup);
187771
+ startupTimers.delete(args.directory);
187772
+ }
187773
+ }
184342
187774
  registeredProjects.set(args.directory, args);
184343
187775
  if (isNewRegistration) {
184344
187776
  log(`[dreamer] registered project ${args.projectIdentity} (dreaming=${dreamingEnabled} embeddings=${embeddingSweepEnabled} commits=${commitIndexingEnabled}; total=${registeredProjects.size})`);
184345
187777
  }
184346
187778
  if (!activeTimer) {
184347
187779
  log(`[dreamer] started independent schedule timer (every ${DREAM_TIMER_INTERVAL_MS / 60000}m)`);
184348
- runTick("startup");
187780
+ scheduleAfterBootQuiet(() => runTick("startup"));
184349
187781
  const timer = setInterval(() => runTick("interval"), DREAM_TIMER_INTERVAL_MS);
184350
187782
  if (typeof timer === "object" && "unref" in timer) {
184351
187783
  timer.unref();
184352
187784
  }
184353
187785
  activeTimer = timer;
184354
- } else if (isNewRegistration) {
184355
- sweepProject(args, "startup", db);
187786
+ } else if (isNewRegistration || previousRegistration !== args) {
187787
+ scheduleInitialProjectRun(args, db);
184356
187788
  }
184357
187789
  return () => {
184358
187790
  registeredProjects.delete(args.directory);
187791
+ const startupTimer = startupTimers.get(args.directory);
187792
+ if (startupTimer) {
187793
+ clearTimeout(startupTimer);
187794
+ startupTimers.delete(args.directory);
187795
+ }
184359
187796
  log(`[dreamer] unregistered project ${args.projectIdentity} (remaining=${registeredProjects.size})`);
184360
187797
  if (registeredProjects.size === 0 && activeTimer) {
184361
187798
  clearInterval(activeTimer);
184362
187799
  activeTimer = null;
187800
+ startupJitters.clear();
187801
+ nextStartupJitterSlot = 0;
184363
187802
  log("[dreamer] stopped dream schedule timer (no projects left)");
184364
187803
  }
184365
187804
  };
@@ -184372,22 +187811,53 @@ function runTick(origin) {
184372
187811
  if (!db)
184373
187812
  return;
184374
187813
  for (const reg of registeredProjects.values()) {
184375
- await reg.ensureRegistered(reg.directory, db);
184376
- const memorySnapshot = getProjectEmbeddingSnapshot(reg.projectIdentity);
184377
- if (memorySnapshot?.enabled) {
184378
- const embeddedCount = await embedUnembeddedMemoriesForProject(db, reg.projectIdentity);
184379
- if (embeddedCount > 0) {
184380
- log(`[magic-context] proactively embedded ${embeddedCount} ${embeddedCount === 1 ? "memory" : "memories"} for project ${reg.projectIdentity}`);
184381
- }
187814
+ if (origin === "startup") {
187815
+ scheduleInitialProjectRun(reg, db);
187816
+ } else {
187817
+ await runProjectMaintenance(reg, origin, db);
184382
187818
  }
184383
- await sweepProject(reg, origin, db);
184384
187819
  }
187820
+ if (origin === "startup")
187821
+ return;
184385
187822
  runSqliteOptimize(db);
184386
187823
  } catch (error51) {
184387
187824
  log("[magic-context] timer-triggered maintenance check failed:", error51);
184388
187825
  }
184389
187826
  })();
184390
187827
  }
187828
+ function startupJitterMs(directory) {
187829
+ const existing = startupJitters.get(directory);
187830
+ if (existing !== undefined)
187831
+ return existing;
187832
+ const slot = nextStartupJitterSlot;
187833
+ nextStartupJitterSlot += 1;
187834
+ const hash2 = [...directory].reduce((value, character) => value * 33 + character.charCodeAt(0) >>> 0, 5381);
187835
+ const jitter = slot * BOOT_PROJECT_JITTER_SLOT_MS + hash2 % BOOT_PROJECT_JITTER_SLOT_MS;
187836
+ startupJitters.set(directory, jitter);
187837
+ return jitter;
187838
+ }
187839
+ function scheduleInitialProjectRun(reg, db) {
187840
+ if (startupTimers.has(reg.directory))
187841
+ return;
187842
+ const timer = scheduleAfterBootQuiet(() => {
187843
+ startupTimers.delete(reg.directory);
187844
+ if (registeredProjects.get(reg.directory) !== reg)
187845
+ return;
187846
+ runProjectMaintenance(reg, "startup", db);
187847
+ }, startupJitterMs(reg.directory));
187848
+ startupTimers.set(reg.directory, timer);
187849
+ }
187850
+ async function runProjectMaintenance(reg, origin, db) {
187851
+ await reg.ensureRegistered(reg.directory, db);
187852
+ const memorySnapshot = getProjectEmbeddingSnapshot(reg.projectIdentity);
187853
+ if (memorySnapshot?.enabled) {
187854
+ const embeddedCount = await embedUnembeddedMemoriesForProject(db, reg.projectIdentity);
187855
+ if (embeddedCount > 0) {
187856
+ log(`[magic-context] proactively embedded ${embeddedCount} ${embeddedCount === 1 ? "memory" : "memories"} for project ${reg.projectIdentity}`);
187857
+ }
187858
+ }
187859
+ await sweepProject(reg, origin, db);
187860
+ }
184391
187861
  async function sweepProject(reg, origin, db, gitCommitEnabled) {
184392
187862
  if (!directoryStillExists(reg.directory)) {
184393
187863
  log(`[dreamer] project directory no longer exists (${reg.projectIdentity}); skipping + unregistering`);
@@ -184555,7 +188025,7 @@ async function sweepGitCommits(args) {
184555
188025
  import { statSync as statSync7 } from "node:fs";
184556
188026
 
184557
188027
  // ../plugin/src/plugin/embedding-bootstrap-helpers.ts
184558
- import { createHash as createHash11 } from "node:crypto";
188028
+ import { createHash as createHash14 } from "node:crypto";
184559
188029
  init_logger();
184560
188030
  var EMBEDDING_AFFECTING_KEYS = new Set([
184561
188031
  "embedding.api_key",
@@ -184565,7 +188035,11 @@ var EMBEDDING_AFFECTING_KEYS = new Set([
184565
188035
  "embedding.input_type",
184566
188036
  "embedding.truncate",
184567
188037
  "embedding.max_input_tokens",
184568
- "embedding.query_input_type"
188038
+ "embedding.query_input_type",
188039
+ "embedding.fallback_provider",
188040
+ "subc",
188041
+ "subc.connection_file",
188042
+ "shadow_embedding"
184569
188043
  ]);
184570
188044
  var LITERAL_CONFIG_TOKEN_RE = /\{(?:env|file):[^}]+\}/;
184571
188045
  function embeddingConfigHasLiteralTokens(embedding2) {
@@ -184578,7 +188052,13 @@ function embeddingConfigHasLiteralTokens(embedding2) {
184578
188052
  }
184579
188053
  return false;
184580
188054
  }
184581
- var EMBEDDING_AFFECTING_TOP_LEVEL_KEYS = new Set(["embedding", "memory", "experimental"]);
188055
+ var EMBEDDING_AFFECTING_TOP_LEVEL_KEYS = new Set([
188056
+ "embedding",
188057
+ "memory",
188058
+ "experimental",
188059
+ "subc",
188060
+ "shadow_embedding"
188061
+ ]);
184582
188062
  var EMBEDDING_WARNING_TERMS = [
184583
188063
  "api_key",
184584
188064
  "endpoint",
@@ -184586,11 +188066,13 @@ var EMBEDDING_WARNING_TERMS = [
184586
188066
  "provider",
184587
188067
  "embedding",
184588
188068
  "input_type",
184589
- "truncate"
188069
+ "truncate",
188070
+ "subc",
188071
+ "shadow_embedding"
184590
188072
  ];
184591
188073
  var loggedFailureSignatures = new Map;
184592
188074
  function sha256Prefix2(value, length = 16) {
184593
- return createHash11("sha256").update(value).digest("hex").slice(0, length);
188075
+ return createHash14("sha256").update(value).digest("hex").slice(0, length);
184594
188076
  }
184595
188077
  function warningLooksEmbeddingRelated(message) {
184596
188078
  const lower = message.toLowerCase();
@@ -184989,7 +188471,7 @@ function migrateLegacyExperimental(rawConfig, warnings) {
184989
188471
  var HIDDEN_AGENT_KEYS = ["historian", "dreamer", "sidekick"];
184990
188472
  var HISTORIAN_USER_ONLY_FIELDS = ["model", "fallback_models"];
184991
188473
  var AGENT_ESCALATION_FIELDS = ["prompt", "permission", "tools", "system_prompt"];
184992
- var EMBEDDING_DESTINATION_FIELDS = ["endpoint", "provider"];
188474
+ var EMBEDDING_DESTINATION_FIELDS = ["endpoint", "provider", "fallback_provider"];
184993
188475
  var PERCENTAGE_THRESHOLD_REASON = "security: a repository may only raise compaction thresholds above the user's effective value; it cannot force earlier historian work or cloned-repo cost escalation.";
184994
188476
  var TOKEN_THRESHOLD_REASON = "security: a repository may only raise execute_threshold_tokens above the user's trusted token threshold; it cannot force earlier historian work or cloned-repo cost escalation.";
184995
188477
  var TOKEN_THRESHOLD_INTRODUCTION_REASON = "security: a repository cannot introduce a new execute_threshold_tokens override when the user has no trusted token threshold for that key; that could force earlier historian work or cloned-repo cost escalation.";
@@ -185105,6 +188587,12 @@ function stripUnsafeProjectConfigFields(projectRaw) {
185105
188587
  delete projectRaw.shadow_transform;
185106
188588
  warnings.push("Ignoring shadow_transform from project config (security: this developer-only mirror lane is user-level only).");
185107
188589
  }
188590
+ for (const field of ["subc", "shadow_embedding"]) {
188591
+ if (field in projectRaw) {
188592
+ delete projectRaw[field];
188593
+ warnings.push(`Ignoring ${field} from project config (security: daemon routing and developer-only embedding traffic are user-level settings).`);
188594
+ }
188595
+ }
185108
188596
  const embedding2 = projectRaw.embedding;
185109
188597
  if (isPlainObject3(embedding2)) {
185110
188598
  const removed = [];
@@ -185280,7 +188768,7 @@ function dropInheritedEmbeddingKeyOnRedirect(projectRaw, mergedRaw, userRaw) {
185280
188768
 
185281
188769
  // ../plugin/src/config/variable.ts
185282
188770
  import { existsSync as existsSync16, readFileSync as readFileSync7 } from "node:fs";
185283
- import { homedir as homedir4 } from "node:os";
188771
+ import { homedir as homedir5 } from "node:os";
185284
188772
  import { dirname as dirname6, isAbsolute as isAbsolute2, resolve } from "node:path";
185285
188773
 
185286
188774
  // ../plugin/src/shared/jsonc-parser.ts
@@ -185343,7 +188831,7 @@ function stripJsonComments(content) {
185343
188831
  var ENV_PATTERN = /\{env:([^}]+)\}/g;
185344
188832
  var FILE_PATTERN = /\{file:([^}]+)\}/g;
185345
188833
  function sensitiveFilePathReason(resolvedPath) {
185346
- const home = homedir4();
188834
+ const home = homedir5();
185347
188835
  const sensitiveDirs = [
185348
188836
  { dir: resolve(home, ".ssh"), label: "SSH keys" },
185349
188837
  { dir: resolve(home, ".aws"), label: "AWS credentials" },
@@ -185406,7 +188894,7 @@ function substituteConfigVariables(input) {
185406
188894
  }
185407
188895
  let filePath = rawPath.trim();
185408
188896
  if (filePath.startsWith("~/")) {
185409
- filePath = resolve(homedir4(), filePath.slice(2));
188897
+ filePath = resolve(homedir5(), filePath.slice(2));
185410
188898
  } else if (!isAbsolute2(filePath)) {
185411
188899
  filePath = resolve(configDir, filePath);
185412
188900
  }
@@ -190767,6 +194255,93 @@ function containsProbeVerbatim(text, probes) {
190767
194255
  return probes.some((probe) => haystack.includes(probe.toLowerCase()));
190768
194256
  }
190769
194257
 
194258
+ // ../plugin/src/features/magic-context/search-measurement.ts
194259
+ import { createHash as createHash15 } from "node:crypto";
194260
+ function resultId(result) {
194261
+ switch (result.source) {
194262
+ case "memory":
194263
+ return `memory:${result.memoryId}`;
194264
+ case "message":
194265
+ return `message:${result.messageId}`;
194266
+ case "compartment":
194267
+ return `chunk:${result.compartmentId}`;
194268
+ case "git_commit":
194269
+ return `commit:${result.sha}`;
194270
+ case "primer":
194271
+ return `primer:${result.primerId}`;
194272
+ case "note":
194273
+ return `note:${result.noteId}`;
194274
+ }
194275
+ }
194276
+ async function recordShadowMeasurement(args) {
194277
+ const shadowCohort = getShadowEmbeddingMeasurementCohort(args.projectPath);
194278
+ if (!shadowCohort)
194279
+ return;
194280
+ const primaryCohort = getPrimaryEmbeddingMeasurementCohort(args.projectPath);
194281
+ const shadowStartedAt = Date.now();
194282
+ let shadowFailed = false;
194283
+ let shadowResults = [];
194284
+ try {
194285
+ const vector = await embedShadowTextForProject(args.projectPath, args.query);
194286
+ if (!vector) {
194287
+ shadowFailed = true;
194288
+ } else {
194289
+ shadowResults = await args.search(args.db, args.sessionId, args.projectPath, args.query, {
194290
+ ...args.options,
194291
+ embedQuery: async () => vector,
194292
+ isEmbeddingRuntimeEnabled: () => true,
194293
+ embeddingEnabled: true,
194294
+ embeddingModelIdOverride: shadowCohort.modelId,
194295
+ chunkModelIdOverride: shadowCohort.chunkModelId,
194296
+ measurementDisabled: true,
194297
+ countRetrievals: false
194298
+ });
194299
+ }
194300
+ } catch {
194301
+ shadowFailed = true;
194302
+ }
194303
+ const primaryModelId = args.primaryQuery?.modelId ?? primaryCohort?.modelId ?? "";
194304
+ const primaryFingerprint = primaryCohort?.fingerprint ?? "";
194305
+ const primaryEpoch = primaryCohort?.epoch ?? 0;
194306
+ const cohortKey = JSON.stringify({
194307
+ primaryFingerprint,
194308
+ primaryEpoch,
194309
+ shadowFingerprint: shadowCohort.fingerprint,
194310
+ shadowEpoch: shadowCohort.epoch
194311
+ });
194312
+ const primaryIds = args.primaryResults.map(resultId);
194313
+ const shadowIds = shadowResults.map(resultId);
194314
+ const corpusHash = sha2562(JSON.stringify({ query: args.query, primaryIds, shadowIds }));
194315
+ recordEmbeddingMeasurement(args.db, {
194316
+ sessionId: args.sessionId,
194317
+ projectPath: args.projectPath,
194318
+ queryText: args.query,
194319
+ cohortKey,
194320
+ primaryResultIds: primaryIds,
194321
+ shadowResultIds: shadowIds,
194322
+ primaryLatencyMs: args.primaryLatencyMs,
194323
+ shadowLatencyMs: Date.now() - shadowStartedAt,
194324
+ primaryFailed: args.primaryQuery === null,
194325
+ shadowFailed,
194326
+ primaryModelId,
194327
+ shadowModelId: shadowCohort.modelId,
194328
+ primaryFingerprint,
194329
+ shadowFingerprint: shadowCohort.fingerprint,
194330
+ primaryEpoch,
194331
+ shadowEpoch: shadowCohort.epoch,
194332
+ corpusHash,
194333
+ coverage: {
194334
+ primaryResultCount: primaryIds.length,
194335
+ shadowResultCount: shadowIds.length,
194336
+ primaryAnswered: args.primaryQuery !== null,
194337
+ shadowAnswered: !shadowFailed
194338
+ }
194339
+ });
194340
+ }
194341
+ function sha2562(value) {
194342
+ return createHash15("sha256").update(value).digest("hex");
194343
+ }
194344
+
190770
194345
  // ../plugin/src/features/magic-context/search.ts
190771
194346
  var DEFAULT_UNIFIED_SEARCH_LIMIT = 10;
190772
194347
  var FTS_SEMANTIC_CANDIDATE_LIMIT = 50;
@@ -191524,6 +195099,7 @@ function resolveSources(sources) {
191524
195099
  }
191525
195100
  async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
191526
195101
  const trimmedQuery = query.trim();
195102
+ const measurementStartedAt = Date.now();
191527
195103
  if (trimmedQuery.length === 0) {
191528
195104
  return [];
191529
195105
  }
@@ -191556,11 +195132,14 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
191556
195132
  maxOrdinal: options.maxMessageOrdinal,
191557
195133
  probes: messageProbes
191558
195134
  }) : [];
191559
- const queryEmbedding = await queryEmbeddingPromise;
191560
- const workspace = resolveSearchWorkspaceContext(db, projectPath);
195135
+ const capturedQuery = await queryEmbeddingPromise;
191561
195136
  const embeddingSnapshot = getProjectEmbeddingSnapshot(projectPath);
191562
- const embeddingModelId = embeddingSnapshot?.modelId;
191563
- const chunkModelId = embeddingSnapshot?.chunkModelId;
195137
+ const queryContract = capturedQuery instanceof Float32Array || capturedQuery === null ? null : capturedQuery;
195138
+ const generationIsCurrent = queryContract === null || embeddingSnapshot !== null && embeddingSnapshot.generation === queryContract.generation;
195139
+ const queryEmbedding = generationIsCurrent ? queryContract?.vector ?? (capturedQuery instanceof Float32Array ? capturedQuery : null) : null;
195140
+ const workspace = resolveSearchWorkspaceContext(db, projectPath);
195141
+ const embeddingModelId = queryContract?.modelId ?? options.embeddingModelIdOverride ?? embeddingSnapshot?.modelId;
195142
+ const chunkModelId = queryContract?.chunkModelId ?? options.chunkModelIdOverride ?? embeddingSnapshot?.chunkModelId;
191564
195143
  const compartmentResults = runCompartmentChunks ? searchCompartmentChunks({
191565
195144
  db,
191566
195145
  sessionId,
@@ -191619,6 +195198,19 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
191619
195198
  ...gitCommitResults,
191620
195199
  ...noteResults
191621
195200
  ].sort(compareUnifiedResults).slice(0, limit);
195201
+ if (!options.measurementDisabled) {
195202
+ recordShadowMeasurement({
195203
+ db,
195204
+ sessionId,
195205
+ projectPath,
195206
+ query: trimmedQuery,
195207
+ options,
195208
+ primaryResults: results,
195209
+ primaryQuery: queryContract,
195210
+ primaryLatencyMs: Date.now() - measurementStartedAt,
195211
+ search: unifiedSearch
195212
+ });
195213
+ }
191622
195214
  const countRetrievals = options.countRetrievals ?? true;
191623
195215
  if (countRetrievals) {
191624
195216
  const memoryIds = results.filter((result) => result.source === "memory").map((result) => result.memoryId);
@@ -193774,15 +197366,19 @@ async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compar
193774
197366
  if (currentModelId !== "off" && chunkEmbeddingWindowsAreCurrent(db, compartment.id, currentModelId, windows, projectPath)) {
193775
197367
  continue;
193776
197368
  }
193777
- const result = await embedBatchForProject(projectPath, windows.map((window) => window.text));
197369
+ const result = await embedItemsForProject(projectPath, windows.map((window) => ({
197370
+ id: `chunk:${compartment.id}:${window.windowIndex}`,
197371
+ text: window.text,
197372
+ contentSha256: contentSha256(window.text)
197373
+ })), undefined, db, sessionId);
193778
197374
  if (!result)
193779
197375
  continue;
193780
197376
  if (chunkEmbeddingWindowsAreCurrent(db, compartment.id, currentModelId, windows, projectPath)) {
193781
197377
  continue;
193782
197378
  }
193783
197379
  const rows = [];
193784
- for (const [index, window] of windows.entries()) {
193785
- const vector = result.vectors[index];
197380
+ for (const window of windows) {
197381
+ const vector = result.vectors.get(`chunk:${compartment.id}:${window.windowIndex}`);
193786
197382
  if (!vector)
193787
197383
  continue;
193788
197384
  rows.push({
@@ -193796,6 +197392,7 @@ async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compar
193796
197392
  }
193797
197393
  if (rows.length === windows.length) {
193798
197394
  replaceCompartmentChunkEmbeddings(db, rows);
197395
+ enqueueShadowEmbeddingItems(projectPath, "chunk", [String(compartment.id)]);
193799
197396
  }
193800
197397
  } catch (error51) {
193801
197398
  sessionLog(sessionId, `compartment chunk embedding failed for compartment ${compartment.id}:`, error51);
@@ -198230,7 +201827,7 @@ function stripPiProcessedImages(args) {
198230
201827
  }
198231
201828
 
198232
201829
  // src/system-prompt.ts
198233
- import { createHash as createHash12 } from "node:crypto";
201830
+ import { createHash as createHash16 } from "node:crypto";
198234
201831
 
198235
201832
  // ../plugin/src/agents/magic-context-prompt.ts
198236
201833
  var LONG_TERM_PARTNER_FRAME = `### You are the user's long-term partner on this project — not a one-off hire
@@ -198383,7 +201980,7 @@ function processSystemPromptForCache(args) {
198383
201980
  sessionLog(sessionId, `system prompt date frozen: real=${liveDate}, using=${stickyDate} (cache-stable pass)`);
198384
201981
  }
198385
201982
  }
198386
- const currentHash = createHash12("md5").update(frozenPrompt).digest("hex");
201983
+ const currentHash = createHash16("md5").update(frozenPrompt).digest("hex");
198387
201984
  const hashChanged = !isFirstHash && currentHash !== previousHash;
198388
201985
  if (hashChanged) {
198389
201986
  sessionLog(sessionId, `system prompt hash changed: ${previousHash} → ${currentHash} (len=${frozenPrompt.length})`);
@@ -201531,6 +205128,19 @@ init_logger();
201531
205128
  init_data_path();
201532
205129
  init_logger();
201533
205130
  var MARKER_SUMMARY_TEXT = "[Compacted by magic-context — session history is managed by the plugin]";
205131
+ function dropMarkerSummaryTag(db, sessionId, summaryMessageId) {
205132
+ const tagNumber = getTagNumberByMessageId(db, sessionId, `${summaryMessageId}:p0`);
205133
+ if (tagNumber !== null)
205134
+ updateTagStatus(db, sessionId, tagNumber, "dropped");
205135
+ }
205136
+ function persistMarkerStateAndDropReplacedTag(db, sessionId, state, replacedSummaryMessageId) {
205137
+ db.transaction(() => {
205138
+ setPersistedCompactionMarkerState(db, sessionId, state);
205139
+ if (replacedSummaryMessageId !== null) {
205140
+ dropMarkerSummaryTag(db, sessionId, replacedSummaryMessageId);
205141
+ }
205142
+ })();
205143
+ }
201534
205144
  function getCompartmentEndMessageIdForOrdinal(db, sessionId, endOrdinal) {
201535
205145
  const row = db.prepare(`SELECT end_message_id
201536
205146
  FROM compartments
@@ -201571,6 +205181,7 @@ function updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEn
201571
205181
  return false;
201572
205182
  }
201573
205183
  const existing = getPersistedCompactionMarkerState(db, sessionId);
205184
+ const removedSummaryMessageId = existing?.summaryMessageId ?? null;
201574
205185
  if (existing) {
201575
205186
  if (existingMarkerAlreadyCoversTarget(sessionId, existing, lastCompartmentEnd, targetEndMessageId)) {
201576
205187
  return true;
@@ -201587,7 +205198,7 @@ function updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEn
201587
205198
  sessionLog(sessionId, `compaction-marker: failed to remove old boundary at ordinal ${existing.boundaryOrdinal}; preserving persisted state for retry (not injecting new marker this pass)`);
201588
205199
  return false;
201589
205200
  }
201590
- setPersistedCompactionMarkerState(db, sessionId, null);
205201
+ persistMarkerStateAndDropReplacedTag(db, sessionId, null, removedSummaryMessageId);
201591
205202
  sessionLog(sessionId, `compaction-marker: removed old boundary at ordinal ${existing.boundaryOrdinal}, moving to ${lastCompartmentEnd}`);
201592
205203
  }
201593
205204
  const result = injectCompactionMarker({
@@ -201599,11 +205210,11 @@ function updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEn
201599
205210
  resolvedBoundary: boundary
201600
205211
  });
201601
205212
  if (result) {
201602
- setPersistedCompactionMarkerState(db, sessionId, {
205213
+ persistMarkerStateAndDropReplacedTag(db, sessionId, {
201603
205214
  ...result,
201604
205215
  boundaryOrdinal: lastCompartmentEnd,
201605
205216
  targetEndMessageId
201606
- });
205217
+ }, removedSummaryMessageId);
201607
205218
  sessionLog(sessionId, `compaction-marker: injected at ordinal ${lastCompartmentEnd}, boundary user msg ${result.boundaryMessageId}`);
201608
205219
  return true;
201609
205220
  }
@@ -203487,6 +207098,11 @@ function applyMemoryMigration(db, projectPath, result) {
203487
207098
  }
203488
207099
  var MIGRATION_SYSTEM_PROMPT = "You re-organize a software project's long-term memory for the magic-context system into a stricter taxonomy. " + "Follow the user instructions exactly. Output ONLY the requested XML blocks, nothing else.";
203489
207100
 
207101
+ // ../plugin/src/hooks/magic-context/lkg-slot.ts
207102
+ var LKG_TOTAL_BYTES = 64 * 1024 * 1024;
207103
+ var LKG_SINGLE_SLOT_BYTES = 24 * 1024 * 1024;
207104
+ var slots = new Map;
207105
+
203490
207106
  // ../plugin/src/hooks/magic-context/recomp-orchestrator.ts
203491
207107
  function isRecompFailure(message) {
203492
207108
  return /—\s*(Failed|Skipped)/.test(message);
@@ -203925,7 +207541,13 @@ import {
203925
207541
 
203926
207542
  // ../plugin/src/hooks/magic-context/m0-token-breakdown.ts
203927
207543
  function computeM0BlockTokens(db, sessionId, args) {
203928
- const { m0Text, projectIdentity, injectionBudgetTokens, memoryBlockCount } = args;
207544
+ const {
207545
+ m0Text,
207546
+ projectIdentity,
207547
+ injectionBudgetTokens,
207548
+ memoryBlockCount,
207549
+ compartmentTokensOverride
207550
+ } = args;
203929
207551
  const docsBlock = extractM0Block(m0Text, "project-docs");
203930
207552
  const docsTokens = docsBlock ? estimateTokens(docsBlock) : 0;
203931
207553
  const profileBlock = extractM0Block(m0Text, "user-profile");
@@ -203939,7 +207561,9 @@ function computeM0BlockTokens(db, sessionId, args) {
203939
207561
  }
203940
207562
  let compartmentTokens = 0;
203941
207563
  const historyBlock = extractM0Block(m0Text, "session-history");
203942
- if (historyBlock) {
207564
+ if (typeof compartmentTokensOverride === "number" && Number.isFinite(compartmentTokensOverride) && compartmentTokensOverride >= 0) {
207565
+ compartmentTokens = compartmentTokensOverride;
207566
+ } else if (historyBlock) {
203943
207567
  compartmentTokens = estimateTokens(historyBlock);
203944
207568
  } else {
203945
207569
  try {
@@ -203976,7 +207600,7 @@ function formatThresholdPercent(value) {
203976
207600
  // package.json
203977
207601
  var package_default = {
203978
207602
  name: "@cortexkit/pi-magic-context",
203979
- version: "0.32.1",
207603
+ version: "0.32.3",
203980
207604
  type: "module",
203981
207605
  description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
203982
207606
  main: "dist/index.js",
@@ -211274,11 +214898,12 @@ async function src_default2(pi) {
211274
214898
  log(`${PREFIX} subagent child detected (${MAGIC_CONTEXT_PI_SUBAGENT_ENV}=1); skipping full extension registration`);
211275
214899
  return;
211276
214900
  }
214901
+ beginBootQuietPeriod();
211277
214902
  const storageDir = getMagicContextStorageDir();
211278
214903
  const dbPath = join13(storageDir, "context.db");
211279
214904
  let db;
211280
214905
  try {
211281
- db = openDatabase();
214906
+ db = await openDatabaseAsync();
211282
214907
  } catch (err5) {
211283
214908
  const message = err5 instanceof Error ? err5.message : String(err5);
211284
214909
  warn(`Magic Context (pi) failed to open SQLite store at ${dbPath}: ${message}. ` + "Plugin will not register hooks; storage path is unwritable or corrupt.");
@@ -211289,10 +214914,12 @@ async function src_default2(pi) {
211289
214914
  return;
211290
214915
  }
211291
214916
  const database = db;
211292
- runDeferredV22Backfill(db).catch((err5) => {
211293
- warn(`[v22-backfill] background runner failed: ${err5}`);
214917
+ scheduleAfterBootQuiet(() => {
214918
+ runDeferredV22Backfill(db).catch((err5) => {
214919
+ warn(`[v22-backfill] background runner failed: ${err5}`);
214920
+ });
211294
214921
  });
211295
- setTimeout(() => {
214922
+ scheduleAfterBootQuiet(() => {
211296
214923
  (async () => {
211297
214924
  try {
211298
214925
  const api2 = await loadDefaultPiSessionApi();