@wolfx/pi-magic-context 0.25.0 → 0.26.0-patch.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.js +14872 -14858
  2. package/dist/subagent-entry.js +292 -451
  3. package/package.json +2 -4
@@ -1,4 +1,3 @@
1
- import { createRequire } from "node:module";
2
1
  var __create = Object.create;
3
2
  var __getProtoOf = Object.getPrototypeOf;
4
3
  var __defProp = Object.defineProperty;
@@ -44,7 +43,6 @@ var __export = (target, all) => {
44
43
  });
45
44
  };
46
45
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
47
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
48
46
 
49
47
  // ../plugin/src/shared/harness.ts
50
48
  function setHarness(value) {
@@ -9582,6 +9580,41 @@ var MIGRATIONS = [
9582
9580
  `);
9583
9581
  }
9584
9582
  }
9583
+ },
9584
+ {
9585
+ version: 37,
9586
+ description: "emergency drain catch-up latch + historian drain failure backoff",
9587
+ up: (db) => {
9588
+ const hasSessionMeta = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='session_meta'").get();
9589
+ if (!hasSessionMeta)
9590
+ return;
9591
+ ensureColumn(db, "session_meta", "emergency_drain_active", "INTEGER NOT NULL DEFAULT 0");
9592
+ ensureColumn(db, "session_meta", "historian_drain_failure_at", "INTEGER NOT NULL DEFAULT 0");
9593
+ }
9594
+ },
9595
+ {
9596
+ version: 38,
9597
+ description: "durable transform decisions for cache-event cause attribution",
9598
+ up: (db) => {
9599
+ db.exec(`
9600
+ CREATE TABLE IF NOT EXISTS transform_decisions (
9601
+ session_id TEXT NOT NULL,
9602
+ harness TEXT NOT NULL DEFAULT 'opencode',
9603
+ message_id TEXT NOT NULL,
9604
+ ts_ms INTEGER NOT NULL,
9605
+ decision TEXT NOT NULL,
9606
+ materialized INTEGER NOT NULL DEFAULT 0,
9607
+ materialize_reason TEXT,
9608
+ emergency INTEGER NOT NULL DEFAULT 0,
9609
+ dropped_tokens INTEGER NOT NULL DEFAULT 0,
9610
+ dropped_count INTEGER NOT NULL DEFAULT 0,
9611
+ input_tokens INTEGER NOT NULL DEFAULT 0,
9612
+ PRIMARY KEY (session_id, harness, message_id)
9613
+ );
9614
+ CREATE INDEX IF NOT EXISTS idx_transform_decisions_session_harness
9615
+ ON transform_decisions(session_id, harness);
9616
+ `);
9617
+ }
9585
9618
  }
9586
9619
  ];
9587
9620
  var LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
@@ -142558,8 +142591,9 @@ function backfillToolOwnersInChunks(db, result) {
142558
142591
  var databases = new Map;
142559
142592
  var persistenceByDatabase = new WeakMap;
142560
142593
  var persistenceErrorByDatabase = new WeakMap;
142594
+ var pathByDatabase = new WeakMap;
142561
142595
  var lastSchemaFenceRejection = null;
142562
- var LATEST_SUPPORTED_VERSION = 36;
142596
+ var LATEST_SUPPORTED_VERSION = 38;
142563
142597
  function resolveDatabasePath(dbPathOverride) {
142564
142598
  if (dbPathOverride) {
142565
142599
  return { dbDir: dirname2(dbPathOverride), dbPath: dbPathOverride };
@@ -142572,6 +142606,9 @@ function resolveDatabasePath(dbPathOverride) {
142572
142606
  const dbDir = getMagicContextStorageDir();
142573
142607
  return { dbDir, dbPath: join4(dbDir, "context.db") };
142574
142608
  }
142609
+ function getDatabasePath(db) {
142610
+ return pathByDatabase.get(db) ?? null;
142611
+ }
142575
142612
  function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
142576
142613
  if (existsSync3(targetDbPath))
142577
142614
  return;
@@ -143086,6 +143123,8 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
143086
143123
  recovery_no_eligible_head_count INTEGER NOT NULL DEFAULT 0,
143087
143124
  force_emergency_bypass_window_start INTEGER NOT NULL DEFAULT 0,
143088
143125
  force_emergency_bypass_used INTEGER NOT NULL DEFAULT 0,
143126
+ emergency_drain_active INTEGER NOT NULL DEFAULT 0,
143127
+ historian_drain_failure_at INTEGER NOT NULL DEFAULT 0,
143089
143128
  cached_m0_materialized_at INTEGER,
143090
143129
  cached_m0_session_facts_version INTEGER,
143091
143130
  cached_m0_upgrade_state TEXT,
@@ -143149,6 +143188,23 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
143149
143188
  CREATE INDEX IF NOT EXISTS idx_historian_runs_status
143150
143189
  ON historian_runs(status, created_at DESC);
143151
143190
 
143191
+ CREATE TABLE IF NOT EXISTS transform_decisions (
143192
+ session_id TEXT NOT NULL,
143193
+ harness TEXT NOT NULL DEFAULT 'opencode',
143194
+ message_id TEXT NOT NULL,
143195
+ ts_ms INTEGER NOT NULL,
143196
+ decision TEXT NOT NULL,
143197
+ materialized INTEGER NOT NULL DEFAULT 0,
143198
+ materialize_reason TEXT,
143199
+ emergency INTEGER NOT NULL DEFAULT 0,
143200
+ dropped_tokens INTEGER NOT NULL DEFAULT 0,
143201
+ dropped_count INTEGER NOT NULL DEFAULT 0,
143202
+ input_tokens INTEGER NOT NULL DEFAULT 0,
143203
+ PRIMARY KEY (session_id, harness, message_id)
143204
+ );
143205
+ CREATE INDEX IF NOT EXISTS idx_transform_decisions_session_harness
143206
+ ON transform_decisions(session_id, harness);
143207
+
143152
143208
  CREATE INDEX IF NOT EXISTS idx_tags_session_tag_number ON tags(session_id, tag_number);
143153
143209
  CREATE INDEX IF NOT EXISTS idx_tags_session_message_id ON tags(session_id, message_id);
143154
143210
  CREATE INDEX IF NOT EXISTS idx_pending_ops_session ON pending_ops(session_id);
@@ -143300,6 +143356,8 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
143300
143356
  ensureColumn(db, "session_meta", "recovery_no_eligible_head_count", "INTEGER NOT NULL DEFAULT 0");
143301
143357
  ensureColumn(db, "session_meta", "force_emergency_bypass_window_start", "INTEGER NOT NULL DEFAULT 0");
143302
143358
  ensureColumn(db, "session_meta", "force_emergency_bypass_used", "INTEGER NOT NULL DEFAULT 0");
143359
+ ensureColumn(db, "session_meta", "emergency_drain_active", "INTEGER NOT NULL DEFAULT 0");
143360
+ ensureColumn(db, "session_meta", "historian_drain_failure_at", "INTEGER NOT NULL DEFAULT 0");
143303
143361
  ensureColumn(db, "session_meta", "cached_m0_materialized_at", "INTEGER");
143304
143362
  ensureColumn(db, "session_meta", "cached_m0_session_facts_version", "INTEGER");
143305
143363
  ensureColumn(db, "session_meta", "cached_m0_upgrade_state", "TEXT");
@@ -143378,6 +143436,22 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
143378
143436
  failed_at INTEGER NOT NULL,
143379
143437
  UNIQUE(table_name, row_id)
143380
143438
  );
143439
+ CREATE TABLE IF NOT EXISTS transform_decisions (
143440
+ session_id TEXT NOT NULL,
143441
+ harness TEXT NOT NULL DEFAULT 'opencode',
143442
+ message_id TEXT NOT NULL,
143443
+ ts_ms INTEGER NOT NULL,
143444
+ decision TEXT NOT NULL,
143445
+ materialized INTEGER NOT NULL DEFAULT 0,
143446
+ materialize_reason TEXT,
143447
+ emergency INTEGER NOT NULL DEFAULT 0,
143448
+ dropped_tokens INTEGER NOT NULL DEFAULT 0,
143449
+ dropped_count INTEGER NOT NULL DEFAULT 0,
143450
+ input_tokens INTEGER NOT NULL DEFAULT 0,
143451
+ PRIMARY KEY (session_id, harness, message_id)
143452
+ );
143453
+ CREATE INDEX IF NOT EXISTS idx_transform_decisions_session_harness
143454
+ ON transform_decisions(session_id, harness);
143381
143455
  `);
143382
143456
  ensureColumn(db, "tags", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
143383
143457
  ensureColumn(db, "pending_ops", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
@@ -143464,7 +143538,9 @@ function healNullIntegerColumns(db) {
143464
143538
  ["protected_tail_drain_tokens", 0],
143465
143539
  ["recovery_no_eligible_head_count", 0],
143466
143540
  ["force_emergency_bypass_window_start", 0],
143467
- ["force_emergency_bypass_used", 0]
143541
+ ["force_emergency_bypass_used", 0],
143542
+ ["emergency_drain_active", 0],
143543
+ ["historian_drain_failure_at", 0]
143468
143544
  ];
143469
143545
  for (const [column, fallback] of columns) {
143470
143546
  try {
@@ -143540,6 +143616,7 @@ function openDatabase(dbPathOrOptions) {
143540
143616
  setDatabase(db);
143541
143617
  loadToolDefinitionMeasurements(db);
143542
143618
  databases.set(dbPath, db);
143619
+ pathByDatabase.set(db, dbPath);
143543
143620
  persistenceByDatabase.set(db, true);
143544
143621
  persistenceErrorByDatabase.delete(db);
143545
143622
  return db;
@@ -158101,7 +158178,6 @@ var DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE = 65;
158101
158178
  var EXECUTE_THRESHOLD_CAP_MESSAGE = "execute_threshold is capped at 80% for cache safety: a single large agent step can overflow the context window before Magic Context can compact between turns, forcing OpenCode's native compaction (hard to recover from). 80% also leaves headroom below the 85%/95% emergency bands. Use a value between 20 and 80.";
158102
158179
  var DEFAULT_HISTORIAN_TIMEOUT_MS = 300000;
158103
158180
  var DEFAULT_HISTORY_BUDGET_PERCENTAGE = 0.15;
158104
- var DEFAULT_LOCAL_EMBEDDING_MODEL = "Xenova/all-MiniLM-L6-v2";
158105
158181
  var DREAMER_TASKS = [
158106
158182
  "consolidate",
158107
158183
  "verify",
@@ -158141,14 +158217,16 @@ var SidekickConfigSchema = AgentOverrideConfigSchema.extend({
158141
158217
  }).optional();
158142
158218
  var HistorianConfigSchema = AgentOverrideConfigSchema.extend({
158143
158219
  two_pass: exports_external.boolean().default(false).describe("Run a second editor pass over historian output to clean low-signal U: lines and cross-compartment duplicates. Adds ~1 extra API call and ~1.3x cost per historian run. Useful for models without extended thinking support. (default: false)"),
158144
- 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")
158220
+ 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"),
158221
+ 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: [])`)
158145
158222
  }).optional();
158146
158223
  var BaseEmbeddingConfigSchema = exports_external.object({
158147
- 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."),
158148
- model: exports_external.string().optional().describe("Embedding model name. Required for openai-compatible, ignored for local."),
158224
+ provider: exports_external.enum(["openai-compatible", "off"]).default("off").describe("Embedding provider. 'openai-compatible' requires endpoint and model, 'off' disables embeddings (default)."),
158225
+ model: exports_external.string().optional().describe("Embedding model name. Required for openai-compatible."),
158149
158226
  endpoint: exports_external.string().optional().describe("API endpoint URL. Required when provider is openai-compatible."),
158150
158227
  api_key: exports_external.string().optional().describe("API key for remote embedding provider (optional)"),
158151
- input_type: exports_external.string().optional().describe("Optional input_type sent in the embedding request body. Required by some openai-compatible providers (e.g. NVIDIA NIM expects 'query' or 'passage'). Omitted from the request when unset."),
158228
+ input_type: exports_external.string().optional().describe("Default input_type for stored/indexed (passage) embeddings in the request body. Required by some openai-compatible providers (e.g. NVIDIA NIM). Omitted from the request when unset."),
158229
+ query_input_type: exports_external.string().optional().describe("Optional input_type for query (search) embeddings on asymmetric models (e.g. NVIDIA NIM 'query'). When unset, query embeddings use embedding.input_type. Passage/stored content always uses embedding.input_type."),
158152
158230
  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."),
158153
158231
  max_input_tokens: exports_external.number().int().positive().optional().describe("Optional maximum input tokens for chunk embeddings. Defaults conservatively to 512 when omitted.")
158154
158232
  }).superRefine((data, ctx) => {
@@ -158168,16 +158246,10 @@ var BaseEmbeddingConfigSchema = exports_external.object({
158168
158246
  }
158169
158247
  });
158170
158248
  var EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data) => {
158171
- if (data.provider === "local") {
158172
- return {
158173
- provider: "local",
158174
- model: data.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
158175
- ...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}
158176
- };
158177
- }
158178
158249
  if (data.provider === "openai-compatible") {
158179
158250
  const apiKey = data.api_key?.trim();
158180
158251
  const inputType = data.input_type?.trim();
158252
+ const queryInputType = data.query_input_type?.trim();
158181
158253
  const truncate = data.truncate?.trim();
158182
158254
  return {
158183
158255
  provider: "openai-compatible",
@@ -158185,6 +158257,7 @@ var EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data) => {
158185
158257
  endpoint: data.endpoint?.trim() ?? "",
158186
158258
  ...apiKey ? { api_key: apiKey } : {},
158187
158259
  ...inputType ? { input_type: inputType } : {},
158260
+ ...queryInputType ? { query_input_type: queryInputType } : {},
158188
158261
  ...truncate ? { truncate } : {},
158189
158262
  ...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}
158190
158263
  };
@@ -158224,8 +158297,7 @@ var MagicContextConfigSchema = exports_external.object({
158224
158297
  mmap_size_mb: exports_external.number().min(0).max(8192).default(0).describe("Memory-mapped I/O size in MiB (PRAGMA mmap_size). 0 disables mmap (SQLite default). Raising it can cut read overhead on large DBs at the cost of address space. (min 0, max 8192, default 0)")
158225
158298
  }).default({ cache_size_mb: 64, mmap_size_mb: 0 }).describe("SQLite connection tuning for Magic Context's own context.db. These are per-connection PRAGMAs applied at open; they do not change the schema or what is stored."),
158226
158299
  embedding: EmbeddingConfigSchema.default({
158227
- provider: "local",
158228
- model: DEFAULT_LOCAL_EMBEDDING_MODEL
158300
+ provider: "off"
158229
158301
  }).describe("Embedding provider configuration"),
158230
158302
  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 start/end date attributes on compartments. 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).'),
158231
158303
  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."),
@@ -158908,6 +158980,16 @@ function buildCanonicalChunkTextFromFts(db, sessionId, startOrdinal, endOrdinal)
158908
158980
  return lines.join(`
158909
158981
  `);
158910
158982
  }
158983
+ function buildCompartmentSummaryFallbackText(db, compartmentId) {
158984
+ const row = db.prepare("SELECT title, p1, content FROM compartments WHERE id = ?").get(compartmentId);
158985
+ if (!row)
158986
+ return "";
158987
+ const title = typeof row.title === "string" ? row.title.trim() : "";
158988
+ const p1 = typeof row.p1 === "string" ? row.p1.trim() : "";
158989
+ const body = p1.length > 0 ? p1 : typeof row.content === "string" ? row.content.trim() : "";
158990
+ return [title, body].filter((s) => s.length > 0).join(`
158991
+ `);
158992
+ }
158911
158993
  function canonicalizeInMemoryChunkTextForEmbedding(chunkText, startOrdinal, endOrdinal) {
158912
158994
  const lines = [];
158913
158995
  for (const rawLine of chunkText.split(/\r?\n/)) {
@@ -159215,377 +159297,11 @@ function getEmbeddingProviderIdentity(config2) {
159215
159297
  endpoint: normalizeEndpoint2(config2.endpoint),
159216
159298
  apiKeyPresent: Boolean(config2.api_key?.trim()),
159217
159299
  inputType: config2.input_type?.trim() || ""
159218
- } : {
159219
- provider: "local",
159220
- model: config2.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
159221
- endpoint: "",
159222
- apiKeyPresent: false
159223
- };
159224
- return `embedding-provider:${computeNormalizedHash(JSON.stringify(identityInput))}`;
159225
- }
159226
-
159227
- // ../plugin/src/features/magic-context/memory/embedding-local.ts
159228
- import { mkdirSync as mkdirSync3 } from "node:fs";
159229
- import { open, stat, unlink, writeFile } from "node:fs/promises";
159230
- import { dirname as dirname4, join as join6 } from "node:path";
159231
- import { pathToFileURL } from "node:url";
159232
- init_data_path();
159233
- init_logger();
159234
- var LOCK_POLL_MS = 150;
159235
- var STALE_LOCK_MS = 3 * 60000;
159236
- var MAX_LOCK_WAIT_MS = 5 * 60000;
159237
- async function acquireModelLoadLock(lockPath) {
159238
- const waitStart = Date.now();
159239
- while (true) {
159240
- try {
159241
- const handle = await open(lockPath, "wx");
159242
- try {
159243
- await handle.writeFile(`pid=${process.pid} started=${Date.now()}
159244
- `);
159245
- } catch {}
159246
- await handle.close();
159247
- return async () => {
159248
- try {
159249
- await unlink(lockPath);
159250
- } catch {}
159251
- };
159252
- } catch (error51) {
159253
- const code = error51.code;
159254
- if (code !== "EEXIST" && code !== "EPERM") {
159255
- throw error51;
159256
- }
159257
- try {
159258
- const info = await stat(lockPath);
159259
- if (Date.now() - info.mtimeMs > STALE_LOCK_MS) {
159260
- log(`[magic-context] embedding-load lock stale (>${STALE_LOCK_MS}ms), taking over`);
159261
- try {
159262
- await unlink(lockPath);
159263
- } catch {}
159264
- continue;
159265
- }
159266
- } catch {
159267
- continue;
159268
- }
159269
- if (Date.now() - waitStart > MAX_LOCK_WAIT_MS) {
159270
- throw new Error(`[magic-context] embedding-load lock wait exceeded ${MAX_LOCK_WAIT_MS}ms; another process is still loading the model. Skipping this init attempt to avoid an unsynchronized native load.`);
159271
- }
159272
- await new Promise((resolve3) => setTimeout(resolve3, LOCK_POLL_MS));
159273
- }
159274
- }
159275
- }
159276
- function startLockHeartbeat(lockPath) {
159277
- const HEARTBEAT_MS = Math.floor(STALE_LOCK_MS / 3);
159278
- const timer = setInterval(() => {
159279
- writeFile(lockPath, `pid=${process.pid} alive=${Date.now()}
159280
- `).catch(() => {});
159281
- }, HEARTBEAT_MS);
159282
- timer.unref?.();
159283
- return () => clearInterval(timer);
159284
- }
159285
- async function injectWasmOrtForElectron() {
159286
- if (typeof process === "undefined" || !process.versions?.electron) {
159287
- return false;
159288
- }
159289
- try {
159290
- const ortWebSpec = `onnxruntime-${"web"}`;
159291
- const ortWeb = await import(ortWebSpec);
159292
- try {
159293
- const { createRequire: createRequireFn } = await import("node:module");
159294
- const requireFn = createRequireFn(import.meta.url);
159295
- const pkgPath = requireFn.resolve("onnxruntime-web/package.json");
159296
- const distDir = join6(dirname4(pkgPath), "dist");
159297
- const wasmPathsPrefix = `${pathToFileURL(distDir).href}/`;
159298
- if (ortWeb.env?.wasm) {
159299
- ortWeb.env.wasm.wasmPaths = wasmPathsPrefix;
159300
- }
159301
- } catch (pathError) {
159302
- log("[magic-context] could not resolve local onnxruntime-web/dist, falling back to default WASM paths:", pathError instanceof Error ? pathError.message : String(pathError));
159303
- }
159304
- globalThis[Symbol.for("onnxruntime")] = ortWeb;
159305
- log("[magic-context] Electron detected — using onnxruntime-web (WASM) for embeddings (bypasses onnxruntime-node native load)");
159306
- return true;
159307
- } catch (error51) {
159308
- log("[magic-context] failed to inject onnxruntime-web for Electron — letting transformers fall back to native:", error51 instanceof Error ? error51.message : String(error51));
159309
- return false;
159310
- }
159311
- }
159312
- async function withQuietConsole(fn) {
159313
- const origWarn = console.warn;
159314
- const origError = console.error;
159315
- const redirect = (...args) => {
159316
- const message = args.map((a) => typeof a === "string" ? a : String(a)).join(" ");
159317
- log(`[transformers] ${message}`);
159318
- };
159319
- console.warn = redirect;
159320
- console.error = redirect;
159321
- try {
159322
- return await fn();
159323
- } finally {
159324
- console.warn = origWarn;
159325
- console.error = origError;
159326
- }
159327
- }
159328
- var nativeRuntimeMissing = false;
159329
- function isNativeRuntimeMissingError(error51) {
159330
- const message = error51 instanceof Error ? error51.message : String(error51 ?? "");
159331
- const lower = message.toLowerCase();
159332
- const code = error51?.code;
159333
- const name2 = error51?.name;
159334
- if (code === "ERR_DLOPEN_FAILED" && lower.includes("onnxruntime")) {
159335
- return true;
159336
- }
159337
- if (!lower.includes("onnxruntime-node"))
159338
- return false;
159339
- return code === "ERR_MODULE_NOT_FOUND" || name2 === "ResolveMessage" || lower.includes("cannot find package") || lower.includes("cannot find module") || lower.includes("err_module_not_found");
159340
- }
159341
- function isTransientLoadError(error51) {
159342
- const message = error51 instanceof Error ? error51.message : String(error51 ?? "");
159343
- if (!message)
159344
- return false;
159345
- const lower = message.toLowerCase();
159346
- return lower.includes("protobuf parsing failed") || lower.includes("unable to get model file path or buffer") || lower.includes("ebusy") || lower.includes("resource busy") || lower.includes("resource temporarily unavailable");
159347
- }
159348
- function isArrayLikeNumber(value) {
159349
- if (typeof value !== "object" || value === null || !("length" in value)) {
159350
- return false;
159351
- }
159352
- const arr = value;
159353
- if (typeof arr.length !== "number") {
159354
- return false;
159355
- }
159356
- return arr.length === 0 || typeof arr[0] === "number";
159357
- }
159358
- function toFloat32Array2(values) {
159359
- return values instanceof Float32Array ? new Float32Array(values) : Float32Array.from(Array.from(values));
159360
- }
159361
- function extractBatchEmbeddings(result, expectedCount) {
159362
- const { data } = result;
159363
- if (Array.isArray(data) && data.length === expectedCount && data.every((entry) => typeof entry !== "number" && isArrayLikeNumber(entry))) {
159364
- return data.map((entry) => toFloat32Array2(entry));
159365
- }
159366
- if (!isArrayLikeNumber(data)) {
159367
- log("[magic-context] embedding batch returned unexpected data shape");
159368
- return Array.from({ length: expectedCount }, () => null);
159369
- }
159370
- const flatData = toFloat32Array2(data);
159371
- const dimension = result.dims?.at(-1) ?? flatData.length / expectedCount;
159372
- if (!Number.isInteger(dimension) || dimension <= 0 || flatData.length !== expectedCount * dimension) {
159373
- log("[magic-context] embedding batch returned invalid dimensions");
159374
- return Array.from({ length: expectedCount }, () => null);
159375
- }
159376
- const embeddings = [];
159377
- for (let index = 0;index < expectedCount; index++) {
159378
- embeddings.push(flatData.slice(index * dimension, (index + 1) * dimension));
159379
- }
159380
- return embeddings;
159381
- }
159382
-
159383
- class LocalEmbeddingProvider {
159384
- modelId;
159385
- maxInputTokens;
159386
- model;
159387
- pipeline = null;
159388
- initPromise = null;
159389
- inFlight = 0;
159390
- disposing = false;
159391
- disposePromise = null;
159392
- inFlightWaiters = [];
159393
- constructor(model = DEFAULT_LOCAL_EMBEDDING_MODEL, maxInputTokens = 512) {
159394
- this.model = model;
159395
- this.maxInputTokens = maxInputTokens;
159396
- this.modelId = getEmbeddingProviderIdentity({ provider: "local", model });
159397
- }
159398
- async initialize() {
159399
- if (this.disposing) {
159400
- return false;
159401
- }
159402
- if (this.pipeline) {
159403
- return true;
159404
- }
159405
- if (nativeRuntimeMissing) {
159406
- return false;
159407
- }
159408
- if (this.initPromise) {
159409
- await this.initPromise;
159410
- return this.pipeline !== null;
159411
- }
159412
- this.initPromise = (async () => {
159413
- try {
159414
- if (this.disposing) {
159415
- return;
159416
- }
159417
- await injectWasmOrtForElectron();
159418
- const transformersSpec = "@huggingface/transformers";
159419
- const transformersModule = await import(transformersSpec);
159420
- const env = transformersModule.env;
159421
- const LogLevel = transformersModule.LogLevel;
159422
- if (LogLevel && "ERROR" in LogLevel) {
159423
- env.logLevel = LogLevel.ERROR;
159424
- }
159425
- const modelCacheDir = join6(getMagicContextStorageDir(), "models");
159426
- try {
159427
- mkdirSync3(modelCacheDir, { recursive: true });
159428
- env.cacheDir = modelCacheDir;
159429
- } catch {
159430
- log("[magic-context] could not create model cache dir, using library default");
159431
- }
159432
- const createPipeline = transformersModule.pipeline;
159433
- const lockPath = join6(modelCacheDir, ".load.lock");
159434
- const releaseLock = await acquireModelLoadLock(lockPath);
159435
- const stopHeartbeat = startLockHeartbeat(lockPath);
159436
- try {
159437
- const MAX_ATTEMPTS = 3;
159438
- let lastError;
159439
- for (let attempt = 1;attempt <= MAX_ATTEMPTS; attempt++) {
159440
- try {
159441
- const pipeline = await withQuietConsole(() => createPipeline("feature-extraction", this.model, {
159442
- dtype: "fp32"
159443
- }));
159444
- if (this.disposing) {
159445
- await pipeline.dispose?.();
159446
- this.pipeline = null;
159447
- } else {
159448
- this.pipeline = pipeline;
159449
- }
159450
- lastError = undefined;
159451
- break;
159452
- } catch (error51) {
159453
- lastError = error51;
159454
- if (!isTransientLoadError(error51) || attempt === MAX_ATTEMPTS) {
159455
- break;
159456
- }
159457
- const delayMs = 300 * attempt + Math.floor(Math.random() * 200);
159458
- log(`[magic-context] embedding model load attempt ${attempt}/${MAX_ATTEMPTS} failed transiently, retrying in ${delayMs}ms`);
159459
- await new Promise((resolve3) => setTimeout(resolve3, delayMs));
159460
- }
159461
- }
159462
- if (this.pipeline) {
159463
- log(`[magic-context] embedding model loaded: ${this.model}`);
159464
- } else if (this.disposing) {
159465
- return;
159466
- } else {
159467
- throw lastError ?? new Error("unknown embedding load failure");
159468
- }
159469
- } finally {
159470
- stopHeartbeat();
159471
- await releaseLock();
159472
- }
159473
- } catch (error51) {
159474
- if (isNativeRuntimeMissingError(error51)) {
159475
- nativeRuntimeMissing = true;
159476
- log("[magic-context] local embedding runtime is not installed (onnxruntime-node missing from this install). Local embeddings are disabled. Fix: reinstall the plugin (run `npx @wolfx/magic-context@latest doctor --force`), or configure an `openai-compatible`/`ollama` embedding endpoint instead. Existing memories are unaffected.");
159477
- } else {
159478
- log("[magic-context] embedding model failed to load:", error51);
159479
- }
159480
- this.pipeline = null;
159481
- } finally {
159482
- this.initPromise = null;
159483
- }
159484
- })();
159485
- await this.initPromise;
159486
- return this.pipeline !== null;
159487
- }
159488
- waitForInFlightToDrain() {
159489
- if (this.inFlight === 0) {
159490
- return Promise.resolve();
159491
- }
159492
- return new Promise((resolve3) => {
159493
- this.inFlightWaiters.push(resolve3);
159494
- });
159495
- }
159496
- finishInFlight() {
159497
- this.inFlight = Math.max(0, this.inFlight - 1);
159498
- if (this.inFlight !== 0)
159499
- return;
159500
- const waiters = this.inFlightWaiters.splice(0);
159501
- for (const waiter of waiters) {
159502
- waiter();
159503
- }
159504
- }
159505
- async embed(text, signal) {
159506
- if (signal?.aborted)
159507
- return null;
159508
- if (this.disposing)
159509
- return null;
159510
- this.inFlight += 1;
159511
- try {
159512
- if (!await this.initialize()) {
159513
- return null;
159514
- }
159515
- const pipeline = this.pipeline;
159516
- if (!pipeline) {
159517
- return null;
159518
- }
159519
- const result = await withQuietConsole(() => pipeline(text, {
159520
- pooling: "mean",
159521
- normalize: true
159522
- }));
159523
- return extractBatchEmbeddings(result, 1)[0] ?? null;
159524
- } catch (error51) {
159525
- log("[magic-context] embedding failed:", error51);
159526
- return null;
159527
- } finally {
159528
- this.finishInFlight();
159529
- }
159530
- }
159531
- async embedBatch(texts, signal) {
159532
- if (texts.length === 0) {
159533
- return [];
159534
- }
159535
- if (signal?.aborted) {
159536
- return Array.from({ length: texts.length }, () => null);
159537
- }
159538
- if (this.disposing) {
159539
- return Array.from({ length: texts.length }, () => null);
159540
- }
159541
- this.inFlight += 1;
159542
- try {
159543
- if (!await this.initialize()) {
159544
- return Array.from({ length: texts.length }, () => null);
159545
- }
159546
- const pipeline = this.pipeline;
159547
- if (!pipeline) {
159548
- return Array.from({ length: texts.length }, () => null);
159549
- }
159550
- const result = await withQuietConsole(() => pipeline(texts, {
159551
- pooling: "mean",
159552
- normalize: true
159553
- }));
159554
- return extractBatchEmbeddings(result, texts.length);
159555
- } catch (error51) {
159556
- log("[magic-context] embedding batch failed:", error51);
159557
- return Array.from({ length: texts.length }, () => null);
159558
- } finally {
159559
- this.finishInFlight();
159560
- }
159561
- }
159562
- async dispose() {
159563
- if (this.disposePromise) {
159564
- return this.disposePromise;
159565
- }
159566
- this.disposing = true;
159567
- this.disposePromise = (async () => {
159568
- if (this.initPromise) {
159569
- await this.initPromise;
159570
- }
159571
- await this.waitForInFlightToDrain();
159572
- const pipelineToDispose = this.pipeline;
159573
- this.pipeline = null;
159574
- this.initPromise = null;
159575
- if (!pipelineToDispose) {
159576
- return;
159577
- }
159578
- try {
159579
- await pipelineToDispose.dispose?.();
159580
- } catch (error51) {
159581
- log("[magic-context] embedding model dispose failed:", error51);
159582
- }
159583
- })();
159584
- return this.disposePromise;
159585
- }
159586
- isLoaded() {
159587
- return this.pipeline !== null;
159300
+ } : null;
159301
+ if (!identityInput) {
159302
+ return "embedding-provider:off";
159588
159303
  }
159304
+ return `embedding-provider:${computeNormalizedHash(JSON.stringify(identityInput))}`;
159589
159305
  }
159590
159306
 
159591
159307
  // ../plugin/src/features/magic-context/memory/embedding-openai.ts
@@ -159667,6 +159383,7 @@ class OpenAICompatibleEmbeddingProvider {
159667
159383
  model;
159668
159384
  apiKey;
159669
159385
  inputType;
159386
+ queryInputType;
159670
159387
  truncate;
159671
159388
  initialized = false;
159672
159389
  failureTimes = [];
@@ -159679,6 +159396,7 @@ class OpenAICompatibleEmbeddingProvider {
159679
159396
  this.model = options.model?.trim() ?? "";
159680
159397
  this.apiKey = options.apiKey?.trim() ?? "";
159681
159398
  this.inputType = options.inputType?.trim() ?? "";
159399
+ this.queryInputType = options.queryInputType?.trim() ?? "";
159682
159400
  this.truncate = options.truncate?.trim() ?? "";
159683
159401
  this.maxInputTokens = typeof options.maxInputTokens === "number" && Number.isFinite(options.maxInputTokens) ? Math.max(1, Math.floor(options.maxInputTokens)) : 512;
159684
159402
  this.modelId = getEmbeddingProviderIdentity({
@@ -159706,11 +159424,17 @@ class OpenAICompatibleEmbeddingProvider {
159706
159424
  this.initialized = true;
159707
159425
  return true;
159708
159426
  }
159709
- async embed(text, signal) {
159710
- const [embedding] = await this.embedBatch([text], signal);
159427
+ resolveInputTypeForPurpose(purpose = "passage") {
159428
+ if (purpose === "query") {
159429
+ return this.queryInputType || this.inputType;
159430
+ }
159431
+ return this.inputType;
159432
+ }
159433
+ async embed(text, signal, purpose) {
159434
+ const [embedding] = await this.embedBatch([text], signal, purpose);
159711
159435
  return embedding ?? null;
159712
159436
  }
159713
- async embedBatch(texts, signal) {
159437
+ async embedBatch(texts, signal, purpose) {
159714
159438
  if (texts.length === 0) {
159715
159439
  return [];
159716
159440
  }
@@ -159736,6 +159460,7 @@ class OpenAICompatibleEmbeddingProvider {
159736
159460
  if (signal) {
159737
159461
  signal.addEventListener("abort", onOuterAbort, { once: true });
159738
159462
  }
159463
+ const inputTypeForRequest = this.resolveInputTypeForPurpose(purpose);
159739
159464
  const response = await fetch(`${this.endpoint}/embeddings`, {
159740
159465
  method: "POST",
159741
159466
  headers: {
@@ -159745,7 +159470,7 @@ class OpenAICompatibleEmbeddingProvider {
159745
159470
  body: JSON.stringify({
159746
159471
  model: this.model,
159747
159472
  input: texts,
159748
- ...this.inputType ? { input_type: this.inputType } : {},
159473
+ ...inputTypeForRequest ? { input_type: inputTypeForRequest } : {},
159749
159474
  ...this.truncate ? { truncate: this.truncate } : {}
159750
159475
  }),
159751
159476
  redirect: "error",
@@ -159901,7 +159626,7 @@ function isEmbeddingRow(row) {
159901
159626
  const candidate = row;
159902
159627
  return typeof candidate.memoryId === "number" && isEmbeddingBlob(candidate.embedding) && (candidate.modelId === null || typeof candidate.modelId === "string");
159903
159628
  }
159904
- function toFloat32Array3(blob) {
159629
+ function toFloat32Array2(blob) {
159905
159630
  if (blob instanceof Uint8Array) {
159906
159631
  const buffer2 = blob.buffer.slice(blob.byteOffset, blob.byteOffset + blob.byteLength);
159907
159632
  return new Float32Array(buffer2);
@@ -159949,7 +159674,7 @@ function loadAllEmbeddings(db, projectPath) {
159949
159674
  const embeddings = new Map;
159950
159675
  for (const row of rows) {
159951
159676
  embeddings.set(row.memoryId, {
159952
- embedding: toFloat32Array3(row.embedding),
159677
+ embedding: toFloat32Array2(row.embedding),
159953
159678
  modelId: row.modelId
159954
159679
  });
159955
159680
  }
@@ -159978,8 +159703,8 @@ function getMemoryEmbedCoverage(db, projectPath, modelId) {
159978
159703
  }
159979
159704
 
159980
159705
  // ../plugin/src/features/magic-context/project-embedding-registry.ts
159981
- import { createHash as createHash6, randomUUID } from "node:crypto";
159982
159706
  init_logger();
159707
+ import { createHash as createHash6, randomUUID } from "node:crypto";
159983
159708
 
159984
159709
  // ../plugin/src/features/magic-context/git-commits/storage-git-commit-embeddings.ts
159985
159710
  var saveStatements = new WeakMap;
@@ -160437,18 +160162,13 @@ var loadUnembeddedMemoriesStatements = new WeakMap;
160437
160162
  var globalRegistrationGeneration = 0;
160438
160163
  var testProviderFactory = null;
160439
160164
  function resolveEmbeddingConfig(config2) {
160440
- if (!config2 || config2.provider === "local") {
160441
- return {
160442
- provider: "local",
160443
- model: config2?.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
160444
- ...config2?.max_input_tokens ? {
160445
- max_input_tokens: normalizeCompartmentChunkMaxInputTokens(config2.max_input_tokens)
160446
- } : {}
160447
- };
160165
+ if (!config2 || config2.provider === "off") {
160166
+ return { provider: "off" };
160448
160167
  }
160449
160168
  if (config2.provider === "openai-compatible") {
160450
160169
  const apiKey = config2.api_key?.trim();
160451
160170
  const inputType = config2.input_type?.trim();
160171
+ const queryInputType = config2.query_input_type?.trim();
160452
160172
  const truncate = config2.truncate?.trim();
160453
160173
  return {
160454
160174
  provider: "openai-compatible",
@@ -160456,6 +160176,7 @@ function resolveEmbeddingConfig(config2) {
160456
160176
  endpoint: config2.endpoint.trim(),
160457
160177
  ...apiKey ? { api_key: apiKey } : {},
160458
160178
  ...inputType ? { input_type: inputType } : {},
160179
+ ...queryInputType ? { query_input_type: queryInputType } : {},
160459
160180
  ...truncate ? { truncate } : {},
160460
160181
  ...config2.max_input_tokens ? {
160461
160182
  max_input_tokens: normalizeCompartmentChunkMaxInputTokens(config2.max_input_tokens)
@@ -160477,11 +160198,12 @@ function createProvider(config2) {
160477
160198
  model: config2.model,
160478
160199
  apiKey: config2.api_key,
160479
160200
  inputType: config2.input_type,
160201
+ queryInputType: config2.query_input_type,
160480
160202
  truncate: config2.truncate,
160481
160203
  maxInputTokens: config2.max_input_tokens
160482
160204
  });
160483
160205
  }
160484
- return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
160206
+ return null;
160485
160207
  }
160486
160208
  function stableStringify2(value) {
160487
160209
  if (Array.isArray(value)) {
@@ -160533,7 +160255,7 @@ function snapshotFor(registration) {
160533
160255
  modelId: registration.observationMode || !providerIsOn ? "off" : registration.modelId,
160534
160256
  chunkModelId: registration.observationMode || !providerIsOn ? "off" : registration.chunkModelId,
160535
160257
  model: registration.observationMode || !providerIsOn ? "off" : ("model" in registration.config) && registration.config.model.trim() ? registration.config.model.trim() : registration.modelId,
160536
- provider: registration.observationMode || !providerIsOn ? "off" : registration.config.provider ?? "local"
160258
+ provider: registration.observationMode || !providerIsOn ? "off" : registration.config.provider ?? "off"
160537
160259
  };
160538
160260
  }
160539
160261
  function disposeProvider(provider) {
@@ -160659,7 +160381,7 @@ function getOrCreateProjectProvider(registration) {
160659
160381
  registration.provider = provider;
160660
160382
  return provider;
160661
160383
  }
160662
- async function embedTextForProject(projectIdentity, text, signal) {
160384
+ async function embedTextForProject(projectIdentity, text, signal, purpose = "passage") {
160663
160385
  const registration = projectRegistrations.get(projectIdentity);
160664
160386
  if (!registration)
160665
160387
  return null;
@@ -160668,7 +160390,7 @@ async function embedTextForProject(projectIdentity, text, signal) {
160668
160390
  const provider = getOrCreateProjectProvider(registration);
160669
160391
  if (!provider)
160670
160392
  return null;
160671
- const vector = await provider.embed(text, signal);
160393
+ const vector = await provider.embed(text, signal, purpose);
160672
160394
  if (!vector)
160673
160395
  return null;
160674
160396
  const current = projectRegistrations.get(projectIdentity);
@@ -160677,7 +160399,7 @@ async function embedTextForProject(projectIdentity, text, signal) {
160677
160399
  }
160678
160400
  return { vector, modelId, generation };
160679
160401
  }
160680
- async function embedBatchForProject(projectIdentity, texts, signal) {
160402
+ async function embedBatchForProject(projectIdentity, texts, signal, purpose = "passage") {
160681
160403
  if (texts.length === 0) {
160682
160404
  const registration2 = projectRegistrations.get(projectIdentity);
160683
160405
  if (!registration2 || registration2.observationMode)
@@ -160693,7 +160415,7 @@ async function embedBatchForProject(projectIdentity, texts, signal) {
160693
160415
  const provider = getOrCreateProjectProvider(registration);
160694
160416
  if (!provider)
160695
160417
  return null;
160696
- const vectors = await provider.embedBatch(texts, signal);
160418
+ const vectors = await provider.embedBatch(texts, signal, purpose);
160697
160419
  const current = projectRegistrations.get(projectIdentity);
160698
160420
  if (!current || current.generation !== generation || current.runtimeFingerprint !== runtimeFingerprint) {
160699
160421
  return null;
@@ -160750,7 +160472,7 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
160750
160472
  const maxInputTokens = getProjectEmbeddingMaxInputTokens(projectIdentity);
160751
160473
  const prepared = [];
160752
160474
  for (const candidate of candidates) {
160753
- const canonicalText = buildCanonicalChunkTextFromFts(db, candidate.sessionId, candidate.startMessage, candidate.endMessage);
160475
+ const canonicalText = buildCanonicalChunkTextFromFts(db, candidate.sessionId, candidate.startMessage, candidate.endMessage) || buildCompartmentSummaryFallbackText(db, candidate.id);
160754
160476
  if (canonicalText.length === 0) {
160755
160477
  noWork.push(candidate.id);
160756
160478
  continue;
@@ -160943,8 +160665,7 @@ function getEmbeddingCoverageStatus(db, projectIdentity, sessionId) {
160943
160665
 
160944
160666
  // ../plugin/src/features/magic-context/memory/embedding.ts
160945
160667
  var DEFAULT_EMBEDDING_CONFIG = {
160946
- provider: "local",
160947
- model: DEFAULT_LOCAL_EMBEDDING_MODEL
160668
+ provider: "off"
160948
160669
  };
160949
160670
  var embeddingConfig = DEFAULT_EMBEDDING_CONFIG;
160950
160671
  var provider = null;
@@ -160959,11 +160680,12 @@ function createProvider2(config2) {
160959
160680
  model: config2.model,
160960
160681
  apiKey: config2.api_key,
160961
160682
  inputType: config2.input_type,
160683
+ queryInputType: config2.query_input_type,
160962
160684
  truncate: config2.truncate,
160963
160685
  maxInputTokens: config2.max_input_tokens
160964
160686
  });
160965
160687
  }
160966
- return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
160688
+ return null;
160967
160689
  }
160968
160690
  function getOrCreateProvider() {
160969
160691
  if (provider) {
@@ -161194,6 +160916,8 @@ var SESSION_META_SELECT_COLUMNS = [
161194
160916
  "recovery_no_eligible_head_count",
161195
160917
  "force_emergency_bypass_window_start",
161196
160918
  "force_emergency_bypass_used",
160919
+ "emergency_drain_active",
160920
+ "historian_drain_failure_at",
161197
160921
  "upgrade_reminded_at",
161198
160922
  "pi_stable_id_scheme"
161199
160923
  ];
@@ -161243,6 +160967,8 @@ var META_COLUMNS = {
161243
160967
  recoveryNoEligibleHeadCount: "recovery_no_eligible_head_count",
161244
160968
  forceEmergencyBypassWindowStart: "force_emergency_bypass_window_start",
161245
160969
  forceEmergencyBypassUsed: "force_emergency_bypass_used",
160970
+ emergencyDrainActive: "emergency_drain_active",
160971
+ historianDrainFailureAt: "historian_drain_failure_at",
161246
160972
  upgradeRemindedAt: "upgrade_reminded_at",
161247
160973
  piStableIdScheme: "pi_stable_id_scheme"
161248
160974
  };
@@ -161630,9 +161356,9 @@ function escapeXmlContent(s) {
161630
161356
  init_data_path();
161631
161357
  init_logger();
161632
161358
  import { existsSync as existsSync6 } from "node:fs";
161633
- import { join as join7 } from "node:path";
161359
+ import { join as join6 } from "node:path";
161634
161360
  function getOpenCodeDbPath() {
161635
- return join7(getDataDir(), "opencode", "opencode.db");
161361
+ return join6(getDataDir(), "opencode", "opencode.db");
161636
161362
  }
161637
161363
  function openCodeDbExists() {
161638
161364
  return existsSync6(getOpenCodeDbPath());
@@ -161944,6 +161670,24 @@ class ToolMutationBatch {
161944
161670
  }
161945
161671
 
161946
161672
  // ../plugin/src/hooks/magic-context/read-session-chunk.ts
161673
+ var BLOCK_TOKEN_MEMO_MAX = 2048;
161674
+ var blockTokenMemo = new Map;
161675
+ function estimateBlockTokens(blockText) {
161676
+ const cached2 = blockTokenMemo.get(blockText);
161677
+ if (cached2 !== undefined) {
161678
+ blockTokenMemo.delete(blockText);
161679
+ blockTokenMemo.set(blockText, cached2);
161680
+ return cached2;
161681
+ }
161682
+ const count = estimateTokens(blockText);
161683
+ if (blockTokenMemo.size >= BLOCK_TOKEN_MEMO_MAX) {
161684
+ const oldest = blockTokenMemo.keys().next().value;
161685
+ if (oldest !== undefined)
161686
+ blockTokenMemo.delete(oldest);
161687
+ }
161688
+ blockTokenMemo.set(blockText, count);
161689
+ return count;
161690
+ }
161947
161691
  var activeRawMessageCache = null;
161948
161692
  var activeAbsoluteCountCache = null;
161949
161693
  var sessionProviders = new Map;
@@ -162126,7 +161870,7 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
162126
161870
  if (!currentBlock)
162127
161871
  return true;
162128
161872
  const blockText = formatBlock(currentBlock);
162129
- const blockTokens = estimateTokens(blockText);
161873
+ const blockTokens = estimateBlockTokens(blockText);
162130
161874
  if (totalTokens + blockTokens > tokenBudget && totalTokens > 0) {
162131
161875
  return false;
162132
161876
  }
@@ -167733,12 +167477,12 @@ function canonicalizeDocContent(raw) {
167733
167477
  }
167734
167478
  function fingerprintFile(filePath) {
167735
167479
  try {
167736
- const stat2 = lstatSync(filePath);
167737
- const isReadableDoc = stat2.isFile() && stat2.size <= MAX_PROJECT_DOC_BYTES;
167480
+ const stat = lstatSync(filePath);
167481
+ const isReadableDoc = stat.isFile() && stat.size <= MAX_PROJECT_DOC_BYTES;
167738
167482
  return {
167739
167483
  exists: isReadableDoc,
167740
- mtimeMs: stat2.mtimeMs,
167741
- size: stat2.size
167484
+ mtimeMs: stat.mtimeMs,
167485
+ size: stat.size
167742
167486
  };
167743
167487
  } catch {
167744
167488
  return { exists: false, mtimeMs: 0, size: 0 };
@@ -168076,7 +167820,9 @@ var DEFAULT_PROTECTED_TAIL_META = {
168076
167820
  protectedTailDrainTokens: 0,
168077
167821
  recoveryNoEligibleHeadCount: 0,
168078
167822
  forceEmergencyBypassWindowStart: 0,
168079
- forceEmergencyBypassUsed: 0
167823
+ forceEmergencyBypassUsed: 0,
167824
+ emergencyDrainActive: 0,
167825
+ historianDrainFailureAt: 0
168080
167826
  };
168081
167827
  function toProtectedTailMeta(row) {
168082
167828
  if (row === null || typeof row !== "object")
@@ -168090,7 +167836,9 @@ function toProtectedTailMeta(row) {
168090
167836
  protectedTailDrainTokens: numberOr(r.protected_tail_drain_tokens, 0),
168091
167837
  recoveryNoEligibleHeadCount: numberOr(r.recovery_no_eligible_head_count, 0),
168092
167838
  forceEmergencyBypassWindowStart: numberOr(r.force_emergency_bypass_window_start, 0),
168093
- forceEmergencyBypassUsed: numberOr(r.force_emergency_bypass_used, 0)
167839
+ forceEmergencyBypassUsed: numberOr(r.force_emergency_bypass_used, 0),
167840
+ emergencyDrainActive: numberOr(r.emergency_drain_active, 0),
167841
+ historianDrainFailureAt: numberOr(r.historian_drain_failure_at, 0)
168094
167842
  };
168095
167843
  }
168096
167844
  function loadProtectedTailMeta(db, sessionId) {
@@ -168098,7 +167846,7 @@ function loadProtectedTailMeta(db, sessionId) {
168098
167846
  const row = db.prepare(`SELECT prior_boundary_ordinal, protected_tail_policy_version,
168099
167847
  protected_tail_drain_window_started_at, protected_tail_drain_tokens,
168100
167848
  recovery_no_eligible_head_count, force_emergency_bypass_window_start,
168101
- force_emergency_bypass_used
167849
+ force_emergency_bypass_used, emergency_drain_active, historian_drain_failure_at
168102
167850
  FROM session_meta WHERE session_id = ?`).get(sessionId);
168103
167851
  return toProtectedTailMeta(row);
168104
167852
  }
@@ -168142,6 +167890,17 @@ function protectedTailWindowBudget(usagePercentage, usable, perRunCap) {
168142
167890
  return Math.min(750000, Math.max(3 * perRunCap, Math.round(0.35 * usable)));
168143
167891
  return Math.min(500000, Math.max(perRunCap, Math.round(0.2 * usable)));
168144
167892
  }
167893
+ var EMERGENCY_DRAIN_ENTER_PERCENTAGE = 95;
167894
+ var EMERGENCY_DRAIN_EXIT_MARGIN = 10;
167895
+ var EMERGENCY_DRAIN_FALLBACK_EXIT_PERCENTAGE = 55;
167896
+ var EMERGENCY_DRAIN_FAILURE_BACKOFF_MS = 60000;
167897
+ var EMERGENCY_DRAIN_MAX_LATCH_MS = 30 * 60 * 1000;
167898
+ function emergencyDrainExitThreshold(executeThresholdPercentage) {
167899
+ if (!Number.isFinite(executeThresholdPercentage) || executeThresholdPercentage <= 0) {
167900
+ return EMERGENCY_DRAIN_FALLBACK_EXIT_PERCENTAGE;
167901
+ }
167902
+ return Math.max(0, executeThresholdPercentage - EMERGENCY_DRAIN_EXIT_MARGIN);
167903
+ }
168145
167904
  function reserveProtectedTailDrainTokens(args) {
168146
167905
  const now = args.now ?? Date.now();
168147
167906
  const requested = Math.max(0, Math.floor(args.trueRawTokens));
@@ -168160,18 +167919,30 @@ function reserveProtectedTailDrainTokens(args) {
168160
167919
  let meta3 = loadProtectedTailMeta(args.db, args.sessionId);
168161
167920
  if (now - meta3.protectedTailDrainWindowStartedAt > DRAIN_WINDOW_MS) {
168162
167921
  args.db.prepare(`UPDATE session_meta
168163
- SET protected_tail_drain_window_started_at = ?, protected_tail_drain_tokens = 0,
168164
- force_emergency_bypass_window_start = ?, force_emergency_bypass_used = 0
168165
- WHERE session_id = ?`).run(now, now, args.sessionId);
167922
+ SET protected_tail_drain_window_started_at = ?, protected_tail_drain_tokens = 0
167923
+ WHERE session_id = ?`).run(now, args.sessionId);
168166
167924
  meta3 = loadProtectedTailMeta(args.db, args.sessionId);
168167
167925
  }
167926
+ const exitThreshold = emergencyDrainExitThreshold(args.executeThresholdPercentage);
167927
+ let latchActiveSince = meta3.emergencyDrainActive;
167928
+ if (args.usagePercentage >= EMERGENCY_DRAIN_ENTER_PERCENTAGE) {
167929
+ if (latchActiveSince <= 0)
167930
+ latchActiveSince = now;
167931
+ } else if (latchActiveSince > 0) {
167932
+ const expired = now - latchActiveSince > EMERGENCY_DRAIN_MAX_LATCH_MS;
167933
+ if (args.usagePercentage < exitThreshold || expired)
167934
+ latchActiveSince = 0;
167935
+ }
167936
+ if (latchActiveSince !== meta3.emergencyDrainActive) {
167937
+ args.db.prepare("UPDATE session_meta SET emergency_drain_active = ? WHERE session_id = ?").run(latchActiveSince, args.sessionId);
167938
+ }
167939
+ const latchActive = latchActiveSince > 0;
168168
167940
  const budget = protectedTailWindowBudget(args.usagePercentage, args.usable, args.perRunCap);
168169
167941
  const remaining = Math.max(0, budget - meta3.protectedTailDrainTokens);
168170
167942
  let reserved = Math.min(requested, args.perRunCap, remaining);
168171
167943
  let bypass = false;
168172
- const bypassWindowExpired = now - meta3.forceEmergencyBypassWindowStart > DRAIN_WINDOW_MS;
168173
- const bypassUsed = bypassWindowExpired ? 0 : meta3.forceEmergencyBypassUsed;
168174
- if (reserved <= 0 && args.usagePercentage >= 95 && bypassUsed === 0) {
167944
+ const inFailureBackoff = meta3.historianDrainFailureAt > 0 && now - meta3.historianDrainFailureAt < EMERGENCY_DRAIN_FAILURE_BACKOFF_MS;
167945
+ if (reserved <= 0 && latchActive && !inFailureBackoff) {
168175
167946
  reserved = Math.min(requested, args.perRunCap);
168176
167947
  bypass = true;
168177
167948
  }
@@ -168179,10 +167950,8 @@ function reserveProtectedTailDrainTokens(args) {
168179
167950
  return;
168180
167951
  args.db.prepare(`UPDATE session_meta
168181
167952
  SET protected_tail_drain_window_started_at = CASE WHEN protected_tail_drain_window_started_at = 0 THEN ? ELSE protected_tail_drain_window_started_at END,
168182
- protected_tail_drain_tokens = COALESCE(protected_tail_drain_tokens, 0) + ?,
168183
- force_emergency_bypass_window_start = CASE WHEN ? THEN ? ELSE force_emergency_bypass_window_start END,
168184
- force_emergency_bypass_used = CASE WHEN ? THEN 1 ELSE force_emergency_bypass_used END
168185
- WHERE session_id = ?`).run(now, reserved, bypass ? 1 : 0, now, bypass ? 1 : 0, args.sessionId);
167953
+ protected_tail_drain_tokens = COALESCE(protected_tail_drain_tokens, 0) + ?
167954
+ WHERE session_id = ?`).run(now, reserved, args.sessionId);
168186
167955
  result = {
168187
167956
  ok: true,
168188
167957
  reservedTokens: reserved,
@@ -168192,6 +167961,25 @@ function reserveProtectedTailDrainTokens(args) {
168192
167961
  })();
168193
167962
  return result;
168194
167963
  }
167964
+ function clearEmergencyDrainLatch(db, sessionId) {
167965
+ db.transaction(() => {
167966
+ ensureSessionMetaRow(db, sessionId);
167967
+ db.prepare("UPDATE session_meta SET emergency_drain_active = 0 WHERE session_id = ?").run(sessionId);
167968
+ })();
167969
+ }
167970
+ function recordHistorianDrainFailure(db, sessionId, now) {
167971
+ const ts = now ?? Date.now();
167972
+ db.transaction(() => {
167973
+ ensureSessionMetaRow(db, sessionId);
167974
+ db.prepare("UPDATE session_meta SET historian_drain_failure_at = ? WHERE session_id = ?").run(ts, sessionId);
167975
+ })();
167976
+ }
167977
+ function clearHistorianDrainFailure(db, sessionId) {
167978
+ db.transaction(() => {
167979
+ ensureSessionMetaRow(db, sessionId);
167980
+ db.prepare("UPDATE session_meta SET historian_drain_failure_at = 0 WHERE session_id = ?").run(sessionId);
167981
+ })();
167982
+ }
168195
167983
  function rollbackProtectedTailDrainReservation(db, reservation) {
168196
167984
  if (!reservation || reservation.tokens <= 0)
168197
167985
  return;
@@ -169213,12 +169001,17 @@ function getOldestActiveUnprotectedToolTags(db, sessionId, protectedTags = 0, li
169213
169001
  toolName: typeof row.tool_name === "string" ? row.tool_name : null
169214
169002
  }));
169215
169003
  }
169216
- function getTriggerTagTokenUpperBound(db, sessionId) {
169217
- const row = db.prepare(`SELECT
169004
+ function getTriggerTagTokenUpperBound(db, sessionId, floor = 0) {
169005
+ const sql = floor > 0 ? `SELECT
169218
169006
  COALESCE(SUM(COALESCE(token_count, 0) + COALESCE(input_token_count, 0) + COALESCE(reasoning_token_count, 0)), 0) AS bound,
169219
169007
  COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
169220
169008
  FROM tags
169221
- WHERE session_id = ? AND status IN ('active', 'dropped')`).get(sessionId);
169009
+ WHERE session_id = ? AND status IN ('active', 'dropped') AND tag_number >= ?` : `SELECT
169010
+ COALESCE(SUM(COALESCE(token_count, 0) + COALESCE(input_token_count, 0) + COALESCE(reasoning_token_count, 0)), 0) AS bound,
169011
+ COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
169012
+ FROM tags
169013
+ WHERE session_id = ? AND status IN ('active', 'dropped')`;
169014
+ const row = floor > 0 ? db.prepare(sql).get(sessionId, floor) : db.prepare(sql).get(sessionId);
169222
169015
  return { bound: row?.bound ?? 0, nullCount: row?.null_count ?? 0 };
169223
169016
  }
169224
169017
  function updateTagInputByteSize(db, sessionId, tagNumber, newInputByteSize) {
@@ -169245,10 +169038,12 @@ function getUpdateTagInputTokenCountStatement(db) {
169245
169038
  function updateTagTokenCount(db, sessionId, tagNumber, newTokenCount) {
169246
169039
  getUpdateTagTokenCountStatement(db).run(newTokenCount, sessionId, tagNumber);
169247
169040
  }
169248
- function getAllStatusTagTokenTotalsFlat(db, sessionId) {
169249
- const rows = db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
169250
- FROM tags
169251
- WHERE session_id = ?`).all(sessionId);
169041
+ function getAllStatusTagTokenTotalsFlat(db, sessionId, floor = 0) {
169042
+ const rows = floor > 0 ? db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
169043
+ FROM tags
169044
+ WHERE session_id = ? AND tag_number >= ?`).all(sessionId, floor) : db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
169045
+ FROM tags
169046
+ WHERE session_id = ?`).all(sessionId);
169252
169047
  const totals = new Map;
169253
169048
  const nullMessageIds = new Set;
169254
169049
  for (const row of rows) {
@@ -169367,6 +169162,52 @@ function getTagNumberByMessageId(db, sessionId, messageId) {
169367
169162
  const row = getTagNumberByMessageIdStatement(db).get(sessionId, messageId);
169368
169163
  return isTagNumberRow(row) ? row.tag_number : null;
169369
169164
  }
169165
+ var getMinMessageTagNumberForRawIdStatements = new WeakMap;
169166
+ function isMinTagNumberRow(row) {
169167
+ return row !== null && typeof row === "object" && "m" in row;
169168
+ }
169169
+ function getMinMessageTagNumberForRawId(db, sessionId, rawId) {
169170
+ if (rawId.includes(":"))
169171
+ return null;
169172
+ let stmt = getMinMessageTagNumberForRawIdStatements.get(db);
169173
+ if (!stmt) {
169174
+ stmt = db.prepare("SELECT MIN(tag_number) AS m FROM tags WHERE session_id = ? AND message_id >= ? AND message_id < ?");
169175
+ getMinMessageTagNumberForRawIdStatements.set(db, stmt);
169176
+ }
169177
+ const row = stmt.get(sessionId, `${rawId}:`, `${rawId};`);
169178
+ return isMinTagNumberRow(row) && typeof row.m === "number" ? row.m : null;
169179
+ }
169180
+ var TAGGER_FLOOR_SCAN_MESSAGES = 8;
169181
+ var TAGGER_FLOOR_MAX_PROBES = 64;
169182
+ var TAGGER_FLOOR_SAFETY_MARGIN = 256;
169183
+ var TAGGER_FLOOR_PER_SKIP_MARGIN = 64;
169184
+ function deriveTagLoadFloor(db, sessionId, rawIds) {
169185
+ let min = Number.POSITIVE_INFINITY;
169186
+ let probes = 0;
169187
+ let hits = 0;
169188
+ let skippedBeforeFirstHit = 0;
169189
+ for (const rawId of rawIds) {
169190
+ if (typeof rawId !== "string" || rawId.length === 0)
169191
+ continue;
169192
+ if (probes >= TAGGER_FLOOR_MAX_PROBES)
169193
+ break;
169194
+ probes++;
169195
+ const m = getMinMessageTagNumberForRawId(db, sessionId, rawId);
169196
+ if (m === null) {
169197
+ if (hits === 0)
169198
+ skippedBeforeFirstHit++;
169199
+ continue;
169200
+ }
169201
+ if (m < min)
169202
+ min = m;
169203
+ if (++hits >= TAGGER_FLOOR_SCAN_MESSAGES)
169204
+ break;
169205
+ }
169206
+ if (!Number.isFinite(min))
169207
+ return 0;
169208
+ const margin = TAGGER_FLOOR_SAFETY_MARGIN + skippedBeforeFirstHit * TAGGER_FLOOR_PER_SKIP_MARGIN;
169209
+ return Math.max(0, min - margin);
169210
+ }
169370
169211
  var TAG_SELECT_COLUMNS = "id, message_id, type, status, drop_mode, tool_name, input_byte_size, byte_size, reasoning_byte_size, session_id, tag_number, caveman_depth, tool_owner_message_id";
169371
169212
  function getTagsBySession(db, sessionId) {
169372
169213
  const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? ORDER BY tag_number ASC, id ASC`).all(sessionId).filter(isTagRow);
@@ -171540,13 +171381,13 @@ function extractM0Block(m0Text, tag) {
171540
171381
 
171541
171382
  // ../plugin/src/hooks/magic-context/key-files-block.ts
171542
171383
  import { readFileSync as readFileSync6, realpathSync as realpathSync2 } from "node:fs";
171543
- import { join as join9, sep as sep2 } from "node:path";
171384
+ import { join as join8, sep as sep2 } from "node:path";
171544
171385
 
171545
171386
  // ../plugin/src/features/magic-context/key-files/aft-availability.ts
171546
171387
  var import_comment_json2 = __toESM(require_src2(), 1);
171547
171388
  import { existsSync as existsSync7, readFileSync as readFileSync5 } from "node:fs";
171548
171389
  import { homedir as homedir4 } from "node:os";
171549
- import { isAbsolute as isAbsolute2, join as join8, resolve as resolve3 } from "node:path";
171390
+ import { isAbsolute as isAbsolute2, join as join7, resolve as resolve3 } from "node:path";
171550
171391
  import { fileURLToPath } from "node:url";
171551
171392
  var overrideAvailability = null;
171552
171393
  function parseConfig(path5) {
@@ -171567,14 +171408,14 @@ function resolveLocalEntryPackageName(value, configDir) {
171567
171408
  return null;
171568
171409
  }
171569
171410
  } else if (value.startsWith("~/")) {
171570
- dir = join8(homedir4(), value.slice(2));
171411
+ dir = join7(homedir4(), value.slice(2));
171571
171412
  } else if (value.startsWith("/") || value.startsWith("./") || value.startsWith("../")) {
171572
171413
  dir = isAbsolute2(value) ? value : resolve3(configDir, value);
171573
171414
  } else {
171574
171415
  return null;
171575
171416
  }
171576
171417
  try {
171577
- const pkg = JSON.parse(readFileSync5(join8(dir, "package.json"), "utf-8"));
171418
+ const pkg = JSON.parse(readFileSync5(join7(dir, "package.json"), "utf-8"));
171578
171419
  return typeof pkg.name === "string" ? pkg.name : null;
171579
171420
  } catch {
171580
171421
  return null;
@@ -171605,16 +171446,16 @@ function hasAftAtKeys(value, keys2, configDir) {
171605
171446
  function getAftAvailability() {
171606
171447
  const home = process.env.HOME || homedir4();
171607
171448
  const opencodePaths = [
171608
- join8(home, ".config", "opencode", "opencode.jsonc"),
171609
- join8(home, ".config", "opencode", "opencode.json")
171449
+ join7(home, ".config", "opencode", "opencode.jsonc"),
171450
+ join7(home, ".config", "opencode", "opencode.json")
171610
171451
  ];
171611
- const piPaths = [join8(home, ".pi", "agent", "settings.json")];
171452
+ const piPaths = [join7(home, ".pi", "agent", "settings.json")];
171612
171453
  const checkedPaths = [...opencodePaths, ...piPaths];
171613
171454
  let opencode = false;
171614
171455
  for (const path5 of opencodePaths) {
171615
171456
  try {
171616
171457
  const config2 = parseConfig(path5);
171617
- const configDir = join8(path5, "..");
171458
+ const configDir = join7(path5, "..");
171618
171459
  if (hasAftAtKeys(config2, ["plugin", "plugins", "mcp", "mcp_servers"], configDir)) {
171619
171460
  opencode = true;
171620
171461
  break;
@@ -171625,7 +171466,7 @@ function getAftAvailability() {
171625
171466
  for (const path5 of piPaths) {
171626
171467
  try {
171627
171468
  const config2 = parseConfig(path5);
171628
- const configDir = join8(path5, "..");
171469
+ const configDir = join7(path5, "..");
171629
171470
  if (hasAftAtKeys(config2, ["packages", "extensions"], configDir)) {
171630
171471
  pi = true;
171631
171472
  break;
@@ -171704,7 +171545,7 @@ function buildKeyFilesBlock(db, projectPath, config2 = { enabled: true, tokenBud
171704
171545
  let nextStale = null;
171705
171546
  let observed = false;
171706
171547
  try {
171707
- const absPath = join9(projectPath, row.path);
171548
+ const absPath = join8(projectPath, row.path);
171708
171549
  const real = realpathSync2(absPath);
171709
171550
  if (!isUnderResolvedRoot(projectRoot, real)) {
171710
171551
  nextStale = "missing";
@@ -172105,7 +171946,7 @@ function createCtxSearchTool(deps) {
172105
171946
  memoryEnabled,
172106
171947
  embeddingEnabled,
172107
171948
  embedQuery: async (text, signal) => {
172108
- const result = await embedTextForProject(projectIdentity, text, signal);
171949
+ const result = await embedTextForProject(projectIdentity, text, signal, "query");
172109
171950
  return result?.vector ?? null;
172110
171951
  },
172111
171952
  isEmbeddingRuntimeEnabled: () => embeddingEnabled === true,