@cortexkit/pi-magic-context 0.32.1 → 0.32.2

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) {
@@ -159428,7 +159752,7 @@ function openOpenCodeDb() {
159428
159752
  }
159429
159753
 
159430
159754
  // ../plugin/src/features/magic-context/dreamer/task-executor.ts
159431
- import { createHash as createHash10 } from "node:crypto";
159755
+ import { createHash as createHash12 } from "node:crypto";
159432
159756
  import { existsSync as existsSync15 } from "node:fs";
159433
159757
 
159434
159758
  // ../plugin/src/agents/dreamer.ts
@@ -159819,6 +160143,9 @@ function parseFields(json) {
159819
160143
  } catch {}
159820
160144
  return {};
159821
160145
  }
160146
+ // ../plugin/src/config/schema/magic-context.ts
160147
+ import { homedir as homedir3 } from "node:os";
160148
+
159822
160149
  // ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
159823
160150
  var exports_external = {};
159824
160151
  __export(exports_external, {
@@ -174342,8 +174669,18 @@ var HistorianConfigSchema = AgentOverrideConfigSchema.extend({
174342
174669
  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
174670
  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
174671
  }).optional();
174672
+ var EmbeddingFallbackProviderSchema = exports_external.enum(["local", "openai-compatible", "off"]);
174673
+ function expandConfigPath(value) {
174674
+ const trimmed = value.trim();
174675
+ if (trimmed === "~")
174676
+ return homedir3();
174677
+ if (trimmed.startsWith("~/"))
174678
+ return `${homedir3()}/${trimmed.slice(2)}`;
174679
+ return trimmed;
174680
+ }
174345
174681
  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."),
174682
+ 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."),
174683
+ fallback_provider: EmbeddingFallbackProviderSchema.optional().describe("Fallback provider for the Synapse lane. Required when provider is 'synapse'; local, openai-compatible, and off are valid."),
174347
174684
  model: exports_external.string().optional().describe("Embedding model name. Required for openai-compatible, ignored for local."),
174348
174685
  endpoint: exports_external.string().optional().describe("API endpoint URL. Required when provider is openai-compatible."),
174349
174686
  api_key: exports_external.string().optional().describe("API key for remote embedding provider (optional)"),
@@ -174352,14 +174689,15 @@ var BaseEmbeddingConfigSchema = exports_external.object({
174352
174689
  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
174690
  max_input_tokens: exports_external.number().int().positive().optional().describe("Optional maximum input tokens for chunk embeddings. Defaults conservatively to 512 when omitted.")
174354
174691
  }).superRefine((data, ctx) => {
174355
- if (data.provider === "openai-compatible" && !data.endpoint?.trim()) {
174692
+ const validationProvider = data.provider === "synapse" ? data.fallback_provider : data.provider;
174693
+ if (validationProvider === "openai-compatible" && !data.endpoint?.trim()) {
174356
174694
  ctx.addIssue({
174357
174695
  code: "custom",
174358
174696
  path: ["endpoint"],
174359
174697
  message: "endpoint is required when embedding.provider is openai-compatible"
174360
174698
  });
174361
174699
  }
174362
- if (data.provider === "openai-compatible" && !data.model?.trim()) {
174700
+ if (validationProvider === "openai-compatible" && !data.model?.trim()) {
174363
174701
  ctx.addIssue({
174364
174702
  code: "custom",
174365
174703
  path: ["model"],
@@ -174368,6 +174706,25 @@ var BaseEmbeddingConfigSchema = exports_external.object({
174368
174706
  }
174369
174707
  });
174370
174708
  var EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data) => {
174709
+ if (data.provider === "synapse") {
174710
+ const model = data.model?.trim();
174711
+ const endpoint = data.endpoint?.trim();
174712
+ const apiKey = data.api_key?.trim();
174713
+ const inputType = data.input_type?.trim();
174714
+ const queryInputType = data.query_input_type?.trim();
174715
+ const truncate = data.truncate?.trim();
174716
+ return {
174717
+ provider: "synapse",
174718
+ ...data.fallback_provider ? { fallback_provider: data.fallback_provider } : {},
174719
+ ...model ? { model } : {},
174720
+ ...endpoint ? { endpoint } : {},
174721
+ ...apiKey ? { api_key: apiKey } : {},
174722
+ ...inputType ? { input_type: inputType } : {},
174723
+ ...queryInputType ? { query_input_type: queryInputType } : {},
174724
+ ...truncate ? { truncate } : {},
174725
+ ...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}
174726
+ };
174727
+ }
174371
174728
  if (data.provider === "local") {
174372
174729
  return {
174373
174730
  provider: "local",
@@ -174395,6 +174752,7 @@ var EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data) => {
174395
174752
  });
174396
174753
  var MagicContextConfigSchema = exports_external.object({
174397
174754
  enabled: exports_external.boolean().default(true).describe("Enable magic context (default: true)"),
174755
+ 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
174756
  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
174757
  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
174758
  historian: HistorianConfigSchema.describe("Historian agent configuration (model, fallback_models, variant, temperature, maxTokens, permission, two_pass, etc.)"),
@@ -174431,6 +174789,12 @@ var MagicContextConfigSchema = exports_external.object({
174431
174789
  provider: "local",
174432
174790
  model: DEFAULT_LOCAL_EMBEDDING_MODEL
174433
174791
  }).describe("Embedding provider configuration"),
174792
+ subc: exports_external.object({
174793
+ connection_file: exports_external.string().trim().min(1).transform(expandConfigPath).describe("Path to the owner-only subc connection file.")
174794
+ }).optional().describe("User-only Synapse daemon connection settings."),
174795
+ shadow_embedding: exports_external.object({
174796
+ enabled: exports_external.boolean().default(false).describe("Developer-only Synapse shadow embedding lane switch.")
174797
+ }).default({ enabled: false }).describe("Developer-only Synapse shadow embedding lane."),
174434
174798
  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
174799
  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
174800
  shadow_transform: exports_external.object({
@@ -174480,7 +174844,7 @@ var MagicContextConfigSchema = exports_external.object({
174480
174844
  init_logger();
174481
174845
 
174482
174846
  // ../plugin/src/features/magic-context/compartment-chunk-embedding.ts
174483
- import { createHash as createHash6 } from "node:crypto";
174847
+ import { createHash as createHash7 } from "node:crypto";
174484
174848
  init_logger();
174485
174849
 
174486
174850
  // ../plugin/src/features/magic-context/recursive-text-splitter.ts
@@ -174692,7 +175056,7 @@ function parseCanonicalLineRange(line) {
174692
175056
  return { start, end };
174693
175057
  }
174694
175058
  function hashChunkText(text) {
174695
- return createHash6("sha256").update(text).digest("hex");
175059
+ return createHash7("sha256").update(text).digest("hex");
174696
175060
  }
174697
175061
  function vectorBlob2(vector) {
174698
175062
  return new Uint8Array(vector.buffer, vector.byteOffset, vector.byteLength);
@@ -175084,14 +175448,2634 @@ function cosineSimilarity(a, b) {
175084
175448
  return denominator === 0 ? 0 : dotProduct / denominator;
175085
175449
  }
175086
175450
 
175451
+ // ../plugin/src/features/magic-context/memory/embedding-synapse.ts
175452
+ import { createHash as createHash8 } from "node:crypto";
175453
+
175454
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/client.js
175455
+ import { promises as fs4 } from "node:fs";
175456
+ import { debuglog } from "node:util";
175457
+
175458
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/auth.js
175459
+ import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
175460
+ var NONCE_LEN = 32;
175461
+ var MAX_AUTH_MESSAGE_LEN = 4096;
175462
+ var SERVER_PROOF_DOMAIN = "subc-server-v1";
175463
+ var CLIENT_AUTH_DOMAIN = "subc-client-v1";
175464
+ var DEFAULT_CLIENT_ROLE = "client";
175465
+
175466
+ class AuthError extends Error {
175467
+ }
175468
+ function computeProof(key, domain2, clientNonce, serverNonce, daemonId) {
175469
+ const mac3 = createHmac("sha256", Buffer.from(key));
175470
+ mac3.update(Buffer.from(domain2, "utf8"));
175471
+ mac3.update(Buffer.from(clientNonce));
175472
+ mac3.update(Buffer.from(serverNonce));
175473
+ mac3.update(Buffer.from(daemonId));
175474
+ return new Uint8Array(mac3.digest());
175475
+ }
175476
+ function constantTimeEq(a, b) {
175477
+ if (a.length !== b.length)
175478
+ return false;
175479
+ return timingSafeEqual(Buffer.from(a), Buffer.from(b));
175480
+ }
175481
+ async function writeMessage(sock, value, deadlineMs) {
175482
+ const json2 = Buffer.from(JSON.stringify(value), "utf8");
175483
+ if (json2.length > MAX_AUTH_MESSAGE_LEN) {
175484
+ throw new AuthError(`auth message too large: ${json2.length} > ${MAX_AUTH_MESSAGE_LEN}`);
175485
+ }
175486
+ const lenPrefix = new Uint8Array(4);
175487
+ new DataView(lenPrefix.buffer).setUint32(0, json2.length, true);
175488
+ await sock.write(lenPrefix, deadlineMs);
175489
+ await sock.write(json2, deadlineMs);
175490
+ }
175491
+ async function readMessage(sock, deadlineMs) {
175492
+ const lenBytes = await sock.readExact(4, deadlineMs);
175493
+ const len = new DataView(lenBytes.buffer, lenBytes.byteOffset, 4).getUint32(0, true);
175494
+ if (len > MAX_AUTH_MESSAGE_LEN) {
175495
+ throw new AuthError(`auth message too large: ${len} > ${MAX_AUTH_MESSAGE_LEN}`);
175496
+ }
175497
+ const body = len === 0 ? new Uint8Array(0) : await sock.readExact(len, deadlineMs);
175498
+ try {
175499
+ return JSON.parse(Buffer.from(body).toString("utf8"));
175500
+ } catch (err) {
175501
+ throw new AuthError(`auth message JSON decode failed: ${String(err)}`);
175502
+ }
175503
+ }
175504
+ async function authenticateClient(sock, conn, deadlineMs) {
175505
+ const clientNonce = new Uint8Array(randomBytes(NONCE_LEN));
175506
+ await writeMessage(sock, { client_nonce: Array.from(clientNonce), role: DEFAULT_CLIENT_ROLE }, deadlineMs);
175507
+ const proof = await readMessage(sock, deadlineMs);
175508
+ const serverNonce = Uint8Array.from(proof.server_nonce);
175509
+ const daemonId = Uint8Array.from(proof.daemon_id);
175510
+ const serverProof = Uint8Array.from(proof.server_proof);
175511
+ const expected = computeProof(conn.key, SERVER_PROOF_DOMAIN, clientNonce, serverNonce, daemonId);
175512
+ if (!constantTimeEq(expected, serverProof)) {
175513
+ throw new AuthError("server proof mismatch — wrong key or impostor daemon");
175514
+ }
175515
+ if (!constantTimeEq(daemonId, conn.daemonId)) {
175516
+ throw new AuthError("daemon id mismatch — connection file points at a different daemon");
175517
+ }
175518
+ const clientAuth = computeProof(conn.key, CLIENT_AUTH_DOMAIN, clientNonce, serverNonce, daemonId);
175519
+ await writeMessage(sock, { client_auth: Array.from(clientAuth) }, deadlineMs);
175520
+ }
175521
+
175522
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/connection-file.js
175523
+ import { promises as fs3 } from "node:fs";
175524
+ var SCHEMA_VERSION = 1;
175525
+ var MIN_KEY_LEN = 32;
175526
+ var DAEMON_ID_LEN = 16;
175527
+
175528
+ class ConnectionFileError extends Error {
175529
+ }
175530
+ function toBytes(value, field) {
175531
+ if (!Array.isArray(value) || value.some((n) => typeof n !== "number")) {
175532
+ throw new ConnectionFileError(`connection file field '${field}' must be a JSON array of bytes`);
175533
+ }
175534
+ return Uint8Array.from(value);
175535
+ }
175536
+ function validate(info) {
175537
+ if (info.schema !== SCHEMA_VERSION) {
175538
+ throw new ConnectionFileError(`unsupported connection file schema ${info.schema}; expected ${SCHEMA_VERSION}`);
175539
+ }
175540
+ if (info.endpoints.length === 0) {
175541
+ throw new ConnectionFileError("connection file must include at least one endpoint");
175542
+ }
175543
+ if (info.key.length < MIN_KEY_LEN) {
175544
+ throw new ConnectionFileError(`connection file key is too short: ${info.key.length} bytes, need at least ${MIN_KEY_LEN}`);
175545
+ }
175546
+ if (info.daemonId.length !== DAEMON_ID_LEN) {
175547
+ throw new ConnectionFileError(`connection file daemon_id must be ${DAEMON_ID_LEN} bytes, got ${info.daemonId.length}`);
175548
+ }
175549
+ }
175550
+ async function verifyOwnerOnly(path7) {
175551
+ if (process.platform === "win32")
175552
+ return;
175553
+ const stat = await fs3.stat(path7);
175554
+ const mode = stat.mode & 511;
175555
+ if ((mode & 63) !== 0) {
175556
+ throw new ConnectionFileError(`connection file ${path7} has insecure permissions 0o${mode.toString(8)}; expected owner-only 0600`);
175557
+ }
175558
+ }
175559
+ async function readConnectionFile(path7) {
175560
+ await verifyOwnerOnly(path7);
175561
+ const raw = await fs3.readFile(path7, "utf8");
175562
+ let parsed;
175563
+ try {
175564
+ parsed = JSON.parse(raw);
175565
+ } catch (err) {
175566
+ throw new ConnectionFileError(`connection file JSON read failed for ${path7}: ${String(err)}`);
175567
+ }
175568
+ const endpointsRaw = parsed.endpoints;
175569
+ if (!Array.isArray(endpointsRaw)) {
175570
+ throw new ConnectionFileError("connection file 'endpoints' must be an array");
175571
+ }
175572
+ const endpoints = endpointsRaw.map((e) => {
175573
+ const ep = e;
175574
+ if (typeof ep.host !== "string" || typeof ep.port !== "number") {
175575
+ throw new ConnectionFileError("connection file endpoint must be { host: string, port: number }");
175576
+ }
175577
+ return { host: ep.host, port: ep.port };
175578
+ });
175579
+ const info = {
175580
+ schema: parsed.schema,
175581
+ endpoints,
175582
+ key: toBytes(parsed.key, "key"),
175583
+ daemonId: toBytes(parsed.daemon_id, "daemon_id"),
175584
+ pid: parsed.pid,
175585
+ daemonVer: parsed.daemon_ver ?? ""
175586
+ };
175587
+ validate(info);
175588
+ return info;
175589
+ }
175590
+
175591
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/envelope.js
175592
+ var PROTOCOL_VERSION = 2;
175593
+ var HEADER_LEN = 21;
175594
+ var FROZEN_PREFIX_LEN = 5;
175595
+ var MAX_FRAME_BODY_LEN = 64 * 1024 * 1024;
175596
+ var FrameType;
175597
+ (function(FrameType2) {
175598
+ FrameType2[FrameType2["Request"] = 0] = "Request";
175599
+ FrameType2[FrameType2["Response"] = 1] = "Response";
175600
+ FrameType2[FrameType2["Push"] = 2] = "Push";
175601
+ FrameType2[FrameType2["StreamData"] = 3] = "StreamData";
175602
+ FrameType2[FrameType2["StreamEnd"] = 4] = "StreamEnd";
175603
+ FrameType2[FrameType2["Error"] = 5] = "Error";
175604
+ FrameType2[FrameType2["Cancel"] = 6] = "Cancel";
175605
+ FrameType2[FrameType2["Ping"] = 7] = "Ping";
175606
+ FrameType2[FrameType2["Pong"] = 8] = "Pong";
175607
+ FrameType2[FrameType2["Hello"] = 9] = "Hello";
175608
+ FrameType2[FrameType2["HelloAck"] = 10] = "HelloAck";
175609
+ FrameType2[FrameType2["Goodbye"] = 11] = "Goodbye";
175610
+ })(FrameType || (FrameType = {}));
175611
+ var FRAME_TYPE_MAX = FrameType.Goodbye;
175612
+ function isPureHeader(ty) {
175613
+ return ty === FrameType.Cancel || ty === FrameType.Ping || ty === FrameType.Pong || ty === FrameType.Goodbye;
175614
+ }
175615
+ var Priority;
175616
+ (function(Priority2) {
175617
+ Priority2[Priority2["Passive"] = 0] = "Passive";
175618
+ Priority2[Priority2["Interactive"] = 1] = "Interactive";
175619
+ Priority2[Priority2["Background"] = 2] = "Background";
175620
+ })(Priority || (Priority = {}));
175621
+ var AdmissionClass;
175622
+ (function(AdmissionClass2) {
175623
+ AdmissionClass2[AdmissionClass2["Normal"] = 0] = "Normal";
175624
+ AdmissionClass2[AdmissionClass2["Expedite"] = 1] = "Expedite";
175625
+ AdmissionClass2[AdmissionClass2["Sheddable"] = 2] = "Sheddable";
175626
+ })(AdmissionClass || (AdmissionClass = {}));
175627
+ var FLAG_BINARY = 1;
175628
+ var FLAG_PRIORITY_MASK = 6;
175629
+ var FLAG_PRIORITY_SHIFT = 1;
175630
+ var FLAG_LAST = 8;
175631
+ var FLAG_ADMISSION_MASK = 48;
175632
+ var FLAG_ADMISSION_SHIFT = 4;
175633
+ var FLAG_RESERVED_MASK = 192;
175634
+ function buildFlags(binary, priority, last, admissionClass = AdmissionClass.Normal) {
175635
+ let flags = 0;
175636
+ if (binary)
175637
+ flags |= FLAG_BINARY;
175638
+ flags |= priority << FLAG_PRIORITY_SHIFT;
175639
+ if (last)
175640
+ flags |= FLAG_LAST;
175641
+ flags |= admissionClass << FLAG_ADMISSION_SHIFT;
175642
+ return flags;
175643
+ }
175644
+ function encodeHeader(header) {
175645
+ const buffer2 = new Uint8Array(HEADER_LEN);
175646
+ const view = new DataView(buffer2.buffer);
175647
+ view.setUint32(0, header.len, true);
175648
+ buffer2[4] = header.ver;
175649
+ buffer2[5] = header.ty;
175650
+ buffer2[6] = header.flags;
175651
+ view.setUint16(7, header.channel, true);
175652
+ view.setUint32(9, header.epoch, true);
175653
+ view.setBigUint64(13, header.corr, true);
175654
+ return buffer2;
175655
+ }
175656
+
175657
+ class DecodeError extends Error {
175658
+ code;
175659
+ constructor(message, code) {
175660
+ super(message);
175661
+ this.code = code;
175662
+ this.name = "DecodeError";
175663
+ }
175664
+ }
175665
+ function decodeHeader(bytes) {
175666
+ if (bytes.length < FROZEN_PREFIX_LEN) {
175667
+ throw new DecodeError(`header shorter than frozen prefix: have ${bytes.length} bytes`, "too_short_for_prefix");
175668
+ }
175669
+ const ver = bytes[4];
175670
+ if (ver !== PROTOCOL_VERSION)
175671
+ throw new DecodeError(`unsupported envelope version ${ver}`, "unsupported_version");
175672
+ if (bytes.length < HEADER_LEN) {
175673
+ throw new DecodeError(`header too short for version: have ${bytes.length} bytes, need ${HEADER_LEN}`, "too_short_for_header");
175674
+ }
175675
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
175676
+ const len = view.getUint32(0, true);
175677
+ const typeByte = bytes[5];
175678
+ if (typeByte > FRAME_TYPE_MAX)
175679
+ throw new DecodeError(`unknown frame type byte ${typeByte}`, "unknown_frame_type");
175680
+ const ty = typeByte;
175681
+ const flags = bytes[6];
175682
+ if ((flags & FLAG_RESERVED_MASK) !== 0) {
175683
+ throw new DecodeError(`reserved flag bits set in flags 0b${flags.toString(2).padStart(8, "0")}`, "reserved_flag_bits");
175684
+ }
175685
+ if ((flags & FLAG_PRIORITY_MASK) >> FLAG_PRIORITY_SHIFT === 3) {
175686
+ throw new DecodeError(`reserved priority bits set in flags 0b${flags.toString(2).padStart(8, "0")}`, "reserved_priority_bits");
175687
+ }
175688
+ const admission = (flags & FLAG_ADMISSION_MASK) >> FLAG_ADMISSION_SHIFT;
175689
+ if (admission === 3) {
175690
+ throw new DecodeError(`reserved admission class set in flags 0b${flags.toString(2).padStart(8, "0")}`, "reserved_admission_class");
175691
+ }
175692
+ if (admission === AdmissionClass.Sheddable && ty !== FrameType.Push && ty !== FrameType.StreamData) {
175693
+ throw new DecodeError(`SHEDDABLE admission class is illegal on ${FrameType[ty]} in flags 0b${flags.toString(2).padStart(8, "0")}`, "sheddable_illegal_frame_type");
175694
+ }
175695
+ const channel = view.getUint16(7, true);
175696
+ const epoch = view.getUint32(9, true);
175697
+ if (channel === 0 && epoch !== 0) {
175698
+ throw new DecodeError(`control channel carried nonzero epoch ${epoch}`, "nonzero_epoch_on_control_channel");
175699
+ }
175700
+ if (isPureHeader(ty) && len !== 0) {
175701
+ throw new DecodeError(`pure-header frame ${FrameType[ty]} declared non-zero body length ${len}`, "pure_header_frame_with_body");
175702
+ }
175703
+ return { len, ver, ty, flags, channel, epoch, corr: view.getBigUint64(13, true) };
175704
+ }
175705
+ function buildFrame(ty, flags, channel, epoch, corr, body) {
175706
+ return buildFrameWithVersion(PROTOCOL_VERSION, ty, flags, channel, epoch, corr, body);
175707
+ }
175708
+ function buildFrameWithVersion(ver, ty, flags, channel, epoch, corr, body) {
175709
+ if (body.length > MAX_FRAME_BODY_LEN) {
175710
+ throw new DecodeError(`frame body ${body.length} exceeds max ${MAX_FRAME_BODY_LEN}`, "frame_body_too_large");
175711
+ }
175712
+ const header = { len: body.length, ver, ty, flags, channel, epoch, corr };
175713
+ decodeHeader(encodeHeader(header));
175714
+ return { header, body };
175715
+ }
175716
+ function encodeFrame(frame) {
175717
+ if (frame.header.len !== frame.body.length) {
175718
+ throw new DecodeError(`frame header length ${frame.header.len} does not match body length ${frame.body.length}`, "frame_length_mismatch");
175719
+ }
175720
+ const header = encodeHeader(frame.header);
175721
+ const output = new Uint8Array(header.length + frame.body.length);
175722
+ output.set(header, 0);
175723
+ output.set(frame.body, header.length);
175724
+ return output;
175725
+ }
175726
+
175727
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/route-handle.js
175728
+ var connectionToken = new WeakMap;
175729
+
175730
+ class RouteHandle {
175731
+ channel;
175732
+ epoch;
175733
+ constructor(channel, epoch, token) {
175734
+ if (!Number.isInteger(channel) || channel <= 0 || channel > 65535) {
175735
+ throw new RangeError(`route channel must be an integer in 1..65535, got ${channel}`);
175736
+ }
175737
+ if (!Number.isInteger(epoch) || epoch <= 0 || epoch > 4294967295) {
175738
+ throw new RangeError(`route epoch must be an integer in 1..4294967295, got ${epoch}`);
175739
+ }
175740
+ this.channel = channel;
175741
+ this.epoch = epoch;
175742
+ connectionToken.set(this, token);
175743
+ Object.freeze(this);
175744
+ }
175745
+ static create(channel, epoch, token) {
175746
+ return new RouteHandle(channel, epoch, token);
175747
+ }
175748
+ }
175749
+ function createRouteHandle(channel, epoch, token) {
175750
+ const factory = RouteHandle;
175751
+ return factory.create(channel, epoch, token);
175752
+ }
175753
+
175754
+ class StaleRouteHandleError extends Error {
175755
+ handle;
175756
+ code = "stale_route_handle";
175757
+ constructor(handle) {
175758
+ super(`route handle (${handle.channel}, ${handle.epoch}) is not live on the current connection`);
175759
+ this.handle = handle;
175760
+ this.name = "StaleRouteHandleError";
175761
+ }
175762
+ }
175763
+ function newConnectionToken() {
175764
+ return Object.freeze({});
175765
+ }
175766
+ function belongsToConnection(handle, token) {
175767
+ return connectionToken.get(handle) === token;
175768
+ }
175769
+ function sameRouteHandle(left, right) {
175770
+ return left === right;
175771
+ }
175772
+
175773
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/socket.js
175774
+ import net from "node:net";
175775
+ class SocketClosedError extends Error {
175776
+ }
175777
+
175778
+ class SocketTimeoutError extends Error {
175779
+ }
175780
+
175781
+ class SocketWriteNotQueuedError extends Error {
175782
+ cause;
175783
+ constructor(message, cause) {
175784
+ super(message);
175785
+ this.cause = cause;
175786
+ }
175787
+ }
175788
+
175789
+ class SocketWriteQueuedError extends Error {
175790
+ cause;
175791
+ constructor(message, cause) {
175792
+ super(message);
175793
+ this.cause = cause;
175794
+ }
175795
+ }
175796
+
175797
+ class SubcSocket {
175798
+ sock;
175799
+ chunks = [];
175800
+ buffered = 0;
175801
+ waiter = null;
175802
+ closedErr = null;
175803
+ bufferedBytes() {
175804
+ return this.buffered;
175805
+ }
175806
+ constructor(sock) {
175807
+ this.sock = sock;
175808
+ sock.on("data", (chunk) => {
175809
+ this.chunks.push(chunk);
175810
+ this.buffered += chunk.length;
175811
+ this.tryServe();
175812
+ });
175813
+ const fail = (err) => {
175814
+ if (!this.closedErr)
175815
+ this.closedErr = err;
175816
+ this.tryServe();
175817
+ };
175818
+ sock.on("error", (err) => fail(err instanceof Error ? err : new Error(String(err))));
175819
+ sock.on("end", () => fail(new SocketClosedError("subc closed the connection")));
175820
+ sock.on("close", () => fail(new SocketClosedError("subc connection closed")));
175821
+ }
175822
+ localPort() {
175823
+ return this.sock.localPort ?? null;
175824
+ }
175825
+ static connect(host, port, deadlineMs) {
175826
+ return new Promise((resolve, reject) => {
175827
+ const sock = net.connect({ host, port });
175828
+ sock.setNoDelay(true);
175829
+ const timer = setTimeout(() => {
175830
+ sock.destroy();
175831
+ reject(new SocketTimeoutError(`timed out connecting to ${host}:${port}`));
175832
+ }, Math.max(0, deadlineMs - Date.now()));
175833
+ sock.once("connect", () => {
175834
+ clearTimeout(timer);
175835
+ resolve(new SubcSocket(sock));
175836
+ });
175837
+ sock.once("error", (err) => {
175838
+ clearTimeout(timer);
175839
+ reject(err);
175840
+ });
175841
+ });
175842
+ }
175843
+ async readFrame(headerDeadlineMs, bodyDeadline, onHeader) {
175844
+ const prefix = await this.readExact(FROZEN_PREFIX_LEN, headerDeadlineMs);
175845
+ const version2 = prefix[4];
175846
+ if (version2 !== PROTOCOL_VERSION)
175847
+ throw new DecodeError(`unsupported envelope version ${version2}`, "unsupported_version");
175848
+ const remainder = await this.readExact(HEADER_LEN - FROZEN_PREFIX_LEN, headerDeadlineMs);
175849
+ const headerBytes = new Uint8Array(HEADER_LEN);
175850
+ headerBytes.set(prefix);
175851
+ headerBytes.set(remainder, FROZEN_PREFIX_LEN);
175852
+ const header = decodeHeader(headerBytes);
175853
+ if (header.len > MAX_FRAME_BODY_LEN) {
175854
+ throw new DecodeError(`frame body ${header.len} exceeds max ${MAX_FRAME_BODY_LEN}`, "frame_body_too_large");
175855
+ }
175856
+ onHeader?.();
175857
+ const bodyDeadlineMs = typeof bodyDeadline === "number" ? bodyDeadline : Date.now() + bodyDeadline.afterHeaderMs;
175858
+ const body = header.len === 0 ? new Uint8Array(0) : await this.readExact(header.len, bodyDeadlineMs);
175859
+ return { header, body };
175860
+ }
175861
+ readExact(n, deadlineMs) {
175862
+ if (this.waiter) {
175863
+ return Promise.reject(new Error("concurrent readExact is not supported"));
175864
+ }
175865
+ if (n === 0)
175866
+ return Promise.resolve(new Uint8Array(0));
175867
+ return new Promise((resolve, reject) => {
175868
+ let timer = null;
175869
+ if (Number.isFinite(deadlineMs)) {
175870
+ const remaining = deadlineMs - Date.now();
175871
+ if (remaining <= 0) {
175872
+ reject(new SocketTimeoutError(`timed out waiting for ${n} bytes`));
175873
+ return;
175874
+ }
175875
+ timer = setTimeout(() => {
175876
+ this.waiter = null;
175877
+ reject(new SocketTimeoutError(`timed out waiting for ${n} bytes`));
175878
+ }, remaining);
175879
+ }
175880
+ this.waiter = { need: n, resolve, reject, timer };
175881
+ this.tryServe();
175882
+ });
175883
+ }
175884
+ async write(bytes, deadlineMs) {
175885
+ try {
175886
+ await this.writeTracked(bytes, deadlineMs).completed;
175887
+ } catch (err) {
175888
+ if (err instanceof SocketWriteNotQueuedError || err instanceof SocketWriteQueuedError) {
175889
+ throw err.cause ?? err;
175890
+ }
175891
+ throw err;
175892
+ }
175893
+ }
175894
+ writeTracked(bytes, deadlineMs) {
175895
+ if (this.closedErr) {
175896
+ return {
175897
+ queued: false,
175898
+ completed: Promise.reject(new SocketWriteNotQueuedError("subc socket was closed before bytes could be queued", this.closedErr))
175899
+ };
175900
+ }
175901
+ let queued = false;
175902
+ let settled = false;
175903
+ let timer = null;
175904
+ const completed = new Promise((resolve, reject) => {
175905
+ const settle = (run) => {
175906
+ if (settled)
175907
+ return;
175908
+ settled = true;
175909
+ if (timer)
175910
+ clearTimeout(timer);
175911
+ run();
175912
+ };
175913
+ const remaining = deadlineMs - Date.now();
175914
+ if (remaining <= 0) {
175915
+ settle(() => reject(new SocketWriteNotQueuedError("timed out before bytes could be queued to subc", new SocketTimeoutError("timed out writing to subc"))));
175916
+ return;
175917
+ }
175918
+ timer = setTimeout(() => {
175919
+ const timeout = new SocketTimeoutError("timed out writing to subc");
175920
+ 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)));
175921
+ }, remaining);
175922
+ try {
175923
+ this.sock.write(Buffer.from(bytes), (err) => {
175924
+ settle(() => {
175925
+ if (err) {
175926
+ reject(new SocketWriteQueuedError("subc socket reported a write error after bytes were handed to the socket", err instanceof Error ? err : new Error(String(err))));
175927
+ } else {
175928
+ resolve();
175929
+ }
175930
+ });
175931
+ });
175932
+ queued = true;
175933
+ } catch (err) {
175934
+ settle(() => reject(new SocketWriteNotQueuedError("subc socket write threw before bytes could be queued", err instanceof Error ? err : new Error(String(err)))));
175935
+ }
175936
+ });
175937
+ return { queued, completed };
175938
+ }
175939
+ close() {
175940
+ this.sock.destroy();
175941
+ }
175942
+ tryServe() {
175943
+ const w = this.waiter;
175944
+ if (!w)
175945
+ return;
175946
+ if (this.buffered >= w.need) {
175947
+ const out = this.take(w.need);
175948
+ this.waiter = null;
175949
+ if (w.timer)
175950
+ clearTimeout(w.timer);
175951
+ w.resolve(out);
175952
+ return;
175953
+ }
175954
+ if (this.closedErr) {
175955
+ this.waiter = null;
175956
+ if (w.timer)
175957
+ clearTimeout(w.timer);
175958
+ w.reject(this.closedErr);
175959
+ }
175960
+ }
175961
+ take(n) {
175962
+ const out = Buffer.allocUnsafe(n);
175963
+ let off = 0;
175964
+ while (off < n) {
175965
+ const head = this.chunks[0];
175966
+ const want = n - off;
175967
+ if (head.length <= want) {
175968
+ head.copy(out, off);
175969
+ off += head.length;
175970
+ this.chunks.shift();
175971
+ } else {
175972
+ head.copy(out, off, 0, want);
175973
+ this.chunks[0] = head.subarray(want);
175974
+ off += want;
175975
+ }
175976
+ }
175977
+ this.buffered -= n;
175978
+ return out;
175979
+ }
175980
+ }
175981
+
175982
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/client.js
175983
+ var debug = debuglog("subc-client");
175984
+ var DEFAULT_HANDSHAKE_TIMEOUT_MS = 1e4;
175985
+ var DEFAULT_REQUEST_TIMEOUT_MS = 30000;
175986
+ var TIMEOUT_ARBITRATION_GRACE_MS = 50;
175987
+ var REQUEST_DEADLINE_MARKER = "request_deadline";
175988
+ var DEADLINE_NO_DROP_CODE = "deadline_exceeded_no_drop_observed";
175989
+ var ROUTE_OPEN_RETRY_DEADLINE_MS = 30000;
175990
+ var BODY_READ_TIMEOUT_MS = 30000;
175991
+ var EMPTY_BODY = new Uint8Array(0);
175992
+ var DEFAULT_MANAGED_TARGET_KIND = "management_surface";
175993
+ var SUBC_MODULE_ID_ENV = "SUBC_MODULE_ID";
175994
+ var SUBC_LAUNCH_NONCE_ENV = "SUBC_LAUNCH_NONCE";
175995
+ var DEFAULT_RECONNECT_BACKOFF = {
175996
+ baseMs: 100,
175997
+ capMs: 2000,
175998
+ maxAttempts: 6
175999
+ };
176000
+
176001
+ class SubcCallError extends Error {
176002
+ kind;
176003
+ code;
176004
+ cause;
176005
+ constructor(kind, message, code, cause) {
176006
+ super(message);
176007
+ this.kind = kind;
176008
+ this.code = code;
176009
+ this.cause = cause;
176010
+ this.name = "SubcCallError";
176011
+ }
176012
+ }
176013
+
176014
+ class SubcError extends Error {
176015
+ code;
176016
+ constructor(message, code) {
176017
+ super(message);
176018
+ this.code = code;
176019
+ }
176020
+ }
176021
+
176022
+ class SubcClient {
176023
+ sock;
176024
+ currentConn;
176025
+ opts;
176026
+ nextCorr = 1n;
176027
+ pending = new Map;
176028
+ lateResponses = new Map;
176029
+ routes = new Map;
176030
+ liveRoutes = new Map;
176031
+ connectionToken = newConnectionToken();
176032
+ ingressEpochDropCount = 0;
176033
+ closedErr = null;
176034
+ closeStarted = false;
176035
+ reconnecting = null;
176036
+ generation = 1;
176037
+ readerActive = false;
176038
+ constructor(sock, currentConn, opts) {
176039
+ this.sock = sock;
176040
+ this.currentConn = currentConn;
176041
+ this.opts = opts;
176042
+ this.readLoop(sock, this.generation);
176043
+ }
176044
+ get conn() {
176045
+ return this.currentConn;
176046
+ }
176047
+ static async connect(opts) {
176048
+ const normalized = normalizeConnectOptions(opts);
176049
+ const opened = await SubcClient.openConnection(normalized);
176050
+ return new SubcClient(opened.sock, opened.conn, normalized);
176051
+ }
176052
+ async catalogList(moduleId) {
176053
+ const body = this.encode(moduleId === undefined ? { op: "catalog.list" } : { op: "catalog.list", module_id: moduleId });
176054
+ const reply = await this.controlRpc(body);
176055
+ const parsed = this.parseJson(reply);
176056
+ return parsed.modules ?? [];
176057
+ }
176058
+ async routeOpen(target, identity, opts = {}) {
176059
+ const consumerIdentity = routeOpenConsumerIdentity(opts);
176060
+ const consumerCapabilities = opts.consumerCapabilities;
176061
+ const body = this.encode({
176062
+ op: "route.open",
176063
+ target,
176064
+ identity,
176065
+ ...consumerIdentity ? { consumer_identity: consumerIdentity } : {},
176066
+ ...consumerCapabilities !== undefined ? { consumer_capabilities: consumerCapabilities } : {}
176067
+ });
176068
+ let installed = null;
176069
+ const install = (frame) => {
176070
+ if (frame.header.ty !== FrameType.Response)
176071
+ return true;
176072
+ const parsed = this.parseJson(frame);
176073
+ if (typeof parsed.route_channel !== "number" || typeof parsed.route_epoch !== "number") {
176074
+ throw new SubcError(`route.open returned no route handle: ${JSON.stringify(parsed)}`);
176075
+ }
176076
+ installed = this.installRoute(parsed.route_channel, parsed.route_epoch);
176077
+ return true;
176078
+ };
176079
+ const closeLateRoute = (frame) => {
176080
+ if (frame.header.ty !== FrameType.Response)
176081
+ return;
176082
+ try {
176083
+ const parsed = this.parseJson(frame);
176084
+ if (typeof parsed.route_channel !== "number" || typeof parsed.route_epoch !== "number")
176085
+ return;
176086
+ const lateHandle = this.installRoute(parsed.route_channel, parsed.route_epoch);
176087
+ this.failHandle(lateHandle, new SubcError("late route.open was closed", "route_closed"));
176088
+ this.liveRoutes.delete(lateHandle.channel);
176089
+ this.sendRouteGoodbye(lateHandle, true);
176090
+ } catch {
176091
+ this.closeConnectionAfterCleanupFailure();
176092
+ }
176093
+ };
176094
+ await this.controlRpc(body, install, closeLateRoute);
176095
+ if (!installed)
176096
+ throw new SubcError("route.open response was not installed");
176097
+ return installed;
176098
+ }
176099
+ async request(handle, body, opts = {}) {
176100
+ this.assertLiveHandle(handle);
176101
+ const bytes = body instanceof Uint8Array ? body : this.encode(body);
176102
+ const priority = opts.priority ?? Priority.Interactive;
176103
+ const admission = opts.admissionClass ?? AdmissionClass.Normal;
176104
+ const reply = await this.send(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress);
176105
+ return this.parseJson(reply);
176106
+ }
176107
+ async call(moduleId, method, params, opts = {}) {
176108
+ const body = params === undefined ? { method } : { method, params };
176109
+ let retriedUnknownChannel = false;
176110
+ for (;; ) {
176111
+ const routeHandle = await this.cachedRouteHandle(moduleId, opts);
176112
+ try {
176113
+ return await this.managedRequest(routeHandle, body, opts);
176114
+ } catch (err) {
176115
+ if (!(err instanceof SubcCallError))
176116
+ throw this.terminalCallError("managed call failed", err);
176117
+ if (err.code === "unknown_channel" && !retriedUnknownChannel && !this.closeStarted) {
176118
+ retriedUnknownChannel = true;
176119
+ this.evictRouteHandle(routeHandle);
176120
+ continue;
176121
+ }
176122
+ if (err.kind === "not_sent") {
176123
+ try {
176124
+ await this.reconnectAfterDrop(err);
176125
+ } catch (reconnectErr) {
176126
+ throw this.notSentRecoveryError("managed call was not sent", reconnectErr);
176127
+ }
176128
+ continue;
176129
+ }
176130
+ if (err.kind === "outcome_unknown" && err.code !== DEADLINE_NO_DROP_CODE) {
176131
+ this.scheduleReconnectAfterDrop(err);
176132
+ }
176133
+ throw err;
176134
+ }
176135
+ }
176136
+ }
176137
+ subscribe(handle, body, onEvent, opts = {}) {
176138
+ this.assertLiveHandle(handle);
176139
+ const bytes = body instanceof Uint8Array ? body : this.encode(body);
176140
+ const priority = opts.priority ?? Priority.Interactive;
176141
+ const admission = opts.admissionClass ?? AdmissionClass.Normal;
176142
+ const corr = this.allocateCorr();
176143
+ const key = pendingKey(handle, corr);
176144
+ const closed = new Promise((resolve, reject) => {
176145
+ if (this.closedErr) {
176146
+ reject(this.closedErr);
176147
+ return;
176148
+ }
176149
+ this.pending.set(key, {
176150
+ handle,
176151
+ resolve: () => resolve(),
176152
+ reject,
176153
+ onProgress: onEvent,
176154
+ timer: null,
176155
+ subscription: true
176156
+ });
176157
+ const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), handle.channel, handle.epoch, corr, bytes);
176158
+ this.sock.write(encodeFrame(frame), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS).catch((err) => {
176159
+ const pending = this.pending.get(key);
176160
+ if (pending)
176161
+ this.rejectPending(key, pending, err instanceof Error ? err : new SubcError(String(err)));
176162
+ });
176163
+ });
176164
+ let cancelled = false;
176165
+ const unsubscribe = () => {
176166
+ if (cancelled)
176167
+ return;
176168
+ cancelled = true;
176169
+ this.cancel(handle, corr, priority);
176170
+ };
176171
+ return { unsubscribe, closed };
176172
+ }
176173
+ cancel(handle, corr, priority = Priority.Interactive) {
176174
+ this.assertLiveHandle(handle);
176175
+ const cancel = buildFrame(FrameType.Cancel, buildFlags(false, priority, false), handle.channel, handle.epoch, corr, EMPTY_BODY);
176176
+ this.sock.write(encodeFrame(cancel), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS).catch(() => {
176177
+ return;
176178
+ });
176179
+ }
176180
+ async routePoll(handle, kind) {
176181
+ this.assertLiveHandle(handle);
176182
+ const body = this.encode({
176183
+ op: "route.poll",
176184
+ route_channel: handle.channel,
176185
+ route_epoch: handle.epoch,
176186
+ kind
176187
+ });
176188
+ const reply = await this.controlRpc(body, (frame) => {
176189
+ if (frame.header.ty !== FrameType.Response)
176190
+ return true;
176191
+ const parsed = this.parseJson(frame);
176192
+ return parsed.route_channel === handle.channel && parsed.route_epoch === handle.epoch;
176193
+ });
176194
+ return this.parseJson(reply);
176195
+ }
176196
+ async closeRoute(handle, opts = {}) {
176197
+ this.assertLiveHandle(handle);
176198
+ for (const [key, cached2] of this.routes) {
176199
+ if (cached2.handle && sameRouteHandle(cached2.handle, handle)) {
176200
+ cached2.closed = true;
176201
+ cached2.handle = null;
176202
+ this.routes.delete(key);
176203
+ }
176204
+ }
176205
+ if (opts.drain)
176206
+ await this.drainUnaryOnHandle(handle);
176207
+ this.failHandle(handle, new SubcError("route closed by closeRoute", "route_closed"));
176208
+ if (this.liveRoutes.get(handle.channel) === handle)
176209
+ this.liveRoutes.delete(handle.channel);
176210
+ this.sendRouteGoodbye(handle);
176211
+ }
176212
+ async closeManagedRoute(target, identity, opts = {}) {
176213
+ const key = routeCacheKey(target, identity, routeOpenConsumerIdentity(opts));
176214
+ const cached2 = this.routes.get(key);
176215
+ if (!cached2)
176216
+ return;
176217
+ cached2.closed = true;
176218
+ this.routes.delete(key);
176219
+ const handle = cached2.handle;
176220
+ cached2.handle = null;
176221
+ if (handle)
176222
+ await this.closeRoute(handle, opts);
176223
+ }
176224
+ async closeRouteChannel(handle, opts = {}) {
176225
+ await this.closeRoute(handle, opts);
176226
+ }
176227
+ close() {
176228
+ this.closeStarted = true;
176229
+ this.fail(new SubcError("client closed"));
176230
+ this.sock.close();
176231
+ }
176232
+ drainUnaryOnHandle(handle) {
176233
+ const waiters = [];
176234
+ for (const pending of this.pending.values()) {
176235
+ if (pending.handle === handle && !pending.subscription) {
176236
+ waiters.push(new Promise((resolve) => {
176237
+ const previous = pending.onSettle;
176238
+ pending.onSettle = () => {
176239
+ previous?.();
176240
+ resolve();
176241
+ };
176242
+ }));
176243
+ }
176244
+ }
176245
+ return Promise.all(waiters).then(() => {
176246
+ return;
176247
+ });
176248
+ }
176249
+ sendRouteGoodbye(handle, closeOnQueueFailure = false) {
176250
+ this.assertLiveConnection(handle);
176251
+ if (this.closedErr) {
176252
+ if (closeOnQueueFailure)
176253
+ this.closeConnectionAfterCleanupFailure();
176254
+ return;
176255
+ }
176256
+ const goodbye = buildFrame(FrameType.Goodbye, buildFlags(false, Priority.Interactive, false), handle.channel, handle.epoch, 0n, EMPTY_BODY);
176257
+ const write = this.sock.writeTracked(encodeFrame(goodbye), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS);
176258
+ if (!write.queued && closeOnQueueFailure)
176259
+ this.closeConnectionAfterCleanupFailure();
176260
+ write.completed.catch(() => {
176261
+ if (closeOnQueueFailure && !write.queued)
176262
+ this.closeConnectionAfterCleanupFailure();
176263
+ });
176264
+ }
176265
+ static async openConnection(opts) {
176266
+ const conn = await readConnectionFile(opts.connectionFile);
176267
+ const deadline = Date.now() + (opts.handshakeTimeoutMs ?? DEFAULT_HANDSHAKE_TIMEOUT_MS);
176268
+ const endpoint = conn.endpoints[0];
176269
+ const sock = await SubcSocket.connect(endpoint.host, endpoint.port, deadline);
176270
+ try {
176271
+ await authenticateClient(sock, conn, deadline);
176272
+ } catch (err) {
176273
+ sock.close();
176274
+ throw err;
176275
+ }
176276
+ return { sock, conn };
176277
+ }
176278
+ async controlRpc(body, acceptFrame, onLateResponse) {
176279
+ return this.send(null, body, Priority.Interactive, AdmissionClass.Normal, undefined, undefined, acceptFrame, onLateResponse);
176280
+ }
176281
+ send(handle, body, priority, admission, timeoutMs, onProgress, acceptFrame, onLateResponse) {
176282
+ if (handle)
176283
+ this.assertLiveHandle(handle);
176284
+ if (this.closedErr)
176285
+ return Promise.reject(this.closedErr);
176286
+ let corr;
176287
+ try {
176288
+ corr = this.allocateCorr();
176289
+ } catch (error51) {
176290
+ return Promise.reject(error51);
176291
+ }
176292
+ const key = pendingKey(handle, corr);
176293
+ const channel = handle?.channel ?? 0;
176294
+ const epoch = handle?.epoch ?? 0;
176295
+ const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), channel, epoch, corr, body);
176296
+ return new Promise((resolve, reject) => {
176297
+ const ms = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
176298
+ const pending = {
176299
+ handle,
176300
+ resolve,
176301
+ reject,
176302
+ onProgress,
176303
+ timer: null,
176304
+ acceptFrame,
176305
+ onLateResponse
176306
+ };
176307
+ pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, channel, corr, ms), ms);
176308
+ this.pending.set(key, pending);
176309
+ this.sock.write(encodeFrame(frame), Date.now() + ms).catch((error51) => {
176310
+ const current = this.pending.get(key);
176311
+ if (current)
176312
+ this.rejectPending(key, current, error51 instanceof Error ? error51 : new SubcError(String(error51)));
176313
+ });
176314
+ });
176315
+ }
176316
+ arbitrateTimeout(key, pending, channel, corr, ms) {
176317
+ const settleAsTimeout = () => {
176318
+ if (pending.onLateResponse)
176319
+ this.lateResponses.set(key, pending.onLateResponse);
176320
+ this.rejectPending(key, pending, new SubcError(this.timeoutMessage(channel, corr, ms), REQUEST_DEADLINE_MARKER));
176321
+ };
176322
+ const graceDeadline = Date.now() + this.opts.timeoutArbitrationGraceMs;
176323
+ const arbitrate = () => {
176324
+ if (this.pending.get(key) !== pending)
176325
+ return;
176326
+ const readerDraining = this.readerActive || this.sock.bufferedBytes() > 0;
176327
+ if (readerDraining && Date.now() < graceDeadline) {
176328
+ setImmediate(arbitrate);
176329
+ return;
176330
+ }
176331
+ settleAsTimeout();
176332
+ };
176333
+ setImmediate(arbitrate);
176334
+ }
176335
+ async managedRequest(handle, body, opts) {
176336
+ const bytes = body instanceof Uint8Array ? body : this.encode(body);
176337
+ const priority = opts.priority ?? Priority.Interactive;
176338
+ const admission = opts.admissionClass ?? AdmissionClass.Normal;
176339
+ try {
176340
+ const reply = await this.sendManaged(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress);
176341
+ return this.parseJson(reply);
176342
+ } catch (error51) {
176343
+ if (error51 instanceof SubcCallError)
176344
+ throw error51;
176345
+ throw this.terminalCallError("managed call failed", error51);
176346
+ }
176347
+ }
176348
+ sendManaged(handle, body, priority, admission, timeoutMs, onProgress) {
176349
+ try {
176350
+ this.assertLiveHandle(handle);
176351
+ } catch (error51) {
176352
+ return Promise.reject(this.notSentCallError("request used a stale route handle", error51));
176353
+ }
176354
+ if (this.closedErr) {
176355
+ return Promise.reject(this.notSentCallError("request was not sent because the subc connection was already closed", this.closedErr));
176356
+ }
176357
+ let corr;
176358
+ try {
176359
+ corr = this.allocateCorr();
176360
+ } catch (error51) {
176361
+ return Promise.reject(this.notSentCallError("request correlation allocator was exhausted", error51));
176362
+ }
176363
+ const key = pendingKey(handle, corr);
176364
+ const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), handle.channel, handle.epoch, corr, body);
176365
+ let handedToSocket = false;
176366
+ const classifyFailure = (error51) => {
176367
+ if (!handedToSocket)
176368
+ return this.notSentCallError("request bytes were not queued to the subc socket", error51);
176369
+ if (error51 instanceof SubcError && error51.code === REQUEST_DEADLINE_MARKER) {
176370
+ 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);
176371
+ }
176372
+ return this.outcomeUnknownCallError("connection dropped before the managed call returned a response", error51);
176373
+ };
176374
+ return new Promise((resolve, reject) => {
176375
+ const ms = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
176376
+ const pending = {
176377
+ handle,
176378
+ resolve,
176379
+ reject,
176380
+ onProgress,
176381
+ timer: null,
176382
+ classifyFailure
176383
+ };
176384
+ pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, handle.channel, corr, ms), ms);
176385
+ this.pending.set(key, pending);
176386
+ const write = this.sock.writeTracked(encodeFrame(frame), Date.now() + ms);
176387
+ handedToSocket = write.queued;
176388
+ write.completed.catch((error51) => {
176389
+ const current = this.pending.get(key);
176390
+ if (current)
176391
+ this.rejectPending(key, current, error51 instanceof Error ? error51 : new SubcError(String(error51)));
176392
+ });
176393
+ });
176394
+ }
176395
+ async cachedRouteHandle(moduleId, opts) {
176396
+ const identity = opts.identity ?? this.opts.identity;
176397
+ if (!identity) {
176398
+ throw new SubcCallError("terminal", "managed call requires a BindIdentity in SubcClient.connect({ identity }) or call(..., { identity })", "missing_identity");
176399
+ }
176400
+ const target = { kind: opts.targetKind ?? this.opts.targetKind, module_id: moduleId };
176401
+ const consumerIdentity = routeOpenConsumerIdentity(opts);
176402
+ const key = routeCacheKey(target, identity, consumerIdentity);
176403
+ let cached2 = this.routes.get(key);
176404
+ if (!cached2) {
176405
+ cached2 = {
176406
+ key,
176407
+ moduleId,
176408
+ target,
176409
+ identity,
176410
+ consumerIdentity,
176411
+ handle: null,
176412
+ opening: null
176413
+ };
176414
+ this.routes.set(key, cached2);
176415
+ }
176416
+ if (cached2.handle && this.isLiveHandle(cached2.handle))
176417
+ return cached2.handle;
176418
+ if (!cached2.opening) {
176419
+ cached2.opening = this.openCachedRoute(cached2).finally(() => {
176420
+ cached2.opening = null;
176421
+ });
176422
+ }
176423
+ return cached2.opening;
176424
+ }
176425
+ async openCachedRoute(cached2) {
176426
+ const routeRetryDeadline = Date.now() + ROUTE_OPEN_RETRY_DEADLINE_MS;
176427
+ let routeRetryDelay = this.opts.reconnectBackoff.baseMs;
176428
+ let routeRetryAttempt = 0;
176429
+ for (;; ) {
176430
+ if (cached2.closed)
176431
+ throw this.routeClosedDuringOpen();
176432
+ try {
176433
+ await this.ensureConnectedForManaged();
176434
+ } catch (error51) {
176435
+ throw this.notSentRecoveryError("route.open could not run because reconnect failed", error51);
176436
+ }
176437
+ if (cached2.handle && this.isLiveHandle(cached2.handle))
176438
+ return cached2.handle;
176439
+ try {
176440
+ const handle = await this.routeOpen(cached2.target, cached2.identity, {
176441
+ consumerIdentity: cached2.consumerIdentity ?? null
176442
+ });
176443
+ if (cached2.closed) {
176444
+ this.liveRoutes.delete(handle.channel);
176445
+ this.sendRouteGoodbye(handle);
176446
+ throw this.routeClosedDuringOpen();
176447
+ }
176448
+ cached2.handle = handle;
176449
+ return handle;
176450
+ } catch (error51) {
176451
+ if (error51 instanceof SubcCallError && error51.code === "route_closed")
176452
+ throw error51;
176453
+ if (!this.closeStarted && isConsumerReconnectTransient(error51)) {
176454
+ try {
176455
+ await this.reconnectAfterDrop(error51);
176456
+ } catch (reconnectError) {
176457
+ throw this.notSentRecoveryError("route.open was not sent and reconnect failed", reconnectError);
176458
+ }
176459
+ continue;
176460
+ }
176461
+ if (!this.closeStarted && error51 instanceof SubcError && isRetryableRouteOpenCode(error51.code)) {
176462
+ routeRetryAttempt += 1;
176463
+ if (routeRetryAttempt < this.opts.reconnectBackoff.maxAttempts && Date.now() < routeRetryDeadline) {
176464
+ await this.opts.sleep(routeRetryDelay);
176465
+ routeRetryDelay = Math.min(routeRetryDelay * 2, this.opts.reconnectBackoff.capMs);
176466
+ continue;
176467
+ }
176468
+ throw this.notSentCallError(`route.open failed for module ${cached2.moduleId}: ${error51.code} (retry budget exhausted)`, error51);
176469
+ }
176470
+ throw this.terminalCallError(`route.open failed for module ${cached2.moduleId}`, error51);
176471
+ }
176472
+ }
176473
+ }
176474
+ async ensureConnectedForManaged() {
176475
+ if (this.closeStarted)
176476
+ throw new SubcError("client closed");
176477
+ if (this.reconnecting)
176478
+ await this.reconnecting;
176479
+ if (this.closedErr)
176480
+ await this.reconnectAfterDrop(this.closedErr);
176481
+ }
176482
+ scheduleReconnectAfterDrop(err) {
176483
+ if (this.closeStarted || this.reconnecting)
176484
+ return;
176485
+ this.reconnectAfterDrop(err).catch(() => {});
176486
+ }
176487
+ reconnectAfterDrop(trigger) {
176488
+ if (this.closeStarted)
176489
+ return Promise.reject(new SubcError("client closed"));
176490
+ if (this.reconnecting)
176491
+ return this.reconnecting;
176492
+ const promise2 = this.reconnectWithRetry(trigger).finally(() => {
176493
+ if (this.reconnecting === promise2)
176494
+ this.reconnecting = null;
176495
+ });
176496
+ this.reconnecting = promise2;
176497
+ return promise2;
176498
+ }
176499
+ async reconnectWithRetry(_trigger) {
176500
+ let attempt = 0;
176501
+ let delay = this.opts.reconnectBackoff.baseMs;
176502
+ for (;; ) {
176503
+ if (this.closeStarted)
176504
+ throw new SubcError("client closed");
176505
+ attempt += 1;
176506
+ try {
176507
+ const opened = await SubcClient.openConnection(this.opts);
176508
+ if (this.closeStarted) {
176509
+ opened.sock.close();
176510
+ throw new SubcError("client closed");
176511
+ }
176512
+ this.replaceConnection(opened);
176513
+ await this.reopenCachedRoutes();
176514
+ return;
176515
+ } catch (err) {
176516
+ if (!isConsumerReconnectTransient(err) || attempt >= this.opts.reconnectBackoff.maxAttempts) {
176517
+ if (err instanceof AuthError && attempt > 1) {
176518
+ 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`);
176519
+ }
176520
+ throw err;
176521
+ }
176522
+ await this.opts.sleep(delay);
176523
+ delay = Math.min(delay * 2, this.opts.reconnectBackoff.capMs);
176524
+ }
176525
+ }
176526
+ }
176527
+ replaceConnection(opened) {
176528
+ this.sock.close();
176529
+ this.sock = opened.sock;
176530
+ this.currentConn = opened.conn;
176531
+ this.closedErr = null;
176532
+ this.generation += 1;
176533
+ this.connectionToken = newConnectionToken();
176534
+ this.liveRoutes.clear();
176535
+ this.lateResponses.clear();
176536
+ this.nextCorr = 1n;
176537
+ this.readLoop(opened.sock, this.generation);
176538
+ }
176539
+ async reopenCachedRoutes() {
176540
+ for (const cached2 of this.routes.values())
176541
+ cached2.handle = null;
176542
+ for (const cached2 of this.routes.values()) {
176543
+ if (cached2.closed)
176544
+ continue;
176545
+ const handle = await this.routeOpen(cached2.target, cached2.identity, {
176546
+ consumerIdentity: cached2.consumerIdentity ?? null
176547
+ });
176548
+ if (cached2.closed) {
176549
+ this.liveRoutes.delete(handle.channel);
176550
+ this.sendRouteGoodbye(handle);
176551
+ continue;
176552
+ }
176553
+ cached2.handle = handle;
176554
+ }
176555
+ }
176556
+ timeoutMessage(channel, corr, ms) {
176557
+ const port = this.sock.localPort();
176558
+ const where = port === null ? "channel" : `local_port=${port} channel`;
176559
+ return `request on ${where} ${channel} corr ${corr} timed out after ${ms}ms`;
176560
+ }
176561
+ routeClosedDuringOpen() {
176562
+ return new SubcCallError("not_sent", "route was closed before route.open completed", "route_closed");
176563
+ }
176564
+ async readLoop(sock, generation) {
176565
+ try {
176566
+ for (;; ) {
176567
+ this.readerActive = false;
176568
+ const frame = await sock.readFrame(Number.POSITIVE_INFINITY, { afterHeaderMs: BODY_READ_TIMEOUT_MS }, () => {
176569
+ this.readerActive = true;
176570
+ });
176571
+ try {
176572
+ if (this.sock === sock && this.generation === generation)
176573
+ this.dispatch(frame);
176574
+ } finally {
176575
+ this.readerActive = false;
176576
+ }
176577
+ }
176578
+ } catch (error51) {
176579
+ if (this.sock === sock && this.generation === generation) {
176580
+ this.fail(error51 instanceof Error ? error51 : new SubcError(String(error51)));
176581
+ }
176582
+ }
176583
+ }
176584
+ dispatch(frame) {
176585
+ let handle = null;
176586
+ if (frame.header.channel !== 0) {
176587
+ handle = this.liveRoutes.get(frame.header.channel) ?? null;
176588
+ if (!handle || handle.epoch !== frame.header.epoch) {
176589
+ this.ingressEpochDropCount += 1;
176590
+ return;
176591
+ }
176592
+ }
176593
+ const key = pendingKey(handle, frame.header.corr);
176594
+ const pending = this.pending.get(key);
176595
+ if (pending) {
176596
+ if (pending.acceptFrame && !pending.acceptFrame(frame))
176597
+ return;
176598
+ switch (frame.header.ty) {
176599
+ case FrameType.Push:
176600
+ case FrameType.StreamData:
176601
+ pending.onProgress?.(frame.body);
176602
+ return;
176603
+ case FrameType.Response:
176604
+ case FrameType.StreamEnd:
176605
+ this.settle(key, pending, () => pending.resolve(frame));
176606
+ return;
176607
+ case FrameType.Error:
176608
+ this.settle(key, pending, () => pending.reject(this.errorFromFrame(frame)));
176609
+ return;
176610
+ default:
176611
+ return;
176612
+ }
176613
+ }
176614
+ const late = this.lateResponses.get(key);
176615
+ if (late && (frame.header.ty === FrameType.Response || frame.header.ty === FrameType.Error)) {
176616
+ this.lateResponses.delete(key);
176617
+ late(frame);
176618
+ return;
176619
+ }
176620
+ if (frame.header.ty === FrameType.Goodbye && handle) {
176621
+ this.failHandle(handle, new SubcError("route closed by subc (GOODBYE)"));
176622
+ if (this.liveRoutes.get(handle.channel) === handle)
176623
+ this.liveRoutes.delete(handle.channel);
176624
+ this.evictRouteHandle(handle);
176625
+ return;
176626
+ }
176627
+ if (frame.header.ty === FrameType.Response || frame.header.ty === FrameType.Error || frame.header.ty === FrameType.StreamEnd) {
176628
+ 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() ?? "?");
176629
+ }
176630
+ }
176631
+ settle(key, pending, run) {
176632
+ if (this.pending.get(key) !== pending)
176633
+ return false;
176634
+ this.pending.delete(key);
176635
+ if (pending.timer)
176636
+ clearTimeout(pending.timer);
176637
+ run();
176638
+ pending.onSettle?.();
176639
+ return true;
176640
+ }
176641
+ rejectPending(key, pending, err) {
176642
+ this.settle(key, pending, () => pending.reject(pending.classifyFailure?.(err) ?? err));
176643
+ }
176644
+ errorFromFrame(frame) {
176645
+ try {
176646
+ const parsed = JSON.parse(Buffer.from(frame.body).toString("utf8"));
176647
+ return new SubcError(parsed.message ?? "subc error", parsed.code);
176648
+ } catch {
176649
+ return new SubcError(Buffer.from(frame.body).toString("utf8") || "subc error");
176650
+ }
176651
+ }
176652
+ evictRouteHandle(handle) {
176653
+ for (const cached2 of this.routes.values()) {
176654
+ if (cached2.handle && sameRouteHandle(cached2.handle, handle))
176655
+ cached2.handle = null;
176656
+ }
176657
+ }
176658
+ failHandle(handle, error51) {
176659
+ for (const [key, pending] of this.pending) {
176660
+ if (pending.handle && sameRouteHandle(pending.handle, handle))
176661
+ this.rejectPending(key, pending, error51);
176662
+ }
176663
+ }
176664
+ fail(err) {
176665
+ if (!this.closedErr)
176666
+ this.closedErr = err;
176667
+ for (const [key, pending] of this.pending) {
176668
+ this.rejectPending(key, pending, err);
176669
+ }
176670
+ }
176671
+ notSentCallError(message, cause) {
176672
+ return new SubcCallError("not_sent", `${message}${causeMessage(cause)}`, errorCode(cause), cause);
176673
+ }
176674
+ outcomeUnknownCallError(message, cause) {
176675
+ return new SubcCallError("outcome_unknown", `${message}${causeMessage(cause)}`, errorCode(cause), cause);
176676
+ }
176677
+ terminalCallError(message, cause) {
176678
+ if (cause instanceof SubcCallError)
176679
+ return cause;
176680
+ return new SubcCallError("terminal", `${message}${causeMessage(cause)}`, errorCode(cause), cause);
176681
+ }
176682
+ notSentRecoveryError(message, cause) {
176683
+ if (cause instanceof SubcCallError)
176684
+ return cause;
176685
+ if (isConsumerReconnectTransient(cause))
176686
+ return this.notSentCallError(message, cause);
176687
+ return this.terminalCallError(message, cause);
176688
+ }
176689
+ get droppedIngressFrames() {
176690
+ return this.ingressEpochDropCount;
176691
+ }
176692
+ installRoute(channel, epoch) {
176693
+ const handle = createRouteHandle(channel, epoch, this.connectionToken);
176694
+ this.liveRoutes.set(channel, handle);
176695
+ return handle;
176696
+ }
176697
+ isLiveHandle(handle) {
176698
+ return belongsToConnection(handle, this.connectionToken) && this.liveRoutes.get(handle.channel) === handle;
176699
+ }
176700
+ assertLiveConnection(handle) {
176701
+ if (!belongsToConnection(handle, this.connectionToken))
176702
+ throw new StaleRouteHandleError(handle);
176703
+ }
176704
+ assertLiveHandle(handle) {
176705
+ if (!this.isLiveHandle(handle))
176706
+ throw new StaleRouteHandleError(handle);
176707
+ }
176708
+ allocateCorr() {
176709
+ const maximum = 0xffffffffffffffffn;
176710
+ if (this.nextCorr > maximum) {
176711
+ const error51 = new SubcError("channel-0 correlation id allocator exhausted", "corr_exhausted");
176712
+ this.fail(error51);
176713
+ this.sock.close();
176714
+ this.scheduleReconnectAfterDrop(error51);
176715
+ throw error51;
176716
+ }
176717
+ const corr = this.nextCorr;
176718
+ this.nextCorr += 1n;
176719
+ return corr;
176720
+ }
176721
+ closeConnectionAfterCleanupFailure() {
176722
+ const error51 = new SubcError("late route cleanup could not be queued", "late_route_cleanup_failed");
176723
+ this.fail(error51);
176724
+ this.sock.close();
176725
+ this.scheduleReconnectAfterDrop(error51);
176726
+ }
176727
+ encode(value) {
176728
+ return new Uint8Array(Buffer.from(JSON.stringify(value), "utf8"));
176729
+ }
176730
+ parseJson(frame) {
176731
+ return JSON.parse(Buffer.from(frame.body).toString("utf8"));
176732
+ }
176733
+ }
176734
+ function isConsumerReconnectTransient(err) {
176735
+ if (err instanceof SocketClosedError || err instanceof SocketTimeoutError)
176736
+ return true;
176737
+ if (err instanceof SocketWriteNotQueuedError || err instanceof SocketWriteQueuedError)
176738
+ return true;
176739
+ if (err instanceof SubcCallError)
176740
+ return err.kind === "not_sent" || err.kind === "outcome_unknown";
176741
+ if (err instanceof AuthError)
176742
+ return true;
176743
+ if (err instanceof SubcError || err instanceof ConnectionFileError)
176744
+ return false;
176745
+ const code = errorCode(err);
176746
+ return code === "ECONNREFUSED" || code === "ECONNRESET" || code === "EPIPE" || code === "ETIMEDOUT" || code === "ENOENT";
176747
+ }
176748
+ function isRetryableRouteOpenCode(code) {
176749
+ return code === "unknown_module" || code === "module_reloading" || code === "target_unavailable" || code === "module_timeout";
176750
+ }
176751
+ async function connectionFileExists(path7) {
176752
+ try {
176753
+ await fs4.access(path7);
176754
+ return true;
176755
+ } catch {
176756
+ return false;
176757
+ }
176758
+ }
176759
+ function normalizeConnectOptions(opts) {
176760
+ return {
176761
+ connectionFile: opts.connectionFile,
176762
+ handshakeTimeoutMs: opts.handshakeTimeoutMs,
176763
+ identity: opts.identity,
176764
+ targetKind: opts.targetKind ?? DEFAULT_MANAGED_TARGET_KIND,
176765
+ reconnectBackoff: opts.reconnectBackoff ?? DEFAULT_RECONNECT_BACKOFF,
176766
+ sleep: opts.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms))),
176767
+ timeoutArbitrationGraceMs: opts.timeoutArbitrationGraceMs ?? TIMEOUT_ARBITRATION_GRACE_MS
176768
+ };
176769
+ }
176770
+ function routeCacheKey(target, identity, consumerIdentity) {
176771
+ const consumerPart = consumerIdentity ? `${consumerIdentity.module_id}\x00${consumerIdentity.launch_nonce}` : "";
176772
+ return `${target.kind}\x00${target.module_id}\x00${identity.project_root}\x00${identity.harness}\x00${identity.session}\x00${consumerPart}`;
176773
+ }
176774
+ function routeOpenConsumerIdentity(opts = {}) {
176775
+ if (opts.consumerIdentity !== undefined)
176776
+ return opts.consumerIdentity ?? undefined;
176777
+ const moduleId = process.env[SUBC_MODULE_ID_ENV];
176778
+ const launchNonce = process.env[SUBC_LAUNCH_NONCE_ENV];
176779
+ if (!moduleId || !launchNonce)
176780
+ return;
176781
+ return { module_id: moduleId, launch_nonce: launchNonce };
176782
+ }
176783
+ function errorCode(err) {
176784
+ if (typeof err === "object" && err !== null && "code" in err) {
176785
+ const code = err.code;
176786
+ if (typeof code === "string")
176787
+ return code;
176788
+ }
176789
+ return;
176790
+ }
176791
+ function causeMessage(cause) {
176792
+ if (cause === undefined)
176793
+ return "";
176794
+ return `: ${cause instanceof Error ? cause.message : String(cause)}`;
176795
+ }
176796
+ function pendingKey(handle, corr) {
176797
+ return handle ? `${handle.channel}:${handle.epoch}:${corr}` : `0:0:${corr}`;
176798
+ }
176799
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/provider.js
176800
+ import { Buffer as Buffer4 } from "node:buffer";
176801
+ var DEFAULT_HANDSHAKE_TIMEOUT_MS2 = 1e4;
176802
+ var BODY_READ_TIMEOUT_MS2 = 30000;
176803
+ var WRITE_TIMEOUT_MS = 30000;
176804
+ var DEFAULT_RESTORED_DEBOUNCE_MS = 250;
176805
+ var DEFAULT_PROVIDER_HANDLER_CAPACITY = 64;
176806
+ var HEALTH_CHECK_OP = "health.check";
176807
+ var HELLO_CORR = 1n;
176808
+
176809
+ class AsyncPermitPool {
176810
+ available;
176811
+ waiters = [];
176812
+ constructor(capacity) {
176813
+ if (!Number.isInteger(capacity) || capacity <= 0) {
176814
+ throw new SubcProviderError("provider handler capacity must be a positive integer", "invalid_handler_capacity");
176815
+ }
176816
+ this.available = capacity;
176817
+ }
176818
+ async acquire() {
176819
+ if (this.available > 0) {
176820
+ this.available -= 1;
176821
+ return this.releaseOnce();
176822
+ }
176823
+ await new Promise((resolve) => {
176824
+ this.waiters.push(resolve);
176825
+ });
176826
+ return this.releaseOnce();
176827
+ }
176828
+ releaseOnce() {
176829
+ let released = false;
176830
+ return () => {
176831
+ if (released)
176832
+ return;
176833
+ released = true;
176834
+ const next = this.waiters.shift();
176835
+ if (next) {
176836
+ next();
176837
+ } else {
176838
+ this.available += 1;
176839
+ }
176840
+ };
176841
+ }
176842
+ }
176843
+
176844
+ class SubcProviderError extends Error {
176845
+ code;
176846
+ constructor(message, code) {
176847
+ super(message);
176848
+ this.code = code;
176849
+ }
176850
+ }
176851
+ class SubcProvider {
176852
+ sock;
176853
+ currentConn;
176854
+ opts;
176855
+ closed;
176856
+ resolveClosed = () => {
176857
+ return;
176858
+ };
176859
+ closeStarted = false;
176860
+ closedErr = null;
176861
+ inflight = new Map;
176862
+ pending = new Map;
176863
+ liveRoutes = new Map;
176864
+ connectionToken = newConnectionToken();
176865
+ nextCorr = 1n;
176866
+ ingressEpochDropCount = 0;
176867
+ requestGate = new AsyncPermitPool(DEFAULT_PROVIDER_HANDLER_CAPACITY);
176868
+ reconnecting = null;
176869
+ generation = 1;
176870
+ connectionEpoch = 1;
176871
+ stateQueue = [];
176872
+ drainingStateQueue = false;
176873
+ restoredDebounceToken = 0;
176874
+ storage;
176875
+ constructor(sock, currentConn, opts, storage) {
176876
+ this.sock = sock;
176877
+ this.currentConn = currentConn;
176878
+ this.opts = opts;
176879
+ this.storage = storage;
176880
+ this.closed = new Promise((resolve) => {
176881
+ this.resolveClosed = resolve;
176882
+ });
176883
+ this.readLoop(sock, this.generation);
176884
+ this.enqueueConnectionState({ state: "connected", epoch: this.connectionEpoch });
176885
+ }
176886
+ get droppedIngressFrames() {
176887
+ return this.ingressEpochDropCount;
176888
+ }
176889
+ get conn() {
176890
+ return this.currentConn;
176891
+ }
176892
+ currentEpoch() {
176893
+ return this.connectionEpoch;
176894
+ }
176895
+ async request(handle, body, opts = {}) {
176896
+ this.assertLiveHandle(handle);
176897
+ const corr = this.allocateCorr();
176898
+ const key = routeKey(handle, corr);
176899
+ const timeoutMs = opts.timeoutMs ?? WRITE_TIMEOUT_MS;
176900
+ const frame = buildFrame(FrameType.Request, buildFlags(false, opts.priority ?? Priority.Interactive, false, opts.admissionClass ?? AdmissionClass.Normal), handle.channel, handle.epoch, corr, body);
176901
+ return await new Promise((resolve, reject) => {
176902
+ const timer = setTimeout(() => {
176903
+ if (this.pending.delete(key))
176904
+ reject(new SubcProviderError("reverse request timed out", "request_timeout"));
176905
+ }, timeoutMs);
176906
+ this.pending.set(key, {
176907
+ resolve: (response) => resolve(response.body),
176908
+ reject,
176909
+ timer
176910
+ });
176911
+ this.sendOn(this.sock, this.generation, frame).catch((error51) => {
176912
+ const pending = this.pending.get(key);
176913
+ if (!pending)
176914
+ return;
176915
+ this.pending.delete(key);
176916
+ clearTimeout(pending.timer);
176917
+ reject(error51 instanceof Error ? error51 : new SubcProviderError(String(error51)));
176918
+ });
176919
+ });
176920
+ }
176921
+ async push(handle, body, opts = {}) {
176922
+ this.assertLiveHandle(handle);
176923
+ 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));
176924
+ }
176925
+ cancel(handle, corr) {
176926
+ this.assertLiveHandle(handle);
176927
+ this.sendOn(this.sock, this.generation, buildFrame(FrameType.Cancel, controlFlags(), handle.channel, handle.epoch, corr, new Uint8Array(0)));
176928
+ }
176929
+ closeRoute(handle) {
176930
+ this.assertLiveHandle(handle);
176931
+ this.liveRoutes.delete(handle.channel);
176932
+ this.abortHandle(handle);
176933
+ this.sendOn(this.sock, this.generation, buildFrame(FrameType.Goodbye, controlFlags(), handle.channel, handle.epoch, 0n, new Uint8Array(0)));
176934
+ }
176935
+ static async connect(opts) {
176936
+ if (opts.manifest.protocol_ver !== PROTOCOL_VERSION) {
176937
+ throw new SubcProviderError(`manifest protocol_ver ${opts.manifest.protocol_ver} does not match client protocol ${PROTOCOL_VERSION}`, "invalid_manifest");
176938
+ }
176939
+ const normalized = normalizeProviderConnectOptions(opts);
176940
+ const opened = await SubcProvider.openConnection(normalized);
176941
+ return new SubcProvider(opened.sock, opened.conn, normalized, opened.ack.storage);
176942
+ }
176943
+ async close() {
176944
+ if (!this.closeStarted) {
176945
+ this.closeStarted = true;
176946
+ this.cancelRestoredDebounce();
176947
+ const sock = this.sock;
176948
+ try {
176949
+ await sendFrame(sock, buildFrame(FrameType.Goodbye, controlFlags(), 0, 0, 0n, new Uint8Array(0)));
176950
+ } catch {} finally {
176951
+ sock.close();
176952
+ this.finishClosed();
176953
+ }
176954
+ }
176955
+ await this.closed;
176956
+ }
176957
+ static async openConnection(opts) {
176958
+ const conn = await readConnectionFile(opts.connectionFile);
176959
+ const deadline = Date.now() + (opts.handshakeTimeoutMs ?? DEFAULT_HANDSHAKE_TIMEOUT_MS2);
176960
+ const endpoint = conn.endpoints[0];
176961
+ const sock = await SubcSocket.connect(endpoint.host, endpoint.port, deadline);
176962
+ try {
176963
+ await authenticateClient(sock, conn, deadline);
176964
+ await sendFrame(sock, buildHelloFrame(opts));
176965
+ const ack = await expectHelloAck(sock, deadline);
176966
+ return { sock, conn, ack };
176967
+ } catch (err) {
176968
+ sock.close();
176969
+ throw err;
176970
+ }
176971
+ }
176972
+ async readLoop(sock, generation) {
176973
+ try {
176974
+ for (;; ) {
176975
+ const frame = await sock.readFrame(Number.POSITIVE_INFINITY, { afterHeaderMs: BODY_READ_TIMEOUT_MS2 });
176976
+ const keepGoing = await this.dispatch(frame, sock, generation);
176977
+ if (!keepGoing) {
176978
+ if (this.sock === sock && this.generation === generation)
176979
+ this.closeStarted = true;
176980
+ break;
176981
+ }
176982
+ }
176983
+ } catch (error51) {
176984
+ if (this.sock === sock && this.generation === generation && !this.closeStarted) {
176985
+ this.handleUnexpectedDrop(sock, generation, error51 instanceof Error ? error51 : new SubcProviderError(String(error51)));
176986
+ return;
176987
+ }
176988
+ } finally {
176989
+ if (this.sock === sock && this.generation === generation) {
176990
+ sock.close();
176991
+ if (this.closeStarted)
176992
+ this.finishClosed();
176993
+ }
176994
+ }
176995
+ }
176996
+ async dispatch(frame, sock, generation) {
176997
+ let handle = null;
176998
+ if (frame.header.channel !== 0) {
176999
+ handle = this.liveRoutes.get(frame.header.channel) ?? null;
177000
+ if (!handle || handle.epoch !== frame.header.epoch) {
177001
+ this.ingressEpochDropCount += 1;
177002
+ return true;
177003
+ }
177004
+ }
177005
+ if (handle) {
177006
+ const pendingKey2 = routeKey(handle, frame.header.corr);
177007
+ const pending = this.pending.get(pendingKey2);
177008
+ if (pending) {
177009
+ if (frame.header.ty === FrameType.Push || frame.header.ty === FrameType.StreamData)
177010
+ return true;
177011
+ if (frame.header.ty === FrameType.Response || frame.header.ty === FrameType.StreamEnd) {
177012
+ this.pending.delete(pendingKey2);
177013
+ clearTimeout(pending.timer);
177014
+ pending.resolve(frame);
177015
+ return true;
177016
+ }
177017
+ if (frame.header.ty === FrameType.Error) {
177018
+ this.pending.delete(pendingKey2);
177019
+ clearTimeout(pending.timer);
177020
+ pending.reject(providerErrorFromFrame(frame));
177021
+ return true;
177022
+ }
177023
+ }
177024
+ }
177025
+ switch (frame.header.ty) {
177026
+ case FrameType.Ping:
177027
+ if (frame.header.channel === 0) {
177028
+ await this.sendOn(sock, generation, buildFrameWithVersion(frame.header.ver, FrameType.Pong, frame.header.flags, 0, 0, frame.header.corr, new Uint8Array(0)));
177029
+ }
177030
+ return true;
177031
+ case FrameType.Goodbye:
177032
+ if (!handle)
177033
+ return false;
177034
+ this.liveRoutes.delete(handle.channel);
177035
+ this.abortHandle(handle);
177036
+ await this.opts.onRouteGone?.(handle);
177037
+ return true;
177038
+ case FrameType.Cancel:
177039
+ if (handle)
177040
+ this.inflight.get(routeKey(handle, frame.header.corr))?.abort();
177041
+ return true;
177042
+ case FrameType.Request:
177043
+ if (frame.header.channel === 0) {
177044
+ await this.handleControlRequest(frame, sock, generation);
177045
+ } else if (handle) {
177046
+ this.handleDataRequest(frame, handle, sock, generation).catch((error51) => {
177047
+ if (!this.closeStarted && this.sock === sock && this.generation === generation) {
177048
+ console.warn("SubcProvider handler failed after its request was dispatched", error51);
177049
+ }
177050
+ });
177051
+ }
177052
+ return true;
177053
+ default:
177054
+ return true;
177055
+ }
177056
+ }
177057
+ abortHandle(handle) {
177058
+ const prefix = `${handle.channel}:${handle.epoch}:`;
177059
+ for (const [key, controller] of this.inflight) {
177060
+ if (key.startsWith(prefix))
177061
+ controller.abort();
177062
+ }
177063
+ for (const [key, pending] of this.pending) {
177064
+ if (!key.startsWith(prefix))
177065
+ continue;
177066
+ this.pending.delete(key);
177067
+ clearTimeout(pending.timer);
177068
+ pending.reject(new StaleRouteHandleError(handle));
177069
+ }
177070
+ }
177071
+ abortGeneration(_generation) {
177072
+ this.abortAllInflight();
177073
+ for (const [key, pending] of this.pending) {
177074
+ this.pending.delete(key);
177075
+ clearTimeout(pending.timer);
177076
+ pending.reject(new SubcProviderError("provider connection dropped", "connection_dropped"));
177077
+ }
177078
+ this.liveRoutes.clear();
177079
+ }
177080
+ abortAllInflight() {
177081
+ for (const controller of this.inflight.values())
177082
+ controller.abort();
177083
+ }
177084
+ async handleControlRequest(frame, sock, generation) {
177085
+ const request = parseJson(frame.body);
177086
+ if (request.op === HEALTH_CHECK_OP) {
177087
+ this.handleHealthRequest(frame, sock, generation).catch((error51) => {
177088
+ if (!this.closeStarted && this.sock === sock && this.generation === generation) {
177089
+ console.warn("SubcProvider health handler failed after its request was dispatched", error51);
177090
+ }
177091
+ });
177092
+ return;
177093
+ }
177094
+ if (request.op !== "route.bind") {
177095
+ throw new SubcProviderError(`unsupported module control request ${request.op ?? "<missing op>"}`);
177096
+ }
177097
+ const tentative = createRouteHandle(numberField(request.route_channel, "route_channel"), numberField(request.epoch, "epoch"), this.connectionToken);
177098
+ const bindRequest = {
177099
+ handle: tentative,
177100
+ target: request.target,
177101
+ identity: request.identity,
177102
+ principal: request.principal,
177103
+ consumer_capabilities: request.consumer_capabilities
177104
+ };
177105
+ let decision;
177106
+ try {
177107
+ decision = await this.opts.onBind?.(bindRequest);
177108
+ } catch (error51) {
177109
+ try {
177110
+ await this.sendError(frame, "route_rejected", error51 instanceof Error ? error51.message : String(error51), controlFlags(), sock, generation);
177111
+ } finally {
177112
+ await this.opts.onRouteGone?.(tentative);
177113
+ }
177114
+ return;
177115
+ }
177116
+ const rejection = bindRejection(decision);
177117
+ if (rejection) {
177118
+ try {
177119
+ await this.sendError(frame, rejection.code, rejection.message, controlFlags(), sock, generation);
177120
+ } finally {
177121
+ await this.opts.onRouteGone?.(tentative);
177122
+ }
177123
+ return;
177124
+ }
177125
+ try {
177126
+ await this.sendOn(sock, generation, buildFrameWithVersion(frame.header.ver, FrameType.Response, controlFlags(), 0, 0, frame.header.corr, encodeJson({ op: "route.bind" })));
177127
+ } catch (error51) {
177128
+ await this.opts.onRouteGone?.(tentative);
177129
+ throw error51;
177130
+ }
177131
+ if (this.sock !== sock || this.generation !== generation || this.closeStarted || this.closedErr) {
177132
+ await this.opts.onRouteGone?.(tentative);
177133
+ return;
177134
+ }
177135
+ this.liveRoutes.set(tentative.channel, tentative);
177136
+ await this.opts.onBound?.(tentative);
177137
+ }
177138
+ async handleDataRequest(frame, handle, sock, generation) {
177139
+ const { corr, ver } = frame.header;
177140
+ const key = routeKey(handle, corr);
177141
+ const controller = new AbortController;
177142
+ this.inflight.set(key, controller);
177143
+ const context = {
177144
+ handle,
177145
+ signal: controller.signal,
177146
+ currentEpoch: () => this.connectionEpoch,
177147
+ emit: async (eventBody, options = {}) => {
177148
+ this.assertLiveHandle(handle);
177149
+ if (controller.signal.aborted)
177150
+ return;
177151
+ 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));
177152
+ }
177153
+ };
177154
+ const releasePermit = await (this.requestGate ?? new AsyncPermitPool(DEFAULT_PROVIDER_HANDLER_CAPACITY)).acquire();
177155
+ const dataFlags = buildFlags(false, Priority.Interactive, false);
177156
+ try {
177157
+ const body = await this.opts.handler(handle, frame.body, context);
177158
+ if (controller.signal.aborted)
177159
+ return;
177160
+ this.assertLiveHandle(handle);
177161
+ if (body === undefined) {
177162
+ await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.StreamEnd, dataFlags, handle.channel, handle.epoch, corr, new Uint8Array(0)));
177163
+ } else if (body instanceof Uint8Array) {
177164
+ await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.Response, dataFlags, handle.channel, handle.epoch, corr, body));
177165
+ } else {
177166
+ throw new SubcProviderError("provider handler must return a Uint8Array or void", "invalid_handler_response");
177167
+ }
177168
+ } catch (error51) {
177169
+ if (error51 instanceof StaleRouteHandleError || controller.signal.aborted)
177170
+ return;
177171
+ await this.sendError(frame, error51 instanceof SubcProviderError && error51.code ? error51.code : "handler_error", error51 instanceof Error ? error51.message : String(error51), dataFlags, sock, generation);
177172
+ } finally {
177173
+ releasePermit();
177174
+ if (this.inflight.get(key) === controller)
177175
+ this.inflight.delete(key);
177176
+ }
177177
+ }
177178
+ async handleHealthRequest(frame, sock, generation) {
177179
+ const { corr, ver } = frame.header;
177180
+ const key = `control:${generation}:${corr}`;
177181
+ const controller = new AbortController;
177182
+ this.inflight.set(key, controller);
177183
+ const releasePermit = await (this.requestGate ?? new AsyncPermitPool(DEFAULT_PROVIDER_HANDLER_CAPACITY)).acquire();
177184
+ try {
177185
+ if (controller.signal.aborted)
177186
+ return;
177187
+ const report = await this.opts.health();
177188
+ await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.Response, controlFlags(), 0, 0, corr, encodeJson({
177189
+ op: HEALTH_CHECK_OP,
177190
+ status: report.status,
177191
+ ...report.detail === undefined ? {} : { detail: report.detail },
177192
+ ...report.metrics === undefined ? {} : { metrics: report.metrics }
177193
+ })));
177194
+ } catch (error51) {
177195
+ await this.sendError(frame, error51 instanceof SubcProviderError && error51.code ? error51.code : "health_error", error51 instanceof Error ? error51.message : String(error51), controlFlags(), sock, generation);
177196
+ } finally {
177197
+ releasePermit();
177198
+ if (this.inflight.get(key) === controller)
177199
+ this.inflight.delete(key);
177200
+ }
177201
+ }
177202
+ async sendError(frame, code, message, flags, sock, generation) {
177203
+ await this.sendOn(sock, generation, buildFrameWithVersion(frame.header.ver, FrameType.Error, flags, frame.header.channel, frame.header.epoch, frame.header.corr, encodeJson({ code, message })));
177204
+ }
177205
+ async sendOn(sock, generation, frame) {
177206
+ if (this.sock !== sock || this.generation !== generation || this.closeStarted || this.closedErr)
177207
+ return;
177208
+ await sendFrame(sock, frame);
177209
+ }
177210
+ handleUnexpectedDrop(sock, generation, cause) {
177211
+ this.cancelRestoredDebounce();
177212
+ this.abortGeneration(generation);
177213
+ this.generation += 1;
177214
+ sock.close();
177215
+ this.enqueueConnectionState({ state: "down", cause });
177216
+ this.scheduleReconnectAfterDrop(cause);
177217
+ }
177218
+ scheduleReconnectAfterDrop(trigger) {
177219
+ if (this.closeStarted || this.reconnecting)
177220
+ return;
177221
+ const promise2 = this.reconnectWithRetry(trigger).catch((err) => {
177222
+ if (!this.closeStarted)
177223
+ this.failFatal(err instanceof Error ? err : new SubcProviderError(String(err)));
177224
+ }).finally(() => {
177225
+ if (this.reconnecting === promise2)
177226
+ this.reconnecting = null;
177227
+ });
177228
+ this.reconnecting = promise2;
177229
+ }
177230
+ async reconnectWithRetry(_trigger) {
177231
+ let attempt = 0;
177232
+ let delay = this.opts.reconnectBackoff.baseMs;
177233
+ for (;; ) {
177234
+ if (this.closeStarted)
177235
+ throw new SubcProviderError("provider closed");
177236
+ attempt += 1;
177237
+ this.enqueueConnectionState({ state: "reconnecting", attempt });
177238
+ try {
177239
+ const opened = await SubcProvider.openConnection(this.opts);
177240
+ if (this.closeStarted) {
177241
+ opened.sock.close();
177242
+ throw new SubcProviderError("provider closed");
177243
+ }
177244
+ this.replaceConnection(opened);
177245
+ return;
177246
+ } catch (err) {
177247
+ if (this.closeStarted)
177248
+ throw err;
177249
+ if (!isProviderReconnectTransient(err))
177250
+ throw err;
177251
+ await this.opts.sleep(delay);
177252
+ delay = Math.min(delay * 2, this.opts.reconnectBackoff.capMs);
177253
+ }
177254
+ }
177255
+ }
177256
+ replaceConnection(opened) {
177257
+ this.sock.close();
177258
+ this.sock = opened.sock;
177259
+ this.currentConn = opened.conn;
177260
+ this.storage = opened.ack.storage;
177261
+ this.closedErr = null;
177262
+ this.connectionEpoch += 1;
177263
+ this.connectionToken = newConnectionToken();
177264
+ this.liveRoutes.clear();
177265
+ this.nextCorr = 1n;
177266
+ const generation = this.generation;
177267
+ this.readLoop(opened.sock, generation);
177268
+ this.scheduleRestored(generation, this.connectionEpoch);
177269
+ }
177270
+ scheduleRestored(generation, epoch) {
177271
+ if (!this.opts.onConnectionState)
177272
+ return;
177273
+ const token = ++this.restoredDebounceToken;
177274
+ this.opts.sleep(this.opts.restoredDebounceMs).then(() => {
177275
+ if (token === this.restoredDebounceToken && !this.closeStarted && this.sock && this.generation === generation && this.connectionEpoch === epoch) {
177276
+ this.enqueueConnectionState({ state: "restored", epoch });
177277
+ }
177278
+ }).catch((err) => {
177279
+ if (token === this.restoredDebounceToken && !this.closeStarted) {
177280
+ console.warn("SubcProvider restored debounce timer failed", err);
177281
+ }
177282
+ });
177283
+ }
177284
+ cancelRestoredDebounce() {
177285
+ this.restoredDebounceToken += 1;
177286
+ }
177287
+ enqueueConnectionState(event) {
177288
+ if (!this.opts.onConnectionState)
177289
+ return;
177290
+ this.stateQueue.push(event);
177291
+ if (!this.drainingStateQueue)
177292
+ this.drainConnectionStateQueue();
177293
+ }
177294
+ async drainConnectionStateQueue() {
177295
+ if (this.drainingStateQueue)
177296
+ return;
177297
+ this.drainingStateQueue = true;
177298
+ try {
177299
+ while (this.stateQueue.length > 0) {
177300
+ const event = this.stateQueue[0];
177301
+ try {
177302
+ await this.opts.onConnectionState?.(event);
177303
+ this.stateQueue.shift();
177304
+ } catch (err) {
177305
+ if (event.state === "restored") {
177306
+ console.warn("SubcProvider restored callback failed; retrying delivery", err);
177307
+ await pauseBeforeStateRetry();
177308
+ continue;
177309
+ }
177310
+ console.warn("SubcProvider connection-state callback failed", err);
177311
+ this.stateQueue.shift();
177312
+ }
177313
+ }
177314
+ } finally {
177315
+ this.drainingStateQueue = false;
177316
+ if (this.stateQueue.length > 0)
177317
+ this.drainConnectionStateQueue();
177318
+ }
177319
+ }
177320
+ isLiveHandle(handle) {
177321
+ return belongsToConnection(handle, this.connectionToken) && this.liveRoutes.get(handle.channel) === handle;
177322
+ }
177323
+ assertLiveHandle(handle) {
177324
+ if (!this.isLiveHandle(handle))
177325
+ throw new StaleRouteHandleError(handle);
177326
+ }
177327
+ allocateCorr() {
177328
+ const maximum = 0xffffffffffffffffn;
177329
+ if (this.nextCorr > maximum) {
177330
+ const error51 = new SubcProviderError("channel-0 correlation id allocator exhausted", "corr_exhausted");
177331
+ this.handleUnexpectedDrop(this.sock, this.generation, error51);
177332
+ throw error51;
177333
+ }
177334
+ const corr = this.nextCorr;
177335
+ this.nextCorr += 1n;
177336
+ return corr;
177337
+ }
177338
+ failFatal(err) {
177339
+ if (!this.closedErr)
177340
+ this.closedErr = err;
177341
+ this.closeStarted = true;
177342
+ this.cancelRestoredDebounce();
177343
+ this.abortAllInflight();
177344
+ this.sock.close();
177345
+ this.finishClosed();
177346
+ }
177347
+ finishClosed() {
177348
+ this.resolveClosed();
177349
+ }
177350
+ }
177351
+ function routeKey(handle, corr) {
177352
+ return `${handle.channel}:${handle.epoch}:${corr}`;
177353
+ }
177354
+ function providerErrorFromFrame(frame) {
177355
+ try {
177356
+ const body = parseJson(frame.body);
177357
+ return new SubcProviderError(body.message ?? "subc error", body.code);
177358
+ } catch {
177359
+ return new SubcProviderError(Buffer4.from(frame.body).toString("utf8") || "subc error");
177360
+ }
177361
+ }
177362
+ function launchNonce(opts) {
177363
+ const nonce = opts.launchNonce ?? process.env[SUBC_LAUNCH_NONCE_ENV2];
177364
+ return nonce && nonce.length > 0 ? nonce : undefined;
177365
+ }
177366
+ var SUBC_LAUNCH_NONCE_ENV2 = "SUBC_LAUNCH_NONCE";
177367
+ function normalizeProviderConnectOptions(opts) {
177368
+ return {
177369
+ connectionFile: opts.connectionFile,
177370
+ manifest: opts.manifest,
177371
+ handler: opts.handler,
177372
+ health: opts.health ?? (() => ({ status: "ok" })),
177373
+ handshakeTimeoutMs: opts.handshakeTimeoutMs,
177374
+ controlOps: opts.controlOps,
177375
+ onBind: opts.onBind,
177376
+ onBound: opts.onBound,
177377
+ onRouteGone: opts.onRouteGone,
177378
+ reconnectBackoff: opts.reconnectBackoff ?? DEFAULT_RECONNECT_BACKOFF,
177379
+ sleep: opts.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms))),
177380
+ restoredDebounceMs: opts.restoredDebounceMs ?? DEFAULT_RESTORED_DEBOUNCE_MS,
177381
+ onConnectionState: opts.onConnectionState,
177382
+ launchNonce: opts.launchNonce
177383
+ };
177384
+ }
177385
+ function normalizedControlOps(controlOps) {
177386
+ if (controlOps === null)
177387
+ return null;
177388
+ const merged = new Set(controlOps ?? []);
177389
+ merged.add(HEALTH_CHECK_OP);
177390
+ return [...merged];
177391
+ }
177392
+ function buildHelloFrame(opts) {
177393
+ const nonce = launchNonce(opts);
177394
+ return buildFrame(FrameType.Hello, controlFlags(), 0, 0, HELLO_CORR, encodeJson({
177395
+ manifest: normalizeManifest(opts.manifest),
177396
+ protocol_ver: PROTOCOL_VERSION,
177397
+ control_ops: normalizedControlOps(opts.controlOps),
177398
+ ...nonce ? { launch_nonce: nonce } : {}
177399
+ }));
177400
+ }
177401
+ function isProviderReconnectTransient(err) {
177402
+ if (err instanceof SubcProviderError)
177403
+ return err.code === "duplicate_module_id";
177404
+ if (err instanceof SocketClosedError || err instanceof SocketTimeoutError)
177405
+ return true;
177406
+ if (err instanceof SocketWriteNotQueuedError || err instanceof SocketWriteQueuedError)
177407
+ return true;
177408
+ if (err instanceof AuthError)
177409
+ return true;
177410
+ if (err instanceof ConnectionFileError)
177411
+ return false;
177412
+ const code = errorCode2(err);
177413
+ return code === "ECONNREFUSED" || code === "ECONNRESET" || code === "EPIPE" || code === "ETIMEDOUT" || code === "ENOENT";
177414
+ }
177415
+ function errorCode2(err) {
177416
+ if (typeof err === "object" && err !== null && "code" in err) {
177417
+ const code = err.code;
177418
+ if (typeof code === "string")
177419
+ return code;
177420
+ }
177421
+ return;
177422
+ }
177423
+ async function pauseBeforeStateRetry() {
177424
+ await new Promise((resolve) => setTimeout(resolve, 0));
177425
+ }
177426
+ function controlFlags() {
177427
+ return buildFlags(false, Priority.Passive, false);
177428
+ }
177429
+ async function sendFrame(sock, frame) {
177430
+ await sock.write(encodeFrame(frame), Date.now() + WRITE_TIMEOUT_MS);
177431
+ }
177432
+ async function expectHelloAck(sock, deadline) {
177433
+ const frame = await sock.readFrame(deadline, deadline);
177434
+ switch (frame.header.ty) {
177435
+ case FrameType.HelloAck: {
177436
+ const ack = parseJson(frame.body);
177437
+ if (ack.negotiated_ver !== PROTOCOL_VERSION) {
177438
+ throw new SubcProviderError(`subc negotiated protocol ${ack.negotiated_ver}; expected exactly ${PROTOCOL_VERSION}`, "unsupported_version");
177439
+ }
177440
+ return ack;
177441
+ }
177442
+ case FrameType.Error: {
177443
+ const error51 = parseJson(frame.body);
177444
+ throw new SubcProviderError(`subc rejected HELLO: ${error51.code ?? "unknown"} — ${error51.message ?? "subc error"}`, error51.code);
177445
+ }
177446
+ default:
177447
+ throw new SubcProviderError(`unexpected frame ${FrameType[frame.header.ty]} awaiting HELLO_ACK`);
177448
+ }
177449
+ }
177450
+ function encodeJson(value) {
177451
+ return new Uint8Array(Buffer4.from(JSON.stringify(value), "utf8"));
177452
+ }
177453
+ function parseJson(bytes) {
177454
+ return JSON.parse(Buffer4.from(bytes).toString("utf8"));
177455
+ }
177456
+ function numberField(value, field) {
177457
+ if (typeof value !== "number" || !Number.isInteger(value)) {
177458
+ throw new SubcProviderError(`route.bind ${field} must be an integer`);
177459
+ }
177460
+ return value;
177461
+ }
177462
+ function bindRejection(decision) {
177463
+ if (decision === undefined || decision === true)
177464
+ return null;
177465
+ if (decision === false) {
177466
+ return { code: "route_rejected", message: "route.bind rejected by provider" };
177467
+ }
177468
+ if (decision.accept)
177469
+ return null;
177470
+ return {
177471
+ code: decision.code ?? "route_rejected",
177472
+ message: decision.message ?? "route.bind rejected by provider"
177473
+ };
177474
+ }
177475
+ function normalizeManifest(manifest) {
177476
+ return {
177477
+ module_id: manifest.module_id,
177478
+ module_version: manifest.module_version,
177479
+ protocol_ver: manifest.protocol_ver,
177480
+ trust_tier: manifest.trust_tier,
177481
+ provides: manifest.provides.map(normalizeProviderRole),
177482
+ consumes: manifest.consumes.map(normalizeConsumerRole),
177483
+ scheduled_tasks: manifest.scheduled_tasks.map(normalizeScheduledTask),
177484
+ bindings: {
177485
+ storage: {
177486
+ kind: manifest.bindings.storage.kind,
177487
+ scope: manifest.bindings.storage.scope,
177488
+ owns_schema: manifest.bindings.storage.owns_schema
177489
+ },
177490
+ vault_grants: manifest.bindings.vault_grants.map((grant) => ({
177491
+ secret: grant.secret,
177492
+ reason: grant.reason
177493
+ })),
177494
+ identity: {
177495
+ requires: [...manifest.bindings.identity.requires],
177496
+ optional: [...manifest.bindings.identity.optional]
177497
+ }
177498
+ }
177499
+ };
177500
+ }
177501
+ function normalizeProviderRole(role) {
177502
+ switch (role.role) {
177503
+ case "tool_provider":
177504
+ return {
177505
+ role: "tool_provider",
177506
+ tools: role.tools.map((tool) => ({
177507
+ name: tool.name,
177508
+ ...tool.description === undefined ? {} : { description: tool.description },
177509
+ execution_mode: tool.execution_mode,
177510
+ schema: tool.schema
177511
+ })),
177512
+ identity_scope: [...role.identity_scope],
177513
+ concurrency: role.concurrency,
177514
+ emits_push: role.emits_push,
177515
+ sub_supervises: role.sub_supervises
177516
+ };
177517
+ case "pipeline_stage":
177518
+ return {
177519
+ role: "pipeline_stage",
177520
+ stage: role.stage,
177521
+ applies_to: {
177522
+ provider: role.applies_to.provider,
177523
+ model: role.applies_to.model
177524
+ },
177525
+ interface: role.interface,
177526
+ declares_frozen_floor: role.declares_frozen_floor,
177527
+ needs_signals: [...role.needs_signals],
177528
+ conformance_class: role.conformance_class
177529
+ };
177530
+ case "management_surface":
177531
+ return {
177532
+ role: "management_surface",
177533
+ operations: role.operations.map((operation) => ({
177534
+ name: operation.name,
177535
+ kind: operation.kind
177536
+ })),
177537
+ config_schema: role.config_schema,
177538
+ observability: role.observability.map((surface) => ({
177539
+ name: surface.name,
177540
+ kind: surface.kind
177541
+ })),
177542
+ identity_scope: [...role.identity_scope]
177543
+ };
177544
+ case "internal_service":
177545
+ return {
177546
+ role: "internal_service",
177547
+ service_id: role.service_id,
177548
+ transport: role.transport,
177549
+ agent_facing: role.agent_facing,
177550
+ operations: [...role.operations]
177551
+ };
177552
+ }
177553
+ }
177554
+ function normalizeConsumerRole(role) {
177555
+ switch (role.role) {
177556
+ case "tool_client":
177557
+ return { role: "tool_client", of: [...role.of] };
177558
+ case "llm_client":
177559
+ return { role: "llm_client", via: role.via, auth: role.auth };
177560
+ case "service_client":
177561
+ return { role: "service_client", of: [...role.of] };
177562
+ }
177563
+ }
177564
+ function normalizeScheduledTask(task) {
177565
+ return {
177566
+ task_id: task.task_id,
177567
+ eligibility: {
177568
+ cooldown: task.eligibility.cooldown,
177569
+ window: task.eligibility.window
177570
+ },
177571
+ lease_scope: task.lease_scope,
177572
+ renews_during_calls: task.renews_during_calls,
177573
+ toolset: [...task.toolset],
177574
+ model_policy: {
177575
+ tier: task.model_policy.tier,
177576
+ fallback_chain: [...task.model_policy.fallback_chain]
177577
+ },
177578
+ step_cap: task.step_cap,
177579
+ circuit_breaker: {
177580
+ identical_failures: task.circuit_breaker.identical_failures
177581
+ }
177582
+ };
177583
+ }
177584
+ // ../plugin/src/features/magic-context/memory/embedding-synapse.ts
177585
+ init_logger();
177586
+ var SYNAPSE_DEFAULT_MODEL = "gte-modernbert-base-f16";
177587
+ var SYNAPSE_MAX_INPUT_TOKENS = 8192;
177588
+ var SYNAPSE_DEFAULT_QUERY_TIMEOUT_MS = 3000;
177589
+ var SYNAPSE_DEFAULT_BATCH_TIMEOUT_MS = 120000;
177590
+
177591
+ class SynapseEmbeddingError extends Error {
177592
+ code;
177593
+ retryAfterMs;
177594
+ permanent;
177595
+ constructor(code, message, options) {
177596
+ super(message, options?.cause === undefined ? undefined : { cause: options.cause });
177597
+ this.name = "SynapseEmbeddingError";
177598
+ this.code = code;
177599
+ this.permanent = options?.permanent ?? isPermanentSynapseCode(code);
177600
+ this.retryAfterMs = options?.retryAfterMs ?? (this.permanent ? undefined : 100);
177601
+ }
177602
+ }
177603
+ function isPermanentSynapseCode(code) {
177604
+ return code === "artifact_invalid" || code === "substitution_rejected" || code === "not_certified" || code === "probe_required" || code === "idempotency_conflict" || code === "schema_violation";
177605
+ }
177606
+ function asRecord(value) {
177607
+ return value !== null && typeof value === "object" ? value : null;
177608
+ }
177609
+ function responseBody(value) {
177610
+ const record2 = asRecord(value);
177611
+ const result = asRecord(record2?.result);
177612
+ return result ? { ...record2, ...result } : record2 ?? {};
177613
+ }
177614
+ function readRetryAfter(value) {
177615
+ const record2 = asRecord(value);
177616
+ const candidate = record2?.retry_after_ms ?? record2?.retryAfterMs;
177617
+ if (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0)
177618
+ return;
177619
+ return Math.ceil(candidate);
177620
+ }
177621
+ function readErrorCode(value) {
177622
+ const record2 = asRecord(value);
177623
+ if (typeof record2?.code === "string")
177624
+ return record2.code;
177625
+ if (value instanceof Error && "code" in value && typeof value.code === "string") {
177626
+ return value.code;
177627
+ }
177628
+ return;
177629
+ }
177630
+ function classifyError(value) {
177631
+ if (value instanceof SynapseEmbeddingError)
177632
+ return value;
177633
+ const code = readErrorCode(value) ?? (value instanceof Error ? value.name : "transport");
177634
+ const normalized = code.toLowerCase();
177635
+ let mapped = "transport";
177636
+ if (normalized.includes("queue_full"))
177637
+ mapped = "queue_full";
177638
+ else if (normalized.includes("model_loading"))
177639
+ mapped = "model_loading";
177640
+ else if (normalized.includes("timeout") || normalized.includes("deadline"))
177641
+ mapped = "timeout";
177642
+ else if (normalized.includes("artifact_invalid"))
177643
+ mapped = "artifact_invalid";
177644
+ else if (normalized.includes("substitution"))
177645
+ mapped = "substitution_rejected";
177646
+ else if (normalized.includes("not_certified"))
177647
+ mapped = "not_certified";
177648
+ else if (normalized.includes("probe_required"))
177649
+ mapped = "probe_required";
177650
+ else if (normalized.includes("idempotency_conflict"))
177651
+ mapped = "idempotency_conflict";
177652
+ else if (normalized.includes("schema"))
177653
+ mapped = "schema_violation";
177654
+ else if (normalized.includes("module_restarted") || normalized.includes("module restarted"))
177655
+ mapped = "module_restarted";
177656
+ const message = value instanceof Error ? value.message : String(value);
177657
+ return new SynapseEmbeddingError(mapped, message, {
177658
+ retryAfterMs: readRetryAfter(value) ?? (isPermanentSynapseCode(mapped) ? undefined : 100),
177659
+ cause: value
177660
+ });
177661
+ }
177662
+ function wait(ms) {
177663
+ return new Promise((resolve) => setTimeout(resolve, ms));
177664
+ }
177665
+ function sha256(value) {
177666
+ return createHash8("sha256").update(value).digest("hex");
177667
+ }
177668
+ function stableJson(value) {
177669
+ if (Array.isArray(value))
177670
+ return `[${value.map(stableJson).join(",")}]`;
177671
+ if (value && typeof value === "object") {
177672
+ return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => `${JSON.stringify(key)}:${stableJson(entry)}`).join(",")}}`;
177673
+ }
177674
+ return JSON.stringify(value);
177675
+ }
177676
+ function getSynapseLaneIdentity(model, fingerprint) {
177677
+ return `synapse:v1:${sha256(stableJson({ model, fingerprint }))}`;
177678
+ }
177679
+ function getSynapseBatchRequestKey(args) {
177680
+ return sha256(stableJson({
177681
+ op: "embed.batch",
177682
+ model: args.model,
177683
+ required_fingerprint: args.fingerprint,
177684
+ required_epoch: args.tableEpoch,
177685
+ allow_equivalent: false,
177686
+ accept_declared: false,
177687
+ ids: args.items.map((item) => item.id),
177688
+ content_sha256: args.items.map((item) => item.contentSha256)
177689
+ }));
177690
+ }
177691
+ function hashContent(text) {
177692
+ return sha256(text);
177693
+ }
177694
+ function extractCatalogEntries(value) {
177695
+ const body = responseBody(value);
177696
+ const raw = Array.isArray(body.models) ? body.models : Array.isArray(body.entries) ? body.entries : Array.isArray(value) ? value : [];
177697
+ const envelopeEpoch = typeof body.table_epoch === "number" && Number.isInteger(body.table_epoch) ? body.table_epoch : undefined;
177698
+ return raw.flatMap((entry) => {
177699
+ const record2 = asRecord(entry);
177700
+ if (!record2)
177701
+ return [];
177702
+ const model = typeof record2.model === "string" && record2.model.length > 0 ? record2.model : typeof record2.model_id === "string" ? record2.model_id : "";
177703
+ const fingerprint = typeof record2.fingerprint === "string" && record2.fingerprint.length > 0 ? record2.fingerprint : Array.isArray(record2.fingerprints) && typeof record2.fingerprints[0] === "string" ? record2.fingerprints[0] : "";
177704
+ const entryEpoch = record2.table_epoch ?? record2.tableEpoch;
177705
+ const tableEpoch = typeof entryEpoch === "number" && Number.isInteger(entryEpoch) ? entryEpoch : envelopeEpoch;
177706
+ const dims = record2.dims ?? record2.dimensions;
177707
+ if (model.length === 0 || fingerprint.length === 0 || typeof tableEpoch !== "number" || !Number.isInteger(tableEpoch)) {
177708
+ return [];
177709
+ }
177710
+ const recommendedBatch = record2.recommended_batch ?? record2.recommendedBatch;
177711
+ const state = typeof record2.state === "string" ? record2.state : undefined;
177712
+ return [
177713
+ {
177714
+ model,
177715
+ fingerprint,
177716
+ table_epoch: tableEpoch,
177717
+ ...typeof dims === "number" && Number.isInteger(dims) && dims > 0 ? { dims } : {},
177718
+ ...typeof recommendedBatch === "number" && recommendedBatch > 0 ? { recommended_batch: Math.floor(recommendedBatch) } : {},
177719
+ ...record2.provenance !== undefined ? { provenance: record2.provenance } : {},
177720
+ ...typeof record2.certified === "boolean" ? { certified: record2.certified } : {},
177721
+ ...typeof record2.status === "string" ? { status: record2.status } : state ? { status: state } : {}
177722
+ }
177723
+ ];
177724
+ });
177725
+ }
177726
+ function extractVector(value) {
177727
+ const body = responseBody(value);
177728
+ const fromVectors = Array.isArray(body.vectors) ? asRecord(body.vectors[0])?.vector : undefined;
177729
+ const raw = fromVectors ?? body.vector ?? body.embedding;
177730
+ if (!Array.isArray(raw) || raw.some((item) => typeof item !== "number" || !Number.isFinite(item))) {
177731
+ return null;
177732
+ }
177733
+ return { vector: Float32Array.from(raw), metadata: body };
177734
+ }
177735
+ function extractBatchItems(value) {
177736
+ const body = responseBody(value);
177737
+ const raw = Array.isArray(body.vectors) ? body.vectors : Array.isArray(body.items) ? body.items : Array.isArray(body.results) ? body.results : [];
177738
+ return raw.flatMap((item) => {
177739
+ const record2 = asRecord(item);
177740
+ return record2 ? [record2] : [];
177741
+ });
177742
+ }
177743
+ var sharedClient = null;
177744
+ var sharedClientFile = null;
177745
+ var sharedClientPromise = null;
177746
+ var factoryClients = new WeakMap;
177747
+ async function getSharedClient(options) {
177748
+ if (options.clientFactory) {
177749
+ let promise2 = factoryClients.get(options.clientFactory);
177750
+ if (!promise2) {
177751
+ promise2 = options.clientFactory();
177752
+ factoryClients.set(options.clientFactory, promise2);
177753
+ }
177754
+ return promise2;
177755
+ }
177756
+ if (sharedClient && sharedClientFile === options.connectionFile)
177757
+ return sharedClient;
177758
+ if (sharedClientPromise && sharedClientFile === options.connectionFile)
177759
+ return sharedClientPromise;
177760
+ sharedClientFile = options.connectionFile;
177761
+ sharedClientPromise = SubcClient.connect({ connectionFile: options.connectionFile }).then((client) => {
177762
+ sharedClient = client;
177763
+ return client;
177764
+ });
177765
+ return sharedClientPromise;
177766
+ }
177767
+
177768
+ class SynapseEmbeddingProvider {
177769
+ modelId;
177770
+ maxInputTokens = SYNAPSE_MAX_INPUT_TOKENS;
177771
+ metadata;
177772
+ options;
177773
+ client = null;
177774
+ initialized = false;
177775
+ initializing = null;
177776
+ permanentFailure = false;
177777
+ batchLimit = 16;
177778
+ constructor(options) {
177779
+ this.options = options;
177780
+ const model = options.model || SYNAPSE_DEFAULT_MODEL;
177781
+ const fingerprint = options.fingerprint ?? "";
177782
+ this.metadata = fingerprint && Number.isInteger(options.tableEpoch) && Number.isInteger(options.dims) && (options.dims ?? 0) > 0 ? {
177783
+ model,
177784
+ fingerprint,
177785
+ table_epoch: options.tableEpoch,
177786
+ dims: options.dims,
177787
+ ...options.recommendedBatch ? { recommended_batch: Math.max(1, Math.floor(options.recommendedBatch)) } : {},
177788
+ ...options.provenance !== undefined ? { provenance: options.provenance } : {},
177789
+ laneIdentity: getSynapseLaneIdentity(model, fingerprint)
177790
+ } : null;
177791
+ this.modelId = this.metadata?.laneIdentity ?? "synapse:v1:pending";
177792
+ this.batchLimit = this.metadata?.recommended_batch ?? 16;
177793
+ }
177794
+ static async discover(options) {
177795
+ const provider = new SynapseEmbeddingProvider(options);
177796
+ if (!await provider.initialize() || !provider.metadata) {
177797
+ throw new SynapseEmbeddingError("not_certified", "Synapse lane is not ready");
177798
+ }
177799
+ return provider.metadata;
177800
+ }
177801
+ async initialize() {
177802
+ if (this.initialized)
177803
+ return true;
177804
+ if (this.permanentFailure)
177805
+ return false;
177806
+ if (this.initializing)
177807
+ return this.initializing;
177808
+ this.initializing = (async () => {
177809
+ try {
177810
+ if (!this.options.clientFactory && !await connectionFileExists(this.options.connectionFile)) {
177811
+ throw new SynapseEmbeddingError("transport", `Synapse connection file is unavailable: ${this.options.connectionFile}`);
177812
+ }
177813
+ this.client = await getSharedClient(this.options);
177814
+ if (!this.metadata) {
177815
+ const discovered = await this.callWithRetry("models.list", {}, this.options.queryTimeoutMs ?? SYNAPSE_DEFAULT_QUERY_TIMEOUT_MS, false);
177816
+ const entries = extractCatalogEntries(discovered);
177817
+ const requested = this.options.model?.trim() || SYNAPSE_DEFAULT_MODEL;
177818
+ const entry = entries.find((candidate) => candidate.model === requested);
177819
+ if (!entry) {
177820
+ throw new SynapseEmbeddingError("artifact_invalid", `Synapse models.list did not return requested model ${requested}`);
177821
+ }
177822
+ if (entry.certified === false || entry.status === "not_certified") {
177823
+ throw new SynapseEmbeddingError("not_certified", `Synapse model ${entry.model} is not certified`);
177824
+ }
177825
+ const metadata = {
177826
+ ...entry,
177827
+ laneIdentity: getSynapseLaneIdentity(entry.model, entry.fingerprint)
177828
+ };
177829
+ this.metadata = metadata;
177830
+ this.modelId = metadata.laneIdentity;
177831
+ this.batchLimit = metadata.recommended_batch ?? this.batchLimit;
177832
+ }
177833
+ this.initialized = true;
177834
+ return true;
177835
+ } catch (error51) {
177836
+ const classified = classifyError(error51);
177837
+ if (classified.permanent) {
177838
+ this.permanentFailure = true;
177839
+ log(`[magic-context] Synapse lane disabled: ${classified.code}: ${classified.message}`);
177840
+ } else {
177841
+ log(`[magic-context] Synapse lane unavailable: ${classified.message}`);
177842
+ }
177843
+ this.initialized = false;
177844
+ return false;
177845
+ } finally {
177846
+ this.initializing = null;
177847
+ }
177848
+ })();
177849
+ return this.initializing;
177850
+ }
177851
+ async embed(text, signal) {
177852
+ if (!await this.initialize() || signal?.aborted || !this.metadata)
177853
+ return null;
177854
+ try {
177855
+ const value = await this.callWithRetry("embed.query", this.requestConstraints({
177856
+ text,
177857
+ deadline_ms: this.options.queryTimeoutMs ?? SYNAPSE_DEFAULT_QUERY_TIMEOUT_MS
177858
+ }), this.options.queryTimeoutMs ?? SYNAPSE_DEFAULT_QUERY_TIMEOUT_MS, true, signal);
177859
+ const extracted = extractVector(value);
177860
+ if (!extracted)
177861
+ throw new SynapseEmbeddingError("schema_violation", "Synapse query returned no vector");
177862
+ this.validateResponse(extracted.metadata, extracted.vector.length);
177863
+ return extracted.vector;
177864
+ } catch (error51) {
177865
+ this.logCallFailure(error51, "embed.query");
177866
+ return null;
177867
+ }
177868
+ }
177869
+ async embedBatch(texts, signal) {
177870
+ if (texts.length === 0)
177871
+ return [];
177872
+ const items = texts.map((text, index) => ({
177873
+ id: `item:${index}`,
177874
+ text,
177875
+ contentSha256: hashContent(text)
177876
+ }));
177877
+ const map2 = await this.embedItems(items, signal);
177878
+ return items.map((item) => map2.get(item.id) ?? null);
177879
+ }
177880
+ async embedItems(items, signal) {
177881
+ const output = new Map;
177882
+ if (items.length === 0 || !await this.initialize() || !this.metadata || signal?.aborted) {
177883
+ return output;
177884
+ }
177885
+ for (let start = 0;start < items.length; start += this.batchLimit) {
177886
+ if (signal?.aborted || this.permanentFailure)
177887
+ break;
177888
+ const page = items.slice(start, start + this.batchLimit);
177889
+ try {
177890
+ const requestKey = this.requestKey(page);
177891
+ let body = {};
177892
+ let restarted = false;
177893
+ for (;; ) {
177894
+ try {
177895
+ body = await this.callWithRetry("embed.batch", this.batchRequest(page, requestKey), this.options.batchTimeoutMs ?? SYNAPSE_DEFAULT_BATCH_TIMEOUT_MS, true, signal);
177896
+ const first = responseBody(body);
177897
+ const jobId = typeof first.job_id === "string" ? first.job_id : null;
177898
+ if (jobId)
177899
+ body = await this.pollBatch(jobId, requestKey, signal);
177900
+ break;
177901
+ } catch (error51) {
177902
+ const classified = classifyError(error51);
177903
+ if (classified.code !== "module_restarted" || restarted)
177904
+ throw classified;
177905
+ restarted = true;
177906
+ }
177907
+ }
177908
+ const batchEnvelope = responseBody(body);
177909
+ for (const item of extractBatchItems(body)) {
177910
+ const id = typeof item.id === "string" ? item.id : "";
177911
+ const vector = item.vector ?? item.embedding;
177912
+ if (!id || !Array.isArray(vector)) {
177913
+ throw new SynapseEmbeddingError("schema_violation", "Synapse batch item is malformed");
177914
+ }
177915
+ const expected = page.find((candidate) => candidate.id === id);
177916
+ if (!expected) {
177917
+ throw new SynapseEmbeddingError("schema_violation", `Synapse returned unknown item ${id}`);
177918
+ }
177919
+ if (typeof item.content_sha256 === "string" && item.content_sha256 !== expected.contentSha256) {
177920
+ throw new SynapseEmbeddingError("artifact_invalid", `Synapse content hash mismatch for item ${id}`);
177921
+ }
177922
+ const vectorArray = Float32Array.from(vector);
177923
+ this.validateResponse({ ...batchEnvelope, ...item }, vectorArray.length);
177924
+ output.set(id, vectorArray);
177925
+ }
177926
+ } catch (error51) {
177927
+ const classified = classifyError(error51);
177928
+ this.logCallFailure(classified, "embed.batch");
177929
+ if (classified.code === "idempotency_conflict")
177930
+ throw classified;
177931
+ if (classified.permanent) {
177932
+ this.permanentFailure = true;
177933
+ this.initialized = false;
177934
+ break;
177935
+ }
177936
+ }
177937
+ }
177938
+ return output;
177939
+ }
177940
+ async dispose() {
177941
+ this.initialized = false;
177942
+ this.client = null;
177943
+ }
177944
+ isLoaded() {
177945
+ return this.initialized;
177946
+ }
177947
+ requestConstraints(extra) {
177948
+ const metadata = this.metadata;
177949
+ if (!metadata)
177950
+ return extra;
177951
+ return {
177952
+ ...extra,
177953
+ model: metadata.model,
177954
+ required_fingerprint: metadata.fingerprint,
177955
+ required_epoch: metadata.table_epoch,
177956
+ allow_equivalent: false,
177957
+ accept_declared: false
177958
+ };
177959
+ }
177960
+ batchRequest(items, requestKey) {
177961
+ return this.requestConstraints({
177962
+ items: items.map((item) => ({
177963
+ id: item.id,
177964
+ text: item.text,
177965
+ content_sha256: item.contentSha256
177966
+ })),
177967
+ request_key: requestKey
177968
+ });
177969
+ }
177970
+ requestKey(items) {
177971
+ if (!this.metadata)
177972
+ throw new SynapseEmbeddingError("transport", "Synapse metadata is unavailable");
177973
+ return getSynapseBatchRequestKey({
177974
+ model: this.metadata.model,
177975
+ fingerprint: this.metadata.fingerprint,
177976
+ tableEpoch: this.metadata.table_epoch,
177977
+ items
177978
+ });
177979
+ }
177980
+ async pollBatch(jobId, requestKey, signal) {
177981
+ let cursor = null;
177982
+ const allItems = [];
177983
+ for (;; ) {
177984
+ if (signal?.aborted)
177985
+ return {};
177986
+ const body = await this.callWithRetry("embed.result", this.requestConstraints({
177987
+ job_id: jobId,
177988
+ cursor,
177989
+ request_key: requestKey
177990
+ }), this.options.batchTimeoutMs ?? SYNAPSE_DEFAULT_BATCH_TIMEOUT_MS, true, signal);
177991
+ const parsed = responseBody(body);
177992
+ const items = extractBatchItems(body);
177993
+ allItems.push(...items);
177994
+ const nextCursor = parsed.next_cursor ?? parsed.cursor;
177995
+ const done = parsed.done === true || parsed.complete === true || nextCursor === undefined || nextCursor === null;
177996
+ if (done)
177997
+ return { ...parsed, items: allItems };
177998
+ cursor = nextCursor;
177999
+ }
178000
+ }
178001
+ async callWithRetry(method, params, timeoutMs, retryEmbeddings, signal) {
178002
+ let attempt = 0;
178003
+ for (;; ) {
178004
+ if (signal?.aborted)
178005
+ throw new SynapseEmbeddingError("transport", "Synapse request aborted");
178006
+ try {
178007
+ if (!this.client)
178008
+ throw new SynapseEmbeddingError("transport", "Synapse client is unavailable");
178009
+ return await this.client.call(this.options.moduleId ?? "synapse", method, params, {
178010
+ timeoutMs,
178011
+ targetKind: "management_surface",
178012
+ identity: {
178013
+ project_root: this.options.projectRoot,
178014
+ harness: getHarness(),
178015
+ session: this.options.session
178016
+ }
178017
+ });
178018
+ } catch (error51) {
178019
+ const classified = classifyError(error51);
178020
+ if (classified.code === "idempotency_conflict")
178021
+ throw classified;
178022
+ const outcomeUnknown = error51 instanceof SubcCallError && error51.kind === "outcome_unknown";
178023
+ const retryable = !classified.permanent && (retryEmbeddings || !outcomeUnknown);
178024
+ if (!retryable || attempt >= 3)
178025
+ throw classified;
178026
+ const delay = classified.retryAfterMs ?? Math.min(2000, 100 * 2 ** attempt);
178027
+ attempt += 1;
178028
+ await wait(delay);
178029
+ }
178030
+ }
178031
+ }
178032
+ validateResponse(body, dims) {
178033
+ const metadata = this.metadata;
178034
+ if (!metadata) {
178035
+ throw new SynapseEmbeddingError("artifact_invalid", "Synapse lane metadata missing");
178036
+ }
178037
+ if (metadata.dims === undefined) {
178038
+ const envelopeDims = body.dims;
178039
+ if (typeof envelopeDims === "number" && envelopeDims !== dims) {
178040
+ throw new SynapseEmbeddingError("artifact_invalid", `Synapse envelope declares ${envelopeDims} dimensions but the vector has ${dims}`);
178041
+ }
178042
+ metadata.dims = dims;
178043
+ }
178044
+ if (dims !== metadata.dims) {
178045
+ throw new SynapseEmbeddingError("artifact_invalid", `Synapse returned ${dims} dimensions, expected ${metadata.dims}`);
178046
+ }
178047
+ const fingerprint = body.fingerprint ?? body.served_fingerprint;
178048
+ if (typeof fingerprint !== "string") {
178049
+ throw new SynapseEmbeddingError("artifact_invalid", "Synapse response omitted the served fingerprint");
178050
+ }
178051
+ if (fingerprint !== metadata.fingerprint) {
178052
+ throw new SynapseEmbeddingError("substitution_rejected", `Synapse fingerprint changed from ${metadata.fingerprint} to ${fingerprint}`);
178053
+ }
178054
+ const epoch = body.table_epoch ?? body.tableEpoch;
178055
+ if (typeof epoch !== "number") {
178056
+ throw new SynapseEmbeddingError("artifact_invalid", "Synapse response omitted the served table epoch");
178057
+ }
178058
+ if (epoch !== metadata.table_epoch) {
178059
+ throw new SynapseEmbeddingError("substitution_rejected", `Synapse table epoch changed from ${metadata.table_epoch} to ${epoch}`);
178060
+ }
178061
+ }
178062
+ logCallFailure(error51, operation) {
178063
+ const classified = classifyError(error51);
178064
+ if (classified.permanent)
178065
+ this.permanentFailure = true;
178066
+ const suffix = classified.retryAfterMs === undefined ? "" : ` retry_after_ms=${classified.retryAfterMs}`;
178067
+ log(`[magic-context] Synapse ${operation} failed: ${classified.code}${suffix}: ${classified.message}`);
178068
+ }
178069
+ }
178070
+
175087
178071
  // ../plugin/src/features/magic-context/memory/normalize-hash.ts
175088
- import { createHash as createHash7 } from "node:crypto";
178072
+ import { createHash as createHash9 } from "node:crypto";
175089
178073
  function normalizeMemoryContent(content) {
175090
178074
  return content.toLowerCase().replace(/\s+/g, " ").trim();
175091
178075
  }
175092
178076
  function computeNormalizedHash(content) {
175093
178077
  const normalized = normalizeMemoryContent(content);
175094
- return createHash7("md5").update(normalized).digest("hex");
178078
+ return createHash9("md5").update(normalized).digest("hex");
175095
178079
  }
175096
178080
 
175097
178081
  // ../plugin/src/features/magic-context/memory/embedding-identity.ts
@@ -175102,6 +178086,15 @@ function getEmbeddingProviderIdentity(config2) {
175102
178086
  if (config2.provider === "off") {
175103
178087
  return "embedding-provider:off";
175104
178088
  }
178089
+ if (config2.provider === "synapse") {
178090
+ const resolved = config2;
178091
+ if (!resolved.model || !resolved.synapse_fingerprint)
178092
+ return "synapse:v1:pending";
178093
+ return getSynapseLaneIdentity(resolved.model, resolved.synapse_fingerprint);
178094
+ }
178095
+ if (config2.provider !== "local" && config2.provider !== "openai-compatible") {
178096
+ throw new Error("Unknown embedding provider");
178097
+ }
175105
178098
  const truncate = config2.provider === "openai-compatible" ? config2.truncate?.trim() : undefined;
175106
178099
  const identityInput = config2.provider === "openai-compatible" ? {
175107
178100
  provider: "openai-compatible",
@@ -175891,7 +178884,7 @@ function getMemoryEmbedCoverage(db, projectPath, modelId) {
175891
178884
  }
175892
178885
 
175893
178886
  // ../plugin/src/features/magic-context/project-embedding-registry.ts
175894
- import { createHash as createHash8, randomUUID as randomUUID2 } from "node:crypto";
178887
+ import { createHash as createHash10, randomUUID as randomUUID2 } from "node:crypto";
175895
178888
  init_logger();
175896
178889
 
175897
178890
  // ../plugin/src/features/magic-context/git-commits/storage-git-commit-embeddings.ts
@@ -176282,6 +179275,12 @@ var EMBED_SLICE_RETRY_BASE_MS = 250;
176282
179275
  var EMBED_SLOW_FAILURE_NO_RETRY_MS = 1e4;
176283
179276
  var MAX_CONSECUTIVE_FAILED_BATCHES = 3;
176284
179277
  var projectRegistrations = new Map;
179278
+ var shadowRegistrations = new Map;
179279
+ var shadowQueue = [];
179280
+ var shadowWorker = null;
179281
+ var SHADOW_MAX_ITEMS_PER_TICK = 64;
179282
+ var SHADOW_MAX_BYTES_PER_TICK = 512 * 1024;
179283
+ var SHADOW_MAX_WALL_CLOCK_MS = 2000;
176285
179284
  var loadUnembeddedMemoriesStatements = new WeakMap;
176286
179285
  var upsertActiveIdentityStatements = new WeakMap;
176287
179286
  var backfillActiveIdentityStatements = new Map;
@@ -176293,6 +179292,35 @@ function markProjectLoadUntrusted(projectIdentity) {
176293
179292
  untrustedLoadProjects.add(projectIdentity);
176294
179293
  }
176295
179294
  var testProviderFactory = null;
179295
+ function synapseConfigFields(config2) {
179296
+ const raw = config2;
179297
+ return {
179298
+ ...typeof raw.model === "string" ? { model: raw.model } : {},
179299
+ ...typeof raw.synapse_fingerprint === "string" ? { fingerprint: raw.synapse_fingerprint } : {},
179300
+ ...typeof raw.synapse_table_epoch === "number" ? { tableEpoch: raw.synapse_table_epoch } : {},
179301
+ ...typeof raw.synapse_dims === "number" ? { dims: raw.synapse_dims } : {},
179302
+ ...raw.synapse_provenance !== undefined ? { provenance: raw.synapse_provenance } : {}
179303
+ };
179304
+ }
179305
+ function persistPrimaryDescriptor(db, registration) {
179306
+ const descriptorTable = db.prepare("SELECT 1 AS present FROM sqlite_master WHERE type = 'table' AND name = 'embedding_registrations'").get();
179307
+ if (!descriptorTable)
179308
+ return;
179309
+ const fields = synapseConfigFields(registration.config);
179310
+ db.prepare(`INSERT INTO embedding_registrations
179311
+ (project_path, provider_identity, model_id, chunk_model_id, fingerprint, table_epoch, dims, provenance_json, generation, updated_at)
179312
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
179313
+ ON CONFLICT(project_path) DO UPDATE SET
179314
+ provider_identity = excluded.provider_identity,
179315
+ model_id = excluded.model_id,
179316
+ chunk_model_id = excluded.chunk_model_id,
179317
+ fingerprint = excluded.fingerprint,
179318
+ table_epoch = excluded.table_epoch,
179319
+ dims = excluded.dims,
179320
+ provenance_json = excluded.provenance_json,
179321
+ generation = excluded.generation,
179322
+ 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());
179323
+ }
176296
179324
  function resolveEmbeddingConfig(config2) {
176297
179325
  if (!config2 || config2.provider === "local") {
176298
179326
  return {
@@ -176321,9 +179349,26 @@ function resolveEmbeddingConfig(config2) {
176321
179349
  } : {}
176322
179350
  };
176323
179351
  }
176324
- return { provider: "off" };
179352
+ if (config2.provider === "off") {
179353
+ return { provider: "off" };
179354
+ }
179355
+ if (config2.provider === "synapse") {
179356
+ const synapse = config2;
179357
+ return {
179358
+ provider: "synapse",
179359
+ model: synapse.model?.trim() || "gte-modernbert-base-f16",
179360
+ max_input_tokens: SYNAPSE_MAX_INPUT_TOKENS,
179361
+ ...synapse.synapse_connection_file ? { synapse_connection_file: synapse.synapse_connection_file } : {},
179362
+ ...synapse.synapse_fingerprint ? { synapse_fingerprint: synapse.synapse_fingerprint } : {},
179363
+ ...typeof synapse.synapse_table_epoch === "number" ? { synapse_table_epoch: synapse.synapse_table_epoch } : {},
179364
+ ...typeof synapse.synapse_dims === "number" ? { synapse_dims: synapse.synapse_dims } : {},
179365
+ ...typeof synapse.synapse_recommended_batch === "number" ? { synapse_recommended_batch: synapse.synapse_recommended_batch } : {},
179366
+ ...synapse.synapse_provenance !== undefined ? { synapse_provenance: synapse.synapse_provenance } : {}
179367
+ };
179368
+ }
179369
+ throw new Error("Unknown embedding provider");
176325
179370
  }
176326
- function createProvider(config2) {
179371
+ function createProvider(config2, context) {
176327
179372
  if (testProviderFactory) {
176328
179373
  return testProviderFactory(config2);
176329
179374
  }
@@ -176341,7 +179386,24 @@ function createProvider(config2) {
176341
179386
  maxInputTokens: config2.max_input_tokens
176342
179387
  });
176343
179388
  }
176344
- return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
179389
+ if (config2.provider === "local") {
179390
+ return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
179391
+ }
179392
+ if (config2.provider === "synapse") {
179393
+ const synapse = config2;
179394
+ return new SynapseEmbeddingProvider({
179395
+ connectionFile: synapse.synapse_connection_file ?? "",
179396
+ projectRoot: context?.projectRoot ?? "",
179397
+ session: context?.session ?? "embedding",
179398
+ model: synapse.model,
179399
+ fingerprint: synapse.synapse_fingerprint,
179400
+ tableEpoch: synapse.synapse_table_epoch,
179401
+ dims: synapse.synapse_dims,
179402
+ recommendedBatch: synapse.synapse_recommended_batch,
179403
+ provenance: synapse.synapse_provenance
179404
+ });
179405
+ }
179406
+ throw new Error("Unknown embedding provider");
176345
179407
  }
176346
179408
  function stableStringify2(value) {
176347
179409
  if (Array.isArray(value)) {
@@ -176354,7 +179416,10 @@ function stableStringify2(value) {
176354
179416
  return JSON.stringify(value);
176355
179417
  }
176356
179418
  function sha256Prefix(value, length = 16) {
176357
- return createHash8("sha256").update(value).digest("hex").slice(0, length);
179419
+ return createHash10("sha256").update(value).digest("hex").slice(0, length);
179420
+ }
179421
+ function contentSha256(value) {
179422
+ return createHash10("sha256").update(value).digest("hex");
176358
179423
  }
176359
179424
  function getRuntimeFingerprint(config2) {
176360
179425
  if (config2.provider === "off") {
@@ -176381,6 +179446,7 @@ function snapshotFor(registration) {
176381
179446
  const providerIsOn = registration.providerIdentity !== OFF_PROVIDER_IDENTITY;
176382
179447
  const enabled = !registration.observationMode && providerIsOn && registration.features.memoryEnabled;
176383
179448
  const gitCommitEnabled = !registration.observationMode && providerIsOn && registration.features.gitCommitEnabled;
179449
+ const configuredModel = "model" in registration.config && typeof registration.config.model === "string" ? registration.config.model.trim() : "";
176384
179450
  return {
176385
179451
  projectIdentity: registration.projectIdentity,
176386
179452
  sourceDirectory: registration.sourceDirectory,
@@ -176392,7 +179458,7 @@ function snapshotFor(registration) {
176392
179458
  gitCommitEnabled,
176393
179459
  modelId: registration.observationMode || !providerIsOn ? "off" : registration.modelId,
176394
179460
  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,
179461
+ model: registration.observationMode || !providerIsOn ? "off" : configuredModel ? configuredModel : registration.modelId,
176396
179462
  provider: registration.observationMode || !providerIsOn ? "off" : registration.config.provider ?? "local"
176397
179463
  };
176398
179464
  }
@@ -176499,9 +179565,9 @@ function getDeleteActiveIdentityStatement(db) {
176499
179565
  }
176500
179566
  return stmt;
176501
179567
  }
176502
- function staleModelsForScope(db, projectIdentity, scope, currentModelId, cutoff) {
179568
+ function staleModelsForScope(db, projectIdentity, scope, currentModelId, cutoff, protectedModelIds = new Set([currentModelId])) {
176503
179569
  const rows = getStaleIdentityStatement(db, scope).all(projectIdentity, scope, currentModelId, cutoff);
176504
- return rows.map((row) => row.modelId).filter((modelId) => typeof modelId === "string");
179570
+ return rows.map((row) => row.modelId).filter((modelId) => typeof modelId === "string" && !protectedModelIds.has(modelId));
176505
179571
  }
176506
179572
  function deleteStaleEmbeddingBatch(db, scope, projectIdentity, modelId, limit) {
176507
179573
  if (scope === "memory") {
@@ -176566,6 +179632,12 @@ function sweepStaleEmbeddingIdentitiesForProject(db, projectIdentity, now = Date
176566
179632
  return result;
176567
179633
  const cutoff = now - EMBEDDING_IDENTITY_GC_GRACE_MS;
176568
179634
  const deleteTracking = getDeleteActiveIdentityStatement(db);
179635
+ const shadow = shadowRegistrations.get(projectIdentity);
179636
+ const protectedModels = {
179637
+ memory: new Set([snapshot.modelId, ...shadow ? [shadow.modelId] : []]),
179638
+ commit: new Set([snapshot.modelId, ...shadow ? [shadow.modelId] : []]),
179639
+ chunk: new Set([snapshot.chunkModelId, ...shadow ? [shadow.chunkModelId] : []])
179640
+ };
176569
179641
  const scopes = [
176570
179642
  {
176571
179643
  scope: "memory",
@@ -176589,7 +179661,7 @@ function sweepStaleEmbeddingIdentitiesForProject(db, projectIdentity, now = Date
176589
179661
  for (const { scope, enabled, currentModelId } of scopes) {
176590
179662
  if (!enabled || remainingBudget === 0)
176591
179663
  continue;
176592
- for (const modelId of staleModelsForScope(db, projectIdentity, scope, currentModelId, cutoff)) {
179664
+ for (const modelId of staleModelsForScope(db, projectIdentity, scope, currentModelId, cutoff, protectedModels[scope])) {
176593
179665
  if (remainingBudget === 0)
176594
179666
  break;
176595
179667
  const deleted = deleteStaleEmbeddingBatch(db, scope, projectIdentity, modelId, remainingBudget);
@@ -176643,11 +179715,206 @@ function registerProjectEmbedding(db, projectIdentity, config2, features, source
176643
179715
  observationMode: false
176644
179716
  };
176645
179717
  projectRegistrations.set(projectIdentity, registration);
179718
+ persistPrimaryDescriptor(db, registration);
176646
179719
  if (!canReuseProvider) {
176647
179720
  disposeProvider(prior?.provider ?? null);
176648
179721
  }
176649
179722
  return snapshotFor(registration);
176650
179723
  }
179724
+ function startShadowWorker() {
179725
+ if (shadowWorker)
179726
+ return;
179727
+ shadowWorker = runShadowWorker().finally(() => {
179728
+ shadowWorker = null;
179729
+ if (shadowQueue.length > 0)
179730
+ startShadowWorker();
179731
+ });
179732
+ }
179733
+ function getShadowEmbeddingMeasurementCohort(projectIdentity) {
179734
+ const registration = shadowRegistrations.get(projectIdentity);
179735
+ if (!registration)
179736
+ return null;
179737
+ const fields = synapseConfigFields(registration.config);
179738
+ return {
179739
+ modelId: registration.modelId,
179740
+ chunkModelId: registration.chunkModelId,
179741
+ fingerprint: fields.fingerprint ?? "",
179742
+ epoch: fields.tableEpoch ?? 0,
179743
+ dims: fields.dims ?? 0
179744
+ };
179745
+ }
179746
+ function getPrimaryEmbeddingMeasurementCohort(projectIdentity) {
179747
+ const registration = projectRegistrations.get(projectIdentity);
179748
+ if (!registration)
179749
+ return null;
179750
+ const fields = synapseConfigFields(registration.config);
179751
+ return {
179752
+ modelId: registration.modelId,
179753
+ chunkModelId: registration.chunkModelId,
179754
+ fingerprint: fields.fingerprint ?? "",
179755
+ epoch: fields.tableEpoch ?? 0,
179756
+ dims: fields.dims ?? 0
179757
+ };
179758
+ }
179759
+ async function embedShadowTextForProject(projectIdentity, text, signal) {
179760
+ const registration = shadowRegistrations.get(projectIdentity);
179761
+ if (!registration)
179762
+ return null;
179763
+ try {
179764
+ return await registration.provider.embed(text, signal, "query");
179765
+ } catch (error51) {
179766
+ log("[magic-context] Synapse shadow query failed:", error51);
179767
+ return null;
179768
+ }
179769
+ }
179770
+ function enqueueShadowEmbeddingItems(projectIdentity, scope, ids) {
179771
+ if (ids.length === 0 || !shadowRegistrations.has(projectIdentity))
179772
+ return;
179773
+ shadowQueue.push({ projectIdentity, scope, ids: [...ids] });
179774
+ startShadowWorker();
179775
+ }
179776
+ async function embedShadowItems(registration, items, db, scope) {
179777
+ const raw = registration.config;
179778
+ const fingerprint = typeof raw.synapse_fingerprint === "string" ? raw.synapse_fingerprint : "";
179779
+ const tableEpoch = typeof raw.synapse_table_epoch === "number" ? raw.synapse_table_epoch : 0;
179780
+ const requestKey = getSynapseBatchRequestKey({
179781
+ model: typeof raw.model === "string" ? raw.model : SYNAPSE_DEFAULT_MODEL,
179782
+ fingerprint,
179783
+ tableEpoch,
179784
+ items
179785
+ });
179786
+ beginSynapseBatchLedger(db, {
179787
+ sessionId: `shadow:${registration.projectIdentity}`,
179788
+ projectPath: registration.projectIdentity,
179789
+ scope,
179790
+ manifest: items.map(({ id, contentSha256: contentSha2562 }) => ({ id, contentSha256: contentSha2562 })),
179791
+ requestKey
179792
+ });
179793
+ try {
179794
+ if (registration.provider.embedItems) {
179795
+ const vectors2 = await registration.provider.embedItems(items);
179796
+ finishSynapseBatchLedger(db, `shadow:${registration.projectIdentity}`, requestKey, vectors2.size === items.length ? "complete" : "partial");
179797
+ return vectors2;
179798
+ }
179799
+ const positional = await registration.provider.embedBatch(items.map((item) => item.text));
179800
+ const vectors = new Map(items.flatMap((item, index) => {
179801
+ const vector = positional[index];
179802
+ return vector ? [[item.id, vector]] : [];
179803
+ }));
179804
+ finishSynapseBatchLedger(db, `shadow:${registration.projectIdentity}`, requestKey, vectors.size === items.length ? "complete" : "partial");
179805
+ return vectors;
179806
+ } catch (error51) {
179807
+ finishSynapseBatchLedger(db, `shadow:${registration.projectIdentity}`, requestKey, "failed");
179808
+ throw error51;
179809
+ }
179810
+ }
179811
+ async function processShadowQueueItem(item) {
179812
+ const registration = shadowRegistrations.get(item.projectIdentity);
179813
+ if (!registration)
179814
+ return;
179815
+ const boundedIds = item.ids.slice(0, SHADOW_MAX_ITEMS_PER_TICK);
179816
+ if (item.scope === "memory") {
179817
+ const db2 = dbForShadowQueue.get(item.projectIdentity);
179818
+ if (!db2)
179819
+ return;
179820
+ const placeholders4 = boundedIds.map(() => "?").join(",");
179821
+ const rows = db2.prepare(`SELECT id, content, normalized_hash FROM memories
179822
+ WHERE project_path = ? AND id IN (${placeholders4}) AND status = 'active'`).all(item.projectIdentity, ...boundedIds.map((id) => Number(id)));
179823
+ const vectors2 = await embedShadowItems(registration, rows.map((row) => ({
179824
+ id: `memory:${row.id}`,
179825
+ text: row.content,
179826
+ contentSha256: contentSha256(row.content)
179827
+ })), db2, "memory");
179828
+ db2.transaction(() => {
179829
+ for (const row of rows) {
179830
+ const vector = vectors2.get(`memory:${row.id}`);
179831
+ if (vector)
179832
+ saveEmbeddingIfHashMatches(db2, row.id, vector, registration.modelId, row.normalized_hash);
179833
+ }
179834
+ })();
179835
+ return;
179836
+ }
179837
+ if (item.scope === "commit") {
179838
+ const db2 = dbForShadowQueue.get(item.projectIdentity);
179839
+ if (!db2)
179840
+ return;
179841
+ const placeholders4 = boundedIds.map(() => "?").join(",");
179842
+ const rows = db2.prepare(`SELECT sha, message FROM git_commits WHERE project_path = ? AND sha IN (${placeholders4})`).all(item.projectIdentity, ...boundedIds);
179843
+ const vectors2 = await embedShadowItems(registration, rows.map((row) => ({
179844
+ id: `commit:${row.sha}`,
179845
+ text: row.message,
179846
+ contentSha256: contentSha256(row.message)
179847
+ })), db2, "commit");
179848
+ db2.transaction(() => {
179849
+ for (const row of rows) {
179850
+ const vector = vectors2.get(`commit:${row.sha}`);
179851
+ if (vector)
179852
+ saveCommitEmbedding(db2, row.sha, vector, registration.modelId);
179853
+ }
179854
+ })();
179855
+ return;
179856
+ }
179857
+ const db = dbForShadowQueue.get(item.projectIdentity);
179858
+ if (!db)
179859
+ return;
179860
+ const placeholders3 = boundedIds.map(() => "?").join(",");
179861
+ const candidates = db.prepare(`SELECT id, session_id, start_message, end_message
179862
+ FROM compartments WHERE id IN (${placeholders3})`).all(...boundedIds.map((id) => Number(id)));
179863
+ const prepared = candidates.flatMap((candidate) => {
179864
+ const text = buildCanonicalChunkTextFromFts(db, candidate.session_id, candidate.start_message, candidate.end_message) || buildCompartmentSummaryFallbackText(db, candidate.id);
179865
+ if (!text)
179866
+ return [];
179867
+ const windows = chunkCanonicalText(text, candidate.start_message, candidate.end_message, SYNAPSE_MAX_INPUT_TOKENS);
179868
+ return windows.length > 0 ? [{ candidate, windows }] : [];
179869
+ });
179870
+ const items = prepared.flatMap((item2) => item2.windows.map((window) => ({
179871
+ id: `chunk:${item2.candidate.id}:${window.windowIndex}`,
179872
+ text: window.text,
179873
+ contentSha256: contentSha256(window.text)
179874
+ })));
179875
+ const vectors = await embedShadowItems(registration, items, db, "chunk");
179876
+ for (const item2 of prepared) {
179877
+ const rows = item2.windows.flatMap((window) => {
179878
+ const vector = vectors.get(`chunk:${item2.candidate.id}:${window.windowIndex}`);
179879
+ return vector ? [
179880
+ {
179881
+ compartmentId: item2.candidate.id,
179882
+ sessionId: item2.candidate.session_id,
179883
+ projectPath: registration.projectIdentity,
179884
+ window,
179885
+ modelId: registration.chunkModelId,
179886
+ vector
179887
+ }
179888
+ ] : [];
179889
+ });
179890
+ if (rows.length === item2.windows.length)
179891
+ replaceCompartmentChunkEmbeddings(db, rows);
179892
+ }
179893
+ }
179894
+ var dbForShadowQueue = new Map;
179895
+ async function runShadowWorker() {
179896
+ const startedAt = Date.now();
179897
+ let processed = 0;
179898
+ let processedBytes = 0;
179899
+ while (shadowQueue.length > 0 && processed < SHADOW_MAX_ITEMS_PER_TICK && Date.now() - startedAt < SHADOW_MAX_WALL_CLOCK_MS) {
179900
+ const item = shadowQueue.shift();
179901
+ if (!item)
179902
+ break;
179903
+ const itemBytes = item.ids.reduce((total, id) => total + id.length, 0);
179904
+ if (processed > 0 && processedBytes + itemBytes > SHADOW_MAX_BYTES_PER_TICK) {
179905
+ shadowQueue.unshift(item);
179906
+ break;
179907
+ }
179908
+ try {
179909
+ await processShadowQueueItem(item);
179910
+ } catch (error51) {
179911
+ log("[magic-context] Synapse shadow write failed:", error51);
179912
+ }
179913
+ processed += item.ids.length;
179914
+ processedBytes += itemBytes;
179915
+ await new Promise((resolve) => setTimeout(resolve, 0));
179916
+ }
179917
+ }
176651
179918
  function registerProjectInObservationMode(db, projectIdentity, sourceDirectory, failedConfig, failureSummary) {
176652
179919
  const prior = projectRegistrations.get(projectIdentity);
176653
179920
  const runtimeFingerprint = `observation:${sha256Prefix(failureSummary)}`;
@@ -176689,7 +179956,10 @@ function getOrCreateProjectProvider(registration) {
176689
179956
  if (registration.provider) {
176690
179957
  return registration.provider;
176691
179958
  }
176692
- const provider = createProvider(registration.config);
179959
+ const provider = createProvider(registration.config, {
179960
+ projectRoot: registration.sourceDirectory,
179961
+ session: `project:${registration.projectIdentity}`
179962
+ });
176693
179963
  registration.provider = provider;
176694
179964
  return provider;
176695
179965
  }
@@ -176709,7 +179979,7 @@ async function embedTextForProject(projectIdentity, text, signal, purpose = "pas
176709
179979
  if (!current || current.generation !== generation || current.runtimeFingerprint !== registration.runtimeFingerprint) {
176710
179980
  return null;
176711
179981
  }
176712
- return { vector, modelId, generation };
179982
+ return { vector, modelId, chunkModelId: registration.chunkModelId, generation };
176713
179983
  }
176714
179984
  async function embedBatchForProject(projectIdentity, texts, signal, purpose = "passage") {
176715
179985
  if (texts.length === 0) {
@@ -176734,31 +180004,81 @@ async function embedBatchForProject(projectIdentity, texts, signal, purpose = "p
176734
180004
  }
176735
180005
  return { vectors, modelId, generation };
176736
180006
  }
176737
- async function embedTextsWindowBounded(projectIdentity, texts, signal) {
176738
- if (texts.length <= MAX_WINDOWS_PER_EMBED_CALL) {
176739
- return embedBatchForProject(projectIdentity, texts, signal);
180007
+ async function embedItemsForProject(projectIdentity, items, signal, db, sessionId = projectIdentity) {
180008
+ const registration = projectRegistrations.get(projectIdentity);
180009
+ if (!registration || registration.observationMode || items.length === 0)
180010
+ return null;
180011
+ const generation = registration.generation;
180012
+ const modelId = registration.modelId;
180013
+ const runtimeFingerprint = registration.runtimeFingerprint;
180014
+ const provider = getOrCreateProjectProvider(registration);
180015
+ if (!provider)
180016
+ return null;
180017
+ const rawConfig = registration.config;
180018
+ const fingerprint = typeof rawConfig.synapse_fingerprint === "string" ? rawConfig.synapse_fingerprint : "";
180019
+ const tableEpoch = typeof rawConfig.synapse_table_epoch === "number" ? rawConfig.synapse_table_epoch : undefined;
180020
+ const isSynapse = registration.providerIdentity.startsWith("synapse:v1:") && fingerprint && tableEpoch !== undefined;
180021
+ const ledgerKey = isSynapse ? getSynapseBatchRequestKey({
180022
+ model: typeof rawConfig.model === "string" ? rawConfig.model : registration.modelId,
180023
+ fingerprint,
180024
+ tableEpoch,
180025
+ items
180026
+ }) : null;
180027
+ if (db && ledgerKey) {
180028
+ beginSynapseBatchLedger(db, {
180029
+ sessionId,
180030
+ projectPath: projectIdentity,
180031
+ scope: items[0].id.split(":", 1)[0],
180032
+ manifest: items.map(({ id, contentSha256: contentSha2562 }) => ({ id, contentSha256: contentSha2562 })),
180033
+ requestKey: ledgerKey
180034
+ });
180035
+ }
180036
+ let vectors;
180037
+ try {
180038
+ if (provider.embedItems) {
180039
+ vectors = await provider.embedItems(items, signal);
180040
+ } else {
180041
+ const positional = await provider.embedBatch(items.map((item) => item.text), signal, "passage");
180042
+ vectors = new Map(items.flatMap((item, index) => {
180043
+ const vector = positional[index];
180044
+ return vector ? [[item.id, vector]] : [];
180045
+ }));
180046
+ }
180047
+ } catch (error51) {
180048
+ if (db && ledgerKey)
180049
+ finishSynapseBatchLedger(db, sessionId, ledgerKey, "failed");
180050
+ throw error51;
176740
180051
  }
176741
- const vectors = [];
180052
+ if (db && ledgerKey) {
180053
+ finishSynapseBatchLedger(db, sessionId, ledgerKey, vectors.size === items.length ? "complete" : "partial");
180054
+ }
180055
+ const current = projectRegistrations.get(projectIdentity);
180056
+ if (!current || current.generation !== generation || current.runtimeFingerprint !== runtimeFingerprint) {
180057
+ return null;
180058
+ }
180059
+ return { vectors, modelId, generation };
180060
+ }
180061
+ async function embedItemsWindowBounded(projectIdentity, items, signal, db) {
180062
+ if (items.length <= MAX_WINDOWS_PER_EMBED_CALL) {
180063
+ return embedItemsForProject(projectIdentity, items, signal, db, projectIdentity);
180064
+ }
180065
+ const vectors = new Map;
176742
180066
  let modelId = null;
176743
180067
  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);
180068
+ for (let start = 0;start < items.length; start += MAX_WINDOWS_PER_EMBED_CALL) {
180069
+ const result = await embedItemsForProject(projectIdentity, items.slice(start, start + MAX_WINDOWS_PER_EMBED_CALL), signal, db, projectIdentity);
176749
180070
  if (!result)
176750
180071
  return null;
176751
180072
  if (modelId === null) {
176752
180073
  modelId = result.modelId;
176753
180074
  generation = result.generation;
176754
- } else if (result.modelId !== modelId || result.generation !== generation) {
180075
+ } else if (modelId !== result.modelId || generation !== result.generation) {
176755
180076
  return null;
176756
180077
  }
176757
- vectors.push(...result.vectors);
180078
+ for (const [id, vector] of result.vectors)
180079
+ vectors.set(id, vector);
176758
180080
  }
176759
- if (modelId === null || generation === null)
176760
- return null;
176761
- return { vectors, modelId, generation };
180081
+ return modelId === null || generation === null ? null : { vectors, modelId, generation };
176762
180082
  }
176763
180083
  function isUnembeddedMemoryRow(row) {
176764
180084
  if (row === null || typeof row !== "object")
@@ -176783,13 +180103,17 @@ async function embedUnembeddedMemoriesForProject(db, projectIdentity, batchSize
176783
180103
  if (memories.length === 0)
176784
180104
  return 0;
176785
180105
  try {
176786
- const result = await embedBatchForProject(projectIdentity, memories.map((memory) => memory.content));
180106
+ const result = await embedItemsForProject(projectIdentity, memories.map((memory) => ({
180107
+ id: `memory:${memory.id}`,
180108
+ text: memory.content,
180109
+ contentSha256: contentSha256(memory.content)
180110
+ })), undefined, db, projectIdentity);
176787
180111
  if (!result)
176788
180112
  return 0;
176789
180113
  let embeddedCount = 0;
176790
180114
  db.transaction(() => {
176791
- for (const [index, memory] of memories.entries()) {
176792
- const embedding = result.vectors[index];
180115
+ for (const memory of memories) {
180116
+ const embedding = result.vectors.get(`memory:${memory.id}`);
176793
180117
  if (!embedding)
176794
180118
  continue;
176795
180119
  if (saveEmbeddingIfHashMatches(db, memory.id, embedding, result.modelId, memory.normalized_hash)) {
@@ -176797,6 +180121,7 @@ async function embedUnembeddedMemoriesForProject(db, projectIdentity, batchSize
176797
180121
  }
176798
180122
  }
176799
180123
  })();
180124
+ enqueueShadowEmbeddingItems(projectIdentity, "memory", memories.filter((memory) => result.vectors.has(`memory:${memory.id}`)).map((memory) => String(memory.id)));
176800
180125
  return embeddedCount;
176801
180126
  } catch (error51) {
176802
180127
  log("[magic-context] failed to proactively embed missing memories:", error51);
@@ -176810,19 +180135,24 @@ async function embedCommitBatch(db, projectIdentity, batchSize) {
176810
180135
  const commits = loadUnembeddedCommits(db, projectIdentity, snapshot.modelId, Math.max(1, Math.floor(batchSize)));
176811
180136
  if (commits.length === 0)
176812
180137
  return 0;
176813
- const result = await embedBatchForProject(projectIdentity, commits.map((commit) => commit.message));
180138
+ const result = await embedItemsForProject(projectIdentity, commits.map((commit) => ({
180139
+ id: `commit:${commit.sha}`,
180140
+ text: commit.message,
180141
+ contentSha256: contentSha256(commit.message)
180142
+ })), undefined, db, projectIdentity);
176814
180143
  if (!result)
176815
180144
  return 0;
176816
180145
  let embeddedCount = 0;
176817
180146
  db.transaction(() => {
176818
- for (const [index, commit] of commits.entries()) {
176819
- const embedding = result.vectors[index];
180147
+ for (const commit of commits) {
180148
+ const embedding = result.vectors.get(`commit:${commit.sha}`);
176820
180149
  if (!embedding)
176821
180150
  continue;
176822
180151
  saveCommitEmbedding(db, commit.sha, embedding, result.modelId);
176823
180152
  embeddedCount += 1;
176824
180153
  }
176825
180154
  })();
180155
+ enqueueShadowEmbeddingItems(projectIdentity, "commit", commits.filter((commit) => result.vectors.has(`commit:${commit.sha}`)).map((commit) => commit.sha));
176826
180156
  return embeddedCount;
176827
180157
  }
176828
180158
  async function drainCommitBacklogForProject(db, projectIdentity, deadline) {
@@ -176895,9 +180225,11 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
176895
180225
  windowCount += item.windows.length;
176896
180226
  i += 1;
176897
180227
  } 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));
180228
+ const items = slice.flatMap((item) => item.windows.map((window) => ({
180229
+ id: `chunk:${item.candidate.id}:${window.windowIndex}`,
180230
+ text: window.text,
180231
+ contentSha256: contentSha256(window.text)
180232
+ })));
176901
180233
  const persistedIds = new Set;
176902
180234
  for (let attempt = 0;attempt < EMBED_SLICE_RETRY_ATTEMPTS; attempt++) {
176903
180235
  if (signal?.aborted)
@@ -176905,19 +180237,17 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
176905
180237
  let result = null;
176906
180238
  const attemptStart = Date.now();
176907
180239
  try {
176908
- result = await embedTextsWindowBounded(projectIdentity, texts, signal);
180240
+ result = await embedItemsWindowBounded(projectIdentity, items, signal, db);
176909
180241
  } catch (error51) {
176910
180242
  log("[magic-context] failed to proactively embed compartment chunks:", error51);
176911
180243
  }
176912
180244
  if (signal?.aborted)
176913
180245
  break;
176914
180246
  if (result) {
176915
- let offset = 0;
176916
180247
  for (const item of slice) {
176917
- const vectors = result.vectors.slice(offset, offset + item.windows.length);
176918
- offset += item.windows.length;
176919
180248
  if (persistedIds.has(item.candidate.id))
176920
180249
  continue;
180250
+ const vectors = item.windows.map((window) => result.vectors.get(`chunk:${item.candidate.id}:${window.windowIndex}`));
176921
180251
  if (vectors.length !== item.windows.length || vectors.some((v) => !v)) {
176922
180252
  continue;
176923
180253
  }
@@ -176931,6 +180261,9 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
176931
180261
  }));
176932
180262
  replaceCompartmentChunkEmbeddings(db, rows);
176933
180263
  persistedIds.add(item.candidate.id);
180264
+ enqueueShadowEmbeddingItems(projectIdentity, "chunk", [
180265
+ String(item.candidate.id)
180266
+ ]);
176934
180267
  }
176935
180268
  }
176936
180269
  if (persistedIds.size === slice.length)
@@ -177099,7 +180432,24 @@ function createProvider2(config2) {
177099
180432
  maxInputTokens: config2.max_input_tokens
177100
180433
  });
177101
180434
  }
177102
- return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
180435
+ if (config2.provider === "local") {
180436
+ return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
180437
+ }
180438
+ if (config2.provider === "synapse") {
180439
+ const synapse = config2;
180440
+ return new SynapseEmbeddingProvider({
180441
+ connectionFile: synapse.synapse_connection_file ?? "",
180442
+ projectRoot: "",
180443
+ session: "embedding",
180444
+ model: synapse.model,
180445
+ fingerprint: synapse.synapse_fingerprint,
180446
+ tableEpoch: synapse.synapse_table_epoch,
180447
+ dims: synapse.synapse_dims,
180448
+ recommendedBatch: synapse.synapse_recommended_batch,
180449
+ provenance: synapse.synapse_provenance
180450
+ });
180451
+ }
180452
+ throw new Error("Unknown embedding provider");
177103
180453
  }
177104
180454
  function getOrCreateProvider() {
177105
180455
  if (provider) {
@@ -178991,7 +182341,7 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
178991
182341
  init_logger();
178992
182342
 
178993
182343
  // ../plugin/src/shared/redaction.ts
178994
- import { homedir as homedir3, userInfo } from "node:os";
182344
+ import { homedir as homedir4, userInfo } from "node:os";
178995
182345
  function escapeRegex3(value) {
178996
182346
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
178997
182347
  }
@@ -179040,7 +182390,7 @@ var SECRET_QUALIFIERS = new Set([
179040
182390
  "azure"
179041
182391
  ]);
179042
182392
  function sanitizePathString(value) {
179043
- const home = homedir3();
182393
+ const home = homedir4();
179044
182394
  const username = userInfo().username;
179045
182395
  let sanitized = value;
179046
182396
  if (home) {
@@ -180036,7 +183386,7 @@ function throwIfAborted2(signal) {
180036
183386
  }
180037
183387
 
180038
183388
  // ../plugin/src/features/magic-context/smart-notes/compiler.ts
180039
- import { createHash as createHash9 } from "node:crypto";
183389
+ import { createHash as createHash11 } from "node:crypto";
180040
183390
  init_logger();
180041
183391
 
180042
183392
  // ../plugin/src/features/magic-context/smart-notes/compiler-prompt.ts
@@ -180347,7 +183697,7 @@ Remember: output only the JSON object described by the system prompt.`;
180347
183697
  });
180348
183698
  const response = run.validated;
180349
183699
  const compiledCheck = normalizeCompiledCheck(response.compiled_check);
180350
- const manifest = normalizeManifest(response.manifest);
183700
+ const manifest = normalizeManifest2(response.manifest);
180351
183701
  const checkCron = normalizeCron(response.check_cron);
180352
183702
  for (const warning of manifestAdvisoryWarnings(compiledCheck, manifest)) {
180353
183703
  log(`[dreamer] smart note #${args.note.id}: manifest advisory — ${warning}`);
@@ -180426,7 +183776,7 @@ function normalizeCompiledCheck(source) {
180426
183776
  }
180427
183777
  return code;
180428
183778
  }
180429
- function normalizeManifest(manifest) {
183779
+ function normalizeManifest2(manifest) {
180430
183780
  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
183781
  return {
180432
183782
  capabilities,
@@ -180470,7 +183820,7 @@ function manifestAdvisoryWarnings(code, manifest) {
180470
183820
  return warnings;
180471
183821
  }
180472
183822
  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");
183823
+ return createHash11("sha256").update(surfaceCondition ?? "").update("\x00").update(compiledCheck).update("\x00").update(JSON.stringify(manifest)).update("\x00").update(checkCron).digest("hex");
180474
183824
  }
180475
183825
  function extractJsonObject(output) {
180476
183826
  const fenced = output.match(/```(?:json)?\s*([\s\S]*?)```/i);
@@ -182405,7 +185755,7 @@ function normalizeOpenCodeRows(db, sessionId, rows) {
182405
185755
  const partsByMessageId = new Map;
182406
185756
  for (const row of partRows) {
182407
185757
  const parts = partsByMessageId.get(row.message_id) ?? [];
182408
- const parsed = parseJson(row.data);
185758
+ const parsed = parseJson2(row.data);
182409
185759
  if (parsed !== null)
182410
185760
  parts.push(parsed);
182411
185761
  partsByMessageId.set(row.message_id, parts);
@@ -182516,7 +185866,7 @@ function stringifyToolOutput(value) {
182516
185866
  return String(value);
182517
185867
  }
182518
185868
  }
182519
- function parseJson(value) {
185869
+ function parseJson2(value) {
182520
185870
  try {
182521
185871
  return JSON.parse(value);
182522
185872
  } catch {
@@ -182524,7 +185874,7 @@ function parseJson(value) {
182524
185874
  }
182525
185875
  }
182526
185876
  function parseJsonRecord2(value) {
182527
- const parsed = parseJson(value);
185877
+ const parsed = parseJson2(value);
182528
185878
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
182529
185879
  return null;
182530
185880
  return parsed;
@@ -183282,7 +186632,7 @@ function parseFrictionGateVerdict(verdict) {
183282
186632
  }
183283
186633
  function computeRetrospectiveWindowKey(flagged) {
183284
186634
  const anchors = flagged.map((message) => `${message.sessionId}:${message.ts}`).sort().join("|");
183285
- return createHash10("sha256").update(anchors).digest("hex").slice(0, 32);
186635
+ return createHash12("sha256").update(anchors).digest("hex").slice(0, 32);
183286
186636
  }
183287
186637
  function renderFrictionWindow(messages, flaggedOrdinals, radius = 2) {
183288
186638
  const flagged = new Set(flaggedOrdinals);
@@ -184136,18 +187486,23 @@ async function embedUnembeddedCommits(db, projectPath) {
184136
187486
  break;
184137
187487
  let embeddedThisBatch = 0;
184138
187488
  try {
184139
- const result = await embedBatchForProject(projectPath, rows.map((row) => row.message));
187489
+ const result = await embedItemsForProject(projectPath, rows.map((row) => ({
187490
+ id: `commit:${row.sha}`,
187491
+ text: row.message,
187492
+ contentSha256: contentSha256(row.message)
187493
+ })), undefined, db, projectPath);
184140
187494
  if (!result)
184141
187495
  break;
184142
187496
  db.transaction(() => {
184143
- for (const [index, row] of rows.entries()) {
184144
- const embedding2 = result.vectors[index];
187497
+ for (const row of rows) {
187498
+ const embedding2 = result.vectors.get(`commit:${row.sha}`);
184145
187499
  if (!embedding2)
184146
187500
  continue;
184147
187501
  saveCommitEmbedding(db, row.sha, embedding2, result.modelId);
184148
187502
  embeddedThisBatch += 1;
184149
187503
  }
184150
187504
  })();
187505
+ enqueueShadowEmbeddingItems(projectPath, "commit", rows.filter((row) => result.vectors.has(`commit:${row.sha}`)).map((row) => row.sha));
184151
187506
  } catch (error51) {
184152
187507
  log(`[git-commits] embed batch failed for ${projectPath}: ${error51 instanceof Error ? error51.message : String(error51)}`);
184153
187508
  break;
@@ -184303,7 +187658,11 @@ function searchGitCommitsSync(db, projectPath, query, options) {
184303
187658
  init_logger();
184304
187659
  var DREAM_TIMER_INTERVAL_MS = 15 * 60 * 1000;
184305
187660
  var GIT_COMMIT_BACKLOG_DRAIN_MAX_MS = 5 * 60 * 1000;
187661
+ var BOOT_PROJECT_JITTER_SLOT_MS = 1000;
184306
187662
  var activeTimer = null;
187663
+ var startupTimers = new Map;
187664
+ var startupJitters = new Map;
187665
+ var nextStartupJitterSlot = 0;
184307
187666
  function directoryStillExists(directory) {
184308
187667
  try {
184309
187668
  return statSync6(directory).isDirectory();
@@ -184327,39 +187686,53 @@ function openTimerDatabaseOrNull(context) {
184327
187686
  }
184328
187687
  var registeredProjects = new Map;
184329
187688
  async function startDreamScheduleTimer(args) {
187689
+ beginBootQuietPeriod();
184330
187690
  const db = openTimerDatabaseOrNull("schedule timer registration");
184331
187691
  if (!db)
184332
187692
  return;
184333
- await args.ensureRegistered(args.directory, db);
184334
- const snapshot = getProjectEmbeddingSnapshot(args.projectIdentity);
184335
187693
  const dreamingEnabled = Boolean(args.dreamerConfig && args.dreamerConfig.disable !== true);
184336
- const embeddingSweepEnabled = snapshot?.enabled ?? false;
184337
- const commitIndexingEnabled = snapshot?.gitCommitEnabled ?? false;
187694
+ const embeddingSweepEnabled = args.memoryEnabled === true;
187695
+ const commitIndexingEnabled = args.gitCommitIndexing?.enabled === true;
184338
187696
  if (!dreamingEnabled && !embeddingSweepEnabled && !commitIndexingEnabled) {
184339
187697
  return;
184340
187698
  }
184341
- const isNewRegistration = !registeredProjects.has(args.directory);
187699
+ const previousRegistration = registeredProjects.get(args.directory);
187700
+ const isNewRegistration = previousRegistration === undefined;
187701
+ if (previousRegistration && previousRegistration !== args) {
187702
+ const pendingStartup = startupTimers.get(args.directory);
187703
+ if (pendingStartup) {
187704
+ clearTimeout(pendingStartup);
187705
+ startupTimers.delete(args.directory);
187706
+ }
187707
+ }
184342
187708
  registeredProjects.set(args.directory, args);
184343
187709
  if (isNewRegistration) {
184344
187710
  log(`[dreamer] registered project ${args.projectIdentity} (dreaming=${dreamingEnabled} embeddings=${embeddingSweepEnabled} commits=${commitIndexingEnabled}; total=${registeredProjects.size})`);
184345
187711
  }
184346
187712
  if (!activeTimer) {
184347
187713
  log(`[dreamer] started independent schedule timer (every ${DREAM_TIMER_INTERVAL_MS / 60000}m)`);
184348
- runTick("startup");
187714
+ scheduleAfterBootQuiet(() => runTick("startup"));
184349
187715
  const timer = setInterval(() => runTick("interval"), DREAM_TIMER_INTERVAL_MS);
184350
187716
  if (typeof timer === "object" && "unref" in timer) {
184351
187717
  timer.unref();
184352
187718
  }
184353
187719
  activeTimer = timer;
184354
- } else if (isNewRegistration) {
184355
- sweepProject(args, "startup", db);
187720
+ } else if (isNewRegistration || previousRegistration !== args) {
187721
+ scheduleInitialProjectRun(args, db);
184356
187722
  }
184357
187723
  return () => {
184358
187724
  registeredProjects.delete(args.directory);
187725
+ const startupTimer = startupTimers.get(args.directory);
187726
+ if (startupTimer) {
187727
+ clearTimeout(startupTimer);
187728
+ startupTimers.delete(args.directory);
187729
+ }
184359
187730
  log(`[dreamer] unregistered project ${args.projectIdentity} (remaining=${registeredProjects.size})`);
184360
187731
  if (registeredProjects.size === 0 && activeTimer) {
184361
187732
  clearInterval(activeTimer);
184362
187733
  activeTimer = null;
187734
+ startupJitters.clear();
187735
+ nextStartupJitterSlot = 0;
184363
187736
  log("[dreamer] stopped dream schedule timer (no projects left)");
184364
187737
  }
184365
187738
  };
@@ -184372,22 +187745,53 @@ function runTick(origin) {
184372
187745
  if (!db)
184373
187746
  return;
184374
187747
  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
- }
187748
+ if (origin === "startup") {
187749
+ scheduleInitialProjectRun(reg, db);
187750
+ } else {
187751
+ await runProjectMaintenance(reg, origin, db);
184382
187752
  }
184383
- await sweepProject(reg, origin, db);
184384
187753
  }
187754
+ if (origin === "startup")
187755
+ return;
184385
187756
  runSqliteOptimize(db);
184386
187757
  } catch (error51) {
184387
187758
  log("[magic-context] timer-triggered maintenance check failed:", error51);
184388
187759
  }
184389
187760
  })();
184390
187761
  }
187762
+ function startupJitterMs(directory) {
187763
+ const existing = startupJitters.get(directory);
187764
+ if (existing !== undefined)
187765
+ return existing;
187766
+ const slot = nextStartupJitterSlot;
187767
+ nextStartupJitterSlot += 1;
187768
+ const hash2 = [...directory].reduce((value, character) => value * 33 + character.charCodeAt(0) >>> 0, 5381);
187769
+ const jitter = slot * BOOT_PROJECT_JITTER_SLOT_MS + hash2 % BOOT_PROJECT_JITTER_SLOT_MS;
187770
+ startupJitters.set(directory, jitter);
187771
+ return jitter;
187772
+ }
187773
+ function scheduleInitialProjectRun(reg, db) {
187774
+ if (startupTimers.has(reg.directory))
187775
+ return;
187776
+ const timer = scheduleAfterBootQuiet(() => {
187777
+ startupTimers.delete(reg.directory);
187778
+ if (registeredProjects.get(reg.directory) !== reg)
187779
+ return;
187780
+ runProjectMaintenance(reg, "startup", db);
187781
+ }, startupJitterMs(reg.directory));
187782
+ startupTimers.set(reg.directory, timer);
187783
+ }
187784
+ async function runProjectMaintenance(reg, origin, db) {
187785
+ await reg.ensureRegistered(reg.directory, db);
187786
+ const memorySnapshot = getProjectEmbeddingSnapshot(reg.projectIdentity);
187787
+ if (memorySnapshot?.enabled) {
187788
+ const embeddedCount = await embedUnembeddedMemoriesForProject(db, reg.projectIdentity);
187789
+ if (embeddedCount > 0) {
187790
+ log(`[magic-context] proactively embedded ${embeddedCount} ${embeddedCount === 1 ? "memory" : "memories"} for project ${reg.projectIdentity}`);
187791
+ }
187792
+ }
187793
+ await sweepProject(reg, origin, db);
187794
+ }
184391
187795
  async function sweepProject(reg, origin, db, gitCommitEnabled) {
184392
187796
  if (!directoryStillExists(reg.directory)) {
184393
187797
  log(`[dreamer] project directory no longer exists (${reg.projectIdentity}); skipping + unregistering`);
@@ -184555,7 +187959,7 @@ async function sweepGitCommits(args) {
184555
187959
  import { statSync as statSync7 } from "node:fs";
184556
187960
 
184557
187961
  // ../plugin/src/plugin/embedding-bootstrap-helpers.ts
184558
- import { createHash as createHash11 } from "node:crypto";
187962
+ import { createHash as createHash13 } from "node:crypto";
184559
187963
  init_logger();
184560
187964
  var EMBEDDING_AFFECTING_KEYS = new Set([
184561
187965
  "embedding.api_key",
@@ -184565,7 +187969,11 @@ var EMBEDDING_AFFECTING_KEYS = new Set([
184565
187969
  "embedding.input_type",
184566
187970
  "embedding.truncate",
184567
187971
  "embedding.max_input_tokens",
184568
- "embedding.query_input_type"
187972
+ "embedding.query_input_type",
187973
+ "embedding.fallback_provider",
187974
+ "subc",
187975
+ "subc.connection_file",
187976
+ "shadow_embedding"
184569
187977
  ]);
184570
187978
  var LITERAL_CONFIG_TOKEN_RE = /\{(?:env|file):[^}]+\}/;
184571
187979
  function embeddingConfigHasLiteralTokens(embedding2) {
@@ -184578,7 +187986,13 @@ function embeddingConfigHasLiteralTokens(embedding2) {
184578
187986
  }
184579
187987
  return false;
184580
187988
  }
184581
- var EMBEDDING_AFFECTING_TOP_LEVEL_KEYS = new Set(["embedding", "memory", "experimental"]);
187989
+ var EMBEDDING_AFFECTING_TOP_LEVEL_KEYS = new Set([
187990
+ "embedding",
187991
+ "memory",
187992
+ "experimental",
187993
+ "subc",
187994
+ "shadow_embedding"
187995
+ ]);
184582
187996
  var EMBEDDING_WARNING_TERMS = [
184583
187997
  "api_key",
184584
187998
  "endpoint",
@@ -184586,11 +188000,13 @@ var EMBEDDING_WARNING_TERMS = [
184586
188000
  "provider",
184587
188001
  "embedding",
184588
188002
  "input_type",
184589
- "truncate"
188003
+ "truncate",
188004
+ "subc",
188005
+ "shadow_embedding"
184590
188006
  ];
184591
188007
  var loggedFailureSignatures = new Map;
184592
188008
  function sha256Prefix2(value, length = 16) {
184593
- return createHash11("sha256").update(value).digest("hex").slice(0, length);
188009
+ return createHash13("sha256").update(value).digest("hex").slice(0, length);
184594
188010
  }
184595
188011
  function warningLooksEmbeddingRelated(message) {
184596
188012
  const lower = message.toLowerCase();
@@ -184989,7 +188405,7 @@ function migrateLegacyExperimental(rawConfig, warnings) {
184989
188405
  var HIDDEN_AGENT_KEYS = ["historian", "dreamer", "sidekick"];
184990
188406
  var HISTORIAN_USER_ONLY_FIELDS = ["model", "fallback_models"];
184991
188407
  var AGENT_ESCALATION_FIELDS = ["prompt", "permission", "tools", "system_prompt"];
184992
- var EMBEDDING_DESTINATION_FIELDS = ["endpoint", "provider"];
188408
+ var EMBEDDING_DESTINATION_FIELDS = ["endpoint", "provider", "fallback_provider"];
184993
188409
  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
188410
  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
188411
  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 +188521,12 @@ function stripUnsafeProjectConfigFields(projectRaw) {
185105
188521
  delete projectRaw.shadow_transform;
185106
188522
  warnings.push("Ignoring shadow_transform from project config (security: this developer-only mirror lane is user-level only).");
185107
188523
  }
188524
+ for (const field of ["subc", "shadow_embedding"]) {
188525
+ if (field in projectRaw) {
188526
+ delete projectRaw[field];
188527
+ warnings.push(`Ignoring ${field} from project config (security: daemon routing and developer-only embedding traffic are user-level settings).`);
188528
+ }
188529
+ }
185108
188530
  const embedding2 = projectRaw.embedding;
185109
188531
  if (isPlainObject3(embedding2)) {
185110
188532
  const removed = [];
@@ -185280,7 +188702,7 @@ function dropInheritedEmbeddingKeyOnRedirect(projectRaw, mergedRaw, userRaw) {
185280
188702
 
185281
188703
  // ../plugin/src/config/variable.ts
185282
188704
  import { existsSync as existsSync16, readFileSync as readFileSync7 } from "node:fs";
185283
- import { homedir as homedir4 } from "node:os";
188705
+ import { homedir as homedir5 } from "node:os";
185284
188706
  import { dirname as dirname6, isAbsolute as isAbsolute2, resolve } from "node:path";
185285
188707
 
185286
188708
  // ../plugin/src/shared/jsonc-parser.ts
@@ -185343,7 +188765,7 @@ function stripJsonComments(content) {
185343
188765
  var ENV_PATTERN = /\{env:([^}]+)\}/g;
185344
188766
  var FILE_PATTERN = /\{file:([^}]+)\}/g;
185345
188767
  function sensitiveFilePathReason(resolvedPath) {
185346
- const home = homedir4();
188768
+ const home = homedir5();
185347
188769
  const sensitiveDirs = [
185348
188770
  { dir: resolve(home, ".ssh"), label: "SSH keys" },
185349
188771
  { dir: resolve(home, ".aws"), label: "AWS credentials" },
@@ -185406,7 +188828,7 @@ function substituteConfigVariables(input) {
185406
188828
  }
185407
188829
  let filePath = rawPath.trim();
185408
188830
  if (filePath.startsWith("~/")) {
185409
- filePath = resolve(homedir4(), filePath.slice(2));
188831
+ filePath = resolve(homedir5(), filePath.slice(2));
185410
188832
  } else if (!isAbsolute2(filePath)) {
185411
188833
  filePath = resolve(configDir, filePath);
185412
188834
  }
@@ -190767,6 +194189,93 @@ function containsProbeVerbatim(text, probes) {
190767
194189
  return probes.some((probe) => haystack.includes(probe.toLowerCase()));
190768
194190
  }
190769
194191
 
194192
+ // ../plugin/src/features/magic-context/search-measurement.ts
194193
+ import { createHash as createHash14 } from "node:crypto";
194194
+ function resultId(result) {
194195
+ switch (result.source) {
194196
+ case "memory":
194197
+ return `memory:${result.memoryId}`;
194198
+ case "message":
194199
+ return `message:${result.messageId}`;
194200
+ case "compartment":
194201
+ return `chunk:${result.compartmentId}`;
194202
+ case "git_commit":
194203
+ return `commit:${result.sha}`;
194204
+ case "primer":
194205
+ return `primer:${result.primerId}`;
194206
+ case "note":
194207
+ return `note:${result.noteId}`;
194208
+ }
194209
+ }
194210
+ async function recordShadowMeasurement(args) {
194211
+ const shadowCohort = getShadowEmbeddingMeasurementCohort(args.projectPath);
194212
+ if (!shadowCohort)
194213
+ return;
194214
+ const primaryCohort = getPrimaryEmbeddingMeasurementCohort(args.projectPath);
194215
+ const shadowStartedAt = Date.now();
194216
+ let shadowFailed = false;
194217
+ let shadowResults = [];
194218
+ try {
194219
+ const vector = await embedShadowTextForProject(args.projectPath, args.query);
194220
+ if (!vector) {
194221
+ shadowFailed = true;
194222
+ } else {
194223
+ shadowResults = await args.search(args.db, args.sessionId, args.projectPath, args.query, {
194224
+ ...args.options,
194225
+ embedQuery: async () => vector,
194226
+ isEmbeddingRuntimeEnabled: () => true,
194227
+ embeddingEnabled: true,
194228
+ embeddingModelIdOverride: shadowCohort.modelId,
194229
+ chunkModelIdOverride: shadowCohort.chunkModelId,
194230
+ measurementDisabled: true,
194231
+ countRetrievals: false
194232
+ });
194233
+ }
194234
+ } catch {
194235
+ shadowFailed = true;
194236
+ }
194237
+ const primaryModelId = args.primaryQuery?.modelId ?? primaryCohort?.modelId ?? "";
194238
+ const primaryFingerprint = primaryCohort?.fingerprint ?? "";
194239
+ const primaryEpoch = primaryCohort?.epoch ?? 0;
194240
+ const cohortKey = JSON.stringify({
194241
+ primaryFingerprint,
194242
+ primaryEpoch,
194243
+ shadowFingerprint: shadowCohort.fingerprint,
194244
+ shadowEpoch: shadowCohort.epoch
194245
+ });
194246
+ const primaryIds = args.primaryResults.map(resultId);
194247
+ const shadowIds = shadowResults.map(resultId);
194248
+ const corpusHash = sha2562(JSON.stringify({ query: args.query, primaryIds, shadowIds }));
194249
+ recordEmbeddingMeasurement(args.db, {
194250
+ sessionId: args.sessionId,
194251
+ projectPath: args.projectPath,
194252
+ queryText: args.query,
194253
+ cohortKey,
194254
+ primaryResultIds: primaryIds,
194255
+ shadowResultIds: shadowIds,
194256
+ primaryLatencyMs: args.primaryLatencyMs,
194257
+ shadowLatencyMs: Date.now() - shadowStartedAt,
194258
+ primaryFailed: args.primaryQuery === null,
194259
+ shadowFailed,
194260
+ primaryModelId,
194261
+ shadowModelId: shadowCohort.modelId,
194262
+ primaryFingerprint,
194263
+ shadowFingerprint: shadowCohort.fingerprint,
194264
+ primaryEpoch,
194265
+ shadowEpoch: shadowCohort.epoch,
194266
+ corpusHash,
194267
+ coverage: {
194268
+ primaryResultCount: primaryIds.length,
194269
+ shadowResultCount: shadowIds.length,
194270
+ primaryAnswered: args.primaryQuery !== null,
194271
+ shadowAnswered: !shadowFailed
194272
+ }
194273
+ });
194274
+ }
194275
+ function sha2562(value) {
194276
+ return createHash14("sha256").update(value).digest("hex");
194277
+ }
194278
+
190770
194279
  // ../plugin/src/features/magic-context/search.ts
190771
194280
  var DEFAULT_UNIFIED_SEARCH_LIMIT = 10;
190772
194281
  var FTS_SEMANTIC_CANDIDATE_LIMIT = 50;
@@ -191524,6 +195033,7 @@ function resolveSources(sources) {
191524
195033
  }
191525
195034
  async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
191526
195035
  const trimmedQuery = query.trim();
195036
+ const measurementStartedAt = Date.now();
191527
195037
  if (trimmedQuery.length === 0) {
191528
195038
  return [];
191529
195039
  }
@@ -191556,11 +195066,14 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
191556
195066
  maxOrdinal: options.maxMessageOrdinal,
191557
195067
  probes: messageProbes
191558
195068
  }) : [];
191559
- const queryEmbedding = await queryEmbeddingPromise;
191560
- const workspace = resolveSearchWorkspaceContext(db, projectPath);
195069
+ const capturedQuery = await queryEmbeddingPromise;
191561
195070
  const embeddingSnapshot = getProjectEmbeddingSnapshot(projectPath);
191562
- const embeddingModelId = embeddingSnapshot?.modelId;
191563
- const chunkModelId = embeddingSnapshot?.chunkModelId;
195071
+ const queryContract = capturedQuery instanceof Float32Array || capturedQuery === null ? null : capturedQuery;
195072
+ const generationIsCurrent = queryContract === null || embeddingSnapshot !== null && embeddingSnapshot.generation === queryContract.generation;
195073
+ const queryEmbedding = generationIsCurrent ? queryContract?.vector ?? (capturedQuery instanceof Float32Array ? capturedQuery : null) : null;
195074
+ const workspace = resolveSearchWorkspaceContext(db, projectPath);
195075
+ const embeddingModelId = queryContract?.modelId ?? options.embeddingModelIdOverride ?? embeddingSnapshot?.modelId;
195076
+ const chunkModelId = queryContract?.chunkModelId ?? options.chunkModelIdOverride ?? embeddingSnapshot?.chunkModelId;
191564
195077
  const compartmentResults = runCompartmentChunks ? searchCompartmentChunks({
191565
195078
  db,
191566
195079
  sessionId,
@@ -191619,6 +195132,19 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
191619
195132
  ...gitCommitResults,
191620
195133
  ...noteResults
191621
195134
  ].sort(compareUnifiedResults).slice(0, limit);
195135
+ if (!options.measurementDisabled) {
195136
+ recordShadowMeasurement({
195137
+ db,
195138
+ sessionId,
195139
+ projectPath,
195140
+ query: trimmedQuery,
195141
+ options,
195142
+ primaryResults: results,
195143
+ primaryQuery: queryContract,
195144
+ primaryLatencyMs: Date.now() - measurementStartedAt,
195145
+ search: unifiedSearch
195146
+ });
195147
+ }
191622
195148
  const countRetrievals = options.countRetrievals ?? true;
191623
195149
  if (countRetrievals) {
191624
195150
  const memoryIds = results.filter((result) => result.source === "memory").map((result) => result.memoryId);
@@ -193774,15 +197300,19 @@ async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compar
193774
197300
  if (currentModelId !== "off" && chunkEmbeddingWindowsAreCurrent(db, compartment.id, currentModelId, windows, projectPath)) {
193775
197301
  continue;
193776
197302
  }
193777
- const result = await embedBatchForProject(projectPath, windows.map((window) => window.text));
197303
+ const result = await embedItemsForProject(projectPath, windows.map((window) => ({
197304
+ id: `chunk:${compartment.id}:${window.windowIndex}`,
197305
+ text: window.text,
197306
+ contentSha256: contentSha256(window.text)
197307
+ })), undefined, db, sessionId);
193778
197308
  if (!result)
193779
197309
  continue;
193780
197310
  if (chunkEmbeddingWindowsAreCurrent(db, compartment.id, currentModelId, windows, projectPath)) {
193781
197311
  continue;
193782
197312
  }
193783
197313
  const rows = [];
193784
- for (const [index, window] of windows.entries()) {
193785
- const vector = result.vectors[index];
197314
+ for (const window of windows) {
197315
+ const vector = result.vectors.get(`chunk:${compartment.id}:${window.windowIndex}`);
193786
197316
  if (!vector)
193787
197317
  continue;
193788
197318
  rows.push({
@@ -193796,6 +197326,7 @@ async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compar
193796
197326
  }
193797
197327
  if (rows.length === windows.length) {
193798
197328
  replaceCompartmentChunkEmbeddings(db, rows);
197329
+ enqueueShadowEmbeddingItems(projectPath, "chunk", [String(compartment.id)]);
193799
197330
  }
193800
197331
  } catch (error51) {
193801
197332
  sessionLog(sessionId, `compartment chunk embedding failed for compartment ${compartment.id}:`, error51);
@@ -198230,7 +201761,7 @@ function stripPiProcessedImages(args) {
198230
201761
  }
198231
201762
 
198232
201763
  // src/system-prompt.ts
198233
- import { createHash as createHash12 } from "node:crypto";
201764
+ import { createHash as createHash15 } from "node:crypto";
198234
201765
 
198235
201766
  // ../plugin/src/agents/magic-context-prompt.ts
198236
201767
  var LONG_TERM_PARTNER_FRAME = `### You are the user's long-term partner on this project — not a one-off hire
@@ -198383,7 +201914,7 @@ function processSystemPromptForCache(args) {
198383
201914
  sessionLog(sessionId, `system prompt date frozen: real=${liveDate}, using=${stickyDate} (cache-stable pass)`);
198384
201915
  }
198385
201916
  }
198386
- const currentHash = createHash12("md5").update(frozenPrompt).digest("hex");
201917
+ const currentHash = createHash15("md5").update(frozenPrompt).digest("hex");
198387
201918
  const hashChanged = !isFirstHash && currentHash !== previousHash;
198388
201919
  if (hashChanged) {
198389
201920
  sessionLog(sessionId, `system prompt hash changed: ${previousHash} → ${currentHash} (len=${frozenPrompt.length})`);
@@ -203487,6 +207018,11 @@ function applyMemoryMigration(db, projectPath, result) {
203487
207018
  }
203488
207019
  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
207020
 
207021
+ // ../plugin/src/hooks/magic-context/lkg-slot.ts
207022
+ var LKG_TOTAL_BYTES = 64 * 1024 * 1024;
207023
+ var LKG_SINGLE_SLOT_BYTES = 24 * 1024 * 1024;
207024
+ var slots = new Map;
207025
+
203490
207026
  // ../plugin/src/hooks/magic-context/recomp-orchestrator.ts
203491
207027
  function isRecompFailure(message) {
203492
207028
  return /—\s*(Failed|Skipped)/.test(message);
@@ -203976,7 +207512,7 @@ function formatThresholdPercent(value) {
203976
207512
  // package.json
203977
207513
  var package_default = {
203978
207514
  name: "@cortexkit/pi-magic-context",
203979
- version: "0.32.1",
207515
+ version: "0.32.2",
203980
207516
  type: "module",
203981
207517
  description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
203982
207518
  main: "dist/index.js",
@@ -211274,11 +214810,12 @@ async function src_default2(pi) {
211274
214810
  log(`${PREFIX} subagent child detected (${MAGIC_CONTEXT_PI_SUBAGENT_ENV}=1); skipping full extension registration`);
211275
214811
  return;
211276
214812
  }
214813
+ beginBootQuietPeriod();
211277
214814
  const storageDir = getMagicContextStorageDir();
211278
214815
  const dbPath = join13(storageDir, "context.db");
211279
214816
  let db;
211280
214817
  try {
211281
- db = openDatabase();
214818
+ db = await openDatabaseAsync();
211282
214819
  } catch (err5) {
211283
214820
  const message = err5 instanceof Error ? err5.message : String(err5);
211284
214821
  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 +214826,12 @@ async function src_default2(pi) {
211289
214826
  return;
211290
214827
  }
211291
214828
  const database = db;
211292
- runDeferredV22Backfill(db).catch((err5) => {
211293
- warn(`[v22-backfill] background runner failed: ${err5}`);
214829
+ scheduleAfterBootQuiet(() => {
214830
+ runDeferredV22Backfill(db).catch((err5) => {
214831
+ warn(`[v22-backfill] background runner failed: ${err5}`);
214832
+ });
211294
214833
  });
211295
- setTimeout(() => {
214834
+ scheduleAfterBootQuiet(() => {
211296
214835
  (async () => {
211297
214836
  try {
211298
214837
  const api2 = await loadDefaultPiSessionApi();