@cortexkit/pi-magic-context 0.22.3 → 0.22.5

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.
@@ -46,167 +46,6 @@ var __export = (target, all) => {
46
46
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
47
47
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
48
48
 
49
- // ../plugin/src/shared/harness.ts
50
- function setHarness(value) {
51
- if (harnessLocked && currentHarness !== value) {
52
- throw new Error(`Magic Context: harness already locked to "${currentHarness}"; cannot change to "${value}"`);
53
- }
54
- currentHarness = value;
55
- harnessLocked = true;
56
- }
57
- function getHarness() {
58
- return currentHarness;
59
- }
60
- var currentHarness = "opencode", harnessLocked = false;
61
-
62
- // ../plugin/src/shared/data-path.ts
63
- import * as os from "node:os";
64
- import * as path from "node:path";
65
- function getDataDir() {
66
- return process.env.XDG_DATA_HOME ?? path.join(os.homedir(), ".local", "share");
67
- }
68
- function getMagicContextTempDir(harness = getHarness()) {
69
- return path.join(os.tmpdir(), harness, "magic-context");
70
- }
71
- function getMagicContextLogPath(harness = getHarness()) {
72
- return path.join(getMagicContextTempDir(harness), "magic-context.log");
73
- }
74
- function getProjectMagicContextDir(directory) {
75
- return path.join(directory, ".opencode", "magic-context");
76
- }
77
- function getProjectMagicContextHistorianDir(directory) {
78
- return path.join(getProjectMagicContextDir(directory), "historian");
79
- }
80
- function getOpenCodeStorageDir() {
81
- return path.join(getDataDir(), "opencode", "storage");
82
- }
83
- function getMagicContextStorageDir() {
84
- return path.join(getDataDir(), "cortexkit", "magic-context");
85
- }
86
- function getLegacyOpenCodeMagicContextStorageDir() {
87
- return path.join(getOpenCodeStorageDir(), "plugin", "magic-context");
88
- }
89
- var init_data_path = () => {};
90
-
91
- // ../plugin/src/shared/logger.ts
92
- import * as fs from "node:fs";
93
- import * as path2 from "node:path";
94
- function ensureDir(filePath) {
95
- const dir = path2.dirname(filePath);
96
- if (dir === lastEnsuredDir)
97
- return;
98
- try {
99
- fs.mkdirSync(dir, { recursive: true });
100
- lastEnsuredDir = dir;
101
- } catch {}
102
- }
103
- function flush() {
104
- if (flushTimer) {
105
- clearTimeout(flushTimer);
106
- flushTimer = null;
107
- }
108
- if (buffer.length === 0)
109
- return;
110
- const data = buffer.join("");
111
- buffer = [];
112
- try {
113
- const logFile = getMagicContextLogPath();
114
- ensureDir(logFile);
115
- fs.appendFileSync(logFile, data);
116
- } catch {}
117
- }
118
- function scheduleFlush() {
119
- if (flushTimer)
120
- return;
121
- flushTimer = setTimeout(() => {
122
- flushTimer = null;
123
- flush();
124
- }, FLUSH_INTERVAL_MS);
125
- }
126
- function log(message, data) {
127
- if (isTestEnv)
128
- return;
129
- try {
130
- const timestamp = new Date().toISOString();
131
- const serialized = data === undefined ? "" : data instanceof Error ? ` ${data.message}${data.stack ? `
132
- ${data.stack}` : ""}` : ` ${JSON.stringify(data)}`;
133
- buffer.push(`[${timestamp}] ${message}${serialized}
134
- `);
135
- if (buffer.length >= BUFFER_SIZE_LIMIT) {
136
- flush();
137
- } else {
138
- scheduleFlush();
139
- }
140
- } catch {}
141
- }
142
- function sessionLog(sessionId, message, data) {
143
- log(`[magic-context][${sessionId}] ${message}`, data);
144
- }
145
- var isTestEnv = false, buffer, flushTimer = null, FLUSH_INTERVAL_MS = 500, BUFFER_SIZE_LIMIT = 50, lastEnsuredDir = null;
146
- var init_logger = __esm(() => {
147
- init_data_path();
148
- buffer = [];
149
- if (!isTestEnv) {
150
- process.on("exit", flush);
151
- }
152
- });
153
-
154
- // ../plugin/src/shared/sqlite.ts
155
- function buildNodeSqliteDatabaseClass(DatabaseSync) {
156
- const SAVEPOINT = "mc_tx_sp";
157
-
158
- class NodeSqliteDatabase extends DatabaseSync {
159
- constructor(filename, options) {
160
- const translated = { ...options };
161
- if (options && "readonly" in options) {
162
- translated.readOnly = options.readonly;
163
- delete translated.readonly;
164
- }
165
- super(typeof filename === "string" ? filename : ":memory:", translated);
166
- }
167
- transaction(fn) {
168
- const self = this;
169
- const wrapped = function(...args) {
170
- const nested = self.isTransaction === true;
171
- self.exec(nested ? `SAVEPOINT ${SAVEPOINT}` : "BEGIN");
172
- try {
173
- const result = fn.apply(this, args);
174
- self.exec(nested ? `RELEASE ${SAVEPOINT}` : "COMMIT");
175
- return result;
176
- } catch (error) {
177
- if (nested) {
178
- self.exec(`ROLLBACK TO ${SAVEPOINT}`);
179
- self.exec(`RELEASE ${SAVEPOINT}`);
180
- } else {
181
- self.exec("ROLLBACK");
182
- }
183
- throw error;
184
- }
185
- };
186
- return wrapped;
187
- }
188
- }
189
- return NodeSqliteDatabase;
190
- }
191
- var isBun, bunSpec, nodeSpec, sqliteModule, DatabaseImpl, Database;
192
- var init_sqlite = __esm(async () => {
193
- isBun = typeof process !== "undefined" && typeof process.versions?.bun === "string";
194
- bunSpec = "bun:" + "sqlite";
195
- nodeSpec = "node:" + "sqlite";
196
- sqliteModule = isBun ? await import(bunSpec) : await import(nodeSpec);
197
- DatabaseImpl = isBun ? sqliteModule.Database : buildNodeSqliteDatabaseClass(sqliteModule.DatabaseSync);
198
- Database = DatabaseImpl;
199
- });
200
-
201
- // ../plugin/src/shared/sqlite-helpers.ts
202
- function closeQuietly(db) {
203
- if (!db)
204
- return;
205
- try {
206
- db.close();
207
- } catch {}
208
- }
209
-
210
49
  // ../../node_modules/.bun/esprima@4.0.1/node_modules/esprima/dist/esprima.js
211
50
  var require_esprima = __commonJS((exports, module) => {
212
51
  (function webpackUniversalModuleDefinition(root, factory) {
@@ -7964,57 +7803,53 @@ var require_src2 = __commonJS((exports, module) => {
7964
7803
  };
7965
7804
  });
7966
7805
 
7967
- // ../plugin/src/hooks/magic-context/read-session-db.ts
7968
- import { existsSync as existsSync6 } from "node:fs";
7969
- import { join as join7 } from "node:path";
7970
- function getOpenCodeDbPath() {
7971
- return join7(getDataDir(), "opencode", "opencode.db");
7806
+ // ../plugin/src/features/magic-context/storage-db.ts
7807
+ import { copyFileSync, cpSync, existsSync as existsSync3, mkdirSync as mkdirSync2 } from "node:fs";
7808
+ import { dirname as dirname2, join as join4 } from "node:path";
7809
+
7810
+ // ../plugin/src/shared/data-path.ts
7811
+ import * as os from "node:os";
7812
+ import * as path from "node:path";
7813
+
7814
+ // ../plugin/src/shared/harness.ts
7815
+ var currentHarness = "opencode";
7816
+ var harnessLocked = false;
7817
+ function setHarness(value) {
7818
+ if (harnessLocked && currentHarness !== value) {
7819
+ throw new Error(`Magic Context: harness already locked to "${currentHarness}"; cannot change to "${value}"`);
7820
+ }
7821
+ currentHarness = value;
7822
+ harnessLocked = true;
7972
7823
  }
7973
- function openCodeDbExists() {
7974
- return existsSync6(getOpenCodeDbPath());
7824
+ function getHarness() {
7825
+ return currentHarness;
7975
7826
  }
7976
- function closeCachedReadOnlyDb() {
7977
- if (!cachedReadOnlyDb) {
7978
- return;
7979
- }
7980
- try {
7981
- closeQuietly(cachedReadOnlyDb.db);
7982
- } catch (error51) {
7983
- log("[magic-context] failed to close cached OpenCode read-only DB:", error51);
7984
- } finally {
7985
- cachedReadOnlyDb = null;
7986
- }
7827
+
7828
+ // ../plugin/src/shared/data-path.ts
7829
+ function getDataDir() {
7830
+ return process.env.XDG_DATA_HOME ?? path.join(os.homedir(), ".local", "share");
7987
7831
  }
7988
- function getReadOnlySessionDb() {
7989
- const dbPath = getOpenCodeDbPath();
7990
- if (cachedReadOnlyDb?.path === dbPath) {
7991
- return cachedReadOnlyDb.db;
7992
- }
7993
- closeCachedReadOnlyDb();
7994
- const db = new Database(dbPath, { readonly: true });
7995
- cachedReadOnlyDb = { path: dbPath, db };
7996
- return db;
7832
+ function getMagicContextTempDir(harness = getHarness()) {
7833
+ return path.join(os.tmpdir(), harness, "magic-context");
7997
7834
  }
7998
- function withReadOnlySessionDb(fn) {
7999
- return fn(getReadOnlySessionDb());
7835
+ function getMagicContextLogPath(harness = getHarness()) {
7836
+ return path.join(getMagicContextTempDir(harness), "magic-context.log");
8000
7837
  }
8001
- function getRawSessionMessageCountFromDb(db, sessionId) {
8002
- const row = db.prepare(`SELECT COUNT(*) as count FROM message WHERE session_id = ?
8003
- AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
8004
- AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')`).get(sessionId);
8005
- return typeof row?.count === "number" ? row.count : 0;
7838
+ function getProjectMagicContextDir(directory) {
7839
+ return path.join(directory, ".opencode", "magic-context");
7840
+ }
7841
+ function getProjectMagicContextHistorianDir(directory) {
7842
+ return path.join(getProjectMagicContextDir(directory), "historian");
7843
+ }
7844
+ function getOpenCodeStorageDir() {
7845
+ return path.join(getDataDir(), "opencode", "storage");
7846
+ }
7847
+ function getMagicContextStorageDir() {
7848
+ return path.join(getDataDir(), "cortexkit", "magic-context");
7849
+ }
7850
+ function getLegacyOpenCodeMagicContextStorageDir() {
7851
+ return path.join(getOpenCodeStorageDir(), "plugin", "magic-context");
8006
7852
  }
8007
- var cachedReadOnlyDb = null;
8008
- var init_read_session_db = __esm(async () => {
8009
- init_data_path();
8010
- init_logger();
8011
- await init_sqlite();
8012
- });
8013
-
8014
- // ../plugin/src/features/magic-context/storage-db.ts
8015
- init_data_path();
8016
- import { copyFileSync, cpSync, existsSync as existsSync3, mkdirSync as mkdirSync2 } from "node:fs";
8017
- import { dirname as dirname2, join as join4 } from "node:path";
8018
7853
 
8019
7854
  // ../plugin/src/shared/error-message.ts
8020
7855
  function getErrorMessage(error) {
@@ -8092,12 +7927,124 @@ function safeString(value) {
8092
7927
  }
8093
7928
  }
8094
7929
 
8095
- // ../plugin/src/features/magic-context/storage-db.ts
8096
- init_logger();
8097
- await init_sqlite();
7930
+ // ../plugin/src/shared/logger.ts
7931
+ import * as fs from "node:fs";
7932
+ import * as path2 from "node:path";
7933
+ var isTestEnv = false;
7934
+ var buffer = [];
7935
+ var flushTimer = null;
7936
+ var FLUSH_INTERVAL_MS = 500;
7937
+ var BUFFER_SIZE_LIMIT = 50;
7938
+ var lastEnsuredDir = null;
7939
+ function ensureDir(filePath) {
7940
+ const dir = path2.dirname(filePath);
7941
+ if (dir === lastEnsuredDir)
7942
+ return;
7943
+ try {
7944
+ fs.mkdirSync(dir, { recursive: true });
7945
+ lastEnsuredDir = dir;
7946
+ } catch {}
7947
+ }
7948
+ function flush() {
7949
+ if (flushTimer) {
7950
+ clearTimeout(flushTimer);
7951
+ flushTimer = null;
7952
+ }
7953
+ if (buffer.length === 0)
7954
+ return;
7955
+ const data = buffer.join("");
7956
+ buffer = [];
7957
+ try {
7958
+ const logFile = getMagicContextLogPath();
7959
+ ensureDir(logFile);
7960
+ fs.appendFileSync(logFile, data);
7961
+ } catch {}
7962
+ }
7963
+ function scheduleFlush() {
7964
+ if (flushTimer)
7965
+ return;
7966
+ flushTimer = setTimeout(() => {
7967
+ flushTimer = null;
7968
+ flush();
7969
+ }, FLUSH_INTERVAL_MS);
7970
+ }
7971
+ function log(message, data) {
7972
+ if (isTestEnv)
7973
+ return;
7974
+ try {
7975
+ const timestamp = new Date().toISOString();
7976
+ const serialized = data === undefined ? "" : data instanceof Error ? ` ${data.message}${data.stack ? `
7977
+ ${data.stack}` : ""}` : ` ${JSON.stringify(data)}`;
7978
+ buffer.push(`[${timestamp}] ${message}${serialized}
7979
+ `);
7980
+ if (buffer.length >= BUFFER_SIZE_LIMIT) {
7981
+ flush();
7982
+ } else {
7983
+ scheduleFlush();
7984
+ }
7985
+ } catch {}
7986
+ }
7987
+ function sessionLog(sessionId, message, data) {
7988
+ log(`[magic-context][${sessionId}] ${message}`, data);
7989
+ }
7990
+ if (!isTestEnv) {
7991
+ process.on("exit", flush);
7992
+ }
7993
+
7994
+ // ../plugin/src/shared/sqlite.ts
7995
+ var isBun = typeof process !== "undefined" && typeof process.versions?.bun === "string";
7996
+ var bunSpec = "bun:" + "sqlite";
7997
+ var nodeSpec = "node:" + "sqlite";
7998
+ var sqliteModule = isBun ? await import(bunSpec) : await import(nodeSpec);
7999
+ var DatabaseImpl = isBun ? sqliteModule.Database : buildNodeSqliteDatabaseClass(sqliteModule.DatabaseSync);
8000
+ function buildNodeSqliteDatabaseClass(DatabaseSync) {
8001
+ const SAVEPOINT = "mc_tx_sp";
8002
+
8003
+ class NodeSqliteDatabase extends DatabaseSync {
8004
+ constructor(filename, options) {
8005
+ const translated = { ...options };
8006
+ if (options && "readonly" in options) {
8007
+ translated.readOnly = options.readonly;
8008
+ delete translated.readonly;
8009
+ }
8010
+ super(typeof filename === "string" ? filename : ":memory:", translated);
8011
+ }
8012
+ transaction(fn) {
8013
+ const self = this;
8014
+ const wrapped = function(...args) {
8015
+ const nested = self.isTransaction === true;
8016
+ self.exec(nested ? `SAVEPOINT ${SAVEPOINT}` : "BEGIN");
8017
+ try {
8018
+ const result = fn.apply(this, args);
8019
+ self.exec(nested ? `RELEASE ${SAVEPOINT}` : "COMMIT");
8020
+ return result;
8021
+ } catch (error) {
8022
+ if (nested) {
8023
+ self.exec(`ROLLBACK TO ${SAVEPOINT}`);
8024
+ self.exec(`RELEASE ${SAVEPOINT}`);
8025
+ } else {
8026
+ self.exec("ROLLBACK");
8027
+ }
8028
+ throw error;
8029
+ }
8030
+ };
8031
+ return wrapped;
8032
+ }
8033
+ }
8034
+ return NodeSqliteDatabase;
8035
+ }
8036
+ var Database = DatabaseImpl;
8037
+
8038
+ // ../plugin/src/shared/sqlite-helpers.ts
8039
+ function closeQuietly(db) {
8040
+ if (!db)
8041
+ return;
8042
+ try {
8043
+ db.close();
8044
+ } catch {}
8045
+ }
8098
8046
 
8099
8047
  // ../plugin/src/features/magic-context/key-files/project-key-files.ts
8100
- init_logger();
8101
8048
  import { createHash } from "node:crypto";
8102
8049
  import { existsSync, readFileSync, realpathSync } from "node:fs";
8103
8050
  import { join as join2, resolve, sep } from "node:path";
@@ -8214,7 +8161,6 @@ function isRelativeProjectFile(projectPath, relativePath) {
8214
8161
  }
8215
8162
 
8216
8163
  // ../plugin/src/features/magic-context/migrations.ts
8217
- init_logger();
8218
8164
  function tableExists(db, name) {
8219
8165
  return Boolean(db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name = ?").get(name));
8220
8166
  }
@@ -8948,6 +8894,28 @@ var MIGRATIONS = [
8948
8894
  db.exec("ALTER TABLE notes ADD COLUMN anchor_ordinal INTEGER");
8949
8895
  }
8950
8896
  }
8897
+ },
8898
+ {
8899
+ version: 30,
8900
+ description: "HARD-bust m[0] markers: cached system/tool-set/model identity",
8901
+ up: (db) => {
8902
+ const hasSessionMeta = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='session_meta' LIMIT 1").get();
8903
+ if (!hasSessionMeta)
8904
+ return;
8905
+ ensureColumn(db, "session_meta", "cached_m0_system_hash", "TEXT");
8906
+ ensureColumn(db, "session_meta", "cached_m0_tool_set_hash", "TEXT");
8907
+ ensureColumn(db, "session_meta", "cached_m0_model_key", "TEXT");
8908
+ const columns = new Set(db.prepare("PRAGMA table_info(session_meta)").all().map((column) => column.name));
8909
+ if (columns.has("cached_m0_bytes")) {
8910
+ db.prepare(`UPDATE session_meta SET
8911
+ cached_m0_bytes = NULL,
8912
+ cached_m1_bytes = NULL,
8913
+ cached_m0_materialized_at = NULL,
8914
+ cached_m0_system_hash = NULL,
8915
+ cached_m0_tool_set_hash = NULL,
8916
+ cached_m0_model_key = NULL`).run();
8917
+ }
8918
+ }
8951
8919
  }
8952
8920
  ];
8953
8921
  var LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
@@ -141663,8 +141631,6 @@ function loadToolDefinitionMeasurements(db) {
141663
141631
  }
141664
141632
 
141665
141633
  // ../plugin/src/features/magic-context/tool-owner-backfill.ts
141666
- init_data_path();
141667
- init_logger();
141668
141634
  import { existsSync as existsSync2 } from "node:fs";
141669
141635
  import { join as join3 } from "node:path";
141670
141636
  var LEASE_DURATION_MS = 5 * 60 * 1000;
@@ -141912,7 +141878,7 @@ var databases = new Map;
141912
141878
  var persistenceByDatabase = new WeakMap;
141913
141879
  var persistenceErrorByDatabase = new WeakMap;
141914
141880
  var lastSchemaFenceRejection = null;
141915
- var LATEST_SUPPORTED_VERSION = 29;
141881
+ var LATEST_SUPPORTED_VERSION = 30;
141916
141882
  function resolveDatabasePath(dbPathOverride) {
141917
141883
  if (dbPathOverride) {
141918
141884
  return { dbDir: dirname2(dbPathOverride), dbPath: dbPathOverride };
@@ -142377,6 +142343,9 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
142377
142343
  cached_m0_materialized_at INTEGER,
142378
142344
  cached_m0_session_facts_version INTEGER,
142379
142345
  cached_m0_upgrade_state TEXT,
142346
+ cached_m0_system_hash TEXT,
142347
+ cached_m0_tool_set_hash TEXT,
142348
+ cached_m0_model_key TEXT,
142380
142349
  cached_m0_last_baseline_end_message_id TEXT,
142381
142350
  upgrade_reminded_at INTEGER,
142382
142351
  pi_stable_id_scheme INTEGER
@@ -142507,6 +142476,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
142507
142476
  ensureColumn(db, "session_meta", "system_prompt_hash", "TEXT DEFAULT ''");
142508
142477
  ensureColumn(db, "session_meta", "cleared_reasoning_through_tag", "INTEGER DEFAULT 0");
142509
142478
  ensureColumn(db, "session_meta", "stripped_placeholder_ids", "TEXT DEFAULT ''");
142479
+ ensureColumn(db, "session_meta", "stale_reduce_stripped_ids", "TEXT DEFAULT ''");
142510
142480
  ensureColumn(db, "compartments", "start_message_id", "TEXT DEFAULT ''");
142511
142481
  ensureColumn(db, "compartments", "end_message_id", "TEXT DEFAULT ''");
142512
142482
  ensureColumn(db, "memory_embeddings", "model_id", "TEXT");
@@ -142568,6 +142538,9 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
142568
142538
  ensureColumn(db, "session_meta", "cached_m0_materialized_at", "INTEGER");
142569
142539
  ensureColumn(db, "session_meta", "cached_m0_session_facts_version", "INTEGER");
142570
142540
  ensureColumn(db, "session_meta", "cached_m0_upgrade_state", "TEXT");
142541
+ ensureColumn(db, "session_meta", "cached_m0_system_hash", "TEXT");
142542
+ ensureColumn(db, "session_meta", "cached_m0_tool_set_hash", "TEXT");
142543
+ ensureColumn(db, "session_meta", "cached_m0_model_key", "TEXT");
142571
142544
  ensureColumn(db, "session_meta", "cached_m0_last_baseline_end_message_id", "TEXT");
142572
142545
  ensureColumn(db, "session_meta", "upgrade_reminded_at", "INTEGER");
142573
142546
  db.exec(`
@@ -142654,6 +142627,7 @@ function healNullTextColumns(db) {
142654
142627
  ["todo_synthetic_state_json", ""],
142655
142628
  ["system_prompt_hash", ""],
142656
142629
  ["stripped_placeholder_ids", ""],
142630
+ ["stale_reduce_stripped_ids", ""],
142657
142631
  ["memory_block_cache", ""],
142658
142632
  ["memory_block_ids", ""],
142659
142633
  ["compaction_marker_state", ""],
@@ -142763,8 +142737,30 @@ function openDatabase(dbPathOrOptions) {
142763
142737
  }
142764
142738
  }
142765
142739
 
142766
- // src/subagent-entry.ts
142767
- init_logger();
142740
+ // ../plugin/src/config/prune-config-leaf.ts
142741
+ function isPlainObject(value) {
142742
+ return typeof value === "object" && value !== null && !Array.isArray(value);
142743
+ }
142744
+ function pruneNestedConfigLeaf(block, relativePath) {
142745
+ if (relativePath.length === 0)
142746
+ return null;
142747
+ const result = { ...block };
142748
+ let cursor = result;
142749
+ for (let i = 0;i < relativePath.length - 1; i++) {
142750
+ const seg = String(relativePath[i]);
142751
+ const child = cursor[seg];
142752
+ if (!isPlainObject(child))
142753
+ return null;
142754
+ const clonedChild = { ...child };
142755
+ cursor[seg] = clonedChild;
142756
+ cursor = clonedChild;
142757
+ }
142758
+ const leaf = String(relativePath[relativePath.length - 1]);
142759
+ if (!(leaf in cursor))
142760
+ return null;
142761
+ delete cursor[leaf];
142762
+ return { block: result, removed: relativePath.map(String).join(".") };
142763
+ }
142768
142764
 
142769
142765
  // src/config/index.ts
142770
142766
  import { existsSync as existsSync5, readFileSync as readFileSync3 } from "node:fs";
@@ -142907,6 +142903,70 @@ function migrateLegacyExperimental(rawConfig, warnings) {
142907
142903
  return patched;
142908
142904
  }
142909
142905
 
142906
+ // ../plugin/src/config/project-security.ts
142907
+ var HIDDEN_AGENT_KEYS = ["historian", "dreamer", "sidekick"];
142908
+ var AGENT_ESCALATION_FIELDS = ["prompt", "permission", "tools", "system_prompt"];
142909
+ function isPlainObject2(value) {
142910
+ return typeof value === "object" && value !== null && !Array.isArray(value);
142911
+ }
142912
+ function stripUnsafeProjectConfigFields(projectRaw) {
142913
+ const warnings = [];
142914
+ if ("auto_update" in projectRaw) {
142915
+ delete projectRaw.auto_update;
142916
+ warnings.push("Ignoring auto_update from project config (security: this setting only honors user-level config).");
142917
+ }
142918
+ for (const agentKey of HIDDEN_AGENT_KEYS) {
142919
+ const block = projectRaw[agentKey];
142920
+ if (!isPlainObject2(block))
142921
+ continue;
142922
+ const removed = [];
142923
+ for (const field of AGENT_ESCALATION_FIELDS) {
142924
+ if (field in block) {
142925
+ delete block[field];
142926
+ removed.push(field);
142927
+ }
142928
+ }
142929
+ if (removed.length > 0) {
142930
+ warnings.push(`Ignoring ${agentKey}.${removed.join("/")} from project config ` + "(security: a repository cannot reprogram or re-permission hidden agents).");
142931
+ }
142932
+ }
142933
+ return warnings;
142934
+ }
142935
+ function normalizeEndpoint(value) {
142936
+ if (typeof value !== "string")
142937
+ return;
142938
+ const trimmed = value.trim().replace(/\/+$/, "");
142939
+ return trimmed.length > 0 ? trimmed.toLowerCase() : undefined;
142940
+ }
142941
+ function dropInheritedEmbeddingKeyOnRedirect(projectRaw, mergedRaw, userRaw) {
142942
+ const projectEmbedding = projectRaw.embedding;
142943
+ if (!isPlainObject2(projectEmbedding))
142944
+ return [];
142945
+ const redirectsEndpoint = "endpoint" in projectEmbedding;
142946
+ if (!redirectsEndpoint)
142947
+ return [];
142948
+ const userEmbedding = userRaw?.embedding;
142949
+ if (isPlainObject2(userEmbedding)) {
142950
+ const projectEndpoint = normalizeEndpoint(projectEmbedding.endpoint);
142951
+ const userEndpoint = normalizeEndpoint(userEmbedding.endpoint);
142952
+ if (projectEndpoint !== undefined && projectEndpoint === userEndpoint) {
142953
+ return [];
142954
+ }
142955
+ }
142956
+ const providesOwnKey = typeof projectEmbedding.api_key === "string" && projectEmbedding.api_key.length > 0;
142957
+ if (providesOwnKey)
142958
+ return [];
142959
+ const mergedEmbedding = mergedRaw.embedding;
142960
+ if (!isPlainObject2(mergedEmbedding))
142961
+ return [];
142962
+ if (!("api_key" in mergedEmbedding))
142963
+ return [];
142964
+ delete mergedEmbedding.api_key;
142965
+ return [
142966
+ "Dropped inherited user embedding api_key because project config redirected " + "embedding.endpoint without supplying its own key (security: prevents key " + "exfiltration to a repository-chosen endpoint)."
142967
+ ];
142968
+ }
142969
+
142910
142970
  // ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
142911
142971
  var exports_external = {};
142912
142972
  __export(exports_external, {
@@ -143538,7 +143598,7 @@ __export(exports_util, {
143538
143598
  jsonStringifyReplacer: () => jsonStringifyReplacer,
143539
143599
  joinValues: () => joinValues,
143540
143600
  issue: () => issue,
143541
- isPlainObject: () => isPlainObject,
143601
+ isPlainObject: () => isPlainObject3,
143542
143602
  isObject: () => isObject,
143543
143603
  hexToUint8Array: () => hexToUint8Array,
143544
143604
  getSizableOrigin: () => getSizableOrigin,
@@ -143720,7 +143780,7 @@ var allowsEval = /* @__PURE__ */ cached(() => {
143720
143780
  return false;
143721
143781
  }
143722
143782
  });
143723
- function isPlainObject(o) {
143783
+ function isPlainObject3(o) {
143724
143784
  if (isObject(o) === false)
143725
143785
  return false;
143726
143786
  const ctor = o.constructor;
@@ -143737,7 +143797,7 @@ function isPlainObject(o) {
143737
143797
  return true;
143738
143798
  }
143739
143799
  function shallowClone(o) {
143740
- if (isPlainObject(o))
143800
+ if (isPlainObject3(o))
143741
143801
  return { ...o };
143742
143802
  if (Array.isArray(o))
143743
143803
  return [...o];
@@ -143941,7 +144001,7 @@ function omit(schema, mask) {
143941
144001
  return clone(schema, def);
143942
144002
  }
143943
144003
  function extend(schema, shape) {
143944
- if (!isPlainObject(shape)) {
144004
+ if (!isPlainObject3(shape)) {
143945
144005
  throw new Error("Invalid input to extend: expected a plain object");
143946
144006
  }
143947
144007
  const checks = schema._zod.def.checks;
@@ -143964,7 +144024,7 @@ function extend(schema, shape) {
143964
144024
  return clone(schema, def);
143965
144025
  }
143966
144026
  function safeExtend(schema, shape) {
143967
- if (!isPlainObject(shape)) {
144027
+ if (!isPlainObject3(shape)) {
143968
144028
  throw new Error("Invalid input to safeExtend: expected a plain object");
143969
144029
  }
143970
144030
  const def = mergeDefs(schema._zod.def, {
@@ -146307,7 +146367,7 @@ function mergeValues(a, b) {
146307
146367
  if (a instanceof Date && b instanceof Date && +a === +b) {
146308
146368
  return { valid: true, data: a };
146309
146369
  }
146310
- if (isPlainObject(a) && isPlainObject(b)) {
146370
+ if (isPlainObject3(a) && isPlainObject3(b)) {
146311
146371
  const bKeys = Object.keys(b);
146312
146372
  const sharedKeys = Object.keys(a).filter((key) => bKeys.indexOf(key) !== -1);
146313
146373
  const newObj = { ...a, ...b };
@@ -146493,7 +146553,7 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
146493
146553
  $ZodType.init(inst, def);
146494
146554
  inst._zod.parse = (payload, ctx) => {
146495
146555
  const input = payload.value;
146496
- if (!isPlainObject(input)) {
146556
+ if (!isPlainObject3(input)) {
146497
146557
  payload.issues.push({
146498
146558
  expected: "record",
146499
146559
  code: "invalid_type",
@@ -157347,6 +157407,7 @@ var MagicContextConfigSchema = exports_external.object({
157347
157407
  model: DEFAULT_LOCAL_EMBEDDING_MODEL
157348
157408
  }).describe("Embedding provider configuration"),
157349
157409
  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).'),
157410
+ 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."),
157350
157411
  caveman_text_compression: exports_external.object({
157351
157412
  enabled: exports_external.boolean().default(false).describe("Apply deterministic caveman-style text compression to old conversation text. Only active when ctx_reduce_enabled=false. Compresses user/assistant text in oldest-first tiers: ultra (oldest 20%), full, lite, untouched (newest 40%)."),
157352
157413
  min_chars: exports_external.number().min(100).max(1e4).default(500).describe("Text parts shorter than this (characters) stay untouched. Min 100, max 10000. Default: 500.")
@@ -157446,6 +157507,21 @@ function stripJsonComments(content) {
157446
157507
  // ../plugin/src/config/variable.ts
157447
157508
  var ENV_PATTERN = /\{env:([^}]+)\}/g;
157448
157509
  var FILE_PATTERN = /\{file:([^}]+)\}/g;
157510
+ function sensitiveFilePathReason(resolvedPath) {
157511
+ const home = homedir2();
157512
+ const sensitiveDirs = [
157513
+ { dir: resolve2(home, ".ssh"), label: "SSH keys" },
157514
+ { dir: resolve2(home, ".aws"), label: "AWS credentials" },
157515
+ { dir: resolve2(home, ".gnupg"), label: "GnuPG keyring" },
157516
+ { dir: resolve2(home, ".config", "gh"), label: "GitHub CLI auth" }
157517
+ ];
157518
+ for (const { dir, label } of sensitiveDirs) {
157519
+ if (resolvedPath === dir || resolvedPath.startsWith(`${dir}/`)) {
157520
+ return label;
157521
+ }
157522
+ }
157523
+ return null;
157524
+ }
157449
157525
  function substituteConfigVariables(input) {
157450
157526
  const warnings = [];
157451
157527
  let text = input.text;
@@ -157499,6 +157575,10 @@ function substituteConfigVariables(input) {
157499
157575
  } else if (!isAbsolute(filePath)) {
157500
157576
  filePath = resolve2(configDir, filePath);
157501
157577
  }
157578
+ const sensitiveReason = sensitiveFilePathReason(filePath);
157579
+ if (sensitiveReason) {
157580
+ warnings.push(`${token} resolves to a sensitive path (${sensitiveReason}: ${filePath}); ` + "inlining its contents into config — make sure this is intentional.");
157581
+ }
157502
157582
  if (!existsSync4(filePath)) {
157503
157583
  warnings.push(`File not found for ${token} (resolved to ${filePath}); using empty string`);
157504
157584
  continue;
@@ -157537,7 +157617,8 @@ function loadConfigFile(path3, scope) {
157537
157617
  const rawText = readFileSync3(path3, "utf-8");
157538
157618
  const substituted = substituteConfigVariables({
157539
157619
  text: rawText,
157540
- configPath: path3
157620
+ configPath: path3,
157621
+ isProjectConfig: scope === "project"
157541
157622
  });
157542
157623
  return {
157543
157624
  path: path3,
@@ -157579,14 +157660,14 @@ function redactConfigValue(value) {
157579
157660
  }
157580
157661
  return typeof value;
157581
157662
  }
157582
- function isPlainObject2(value) {
157663
+ function isPlainObject4(value) {
157583
157664
  return typeof value === "object" && value !== null && !Array.isArray(value);
157584
157665
  }
157585
157666
  function mergeRawConfigs(base, override) {
157586
157667
  const merged = { ...base };
157587
157668
  for (const [key, overrideValue] of Object.entries(override)) {
157588
157669
  const baseValue = merged[key];
157589
- merged[key] = isPlainObject2(baseValue) && isPlainObject2(overrideValue) ? mergeRawConfigs(baseValue, overrideValue) : overrideValue;
157670
+ merged[key] = isPlainObject4(baseValue) && isPlainObject4(overrideValue) ? mergeRawConfigs(baseValue, overrideValue) : overrideValue;
157590
157671
  }
157591
157672
  return merged;
157592
157673
  }
@@ -157600,10 +157681,15 @@ function parsePiConfig(rawConfig, recoveredTopLevelKeys = []) {
157600
157681
  }
157601
157682
  const defaults = MagicContextConfigSchema.parse({});
157602
157683
  const errorPaths = new Set;
157684
+ const issuePathsByKey = new Map;
157603
157685
  for (const issue2 of parsed.error.issues) {
157604
157686
  const topKey = issue2.path[0];
157605
157687
  if (topKey !== undefined) {
157606
- errorPaths.add(String(topKey));
157688
+ const key = String(topKey);
157689
+ errorPaths.add(key);
157690
+ const paths = issuePathsByKey.get(key) ?? [];
157691
+ paths.push([...issue2.path]);
157692
+ issuePathsByKey.set(key, paths);
157607
157693
  }
157608
157694
  }
157609
157695
  const patched = { ...migrated };
@@ -157611,11 +157697,32 @@ function parsePiConfig(rawConfig, recoveredTopLevelKeys = []) {
157611
157697
  for (const key of errorPaths) {
157612
157698
  recoveredTopLevelKeys.push(key);
157613
157699
  const isAgentConfig = key === "historian" || key === "dreamer" || key === "sidekick";
157614
- delete patched[key];
157615
157700
  if (isAgentConfig) {
157701
+ delete patched[key];
157616
157702
  warnings.push(`"${key}": invalid agent configuration, ignoring. Check your magic-context.jsonc.`);
157617
157703
  continue;
157618
157704
  }
157705
+ const issuePaths = issuePathsByKey.get(key) ?? [];
157706
+ const rawValue = migrated[key];
157707
+ const allNested = issuePaths.length > 0 && issuePaths.every((p) => p.length >= 2) && typeof rawValue === "object" && rawValue !== null && !Array.isArray(rawValue);
157708
+ if (allNested) {
157709
+ let prunedBlock = {
157710
+ ...rawValue
157711
+ };
157712
+ const prunedLeaves = [];
157713
+ for (const p of issuePaths) {
157714
+ const relative = p.slice(1);
157715
+ const result = pruneNestedConfigLeaf(prunedBlock, relative);
157716
+ if (result) {
157717
+ prunedBlock = result.block;
157718
+ prunedLeaves.push(result.removed);
157719
+ }
157720
+ }
157721
+ patched[key] = prunedBlock;
157722
+ warnings.push(`"${key}": invalid nested field(s) ${prunedLeaves.map((l) => `"${l}"`).join(", ")}, using defaults for those.`);
157723
+ continue;
157724
+ }
157725
+ delete patched[key];
157619
157726
  const defaultValue = defaults[key];
157620
157727
  warnings.push(`"${key}": invalid value (${redactConfigValue(rawConfig[key])}), using default ${JSON.stringify(defaultValue)}.`);
157621
157728
  }
@@ -157648,10 +157755,22 @@ function loadPiConfig(opts = {}) {
157648
157755
  return 0;
157649
157756
  return a.scope === "user" ? -1 : 1;
157650
157757
  });
157758
+ const userRaw = mergeFiles.find((f) => f.scope === "user")?.config;
157651
157759
  for (const loaded of mergeFiles) {
157652
157760
  const prefix = loaded.scope === "user" ? "[user config]" : "[project config]";
157653
157761
  warnings.push(...loaded.warnings.map((warning) => `${prefix} ${warning}`));
157654
- rawConfig = mergeRawConfigs(rawConfig, loaded.config);
157762
+ if (loaded.scope === "project") {
157763
+ const projectRaw = { ...loaded.config };
157764
+ for (const warning of stripUnsafeProjectConfigFields(projectRaw)) {
157765
+ warnings.push(`${prefix} ${warning}`);
157766
+ }
157767
+ rawConfig = mergeRawConfigs(rawConfig, projectRaw);
157768
+ for (const warning of dropInheritedEmbeddingKeyOnRedirect(projectRaw, rawConfig, userRaw)) {
157769
+ warnings.push(`${prefix} ${warning}`);
157770
+ }
157771
+ } else {
157772
+ rawConfig = mergeRawConfigs(rawConfig, loaded.config);
157773
+ }
157655
157774
  }
157656
157775
  const parsed = parsePiConfig(rawConfig);
157657
157776
  warnings.push(...parsed.warnings.map((warning) => `[merged config] ${warning}`));
@@ -157726,10 +157845,22 @@ function loadPiConfigDetailed(opts = {}) {
157726
157845
  return 0;
157727
157846
  return a.scope === "user" ? -1 : 1;
157728
157847
  });
157848
+ const userRaw = mergeFiles.find((f) => f.scope === "user")?.config;
157729
157849
  for (const loaded of mergeFiles) {
157730
157850
  const prefix = loaded.scope === "user" ? "[user config]" : "[project config]";
157731
157851
  warnings.push(...loaded.warnings.map((warning) => `${prefix} ${warning}`));
157732
- rawConfig = mergeRawConfigs(rawConfig, loaded.config);
157852
+ if (loaded.scope === "project") {
157853
+ const projectRaw = { ...loaded.config };
157854
+ for (const warning of stripUnsafeProjectConfigFields(projectRaw)) {
157855
+ warnings.push(`${prefix} ${warning}`);
157856
+ }
157857
+ rawConfig = mergeRawConfigs(rawConfig, projectRaw);
157858
+ for (const warning of dropInheritedEmbeddingKeyOnRedirect(projectRaw, rawConfig, userRaw)) {
157859
+ warnings.push(`${prefix} ${warning}`);
157860
+ }
157861
+ } else {
157862
+ rawConfig = mergeRawConfigs(rawConfig, loaded.config);
157863
+ }
157733
157864
  }
157734
157865
  const recoveredTopLevelKeys = [];
157735
157866
  const parsed = parsePiConfig(rawConfig, recoveredTopLevelKeys);
@@ -157756,9 +157887,6 @@ function loadPiConfigDetailed(opts = {}) {
157756
157887
  };
157757
157888
  }
157758
157889
 
157759
- // ../plugin/src/features/magic-context/memory/embedding.ts
157760
- init_logger();
157761
-
157762
157890
  // ../plugin/src/features/magic-context/memory/cosine-similarity.ts
157763
157891
  function cosineSimilarity(a, b) {
157764
157892
  if (a.length !== b.length) {
@@ -157787,7 +157915,7 @@ function computeNormalizedHash(content) {
157787
157915
  }
157788
157916
 
157789
157917
  // ../plugin/src/features/magic-context/memory/embedding-identity.ts
157790
- function normalizeEndpoint(endpoint) {
157918
+ function normalizeEndpoint2(endpoint) {
157791
157919
  return endpoint?.trim().replace(/\/+$/, "") ?? "";
157792
157920
  }
157793
157921
  function getEmbeddingProviderIdentity(config2) {
@@ -157797,7 +157925,7 @@ function getEmbeddingProviderIdentity(config2) {
157797
157925
  const identityInput = config2.provider === "openai-compatible" ? {
157798
157926
  provider: "openai-compatible",
157799
157927
  model: config2.model.trim(),
157800
- endpoint: normalizeEndpoint(config2.endpoint),
157928
+ endpoint: normalizeEndpoint2(config2.endpoint),
157801
157929
  apiKeyPresent: Boolean(config2.api_key?.trim()),
157802
157930
  inputType: config2.input_type?.trim() || ""
157803
157931
  } : {
@@ -157814,8 +157942,6 @@ import { mkdirSync as mkdirSync3 } from "node:fs";
157814
157942
  import { open, stat, unlink, writeFile } from "node:fs/promises";
157815
157943
  import { dirname as dirname4, join as join6 } from "node:path";
157816
157944
  import { pathToFileURL } from "node:url";
157817
- init_data_path();
157818
- init_logger();
157819
157945
  var LOCK_POLL_MS = 150;
157820
157946
  var STALE_LOCK_MS = 3 * 60000;
157821
157947
  var MAX_LOCK_WAIT_MS = 5 * 60000;
@@ -158150,9 +158276,61 @@ class LocalEmbeddingProvider {
158150
158276
  }
158151
158277
  }
158152
158278
 
158279
+ // ../plugin/src/features/magic-context/memory/embedding-ssrf.ts
158280
+ var METADATA_HOSTNAMES = new Set(["metadata.google.internal", "metadata.goog"]);
158281
+ var IPV6_METADATA_HOSTS = new Set(["fd00:ec2::254"]);
158282
+ function isLinkLocalIpv4(host) {
158283
+ return /^169\.254\.\d{1,3}\.\d{1,3}$/.test(host);
158284
+ }
158285
+ function ipv4FromMappedIpv6(host) {
158286
+ const m = /^::ffff:(.+)$/.exec(host);
158287
+ if (!m)
158288
+ return null;
158289
+ const tail = m[1];
158290
+ if (/^\d{1,3}(\.\d{1,3}){3}$/.test(tail))
158291
+ return tail;
158292
+ const hex3 = /^([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(tail);
158293
+ if (hex3) {
158294
+ const hi = Number.parseInt(hex3[1], 16);
158295
+ const lo = Number.parseInt(hex3[2], 16);
158296
+ if (Number.isNaN(hi) || Number.isNaN(lo))
158297
+ return null;
158298
+ return `${hi >> 8 & 255}.${hi & 255}.${lo >> 8 & 255}.${lo & 255}`;
158299
+ }
158300
+ return null;
158301
+ }
158302
+ function blockedEmbeddingEndpointReason(endpoint) {
158303
+ const trimmed = endpoint.trim();
158304
+ if (trimmed.length === 0)
158305
+ return null;
158306
+ let url2;
158307
+ try {
158308
+ url2 = new URL(trimmed);
158309
+ } catch {
158310
+ return `embedding endpoint is not a valid URL: ${trimmed}`;
158311
+ }
158312
+ const host = url2.hostname.toLowerCase().replace(/^\[/, "").replace(/\]$/, "");
158313
+ if (METADATA_HOSTNAMES.has(host)) {
158314
+ return `embedding endpoint host ${host} is a cloud metadata service (blocked)`;
158315
+ }
158316
+ if (IPV6_METADATA_HOSTS.has(host)) {
158317
+ return `embedding endpoint host ${host} is the AWS IPv6 metadata service (blocked)`;
158318
+ }
158319
+ if (isLinkLocalIpv4(host)) {
158320
+ return `embedding endpoint host ${host} is link-local / cloud metadata (blocked)`;
158321
+ }
158322
+ const mappedV4 = ipv4FromMappedIpv6(host);
158323
+ if (mappedV4 && isLinkLocalIpv4(mappedV4)) {
158324
+ return `embedding endpoint host ${host} (IPv4-mapped ${mappedV4}) is link-local / cloud metadata (blocked)`;
158325
+ }
158326
+ if (host.startsWith("fe80:")) {
158327
+ return `embedding endpoint host ${host} is link-local / cloud metadata (blocked)`;
158328
+ }
158329
+ return null;
158330
+ }
158331
+
158153
158332
  // ../plugin/src/features/magic-context/memory/embedding-openai.ts
158154
- init_logger();
158155
- function normalizeEndpoint2(endpoint) {
158333
+ function normalizeEndpoint3(endpoint) {
158156
158334
  return endpoint?.trim().replace(/\/+$/, "") ?? "";
158157
158335
  }
158158
158336
  var FAILURE_THRESHOLD = 3;
@@ -158173,7 +158351,7 @@ class OpenAICompatibleEmbeddingProvider {
158173
158351
  openLogged = false;
158174
158352
  halfOpenProbeInFlight = false;
158175
158353
  constructor(options) {
158176
- this.endpoint = normalizeEndpoint2(options.endpoint);
158354
+ this.endpoint = normalizeEndpoint3(options.endpoint);
158177
158355
  this.model = options.model?.trim() ?? "";
158178
158356
  this.apiKey = options.apiKey?.trim() ?? "";
158179
158357
  this.inputType = options.inputType?.trim() ?? "";
@@ -158193,6 +158371,12 @@ class OpenAICompatibleEmbeddingProvider {
158193
158371
  this.initialized = false;
158194
158372
  return false;
158195
158373
  }
158374
+ const blockedReason = blockedEmbeddingEndpointReason(this.endpoint);
158375
+ if (blockedReason) {
158376
+ log(`[magic-context] embedding endpoint blocked: ${blockedReason}`);
158377
+ this.initialized = false;
158378
+ return false;
158379
+ }
158196
158380
  this.initialized = true;
158197
158381
  return true;
158198
158382
  }
@@ -158238,6 +158422,7 @@ class OpenAICompatibleEmbeddingProvider {
158238
158422
  ...this.inputType ? { input_type: this.inputType } : {},
158239
158423
  ...this.truncate ? { truncate: this.truncate } : {}
158240
158424
  }),
158425
+ redirect: "error",
158241
158426
  signal: internalController.signal
158242
158427
  });
158243
158428
  if (!response.ok) {
@@ -158442,7 +158627,6 @@ function getDistinctStoredModelIds(db, projectPath) {
158442
158627
 
158443
158628
  // ../plugin/src/features/magic-context/project-embedding-registry.ts
158444
158629
  import { createHash as createHash3, randomUUID } from "node:crypto";
158445
- init_logger();
158446
158630
 
158447
158631
  // ../plugin/src/features/magic-context/git-commits/storage-git-commit-embeddings.ts
158448
158632
  var saveStatements = new WeakMap;
@@ -158718,11 +158902,15 @@ function resolveEmbeddingConfig(config2) {
158718
158902
  }
158719
158903
  if (config2.provider === "openai-compatible") {
158720
158904
  const apiKey = config2.api_key?.trim();
158905
+ const inputType = config2.input_type?.trim();
158906
+ const truncate = config2.truncate?.trim();
158721
158907
  return {
158722
158908
  provider: "openai-compatible",
158723
158909
  model: config2.model.trim(),
158724
158910
  endpoint: config2.endpoint.trim(),
158725
- ...apiKey ? { api_key: apiKey } : {}
158911
+ ...apiKey ? { api_key: apiKey } : {},
158912
+ ...inputType ? { input_type: inputType } : {},
158913
+ ...truncate ? { truncate } : {}
158726
158914
  };
158727
158915
  }
158728
158916
  return { provider: "off" };
@@ -158738,7 +158926,9 @@ function createProvider(config2) {
158738
158926
  return new OpenAICompatibleEmbeddingProvider({
158739
158927
  endpoint: config2.endpoint,
158740
158928
  model: config2.model,
158741
- apiKey: config2.api_key
158929
+ apiKey: config2.api_key,
158930
+ inputType: config2.input_type,
158931
+ truncate: config2.truncate
158742
158932
  });
158743
158933
  }
158744
158934
  return new LocalEmbeddingProvider(config2.model);
@@ -159177,18 +159367,40 @@ function hasGitDir(canonical) {
159177
159367
  return false;
159178
159368
  }
159179
159369
  }
159370
+ function normalizeStoredProjectPath(rawOrStored) {
159371
+ if (rawOrStored.startsWith("git:") || rawOrStored.startsWith("dir:")) {
159372
+ return rawOrStored;
159373
+ }
159374
+ try {
159375
+ return resolveProjectIdentity(rawOrStored);
159376
+ } catch {
159377
+ return directoryFallback(rawOrStored);
159378
+ }
159379
+ }
159380
+ function storedPathBelongsToIdentity(storedProjectPath, projectIdentity) {
159381
+ return storedProjectPath === projectIdentity || normalizeStoredProjectPath(storedProjectPath) === projectIdentity;
159382
+ }
159180
159383
 
159181
159384
  // ../plugin/src/plugin/embedding-bootstrap-helpers.ts
159182
159385
  import { createHash as createHash5 } from "node:crypto";
159183
- init_logger();
159184
159386
  var EMBEDDING_AFFECTING_KEYS = new Set([
159185
159387
  "embedding.api_key",
159186
159388
  "embedding.endpoint",
159187
159389
  "embedding.model",
159188
- "embedding.provider"
159390
+ "embedding.provider",
159391
+ "embedding.input_type",
159392
+ "embedding.truncate"
159189
159393
  ]);
159190
159394
  var EMBEDDING_AFFECTING_TOP_LEVEL_KEYS = new Set(["embedding", "memory", "experimental"]);
159191
- var EMBEDDING_WARNING_TERMS = ["api_key", "endpoint", "model", "provider", "embedding"];
159395
+ var EMBEDDING_WARNING_TERMS = [
159396
+ "api_key",
159397
+ "endpoint",
159398
+ "model",
159399
+ "provider",
159400
+ "embedding",
159401
+ "input_type",
159402
+ "truncate"
159403
+ ];
159192
159404
  var loggedFailureSignatures = new Map;
159193
159405
  function sha256Prefix2(value, length = 16) {
159194
159406
  return createHash5("sha256").update(value).digest("hex").slice(0, length);
@@ -159268,6 +159480,7 @@ async function ensureProjectRegisteredFromPiDirectory(directory, db) {
159268
159480
  };
159269
159481
  registerProjectEmbeddingAndMaybeWipe(db, projectIdentity, detailed.config.embedding, features, directory);
159270
159482
  }
159483
+
159271
159484
  // ../plugin/src/features/magic-context/compartment-lease.ts
159272
159485
  var COMPARTMENT_LEASE_TTL_MS = 5 * 60 * 1000;
159273
159486
  var COMPARTMENT_LEASE_RENEWAL_MS = 60 * 1000;
@@ -159361,6 +159574,9 @@ var SESSION_META_SELECT_COLUMNS = [
159361
159574
  "cached_m0_materialized_at",
159362
159575
  "cached_m0_session_facts_version",
159363
159576
  "cached_m0_upgrade_state",
159577
+ "cached_m0_system_hash",
159578
+ "cached_m0_tool_set_hash",
159579
+ "cached_m0_model_key",
159364
159580
  "last_observed_model_key",
159365
159581
  "upgrade_reminded_at",
159366
159582
  "pi_stable_id_scheme"
@@ -159397,6 +159613,9 @@ var META_COLUMNS = {
159397
159613
  cachedM0MaterializedAt: "cached_m0_materialized_at",
159398
159614
  cachedM0SessionFactsVersion: "cached_m0_session_facts_version",
159399
159615
  cachedM0UpgradeState: "cached_m0_upgrade_state",
159616
+ cachedM0SystemHash: "cached_m0_system_hash",
159617
+ cachedM0ToolSetHash: "cached_m0_tool_set_hash",
159618
+ cachedM0ModelKey: "cached_m0_model_key",
159400
159619
  lastObservedModelKey: "last_observed_model_key",
159401
159620
  upgradeRemindedAt: "upgrade_reminded_at",
159402
159621
  piStableIdScheme: "pi_stable_id_scheme"
@@ -159439,7 +159658,7 @@ function isSessionMetaRow(row) {
159439
159658
  if (row === null || typeof row !== "object")
159440
159659
  return false;
159441
159660
  const r = row;
159442
- return typeof r.session_id === "string" && typeof r.last_response_time === "number" && isStringOrNull(r.cache_ttl) && typeof r.counter === "number" && typeof r.last_nudge_tokens === "number" && isStringOrNull(r.last_nudge_band) && isStringOrNull(r.last_transform_error) && typeof r.is_subagent === "number" && typeof r.last_context_percentage === "number" && typeof r.last_input_tokens === "number" && isNumberOrNull(r.observed_safe_input_tokens) && isNumberOrNull(r.cache_alert_sent) && isNumberOrNull(r.times_execute_threshold_reached) && isNumberOrNull(r.compartment_in_progress) && (r.system_prompt_hash === null || typeof r.system_prompt_hash === "string" || typeof r.system_prompt_hash === "number") && isNumberOrNull(r.system_prompt_tokens) && isNumberOrNull(r.conversation_tokens) && isNumberOrNull(r.tool_call_tokens) && isNumberOrNull(r.cleared_reasoning_through_tag) && isStringOrNull(r.last_todo_state) && isBlobOrNull(r.cached_m0_bytes) && isBlobOrNull(r.cached_m1_bytes) && isNumberOrNull(r.cached_m0_project_memory_epoch) && isNumberOrNull(r.cached_m0_project_user_profile_version) && isNumberOrNull(r.cached_m0_max_compartment_seq) && isNumberOrNull(r.cached_m0_max_memory_id) && isNumberOrNull(r.cached_m0_max_mutation_id) && isNumberOrNull(r.cached_m0_max_memory_mutation_id) && isStringOrNull(r.cached_m0_project_docs_hash) && isNumberOrNull(r.cached_m0_materialized_at) && isNumberOrNull(r.cached_m0_session_facts_version) && isStringOrNull(r.cached_m0_upgrade_state) && isStringOrNull(r.last_observed_model_key) && isNumberOrNull(r.upgrade_reminded_at) && isNumberOrNull(r.pi_stable_id_scheme);
159661
+ return typeof r.session_id === "string" && typeof r.last_response_time === "number" && isStringOrNull(r.cache_ttl) && typeof r.counter === "number" && typeof r.last_nudge_tokens === "number" && isStringOrNull(r.last_nudge_band) && isStringOrNull(r.last_transform_error) && typeof r.is_subagent === "number" && typeof r.last_context_percentage === "number" && typeof r.last_input_tokens === "number" && isNumberOrNull(r.observed_safe_input_tokens) && isNumberOrNull(r.cache_alert_sent) && isNumberOrNull(r.times_execute_threshold_reached) && isNumberOrNull(r.compartment_in_progress) && (r.system_prompt_hash === null || typeof r.system_prompt_hash === "string" || typeof r.system_prompt_hash === "number") && isNumberOrNull(r.system_prompt_tokens) && isNumberOrNull(r.conversation_tokens) && isNumberOrNull(r.tool_call_tokens) && isNumberOrNull(r.cleared_reasoning_through_tag) && isStringOrNull(r.last_todo_state) && isBlobOrNull(r.cached_m0_bytes) && isBlobOrNull(r.cached_m1_bytes) && isNumberOrNull(r.cached_m0_project_memory_epoch) && isNumberOrNull(r.cached_m0_project_user_profile_version) && isNumberOrNull(r.cached_m0_max_compartment_seq) && isNumberOrNull(r.cached_m0_max_memory_id) && isNumberOrNull(r.cached_m0_max_mutation_id) && isNumberOrNull(r.cached_m0_max_memory_mutation_id) && isStringOrNull(r.cached_m0_project_docs_hash) && isNumberOrNull(r.cached_m0_materialized_at) && isNumberOrNull(r.cached_m0_session_facts_version) && isStringOrNull(r.cached_m0_upgrade_state) && isStringOrNull(r.cached_m0_system_hash) && isStringOrNull(r.cached_m0_tool_set_hash) && isStringOrNull(r.cached_m0_model_key) && isStringOrNull(r.last_observed_model_key) && isNumberOrNull(r.upgrade_reminded_at) && isNumberOrNull(r.pi_stable_id_scheme);
159443
159662
  }
159444
159663
  function getDefaultSessionMeta(sessionId) {
159445
159664
  return {
@@ -159475,6 +159694,9 @@ function getDefaultSessionMeta(sessionId) {
159475
159694
  cachedM0MaterializedAt: null,
159476
159695
  cachedM0SessionFactsVersion: null,
159477
159696
  cachedM0UpgradeState: null,
159697
+ cachedM0SystemHash: null,
159698
+ cachedM0ToolSetHash: null,
159699
+ cachedM0ModelKey: null,
159478
159700
  lastObservedModelKey: null,
159479
159701
  upgradeRemindedAt: null,
159480
159702
  piStableIdScheme: null
@@ -159526,6 +159748,9 @@ function toSessionMeta(row) {
159526
159748
  cachedM0MaterializedAt: numOrNull(row.cached_m0_materialized_at),
159527
159749
  cachedM0SessionFactsVersion: numOrNull(row.cached_m0_session_facts_version),
159528
159750
  cachedM0UpgradeState: stringOrNull(row.cached_m0_upgrade_state),
159751
+ cachedM0SystemHash: stringOrNull(row.cached_m0_system_hash),
159752
+ cachedM0ToolSetHash: stringOrNull(row.cached_m0_tool_set_hash),
159753
+ cachedM0ModelKey: stringOrNull(row.cached_m0_model_key),
159529
159754
  lastObservedModelKey: stringOrNull(row.last_observed_model_key),
159530
159755
  upgradeRemindedAt: numOrNull(row.upgrade_reminded_at),
159531
159756
  piStableIdScheme: numOrNull(row.pi_stable_id_scheme)
@@ -159545,8 +159770,11 @@ function persistCachedM0(db, sessionId, payload) {
159545
159770
  cached_m0_project_docs_hash = ?,
159546
159771
  cached_m0_materialized_at = ?,
159547
159772
  cached_m0_session_facts_version = ?,
159548
- cached_m0_upgrade_state = ?
159549
- WHERE session_id = ?`).run(Buffer2.from(payload.m0Bytes), payload.projectMemoryEpoch, 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, sessionId);
159773
+ cached_m0_upgrade_state = ?,
159774
+ cached_m0_system_hash = ?,
159775
+ cached_m0_tool_set_hash = ?,
159776
+ cached_m0_model_key = ?
159777
+ WHERE session_id = ?`).run(Buffer2.from(payload.m0Bytes), payload.projectMemoryEpoch, 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.toolSetHash ?? "", payload.modelKey ?? "", sessionId);
159550
159778
  }
159551
159779
  function clearCachedM0M1(db, sessionId) {
159552
159780
  ensureSessionMetaRow(db, sessionId);
@@ -159564,6 +159792,9 @@ function clearCachedM0M1(db, sessionId) {
159564
159792
  ["cached_m0_materialized_at", null],
159565
159793
  ["cached_m0_session_facts_version", null],
159566
159794
  ["cached_m0_upgrade_state", null],
159795
+ ["cached_m0_system_hash", null],
159796
+ ["cached_m0_tool_set_hash", null],
159797
+ ["cached_m0_model_key", null],
159567
159798
  ["cached_m0_last_baseline_end_message_id", null],
159568
159799
  ["memory_block_cache", ""],
159569
159800
  ["memory_block_count", 0],
@@ -159605,12 +159836,6 @@ function isCompartmentRow(row) {
159605
159836
  const candidate = row;
159606
159837
  return typeof candidate.id === "number" && typeof candidate.session_id === "string" && typeof candidate.sequence === "number" && typeof candidate.start_message === "number" && typeof candidate.end_message === "number" && typeof candidate.start_message_id === "string" && typeof candidate.end_message_id === "string" && typeof candidate.title === "string" && typeof candidate.content === "string" && isStringOrNullish(candidate.p1) && isStringOrNullish(candidate.p2) && isStringOrNullish(candidate.p3) && isStringOrNullish(candidate.p4) && isNumberOrNullish(candidate.importance) && isStringOrNullish(candidate.episode_type) && isNumberOrNullish(candidate.legacy) && typeof candidate.created_at === "number";
159607
159838
  }
159608
- function isSessionFactRow(row) {
159609
- if (row === null || typeof row !== "object")
159610
- return false;
159611
- const candidate = row;
159612
- return typeof candidate.id === "number" && typeof candidate.session_id === "string" && typeof candidate.category === "string" && typeof candidate.content === "string" && typeof candidate.created_at === "number" && typeof candidate.updated_at === "number";
159613
- }
159614
159839
  function insertCompartmentRows(db, sessionId, compartments, now) {
159615
159840
  const stmt = getInsertCompartmentStatement(db);
159616
159841
  for (const compartment of compartments) {
@@ -159639,16 +159864,6 @@ function toCompartment(row) {
159639
159864
  createdAt: row.created_at
159640
159865
  };
159641
159866
  }
159642
- function toSessionFact(row) {
159643
- return {
159644
- id: row.id,
159645
- sessionId: row.session_id,
159646
- category: row.category,
159647
- content: row.content,
159648
- createdAt: row.created_at,
159649
- updatedAt: row.updated_at
159650
- };
159651
- }
159652
159867
  function getCompartments(db, sessionId) {
159653
159868
  const rows = db.prepare("SELECT * FROM compartments WHERE session_id = ? ORDER BY sequence ASC").all(sessionId).filter(isCompartmentRow);
159654
159869
  return rows.map(toCompartment);
@@ -159669,10 +159884,6 @@ function appendCompartments(db, sessionId, compartments) {
159669
159884
  insertCompartmentRows(db, sessionId, compartments, now);
159670
159885
  })();
159671
159886
  }
159672
- function getSessionFacts(db, sessionId) {
159673
- const rows = db.prepare("SELECT * FROM session_facts WHERE session_id = ? ORDER BY category ASC, id ASC").all(sessionId).filter(isSessionFactRow);
159674
- return rows.map(toSessionFact);
159675
- }
159676
159887
  function saveRecompStagingPass(db, sessionId, passNumber, compartments, facts) {
159677
159888
  const now = Date.now();
159678
159889
  db.transaction(() => {
@@ -159716,14 +159927,6 @@ function getRecompStaging(db, sessionId) {
159716
159927
  lastEndMessage: lastEnd
159717
159928
  };
159718
159929
  }
159719
- function invalidateAllMemoryBlockCaches(db) {
159720
- try {
159721
- const rows = db.prepare("SELECT session_id FROM session_meta").all();
159722
- for (const row of rows) {
159723
- clearCachedM0M1(db, row.session_id);
159724
- }
159725
- } catch {}
159726
- }
159727
159930
  function clearRecompStaging(db, sessionId) {
159728
159931
  db.transaction(() => {
159729
159932
  db.prepare("DELETE FROM recomp_compartments WHERE session_id = ?").run(sessionId);
@@ -159770,8 +159973,47 @@ function escapeXmlContent(s) {
159770
159973
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
159771
159974
  }
159772
159975
 
159773
- // ../plugin/src/hooks/magic-context/read-session-chunk.ts
159774
- await init_read_session_db();
159976
+ // ../plugin/src/hooks/magic-context/read-session-db.ts
159977
+ import { existsSync as existsSync6 } from "node:fs";
159978
+ import { join as join7 } from "node:path";
159979
+ function getOpenCodeDbPath() {
159980
+ return join7(getDataDir(), "opencode", "opencode.db");
159981
+ }
159982
+ function openCodeDbExists() {
159983
+ return existsSync6(getOpenCodeDbPath());
159984
+ }
159985
+ var cachedReadOnlyDb = null;
159986
+ function closeCachedReadOnlyDb() {
159987
+ if (!cachedReadOnlyDb) {
159988
+ return;
159989
+ }
159990
+ try {
159991
+ closeQuietly(cachedReadOnlyDb.db);
159992
+ } catch (error51) {
159993
+ log("[magic-context] failed to close cached OpenCode read-only DB:", error51);
159994
+ } finally {
159995
+ cachedReadOnlyDb = null;
159996
+ }
159997
+ }
159998
+ function getReadOnlySessionDb() {
159999
+ const dbPath = getOpenCodeDbPath();
160000
+ if (cachedReadOnlyDb?.path === dbPath) {
160001
+ return cachedReadOnlyDb.db;
160002
+ }
160003
+ closeCachedReadOnlyDb();
160004
+ const db = new Database(dbPath, { readonly: true });
160005
+ cachedReadOnlyDb = { path: dbPath, db };
160006
+ return db;
160007
+ }
160008
+ function withReadOnlySessionDb(fn) {
160009
+ return fn(getReadOnlySessionDb());
160010
+ }
160011
+ function getRawSessionMessageCountFromDb(db, sessionId) {
160012
+ const row = db.prepare(`SELECT COUNT(*) as count FROM message WHERE session_id = ?
160013
+ AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
160014
+ AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')`).get(sessionId);
160015
+ return typeof row?.count === "number" ? row.count : 0;
160016
+ }
159775
160017
 
159776
160018
  // ../plugin/src/hooks/magic-context/read-session-raw.ts
159777
160019
  function isRawMessageRow(row) {
@@ -164666,7 +164908,6 @@ var CATEGORY_DEFAULT_TTL = {
164666
164908
  KNOWN_ISSUES: 30 * 24 * 60 * 60 * 1000
164667
164909
  };
164668
164910
  // ../plugin/src/features/magic-context/memory/embedding-backfill.ts
164669
- init_logger();
164670
164911
  async function ensureMemoryEmbeddings(args) {
164671
164912
  const snapshot = getProjectEmbeddingSnapshot(args.projectIdentity);
164672
164913
  if (!snapshot?.enabled) {
@@ -164704,9 +164945,6 @@ async function ensureMemoryEmbeddings(args) {
164704
164945
  }
164705
164946
  return args.existingEmbeddings;
164706
164947
  }
164707
- // ../plugin/src/features/magic-context/memory/promotion.ts
164708
- init_logger();
164709
-
164710
164948
  // ../plugin/src/features/magic-context/memory/storage-memory.ts
164711
164949
  var COLUMN_MAP = {
164712
164950
  id: "id",
@@ -165378,7 +165616,7 @@ function indexMessagesAfterOrdinal(db, sessionId, messages, lastIndexedOrdinal,
165378
165616
  }
165379
165617
  // ../plugin/src/features/magic-context/project-docs-hash.ts
165380
165618
  import { createHash as createHash6 } from "node:crypto";
165381
- import { readFileSync as readFileSync4, statSync as statSync2 } from "node:fs";
165619
+ import { lstatSync, readFileSync as readFileSync4, statSync as statSync2 } from "node:fs";
165382
165620
  import path4 from "node:path";
165383
165621
  var PROJECT_DOC_FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
165384
165622
  var PROJECT_DOCS_DELIMITER = `
@@ -165386,6 +165624,7 @@ var PROJECT_DOCS_DELIMITER = `
165386
165624
  ---
165387
165625
 
165388
165626
  `;
165627
+ var MAX_PROJECT_DOC_BYTES = 256 * 1024;
165389
165628
  var docsCache = new Map;
165390
165629
  function canonicalizeDocContent(raw) {
165391
165630
  return raw.replace(/^\uFEFF/, "").replace(/\r\n/g, `
@@ -165395,9 +165634,10 @@ function canonicalizeDocContent(raw) {
165395
165634
  }
165396
165635
  function fingerprintFile(filePath) {
165397
165636
  try {
165398
- const stat2 = statSync2(filePath);
165637
+ const stat2 = lstatSync(filePath);
165638
+ const isReadableDoc = stat2.isFile() && stat2.size <= MAX_PROJECT_DOC_BYTES;
165399
165639
  return {
165400
- exists: stat2.isFile(),
165640
+ exists: isReadableDoc,
165401
165641
  mtimeMs: stat2.mtimeMs,
165402
165642
  size: stat2.size
165403
165643
  };
@@ -165440,6 +165680,16 @@ function readCanonicalPieces(projectDirectory, files) {
165440
165680
  if (!fingerprint?.exists) {
165441
165681
  continue;
165442
165682
  }
165683
+ let safeToRead = false;
165684
+ try {
165685
+ const st = lstatSync(filePath);
165686
+ safeToRead = st.isFile() && st.size <= MAX_PROJECT_DOC_BYTES;
165687
+ } catch {
165688
+ safeToRead = false;
165689
+ }
165690
+ if (!safeToRead) {
165691
+ continue;
165692
+ }
165443
165693
  const canonicalContent = canonicalizeDocContent(readFileSync4(filePath, "utf8"));
165444
165694
  hashPieces.push(`file:${filename}
165445
165695
  ${canonicalContent}`);
@@ -165606,7 +165856,6 @@ function getMaxMemoryMutationId(db, projectPath) {
165606
165856
  return row?.max_id ?? null;
165607
165857
  }
165608
165858
  // ../plugin/src/features/magic-context/storage-meta-persisted.ts
165609
- init_logger();
165610
165859
  var CAS_RETRY_LIMIT = 5;
165611
165860
  var AUTO_SEARCH_NO_HINT_REASONS = new Set([
165612
165861
  "below-threshold",
@@ -165761,7 +166010,8 @@ function casUpdateJsonArrayColumn(db, sessionId, column, validator, mutate, opti
165761
166010
  }
165762
166011
  for (let attempt = 0;attempt < CAS_RETRY_LIMIT; attempt += 1) {
165763
166012
  const row = db.prepare(`SELECT ${column} FROM session_meta WHERE session_id = ?`).get(sessionId);
165764
- const currentBlob = row?.[column] ?? "[]";
166013
+ const rawCurrent = row?.[column] ?? null;
166014
+ const currentBlob = rawCurrent ?? "[]";
165765
166015
  const current = parseJsonArray(currentBlob, validator);
165766
166016
  const next = mutate(current);
165767
166017
  if (next === null)
@@ -165769,7 +166019,7 @@ function casUpdateJsonArrayColumn(db, sessionId, column, validator, mutate, opti
165769
166019
  const nextBlob = stableStringify(next);
165770
166020
  if (nextBlob === currentBlob)
165771
166021
  return true;
165772
- const result = db.prepare(`UPDATE session_meta SET ${column} = ? WHERE session_id = ? AND ${column} = ?`).run(nextBlob, sessionId, currentBlob);
166022
+ const result = db.prepare(`UPDATE session_meta SET ${column} = ? WHERE session_id = ? AND ${column} IS ?`).run(nextBlob, sessionId, rawCurrent);
165773
166023
  if (result.changes > 0)
165774
166024
  return true;
165775
166025
  }
@@ -165898,14 +166148,16 @@ function getHistorianFailureState(db, sessionId) {
165898
166148
  };
165899
166149
  }
165900
166150
  function incrementHistorianFailure(db, sessionId, error51) {
166151
+ let nextCount = 1;
165901
166152
  db.transaction(() => {
165902
166153
  ensureSessionMetaRow(db, sessionId);
165903
166154
  const current = getHistorianFailureState(db, sessionId);
165904
- const nextCount = current.failureCount + 1;
166155
+ nextCount = current.failureCount + 1;
165905
166156
  db.prepare("UPDATE session_meta SET historian_failure_count = ?, historian_last_error = ?, historian_last_failure_at = ? WHERE session_id = ?").run(nextCount, error51, Date.now(), sessionId);
165906
166157
  const reason = error51.replace(/\s+/g, " ").trim().slice(0, 300);
165907
166158
  sessionLog(sessionId, `historian failure recorded: count=${nextCount} reason="${reason}"`);
165908
166159
  })();
166160
+ return nextCount;
165909
166161
  }
165910
166162
  function clearHistorianFailureState(db, sessionId) {
165911
166163
  db.transaction(() => {
@@ -165974,10 +166226,39 @@ function getStrippedPlaceholderIds(db, sessionId) {
165974
166226
  } catch {}
165975
166227
  return new Set;
165976
166228
  }
165977
- function setStrippedPlaceholderIds(db, sessionId, ids) {
166229
+ function applyStrippedPlaceholderDelta(db, sessionId, delta) {
166230
+ const add = delta.add ? [...delta.add] : [];
166231
+ const remove = delta.remove ? [...delta.remove] : [];
166232
+ if (add.length === 0 && remove.length === 0)
166233
+ return true;
165978
166234
  ensureSessionMetaRow(db, sessionId);
165979
- const json2 = ids.size > 0 ? JSON.stringify([...ids]) : "";
165980
- db.prepare("UPDATE session_meta SET stripped_placeholder_ids = ? WHERE session_id = ?").run(json2, sessionId);
166235
+ for (let attempt = 0;attempt < CAS_RETRY_LIMIT; attempt += 1) {
166236
+ const row = db.prepare("SELECT stripped_placeholder_ids FROM session_meta WHERE session_id = ?").get(sessionId);
166237
+ const rawStored = row ? row.stripped_placeholder_ids ?? null : null;
166238
+ const current = new Set(parseStrippedBlob(rawStored));
166239
+ for (const id of add)
166240
+ current.add(id);
166241
+ for (const id of remove)
166242
+ current.delete(id);
166243
+ const nextBlob = current.size > 0 ? JSON.stringify([...current]) : "";
166244
+ if (nextBlob === (rawStored ?? ""))
166245
+ return true;
166246
+ const result = db.prepare("UPDATE session_meta SET stripped_placeholder_ids = ? WHERE session_id = ? AND stripped_placeholder_ids IS ?").run(nextBlob, sessionId, rawStored);
166247
+ if (result.changes > 0)
166248
+ return true;
166249
+ }
166250
+ sessionLog(sessionId, `stripped_placeholder_ids CAS: ${CAS_RETRY_LIMIT} retries exhausted`);
166251
+ return false;
166252
+ }
166253
+ function parseStrippedBlob(raw) {
166254
+ if (!raw || raw.length === 0)
166255
+ return [];
166256
+ try {
166257
+ const parsed = JSON.parse(raw);
166258
+ if (Array.isArray(parsed))
166259
+ return parsed.filter((v) => typeof v === "string");
166260
+ } catch {}
166261
+ return [];
165981
166262
  }
165982
166263
  function isPendingCompactionMarker(value) {
165983
166264
  return typeof value === "object" && value !== null && typeof value.ordinal === "number" && typeof value.endMessageId === "string" && typeof value.publishedAt === "number";
@@ -166069,8 +166350,6 @@ function setSessionWorkMetrics(db, sessionId, newWorkTokens, totalInputTokens) {
166069
166350
  import { Buffer as Buffer3 } from "node:buffer";
166070
166351
 
166071
166352
  // ../plugin/src/features/magic-context/resolve-subagent-fallback.ts
166072
- init_logger();
166073
- await init_read_session_db();
166074
166353
  function resolveIsSubagentFromOpenCodeDb(sessionId) {
166075
166354
  try {
166076
166355
  return withReadOnlySessionDb((openCodeDb) => {
@@ -166104,6 +166383,9 @@ var SESSION_META_FALLBACK_SELECTS = {
166104
166383
  cached_m0_materialized_at: "NULL AS cached_m0_materialized_at",
166105
166384
  cached_m0_session_facts_version: "NULL AS cached_m0_session_facts_version",
166106
166385
  cached_m0_upgrade_state: "NULL AS cached_m0_upgrade_state",
166386
+ cached_m0_system_hash: "NULL AS cached_m0_system_hash",
166387
+ cached_m0_tool_set_hash: "NULL AS cached_m0_tool_set_hash",
166388
+ cached_m0_model_key: "NULL AS cached_m0_model_key",
166107
166389
  last_observed_model_key: "NULL AS last_observed_model_key",
166108
166390
  upgrade_reminded_at: "NULL AS upgrade_reminded_at"
166109
166391
  };
@@ -166336,7 +166618,6 @@ function markNoteChecked(db, noteId) {
166336
166618
  db.prepare("UPDATE notes SET last_checked_at = ?, updated_at = ? WHERE id = ? AND type = 'smart'").run(now, now, noteId);
166337
166619
  }
166338
166620
  // ../plugin/src/features/magic-context/storage-ops.ts
166339
- init_logger();
166340
166621
  var queuePendingOpStatements = new WeakMap;
166341
166622
  var getPendingOpsStatements = new WeakMap;
166342
166623
  var clearPendingOpsStatements = new WeakMap;
@@ -166738,7 +167019,6 @@ var ERROR_CLASSES = new Set([
166738
167019
  "unknown"
166739
167020
  ]);
166740
167021
  // src/tools/ctx-memory.ts
166741
- init_logger();
166742
167022
  var DEFAULT_LIST_LIMIT = 10;
166743
167023
  var VALID_CATEGORIES = new Set(CATEGORY_PRIORITY);
166744
167024
  function isMemoryCategory2(value) {
@@ -166883,7 +167163,6 @@ function createCtxMemoryTool(deps) {
166883
167163
  sourceType: dreamerAllowed ? "dreamer" : "agent"
166884
167164
  });
166885
167165
  queueEmbedding({ deps, projectIdentity, memoryId: memory2.id, content });
166886
- invalidateAllMemoryBlockCaches(deps.db);
166887
167166
  return ok2(`Saved memory [ID: ${memory2.id}] in ${rawCategory}.`);
166888
167167
  }
166889
167168
  if (params.action === "delete") {
@@ -166891,7 +167170,7 @@ function createCtxMemoryTool(deps) {
166891
167170
  return err2("Error: 'id' is required when action is 'delete'.");
166892
167171
  }
166893
167172
  const memory2 = getMemoryById(deps.db, params.id);
166894
- if (!memory2 || memory2.projectPath !== projectIdentity) {
167173
+ if (!memory2 || !storedPathBelongsToIdentity(memory2.projectPath, projectIdentity)) {
166895
167174
  return err2(`Error: Memory with ID ${params.id} was not found.`);
166896
167175
  }
166897
167176
  deps.db.transaction(() => {
@@ -166920,7 +167199,7 @@ function createCtxMemoryTool(deps) {
166920
167199
  return err2("Error: 'content' is required when action is 'update'.");
166921
167200
  }
166922
167201
  const memory2 = getMemoryById(deps.db, params.id);
166923
- if (!memory2 || memory2.projectPath !== projectIdentity) {
167202
+ if (!memory2 || !storedPathBelongsToIdentity(memory2.projectPath, projectIdentity)) {
166924
167203
  return err2(`Error: Memory with ID ${params.id} was not found.`);
166925
167204
  }
166926
167205
  const normalizedHash = computeNormalizedHash(content);
@@ -166954,9 +167233,6 @@ function createCtxMemoryTool(deps) {
166954
167233
  if (sourceMemories.length !== ids.length) {
166955
167234
  return err2("Error: One or more source memories were not found.");
166956
167235
  }
166957
- if (sourceMemories.some((memory2) => memory2.projectPath !== projectIdentity)) {
166958
- return err2("Error: All memories to merge must belong to the current project.");
166959
- }
166960
167236
  const requestedCategory = params.category?.trim();
166961
167237
  if (requestedCategory && !isMemoryCategory2(requestedCategory)) {
166962
167238
  return err2(`Error: Unknown memory category '${requestedCategory}'. Valid: ${CATEGORY_PRIORITY.join(", ")}`);
@@ -167015,7 +167291,7 @@ function createCtxMemoryTool(deps) {
167015
167291
  }
167016
167292
  supersededMemory(deps.db, memory2.id, canonicalMemory.id);
167017
167293
  queueMemoryMutation(deps.db, {
167018
- projectPath: memory2.projectPath,
167294
+ projectPath: normalizeStoredProjectPath(memory2.projectPath),
167019
167295
  mutationType: "superseded",
167020
167296
  targetMemoryId: memory2.id,
167021
167297
  supersededById: canonicalMemory.id
@@ -167023,7 +167299,7 @@ function createCtxMemoryTool(deps) {
167023
167299
  }
167024
167300
  if (canonicalExisting && canonicalContentChanged) {
167025
167301
  queueMemoryMutation(deps.db, {
167026
- projectPath: canonicalMemory.projectPath,
167302
+ projectPath: normalizeStoredProjectPath(canonicalMemory.projectPath),
167027
167303
  mutationType: "update",
167028
167304
  targetMemoryId: canonicalMemory.id,
167029
167305
  category,
@@ -167045,7 +167321,7 @@ function createCtxMemoryTool(deps) {
167045
167321
  return err2("Error: 'id' is required when action is 'archive'.");
167046
167322
  }
167047
167323
  const memory2 = getMemoryById(deps.db, params.id);
167048
- if (!memory2 || memory2.projectPath !== projectIdentity) {
167324
+ if (!memory2 || !storedPathBelongsToIdentity(memory2.projectPath, projectIdentity)) {
167049
167325
  return err2(`Error: Memory with ID ${params.id} was not found.`);
167050
167326
  }
167051
167327
  deps.db.transaction(() => {
@@ -167307,7 +167583,7 @@ ${smartNotes.map(formatNoteLine).join(`
167307
167583
  // ../plugin/src/features/magic-context/range-parser.ts
167308
167584
  function parseRangeString(input) {
167309
167585
  const maxRangeElements = 1000;
167310
- const trimmed = input.trim();
167586
+ const trimmed = input.replace(/§/g, "").trim();
167311
167587
  if (trimmed === "") {
167312
167588
  throw new Error("Range string must not be empty");
167313
167589
  }
@@ -167455,11 +167731,7 @@ function createCtxReduceTool(deps) {
167455
167731
  };
167456
167732
  }
167457
167733
 
167458
- // ../plugin/src/features/magic-context/search.ts
167459
- init_logger();
167460
-
167461
167734
  // ../plugin/src/features/magic-context/git-commits/git-log-reader.ts
167462
- init_logger();
167463
167735
  import { execFile } from "node:child_process";
167464
167736
  import { promisify } from "node:util";
167465
167737
  var execFileAsync = promisify(execFile);
@@ -167543,11 +167815,7 @@ ${body}` : subject;
167543
167815
  }
167544
167816
  return commits;
167545
167817
  }
167546
- // ../plugin/src/features/magic-context/git-commits/indexer.ts
167547
- init_logger();
167548
-
167549
167818
  // ../plugin/src/features/magic-context/git-commits/storage-git-commits.ts
167550
- init_logger();
167551
167819
  var insertStatements = new WeakMap;
167552
167820
  var existingShasStatements = new WeakMap;
167553
167821
  var projectCountStatements = new WeakMap;
@@ -167760,7 +168028,6 @@ async function embedUnembeddedCommits(db, projectPath) {
167760
168028
  }
167761
168029
  }
167762
168030
  // ../plugin/src/features/magic-context/git-commits/search-git-commits.ts
167763
- init_logger();
167764
168031
  var ftsStatements = new WeakMap;
167765
168032
  var ftsPlainStatements = new WeakMap;
167766
168033
  var getBySHAStatements = new WeakMap;
@@ -168431,9 +168698,6 @@ class BoundedSessionMap {
168431
168698
  }
168432
168699
  }
168433
168700
 
168434
- // ../plugin/src/hooks/magic-context/inject-compartments.ts
168435
- init_logger();
168436
-
168437
168701
  // ../plugin/src/hooks/magic-context/decay-curve.ts
168438
168702
  var H50 = 24;
168439
168703
  var D = 25;
@@ -168497,6 +168761,9 @@ function escapeXmlAttr2(s) {
168497
168761
  function escapeXmlContent2(s) {
168498
168762
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
168499
168763
  }
168764
+ function isTieredRow(c) {
168765
+ return typeof c.p1 === "string" && c.p1.length > 0;
168766
+ }
168500
168767
  function tierBody(c, tier2) {
168501
168768
  const tiers = [c.p1, c.p2, c.p3, c.p4];
168502
168769
  const requested = tiers[tier2 - 1];
@@ -168526,12 +168793,13 @@ function renderOneCompartment(c, tier2) {
168526
168793
  const baseAttrs = `start="${c.startMessage}" end="${c.endMessage}" title="${escapeXmlAttr2(c.title)}"`;
168527
168794
  if (tier2 >= 5)
168528
168795
  return "";
168529
- if (c.legacy === 1) {
168530
- if (tier2 >= 4)
168796
+ if (c.legacy === 1 || !isTieredRow(c)) {
168797
+ const flat = (c.content ?? "").trim();
168798
+ if (tier2 >= 4 || flat.length === 0)
168531
168799
  return `<compartment ${baseAttrs} />`;
168532
168800
  return [
168533
168801
  `<compartment ${baseAttrs}>`,
168534
- escapeXmlContent2(legacyBodyForTier(c.content, tier2)),
168802
+ escapeXmlContent2(legacyBodyForTier(flat, tier2)),
168535
168803
  "</compartment>"
168536
168804
  ].join(`
168537
168805
  `);
@@ -168608,26 +168876,58 @@ import { join as join9, sep as sep2 } from "node:path";
168608
168876
  var import_comment_json2 = __toESM(require_src2(), 1);
168609
168877
  import { existsSync as existsSync7, readFileSync as readFileSync5 } from "node:fs";
168610
168878
  import { homedir as homedir4 } from "node:os";
168611
- import { join as join8 } from "node:path";
168879
+ import { isAbsolute as isAbsolute2, join as join8, resolve as resolve3 } from "node:path";
168880
+ import { fileURLToPath } from "node:url";
168612
168881
  var overrideAvailability = null;
168613
168882
  function parseConfig(path5) {
168614
168883
  if (!existsSync7(path5))
168615
168884
  return null;
168616
168885
  return import_comment_json2.parse(readFileSync5(path5, "utf-8"));
168617
168886
  }
168618
- function entryMatchesAft(entry) {
168887
+ var AFT_NAME_NEEDLES = ["@cortexkit/aft", "aft-opencode", "aft-pi"];
168888
+ function stringMentionsAft(value) {
168889
+ return AFT_NAME_NEEDLES.some((needle) => value.includes(needle));
168890
+ }
168891
+ function resolveLocalEntryPackageName(value, configDir) {
168892
+ let dir = null;
168893
+ if (value.startsWith("file://")) {
168894
+ try {
168895
+ dir = fileURLToPath(value);
168896
+ } catch {
168897
+ return null;
168898
+ }
168899
+ } else if (value.startsWith("~/")) {
168900
+ dir = join8(homedir4(), value.slice(2));
168901
+ } else if (value.startsWith("/") || value.startsWith("./") || value.startsWith("../")) {
168902
+ dir = isAbsolute2(value) ? value : resolve3(configDir, value);
168903
+ } else {
168904
+ return null;
168905
+ }
168906
+ try {
168907
+ const pkg = JSON.parse(readFileSync5(join8(dir, "package.json"), "utf-8"));
168908
+ return typeof pkg.name === "string" ? pkg.name : null;
168909
+ } catch {
168910
+ return null;
168911
+ }
168912
+ }
168913
+ function entryMatchesAft(entry, configDir) {
168619
168914
  const value = Array.isArray(entry) ? entry[0] : entry;
168620
- return typeof value === "string" && (value.includes("@cortexkit/aft") || value.includes("aft-opencode") || value.includes("aft-pi"));
168915
+ if (typeof value !== "string")
168916
+ return false;
168917
+ if (stringMentionsAft(value))
168918
+ return true;
168919
+ const name2 = resolveLocalEntryPackageName(value, configDir);
168920
+ return name2 != null && stringMentionsAft(name2);
168621
168921
  }
168622
- function hasAftInArray(value) {
168623
- return Array.isArray(value) && value.some(entryMatchesAft);
168922
+ function hasAftInArray(value, configDir) {
168923
+ return Array.isArray(value) && value.some((entry) => entryMatchesAft(entry, configDir));
168624
168924
  }
168625
- function hasAftAtKeys(value, keys2) {
168925
+ function hasAftAtKeys(value, keys2, configDir) {
168626
168926
  if (!value || typeof value !== "object")
168627
168927
  return false;
168628
168928
  const record4 = value;
168629
168929
  for (const key of keys2) {
168630
- if (hasAftInArray(record4[key]))
168930
+ if (hasAftInArray(record4[key], configDir))
168631
168931
  return true;
168632
168932
  }
168633
168933
  return false;
@@ -168644,7 +168944,8 @@ function getAftAvailability() {
168644
168944
  for (const path5 of opencodePaths) {
168645
168945
  try {
168646
168946
  const config2 = parseConfig(path5);
168647
- if (hasAftAtKeys(config2, ["plugin", "plugins", "mcp", "mcp_servers"])) {
168947
+ const configDir = join8(path5, "..");
168948
+ if (hasAftAtKeys(config2, ["plugin", "plugins", "mcp", "mcp_servers"], configDir)) {
168648
168949
  opencode = true;
168649
168950
  break;
168650
168951
  }
@@ -168654,12 +168955,13 @@ function getAftAvailability() {
168654
168955
  for (const path5 of piPaths) {
168655
168956
  try {
168656
168957
  const config2 = parseConfig(path5);
168657
- if (hasAftAtKeys(config2, ["packages", "extensions"])) {
168958
+ const configDir = join8(path5, "..");
168959
+ if (hasAftAtKeys(config2, ["packages", "extensions"], configDir)) {
168658
168960
  pi = true;
168659
168961
  break;
168660
168962
  }
168661
168963
  const agent = config2?.agent;
168662
- if (hasAftAtKeys(agent, ["packages", "extensions"])) {
168964
+ if (hasAftAtKeys(agent, ["packages", "extensions"], configDir)) {
168663
168965
  pi = true;
168664
168966
  break;
168665
168967
  }
@@ -168678,7 +168980,6 @@ function isAftAvailable() {
168678
168980
  }
168679
168981
 
168680
168982
  // ../plugin/src/hooks/magic-context/key-files-block.ts
168681
- init_logger();
168682
168983
  var cachedKeyFilesBySession = new Map;
168683
168984
  var staleUpdates = new Map;
168684
168985
  function staleKey(update2) {
@@ -168776,9 +169077,6 @@ ${blocks.join(`
168776
169077
  return rendered;
168777
169078
  }
168778
169079
 
168779
- // ../plugin/src/hooks/magic-context/inject-compartments.ts
168780
- await init_read_session_db();
168781
-
168782
169080
  // ../plugin/src/hooks/magic-context/temporal-awareness.ts
168783
169081
  var TEMPORAL_AWARENESS_THRESHOLD_SECONDS = 300;
168784
169082
  var SECONDS_PER_MINUTE = 60;
@@ -169048,6 +169346,7 @@ function createCtxSearchTool(deps) {
169048
169346
  const embeddingEnabled = snapshot ? snapshot.enabled || snapshot.gitCommitEnabled : deps.embeddingEnabled;
169049
169347
  const gitCommitsEnabled = snapshot?.gitCommitEnabled ?? deps.gitCommitsEnabled ?? false;
169050
169348
  const lastCompartmentEnd = getLastCompartmentEndMessage(deps.db, sessionId);
169349
+ const messageOrdinalCutoff = lastCompartmentEnd >= 0 ? lastCompartmentEnd : 0;
169051
169350
  const visibleMemoryIds = getVisibleMemoryIds(deps.db, sessionId);
169052
169351
  const results = await unifiedSearch(deps.db, sessionId, projectIdentity, query, {
169053
169352
  limit: normalizeLimit3(params.limit),
@@ -169058,7 +169357,7 @@ function createCtxSearchTool(deps) {
169058
169357
  return result?.vector ?? null;
169059
169358
  },
169060
169359
  isEmbeddingRuntimeEnabled: () => embeddingEnabled === true,
169061
- maxMessageOrdinal: lastCompartmentEnd >= 0 ? lastCompartmentEnd : undefined,
169360
+ maxMessageOrdinal: messageOrdinalCutoff,
169062
169361
  gitCommitsEnabled,
169063
169362
  sources: params.sources,
169064
169363
  visibleMemoryIds,