@cortexkit/pi-magic-context 0.32.1 → 0.32.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8018,9 +8018,27 @@ var require_src2 = __commonJS((exports, module) => {
8018
8018
 
8019
8019
  // ../plugin/src/features/magic-context/storage-db.ts
8020
8020
  import { chmodSync, copyFileSync, cpSync, existsSync as existsSync4, mkdirSync as mkdirSync3, mkdtempSync } from "node:fs";
8021
- init_data_path();
8022
8021
  import { dirname as dirname2, join as join3 } from "node:path";
8023
8022
 
8023
+ // ../plugin/src/plugin/boot-quiet.ts
8024
+ var BOOT_QUIET_MS = 120000;
8025
+ var bootQuietUntilMs = 0;
8026
+ function beginBootQuietPeriod(now = Date.now()) {
8027
+ if (bootQuietUntilMs === 0)
8028
+ bootQuietUntilMs = now + BOOT_QUIET_MS;
8029
+ }
8030
+ function bootQuietRemainingMs(now = Date.now()) {
8031
+ return Math.max(0, bootQuietUntilMs - now);
8032
+ }
8033
+ function scheduleAfterBootQuiet(task, additionalDelayMs = 0) {
8034
+ const timer = setTimeout(task, bootQuietRemainingMs() + Math.max(0, additionalDelayMs));
8035
+ timer.unref?.();
8036
+ return timer;
8037
+ }
8038
+
8039
+ // ../plugin/src/features/magic-context/storage-db.ts
8040
+ init_data_path();
8041
+
8024
8042
  // ../plugin/src/shared/error-message.ts
8025
8043
  function getErrorMessage(error) {
8026
8044
  return error instanceof Error ? error.message : String(error);
@@ -8901,6 +8919,22 @@ function bumpEpochsForWorkspaceMemberSet(db, identities, now = Date.now()) {
8901
8919
  }
8902
8920
 
8903
8921
  // ../plugin/src/features/magic-context/migrations.ts
8922
+ var MIGRATION_LOCK_RETRY_DELAYS_MS = [1000, 2000, 4000, 8000, 15000];
8923
+
8924
+ class MigrationLockBusyError extends Error {
8925
+ constructor(message) {
8926
+ super(message);
8927
+ this.name = "MigrationLockBusyError";
8928
+ }
8929
+ }
8930
+ function isSqliteLockError(error) {
8931
+ if (!error || typeof error !== "object")
8932
+ return false;
8933
+ const candidate = error;
8934
+ if (candidate.code === "SQLITE_BUSY" || candidate.code === "SQLITE_LOCKED")
8935
+ return true;
8936
+ return typeof candidate.message === "string" && /database is locked|sqlite_(busy|locked)/i.test(candidate.message);
8937
+ }
8904
8938
  function tableExists2(db, name) {
8905
8939
  return Boolean(db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name = ?").get(name));
8906
8940
  }
@@ -10260,6 +10294,80 @@ var MIGRATIONS = [
10260
10294
  ensureColumn(db, "session_meta", "emergency_recovery_origin", "TEXT DEFAULT ''");
10261
10295
  }
10262
10296
  }
10297
+ },
10298
+ {
10299
+ version: 53,
10300
+ description: "add Synapse batch, shadow, and measurement storage",
10301
+ up(db) {
10302
+ db.exec(`
10303
+ CREATE TABLE IF NOT EXISTS embedding_registrations (
10304
+ project_path TEXT PRIMARY KEY,
10305
+ provider_identity TEXT NOT NULL DEFAULT '',
10306
+ model_id TEXT NOT NULL DEFAULT '',
10307
+ chunk_model_id TEXT NOT NULL DEFAULT '',
10308
+ fingerprint TEXT NOT NULL DEFAULT '',
10309
+ table_epoch INTEGER NOT NULL DEFAULT 0,
10310
+ dims INTEGER NOT NULL DEFAULT 0,
10311
+ provenance_json TEXT NOT NULL DEFAULT '{}',
10312
+ generation INTEGER NOT NULL DEFAULT 0,
10313
+ updated_at INTEGER NOT NULL DEFAULT 0
10314
+ );
10315
+ CREATE TABLE IF NOT EXISTS synapse_batch_ledger (
10316
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
10317
+ session_id TEXT NOT NULL,
10318
+ project_path TEXT NOT NULL DEFAULT '',
10319
+ scope TEXT NOT NULL DEFAULT '',
10320
+ manifest_json TEXT NOT NULL DEFAULT '{}',
10321
+ request_key TEXT NOT NULL DEFAULT '',
10322
+ job_id TEXT,
10323
+ cursor TEXT,
10324
+ status TEXT NOT NULL DEFAULT 'pending',
10325
+ created_at INTEGER NOT NULL DEFAULT 0,
10326
+ updated_at INTEGER NOT NULL DEFAULT 0,
10327
+ UNIQUE(session_id, request_key)
10328
+ );
10329
+ CREATE INDEX IF NOT EXISTS idx_synapse_batch_ledger_session
10330
+ ON synapse_batch_ledger(session_id, updated_at);
10331
+ CREATE TABLE IF NOT EXISTS shadow_embedding_registrations (
10332
+ project_path TEXT NOT NULL,
10333
+ scope TEXT NOT NULL CHECK(scope IN ('memory', 'commit', 'chunk')),
10334
+ model_id TEXT NOT NULL,
10335
+ generation INTEGER NOT NULL DEFAULT 0,
10336
+ fingerprint TEXT NOT NULL DEFAULT '',
10337
+ table_epoch INTEGER NOT NULL DEFAULT 0,
10338
+ dims INTEGER NOT NULL DEFAULT 0,
10339
+ provenance_json TEXT NOT NULL DEFAULT '{}',
10340
+ updated_at INTEGER NOT NULL DEFAULT 0,
10341
+ PRIMARY KEY(project_path, scope, model_id)
10342
+ );
10343
+ CREATE TABLE IF NOT EXISTS embedding_measurement_corpus (
10344
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
10345
+ session_id TEXT NOT NULL,
10346
+ project_path TEXT NOT NULL DEFAULT '',
10347
+ dedup_key TEXT NOT NULL DEFAULT '',
10348
+ cohort_key TEXT NOT NULL DEFAULT '',
10349
+ query_text_hash TEXT NOT NULL DEFAULT '',
10350
+ primary_result_ids_json TEXT NOT NULL DEFAULT '[]',
10351
+ shadow_result_ids_json TEXT NOT NULL DEFAULT '[]',
10352
+ primary_latency_ms INTEGER,
10353
+ shadow_latency_ms INTEGER,
10354
+ primary_failed INTEGER NOT NULL DEFAULT 0,
10355
+ shadow_failed INTEGER NOT NULL DEFAULT 0,
10356
+ primary_model_id TEXT NOT NULL DEFAULT '',
10357
+ shadow_model_id TEXT NOT NULL DEFAULT '',
10358
+ primary_fingerprint TEXT NOT NULL DEFAULT '',
10359
+ shadow_fingerprint TEXT NOT NULL DEFAULT '',
10360
+ primary_epoch INTEGER NOT NULL DEFAULT 0,
10361
+ shadow_epoch INTEGER NOT NULL DEFAULT 0,
10362
+ corpus_hash TEXT NOT NULL DEFAULT '',
10363
+ coverage_json TEXT NOT NULL DEFAULT '{}',
10364
+ created_at INTEGER NOT NULL DEFAULT 0,
10365
+ UNIQUE(dedup_key, cohort_key)
10366
+ );
10367
+ CREATE INDEX IF NOT EXISTS idx_embedding_measurement_session
10368
+ ON embedding_measurement_corpus(session_id, created_at);
10369
+ `);
10370
+ }
10263
10371
  }
10264
10372
  ];
10265
10373
  var LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
@@ -10288,7 +10396,14 @@ function isSiblingMigrationConflict(db, error, version) {
10288
10396
  return confirmed != null;
10289
10397
  }
10290
10398
  function runMigrations(db) {
10291
- ensureMigrationsTable(db);
10399
+ try {
10400
+ ensureMigrationsTable(db);
10401
+ } catch (error) {
10402
+ if (isSqliteLockError(error)) {
10403
+ throw new MigrationLockBusyError(`failed to prepare migration lock: ${error instanceof Error ? error.message : String(error)}`);
10404
+ }
10405
+ throw error;
10406
+ }
10292
10407
  let loggedPlan = false;
10293
10408
  while (true) {
10294
10409
  let migration;
@@ -10312,6 +10427,9 @@ function runMigrations(db) {
10312
10427
  break;
10313
10428
  log(`[migrations] applied v${migration.version}: ${migration.description}`);
10314
10429
  } catch (error) {
10430
+ if (!migration && isSqliteLockError(error)) {
10431
+ throw new MigrationLockBusyError(`failed to acquire migration write lock: ${error instanceof Error ? error.message : String(error)}`);
10432
+ }
10315
10433
  if (migration && isSiblingMigrationConflict(db, error, migration.version)) {
10316
10434
  log(`[migrations] v${migration.version} already applied by sibling instance — resuming with re-read version`);
10317
10435
  const reReadVersion = getCurrentVersion(db);
@@ -10329,6 +10447,26 @@ function runMigrations(db) {
10329
10447
  log(`[migrations] schema version now: ${MIGRATIONS[MIGRATIONS.length - 1].version}`);
10330
10448
  }
10331
10449
  }
10450
+ async function runMigrationsWithRetry(db, options = {}) {
10451
+ const retryDelaysMs = options.retryDelaysMs ?? MIGRATION_LOCK_RETRY_DELAYS_MS;
10452
+ const sleep = options.sleep ?? ((delayMs) => new Promise((resolve) => setTimeout(resolve, delayMs)));
10453
+ const totalAttempts = retryDelaysMs.length + 1;
10454
+ for (let attempt = 1;attempt <= totalAttempts; attempt += 1) {
10455
+ log(`[migrations] migration lock check attempt ${attempt}/${totalAttempts}`);
10456
+ try {
10457
+ runMigrations(db);
10458
+ return;
10459
+ } catch (error) {
10460
+ if (!(error instanceof MigrationLockBusyError))
10461
+ throw error;
10462
+ const delayMs = retryDelaysMs[attempt - 1];
10463
+ if (delayMs === undefined)
10464
+ throw error;
10465
+ log(`[migrations] migration write lock is busy; retrying attempt ${attempt + 1}/${totalAttempts} in ${delayMs}ms`);
10466
+ await sleep(delayMs);
10467
+ }
10468
+ }
10469
+ }
10332
10470
 
10333
10471
  // ../plugin/src/shared/commit-detection.ts
10334
10472
  var HASH_HEX = "[0-9a-f]{7,12}";
@@ -143242,11 +143380,12 @@ function backfillToolOwnersInChunks(db, result) {
143242
143380
 
143243
143381
  // ../plugin/src/features/magic-context/storage-db.ts
143244
143382
  var databases = new Map;
143383
+ var pendingAsyncOpens = new Map;
143245
143384
  var persistenceByDatabase = new WeakMap;
143246
143385
  var persistenceErrorByDatabase = new WeakMap;
143247
143386
  var pathByDatabase = new WeakMap;
143248
143387
  var lastSchemaFenceRejection = null;
143249
- var LATEST_SUPPORTED_VERSION = 52;
143388
+ var LATEST_SUPPORTED_VERSION = 53;
143250
143389
  var PERMISSIONS_ENFORCEABLE = process.platform !== "win32";
143251
143390
  function ensureSecureStorageDir(dir) {
143252
143391
  mkdirSync3(dir, { recursive: true, mode: 448 });
@@ -143376,6 +143515,34 @@ function runSqliteOptimize(db) {
143376
143515
  db.exec("PRAGMA optimize");
143377
143516
  } catch {}
143378
143517
  }
143518
+ function finishDatabaseOpen(db, dbPath, explicitDbPath, latestSupportedVersion) {
143519
+ if (!enforceSchemaFence(db, dbPath, latestSupportedVersion)) {
143520
+ closeQuietly(db);
143521
+ return null;
143522
+ }
143523
+ healWedgedChannel2Claims(db);
143524
+ if (!explicitDbPath) {
143525
+ const runBackfill = () => {
143526
+ try {
143527
+ runToolOwnerBackfill(db);
143528
+ } catch (error) {
143529
+ log(`[magic-context] tool-owner backfill failed (continuing with lazy adoption fallback): ${getErrorMessage(error)}`);
143530
+ }
143531
+ };
143532
+ if (bootQuietRemainingMs() > 0)
143533
+ scheduleAfterBootQuiet(runBackfill);
143534
+ else
143535
+ runBackfill();
143536
+ }
143537
+ setDatabase(db);
143538
+ loadToolDefinitionMeasurements(db);
143539
+ restrictDatabaseFilePermissions(dbPath);
143540
+ databases.set(dbPath, db);
143541
+ pathByDatabase.set(db, dbPath);
143542
+ persistenceByDatabase.set(db, true);
143543
+ persistenceErrorByDatabase.delete(db);
143544
+ return db;
143545
+ }
143379
143546
  function initializeDatabase(db) {
143380
143547
  db.exec("PRAGMA busy_timeout=5000");
143381
143548
  db.exec("PRAGMA foreign_keys=ON");
@@ -143633,6 +143800,76 @@ function initializeDatabase(db) {
143633
143800
  PRIMARY KEY(project_path, scope, model_id)
143634
143801
  );
143635
143802
 
143803
+ CREATE TABLE IF NOT EXISTS embedding_registrations (
143804
+ project_path TEXT PRIMARY KEY,
143805
+ provider_identity TEXT NOT NULL DEFAULT '',
143806
+ model_id TEXT NOT NULL DEFAULT '',
143807
+ chunk_model_id TEXT NOT NULL DEFAULT '',
143808
+ fingerprint TEXT NOT NULL DEFAULT '',
143809
+ table_epoch INTEGER NOT NULL DEFAULT 0,
143810
+ dims INTEGER NOT NULL DEFAULT 0,
143811
+ provenance_json TEXT NOT NULL DEFAULT '{}',
143812
+ generation INTEGER NOT NULL DEFAULT 0,
143813
+ updated_at INTEGER NOT NULL DEFAULT 0
143814
+ );
143815
+
143816
+ CREATE TABLE IF NOT EXISTS synapse_batch_ledger (
143817
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
143818
+ session_id TEXT NOT NULL,
143819
+ project_path TEXT NOT NULL DEFAULT '',
143820
+ scope TEXT NOT NULL DEFAULT '',
143821
+ manifest_json TEXT NOT NULL DEFAULT '{}',
143822
+ request_key TEXT NOT NULL DEFAULT '',
143823
+ job_id TEXT,
143824
+ cursor TEXT,
143825
+ status TEXT NOT NULL DEFAULT 'pending',
143826
+ created_at INTEGER NOT NULL DEFAULT 0,
143827
+ updated_at INTEGER NOT NULL DEFAULT 0,
143828
+ UNIQUE(session_id, request_key)
143829
+ );
143830
+ CREATE INDEX IF NOT EXISTS idx_synapse_batch_ledger_session
143831
+ ON synapse_batch_ledger(session_id, updated_at);
143832
+
143833
+ CREATE TABLE IF NOT EXISTS shadow_embedding_registrations (
143834
+ project_path TEXT NOT NULL,
143835
+ scope TEXT NOT NULL CHECK(scope IN ('memory', 'commit', 'chunk')),
143836
+ model_id TEXT NOT NULL,
143837
+ generation INTEGER NOT NULL DEFAULT 0,
143838
+ fingerprint TEXT NOT NULL DEFAULT '',
143839
+ table_epoch INTEGER NOT NULL DEFAULT 0,
143840
+ dims INTEGER NOT NULL DEFAULT 0,
143841
+ provenance_json TEXT NOT NULL DEFAULT '{}',
143842
+ updated_at INTEGER NOT NULL DEFAULT 0,
143843
+ PRIMARY KEY(project_path, scope, model_id)
143844
+ );
143845
+
143846
+ CREATE TABLE IF NOT EXISTS embedding_measurement_corpus (
143847
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
143848
+ session_id TEXT NOT NULL,
143849
+ project_path TEXT NOT NULL DEFAULT '',
143850
+ dedup_key TEXT NOT NULL DEFAULT '',
143851
+ cohort_key TEXT NOT NULL DEFAULT '',
143852
+ query_text_hash TEXT NOT NULL DEFAULT '',
143853
+ primary_result_ids_json TEXT NOT NULL DEFAULT '[]',
143854
+ shadow_result_ids_json TEXT NOT NULL DEFAULT '[]',
143855
+ primary_latency_ms INTEGER,
143856
+ shadow_latency_ms INTEGER,
143857
+ primary_failed INTEGER NOT NULL DEFAULT 0,
143858
+ shadow_failed INTEGER NOT NULL DEFAULT 0,
143859
+ primary_model_id TEXT NOT NULL DEFAULT '',
143860
+ shadow_model_id TEXT NOT NULL DEFAULT '',
143861
+ primary_fingerprint TEXT NOT NULL DEFAULT '',
143862
+ shadow_fingerprint TEXT NOT NULL DEFAULT '',
143863
+ primary_epoch INTEGER NOT NULL DEFAULT 0,
143864
+ shadow_epoch INTEGER NOT NULL DEFAULT 0,
143865
+ corpus_hash TEXT NOT NULL DEFAULT '',
143866
+ coverage_json TEXT NOT NULL DEFAULT '{}',
143867
+ created_at INTEGER NOT NULL DEFAULT 0,
143868
+ UNIQUE(dedup_key, cohort_key)
143869
+ );
143870
+ CREATE INDEX IF NOT EXISTS idx_embedding_measurement_session
143871
+ ON embedding_measurement_corpus(session_id, created_at);
143872
+
143636
143873
  CREATE TABLE IF NOT EXISTS memory_verifications (
143637
143874
  memory_id INTEGER NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
143638
143875
  file_path TEXT NOT NULL,
@@ -144373,32 +144610,60 @@ function openDatabase(dbPathOrOptions) {
144373
144610
  }
144374
144611
  initializeDatabase(db);
144375
144612
  runMigrations(db);
144376
- if (!enforceSchemaFence(db, dbPath, latestSupportedVersion)) {
144377
- closeQuietly(db);
144378
- return null;
144379
- }
144380
- healWedgedChannel2Claims(db);
144381
- if (!explicitDbPath) {
144382
- try {
144383
- runToolOwnerBackfill(db);
144384
- } catch (error) {
144385
- log(`[magic-context] tool-owner backfill failed (continuing with lazy adoption fallback): ${getErrorMessage(error)}`);
144386
- }
144387
- }
144388
- setDatabase(db);
144389
- loadToolDefinitionMeasurements(db);
144390
- restrictDatabaseFilePermissions(dbPath);
144391
- databases.set(dbPath, db);
144392
- pathByDatabase.set(db, dbPath);
144393
- persistenceByDatabase.set(db, true);
144394
- persistenceErrorByDatabase.delete(db);
144395
- return db;
144613
+ return finishDatabaseOpen(db, dbPath, explicitDbPath, latestSupportedVersion);
144396
144614
  } catch (error) {
144397
144615
  const detail = getErrorMessage(error);
144398
144616
  log(`[magic-context] storage fatal: failed to open ${dbPath}: ${detail}`);
144399
144617
  throw new Error(`[magic-context] storage unavailable: ${detail}. Magic Context is disabled for this run; check log for details.`);
144400
144618
  }
144401
144619
  }
144620
+ async function openDatabaseAsync(dbPathOrOptions) {
144621
+ const options = typeof dbPathOrOptions === "string" ? { dbPath: dbPathOrOptions } : dbPathOrOptions;
144622
+ const explicitDbPath = options?.dbPath !== undefined;
144623
+ const { dbDir, dbPath } = resolveDatabasePath(options?.dbPath);
144624
+ const latestSupportedVersion = getRuntimeLatestSupportedVersion(options);
144625
+ const existing = databases.get(dbPath);
144626
+ if (existing) {
144627
+ if (!enforceSchemaFence(existing, dbPath, latestSupportedVersion))
144628
+ return null;
144629
+ if (!persistenceByDatabase.has(existing))
144630
+ persistenceByDatabase.set(existing, true);
144631
+ healWedgedChannel2Claims(existing);
144632
+ return existing;
144633
+ }
144634
+ const pending = pendingAsyncOpens.get(dbPath);
144635
+ if (pending)
144636
+ return pending;
144637
+ const opening = (async () => {
144638
+ let db;
144639
+ try {
144640
+ if (!explicitDbPath)
144641
+ migrateLegacyStorageIfNeeded(dbPath, dbDir);
144642
+ ensureSecureStorageDir(dbDir);
144643
+ db = new Database(dbPath);
144644
+ if (!enforceSchemaFence(db, dbPath, latestSupportedVersion)) {
144645
+ closeQuietly(db);
144646
+ return null;
144647
+ }
144648
+ initializeDatabase(db);
144649
+ await runMigrationsWithRetry(db);
144650
+ return finishDatabaseOpen(db, dbPath, explicitDbPath, latestSupportedVersion);
144651
+ } catch (error) {
144652
+ if (db)
144653
+ closeQuietly(db);
144654
+ const detail = getErrorMessage(error);
144655
+ log(`[magic-context] storage fatal: failed to open ${dbPath}: ${detail}`);
144656
+ throw new Error(`[magic-context] storage unavailable: ${detail}. Magic Context is disabled for this run; check log for details.`);
144657
+ }
144658
+ })();
144659
+ pendingAsyncOpens.set(dbPath, opening);
144660
+ try {
144661
+ return await opening;
144662
+ } finally {
144663
+ if (pendingAsyncOpens.get(dbPath) === opening)
144664
+ pendingAsyncOpens.delete(dbPath);
144665
+ }
144666
+ }
144402
144667
 
144403
144668
  // src/subagent-entry.ts
144404
144669
  init_logger();
@@ -145159,6 +145424,9 @@ function migrateLegacyExperimental(rawConfig, warnings) {
145159
145424
  return patched;
145160
145425
  }
145161
145426
 
145427
+ // ../plugin/src/config/schema/magic-context.ts
145428
+ import { homedir as homedir3 } from "node:os";
145429
+
145162
145430
  // ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
145163
145431
  var exports_external = {};
145164
145432
  __export(exports_external, {
@@ -159825,8 +160093,18 @@ var HistorianConfigSchema = AgentOverrideConfigSchema.extend({
159825
160093
  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"),
159826
160094
  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: [])`)
159827
160095
  }).optional();
160096
+ var EmbeddingFallbackProviderSchema = exports_external.enum(["local", "openai-compatible", "off"]);
160097
+ function expandConfigPath(value) {
160098
+ const trimmed = value.trim();
160099
+ if (trimmed === "~")
160100
+ return homedir3();
160101
+ if (trimmed.startsWith("~/"))
160102
+ return `${homedir3()}/${trimmed.slice(2)}`;
160103
+ return trimmed;
160104
+ }
159828
160105
  var BaseEmbeddingConfigSchema = exports_external.object({
159829
- 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."),
160106
+ 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."),
160107
+ fallback_provider: EmbeddingFallbackProviderSchema.optional().describe("Fallback provider for the Synapse lane. Required when provider is 'synapse'; local, openai-compatible, and off are valid."),
159830
160108
  model: exports_external.string().optional().describe("Embedding model name. Required for openai-compatible, ignored for local."),
159831
160109
  endpoint: exports_external.string().optional().describe("API endpoint URL. Required when provider is openai-compatible."),
159832
160110
  api_key: exports_external.string().optional().describe("API key for remote embedding provider (optional)"),
@@ -159835,14 +160113,15 @@ var BaseEmbeddingConfigSchema = exports_external.object({
159835
160113
  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."),
159836
160114
  max_input_tokens: exports_external.number().int().positive().optional().describe("Optional maximum input tokens for chunk embeddings. Defaults conservatively to 512 when omitted.")
159837
160115
  }).superRefine((data, ctx) => {
159838
- if (data.provider === "openai-compatible" && !data.endpoint?.trim()) {
160116
+ const validationProvider = data.provider === "synapse" ? data.fallback_provider : data.provider;
160117
+ if (validationProvider === "openai-compatible" && !data.endpoint?.trim()) {
159839
160118
  ctx.addIssue({
159840
160119
  code: "custom",
159841
160120
  path: ["endpoint"],
159842
160121
  message: "endpoint is required when embedding.provider is openai-compatible"
159843
160122
  });
159844
160123
  }
159845
- if (data.provider === "openai-compatible" && !data.model?.trim()) {
160124
+ if (validationProvider === "openai-compatible" && !data.model?.trim()) {
159846
160125
  ctx.addIssue({
159847
160126
  code: "custom",
159848
160127
  path: ["model"],
@@ -159851,6 +160130,25 @@ var BaseEmbeddingConfigSchema = exports_external.object({
159851
160130
  }
159852
160131
  });
159853
160132
  var EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data) => {
160133
+ if (data.provider === "synapse") {
160134
+ const model = data.model?.trim();
160135
+ const endpoint = data.endpoint?.trim();
160136
+ const apiKey = data.api_key?.trim();
160137
+ const inputType = data.input_type?.trim();
160138
+ const queryInputType = data.query_input_type?.trim();
160139
+ const truncate = data.truncate?.trim();
160140
+ return {
160141
+ provider: "synapse",
160142
+ ...data.fallback_provider ? { fallback_provider: data.fallback_provider } : {},
160143
+ ...model ? { model } : {},
160144
+ ...endpoint ? { endpoint } : {},
160145
+ ...apiKey ? { api_key: apiKey } : {},
160146
+ ...inputType ? { input_type: inputType } : {},
160147
+ ...queryInputType ? { query_input_type: queryInputType } : {},
160148
+ ...truncate ? { truncate } : {},
160149
+ ...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}
160150
+ };
160151
+ }
159854
160152
  if (data.provider === "local") {
159855
160153
  return {
159856
160154
  provider: "local",
@@ -159878,6 +160176,7 @@ var EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data) => {
159878
160176
  });
159879
160177
  var MagicContextConfigSchema = exports_external.object({
159880
160178
  enabled: exports_external.boolean().default(true).describe("Enable magic context (default: true)"),
160179
+ 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.'),
159881
160180
  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."),
159882
160181
  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."),
159883
160182
  historian: HistorianConfigSchema.describe("Historian agent configuration (model, fallback_models, variant, temperature, maxTokens, permission, two_pass, etc.)"),
@@ -159914,6 +160213,12 @@ var MagicContextConfigSchema = exports_external.object({
159914
160213
  provider: "local",
159915
160214
  model: DEFAULT_LOCAL_EMBEDDING_MODEL
159916
160215
  }).describe("Embedding provider configuration"),
160216
+ subc: exports_external.object({
160217
+ connection_file: exports_external.string().trim().min(1).transform(expandConfigPath).describe("Path to the owner-only subc connection file.")
160218
+ }).optional().describe("User-only Synapse daemon connection settings."),
160219
+ shadow_embedding: exports_external.object({
160220
+ enabled: exports_external.boolean().default(false).describe("Developer-only Synapse shadow embedding lane switch.")
160221
+ }).default({ enabled: false }).describe("Developer-only Synapse shadow embedding lane."),
159917
160222
  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).'),
159918
160223
  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."),
159919
160224
  shadow_transform: exports_external.object({
@@ -159963,7 +160268,7 @@ var MagicContextConfigSchema = exports_external.object({
159963
160268
  var HIDDEN_AGENT_KEYS = ["historian", "dreamer", "sidekick"];
159964
160269
  var HISTORIAN_USER_ONLY_FIELDS = ["model", "fallback_models"];
159965
160270
  var AGENT_ESCALATION_FIELDS = ["prompt", "permission", "tools", "system_prompt"];
159966
- var EMBEDDING_DESTINATION_FIELDS = ["endpoint", "provider"];
160271
+ var EMBEDDING_DESTINATION_FIELDS = ["endpoint", "provider", "fallback_provider"];
159967
160272
  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.";
159968
160273
  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.";
159969
160274
  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.";
@@ -160079,6 +160384,12 @@ function stripUnsafeProjectConfigFields(projectRaw) {
160079
160384
  delete projectRaw.shadow_transform;
160080
160385
  warnings.push("Ignoring shadow_transform from project config (security: this developer-only mirror lane is user-level only).");
160081
160386
  }
160387
+ for (const field of ["subc", "shadow_embedding"]) {
160388
+ if (field in projectRaw) {
160389
+ delete projectRaw[field];
160390
+ warnings.push(`Ignoring ${field} from project config (security: daemon routing and developer-only embedding traffic are user-level settings).`);
160391
+ }
160392
+ }
160082
160393
  const embedding = projectRaw.embedding;
160083
160394
  if (isPlainObject3(embedding)) {
160084
160395
  const removed = [];
@@ -160254,7 +160565,7 @@ function dropInheritedEmbeddingKeyOnRedirect(projectRaw, mergedRaw, userRaw) {
160254
160565
 
160255
160566
  // ../plugin/src/config/variable.ts
160256
160567
  import { existsSync as existsSync6, readFileSync as readFileSync3 } from "node:fs";
160257
- import { homedir as homedir3 } from "node:os";
160568
+ import { homedir as homedir4 } from "node:os";
160258
160569
  import { dirname as dirname4, isAbsolute as isAbsolute2, resolve } from "node:path";
160259
160570
 
160260
160571
  // ../plugin/src/shared/jsonc-parser.ts
@@ -160317,7 +160628,7 @@ function stripJsonComments(content) {
160317
160628
  var ENV_PATTERN = /\{env:([^}]+)\}/g;
160318
160629
  var FILE_PATTERN = /\{file:([^}]+)\}/g;
160319
160630
  function sensitiveFilePathReason(resolvedPath) {
160320
- const home = homedir3();
160631
+ const home = homedir4();
160321
160632
  const sensitiveDirs = [
160322
160633
  { dir: resolve(home, ".ssh"), label: "SSH keys" },
160323
160634
  { dir: resolve(home, ".aws"), label: "AWS credentials" },
@@ -160380,7 +160691,7 @@ function substituteConfigVariables(input) {
160380
160691
  }
160381
160692
  let filePath = rawPath.trim();
160382
160693
  if (filePath.startsWith("~/")) {
160383
- filePath = resolve(homedir3(), filePath.slice(2));
160694
+ filePath = resolve(homedir4(), filePath.slice(2));
160384
160695
  } else if (!isAbsolute2(filePath)) {
160385
160696
  filePath = resolve(configDir, filePath);
160386
160697
  }
@@ -161362,14 +161673,2634 @@ function cosineSimilarity(a, b) {
161362
161673
  return denominator === 0 ? 0 : dotProduct / denominator;
161363
161674
  }
161364
161675
 
161365
- // ../plugin/src/features/magic-context/memory/normalize-hash.ts
161676
+ // ../plugin/src/features/magic-context/memory/embedding-synapse.ts
161366
161677
  import { createHash as createHash4 } from "node:crypto";
161678
+
161679
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/client.js
161680
+ import { promises as fs3 } from "node:fs";
161681
+ import { debuglog } from "node:util";
161682
+
161683
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/auth.js
161684
+ import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
161685
+ var NONCE_LEN = 32;
161686
+ var MAX_AUTH_MESSAGE_LEN = 4096;
161687
+ var SERVER_PROOF_DOMAIN = "subc-server-v1";
161688
+ var CLIENT_AUTH_DOMAIN = "subc-client-v1";
161689
+ var DEFAULT_CLIENT_ROLE = "client";
161690
+
161691
+ class AuthError extends Error {
161692
+ }
161693
+ function computeProof(key, domain2, clientNonce, serverNonce, daemonId) {
161694
+ const mac3 = createHmac("sha256", Buffer.from(key));
161695
+ mac3.update(Buffer.from(domain2, "utf8"));
161696
+ mac3.update(Buffer.from(clientNonce));
161697
+ mac3.update(Buffer.from(serverNonce));
161698
+ mac3.update(Buffer.from(daemonId));
161699
+ return new Uint8Array(mac3.digest());
161700
+ }
161701
+ function constantTimeEq(a, b) {
161702
+ if (a.length !== b.length)
161703
+ return false;
161704
+ return timingSafeEqual(Buffer.from(a), Buffer.from(b));
161705
+ }
161706
+ async function writeMessage(sock, value, deadlineMs) {
161707
+ const json2 = Buffer.from(JSON.stringify(value), "utf8");
161708
+ if (json2.length > MAX_AUTH_MESSAGE_LEN) {
161709
+ throw new AuthError(`auth message too large: ${json2.length} > ${MAX_AUTH_MESSAGE_LEN}`);
161710
+ }
161711
+ const lenPrefix = new Uint8Array(4);
161712
+ new DataView(lenPrefix.buffer).setUint32(0, json2.length, true);
161713
+ await sock.write(lenPrefix, deadlineMs);
161714
+ await sock.write(json2, deadlineMs);
161715
+ }
161716
+ async function readMessage(sock, deadlineMs) {
161717
+ const lenBytes = await sock.readExact(4, deadlineMs);
161718
+ const len = new DataView(lenBytes.buffer, lenBytes.byteOffset, 4).getUint32(0, true);
161719
+ if (len > MAX_AUTH_MESSAGE_LEN) {
161720
+ throw new AuthError(`auth message too large: ${len} > ${MAX_AUTH_MESSAGE_LEN}`);
161721
+ }
161722
+ const body = len === 0 ? new Uint8Array(0) : await sock.readExact(len, deadlineMs);
161723
+ try {
161724
+ return JSON.parse(Buffer.from(body).toString("utf8"));
161725
+ } catch (err) {
161726
+ throw new AuthError(`auth message JSON decode failed: ${String(err)}`);
161727
+ }
161728
+ }
161729
+ async function authenticateClient(sock, conn, deadlineMs) {
161730
+ const clientNonce = new Uint8Array(randomBytes(NONCE_LEN));
161731
+ await writeMessage(sock, { client_nonce: Array.from(clientNonce), role: DEFAULT_CLIENT_ROLE }, deadlineMs);
161732
+ const proof = await readMessage(sock, deadlineMs);
161733
+ const serverNonce = Uint8Array.from(proof.server_nonce);
161734
+ const daemonId = Uint8Array.from(proof.daemon_id);
161735
+ const serverProof = Uint8Array.from(proof.server_proof);
161736
+ const expected = computeProof(conn.key, SERVER_PROOF_DOMAIN, clientNonce, serverNonce, daemonId);
161737
+ if (!constantTimeEq(expected, serverProof)) {
161738
+ throw new AuthError("server proof mismatch — wrong key or impostor daemon");
161739
+ }
161740
+ if (!constantTimeEq(daemonId, conn.daemonId)) {
161741
+ throw new AuthError("daemon id mismatch — connection file points at a different daemon");
161742
+ }
161743
+ const clientAuth = computeProof(conn.key, CLIENT_AUTH_DOMAIN, clientNonce, serverNonce, daemonId);
161744
+ await writeMessage(sock, { client_auth: Array.from(clientAuth) }, deadlineMs);
161745
+ }
161746
+
161747
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/connection-file.js
161748
+ import { promises as fs2 } from "node:fs";
161749
+ var SCHEMA_VERSION = 1;
161750
+ var MIN_KEY_LEN = 32;
161751
+ var DAEMON_ID_LEN = 16;
161752
+
161753
+ class ConnectionFileError extends Error {
161754
+ }
161755
+ function toBytes(value, field) {
161756
+ if (!Array.isArray(value) || value.some((n) => typeof n !== "number")) {
161757
+ throw new ConnectionFileError(`connection file field '${field}' must be a JSON array of bytes`);
161758
+ }
161759
+ return Uint8Array.from(value);
161760
+ }
161761
+ function validate(info) {
161762
+ if (info.schema !== SCHEMA_VERSION) {
161763
+ throw new ConnectionFileError(`unsupported connection file schema ${info.schema}; expected ${SCHEMA_VERSION}`);
161764
+ }
161765
+ if (info.endpoints.length === 0) {
161766
+ throw new ConnectionFileError("connection file must include at least one endpoint");
161767
+ }
161768
+ if (info.key.length < MIN_KEY_LEN) {
161769
+ throw new ConnectionFileError(`connection file key is too short: ${info.key.length} bytes, need at least ${MIN_KEY_LEN}`);
161770
+ }
161771
+ if (info.daemonId.length !== DAEMON_ID_LEN) {
161772
+ throw new ConnectionFileError(`connection file daemon_id must be ${DAEMON_ID_LEN} bytes, got ${info.daemonId.length}`);
161773
+ }
161774
+ }
161775
+ async function verifyOwnerOnly(path4) {
161776
+ if (process.platform === "win32")
161777
+ return;
161778
+ const stat = await fs2.stat(path4);
161779
+ const mode = stat.mode & 511;
161780
+ if ((mode & 63) !== 0) {
161781
+ throw new ConnectionFileError(`connection file ${path4} has insecure permissions 0o${mode.toString(8)}; expected owner-only 0600`);
161782
+ }
161783
+ }
161784
+ async function readConnectionFile(path4) {
161785
+ await verifyOwnerOnly(path4);
161786
+ const raw = await fs2.readFile(path4, "utf8");
161787
+ let parsed;
161788
+ try {
161789
+ parsed = JSON.parse(raw);
161790
+ } catch (err) {
161791
+ throw new ConnectionFileError(`connection file JSON read failed for ${path4}: ${String(err)}`);
161792
+ }
161793
+ const endpointsRaw = parsed.endpoints;
161794
+ if (!Array.isArray(endpointsRaw)) {
161795
+ throw new ConnectionFileError("connection file 'endpoints' must be an array");
161796
+ }
161797
+ const endpoints = endpointsRaw.map((e) => {
161798
+ const ep = e;
161799
+ if (typeof ep.host !== "string" || typeof ep.port !== "number") {
161800
+ throw new ConnectionFileError("connection file endpoint must be { host: string, port: number }");
161801
+ }
161802
+ return { host: ep.host, port: ep.port };
161803
+ });
161804
+ const info = {
161805
+ schema: parsed.schema,
161806
+ endpoints,
161807
+ key: toBytes(parsed.key, "key"),
161808
+ daemonId: toBytes(parsed.daemon_id, "daemon_id"),
161809
+ pid: parsed.pid,
161810
+ daemonVer: parsed.daemon_ver ?? ""
161811
+ };
161812
+ validate(info);
161813
+ return info;
161814
+ }
161815
+
161816
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/envelope.js
161817
+ var PROTOCOL_VERSION = 2;
161818
+ var HEADER_LEN = 21;
161819
+ var FROZEN_PREFIX_LEN = 5;
161820
+ var MAX_FRAME_BODY_LEN = 64 * 1024 * 1024;
161821
+ var FrameType;
161822
+ (function(FrameType2) {
161823
+ FrameType2[FrameType2["Request"] = 0] = "Request";
161824
+ FrameType2[FrameType2["Response"] = 1] = "Response";
161825
+ FrameType2[FrameType2["Push"] = 2] = "Push";
161826
+ FrameType2[FrameType2["StreamData"] = 3] = "StreamData";
161827
+ FrameType2[FrameType2["StreamEnd"] = 4] = "StreamEnd";
161828
+ FrameType2[FrameType2["Error"] = 5] = "Error";
161829
+ FrameType2[FrameType2["Cancel"] = 6] = "Cancel";
161830
+ FrameType2[FrameType2["Ping"] = 7] = "Ping";
161831
+ FrameType2[FrameType2["Pong"] = 8] = "Pong";
161832
+ FrameType2[FrameType2["Hello"] = 9] = "Hello";
161833
+ FrameType2[FrameType2["HelloAck"] = 10] = "HelloAck";
161834
+ FrameType2[FrameType2["Goodbye"] = 11] = "Goodbye";
161835
+ })(FrameType || (FrameType = {}));
161836
+ var FRAME_TYPE_MAX = FrameType.Goodbye;
161837
+ function isPureHeader(ty) {
161838
+ return ty === FrameType.Cancel || ty === FrameType.Ping || ty === FrameType.Pong || ty === FrameType.Goodbye;
161839
+ }
161840
+ var Priority;
161841
+ (function(Priority2) {
161842
+ Priority2[Priority2["Passive"] = 0] = "Passive";
161843
+ Priority2[Priority2["Interactive"] = 1] = "Interactive";
161844
+ Priority2[Priority2["Background"] = 2] = "Background";
161845
+ })(Priority || (Priority = {}));
161846
+ var AdmissionClass;
161847
+ (function(AdmissionClass2) {
161848
+ AdmissionClass2[AdmissionClass2["Normal"] = 0] = "Normal";
161849
+ AdmissionClass2[AdmissionClass2["Expedite"] = 1] = "Expedite";
161850
+ AdmissionClass2[AdmissionClass2["Sheddable"] = 2] = "Sheddable";
161851
+ })(AdmissionClass || (AdmissionClass = {}));
161852
+ var FLAG_BINARY = 1;
161853
+ var FLAG_PRIORITY_MASK = 6;
161854
+ var FLAG_PRIORITY_SHIFT = 1;
161855
+ var FLAG_LAST = 8;
161856
+ var FLAG_ADMISSION_MASK = 48;
161857
+ var FLAG_ADMISSION_SHIFT = 4;
161858
+ var FLAG_RESERVED_MASK = 192;
161859
+ function buildFlags(binary, priority, last, admissionClass = AdmissionClass.Normal) {
161860
+ let flags = 0;
161861
+ if (binary)
161862
+ flags |= FLAG_BINARY;
161863
+ flags |= priority << FLAG_PRIORITY_SHIFT;
161864
+ if (last)
161865
+ flags |= FLAG_LAST;
161866
+ flags |= admissionClass << FLAG_ADMISSION_SHIFT;
161867
+ return flags;
161868
+ }
161869
+ function encodeHeader(header) {
161870
+ const buffer2 = new Uint8Array(HEADER_LEN);
161871
+ const view = new DataView(buffer2.buffer);
161872
+ view.setUint32(0, header.len, true);
161873
+ buffer2[4] = header.ver;
161874
+ buffer2[5] = header.ty;
161875
+ buffer2[6] = header.flags;
161876
+ view.setUint16(7, header.channel, true);
161877
+ view.setUint32(9, header.epoch, true);
161878
+ view.setBigUint64(13, header.corr, true);
161879
+ return buffer2;
161880
+ }
161881
+
161882
+ class DecodeError extends Error {
161883
+ code;
161884
+ constructor(message, code) {
161885
+ super(message);
161886
+ this.code = code;
161887
+ this.name = "DecodeError";
161888
+ }
161889
+ }
161890
+ function decodeHeader(bytes) {
161891
+ if (bytes.length < FROZEN_PREFIX_LEN) {
161892
+ throw new DecodeError(`header shorter than frozen prefix: have ${bytes.length} bytes`, "too_short_for_prefix");
161893
+ }
161894
+ const ver = bytes[4];
161895
+ if (ver !== PROTOCOL_VERSION)
161896
+ throw new DecodeError(`unsupported envelope version ${ver}`, "unsupported_version");
161897
+ if (bytes.length < HEADER_LEN) {
161898
+ throw new DecodeError(`header too short for version: have ${bytes.length} bytes, need ${HEADER_LEN}`, "too_short_for_header");
161899
+ }
161900
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
161901
+ const len = view.getUint32(0, true);
161902
+ const typeByte = bytes[5];
161903
+ if (typeByte > FRAME_TYPE_MAX)
161904
+ throw new DecodeError(`unknown frame type byte ${typeByte}`, "unknown_frame_type");
161905
+ const ty = typeByte;
161906
+ const flags = bytes[6];
161907
+ if ((flags & FLAG_RESERVED_MASK) !== 0) {
161908
+ throw new DecodeError(`reserved flag bits set in flags 0b${flags.toString(2).padStart(8, "0")}`, "reserved_flag_bits");
161909
+ }
161910
+ if ((flags & FLAG_PRIORITY_MASK) >> FLAG_PRIORITY_SHIFT === 3) {
161911
+ throw new DecodeError(`reserved priority bits set in flags 0b${flags.toString(2).padStart(8, "0")}`, "reserved_priority_bits");
161912
+ }
161913
+ const admission = (flags & FLAG_ADMISSION_MASK) >> FLAG_ADMISSION_SHIFT;
161914
+ if (admission === 3) {
161915
+ throw new DecodeError(`reserved admission class set in flags 0b${flags.toString(2).padStart(8, "0")}`, "reserved_admission_class");
161916
+ }
161917
+ if (admission === AdmissionClass.Sheddable && ty !== FrameType.Push && ty !== FrameType.StreamData) {
161918
+ throw new DecodeError(`SHEDDABLE admission class is illegal on ${FrameType[ty]} in flags 0b${flags.toString(2).padStart(8, "0")}`, "sheddable_illegal_frame_type");
161919
+ }
161920
+ const channel = view.getUint16(7, true);
161921
+ const epoch = view.getUint32(9, true);
161922
+ if (channel === 0 && epoch !== 0) {
161923
+ throw new DecodeError(`control channel carried nonzero epoch ${epoch}`, "nonzero_epoch_on_control_channel");
161924
+ }
161925
+ if (isPureHeader(ty) && len !== 0) {
161926
+ throw new DecodeError(`pure-header frame ${FrameType[ty]} declared non-zero body length ${len}`, "pure_header_frame_with_body");
161927
+ }
161928
+ return { len, ver, ty, flags, channel, epoch, corr: view.getBigUint64(13, true) };
161929
+ }
161930
+ function buildFrame(ty, flags, channel, epoch, corr, body) {
161931
+ return buildFrameWithVersion(PROTOCOL_VERSION, ty, flags, channel, epoch, corr, body);
161932
+ }
161933
+ function buildFrameWithVersion(ver, ty, flags, channel, epoch, corr, body) {
161934
+ if (body.length > MAX_FRAME_BODY_LEN) {
161935
+ throw new DecodeError(`frame body ${body.length} exceeds max ${MAX_FRAME_BODY_LEN}`, "frame_body_too_large");
161936
+ }
161937
+ const header = { len: body.length, ver, ty, flags, channel, epoch, corr };
161938
+ decodeHeader(encodeHeader(header));
161939
+ return { header, body };
161940
+ }
161941
+ function encodeFrame(frame) {
161942
+ if (frame.header.len !== frame.body.length) {
161943
+ throw new DecodeError(`frame header length ${frame.header.len} does not match body length ${frame.body.length}`, "frame_length_mismatch");
161944
+ }
161945
+ const header = encodeHeader(frame.header);
161946
+ const output = new Uint8Array(header.length + frame.body.length);
161947
+ output.set(header, 0);
161948
+ output.set(frame.body, header.length);
161949
+ return output;
161950
+ }
161951
+
161952
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/route-handle.js
161953
+ var connectionToken = new WeakMap;
161954
+
161955
+ class RouteHandle {
161956
+ channel;
161957
+ epoch;
161958
+ constructor(channel, epoch, token) {
161959
+ if (!Number.isInteger(channel) || channel <= 0 || channel > 65535) {
161960
+ throw new RangeError(`route channel must be an integer in 1..65535, got ${channel}`);
161961
+ }
161962
+ if (!Number.isInteger(epoch) || epoch <= 0 || epoch > 4294967295) {
161963
+ throw new RangeError(`route epoch must be an integer in 1..4294967295, got ${epoch}`);
161964
+ }
161965
+ this.channel = channel;
161966
+ this.epoch = epoch;
161967
+ connectionToken.set(this, token);
161968
+ Object.freeze(this);
161969
+ }
161970
+ static create(channel, epoch, token) {
161971
+ return new RouteHandle(channel, epoch, token);
161972
+ }
161973
+ }
161974
+ function createRouteHandle(channel, epoch, token) {
161975
+ const factory = RouteHandle;
161976
+ return factory.create(channel, epoch, token);
161977
+ }
161978
+
161979
+ class StaleRouteHandleError extends Error {
161980
+ handle;
161981
+ code = "stale_route_handle";
161982
+ constructor(handle) {
161983
+ super(`route handle (${handle.channel}, ${handle.epoch}) is not live on the current connection`);
161984
+ this.handle = handle;
161985
+ this.name = "StaleRouteHandleError";
161986
+ }
161987
+ }
161988
+ function newConnectionToken() {
161989
+ return Object.freeze({});
161990
+ }
161991
+ function belongsToConnection(handle, token) {
161992
+ return connectionToken.get(handle) === token;
161993
+ }
161994
+ function sameRouteHandle(left, right) {
161995
+ return left === right;
161996
+ }
161997
+
161998
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/socket.js
161999
+ import net from "node:net";
162000
+ class SocketClosedError extends Error {
162001
+ }
162002
+
162003
+ class SocketTimeoutError extends Error {
162004
+ }
162005
+
162006
+ class SocketWriteNotQueuedError extends Error {
162007
+ cause;
162008
+ constructor(message, cause) {
162009
+ super(message);
162010
+ this.cause = cause;
162011
+ }
162012
+ }
162013
+
162014
+ class SocketWriteQueuedError extends Error {
162015
+ cause;
162016
+ constructor(message, cause) {
162017
+ super(message);
162018
+ this.cause = cause;
162019
+ }
162020
+ }
162021
+
162022
+ class SubcSocket {
162023
+ sock;
162024
+ chunks = [];
162025
+ buffered = 0;
162026
+ waiter = null;
162027
+ closedErr = null;
162028
+ bufferedBytes() {
162029
+ return this.buffered;
162030
+ }
162031
+ constructor(sock) {
162032
+ this.sock = sock;
162033
+ sock.on("data", (chunk) => {
162034
+ this.chunks.push(chunk);
162035
+ this.buffered += chunk.length;
162036
+ this.tryServe();
162037
+ });
162038
+ const fail = (err) => {
162039
+ if (!this.closedErr)
162040
+ this.closedErr = err;
162041
+ this.tryServe();
162042
+ };
162043
+ sock.on("error", (err) => fail(err instanceof Error ? err : new Error(String(err))));
162044
+ sock.on("end", () => fail(new SocketClosedError("subc closed the connection")));
162045
+ sock.on("close", () => fail(new SocketClosedError("subc connection closed")));
162046
+ }
162047
+ localPort() {
162048
+ return this.sock.localPort ?? null;
162049
+ }
162050
+ static connect(host, port, deadlineMs) {
162051
+ return new Promise((resolve2, reject) => {
162052
+ const sock = net.connect({ host, port });
162053
+ sock.setNoDelay(true);
162054
+ const timer = setTimeout(() => {
162055
+ sock.destroy();
162056
+ reject(new SocketTimeoutError(`timed out connecting to ${host}:${port}`));
162057
+ }, Math.max(0, deadlineMs - Date.now()));
162058
+ sock.once("connect", () => {
162059
+ clearTimeout(timer);
162060
+ resolve2(new SubcSocket(sock));
162061
+ });
162062
+ sock.once("error", (err) => {
162063
+ clearTimeout(timer);
162064
+ reject(err);
162065
+ });
162066
+ });
162067
+ }
162068
+ async readFrame(headerDeadlineMs, bodyDeadline, onHeader) {
162069
+ const prefix = await this.readExact(FROZEN_PREFIX_LEN, headerDeadlineMs);
162070
+ const version2 = prefix[4];
162071
+ if (version2 !== PROTOCOL_VERSION)
162072
+ throw new DecodeError(`unsupported envelope version ${version2}`, "unsupported_version");
162073
+ const remainder = await this.readExact(HEADER_LEN - FROZEN_PREFIX_LEN, headerDeadlineMs);
162074
+ const headerBytes = new Uint8Array(HEADER_LEN);
162075
+ headerBytes.set(prefix);
162076
+ headerBytes.set(remainder, FROZEN_PREFIX_LEN);
162077
+ const header = decodeHeader(headerBytes);
162078
+ if (header.len > MAX_FRAME_BODY_LEN) {
162079
+ throw new DecodeError(`frame body ${header.len} exceeds max ${MAX_FRAME_BODY_LEN}`, "frame_body_too_large");
162080
+ }
162081
+ onHeader?.();
162082
+ const bodyDeadlineMs = typeof bodyDeadline === "number" ? bodyDeadline : Date.now() + bodyDeadline.afterHeaderMs;
162083
+ const body = header.len === 0 ? new Uint8Array(0) : await this.readExact(header.len, bodyDeadlineMs);
162084
+ return { header, body };
162085
+ }
162086
+ readExact(n, deadlineMs) {
162087
+ if (this.waiter) {
162088
+ return Promise.reject(new Error("concurrent readExact is not supported"));
162089
+ }
162090
+ if (n === 0)
162091
+ return Promise.resolve(new Uint8Array(0));
162092
+ return new Promise((resolve2, reject) => {
162093
+ let timer = null;
162094
+ if (Number.isFinite(deadlineMs)) {
162095
+ const remaining = deadlineMs - Date.now();
162096
+ if (remaining <= 0) {
162097
+ reject(new SocketTimeoutError(`timed out waiting for ${n} bytes`));
162098
+ return;
162099
+ }
162100
+ timer = setTimeout(() => {
162101
+ this.waiter = null;
162102
+ reject(new SocketTimeoutError(`timed out waiting for ${n} bytes`));
162103
+ }, remaining);
162104
+ }
162105
+ this.waiter = { need: n, resolve: resolve2, reject, timer };
162106
+ this.tryServe();
162107
+ });
162108
+ }
162109
+ async write(bytes, deadlineMs) {
162110
+ try {
162111
+ await this.writeTracked(bytes, deadlineMs).completed;
162112
+ } catch (err) {
162113
+ if (err instanceof SocketWriteNotQueuedError || err instanceof SocketWriteQueuedError) {
162114
+ throw err.cause ?? err;
162115
+ }
162116
+ throw err;
162117
+ }
162118
+ }
162119
+ writeTracked(bytes, deadlineMs) {
162120
+ if (this.closedErr) {
162121
+ return {
162122
+ queued: false,
162123
+ completed: Promise.reject(new SocketWriteNotQueuedError("subc socket was closed before bytes could be queued", this.closedErr))
162124
+ };
162125
+ }
162126
+ let queued = false;
162127
+ let settled = false;
162128
+ let timer = null;
162129
+ const completed = new Promise((resolve2, reject) => {
162130
+ const settle = (run) => {
162131
+ if (settled)
162132
+ return;
162133
+ settled = true;
162134
+ if (timer)
162135
+ clearTimeout(timer);
162136
+ run();
162137
+ };
162138
+ const remaining = deadlineMs - Date.now();
162139
+ if (remaining <= 0) {
162140
+ settle(() => reject(new SocketWriteNotQueuedError("timed out before bytes could be queued to subc", new SocketTimeoutError("timed out writing to subc"))));
162141
+ return;
162142
+ }
162143
+ timer = setTimeout(() => {
162144
+ const timeout = new SocketTimeoutError("timed out writing to subc");
162145
+ 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)));
162146
+ }, remaining);
162147
+ try {
162148
+ this.sock.write(Buffer.from(bytes), (err) => {
162149
+ settle(() => {
162150
+ if (err) {
162151
+ reject(new SocketWriteQueuedError("subc socket reported a write error after bytes were handed to the socket", err instanceof Error ? err : new Error(String(err))));
162152
+ } else {
162153
+ resolve2();
162154
+ }
162155
+ });
162156
+ });
162157
+ queued = true;
162158
+ } catch (err) {
162159
+ settle(() => reject(new SocketWriteNotQueuedError("subc socket write threw before bytes could be queued", err instanceof Error ? err : new Error(String(err)))));
162160
+ }
162161
+ });
162162
+ return { queued, completed };
162163
+ }
162164
+ close() {
162165
+ this.sock.destroy();
162166
+ }
162167
+ tryServe() {
162168
+ const w = this.waiter;
162169
+ if (!w)
162170
+ return;
162171
+ if (this.buffered >= w.need) {
162172
+ const out = this.take(w.need);
162173
+ this.waiter = null;
162174
+ if (w.timer)
162175
+ clearTimeout(w.timer);
162176
+ w.resolve(out);
162177
+ return;
162178
+ }
162179
+ if (this.closedErr) {
162180
+ this.waiter = null;
162181
+ if (w.timer)
162182
+ clearTimeout(w.timer);
162183
+ w.reject(this.closedErr);
162184
+ }
162185
+ }
162186
+ take(n) {
162187
+ const out = Buffer.allocUnsafe(n);
162188
+ let off = 0;
162189
+ while (off < n) {
162190
+ const head = this.chunks[0];
162191
+ const want = n - off;
162192
+ if (head.length <= want) {
162193
+ head.copy(out, off);
162194
+ off += head.length;
162195
+ this.chunks.shift();
162196
+ } else {
162197
+ head.copy(out, off, 0, want);
162198
+ this.chunks[0] = head.subarray(want);
162199
+ off += want;
162200
+ }
162201
+ }
162202
+ this.buffered -= n;
162203
+ return out;
162204
+ }
162205
+ }
162206
+
162207
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/client.js
162208
+ var debug = debuglog("subc-client");
162209
+ var DEFAULT_HANDSHAKE_TIMEOUT_MS = 1e4;
162210
+ var DEFAULT_REQUEST_TIMEOUT_MS = 30000;
162211
+ var TIMEOUT_ARBITRATION_GRACE_MS = 50;
162212
+ var REQUEST_DEADLINE_MARKER = "request_deadline";
162213
+ var DEADLINE_NO_DROP_CODE = "deadline_exceeded_no_drop_observed";
162214
+ var ROUTE_OPEN_RETRY_DEADLINE_MS = 30000;
162215
+ var BODY_READ_TIMEOUT_MS = 30000;
162216
+ var EMPTY_BODY = new Uint8Array(0);
162217
+ var DEFAULT_MANAGED_TARGET_KIND = "management_surface";
162218
+ var SUBC_MODULE_ID_ENV = "SUBC_MODULE_ID";
162219
+ var SUBC_LAUNCH_NONCE_ENV = "SUBC_LAUNCH_NONCE";
162220
+ var DEFAULT_RECONNECT_BACKOFF = {
162221
+ baseMs: 100,
162222
+ capMs: 2000,
162223
+ maxAttempts: 6
162224
+ };
162225
+
162226
+ class SubcCallError extends Error {
162227
+ kind;
162228
+ code;
162229
+ cause;
162230
+ constructor(kind, message, code, cause) {
162231
+ super(message);
162232
+ this.kind = kind;
162233
+ this.code = code;
162234
+ this.cause = cause;
162235
+ this.name = "SubcCallError";
162236
+ }
162237
+ }
162238
+
162239
+ class SubcError extends Error {
162240
+ code;
162241
+ constructor(message, code) {
162242
+ super(message);
162243
+ this.code = code;
162244
+ }
162245
+ }
162246
+
162247
+ class SubcClient {
162248
+ sock;
162249
+ currentConn;
162250
+ opts;
162251
+ nextCorr = 1n;
162252
+ pending = new Map;
162253
+ lateResponses = new Map;
162254
+ routes = new Map;
162255
+ liveRoutes = new Map;
162256
+ connectionToken = newConnectionToken();
162257
+ ingressEpochDropCount = 0;
162258
+ closedErr = null;
162259
+ closeStarted = false;
162260
+ reconnecting = null;
162261
+ generation = 1;
162262
+ readerActive = false;
162263
+ constructor(sock, currentConn, opts) {
162264
+ this.sock = sock;
162265
+ this.currentConn = currentConn;
162266
+ this.opts = opts;
162267
+ this.readLoop(sock, this.generation);
162268
+ }
162269
+ get conn() {
162270
+ return this.currentConn;
162271
+ }
162272
+ static async connect(opts) {
162273
+ const normalized = normalizeConnectOptions(opts);
162274
+ const opened = await SubcClient.openConnection(normalized);
162275
+ return new SubcClient(opened.sock, opened.conn, normalized);
162276
+ }
162277
+ async catalogList(moduleId) {
162278
+ const body = this.encode(moduleId === undefined ? { op: "catalog.list" } : { op: "catalog.list", module_id: moduleId });
162279
+ const reply = await this.controlRpc(body);
162280
+ const parsed = this.parseJson(reply);
162281
+ return parsed.modules ?? [];
162282
+ }
162283
+ async routeOpen(target, identity, opts = {}) {
162284
+ const consumerIdentity = routeOpenConsumerIdentity(opts);
162285
+ const consumerCapabilities = opts.consumerCapabilities;
162286
+ const body = this.encode({
162287
+ op: "route.open",
162288
+ target,
162289
+ identity,
162290
+ ...consumerIdentity ? { consumer_identity: consumerIdentity } : {},
162291
+ ...consumerCapabilities !== undefined ? { consumer_capabilities: consumerCapabilities } : {}
162292
+ });
162293
+ let installed = null;
162294
+ const install = (frame) => {
162295
+ if (frame.header.ty !== FrameType.Response)
162296
+ return true;
162297
+ const parsed = this.parseJson(frame);
162298
+ if (typeof parsed.route_channel !== "number" || typeof parsed.route_epoch !== "number") {
162299
+ throw new SubcError(`route.open returned no route handle: ${JSON.stringify(parsed)}`);
162300
+ }
162301
+ installed = this.installRoute(parsed.route_channel, parsed.route_epoch);
162302
+ return true;
162303
+ };
162304
+ const closeLateRoute = (frame) => {
162305
+ if (frame.header.ty !== FrameType.Response)
162306
+ return;
162307
+ try {
162308
+ const parsed = this.parseJson(frame);
162309
+ if (typeof parsed.route_channel !== "number" || typeof parsed.route_epoch !== "number")
162310
+ return;
162311
+ const lateHandle = this.installRoute(parsed.route_channel, parsed.route_epoch);
162312
+ this.failHandle(lateHandle, new SubcError("late route.open was closed", "route_closed"));
162313
+ this.liveRoutes.delete(lateHandle.channel);
162314
+ this.sendRouteGoodbye(lateHandle, true);
162315
+ } catch {
162316
+ this.closeConnectionAfterCleanupFailure();
162317
+ }
162318
+ };
162319
+ await this.controlRpc(body, install, closeLateRoute);
162320
+ if (!installed)
162321
+ throw new SubcError("route.open response was not installed");
162322
+ return installed;
162323
+ }
162324
+ async request(handle, body, opts = {}) {
162325
+ this.assertLiveHandle(handle);
162326
+ const bytes = body instanceof Uint8Array ? body : this.encode(body);
162327
+ const priority = opts.priority ?? Priority.Interactive;
162328
+ const admission = opts.admissionClass ?? AdmissionClass.Normal;
162329
+ const reply = await this.send(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress);
162330
+ return this.parseJson(reply);
162331
+ }
162332
+ async call(moduleId, method, params, opts = {}) {
162333
+ const body = params === undefined ? { method } : { method, params };
162334
+ let retriedUnknownChannel = false;
162335
+ for (;; ) {
162336
+ const routeHandle = await this.cachedRouteHandle(moduleId, opts);
162337
+ try {
162338
+ return await this.managedRequest(routeHandle, body, opts);
162339
+ } catch (err) {
162340
+ if (!(err instanceof SubcCallError))
162341
+ throw this.terminalCallError("managed call failed", err);
162342
+ if (err.code === "unknown_channel" && !retriedUnknownChannel && !this.closeStarted) {
162343
+ retriedUnknownChannel = true;
162344
+ this.evictRouteHandle(routeHandle);
162345
+ continue;
162346
+ }
162347
+ if (err.kind === "not_sent") {
162348
+ try {
162349
+ await this.reconnectAfterDrop(err);
162350
+ } catch (reconnectErr) {
162351
+ throw this.notSentRecoveryError("managed call was not sent", reconnectErr);
162352
+ }
162353
+ continue;
162354
+ }
162355
+ if (err.kind === "outcome_unknown" && err.code !== DEADLINE_NO_DROP_CODE) {
162356
+ this.scheduleReconnectAfterDrop(err);
162357
+ }
162358
+ throw err;
162359
+ }
162360
+ }
162361
+ }
162362
+ subscribe(handle, body, onEvent, opts = {}) {
162363
+ this.assertLiveHandle(handle);
162364
+ const bytes = body instanceof Uint8Array ? body : this.encode(body);
162365
+ const priority = opts.priority ?? Priority.Interactive;
162366
+ const admission = opts.admissionClass ?? AdmissionClass.Normal;
162367
+ const corr = this.allocateCorr();
162368
+ const key = pendingKey(handle, corr);
162369
+ const closed = new Promise((resolve2, reject) => {
162370
+ if (this.closedErr) {
162371
+ reject(this.closedErr);
162372
+ return;
162373
+ }
162374
+ this.pending.set(key, {
162375
+ handle,
162376
+ resolve: () => resolve2(),
162377
+ reject,
162378
+ onProgress: onEvent,
162379
+ timer: null,
162380
+ subscription: true
162381
+ });
162382
+ const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), handle.channel, handle.epoch, corr, bytes);
162383
+ this.sock.write(encodeFrame(frame), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS).catch((err) => {
162384
+ const pending = this.pending.get(key);
162385
+ if (pending)
162386
+ this.rejectPending(key, pending, err instanceof Error ? err : new SubcError(String(err)));
162387
+ });
162388
+ });
162389
+ let cancelled = false;
162390
+ const unsubscribe = () => {
162391
+ if (cancelled)
162392
+ return;
162393
+ cancelled = true;
162394
+ this.cancel(handle, corr, priority);
162395
+ };
162396
+ return { unsubscribe, closed };
162397
+ }
162398
+ cancel(handle, corr, priority = Priority.Interactive) {
162399
+ this.assertLiveHandle(handle);
162400
+ const cancel = buildFrame(FrameType.Cancel, buildFlags(false, priority, false), handle.channel, handle.epoch, corr, EMPTY_BODY);
162401
+ this.sock.write(encodeFrame(cancel), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS).catch(() => {
162402
+ return;
162403
+ });
162404
+ }
162405
+ async routePoll(handle, kind) {
162406
+ this.assertLiveHandle(handle);
162407
+ const body = this.encode({
162408
+ op: "route.poll",
162409
+ route_channel: handle.channel,
162410
+ route_epoch: handle.epoch,
162411
+ kind
162412
+ });
162413
+ const reply = await this.controlRpc(body, (frame) => {
162414
+ if (frame.header.ty !== FrameType.Response)
162415
+ return true;
162416
+ const parsed = this.parseJson(frame);
162417
+ return parsed.route_channel === handle.channel && parsed.route_epoch === handle.epoch;
162418
+ });
162419
+ return this.parseJson(reply);
162420
+ }
162421
+ async closeRoute(handle, opts = {}) {
162422
+ this.assertLiveHandle(handle);
162423
+ for (const [key, cached2] of this.routes) {
162424
+ if (cached2.handle && sameRouteHandle(cached2.handle, handle)) {
162425
+ cached2.closed = true;
162426
+ cached2.handle = null;
162427
+ this.routes.delete(key);
162428
+ }
162429
+ }
162430
+ if (opts.drain)
162431
+ await this.drainUnaryOnHandle(handle);
162432
+ this.failHandle(handle, new SubcError("route closed by closeRoute", "route_closed"));
162433
+ if (this.liveRoutes.get(handle.channel) === handle)
162434
+ this.liveRoutes.delete(handle.channel);
162435
+ this.sendRouteGoodbye(handle);
162436
+ }
162437
+ async closeManagedRoute(target, identity, opts = {}) {
162438
+ const key = routeCacheKey(target, identity, routeOpenConsumerIdentity(opts));
162439
+ const cached2 = this.routes.get(key);
162440
+ if (!cached2)
162441
+ return;
162442
+ cached2.closed = true;
162443
+ this.routes.delete(key);
162444
+ const handle = cached2.handle;
162445
+ cached2.handle = null;
162446
+ if (handle)
162447
+ await this.closeRoute(handle, opts);
162448
+ }
162449
+ async closeRouteChannel(handle, opts = {}) {
162450
+ await this.closeRoute(handle, opts);
162451
+ }
162452
+ close() {
162453
+ this.closeStarted = true;
162454
+ this.fail(new SubcError("client closed"));
162455
+ this.sock.close();
162456
+ }
162457
+ drainUnaryOnHandle(handle) {
162458
+ const waiters = [];
162459
+ for (const pending of this.pending.values()) {
162460
+ if (pending.handle === handle && !pending.subscription) {
162461
+ waiters.push(new Promise((resolve2) => {
162462
+ const previous = pending.onSettle;
162463
+ pending.onSettle = () => {
162464
+ previous?.();
162465
+ resolve2();
162466
+ };
162467
+ }));
162468
+ }
162469
+ }
162470
+ return Promise.all(waiters).then(() => {
162471
+ return;
162472
+ });
162473
+ }
162474
+ sendRouteGoodbye(handle, closeOnQueueFailure = false) {
162475
+ this.assertLiveConnection(handle);
162476
+ if (this.closedErr) {
162477
+ if (closeOnQueueFailure)
162478
+ this.closeConnectionAfterCleanupFailure();
162479
+ return;
162480
+ }
162481
+ const goodbye = buildFrame(FrameType.Goodbye, buildFlags(false, Priority.Interactive, false), handle.channel, handle.epoch, 0n, EMPTY_BODY);
162482
+ const write = this.sock.writeTracked(encodeFrame(goodbye), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS);
162483
+ if (!write.queued && closeOnQueueFailure)
162484
+ this.closeConnectionAfterCleanupFailure();
162485
+ write.completed.catch(() => {
162486
+ if (closeOnQueueFailure && !write.queued)
162487
+ this.closeConnectionAfterCleanupFailure();
162488
+ });
162489
+ }
162490
+ static async openConnection(opts) {
162491
+ const conn = await readConnectionFile(opts.connectionFile);
162492
+ const deadline = Date.now() + (opts.handshakeTimeoutMs ?? DEFAULT_HANDSHAKE_TIMEOUT_MS);
162493
+ const endpoint = conn.endpoints[0];
162494
+ const sock = await SubcSocket.connect(endpoint.host, endpoint.port, deadline);
162495
+ try {
162496
+ await authenticateClient(sock, conn, deadline);
162497
+ } catch (err) {
162498
+ sock.close();
162499
+ throw err;
162500
+ }
162501
+ return { sock, conn };
162502
+ }
162503
+ async controlRpc(body, acceptFrame, onLateResponse) {
162504
+ return this.send(null, body, Priority.Interactive, AdmissionClass.Normal, undefined, undefined, acceptFrame, onLateResponse);
162505
+ }
162506
+ send(handle, body, priority, admission, timeoutMs, onProgress, acceptFrame, onLateResponse) {
162507
+ if (handle)
162508
+ this.assertLiveHandle(handle);
162509
+ if (this.closedErr)
162510
+ return Promise.reject(this.closedErr);
162511
+ let corr;
162512
+ try {
162513
+ corr = this.allocateCorr();
162514
+ } catch (error51) {
162515
+ return Promise.reject(error51);
162516
+ }
162517
+ const key = pendingKey(handle, corr);
162518
+ const channel = handle?.channel ?? 0;
162519
+ const epoch = handle?.epoch ?? 0;
162520
+ const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), channel, epoch, corr, body);
162521
+ return new Promise((resolve2, reject) => {
162522
+ const ms = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
162523
+ const pending = {
162524
+ handle,
162525
+ resolve: resolve2,
162526
+ reject,
162527
+ onProgress,
162528
+ timer: null,
162529
+ acceptFrame,
162530
+ onLateResponse
162531
+ };
162532
+ pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, channel, corr, ms), ms);
162533
+ this.pending.set(key, pending);
162534
+ this.sock.write(encodeFrame(frame), Date.now() + ms).catch((error51) => {
162535
+ const current = this.pending.get(key);
162536
+ if (current)
162537
+ this.rejectPending(key, current, error51 instanceof Error ? error51 : new SubcError(String(error51)));
162538
+ });
162539
+ });
162540
+ }
162541
+ arbitrateTimeout(key, pending, channel, corr, ms) {
162542
+ const settleAsTimeout = () => {
162543
+ if (pending.onLateResponse)
162544
+ this.lateResponses.set(key, pending.onLateResponse);
162545
+ this.rejectPending(key, pending, new SubcError(this.timeoutMessage(channel, corr, ms), REQUEST_DEADLINE_MARKER));
162546
+ };
162547
+ const graceDeadline = Date.now() + this.opts.timeoutArbitrationGraceMs;
162548
+ const arbitrate = () => {
162549
+ if (this.pending.get(key) !== pending)
162550
+ return;
162551
+ const readerDraining = this.readerActive || this.sock.bufferedBytes() > 0;
162552
+ if (readerDraining && Date.now() < graceDeadline) {
162553
+ setImmediate(arbitrate);
162554
+ return;
162555
+ }
162556
+ settleAsTimeout();
162557
+ };
162558
+ setImmediate(arbitrate);
162559
+ }
162560
+ async managedRequest(handle, body, opts) {
162561
+ const bytes = body instanceof Uint8Array ? body : this.encode(body);
162562
+ const priority = opts.priority ?? Priority.Interactive;
162563
+ const admission = opts.admissionClass ?? AdmissionClass.Normal;
162564
+ try {
162565
+ const reply = await this.sendManaged(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress);
162566
+ return this.parseJson(reply);
162567
+ } catch (error51) {
162568
+ if (error51 instanceof SubcCallError)
162569
+ throw error51;
162570
+ throw this.terminalCallError("managed call failed", error51);
162571
+ }
162572
+ }
162573
+ sendManaged(handle, body, priority, admission, timeoutMs, onProgress) {
162574
+ try {
162575
+ this.assertLiveHandle(handle);
162576
+ } catch (error51) {
162577
+ return Promise.reject(this.notSentCallError("request used a stale route handle", error51));
162578
+ }
162579
+ if (this.closedErr) {
162580
+ return Promise.reject(this.notSentCallError("request was not sent because the subc connection was already closed", this.closedErr));
162581
+ }
162582
+ let corr;
162583
+ try {
162584
+ corr = this.allocateCorr();
162585
+ } catch (error51) {
162586
+ return Promise.reject(this.notSentCallError("request correlation allocator was exhausted", error51));
162587
+ }
162588
+ const key = pendingKey(handle, corr);
162589
+ const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), handle.channel, handle.epoch, corr, body);
162590
+ let handedToSocket = false;
162591
+ const classifyFailure = (error51) => {
162592
+ if (!handedToSocket)
162593
+ return this.notSentCallError("request bytes were not queued to the subc socket", error51);
162594
+ if (error51 instanceof SubcError && error51.code === REQUEST_DEADLINE_MARKER) {
162595
+ 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);
162596
+ }
162597
+ return this.outcomeUnknownCallError("connection dropped before the managed call returned a response", error51);
162598
+ };
162599
+ return new Promise((resolve2, reject) => {
162600
+ const ms = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
162601
+ const pending = {
162602
+ handle,
162603
+ resolve: resolve2,
162604
+ reject,
162605
+ onProgress,
162606
+ timer: null,
162607
+ classifyFailure
162608
+ };
162609
+ pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, handle.channel, corr, ms), ms);
162610
+ this.pending.set(key, pending);
162611
+ const write = this.sock.writeTracked(encodeFrame(frame), Date.now() + ms);
162612
+ handedToSocket = write.queued;
162613
+ write.completed.catch((error51) => {
162614
+ const current = this.pending.get(key);
162615
+ if (current)
162616
+ this.rejectPending(key, current, error51 instanceof Error ? error51 : new SubcError(String(error51)));
162617
+ });
162618
+ });
162619
+ }
162620
+ async cachedRouteHandle(moduleId, opts) {
162621
+ const identity = opts.identity ?? this.opts.identity;
162622
+ if (!identity) {
162623
+ throw new SubcCallError("terminal", "managed call requires a BindIdentity in SubcClient.connect({ identity }) or call(..., { identity })", "missing_identity");
162624
+ }
162625
+ const target = { kind: opts.targetKind ?? this.opts.targetKind, module_id: moduleId };
162626
+ const consumerIdentity = routeOpenConsumerIdentity(opts);
162627
+ const key = routeCacheKey(target, identity, consumerIdentity);
162628
+ let cached2 = this.routes.get(key);
162629
+ if (!cached2) {
162630
+ cached2 = {
162631
+ key,
162632
+ moduleId,
162633
+ target,
162634
+ identity,
162635
+ consumerIdentity,
162636
+ handle: null,
162637
+ opening: null
162638
+ };
162639
+ this.routes.set(key, cached2);
162640
+ }
162641
+ if (cached2.handle && this.isLiveHandle(cached2.handle))
162642
+ return cached2.handle;
162643
+ if (!cached2.opening) {
162644
+ cached2.opening = this.openCachedRoute(cached2).finally(() => {
162645
+ cached2.opening = null;
162646
+ });
162647
+ }
162648
+ return cached2.opening;
162649
+ }
162650
+ async openCachedRoute(cached2) {
162651
+ const routeRetryDeadline = Date.now() + ROUTE_OPEN_RETRY_DEADLINE_MS;
162652
+ let routeRetryDelay = this.opts.reconnectBackoff.baseMs;
162653
+ let routeRetryAttempt = 0;
162654
+ for (;; ) {
162655
+ if (cached2.closed)
162656
+ throw this.routeClosedDuringOpen();
162657
+ try {
162658
+ await this.ensureConnectedForManaged();
162659
+ } catch (error51) {
162660
+ throw this.notSentRecoveryError("route.open could not run because reconnect failed", error51);
162661
+ }
162662
+ if (cached2.handle && this.isLiveHandle(cached2.handle))
162663
+ return cached2.handle;
162664
+ try {
162665
+ const handle = await this.routeOpen(cached2.target, cached2.identity, {
162666
+ consumerIdentity: cached2.consumerIdentity ?? null
162667
+ });
162668
+ if (cached2.closed) {
162669
+ this.liveRoutes.delete(handle.channel);
162670
+ this.sendRouteGoodbye(handle);
162671
+ throw this.routeClosedDuringOpen();
162672
+ }
162673
+ cached2.handle = handle;
162674
+ return handle;
162675
+ } catch (error51) {
162676
+ if (error51 instanceof SubcCallError && error51.code === "route_closed")
162677
+ throw error51;
162678
+ if (!this.closeStarted && isConsumerReconnectTransient(error51)) {
162679
+ try {
162680
+ await this.reconnectAfterDrop(error51);
162681
+ } catch (reconnectError) {
162682
+ throw this.notSentRecoveryError("route.open was not sent and reconnect failed", reconnectError);
162683
+ }
162684
+ continue;
162685
+ }
162686
+ if (!this.closeStarted && error51 instanceof SubcError && isRetryableRouteOpenCode(error51.code)) {
162687
+ routeRetryAttempt += 1;
162688
+ if (routeRetryAttempt < this.opts.reconnectBackoff.maxAttempts && Date.now() < routeRetryDeadline) {
162689
+ await this.opts.sleep(routeRetryDelay);
162690
+ routeRetryDelay = Math.min(routeRetryDelay * 2, this.opts.reconnectBackoff.capMs);
162691
+ continue;
162692
+ }
162693
+ throw this.notSentCallError(`route.open failed for module ${cached2.moduleId}: ${error51.code} (retry budget exhausted)`, error51);
162694
+ }
162695
+ throw this.terminalCallError(`route.open failed for module ${cached2.moduleId}`, error51);
162696
+ }
162697
+ }
162698
+ }
162699
+ async ensureConnectedForManaged() {
162700
+ if (this.closeStarted)
162701
+ throw new SubcError("client closed");
162702
+ if (this.reconnecting)
162703
+ await this.reconnecting;
162704
+ if (this.closedErr)
162705
+ await this.reconnectAfterDrop(this.closedErr);
162706
+ }
162707
+ scheduleReconnectAfterDrop(err) {
162708
+ if (this.closeStarted || this.reconnecting)
162709
+ return;
162710
+ this.reconnectAfterDrop(err).catch(() => {});
162711
+ }
162712
+ reconnectAfterDrop(trigger) {
162713
+ if (this.closeStarted)
162714
+ return Promise.reject(new SubcError("client closed"));
162715
+ if (this.reconnecting)
162716
+ return this.reconnecting;
162717
+ const promise2 = this.reconnectWithRetry(trigger).finally(() => {
162718
+ if (this.reconnecting === promise2)
162719
+ this.reconnecting = null;
162720
+ });
162721
+ this.reconnecting = promise2;
162722
+ return promise2;
162723
+ }
162724
+ async reconnectWithRetry(_trigger) {
162725
+ let attempt = 0;
162726
+ let delay = this.opts.reconnectBackoff.baseMs;
162727
+ for (;; ) {
162728
+ if (this.closeStarted)
162729
+ throw new SubcError("client closed");
162730
+ attempt += 1;
162731
+ try {
162732
+ const opened = await SubcClient.openConnection(this.opts);
162733
+ if (this.closeStarted) {
162734
+ opened.sock.close();
162735
+ throw new SubcError("client closed");
162736
+ }
162737
+ this.replaceConnection(opened);
162738
+ await this.reopenCachedRoutes();
162739
+ return;
162740
+ } catch (err) {
162741
+ if (!isConsumerReconnectTransient(err) || attempt >= this.opts.reconnectBackoff.maxAttempts) {
162742
+ if (err instanceof AuthError && attempt > 1) {
162743
+ 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`);
162744
+ }
162745
+ throw err;
162746
+ }
162747
+ await this.opts.sleep(delay);
162748
+ delay = Math.min(delay * 2, this.opts.reconnectBackoff.capMs);
162749
+ }
162750
+ }
162751
+ }
162752
+ replaceConnection(opened) {
162753
+ this.sock.close();
162754
+ this.sock = opened.sock;
162755
+ this.currentConn = opened.conn;
162756
+ this.closedErr = null;
162757
+ this.generation += 1;
162758
+ this.connectionToken = newConnectionToken();
162759
+ this.liveRoutes.clear();
162760
+ this.lateResponses.clear();
162761
+ this.nextCorr = 1n;
162762
+ this.readLoop(opened.sock, this.generation);
162763
+ }
162764
+ async reopenCachedRoutes() {
162765
+ for (const cached2 of this.routes.values())
162766
+ cached2.handle = null;
162767
+ for (const cached2 of this.routes.values()) {
162768
+ if (cached2.closed)
162769
+ continue;
162770
+ const handle = await this.routeOpen(cached2.target, cached2.identity, {
162771
+ consumerIdentity: cached2.consumerIdentity ?? null
162772
+ });
162773
+ if (cached2.closed) {
162774
+ this.liveRoutes.delete(handle.channel);
162775
+ this.sendRouteGoodbye(handle);
162776
+ continue;
162777
+ }
162778
+ cached2.handle = handle;
162779
+ }
162780
+ }
162781
+ timeoutMessage(channel, corr, ms) {
162782
+ const port = this.sock.localPort();
162783
+ const where = port === null ? "channel" : `local_port=${port} channel`;
162784
+ return `request on ${where} ${channel} corr ${corr} timed out after ${ms}ms`;
162785
+ }
162786
+ routeClosedDuringOpen() {
162787
+ return new SubcCallError("not_sent", "route was closed before route.open completed", "route_closed");
162788
+ }
162789
+ async readLoop(sock, generation) {
162790
+ try {
162791
+ for (;; ) {
162792
+ this.readerActive = false;
162793
+ const frame = await sock.readFrame(Number.POSITIVE_INFINITY, { afterHeaderMs: BODY_READ_TIMEOUT_MS }, () => {
162794
+ this.readerActive = true;
162795
+ });
162796
+ try {
162797
+ if (this.sock === sock && this.generation === generation)
162798
+ this.dispatch(frame);
162799
+ } finally {
162800
+ this.readerActive = false;
162801
+ }
162802
+ }
162803
+ } catch (error51) {
162804
+ if (this.sock === sock && this.generation === generation) {
162805
+ this.fail(error51 instanceof Error ? error51 : new SubcError(String(error51)));
162806
+ }
162807
+ }
162808
+ }
162809
+ dispatch(frame) {
162810
+ let handle = null;
162811
+ if (frame.header.channel !== 0) {
162812
+ handle = this.liveRoutes.get(frame.header.channel) ?? null;
162813
+ if (!handle || handle.epoch !== frame.header.epoch) {
162814
+ this.ingressEpochDropCount += 1;
162815
+ return;
162816
+ }
162817
+ }
162818
+ const key = pendingKey(handle, frame.header.corr);
162819
+ const pending = this.pending.get(key);
162820
+ if (pending) {
162821
+ if (pending.acceptFrame && !pending.acceptFrame(frame))
162822
+ return;
162823
+ switch (frame.header.ty) {
162824
+ case FrameType.Push:
162825
+ case FrameType.StreamData:
162826
+ pending.onProgress?.(frame.body);
162827
+ return;
162828
+ case FrameType.Response:
162829
+ case FrameType.StreamEnd:
162830
+ this.settle(key, pending, () => pending.resolve(frame));
162831
+ return;
162832
+ case FrameType.Error:
162833
+ this.settle(key, pending, () => pending.reject(this.errorFromFrame(frame)));
162834
+ return;
162835
+ default:
162836
+ return;
162837
+ }
162838
+ }
162839
+ const late = this.lateResponses.get(key);
162840
+ if (late && (frame.header.ty === FrameType.Response || frame.header.ty === FrameType.Error)) {
162841
+ this.lateResponses.delete(key);
162842
+ late(frame);
162843
+ return;
162844
+ }
162845
+ if (frame.header.ty === FrameType.Goodbye && handle) {
162846
+ this.failHandle(handle, new SubcError("route closed by subc (GOODBYE)"));
162847
+ if (this.liveRoutes.get(handle.channel) === handle)
162848
+ this.liveRoutes.delete(handle.channel);
162849
+ this.evictRouteHandle(handle);
162850
+ return;
162851
+ }
162852
+ if (frame.header.ty === FrameType.Response || frame.header.ty === FrameType.Error || frame.header.ty === FrameType.StreamEnd) {
162853
+ 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() ?? "?");
162854
+ }
162855
+ }
162856
+ settle(key, pending, run) {
162857
+ if (this.pending.get(key) !== pending)
162858
+ return false;
162859
+ this.pending.delete(key);
162860
+ if (pending.timer)
162861
+ clearTimeout(pending.timer);
162862
+ run();
162863
+ pending.onSettle?.();
162864
+ return true;
162865
+ }
162866
+ rejectPending(key, pending, err) {
162867
+ this.settle(key, pending, () => pending.reject(pending.classifyFailure?.(err) ?? err));
162868
+ }
162869
+ errorFromFrame(frame) {
162870
+ try {
162871
+ const parsed = JSON.parse(Buffer.from(frame.body).toString("utf8"));
162872
+ return new SubcError(parsed.message ?? "subc error", parsed.code);
162873
+ } catch {
162874
+ return new SubcError(Buffer.from(frame.body).toString("utf8") || "subc error");
162875
+ }
162876
+ }
162877
+ evictRouteHandle(handle) {
162878
+ for (const cached2 of this.routes.values()) {
162879
+ if (cached2.handle && sameRouteHandle(cached2.handle, handle))
162880
+ cached2.handle = null;
162881
+ }
162882
+ }
162883
+ failHandle(handle, error51) {
162884
+ for (const [key, pending] of this.pending) {
162885
+ if (pending.handle && sameRouteHandle(pending.handle, handle))
162886
+ this.rejectPending(key, pending, error51);
162887
+ }
162888
+ }
162889
+ fail(err) {
162890
+ if (!this.closedErr)
162891
+ this.closedErr = err;
162892
+ for (const [key, pending] of this.pending) {
162893
+ this.rejectPending(key, pending, err);
162894
+ }
162895
+ }
162896
+ notSentCallError(message, cause) {
162897
+ return new SubcCallError("not_sent", `${message}${causeMessage(cause)}`, errorCode(cause), cause);
162898
+ }
162899
+ outcomeUnknownCallError(message, cause) {
162900
+ return new SubcCallError("outcome_unknown", `${message}${causeMessage(cause)}`, errorCode(cause), cause);
162901
+ }
162902
+ terminalCallError(message, cause) {
162903
+ if (cause instanceof SubcCallError)
162904
+ return cause;
162905
+ return new SubcCallError("terminal", `${message}${causeMessage(cause)}`, errorCode(cause), cause);
162906
+ }
162907
+ notSentRecoveryError(message, cause) {
162908
+ if (cause instanceof SubcCallError)
162909
+ return cause;
162910
+ if (isConsumerReconnectTransient(cause))
162911
+ return this.notSentCallError(message, cause);
162912
+ return this.terminalCallError(message, cause);
162913
+ }
162914
+ get droppedIngressFrames() {
162915
+ return this.ingressEpochDropCount;
162916
+ }
162917
+ installRoute(channel, epoch) {
162918
+ const handle = createRouteHandle(channel, epoch, this.connectionToken);
162919
+ this.liveRoutes.set(channel, handle);
162920
+ return handle;
162921
+ }
162922
+ isLiveHandle(handle) {
162923
+ return belongsToConnection(handle, this.connectionToken) && this.liveRoutes.get(handle.channel) === handle;
162924
+ }
162925
+ assertLiveConnection(handle) {
162926
+ if (!belongsToConnection(handle, this.connectionToken))
162927
+ throw new StaleRouteHandleError(handle);
162928
+ }
162929
+ assertLiveHandle(handle) {
162930
+ if (!this.isLiveHandle(handle))
162931
+ throw new StaleRouteHandleError(handle);
162932
+ }
162933
+ allocateCorr() {
162934
+ const maximum = 0xffffffffffffffffn;
162935
+ if (this.nextCorr > maximum) {
162936
+ const error51 = new SubcError("channel-0 correlation id allocator exhausted", "corr_exhausted");
162937
+ this.fail(error51);
162938
+ this.sock.close();
162939
+ this.scheduleReconnectAfterDrop(error51);
162940
+ throw error51;
162941
+ }
162942
+ const corr = this.nextCorr;
162943
+ this.nextCorr += 1n;
162944
+ return corr;
162945
+ }
162946
+ closeConnectionAfterCleanupFailure() {
162947
+ const error51 = new SubcError("late route cleanup could not be queued", "late_route_cleanup_failed");
162948
+ this.fail(error51);
162949
+ this.sock.close();
162950
+ this.scheduleReconnectAfterDrop(error51);
162951
+ }
162952
+ encode(value) {
162953
+ return new Uint8Array(Buffer.from(JSON.stringify(value), "utf8"));
162954
+ }
162955
+ parseJson(frame) {
162956
+ return JSON.parse(Buffer.from(frame.body).toString("utf8"));
162957
+ }
162958
+ }
162959
+ function isConsumerReconnectTransient(err) {
162960
+ if (err instanceof SocketClosedError || err instanceof SocketTimeoutError)
162961
+ return true;
162962
+ if (err instanceof SocketWriteNotQueuedError || err instanceof SocketWriteQueuedError)
162963
+ return true;
162964
+ if (err instanceof SubcCallError)
162965
+ return err.kind === "not_sent" || err.kind === "outcome_unknown";
162966
+ if (err instanceof AuthError)
162967
+ return true;
162968
+ if (err instanceof SubcError || err instanceof ConnectionFileError)
162969
+ return false;
162970
+ const code = errorCode(err);
162971
+ return code === "ECONNREFUSED" || code === "ECONNRESET" || code === "EPIPE" || code === "ETIMEDOUT" || code === "ENOENT";
162972
+ }
162973
+ function isRetryableRouteOpenCode(code) {
162974
+ return code === "unknown_module" || code === "module_reloading" || code === "target_unavailable" || code === "module_timeout";
162975
+ }
162976
+ async function connectionFileExists(path4) {
162977
+ try {
162978
+ await fs3.access(path4);
162979
+ return true;
162980
+ } catch {
162981
+ return false;
162982
+ }
162983
+ }
162984
+ function normalizeConnectOptions(opts) {
162985
+ return {
162986
+ connectionFile: opts.connectionFile,
162987
+ handshakeTimeoutMs: opts.handshakeTimeoutMs,
162988
+ identity: opts.identity,
162989
+ targetKind: opts.targetKind ?? DEFAULT_MANAGED_TARGET_KIND,
162990
+ reconnectBackoff: opts.reconnectBackoff ?? DEFAULT_RECONNECT_BACKOFF,
162991
+ sleep: opts.sleep ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms))),
162992
+ timeoutArbitrationGraceMs: opts.timeoutArbitrationGraceMs ?? TIMEOUT_ARBITRATION_GRACE_MS
162993
+ };
162994
+ }
162995
+ function routeCacheKey(target, identity, consumerIdentity) {
162996
+ const consumerPart = consumerIdentity ? `${consumerIdentity.module_id}\x00${consumerIdentity.launch_nonce}` : "";
162997
+ return `${target.kind}\x00${target.module_id}\x00${identity.project_root}\x00${identity.harness}\x00${identity.session}\x00${consumerPart}`;
162998
+ }
162999
+ function routeOpenConsumerIdentity(opts = {}) {
163000
+ if (opts.consumerIdentity !== undefined)
163001
+ return opts.consumerIdentity ?? undefined;
163002
+ const moduleId = process.env[SUBC_MODULE_ID_ENV];
163003
+ const launchNonce = process.env[SUBC_LAUNCH_NONCE_ENV];
163004
+ if (!moduleId || !launchNonce)
163005
+ return;
163006
+ return { module_id: moduleId, launch_nonce: launchNonce };
163007
+ }
163008
+ function errorCode(err) {
163009
+ if (typeof err === "object" && err !== null && "code" in err) {
163010
+ const code = err.code;
163011
+ if (typeof code === "string")
163012
+ return code;
163013
+ }
163014
+ return;
163015
+ }
163016
+ function causeMessage(cause) {
163017
+ if (cause === undefined)
163018
+ return "";
163019
+ return `: ${cause instanceof Error ? cause.message : String(cause)}`;
163020
+ }
163021
+ function pendingKey(handle, corr) {
163022
+ return handle ? `${handle.channel}:${handle.epoch}:${corr}` : `0:0:${corr}`;
163023
+ }
163024
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/provider.js
163025
+ import { Buffer as Buffer2 } from "node:buffer";
163026
+ var DEFAULT_HANDSHAKE_TIMEOUT_MS2 = 1e4;
163027
+ var BODY_READ_TIMEOUT_MS2 = 30000;
163028
+ var WRITE_TIMEOUT_MS = 30000;
163029
+ var DEFAULT_RESTORED_DEBOUNCE_MS = 250;
163030
+ var DEFAULT_PROVIDER_HANDLER_CAPACITY = 64;
163031
+ var HEALTH_CHECK_OP = "health.check";
163032
+ var HELLO_CORR = 1n;
163033
+
163034
+ class AsyncPermitPool {
163035
+ available;
163036
+ waiters = [];
163037
+ constructor(capacity) {
163038
+ if (!Number.isInteger(capacity) || capacity <= 0) {
163039
+ throw new SubcProviderError("provider handler capacity must be a positive integer", "invalid_handler_capacity");
163040
+ }
163041
+ this.available = capacity;
163042
+ }
163043
+ async acquire() {
163044
+ if (this.available > 0) {
163045
+ this.available -= 1;
163046
+ return this.releaseOnce();
163047
+ }
163048
+ await new Promise((resolve2) => {
163049
+ this.waiters.push(resolve2);
163050
+ });
163051
+ return this.releaseOnce();
163052
+ }
163053
+ releaseOnce() {
163054
+ let released = false;
163055
+ return () => {
163056
+ if (released)
163057
+ return;
163058
+ released = true;
163059
+ const next = this.waiters.shift();
163060
+ if (next) {
163061
+ next();
163062
+ } else {
163063
+ this.available += 1;
163064
+ }
163065
+ };
163066
+ }
163067
+ }
163068
+
163069
+ class SubcProviderError extends Error {
163070
+ code;
163071
+ constructor(message, code) {
163072
+ super(message);
163073
+ this.code = code;
163074
+ }
163075
+ }
163076
+ class SubcProvider {
163077
+ sock;
163078
+ currentConn;
163079
+ opts;
163080
+ closed;
163081
+ resolveClosed = () => {
163082
+ return;
163083
+ };
163084
+ closeStarted = false;
163085
+ closedErr = null;
163086
+ inflight = new Map;
163087
+ pending = new Map;
163088
+ liveRoutes = new Map;
163089
+ connectionToken = newConnectionToken();
163090
+ nextCorr = 1n;
163091
+ ingressEpochDropCount = 0;
163092
+ requestGate = new AsyncPermitPool(DEFAULT_PROVIDER_HANDLER_CAPACITY);
163093
+ reconnecting = null;
163094
+ generation = 1;
163095
+ connectionEpoch = 1;
163096
+ stateQueue = [];
163097
+ drainingStateQueue = false;
163098
+ restoredDebounceToken = 0;
163099
+ storage;
163100
+ constructor(sock, currentConn, opts, storage) {
163101
+ this.sock = sock;
163102
+ this.currentConn = currentConn;
163103
+ this.opts = opts;
163104
+ this.storage = storage;
163105
+ this.closed = new Promise((resolve2) => {
163106
+ this.resolveClosed = resolve2;
163107
+ });
163108
+ this.readLoop(sock, this.generation);
163109
+ this.enqueueConnectionState({ state: "connected", epoch: this.connectionEpoch });
163110
+ }
163111
+ get droppedIngressFrames() {
163112
+ return this.ingressEpochDropCount;
163113
+ }
163114
+ get conn() {
163115
+ return this.currentConn;
163116
+ }
163117
+ currentEpoch() {
163118
+ return this.connectionEpoch;
163119
+ }
163120
+ async request(handle, body, opts = {}) {
163121
+ this.assertLiveHandle(handle);
163122
+ const corr = this.allocateCorr();
163123
+ const key = routeKey(handle, corr);
163124
+ const timeoutMs = opts.timeoutMs ?? WRITE_TIMEOUT_MS;
163125
+ const frame = buildFrame(FrameType.Request, buildFlags(false, opts.priority ?? Priority.Interactive, false, opts.admissionClass ?? AdmissionClass.Normal), handle.channel, handle.epoch, corr, body);
163126
+ return await new Promise((resolve2, reject) => {
163127
+ const timer = setTimeout(() => {
163128
+ if (this.pending.delete(key))
163129
+ reject(new SubcProviderError("reverse request timed out", "request_timeout"));
163130
+ }, timeoutMs);
163131
+ this.pending.set(key, {
163132
+ resolve: (response) => resolve2(response.body),
163133
+ reject,
163134
+ timer
163135
+ });
163136
+ this.sendOn(this.sock, this.generation, frame).catch((error51) => {
163137
+ const pending = this.pending.get(key);
163138
+ if (!pending)
163139
+ return;
163140
+ this.pending.delete(key);
163141
+ clearTimeout(pending.timer);
163142
+ reject(error51 instanceof Error ? error51 : new SubcProviderError(String(error51)));
163143
+ });
163144
+ });
163145
+ }
163146
+ async push(handle, body, opts = {}) {
163147
+ this.assertLiveHandle(handle);
163148
+ 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));
163149
+ }
163150
+ cancel(handle, corr) {
163151
+ this.assertLiveHandle(handle);
163152
+ this.sendOn(this.sock, this.generation, buildFrame(FrameType.Cancel, controlFlags(), handle.channel, handle.epoch, corr, new Uint8Array(0)));
163153
+ }
163154
+ closeRoute(handle) {
163155
+ this.assertLiveHandle(handle);
163156
+ this.liveRoutes.delete(handle.channel);
163157
+ this.abortHandle(handle);
163158
+ this.sendOn(this.sock, this.generation, buildFrame(FrameType.Goodbye, controlFlags(), handle.channel, handle.epoch, 0n, new Uint8Array(0)));
163159
+ }
163160
+ static async connect(opts) {
163161
+ if (opts.manifest.protocol_ver !== PROTOCOL_VERSION) {
163162
+ throw new SubcProviderError(`manifest protocol_ver ${opts.manifest.protocol_ver} does not match client protocol ${PROTOCOL_VERSION}`, "invalid_manifest");
163163
+ }
163164
+ const normalized = normalizeProviderConnectOptions(opts);
163165
+ const opened = await SubcProvider.openConnection(normalized);
163166
+ return new SubcProvider(opened.sock, opened.conn, normalized, opened.ack.storage);
163167
+ }
163168
+ async close() {
163169
+ if (!this.closeStarted) {
163170
+ this.closeStarted = true;
163171
+ this.cancelRestoredDebounce();
163172
+ const sock = this.sock;
163173
+ try {
163174
+ await sendFrame(sock, buildFrame(FrameType.Goodbye, controlFlags(), 0, 0, 0n, new Uint8Array(0)));
163175
+ } catch {} finally {
163176
+ sock.close();
163177
+ this.finishClosed();
163178
+ }
163179
+ }
163180
+ await this.closed;
163181
+ }
163182
+ static async openConnection(opts) {
163183
+ const conn = await readConnectionFile(opts.connectionFile);
163184
+ const deadline = Date.now() + (opts.handshakeTimeoutMs ?? DEFAULT_HANDSHAKE_TIMEOUT_MS2);
163185
+ const endpoint = conn.endpoints[0];
163186
+ const sock = await SubcSocket.connect(endpoint.host, endpoint.port, deadline);
163187
+ try {
163188
+ await authenticateClient(sock, conn, deadline);
163189
+ await sendFrame(sock, buildHelloFrame(opts));
163190
+ const ack = await expectHelloAck(sock, deadline);
163191
+ return { sock, conn, ack };
163192
+ } catch (err) {
163193
+ sock.close();
163194
+ throw err;
163195
+ }
163196
+ }
163197
+ async readLoop(sock, generation) {
163198
+ try {
163199
+ for (;; ) {
163200
+ const frame = await sock.readFrame(Number.POSITIVE_INFINITY, { afterHeaderMs: BODY_READ_TIMEOUT_MS2 });
163201
+ const keepGoing = await this.dispatch(frame, sock, generation);
163202
+ if (!keepGoing) {
163203
+ if (this.sock === sock && this.generation === generation)
163204
+ this.closeStarted = true;
163205
+ break;
163206
+ }
163207
+ }
163208
+ } catch (error51) {
163209
+ if (this.sock === sock && this.generation === generation && !this.closeStarted) {
163210
+ this.handleUnexpectedDrop(sock, generation, error51 instanceof Error ? error51 : new SubcProviderError(String(error51)));
163211
+ return;
163212
+ }
163213
+ } finally {
163214
+ if (this.sock === sock && this.generation === generation) {
163215
+ sock.close();
163216
+ if (this.closeStarted)
163217
+ this.finishClosed();
163218
+ }
163219
+ }
163220
+ }
163221
+ async dispatch(frame, sock, generation) {
163222
+ let handle = null;
163223
+ if (frame.header.channel !== 0) {
163224
+ handle = this.liveRoutes.get(frame.header.channel) ?? null;
163225
+ if (!handle || handle.epoch !== frame.header.epoch) {
163226
+ this.ingressEpochDropCount += 1;
163227
+ return true;
163228
+ }
163229
+ }
163230
+ if (handle) {
163231
+ const pendingKey2 = routeKey(handle, frame.header.corr);
163232
+ const pending = this.pending.get(pendingKey2);
163233
+ if (pending) {
163234
+ if (frame.header.ty === FrameType.Push || frame.header.ty === FrameType.StreamData)
163235
+ return true;
163236
+ if (frame.header.ty === FrameType.Response || frame.header.ty === FrameType.StreamEnd) {
163237
+ this.pending.delete(pendingKey2);
163238
+ clearTimeout(pending.timer);
163239
+ pending.resolve(frame);
163240
+ return true;
163241
+ }
163242
+ if (frame.header.ty === FrameType.Error) {
163243
+ this.pending.delete(pendingKey2);
163244
+ clearTimeout(pending.timer);
163245
+ pending.reject(providerErrorFromFrame(frame));
163246
+ return true;
163247
+ }
163248
+ }
163249
+ }
163250
+ switch (frame.header.ty) {
163251
+ case FrameType.Ping:
163252
+ if (frame.header.channel === 0) {
163253
+ await this.sendOn(sock, generation, buildFrameWithVersion(frame.header.ver, FrameType.Pong, frame.header.flags, 0, 0, frame.header.corr, new Uint8Array(0)));
163254
+ }
163255
+ return true;
163256
+ case FrameType.Goodbye:
163257
+ if (!handle)
163258
+ return false;
163259
+ this.liveRoutes.delete(handle.channel);
163260
+ this.abortHandle(handle);
163261
+ await this.opts.onRouteGone?.(handle);
163262
+ return true;
163263
+ case FrameType.Cancel:
163264
+ if (handle)
163265
+ this.inflight.get(routeKey(handle, frame.header.corr))?.abort();
163266
+ return true;
163267
+ case FrameType.Request:
163268
+ if (frame.header.channel === 0) {
163269
+ await this.handleControlRequest(frame, sock, generation);
163270
+ } else if (handle) {
163271
+ this.handleDataRequest(frame, handle, sock, generation).catch((error51) => {
163272
+ if (!this.closeStarted && this.sock === sock && this.generation === generation) {
163273
+ console.warn("SubcProvider handler failed after its request was dispatched", error51);
163274
+ }
163275
+ });
163276
+ }
163277
+ return true;
163278
+ default:
163279
+ return true;
163280
+ }
163281
+ }
163282
+ abortHandle(handle) {
163283
+ const prefix = `${handle.channel}:${handle.epoch}:`;
163284
+ for (const [key, controller] of this.inflight) {
163285
+ if (key.startsWith(prefix))
163286
+ controller.abort();
163287
+ }
163288
+ for (const [key, pending] of this.pending) {
163289
+ if (!key.startsWith(prefix))
163290
+ continue;
163291
+ this.pending.delete(key);
163292
+ clearTimeout(pending.timer);
163293
+ pending.reject(new StaleRouteHandleError(handle));
163294
+ }
163295
+ }
163296
+ abortGeneration(_generation) {
163297
+ this.abortAllInflight();
163298
+ for (const [key, pending] of this.pending) {
163299
+ this.pending.delete(key);
163300
+ clearTimeout(pending.timer);
163301
+ pending.reject(new SubcProviderError("provider connection dropped", "connection_dropped"));
163302
+ }
163303
+ this.liveRoutes.clear();
163304
+ }
163305
+ abortAllInflight() {
163306
+ for (const controller of this.inflight.values())
163307
+ controller.abort();
163308
+ }
163309
+ async handleControlRequest(frame, sock, generation) {
163310
+ const request = parseJson(frame.body);
163311
+ if (request.op === HEALTH_CHECK_OP) {
163312
+ this.handleHealthRequest(frame, sock, generation).catch((error51) => {
163313
+ if (!this.closeStarted && this.sock === sock && this.generation === generation) {
163314
+ console.warn("SubcProvider health handler failed after its request was dispatched", error51);
163315
+ }
163316
+ });
163317
+ return;
163318
+ }
163319
+ if (request.op !== "route.bind") {
163320
+ throw new SubcProviderError(`unsupported module control request ${request.op ?? "<missing op>"}`);
163321
+ }
163322
+ const tentative = createRouteHandle(numberField(request.route_channel, "route_channel"), numberField(request.epoch, "epoch"), this.connectionToken);
163323
+ const bindRequest = {
163324
+ handle: tentative,
163325
+ target: request.target,
163326
+ identity: request.identity,
163327
+ principal: request.principal,
163328
+ consumer_capabilities: request.consumer_capabilities
163329
+ };
163330
+ let decision;
163331
+ try {
163332
+ decision = await this.opts.onBind?.(bindRequest);
163333
+ } catch (error51) {
163334
+ try {
163335
+ await this.sendError(frame, "route_rejected", error51 instanceof Error ? error51.message : String(error51), controlFlags(), sock, generation);
163336
+ } finally {
163337
+ await this.opts.onRouteGone?.(tentative);
163338
+ }
163339
+ return;
163340
+ }
163341
+ const rejection = bindRejection(decision);
163342
+ if (rejection) {
163343
+ try {
163344
+ await this.sendError(frame, rejection.code, rejection.message, controlFlags(), sock, generation);
163345
+ } finally {
163346
+ await this.opts.onRouteGone?.(tentative);
163347
+ }
163348
+ return;
163349
+ }
163350
+ try {
163351
+ await this.sendOn(sock, generation, buildFrameWithVersion(frame.header.ver, FrameType.Response, controlFlags(), 0, 0, frame.header.corr, encodeJson({ op: "route.bind" })));
163352
+ } catch (error51) {
163353
+ await this.opts.onRouteGone?.(tentative);
163354
+ throw error51;
163355
+ }
163356
+ if (this.sock !== sock || this.generation !== generation || this.closeStarted || this.closedErr) {
163357
+ await this.opts.onRouteGone?.(tentative);
163358
+ return;
163359
+ }
163360
+ this.liveRoutes.set(tentative.channel, tentative);
163361
+ await this.opts.onBound?.(tentative);
163362
+ }
163363
+ async handleDataRequest(frame, handle, sock, generation) {
163364
+ const { corr, ver } = frame.header;
163365
+ const key = routeKey(handle, corr);
163366
+ const controller = new AbortController;
163367
+ this.inflight.set(key, controller);
163368
+ const context = {
163369
+ handle,
163370
+ signal: controller.signal,
163371
+ currentEpoch: () => this.connectionEpoch,
163372
+ emit: async (eventBody, options = {}) => {
163373
+ this.assertLiveHandle(handle);
163374
+ if (controller.signal.aborted)
163375
+ return;
163376
+ 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));
163377
+ }
163378
+ };
163379
+ const releasePermit = await (this.requestGate ?? new AsyncPermitPool(DEFAULT_PROVIDER_HANDLER_CAPACITY)).acquire();
163380
+ const dataFlags = buildFlags(false, Priority.Interactive, false);
163381
+ try {
163382
+ const body = await this.opts.handler(handle, frame.body, context);
163383
+ if (controller.signal.aborted)
163384
+ return;
163385
+ this.assertLiveHandle(handle);
163386
+ if (body === undefined) {
163387
+ await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.StreamEnd, dataFlags, handle.channel, handle.epoch, corr, new Uint8Array(0)));
163388
+ } else if (body instanceof Uint8Array) {
163389
+ await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.Response, dataFlags, handle.channel, handle.epoch, corr, body));
163390
+ } else {
163391
+ throw new SubcProviderError("provider handler must return a Uint8Array or void", "invalid_handler_response");
163392
+ }
163393
+ } catch (error51) {
163394
+ if (error51 instanceof StaleRouteHandleError || controller.signal.aborted)
163395
+ return;
163396
+ await this.sendError(frame, error51 instanceof SubcProviderError && error51.code ? error51.code : "handler_error", error51 instanceof Error ? error51.message : String(error51), dataFlags, sock, generation);
163397
+ } finally {
163398
+ releasePermit();
163399
+ if (this.inflight.get(key) === controller)
163400
+ this.inflight.delete(key);
163401
+ }
163402
+ }
163403
+ async handleHealthRequest(frame, sock, generation) {
163404
+ const { corr, ver } = frame.header;
163405
+ const key = `control:${generation}:${corr}`;
163406
+ const controller = new AbortController;
163407
+ this.inflight.set(key, controller);
163408
+ const releasePermit = await (this.requestGate ?? new AsyncPermitPool(DEFAULT_PROVIDER_HANDLER_CAPACITY)).acquire();
163409
+ try {
163410
+ if (controller.signal.aborted)
163411
+ return;
163412
+ const report = await this.opts.health();
163413
+ await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.Response, controlFlags(), 0, 0, corr, encodeJson({
163414
+ op: HEALTH_CHECK_OP,
163415
+ status: report.status,
163416
+ ...report.detail === undefined ? {} : { detail: report.detail },
163417
+ ...report.metrics === undefined ? {} : { metrics: report.metrics }
163418
+ })));
163419
+ } catch (error51) {
163420
+ await this.sendError(frame, error51 instanceof SubcProviderError && error51.code ? error51.code : "health_error", error51 instanceof Error ? error51.message : String(error51), controlFlags(), sock, generation);
163421
+ } finally {
163422
+ releasePermit();
163423
+ if (this.inflight.get(key) === controller)
163424
+ this.inflight.delete(key);
163425
+ }
163426
+ }
163427
+ async sendError(frame, code, message, flags, sock, generation) {
163428
+ await this.sendOn(sock, generation, buildFrameWithVersion(frame.header.ver, FrameType.Error, flags, frame.header.channel, frame.header.epoch, frame.header.corr, encodeJson({ code, message })));
163429
+ }
163430
+ async sendOn(sock, generation, frame) {
163431
+ if (this.sock !== sock || this.generation !== generation || this.closeStarted || this.closedErr)
163432
+ return;
163433
+ await sendFrame(sock, frame);
163434
+ }
163435
+ handleUnexpectedDrop(sock, generation, cause) {
163436
+ this.cancelRestoredDebounce();
163437
+ this.abortGeneration(generation);
163438
+ this.generation += 1;
163439
+ sock.close();
163440
+ this.enqueueConnectionState({ state: "down", cause });
163441
+ this.scheduleReconnectAfterDrop(cause);
163442
+ }
163443
+ scheduleReconnectAfterDrop(trigger) {
163444
+ if (this.closeStarted || this.reconnecting)
163445
+ return;
163446
+ const promise2 = this.reconnectWithRetry(trigger).catch((err) => {
163447
+ if (!this.closeStarted)
163448
+ this.failFatal(err instanceof Error ? err : new SubcProviderError(String(err)));
163449
+ }).finally(() => {
163450
+ if (this.reconnecting === promise2)
163451
+ this.reconnecting = null;
163452
+ });
163453
+ this.reconnecting = promise2;
163454
+ }
163455
+ async reconnectWithRetry(_trigger) {
163456
+ let attempt = 0;
163457
+ let delay = this.opts.reconnectBackoff.baseMs;
163458
+ for (;; ) {
163459
+ if (this.closeStarted)
163460
+ throw new SubcProviderError("provider closed");
163461
+ attempt += 1;
163462
+ this.enqueueConnectionState({ state: "reconnecting", attempt });
163463
+ try {
163464
+ const opened = await SubcProvider.openConnection(this.opts);
163465
+ if (this.closeStarted) {
163466
+ opened.sock.close();
163467
+ throw new SubcProviderError("provider closed");
163468
+ }
163469
+ this.replaceConnection(opened);
163470
+ return;
163471
+ } catch (err) {
163472
+ if (this.closeStarted)
163473
+ throw err;
163474
+ if (!isProviderReconnectTransient(err))
163475
+ throw err;
163476
+ await this.opts.sleep(delay);
163477
+ delay = Math.min(delay * 2, this.opts.reconnectBackoff.capMs);
163478
+ }
163479
+ }
163480
+ }
163481
+ replaceConnection(opened) {
163482
+ this.sock.close();
163483
+ this.sock = opened.sock;
163484
+ this.currentConn = opened.conn;
163485
+ this.storage = opened.ack.storage;
163486
+ this.closedErr = null;
163487
+ this.connectionEpoch += 1;
163488
+ this.connectionToken = newConnectionToken();
163489
+ this.liveRoutes.clear();
163490
+ this.nextCorr = 1n;
163491
+ const generation = this.generation;
163492
+ this.readLoop(opened.sock, generation);
163493
+ this.scheduleRestored(generation, this.connectionEpoch);
163494
+ }
163495
+ scheduleRestored(generation, epoch) {
163496
+ if (!this.opts.onConnectionState)
163497
+ return;
163498
+ const token = ++this.restoredDebounceToken;
163499
+ this.opts.sleep(this.opts.restoredDebounceMs).then(() => {
163500
+ if (token === this.restoredDebounceToken && !this.closeStarted && this.sock && this.generation === generation && this.connectionEpoch === epoch) {
163501
+ this.enqueueConnectionState({ state: "restored", epoch });
163502
+ }
163503
+ }).catch((err) => {
163504
+ if (token === this.restoredDebounceToken && !this.closeStarted) {
163505
+ console.warn("SubcProvider restored debounce timer failed", err);
163506
+ }
163507
+ });
163508
+ }
163509
+ cancelRestoredDebounce() {
163510
+ this.restoredDebounceToken += 1;
163511
+ }
163512
+ enqueueConnectionState(event) {
163513
+ if (!this.opts.onConnectionState)
163514
+ return;
163515
+ this.stateQueue.push(event);
163516
+ if (!this.drainingStateQueue)
163517
+ this.drainConnectionStateQueue();
163518
+ }
163519
+ async drainConnectionStateQueue() {
163520
+ if (this.drainingStateQueue)
163521
+ return;
163522
+ this.drainingStateQueue = true;
163523
+ try {
163524
+ while (this.stateQueue.length > 0) {
163525
+ const event = this.stateQueue[0];
163526
+ try {
163527
+ await this.opts.onConnectionState?.(event);
163528
+ this.stateQueue.shift();
163529
+ } catch (err) {
163530
+ if (event.state === "restored") {
163531
+ console.warn("SubcProvider restored callback failed; retrying delivery", err);
163532
+ await pauseBeforeStateRetry();
163533
+ continue;
163534
+ }
163535
+ console.warn("SubcProvider connection-state callback failed", err);
163536
+ this.stateQueue.shift();
163537
+ }
163538
+ }
163539
+ } finally {
163540
+ this.drainingStateQueue = false;
163541
+ if (this.stateQueue.length > 0)
163542
+ this.drainConnectionStateQueue();
163543
+ }
163544
+ }
163545
+ isLiveHandle(handle) {
163546
+ return belongsToConnection(handle, this.connectionToken) && this.liveRoutes.get(handle.channel) === handle;
163547
+ }
163548
+ assertLiveHandle(handle) {
163549
+ if (!this.isLiveHandle(handle))
163550
+ throw new StaleRouteHandleError(handle);
163551
+ }
163552
+ allocateCorr() {
163553
+ const maximum = 0xffffffffffffffffn;
163554
+ if (this.nextCorr > maximum) {
163555
+ const error51 = new SubcProviderError("channel-0 correlation id allocator exhausted", "corr_exhausted");
163556
+ this.handleUnexpectedDrop(this.sock, this.generation, error51);
163557
+ throw error51;
163558
+ }
163559
+ const corr = this.nextCorr;
163560
+ this.nextCorr += 1n;
163561
+ return corr;
163562
+ }
163563
+ failFatal(err) {
163564
+ if (!this.closedErr)
163565
+ this.closedErr = err;
163566
+ this.closeStarted = true;
163567
+ this.cancelRestoredDebounce();
163568
+ this.abortAllInflight();
163569
+ this.sock.close();
163570
+ this.finishClosed();
163571
+ }
163572
+ finishClosed() {
163573
+ this.resolveClosed();
163574
+ }
163575
+ }
163576
+ function routeKey(handle, corr) {
163577
+ return `${handle.channel}:${handle.epoch}:${corr}`;
163578
+ }
163579
+ function providerErrorFromFrame(frame) {
163580
+ try {
163581
+ const body = parseJson(frame.body);
163582
+ return new SubcProviderError(body.message ?? "subc error", body.code);
163583
+ } catch {
163584
+ return new SubcProviderError(Buffer2.from(frame.body).toString("utf8") || "subc error");
163585
+ }
163586
+ }
163587
+ function launchNonce(opts) {
163588
+ const nonce = opts.launchNonce ?? process.env[SUBC_LAUNCH_NONCE_ENV2];
163589
+ return nonce && nonce.length > 0 ? nonce : undefined;
163590
+ }
163591
+ var SUBC_LAUNCH_NONCE_ENV2 = "SUBC_LAUNCH_NONCE";
163592
+ function normalizeProviderConnectOptions(opts) {
163593
+ return {
163594
+ connectionFile: opts.connectionFile,
163595
+ manifest: opts.manifest,
163596
+ handler: opts.handler,
163597
+ health: opts.health ?? (() => ({ status: "ok" })),
163598
+ handshakeTimeoutMs: opts.handshakeTimeoutMs,
163599
+ controlOps: opts.controlOps,
163600
+ onBind: opts.onBind,
163601
+ onBound: opts.onBound,
163602
+ onRouteGone: opts.onRouteGone,
163603
+ reconnectBackoff: opts.reconnectBackoff ?? DEFAULT_RECONNECT_BACKOFF,
163604
+ sleep: opts.sleep ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms))),
163605
+ restoredDebounceMs: opts.restoredDebounceMs ?? DEFAULT_RESTORED_DEBOUNCE_MS,
163606
+ onConnectionState: opts.onConnectionState,
163607
+ launchNonce: opts.launchNonce
163608
+ };
163609
+ }
163610
+ function normalizedControlOps(controlOps) {
163611
+ if (controlOps === null)
163612
+ return null;
163613
+ const merged = new Set(controlOps ?? []);
163614
+ merged.add(HEALTH_CHECK_OP);
163615
+ return [...merged];
163616
+ }
163617
+ function buildHelloFrame(opts) {
163618
+ const nonce = launchNonce(opts);
163619
+ return buildFrame(FrameType.Hello, controlFlags(), 0, 0, HELLO_CORR, encodeJson({
163620
+ manifest: normalizeManifest(opts.manifest),
163621
+ protocol_ver: PROTOCOL_VERSION,
163622
+ control_ops: normalizedControlOps(opts.controlOps),
163623
+ ...nonce ? { launch_nonce: nonce } : {}
163624
+ }));
163625
+ }
163626
+ function isProviderReconnectTransient(err) {
163627
+ if (err instanceof SubcProviderError)
163628
+ return err.code === "duplicate_module_id";
163629
+ if (err instanceof SocketClosedError || err instanceof SocketTimeoutError)
163630
+ return true;
163631
+ if (err instanceof SocketWriteNotQueuedError || err instanceof SocketWriteQueuedError)
163632
+ return true;
163633
+ if (err instanceof AuthError)
163634
+ return true;
163635
+ if (err instanceof ConnectionFileError)
163636
+ return false;
163637
+ const code = errorCode2(err);
163638
+ return code === "ECONNREFUSED" || code === "ECONNRESET" || code === "EPIPE" || code === "ETIMEDOUT" || code === "ENOENT";
163639
+ }
163640
+ function errorCode2(err) {
163641
+ if (typeof err === "object" && err !== null && "code" in err) {
163642
+ const code = err.code;
163643
+ if (typeof code === "string")
163644
+ return code;
163645
+ }
163646
+ return;
163647
+ }
163648
+ async function pauseBeforeStateRetry() {
163649
+ await new Promise((resolve2) => setTimeout(resolve2, 0));
163650
+ }
163651
+ function controlFlags() {
163652
+ return buildFlags(false, Priority.Passive, false);
163653
+ }
163654
+ async function sendFrame(sock, frame) {
163655
+ await sock.write(encodeFrame(frame), Date.now() + WRITE_TIMEOUT_MS);
163656
+ }
163657
+ async function expectHelloAck(sock, deadline) {
163658
+ const frame = await sock.readFrame(deadline, deadline);
163659
+ switch (frame.header.ty) {
163660
+ case FrameType.HelloAck: {
163661
+ const ack = parseJson(frame.body);
163662
+ if (ack.negotiated_ver !== PROTOCOL_VERSION) {
163663
+ throw new SubcProviderError(`subc negotiated protocol ${ack.negotiated_ver}; expected exactly ${PROTOCOL_VERSION}`, "unsupported_version");
163664
+ }
163665
+ return ack;
163666
+ }
163667
+ case FrameType.Error: {
163668
+ const error51 = parseJson(frame.body);
163669
+ throw new SubcProviderError(`subc rejected HELLO: ${error51.code ?? "unknown"} — ${error51.message ?? "subc error"}`, error51.code);
163670
+ }
163671
+ default:
163672
+ throw new SubcProviderError(`unexpected frame ${FrameType[frame.header.ty]} awaiting HELLO_ACK`);
163673
+ }
163674
+ }
163675
+ function encodeJson(value) {
163676
+ return new Uint8Array(Buffer2.from(JSON.stringify(value), "utf8"));
163677
+ }
163678
+ function parseJson(bytes) {
163679
+ return JSON.parse(Buffer2.from(bytes).toString("utf8"));
163680
+ }
163681
+ function numberField(value, field) {
163682
+ if (typeof value !== "number" || !Number.isInteger(value)) {
163683
+ throw new SubcProviderError(`route.bind ${field} must be an integer`);
163684
+ }
163685
+ return value;
163686
+ }
163687
+ function bindRejection(decision) {
163688
+ if (decision === undefined || decision === true)
163689
+ return null;
163690
+ if (decision === false) {
163691
+ return { code: "route_rejected", message: "route.bind rejected by provider" };
163692
+ }
163693
+ if (decision.accept)
163694
+ return null;
163695
+ return {
163696
+ code: decision.code ?? "route_rejected",
163697
+ message: decision.message ?? "route.bind rejected by provider"
163698
+ };
163699
+ }
163700
+ function normalizeManifest(manifest) {
163701
+ return {
163702
+ module_id: manifest.module_id,
163703
+ module_version: manifest.module_version,
163704
+ protocol_ver: manifest.protocol_ver,
163705
+ trust_tier: manifest.trust_tier,
163706
+ provides: manifest.provides.map(normalizeProviderRole),
163707
+ consumes: manifest.consumes.map(normalizeConsumerRole),
163708
+ scheduled_tasks: manifest.scheduled_tasks.map(normalizeScheduledTask),
163709
+ bindings: {
163710
+ storage: {
163711
+ kind: manifest.bindings.storage.kind,
163712
+ scope: manifest.bindings.storage.scope,
163713
+ owns_schema: manifest.bindings.storage.owns_schema
163714
+ },
163715
+ vault_grants: manifest.bindings.vault_grants.map((grant) => ({
163716
+ secret: grant.secret,
163717
+ reason: grant.reason
163718
+ })),
163719
+ identity: {
163720
+ requires: [...manifest.bindings.identity.requires],
163721
+ optional: [...manifest.bindings.identity.optional]
163722
+ }
163723
+ }
163724
+ };
163725
+ }
163726
+ function normalizeProviderRole(role) {
163727
+ switch (role.role) {
163728
+ case "tool_provider":
163729
+ return {
163730
+ role: "tool_provider",
163731
+ tools: role.tools.map((tool) => ({
163732
+ name: tool.name,
163733
+ ...tool.description === undefined ? {} : { description: tool.description },
163734
+ execution_mode: tool.execution_mode,
163735
+ schema: tool.schema
163736
+ })),
163737
+ identity_scope: [...role.identity_scope],
163738
+ concurrency: role.concurrency,
163739
+ emits_push: role.emits_push,
163740
+ sub_supervises: role.sub_supervises
163741
+ };
163742
+ case "pipeline_stage":
163743
+ return {
163744
+ role: "pipeline_stage",
163745
+ stage: role.stage,
163746
+ applies_to: {
163747
+ provider: role.applies_to.provider,
163748
+ model: role.applies_to.model
163749
+ },
163750
+ interface: role.interface,
163751
+ declares_frozen_floor: role.declares_frozen_floor,
163752
+ needs_signals: [...role.needs_signals],
163753
+ conformance_class: role.conformance_class
163754
+ };
163755
+ case "management_surface":
163756
+ return {
163757
+ role: "management_surface",
163758
+ operations: role.operations.map((operation) => ({
163759
+ name: operation.name,
163760
+ kind: operation.kind
163761
+ })),
163762
+ config_schema: role.config_schema,
163763
+ observability: role.observability.map((surface) => ({
163764
+ name: surface.name,
163765
+ kind: surface.kind
163766
+ })),
163767
+ identity_scope: [...role.identity_scope]
163768
+ };
163769
+ case "internal_service":
163770
+ return {
163771
+ role: "internal_service",
163772
+ service_id: role.service_id,
163773
+ transport: role.transport,
163774
+ agent_facing: role.agent_facing,
163775
+ operations: [...role.operations]
163776
+ };
163777
+ }
163778
+ }
163779
+ function normalizeConsumerRole(role) {
163780
+ switch (role.role) {
163781
+ case "tool_client":
163782
+ return { role: "tool_client", of: [...role.of] };
163783
+ case "llm_client":
163784
+ return { role: "llm_client", via: role.via, auth: role.auth };
163785
+ case "service_client":
163786
+ return { role: "service_client", of: [...role.of] };
163787
+ }
163788
+ }
163789
+ function normalizeScheduledTask(task) {
163790
+ return {
163791
+ task_id: task.task_id,
163792
+ eligibility: {
163793
+ cooldown: task.eligibility.cooldown,
163794
+ window: task.eligibility.window
163795
+ },
163796
+ lease_scope: task.lease_scope,
163797
+ renews_during_calls: task.renews_during_calls,
163798
+ toolset: [...task.toolset],
163799
+ model_policy: {
163800
+ tier: task.model_policy.tier,
163801
+ fallback_chain: [...task.model_policy.fallback_chain]
163802
+ },
163803
+ step_cap: task.step_cap,
163804
+ circuit_breaker: {
163805
+ identical_failures: task.circuit_breaker.identical_failures
163806
+ }
163807
+ };
163808
+ }
163809
+ // ../plugin/src/features/magic-context/memory/embedding-synapse.ts
163810
+ init_logger();
163811
+ var SYNAPSE_DEFAULT_MODEL = "gte-modernbert-base-f16";
163812
+ var SYNAPSE_MAX_INPUT_TOKENS = 8192;
163813
+ var SYNAPSE_DEFAULT_QUERY_TIMEOUT_MS = 3000;
163814
+ var SYNAPSE_DEFAULT_BATCH_TIMEOUT_MS = 120000;
163815
+
163816
+ class SynapseEmbeddingError extends Error {
163817
+ code;
163818
+ retryAfterMs;
163819
+ permanent;
163820
+ constructor(code, message, options) {
163821
+ super(message, options?.cause === undefined ? undefined : { cause: options.cause });
163822
+ this.name = "SynapseEmbeddingError";
163823
+ this.code = code;
163824
+ this.permanent = options?.permanent ?? isPermanentSynapseCode(code);
163825
+ this.retryAfterMs = options?.retryAfterMs ?? (this.permanent ? undefined : 100);
163826
+ }
163827
+ }
163828
+ function isPermanentSynapseCode(code) {
163829
+ return code === "artifact_invalid" || code === "substitution_rejected" || code === "not_certified" || code === "probe_required" || code === "idempotency_conflict" || code === "schema_violation";
163830
+ }
163831
+ function asRecord(value) {
163832
+ return value !== null && typeof value === "object" ? value : null;
163833
+ }
163834
+ function responseBody(value) {
163835
+ const record2 = asRecord(value);
163836
+ const result = asRecord(record2?.result);
163837
+ return result ? { ...record2, ...result } : record2 ?? {};
163838
+ }
163839
+ function readRetryAfter(value) {
163840
+ const record2 = asRecord(value);
163841
+ const candidate = record2?.retry_after_ms ?? record2?.retryAfterMs;
163842
+ if (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0)
163843
+ return;
163844
+ return Math.ceil(candidate);
163845
+ }
163846
+ function readErrorCode(value) {
163847
+ const record2 = asRecord(value);
163848
+ if (typeof record2?.code === "string")
163849
+ return record2.code;
163850
+ if (value instanceof Error && "code" in value && typeof value.code === "string") {
163851
+ return value.code;
163852
+ }
163853
+ return;
163854
+ }
163855
+ function classifyError(value) {
163856
+ if (value instanceof SynapseEmbeddingError)
163857
+ return value;
163858
+ const code = readErrorCode(value) ?? (value instanceof Error ? value.name : "transport");
163859
+ const normalized = code.toLowerCase();
163860
+ let mapped = "transport";
163861
+ if (normalized.includes("queue_full"))
163862
+ mapped = "queue_full";
163863
+ else if (normalized.includes("model_loading"))
163864
+ mapped = "model_loading";
163865
+ else if (normalized.includes("timeout") || normalized.includes("deadline"))
163866
+ mapped = "timeout";
163867
+ else if (normalized.includes("artifact_invalid"))
163868
+ mapped = "artifact_invalid";
163869
+ else if (normalized.includes("substitution"))
163870
+ mapped = "substitution_rejected";
163871
+ else if (normalized.includes("not_certified"))
163872
+ mapped = "not_certified";
163873
+ else if (normalized.includes("probe_required"))
163874
+ mapped = "probe_required";
163875
+ else if (normalized.includes("idempotency_conflict"))
163876
+ mapped = "idempotency_conflict";
163877
+ else if (normalized.includes("schema"))
163878
+ mapped = "schema_violation";
163879
+ else if (normalized.includes("module_restarted") || normalized.includes("module restarted"))
163880
+ mapped = "module_restarted";
163881
+ const message = value instanceof Error ? value.message : String(value);
163882
+ return new SynapseEmbeddingError(mapped, message, {
163883
+ retryAfterMs: readRetryAfter(value) ?? (isPermanentSynapseCode(mapped) ? undefined : 100),
163884
+ cause: value
163885
+ });
163886
+ }
163887
+ function wait(ms) {
163888
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
163889
+ }
163890
+ function sha256(value) {
163891
+ return createHash4("sha256").update(value).digest("hex");
163892
+ }
163893
+ function stableJson(value) {
163894
+ if (Array.isArray(value))
163895
+ return `[${value.map(stableJson).join(",")}]`;
163896
+ if (value && typeof value === "object") {
163897
+ return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => `${JSON.stringify(key)}:${stableJson(entry)}`).join(",")}}`;
163898
+ }
163899
+ return JSON.stringify(value);
163900
+ }
163901
+ function getSynapseLaneIdentity(model, fingerprint) {
163902
+ return `synapse:v1:${sha256(stableJson({ model, fingerprint }))}`;
163903
+ }
163904
+ function getSynapseBatchRequestKey(args) {
163905
+ return sha256(stableJson({
163906
+ op: "embed.batch",
163907
+ model: args.model,
163908
+ required_fingerprint: args.fingerprint,
163909
+ required_epoch: args.tableEpoch,
163910
+ allow_equivalent: false,
163911
+ accept_declared: false,
163912
+ ids: args.items.map((item) => item.id),
163913
+ content_sha256: args.items.map((item) => item.contentSha256)
163914
+ }));
163915
+ }
163916
+ function hashContent(text) {
163917
+ return sha256(text);
163918
+ }
163919
+ function extractCatalogEntries(value) {
163920
+ const body = responseBody(value);
163921
+ const raw = Array.isArray(body.models) ? body.models : Array.isArray(body.entries) ? body.entries : Array.isArray(value) ? value : [];
163922
+ const envelopeEpoch = typeof body.table_epoch === "number" && Number.isInteger(body.table_epoch) ? body.table_epoch : undefined;
163923
+ return raw.flatMap((entry) => {
163924
+ const record2 = asRecord(entry);
163925
+ if (!record2)
163926
+ return [];
163927
+ const model = typeof record2.model === "string" && record2.model.length > 0 ? record2.model : typeof record2.model_id === "string" ? record2.model_id : "";
163928
+ const fingerprint = typeof record2.fingerprint === "string" && record2.fingerprint.length > 0 ? record2.fingerprint : Array.isArray(record2.fingerprints) && typeof record2.fingerprints[0] === "string" ? record2.fingerprints[0] : "";
163929
+ const entryEpoch = record2.table_epoch ?? record2.tableEpoch;
163930
+ const tableEpoch = typeof entryEpoch === "number" && Number.isInteger(entryEpoch) ? entryEpoch : envelopeEpoch;
163931
+ const dims = record2.dims ?? record2.dimensions;
163932
+ if (model.length === 0 || fingerprint.length === 0 || typeof tableEpoch !== "number" || !Number.isInteger(tableEpoch)) {
163933
+ return [];
163934
+ }
163935
+ const recommendedBatch = record2.recommended_batch ?? record2.recommendedBatch;
163936
+ const state = typeof record2.state === "string" ? record2.state : undefined;
163937
+ return [
163938
+ {
163939
+ model,
163940
+ fingerprint,
163941
+ table_epoch: tableEpoch,
163942
+ ...typeof dims === "number" && Number.isInteger(dims) && dims > 0 ? { dims } : {},
163943
+ ...typeof recommendedBatch === "number" && recommendedBatch > 0 ? { recommended_batch: Math.floor(recommendedBatch) } : {},
163944
+ ...record2.provenance !== undefined ? { provenance: record2.provenance } : {},
163945
+ ...typeof record2.certified === "boolean" ? { certified: record2.certified } : {},
163946
+ ...typeof record2.status === "string" ? { status: record2.status } : state ? { status: state } : {}
163947
+ }
163948
+ ];
163949
+ });
163950
+ }
163951
+ function extractVector(value) {
163952
+ const body = responseBody(value);
163953
+ const fromVectors = Array.isArray(body.vectors) ? asRecord(body.vectors[0])?.vector : undefined;
163954
+ const raw = fromVectors ?? body.vector ?? body.embedding;
163955
+ if (!Array.isArray(raw) || raw.some((item) => typeof item !== "number" || !Number.isFinite(item))) {
163956
+ return null;
163957
+ }
163958
+ return { vector: Float32Array.from(raw), metadata: body };
163959
+ }
163960
+ function extractBatchItems(value) {
163961
+ const body = responseBody(value);
163962
+ const raw = Array.isArray(body.vectors) ? body.vectors : Array.isArray(body.items) ? body.items : Array.isArray(body.results) ? body.results : [];
163963
+ return raw.flatMap((item) => {
163964
+ const record2 = asRecord(item);
163965
+ return record2 ? [record2] : [];
163966
+ });
163967
+ }
163968
+ var sharedClient = null;
163969
+ var sharedClientFile = null;
163970
+ var sharedClientPromise = null;
163971
+ var factoryClients = new WeakMap;
163972
+ async function getSharedClient(options) {
163973
+ if (options.clientFactory) {
163974
+ let promise2 = factoryClients.get(options.clientFactory);
163975
+ if (!promise2) {
163976
+ promise2 = options.clientFactory();
163977
+ factoryClients.set(options.clientFactory, promise2);
163978
+ }
163979
+ return promise2;
163980
+ }
163981
+ if (sharedClient && sharedClientFile === options.connectionFile)
163982
+ return sharedClient;
163983
+ if (sharedClientPromise && sharedClientFile === options.connectionFile)
163984
+ return sharedClientPromise;
163985
+ sharedClientFile = options.connectionFile;
163986
+ sharedClientPromise = SubcClient.connect({ connectionFile: options.connectionFile }).then((client) => {
163987
+ sharedClient = client;
163988
+ return client;
163989
+ });
163990
+ return sharedClientPromise;
163991
+ }
163992
+
163993
+ class SynapseEmbeddingProvider {
163994
+ modelId;
163995
+ maxInputTokens = SYNAPSE_MAX_INPUT_TOKENS;
163996
+ metadata;
163997
+ options;
163998
+ client = null;
163999
+ initialized = false;
164000
+ initializing = null;
164001
+ permanentFailure = false;
164002
+ batchLimit = 16;
164003
+ constructor(options) {
164004
+ this.options = options;
164005
+ const model = options.model || SYNAPSE_DEFAULT_MODEL;
164006
+ const fingerprint = options.fingerprint ?? "";
164007
+ this.metadata = fingerprint && Number.isInteger(options.tableEpoch) && Number.isInteger(options.dims) && (options.dims ?? 0) > 0 ? {
164008
+ model,
164009
+ fingerprint,
164010
+ table_epoch: options.tableEpoch,
164011
+ dims: options.dims,
164012
+ ...options.recommendedBatch ? { recommended_batch: Math.max(1, Math.floor(options.recommendedBatch)) } : {},
164013
+ ...options.provenance !== undefined ? { provenance: options.provenance } : {},
164014
+ laneIdentity: getSynapseLaneIdentity(model, fingerprint)
164015
+ } : null;
164016
+ this.modelId = this.metadata?.laneIdentity ?? "synapse:v1:pending";
164017
+ this.batchLimit = this.metadata?.recommended_batch ?? 16;
164018
+ }
164019
+ static async discover(options) {
164020
+ const provider = new SynapseEmbeddingProvider(options);
164021
+ if (!await provider.initialize() || !provider.metadata) {
164022
+ throw new SynapseEmbeddingError("not_certified", "Synapse lane is not ready");
164023
+ }
164024
+ return provider.metadata;
164025
+ }
164026
+ async initialize() {
164027
+ if (this.initialized)
164028
+ return true;
164029
+ if (this.permanentFailure)
164030
+ return false;
164031
+ if (this.initializing)
164032
+ return this.initializing;
164033
+ this.initializing = (async () => {
164034
+ try {
164035
+ if (!this.options.clientFactory && !await connectionFileExists(this.options.connectionFile)) {
164036
+ throw new SynapseEmbeddingError("transport", `Synapse connection file is unavailable: ${this.options.connectionFile}`);
164037
+ }
164038
+ this.client = await getSharedClient(this.options);
164039
+ if (!this.metadata) {
164040
+ const discovered = await this.callWithRetry("models.list", {}, this.options.queryTimeoutMs ?? SYNAPSE_DEFAULT_QUERY_TIMEOUT_MS, false);
164041
+ const entries = extractCatalogEntries(discovered);
164042
+ const requested = this.options.model?.trim() || SYNAPSE_DEFAULT_MODEL;
164043
+ const entry = entries.find((candidate) => candidate.model === requested);
164044
+ if (!entry) {
164045
+ throw new SynapseEmbeddingError("artifact_invalid", `Synapse models.list did not return requested model ${requested}`);
164046
+ }
164047
+ if (entry.certified === false || entry.status === "not_certified") {
164048
+ throw new SynapseEmbeddingError("not_certified", `Synapse model ${entry.model} is not certified`);
164049
+ }
164050
+ const metadata = {
164051
+ ...entry,
164052
+ laneIdentity: getSynapseLaneIdentity(entry.model, entry.fingerprint)
164053
+ };
164054
+ this.metadata = metadata;
164055
+ this.modelId = metadata.laneIdentity;
164056
+ this.batchLimit = metadata.recommended_batch ?? this.batchLimit;
164057
+ }
164058
+ this.initialized = true;
164059
+ return true;
164060
+ } catch (error51) {
164061
+ const classified = classifyError(error51);
164062
+ if (classified.permanent) {
164063
+ this.permanentFailure = true;
164064
+ log(`[magic-context] Synapse lane disabled: ${classified.code}: ${classified.message}`);
164065
+ } else {
164066
+ log(`[magic-context] Synapse lane unavailable: ${classified.message}`);
164067
+ }
164068
+ this.initialized = false;
164069
+ return false;
164070
+ } finally {
164071
+ this.initializing = null;
164072
+ }
164073
+ })();
164074
+ return this.initializing;
164075
+ }
164076
+ async embed(text, signal) {
164077
+ if (!await this.initialize() || signal?.aborted || !this.metadata)
164078
+ return null;
164079
+ try {
164080
+ const value = await this.callWithRetry("embed.query", this.requestConstraints({
164081
+ text,
164082
+ deadline_ms: this.options.queryTimeoutMs ?? SYNAPSE_DEFAULT_QUERY_TIMEOUT_MS
164083
+ }), this.options.queryTimeoutMs ?? SYNAPSE_DEFAULT_QUERY_TIMEOUT_MS, true, signal);
164084
+ const extracted = extractVector(value);
164085
+ if (!extracted)
164086
+ throw new SynapseEmbeddingError("schema_violation", "Synapse query returned no vector");
164087
+ this.validateResponse(extracted.metadata, extracted.vector.length);
164088
+ return extracted.vector;
164089
+ } catch (error51) {
164090
+ this.logCallFailure(error51, "embed.query");
164091
+ return null;
164092
+ }
164093
+ }
164094
+ async embedBatch(texts, signal) {
164095
+ if (texts.length === 0)
164096
+ return [];
164097
+ const items = texts.map((text, index) => ({
164098
+ id: `item:${index}`,
164099
+ text,
164100
+ contentSha256: hashContent(text)
164101
+ }));
164102
+ const map2 = await this.embedItems(items, signal);
164103
+ return items.map((item) => map2.get(item.id) ?? null);
164104
+ }
164105
+ async embedItems(items, signal) {
164106
+ const output = new Map;
164107
+ if (items.length === 0 || !await this.initialize() || !this.metadata || signal?.aborted) {
164108
+ return output;
164109
+ }
164110
+ for (let start = 0;start < items.length; start += this.batchLimit) {
164111
+ if (signal?.aborted || this.permanentFailure)
164112
+ break;
164113
+ const page = items.slice(start, start + this.batchLimit);
164114
+ try {
164115
+ const requestKey = this.requestKey(page);
164116
+ let body = {};
164117
+ let restarted = false;
164118
+ for (;; ) {
164119
+ try {
164120
+ body = await this.callWithRetry("embed.batch", this.batchRequest(page, requestKey), this.options.batchTimeoutMs ?? SYNAPSE_DEFAULT_BATCH_TIMEOUT_MS, true, signal);
164121
+ const first = responseBody(body);
164122
+ const jobId = typeof first.job_id === "string" ? first.job_id : null;
164123
+ if (jobId)
164124
+ body = await this.pollBatch(jobId, requestKey, signal);
164125
+ break;
164126
+ } catch (error51) {
164127
+ const classified = classifyError(error51);
164128
+ if (classified.code !== "module_restarted" || restarted)
164129
+ throw classified;
164130
+ restarted = true;
164131
+ }
164132
+ }
164133
+ const batchEnvelope = responseBody(body);
164134
+ for (const item of extractBatchItems(body)) {
164135
+ const id = typeof item.id === "string" ? item.id : "";
164136
+ const vector = item.vector ?? item.embedding;
164137
+ if (!id || !Array.isArray(vector)) {
164138
+ throw new SynapseEmbeddingError("schema_violation", "Synapse batch item is malformed");
164139
+ }
164140
+ const expected = page.find((candidate) => candidate.id === id);
164141
+ if (!expected) {
164142
+ throw new SynapseEmbeddingError("schema_violation", `Synapse returned unknown item ${id}`);
164143
+ }
164144
+ if (typeof item.content_sha256 === "string" && item.content_sha256 !== expected.contentSha256) {
164145
+ throw new SynapseEmbeddingError("artifact_invalid", `Synapse content hash mismatch for item ${id}`);
164146
+ }
164147
+ const vectorArray = Float32Array.from(vector);
164148
+ this.validateResponse({ ...batchEnvelope, ...item }, vectorArray.length);
164149
+ output.set(id, vectorArray);
164150
+ }
164151
+ } catch (error51) {
164152
+ const classified = classifyError(error51);
164153
+ this.logCallFailure(classified, "embed.batch");
164154
+ if (classified.code === "idempotency_conflict")
164155
+ throw classified;
164156
+ if (classified.permanent) {
164157
+ this.permanentFailure = true;
164158
+ this.initialized = false;
164159
+ break;
164160
+ }
164161
+ }
164162
+ }
164163
+ return output;
164164
+ }
164165
+ async dispose() {
164166
+ this.initialized = false;
164167
+ this.client = null;
164168
+ }
164169
+ isLoaded() {
164170
+ return this.initialized;
164171
+ }
164172
+ requestConstraints(extra) {
164173
+ const metadata = this.metadata;
164174
+ if (!metadata)
164175
+ return extra;
164176
+ return {
164177
+ ...extra,
164178
+ model: metadata.model,
164179
+ required_fingerprint: metadata.fingerprint,
164180
+ required_epoch: metadata.table_epoch,
164181
+ allow_equivalent: false,
164182
+ accept_declared: false
164183
+ };
164184
+ }
164185
+ batchRequest(items, requestKey) {
164186
+ return this.requestConstraints({
164187
+ items: items.map((item) => ({
164188
+ id: item.id,
164189
+ text: item.text,
164190
+ content_sha256: item.contentSha256
164191
+ })),
164192
+ request_key: requestKey
164193
+ });
164194
+ }
164195
+ requestKey(items) {
164196
+ if (!this.metadata)
164197
+ throw new SynapseEmbeddingError("transport", "Synapse metadata is unavailable");
164198
+ return getSynapseBatchRequestKey({
164199
+ model: this.metadata.model,
164200
+ fingerprint: this.metadata.fingerprint,
164201
+ tableEpoch: this.metadata.table_epoch,
164202
+ items
164203
+ });
164204
+ }
164205
+ async pollBatch(jobId, requestKey, signal) {
164206
+ let cursor = null;
164207
+ const allItems = [];
164208
+ for (;; ) {
164209
+ if (signal?.aborted)
164210
+ return {};
164211
+ const body = await this.callWithRetry("embed.result", this.requestConstraints({
164212
+ job_id: jobId,
164213
+ cursor,
164214
+ request_key: requestKey
164215
+ }), this.options.batchTimeoutMs ?? SYNAPSE_DEFAULT_BATCH_TIMEOUT_MS, true, signal);
164216
+ const parsed = responseBody(body);
164217
+ const items = extractBatchItems(body);
164218
+ allItems.push(...items);
164219
+ const nextCursor = parsed.next_cursor ?? parsed.cursor;
164220
+ const done = parsed.done === true || parsed.complete === true || nextCursor === undefined || nextCursor === null;
164221
+ if (done)
164222
+ return { ...parsed, items: allItems };
164223
+ cursor = nextCursor;
164224
+ }
164225
+ }
164226
+ async callWithRetry(method, params, timeoutMs, retryEmbeddings, signal) {
164227
+ let attempt = 0;
164228
+ for (;; ) {
164229
+ if (signal?.aborted)
164230
+ throw new SynapseEmbeddingError("transport", "Synapse request aborted");
164231
+ try {
164232
+ if (!this.client)
164233
+ throw new SynapseEmbeddingError("transport", "Synapse client is unavailable");
164234
+ return await this.client.call(this.options.moduleId ?? "synapse", method, params, {
164235
+ timeoutMs,
164236
+ targetKind: "management_surface",
164237
+ identity: {
164238
+ project_root: this.options.projectRoot,
164239
+ harness: getHarness(),
164240
+ session: this.options.session
164241
+ }
164242
+ });
164243
+ } catch (error51) {
164244
+ const classified = classifyError(error51);
164245
+ if (classified.code === "idempotency_conflict")
164246
+ throw classified;
164247
+ const outcomeUnknown = error51 instanceof SubcCallError && error51.kind === "outcome_unknown";
164248
+ const retryable = !classified.permanent && (retryEmbeddings || !outcomeUnknown);
164249
+ if (!retryable || attempt >= 3)
164250
+ throw classified;
164251
+ const delay = classified.retryAfterMs ?? Math.min(2000, 100 * 2 ** attempt);
164252
+ attempt += 1;
164253
+ await wait(delay);
164254
+ }
164255
+ }
164256
+ }
164257
+ validateResponse(body, dims) {
164258
+ const metadata = this.metadata;
164259
+ if (!metadata) {
164260
+ throw new SynapseEmbeddingError("artifact_invalid", "Synapse lane metadata missing");
164261
+ }
164262
+ if (metadata.dims === undefined) {
164263
+ const envelopeDims = body.dims;
164264
+ if (typeof envelopeDims === "number" && envelopeDims !== dims) {
164265
+ throw new SynapseEmbeddingError("artifact_invalid", `Synapse envelope declares ${envelopeDims} dimensions but the vector has ${dims}`);
164266
+ }
164267
+ metadata.dims = dims;
164268
+ }
164269
+ if (dims !== metadata.dims) {
164270
+ throw new SynapseEmbeddingError("artifact_invalid", `Synapse returned ${dims} dimensions, expected ${metadata.dims}`);
164271
+ }
164272
+ const fingerprint = body.fingerprint ?? body.served_fingerprint;
164273
+ if (typeof fingerprint !== "string") {
164274
+ throw new SynapseEmbeddingError("artifact_invalid", "Synapse response omitted the served fingerprint");
164275
+ }
164276
+ if (fingerprint !== metadata.fingerprint) {
164277
+ throw new SynapseEmbeddingError("substitution_rejected", `Synapse fingerprint changed from ${metadata.fingerprint} to ${fingerprint}`);
164278
+ }
164279
+ const epoch = body.table_epoch ?? body.tableEpoch;
164280
+ if (typeof epoch !== "number") {
164281
+ throw new SynapseEmbeddingError("artifact_invalid", "Synapse response omitted the served table epoch");
164282
+ }
164283
+ if (epoch !== metadata.table_epoch) {
164284
+ throw new SynapseEmbeddingError("substitution_rejected", `Synapse table epoch changed from ${metadata.table_epoch} to ${epoch}`);
164285
+ }
164286
+ }
164287
+ logCallFailure(error51, operation) {
164288
+ const classified = classifyError(error51);
164289
+ if (classified.permanent)
164290
+ this.permanentFailure = true;
164291
+ const suffix = classified.retryAfterMs === undefined ? "" : ` retry_after_ms=${classified.retryAfterMs}`;
164292
+ log(`[magic-context] Synapse ${operation} failed: ${classified.code}${suffix}: ${classified.message}`);
164293
+ }
164294
+ }
164295
+
164296
+ // ../plugin/src/features/magic-context/memory/normalize-hash.ts
164297
+ import { createHash as createHash5 } from "node:crypto";
161367
164298
  function normalizeMemoryContent(content) {
161368
164299
  return content.toLowerCase().replace(/\s+/g, " ").trim();
161369
164300
  }
161370
164301
  function computeNormalizedHash(content) {
161371
164302
  const normalized = normalizeMemoryContent(content);
161372
- return createHash4("md5").update(normalized).digest("hex");
164303
+ return createHash5("md5").update(normalized).digest("hex");
161373
164304
  }
161374
164305
 
161375
164306
  // ../plugin/src/features/magic-context/memory/embedding-identity.ts
@@ -161380,6 +164311,15 @@ function getEmbeddingProviderIdentity(config2) {
161380
164311
  if (config2.provider === "off") {
161381
164312
  return "embedding-provider:off";
161382
164313
  }
164314
+ if (config2.provider === "synapse") {
164315
+ const resolved = config2;
164316
+ if (!resolved.model || !resolved.synapse_fingerprint)
164317
+ return "synapse:v1:pending";
164318
+ return getSynapseLaneIdentity(resolved.model, resolved.synapse_fingerprint);
164319
+ }
164320
+ if (config2.provider !== "local" && config2.provider !== "openai-compatible") {
164321
+ throw new Error("Unknown embedding provider");
164322
+ }
161383
164323
  const truncate = config2.provider === "openai-compatible" ? config2.truncate?.trim() : undefined;
161384
164324
  const identityInput = config2.provider === "openai-compatible" ? {
161385
164325
  provider: "openai-compatible",
@@ -162169,7 +165109,7 @@ function getMemoryEmbedCoverage(db, projectPath, modelId) {
162169
165109
  }
162170
165110
 
162171
165111
  // ../plugin/src/features/magic-context/project-embedding-registry.ts
162172
- import { createHash as createHash5, randomUUID } from "node:crypto";
165112
+ import { createHash as createHash7, randomUUID } from "node:crypto";
162173
165113
  init_logger();
162174
165114
 
162175
165115
  // ../plugin/src/features/magic-context/git-commits/storage-git-commit-embeddings.ts
@@ -162622,6 +165562,37 @@ function repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectPath) {
162622
165562
  return getRepairProjectChunkProjectStatement(db).run(projectPath, projectPath).changes;
162623
165563
  }
162624
165564
 
165565
+ // ../plugin/src/features/magic-context/storage-embedding-measurements.ts
165566
+ import { createHash as createHash6 } from "node:crypto";
165567
+ function normalizedQueryHash(query) {
165568
+ const normalized = query.trim().replace(/\s+/g, " ").toLowerCase();
165569
+ return createHash6("sha256").update(normalized).digest("hex");
165570
+ }
165571
+ function recordEmbeddingMeasurement(db, input) {
165572
+ const queryTextHash = normalizedQueryHash(input.queryText);
165573
+ const dedupKey = queryTextHash;
165574
+ const result = db.prepare(`INSERT OR IGNORE INTO embedding_measurement_corpus
165575
+ (session_id, project_path, dedup_key, cohort_key, query_text_hash,
165576
+ primary_result_ids_json, shadow_result_ids_json, primary_latency_ms, shadow_latency_ms,
165577
+ primary_failed, shadow_failed, primary_model_id, shadow_model_id,
165578
+ primary_fingerprint, shadow_fingerprint, primary_epoch, shadow_epoch,
165579
+ corpus_hash, coverage_json, created_at)
165580
+ 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());
165581
+ return result.changes > 0;
165582
+ }
165583
+ function beginSynapseBatchLedger(db, input) {
165584
+ const now = Date.now();
165585
+ db.prepare(`INSERT INTO synapse_batch_ledger
165586
+ (session_id, project_path, scope, manifest_json, request_key, status, created_at, updated_at)
165587
+ VALUES (?, ?, ?, ?, ?, 'pending', ?, ?)
165588
+ ON CONFLICT(session_id, request_key) DO UPDATE SET
165589
+ manifest_json = excluded.manifest_json,
165590
+ updated_at = excluded.updated_at`).run(input.sessionId, input.projectPath, input.scope, JSON.stringify(input.manifest), input.requestKey, now, now);
165591
+ }
165592
+ function finishSynapseBatchLedger(db, sessionId, requestKey, status) {
165593
+ db.prepare("UPDATE synapse_batch_ledger SET status = ?, updated_at = ? WHERE session_id = ? AND request_key = ?").run(status, Date.now(), sessionId, requestKey);
165594
+ }
165595
+
162625
165596
  // ../plugin/src/features/magic-context/project-embedding-registry.ts
162626
165597
  var OFF_PROVIDER_IDENTITY = "embedding-provider:off";
162627
165598
  var SWEEP_MAX_WALL_CLOCK_MS = 10 * 60 * 1000;
@@ -162637,6 +165608,12 @@ var EMBED_SLICE_RETRY_BASE_MS = 250;
162637
165608
  var EMBED_SLOW_FAILURE_NO_RETRY_MS = 1e4;
162638
165609
  var MAX_CONSECUTIVE_FAILED_BATCHES = 3;
162639
165610
  var projectRegistrations = new Map;
165611
+ var shadowRegistrations = new Map;
165612
+ var shadowQueue = [];
165613
+ var shadowWorker = null;
165614
+ var SHADOW_MAX_ITEMS_PER_TICK = 64;
165615
+ var SHADOW_MAX_BYTES_PER_TICK = 512 * 1024;
165616
+ var SHADOW_MAX_WALL_CLOCK_MS = 2000;
162640
165617
  var loadUnembeddedMemoriesStatements = new WeakMap;
162641
165618
  var upsertActiveIdentityStatements = new WeakMap;
162642
165619
  var backfillActiveIdentityStatements = new Map;
@@ -162648,6 +165625,35 @@ function markProjectLoadUntrusted(projectIdentity) {
162648
165625
  untrustedLoadProjects.add(projectIdentity);
162649
165626
  }
162650
165627
  var testProviderFactory = null;
165628
+ function synapseConfigFields(config2) {
165629
+ const raw = config2;
165630
+ return {
165631
+ ...typeof raw.model === "string" ? { model: raw.model } : {},
165632
+ ...typeof raw.synapse_fingerprint === "string" ? { fingerprint: raw.synapse_fingerprint } : {},
165633
+ ...typeof raw.synapse_table_epoch === "number" ? { tableEpoch: raw.synapse_table_epoch } : {},
165634
+ ...typeof raw.synapse_dims === "number" ? { dims: raw.synapse_dims } : {},
165635
+ ...raw.synapse_provenance !== undefined ? { provenance: raw.synapse_provenance } : {}
165636
+ };
165637
+ }
165638
+ function persistPrimaryDescriptor(db, registration) {
165639
+ const descriptorTable = db.prepare("SELECT 1 AS present FROM sqlite_master WHERE type = 'table' AND name = 'embedding_registrations'").get();
165640
+ if (!descriptorTable)
165641
+ return;
165642
+ const fields = synapseConfigFields(registration.config);
165643
+ db.prepare(`INSERT INTO embedding_registrations
165644
+ (project_path, provider_identity, model_id, chunk_model_id, fingerprint, table_epoch, dims, provenance_json, generation, updated_at)
165645
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
165646
+ ON CONFLICT(project_path) DO UPDATE SET
165647
+ provider_identity = excluded.provider_identity,
165648
+ model_id = excluded.model_id,
165649
+ chunk_model_id = excluded.chunk_model_id,
165650
+ fingerprint = excluded.fingerprint,
165651
+ table_epoch = excluded.table_epoch,
165652
+ dims = excluded.dims,
165653
+ provenance_json = excluded.provenance_json,
165654
+ generation = excluded.generation,
165655
+ 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());
165656
+ }
162651
165657
  function resolveEmbeddingConfig(config2) {
162652
165658
  if (!config2 || config2.provider === "local") {
162653
165659
  return {
@@ -162676,9 +165682,26 @@ function resolveEmbeddingConfig(config2) {
162676
165682
  } : {}
162677
165683
  };
162678
165684
  }
162679
- return { provider: "off" };
165685
+ if (config2.provider === "off") {
165686
+ return { provider: "off" };
165687
+ }
165688
+ if (config2.provider === "synapse") {
165689
+ const synapse = config2;
165690
+ return {
165691
+ provider: "synapse",
165692
+ model: synapse.model?.trim() || "gte-modernbert-base-f16",
165693
+ max_input_tokens: SYNAPSE_MAX_INPUT_TOKENS,
165694
+ ...synapse.synapse_connection_file ? { synapse_connection_file: synapse.synapse_connection_file } : {},
165695
+ ...synapse.synapse_fingerprint ? { synapse_fingerprint: synapse.synapse_fingerprint } : {},
165696
+ ...typeof synapse.synapse_table_epoch === "number" ? { synapse_table_epoch: synapse.synapse_table_epoch } : {},
165697
+ ...typeof synapse.synapse_dims === "number" ? { synapse_dims: synapse.synapse_dims } : {},
165698
+ ...typeof synapse.synapse_recommended_batch === "number" ? { synapse_recommended_batch: synapse.synapse_recommended_batch } : {},
165699
+ ...synapse.synapse_provenance !== undefined ? { synapse_provenance: synapse.synapse_provenance } : {}
165700
+ };
165701
+ }
165702
+ throw new Error("Unknown embedding provider");
162680
165703
  }
162681
- function createProvider(config2) {
165704
+ function createProvider(config2, context) {
162682
165705
  if (testProviderFactory) {
162683
165706
  return testProviderFactory(config2);
162684
165707
  }
@@ -162696,7 +165719,24 @@ function createProvider(config2) {
162696
165719
  maxInputTokens: config2.max_input_tokens
162697
165720
  });
162698
165721
  }
162699
- return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
165722
+ if (config2.provider === "local") {
165723
+ return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
165724
+ }
165725
+ if (config2.provider === "synapse") {
165726
+ const synapse = config2;
165727
+ return new SynapseEmbeddingProvider({
165728
+ connectionFile: synapse.synapse_connection_file ?? "",
165729
+ projectRoot: context?.projectRoot ?? "",
165730
+ session: context?.session ?? "embedding",
165731
+ model: synapse.model,
165732
+ fingerprint: synapse.synapse_fingerprint,
165733
+ tableEpoch: synapse.synapse_table_epoch,
165734
+ dims: synapse.synapse_dims,
165735
+ recommendedBatch: synapse.synapse_recommended_batch,
165736
+ provenance: synapse.synapse_provenance
165737
+ });
165738
+ }
165739
+ throw new Error("Unknown embedding provider");
162700
165740
  }
162701
165741
  function stableStringify2(value) {
162702
165742
  if (Array.isArray(value)) {
@@ -162709,7 +165749,10 @@ function stableStringify2(value) {
162709
165749
  return JSON.stringify(value);
162710
165750
  }
162711
165751
  function sha256Prefix(value, length = 16) {
162712
- return createHash5("sha256").update(value).digest("hex").slice(0, length);
165752
+ return createHash7("sha256").update(value).digest("hex").slice(0, length);
165753
+ }
165754
+ function contentSha256(value) {
165755
+ return createHash7("sha256").update(value).digest("hex");
162713
165756
  }
162714
165757
  function getRuntimeFingerprint(config2) {
162715
165758
  if (config2.provider === "off") {
@@ -162736,6 +165779,7 @@ function snapshotFor(registration) {
162736
165779
  const providerIsOn = registration.providerIdentity !== OFF_PROVIDER_IDENTITY;
162737
165780
  const enabled = !registration.observationMode && providerIsOn && registration.features.memoryEnabled;
162738
165781
  const gitCommitEnabled = !registration.observationMode && providerIsOn && registration.features.gitCommitEnabled;
165782
+ const configuredModel = "model" in registration.config && typeof registration.config.model === "string" ? registration.config.model.trim() : "";
162739
165783
  return {
162740
165784
  projectIdentity: registration.projectIdentity,
162741
165785
  sourceDirectory: registration.sourceDirectory,
@@ -162747,7 +165791,7 @@ function snapshotFor(registration) {
162747
165791
  gitCommitEnabled,
162748
165792
  modelId: registration.observationMode || !providerIsOn ? "off" : registration.modelId,
162749
165793
  chunkModelId: registration.observationMode || !providerIsOn ? "off" : registration.chunkModelId,
162750
- model: registration.observationMode || !providerIsOn ? "off" : ("model" in registration.config) && registration.config.model.trim() ? registration.config.model.trim() : registration.modelId,
165794
+ model: registration.observationMode || !providerIsOn ? "off" : configuredModel ? configuredModel : registration.modelId,
162751
165795
  provider: registration.observationMode || !providerIsOn ? "off" : registration.config.provider ?? "local"
162752
165796
  };
162753
165797
  }
@@ -162854,9 +165898,9 @@ function getDeleteActiveIdentityStatement(db) {
162854
165898
  }
162855
165899
  return stmt;
162856
165900
  }
162857
- function staleModelsForScope(db, projectIdentity, scope, currentModelId, cutoff) {
165901
+ function staleModelsForScope(db, projectIdentity, scope, currentModelId, cutoff, protectedModelIds = new Set([currentModelId])) {
162858
165902
  const rows = getStaleIdentityStatement(db, scope).all(projectIdentity, scope, currentModelId, cutoff);
162859
- return rows.map((row) => row.modelId).filter((modelId) => typeof modelId === "string");
165903
+ return rows.map((row) => row.modelId).filter((modelId) => typeof modelId === "string" && !protectedModelIds.has(modelId));
162860
165904
  }
162861
165905
  function deleteStaleEmbeddingBatch(db, scope, projectIdentity, modelId, limit) {
162862
165906
  if (scope === "memory") {
@@ -162921,6 +165965,12 @@ function sweepStaleEmbeddingIdentitiesForProject(db, projectIdentity, now = Date
162921
165965
  return result;
162922
165966
  const cutoff = now - EMBEDDING_IDENTITY_GC_GRACE_MS;
162923
165967
  const deleteTracking = getDeleteActiveIdentityStatement(db);
165968
+ const shadow = shadowRegistrations.get(projectIdentity);
165969
+ const protectedModels = {
165970
+ memory: new Set([snapshot.modelId, ...shadow ? [shadow.modelId] : []]),
165971
+ commit: new Set([snapshot.modelId, ...shadow ? [shadow.modelId] : []]),
165972
+ chunk: new Set([snapshot.chunkModelId, ...shadow ? [shadow.chunkModelId] : []])
165973
+ };
162924
165974
  const scopes = [
162925
165975
  {
162926
165976
  scope: "memory",
@@ -162944,7 +165994,7 @@ function sweepStaleEmbeddingIdentitiesForProject(db, projectIdentity, now = Date
162944
165994
  for (const { scope, enabled, currentModelId } of scopes) {
162945
165995
  if (!enabled || remainingBudget === 0)
162946
165996
  continue;
162947
- for (const modelId of staleModelsForScope(db, projectIdentity, scope, currentModelId, cutoff)) {
165997
+ for (const modelId of staleModelsForScope(db, projectIdentity, scope, currentModelId, cutoff, protectedModels[scope])) {
162948
165998
  if (remainingBudget === 0)
162949
165999
  break;
162950
166000
  const deleted = deleteStaleEmbeddingBatch(db, scope, projectIdentity, modelId, remainingBudget);
@@ -162998,11 +166048,206 @@ function registerProjectEmbedding(db, projectIdentity, config2, features, source
162998
166048
  observationMode: false
162999
166049
  };
163000
166050
  projectRegistrations.set(projectIdentity, registration);
166051
+ persistPrimaryDescriptor(db, registration);
163001
166052
  if (!canReuseProvider) {
163002
166053
  disposeProvider(prior?.provider ?? null);
163003
166054
  }
163004
166055
  return snapshotFor(registration);
163005
166056
  }
166057
+ function startShadowWorker() {
166058
+ if (shadowWorker)
166059
+ return;
166060
+ shadowWorker = runShadowWorker().finally(() => {
166061
+ shadowWorker = null;
166062
+ if (shadowQueue.length > 0)
166063
+ startShadowWorker();
166064
+ });
166065
+ }
166066
+ function getShadowEmbeddingMeasurementCohort(projectIdentity) {
166067
+ const registration = shadowRegistrations.get(projectIdentity);
166068
+ if (!registration)
166069
+ return null;
166070
+ const fields = synapseConfigFields(registration.config);
166071
+ return {
166072
+ modelId: registration.modelId,
166073
+ chunkModelId: registration.chunkModelId,
166074
+ fingerprint: fields.fingerprint ?? "",
166075
+ epoch: fields.tableEpoch ?? 0,
166076
+ dims: fields.dims ?? 0
166077
+ };
166078
+ }
166079
+ function getPrimaryEmbeddingMeasurementCohort(projectIdentity) {
166080
+ const registration = projectRegistrations.get(projectIdentity);
166081
+ if (!registration)
166082
+ return null;
166083
+ const fields = synapseConfigFields(registration.config);
166084
+ return {
166085
+ modelId: registration.modelId,
166086
+ chunkModelId: registration.chunkModelId,
166087
+ fingerprint: fields.fingerprint ?? "",
166088
+ epoch: fields.tableEpoch ?? 0,
166089
+ dims: fields.dims ?? 0
166090
+ };
166091
+ }
166092
+ async function embedShadowTextForProject(projectIdentity, text, signal) {
166093
+ const registration = shadowRegistrations.get(projectIdentity);
166094
+ if (!registration)
166095
+ return null;
166096
+ try {
166097
+ return await registration.provider.embed(text, signal, "query");
166098
+ } catch (error51) {
166099
+ log("[magic-context] Synapse shadow query failed:", error51);
166100
+ return null;
166101
+ }
166102
+ }
166103
+ function enqueueShadowEmbeddingItems(projectIdentity, scope, ids) {
166104
+ if (ids.length === 0 || !shadowRegistrations.has(projectIdentity))
166105
+ return;
166106
+ shadowQueue.push({ projectIdentity, scope, ids: [...ids] });
166107
+ startShadowWorker();
166108
+ }
166109
+ async function embedShadowItems(registration, items, db, scope) {
166110
+ const raw = registration.config;
166111
+ const fingerprint = typeof raw.synapse_fingerprint === "string" ? raw.synapse_fingerprint : "";
166112
+ const tableEpoch = typeof raw.synapse_table_epoch === "number" ? raw.synapse_table_epoch : 0;
166113
+ const requestKey = getSynapseBatchRequestKey({
166114
+ model: typeof raw.model === "string" ? raw.model : SYNAPSE_DEFAULT_MODEL,
166115
+ fingerprint,
166116
+ tableEpoch,
166117
+ items
166118
+ });
166119
+ beginSynapseBatchLedger(db, {
166120
+ sessionId: `shadow:${registration.projectIdentity}`,
166121
+ projectPath: registration.projectIdentity,
166122
+ scope,
166123
+ manifest: items.map(({ id, contentSha256: contentSha2562 }) => ({ id, contentSha256: contentSha2562 })),
166124
+ requestKey
166125
+ });
166126
+ try {
166127
+ if (registration.provider.embedItems) {
166128
+ const vectors2 = await registration.provider.embedItems(items);
166129
+ finishSynapseBatchLedger(db, `shadow:${registration.projectIdentity}`, requestKey, vectors2.size === items.length ? "complete" : "partial");
166130
+ return vectors2;
166131
+ }
166132
+ const positional = await registration.provider.embedBatch(items.map((item) => item.text));
166133
+ const vectors = new Map(items.flatMap((item, index) => {
166134
+ const vector = positional[index];
166135
+ return vector ? [[item.id, vector]] : [];
166136
+ }));
166137
+ finishSynapseBatchLedger(db, `shadow:${registration.projectIdentity}`, requestKey, vectors.size === items.length ? "complete" : "partial");
166138
+ return vectors;
166139
+ } catch (error51) {
166140
+ finishSynapseBatchLedger(db, `shadow:${registration.projectIdentity}`, requestKey, "failed");
166141
+ throw error51;
166142
+ }
166143
+ }
166144
+ async function processShadowQueueItem(item) {
166145
+ const registration = shadowRegistrations.get(item.projectIdentity);
166146
+ if (!registration)
166147
+ return;
166148
+ const boundedIds = item.ids.slice(0, SHADOW_MAX_ITEMS_PER_TICK);
166149
+ if (item.scope === "memory") {
166150
+ const db2 = dbForShadowQueue.get(item.projectIdentity);
166151
+ if (!db2)
166152
+ return;
166153
+ const placeholders3 = boundedIds.map(() => "?").join(",");
166154
+ const rows = db2.prepare(`SELECT id, content, normalized_hash FROM memories
166155
+ WHERE project_path = ? AND id IN (${placeholders3}) AND status = 'active'`).all(item.projectIdentity, ...boundedIds.map((id) => Number(id)));
166156
+ const vectors2 = await embedShadowItems(registration, rows.map((row) => ({
166157
+ id: `memory:${row.id}`,
166158
+ text: row.content,
166159
+ contentSha256: contentSha256(row.content)
166160
+ })), db2, "memory");
166161
+ db2.transaction(() => {
166162
+ for (const row of rows) {
166163
+ const vector = vectors2.get(`memory:${row.id}`);
166164
+ if (vector)
166165
+ saveEmbeddingIfHashMatches(db2, row.id, vector, registration.modelId, row.normalized_hash);
166166
+ }
166167
+ })();
166168
+ return;
166169
+ }
166170
+ if (item.scope === "commit") {
166171
+ const db2 = dbForShadowQueue.get(item.projectIdentity);
166172
+ if (!db2)
166173
+ return;
166174
+ const placeholders3 = boundedIds.map(() => "?").join(",");
166175
+ const rows = db2.prepare(`SELECT sha, message FROM git_commits WHERE project_path = ? AND sha IN (${placeholders3})`).all(item.projectIdentity, ...boundedIds);
166176
+ const vectors2 = await embedShadowItems(registration, rows.map((row) => ({
166177
+ id: `commit:${row.sha}`,
166178
+ text: row.message,
166179
+ contentSha256: contentSha256(row.message)
166180
+ })), db2, "commit");
166181
+ db2.transaction(() => {
166182
+ for (const row of rows) {
166183
+ const vector = vectors2.get(`commit:${row.sha}`);
166184
+ if (vector)
166185
+ saveCommitEmbedding(db2, row.sha, vector, registration.modelId);
166186
+ }
166187
+ })();
166188
+ return;
166189
+ }
166190
+ const db = dbForShadowQueue.get(item.projectIdentity);
166191
+ if (!db)
166192
+ return;
166193
+ const placeholders2 = boundedIds.map(() => "?").join(",");
166194
+ const candidates = db.prepare(`SELECT id, session_id, start_message, end_message
166195
+ FROM compartments WHERE id IN (${placeholders2})`).all(...boundedIds.map((id) => Number(id)));
166196
+ const prepared = candidates.flatMap((candidate) => {
166197
+ const text = buildCanonicalChunkTextFromFts(db, candidate.session_id, candidate.start_message, candidate.end_message) || buildCompartmentSummaryFallbackText(db, candidate.id);
166198
+ if (!text)
166199
+ return [];
166200
+ const windows = chunkCanonicalText(text, candidate.start_message, candidate.end_message, SYNAPSE_MAX_INPUT_TOKENS);
166201
+ return windows.length > 0 ? [{ candidate, windows }] : [];
166202
+ });
166203
+ const items = prepared.flatMap((item2) => item2.windows.map((window) => ({
166204
+ id: `chunk:${item2.candidate.id}:${window.windowIndex}`,
166205
+ text: window.text,
166206
+ contentSha256: contentSha256(window.text)
166207
+ })));
166208
+ const vectors = await embedShadowItems(registration, items, db, "chunk");
166209
+ for (const item2 of prepared) {
166210
+ const rows = item2.windows.flatMap((window) => {
166211
+ const vector = vectors.get(`chunk:${item2.candidate.id}:${window.windowIndex}`);
166212
+ return vector ? [
166213
+ {
166214
+ compartmentId: item2.candidate.id,
166215
+ sessionId: item2.candidate.session_id,
166216
+ projectPath: registration.projectIdentity,
166217
+ window,
166218
+ modelId: registration.chunkModelId,
166219
+ vector
166220
+ }
166221
+ ] : [];
166222
+ });
166223
+ if (rows.length === item2.windows.length)
166224
+ replaceCompartmentChunkEmbeddings(db, rows);
166225
+ }
166226
+ }
166227
+ var dbForShadowQueue = new Map;
166228
+ async function runShadowWorker() {
166229
+ const startedAt = Date.now();
166230
+ let processed = 0;
166231
+ let processedBytes = 0;
166232
+ while (shadowQueue.length > 0 && processed < SHADOW_MAX_ITEMS_PER_TICK && Date.now() - startedAt < SHADOW_MAX_WALL_CLOCK_MS) {
166233
+ const item = shadowQueue.shift();
166234
+ if (!item)
166235
+ break;
166236
+ const itemBytes = item.ids.reduce((total, id) => total + id.length, 0);
166237
+ if (processed > 0 && processedBytes + itemBytes > SHADOW_MAX_BYTES_PER_TICK) {
166238
+ shadowQueue.unshift(item);
166239
+ break;
166240
+ }
166241
+ try {
166242
+ await processShadowQueueItem(item);
166243
+ } catch (error51) {
166244
+ log("[magic-context] Synapse shadow write failed:", error51);
166245
+ }
166246
+ processed += item.ids.length;
166247
+ processedBytes += itemBytes;
166248
+ await new Promise((resolve2) => setTimeout(resolve2, 0));
166249
+ }
166250
+ }
163006
166251
  function registerProjectInObservationMode(db, projectIdentity, sourceDirectory, failedConfig, failureSummary) {
163007
166252
  const prior = projectRegistrations.get(projectIdentity);
163008
166253
  const runtimeFingerprint = `observation:${sha256Prefix(failureSummary)}`;
@@ -163044,7 +166289,10 @@ function getOrCreateProjectProvider(registration) {
163044
166289
  if (registration.provider) {
163045
166290
  return registration.provider;
163046
166291
  }
163047
- const provider = createProvider(registration.config);
166292
+ const provider = createProvider(registration.config, {
166293
+ projectRoot: registration.sourceDirectory,
166294
+ session: `project:${registration.projectIdentity}`
166295
+ });
163048
166296
  registration.provider = provider;
163049
166297
  return provider;
163050
166298
  }
@@ -163064,7 +166312,7 @@ async function embedTextForProject(projectIdentity, text, signal, purpose = "pas
163064
166312
  if (!current || current.generation !== generation || current.runtimeFingerprint !== registration.runtimeFingerprint) {
163065
166313
  return null;
163066
166314
  }
163067
- return { vector, modelId, generation };
166315
+ return { vector, modelId, chunkModelId: registration.chunkModelId, generation };
163068
166316
  }
163069
166317
  async function embedBatchForProject(projectIdentity, texts, signal, purpose = "passage") {
163070
166318
  if (texts.length === 0) {
@@ -163089,31 +166337,81 @@ async function embedBatchForProject(projectIdentity, texts, signal, purpose = "p
163089
166337
  }
163090
166338
  return { vectors, modelId, generation };
163091
166339
  }
163092
- async function embedTextsWindowBounded(projectIdentity, texts, signal) {
163093
- if (texts.length <= MAX_WINDOWS_PER_EMBED_CALL) {
163094
- return embedBatchForProject(projectIdentity, texts, signal);
166340
+ async function embedItemsForProject(projectIdentity, items, signal, db, sessionId = projectIdentity) {
166341
+ const registration = projectRegistrations.get(projectIdentity);
166342
+ if (!registration || registration.observationMode || items.length === 0)
166343
+ return null;
166344
+ const generation = registration.generation;
166345
+ const modelId = registration.modelId;
166346
+ const runtimeFingerprint = registration.runtimeFingerprint;
166347
+ const provider = getOrCreateProjectProvider(registration);
166348
+ if (!provider)
166349
+ return null;
166350
+ const rawConfig = registration.config;
166351
+ const fingerprint = typeof rawConfig.synapse_fingerprint === "string" ? rawConfig.synapse_fingerprint : "";
166352
+ const tableEpoch = typeof rawConfig.synapse_table_epoch === "number" ? rawConfig.synapse_table_epoch : undefined;
166353
+ const isSynapse = registration.providerIdentity.startsWith("synapse:v1:") && fingerprint && tableEpoch !== undefined;
166354
+ const ledgerKey = isSynapse ? getSynapseBatchRequestKey({
166355
+ model: typeof rawConfig.model === "string" ? rawConfig.model : registration.modelId,
166356
+ fingerprint,
166357
+ tableEpoch,
166358
+ items
166359
+ }) : null;
166360
+ if (db && ledgerKey) {
166361
+ beginSynapseBatchLedger(db, {
166362
+ sessionId,
166363
+ projectPath: projectIdentity,
166364
+ scope: items[0].id.split(":", 1)[0],
166365
+ manifest: items.map(({ id, contentSha256: contentSha2562 }) => ({ id, contentSha256: contentSha2562 })),
166366
+ requestKey: ledgerKey
166367
+ });
163095
166368
  }
163096
- const vectors = [];
166369
+ let vectors;
166370
+ try {
166371
+ if (provider.embedItems) {
166372
+ vectors = await provider.embedItems(items, signal);
166373
+ } else {
166374
+ const positional = await provider.embedBatch(items.map((item) => item.text), signal, "passage");
166375
+ vectors = new Map(items.flatMap((item, index) => {
166376
+ const vector = positional[index];
166377
+ return vector ? [[item.id, vector]] : [];
166378
+ }));
166379
+ }
166380
+ } catch (error51) {
166381
+ if (db && ledgerKey)
166382
+ finishSynapseBatchLedger(db, sessionId, ledgerKey, "failed");
166383
+ throw error51;
166384
+ }
166385
+ if (db && ledgerKey) {
166386
+ finishSynapseBatchLedger(db, sessionId, ledgerKey, vectors.size === items.length ? "complete" : "partial");
166387
+ }
166388
+ const current = projectRegistrations.get(projectIdentity);
166389
+ if (!current || current.generation !== generation || current.runtimeFingerprint !== runtimeFingerprint) {
166390
+ return null;
166391
+ }
166392
+ return { vectors, modelId, generation };
166393
+ }
166394
+ async function embedItemsWindowBounded(projectIdentity, items, signal, db) {
166395
+ if (items.length <= MAX_WINDOWS_PER_EMBED_CALL) {
166396
+ return embedItemsForProject(projectIdentity, items, signal, db, projectIdentity);
166397
+ }
166398
+ const vectors = new Map;
163097
166399
  let modelId = null;
163098
166400
  let generation = null;
163099
- for (let start = 0;start < texts.length; start += MAX_WINDOWS_PER_EMBED_CALL) {
163100
- if (signal?.aborted)
163101
- return null;
163102
- const sub = texts.slice(start, start + MAX_WINDOWS_PER_EMBED_CALL);
163103
- const result = await embedBatchForProject(projectIdentity, sub, signal);
166401
+ for (let start = 0;start < items.length; start += MAX_WINDOWS_PER_EMBED_CALL) {
166402
+ const result = await embedItemsForProject(projectIdentity, items.slice(start, start + MAX_WINDOWS_PER_EMBED_CALL), signal, db, projectIdentity);
163104
166403
  if (!result)
163105
166404
  return null;
163106
166405
  if (modelId === null) {
163107
166406
  modelId = result.modelId;
163108
166407
  generation = result.generation;
163109
- } else if (result.modelId !== modelId || result.generation !== generation) {
166408
+ } else if (modelId !== result.modelId || generation !== result.generation) {
163110
166409
  return null;
163111
166410
  }
163112
- vectors.push(...result.vectors);
166411
+ for (const [id, vector] of result.vectors)
166412
+ vectors.set(id, vector);
163113
166413
  }
163114
- if (modelId === null || generation === null)
163115
- return null;
163116
- return { vectors, modelId, generation };
166414
+ return modelId === null || generation === null ? null : { vectors, modelId, generation };
163117
166415
  }
163118
166416
  function isUnembeddedMemoryRow(row) {
163119
166417
  if (row === null || typeof row !== "object")
@@ -163138,13 +166436,17 @@ async function embedUnembeddedMemoriesForProject(db, projectIdentity, batchSize
163138
166436
  if (memories.length === 0)
163139
166437
  return 0;
163140
166438
  try {
163141
- const result = await embedBatchForProject(projectIdentity, memories.map((memory) => memory.content));
166439
+ const result = await embedItemsForProject(projectIdentity, memories.map((memory) => ({
166440
+ id: `memory:${memory.id}`,
166441
+ text: memory.content,
166442
+ contentSha256: contentSha256(memory.content)
166443
+ })), undefined, db, projectIdentity);
163142
166444
  if (!result)
163143
166445
  return 0;
163144
166446
  let embeddedCount = 0;
163145
166447
  db.transaction(() => {
163146
- for (const [index, memory] of memories.entries()) {
163147
- const embedding = result.vectors[index];
166448
+ for (const memory of memories) {
166449
+ const embedding = result.vectors.get(`memory:${memory.id}`);
163148
166450
  if (!embedding)
163149
166451
  continue;
163150
166452
  if (saveEmbeddingIfHashMatches(db, memory.id, embedding, result.modelId, memory.normalized_hash)) {
@@ -163152,6 +166454,7 @@ async function embedUnembeddedMemoriesForProject(db, projectIdentity, batchSize
163152
166454
  }
163153
166455
  }
163154
166456
  })();
166457
+ enqueueShadowEmbeddingItems(projectIdentity, "memory", memories.filter((memory) => result.vectors.has(`memory:${memory.id}`)).map((memory) => String(memory.id)));
163155
166458
  return embeddedCount;
163156
166459
  } catch (error51) {
163157
166460
  log("[magic-context] failed to proactively embed missing memories:", error51);
@@ -163165,19 +166468,24 @@ async function embedCommitBatch(db, projectIdentity, batchSize) {
163165
166468
  const commits = loadUnembeddedCommits(db, projectIdentity, snapshot.modelId, Math.max(1, Math.floor(batchSize)));
163166
166469
  if (commits.length === 0)
163167
166470
  return 0;
163168
- const result = await embedBatchForProject(projectIdentity, commits.map((commit) => commit.message));
166471
+ const result = await embedItemsForProject(projectIdentity, commits.map((commit) => ({
166472
+ id: `commit:${commit.sha}`,
166473
+ text: commit.message,
166474
+ contentSha256: contentSha256(commit.message)
166475
+ })), undefined, db, projectIdentity);
163169
166476
  if (!result)
163170
166477
  return 0;
163171
166478
  let embeddedCount = 0;
163172
166479
  db.transaction(() => {
163173
- for (const [index, commit] of commits.entries()) {
163174
- const embedding = result.vectors[index];
166480
+ for (const commit of commits) {
166481
+ const embedding = result.vectors.get(`commit:${commit.sha}`);
163175
166482
  if (!embedding)
163176
166483
  continue;
163177
166484
  saveCommitEmbedding(db, commit.sha, embedding, result.modelId);
163178
166485
  embeddedCount += 1;
163179
166486
  }
163180
166487
  })();
166488
+ enqueueShadowEmbeddingItems(projectIdentity, "commit", commits.filter((commit) => result.vectors.has(`commit:${commit.sha}`)).map((commit) => commit.sha));
163181
166489
  return embeddedCount;
163182
166490
  }
163183
166491
  async function drainCommitBacklogForProject(db, projectIdentity, deadline) {
@@ -163250,9 +166558,11 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
163250
166558
  windowCount += item.windows.length;
163251
166559
  i += 1;
163252
166560
  } while (i < prepared.length && windowCount + prepared[i].windows.length <= MAX_WINDOWS_PER_EMBED_CALL);
163253
- const texts = [];
163254
- for (const item of slice)
163255
- texts.push(...item.windows.map((w) => w.text));
166561
+ const items = slice.flatMap((item) => item.windows.map((window) => ({
166562
+ id: `chunk:${item.candidate.id}:${window.windowIndex}`,
166563
+ text: window.text,
166564
+ contentSha256: contentSha256(window.text)
166565
+ })));
163256
166566
  const persistedIds = new Set;
163257
166567
  for (let attempt = 0;attempt < EMBED_SLICE_RETRY_ATTEMPTS; attempt++) {
163258
166568
  if (signal?.aborted)
@@ -163260,19 +166570,17 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
163260
166570
  let result = null;
163261
166571
  const attemptStart = Date.now();
163262
166572
  try {
163263
- result = await embedTextsWindowBounded(projectIdentity, texts, signal);
166573
+ result = await embedItemsWindowBounded(projectIdentity, items, signal, db);
163264
166574
  } catch (error51) {
163265
166575
  log("[magic-context] failed to proactively embed compartment chunks:", error51);
163266
166576
  }
163267
166577
  if (signal?.aborted)
163268
166578
  break;
163269
166579
  if (result) {
163270
- let offset = 0;
163271
166580
  for (const item of slice) {
163272
- const vectors = result.vectors.slice(offset, offset + item.windows.length);
163273
- offset += item.windows.length;
163274
166581
  if (persistedIds.has(item.candidate.id))
163275
166582
  continue;
166583
+ const vectors = item.windows.map((window) => result.vectors.get(`chunk:${item.candidate.id}:${window.windowIndex}`));
163276
166584
  if (vectors.length !== item.windows.length || vectors.some((v) => !v)) {
163277
166585
  continue;
163278
166586
  }
@@ -163286,6 +166594,9 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
163286
166594
  }));
163287
166595
  replaceCompartmentChunkEmbeddings(db, rows);
163288
166596
  persistedIds.add(item.candidate.id);
166597
+ enqueueShadowEmbeddingItems(projectIdentity, "chunk", [
166598
+ String(item.candidate.id)
166599
+ ]);
163289
166600
  }
163290
166601
  }
163291
166602
  if (persistedIds.size === slice.length)
@@ -163454,7 +166765,24 @@ function createProvider2(config2) {
163454
166765
  maxInputTokens: config2.max_input_tokens
163455
166766
  });
163456
166767
  }
163457
- return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
166768
+ if (config2.provider === "local") {
166769
+ return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
166770
+ }
166771
+ if (config2.provider === "synapse") {
166772
+ const synapse = config2;
166773
+ return new SynapseEmbeddingProvider({
166774
+ connectionFile: synapse.synapse_connection_file ?? "",
166775
+ projectRoot: "",
166776
+ session: "embedding",
166777
+ model: synapse.model,
166778
+ fingerprint: synapse.synapse_fingerprint,
166779
+ tableEpoch: synapse.synapse_table_epoch,
166780
+ dims: synapse.synapse_dims,
166781
+ recommendedBatch: synapse.synapse_recommended_batch,
166782
+ provenance: synapse.synapse_provenance
166783
+ });
166784
+ }
166785
+ throw new Error("Unknown embedding provider");
163458
166786
  }
163459
166787
  function getOrCreateProvider() {
163460
166788
  if (provider) {
@@ -163479,7 +166807,7 @@ async function embedText(text, signal) {
163479
166807
  var SWEEP_MAX_WALL_CLOCK_MS2 = 10 * 60 * 1000;
163480
166808
 
163481
166809
  // ../plugin/src/plugin/embedding-bootstrap-helpers.ts
163482
- import { createHash as createHash6 } from "node:crypto";
166810
+ import { createHash as createHash8 } from "node:crypto";
163483
166811
  init_logger();
163484
166812
  var EMBEDDING_AFFECTING_KEYS = new Set([
163485
166813
  "embedding.api_key",
@@ -163489,7 +166817,11 @@ var EMBEDDING_AFFECTING_KEYS = new Set([
163489
166817
  "embedding.input_type",
163490
166818
  "embedding.truncate",
163491
166819
  "embedding.max_input_tokens",
163492
- "embedding.query_input_type"
166820
+ "embedding.query_input_type",
166821
+ "embedding.fallback_provider",
166822
+ "subc",
166823
+ "subc.connection_file",
166824
+ "shadow_embedding"
163493
166825
  ]);
163494
166826
  var LITERAL_CONFIG_TOKEN_RE = /\{(?:env|file):[^}]+\}/;
163495
166827
  function embeddingConfigHasLiteralTokens(embedding) {
@@ -163502,7 +166834,13 @@ function embeddingConfigHasLiteralTokens(embedding) {
163502
166834
  }
163503
166835
  return false;
163504
166836
  }
163505
- var EMBEDDING_AFFECTING_TOP_LEVEL_KEYS = new Set(["embedding", "memory", "experimental"]);
166837
+ var EMBEDDING_AFFECTING_TOP_LEVEL_KEYS = new Set([
166838
+ "embedding",
166839
+ "memory",
166840
+ "experimental",
166841
+ "subc",
166842
+ "shadow_embedding"
166843
+ ]);
163506
166844
  var EMBEDDING_WARNING_TERMS = [
163507
166845
  "api_key",
163508
166846
  "endpoint",
@@ -163510,11 +166848,13 @@ var EMBEDDING_WARNING_TERMS = [
163510
166848
  "provider",
163511
166849
  "embedding",
163512
166850
  "input_type",
163513
- "truncate"
166851
+ "truncate",
166852
+ "subc",
166853
+ "shadow_embedding"
163514
166854
  ];
163515
166855
  var loggedFailureSignatures = new Map;
163516
166856
  function sha256Prefix2(value, length = 16) {
163517
- return createHash6("sha256").update(value).digest("hex").slice(0, length);
166857
+ return createHash8("sha256").update(value).digest("hex").slice(0, length);
163518
166858
  }
163519
166859
  function warningLooksEmbeddingRelated(message) {
163520
166860
  const lower = message.toLowerCase();
@@ -163689,7 +167029,7 @@ function clearCompressionDepthRange(db, sessionId, startOrdinal, endOrdinal) {
163689
167029
  }
163690
167030
 
163691
167031
  // ../plugin/src/features/magic-context/storage-meta-shared.ts
163692
- import { Buffer as Buffer2 } from "node:buffer";
167032
+ import { Buffer as Buffer3 } from "node:buffer";
163693
167033
  var SESSION_META_SELECT_COLUMNS = [
163694
167034
  "session_id",
163695
167035
  "last_response_time",
@@ -163822,14 +167162,14 @@ function isNumberOrNull(value) {
163822
167162
  return value === null || typeof value === "number";
163823
167163
  }
163824
167164
  function isBlobOrNull(value) {
163825
- return value === null || Buffer2.isBuffer(value) || value instanceof Uint8Array;
167165
+ return value === null || Buffer3.isBuffer(value) || value instanceof Uint8Array;
163826
167166
  }
163827
167167
  function toBufferOrNull(value) {
163828
167168
  if (value === null)
163829
167169
  return null;
163830
- if (Buffer2.isBuffer(value))
167170
+ if (Buffer3.isBuffer(value))
163831
167171
  return value;
163832
- return Buffer2.from(value.buffer, value.byteOffset, value.byteLength);
167172
+ return Buffer3.from(value.buffer, value.byteOffset, value.byteLength);
163833
167173
  }
163834
167174
  function isSessionMetaRow(row) {
163835
167175
  if (row === null || typeof row !== "object")
@@ -163974,7 +167314,7 @@ function persistCachedM0(db, sessionId, payload) {
163974
167314
  cached_m0_system_hash = ?,
163975
167315
  cached_m0_model_key = ?,
163976
167316
  cached_m0_project_identity = ?
163977
- WHERE session_id = ?`).run(Buffer2.from(payload.m0Bytes), payload.projectMemoryEpoch, payload.workspaceFingerprint ?? null, payload.projectUserProfileVersion, payload.maxCompartmentSeq, payload.maxMemoryId, payload.maxMutationId, payload.maxMemoryMutationId ?? null, payload.m1Bytes ? Buffer2.from(payload.m1Bytes) : null, payload.projectDocsHash, payload.materializedAt, payload.sessionFactsVersion, payload.upgradeState, payload.systemHash ?? "", payload.modelKey ?? "", payload.projectIdentity ?? null, sessionId);
167317
+ WHERE session_id = ?`).run(Buffer3.from(payload.m0Bytes), payload.projectMemoryEpoch, payload.workspaceFingerprint ?? null, payload.projectUserProfileVersion, payload.maxCompartmentSeq, payload.maxMemoryId, payload.maxMutationId, payload.maxMemoryMutationId ?? null, payload.m1Bytes ? Buffer3.from(payload.m1Bytes) : null, payload.projectDocsHash, payload.materializedAt, payload.sessionFactsVersion, payload.upgradeState, payload.systemHash ?? "", payload.modelKey ?? "", payload.projectIdentity ?? null, sessionId);
163978
167318
  }
163979
167319
  function clearCachedM0M1(db, sessionId) {
163980
167320
  ensureSessionMetaRow(db, sessionId);
@@ -171029,7 +174369,7 @@ function indexMessagesAfterOrdinal(db, sessionId, messages, _lastIndexedOrdinal,
171029
174369
  return inserted;
171030
174370
  }
171031
174371
  // ../plugin/src/features/magic-context/project-docs-hash.ts
171032
- import { createHash as createHash7 } from "node:crypto";
174372
+ import { createHash as createHash9 } from "node:crypto";
171033
174373
  import { lstatSync, readFileSync as readFileSync5, statSync as statSync5 } from "node:fs";
171034
174374
  import path5 from "node:path";
171035
174375
  var PROJECT_DOC_FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
@@ -171127,7 +174467,7 @@ function hashCanonicalPieces(hashPieces) {
171127
174467
  if (hashPieces.length === 0) {
171128
174468
  return "";
171129
174469
  }
171130
- return createHash7("sha256").update(hashPieces.join(PROJECT_DOCS_DELIMITER), "utf8").digest("hex");
174470
+ return createHash9("sha256").update(hashPieces.join(PROJECT_DOCS_DELIMITER), "utf8").digest("hex");
171131
174471
  }
171132
174472
  function readProjectDocsCanonical(projectDirectory) {
171133
174473
  const canonicalDirectory = path5.resolve(projectDirectory);
@@ -171172,14 +174512,19 @@ function countRows(db, table, sessionId) {
171172
174512
  const row = db.prepare(`SELECT COUNT(*) AS count FROM ${table} WHERE session_id = ?`).get(sessionId);
171173
174513
  return typeof row?.count === "number" ? row.count : 0;
171174
174514
  }
171175
- function filterIdBlob(raw, includeMessageId) {
174515
+ function mapMessageId(filter, messageId) {
174516
+ if (messageId === null)
174517
+ return null;
174518
+ return filter.mapMessageId?.(messageId) ?? messageId;
174519
+ }
174520
+ function filterIdBlob(raw, filter) {
171176
174521
  if (!raw)
171177
174522
  return "";
171178
174523
  try {
171179
174524
  const value = JSON.parse(raw);
171180
174525
  if (!Array.isArray(value))
171181
174526
  return "";
171182
- const filtered = value.filter((id) => typeof id === "string" && includeMessageId(id));
174527
+ const filtered = value.filter((id) => typeof id === "string" && filter.includeMessageId(id)).map((id) => mapMessageId(filter, id));
171183
174528
  return filtered.length > 0 ? JSON.stringify(filtered) : "";
171184
174529
  } catch {
171185
174530
  return "";
@@ -171216,16 +174561,16 @@ function copySessionStateForClone(db, sourceSessionId, destinationSessionId, fil
171216
174561
  const endMessage = filter.resolveBoundaryOrdinal(row.end_message_id);
171217
174562
  if (startMessage === undefined || endMessage === undefined)
171218
174563
  continue;
171219
- 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);
174564
+ 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);
171220
174565
  copiedCompartments.push({
171221
174566
  sequence: row.sequence,
171222
174567
  startMessage,
171223
174568
  endMessage,
171224
- startMessageId: row.start_message_id,
171225
- endMessageId: row.end_message_id
174569
+ startMessageId: mapMessageId(filter, row.start_message_id) ?? row.start_message_id,
174570
+ endMessageId: mapMessageId(filter, row.end_message_id) ?? row.end_message_id
171226
174571
  });
171227
174572
  }
171228
- const sourceTags = db.prepare(`SELECT message_id, type, status, byte_size, tag_number, harness,
174573
+ const sourceTags = db.prepare(`SELECT id, message_id, type, status, byte_size, tag_number, harness,
171229
174574
  entry_fingerprint, token_count, input_token_count,
171230
174575
  reasoning_token_count, reasoning_byte_size, drop_mode, tool_name,
171231
174576
  input_byte_size, caveman_depth, tool_owner_message_id
@@ -171237,6 +174582,7 @@ function copySessionStateForClone(db, sourceSessionId, destinationSessionId, fil
171237
174582
  caveman_depth, tool_owner_message_id)
171238
174583
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
171239
174584
  const copiedTagNumbers = [];
174585
+ const copiedTagIds = new Map;
171240
174586
  for (const row of sourceTags) {
171241
174587
  if (!filter.includeTag({
171242
174588
  messageId: row.message_id,
@@ -171246,19 +174592,39 @@ function copySessionStateForClone(db, sourceSessionId, destinationSessionId, fil
171246
174592
  })) {
171247
174593
  continue;
171248
174594
  }
171249
- 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);
174595
+ 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));
174596
+ const insertedTagId = Number(insertResult.lastInsertRowid);
174597
+ if (!Number.isSafeInteger(insertedTagId) || insertedTagId <= 0) {
174598
+ throw new Error(`failed to obtain destination tag id for tag ${row.tag_number}`);
174599
+ }
174600
+ const sourceTagId = filter.mapTagId ? row.id : row.tag_number;
174601
+ const destinationTagId = filter.mapTagId ? filter.mapTagId(sourceTagId, insertedTagId) : sourceTagId;
174602
+ copiedTagIds.set(sourceTagId, destinationTagId);
171250
174603
  copiedTagNumbers.push(row.tag_number);
171251
174604
  }
171252
174605
  if (copiedTagNumbers.length > 0) {
171253
- const placeholders3 = copiedTagNumbers.map(() => "?").join(", ");
171254
- db.prepare(`INSERT INTO source_contents (tag_id, session_id, content, created_at, harness)
171255
- SELECT tag_id, ?, content, created_at, harness
171256
- FROM source_contents
171257
- WHERE session_id = ? AND tag_id IN (${placeholders3})`).run(destinationSessionId, sourceSessionId, ...copiedTagNumbers);
171258
- db.prepare(`INSERT INTO pending_ops (session_id, tag_id, operation, queued_at, harness)
171259
- SELECT ?, tag_id, operation, queued_at, harness
171260
- FROM pending_ops
171261
- WHERE session_id = ? AND tag_id IN (${placeholders3})`).run(destinationSessionId, sourceSessionId, ...copiedTagNumbers);
174606
+ const sourceTagIds = [...copiedTagIds.keys()];
174607
+ const placeholders3 = sourceTagIds.map(() => "?").join(", ");
174608
+ const sourceContents = db.prepare(`SELECT tag_id, content, created_at, harness
174609
+ FROM source_contents
174610
+ WHERE session_id = ? AND tag_id IN (${placeholders3})`).all(sourceSessionId, ...sourceTagIds);
174611
+ const insertSourceContent = db.prepare("INSERT INTO source_contents (tag_id, session_id, content, created_at, harness) VALUES (?, ?, ?, ?, ?)");
174612
+ for (const row of sourceContents) {
174613
+ const destinationTagId = copiedTagIds.get(row.tag_id);
174614
+ if (destinationTagId === undefined)
174615
+ continue;
174616
+ insertSourceContent.run(destinationTagId, destinationSessionId, row.content, row.created_at, row.harness);
174617
+ }
174618
+ const pendingOps = db.prepare(`SELECT tag_id, operation, queued_at, harness
174619
+ FROM pending_ops
174620
+ WHERE session_id = ? AND tag_id IN (${placeholders3})`).all(sourceSessionId, ...sourceTagIds);
174621
+ const insertPendingOp = db.prepare("INSERT INTO pending_ops (session_id, tag_id, operation, queued_at, harness) VALUES (?, ?, ?, ?, ?)");
174622
+ for (const row of pendingOps) {
174623
+ const destinationTagId = copiedTagIds.get(row.tag_id);
174624
+ if (destinationTagId === undefined)
174625
+ continue;
174626
+ insertPendingOp.run(destinationSessionId, destinationTagId, row.operation, row.queued_at, row.harness);
174627
+ }
171262
174628
  }
171263
174629
  const meta3 = db.prepare(`SELECT cleared_reasoning_through_tag, tool_reclaim_watermark,
171264
174630
  pi_stable_id_scheme, stripped_placeholder_ids,
@@ -171294,7 +174660,7 @@ function copySessionStateForClone(db, sourceSessionId, destinationSessionId, fil
171294
174660
  todo_synthetic_anchor_message_id = excluded.todo_synthetic_anchor_message_id,
171295
174661
  todo_synthetic_state_json = excluded.todo_synthetic_state_json,
171296
174662
  cached_m0_bytes = NULL,
171297
- cached_m1_bytes = NULL`).run(destinationSessionId, getHarness(), maxCopiedTag, clampWatermark(meta3?.cleared_reasoning_through_tag ?? null, maxCopiedTag), clampWatermark(meta3?.tool_reclaim_watermark ?? null, maxCopiedTag), typeof meta3?.pi_stable_id_scheme === "number" && Number.isFinite(meta3.pi_stable_id_scheme) ? meta3.pi_stable_id_scheme : null, filterIdBlob(meta3?.stripped_placeholder_ids ?? null, filter.includeMessageId), filterIdBlob(meta3?.stale_reduce_stripped_ids ?? null, filter.includeMessageId), filterIdBlob(meta3?.processed_image_stripped_ids ?? null, filter.includeMessageId), pendingMarker, migrateTodo ? meta3?.last_todo_state ?? "" : "", migrateTodo ? meta3?.todo_synthetic_call_id ?? "" : "", migrateTodo ? todoAnchor : "", migrateTodo ? meta3?.todo_synthetic_state_json ?? "" : "");
174663
+ cached_m1_bytes = NULL`).run(destinationSessionId, getHarness(), maxCopiedTag, clampWatermark(meta3?.cleared_reasoning_through_tag ?? null, maxCopiedTag), clampWatermark(meta3?.tool_reclaim_watermark ?? null, maxCopiedTag), typeof meta3?.pi_stable_id_scheme === "number" && Number.isFinite(meta3.pi_stable_id_scheme) ? meta3.pi_stable_id_scheme : null, filterIdBlob(meta3?.stripped_placeholder_ids ?? null, filter), filterIdBlob(meta3?.stale_reduce_stripped_ids ?? null, filter), filterIdBlob(meta3?.processed_image_stripped_ids ?? null, filter), pendingMarker, migrateTodo ? meta3?.last_todo_state ?? "" : "", migrateTodo ? meta3?.todo_synthetic_call_id ?? "" : "", migrateTodo ? mapMessageId(filter, todoAnchor) ?? "" : "", migrateTodo ? meta3?.todo_synthetic_state_json ?? "" : "");
171298
174664
  const pendingOpsRow = db.prepare("SELECT COUNT(*) AS count FROM pending_ops WHERE session_id = ?").get(destinationSessionId);
171299
174665
  return {
171300
174666
  kind: "migrated",
@@ -171464,6 +174830,7 @@ function getMaxMemoryMutationIdForProjects(db, projectPaths) {
171464
174830
  }
171465
174831
  // ../plugin/src/features/magic-context/storage-meta-persisted.ts
171466
174832
  init_logger();
174833
+ var emergencyRecoveryArmedSessions = new Set;
171467
174834
  var CAS_RETRY_LIMIT = 5;
171468
174835
  var AUTO_SEARCH_NO_HINT_REASONS = new Set([
171469
174836
  "below-threshold",
@@ -172185,6 +175552,7 @@ function getOverflowState(db, sessionId, modelKey) {
172185
175552
  };
172186
175553
  }
172187
175554
  function recordOverflowDetected(db, sessionId, reportedLimit, modelKey, origin = "provider_overflow") {
175555
+ emergencyRecoveryArmedSessions.add(sessionId);
172188
175556
  db.transaction(() => {
172189
175557
  ensureSessionMetaRow(db, sessionId);
172190
175558
  if (typeof reportedLimit === "number" && reportedLimit > 0) {
@@ -172203,6 +175571,7 @@ function clearEmergencyRecovery(db, sessionId) {
172203
175571
  db.prepare("UPDATE session_meta SET needs_emergency_recovery = 0, emergency_recovery_origin = '' WHERE session_id = ?").run(sessionId);
172204
175572
  }
172205
175573
  })();
175574
+ emergencyRecoveryArmedSessions.delete(sessionId);
172206
175575
  }
172207
175576
  function clearDetectedContextLimit(db, sessionId) {
172208
175577
  db.transaction(() => {
@@ -172402,7 +175771,7 @@ function getSessionWorkMetrics(db, sessionId) {
172402
175771
  };
172403
175772
  }
172404
175773
  // ../plugin/src/features/magic-context/storage-meta-session.ts
172405
- import { Buffer as Buffer3 } from "node:buffer";
175774
+ import { Buffer as Buffer4 } from "node:buffer";
172406
175775
 
172407
175776
  // ../plugin/src/features/magic-context/resolve-subagent-fallback.ts
172408
175777
  init_logger();
@@ -172489,7 +175858,7 @@ function updateSessionMeta(db, sessionId, updates) {
172489
175858
  values.push(NULL_BIND_META_KEYS.has(key) ? null : "");
172490
175859
  } else if ((key === "cachedM0Bytes" || key === "cachedM1Bytes") && value instanceof Uint8Array) {
172491
175860
  setClauses.push(`${column} = ?`);
172492
- values.push(Buffer3.from(value.buffer, value.byteOffset, value.byteLength));
175861
+ values.push(Buffer4.from(value.buffer, value.byteOffset, value.byteLength));
172493
175862
  } else if (BOOLEAN_META_KEYS.has(key)) {
172494
175863
  setClauses.push(`${column} = ?`);
172495
175864
  values.push(value ? 1 : 0);
@@ -174743,18 +178112,23 @@ async function embedUnembeddedCommits(db, projectPath) {
174743
178112
  break;
174744
178113
  let embeddedThisBatch = 0;
174745
178114
  try {
174746
- const result = await embedBatchForProject(projectPath, rows.map((row) => row.message));
178115
+ const result = await embedItemsForProject(projectPath, rows.map((row) => ({
178116
+ id: `commit:${row.sha}`,
178117
+ text: row.message,
178118
+ contentSha256: contentSha256(row.message)
178119
+ })), undefined, db, projectPath);
174747
178120
  if (!result)
174748
178121
  break;
174749
178122
  db.transaction(() => {
174750
- for (const [index, row] of rows.entries()) {
174751
- const embedding2 = result.vectors[index];
178123
+ for (const row of rows) {
178124
+ const embedding2 = result.vectors.get(`commit:${row.sha}`);
174752
178125
  if (!embedding2)
174753
178126
  continue;
174754
178127
  saveCommitEmbedding(db, row.sha, embedding2, result.modelId);
174755
178128
  embeddedThisBatch += 1;
174756
178129
  }
174757
178130
  })();
178131
+ enqueueShadowEmbeddingItems(projectPath, "commit", rows.filter((row) => result.vectors.has(`commit:${row.sha}`)).map((row) => row.sha));
174758
178132
  } catch (error51) {
174759
178133
  log(`[git-commits] embed batch failed for ${projectPath}: ${error51 instanceof Error ? error51.message : String(error51)}`);
174760
178134
  break;
@@ -174962,6 +178336,93 @@ function containsProbeVerbatim(text, probes) {
174962
178336
  return probes.some((probe) => haystack.includes(probe.toLowerCase()));
174963
178337
  }
174964
178338
 
178339
+ // ../plugin/src/features/magic-context/search-measurement.ts
178340
+ import { createHash as createHash10 } from "node:crypto";
178341
+ function resultId(result) {
178342
+ switch (result.source) {
178343
+ case "memory":
178344
+ return `memory:${result.memoryId}`;
178345
+ case "message":
178346
+ return `message:${result.messageId}`;
178347
+ case "compartment":
178348
+ return `chunk:${result.compartmentId}`;
178349
+ case "git_commit":
178350
+ return `commit:${result.sha}`;
178351
+ case "primer":
178352
+ return `primer:${result.primerId}`;
178353
+ case "note":
178354
+ return `note:${result.noteId}`;
178355
+ }
178356
+ }
178357
+ async function recordShadowMeasurement(args) {
178358
+ const shadowCohort = getShadowEmbeddingMeasurementCohort(args.projectPath);
178359
+ if (!shadowCohort)
178360
+ return;
178361
+ const primaryCohort = getPrimaryEmbeddingMeasurementCohort(args.projectPath);
178362
+ const shadowStartedAt = Date.now();
178363
+ let shadowFailed = false;
178364
+ let shadowResults = [];
178365
+ try {
178366
+ const vector = await embedShadowTextForProject(args.projectPath, args.query);
178367
+ if (!vector) {
178368
+ shadowFailed = true;
178369
+ } else {
178370
+ shadowResults = await args.search(args.db, args.sessionId, args.projectPath, args.query, {
178371
+ ...args.options,
178372
+ embedQuery: async () => vector,
178373
+ isEmbeddingRuntimeEnabled: () => true,
178374
+ embeddingEnabled: true,
178375
+ embeddingModelIdOverride: shadowCohort.modelId,
178376
+ chunkModelIdOverride: shadowCohort.chunkModelId,
178377
+ measurementDisabled: true,
178378
+ countRetrievals: false
178379
+ });
178380
+ }
178381
+ } catch {
178382
+ shadowFailed = true;
178383
+ }
178384
+ const primaryModelId = args.primaryQuery?.modelId ?? primaryCohort?.modelId ?? "";
178385
+ const primaryFingerprint = primaryCohort?.fingerprint ?? "";
178386
+ const primaryEpoch = primaryCohort?.epoch ?? 0;
178387
+ const cohortKey = JSON.stringify({
178388
+ primaryFingerprint,
178389
+ primaryEpoch,
178390
+ shadowFingerprint: shadowCohort.fingerprint,
178391
+ shadowEpoch: shadowCohort.epoch
178392
+ });
178393
+ const primaryIds = args.primaryResults.map(resultId);
178394
+ const shadowIds = shadowResults.map(resultId);
178395
+ const corpusHash = sha2562(JSON.stringify({ query: args.query, primaryIds, shadowIds }));
178396
+ recordEmbeddingMeasurement(args.db, {
178397
+ sessionId: args.sessionId,
178398
+ projectPath: args.projectPath,
178399
+ queryText: args.query,
178400
+ cohortKey,
178401
+ primaryResultIds: primaryIds,
178402
+ shadowResultIds: shadowIds,
178403
+ primaryLatencyMs: args.primaryLatencyMs,
178404
+ shadowLatencyMs: Date.now() - shadowStartedAt,
178405
+ primaryFailed: args.primaryQuery === null,
178406
+ shadowFailed,
178407
+ primaryModelId,
178408
+ shadowModelId: shadowCohort.modelId,
178409
+ primaryFingerprint,
178410
+ shadowFingerprint: shadowCohort.fingerprint,
178411
+ primaryEpoch,
178412
+ shadowEpoch: shadowCohort.epoch,
178413
+ corpusHash,
178414
+ coverage: {
178415
+ primaryResultCount: primaryIds.length,
178416
+ shadowResultCount: shadowIds.length,
178417
+ primaryAnswered: args.primaryQuery !== null,
178418
+ shadowAnswered: !shadowFailed
178419
+ }
178420
+ });
178421
+ }
178422
+ function sha2562(value) {
178423
+ return createHash10("sha256").update(value).digest("hex");
178424
+ }
178425
+
174965
178426
  // ../plugin/src/features/magic-context/search.ts
174966
178427
  var DEFAULT_UNIFIED_SEARCH_LIMIT = 10;
174967
178428
  var FTS_SEMANTIC_CANDIDATE_LIMIT = 50;
@@ -175719,6 +179180,7 @@ function resolveSources(sources) {
175719
179180
  }
175720
179181
  async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
175721
179182
  const trimmedQuery = query.trim();
179183
+ const measurementStartedAt = Date.now();
175722
179184
  if (trimmedQuery.length === 0) {
175723
179185
  return [];
175724
179186
  }
@@ -175751,11 +179213,14 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
175751
179213
  maxOrdinal: options.maxMessageOrdinal,
175752
179214
  probes: messageProbes
175753
179215
  }) : [];
175754
- const queryEmbedding = await queryEmbeddingPromise;
175755
- const workspace = resolveSearchWorkspaceContext(db, projectPath);
179216
+ const capturedQuery = await queryEmbeddingPromise;
175756
179217
  const embeddingSnapshot = getProjectEmbeddingSnapshot(projectPath);
175757
- const embeddingModelId = embeddingSnapshot?.modelId;
175758
- const chunkModelId = embeddingSnapshot?.chunkModelId;
179218
+ const queryContract = capturedQuery instanceof Float32Array || capturedQuery === null ? null : capturedQuery;
179219
+ const generationIsCurrent = queryContract === null || embeddingSnapshot !== null && embeddingSnapshot.generation === queryContract.generation;
179220
+ const queryEmbedding = generationIsCurrent ? queryContract?.vector ?? (capturedQuery instanceof Float32Array ? capturedQuery : null) : null;
179221
+ const workspace = resolveSearchWorkspaceContext(db, projectPath);
179222
+ const embeddingModelId = queryContract?.modelId ?? options.embeddingModelIdOverride ?? embeddingSnapshot?.modelId;
179223
+ const chunkModelId = queryContract?.chunkModelId ?? options.chunkModelIdOverride ?? embeddingSnapshot?.chunkModelId;
175759
179224
  const compartmentResults = runCompartmentChunks ? searchCompartmentChunks({
175760
179225
  db,
175761
179226
  sessionId,
@@ -175814,6 +179279,19 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
175814
179279
  ...gitCommitResults,
175815
179280
  ...noteResults
175816
179281
  ].sort(compareUnifiedResults).slice(0, limit);
179282
+ if (!options.measurementDisabled) {
179283
+ recordShadowMeasurement({
179284
+ db,
179285
+ sessionId,
179286
+ projectPath,
179287
+ query: trimmedQuery,
179288
+ options,
179289
+ primaryResults: results,
179290
+ primaryQuery: queryContract,
179291
+ primaryLatencyMs: Date.now() - measurementStartedAt,
179292
+ search: unifiedSearch
179293
+ });
179294
+ }
175817
179295
  const countRetrievals = options.countRetrievals ?? true;
175818
179296
  if (countRetrievals) {
175819
179297
  const memoryIds = results.filter((result) => result.source === "memory").map((result) => result.memoryId);
@@ -176579,7 +180057,7 @@ import {
176579
180057
  } from "@earendil-works/pi-tui";
176580
180058
 
176581
180059
  // ../plugin/src/hooks/magic-context/todo-view.ts
176582
- import { createHash as createHash8 } from "node:crypto";
180060
+ import { createHash as createHash11 } from "node:crypto";
176583
180061
  var TODO_STATUS_PENDING = "pending";
176584
180062
  var TODO_STATUS_IN_PROGRESS = "in_progress";
176585
180063
  var TODO_STATUS_COMPLETED = "completed";
@@ -176647,7 +180125,7 @@ function buildSyntheticTodoPart(stateJson) {
176647
180125
  };
176648
180126
  }
176649
180127
  function computeSyntheticCallId(stateJson) {
176650
- const hash2 = createHash8("sha256").update(stateJson).digest("hex").slice(0, 16);
180128
+ const hash2 = createHash11("sha256").update(stateJson).digest("hex").slice(0, 16);
176651
180129
  return `${SYNTHETIC_CALL_ID_PREFIX}${hash2}`;
176652
180130
  }
176653
180131
  function parseTodoState(stateJson) {