@wolfx/pi-magic-context 0.22.1-patch.0 → 0.22.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -46,217 +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 path2 from "node:path";
65
- function getDataDir() {
66
- return process.env.XDG_DATA_HOME ?? path2.join(os.homedir(), ".local", "share");
67
- }
68
- function getMagicContextTempDir(harness = getHarness()) {
69
- return path2.join(os.tmpdir(), harness, "magic-context");
70
- }
71
- function getMagicContextLogPath(harness = getHarness()) {
72
- return path2.join(getMagicContextTempDir(harness), "magic-context.log");
73
- }
74
- function getProjectMagicContextDir(directory) {
75
- return path2.join(directory, ".magic-context");
76
- }
77
- function getProjectMagicContextHistorianDir(directory) {
78
- return path2.join(getProjectMagicContextDir(directory), "historian");
79
- }
80
- function getOpenCodeStorageDir() {
81
- return path2.join(getDataDir(), "opencode", "storage");
82
- }
83
- function getMagicContextStorageDir() {
84
- return path2.join(getDataDir(), "cortexkit", "magic-context");
85
- }
86
- function getLegacyOpenCodeMagicContextStorageDir() {
87
- return path2.join(getOpenCodeStorageDir(), "plugin", "magic-context");
88
- }
89
- function getCacheDir() {
90
- return process.env.XDG_CACHE_HOME ?? path2.join(os.homedir(), ".cache");
91
- }
92
- var init_data_path = () => {};
93
-
94
- // ../plugin/src/shared/logger.ts
95
- import * as fs from "node:fs";
96
- import * as path3 from "node:path";
97
- function ensureDir(filePath) {
98
- const dir = path3.dirname(filePath);
99
- if (dir === lastEnsuredDir)
100
- return;
101
- try {
102
- fs.mkdirSync(dir, { recursive: true });
103
- lastEnsuredDir = dir;
104
- } catch {}
105
- }
106
- function flush() {
107
- if (flushTimer) {
108
- clearTimeout(flushTimer);
109
- flushTimer = null;
110
- }
111
- if (buffer.length === 0)
112
- return;
113
- const data = buffer.join("");
114
- buffer = [];
115
- try {
116
- const logFile = getMagicContextLogPath();
117
- ensureDir(logFile);
118
- fs.appendFileSync(logFile, data);
119
- } catch {}
120
- }
121
- function scheduleFlush() {
122
- if (flushTimer)
123
- return;
124
- flushTimer = setTimeout(() => {
125
- flushTimer = null;
126
- flush();
127
- }, FLUSH_INTERVAL_MS);
128
- }
129
- function log(message, data) {
130
- if (isTestEnv)
131
- return;
132
- try {
133
- const timestamp = new Date().toISOString();
134
- const serialized = data === undefined ? "" : data instanceof Error ? ` ${data.message}${data.stack ? `
135
- ${data.stack}` : ""}` : ` ${JSON.stringify(data)}`;
136
- buffer.push(`[${timestamp}] ${message}${serialized}
137
- `);
138
- if (buffer.length >= BUFFER_SIZE_LIMIT) {
139
- flush();
140
- } else {
141
- scheduleFlush();
142
- }
143
- } catch {}
144
- }
145
- function sessionLog(sessionId, message, data) {
146
- log(`[magic-context][${sessionId}] ${message}`, data);
147
- }
148
- var isTestEnv = false, buffer, flushTimer = null, FLUSH_INTERVAL_MS = 500, BUFFER_SIZE_LIMIT = 50, lastEnsuredDir = null;
149
- var init_logger = __esm(() => {
150
- init_data_path();
151
- buffer = [];
152
- if (!isTestEnv) {
153
- process.on("exit", flush);
154
- }
155
- });
156
-
157
- // ../plugin/src/shared/sqlite.ts
158
- function buildNodeSqliteDatabaseClass(DatabaseSync) {
159
- const SAVEPOINT = "mc_tx_sp";
160
-
161
- class NodeSqliteDatabase extends DatabaseSync {
162
- constructor(filename, options) {
163
- const translated = { ...options };
164
- if (options && "readonly" in options) {
165
- translated.readOnly = options.readonly;
166
- delete translated.readonly;
167
- }
168
- super(typeof filename === "string" ? filename : ":memory:", translated);
169
- }
170
- transaction(fn) {
171
- const self = this;
172
- const wrapped = function(...args) {
173
- const nested = self.isTransaction === true;
174
- self.exec(nested ? `SAVEPOINT ${SAVEPOINT}` : "BEGIN");
175
- try {
176
- const result = fn.apply(this, args);
177
- self.exec(nested ? `RELEASE ${SAVEPOINT}` : "COMMIT");
178
- return result;
179
- } catch (error) {
180
- if (nested) {
181
- self.exec(`ROLLBACK TO ${SAVEPOINT}`);
182
- self.exec(`RELEASE ${SAVEPOINT}`);
183
- } else {
184
- self.exec("ROLLBACK");
185
- }
186
- throw error;
187
- }
188
- };
189
- return wrapped;
190
- }
191
- }
192
- return NodeSqliteDatabase;
193
- }
194
- var isBun, bunSpec, nodeSpec, sqliteModule, DatabaseImpl, Database;
195
- var init_sqlite = __esm(async () => {
196
- isBun = typeof process !== "undefined" && typeof process.versions?.bun === "string";
197
- bunSpec = "bun:" + "sqlite";
198
- nodeSpec = "node:" + "sqlite";
199
- sqliteModule = isBun ? await import(bunSpec) : await import(nodeSpec);
200
- DatabaseImpl = isBun ? sqliteModule.Database : buildNodeSqliteDatabaseClass(sqliteModule.DatabaseSync);
201
- Database = DatabaseImpl;
202
- });
203
-
204
- // ../plugin/src/shared/sqlite-helpers.ts
205
- function closeQuietly(db) {
206
- if (!db)
207
- return;
208
- try {
209
- db.close();
210
- } catch {}
211
- }
212
-
213
- // ../plugin/src/hooks/magic-context/read-session-db.ts
214
- import { existsSync } from "node:fs";
215
- import { join as join2 } from "node:path";
216
- function getOpenCodeDbPath() {
217
- return join2(getDataDir(), "opencode", "opencode.db");
218
- }
219
- function openCodeDbExists() {
220
- return existsSync(getOpenCodeDbPath());
221
- }
222
- function closeCachedReadOnlyDb() {
223
- if (!cachedReadOnlyDb) {
224
- return;
225
- }
226
- try {
227
- closeQuietly(cachedReadOnlyDb.db);
228
- } catch (error) {
229
- log("[magic-context] failed to close cached OpenCode read-only DB:", error);
230
- } finally {
231
- cachedReadOnlyDb = null;
232
- }
233
- }
234
- function getReadOnlySessionDb() {
235
- const dbPath = getOpenCodeDbPath();
236
- if (cachedReadOnlyDb?.path === dbPath) {
237
- return cachedReadOnlyDb.db;
238
- }
239
- closeCachedReadOnlyDb();
240
- const db = new Database(dbPath, { readonly: true });
241
- cachedReadOnlyDb = { path: dbPath, db };
242
- return db;
243
- }
244
- function withReadOnlySessionDb(fn) {
245
- return fn(getReadOnlySessionDb());
246
- }
247
- function getRawSessionMessageCountFromDb(db, sessionId) {
248
- const row = db.prepare(`SELECT COUNT(*) as count FROM message WHERE session_id = ?
249
- AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
250
- AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')`).get(sessionId);
251
- return typeof row?.count === "number" ? row.count : 0;
252
- }
253
- var cachedReadOnlyDb = null;
254
- var init_read_session_db = __esm(async () => {
255
- init_data_path();
256
- init_logger();
257
- await init_sqlite();
258
- });
259
-
260
49
  // ../../node_modules/.bun/esprima@4.0.1/node_modules/esprima/dist/esprima.js
261
50
  var require_esprima = __commonJS((exports, module) => {
262
51
  (function webpackUniversalModuleDefinition(root, factory) {
@@ -8285,8 +8074,115 @@ function hasGitDir(canonical) {
8285
8074
  }
8286
8075
  }
8287
8076
 
8288
- // ../plugin/src/features/magic-context/message-index-async.ts
8289
- init_logger();
8077
+ // ../plugin/src/shared/logger.ts
8078
+ import * as fs from "node:fs";
8079
+ import * as path3 from "node:path";
8080
+
8081
+ // ../plugin/src/shared/data-path.ts
8082
+ import * as os from "node:os";
8083
+ import * as path2 from "node:path";
8084
+
8085
+ // ../plugin/src/shared/harness.ts
8086
+ var currentHarness = "opencode";
8087
+ var harnessLocked = false;
8088
+ function setHarness(value) {
8089
+ if (harnessLocked && currentHarness !== value) {
8090
+ throw new Error(`Magic Context: harness already locked to "${currentHarness}"; cannot change to "${value}"`);
8091
+ }
8092
+ currentHarness = value;
8093
+ harnessLocked = true;
8094
+ }
8095
+ function getHarness() {
8096
+ return currentHarness;
8097
+ }
8098
+
8099
+ // ../plugin/src/shared/data-path.ts
8100
+ function getDataDir() {
8101
+ return process.env.XDG_DATA_HOME ?? path2.join(os.homedir(), ".local", "share");
8102
+ }
8103
+ function getMagicContextTempDir(harness = getHarness()) {
8104
+ return path2.join(os.tmpdir(), harness, "magic-context");
8105
+ }
8106
+ function getMagicContextLogPath(harness = getHarness()) {
8107
+ return path2.join(getMagicContextTempDir(harness), "magic-context.log");
8108
+ }
8109
+ function getProjectMagicContextDir(directory) {
8110
+ return path2.join(directory, ".magic-context");
8111
+ }
8112
+ function getProjectMagicContextHistorianDir(directory) {
8113
+ return path2.join(getProjectMagicContextDir(directory), "historian");
8114
+ }
8115
+ function getOpenCodeStorageDir() {
8116
+ return path2.join(getDataDir(), "opencode", "storage");
8117
+ }
8118
+ function getMagicContextStorageDir() {
8119
+ return path2.join(getDataDir(), "cortexkit", "magic-context");
8120
+ }
8121
+ function getLegacyOpenCodeMagicContextStorageDir() {
8122
+ return path2.join(getOpenCodeStorageDir(), "plugin", "magic-context");
8123
+ }
8124
+
8125
+ // ../plugin/src/shared/logger.ts
8126
+ var isTestEnv = false;
8127
+ var buffer = [];
8128
+ var flushTimer = null;
8129
+ var FLUSH_INTERVAL_MS = 500;
8130
+ var BUFFER_SIZE_LIMIT = 50;
8131
+ var lastEnsuredDir = null;
8132
+ function ensureDir(filePath) {
8133
+ const dir = path3.dirname(filePath);
8134
+ if (dir === lastEnsuredDir)
8135
+ return;
8136
+ try {
8137
+ fs.mkdirSync(dir, { recursive: true });
8138
+ lastEnsuredDir = dir;
8139
+ } catch {}
8140
+ }
8141
+ function flush() {
8142
+ if (flushTimer) {
8143
+ clearTimeout(flushTimer);
8144
+ flushTimer = null;
8145
+ }
8146
+ if (buffer.length === 0)
8147
+ return;
8148
+ const data = buffer.join("");
8149
+ buffer = [];
8150
+ try {
8151
+ const logFile = getMagicContextLogPath();
8152
+ ensureDir(logFile);
8153
+ fs.appendFileSync(logFile, data);
8154
+ } catch {}
8155
+ }
8156
+ function scheduleFlush() {
8157
+ if (flushTimer)
8158
+ return;
8159
+ flushTimer = setTimeout(() => {
8160
+ flushTimer = null;
8161
+ flush();
8162
+ }, FLUSH_INTERVAL_MS);
8163
+ }
8164
+ function log(message, data) {
8165
+ if (isTestEnv)
8166
+ return;
8167
+ try {
8168
+ const timestamp = new Date().toISOString();
8169
+ const serialized = data === undefined ? "" : data instanceof Error ? ` ${data.message}${data.stack ? `
8170
+ ${data.stack}` : ""}` : ` ${JSON.stringify(data)}`;
8171
+ buffer.push(`[${timestamp}] ${message}${serialized}
8172
+ `);
8173
+ if (buffer.length >= BUFFER_SIZE_LIMIT) {
8174
+ flush();
8175
+ } else {
8176
+ scheduleFlush();
8177
+ }
8178
+ } catch {}
8179
+ }
8180
+ function sessionLog(sessionId, message, data) {
8181
+ log(`[magic-context][${sessionId}] ${message}`, data);
8182
+ }
8183
+ if (!isTestEnv) {
8184
+ process.on("exit", flush);
8185
+ }
8290
8186
 
8291
8187
  // ../plugin/src/shared/internal-initiator-marker.ts
8292
8188
  var OMO_INTERNAL_INITIATOR_MARKER = "<!-- OMO_INTERNAL_INITIATOR -->";
@@ -8300,8 +8196,102 @@ function removeSystemReminders(text) {
8300
8196
  return text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/gi, "").trim();
8301
8197
  }
8302
8198
 
8303
- // ../plugin/src/hooks/magic-context/read-session-chunk.ts
8304
- await init_read_session_db();
8199
+ // ../plugin/src/hooks/magic-context/read-session-db.ts
8200
+ import { existsSync } from "node:fs";
8201
+ import { join as join2 } from "node:path";
8202
+
8203
+ // ../plugin/src/shared/sqlite.ts
8204
+ var isBun = typeof process !== "undefined" && typeof process.versions?.bun === "string";
8205
+ var bunSpec = "bun:" + "sqlite";
8206
+ var nodeSpec = "node:" + "sqlite";
8207
+ var sqliteModule = isBun ? await import(bunSpec) : await import(nodeSpec);
8208
+ var DatabaseImpl = isBun ? sqliteModule.Database : buildNodeSqliteDatabaseClass(sqliteModule.DatabaseSync);
8209
+ function buildNodeSqliteDatabaseClass(DatabaseSync) {
8210
+ const SAVEPOINT = "mc_tx_sp";
8211
+
8212
+ class NodeSqliteDatabase extends DatabaseSync {
8213
+ constructor(filename, options) {
8214
+ const translated = { ...options };
8215
+ if (options && "readonly" in options) {
8216
+ translated.readOnly = options.readonly;
8217
+ delete translated.readonly;
8218
+ }
8219
+ super(typeof filename === "string" ? filename : ":memory:", translated);
8220
+ }
8221
+ transaction(fn) {
8222
+ const self = this;
8223
+ const wrapped = function(...args) {
8224
+ const nested = self.isTransaction === true;
8225
+ self.exec(nested ? `SAVEPOINT ${SAVEPOINT}` : "BEGIN");
8226
+ try {
8227
+ const result = fn.apply(this, args);
8228
+ self.exec(nested ? `RELEASE ${SAVEPOINT}` : "COMMIT");
8229
+ return result;
8230
+ } catch (error) {
8231
+ if (nested) {
8232
+ self.exec(`ROLLBACK TO ${SAVEPOINT}`);
8233
+ self.exec(`RELEASE ${SAVEPOINT}`);
8234
+ } else {
8235
+ self.exec("ROLLBACK");
8236
+ }
8237
+ throw error;
8238
+ }
8239
+ };
8240
+ return wrapped;
8241
+ }
8242
+ }
8243
+ return NodeSqliteDatabase;
8244
+ }
8245
+ var Database = DatabaseImpl;
8246
+
8247
+ // ../plugin/src/shared/sqlite-helpers.ts
8248
+ function closeQuietly(db) {
8249
+ if (!db)
8250
+ return;
8251
+ try {
8252
+ db.close();
8253
+ } catch {}
8254
+ }
8255
+
8256
+ // ../plugin/src/hooks/magic-context/read-session-db.ts
8257
+ function getOpenCodeDbPath() {
8258
+ return join2(getDataDir(), "opencode", "opencode.db");
8259
+ }
8260
+ function openCodeDbExists() {
8261
+ return existsSync(getOpenCodeDbPath());
8262
+ }
8263
+ var cachedReadOnlyDb = null;
8264
+ function closeCachedReadOnlyDb() {
8265
+ if (!cachedReadOnlyDb) {
8266
+ return;
8267
+ }
8268
+ try {
8269
+ closeQuietly(cachedReadOnlyDb.db);
8270
+ } catch (error) {
8271
+ log("[magic-context] failed to close cached OpenCode read-only DB:", error);
8272
+ } finally {
8273
+ cachedReadOnlyDb = null;
8274
+ }
8275
+ }
8276
+ function getReadOnlySessionDb() {
8277
+ const dbPath = getOpenCodeDbPath();
8278
+ if (cachedReadOnlyDb?.path === dbPath) {
8279
+ return cachedReadOnlyDb.db;
8280
+ }
8281
+ closeCachedReadOnlyDb();
8282
+ const db = new Database(dbPath, { readonly: true });
8283
+ cachedReadOnlyDb = { path: dbPath, db };
8284
+ return db;
8285
+ }
8286
+ function withReadOnlySessionDb(fn) {
8287
+ return fn(getReadOnlySessionDb());
8288
+ }
8289
+ function getRawSessionMessageCountFromDb(db, sessionId) {
8290
+ const row = db.prepare(`SELECT COUNT(*) as count FROM message WHERE session_id = ?
8291
+ AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
8292
+ AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')`).get(sessionId);
8293
+ return typeof row?.count === "number" ? row.count : 0;
8294
+ }
8305
8295
 
8306
8296
  // ../../node_modules/.bun/ai-tokenizer@1.0.6/node_modules/ai-tokenizer/dist/index.js
8307
8297
  function _typeof(o) {
@@ -140945,14 +140935,48 @@ function readRawSessionMessagesFromDb(db, sessionId) {
140945
140935
  var encoder = new TextEncoder;
140946
140936
  var TAG_PREFIX_REGEX = /^(?:§\d+§\s*)+/;
140947
140937
  var MALFORMED_TAG_PREFIX_REGEX = /^(?:§\d+">§(?:\d+§)?\s*)+/;
140938
+ var COMPLETE_TAG_PAIR_GLOBAL_REGEX = /\u00a7\d+\u00a7/g;
140939
+ var MALFORMED_TAG_GLOBAL_REGEX = /\u00a7\d+">(?:\u00a7(?:\d+\u00a7)?)?/g;
140940
+ var STRAY_SECTION_CHAR_REGEX = /\u00a7/g;
140941
+ function stripWellFormedLeadingTagPrefix(value) {
140942
+ return value.replace(/^(\u00a7\d+\u00a7\s*)+/, "");
140943
+ }
140944
+ function stripCompleteTagPairsGlobally(value) {
140945
+ return value.replace(COMPLETE_TAG_PAIR_GLOBAL_REGEX, "");
140946
+ }
140947
+ function stripMalformedTagNotationGlobally(value) {
140948
+ return value.replace(MALFORMED_TAG_GLOBAL_REGEX, "");
140949
+ }
140950
+ function stripTagSectionCharacters(value) {
140951
+ return value.replace(STRAY_SECTION_CHAR_REGEX, "");
140952
+ }
140953
+ function stripPersistedAssistantText(value) {
140954
+ let text = stripWellFormedLeadingTagPrefix(value);
140955
+ text = stripCompleteTagPairsGlobally(text);
140956
+ text = stripMalformedTagNotationGlobally(text);
140957
+ text = stripTagSectionCharacters(text);
140958
+ return text.trim();
140959
+ }
140948
140960
  function byteSize(value) {
140949
140961
  return encoder.encode(value).length;
140950
140962
  }
140951
140963
  function stripTagPrefix(value) {
140952
- let stripped = value.replace(MALFORMED_TAG_PREFIX_REGEX, "");
140953
- stripped = stripped.replace(TAG_PREFIX_REGEX, "");
140964
+ let stripped = value;
140965
+ for (let pass = 0;pass < 8; pass++) {
140966
+ const prev = stripped;
140967
+ stripped = stripped.replace(MALFORMED_TAG_PREFIX_REGEX, "");
140968
+ stripped = stripped.replace(TAG_PREFIX_REGEX, "");
140969
+ if (stripped === prev)
140970
+ break;
140971
+ }
140954
140972
  return stripped;
140955
140973
  }
140974
+ function peelLeadingMcTagNotation(value) {
140975
+ const body = stripTagPrefix(value);
140976
+ if (body === value)
140977
+ return { tagPrefix: "", body };
140978
+ return { tagPrefix: value.slice(0, value.length - body.length), body };
140979
+ }
140956
140980
  function prependTag(tagId, value) {
140957
140981
  const stripped = stripTagPrefix(value);
140958
140982
  return `§${tagId}§ ${stripped}`;
@@ -140994,7 +141018,9 @@ function hasMeaningfulPart(part) {
140994
141018
  return false;
140995
141019
  const type = part.type;
140996
141020
  if (type === "text") {
140997
- return typeof part.text === "string" && part.text.trim().length > 0;
141021
+ if (typeof part.text !== "string")
141022
+ return false;
141023
+ return stripTagPrefix(part.text).trim().length > 0;
140998
141024
  }
140999
141025
  if (typeof type !== "string")
141000
141026
  return false;
@@ -141309,6 +141335,7 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
141309
141335
  toolOnlyRanges
141310
141336
  };
141311
141337
  }
141338
+
141312
141339
  // ../plugin/src/features/magic-context/compression-depth-storage.ts
141313
141340
  var incrementDepthStatements = new WeakMap;
141314
141341
  var totalDepthStatements = new WeakMap;
@@ -141712,6 +141739,7 @@ function parseReportedLimit(message) {
141712
141739
  }
141713
141740
  return;
141714
141741
  }
141742
+
141715
141743
  // ../plugin/src/features/magic-context/compartment-lease.ts
141716
141744
  var COMPARTMENT_LEASE_TTL_MS = 5 * 60 * 1000;
141717
141745
  var COMPARTMENT_LEASE_RENEWAL_MS = 60 * 1000;
@@ -141782,6 +141810,9 @@ var SESSION_META_SELECT_COLUMNS = [
141782
141810
  "cached_m0_materialized_at",
141783
141811
  "cached_m0_session_facts_version",
141784
141812
  "cached_m0_upgrade_state",
141813
+ "cached_m0_system_hash",
141814
+ "cached_m0_tool_set_hash",
141815
+ "cached_m0_model_key",
141785
141816
  "last_observed_model_key",
141786
141817
  "upgrade_reminded_at",
141787
141818
  "pi_stable_id_scheme"
@@ -141818,6 +141849,9 @@ var META_COLUMNS = {
141818
141849
  cachedM0MaterializedAt: "cached_m0_materialized_at",
141819
141850
  cachedM0SessionFactsVersion: "cached_m0_session_facts_version",
141820
141851
  cachedM0UpgradeState: "cached_m0_upgrade_state",
141852
+ cachedM0SystemHash: "cached_m0_system_hash",
141853
+ cachedM0ToolSetHash: "cached_m0_tool_set_hash",
141854
+ cachedM0ModelKey: "cached_m0_model_key",
141821
141855
  lastObservedModelKey: "last_observed_model_key",
141822
141856
  upgradeRemindedAt: "upgrade_reminded_at",
141823
141857
  piStableIdScheme: "pi_stable_id_scheme"
@@ -141860,7 +141894,7 @@ function isSessionMetaRow(row) {
141860
141894
  if (row === null || typeof row !== "object")
141861
141895
  return false;
141862
141896
  const r = row;
141863
- 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);
141897
+ 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);
141864
141898
  }
141865
141899
  function getDefaultSessionMeta(sessionId) {
141866
141900
  return {
@@ -141896,6 +141930,9 @@ function getDefaultSessionMeta(sessionId) {
141896
141930
  cachedM0MaterializedAt: null,
141897
141931
  cachedM0SessionFactsVersion: null,
141898
141932
  cachedM0UpgradeState: null,
141933
+ cachedM0SystemHash: null,
141934
+ cachedM0ToolSetHash: null,
141935
+ cachedM0ModelKey: null,
141899
141936
  lastObservedModelKey: null,
141900
141937
  upgradeRemindedAt: null,
141901
141938
  piStableIdScheme: null
@@ -141947,6 +141984,9 @@ function toSessionMeta(row) {
141947
141984
  cachedM0MaterializedAt: numOrNull(row.cached_m0_materialized_at),
141948
141985
  cachedM0SessionFactsVersion: numOrNull(row.cached_m0_session_facts_version),
141949
141986
  cachedM0UpgradeState: stringOrNull(row.cached_m0_upgrade_state),
141987
+ cachedM0SystemHash: stringOrNull(row.cached_m0_system_hash),
141988
+ cachedM0ToolSetHash: stringOrNull(row.cached_m0_tool_set_hash),
141989
+ cachedM0ModelKey: stringOrNull(row.cached_m0_model_key),
141950
141990
  lastObservedModelKey: stringOrNull(row.last_observed_model_key),
141951
141991
  upgradeRemindedAt: numOrNull(row.upgrade_reminded_at),
141952
141992
  piStableIdScheme: numOrNull(row.pi_stable_id_scheme)
@@ -141966,8 +142006,11 @@ function persistCachedM0(db, sessionId, payload) {
141966
142006
  cached_m0_project_docs_hash = ?,
141967
142007
  cached_m0_materialized_at = ?,
141968
142008
  cached_m0_session_facts_version = ?,
141969
- cached_m0_upgrade_state = ?
141970
- 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);
142009
+ cached_m0_upgrade_state = ?,
142010
+ cached_m0_system_hash = ?,
142011
+ cached_m0_tool_set_hash = ?,
142012
+ cached_m0_model_key = ?
142013
+ 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);
141971
142014
  }
141972
142015
  function clearCachedM0M1(db, sessionId) {
141973
142016
  ensureSessionMetaRow(db, sessionId);
@@ -141985,6 +142028,9 @@ function clearCachedM0M1(db, sessionId) {
141985
142028
  ["cached_m0_materialized_at", null],
141986
142029
  ["cached_m0_session_facts_version", null],
141987
142030
  ["cached_m0_upgrade_state", null],
142031
+ ["cached_m0_system_hash", null],
142032
+ ["cached_m0_tool_set_hash", null],
142033
+ ["cached_m0_model_key", null],
141988
142034
  ["cached_m0_last_baseline_end_message_id", null],
141989
142035
  ["memory_block_cache", ""],
141990
142036
  ["memory_block_count", 0],
@@ -142190,11 +142236,7 @@ function escapeXmlAttr(s) {
142190
142236
  function escapeXmlContent(s) {
142191
142237
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
142192
142238
  }
142193
- // ../plugin/src/features/magic-context/migrations.ts
142194
- init_logger();
142195
-
142196
142239
  // ../plugin/src/features/magic-context/storage-db.ts
142197
- init_data_path();
142198
142240
  import { copyFileSync, cpSync, existsSync as existsSync4, mkdirSync as mkdirSync2 } from "node:fs";
142199
142241
  import { dirname as dirname2, join as join5 } from "node:path";
142200
142242
 
@@ -142274,12 +142316,7 @@ function safeString(value) {
142274
142316
  }
142275
142317
  }
142276
142318
 
142277
- // ../plugin/src/features/magic-context/storage-db.ts
142278
- init_logger();
142279
- await init_sqlite();
142280
-
142281
142319
  // ../plugin/src/features/magic-context/key-files/project-key-files.ts
142282
- init_logger();
142283
142320
  import { createHash as createHash2 } from "node:crypto";
142284
142321
  import { existsSync as existsSync2, readFileSync, realpathSync } from "node:fs";
142285
142322
  import { join as join3, resolve, sep } from "node:path";
@@ -142449,8 +142486,6 @@ function loadToolDefinitionMeasurements(db) {
142449
142486
  }
142450
142487
 
142451
142488
  // ../plugin/src/features/magic-context/tool-owner-backfill.ts
142452
- init_data_path();
142453
- init_logger();
142454
142489
  import { existsSync as existsSync3 } from "node:fs";
142455
142490
  import { join as join4 } from "node:path";
142456
142491
  var LEASE_DURATION_MS = 5 * 60 * 1000;
@@ -142698,7 +142733,7 @@ var databases = new Map;
142698
142733
  var persistenceByDatabase = new WeakMap;
142699
142734
  var persistenceErrorByDatabase = new WeakMap;
142700
142735
  var lastSchemaFenceRejection = null;
142701
- var LATEST_SUPPORTED_VERSION = 27;
142736
+ var LATEST_SUPPORTED_VERSION = 30;
142702
142737
  function resolveDatabasePath(dbPathOverride) {
142703
142738
  if (dbPathOverride) {
142704
142739
  return { dbDir: dirname2(dbPathOverride), dbPath: dbPathOverride };
@@ -143018,6 +143053,17 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
143018
143053
  updated_at INTEGER NOT NULL DEFAULT 0
143019
143054
  );
143020
143055
 
143056
+ CREATE TABLE IF NOT EXISTS git_sweep_coordinator (
143057
+ project_path TEXT PRIMARY KEY,
143058
+ lease_holder TEXT,
143059
+ lease_expires_at INTEGER,
143060
+ last_swept_at INTEGER
143061
+ );
143062
+ CREATE INDEX IF NOT EXISTS idx_git_sweep_coordinator_lease_expires
143063
+ ON git_sweep_coordinator(lease_expires_at);
143064
+ CREATE INDEX IF NOT EXISTS idx_git_sweep_coordinator_last_swept
143065
+ ON git_sweep_coordinator(last_swept_at);
143066
+
143021
143067
  CREATE TABLE IF NOT EXISTS m0_mutation_log (
143022
143068
  id INTEGER PRIMARY KEY AUTOINCREMENT,
143023
143069
  session_id TEXT NOT NULL,
@@ -143152,6 +143198,9 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
143152
143198
  cached_m0_materialized_at INTEGER,
143153
143199
  cached_m0_session_facts_version INTEGER,
143154
143200
  cached_m0_upgrade_state TEXT,
143201
+ cached_m0_system_hash TEXT,
143202
+ cached_m0_tool_set_hash TEXT,
143203
+ cached_m0_model_key TEXT,
143155
143204
  cached_m0_last_baseline_end_message_id TEXT,
143156
143205
  upgrade_reminded_at INTEGER,
143157
143206
  pi_stable_id_scheme INTEGER
@@ -143343,6 +143392,9 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
143343
143392
  ensureColumn(db, "session_meta", "cached_m0_materialized_at", "INTEGER");
143344
143393
  ensureColumn(db, "session_meta", "cached_m0_session_facts_version", "INTEGER");
143345
143394
  ensureColumn(db, "session_meta", "cached_m0_upgrade_state", "TEXT");
143395
+ ensureColumn(db, "session_meta", "cached_m0_system_hash", "TEXT");
143396
+ ensureColumn(db, "session_meta", "cached_m0_tool_set_hash", "TEXT");
143397
+ ensureColumn(db, "session_meta", "cached_m0_model_key", "TEXT");
143346
143398
  ensureColumn(db, "session_meta", "cached_m0_last_baseline_end_message_id", "TEXT");
143347
143399
  ensureColumn(db, "session_meta", "upgrade_reminded_at", "INTEGER");
143348
143400
  db.exec(`
@@ -144240,6 +144292,60 @@ var MIGRATIONS = [
144240
144292
  ON tags(session_id, entry_fingerprint)
144241
144293
  WHERE type='message' AND entry_fingerprint IS NOT NULL`);
144242
144294
  }
144295
+ },
144296
+ {
144297
+ version: 28,
144298
+ description: "Add git commit sweep coordinator lease/cooldown table",
144299
+ up: (db) => {
144300
+ db.exec(`
144301
+ CREATE TABLE IF NOT EXISTS git_sweep_coordinator (
144302
+ project_path TEXT PRIMARY KEY,
144303
+ lease_holder TEXT,
144304
+ lease_expires_at INTEGER,
144305
+ last_swept_at INTEGER
144306
+ );
144307
+ CREATE INDEX IF NOT EXISTS idx_git_sweep_coordinator_lease_expires
144308
+ ON git_sweep_coordinator(lease_expires_at);
144309
+ CREATE INDEX IF NOT EXISTS idx_git_sweep_coordinator_last_swept
144310
+ ON git_sweep_coordinator(last_swept_at);
144311
+ `);
144312
+ }
144313
+ },
144314
+ {
144315
+ version: 29,
144316
+ description: "Add anchor_ordinal to notes (traceback to the conversation tail)",
144317
+ up: (db) => {
144318
+ const notesExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='notes'").get();
144319
+ if (!notesExists) {
144320
+ return;
144321
+ }
144322
+ const columns = db.prepare("PRAGMA table_info(notes)").all();
144323
+ if (!columns.some((column) => column.name === "anchor_ordinal")) {
144324
+ db.exec("ALTER TABLE notes ADD COLUMN anchor_ordinal INTEGER");
144325
+ }
144326
+ }
144327
+ },
144328
+ {
144329
+ version: 30,
144330
+ description: "HARD-bust m[0] markers: cached system/tool-set/model identity",
144331
+ up: (db) => {
144332
+ const hasSessionMeta = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='session_meta' LIMIT 1").get();
144333
+ if (!hasSessionMeta)
144334
+ return;
144335
+ ensureColumn(db, "session_meta", "cached_m0_system_hash", "TEXT");
144336
+ ensureColumn(db, "session_meta", "cached_m0_tool_set_hash", "TEXT");
144337
+ ensureColumn(db, "session_meta", "cached_m0_model_key", "TEXT");
144338
+ const columns = new Set(db.prepare("PRAGMA table_info(session_meta)").all().map((column) => column.name));
144339
+ if (columns.has("cached_m0_bytes")) {
144340
+ db.prepare(`UPDATE session_meta SET
144341
+ cached_m0_bytes = NULL,
144342
+ cached_m1_bytes = NULL,
144343
+ cached_m0_materialized_at = NULL,
144344
+ cached_m0_system_hash = NULL,
144345
+ cached_m0_tool_set_hash = NULL,
144346
+ cached_m0_model_key = NULL`).run();
144347
+ }
144348
+ }
144243
144349
  }
144244
144350
  ];
144245
144351
  var LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
@@ -144538,7 +144644,6 @@ function getMaxMemoryMutationId(db, projectPath) {
144538
144644
  return row?.max_id ?? null;
144539
144645
  }
144540
144646
  // ../plugin/src/features/magic-context/storage-meta-persisted.ts
144541
- init_logger();
144542
144647
  var CAS_RETRY_LIMIT = 5;
144543
144648
  var AUTO_SEARCH_NO_HINT_REASONS = new Set([
144544
144649
  "below-threshold",
@@ -145001,8 +145106,6 @@ function setSessionWorkMetrics(db, sessionId, newWorkTokens, totalInputTokens) {
145001
145106
  import { Buffer as Buffer3 } from "node:buffer";
145002
145107
 
145003
145108
  // ../plugin/src/features/magic-context/resolve-subagent-fallback.ts
145004
- init_logger();
145005
- await init_read_session_db();
145006
145109
  function resolveIsSubagentFromOpenCodeDb(sessionId) {
145007
145110
  try {
145008
145111
  return withReadOnlySessionDb((openCodeDb) => {
@@ -145036,6 +145139,9 @@ var SESSION_META_FALLBACK_SELECTS = {
145036
145139
  cached_m0_materialized_at: "NULL AS cached_m0_materialized_at",
145037
145140
  cached_m0_session_facts_version: "NULL AS cached_m0_session_facts_version",
145038
145141
  cached_m0_upgrade_state: "NULL AS cached_m0_upgrade_state",
145142
+ cached_m0_system_hash: "NULL AS cached_m0_system_hash",
145143
+ cached_m0_tool_set_hash: "NULL AS cached_m0_tool_set_hash",
145144
+ cached_m0_model_key: "NULL AS cached_m0_model_key",
145039
145145
  last_observed_model_key: "NULL AS last_observed_model_key",
145040
145146
  upgrade_reminded_at: "NULL AS upgrade_reminded_at"
145041
145147
  };
@@ -145127,7 +145233,8 @@ function toNote(row) {
145127
145233
  updatedAt: row.updated_at,
145128
145234
  lastCheckedAt: toNullableNumber(row.last_checked_at),
145129
145235
  readyAt: toNullableNumber(row.ready_at),
145130
- readyReason: toNullableString(row.ready_reason)
145236
+ readyReason: toNullableString(row.ready_reason),
145237
+ anchorOrdinal: toNullableNumber(row.anchor_ordinal)
145131
145238
  };
145132
145239
  }
145133
145240
  function getNoteById(db, noteId) {
@@ -145179,7 +145286,7 @@ function getNotes(db, options = {}) {
145179
145286
  }
145180
145287
  function addNote(db, type, options) {
145181
145288
  const now = Date.now();
145182
- const result = type === "session" ? db.prepare("INSERT INTO notes (type, status, content, session_id, created_at, updated_at, harness) VALUES ('session', 'active', ?, ?, ?, ?, ?) RETURNING *").get(options.content, options.sessionId, now, now, getHarness()) : db.prepare("INSERT INTO notes (type, status, content, session_id, project_path, surface_condition, created_at, updated_at, harness) VALUES ('smart', 'pending', ?, ?, ?, ?, ?, ?, ?) RETURNING *").get(options.content, options.sessionId ?? null, options.projectPath, options.surfaceCondition, now, now, getHarness());
145289
+ const result = type === "session" ? db.prepare("INSERT INTO notes (type, status, content, session_id, created_at, updated_at, harness, anchor_ordinal) VALUES ('session', 'active', ?, ?, ?, ?, ?, ?) RETURNING *").get(options.content, options.sessionId, now, now, getHarness(), options.anchorOrdinal ?? null) : db.prepare("INSERT INTO notes (type, status, content, session_id, project_path, surface_condition, created_at, updated_at, harness, anchor_ordinal) VALUES ('smart', 'pending', ?, ?, ?, ?, ?, ?, ?, ?) RETURNING *").get(options.content, options.sessionId ?? null, options.projectPath, options.surfaceCondition, now, now, getHarness(), options.anchorOrdinal ?? null);
145183
145290
  if (!isNoteRow(result)) {
145184
145291
  throw new Error("[notes] failed to insert note");
145185
145292
  }
@@ -145267,7 +145374,6 @@ function markNoteChecked(db, noteId) {
145267
145374
  db.prepare("UPDATE notes SET last_checked_at = ?, updated_at = ? WHERE id = ? AND type = 'smart'").run(now, now, noteId);
145268
145375
  }
145269
145376
  // ../plugin/src/features/magic-context/storage-ops.ts
145270
- init_logger();
145271
145377
  var queuePendingOpStatements = new WeakMap;
145272
145378
  var getPendingOpsStatements = new WeakMap;
145273
145379
  var clearPendingOpsStatements = new WeakMap;
@@ -145669,7 +145775,6 @@ var ERROR_CLASSES = new Set([
145669
145775
  "unknown"
145670
145776
  ]);
145671
145777
  // ../plugin/src/features/magic-context/v22-deferred-backfill.ts
145672
- init_logger();
145673
145778
  import { createHash as createHash4 } from "node:crypto";
145674
145779
  import { realpathSync as realpathSync2 } from "node:fs";
145675
145780
  import path5 from "node:path";
@@ -145948,213 +146053,40 @@ function getAgentFallbackModels(agent) {
145948
146053
  }
145949
146054
 
145950
146055
  // ../plugin/src/shared/models-dev-cache.ts
145951
- init_data_path();
145952
- import { createHash as createHash5 } from "node:crypto";
145953
- import { existsSync as existsSync5, readFileSync as readFileSync3 } from "node:fs";
145954
- import { homedir as homedir2, platform } from "node:os";
146056
+ import { mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync, writeFileSync } from "node:fs";
145955
146057
  import { join as join6 } from "node:path";
145956
-
145957
- // ../plugin/src/shared/jsonc-parser.ts
145958
- function stripJsonComments(content) {
145959
- let result = "";
145960
- let inString = false;
145961
- let escaped = false;
145962
- let inLineComment = false;
145963
- let inBlockComment = false;
145964
- for (let index = 0;index < content.length; index += 1) {
145965
- const char = content[index];
145966
- const next = content[index + 1];
145967
- if (inLineComment) {
145968
- if (char === `
145969
- `) {
145970
- inLineComment = false;
145971
- result += char;
145972
- }
145973
- continue;
145974
- }
145975
- if (inBlockComment) {
145976
- if (char === "*" && next === "/") {
145977
- inBlockComment = false;
145978
- index += 1;
145979
- }
145980
- continue;
145981
- }
145982
- if (inString) {
145983
- result += char;
145984
- if (escaped) {
145985
- escaped = false;
145986
- } else if (char === "\\") {
145987
- escaped = true;
145988
- } else if (char === '"') {
145989
- inString = false;
145990
- }
145991
- continue;
145992
- }
145993
- if (char === '"') {
145994
- inString = true;
145995
- result += char;
145996
- continue;
145997
- }
145998
- if (char === "/" && next === "/") {
145999
- inLineComment = true;
146000
- index += 1;
146001
- continue;
146002
- }
146003
- if (char === "/" && next === "*") {
146004
- inBlockComment = true;
146005
- index += 1;
146006
- continue;
146007
- }
146008
- result += char;
146009
- }
146010
- return result;
146011
- }
146012
- function stripTrailingCommas(content) {
146013
- let result = "";
146014
- let inString = false;
146015
- let escaped = false;
146016
- for (let index = 0;index < content.length; index += 1) {
146017
- const char = content[index];
146018
- if (inString) {
146019
- result += char;
146020
- if (escaped) {
146021
- escaped = false;
146022
- } else if (char === "\\") {
146023
- escaped = true;
146024
- } else if (char === '"') {
146025
- inString = false;
146026
- }
146027
- continue;
146028
- }
146029
- if (char === '"') {
146030
- inString = true;
146031
- result += char;
146032
- continue;
146033
- }
146034
- if (char === ",") {
146035
- let lookahead = index + 1;
146036
- while (lookahead < content.length && /\s/.test(content[lookahead] ?? "")) {
146037
- lookahead += 1;
146038
- }
146039
- const next = content[lookahead];
146040
- if (next === "}" || next === "]") {
146041
- continue;
146042
- }
146043
- }
146044
- result += char;
146045
- }
146046
- return result;
146047
- }
146048
- function parseJsonc(content) {
146049
- const normalized = stripTrailingCommas(stripJsonComments(content));
146050
- return JSON.parse(normalized);
146058
+ var MIN_SANE_LIMIT = 20000;
146059
+ var MAX_SANE_LIMIT = 3000000;
146060
+ function isSaneLimit(limit) {
146061
+ return typeof limit === "number" && limit >= MIN_SANE_LIMIT && limit <= MAX_SANE_LIMIT;
146051
146062
  }
146052
-
146053
- // ../plugin/src/shared/models-dev-cache.ts
146054
- init_logger();
146055
- var RELOAD_INTERVAL_MS = 5 * 60 * 1000;
146056
146063
  var apiCache = null;
146057
- var apiLoadedAt = 0;
146058
- var fileCache = null;
146059
- var fileLastAttempt = 0;
146060
- function hashFast(input) {
146061
- return createHash5("sha1").update(input).digest("hex");
146062
- }
146063
- function getModelsJsonPath() {
146064
- const explicit = process.env.OPENCODE_MODELS_PATH?.trim();
146065
- if (explicit)
146066
- return explicit;
146067
- const cacheBase = getCacheDir();
146068
- const source = process.env.OPENCODE_MODELS_URL?.trim();
146069
- const filename = source && source !== "https://models.dev" ? `models-${hashFast(source)}.json` : "models.json";
146070
- return join6(cacheBase, "opencode", filename);
146071
- }
146072
- function getOpencodeConfigPath() {
146073
- const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
146074
- const configDir = envDir ? envDir : platform() === "win32" ? join6(homedir2(), ".config", "opencode") : join6(process.env.XDG_CONFIG_HOME || join6(homedir2(), ".config"), "opencode");
146075
- const jsonc = join6(configDir, "opencode.jsonc");
146076
- if (existsSync5(jsonc))
146077
- return jsonc;
146078
- const json = join6(configDir, "opencode.json");
146079
- if (existsSync5(json))
146080
- return json;
146081
- return null;
146082
- }
146083
- function resolveLimit(limit) {
146084
- if (!limit)
146085
- return;
146086
- if (typeof limit.input === "number" && limit.input > 0)
146087
- return limit.input;
146088
- if (typeof limit.context === "number" && limit.context > 0)
146089
- return limit.context;
146090
- return;
146064
+ var persistSeedLoaded = false;
146065
+ function persistFilePath() {
146066
+ return join6(getMagicContextStorageDir(), `model-context-limits-${getHarness()}.json`);
146091
146067
  }
146092
- function setCachedModelMetadata(cache, key, model) {
146093
- const limit = resolveLimit(model?.limit);
146094
- if (limit === undefined) {
146068
+ function loadPersistedApiCacheOnce() {
146069
+ if (persistSeedLoaded || apiCache !== null)
146095
146070
  return;
146096
- }
146097
- const value = { limit };
146098
- cache.set(key, value);
146099
- const modes = model?.experimental?.modes;
146100
- if (modes && typeof modes === "object") {
146101
- for (const mode of Object.keys(modes)) {
146102
- cache.set(`${key}-${mode}`, value);
146103
- }
146104
- }
146105
- }
146106
- function loadModelsDevMetadataFromFile() {
146107
- const metadata = new Map;
146108
- const modelsJsonPath = getModelsJsonPath();
146109
- let fileFound = false;
146071
+ persistSeedLoaded = true;
146110
146072
  try {
146111
- if (existsSync5(modelsJsonPath)) {
146112
- fileFound = true;
146113
- const raw = readFileSync3(modelsJsonPath, "utf-8");
146114
- const data = JSON.parse(raw);
146115
- for (const [providerId, provider] of Object.entries(data)) {
146116
- if (!provider?.models || typeof provider.models !== "object")
146117
- continue;
146118
- for (const [modelId, model] of Object.entries(provider.models)) {
146119
- setCachedModelMetadata(metadata, `${providerId}/${modelId}`, model);
146120
- }
146121
- }
146073
+ const raw = readFileSync3(persistFilePath(), "utf-8");
146074
+ const obj = JSON.parse(raw);
146075
+ const map = new Map;
146076
+ for (const [key, limit] of Object.entries(obj)) {
146077
+ if (isSaneLimit(limit))
146078
+ map.set(key, { limit });
146122
146079
  }
146123
- } catch (error) {
146124
- sessionLog("global", `models-dev-cache: failed to read models.json at ${modelsJsonPath}:`, error instanceof Error ? error.message : String(error));
146125
- }
146126
- try {
146127
- const configPath = getOpencodeConfigPath();
146128
- if (configPath && existsSync5(configPath)) {
146129
- const config = parseJsonc(readFileSync3(configPath, "utf-8"));
146130
- if (config.provider && typeof config.provider === "object") {
146131
- for (const [providerId, provider] of Object.entries(config.provider)) {
146132
- if (!provider?.models || typeof provider.models !== "object")
146133
- continue;
146134
- for (const [modelId, model] of Object.entries(provider.models)) {
146135
- setCachedModelMetadata(metadata, `${providerId}/${modelId}`, model);
146136
- }
146137
- }
146138
- }
146080
+ if (map.size > 0) {
146081
+ apiCache = map;
146082
+ sessionLog("global", `models-dev-cache: seeded ${map.size} entries from persisted cache (cold start)`);
146139
146083
  }
146140
- } catch (error) {
146141
- sessionLog("global", "models-dev-cache: failed to read opencode config for custom models:", error instanceof Error ? error.message : String(error));
146142
- }
146143
- sessionLog("global", `models-dev-cache: file-layer loaded ${metadata.size} model metadata entries (modelsJsonPath=${modelsJsonPath}, found=${fileFound})`);
146144
- return metadata;
146084
+ } catch {}
146145
146085
  }
146146
- function getModelsDevContextLimit(providerID, modelID) {
146147
- const now = Date.now();
146148
- if (!fileCache || now - fileLastAttempt > RELOAD_INTERVAL_MS) {
146149
- fileLastAttempt = now;
146150
- fileCache = loadModelsDevMetadataFromFile();
146151
- }
146086
+ function getSdkContextLimit(providerID, modelID) {
146087
+ loadPersistedApiCacheOnce();
146152
146088
  const fromApi = lookupLimitWithTagFallback(apiCache, providerID, modelID);
146153
- const fromFile = lookupLimitWithTagFallback(fileCache, providerID, modelID);
146154
- if (typeof fromApi === "number" && typeof fromFile === "number") {
146155
- return Math.max(fromApi, fromFile);
146156
- }
146157
- return fromApi ?? fromFile;
146089
+ return isSaneLimit(fromApi) ? fromApi : undefined;
146158
146090
  }
146159
146091
  function lookupLimitWithTagFallback(cache, providerID, modelID) {
146160
146092
  if (!cache)
@@ -146171,12 +146103,6 @@ function lookupLimitWithTagFallback(cache, providerID, modelID) {
146171
146103
  }
146172
146104
  return;
146173
146105
  }
146174
- function clearModelsDevCache() {
146175
- apiCache = null;
146176
- apiLoadedAt = 0;
146177
- fileCache = null;
146178
- fileLastAttempt = 0;
146179
- }
146180
146106
 
146181
146107
  // ../plugin/src/hooks/magic-context/derive-budgets.ts
146182
146108
  var TRIGGER_BUDGET_PERCENTAGE = 0.05;
@@ -146207,7 +146133,7 @@ function resolveHistorianContextLimit(historianModelOverride) {
146207
146133
  const [providerID, ...rest] = historianModelOverride.split("/");
146208
146134
  const modelID = rest.join("/");
146209
146135
  if (providerID && modelID) {
146210
- const limit = getModelsDevContextLimit(providerID, modelID);
146136
+ const limit = getSdkContextLimit(providerID, modelID);
146211
146137
  if (typeof limit === "number" && limit > 0)
146212
146138
  return limit;
146213
146139
  }
@@ -146226,7 +146152,7 @@ function resolveHistorianContextLimit(historianModelOverride) {
146226
146152
  const modelID = rest.join("/");
146227
146153
  if (!providerID || !modelID)
146228
146154
  continue;
146229
- const limit = getModelsDevContextLimit(providerID, modelID);
146155
+ const limit = getSdkContextLimit(providerID, modelID);
146230
146156
  if (typeof limit !== "number" || limit <= 0)
146231
146157
  continue;
146232
146158
  if (minLimit === undefined || limit < minLimit)
@@ -146236,40 +146162,8 @@ function resolveHistorianContextLimit(historianModelOverride) {
146236
146162
  }
146237
146163
 
146238
146164
  // ../plugin/src/hooks/magic-context/event-resolvers.ts
146239
- init_logger();
146240
146165
  var DEFAULT_CONTEXT_LIMIT = 128000;
146241
146166
  var MAX_EXECUTE_THRESHOLD = 80;
146242
- function resolveContextLimit(providerID, modelID, ctx) {
146243
- const fromModelsDev = providerID && modelID ? getModelsDevContextLimit(providerID, modelID) : undefined;
146244
- const baseline = fromModelsDev ?? DEFAULT_CONTEXT_LIMIT;
146245
- if (ctx?.db && ctx.sessionID) {
146246
- try {
146247
- const overflow = getOverflowState(ctx.db, ctx.sessionID);
146248
- if (overflow.detectedContextLimit > 0 && overflow.detectedContextLimit < baseline) {
146249
- return overflow.detectedContextLimit;
146250
- }
146251
- } catch {}
146252
- }
146253
- return baseline;
146254
- }
146255
- function resolveTrustedContextLimit(providerID, modelID, ctx) {
146256
- const fromModelsDev = providerID && modelID ? getModelsDevContextLimit(providerID, modelID) : undefined;
146257
- let detected;
146258
- if (ctx?.db && ctx.sessionID) {
146259
- try {
146260
- const overflow = getOverflowState(ctx.db, ctx.sessionID);
146261
- if (overflow.detectedContextLimit > 0) {
146262
- detected = overflow.detectedContextLimit;
146263
- }
146264
- } catch {}
146265
- }
146266
- if (typeof fromModelsDev === "number" && fromModelsDev > 0) {
146267
- if (detected !== undefined && detected < fromModelsDev)
146268
- return detected;
146269
- return fromModelsDev;
146270
- }
146271
- return detected;
146272
- }
146273
146167
  function resolveCacheTtl(cacheTtl, modelKey) {
146274
146168
  if (typeof cacheTtl === "string") {
146275
146169
  return cacheTtl;
@@ -146400,7 +146294,6 @@ function resolveTokensMatchWithKey(tokensConfig, modelKey) {
146400
146294
  }
146401
146295
 
146402
146296
  // ../plugin/src/hooks/magic-context/note-nudger.ts
146403
- init_logger();
146404
146297
  var NOTE_NUDGE_COOLDOWN_MS = 15 * 60 * 1000;
146405
146298
  var lastDeliveredAt = new Map;
146406
146299
  function getPersistedNoteNudgeDeliveredAt(_db, sessionId) {
@@ -146490,7 +146383,7 @@ function clearNoteNudgeTriggerOnly(db, sessionId) {
146490
146383
  }
146491
146384
 
146492
146385
  // ../plugin/src/hooks/magic-context/todo-view.ts
146493
- import { createHash as createHash6 } from "node:crypto";
146386
+ import { createHash as createHash5 } from "node:crypto";
146494
146387
  var TERMINAL_STATUSES = new Set(["completed", "cancelled"]);
146495
146388
  var TITLE_DONE_STATUSES = new Set(["completed"]);
146496
146389
  var SYNTHETIC_CALL_ID_PREFIX = "mc_synthetic_todo_";
@@ -146535,7 +146428,7 @@ function buildSyntheticTodoPart(stateJson) {
146535
146428
  };
146536
146429
  }
146537
146430
  function computeSyntheticCallId(stateJson) {
146538
- const hash = createHash6("sha256").update(stateJson).digest("hex").slice(0, 16);
146431
+ const hash = createHash5("sha256").update(stateJson).digest("hex").slice(0, 16);
146539
146432
  return `${SYNTHETIC_CALL_ID_PREFIX}${hash}`;
146540
146433
  }
146541
146434
  function parseTodoState(stateJson) {
@@ -146568,7 +146461,6 @@ function isTodoItem(value) {
146568
146461
  }
146569
146462
 
146570
146463
  // ../plugin/src/hooks/magic-context/upgrade-reminder.ts
146571
- init_logger();
146572
146464
  var remindedThisProcess = new Set;
146573
146465
  var UPGRADE_REMINDER_TEXT = [
146574
146466
  "\uD83C\uDF86 Historian V2 is released!",
@@ -146669,7 +146561,6 @@ async function maybeSendUpgradeReminder(deps, sessionId) {
146669
146561
  }
146670
146562
 
146671
146563
  // ../plugin/src/shared/announcement.ts
146672
- init_data_path();
146673
146564
  import * as fs2 from "node:fs";
146674
146565
  import * as path6 from "node:path";
146675
146566
  var ANNOUNCEMENT_VERSION = "0.22.0";
@@ -146715,9 +146606,14 @@ function shouldShowAnnouncement() {
146715
146606
  return lastVersion !== ANNOUNCEMENT_VERSION;
146716
146607
  }
146717
146608
 
146718
- // src/index.ts
146719
- init_data_path();
146720
- init_logger();
146609
+ // ../plugin/src/shared/keep-subagents.ts
146610
+ var keepSubagents = false;
146611
+ function setKeepSubagents(value) {
146612
+ keepSubagents = value === true;
146613
+ }
146614
+ function shouldKeepSubagents() {
146615
+ return keepSubagents;
146616
+ }
146721
146617
 
146722
146618
  // ../plugin/src/shared/resolve-fallbacks.ts
146723
146619
  function resolveFallbackChain(agentName, userFallbacks) {
@@ -146784,19 +146680,15 @@ function isEmptySidekickResult(text) {
146784
146680
  return trimmed.length === 0 || trimmed === "no relevant memories found";
146785
146681
  }
146786
146682
 
146787
- // src/commands/ctx-aug.ts
146788
- init_logger();
146789
-
146790
146683
  // src/subagent-runner.ts
146791
146684
  import * as childProcess from "node:child_process";
146792
- import { existsSync as existsSync7 } from "node:fs";
146685
+ import { existsSync as existsSync6 } from "node:fs";
146793
146686
  import { createRequire as createRequire2 } from "node:module";
146794
146687
  import { dirname as dirname3, join as join8, resolve as resolvePath } from "node:path";
146795
146688
  import { createInterface } from "node:readline";
146796
146689
  import { fileURLToPath } from "node:url";
146797
146690
 
146798
146691
  // ../plugin/src/features/magic-context/subagent-token-capture.ts
146799
- init_logger();
146800
146692
  function asNumber(value) {
146801
146693
  return typeof value === "number" && Number.isFinite(value) ? value : 0;
146802
146694
  }
@@ -146887,13 +146779,12 @@ function recordChildInvocation(input) {
146887
146779
  }
146888
146780
 
146889
146781
  // src/subagent-runner.ts
146890
- init_logger();
146891
146782
  function resolveBundledPiCli() {
146892
146783
  try {
146893
146784
  const require_ = createRequire2(import.meta.url);
146894
146785
  const pkgJson = require_.resolve("@earendil-works/pi-coding-agent/package.json");
146895
146786
  const cliPath = join8(dirname3(pkgJson), "dist/cli.js");
146896
- if (existsSync7(cliPath))
146787
+ if (existsSync6(cliPath))
146897
146788
  return cliPath;
146898
146789
  return null;
146899
146790
  } catch {
@@ -146904,7 +146795,7 @@ function resolveSubagentEntryPath() {
146904
146795
  try {
146905
146796
  const here = dirname3(fileURLToPath(import.meta.url));
146906
146797
  const candidate = resolvePath(here, "subagent-entry.js");
146907
- if (existsSync7(candidate))
146798
+ if (existsSync6(candidate))
146908
146799
  return candidate;
146909
146800
  return;
146910
146801
  } catch {
@@ -147660,18 +147551,10 @@ function clearStaleEntries(db, maxAgeMs, projectIdentity) {
147660
147551
  const result = projectIdentity ? db.prepare("DELETE FROM dream_queue WHERE project_path = ? AND started_at IS NOT NULL AND started_at < ?").run(projectIdentity, cutoff) : db.prepare("DELETE FROM dream_queue WHERE started_at IS NOT NULL AND started_at < ?").run(cutoff);
147661
147552
  return result.changes;
147662
147553
  }
147663
-
147664
- // src/commands/ctx-dream.ts
147665
- init_logger();
147666
147554
  // ../plugin/src/features/magic-context/dreamer/runner.ts
147667
- import { existsSync as existsSync9 } from "node:fs";
147555
+ import { existsSync as existsSync8 } from "node:fs";
147668
147556
  import { join as join11 } from "node:path";
147669
-
147670
- // ../plugin/src/shared/index.ts
147671
- init_logger();
147672
-
147673
147557
  // ../plugin/src/shared/model-suggestion-retry.ts
147674
- init_logger();
147675
147558
  function extractMessage(error) {
147676
147559
  if (typeof error === "string")
147677
147560
  return error;
@@ -147906,46 +147789,72 @@ function extractLatestAssistantText(messages) {
147906
147789
  `) || null;
147907
147790
  }
147908
147791
 
147909
- // ../plugin/src/features/magic-context/dreamer/runner.ts
147910
- init_data_path();
147911
- init_logger();
147912
- await init_sqlite();
147913
-
147914
147792
  // ../plugin/src/features/magic-context/key-files/identify-key-files.ts
147915
147793
  import { readFileSync as readFileSync6 } from "node:fs";
147916
- import { isAbsolute, join as join10, relative as relative2 } from "node:path";
147917
- init_logger();
147794
+ import { isAbsolute as isAbsolute2, join as join10, relative as relative2 } from "node:path";
147918
147795
 
147919
147796
  // ../plugin/src/features/magic-context/key-files/aft-availability.ts
147920
147797
  var import_comment_json = __toESM(require_src2(), 1);
147921
- import { existsSync as existsSync8, readFileSync as readFileSync5 } from "node:fs";
147922
- import { homedir as homedir3 } from "node:os";
147923
- import { join as join9 } from "node:path";
147798
+ import { existsSync as existsSync7, readFileSync as readFileSync5 } from "node:fs";
147799
+ import { homedir as homedir2 } from "node:os";
147800
+ import { isAbsolute, join as join9, resolve as resolve2 } from "node:path";
147801
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
147924
147802
  var overrideAvailability = null;
147925
147803
  function parseConfig(path7) {
147926
- if (!existsSync8(path7))
147804
+ if (!existsSync7(path7))
147927
147805
  return null;
147928
147806
  return import_comment_json.parse(readFileSync5(path7, "utf-8"));
147929
147807
  }
147930
- function entryMatchesAft(entry) {
147808
+ var AFT_NAME_NEEDLES = ["@cortexkit/aft", "aft-opencode", "aft-pi"];
147809
+ function stringMentionsAft(value) {
147810
+ return AFT_NAME_NEEDLES.some((needle) => value.includes(needle));
147811
+ }
147812
+ function resolveLocalEntryPackageName(value, configDir) {
147813
+ let dir = null;
147814
+ if (value.startsWith("file://")) {
147815
+ try {
147816
+ dir = fileURLToPath2(value);
147817
+ } catch {
147818
+ return null;
147819
+ }
147820
+ } else if (value.startsWith("~/")) {
147821
+ dir = join9(homedir2(), value.slice(2));
147822
+ } else if (value.startsWith("/") || value.startsWith("./") || value.startsWith("../")) {
147823
+ dir = isAbsolute(value) ? value : resolve2(configDir, value);
147824
+ } else {
147825
+ return null;
147826
+ }
147827
+ try {
147828
+ const pkg = JSON.parse(readFileSync5(join9(dir, "package.json"), "utf-8"));
147829
+ return typeof pkg.name === "string" ? pkg.name : null;
147830
+ } catch {
147831
+ return null;
147832
+ }
147833
+ }
147834
+ function entryMatchesAft(entry, configDir) {
147931
147835
  const value = Array.isArray(entry) ? entry[0] : entry;
147932
- return typeof value === "string" && (value.includes("@cortexkit/aft") || value.includes("aft-opencode") || value.includes("aft-pi"));
147836
+ if (typeof value !== "string")
147837
+ return false;
147838
+ if (stringMentionsAft(value))
147839
+ return true;
147840
+ const name2 = resolveLocalEntryPackageName(value, configDir);
147841
+ return name2 != null && stringMentionsAft(name2);
147933
147842
  }
147934
- function hasAftInArray(value) {
147935
- return Array.isArray(value) && value.some(entryMatchesAft);
147843
+ function hasAftInArray(value, configDir) {
147844
+ return Array.isArray(value) && value.some((entry) => entryMatchesAft(entry, configDir));
147936
147845
  }
147937
- function hasAftAtKeys(value, keys) {
147846
+ function hasAftAtKeys(value, keys, configDir) {
147938
147847
  if (!value || typeof value !== "object")
147939
147848
  return false;
147940
147849
  const record = value;
147941
147850
  for (const key of keys) {
147942
- if (hasAftInArray(record[key]))
147851
+ if (hasAftInArray(record[key], configDir))
147943
147852
  return true;
147944
147853
  }
147945
147854
  return false;
147946
147855
  }
147947
147856
  function getAftAvailability() {
147948
- const home = process.env.HOME || homedir3();
147857
+ const home = process.env.HOME || homedir2();
147949
147858
  const opencodePaths = [
147950
147859
  join9(home, ".config", "opencode", "opencode.jsonc"),
147951
147860
  join9(home, ".config", "opencode", "opencode.json")
@@ -147956,7 +147865,8 @@ function getAftAvailability() {
147956
147865
  for (const path7 of opencodePaths) {
147957
147866
  try {
147958
147867
  const config = parseConfig(path7);
147959
- if (hasAftAtKeys(config, ["plugin", "plugins", "mcp", "mcp_servers"])) {
147868
+ const configDir = join9(path7, "..");
147869
+ if (hasAftAtKeys(config, ["plugin", "plugins", "mcp", "mcp_servers"], configDir)) {
147960
147870
  opencode = true;
147961
147871
  break;
147962
147872
  }
@@ -147966,12 +147876,13 @@ function getAftAvailability() {
147966
147876
  for (const path7 of piPaths) {
147967
147877
  try {
147968
147878
  const config = parseConfig(path7);
147969
- if (hasAftAtKeys(config, ["packages", "extensions"])) {
147879
+ const configDir = join9(path7, "..");
147880
+ if (hasAftAtKeys(config, ["packages", "extensions"], configDir)) {
147970
147881
  pi = true;
147971
147882
  break;
147972
147883
  }
147973
147884
  const agent = config?.agent;
147974
- if (hasAftAtKeys(agent, ["packages", "extensions"])) {
147885
+ if (hasAftAtKeys(agent, ["packages", "extensions"], configDir)) {
147975
147886
  pi = true;
147976
147887
  break;
147977
147888
  }
@@ -147991,7 +147902,7 @@ function isAftAvailable() {
147991
147902
 
147992
147903
  // ../plugin/src/features/magic-context/key-files/read-history.ts
147993
147904
  import { realpathSync as realpathSync3 } from "node:fs";
147994
- import { relative, resolve as resolve2 } from "node:path";
147905
+ import { relative, resolve as resolve3 } from "node:path";
147995
147906
  function toMs(value) {
147996
147907
  if (typeof value === "number" && Number.isFinite(value))
147997
147908
  return value;
@@ -148028,7 +147939,7 @@ function coalesceRanges(ranges) {
148028
147939
  }
148029
147940
  function normalizeProjectRelativePath(projectPath, filePath) {
148030
147941
  const root = realpathSync3(projectPath);
148031
- const abs = filePath.startsWith("/") ? resolve2(filePath) : resolve2(root, filePath);
147942
+ const abs = filePath.startsWith("/") ? resolve3(filePath) : resolve3(root, filePath);
148032
147943
  let real = abs;
148033
147944
  try {
148034
147945
  real = realpathSync3(abs);
@@ -148171,9 +148082,6 @@ function collectKeyFileCandidates(args) {
148171
148082
  })).sort((a, b) => b.totalReads - a.totalReads || b.lastReadAt - a.lastReadAt).slice(0, 200);
148172
148083
  }
148173
148084
 
148174
- // ../plugin/src/features/magic-context/key-files/storage-key-files.ts
148175
- init_logger();
148176
-
148177
148085
  // ../plugin/src/features/magic-context/key-files/identify-key-files.ts
148178
148086
  var KEY_FILES_SYSTEM_PROMPT = "You are a file importance evaluator. Given read statistics about files in a coding session, identify which are core orientation files worth pinning in context. Return a JSON array.";
148179
148087
  class KeyFilesValidationError extends Error {
@@ -148393,11 +148301,13 @@ async function runKeyFilesLlm(args) {
148393
148301
  const text = extractLatestAssistantText(messages);
148394
148302
  if (!text)
148395
148303
  throw new Error("Dreamer returned no key-files output.");
148396
- return text;
148304
+ return { text, messages };
148397
148305
  } finally {
148398
- await args.client.session.delete({ path: { id: agentSessionId } }).catch(() => {
148399
- return;
148400
- });
148306
+ if (!shouldKeepSubagents()) {
148307
+ await args.client.session.delete({ path: { id: agentSessionId } }).catch(() => {
148308
+ return;
148309
+ });
148310
+ }
148401
148311
  }
148402
148312
  }
148403
148313
  async function runKeyFilesTask(args) {
@@ -148443,9 +148353,27 @@ async function runKeyFilesTask(args) {
148443
148353
  log(`[key-files] lease renewal threw: ${getErrorMessage(error)}`);
148444
148354
  }
148445
148355
  }, 60000);
148356
+ let invocationRecorded = false;
148357
+ const llmStartedAt = Date.now();
148358
+ const recordKeyFilesInvocation = (params) => {
148359
+ if (!args.parentSessionId || invocationRecorded)
148360
+ return;
148361
+ invocationRecorded = true;
148362
+ recordChildInvocation({
148363
+ db: args.db,
148364
+ parentSessionId: args.parentSessionId,
148365
+ harness: getHarness(),
148366
+ subagent: "dreamer",
148367
+ task: "key files",
148368
+ startedAt: llmStartedAt,
148369
+ status: params.status,
148370
+ messages: params.messages,
148371
+ error: params.error
148372
+ });
148373
+ };
148446
148374
  try {
148447
148375
  try {
148448
- const raw = await runKeyFilesLlm({
148376
+ const { text: raw, messages: llmMessages } = await runKeyFilesLlm({
148449
148377
  client: args.client,
148450
148378
  parentSessionId: args.parentSessionId,
148451
148379
  projectPath,
@@ -148453,8 +148381,10 @@ async function runKeyFilesTask(args) {
148453
148381
  deadline: args.deadline,
148454
148382
  fallbackModels: args.fallbackModels
148455
148383
  });
148384
+ recordKeyFilesInvocation({ status: "completed", messages: llmMessages });
148456
148385
  validated = validateLlmOutput(raw, args.config, projectPath, new Set(candidates.map((candidate) => candidate.path)));
148457
148386
  } catch (error) {
148387
+ recordKeyFilesInvocation({ status: "failed", error });
148458
148388
  log(`[key-files] LLM validation failed: ${getErrorMessage(error)}`);
148459
148389
  throw error;
148460
148390
  }
@@ -148589,13 +148519,13 @@ function invalidateMemory(projectPath, memoryId) {
148589
148519
  }
148590
148520
 
148591
148521
  // ../plugin/src/features/magic-context/memory/normalize-hash.ts
148592
- import { createHash as createHash7 } from "node:crypto";
148522
+ import { createHash as createHash6 } from "node:crypto";
148593
148523
  function normalizeMemoryContent(content) {
148594
148524
  return content.toLowerCase().replace(/\s+/g, " ").trim();
148595
148525
  }
148596
148526
  function computeNormalizedHash(content) {
148597
148527
  const normalized = normalizeMemoryContent(content);
148598
- return createHash7("md5").update(normalized).digest("hex");
148528
+ return createHash6("md5").update(normalized).digest("hex");
148599
148529
  }
148600
148530
 
148601
148531
  // ../plugin/src/features/magic-context/memory/storage-memory.ts
@@ -149048,9 +148978,6 @@ function getMemoryCountsByStatus(db, projectPath) {
149048
148978
  return counts;
149049
148979
  }
149050
148980
 
149051
- // ../plugin/src/features/magic-context/user-memory/review-user-memories.ts
149052
- init_logger();
149053
-
149054
148981
  // ../plugin/src/features/magic-context/dreamer/task-prompts.ts
149055
148982
  var DREAMER_SYSTEM_PROMPT = `You are a memory maintenance agent for the magic-context system.
149056
148983
  You run during scheduled dream windows to maintain a project's cross-session memory store and codebase documentation.
@@ -149553,7 +149480,8 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
149553
149480
  db: args.db,
149554
149481
  parentSessionId: args.parentSessionId,
149555
149482
  harness: "opencode",
149556
- subagent: "user_memory_review",
149483
+ subagent: "dreamer",
149484
+ task: "user memories",
149557
149485
  startedAt,
149558
149486
  status: params.status,
149559
149487
  messages: params.messages,
@@ -149677,7 +149605,7 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
149677
149605
  return result;
149678
149606
  } finally {
149679
149607
  clearInterval(leaseInterval);
149680
- if (agentSessionId) {
149608
+ if (agentSessionId && !shouldKeepSubagents()) {
149681
149609
  await args.client.session.delete({
149682
149610
  path: { id: agentSessionId },
149683
149611
  query: { directory: args.sessionDirectory }
@@ -149746,7 +149674,7 @@ function getOpenCodeDbPath2() {
149746
149674
  }
149747
149675
  function openOpenCodeDb() {
149748
149676
  const dbPath = getOpenCodeDbPath2();
149749
- if (!existsSync9(dbPath)) {
149677
+ if (!existsSync8(dbPath)) {
149750
149678
  log(`[key-files] OpenCode DB not found at ${dbPath} — skipping`);
149751
149679
  return null;
149752
149680
  }
@@ -149896,8 +149824,8 @@ async function runDream(args) {
149896
149824
  try {
149897
149825
  const docsDir = args.sessionDirectory ?? args.projectIdentity;
149898
149826
  const existingDocs = taskName === "maintain-docs" ? {
149899
- architecture: existsSync9(join11(docsDir, "ARCHITECTURE.md")),
149900
- structure: existsSync9(join11(docsDir, "STRUCTURE.md"))
149827
+ architecture: existsSync8(join11(docsDir, "ARCHITECTURE.md")),
149828
+ structure: existsSync8(join11(docsDir, "STRUCTURE.md"))
149901
149829
  } : undefined;
149902
149830
  const userMemories = taskName === "archive-stale" ? getActiveUserMemories(args.db).map((um) => ({
149903
149831
  id: um.id,
@@ -150001,14 +149929,14 @@ async function runDream(args) {
150001
149929
  }
150002
149930
  } finally {
150003
149931
  clearInterval(leaseRenewalInterval);
150004
- if (agentSessionId && !taskFailed) {
149932
+ if (agentSessionId && !taskFailed && !shouldKeepSubagents()) {
150005
149933
  await args.client.session.delete({
150006
149934
  path: { id: agentSessionId }
150007
149935
  }).catch((error) => {
150008
149936
  log("[dreamer] failed to delete child session:", error);
150009
149937
  });
150010
- } else if (agentSessionId && taskFailed) {
150011
- log(`[dreamer] KEEPING failed child session ${agentSessionId} for task ${taskName} (debugging)`);
149938
+ } else if (agentSessionId && (taskFailed || shouldKeepSubagents())) {
149939
+ log(`[dreamer] KEEPING child session ${agentSessionId} for task ${taskName} (${taskFailed ? "failed" : "keep_subagents"})`);
150012
149940
  }
150013
149941
  }
150014
149942
  if (lostLease) {
@@ -150293,7 +150221,7 @@ Only include notes whose conditions you could definitively evaluate against exte
150293
150221
  parts: [{ type: "text", text: evaluationPrompt, synthetic: true }]
150294
150222
  }
150295
150223
  }, {
150296
- timeoutMs: Math.min(remainingMs, 300000),
150224
+ timeoutMs: Math.min(remainingMs, 5 * 60 * 1000),
150297
150225
  signal: abortController.signal,
150298
150226
  fallbackModels: args.fallbackModels,
150299
150227
  callContext: "dreamer:smart-notes"
@@ -150369,7 +150297,7 @@ Only include notes whose conditions you could definitively evaluate against exte
150369
150297
  });
150370
150298
  } finally {
150371
150299
  clearInterval(leaseInterval);
150372
- if (agentSessionId) {
150300
+ if (agentSessionId && !shouldKeepSubagents()) {
150373
150301
  await args.client.session.delete({
150374
150302
  path: { id: agentSessionId }
150375
150303
  }).catch(() => {});
@@ -150380,14 +150308,14 @@ var MAX_LEASE_RETRIES = 3;
150380
150308
  async function processDreamQueue(args) {
150381
150309
  const maxRuntimeMs = args.maxRuntimeMinutes * 60 * 1000;
150382
150310
  if (!hasActiveDreamLease(args.db)) {
150383
- clearStaleEntries(args.db, maxRuntimeMs + 1800000, args.projectIdentity);
150311
+ clearStaleEntries(args.db, maxRuntimeMs + 30 * 60 * 1000, args.projectIdentity);
150384
150312
  }
150385
150313
  const entry = dequeueNext(args.db, args.projectIdentity);
150386
150314
  if (!entry) {
150387
150315
  return null;
150388
150316
  }
150389
150317
  const projectDirectory = args.sessionDirectoryOverride ?? resolveDreamSessionDirectory(entry.projectIdentity);
150390
- log(`[dreamer] dequeued project ${entry.projectIdentity} (dir=${projectDirectory}), starting dream run`);
150318
+ log(`[dreamer] dequeued project ${entry.projectIdentity}, starting dream run`);
150391
150319
  let result;
150392
150320
  try {
150393
150321
  result = await runDream({
@@ -150423,7 +150351,6 @@ async function processDreamQueue(args) {
150423
150351
  return result;
150424
150352
  }
150425
150353
  // ../plugin/src/features/magic-context/dreamer/scheduler.ts
150426
- init_logger();
150427
150354
  function parseScheduleWindow(schedule) {
150428
150355
  const match = /^(\d{1,2}):(\d{2})-(\d{1,2}):(\d{2})$/.exec(schedule.trim());
150429
150356
  if (!match)
@@ -150498,7 +150425,6 @@ function checkScheduleAndEnqueue(db, schedule, ownProjectIdentity) {
150498
150425
  return enqueued;
150499
150426
  }
150500
150427
  // ../plugin/src/features/magic-context/git-commits/git-log-reader.ts
150501
- init_logger();
150502
150428
  import { execFile } from "node:child_process";
150503
150429
  import { promisify } from "node:util";
150504
150430
  var execFileAsync = promisify(execFile);
@@ -150511,6 +150437,7 @@ async function readGitCommits(directory, options = {}) {
150511
150437
  if (revision.startsWith("-")) {
150512
150438
  throw new Error(`readGitCommits: refusing revision that looks like an option: "${revision}"`);
150513
150439
  }
150440
+ const projectLabel = options.projectIdentity ?? "<project>";
150514
150441
  const args = [
150515
150442
  "log",
150516
150443
  revision,
@@ -150533,11 +150460,11 @@ async function readGitCommits(directory, options = {}) {
150533
150460
  stdout = result.stdout;
150534
150461
  } catch (error) {
150535
150462
  const message = error instanceof Error ? error.message : String(error);
150536
- log(`[git-commits] readGitCommits failed at cwd=${directory}: ${message.slice(0, 500)}`);
150463
+ log(`[git-commits] readGitCommits failed for ${projectLabel}: ${message.slice(0, 500)}`);
150537
150464
  return [];
150538
150465
  }
150539
150466
  if (stdout.trim().length === 0) {
150540
- log(`[git-commits] readGitCommits returned empty stdout at cwd=${directory} (sinceMs=${options.sinceMs ?? "none"} args=${args.slice(0, 4).join(" ")})`);
150467
+ log(`[git-commits] readGitCommits returned empty stdout for ${projectLabel} (sinceMs=${options.sinceMs ?? "none"} args=${args.slice(0, 4).join(" ")})`);
150541
150468
  }
150542
150469
  return parseGitLogOutput(stdout);
150543
150470
  }
@@ -150581,9 +150508,6 @@ ${body}` : subject;
150581
150508
  }
150582
150509
  return commits;
150583
150510
  }
150584
- // ../plugin/src/features/magic-context/git-commits/indexer.ts
150585
- init_logger();
150586
-
150587
150511
  // ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
150588
150512
  var exports_external = {};
150589
150513
  __export(exports_external, {
@@ -165023,6 +164947,7 @@ var MagicContextConfigSchema = exports_external.object({
165023
164947
  model: DEFAULT_LOCAL_EMBEDDING_MODEL
165024
164948
  }).describe("Embedding provider configuration"),
165025
164949
  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).'),
164950
+ 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."),
165026
164951
  caveman_text_compression: exports_external.object({
165027
164952
  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%)."),
165028
164953
  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.")
@@ -165062,9 +164987,6 @@ var MagicContextConfigSchema = exports_external.object({
165062
164987
  };
165063
164988
  });
165064
164989
 
165065
- // ../plugin/src/features/magic-context/memory/embedding.ts
165066
- init_logger();
165067
-
165068
164990
  // ../plugin/src/features/magic-context/memory/cosine-similarity.ts
165069
164991
  function cosineSimilarity(a, b) {
165070
164992
  if (a.length !== b.length) {
@@ -165106,12 +165028,10 @@ function getEmbeddingProviderIdentity(config2) {
165106
165028
  }
165107
165029
 
165108
165030
  // ../plugin/src/features/magic-context/memory/embedding-local.ts
165109
- import { mkdirSync as mkdirSync4 } from "node:fs";
165031
+ import { mkdirSync as mkdirSync5 } from "node:fs";
165110
165032
  import { open, stat, unlink, writeFile } from "node:fs/promises";
165111
165033
  import { dirname as dirname4, join as join12 } from "node:path";
165112
165034
  import { pathToFileURL } from "node:url";
165113
- init_data_path();
165114
- init_logger();
165115
165035
  var LOCK_POLL_MS = 150;
165116
165036
  var STALE_LOCK_MS = 3 * 60000;
165117
165037
  var MAX_LOCK_WAIT_MS = 5 * 60000;
@@ -165150,7 +165070,7 @@ async function acquireModelLoadLock(lockPath) {
165150
165070
  if (Date.now() - waitStart > MAX_LOCK_WAIT_MS) {
165151
165071
  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.`);
165152
165072
  }
165153
- await new Promise((resolve3) => setTimeout(resolve3, LOCK_POLL_MS));
165073
+ await new Promise((resolve4) => setTimeout(resolve4, LOCK_POLL_MS));
165154
165074
  }
165155
165075
  }
165156
165076
  }
@@ -165287,7 +165207,7 @@ class LocalEmbeddingProvider {
165287
165207
  }
165288
165208
  const modelCacheDir = join12(getMagicContextStorageDir(), "models");
165289
165209
  try {
165290
- mkdirSync4(modelCacheDir, { recursive: true });
165210
+ mkdirSync5(modelCacheDir, { recursive: true });
165291
165211
  env.cacheDir = modelCacheDir;
165292
165212
  } catch {
165293
165213
  log("[magic-context] could not create model cache dir, using library default");
@@ -165319,7 +165239,7 @@ class LocalEmbeddingProvider {
165319
165239
  }
165320
165240
  const delayMs = 300 * attempt + Math.floor(Math.random() * 200);
165321
165241
  log(`[magic-context] embedding model load attempt ${attempt}/${MAX_ATTEMPTS} failed transiently, retrying in ${delayMs}ms`);
165322
- await new Promise((resolve3) => setTimeout(resolve3, delayMs));
165242
+ await new Promise((resolve4) => setTimeout(resolve4, delayMs));
165323
165243
  }
165324
165244
  }
165325
165245
  if (this.pipeline) {
@@ -165347,8 +165267,8 @@ class LocalEmbeddingProvider {
165347
165267
  if (this.inFlight === 0) {
165348
165268
  return Promise.resolve();
165349
165269
  }
165350
- return new Promise((resolve3) => {
165351
- this.inFlightWaiters.push(resolve3);
165270
+ return new Promise((resolve4) => {
165271
+ this.inFlightWaiters.push(resolve4);
165352
165272
  });
165353
165273
  }
165354
165274
  finishInFlight() {
@@ -165447,7 +165367,6 @@ class LocalEmbeddingProvider {
165447
165367
  }
165448
165368
 
165449
165369
  // ../plugin/src/features/magic-context/memory/embedding-openai.ts
165450
- init_logger();
165451
165370
  function normalizeEndpoint2(endpoint) {
165452
165371
  return endpoint?.trim().replace(/\/+$/, "") ?? "";
165453
165372
  }
@@ -165662,8 +165581,7 @@ class OpenAICompatibleEmbeddingProvider {
165662
165581
  }
165663
165582
 
165664
165583
  // ../plugin/src/features/magic-context/project-embedding-registry.ts
165665
- import { createHash as createHash8 } from "node:crypto";
165666
- init_logger();
165584
+ import { createHash as createHash7, randomUUID } from "node:crypto";
165667
165585
 
165668
165586
  // ../plugin/src/features/magic-context/git-commits/storage-git-commit-embeddings.ts
165669
165587
  var saveStatements = new WeakMap;
@@ -165766,6 +165684,125 @@ function getDistinctCommitEmbeddingModelIds(db, projectPath) {
165766
165684
  return new Set(rows.map((row) => typeof row.modelId === "string" ? row.modelId : null));
165767
165685
  }
165768
165686
 
165687
+ // ../plugin/src/features/magic-context/git-commits/sweep-coordinator.ts
165688
+ var GIT_SWEEP_COOLDOWN_MS = 10 * 60 * 1000;
165689
+ var GIT_SWEEP_LEASE_TTL_MS = 5 * 60 * 1000;
165690
+ var GIT_SWEEP_LEASE_RENEWAL_MS = 60 * 1000;
165691
+ function runImmediate2(db, body) {
165692
+ db.exec("BEGIN IMMEDIATE");
165693
+ let committed = false;
165694
+ try {
165695
+ const result = body();
165696
+ db.exec("COMMIT");
165697
+ committed = true;
165698
+ return result;
165699
+ } finally {
165700
+ if (!committed) {
165701
+ try {
165702
+ db.exec("ROLLBACK");
165703
+ } catch {}
165704
+ }
165705
+ }
165706
+ }
165707
+ function rowToState(row) {
165708
+ return {
165709
+ projectPath: row.project_path,
165710
+ leaseHolder: row.lease_holder,
165711
+ leaseExpiresAt: row.lease_expires_at,
165712
+ lastSweptAt: row.last_swept_at
165713
+ };
165714
+ }
165715
+ function getGitSweepCoordinatorState(db, projectPath) {
165716
+ const row = db.prepare(`SELECT project_path, lease_holder, lease_expires_at, last_swept_at
165717
+ FROM git_sweep_coordinator
165718
+ WHERE project_path = ?`).get(projectPath);
165719
+ return row ? rowToState(row) : null;
165720
+ }
165721
+ function acquireGitSweepLease(db, projectPath, holderId, options = {}) {
165722
+ const cooldownMs = options.cooldownMs ?? GIT_SWEEP_COOLDOWN_MS;
165723
+ const leaseTtlMs = options.leaseTtlMs ?? GIT_SWEEP_LEASE_TTL_MS;
165724
+ return runImmediate2(db, () => {
165725
+ const now = Date.now();
165726
+ const row = getGitSweepCoordinatorState(db, projectPath);
165727
+ if (row?.leaseHolder && row.leaseExpiresAt !== null && row.leaseExpiresAt > now) {
165728
+ return {
165729
+ acquired: false,
165730
+ projectPath,
165731
+ reason: "lease_active",
165732
+ leaseHolder: row.leaseHolder,
165733
+ leaseExpiresAt: row.leaseExpiresAt,
165734
+ lastSweptAt: row.lastSweptAt,
165735
+ nextAllowedAt: null
165736
+ };
165737
+ }
165738
+ if (!options.ignoreCooldown && row?.lastSweptAt !== null && row?.lastSweptAt !== undefined) {
165739
+ const nextAllowedAt = row.lastSweptAt + cooldownMs;
165740
+ if (nextAllowedAt > now) {
165741
+ return {
165742
+ acquired: false,
165743
+ projectPath,
165744
+ reason: "cooldown_active",
165745
+ leaseHolder: row.leaseHolder,
165746
+ leaseExpiresAt: row.leaseExpiresAt,
165747
+ lastSweptAt: row.lastSweptAt,
165748
+ nextAllowedAt
165749
+ };
165750
+ }
165751
+ }
165752
+ const leaseExpiresAt = now + leaseTtlMs;
165753
+ db.prepare(`INSERT INTO git_sweep_coordinator (
165754
+ project_path,
165755
+ lease_holder,
165756
+ lease_expires_at,
165757
+ last_swept_at
165758
+ ) VALUES (?, ?, ?, NULL)
165759
+ ON CONFLICT(project_path) DO UPDATE SET
165760
+ lease_holder = excluded.lease_holder,
165761
+ lease_expires_at = excluded.lease_expires_at`).run(projectPath, holderId, leaseExpiresAt);
165762
+ return {
165763
+ acquired: true,
165764
+ projectPath,
165765
+ holderId,
165766
+ acquiredAt: now,
165767
+ leaseExpiresAt
165768
+ };
165769
+ });
165770
+ }
165771
+ function renewGitSweepLease(db, projectPath, holderId, leaseTtlMs = GIT_SWEEP_LEASE_TTL_MS) {
165772
+ return runImmediate2(db, () => {
165773
+ const now = Date.now();
165774
+ const leaseExpiresAt = now + leaseTtlMs;
165775
+ const result = db.prepare(`UPDATE git_sweep_coordinator
165776
+ SET lease_expires_at = ?
165777
+ WHERE project_path = ?
165778
+ AND lease_holder = ?
165779
+ AND lease_expires_at > ?`).run(leaseExpiresAt, projectPath, holderId, now);
165780
+ return result.changes === 1;
165781
+ });
165782
+ }
165783
+ function markGitSweepSuccessAndRelease(db, projectPath, holderId) {
165784
+ return runImmediate2(db, () => {
165785
+ const now = Date.now();
165786
+ const result = db.prepare(`UPDATE git_sweep_coordinator
165787
+ SET lease_holder = NULL,
165788
+ lease_expires_at = NULL,
165789
+ last_swept_at = ?
165790
+ WHERE project_path = ?
165791
+ AND lease_holder = ?
165792
+ AND lease_expires_at > ?`).run(now, projectPath, holderId, now);
165793
+ return result.changes === 1;
165794
+ });
165795
+ }
165796
+ function releaseGitSweepLease(db, projectPath, holderId) {
165797
+ runImmediate2(db, () => {
165798
+ db.prepare(`UPDATE git_sweep_coordinator
165799
+ SET lease_holder = NULL,
165800
+ lease_expires_at = NULL
165801
+ WHERE project_path = ?
165802
+ AND lease_holder = ?`).run(projectPath, holderId);
165803
+ });
165804
+ }
165805
+
165769
165806
  // ../plugin/src/features/magic-context/project-embedding-registry.ts
165770
165807
  var OFF_PROVIDER_IDENTITY = "embedding-provider:off";
165771
165808
  var SWEEP_MAX_WALL_CLOCK_MS = 10 * 60 * 1000;
@@ -165818,7 +165855,7 @@ function stableStringify2(value) {
165818
165855
  return JSON.stringify(value);
165819
165856
  }
165820
165857
  function sha256Prefix(value, length = 16) {
165821
- return createHash8("sha256").update(value).digest("hex").slice(0, length);
165858
+ return createHash7("sha256").update(value).digest("hex").slice(0, length);
165822
165859
  }
165823
165860
  function getRuntimeFingerprint(config2) {
165824
165861
  if (config2.provider === "off") {
@@ -166078,11 +166115,11 @@ async function embedText(text, signal) {
166078
166115
  var SWEEP_MAX_WALL_CLOCK_MS2 = 10 * 60 * 1000;
166079
166116
 
166080
166117
  // ../plugin/src/features/magic-context/git-commits/storage-git-commits.ts
166081
- init_logger();
166082
166118
  var insertStatements = new WeakMap;
166083
166119
  var existingShasStatements = new WeakMap;
166084
166120
  var projectCountStatements = new WeakMap;
166085
166121
  var evictStatements = new WeakMap;
166122
+ var evictOverflowStatements = new WeakMap;
166086
166123
  var latestCommitTimeStatements = new WeakMap;
166087
166124
  function getInsertStatement(db) {
166088
166125
  let stmt = insertStatements.get(db);
@@ -166125,17 +166162,17 @@ function getLatestCommitTimeStatement(db) {
166125
166162
  }
166126
166163
  return stmt;
166127
166164
  }
166128
- function getEvictStatement(db) {
166129
- let stmt = evictStatements.get(db);
166165
+ function getEvictOverflowStatement(db) {
166166
+ let stmt = evictOverflowStatements.get(db);
166130
166167
  if (!stmt) {
166131
166168
  stmt = db.prepare(`DELETE FROM git_commits
166132
- WHERE sha IN (
166133
- SELECT sha FROM git_commits
166169
+ WHERE rowid IN (
166170
+ SELECT rowid FROM git_commits
166134
166171
  WHERE project_path = ?
166135
- ORDER BY committed_at ASC
166136
- LIMIT ?
166172
+ ORDER BY committed_at DESC, sha DESC
166173
+ LIMIT -1 OFFSET ?
166137
166174
  )`);
166138
- evictStatements.set(db, stmt);
166175
+ evictOverflowStatements.set(db, stmt);
166139
166176
  }
166140
166177
  return stmt;
166141
166178
  }
@@ -166173,22 +166210,15 @@ function getLatestIndexedCommitTimeMs(db, projectPath) {
166173
166210
  const row = getLatestCommitTimeStatement(db).get(projectPath);
166174
166211
  return row?.latest ?? null;
166175
166212
  }
166176
- function evictOldestCommits(db, projectPath, excess) {
166177
- if (excess <= 0)
166178
- return 0;
166179
- const before = getCommitCount(db, projectPath);
166180
- getEvictStatement(db).run(projectPath, excess);
166181
- const after = getCommitCount(db, projectPath);
166182
- return Math.max(0, before - after);
166183
- }
166184
166213
  function enforceProjectCap(db, projectPath, maxCommits) {
166185
166214
  if (maxCommits <= 0)
166186
166215
  return 0;
166187
166216
  const count = getCommitCount(db, projectPath);
166188
166217
  if (count <= maxCommits)
166189
166218
  return 0;
166190
- const excess = count - maxCommits;
166191
- const evicted = evictOldestCommits(db, projectPath, excess);
166219
+ getEvictOverflowStatement(db).run(projectPath, maxCommits);
166220
+ const after = getCommitCount(db, projectPath);
166221
+ const evicted = Math.max(0, count - after);
166192
166222
  if (evicted > 0) {
166193
166223
  log(`[git-commits] evicted ${evicted} oldest commits for project ${projectPath} (cap=${maxCommits}, was=${count})`);
166194
166224
  }
@@ -166220,7 +166250,8 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
166220
166250
  const sinceMs = latestIndexed !== null ? Math.max(latestIndexed - 60000, Date.now() - options.sinceDays * MS_PER_DAY) : Date.now() - options.sinceDays * MS_PER_DAY;
166221
166251
  const commits = await readGitCommits(directory, {
166222
166252
  sinceMs,
166223
- maxCommits: options.maxCommits
166253
+ maxCommits: options.maxCommits,
166254
+ projectIdentity: projectPath
166224
166255
  });
166225
166256
  result.scanned = commits.length;
166226
166257
  if (commits.length === 0) {
@@ -166295,9 +166326,6 @@ async function embedUnembeddedCommits(db, projectPath) {
166295
166326
  embedInProgress.delete(projectPath);
166296
166327
  }
166297
166328
  }
166298
- // ../plugin/src/features/magic-context/git-commits/search-git-commits.ts
166299
- init_logger();
166300
-
166301
166329
  // ../plugin/src/features/magic-context/memory/storage-memory-fts.ts
166302
166330
  var DEFAULT_SEARCH_LIMIT = 10;
166303
166331
  var searchStatements = new WeakMap;
@@ -166460,7 +166488,6 @@ function searchGitCommitsSync(db, projectPath, query, options) {
166460
166488
  return results.slice(0, options.limit);
166461
166489
  }
166462
166490
  // ../plugin/src/plugin/dream-timer.ts
166463
- init_logger();
166464
166491
  var DREAM_TIMER_INTERVAL_MS = 15 * 60 * 1000;
166465
166492
  var activeTimer = null;
166466
166493
  function openTimerDatabaseOrNull(context) {
@@ -166487,7 +166514,7 @@ async function startDreamScheduleTimer(args) {
166487
166514
  const isNewRegistration = !registeredProjects.has(args.directory);
166488
166515
  registeredProjects.set(args.directory, args);
166489
166516
  if (isNewRegistration) {
166490
- log(`[dreamer] registered project ${args.directory} (dreaming=${dreamingEnabled} embeddings=${embeddingSweepEnabled} commits=${commitIndexingEnabled}; total=${registeredProjects.size})`);
166517
+ log(`[dreamer] registered project ${args.projectIdentity} (dreaming=${dreamingEnabled} embeddings=${embeddingSweepEnabled} commits=${commitIndexingEnabled}; total=${registeredProjects.size})`);
166491
166518
  }
166492
166519
  if (!activeTimer) {
166493
166520
  log(`[dreamer] started independent schedule timer (every ${DREAM_TIMER_INTERVAL_MS / 60000}m)`);
@@ -166502,7 +166529,7 @@ async function startDreamScheduleTimer(args) {
166502
166529
  }
166503
166530
  return () => {
166504
166531
  registeredProjects.delete(args.directory);
166505
- log(`[dreamer] unregistered project ${args.directory} (remaining=${registeredProjects.size})`);
166532
+ log(`[dreamer] unregistered project ${args.projectIdentity} (remaining=${registeredProjects.size})`);
166506
166533
  if (registeredProjects.size === 0 && activeTimer) {
166507
166534
  clearInterval(activeTimer);
166508
166535
  activeTimer = null;
@@ -166550,7 +166577,7 @@ async function sweepProject(reg, origin, db, gitCommitEnabled = getProjectEmbedd
166550
166577
  return;
166551
166578
  }
166552
166579
  try {
166553
- log(`[dreamer] timer tick (${origin}) ${reg.directory} — checking schedule window "${reg.dreamerConfig.schedule}"`);
166580
+ log(`[dreamer] timer tick (${origin}) ${reg.projectIdentity} — checking schedule window "${reg.dreamerConfig.schedule}"`);
166554
166581
  checkScheduleAndEnqueue(db, reg.dreamerConfig.schedule, reg.projectIdentity);
166555
166582
  await processDreamQueue({
166556
166583
  db,
@@ -166565,13 +166592,34 @@ async function sweepProject(reg, origin, db, gitCommitEnabled = getProjectEmbedd
166565
166592
  fallbackModels: resolveFallbackChain(DREAMER_AGENT, reg.dreamerConfig.fallback_models)
166566
166593
  });
166567
166594
  } catch (error51) {
166568
- log(`[dreamer] timer-triggered queue processing failed for ${reg.directory}:`, error51);
166595
+ log(`[dreamer] timer-triggered queue processing failed for ${reg.projectIdentity}:`, error51);
166569
166596
  }
166570
166597
  }
166598
+ function startGitSweepLeaseRenewal(db, projectIdentity, holderId) {
166599
+ const timer = setInterval(() => {
166600
+ try {
166601
+ if (!renewGitSweepLease(db, projectIdentity, holderId)) {
166602
+ log(`[git-commits] sweep lease renewal failed for ${projectIdentity}`);
166603
+ }
166604
+ } catch (error51) {
166605
+ log(`[git-commits] sweep lease renewal errored for ${projectIdentity}: ${error51 instanceof Error ? error51.message : String(error51)}`);
166606
+ }
166607
+ }, GIT_SWEEP_LEASE_RENEWAL_MS);
166608
+ timer.unref?.();
166609
+ return () => clearInterval(timer);
166610
+ }
166571
166611
  async function sweepGitCommits(args) {
166572
166612
  const { directory, projectIdentity, db, gitCommitIndexing } = args;
166613
+ const holderId = crypto.randomUUID();
166614
+ const lease2 = acquireGitSweepLease(db, projectIdentity, holderId);
166615
+ if (!lease2.acquired) {
166616
+ const reason = lease2.reason === "cooldown_active" ? `cooldown active until ${lease2.nextAllowedAt}` : `lease held by ${lease2.leaseHolder ?? "another holder"} until ${lease2.leaseExpiresAt ?? "unknown"}`;
166617
+ log(`[git-commits] sweep skipped for ${projectIdentity}: ${reason}`);
166618
+ return;
166619
+ }
166573
166620
  const startedAt = Date.now();
166574
- log(`[git-commits] sweep starting for ${directory} (sinceDays=${gitCommitIndexing.since_days} maxCommits=${gitCommitIndexing.max_commits})`);
166621
+ const stopRenewal = startGitSweepLeaseRenewal(db, projectIdentity, holderId);
166622
+ log(`[git-commits] sweep starting for ${projectIdentity} (sinceDays=${gitCommitIndexing.since_days} maxCommits=${gitCommitIndexing.max_commits})`);
166575
166623
  try {
166576
166624
  const result = await indexCommitsForProject(db, projectIdentity, directory, {
166577
166625
  sinceDays: gitCommitIndexing.since_days,
@@ -166581,17 +166629,24 @@ async function sweepGitCommits(args) {
166581
166629
  if (result.embedded > 0) {
166582
166630
  drainedEmbeddings = await embedUnembeddedCommits(db, projectIdentity);
166583
166631
  }
166632
+ const cooldownMarked = markGitSweepSuccessAndRelease(db, projectIdentity, holderId);
166633
+ if (!cooldownMarked) {
166634
+ releaseGitSweepLease(db, projectIdentity, holderId);
166635
+ log(`[git-commits] sweep finished for ${projectIdentity}, but lease was no longer active; cooldown not advanced`);
166636
+ }
166584
166637
  const elapsedMs = Date.now() - startedAt;
166585
166638
  log(`[git-commits] sweep finished for ${projectIdentity} in ${elapsedMs}ms: scanned=${result.scanned} inserted=${result.inserted} updated=${result.updated} evicted=${result.evicted} embedded=${result.embedded} drained=${drainedEmbeddings}`);
166586
166639
  } catch (error51) {
166640
+ releaseGitSweepLease(db, projectIdentity, holderId);
166587
166641
  const elapsedMs = Date.now() - startedAt;
166588
- log(`[git-commits] sweep failed for ${directory} after ${elapsedMs}ms: ${error51 instanceof Error ? error51.message : String(error51)}`);
166642
+ log(`[git-commits] sweep failed for ${projectIdentity} after ${elapsedMs}ms: ${error51 instanceof Error ? error51.message : String(error51)}`);
166643
+ } finally {
166644
+ stopRenewal();
166589
166645
  }
166590
166646
  }
166591
166647
 
166592
166648
  // ../plugin/src/plugin/embedding-bootstrap-helpers.ts
166593
- import { createHash as createHash9 } from "node:crypto";
166594
- init_logger();
166649
+ import { createHash as createHash8 } from "node:crypto";
166595
166650
  var EMBEDDING_AFFECTING_KEYS = new Set([
166596
166651
  "embedding.api_key",
166597
166652
  "embedding.endpoint",
@@ -166602,7 +166657,7 @@ var EMBEDDING_AFFECTING_TOP_LEVEL_KEYS = new Set(["embedding", "memory", "experi
166602
166657
  var EMBEDDING_WARNING_TERMS = ["api_key", "endpoint", "model", "provider", "embedding"];
166603
166658
  var loggedFailureSignatures = new Map;
166604
166659
  function sha256Prefix2(value, length = 16) {
166605
- return createHash9("sha256").update(value).digest("hex").slice(0, length);
166660
+ return createHash8("sha256").update(value).digest("hex").slice(0, length);
166606
166661
  }
166607
166662
  function warningLooksEmbeddingRelated(message) {
166608
166663
  const lower = message.toLowerCase();
@@ -166666,8 +166721,8 @@ function handleUntrustedLoad(db, projectIdentity, directory, detailed) {
166666
166721
  }
166667
166722
 
166668
166723
  // src/config/index.ts
166669
- import { existsSync as existsSync11, readFileSync as readFileSync8 } from "node:fs";
166670
- import { homedir as homedir5 } from "node:os";
166724
+ import { existsSync as existsSync10, readFileSync as readFileSync8 } from "node:fs";
166725
+ import { homedir as homedir4 } from "node:os";
166671
166726
  import { join as join13 } from "node:path";
166672
166727
 
166673
166728
  // ../plugin/src/config/migrate-experimental.ts
@@ -166761,9 +166816,67 @@ function migrateLegacyExperimental(rawConfig, warnings) {
166761
166816
  }
166762
166817
 
166763
166818
  // ../plugin/src/config/variable.ts
166764
- import { existsSync as existsSync10, readFileSync as readFileSync7 } from "node:fs";
166765
- import { homedir as homedir4 } from "node:os";
166766
- import { dirname as dirname5, isAbsolute as isAbsolute2, resolve as resolve3 } from "node:path";
166819
+ import { existsSync as existsSync9, readFileSync as readFileSync7 } from "node:fs";
166820
+ import { homedir as homedir3 } from "node:os";
166821
+ import { dirname as dirname5, isAbsolute as isAbsolute3, resolve as resolve4 } from "node:path";
166822
+
166823
+ // ../plugin/src/shared/jsonc-parser.ts
166824
+ function stripJsonComments(content) {
166825
+ let result = "";
166826
+ let inString = false;
166827
+ let escaped = false;
166828
+ let inLineComment = false;
166829
+ let inBlockComment = false;
166830
+ for (let index = 0;index < content.length; index += 1) {
166831
+ const char = content[index];
166832
+ const next = content[index + 1];
166833
+ if (inLineComment) {
166834
+ if (char === `
166835
+ `) {
166836
+ inLineComment = false;
166837
+ result += char;
166838
+ }
166839
+ continue;
166840
+ }
166841
+ if (inBlockComment) {
166842
+ if (char === "*" && next === "/") {
166843
+ inBlockComment = false;
166844
+ index += 1;
166845
+ }
166846
+ continue;
166847
+ }
166848
+ if (inString) {
166849
+ result += char;
166850
+ if (escaped) {
166851
+ escaped = false;
166852
+ } else if (char === "\\") {
166853
+ escaped = true;
166854
+ } else if (char === '"') {
166855
+ inString = false;
166856
+ }
166857
+ continue;
166858
+ }
166859
+ if (char === '"') {
166860
+ inString = true;
166861
+ result += char;
166862
+ continue;
166863
+ }
166864
+ if (char === "/" && next === "/") {
166865
+ inLineComment = true;
166866
+ index += 1;
166867
+ continue;
166868
+ }
166869
+ if (char === "/" && next === "*") {
166870
+ inBlockComment = true;
166871
+ index += 1;
166872
+ continue;
166873
+ }
166874
+ result += char;
166875
+ }
166876
+ return result;
166877
+ }
166878
+
166879
+ // ../plugin/src/config/variable.ts
166767
166880
  var ENV_PATTERN = /\{env:([^}]+)\}/g;
166768
166881
  var FILE_PATTERN = /\{file:([^}]+)\}/g;
166769
166882
  function substituteConfigVariables(input) {
@@ -166815,11 +166928,11 @@ function substituteConfigVariables(input) {
166815
166928
  }
166816
166929
  let filePath = rawPath.trim();
166817
166930
  if (filePath.startsWith("~/")) {
166818
- filePath = resolve3(homedir4(), filePath.slice(2));
166819
- } else if (!isAbsolute2(filePath)) {
166820
- filePath = resolve3(configDir, filePath);
166931
+ filePath = resolve4(homedir3(), filePath.slice(2));
166932
+ } else if (!isAbsolute3(filePath)) {
166933
+ filePath = resolve4(configDir, filePath);
166821
166934
  }
166822
- if (!existsSync10(filePath)) {
166935
+ if (!existsSync9(filePath)) {
166823
166936
  warnings.push(`File not found for ${token} (resolved to ${filePath}); using empty string`);
166824
166937
  continue;
166825
166938
  }
@@ -166845,12 +166958,12 @@ function getProjectConfigPaths(cwd) {
166845
166958
  return [`${basePath}.jsonc`, `${basePath}.json`];
166846
166959
  }
166847
166960
  function getUserConfigPaths() {
166848
- const home = process.env.HOME ?? homedir5();
166961
+ const home = process.env.HOME ?? homedir4();
166849
166962
  const basePath = join13(home, ".pi", "agent", CONFIG_FILE_NAME);
166850
166963
  return [`${basePath}.jsonc`, `${basePath}.json`];
166851
166964
  }
166852
166965
  function resolveFirstExisting(paths) {
166853
- return paths.find((path7) => existsSync11(path7));
166966
+ return paths.find((path7) => existsSync10(path7));
166854
166967
  }
166855
166968
  function loadConfigFile(path7, scope) {
166856
166969
  try {
@@ -167432,7 +167545,6 @@ function registerCtxDreamCommand(pi, deps) {
167432
167545
  }
167433
167546
 
167434
167547
  // ../plugin/src/hooks/magic-context/execute-flush.ts
167435
- init_logger();
167436
167548
  function executeFlush(db, sessionId) {
167437
167549
  try {
167438
167550
  const pendingOps = getPendingOps(db, sessionId);
@@ -167464,7 +167576,6 @@ function executeFlush(db, sessionId) {
167464
167576
  import * as crypto2 from "node:crypto";
167465
167577
 
167466
167578
  // ../plugin/src/features/magic-context/scheduler.ts
167467
- init_logger();
167468
167579
  var TTL_PATTERN = /^(\d+)([smh])$/;
167469
167580
  var NUMERIC_PATTERN = /^\d+$/;
167470
167581
  var UNIT_TO_MS = {
@@ -167519,6 +167630,7 @@ function createScheduler(config2) {
167519
167630
  }
167520
167631
  };
167521
167632
  }
167633
+
167522
167634
  // ../plugin/src/features/magic-context/tagger.ts
167523
167635
  var TOOL_COMPOSITE_KEY_SEP = "\x00";
167524
167636
  function makeToolCompositeKey(ownerMsgId, callId) {
@@ -168278,7 +168390,6 @@ function replayCavemanCompression(sessionId, db, targets, tags) {
168278
168390
  }
168279
168391
 
168280
168392
  // ../plugin/src/hooks/magic-context/compartment-trigger.ts
168281
- init_logger();
168282
168393
  var PROACTIVE_TRIGGER_OFFSET_PERCENTAGE = 2;
168283
168394
  var POST_DROP_TARGET_RATIO = 0.75;
168284
168395
  var MIN_PROACTIVE_TAIL_TOKEN_ESTIMATE = 6000;
@@ -168515,9 +168626,6 @@ class BoundedSessionMap {
168515
168626
  }
168516
168627
  }
168517
168628
 
168518
- // ../plugin/src/hooks/magic-context/inject-compartments.ts
168519
- init_logger();
168520
-
168521
168629
  // ../plugin/src/hooks/magic-context/decay-curve.ts
168522
168630
  var H50 = 24;
168523
168631
  var D = 25;
@@ -168687,7 +168795,6 @@ function extractM0Block(m0Text, tag) {
168687
168795
  // ../plugin/src/hooks/magic-context/key-files-block.ts
168688
168796
  import { readFileSync as readFileSync9, realpathSync as realpathSync4 } from "node:fs";
168689
168797
  import { join as join14, sep as sep2 } from "node:path";
168690
- init_logger();
168691
168798
  var cachedKeyFilesBySession = new Map;
168692
168799
  var staleUpdates = new Map;
168693
168800
  function staleKey(update) {
@@ -168785,9 +168892,6 @@ ${blocks.join(`
168785
168892
  return rendered;
168786
168893
  }
168787
168894
 
168788
- // ../plugin/src/hooks/magic-context/inject-compartments.ts
168789
- await init_read_session_db();
168790
-
168791
168895
  // ../plugin/src/hooks/magic-context/temporal-awareness.ts
168792
168896
  var TEMPORAL_AWARENESS_THRESHOLD_SECONDS = 300;
168793
168897
  var SECONDS_PER_MINUTE = 60;
@@ -168944,9 +169048,6 @@ function renderMemoryBlockV2(memories, wrapper = "project-memory") {
168944
169048
  `);
168945
169049
  }
168946
169050
 
168947
- // ../plugin/src/hooks/magic-context/nudger.ts
168948
- init_logger();
168949
-
168950
169051
  // ../plugin/src/shared/format-bytes.ts
168951
169052
  function formatBytes(bytes) {
168952
169053
  if (bytes < 1024)
@@ -169148,9 +169249,6 @@ function estimateProjectedPercentage(db, sessionId, contextUsage, preloadedTags)
169148
169249
  return contextUsage.percentage * (1 - dropRatio);
169149
169250
  }
169150
169251
 
169151
- // src/context-handler.ts
169152
- init_logger();
169153
-
169154
169252
  // ../plugin/src/shared/tag-transcript.ts
169155
169253
  function tagTranscript(sessionId, transcript, tagger, db, options = {}) {
169156
169254
  const skipPrefixInjection = options.skipPrefixInjection === true;
@@ -169452,10 +169550,62 @@ function buildToolTarget(part, message) {
169452
169550
  };
169453
169551
  }
169454
169552
 
169455
- // ../plugin/src/features/magic-context/search.ts
169456
- init_logger();
169553
+ // ../plugin/src/features/magic-context/literal-probes.ts
169554
+ var MAX_PROBES = 5;
169555
+ var MIN_PROBE_LENGTH = 3;
169556
+ var SLASH_COMMAND_RE = /\/[a-z][a-z0-9]*(?:-[a-z0-9]+)+/gi;
169557
+ var KEBAB_SNAKE_RE = /[a-z][a-z0-9]*(?:[-_][a-z0-9]+)+/gi;
169558
+ var DOTTED_RE = /[a-z0-9][a-z0-9_-]*(?:\.[a-z0-9_-]+)+/gi;
169559
+ var CAMEL_RE = /\b[a-zA-Z][a-z0-9]*(?:[A-Z][a-z0-9]*)+\b/g;
169560
+ var SHA_RE = /\b[0-9a-f]{7,40}\b/gi;
169561
+ var ERROR_CODE_RE = /\b(?:TS\d{4,}|ERR_[A-Z][A-Z0-9_]*)\b/g;
169562
+ var QUOTED_RE = /["`]([^"`]{3,80})["`]/g;
169563
+ function looksLikeSha(token) {
169564
+ return /[0-9]/.test(token) && /^[0-9a-f]{7,40}$/i.test(token);
169565
+ }
169566
+ function extractLiteralProbes(query) {
169567
+ const trimmed = query.trim();
169568
+ if (trimmed.length === 0)
169569
+ return [];
169570
+ const ordered = [];
169571
+ const seen = new Set;
169572
+ const add = (raw) => {
169573
+ if (!raw)
169574
+ return;
169575
+ const probe = raw.trim();
169576
+ if (probe.length < MIN_PROBE_LENGTH)
169577
+ return;
169578
+ const key = probe.toLowerCase();
169579
+ if (seen.has(key))
169580
+ return;
169581
+ seen.add(key);
169582
+ ordered.push(probe);
169583
+ };
169584
+ for (const m of trimmed.matchAll(QUOTED_RE))
169585
+ add(m[1]);
169586
+ for (const m of trimmed.matchAll(SLASH_COMMAND_RE))
169587
+ add(m[0]);
169588
+ for (const m of trimmed.matchAll(ERROR_CODE_RE))
169589
+ add(m[0]);
169590
+ for (const m of trimmed.matchAll(DOTTED_RE))
169591
+ add(m[0]);
169592
+ for (const m of trimmed.matchAll(KEBAB_SNAKE_RE))
169593
+ add(m[0]);
169594
+ for (const m of trimmed.matchAll(CAMEL_RE))
169595
+ add(m[0]);
169596
+ for (const m of trimmed.matchAll(SHA_RE)) {
169597
+ if (looksLikeSha(m[0]))
169598
+ add(m[0]);
169599
+ }
169600
+ return ordered.slice(0, MAX_PROBES);
169601
+ }
169602
+ function containsProbeVerbatim(text, probes) {
169603
+ if (probes.length === 0)
169604
+ return false;
169605
+ const haystack = text.toLowerCase();
169606
+ return probes.some((probe) => haystack.includes(probe.toLowerCase()));
169607
+ }
169457
169608
  // ../plugin/src/features/magic-context/memory/embedding-backfill.ts
169458
- init_logger();
169459
169609
  async function ensureMemoryEmbeddings(args) {
169460
169610
  const snapshot = getProjectEmbeddingSnapshot(args.projectIdentity);
169461
169611
  if (!snapshot?.enabled) {
@@ -169494,7 +169644,6 @@ async function ensureMemoryEmbeddings(args) {
169494
169644
  return args.existingEmbeddings;
169495
169645
  }
169496
169646
  // ../plugin/src/features/magic-context/memory/promotion.ts
169497
- init_logger();
169498
169647
  function isPromotableCategory(category) {
169499
169648
  return PROMOTABLE_CATEGORIES.some((promotableCategory) => promotableCategory === category);
169500
169649
  }
@@ -169716,36 +169865,82 @@ function linearDecayScore(rank, total) {
169716
169865
  return 0;
169717
169866
  return Math.max(0, 1 - rank / total);
169718
169867
  }
169719
- function searchMessages(args) {
169720
- const sanitizedQuery = sanitizeFtsQuery(args.query.trim());
169721
- if (sanitizedQuery.length === 0) {
169868
+ function runMessageFtsQuery(db, sessionId, ftsQuery, fetchLimit, cutoff) {
169869
+ if (ftsQuery.length === 0)
169722
169870
  return [];
169723
- }
169724
- const fetchLimit = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.limit * 3 : args.limit;
169725
- const rows = getMessageSearchStatement(args.db).all(args.sessionId, sanitizedQuery, fetchLimit).map((row) => row);
169726
- const cutoff = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.maxOrdinal : null;
169727
- const filtered = rows.map((row) => {
169871
+ const rows = getMessageSearchStatement(db).all(sessionId, ftsQuery, fetchLimit).map((row) => row);
169872
+ const result = [];
169873
+ for (const row of rows) {
169728
169874
  const messageOrdinal = getMessageOrdinal(row.messageOrdinal);
169729
169875
  if (messageOrdinal === null || typeof row.messageId !== "string" || typeof row.role !== "string" || typeof row.content !== "string") {
169730
- return null;
169876
+ continue;
169731
169877
  }
169732
169878
  if (cutoff !== null && messageOrdinal > cutoff) {
169733
- return null;
169879
+ continue;
169734
169880
  }
169735
- return {
169881
+ result.push({
169736
169882
  messageOrdinal,
169737
169883
  messageId: row.messageId,
169738
169884
  role: row.role,
169739
169885
  content: row.content
169740
- };
169741
- }).filter((result) => result !== null).slice(0, args.limit);
169742
- return filtered.map((row, rank) => ({
169886
+ });
169887
+ }
169888
+ return result;
169889
+ }
169890
+ var RRF_K = 60;
169891
+ var VERBATIM_PROBE_BONUS = 0.5;
169892
+ function searchMessages(args) {
169893
+ const cutoff = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.maxOrdinal : null;
169894
+ const fetchLimit = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.limit * 3 : args.limit;
169895
+ const baseQuery = sanitizeFtsQuery(args.query.trim());
169896
+ const probes = args.probes ?? [];
169897
+ if (probes.length === 0) {
169898
+ const filtered = runMessageFtsQuery(args.db, args.sessionId, baseQuery, fetchLimit, cutoff).slice(0, args.limit);
169899
+ return filtered.map((row, rank) => ({
169900
+ source: "message",
169901
+ content: previewText(row.content),
169902
+ score: linearDecayScore(rank, filtered.length),
169903
+ messageOrdinal: row.messageOrdinal,
169904
+ messageId: row.messageId,
169905
+ role: row.role
169906
+ }));
169907
+ }
169908
+ const queryLists = [];
169909
+ if (baseQuery.length > 0) {
169910
+ queryLists.push(runMessageFtsQuery(args.db, args.sessionId, baseQuery, fetchLimit, cutoff));
169911
+ }
169912
+ for (const probe of probes) {
169913
+ const probeQuery = sanitizeFtsQuery(probe);
169914
+ if (probeQuery.length === 0)
169915
+ continue;
169916
+ queryLists.push(runMessageFtsQuery(args.db, args.sessionId, probeQuery, fetchLimit, cutoff));
169917
+ }
169918
+ const fused = new Map;
169919
+ for (const list of queryLists) {
169920
+ list.forEach((row, rank) => {
169921
+ const rrf = 1 / (RRF_K + rank);
169922
+ const existing = fused.get(row.messageId);
169923
+ if (existing) {
169924
+ existing.score += rrf;
169925
+ } else {
169926
+ fused.set(row.messageId, { row, score: rrf });
169927
+ }
169928
+ });
169929
+ }
169930
+ for (const entry of fused.values()) {
169931
+ if (containsProbeVerbatim(entry.row.content, probes)) {
169932
+ entry.score += VERBATIM_PROBE_BONUS;
169933
+ }
169934
+ }
169935
+ const ranked = [...fused.values()].sort((a, b) => b.score !== a.score ? b.score - a.score : a.row.messageOrdinal - b.row.messageOrdinal).slice(0, args.limit);
169936
+ const maxScore = ranked.length > 0 ? ranked[0].score : 1;
169937
+ return ranked.map((entry) => ({
169743
169938
  source: "message",
169744
- content: previewText(row.content),
169745
- score: linearDecayScore(rank, filtered.length),
169746
- messageOrdinal: row.messageOrdinal,
169747
- messageId: row.messageId,
169748
- role: row.role
169939
+ content: previewText(entry.row.content),
169940
+ score: maxScore > 0 ? entry.score / maxScore : 0,
169941
+ messageOrdinal: entry.row.messageOrdinal,
169942
+ messageId: entry.row.messageId,
169943
+ role: entry.row.role
169749
169944
  }));
169750
169945
  }
169751
169946
  function getSourceBoost(result) {
@@ -169829,12 +170024,14 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
169829
170024
  return null;
169830
170025
  }) : Promise.resolve(null);
169831
170026
  await Promise.resolve();
170027
+ const messageProbes = options.explicitSearch ? extractLiteralProbes(trimmedQuery) : [];
169832
170028
  const messageResults = runMessages ? searchMessages({
169833
170029
  db,
169834
170030
  sessionId,
169835
170031
  query: trimmedQuery,
169836
170032
  limit: tierLimit,
169837
- maxOrdinal: options.maxMessageOrdinal
170033
+ maxOrdinal: options.maxMessageOrdinal,
170034
+ probes: messageProbes
169838
170035
  }) : [];
169839
170036
  const queryEmbedding = await queryEmbeddingPromise;
169840
170037
  const [memoryResults, gitCommitResults] = await Promise.all([
@@ -169948,17 +170145,16 @@ ${trimmedBody}…
169948
170145
  }
169949
170146
 
169950
170147
  // src/auto-search-pi.ts
169951
- init_logger();
169952
170148
  var AUTO_SEARCH_TIMEOUT_MS = 3000;
169953
170149
  var DEFAULT_SCORE_THRESHOLD = 0.55;
169954
170150
  var DEFAULT_MIN_PROMPT_CHARS = 20;
169955
170151
  async function unifiedSearchWithTimeout(db, sessionId, projectPath, prompt, options, timeoutMs) {
169956
170152
  const controller = new AbortController;
169957
170153
  let timer;
169958
- const timeoutPromise = new Promise((resolve4) => {
170154
+ const timeoutPromise = new Promise((resolve5) => {
169959
170155
  timer = setTimeout(() => {
169960
170156
  controller.abort();
169961
- resolve4(null);
170157
+ resolve5(null);
169962
170158
  }, timeoutMs);
169963
170159
  });
169964
170160
  try {
@@ -170178,7 +170374,6 @@ ${hintText}`;
170178
170374
  function clearAutoSearchForPiSession(_sessionId) {}
170179
170375
 
170180
170376
  // src/compaction-marker-manager-pi.ts
170181
- init_logger();
170182
170377
  function applyDeferredPiCompactionMarker(deps, sessionId, pending) {
170183
170378
  try {
170184
170379
  const matches = getCompartmentsByEndMessageId(deps.db, sessionId, pending.endMessageId);
@@ -170320,7 +170515,6 @@ function stripSystemInjection(text) {
170320
170515
  }
170321
170516
 
170322
170517
  // src/heuristic-cleanup-pi.ts
170323
- init_logger();
170324
170518
  var DEDUP_SAFE_TOOLS = new Set([
170325
170519
  "mcp_grep",
170326
170520
  "mcp_read",
@@ -170570,9 +170764,6 @@ function buildMessageIdToMaxTagFromTargets(targets) {
170570
170764
  return byMessage;
170571
170765
  }
170572
170766
 
170573
- // src/inject-compartments-pi.ts
170574
- init_logger();
170575
-
170576
170767
  // src/read-session-pi.ts
170577
170768
  var SYNTH_USER_ID_PREFIX = "synth-user-";
170578
170769
  function resolvePiStableId(msg, index, entryIds, entryIdByRef) {
@@ -170955,6 +171146,13 @@ function safeGetActiveUserMemoriesPi(db) {
170955
171146
  throw error51;
170956
171147
  }
170957
171148
  }
171149
+ var EMPTY_PI_HARD_SIGNALS = {
171150
+ systemHash: "",
171151
+ toolSetHash: "",
171152
+ modelKey: "",
171153
+ cacheExpired: false,
171154
+ lastResponseTime: 0
171155
+ };
170958
171156
  function decodeCachedM0(value) {
170959
171157
  if (!value)
170960
171158
  return null;
@@ -171001,7 +171199,10 @@ function getCachedMarkers(db, state, compartmentsForNormalization) {
171001
171199
  sessionFactsVersion: meta3.cachedM0SessionFactsVersion,
171002
171200
  materializedAt: meta3.cachedM0MaterializedAt,
171003
171201
  upgradeState: meta3.cachedM0UpgradeState,
171004
- lastBaselineEndMessageId: cachedBoundary
171202
+ lastBaselineEndMessageId: cachedBoundary,
171203
+ systemHash: meta3.cachedM0SystemHash ?? "",
171204
+ toolSetHash: meta3.cachedM0ToolSetHash ?? "",
171205
+ modelKey: meta3.cachedM0ModelKey ?? ""
171005
171206
  };
171006
171207
  }
171007
171208
  function lastBaselineEndMessageId(compartments) {
@@ -171029,7 +171230,10 @@ function readCurrentMarkersFromCompartments(db, state, compartments, projectDocs
171029
171230
  sessionFactsVersion: getSessionFactsVersion(db, state.sessionId),
171030
171231
  materializedAt: Date.now(),
171031
171232
  upgradeState: `${PI_M0_UPGRADE_STATE}:${compartments.some((c) => c.legacy === 1) ? "legacy" : "ready"}`,
171032
- lastBaselineEndMessageId: lastBaselineEndMessageId(compartments)
171233
+ lastBaselineEndMessageId: lastBaselineEndMessageId(compartments),
171234
+ systemHash: (state.hardSignals ?? EMPTY_PI_HARD_SIGNALS).systemHash,
171235
+ toolSetHash: (state.hardSignals ?? EMPTY_PI_HARD_SIGNALS).toolSetHash,
171236
+ modelKey: (state.hardSignals ?? EMPTY_PI_HARD_SIGNALS).modelKey
171033
171237
  };
171034
171238
  }
171035
171239
  function mustMaterializePi(state, db, currentCompartmentsOverride) {
@@ -171046,7 +171250,19 @@ function mustMaterializePi(state, db, currentCompartmentsOverride) {
171046
171250
  if (getCachedMarkers(db, state, currentCompartments) === null) {
171047
171251
  return { value: true, reason: "cache_invalid" };
171048
171252
  }
171049
- const cachedMaxCompartmentSeq = normalizeCachedMaxCompartmentSeq(meta3.cachedM0MaxCompartmentSeq ?? EMPTY_MAX_COMPARTMENT_SEQ, currentCompartments);
171253
+ const hard = state.hardSignals ?? EMPTY_PI_HARD_SIGNALS;
171254
+ if (hard.modelKey !== "" && hard.modelKey !== (meta3.cachedM0ModelKey ?? "")) {
171255
+ return { value: true, reason: "model_change" };
171256
+ }
171257
+ if (hard.systemHash !== "" && hard.systemHash !== (meta3.cachedM0SystemHash ?? "")) {
171258
+ return { value: true, reason: "system_hash" };
171259
+ }
171260
+ if (hard.toolSetHash !== "" && hard.toolSetHash !== (meta3.cachedM0ToolSetHash ?? "")) {
171261
+ return { value: true, reason: "tool_set_hash" };
171262
+ }
171263
+ if (hard.cacheExpired && hard.lastResponseTime > 0 && hard.lastResponseTime > (meta3.cachedM0MaterializedAt ?? 0)) {
171264
+ return { value: true, reason: "ttl_idle" };
171265
+ }
171050
171266
  if (meta3.cachedM0UpgradeState !== current.upgradeState) {
171051
171267
  return { value: true, reason: "renderer_upgrade" };
171052
171268
  }
@@ -171056,15 +171272,9 @@ function mustMaterializePi(state, db, currentCompartmentsOverride) {
171056
171272
  if (current.projectMemoryEpoch !== (meta3.cachedM0ProjectMemoryEpoch ?? 0)) {
171057
171273
  return { value: true, reason: "project_memory_change" };
171058
171274
  }
171059
- if (current.projectUserProfileVersion !== (meta3.cachedM0ProjectUserProfileVersion ?? 0)) {
171060
- return { value: true, reason: "user_profile_change" };
171061
- }
171062
171275
  if (current.maxMutationId !== (meta3.cachedM0MaxMutationId ?? 0)) {
171063
171276
  return { value: true, reason: "pending_mutations" };
171064
171277
  }
171065
- if (current.maxCompartmentSeq !== cachedMaxCompartmentSeq) {
171066
- return { value: true, reason: "new_compartment" };
171067
- }
171068
171278
  return { value: false, reason: null };
171069
171279
  }
171070
171280
  function renderUserProfileBlock(db, wrapper = "user-profile", memoriesOverride) {
@@ -171144,7 +171354,10 @@ function readFrozenM0InputsPi(state, db, docs = readProjectDocsCanonical(state.p
171144
171354
  sessionFactsVersion: getSessionFactsVersion(db, state.sessionId),
171145
171355
  materializedAt: Date.now(),
171146
171356
  upgradeState: `${PI_M0_UPGRADE_STATE}:${compartments.some((c) => c.legacy === 1) ? "legacy" : "ready"}`,
171147
- lastBaselineEndMessageId: lastBaselineEndMessageId(compartments)
171357
+ lastBaselineEndMessageId: lastBaselineEndMessageId(compartments),
171358
+ systemHash: (state.hardSignals ?? EMPTY_PI_HARD_SIGNALS).systemHash,
171359
+ toolSetHash: (state.hardSignals ?? EMPTY_PI_HARD_SIGNALS).toolSetHash,
171360
+ modelKey: (state.hardSignals ?? EMPTY_PI_HARD_SIGNALS).modelKey
171148
171361
  };
171149
171362
  return { docs, markers, compartments, memories, userProfile };
171150
171363
  });
@@ -171220,7 +171433,10 @@ function materializeM0Pi(state, db) {
171220
171433
  projectDocsHash: snapshotMarkers.projectDocsHash,
171221
171434
  materializedAt: snapshotMarkers.materializedAt,
171222
171435
  sessionFactsVersion: snapshotMarkers.sessionFactsVersion,
171223
- upgradeState: snapshotMarkers.upgradeState
171436
+ upgradeState: snapshotMarkers.upgradeState,
171437
+ systemHash: snapshotMarkers.systemHash,
171438
+ toolSetHash: snapshotMarkers.toolSetHash,
171439
+ modelKey: snapshotMarkers.modelKey
171224
171440
  });
171225
171441
  db.prepare("UPDATE session_meta SET memory_block_count = ?, memory_block_ids = ? WHERE session_id = ?").run(renderedMemoryIds.length, JSON.stringify(renderedMemoryIds), state.sessionId);
171226
171442
  setCachedBoundary(db, state.sessionId, snapshotMarkers.lastBaselineEndMessageId);
@@ -171386,6 +171602,9 @@ function readCachedPiM0M1Row(db, sessionId) {
171386
171602
  cached_m0_materialized_at,
171387
171603
  cached_m0_session_facts_version,
171388
171604
  cached_m0_upgrade_state,
171605
+ cached_m0_system_hash,
171606
+ cached_m0_tool_set_hash,
171607
+ cached_m0_model_key,
171389
171608
  cached_m0_last_baseline_end_message_id,
171390
171609
  memory_block_ids
171391
171610
  FROM session_meta
@@ -171423,14 +171642,17 @@ function markersFromCachedPiRow(row, compartmentsForNormalization) {
171423
171642
  materializedAt: row.cached_m0_materialized_at,
171424
171643
  sessionFactsVersion: row.cached_m0_session_facts_version,
171425
171644
  upgradeState: row.cached_m0_upgrade_state,
171426
- lastBaselineEndMessageId: typeof row.cached_m0_last_baseline_end_message_id === "string" && row.cached_m0_last_baseline_end_message_id.length > 0 ? row.cached_m0_last_baseline_end_message_id : null
171645
+ lastBaselineEndMessageId: typeof row.cached_m0_last_baseline_end_message_id === "string" && row.cached_m0_last_baseline_end_message_id.length > 0 ? row.cached_m0_last_baseline_end_message_id : null,
171646
+ systemHash: row.cached_m0_system_hash ?? "",
171647
+ toolSetHash: row.cached_m0_tool_set_hash ?? "",
171648
+ modelKey: row.cached_m0_model_key ?? ""
171427
171649
  };
171428
171650
  }
171429
171651
  function cachedPiRowMatchesSnapshot(args) {
171430
171652
  const rowMarkers = markersFromCachedPiRow(args.row, args.compartmentsForNormalization);
171431
171653
  if (!rowMarkers)
171432
171654
  return false;
171433
- return bufferEqualsNullable(args.row.cached_m0_bytes, args.m0Bytes) && rowMarkers.projectMemoryEpoch === args.markers.projectMemoryEpoch && rowMarkers.projectUserProfileVersion === args.markers.projectUserProfileVersion && rowMarkers.maxCompartmentSeq === args.markers.maxCompartmentSeq && rowMarkers.maxMemoryId === args.markers.maxMemoryId && rowMarkers.maxMutationId === args.markers.maxMutationId && rowMarkers.maxMemoryMutationId === args.markers.maxMemoryMutationId && (rowMarkers.projectDocsHash ?? "") === (args.markers.projectDocsHash ?? "") && rowMarkers.materializedAt === args.markers.materializedAt && rowMarkers.sessionFactsVersion === args.markers.sessionFactsVersion && (rowMarkers.upgradeState ?? null) === (args.markers.upgradeState ?? null);
171655
+ return bufferEqualsNullable(args.row.cached_m0_bytes, args.m0Bytes) && rowMarkers.projectMemoryEpoch === args.markers.projectMemoryEpoch && rowMarkers.projectUserProfileVersion === args.markers.projectUserProfileVersion && rowMarkers.maxCompartmentSeq === args.markers.maxCompartmentSeq && rowMarkers.maxMemoryId === args.markers.maxMemoryId && rowMarkers.maxMutationId === args.markers.maxMutationId && rowMarkers.maxMemoryMutationId === args.markers.maxMemoryMutationId && (rowMarkers.projectDocsHash ?? "") === (args.markers.projectDocsHash ?? "") && rowMarkers.materializedAt === args.markers.materializedAt && rowMarkers.sessionFactsVersion === args.markers.sessionFactsVersion && (rowMarkers.upgradeState ?? null) === (args.markers.upgradeState ?? null) && (rowMarkers.systemHash ?? "") === (args.markers.systemHash ?? "") && (rowMarkers.toolSetHash ?? "") === (args.markers.toolSetHash ?? "") && (rowMarkers.modelKey ?? "") === (args.markers.modelKey ?? "");
171434
171656
  }
171435
171657
  function decodeCachedM1(row, sessionId) {
171436
171658
  if (!row.cached_m1_bytes) {
@@ -171490,12 +171712,14 @@ function softRefreshCachedM1Pi(args) {
171490
171712
  }
171491
171713
  const rendered = renderM1PiWithMetadata(args.state, args.db, markers, parseMemoryBlockIds(row.memory_block_ids), preRenderedKeyFilesBlock);
171492
171714
  const m1Bytes = Buffer.from(rendered.text, "utf8");
171493
- args.db.prepare("UPDATE session_meta SET cached_m1_bytes = ? WHERE session_id = ?").run(m1Bytes, args.state.sessionId);
171715
+ const latestCompartment = args.compartmentsForNormalization.at(-1);
171716
+ const advancedBoundary = latestCompartment?.endMessageId && latestCompartment.endMessageId.length > 0 ? latestCompartment.endMessageId : markers.lastBaselineEndMessageId;
171717
+ args.db.prepare("UPDATE session_meta SET cached_m1_bytes = ?, cached_m0_last_baseline_end_message_id = ? WHERE session_id = ?").run(m1Bytes, advancedBoundary, args.state.sessionId);
171494
171718
  args.db.exec("COMMIT");
171495
171719
  return {
171496
171720
  m0: decodeCachedM0(row.cached_m0_bytes) ?? "",
171497
171721
  m1: rendered.text,
171498
- markers,
171722
+ markers: { ...markers, lastBaselineEndMessageId: advancedBoundary },
171499
171723
  memoryUpdateCount: rendered.memoryUpdateCount,
171500
171724
  recomputed: true
171501
171725
  };
@@ -171615,7 +171839,10 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
171615
171839
  markers = replayed.markers;
171616
171840
  }
171617
171841
  const M0_DRIFT_RATIO_FLOOR = 2000;
171618
- if (!materialized && !contentionExhausted && m1Recomputed && recomputeM1ThisPass && (memoryUpdateCount > 40 || m1 !== PI_M1_PLACEHOLDER && m0.length >= M0_DRIFT_RATIO_FLOOR && m1.length > m0.length * 0.15)) {
171842
+ const M1_ABSOLUTE_CAP_RATIO = 0.2;
171843
+ const m1AbsoluteBudget = (state.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS) * M1_ABSOLUTE_CAP_RATIO;
171844
+ const m1OverAbsoluteCap = m1 !== PI_M1_PLACEHOLDER && estimateTokens(m1) > m1AbsoluteBudget;
171845
+ if (!materialized && !contentionExhausted && m1Recomputed && recomputeM1ThisPass && (memoryUpdateCount > 40 || m1OverAbsoluteCap || m1 !== PI_M1_PLACEHOLDER && m0.length >= M0_DRIFT_RATIO_FLOOR && m1.length > m0.length * 0.15)) {
171619
171846
  decision = { value: true, reason: "drift" };
171620
171847
  try {
171621
171848
  const result = materializeM0PiWithRetry(state, db);
@@ -171798,7 +172025,6 @@ function isRecord3(value) {
171798
172025
  }
171799
172026
 
171800
172027
  // ../plugin/src/features/magic-context/compartment-embedding.ts
171801
- init_logger();
171802
172028
  async function embedAndStoreCompartments(db, sessionId, projectPath, compartments) {
171803
172029
  if (compartments.length === 0)
171804
172030
  return;
@@ -172695,7 +172921,6 @@ Memory is disabled for this project: do NOT emit a <facts> block. Produce compar
172695
172921
  }
172696
172922
 
172697
172923
  // ../plugin/src/hooks/magic-context/compartment-runner-drop-queue.ts
172698
- init_logger();
172699
172924
  function queueDropsForCompartmentalizedMessages(db, sessionId, upToMessageIndex) {
172700
172925
  const tags = getTagsBySession(db, sessionId);
172701
172926
  const { messageFileKeys, toolObservations } = getRawSessionTagKeysThrough(sessionId, upToMessageIndex);
@@ -174819,7 +175044,6 @@ function buildReferenceBlocks(args) {
174819
175044
  }
174820
175045
 
174821
175046
  // src/pi-historian-runner.ts
174822
- init_logger();
174823
175047
  var HISTORIAN_AGENT_NAME = "magic-context-historian";
174824
175048
  var DEFAULT_HISTORIAN_TIMEOUT_MS2 = 120000;
174825
175049
  var HISTORIAN_ALERT_COOLDOWN_MS = 60 * 1000;
@@ -175602,7 +175826,6 @@ function replayStrippedInlineThinkingPi(args) {
175602
175826
  }
175603
175827
 
175604
175828
  // src/strip-placeholders-pi.ts
175605
- init_logger();
175606
175829
  var DROPPED_SEGMENT_PATTERN = /^\[dropped(?: §[^§]+§)?\]$/;
175607
175830
  function isDroppedOnlyText(text) {
175608
175831
  const trimmed = text.trim();
@@ -175697,7 +175920,7 @@ function stripPiDroppedPlaceholderMessages(args) {
175697
175920
  }
175698
175921
 
175699
175922
  // src/system-prompt.ts
175700
- import { createHash as createHash10 } from "node:crypto";
175923
+ import { createHash as createHash9 } from "node:crypto";
175701
175924
 
175702
175925
  // ../plugin/src/agents/magic-context-prompt.ts
175703
175926
  var LONG_TERM_PARTNER_FRAME = `### You are the user's long-term partner on this project — not a one-off hire
@@ -175806,7 +176029,6 @@ Prefer many small targeted operations over one large blanket operation, and keep
175806
176029
  }
175807
176030
 
175808
176031
  // src/system-prompt.ts
175809
- init_logger();
175810
176032
  var MAGIC_CONTEXT_MARKER = "## Magic Context";
175811
176033
  var stickyDateBySession = new Map;
175812
176034
  function buildMagicContextBlock(opts) {
@@ -175842,7 +176064,7 @@ function processSystemPromptForCache(args) {
175842
176064
  sessionLog(sessionId, `system prompt date frozen: real=${liveDate}, using=${stickyDate} (cache-stable pass)`);
175843
176065
  }
175844
176066
  }
175845
- const currentHash = createHash10("md5").update(frozenPrompt).digest("hex");
176067
+ const currentHash = createHash9("md5").update(frozenPrompt).digest("hex");
175846
176068
  const hashChanged = !isFirstHash && currentHash !== previousHash;
175847
176069
  if (hashChanged) {
175848
176070
  sessionLog(sessionId, `system prompt hash changed: ${previousHash} → ${currentHash} (len=${frozenPrompt.length})`);
@@ -175887,10 +176109,8 @@ function injectPiTemporalMarkers(messages) {
175887
176109
  if (prefix !== null) {
175888
176110
  const userMsg = msg;
175889
176111
  if (typeof userMsg.content === "string") {
175890
- if (!TEMPORAL_MARKER_PATTERN.test(stripTagPrefix2(userMsg.content))) {
175891
- const tagMatch = userMsg.content.match(/^(?:§\d+§\s*)+/);
175892
- const tagPrefix = tagMatch ? tagMatch[0] : "";
175893
- const body = userMsg.content.slice(tagPrefix.length);
176112
+ if (!TEMPORAL_MARKER_PATTERN.test(stripTagPrefix(userMsg.content))) {
176113
+ const { tagPrefix, body } = peelLeadingMcTagNotation(userMsg.content);
175894
176114
  messages[i] = {
175895
176115
  ...userMsg,
175896
176116
  content: tagPrefix + prefix + body
@@ -175901,9 +176121,7 @@ function injectPiTemporalMarkers(messages) {
175901
176121
  const firstTextIndex = userMsg.content.findIndex((p) => p && typeof p === "object" && p.type === "text");
175902
176122
  if (firstTextIndex >= 0) {
175903
176123
  const existing = userMsg.content[firstTextIndex];
175904
- const tagMatch = existing.text.match(/^(?:§\d+§\s*)+/);
175905
- const tagPrefix = tagMatch ? tagMatch[0] : "";
175906
- const body = existing.text.slice(tagPrefix.length);
176124
+ const { tagPrefix, body } = peelLeadingMcTagNotation(existing.text);
175907
176125
  if (!TEMPORAL_MARKER_PATTERN.test(body)) {
175908
176126
  const newContent = userMsg.content.slice();
175909
176127
  newContent[firstTextIndex] = {
@@ -175926,18 +176144,12 @@ function injectPiTemporalMarkers(messages) {
175926
176144
  }
175927
176145
  return injected;
175928
176146
  }
175929
- function stripTagPrefix2(text) {
175930
- const match = text.match(/^(?:§\d+§\s*)+/);
175931
- if (!match)
175932
- return text;
175933
- return text.slice(match[0].length);
175934
- }
175935
176147
 
175936
176148
  // src/timeout.ts
175937
176149
  function withTimeout(p, ms) {
175938
176150
  let handle;
175939
- const timeout = new Promise((resolve4) => {
175940
- handle = setTimeout(() => resolve4(undefined), ms);
176151
+ const timeout = new Promise((resolve5) => {
176152
+ handle = setTimeout(() => resolve5(undefined), ms);
175941
176153
  handle.unref?.();
175942
176154
  });
175943
176155
  return Promise.race([p, timeout]).finally(() => {
@@ -176958,14 +177170,10 @@ function registerPiContextHandler(pi, options) {
176958
177170
  }
176959
177171
  const sessionMeta = sessionMetaForUsage;
176960
177172
  const modelKey = liveModelBySession.get(sessionId);
176961
- if (usageContextLimit === undefined && modelKey) {
176962
- const { providerID, modelID } = splitModelKeyForPi(modelKey);
176963
- const trusted = resolveTrustedContextLimit(providerID, modelID, {
176964
- db: options.db,
176965
- sessionID: sessionId
176966
- });
176967
- if (trusted !== undefined && trusted > 0) {
176968
- usageContextLimit = trusted;
177173
+ if (usageContextLimit === undefined) {
177174
+ const modelWindow = ctx.model?.contextWindow;
177175
+ if (isSaneLimit(modelWindow)) {
177176
+ usageContextLimit = modelWindow;
176969
177177
  }
176970
177178
  }
176971
177179
  let schedulerDecision;
@@ -177218,27 +177426,8 @@ async function awaitInFlightHistorians() {
177218
177426
  return;
177219
177427
  await Promise.allSettled(Array.from(inFlightHistorian.values()));
177220
177428
  }
177221
- function splitModelKeyForPi(modelKey) {
177222
- if (!modelKey)
177223
- return { providerID: undefined, modelID: undefined };
177224
- const slash = modelKey.indexOf("/");
177225
- if (slash <= 0 || slash === modelKey.length - 1) {
177226
- return { providerID: undefined, modelID: undefined };
177227
- }
177228
- return {
177229
- providerID: modelKey.slice(0, slash),
177230
- modelID: modelKey.slice(slash + 1)
177231
- };
177232
- }
177233
177429
  function resolvePiHistorianTriggerInputs(args) {
177234
- const { providerID, modelID } = splitModelKeyForPi(args.modelKey);
177235
- let contextLimit = resolveContextLimit(providerID, modelID, {
177236
- db: args.db,
177237
- sessionID: args.sessionId
177238
- });
177239
- if ((providerID === undefined || modelID === undefined) && typeof args.usageContextLimit === "number" && Number.isFinite(args.usageContextLimit) && args.usageContextLimit > 0) {
177240
- contextLimit = args.usageContextLimit;
177241
- }
177430
+ const contextLimit = typeof args.usageContextLimit === "number" && Number.isFinite(args.usageContextLimit) && args.usageContextLimit > 0 ? args.usageContextLimit : DEFAULT_CONTEXT_LIMIT;
177242
177431
  const executeThresholdPercentage = resolveExecuteThreshold(args.historian.executeThresholdPercentage ?? 65, args.modelKey, 65, {
177243
177432
  tokensConfig: args.historian.executeThresholdTokens,
177244
177433
  contextLimit,
@@ -177692,9 +177881,18 @@ async function runPipeline(args) {
177692
177881
  if (args.injection) {
177693
177882
  try {
177694
177883
  const tInjection = performance.now();
177695
- if (args.isCacheBusting || deferredHistoryRefresh) {
177696
- clearM0M1PiCache(args.db, args.sessionId, args.isCacheBusting ? "history refresh" : "deferred history refresh");
177697
- }
177884
+ const hardMeta = getOrCreateSessionMeta(args.db, args.sessionId);
177885
+ let piTtlMs = 5 * 60 * 1000;
177886
+ try {
177887
+ piTtlMs = parseCacheTtl(hardMeta.cacheTtl);
177888
+ } catch {}
177889
+ const piHardSignals = {
177890
+ systemHash: typeof hardMeta.systemPromptHash === "string" ? hardMeta.systemPromptHash : "",
177891
+ toolSetHash: "",
177892
+ modelKey: liveModelBySession.get(args.sessionId) ?? "",
177893
+ cacheExpired: hardMeta.lastResponseTime > 0 && Date.now() - hardMeta.lastResponseTime >= piTtlMs,
177894
+ lastResponseTime: hardMeta.lastResponseTime
177895
+ };
177698
177896
  injectionResult = injectM0M1Pi({
177699
177897
  sessionId: args.sessionId,
177700
177898
  projectIdentity: args.projectIdentity,
@@ -177702,8 +177900,9 @@ async function runPipeline(args) {
177702
177900
  injectionBudgetTokens: args.injection.injectionBudgetTokens,
177703
177901
  historyBudgetTokens: args.injection.historyBudgetTokens,
177704
177902
  keyFilesEnabled: args.injection.keyFilesEnabled,
177705
- keyFilesTokenBudget: args.injection.keyFilesTokenBudget
177706
- }, args.db, args.messages, args.entryIds, executedWorkThisPass);
177903
+ keyFilesTokenBudget: args.injection.keyFilesTokenBudget,
177904
+ hardSignals: piHardSignals
177905
+ }, args.db, args.messages, args.entryIds, args.isCacheBusting || deferredHistoryRefresh || executedWorkThisPass);
177707
177906
  if (args.isCacheBusting) {
177708
177907
  historyRefreshSessions.delete(args.sessionId);
177709
177908
  historyWasConsumedThisPass = true;
@@ -178056,12 +178255,8 @@ ${result}`;
178056
178255
  });
178057
178256
  }
178058
178257
 
178059
- // ../plugin/src/hooks/magic-context/compartment-runner.ts
178060
- init_logger();
178061
-
178062
178258
  // ../plugin/src/hooks/magic-context/historian-state-file.ts
178063
- import { mkdirSync as mkdirSync5, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
178064
- init_data_path();
178259
+ import { mkdirSync as mkdirSync6, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
178065
178260
  function cleanupHistorianStateFile(path7) {
178066
178261
  if (!path7)
178067
178262
  return;
@@ -178069,13 +178264,7 @@ function cleanupHistorianStateFile(path7) {
178069
178264
  unlinkSync(path7);
178070
178265
  } catch {}
178071
178266
  }
178072
- // ../plugin/src/hooks/magic-context/compartment-runner-incremental.ts
178073
- init_logger();
178074
-
178075
178267
  // ../plugin/src/features/magic-context/compaction-marker.ts
178076
- init_data_path();
178077
- init_logger();
178078
- await init_sqlite();
178079
178268
  import { join as join15 } from "node:path";
178080
178269
  var BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
178081
178270
  function randomBase62(length) {
@@ -178230,9 +178419,6 @@ function removeCompactionMarker(state) {
178230
178419
  }
178231
178420
 
178232
178421
  // ../plugin/src/hooks/magic-context/compaction-marker-manager.ts
178233
- init_data_path();
178234
- init_logger();
178235
- await init_sqlite();
178236
178422
  var MARKER_SUMMARY_TEXT = "[Compacted by magic-context — session history is managed by the plugin]";
178237
178423
  function updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEnd, directory) {
178238
178424
  const existing = getPersistedCompactionMarkerState(db, sessionId);
@@ -178264,9 +178450,8 @@ function updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEn
178264
178450
  }
178265
178451
 
178266
178452
  // ../plugin/src/hooks/magic-context/compartment-runner-historian.ts
178267
- import { mkdirSync as mkdirSync6, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
178453
+ import { mkdirSync as mkdirSync7, unlinkSync as unlinkSync2, writeFileSync as writeFileSync4 } from "node:fs";
178268
178454
  import { join as join16 } from "node:path";
178269
- init_data_path();
178270
178455
  function historianResponseDumpDir(directory) {
178271
178456
  return getProjectMagicContextHistorianDir(directory);
178272
178457
  }
@@ -178466,12 +178651,12 @@ async function runHistorianPrompt(args) {
178466
178651
  error: `Historian failed while processing this session: ${desc.brief}`
178467
178652
  };
178468
178653
  } finally {
178469
- if (agentSessionId && outcomeOk) {
178654
+ if (agentSessionId && outcomeOk && !shouldKeepSubagents()) {
178470
178655
  await client.session.delete({ path: { id: agentSessionId } }).catch((e) => {
178471
178656
  sessionLog(parentSessionId, "compartment agent: session cleanup failed", getErrorMessage(e));
178472
178657
  });
178473
- } else if (agentSessionId && !outcomeOk) {
178474
- sessionLog(parentSessionId, `historian: KEEPING failed child session ${agentSessionId} for debugging (not deleted)`);
178658
+ } else if (agentSessionId && (!outcomeOk || shouldKeepSubagents())) {
178659
+ sessionLog(parentSessionId, `historian: KEEPING child session ${agentSessionId} (${outcomeOk ? "keep_subagents" : "failed"}) — not deleted`);
178475
178660
  }
178476
178661
  }
178477
178662
  }
@@ -178550,8 +178735,8 @@ function isTransientHistorianPromptError(message) {
178550
178735
  ].some((token) => normalized.includes(token));
178551
178736
  }
178552
178737
  function sleep(ms) {
178553
- return new Promise((resolve4) => {
178554
- setTimeout(resolve4, ms);
178738
+ return new Promise((resolve5) => {
178739
+ setTimeout(resolve5, ms);
178555
178740
  });
178556
178741
  }
178557
178742
  function cleanupHistorianDump(sessionId, dumpPath) {
@@ -178569,11 +178754,11 @@ function cleanupHistorianDump(sessionId, dumpPath) {
178569
178754
  function dumpHistorianResponse(sessionId, directory, label, text) {
178570
178755
  try {
178571
178756
  const dumpDir = historianResponseDumpDir(directory);
178572
- mkdirSync6(dumpDir, { recursive: true });
178757
+ mkdirSync7(dumpDir, { recursive: true });
178573
178758
  const safeSessionId = sanitizeDumpName(sessionId);
178574
178759
  const safeLabel = sanitizeDumpName(label);
178575
178760
  const dumpPath = join16(dumpDir, `${safeSessionId}-${safeLabel}-${Date.now()}.xml`);
178576
- writeFileSync3(dumpPath, text, "utf8");
178761
+ writeFileSync4(dumpPath, text, "utf8");
178577
178762
  sessionLog(sessionId, "compartment agent: historian response dumped", {
178578
178763
  label,
178579
178764
  dumpPath
@@ -178592,7 +178777,6 @@ function sanitizeDumpName(value) {
178592
178777
  }
178593
178778
 
178594
178779
  // ../plugin/src/hooks/magic-context/send-session-notification.ts
178595
- init_logger();
178596
178780
  function hasNotificationSessionClient(client) {
178597
178781
  if (client === null || typeof client !== "object")
178598
178782
  return false;
@@ -178691,11 +178875,7 @@ async function sendIgnoredMessage(client, sessionId, text, params, forcePersist
178691
178875
  var HISTORIAN_ALERT_COOLDOWN_MS2 = 60 * 1000;
178692
178876
  var lastHistorianAlertBySession2 = new Map;
178693
178877
 
178694
- // ../plugin/src/hooks/magic-context/compartment-runner-partial-recomp.ts
178695
- init_logger();
178696
-
178697
178878
  // ../plugin/src/hooks/magic-context/compartment-runner-recomp.ts
178698
- init_logger();
178699
178879
  function insertRecompCompartmentRows(db, sessionId, compartments, now) {
178700
178880
  const stmt = db.prepare("INSERT INTO compartments (session_id, sequence, start_message, end_message, start_message_id, end_message_id, title, content, p1, p2, p3, p4, importance, episode_type, legacy, created_at, harness) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
178701
178881
  for (const c of compartments) {
@@ -179464,9 +179644,6 @@ async function executeContextRecompWithResult(deps, options = {}) {
179464
179644
  }
179465
179645
  }
179466
179646
 
179467
- // src/commands/ctx-recomp.ts
179468
- init_logger();
179469
-
179470
179647
  // src/pi-recomp-client-shared.ts
179471
179648
  function createPiHistorianClient(args) {
179472
179649
  const sessions = new Map;
@@ -179598,9 +179775,6 @@ function resolvePiReadBranchEntries2(ctx) {
179598
179775
  };
179599
179776
  }
179600
179777
 
179601
- // src/pi-recomp-runner.ts
179602
- init_logger();
179603
-
179604
179778
  // src/status-line.ts
179605
179779
  var STATUS_KEY = "magic-context";
179606
179780
  var RECENT_FAILURE_MS = 60000;
@@ -179929,7 +180103,6 @@ function inferLevel(text) {
179929
180103
  }
179930
180104
 
179931
180105
  // ../plugin/src/features/magic-context/memory/memory-migration.ts
179932
- init_logger();
179933
180106
  function memoryMigrationGuardKey(projectPath) {
179934
180107
  return `memory_migration_5cat:${projectPath}`;
179935
180108
  }
@@ -180039,11 +180212,7 @@ function contextualizeUpgradeReason(reason) {
180039
180212
  return rewritten;
180040
180213
  }
180041
180214
 
180042
- // src/commands/ctx-session-upgrade.ts
180043
- init_logger();
180044
-
180045
180215
  // src/pi-memory-migration.ts
180046
- init_logger();
180047
180216
  var MIGRATION_SYSTEM_PROMPT2 = "You re-organize a software project's long-term memory into a stricter taxonomy. " + "Follow the user instructions exactly. Output ONLY the requested XML blocks, nothing else.";
180048
180217
  async function runPiMemoryMigration(deps) {
180049
180218
  const projectPath = resolveProjectIdentity(deps.directory);
@@ -180318,7 +180487,6 @@ ${migrationSummary}` : "",
180318
180487
  }
180319
180488
 
180320
180489
  // ../plugin/src/hooks/magic-context/execute-status.ts
180321
- init_logger();
180322
180490
  function formatExecuteThreshold(thresholdPercentage, mode, contextLimit) {
180323
180491
  if (mode === "tokens" && contextLimit > 0) {
180324
180492
  const tokens = Math.floor(thresholdPercentage / 100 * contextLimit);
@@ -180485,7 +180653,7 @@ function formatThresholdPercent(value) {
180485
180653
  // package.json
180486
180654
  var package_default = {
180487
180655
  name: "@wolfx/pi-magic-context",
180488
- version: "0.22.1-patch.0",
180656
+ version: "0.22.4",
180489
180657
  type: "module",
180490
180658
  description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
180491
180659
  main: "dist/index.js",
@@ -181070,10 +181238,6 @@ function computePiPressure(usage, contextLimit) {
181070
181238
  }
181071
181239
 
181072
181240
  // src/strip-tag-prefix.ts
181073
- var DEFAULT_PATTERNS = [
181074
- /^(\u00a7\d+\u00a7\s*)+/,
181075
- /\u00a7/g
181076
- ];
181077
181241
  function parseRegex(src) {
181078
181242
  if (src.startsWith("/")) {
181079
181243
  const lastSlash = src.lastIndexOf("/");
@@ -181085,43 +181249,42 @@ function parseRegex(src) {
181085
181249
  }
181086
181250
  return new RegExp(src);
181087
181251
  }
181088
- function resolveStripPatterns(stripConfig) {
181252
+ function stripTagPrefixFromAssistantMessage(message, stripConfig) {
181253
+ if (message.role !== "assistant")
181254
+ return false;
181255
+ if (!Array.isArray(message.content))
181256
+ return false;
181089
181257
  const isEnabled = stripConfig?.enabled ?? true;
181090
181258
  if (!isEnabled)
181091
- return [];
181259
+ return false;
181260
+ let patterns = null;
181092
181261
  if (stripConfig?.patterns && stripConfig.patterns.length > 0) {
181093
- return stripConfig.patterns.map(parseRegex);
181262
+ patterns = stripConfig.patterns.map(parseRegex);
181094
181263
  }
181095
- return DEFAULT_PATTERNS;
181096
- }
181097
- function createStripTagPrefixHandler(stripConfig) {
181098
- const patterns = resolveStripPatterns(stripConfig);
181099
- return function stripTagPrefixFromAssistantMessage(message) {
181100
- if (message.role !== "assistant")
181101
- return false;
181102
- if (!Array.isArray(message.content))
181103
- return false;
181104
- let mutated = false;
181105
- for (const part of message.content) {
181106
- if (part === null || typeof part !== "object" || part.type !== "text") {
181107
- continue;
181108
- }
181109
- const textPart = part;
181110
- if (typeof textPart.text !== "string")
181111
- continue;
181112
- let stripped = textPart.text;
181264
+ let mutated = false;
181265
+ for (const part of message.content) {
181266
+ if (part === null || typeof part !== "object" || part.type !== "text") {
181267
+ continue;
181268
+ }
181269
+ const textPart = part;
181270
+ if (typeof textPart.text !== "string")
181271
+ continue;
181272
+ let stripped;
181273
+ if (patterns) {
181274
+ stripped = textPart.text;
181113
181275
  for (const regex of patterns) {
181114
181276
  stripped = stripped.replace(regex, "");
181115
181277
  }
181116
- if (stripped !== textPart.text) {
181117
- textPart.text = stripped;
181118
- mutated = true;
181119
- }
181278
+ } else {
181279
+ stripped = stripPersistedAssistantText(textPart.text);
181120
181280
  }
181121
- return mutated;
181122
- };
181281
+ if (stripped !== textPart.text) {
181282
+ textPart.text = stripped;
181283
+ mutated = true;
181284
+ }
181285
+ }
181286
+ return mutated;
181123
181287
  }
181124
- var defaultHandler = createStripTagPrefixHandler();
181125
181288
 
181126
181289
  // ../plugin/src/tools/ctx-expand/constants.ts
181127
181290
  var CTX_EXPAND_DESCRIPTION = "Decompress a compartment range to see the original conversation transcript. " + 'Use start/end from <compartment start="N" end="M"> attributes. ' + "Returns the compacted U:/A: transcript for that message range, capped at ~15K tokens.";
@@ -185254,7 +185417,6 @@ function createCtxExpandTool(deps) {
185254
185417
  }
185255
185418
 
185256
185419
  // src/tools/ctx-memory.ts
185257
- init_logger();
185258
185420
  var DEFAULT_LIST_LIMIT = 10;
185259
185421
  var VALID_CATEGORIES = new Set(CATEGORY_PRIORITY);
185260
185422
  function isMemoryCategory2(value) {
@@ -185618,15 +185780,26 @@ function err3(text) {
185618
185780
  isError: true
185619
185781
  };
185620
185782
  }
185783
+ function captureAnchorOrdinal(db, sessionId) {
185784
+ try {
185785
+ const ordinal = getLastIndexedOrdinal(db, sessionId);
185786
+ return ordinal > 0 ? ordinal : null;
185787
+ } catch {
185788
+ return null;
185789
+ }
185790
+ }
185791
+ function anchorSuffix(note) {
185792
+ return note.anchorOrdinal !== null ? ` ↳ @msg ${note.anchorOrdinal}` : "";
185793
+ }
185621
185794
  function formatNoteLine(note) {
185622
185795
  if (note.type === "smart") {
185623
185796
  const conditionLine = note.status === "ready" ? note.readyReason ?? note.surfaceCondition ?? "Condition satisfied" : note.surfaceCondition ?? "No condition recorded";
185624
185797
  const statusSuffix2 = note.status === "active" ? "" : ` (${note.status})`;
185625
- return `- **#${note.id}**${statusSuffix2}: ${note.content}
185798
+ return `- **#${note.id}**${statusSuffix2}: ${note.content}${anchorSuffix(note)}
185626
185799
  *Condition*: ${conditionLine}`;
185627
185800
  }
185628
185801
  const statusSuffix = note.status === "active" ? "" : ` (${note.status})`;
185629
- return `- **#${note.id}**${statusSuffix}: ${note.content}`;
185802
+ return `- **#${note.id}**${statusSuffix}: ${note.content}${anchorSuffix(note)}`;
185630
185803
  }
185631
185804
  var DISMISS_FOOTER = `
185632
185805
 
@@ -185648,6 +185821,7 @@ function createCtxNoteTool(deps) {
185648
185821
  const content = params.content?.trim();
185649
185822
  if (!content)
185650
185823
  return err3("Error: 'content' is required when action is 'write'.");
185824
+ const anchorOrdinal = captureAnchorOrdinal(deps.db, sessionId);
185651
185825
  const surfaceCondition = params.surface_condition?.trim();
185652
185826
  if (surfaceCondition) {
185653
185827
  if (deps.dreamerEnabled !== true) {
@@ -185660,13 +185834,18 @@ function createCtxNoteTool(deps) {
185660
185834
  const note2 = addNote(deps.db, "smart", {
185661
185835
  content,
185662
185836
  projectPath: projectIdentity,
185663
- surfaceCondition
185837
+ surfaceCondition,
185838
+ anchorOrdinal
185664
185839
  });
185665
185840
  return ok3(`Created smart note #${note2.id}. Dreamer will evaluate the condition during nightly runs:
185666
185841
  - Content: ${content}
185667
185842
  - Condition: ${surfaceCondition}`);
185668
185843
  }
185669
- const note = addNote(deps.db, "session", { sessionId, content });
185844
+ const note = addNote(deps.db, "session", {
185845
+ sessionId,
185846
+ content,
185847
+ anchorOrdinal
185848
+ });
185670
185849
  return ok3(`Saved session note #${note.id}.`);
185671
185850
  }
185672
185851
  if (action2 === "dismiss") {
@@ -185729,9 +185908,13 @@ function createCtxNoteTool(deps) {
185729
185908
 
185730
185909
  No notes for the current filter.`);
185731
185910
  }
185732
- return ok3(`${sections.join(`
185911
+ const body = sections.join(`
185912
+
185913
+ `);
185914
+ const anchorHint = body.includes("↳ @msg ") ? `
185733
185915
 
185734
- `)}${DISMISS_FOOTER}`);
185916
+ ↳ @msg N marks the conversation tail when a note was written. To see what led to it: ctx_expand(start=N-x, end=N) (pick x for how far back to look).` : "";
185917
+ return ok3(`${body}${anchorHint}${DISMISS_FOOTER}`);
185735
185918
  }
185736
185919
  };
185737
185920
  }
@@ -186076,7 +186259,8 @@ function createCtxSearchTool(deps) {
186076
186259
  maxMessageOrdinal: lastCompartmentEnd >= 0 ? lastCompartmentEnd : undefined,
186077
186260
  gitCommitsEnabled,
186078
186261
  sources: params.sources,
186079
- visibleMemoryIds
186262
+ visibleMemoryIds,
186263
+ explicitSearch: true
186080
186264
  });
186081
186265
  return {
186082
186266
  content: [{ type: "text", text: formatSearchResults(query, results) }],
@@ -186224,8 +186408,7 @@ function getPiMessageModel(message) {
186224
186408
  };
186225
186409
  }
186226
186410
  function resolvePiPressureContextLimit(args) {
186227
- const cachedLimit = args.provider && args.model ? getModelsDevContextLimit(args.provider, args.model) : undefined;
186228
- let effectiveContextLimit = cachedLimit ?? args.piContextWindow;
186411
+ let effectiveContextLimit = isSaneLimit(args.piContextWindow) ? args.piContextWindow : 0;
186229
186412
  try {
186230
186413
  const overflowState = getOverflowState(args.db, args.sessionId);
186231
186414
  if (overflowState.detectedContextLimit > 0) {
@@ -186241,8 +186424,6 @@ async function persistPiPressureFromMessageEnd(args) {
186241
186424
  const effectiveContextLimit = resolvePiPressureContextLimit({
186242
186425
  db: args.db,
186243
186426
  sessionId: args.sessionId,
186244
- provider: provider2,
186245
- model,
186246
186427
  piContextWindow: args.piContextWindow
186247
186428
  });
186248
186429
  const usage = extractAssistantUsage(args.message);
@@ -186251,28 +186432,16 @@ async function persistPiPressureFromMessageEnd(args) {
186251
186432
  const messageHadOverflowError = typeof msg?.errorMessage === "string" && detectOverflow(msg.errorMessage).isOverflow;
186252
186433
  const updates = { lastResponseTime: Date.now() };
186253
186434
  if (pressure) {
186254
- let percentage = pressure.percentage;
186255
- let contextLimit = effectiveContextLimit;
186435
+ const percentage = pressure.percentage;
186436
+ const contextLimit = effectiveContextLimit;
186256
186437
  const meta3 = getOrCreateSessionMeta(args.db, args.sessionId);
186257
186438
  const observedSafeInputTokens = meta3.observedSafeInputTokens ?? 0;
186258
186439
  if (percentage > 100 && observedSafeInputTokens > 0 && pressure.inputTokens <= observedSafeInputTokens * 2) {
186259
- const oldLimit = contextLimit;
186260
- clearModelsDevCache();
186261
- contextLimit = resolvePiPressureContextLimit({
186262
- db: args.db,
186263
- sessionId: args.sessionId,
186264
- provider: provider2,
186265
- model,
186266
- piContextWindow: args.piContextWindow
186267
- });
186268
- if (contextLimit >= pressure.inputTokens) {
186269
- percentage = pressure.inputTokens / contextLimit * 100;
186270
- log(`${PREFIX} models-dev-cache: regression recovered for ${provider2}/${model} via Pi cache reload (was=${oldLimit}, now=${contextLimit})`);
186271
- } else if (!meta3.cacheAlertSent) {
186440
+ if (!meta3.cacheAlertSent) {
186272
186441
  updates.cacheAlertSent = true;
186273
186442
  const safeTokens = Math.max(observedSafeInputTokens, pressure.inputTokens);
186274
186443
  const modelLabel = provider2 && model ? `${provider2}/${model}` : "the active model";
186275
- await args.notifyIssue?.(`⚠️ Magic Context: Pi reports a context limit of ${formatTokens(contextLimit)} tokens for ${modelLabel} but you've successfully sent ${formatTokens(safeTokens)} tokens in this session — the cached limit looks wrong. Restart Pi if you suspect this is incorrect.`);
186444
+ await args.notifyIssue?.(`⚠️ Magic Context: Pi reports a context limit of ${formatTokens(contextLimit)} tokens for ${modelLabel} but you've successfully sent ${formatTokens(safeTokens)} tokens in this session — the reported limit looks wrong. Restart Pi if you suspect this is incorrect.`);
186276
186445
  }
186277
186446
  }
186278
186447
  updates.lastContextPercentage = percentage;
@@ -186415,6 +186584,7 @@ async function src_default2(pi) {
186415
186584
  mmapSizeMb: config2.sqlite.mmap_size_mb
186416
186585
  });
186417
186586
  applySqliteTuningPragmas(db);
186587
+ setKeepSubagents(config2.keep_subagents === true);
186418
186588
  if (!config2.enabled) {
186419
186589
  info("plugin DISABLED via config (enabled: false) — skipping registration");
186420
186590
  return;
@@ -186710,15 +186880,14 @@ ${block}` : event.systemPrompt;
186710
186880
  info("session_before_compact: cancelling — magic-context owns compaction");
186711
186881
  return { cancel: true };
186712
186882
  });
186713
- const stripTagPrefix3 = createStripTagPrefixHandler(config2.text_complete_strip);
186714
186883
  pi.on("message_end", async (event, ctx) => {
186715
186884
  try {
186716
186885
  const msg = event.message;
186717
186886
  if (msg !== null && typeof msg === "object") {
186718
- stripTagPrefix3(msg);
186887
+ stripTagPrefixFromAssistantMessage(msg, config2.text_complete_strip);
186719
186888
  }
186720
186889
  } catch (err5) {
186721
- warn("message_end: stripTagPrefix threw:", err5);
186890
+ warn("message_end: stripTagPrefixFromAssistantMessage threw:", err5);
186722
186891
  }
186723
186892
  try {
186724
186893
  const sm = ctx.sessionManager;
@@ -186740,7 +186909,7 @@ ${block}` : event.systemPrompt;
186740
186909
  cacheTtlConfig: config2.cache_ttl
186741
186910
  });
186742
186911
  const piUsage = ctx.getContextUsage?.();
186743
- const piContextWindow = piUsage && typeof piUsage.contextWindow === "number" ? piUsage.contextWindow : 0;
186912
+ const piContextWindow = piUsage && typeof piUsage.contextWindow === "number" && piUsage.contextWindow > 0 ? piUsage.contextWindow : ctx.model?.contextWindow ?? 0;
186744
186913
  await persistPiPressureFromMessageEnd({
186745
186914
  db,
186746
186915
  sessionId,