@cortexkit/pi-magic-context 0.31.5 → 0.32.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +3205 -1176
- package/dist/subagent-entry.js +911 -342
- package/package.json +1 -1
package/dist/subagent-entry.js
CHANGED
|
@@ -8128,11 +8128,11 @@ function buildNodeSqliteDatabaseClass(DatabaseSync) {
|
|
|
8128
8128
|
}
|
|
8129
8129
|
transaction(fn) {
|
|
8130
8130
|
const self = this;
|
|
8131
|
-
const
|
|
8131
|
+
const execute = (mode, receiver, args) => {
|
|
8132
8132
|
const nested = self.isTransaction === true;
|
|
8133
|
-
self.exec(nested ? `SAVEPOINT ${SAVEPOINT}` :
|
|
8133
|
+
self.exec(nested ? `SAVEPOINT ${SAVEPOINT}` : `BEGIN${mode ? ` ${mode}` : ""}`);
|
|
8134
8134
|
try {
|
|
8135
|
-
const result = fn.apply(
|
|
8135
|
+
const result = fn.apply(receiver, args);
|
|
8136
8136
|
self.exec(nested ? `RELEASE ${SAVEPOINT}` : "COMMIT");
|
|
8137
8137
|
return result;
|
|
8138
8138
|
} catch (error) {
|
|
@@ -8145,6 +8145,21 @@ function buildNodeSqliteDatabaseClass(DatabaseSync) {
|
|
|
8145
8145
|
throw error;
|
|
8146
8146
|
}
|
|
8147
8147
|
};
|
|
8148
|
+
const wrapped = function(...args) {
|
|
8149
|
+
return execute("", this, args);
|
|
8150
|
+
};
|
|
8151
|
+
wrapped.default = function(...args) {
|
|
8152
|
+
return execute("", this, args);
|
|
8153
|
+
};
|
|
8154
|
+
wrapped.deferred = function(...args) {
|
|
8155
|
+
return execute("DEFERRED", this, args);
|
|
8156
|
+
};
|
|
8157
|
+
wrapped.immediate = function(...args) {
|
|
8158
|
+
return execute("IMMEDIATE", this, args);
|
|
8159
|
+
};
|
|
8160
|
+
wrapped.exclusive = function(...args) {
|
|
8161
|
+
return execute("EXCLUSIVE", this, args);
|
|
8162
|
+
};
|
|
8148
8163
|
return wrapped;
|
|
8149
8164
|
}
|
|
8150
8165
|
}
|
|
@@ -8188,10 +8203,16 @@ function healAllNullColumns(db) {
|
|
|
8188
8203
|
healNullIntegerColumns(db);
|
|
8189
8204
|
healMissingMemoryBlockIds(db);
|
|
8190
8205
|
}
|
|
8206
|
+
function getSessionMetaColumns(db) {
|
|
8207
|
+
const rows = db.prepare("PRAGMA table_info(session_meta)").all();
|
|
8208
|
+
return new Set(rows.flatMap((row) => typeof row.name === "string" ? [row.name] : []));
|
|
8209
|
+
}
|
|
8191
8210
|
function healMissingMemoryBlockIds(db) {
|
|
8192
|
-
|
|
8193
|
-
|
|
8194
|
-
|
|
8211
|
+
const columns = getSessionMetaColumns(db);
|
|
8212
|
+
if (!columns.has("memory_block_cache") || !columns.has("memory_block_ids") || !columns.has("memory_block_count")) {
|
|
8213
|
+
return;
|
|
8214
|
+
}
|
|
8215
|
+
db.prepare("UPDATE session_meta SET memory_block_cache = '' WHERE memory_block_cache != '' AND (memory_block_ids IS NULL OR memory_block_ids = '') AND memory_block_count > 0").run();
|
|
8195
8216
|
}
|
|
8196
8217
|
function healNullTextColumns(db) {
|
|
8197
8218
|
const columns = [
|
|
@@ -8220,10 +8241,11 @@ function healNullTextColumns(db) {
|
|
|
8220
8241
|
["compaction_marker_state", ""],
|
|
8221
8242
|
["key_files", ""]
|
|
8222
8243
|
];
|
|
8244
|
+
const existingColumns = getSessionMetaColumns(db);
|
|
8223
8245
|
for (const [column, fallback] of columns) {
|
|
8224
|
-
|
|
8225
|
-
|
|
8226
|
-
}
|
|
8246
|
+
if (!existingColumns.has(column))
|
|
8247
|
+
continue;
|
|
8248
|
+
db.prepare(`UPDATE session_meta SET ${column} = ? WHERE ${column} IS NULL`).run(fallback);
|
|
8227
8249
|
}
|
|
8228
8250
|
}
|
|
8229
8251
|
function healNullIntegerColumns(db) {
|
|
@@ -8254,10 +8276,11 @@ function healNullIntegerColumns(db) {
|
|
|
8254
8276
|
["emergency_drain_active", 0],
|
|
8255
8277
|
["historian_drain_failure_at", 0]
|
|
8256
8278
|
];
|
|
8279
|
+
const existingColumns = getSessionMetaColumns(db);
|
|
8257
8280
|
for (const [column, fallback] of columns) {
|
|
8258
|
-
|
|
8259
|
-
|
|
8260
|
-
}
|
|
8281
|
+
if (!existingColumns.has(column))
|
|
8282
|
+
continue;
|
|
8283
|
+
db.prepare(`UPDATE session_meta SET ${column} = ? WHERE ${column} IS NULL`).run(fallback);
|
|
8261
8284
|
}
|
|
8262
8285
|
}
|
|
8263
8286
|
|
|
@@ -10209,6 +10232,34 @@ var MIGRATIONS = [
|
|
|
10209
10232
|
ensureColumn(db, "session_meta", "wrapup_in_progress_state", "TEXT");
|
|
10210
10233
|
}
|
|
10211
10234
|
}
|
|
10235
|
+
},
|
|
10236
|
+
{
|
|
10237
|
+
version: 51,
|
|
10238
|
+
description: "version tool-owner backfill state and repair legacy NULL session metadata",
|
|
10239
|
+
up(db) {
|
|
10240
|
+
db.exec(`
|
|
10241
|
+
CREATE TABLE IF NOT EXISTS tool_owner_backfill_state (
|
|
10242
|
+
session_id TEXT PRIMARY KEY,
|
|
10243
|
+
status TEXT NOT NULL CHECK (status IN ('pending', 'running', 'completed', 'skipped')),
|
|
10244
|
+
started_at INTEGER,
|
|
10245
|
+
lease_expires_at INTEGER,
|
|
10246
|
+
completed_at INTEGER,
|
|
10247
|
+
last_error TEXT
|
|
10248
|
+
);
|
|
10249
|
+
CREATE INDEX IF NOT EXISTS idx_tool_owner_backfill_state_status
|
|
10250
|
+
ON tool_owner_backfill_state(status);
|
|
10251
|
+
`);
|
|
10252
|
+
healAllNullColumns(db);
|
|
10253
|
+
}
|
|
10254
|
+
},
|
|
10255
|
+
{
|
|
10256
|
+
version: 52,
|
|
10257
|
+
description: "persist emergency recovery origin",
|
|
10258
|
+
up(db) {
|
|
10259
|
+
if (tableExists2(db, "session_meta")) {
|
|
10260
|
+
ensureColumn(db, "session_meta", "emergency_recovery_origin", "TEXT DEFAULT ''");
|
|
10261
|
+
}
|
|
10262
|
+
}
|
|
10212
10263
|
}
|
|
10213
10264
|
];
|
|
10214
10265
|
var LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
|
|
@@ -10238,40 +10289,45 @@ function isSiblingMigrationConflict(db, error, version) {
|
|
|
10238
10289
|
}
|
|
10239
10290
|
function runMigrations(db) {
|
|
10240
10291
|
ensureMigrationsTable(db);
|
|
10241
|
-
let
|
|
10242
|
-
|
|
10243
|
-
|
|
10244
|
-
|
|
10245
|
-
}
|
|
10246
|
-
log(`[migrations] current schema version: ${currentVersion}, applying ${pendingMigrations.length} migration(s)`);
|
|
10247
|
-
let migrationIndex = 0;
|
|
10248
|
-
while (migrationIndex < pendingMigrations.length) {
|
|
10249
|
-
const migration = pendingMigrations[migrationIndex];
|
|
10292
|
+
let loggedPlan = false;
|
|
10293
|
+
while (true) {
|
|
10294
|
+
let migration;
|
|
10295
|
+
let currentVersion = 0;
|
|
10250
10296
|
try {
|
|
10251
|
-
db.transaction(() => {
|
|
10297
|
+
const applied = db.transaction(() => {
|
|
10298
|
+
currentVersion = getCurrentVersion(db);
|
|
10299
|
+
migration = MIGRATIONS.find((candidate) => candidate.version > currentVersion);
|
|
10300
|
+
if (!migration)
|
|
10301
|
+
return false;
|
|
10302
|
+
if (!loggedPlan) {
|
|
10303
|
+
const pendingCount = MIGRATIONS.filter((candidate) => candidate.version > currentVersion).length;
|
|
10304
|
+
log(`[migrations] current schema version: ${currentVersion}, applying ${pendingCount} migration(s)`);
|
|
10305
|
+
loggedPlan = true;
|
|
10306
|
+
}
|
|
10252
10307
|
migration.up(db);
|
|
10253
10308
|
db.prepare("INSERT INTO schema_migrations (version, description, applied_at) VALUES (?, ?, ?)").run(migration.version, migration.description, Date.now());
|
|
10254
|
-
|
|
10309
|
+
return true;
|
|
10310
|
+
}).immediate();
|
|
10311
|
+
if (!applied || !migration)
|
|
10312
|
+
break;
|
|
10255
10313
|
log(`[migrations] applied v${migration.version}: ${migration.description}`);
|
|
10256
|
-
migrationIndex += 1;
|
|
10257
10314
|
} catch (error) {
|
|
10258
|
-
if (isSiblingMigrationConflict(db, error, migration.version)) {
|
|
10315
|
+
if (migration && isSiblingMigrationConflict(db, error, migration.version)) {
|
|
10259
10316
|
log(`[migrations] v${migration.version} already applied by sibling instance — resuming with re-read version`);
|
|
10260
10317
|
const reReadVersion = getCurrentVersion(db);
|
|
10261
|
-
if (reReadVersion
|
|
10262
|
-
|
|
10263
|
-
|
|
10264
|
-
}
|
|
10265
|
-
currentVersion = reReadVersion;
|
|
10266
|
-
pendingMigrations = MIGRATIONS.filter((m) => m.version > currentVersion);
|
|
10267
|
-
migrationIndex = 0;
|
|
10268
|
-
continue;
|
|
10318
|
+
if (reReadVersion > currentVersion)
|
|
10319
|
+
continue;
|
|
10320
|
+
throw new Error(`Migration v${migration.version} failed: sibling conflict reported but version did not advance. Database may need manual repair.`);
|
|
10269
10321
|
}
|
|
10270
|
-
|
|
10271
|
-
|
|
10322
|
+
const version = migration?.version ?? currentVersion + 1;
|
|
10323
|
+
const description = migration?.description ?? "acquire migration write lock";
|
|
10324
|
+
log(`[migrations] FAILED v${version}: ${description} — ${error instanceof Error ? error.message : String(error)}`);
|
|
10325
|
+
throw new Error(`Migration v${version} failed: ${error instanceof Error ? error.message : String(error)}. Database may need manual repair.`);
|
|
10272
10326
|
}
|
|
10273
10327
|
}
|
|
10274
|
-
|
|
10328
|
+
if (loggedPlan) {
|
|
10329
|
+
log(`[migrations] schema version now: ${MIGRATIONS[MIGRATIONS.length - 1].version}`);
|
|
10330
|
+
}
|
|
10275
10331
|
}
|
|
10276
10332
|
|
|
10277
10333
|
// ../plugin/src/shared/commit-detection.ts
|
|
@@ -143025,7 +143081,8 @@ function countSessionsByStatus(db, status) {
|
|
|
143025
143081
|
function acquireSessionLease(db, sessionId, now) {
|
|
143026
143082
|
const expiresAt = now + LEASE_DURATION_MS;
|
|
143027
143083
|
const result = db.prepare(`INSERT INTO tool_owner_backfill_state(session_id, status, started_at, lease_expires_at)
|
|
143028
|
-
|
|
143084
|
+
SELECT ?, 'running', ?, ?
|
|
143085
|
+
WHERE EXISTS (SELECT 1 FROM tags WHERE session_id = ?)
|
|
143029
143086
|
ON CONFLICT(session_id) DO UPDATE SET
|
|
143030
143087
|
status = 'running',
|
|
143031
143088
|
started_at = excluded.started_at,
|
|
@@ -143033,7 +143090,7 @@ function acquireSessionLease(db, sessionId, now) {
|
|
|
143033
143090
|
last_error = NULL
|
|
143034
143091
|
WHERE tool_owner_backfill_state.status IN ('pending', 'skipped')
|
|
143035
143092
|
OR (tool_owner_backfill_state.status = 'running'
|
|
143036
|
-
AND tool_owner_backfill_state.lease_expires_at < ?)`).run(sessionId, now, expiresAt, now);
|
|
143093
|
+
AND tool_owner_backfill_state.lease_expires_at < ?)`).run(sessionId, now, expiresAt, sessionId, now);
|
|
143037
143094
|
return (result.changes ?? 0) === 1;
|
|
143038
143095
|
}
|
|
143039
143096
|
function renewSessionLease(db, sessionId, now) {
|
|
@@ -143053,13 +143110,9 @@ function markSessionPendingRetry(db, sessionId) {
|
|
|
143053
143110
|
WHERE session_id = ?`).run(sessionId);
|
|
143054
143111
|
}
|
|
143055
143112
|
function markSessionSkipped(db, sessionId, now, reason) {
|
|
143056
|
-
db.prepare(`
|
|
143057
|
-
|
|
143058
|
-
|
|
143059
|
-
status = 'skipped',
|
|
143060
|
-
completed_at = excluded.completed_at,
|
|
143061
|
-
last_error = excluded.last_error,
|
|
143062
|
-
lease_expires_at = NULL`).run(sessionId, now, reason);
|
|
143113
|
+
db.prepare(`UPDATE tool_owner_backfill_state
|
|
143114
|
+
SET status = 'skipped', completed_at = ?, last_error = ?, lease_expires_at = NULL
|
|
143115
|
+
WHERE session_id = ? AND status = 'running'`).run(now, reason, sessionId);
|
|
143063
143116
|
}
|
|
143064
143117
|
function markSessionErrored(db, sessionId, error) {
|
|
143065
143118
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -143143,7 +143196,7 @@ function applyOwnersForSession(db, sessionId, ownersByCallId) {
|
|
|
143143
143196
|
const result = updateRowStmt.run(ownerId, orphan.id);
|
|
143144
143197
|
rowsUpdated += result.changes ?? 0;
|
|
143145
143198
|
}
|
|
143146
|
-
})();
|
|
143199
|
+
}).immediate();
|
|
143147
143200
|
const rowsLeftNull = db.prepare(`SELECT COUNT(*) AS c FROM tags
|
|
143148
143201
|
WHERE session_id = ? AND type = 'tool'
|
|
143149
143202
|
AND tool_owner_message_id IS NULL`).get(sessionId).c;
|
|
@@ -143193,7 +143246,7 @@ var persistenceByDatabase = new WeakMap;
|
|
|
143193
143246
|
var persistenceErrorByDatabase = new WeakMap;
|
|
143194
143247
|
var pathByDatabase = new WeakMap;
|
|
143195
143248
|
var lastSchemaFenceRejection = null;
|
|
143196
|
-
var LATEST_SUPPORTED_VERSION =
|
|
143249
|
+
var LATEST_SUPPORTED_VERSION = 52;
|
|
143197
143250
|
var PERMISSIONS_ENFORCEABLE = process.platform !== "win32";
|
|
143198
143251
|
function ensureSecureStorageDir(dir) {
|
|
143199
143252
|
mkdirSync3(dir, { recursive: true, mode: 448 });
|
|
@@ -143886,6 +143939,17 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
143886
143939
|
pi_stable_id_scheme INTEGER
|
|
143887
143940
|
);
|
|
143888
143941
|
|
|
143942
|
+
CREATE TABLE IF NOT EXISTS tool_owner_backfill_state (
|
|
143943
|
+
session_id TEXT PRIMARY KEY,
|
|
143944
|
+
status TEXT NOT NULL CHECK (status IN ('pending', 'running', 'completed', 'skipped')),
|
|
143945
|
+
started_at INTEGER,
|
|
143946
|
+
lease_expires_at INTEGER,
|
|
143947
|
+
completed_at INTEGER,
|
|
143948
|
+
last_error TEXT
|
|
143949
|
+
);
|
|
143950
|
+
CREATE INDEX IF NOT EXISTS idx_tool_owner_backfill_state_status
|
|
143951
|
+
ON tool_owner_backfill_state(status);
|
|
143952
|
+
|
|
143889
143953
|
CREATE TABLE IF NOT EXISTS subagent_invocations (
|
|
143890
143954
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
143891
143955
|
session_id TEXT NOT NULL,
|
|
@@ -144119,6 +144183,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
144119
144183
|
ensureColumn(db, "session_meta", "detected_context_limit", "INTEGER DEFAULT 0");
|
|
144120
144184
|
ensureColumn(db, "session_meta", "detected_context_limit_model_key", "TEXT");
|
|
144121
144185
|
ensureColumn(db, "session_meta", "needs_emergency_recovery", "INTEGER DEFAULT 0");
|
|
144186
|
+
ensureColumn(db, "session_meta", "emergency_recovery_origin", "TEXT DEFAULT ''");
|
|
144122
144187
|
ensureColumn(db, "session_meta", "pending_compaction_marker_state", "TEXT");
|
|
144123
144188
|
ensureColumn(db, "session_meta", "pending_pi_compaction_marker_state", "TEXT");
|
|
144124
144189
|
ensureColumn(db, "session_meta", "new_work_tokens", "INTEGER NOT NULL DEFAULT 0");
|
|
@@ -159576,10 +159641,10 @@ function civilMinuteKey(date5) {
|
|
|
159576
159641
|
const p = (n, w = 2) => String(n).padStart(w, "0");
|
|
159577
159642
|
return `${p(date5.getFullYear(), 4)}-${p(date5.getMonth() + 1)}-${p(date5.getDate())} ${p(date5.getHours())}:${p(date5.getMinutes())}`;
|
|
159578
159643
|
}
|
|
159579
|
-
function nextOccurrence(cron, after, excludeCivilMinute) {
|
|
159644
|
+
function nextOccurrence(cron, after, excludeCivilMinute, maxSearchMs = MAX_SEARCH_MS) {
|
|
159580
159645
|
const afterMs = after.getTime();
|
|
159581
159646
|
let cursorMs = Math.floor(afterMs / MINUTE_MS) * MINUTE_MS + MINUTE_MS;
|
|
159582
|
-
const capMs = afterMs + MAX_SEARCH_MS;
|
|
159647
|
+
const capMs = afterMs + Math.max(0, Math.min(MAX_SEARCH_MS, maxSearchMs));
|
|
159583
159648
|
while (cursorMs <= capMs) {
|
|
159584
159649
|
const candidate = new Date(cursorMs);
|
|
159585
159650
|
if (matchesCron(cron, candidate)) {
|
|
@@ -159591,14 +159656,14 @@ function nextOccurrence(cron, after, excludeCivilMinute) {
|
|
|
159591
159656
|
}
|
|
159592
159657
|
return null;
|
|
159593
159658
|
}
|
|
159594
|
-
function nextDueAtMs(expression, afterMs, consumedScheduledAtMs) {
|
|
159659
|
+
function nextDueAtMs(expression, afterMs, consumedScheduledAtMs, maxSearchMs = MAX_SEARCH_MS) {
|
|
159595
159660
|
if (expression.trim().length === 0)
|
|
159596
159661
|
return null;
|
|
159597
159662
|
const parsed = parseCron(expression);
|
|
159598
159663
|
if (!parsed.ok)
|
|
159599
159664
|
return null;
|
|
159600
159665
|
const exclude = consumedScheduledAtMs !== undefined ? civilMinuteKey(new Date(consumedScheduledAtMs)) : undefined;
|
|
159601
|
-
const next = nextOccurrence(parsed.cron, new Date(afterMs), exclude);
|
|
159666
|
+
const next = nextOccurrence(parsed.cron, new Date(afterMs), exclude, maxSearchMs);
|
|
159602
159667
|
return next ? next.getTime() : null;
|
|
159603
159668
|
}
|
|
159604
159669
|
|
|
@@ -159849,8 +159914,11 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
159849
159914
|
provider: "local",
|
|
159850
159915
|
model: DEFAULT_LOCAL_EMBEDDING_MODEL
|
|
159851
159916
|
}).describe("Embedding provider configuration"),
|
|
159852
|
-
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
|
|
159917
|
+
temporal_awareness: exports_external.boolean().default(true).describe('Inject wall-clock gap markers (<!-- +Xm -->) between user messages where > 5 min elapsed since the previous message, and add compact date ranges to compartment headings. Gives the agent a sense of session pacing and "how long ago" across multi-day sessions. Graduated from experimental.temporal_awareness; default: true (set false to opt out).'),
|
|
159853
159918
|
keep_subagents: exports_external.boolean().default(false).describe("Debug: keep the child sessions Magic Context spawns for its own subagents (historian, dreamer, sidekick, memory-migration) instead of deleting them on success. Useful for short-term inspection/data collection — their full transcript (prompt, tool calls, token usage, output) stays in the host session store. Kept sessions accumulate until manually cleared; leave false for normal use. Requires a restart to take effect."),
|
|
159919
|
+
shadow_transform: exports_external.object({
|
|
159920
|
+
enabled: exports_external.boolean().default(false).describe("Dev flag: mirror every transform pass to the Magic Context Rust module over subc and byte-compare outputs. No behavior impact; default off.")
|
|
159921
|
+
}).default({ enabled: false }).describe("Developer-only shadow transform lane. When enabled, the plugin fire-and-forgets a copy of each finalized transform to the Rust module for comparison; the live output is unchanged."),
|
|
159854
159922
|
todowrite: exports_external.object({
|
|
159855
159923
|
enabled: exports_external.boolean().default(true).describe("Pi only: register Magic Context's todowrite task-list tool. Disable if you use your own todo extension. OpenCode ships its own built-in todowrite; this setting has no effect there."),
|
|
159856
159924
|
overlay: exports_external.boolean().default(true).describe("Pi only: show the persistent todo overlay above the editor while tasks are active.")
|
|
@@ -160007,6 +160075,10 @@ function stripUnsafeProjectConfigFields(projectRaw) {
|
|
|
160007
160075
|
delete projectRaw.sqlite;
|
|
160008
160076
|
warnings.push("Ignoring sqlite.* from project config (security: SQLite cache/mmap PRAGMAs apply to the " + "process-global shared database handle; only user-level config may set them).");
|
|
160009
160077
|
}
|
|
160078
|
+
if ("shadow_transform" in projectRaw) {
|
|
160079
|
+
delete projectRaw.shadow_transform;
|
|
160080
|
+
warnings.push("Ignoring shadow_transform from project config (security: this developer-only mirror lane is user-level only).");
|
|
160081
|
+
}
|
|
160010
160082
|
const embedding = projectRaw.embedding;
|
|
160011
160083
|
if (isPlainObject3(embedding)) {
|
|
160012
160084
|
const removed = [];
|
|
@@ -160679,6 +160751,9 @@ function loadPiConfigDetailed(opts = {}) {
|
|
|
160679
160751
|
};
|
|
160680
160752
|
}
|
|
160681
160753
|
|
|
160754
|
+
// src/embedding-bootstrap.ts
|
|
160755
|
+
import { statSync as statSync3 } from "node:fs";
|
|
160756
|
+
|
|
160682
160757
|
// ../plugin/src/features/magic-context/memory/embedding.ts
|
|
160683
160758
|
init_logger();
|
|
160684
160759
|
|
|
@@ -160832,22 +160907,6 @@ function getInsertEmbeddingStatement(db) {
|
|
|
160832
160907
|
}
|
|
160833
160908
|
return stmt;
|
|
160834
160909
|
}
|
|
160835
|
-
function getClearProjectStatement(db) {
|
|
160836
|
-
let stmt = clearProjectStatements.get(db);
|
|
160837
|
-
if (!stmt) {
|
|
160838
|
-
stmt = db.prepare("DELETE FROM compartment_chunk_embeddings WHERE project_path = ?");
|
|
160839
|
-
clearProjectStatements.set(db, stmt);
|
|
160840
|
-
}
|
|
160841
|
-
return stmt;
|
|
160842
|
-
}
|
|
160843
|
-
function getClearProjectModelStatement(db) {
|
|
160844
|
-
let stmt = clearProjectModelStatements.get(db);
|
|
160845
|
-
if (!stmt) {
|
|
160846
|
-
stmt = db.prepare("DELETE FROM compartment_chunk_embeddings WHERE project_path = ? AND model_id = ?");
|
|
160847
|
-
clearProjectModelStatements.set(db, stmt);
|
|
160848
|
-
}
|
|
160849
|
-
return stmt;
|
|
160850
|
-
}
|
|
160851
160910
|
function getSearchRowsStatement(db, withModel) {
|
|
160852
160911
|
const map2 = withModel ? searchRowsByModelStatements : searchRowsStatements;
|
|
160853
160912
|
let stmt = map2.get(db);
|
|
@@ -161151,12 +161210,6 @@ function replaceCompartmentChunkEmbeddings(db, rows) {
|
|
|
161151
161210
|
}
|
|
161152
161211
|
})();
|
|
161153
161212
|
}
|
|
161154
|
-
function clearChunkEmbeddingsForProject(db, projectPath, modelId) {
|
|
161155
|
-
if (modelId) {
|
|
161156
|
-
return getClearProjectModelStatement(db).run(projectPath, modelId).changes;
|
|
161157
|
-
}
|
|
161158
|
-
return getClearProjectStatement(db).run(projectPath).changes;
|
|
161159
|
-
}
|
|
161160
161213
|
function loadCompartmentChunkEmbeddingsForSearch(db, sessionId, projectPath, modelId) {
|
|
161161
161214
|
if (!modelId) {
|
|
161162
161215
|
throw new Error("loadCompartmentChunkEmbeddingsForSearch requires a current model id");
|
|
@@ -162081,22 +162134,6 @@ function getLoadAllEmbeddingsStatement(db) {
|
|
|
162081
162134
|
}
|
|
162082
162135
|
return stmt;
|
|
162083
162136
|
}
|
|
162084
|
-
function getClearAllEmbeddingsStatement(db) {
|
|
162085
|
-
let stmt = clearAllEmbeddingsStatements.get(db);
|
|
162086
|
-
if (!stmt) {
|
|
162087
|
-
stmt = db.prepare("DELETE FROM memory_embeddings WHERE memory_id IN (SELECT id FROM memories WHERE project_path = ?)");
|
|
162088
|
-
clearAllEmbeddingsStatements.set(db, stmt);
|
|
162089
|
-
}
|
|
162090
|
-
return stmt;
|
|
162091
|
-
}
|
|
162092
|
-
function getClearModelEmbeddingsStatement(db) {
|
|
162093
|
-
let stmt = clearModelEmbeddingsStatements.get(db);
|
|
162094
|
-
if (!stmt) {
|
|
162095
|
-
stmt = db.prepare("DELETE FROM memory_embeddings WHERE model_id = ? AND memory_id IN (SELECT id FROM memories WHERE project_path = ?)");
|
|
162096
|
-
clearModelEmbeddingsStatements.set(db, stmt);
|
|
162097
|
-
}
|
|
162098
|
-
return stmt;
|
|
162099
|
-
}
|
|
162100
162137
|
function saveEmbedding(db, memoryId, embedding, modelId) {
|
|
162101
162138
|
const blob = Buffer.from(embedding.buffer, embedding.byteOffset, embedding.byteLength);
|
|
162102
162139
|
getSaveEmbeddingStatement(db).run(memoryId, blob, modelId);
|
|
@@ -162116,12 +162153,6 @@ function loadAllEmbeddings(db, projectPath, modelId) {
|
|
|
162116
162153
|
}
|
|
162117
162154
|
return embeddings;
|
|
162118
162155
|
}
|
|
162119
|
-
function clearEmbeddingsForProject(db, projectPath, modelId) {
|
|
162120
|
-
if (modelId) {
|
|
162121
|
-
return getClearModelEmbeddingsStatement(db).run(modelId, projectPath).changes;
|
|
162122
|
-
}
|
|
162123
|
-
return getClearAllEmbeddingsStatement(db).run(projectPath).changes;
|
|
162124
|
-
}
|
|
162125
162156
|
function getMemoryEmbedCoverage(db, projectPath, modelId) {
|
|
162126
162157
|
const row = db.prepare(`SELECT
|
|
162127
162158
|
COUNT(*) AS total,
|
|
@@ -162194,24 +162225,6 @@ function getCountEmbeddedStatement(db) {
|
|
|
162194
162225
|
}
|
|
162195
162226
|
return stmt;
|
|
162196
162227
|
}
|
|
162197
|
-
function getClearProjectStatement2(db) {
|
|
162198
|
-
let stmt = clearProjectStatements2.get(db);
|
|
162199
|
-
if (!stmt) {
|
|
162200
|
-
stmt = db.prepare(`DELETE FROM git_commit_embeddings
|
|
162201
|
-
WHERE sha IN (SELECT sha FROM git_commits WHERE project_path = ?)`);
|
|
162202
|
-
clearProjectStatements2.set(db, stmt);
|
|
162203
|
-
}
|
|
162204
|
-
return stmt;
|
|
162205
|
-
}
|
|
162206
|
-
function getClearProjectModelStatement2(db) {
|
|
162207
|
-
let stmt = clearProjectModelStatements2.get(db);
|
|
162208
|
-
if (!stmt) {
|
|
162209
|
-
stmt = db.prepare(`DELETE FROM git_commit_embeddings
|
|
162210
|
-
WHERE model_id = ? AND sha IN (SELECT sha FROM git_commits WHERE project_path = ?)`);
|
|
162211
|
-
clearProjectModelStatements2.set(db, stmt);
|
|
162212
|
-
}
|
|
162213
|
-
return stmt;
|
|
162214
|
-
}
|
|
162215
162228
|
function saveCommitEmbedding(db, sha, embedding, modelId) {
|
|
162216
162229
|
const bytes = new Uint8Array(embedding.buffer, embedding.byteOffset, embedding.byteLength);
|
|
162217
162230
|
getSaveStatement(db).run(sha, bytes, modelId, Date.now());
|
|
@@ -162232,12 +162245,6 @@ function countEmbeddedCommits(db, projectPath, modelId) {
|
|
|
162232
162245
|
const row = getCountEmbeddedStatement(db).get(projectPath, modelId);
|
|
162233
162246
|
return row?.count ?? 0;
|
|
162234
162247
|
}
|
|
162235
|
-
function clearProjectCommitEmbeddings(db, projectPath, modelId) {
|
|
162236
|
-
if (modelId) {
|
|
162237
|
-
return getClearProjectModelStatement2(db).run(modelId, projectPath).changes;
|
|
162238
|
-
}
|
|
162239
|
-
return getClearProjectStatement2(db).run(projectPath).changes;
|
|
162240
|
-
}
|
|
162241
162248
|
|
|
162242
162249
|
// ../plugin/src/features/magic-context/git-commits/storage-git-commits.ts
|
|
162243
162250
|
init_logger();
|
|
@@ -162539,6 +162546,7 @@ function invalidateMemory(projectPath, memoryId) {
|
|
|
162539
162546
|
}
|
|
162540
162547
|
|
|
162541
162548
|
// ../plugin/src/features/magic-context/session-project-storage.ts
|
|
162549
|
+
var SESSION_CHUNK_REPAIR_BATCH_SIZE = 100;
|
|
162542
162550
|
var upsertSessionProjectStatements = new WeakMap;
|
|
162543
162551
|
var repairSessionChunkProjectStatements = new WeakMap;
|
|
162544
162552
|
var repairProjectChunkProjectStatements = new WeakMap;
|
|
@@ -162560,9 +162568,14 @@ function getRepairSessionChunkProjectStatement(db) {
|
|
|
162560
162568
|
if (!stmt) {
|
|
162561
162569
|
stmt = db.prepare(`UPDATE compartment_chunk_embeddings
|
|
162562
162570
|
SET project_path = ?
|
|
162563
|
-
WHERE
|
|
162564
|
-
|
|
162565
|
-
|
|
162571
|
+
WHERE id IN (
|
|
162572
|
+
SELECT id
|
|
162573
|
+
FROM compartment_chunk_embeddings
|
|
162574
|
+
WHERE session_id = ?
|
|
162575
|
+
AND harness = ?
|
|
162576
|
+
AND project_path <> ?
|
|
162577
|
+
LIMIT ?
|
|
162578
|
+
)`);
|
|
162566
162579
|
repairSessionChunkProjectStatements.set(db, stmt);
|
|
162567
162580
|
}
|
|
162568
162581
|
return stmt;
|
|
@@ -162600,7 +162613,7 @@ function recordSessionProjectIdentity(db, sessionId, projectPath) {
|
|
|
162600
162613
|
const now = Date.now();
|
|
162601
162614
|
db.transaction(() => {
|
|
162602
162615
|
getUpsertSessionProjectStatement(db).run(sessionId, harness, projectPath, now);
|
|
162603
|
-
getRepairSessionChunkProjectStatement(db).run(projectPath, sessionId, harness, projectPath);
|
|
162616
|
+
getRepairSessionChunkProjectStatement(db).run(projectPath, sessionId, harness, projectPath, SESSION_CHUNK_REPAIR_BATCH_SIZE);
|
|
162604
162617
|
})();
|
|
162605
162618
|
}
|
|
162606
162619
|
function repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectPath) {
|
|
@@ -162616,6 +162629,7 @@ var COMMIT_DRAIN_BATCH_SIZE = 16;
|
|
|
162616
162629
|
var COMMIT_DRAIN_MAX_PER_SWEEP = 500;
|
|
162617
162630
|
var CHUNK_DRAIN_BATCH_SIZE = 8;
|
|
162618
162631
|
var EMBEDDING_IDENTITY_GC_GRACE_MS = 14 * 24 * 60 * 60 * 1000;
|
|
162632
|
+
var STALE_EMBEDDING_GC_BATCH_SIZE = 250;
|
|
162619
162633
|
var MAX_WINDOWS_PER_EMBED_CALL = 2;
|
|
162620
162634
|
var SESSION_EMBED_LEASE_RENEWAL_MS = 60 * 1000;
|
|
162621
162635
|
var EMBED_SLICE_RETRY_ATTEMPTS = 3;
|
|
@@ -162844,6 +162858,55 @@ function staleModelsForScope(db, projectIdentity, scope, currentModelId, cutoff)
|
|
|
162844
162858
|
const rows = getStaleIdentityStatement(db, scope).all(projectIdentity, scope, currentModelId, cutoff);
|
|
162845
162859
|
return rows.map((row) => row.modelId).filter((modelId) => typeof modelId === "string");
|
|
162846
162860
|
}
|
|
162861
|
+
function deleteStaleEmbeddingBatch(db, scope, projectIdentity, modelId, limit) {
|
|
162862
|
+
if (scope === "memory") {
|
|
162863
|
+
return db.prepare(`DELETE FROM memory_embeddings
|
|
162864
|
+
WHERE rowid IN (
|
|
162865
|
+
SELECT me.rowid
|
|
162866
|
+
FROM memory_embeddings me
|
|
162867
|
+
JOIN memories m ON m.id = me.memory_id
|
|
162868
|
+
WHERE m.project_path = ? AND me.model_id = ?
|
|
162869
|
+
LIMIT ?
|
|
162870
|
+
)`).run(projectIdentity, modelId, limit).changes;
|
|
162871
|
+
}
|
|
162872
|
+
if (scope === "commit") {
|
|
162873
|
+
return db.prepare(`DELETE FROM git_commit_embeddings
|
|
162874
|
+
WHERE rowid IN (
|
|
162875
|
+
SELECT gce.rowid
|
|
162876
|
+
FROM git_commit_embeddings gce
|
|
162877
|
+
JOIN git_commits gc ON gc.sha = gce.sha
|
|
162878
|
+
WHERE gc.project_path = ? AND gce.model_id = ?
|
|
162879
|
+
LIMIT ?
|
|
162880
|
+
)`).run(projectIdentity, modelId, limit).changes;
|
|
162881
|
+
}
|
|
162882
|
+
return db.prepare(`DELETE FROM compartment_chunk_embeddings
|
|
162883
|
+
WHERE id IN (
|
|
162884
|
+
SELECT id
|
|
162885
|
+
FROM compartment_chunk_embeddings
|
|
162886
|
+
WHERE project_path = ? AND model_id = ?
|
|
162887
|
+
LIMIT ?
|
|
162888
|
+
)`).run(projectIdentity, modelId, limit).changes;
|
|
162889
|
+
}
|
|
162890
|
+
function hasStaleEmbeddingRows(db, scope, projectIdentity, modelId) {
|
|
162891
|
+
if (scope === "memory") {
|
|
162892
|
+
return Boolean(db.prepare(`SELECT 1
|
|
162893
|
+
FROM memory_embeddings me
|
|
162894
|
+
JOIN memories m ON m.id = me.memory_id
|
|
162895
|
+
WHERE m.project_path = ? AND me.model_id = ?
|
|
162896
|
+
LIMIT 1`).get(projectIdentity, modelId));
|
|
162897
|
+
}
|
|
162898
|
+
if (scope === "commit") {
|
|
162899
|
+
return Boolean(db.prepare(`SELECT 1
|
|
162900
|
+
FROM git_commit_embeddings gce
|
|
162901
|
+
JOIN git_commits gc ON gc.sha = gce.sha
|
|
162902
|
+
WHERE gc.project_path = ? AND gce.model_id = ?
|
|
162903
|
+
LIMIT 1`).get(projectIdentity, modelId));
|
|
162904
|
+
}
|
|
162905
|
+
return Boolean(db.prepare(`SELECT 1
|
|
162906
|
+
FROM compartment_chunk_embeddings
|
|
162907
|
+
WHERE project_path = ? AND model_id = ?
|
|
162908
|
+
LIMIT 1`).get(projectIdentity, modelId));
|
|
162909
|
+
}
|
|
162847
162910
|
function sweepStaleEmbeddingIdentitiesForProject(db, projectIdentity, now = Date.now()) {
|
|
162848
162911
|
const snapshot = getProjectEmbeddingSnapshot(projectIdentity);
|
|
162849
162912
|
const result = {
|
|
@@ -162858,24 +162921,45 @@ function sweepStaleEmbeddingIdentitiesForProject(db, projectIdentity, now = Date
|
|
|
162858
162921
|
return result;
|
|
162859
162922
|
const cutoff = now - EMBEDDING_IDENTITY_GC_GRACE_MS;
|
|
162860
162923
|
const deleteTracking = getDeleteActiveIdentityStatement(db);
|
|
162924
|
+
const scopes = [
|
|
162925
|
+
{
|
|
162926
|
+
scope: "memory",
|
|
162927
|
+
enabled: snapshot.enabled && snapshot.modelId !== "off",
|
|
162928
|
+
currentModelId: snapshot.modelId
|
|
162929
|
+
},
|
|
162930
|
+
{
|
|
162931
|
+
scope: "commit",
|
|
162932
|
+
enabled: snapshot.gitCommitEnabled && snapshot.modelId !== "off",
|
|
162933
|
+
currentModelId: snapshot.modelId
|
|
162934
|
+
},
|
|
162935
|
+
{
|
|
162936
|
+
scope: "chunk",
|
|
162937
|
+
enabled: snapshot.enabled && snapshot.chunkModelId !== "off",
|
|
162938
|
+
currentModelId: snapshot.chunkModelId
|
|
162939
|
+
}
|
|
162940
|
+
];
|
|
162941
|
+
let remainingBudget = STALE_EMBEDDING_GC_BATCH_SIZE;
|
|
162861
162942
|
db.exec("BEGIN IMMEDIATE");
|
|
162862
162943
|
try {
|
|
162863
|
-
|
|
162864
|
-
|
|
162865
|
-
|
|
162866
|
-
|
|
162867
|
-
|
|
162868
|
-
|
|
162869
|
-
|
|
162870
|
-
|
|
162871
|
-
|
|
162872
|
-
|
|
162873
|
-
|
|
162874
|
-
|
|
162875
|
-
|
|
162876
|
-
|
|
162877
|
-
|
|
162878
|
-
|
|
162944
|
+
for (const { scope, enabled, currentModelId } of scopes) {
|
|
162945
|
+
if (!enabled || remainingBudget === 0)
|
|
162946
|
+
continue;
|
|
162947
|
+
for (const modelId of staleModelsForScope(db, projectIdentity, scope, currentModelId, cutoff)) {
|
|
162948
|
+
if (remainingBudget === 0)
|
|
162949
|
+
break;
|
|
162950
|
+
const deleted = deleteStaleEmbeddingBatch(db, scope, projectIdentity, modelId, remainingBudget);
|
|
162951
|
+
remainingBudget -= deleted;
|
|
162952
|
+
if (scope === "memory")
|
|
162953
|
+
result.memoryRowsDeleted += deleted;
|
|
162954
|
+
else if (scope === "commit")
|
|
162955
|
+
result.commitRowsDeleted += deleted;
|
|
162956
|
+
else
|
|
162957
|
+
result.chunkRowsDeleted += deleted;
|
|
162958
|
+
if (!hasStaleEmbeddingRows(db, scope, projectIdentity, modelId)) {
|
|
162959
|
+
result.trackingRowsDeleted += deleteTracking.run(projectIdentity, scope, modelId).changes;
|
|
162960
|
+
} else if (deleted === 0) {
|
|
162961
|
+
remainingBudget = 0;
|
|
162962
|
+
}
|
|
162879
162963
|
}
|
|
162880
162964
|
}
|
|
162881
162965
|
db.exec("COMMIT");
|
|
@@ -162885,9 +162969,8 @@ function sweepStaleEmbeddingIdentitiesForProject(db, projectIdentity, now = Date
|
|
|
162885
162969
|
} catch {}
|
|
162886
162970
|
throw error51;
|
|
162887
162971
|
}
|
|
162888
|
-
if (result.memoryRowsDeleted > 0)
|
|
162972
|
+
if (result.memoryRowsDeleted > 0)
|
|
162889
162973
|
invalidateProject(projectIdentity);
|
|
162890
|
-
}
|
|
162891
162974
|
return result;
|
|
162892
162975
|
}
|
|
162893
162976
|
function registerProjectEmbedding(db, projectIdentity, config2, features, sourceDirectory) {
|
|
@@ -163107,16 +163190,27 @@ async function drainCommitBacklogForProject(db, projectIdentity, deadline) {
|
|
|
163107
163190
|
return 0;
|
|
163108
163191
|
}
|
|
163109
163192
|
let total = 0;
|
|
163193
|
+
let leaseLost = false;
|
|
163194
|
+
const renewal = setInterval(() => {
|
|
163195
|
+
try {
|
|
163196
|
+
if (!renewGitSweepLease(db, projectIdentity, holderId))
|
|
163197
|
+
leaseLost = true;
|
|
163198
|
+
} catch {}
|
|
163199
|
+
}, SESSION_EMBED_LEASE_RENEWAL_MS);
|
|
163200
|
+
renewal.unref?.();
|
|
163110
163201
|
try {
|
|
163111
|
-
while (Date.now() < deadline && total < COMMIT_DRAIN_MAX_PER_SWEEP) {
|
|
163202
|
+
while (!leaseLost && Date.now() < deadline && total < COMMIT_DRAIN_MAX_PER_SWEEP) {
|
|
163112
163203
|
const embedded = await embedCommitBatch(db, projectIdentity, COMMIT_DRAIN_BATCH_SIZE);
|
|
163113
|
-
if (
|
|
163204
|
+
if (!renewGitSweepLease(db, projectIdentity, holderId))
|
|
163205
|
+
leaseLost = true;
|
|
163206
|
+
if (leaseLost || embedded === 0)
|
|
163114
163207
|
break;
|
|
163115
163208
|
total += embedded;
|
|
163116
163209
|
if (embedded < COMMIT_DRAIN_BATCH_SIZE)
|
|
163117
163210
|
break;
|
|
163118
163211
|
}
|
|
163119
163212
|
} finally {
|
|
163213
|
+
clearInterval(renewal);
|
|
163120
163214
|
releaseGitSweepLease(db, projectIdentity, holderId);
|
|
163121
163215
|
}
|
|
163122
163216
|
return total;
|
|
@@ -163227,9 +163321,19 @@ async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, opt
|
|
|
163227
163321
|
const lease = acquireGitSweepLease(db, projectIdentity, holderId, { ignoreCooldown: true });
|
|
163228
163322
|
if (!lease.acquired)
|
|
163229
163323
|
return { status: "busy", embedded: 0, total };
|
|
163324
|
+
let leaseLost = false;
|
|
163325
|
+
const drainAbort = new AbortController;
|
|
163326
|
+
const forwardCallerAbort = () => drainAbort.abort();
|
|
163327
|
+
if (options?.signal?.aborted)
|
|
163328
|
+
drainAbort.abort();
|
|
163329
|
+
else
|
|
163330
|
+
options?.signal?.addEventListener("abort", forwardCallerAbort, { once: true });
|
|
163230
163331
|
const renewal = setInterval(() => {
|
|
163231
163332
|
try {
|
|
163232
|
-
renewGitSweepLease(db, projectIdentity, holderId)
|
|
163333
|
+
if (!renewGitSweepLease(db, projectIdentity, holderId)) {
|
|
163334
|
+
leaseLost = true;
|
|
163335
|
+
drainAbort.abort();
|
|
163336
|
+
}
|
|
163233
163337
|
} catch {}
|
|
163234
163338
|
}, SESSION_EMBED_LEASE_RENEWAL_MS);
|
|
163235
163339
|
renewal.unref?.();
|
|
@@ -163243,7 +163347,7 @@ async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, opt
|
|
|
163243
163347
|
try {
|
|
163244
163348
|
options?.onProgress?.({ embedded, total });
|
|
163245
163349
|
for (;; ) {
|
|
163246
|
-
if (
|
|
163350
|
+
if (leaseLost || drainAbort.signal.aborted) {
|
|
163247
163351
|
aborted2 = true;
|
|
163248
163352
|
break;
|
|
163249
163353
|
}
|
|
@@ -163254,7 +163358,13 @@ async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, opt
|
|
|
163254
163358
|
embedded: n,
|
|
163255
163359
|
noWork,
|
|
163256
163360
|
failed
|
|
163257
|
-
} = await embedCandidateChunkBatch(db, projectIdentity, snapshot.chunkModelId, candidates,
|
|
163361
|
+
} = await embedCandidateChunkBatch(db, projectIdentity, snapshot.chunkModelId, candidates, drainAbort.signal);
|
|
163362
|
+
if (leaseLost || !renewGitSweepLease(db, projectIdentity, holderId)) {
|
|
163363
|
+
leaseLost = true;
|
|
163364
|
+
drainAbort.abort();
|
|
163365
|
+
aborted2 = true;
|
|
163366
|
+
break;
|
|
163367
|
+
}
|
|
163258
163368
|
for (const id of noWork)
|
|
163259
163369
|
skipIds.push(id);
|
|
163260
163370
|
for (const id of failed)
|
|
@@ -163274,6 +163384,7 @@ async function embedSessionCompartmentChunks(db, projectIdentity, sessionId, opt
|
|
|
163274
163384
|
}
|
|
163275
163385
|
} finally {
|
|
163276
163386
|
clearInterval(renewal);
|
|
163387
|
+
options?.signal?.removeEventListener("abort", forwardCallerAbort);
|
|
163277
163388
|
try {
|
|
163278
163389
|
releaseGitSweepLease(db, projectIdentity, holderId);
|
|
163279
163390
|
} catch (error51) {
|
|
@@ -163471,8 +163582,38 @@ function handleUntrustedLoad(db, projectIdentity, directory, detailed) {
|
|
|
163471
163582
|
}
|
|
163472
163583
|
|
|
163473
163584
|
// src/embedding-bootstrap.ts
|
|
163585
|
+
var registrationFingerprintsByDatabase = new WeakMap;
|
|
163586
|
+
function configCandidatePaths(directory, loadedPaths) {
|
|
163587
|
+
const projectBase = cortexKitProjectConfigBasePath(directory);
|
|
163588
|
+
const userBase = cortexKitUserConfigBasePath();
|
|
163589
|
+
return [
|
|
163590
|
+
`${projectBase}.jsonc`,
|
|
163591
|
+
`${projectBase}.json`,
|
|
163592
|
+
`${userBase}.jsonc`,
|
|
163593
|
+
`${userBase}.json`,
|
|
163594
|
+
...loadedPaths
|
|
163595
|
+
].filter((path4, index, paths) => paths.indexOf(path4) === index);
|
|
163596
|
+
}
|
|
163597
|
+
function configFingerprint(paths) {
|
|
163598
|
+
return paths.map((path4) => {
|
|
163599
|
+
try {
|
|
163600
|
+
const stat2 = statSync3(path4);
|
|
163601
|
+
return `${path4}:${stat2.size}:${stat2.mtimeMs}`;
|
|
163602
|
+
} catch {
|
|
163603
|
+
return `${path4}:missing`;
|
|
163604
|
+
}
|
|
163605
|
+
}).join("|");
|
|
163606
|
+
}
|
|
163474
163607
|
async function ensureProjectRegisteredFromPiDirectory(directory, db) {
|
|
163475
163608
|
const projectIdentity = resolveProjectIdentity(directory);
|
|
163609
|
+
let registrationFingerprints = registrationFingerprintsByDatabase.get(db);
|
|
163610
|
+
if (!registrationFingerprints) {
|
|
163611
|
+
registrationFingerprints = new Map;
|
|
163612
|
+
registrationFingerprintsByDatabase.set(db, registrationFingerprints);
|
|
163613
|
+
}
|
|
163614
|
+
const cached2 = registrationFingerprints.get(projectIdentity);
|
|
163615
|
+
if (cached2 && configFingerprint(cached2.paths) === cached2.fingerprint)
|
|
163616
|
+
return;
|
|
163476
163617
|
const detailed = loadPiConfigDetailed({ cwd: directory });
|
|
163477
163618
|
if (isConfigLoadUntrusted(detailed)) {
|
|
163478
163619
|
handleUntrustedLoad(db, projectIdentity, directory, detailed);
|
|
@@ -163483,6 +163624,11 @@ async function ensureProjectRegisteredFromPiDirectory(directory, db) {
|
|
|
163483
163624
|
gitCommitEnabled: detailed.config.memory.git_commit_indexing.enabled
|
|
163484
163625
|
};
|
|
163485
163626
|
registerProjectEmbedding(db, projectIdentity, detailed.config.embedding, features, directory);
|
|
163627
|
+
const fingerprintPaths = configCandidatePaths(directory, detailed.loadedFromPaths);
|
|
163628
|
+
registrationFingerprints.set(projectIdentity, {
|
|
163629
|
+
paths: fingerprintPaths,
|
|
163630
|
+
fingerprint: configFingerprint(fingerprintPaths)
|
|
163631
|
+
});
|
|
163486
163632
|
}
|
|
163487
163633
|
// ../plugin/src/features/magic-context/compartment-lease.ts
|
|
163488
163634
|
var COMPARTMENT_LEASE_TTL_MS = 5 * 60 * 1000;
|
|
@@ -164102,6 +164248,12 @@ function parseJsonRecord(value) {
|
|
|
164102
164248
|
return null;
|
|
164103
164249
|
}
|
|
164104
164250
|
}
|
|
164251
|
+
function isRawCompactionSummaryInfo(info) {
|
|
164252
|
+
if (info === null || typeof info !== "object" || Array.isArray(info))
|
|
164253
|
+
return false;
|
|
164254
|
+
const candidate = info;
|
|
164255
|
+
return candidate.summary === true && candidate.finish === "stop";
|
|
164256
|
+
}
|
|
164105
164257
|
function parseJsonUnknown(value) {
|
|
164106
164258
|
try {
|
|
164107
164259
|
return JSON.parse(value);
|
|
@@ -164124,7 +164276,7 @@ function attachRawPartVersion(value, timeUpdated) {
|
|
|
164124
164276
|
return value;
|
|
164125
164277
|
}
|
|
164126
164278
|
function readRawSessionMessagesFromDb(db, sessionId) {
|
|
164127
|
-
const messageRows = db.prepare("SELECT id, data, time_updated FROM message WHERE session_id = ? ORDER BY time_created ASC, id ASC").all(sessionId).filter(isRawMessageRow);
|
|
164279
|
+
const messageRows = db.prepare("SELECT id, data, time_created, time_updated FROM message WHERE session_id = ? ORDER BY time_created ASC, id ASC").all(sessionId).filter(isRawMessageRow);
|
|
164128
164280
|
const partRows = db.prepare("SELECT message_id, data, time_updated FROM part WHERE session_id = ? ORDER BY time_created ASC, id ASC").all(sessionId).filter(isRawPartRow);
|
|
164129
164281
|
const partsByMessageId = new Map;
|
|
164130
164282
|
for (const part of partRows) {
|
|
@@ -164132,10 +164284,7 @@ function readRawSessionMessagesFromDb(db, sessionId) {
|
|
|
164132
164284
|
list.push(attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated));
|
|
164133
164285
|
partsByMessageId.set(part.message_id, list);
|
|
164134
164286
|
}
|
|
164135
|
-
const filtered = messageRows.filter((row) =>
|
|
164136
|
-
const info = parseJsonRecord(row.data);
|
|
164137
|
-
return !(info?.summary === true && info?.finish === "stop");
|
|
164138
|
-
});
|
|
164287
|
+
const filtered = messageRows.filter((row) => !isRawCompactionSummaryInfo(parseJsonRecord(row.data)));
|
|
164139
164288
|
return filtered.flatMap((row, index) => {
|
|
164140
164289
|
const info = parseJsonRecord(row.data);
|
|
164141
164290
|
if (!info)
|
|
@@ -164146,10 +164295,71 @@ function readRawSessionMessagesFromDb(db, sessionId) {
|
|
|
164146
164295
|
id: row.id,
|
|
164147
164296
|
role,
|
|
164148
164297
|
parts: partsByMessageId.get(row.id) ?? [],
|
|
164298
|
+
createdAt: row.time_created ?? null,
|
|
164299
|
+
version: row.time_updated ?? null
|
|
164300
|
+
};
|
|
164301
|
+
});
|
|
164302
|
+
}
|
|
164303
|
+
function readRawSessionMessagePageFromDb(db, sessionId, afterOrdinal, limit, finalWatermark = Number.MAX_SAFE_INTEGER) {
|
|
164304
|
+
const remaining = Math.max(0, Math.floor(finalWatermark) - Math.floor(afterOrdinal));
|
|
164305
|
+
const pageSize = Math.min(Math.max(1, Math.floor(limit)), remaining);
|
|
164306
|
+
if (pageSize === 0)
|
|
164307
|
+
return [];
|
|
164308
|
+
const messageRows = db.prepare(`SELECT id, data, time_created, time_updated
|
|
164309
|
+
FROM message
|
|
164310
|
+
WHERE session_id = ?
|
|
164311
|
+
AND NOT (
|
|
164312
|
+
CASE WHEN json_valid(data) = 1
|
|
164313
|
+
THEN COALESCE(json_extract(data, '$.summary'), 0)
|
|
164314
|
+
ELSE 0 END = 1
|
|
164315
|
+
AND CASE WHEN json_valid(data) = 1
|
|
164316
|
+
THEN COALESCE(json_extract(data, '$.finish'), '')
|
|
164317
|
+
ELSE '' END = 'stop'
|
|
164318
|
+
)
|
|
164319
|
+
ORDER BY time_created ASC, id ASC
|
|
164320
|
+
LIMIT ? OFFSET ?`).all(sessionId, pageSize, Math.max(0, Math.floor(afterOrdinal))).filter(isRawMessageRow).map((row, index) => ({
|
|
164321
|
+
...row,
|
|
164322
|
+
ordinal: Math.floor(afterOrdinal) + index + 1
|
|
164323
|
+
}));
|
|
164324
|
+
if (messageRows.length === 0)
|
|
164325
|
+
return [];
|
|
164326
|
+
const placeholders2 = messageRows.map(() => "?").join(", ");
|
|
164327
|
+
const partRows = db.prepare(`SELECT message_id, data, time_updated
|
|
164328
|
+
FROM part
|
|
164329
|
+
WHERE session_id = ? AND message_id IN (${placeholders2})
|
|
164330
|
+
ORDER BY time_created ASC, id ASC`).all(sessionId, ...messageRows.map((row) => row.id)).filter(isRawPartRow);
|
|
164331
|
+
const partsByMessageId = new Map;
|
|
164332
|
+
for (const part of partRows) {
|
|
164333
|
+
const list = partsByMessageId.get(part.message_id) ?? [];
|
|
164334
|
+
list.push(attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated));
|
|
164335
|
+
partsByMessageId.set(part.message_id, list);
|
|
164336
|
+
}
|
|
164337
|
+
return messageRows.map((row) => {
|
|
164338
|
+
const info = parseJsonRecord(row.data);
|
|
164339
|
+
return {
|
|
164340
|
+
ordinal: row.ordinal,
|
|
164341
|
+
id: row.id,
|
|
164342
|
+
role: typeof info?.role === "string" ? info.role : "unknown",
|
|
164343
|
+
parts: partsByMessageId.get(row.id) ?? [],
|
|
164344
|
+
createdAt: row.time_created ?? null,
|
|
164149
164345
|
version: row.time_updated ?? null
|
|
164150
164346
|
};
|
|
164151
164347
|
});
|
|
164152
164348
|
}
|
|
164349
|
+
function countRawSessionMessageOrdinalsFromDb(db, sessionId) {
|
|
164350
|
+
const row = db.prepare(`SELECT COUNT(*) AS count
|
|
164351
|
+
FROM message
|
|
164352
|
+
WHERE session_id = ?
|
|
164353
|
+
AND NOT (
|
|
164354
|
+
CASE WHEN json_valid(data) = 1
|
|
164355
|
+
THEN COALESCE(json_extract(data, '$.summary'), 0)
|
|
164356
|
+
ELSE 0 END = 1
|
|
164357
|
+
AND CASE WHEN json_valid(data) = 1
|
|
164358
|
+
THEN COALESCE(json_extract(data, '$.finish'), '')
|
|
164359
|
+
ELSE '' END = 'stop'
|
|
164360
|
+
)`).get(sessionId);
|
|
164361
|
+
return typeof row?.count === "number" ? row.count : 0;
|
|
164362
|
+
}
|
|
164153
164363
|
function isAnchorRow(row) {
|
|
164154
164364
|
return row !== null && typeof row === "object" && typeof row.time_created === "number" && typeof row.id === "string";
|
|
164155
164365
|
}
|
|
@@ -164160,7 +164370,7 @@ function readRawSessionTailFromDb(db, sessionId, baseOrdinal, anchorMessageId) {
|
|
|
164160
164370
|
const anchorInfo = parseJsonRecord(anchorRow.data ?? "");
|
|
164161
164371
|
if (anchorInfo?.summary === true && anchorInfo?.finish === "stop")
|
|
164162
164372
|
return null;
|
|
164163
|
-
const messageRows = db.prepare(`SELECT id, data, time_updated FROM message
|
|
164373
|
+
const messageRows = db.prepare(`SELECT id, data, time_created, time_updated FROM message
|
|
164164
164374
|
WHERE session_id = ?
|
|
164165
164375
|
AND (time_created > ? OR (time_created = ? AND id >= ?))
|
|
164166
164376
|
ORDER BY time_created ASC, id ASC`).all(sessionId, anchorRow.time_created, anchorRow.time_created, anchorRow.id).filter(isRawMessageRow);
|
|
@@ -164196,6 +164406,7 @@ function readRawSessionTailFromDb(db, sessionId, baseOrdinal, anchorMessageId) {
|
|
|
164196
164406
|
id: row.id,
|
|
164197
164407
|
role: typeof info.role === "string" ? info.role : "unknown",
|
|
164198
164408
|
parts: partsByMessageId.get(row.id) ?? [],
|
|
164409
|
+
createdAt: row.time_created ?? null,
|
|
164199
164410
|
version: row.time_updated ?? null
|
|
164200
164411
|
});
|
|
164201
164412
|
ord += 1;
|
|
@@ -164456,6 +164667,31 @@ function readRawSessionMessages(sessionId) {
|
|
|
164456
164667
|
}
|
|
164457
164668
|
return readRawSessionMessagesFromSource(sessionId);
|
|
164458
164669
|
}
|
|
164670
|
+
function readRawSessionMessagePage(sessionId, afterOrdinal, limit, finalWatermark) {
|
|
164671
|
+
const provider2 = sessionProviders.get(sessionId);
|
|
164672
|
+
if (provider2?.readMessagePage) {
|
|
164673
|
+
return provider2.readMessagePage(afterOrdinal, limit, finalWatermark);
|
|
164674
|
+
}
|
|
164675
|
+
if (provider2) {
|
|
164676
|
+
return provider2.readMessages().filter((message) => message.ordinal > afterOrdinal && message.ordinal <= finalWatermark).slice(0, limit);
|
|
164677
|
+
}
|
|
164678
|
+
if (!openCodeDbExists())
|
|
164679
|
+
return [];
|
|
164680
|
+
return withReadOnlySessionDb((db) => readRawSessionMessagePageFromDb(db, sessionId, afterOrdinal, limit, finalWatermark));
|
|
164681
|
+
}
|
|
164682
|
+
function getRawSessionMessageOrdinalCount(sessionId) {
|
|
164683
|
+
const provider2 = sessionProviders.get(sessionId);
|
|
164684
|
+
if (provider2) {
|
|
164685
|
+
if (provider2.getMessageCount)
|
|
164686
|
+
return provider2.getMessageCount();
|
|
164687
|
+
return provider2.readMessages().length;
|
|
164688
|
+
}
|
|
164689
|
+
if (!openCodeDbExists())
|
|
164690
|
+
return 0;
|
|
164691
|
+
return withReadOnlySessionDb((db) => countRawSessionMessageOrdinalsFromDb(db, sessionId));
|
|
164692
|
+
}
|
|
164693
|
+
readRawSessionMessages.readPage = readRawSessionMessagePage;
|
|
164694
|
+
readRawSessionMessages.getCount = getRawSessionMessageOrdinalCount;
|
|
164459
164695
|
function primeTailRawMessageCache(args) {
|
|
164460
164696
|
const { sessionId, lastCompartmentEnd, anchorMessageId } = args;
|
|
164461
164697
|
if (!activeRawMessageCache)
|
|
@@ -164714,9 +164950,9 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
|
|
|
164714
164950
|
// ../plugin/src/tools/ctx-expand/constants.ts
|
|
164715
164951
|
var CTX_EXPAND_DESCRIPTION = `Recover the original conversation from your compacted history.
|
|
164716
164952
|
|
|
164717
|
-
Older parts of this session are summarized
|
|
164953
|
+
Older parts of this session are summarized under \`## start-end · date · title\` headings inside <session-history> — e.g. \`## 120-245 · … · Fixed tagger collision\`. Each heading replaces the raw messages in that ordinal range with a summary. When the summary isn't enough — you need exact wording, a specific value, an error message, or the reasoning behind a decision — expand the range:
|
|
164718
164954
|
|
|
164719
|
-
ctx_expand(start=120, end=245) ← the
|
|
164955
|
+
ctx_expand(start=120, end=245) ← the heading's start/end range
|
|
164720
164956
|
|
|
164721
164957
|
Returns the raw transcript as [N] U:/A: lines, capped at ~15K tokens; an oversized range returns the head and tells you where to continue. Also works with ordinals from ctx_search message results — expand a window around a hit (e.g. start=N-10, end=N+5). Ranges after the last compartment are your live tail — already visible in context, not expandable.
|
|
164722
164958
|
|
|
@@ -169128,7 +169364,7 @@ function resolvePiStableId(msg, index, entryIds, entryIdByRef) {
|
|
|
169128
169364
|
const role = m.role ?? "unknown";
|
|
169129
169365
|
return typeof m.timestamp === "number" ? `pi-msg-${index}-${m.timestamp}-${role}` : `pi-msg-${index}-${role}`;
|
|
169130
169366
|
}
|
|
169131
|
-
function isMidTurnPi(event, _sessionId) {
|
|
169367
|
+
function isMidTurnPi(event, _sessionId, branchEntries) {
|
|
169132
169368
|
const messages = event?.messages;
|
|
169133
169369
|
if (!Array.isArray(messages))
|
|
169134
169370
|
return false;
|
|
@@ -169147,7 +169383,7 @@ function isMidTurnPi(event, _sessionId) {
|
|
|
169147
169383
|
}
|
|
169148
169384
|
if (latestAssistant === null)
|
|
169149
169385
|
return false;
|
|
169150
|
-
if (hasRealUserAfter(messages, latestAssistantIndex))
|
|
169386
|
+
if (hasRealUserAfter(messages, latestAssistantIndex, branchEntries))
|
|
169151
169387
|
return false;
|
|
169152
169388
|
if (latestAssistant.stopReason === "toolUse")
|
|
169153
169389
|
return true;
|
|
@@ -169171,12 +169407,27 @@ function isMidTurnPi(event, _sessionId) {
|
|
|
169171
169407
|
}
|
|
169172
169408
|
return false;
|
|
169173
169409
|
}
|
|
169174
|
-
function hasRealUserAfter(messages, latestAssistantIndex) {
|
|
169175
|
-
|
|
169176
|
-
|
|
169410
|
+
function hasRealUserAfter(messages, latestAssistantIndex, branchEntries) {
|
|
169411
|
+
if (!branchEntries)
|
|
169412
|
+
return false;
|
|
169413
|
+
const genuineUserMessages = new Set;
|
|
169414
|
+
for (const entry of branchEntries) {
|
|
169415
|
+
if (entry === null || typeof entry !== "object")
|
|
169177
169416
|
continue;
|
|
169178
|
-
|
|
169417
|
+
const record4 = entry;
|
|
169418
|
+
if (record4.type !== "message")
|
|
169419
|
+
continue;
|
|
169420
|
+
const message = record4.message;
|
|
169421
|
+
if (message === null || typeof message !== "object")
|
|
169422
|
+
continue;
|
|
169423
|
+
if (message.role === "user") {
|
|
169424
|
+
genuineUserMessages.add(message);
|
|
169425
|
+
}
|
|
169426
|
+
}
|
|
169427
|
+
for (const msg of messages.slice(latestAssistantIndex + 1)) {
|
|
169428
|
+
if (msg !== null && typeof msg === "object" && genuineUserMessages.has(msg)) {
|
|
169179
169429
|
return true;
|
|
169430
|
+
}
|
|
169180
169431
|
}
|
|
169181
169432
|
return false;
|
|
169182
169433
|
}
|
|
@@ -170406,7 +170657,7 @@ function getMemoryVerifications(db, memoryIds) {
|
|
|
170406
170657
|
}
|
|
170407
170658
|
// ../plugin/src/features/magic-context/memory/verification-paths.ts
|
|
170408
170659
|
import { execFile } from "node:child_process";
|
|
170409
|
-
import { existsSync as existsSync9, realpathSync as realpathSync2, statSync as
|
|
170660
|
+
import { existsSync as existsSync9, realpathSync as realpathSync2, statSync as statSync4 } from "node:fs";
|
|
170410
170661
|
import path4 from "node:path";
|
|
170411
170662
|
import { promisify } from "node:util";
|
|
170412
170663
|
var execFileAsync = promisify(execFile);
|
|
@@ -170548,7 +170799,7 @@ async function normalizeVerificationFiles(args) {
|
|
|
170548
170799
|
}
|
|
170549
170800
|
if (existsSync9(candidate)) {
|
|
170550
170801
|
try {
|
|
170551
|
-
if (
|
|
170802
|
+
if (statSync4(candidate).isDirectory()) {
|
|
170552
170803
|
warnings.push(`Skipped verification path "${value}" because it is a directory.`);
|
|
170553
170804
|
continue;
|
|
170554
170805
|
}
|
|
@@ -170598,11 +170849,10 @@ async function normalizeVerificationFiles(args) {
|
|
|
170598
170849
|
// ../plugin/src/features/magic-context/message-index.ts
|
|
170599
170850
|
var lastIndexedStatements = new WeakMap;
|
|
170600
170851
|
var insertMessageStatements = new WeakMap;
|
|
170601
|
-
var
|
|
170602
|
-
var upsertCleanIndexStatements = new WeakMap;
|
|
170852
|
+
var upsertProgressStatements = new WeakMap;
|
|
170603
170853
|
var upsertDirtyFloorStatements = new WeakMap;
|
|
170604
170854
|
var deleteFtsStatements = new WeakMap;
|
|
170605
|
-
var
|
|
170855
|
+
var deleteFtsRangeStatements = new WeakMap;
|
|
170606
170856
|
var deleteIndexStatements = new WeakMap;
|
|
170607
170857
|
var countIndexedMessageStatements = new WeakMap;
|
|
170608
170858
|
function normalizeIndexText(text) {
|
|
@@ -170624,19 +170874,11 @@ function getInsertMessageStatement(db) {
|
|
|
170624
170874
|
}
|
|
170625
170875
|
return stmt;
|
|
170626
170876
|
}
|
|
170627
|
-
function
|
|
170628
|
-
let stmt =
|
|
170877
|
+
function getUpsertProgressStatement(db) {
|
|
170878
|
+
let stmt = upsertProgressStatements.get(db);
|
|
170629
170879
|
if (!stmt) {
|
|
170630
|
-
stmt = db.prepare("INSERT INTO message_history_index (session_id, last_indexed_ordinal, updated_at, harness) VALUES (?, ?, ?, ?) ON CONFLICT(session_id) DO UPDATE SET last_indexed_ordinal = excluded.last_indexed_ordinal, updated_at = excluded.updated_at");
|
|
170631
|
-
|
|
170632
|
-
}
|
|
170633
|
-
return stmt;
|
|
170634
|
-
}
|
|
170635
|
-
function getUpsertCleanIndexStatement(db) {
|
|
170636
|
-
let stmt = upsertCleanIndexStatements.get(db);
|
|
170637
|
-
if (!stmt) {
|
|
170638
|
-
stmt = db.prepare("INSERT INTO message_history_index (session_id, last_indexed_ordinal, dirty_floor_ordinal, updated_at, harness) VALUES (?, ?, 0, ?, ?) ON CONFLICT(session_id) DO UPDATE SET last_indexed_ordinal = excluded.last_indexed_ordinal, dirty_floor_ordinal = 0, updated_at = excluded.updated_at");
|
|
170639
|
-
upsertCleanIndexStatements.set(db, stmt);
|
|
170880
|
+
stmt = db.prepare("INSERT INTO message_history_index (session_id, last_indexed_ordinal, dirty_floor_ordinal, updated_at, harness) VALUES (?, ?, ?, ?, ?) ON CONFLICT(session_id) DO UPDATE SET last_indexed_ordinal = excluded.last_indexed_ordinal, dirty_floor_ordinal = excluded.dirty_floor_ordinal, updated_at = excluded.updated_at");
|
|
170881
|
+
upsertProgressStatements.set(db, stmt);
|
|
170640
170882
|
}
|
|
170641
170883
|
return stmt;
|
|
170642
170884
|
}
|
|
@@ -170648,27 +170890,11 @@ function getUpsertDirtyFloorStatement(db) {
|
|
|
170648
170890
|
}
|
|
170649
170891
|
return stmt;
|
|
170650
170892
|
}
|
|
170651
|
-
function
|
|
170652
|
-
let stmt =
|
|
170653
|
-
if (!stmt) {
|
|
170654
|
-
stmt = db.prepare("DELETE FROM message_history_fts WHERE session_id = ?");
|
|
170655
|
-
deleteFtsStatements.set(db, stmt);
|
|
170656
|
-
}
|
|
170657
|
-
return stmt;
|
|
170658
|
-
}
|
|
170659
|
-
function getDeleteFtsFromOrdinalStatement(db) {
|
|
170660
|
-
let stmt = deleteFtsFromOrdinalStatements.get(db);
|
|
170893
|
+
function getDeleteFtsRangeStatement(db) {
|
|
170894
|
+
let stmt = deleteFtsRangeStatements.get(db);
|
|
170661
170895
|
if (!stmt) {
|
|
170662
|
-
stmt = db.prepare("DELETE FROM message_history_fts WHERE session_id = ? AND CAST(message_ordinal AS INTEGER)
|
|
170663
|
-
|
|
170664
|
-
}
|
|
170665
|
-
return stmt;
|
|
170666
|
-
}
|
|
170667
|
-
function getDeleteIndexStatement(db) {
|
|
170668
|
-
let stmt = deleteIndexStatements.get(db);
|
|
170669
|
-
if (!stmt) {
|
|
170670
|
-
stmt = db.prepare("DELETE FROM message_history_index WHERE session_id = ?");
|
|
170671
|
-
deleteIndexStatements.set(db, stmt);
|
|
170896
|
+
stmt = db.prepare("DELETE FROM message_history_fts WHERE session_id = ? AND CAST(message_ordinal AS INTEGER) BETWEEN ? AND ?");
|
|
170897
|
+
deleteFtsRangeStatements.set(db, stmt);
|
|
170672
170898
|
}
|
|
170673
170899
|
return stmt;
|
|
170674
170900
|
}
|
|
@@ -170696,16 +170922,17 @@ function isMessageAlreadyIndexed(db, sessionId, messageId) {
|
|
|
170696
170922
|
const row = getCountIndexedMessageStatement(db).get(sessionId, messageId);
|
|
170697
170923
|
return (typeof row?.count === "number" ? row.count : 0) > 0;
|
|
170698
170924
|
}
|
|
170699
|
-
function
|
|
170700
|
-
|
|
170701
|
-
getUpsertIndexStatement(db).run(sessionId, Math.max(current, ordinal), now, getHarness());
|
|
170925
|
+
function setIndexProgress(db, sessionId, watermark, dirtyFloor, now) {
|
|
170926
|
+
getUpsertProgressStatement(db).run(sessionId, Math.max(0, Math.floor(watermark)), dirtyFloor ?? 0, now, getHarness());
|
|
170702
170927
|
}
|
|
170703
|
-
function
|
|
170704
|
-
db
|
|
170705
|
-
|
|
170706
|
-
|
|
170707
|
-
|
|
170708
|
-
|
|
170928
|
+
function getMessageIndexReconciliationStartOrdinal(db, sessionId) {
|
|
170929
|
+
const watermark = getLastIndexedOrdinal(db, sessionId);
|
|
170930
|
+
const dirtyFloor = getDirtyIndexFloor(db, sessionId);
|
|
170931
|
+
return dirtyFloor === null ? watermark : Math.min(watermark, dirtyFloor - 1);
|
|
170932
|
+
}
|
|
170933
|
+
function isMessageIndexReconciledThrough(db, sessionId, finalWatermark) {
|
|
170934
|
+
const dirtyFloor = getDirtyIndexFloor(db, sessionId);
|
|
170935
|
+
return getLastIndexedOrdinal(db, sessionId) >= finalWatermark && dirtyFloor === null;
|
|
170709
170936
|
}
|
|
170710
170937
|
function getIndexableContent(role, parts) {
|
|
170711
170938
|
if (role === "user") {
|
|
@@ -170720,22 +170947,21 @@ function getIndexableContent(role, parts) {
|
|
|
170720
170947
|
return "";
|
|
170721
170948
|
}
|
|
170722
170949
|
function indexSingleMessageInTransaction(db, sessionId, message, now) {
|
|
170723
|
-
|
|
170724
|
-
|
|
170725
|
-
|
|
170726
|
-
}
|
|
170727
|
-
const content = getIndexableContent(message.role, message.parts);
|
|
170728
|
-
if (content.length === 0) {
|
|
170729
|
-
advanceIndexWatermark(db, sessionId, message.ordinal, now);
|
|
170950
|
+
const currentWatermark = getLastIndexedOrdinal(db, sessionId);
|
|
170951
|
+
const dirtyFloor = getDirtyIndexFloor(db, sessionId);
|
|
170952
|
+
if (message.ordinal !== currentWatermark + 1 || dirtyFloor !== null && dirtyFloor !== message.ordinal) {
|
|
170730
170953
|
return false;
|
|
170731
170954
|
}
|
|
170732
|
-
|
|
170733
|
-
|
|
170734
|
-
|
|
170955
|
+
let inserted = false;
|
|
170956
|
+
if (message.role === "user" || message.role === "assistant") {
|
|
170957
|
+
const content = getIndexableContent(message.role, message.parts);
|
|
170958
|
+
if (content.length > 0 && !isMessageAlreadyIndexed(db, sessionId, message.id)) {
|
|
170959
|
+
getInsertMessageStatement(db).run(sessionId, message.ordinal, message.id, message.role, content);
|
|
170960
|
+
inserted = true;
|
|
170961
|
+
}
|
|
170735
170962
|
}
|
|
170736
|
-
|
|
170737
|
-
|
|
170738
|
-
return true;
|
|
170963
|
+
setIndexProgress(db, sessionId, message.ordinal, null, now);
|
|
170964
|
+
return inserted;
|
|
170739
170965
|
}
|
|
170740
170966
|
function indexSingleMessage(db, sessionId, message) {
|
|
170741
170967
|
db.exec("BEGIN IMMEDIATE");
|
|
@@ -170753,38 +170979,44 @@ function indexSingleMessage(db, sessionId, message) {
|
|
|
170753
170979
|
}
|
|
170754
170980
|
}
|
|
170755
170981
|
}
|
|
170756
|
-
function indexMessagesAfterOrdinal(db, sessionId, messages,
|
|
170982
|
+
function indexMessagesAfterOrdinal(db, sessionId, messages, _lastIndexedOrdinal, finalWatermark = messages.length) {
|
|
170757
170983
|
const now = Date.now();
|
|
170758
170984
|
let inserted = 0;
|
|
170759
170985
|
db.exec("BEGIN IMMEDIATE");
|
|
170760
170986
|
let committed = false;
|
|
170761
170987
|
try {
|
|
170762
|
-
|
|
170988
|
+
const currentWatermark = getLastIndexedOrdinal(db, sessionId);
|
|
170763
170989
|
const dirtyFloor = getDirtyIndexFloor(db, sessionId);
|
|
170764
|
-
|
|
170765
|
-
|
|
170766
|
-
|
|
170767
|
-
getDeleteFtsFromOrdinalStatement(db).run(sessionId, rewindOrdinal);
|
|
170768
|
-
}
|
|
170769
|
-
effectiveWatermark = Math.min(effectiveWatermark, rewindOrdinal - 1);
|
|
170990
|
+
const effectiveWatermark = dirtyFloor === null ? currentWatermark : Math.min(currentWatermark, Math.max(0, dirtyFloor - 1));
|
|
170991
|
+
if (dirtyFloor !== null && dirtyFloor <= finalWatermark) {
|
|
170992
|
+
getDeleteFtsRangeStatement(db).run(sessionId, dirtyFloor, finalWatermark);
|
|
170770
170993
|
}
|
|
170771
|
-
const
|
|
170994
|
+
const messagesByOrdinal = new Map;
|
|
170772
170995
|
for (const message of messages) {
|
|
170773
|
-
if (message.ordinal <=
|
|
170774
|
-
|
|
170996
|
+
if (message.ordinal > effectiveWatermark && message.ordinal <= finalWatermark) {
|
|
170997
|
+
messagesByOrdinal.set(message.ordinal, message);
|
|
170775
170998
|
}
|
|
170776
|
-
|
|
170999
|
+
}
|
|
171000
|
+
let coveredWatermark = effectiveWatermark;
|
|
171001
|
+
while (coveredWatermark < finalWatermark && messagesByOrdinal.has(coveredWatermark + 1)) {
|
|
171002
|
+
coveredWatermark += 1;
|
|
171003
|
+
}
|
|
171004
|
+
for (let ordinal = effectiveWatermark + 1;ordinal <= coveredWatermark; ordinal++) {
|
|
171005
|
+
const message = messagesByOrdinal.get(ordinal);
|
|
171006
|
+
if (!message || message.role !== "user" && message.role !== "assistant") {
|
|
170777
171007
|
continue;
|
|
170778
171008
|
}
|
|
170779
171009
|
const content = getIndexableContent(message.role, message.parts);
|
|
170780
|
-
if (content.length === 0) {
|
|
171010
|
+
if (content.length === 0 || isMessageAlreadyIndexed(db, sessionId, message.id)) {
|
|
170781
171011
|
continue;
|
|
170782
171012
|
}
|
|
170783
|
-
|
|
170784
|
-
inserted
|
|
171013
|
+
getInsertMessageStatement(db).run(sessionId, message.ordinal, message.id, message.role, content);
|
|
171014
|
+
inserted += 1;
|
|
170785
171015
|
}
|
|
170786
|
-
const
|
|
170787
|
-
|
|
171016
|
+
const missingFloor = coveredWatermark < finalWatermark ? coveredWatermark + 1 : null;
|
|
171017
|
+
const preservedFloor = dirtyFloor !== null && dirtyFloor > finalWatermark ? dirtyFloor : null;
|
|
171018
|
+
const nextDirtyFloor = missingFloor === null ? preservedFloor : preservedFloor === null ? missingFloor : Math.min(missingFloor, preservedFloor);
|
|
171019
|
+
setIndexProgress(db, sessionId, coveredWatermark, nextDirtyFloor, now);
|
|
170788
171020
|
db.exec("COMMIT");
|
|
170789
171021
|
committed = true;
|
|
170790
171022
|
} finally {
|
|
@@ -170798,7 +171030,7 @@ function indexMessagesAfterOrdinal(db, sessionId, messages, lastIndexedOrdinal,
|
|
|
170798
171030
|
}
|
|
170799
171031
|
// ../plugin/src/features/magic-context/project-docs-hash.ts
|
|
170800
171032
|
import { createHash as createHash7 } from "node:crypto";
|
|
170801
|
-
import { lstatSync, readFileSync as readFileSync5, statSync as
|
|
171033
|
+
import { lstatSync, readFileSync as readFileSync5, statSync as statSync5 } from "node:fs";
|
|
170802
171034
|
import path5 from "node:path";
|
|
170803
171035
|
var PROJECT_DOC_FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
|
|
170804
171036
|
var PROJECT_DOCS_DELIMITER = `
|
|
@@ -170829,7 +171061,7 @@ function fingerprintFile(filePath) {
|
|
|
170829
171061
|
}
|
|
170830
171062
|
function readDirectoryMtimeMs(projectDirectory) {
|
|
170831
171063
|
try {
|
|
170832
|
-
return
|
|
171064
|
+
return statSync5(projectDirectory).mtimeMs;
|
|
170833
171065
|
} catch {
|
|
170834
171066
|
return 0;
|
|
170835
171067
|
}
|
|
@@ -170919,6 +171151,160 @@ function readProjectDocsCanonical(projectDirectory) {
|
|
|
170919
171151
|
});
|
|
170920
171152
|
return { renderedBlock, canonicalHash };
|
|
170921
171153
|
}
|
|
171154
|
+
// ../plugin/src/features/magic-context/storage-clone.ts
|
|
171155
|
+
function runImmediate2(db, body) {
|
|
171156
|
+
db.exec("BEGIN IMMEDIATE");
|
|
171157
|
+
let committed = false;
|
|
171158
|
+
try {
|
|
171159
|
+
const result = body();
|
|
171160
|
+
db.exec("COMMIT");
|
|
171161
|
+
committed = true;
|
|
171162
|
+
return result;
|
|
171163
|
+
} finally {
|
|
171164
|
+
if (!committed) {
|
|
171165
|
+
try {
|
|
171166
|
+
db.exec("ROLLBACK");
|
|
171167
|
+
} catch {}
|
|
171168
|
+
}
|
|
171169
|
+
}
|
|
171170
|
+
}
|
|
171171
|
+
function countRows(db, table, sessionId) {
|
|
171172
|
+
const row = db.prepare(`SELECT COUNT(*) AS count FROM ${table} WHERE session_id = ?`).get(sessionId);
|
|
171173
|
+
return typeof row?.count === "number" ? row.count : 0;
|
|
171174
|
+
}
|
|
171175
|
+
function filterIdBlob(raw, includeMessageId) {
|
|
171176
|
+
if (!raw)
|
|
171177
|
+
return "";
|
|
171178
|
+
try {
|
|
171179
|
+
const value = JSON.parse(raw);
|
|
171180
|
+
if (!Array.isArray(value))
|
|
171181
|
+
return "";
|
|
171182
|
+
const filtered = value.filter((id) => typeof id === "string" && includeMessageId(id));
|
|
171183
|
+
return filtered.length > 0 ? JSON.stringify(filtered) : "";
|
|
171184
|
+
} catch {
|
|
171185
|
+
return "";
|
|
171186
|
+
}
|
|
171187
|
+
}
|
|
171188
|
+
function clampWatermark(value, maxCopiedTag) {
|
|
171189
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0)
|
|
171190
|
+
return 0;
|
|
171191
|
+
return Math.min(Math.floor(value), maxCopiedTag);
|
|
171192
|
+
}
|
|
171193
|
+
function copySessionStateForClone(db, sourceSessionId, destinationSessionId, filter) {
|
|
171194
|
+
return runImmediate2(db, () => {
|
|
171195
|
+
if (countRows(db, "compartments", destinationSessionId) > 0 || countRows(db, "tags", destinationSessionId) > 0) {
|
|
171196
|
+
return {
|
|
171197
|
+
kind: "destination-not-empty",
|
|
171198
|
+
compartmentsCopied: 0,
|
|
171199
|
+
tagsCopied: 0,
|
|
171200
|
+
pendingOpsCopied: 0,
|
|
171201
|
+
pendingMarkerMigrated: false
|
|
171202
|
+
};
|
|
171203
|
+
}
|
|
171204
|
+
const sourceCompartments = db.prepare(`SELECT sequence, start_message, end_message, start_message_id, end_message_id,
|
|
171205
|
+
title, content, p1, p2, p3, p4, importance, episode_type, legacy,
|
|
171206
|
+
created_at, harness
|
|
171207
|
+
FROM compartments WHERE session_id = ? ORDER BY sequence ASC`).all(sourceSessionId);
|
|
171208
|
+
const insertCompartment = db.prepare(`INSERT INTO compartments
|
|
171209
|
+
(session_id, sequence, start_message, end_message, start_message_id,
|
|
171210
|
+
end_message_id, title, content, p1, p2, p3, p4, importance,
|
|
171211
|
+
episode_type, legacy, created_at, harness)
|
|
171212
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
171213
|
+
const copiedCompartments = [];
|
|
171214
|
+
for (const row of sourceCompartments) {
|
|
171215
|
+
const startMessage = filter.resolveBoundaryOrdinal(row.start_message_id);
|
|
171216
|
+
const endMessage = filter.resolveBoundaryOrdinal(row.end_message_id);
|
|
171217
|
+
if (startMessage === undefined || endMessage === undefined)
|
|
171218
|
+
continue;
|
|
171219
|
+
insertCompartment.run(destinationSessionId, row.sequence, startMessage, endMessage, row.start_message_id, row.end_message_id, row.title, row.content, row.p1, row.p2, row.p3, row.p4, row.importance, row.episode_type, row.legacy, row.created_at, row.harness);
|
|
171220
|
+
copiedCompartments.push({
|
|
171221
|
+
sequence: row.sequence,
|
|
171222
|
+
startMessage,
|
|
171223
|
+
endMessage,
|
|
171224
|
+
startMessageId: row.start_message_id,
|
|
171225
|
+
endMessageId: row.end_message_id
|
|
171226
|
+
});
|
|
171227
|
+
}
|
|
171228
|
+
const sourceTags = db.prepare(`SELECT message_id, type, status, byte_size, tag_number, harness,
|
|
171229
|
+
entry_fingerprint, token_count, input_token_count,
|
|
171230
|
+
reasoning_token_count, reasoning_byte_size, drop_mode, tool_name,
|
|
171231
|
+
input_byte_size, caveman_depth, tool_owner_message_id
|
|
171232
|
+
FROM tags WHERE session_id = ? ORDER BY tag_number ASC`).all(sourceSessionId);
|
|
171233
|
+
const insertTag = db.prepare(`INSERT INTO tags
|
|
171234
|
+
(session_id, message_id, type, status, byte_size, tag_number, harness,
|
|
171235
|
+
entry_fingerprint, token_count, input_token_count, reasoning_token_count,
|
|
171236
|
+
reasoning_byte_size, drop_mode, tool_name, input_byte_size,
|
|
171237
|
+
caveman_depth, tool_owner_message_id)
|
|
171238
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
171239
|
+
const copiedTagNumbers = [];
|
|
171240
|
+
for (const row of sourceTags) {
|
|
171241
|
+
if (!filter.includeTag({
|
|
171242
|
+
messageId: row.message_id,
|
|
171243
|
+
type: row.type,
|
|
171244
|
+
tagNumber: row.tag_number,
|
|
171245
|
+
toolOwnerMessageId: row.tool_owner_message_id
|
|
171246
|
+
})) {
|
|
171247
|
+
continue;
|
|
171248
|
+
}
|
|
171249
|
+
insertTag.run(destinationSessionId, row.message_id, row.type, row.status, row.byte_size, row.tag_number, row.harness, row.entry_fingerprint, row.token_count, row.input_token_count, row.reasoning_token_count, row.reasoning_byte_size, row.drop_mode, row.tool_name, row.input_byte_size, row.caveman_depth, row.tool_owner_message_id);
|
|
171250
|
+
copiedTagNumbers.push(row.tag_number);
|
|
171251
|
+
}
|
|
171252
|
+
if (copiedTagNumbers.length > 0) {
|
|
171253
|
+
const placeholders3 = copiedTagNumbers.map(() => "?").join(", ");
|
|
171254
|
+
db.prepare(`INSERT INTO source_contents (tag_id, session_id, content, created_at, harness)
|
|
171255
|
+
SELECT tag_id, ?, content, created_at, harness
|
|
171256
|
+
FROM source_contents
|
|
171257
|
+
WHERE session_id = ? AND tag_id IN (${placeholders3})`).run(destinationSessionId, sourceSessionId, ...copiedTagNumbers);
|
|
171258
|
+
db.prepare(`INSERT INTO pending_ops (session_id, tag_id, operation, queued_at, harness)
|
|
171259
|
+
SELECT ?, tag_id, operation, queued_at, harness
|
|
171260
|
+
FROM pending_ops
|
|
171261
|
+
WHERE session_id = ? AND tag_id IN (${placeholders3})`).run(destinationSessionId, sourceSessionId, ...copiedTagNumbers);
|
|
171262
|
+
}
|
|
171263
|
+
const meta3 = db.prepare(`SELECT cleared_reasoning_through_tag, tool_reclaim_watermark,
|
|
171264
|
+
pi_stable_id_scheme, stripped_placeholder_ids,
|
|
171265
|
+
stale_reduce_stripped_ids, processed_image_stripped_ids,
|
|
171266
|
+
pending_pi_compaction_marker_state, last_todo_state,
|
|
171267
|
+
todo_synthetic_call_id, todo_synthetic_anchor_message_id,
|
|
171268
|
+
todo_synthetic_state_json
|
|
171269
|
+
FROM session_meta WHERE session_id = ?`).get(sourceSessionId);
|
|
171270
|
+
const maxCopiedTag = copiedTagNumbers.reduce((max, value) => Math.max(max, value), 0);
|
|
171271
|
+
const pendingMarker = filter.selectPendingPiMarker(meta3?.pending_pi_compaction_marker_state ?? null, copiedCompartments);
|
|
171272
|
+
const todoAnchor = meta3?.todo_synthetic_anchor_message_id ?? "";
|
|
171273
|
+
const migrateTodo = todoAnchor.length > 0 && filter.includeMessageId(todoAnchor);
|
|
171274
|
+
db.prepare(`INSERT INTO session_meta
|
|
171275
|
+
(session_id, harness, counter, cleared_reasoning_through_tag,
|
|
171276
|
+
tool_reclaim_watermark, pi_stable_id_scheme, stripped_placeholder_ids,
|
|
171277
|
+
stale_reduce_stripped_ids, processed_image_stripped_ids,
|
|
171278
|
+
pending_pi_compaction_marker_state, last_todo_state,
|
|
171279
|
+
todo_synthetic_call_id, todo_synthetic_anchor_message_id,
|
|
171280
|
+
todo_synthetic_state_json)
|
|
171281
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
171282
|
+
ON CONFLICT(session_id) DO UPDATE SET
|
|
171283
|
+
harness = excluded.harness,
|
|
171284
|
+
counter = excluded.counter,
|
|
171285
|
+
cleared_reasoning_through_tag = excluded.cleared_reasoning_through_tag,
|
|
171286
|
+
tool_reclaim_watermark = excluded.tool_reclaim_watermark,
|
|
171287
|
+
pi_stable_id_scheme = excluded.pi_stable_id_scheme,
|
|
171288
|
+
stripped_placeholder_ids = excluded.stripped_placeholder_ids,
|
|
171289
|
+
stale_reduce_stripped_ids = excluded.stale_reduce_stripped_ids,
|
|
171290
|
+
processed_image_stripped_ids = excluded.processed_image_stripped_ids,
|
|
171291
|
+
pending_pi_compaction_marker_state = excluded.pending_pi_compaction_marker_state,
|
|
171292
|
+
last_todo_state = excluded.last_todo_state,
|
|
171293
|
+
todo_synthetic_call_id = excluded.todo_synthetic_call_id,
|
|
171294
|
+
todo_synthetic_anchor_message_id = excluded.todo_synthetic_anchor_message_id,
|
|
171295
|
+
todo_synthetic_state_json = excluded.todo_synthetic_state_json,
|
|
171296
|
+
cached_m0_bytes = NULL,
|
|
171297
|
+
cached_m1_bytes = NULL`).run(destinationSessionId, getHarness(), maxCopiedTag, clampWatermark(meta3?.cleared_reasoning_through_tag ?? null, maxCopiedTag), clampWatermark(meta3?.tool_reclaim_watermark ?? null, maxCopiedTag), typeof meta3?.pi_stable_id_scheme === "number" && Number.isFinite(meta3.pi_stable_id_scheme) ? meta3.pi_stable_id_scheme : null, filterIdBlob(meta3?.stripped_placeholder_ids ?? null, filter.includeMessageId), filterIdBlob(meta3?.stale_reduce_stripped_ids ?? null, filter.includeMessageId), filterIdBlob(meta3?.processed_image_stripped_ids ?? null, filter.includeMessageId), pendingMarker, migrateTodo ? meta3?.last_todo_state ?? "" : "", migrateTodo ? meta3?.todo_synthetic_call_id ?? "" : "", migrateTodo ? todoAnchor : "", migrateTodo ? meta3?.todo_synthetic_state_json ?? "" : "");
|
|
171298
|
+
const pendingOpsRow = db.prepare("SELECT COUNT(*) AS count FROM pending_ops WHERE session_id = ?").get(destinationSessionId);
|
|
171299
|
+
return {
|
|
171300
|
+
kind: "migrated",
|
|
171301
|
+
compartmentsCopied: copiedCompartments.length,
|
|
171302
|
+
tagsCopied: copiedTagNumbers.length,
|
|
171303
|
+
pendingOpsCopied: typeof pendingOpsRow?.count === "number" ? pendingOpsRow.count : 0,
|
|
171304
|
+
pendingMarkerMigrated: pendingMarker !== null
|
|
171305
|
+
};
|
|
171306
|
+
});
|
|
171307
|
+
}
|
|
170922
171308
|
// ../plugin/src/features/magic-context/storage-m0-mutation-log.ts
|
|
170923
171309
|
var M0_MUTATION_TYPES = new Set([
|
|
170924
171310
|
"compartment_delete",
|
|
@@ -171771,13 +172157,17 @@ function clearHistorianFailureState(db, sessionId) {
|
|
|
171771
172157
|
function normalizeDetectedLimitModelKey(modelKey) {
|
|
171772
172158
|
return typeof modelKey === "string" && modelKey.length > 0 ? modelKey : null;
|
|
171773
172159
|
}
|
|
172160
|
+
function normalizeEmergencyRecoveryOrigin(value) {
|
|
172161
|
+
return value === "provider_overflow" || value === "proactive_model_shrink" ? value : null;
|
|
172162
|
+
}
|
|
171774
172163
|
function getOverflowState(db, sessionId, modelKey) {
|
|
171775
|
-
const result = db.prepare("SELECT detected_context_limit, detected_context_limit_model_key, needs_emergency_recovery FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
172164
|
+
const result = db.prepare("SELECT detected_context_limit, detected_context_limit_model_key, needs_emergency_recovery, emergency_recovery_origin FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
171776
172165
|
if (!result) {
|
|
171777
172166
|
return {
|
|
171778
172167
|
detectedContextLimit: 0,
|
|
171779
172168
|
detectedContextLimitModelKey: null,
|
|
171780
|
-
needsEmergencyRecovery: false
|
|
172169
|
+
needsEmergencyRecovery: false,
|
|
172170
|
+
emergencyRecoveryOrigin: null
|
|
171781
172171
|
};
|
|
171782
172172
|
}
|
|
171783
172173
|
const storedModelKey = normalizeDetectedLimitModelKey(result.detected_context_limit_model_key);
|
|
@@ -171785,19 +172175,22 @@ function getOverflowState(db, sessionId, modelKey) {
|
|
|
171785
172175
|
const limit = typeof result.detected_context_limit === "number" && result.detected_context_limit > 0 ? result.detected_context_limit : 0;
|
|
171786
172176
|
const modelMatches = limit > 0 && requestedModelKey && storedModelKey ? requestedModelKey === storedModelKey : true;
|
|
171787
172177
|
const needs = typeof result.needs_emergency_recovery === "number" && result.needs_emergency_recovery > 0;
|
|
172178
|
+
const persistedOrigin = normalizeEmergencyRecoveryOrigin(result.emergency_recovery_origin);
|
|
172179
|
+
const recoveryOrigin = needs ? persistedOrigin ?? (limit > 0 ? "provider_overflow" : null) : null;
|
|
171788
172180
|
return {
|
|
171789
172181
|
detectedContextLimit: modelMatches ? limit : 0,
|
|
171790
172182
|
detectedContextLimitModelKey: storedModelKey,
|
|
171791
|
-
needsEmergencyRecovery: needs
|
|
172183
|
+
needsEmergencyRecovery: needs,
|
|
172184
|
+
emergencyRecoveryOrigin: recoveryOrigin
|
|
171792
172185
|
};
|
|
171793
172186
|
}
|
|
171794
|
-
function recordOverflowDetected(db, sessionId, reportedLimit, modelKey) {
|
|
172187
|
+
function recordOverflowDetected(db, sessionId, reportedLimit, modelKey, origin = "provider_overflow") {
|
|
171795
172188
|
db.transaction(() => {
|
|
171796
172189
|
ensureSessionMetaRow(db, sessionId);
|
|
171797
172190
|
if (typeof reportedLimit === "number" && reportedLimit > 0) {
|
|
171798
|
-
db.prepare("UPDATE session_meta SET detected_context_limit = ?, detected_context_limit_model_key = ?, needs_emergency_recovery = 1, observed_safe_input_tokens = 0, cache_alert_sent = 0 WHERE session_id = ?").run(reportedLimit, normalizeDetectedLimitModelKey(modelKey), sessionId);
|
|
172191
|
+
db.prepare("UPDATE session_meta SET detected_context_limit = ?, detected_context_limit_model_key = ?, needs_emergency_recovery = 1, emergency_recovery_origin = ?, observed_safe_input_tokens = 0, cache_alert_sent = 0 WHERE session_id = ?").run(reportedLimit, normalizeDetectedLimitModelKey(modelKey), origin, sessionId);
|
|
171799
172192
|
} else {
|
|
171800
|
-
db.prepare("UPDATE session_meta SET needs_emergency_recovery = 1, observed_safe_input_tokens = 0, cache_alert_sent = 0 WHERE session_id = ?").run(sessionId);
|
|
172193
|
+
db.prepare("UPDATE session_meta SET needs_emergency_recovery = 1, emergency_recovery_origin = ?, observed_safe_input_tokens = 0, cache_alert_sent = 0 WHERE session_id = ?").run(origin, sessionId);
|
|
171801
172194
|
}
|
|
171802
172195
|
})();
|
|
171803
172196
|
}
|
|
@@ -171805,9 +172198,9 @@ function clearEmergencyRecovery(db, sessionId) {
|
|
|
171805
172198
|
db.transaction(() => {
|
|
171806
172199
|
ensureSessionMetaRow(db, sessionId);
|
|
171807
172200
|
try {
|
|
171808
|
-
db.prepare("UPDATE session_meta SET needs_emergency_recovery = 0, recovery_no_eligible_head_count = 0 WHERE session_id = ?").run(sessionId);
|
|
172201
|
+
db.prepare("UPDATE session_meta SET needs_emergency_recovery = 0, emergency_recovery_origin = '', recovery_no_eligible_head_count = 0 WHERE session_id = ?").run(sessionId);
|
|
171809
172202
|
} catch {
|
|
171810
|
-
db.prepare("UPDATE session_meta SET needs_emergency_recovery = 0 WHERE session_id = ?").run(sessionId);
|
|
172203
|
+
db.prepare("UPDATE session_meta SET needs_emergency_recovery = 0, emergency_recovery_origin = '' WHERE session_id = ?").run(sessionId);
|
|
171811
172204
|
}
|
|
171812
172205
|
})();
|
|
171813
172206
|
}
|
|
@@ -171885,6 +172278,36 @@ function parseStrippedBlob(raw) {
|
|
|
171885
172278
|
} catch {}
|
|
171886
172279
|
return [];
|
|
171887
172280
|
}
|
|
172281
|
+
function getProcessedImageStrippedIds(db, sessionId) {
|
|
172282
|
+
const row = db.prepare("SELECT processed_image_stripped_ids FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
172283
|
+
return new Set(parseStrippedBlob(row?.processed_image_stripped_ids));
|
|
172284
|
+
}
|
|
172285
|
+
function addProcessedImageStrippedIds(db, sessionId, ids) {
|
|
172286
|
+
const add = [...ids];
|
|
172287
|
+
if (add.length === 0)
|
|
172288
|
+
return true;
|
|
172289
|
+
ensureSessionMetaRow(db, sessionId);
|
|
172290
|
+
for (let attempt = 0;attempt < CAS_RETRY_LIMIT; attempt += 1) {
|
|
172291
|
+
const row = db.prepare("SELECT processed_image_stripped_ids FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
172292
|
+
const rawStored = row ? row.processed_image_stripped_ids ?? null : null;
|
|
172293
|
+
const current = new Set(parseStrippedBlob(rawStored));
|
|
172294
|
+
let changed = false;
|
|
172295
|
+
for (const id of add) {
|
|
172296
|
+
if (!current.has(id)) {
|
|
172297
|
+
current.add(id);
|
|
172298
|
+
changed = true;
|
|
172299
|
+
}
|
|
172300
|
+
}
|
|
172301
|
+
if (!changed)
|
|
172302
|
+
return true;
|
|
172303
|
+
const nextBlob = JSON.stringify([...current]);
|
|
172304
|
+
const result = db.prepare("UPDATE session_meta SET processed_image_stripped_ids = ? WHERE session_id = ? AND processed_image_stripped_ids IS ?").run(nextBlob, sessionId, rawStored);
|
|
172305
|
+
if (result.changes > 0)
|
|
172306
|
+
return true;
|
|
172307
|
+
}
|
|
172308
|
+
sessionLog(sessionId, `processed_image_stripped_ids CAS: ${CAS_RETRY_LIMIT} retries exhausted`);
|
|
172309
|
+
return false;
|
|
172310
|
+
}
|
|
171888
172311
|
function isPendingCompactionMarker(value) {
|
|
171889
172312
|
return typeof value === "object" && value !== null && typeof value.ordinal === "number" && typeof value.endMessageId === "string" && typeof value.publishedAt === "number";
|
|
171890
172313
|
}
|
|
@@ -172607,6 +173030,7 @@ var getTagNumbersByMessageIdStatements = new WeakMap;
|
|
|
172607
173030
|
var deleteTagsByMessageIdStatements = new WeakMap;
|
|
172608
173031
|
var getMaxTagNumberBySessionStatements = new WeakMap;
|
|
172609
173032
|
var getTagNumberByMessageIdStatements = new WeakMap;
|
|
173033
|
+
var hasPiFallbackMessageTagStatements = new WeakMap;
|
|
172610
173034
|
function getInsertTagStatement(db) {
|
|
172611
173035
|
let stmt = insertTagStatements.get(db);
|
|
172612
173036
|
if (!stmt) {
|
|
@@ -172750,6 +173174,18 @@ function getUpdateTagInputTokenCountStatement(db) {
|
|
|
172750
173174
|
function updateTagTokenCount(db, sessionId, tagNumber, newTokenCount) {
|
|
172751
173175
|
getUpdateTagTokenCountStatement(db).run(newTokenCount, sessionId, tagNumber);
|
|
172752
173176
|
}
|
|
173177
|
+
function getPersistedToolTagAccounting(db, sessionId, tagNumber) {
|
|
173178
|
+
const row = db.prepare(`SELECT byte_size AS byteSize,
|
|
173179
|
+
token_count AS tokenCount,
|
|
173180
|
+
input_byte_size AS inputByteSize,
|
|
173181
|
+
input_token_count AS inputTokenCount
|
|
173182
|
+
FROM tags
|
|
173183
|
+
WHERE session_id = ? AND tag_number = ? AND type = 'tool'`).get(sessionId, tagNumber);
|
|
173184
|
+
if (!row || typeof row.byteSize !== "number" || row.tokenCount !== null && typeof row.tokenCount !== "number" || typeof row.inputByteSize !== "number" || row.inputTokenCount !== null && typeof row.inputTokenCount !== "number") {
|
|
173185
|
+
return null;
|
|
173186
|
+
}
|
|
173187
|
+
return row;
|
|
173188
|
+
}
|
|
172753
173189
|
function getAllStatusTagTokenTotalsFlat(db, sessionId, floor = 0) {
|
|
172754
173190
|
const rows = floor > 0 ? db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
|
|
172755
173191
|
FROM tags
|
|
@@ -172851,6 +173287,19 @@ function updateTagDropMode(db, sessionId, tagNumber, dropMode) {
|
|
|
172851
173287
|
function updateCavemanDepth(db, sessionId, tagNumber, depth) {
|
|
172852
173288
|
db.prepare("UPDATE tags SET caveman_depth = ? WHERE session_id = ? AND tag_number = ?").run(depth, sessionId, tagNumber);
|
|
172853
173289
|
}
|
|
173290
|
+
function hasPiFallbackMessageTags(db, sessionId) {
|
|
173291
|
+
let statement = hasPiFallbackMessageTagStatements.get(db);
|
|
173292
|
+
if (!statement) {
|
|
173293
|
+
statement = db.prepare(`SELECT 1
|
|
173294
|
+
FROM tags
|
|
173295
|
+
WHERE session_id = ?
|
|
173296
|
+
AND type = 'message'
|
|
173297
|
+
AND message_id LIKE 'pi-msg-%'
|
|
173298
|
+
LIMIT 1`);
|
|
173299
|
+
hasPiFallbackMessageTagStatements.set(db, statement);
|
|
173300
|
+
}
|
|
173301
|
+
return statement.get(sessionId) != null;
|
|
173302
|
+
}
|
|
172854
173303
|
function findAdoptableFallbackTags(db, sessionId, entryFingerprint) {
|
|
172855
173304
|
const rows = db.prepare(`SELECT tag_number AS tagNumber, message_id AS messageId
|
|
172856
173305
|
FROM tags
|
|
@@ -173021,27 +173470,24 @@ function adoptPiFallbackToolOwnerTag(db, sessionId, tagNumber, callId, oldOwnerM
|
|
|
173021
173470
|
}
|
|
173022
173471
|
const existing = getPiFallbackToolFoldTagRowByOwner(db, sessionId, callId, newOwnerMessageId);
|
|
173023
173472
|
if (existing === null) {
|
|
173024
|
-
const
|
|
173473
|
+
const result = db.prepare(`UPDATE tags
|
|
173025
173474
|
SET tool_owner_message_id = ?
|
|
173026
173475
|
WHERE session_id = ?
|
|
173027
173476
|
AND tag_number = ?
|
|
173028
173477
|
AND type = 'tool'
|
|
173029
173478
|
AND message_id = ?
|
|
173030
173479
|
AND tool_owner_message_id = ?`).run(newOwnerMessageId, sessionId, tagNumber, callId, oldOwnerMessageId);
|
|
173031
|
-
return (
|
|
173480
|
+
return (result.changes ?? 0) === 1 ? { action: "rekeyed", tagNumber } : { action: "skipped" };
|
|
173032
173481
|
}
|
|
173033
173482
|
if (existing.tagNumber === tagNumber) {
|
|
173034
173483
|
return { action: "skipped" };
|
|
173035
173484
|
}
|
|
173036
|
-
foldDuplicateIntoSurvivor(db, sessionId,
|
|
173037
|
-
|
|
173038
|
-
|
|
173039
|
-
|
|
173040
|
-
|
|
173041
|
-
|
|
173042
|
-
AND message_id = ?
|
|
173043
|
-
AND tool_owner_message_id = ?`).run(newOwnerMessageId, sessionId, tagNumber, callId, oldOwnerMessageId);
|
|
173044
|
-
return (result.changes ?? 0) === 1 ? { action: "folded", tagNumber, deletedTagNumbers: [existing.tagNumber] } : { action: "skipped" };
|
|
173485
|
+
foldDuplicateIntoSurvivor(db, sessionId, existing, survivor);
|
|
173486
|
+
return {
|
|
173487
|
+
action: "folded",
|
|
173488
|
+
tagNumber: existing.tagNumber,
|
|
173489
|
+
deletedTagNumbers: [tagNumber]
|
|
173490
|
+
};
|
|
173045
173491
|
}
|
|
173046
173492
|
function adoptPiFallbackMessageTag(db, sessionId, tagNumber, oldFallbackMessageId, newRealMessageId) {
|
|
173047
173493
|
const survivor = getPiFallbackFoldTagRowByNumber(db, sessionId, tagNumber);
|
|
@@ -173050,26 +173496,28 @@ function adoptPiFallbackMessageTag(db, sessionId, tagNumber, oldFallbackMessageI
|
|
|
173050
173496
|
}
|
|
173051
173497
|
const duplicates = getPiFallbackMessageFoldTagRowsByMessageId(db, sessionId, newRealMessageId).filter((row) => row.tagNumber !== tagNumber);
|
|
173052
173498
|
if (duplicates.length === 0) {
|
|
173053
|
-
const
|
|
173499
|
+
const result = db.prepare(`UPDATE tags
|
|
173054
173500
|
SET message_id = ?
|
|
173055
173501
|
WHERE session_id = ?
|
|
173056
173502
|
AND tag_number = ?
|
|
173057
173503
|
AND type = 'message'
|
|
173058
173504
|
AND message_id = ?`).run(newRealMessageId, sessionId, tagNumber, oldFallbackMessageId);
|
|
173059
|
-
return (
|
|
173505
|
+
return (result.changes ?? 0) === 1 ? { action: "rekeyed", tagNumber } : { action: "skipped" };
|
|
173060
173506
|
}
|
|
173061
|
-
const
|
|
173062
|
-
|
|
173063
|
-
|
|
173507
|
+
const realSurvivor = duplicates[0];
|
|
173508
|
+
if (!realSurvivor)
|
|
173509
|
+
return { action: "skipped" };
|
|
173510
|
+
const deletedTagNumbers = [tagNumber];
|
|
173511
|
+
foldDuplicateIntoSurvivor(db, sessionId, realSurvivor, survivor);
|
|
173512
|
+
for (const duplicate of duplicates.slice(1)) {
|
|
173513
|
+
foldDuplicateIntoSurvivor(db, sessionId, realSurvivor, duplicate);
|
|
173064
173514
|
deletedTagNumbers.push(duplicate.tagNumber);
|
|
173065
173515
|
}
|
|
173066
|
-
|
|
173067
|
-
|
|
173068
|
-
|
|
173069
|
-
|
|
173070
|
-
|
|
173071
|
-
AND message_id = ?`).run(newRealMessageId, sessionId, tagNumber, oldFallbackMessageId);
|
|
173072
|
-
return (result.changes ?? 0) === 1 ? { action: "folded", tagNumber, deletedTagNumbers } : { action: "skipped" };
|
|
173516
|
+
return {
|
|
173517
|
+
action: "folded",
|
|
173518
|
+
tagNumber: realSurvivor.tagNumber,
|
|
173519
|
+
deletedTagNumbers
|
|
173520
|
+
};
|
|
173073
173521
|
}
|
|
173074
173522
|
var getOwnerScopedToolTagNumbersStatements = new WeakMap;
|
|
173075
173523
|
function getMaxTagNumberBySession(db, sessionId) {
|
|
@@ -173141,10 +173589,40 @@ function getActiveTagsBySessionStatement(db) {
|
|
|
173141
173589
|
}
|
|
173142
173590
|
return stmt;
|
|
173143
173591
|
}
|
|
173592
|
+
function getMaxDroppedTagNumberStatement(db) {
|
|
173593
|
+
let stmt = getMaxDroppedTagNumberStatements.get(db);
|
|
173594
|
+
if (!stmt) {
|
|
173595
|
+
stmt = db.prepare("SELECT COALESCE(MAX(tag_number), 0) AS max_tag_number FROM tags WHERE session_id = ? AND status = 'dropped'");
|
|
173596
|
+
getMaxDroppedTagNumberStatements.set(db, stmt);
|
|
173597
|
+
}
|
|
173598
|
+
return stmt;
|
|
173599
|
+
}
|
|
173144
173600
|
function getActiveTagsBySession(db, sessionId) {
|
|
173145
173601
|
const rows = getActiveTagsBySessionStatement(db).all(sessionId).filter(isTagRow);
|
|
173146
173602
|
return rows.map(toTagEntry);
|
|
173147
173603
|
}
|
|
173604
|
+
function getTagsForPendingOperations(db, sessionId, pendingTagNumbers, protectedTags, recentToolWindow) {
|
|
173605
|
+
const byNumber = new Map;
|
|
173606
|
+
for (const tag of getTagsByNumbers(db, sessionId, pendingTagNumbers)) {
|
|
173607
|
+
byNumber.set(tag.tagNumber, tag);
|
|
173608
|
+
}
|
|
173609
|
+
const addRows = (sql, limit) => {
|
|
173610
|
+
if (limit <= 0)
|
|
173611
|
+
return;
|
|
173612
|
+
const rows = db.prepare(sql).all(sessionId, limit).filter(isTagRow);
|
|
173613
|
+
for (const row of rows) {
|
|
173614
|
+
const tag = toTagEntry(row);
|
|
173615
|
+
byNumber.set(tag.tagNumber, tag);
|
|
173616
|
+
}
|
|
173617
|
+
};
|
|
173618
|
+
addRows(`SELECT ${TAG_SELECT_COLUMNS} FROM tags
|
|
173619
|
+
WHERE session_id = ? AND status = 'active'
|
|
173620
|
+
ORDER BY tag_number DESC, id DESC LIMIT ?`, protectedTags);
|
|
173621
|
+
addRows(`SELECT ${TAG_SELECT_COLUMNS} FROM tags
|
|
173622
|
+
WHERE session_id = ? AND type = 'tool'
|
|
173623
|
+
ORDER BY tag_number DESC, id DESC LIMIT ?`, recentToolWindow);
|
|
173624
|
+
return [...byNumber.values()].sort((left, right) => left.tagNumber - right.tagNumber);
|
|
173625
|
+
}
|
|
173148
173626
|
function getTagsByNumbers(db, sessionId, tagNumbers) {
|
|
173149
173627
|
if (tagNumbers.length === 0)
|
|
173150
173628
|
return [];
|
|
@@ -173159,6 +173637,10 @@ function getTagsByNumbers(db, sessionId, tagNumbers) {
|
|
|
173159
173637
|
const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? AND tag_number IN (${placeholders4}) ORDER BY tag_number ASC, id ASC`).all(sessionId, ...tagNumbers).filter(isTagRow);
|
|
173160
173638
|
return rows.map(toTagEntry);
|
|
173161
173639
|
}
|
|
173640
|
+
function getMaxDroppedTagNumber(db, sessionId) {
|
|
173641
|
+
const row = getMaxDroppedTagNumberStatement(db).get(sessionId);
|
|
173642
|
+
return isMaxTagNumberRow(row) ? row.max_tag_number : 0;
|
|
173643
|
+
}
|
|
173162
173644
|
var getToolTagNumberByOwnerStatements = new WeakMap;
|
|
173163
173645
|
var getNullOwnerToolTagStatements = new WeakMap;
|
|
173164
173646
|
var adoptNullOwnerToolTagStatements = new WeakMap;
|
|
@@ -175460,6 +175942,30 @@ class BoundedSessionMap {
|
|
|
175460
175942
|
// ../plugin/src/hooks/magic-context/inject-compartments.ts
|
|
175461
175943
|
init_logger();
|
|
175462
175944
|
|
|
175945
|
+
// ../plugin/src/hooks/magic-context/compartment-render-epoch.ts
|
|
175946
|
+
var COMPARTMENT_RENDER_EPOCH = "cre2";
|
|
175947
|
+
var EPOCH_COMPONENT_PREFIX = "|compartment-render:";
|
|
175948
|
+
function encodeCachedM0UpgradeIdentity(upgradeState, compartmentRenderEpoch = COMPARTMENT_RENDER_EPOCH) {
|
|
175949
|
+
if (compartmentRenderEpoch === null)
|
|
175950
|
+
return upgradeState;
|
|
175951
|
+
return `${upgradeState ?? ""}${EPOCH_COMPONENT_PREFIX}${compartmentRenderEpoch}`;
|
|
175952
|
+
}
|
|
175953
|
+
function decodeCachedM0UpgradeIdentity(value) {
|
|
175954
|
+
if (value === null) {
|
|
175955
|
+
return { upgradeState: null, compartmentRenderEpoch: null };
|
|
175956
|
+
}
|
|
175957
|
+
const componentIndex = value.lastIndexOf(EPOCH_COMPONENT_PREFIX);
|
|
175958
|
+
if (componentIndex < 0) {
|
|
175959
|
+
return { upgradeState: value, compartmentRenderEpoch: null };
|
|
175960
|
+
}
|
|
175961
|
+
const upgradeState = value.slice(0, componentIndex);
|
|
175962
|
+
const compartmentRenderEpoch = value.slice(componentIndex + EPOCH_COMPONENT_PREFIX.length);
|
|
175963
|
+
return {
|
|
175964
|
+
upgradeState: upgradeState.length > 0 ? upgradeState : null,
|
|
175965
|
+
compartmentRenderEpoch: compartmentRenderEpoch.length > 0 ? compartmentRenderEpoch : null
|
|
175966
|
+
};
|
|
175967
|
+
}
|
|
175968
|
+
|
|
175463
175969
|
// ../plugin/src/hooks/magic-context/decay-curve.ts
|
|
175464
175970
|
var H50 = 24;
|
|
175465
175971
|
var D = 25;
|
|
@@ -175517,12 +176023,29 @@ function computeBudgetPressure(compartments, historyBudget) {
|
|
|
175517
176023
|
|
|
175518
176024
|
// ../plugin/src/hooks/magic-context/decay-render.ts
|
|
175519
176025
|
var DEFAULT_HISTORY_BUDGET_TOKENS = 60000;
|
|
175520
|
-
function escapeXmlAttr2(s) {
|
|
175521
|
-
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
175522
|
-
}
|
|
175523
176026
|
function escapeXmlContent2(s) {
|
|
175524
176027
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
175525
176028
|
}
|
|
176029
|
+
function formatDateRange(startDate, endDate) {
|
|
176030
|
+
if (!startDate || !endDate)
|
|
176031
|
+
return "";
|
|
176032
|
+
if (startDate === endDate)
|
|
176033
|
+
return startDate;
|
|
176034
|
+
if (startDate.slice(0, 7) === endDate.slice(0, 7))
|
|
176035
|
+
return `${startDate}→${endDate.slice(8)}`;
|
|
176036
|
+
return `${startDate}→${endDate}`;
|
|
176037
|
+
}
|
|
176038
|
+
function sanitizeCompartmentTitle(title) {
|
|
176039
|
+
return escapeXmlContent2(title.replace(/[\p{Cc}\p{Zl}\p{Zp}]+/gu, " "));
|
|
176040
|
+
}
|
|
176041
|
+
function compartmentHeading(c) {
|
|
176042
|
+
const dateRange = formatDateRange(c.startDate, c.endDate);
|
|
176043
|
+
const dateSegment = dateRange ? ` · ${dateRange}` : "";
|
|
176044
|
+
return `## ${c.startMessage}-${c.endMessage}${dateSegment} · ${sanitizeCompartmentTitle(c.title)}`;
|
|
176045
|
+
}
|
|
176046
|
+
function guardCompartmentBody(body) {
|
|
176047
|
+
return body.replace(/^## /gm, " ## ");
|
|
176048
|
+
}
|
|
175526
176049
|
function isTieredRow(c) {
|
|
175527
176050
|
return typeof c.p1 === "string" && c.p1.length > 0;
|
|
175528
176051
|
}
|
|
@@ -175552,25 +176075,22 @@ function renderCompartmentAtTier(c, tier2) {
|
|
|
175552
176075
|
return renderOneCompartment(c, tier2);
|
|
175553
176076
|
}
|
|
175554
176077
|
function renderOneCompartment(c, tier2) {
|
|
175555
|
-
const baseAttrs = `start="${c.startMessage}" end="${c.endMessage}" title="${escapeXmlAttr2(c.title)}"`;
|
|
175556
176078
|
if (tier2 >= 5)
|
|
175557
176079
|
return "";
|
|
176080
|
+
const heading = compartmentHeading(c);
|
|
175558
176081
|
if (c.legacy === 1 || !isTieredRow(c)) {
|
|
175559
176082
|
const flat = (c.content ?? "").trim();
|
|
175560
176083
|
if (tier2 >= 4 || flat.length === 0)
|
|
175561
|
-
return
|
|
175562
|
-
|
|
175563
|
-
|
|
175564
|
-
|
|
175565
|
-
"</compartment>"
|
|
175566
|
-
].join(`
|
|
175567
|
-
`);
|
|
176084
|
+
return heading;
|
|
176085
|
+
const body2 = guardCompartmentBody(escapeXmlContent2(legacyBodyForTier(flat, tier2)));
|
|
176086
|
+
return `${heading}
|
|
176087
|
+
${body2}`;
|
|
175568
176088
|
}
|
|
175569
176089
|
const body = tierBody(c, tier2);
|
|
175570
176090
|
if (body.length === 0)
|
|
175571
|
-
return
|
|
175572
|
-
return
|
|
175573
|
-
|
|
176091
|
+
return heading;
|
|
176092
|
+
return `${heading}
|
|
176093
|
+
${guardCompartmentBody(escapeXmlContent2(body))}`;
|
|
175574
176094
|
}
|
|
175575
176095
|
function computeTiers(compartments, historyBudgetTokens) {
|
|
175576
176096
|
const v2Compartments = compartments.map((c, originalIndex) => ({ c, originalIndex })).filter(({ c }) => c.legacy !== 1);
|
|
@@ -175693,33 +176213,9 @@ function getVisibleMemoryIds(db, sessionId) {
|
|
|
175693
176213
|
}
|
|
175694
176214
|
}
|
|
175695
176215
|
function renderMemoryBlock(memories) {
|
|
175696
|
-
|
|
175697
|
-
for (const m of memories) {
|
|
175698
|
-
const existing = byCategory.get(m.category);
|
|
175699
|
-
if (existing) {
|
|
175700
|
-
existing.push(m);
|
|
175701
|
-
} else {
|
|
175702
|
-
byCategory.set(m.category, [m]);
|
|
175703
|
-
}
|
|
175704
|
-
}
|
|
175705
|
-
const sections = [];
|
|
175706
|
-
for (const category of CATEGORY_PRIORITY) {
|
|
175707
|
-
const categoryMemories = byCategory.get(category);
|
|
175708
|
-
if (!categoryMemories || categoryMemories.length === 0) {
|
|
175709
|
-
continue;
|
|
175710
|
-
}
|
|
175711
|
-
sections.push(`<${category}>`, ...categoryMemories.map((m) => `- ${escapeXmlContent(m.content)}`), `</${category}>`);
|
|
175712
|
-
}
|
|
175713
|
-
if (sections.length === 0) {
|
|
175714
|
-
return null;
|
|
175715
|
-
}
|
|
175716
|
-
return `<project-memory>
|
|
175717
|
-
${sections.join(`
|
|
175718
|
-
`)}
|
|
175719
|
-
</project-memory>`;
|
|
176216
|
+
return renderMemoryBlockV2(memories) || null;
|
|
175720
176217
|
}
|
|
175721
176218
|
var DEFAULT_MEMORY_BUDGET_TOKENS = 8000;
|
|
175722
|
-
var MEMORY_BLOCK_WRAPPER_TOKENS = 6;
|
|
175723
176219
|
var DEFAULT_USER_PROFILE_BUDGET_TOKENS = 4000;
|
|
175724
176220
|
function memoryCanonicalIdentity(memory2, workspace) {
|
|
175725
176221
|
return resolveStoredPathWorkspaceIdentity(memory2.projectPath, workspace.identities, workspace.canonicalIdentityByStoredPath);
|
|
@@ -175737,11 +176233,18 @@ function memorySelectionOrder(left, right) {
|
|
|
175737
176233
|
return left.id - right.id;
|
|
175738
176234
|
}
|
|
175739
176235
|
function memoryRenderOrder(left, right) {
|
|
175740
|
-
const
|
|
175741
|
-
const
|
|
175742
|
-
|
|
175743
|
-
|
|
175744
|
-
|
|
176236
|
+
const leftPriority = V2_MEMORY_CATEGORIES.indexOf(left.category);
|
|
176237
|
+
const rightPriority = V2_MEMORY_CATEGORIES.indexOf(right.category);
|
|
176238
|
+
if (leftPriority >= 0 || rightPriority >= 0) {
|
|
176239
|
+
if (leftPriority < 0)
|
|
176240
|
+
return 1;
|
|
176241
|
+
if (rightPriority < 0)
|
|
176242
|
+
return -1;
|
|
176243
|
+
if (leftPriority !== rightPriority)
|
|
176244
|
+
return leftPriority - rightPriority;
|
|
176245
|
+
} else if (left.category !== right.category) {
|
|
176246
|
+
return left.category < right.category ? -1 : 1;
|
|
176247
|
+
}
|
|
175745
176248
|
return left.id - right.id;
|
|
175746
176249
|
}
|
|
175747
176250
|
var maxCompartmentSeqStatements = new WeakMap;
|
|
@@ -175752,13 +176255,13 @@ var newCompartmentStatements = new WeakMap;
|
|
|
175752
176255
|
function trimMemoriesToBudgetV2(sessionId, memories, budgetTokens, renderOptions = {}) {
|
|
175753
176256
|
const selectionOrder = [...memories].sort(memorySelectionOrder);
|
|
175754
176257
|
const selected = [];
|
|
175755
|
-
|
|
176258
|
+
const accounting = createMemoryBlockAccounting(renderOptions);
|
|
175756
176259
|
for (const memory2 of selectionOrder) {
|
|
175757
|
-
const
|
|
175758
|
-
if (usedTokens +
|
|
176260
|
+
const cost = accounting.candidateCost(memory2);
|
|
176261
|
+
if (accounting.usedTokens + cost > budgetTokens)
|
|
175759
176262
|
continue;
|
|
176263
|
+
accounting.admit(memory2, cost);
|
|
175760
176264
|
selected.push(memory2);
|
|
175761
|
-
usedTokens += memoryTokens;
|
|
175762
176265
|
}
|
|
175763
176266
|
if (selected.length < memories.length) {
|
|
175764
176267
|
sessionLog(sessionId, `v2 trimmed memories from ${memories.length} to ${selected.length} to fit injection budget of ${budgetTokens} tokens`);
|
|
@@ -175772,23 +176275,22 @@ function trimWorkspaceMemoriesToBudgetV2(sessionId, memories, budgetTokens, work
|
|
|
175772
176275
|
}
|
|
175773
176276
|
const selected = [];
|
|
175774
176277
|
const selectedIds = new Set;
|
|
175775
|
-
|
|
175776
|
-
const tokenCost = (memory2) => estimateTokens(renderMemoryLineV2(memory2, renderOptions.sourceNameByMemoryId?.get(memory2.id)));
|
|
176278
|
+
const accounting = createMemoryBlockAccounting(renderOptions);
|
|
175777
176279
|
const trySelect = (memory2) => {
|
|
175778
176280
|
if (selectedIds.has(memory2.id))
|
|
175779
176281
|
return false;
|
|
175780
|
-
const
|
|
175781
|
-
if (usedTokens +
|
|
176282
|
+
const cost = accounting.candidateCost(memory2);
|
|
176283
|
+
if (accounting.usedTokens + cost > budgetTokens)
|
|
175782
176284
|
return false;
|
|
175783
176285
|
selected.push(memory2);
|
|
175784
176286
|
selectedIds.add(memory2.id);
|
|
175785
|
-
|
|
176287
|
+
accounting.admit(memory2, cost);
|
|
175786
176288
|
return true;
|
|
175787
176289
|
};
|
|
175788
176290
|
for (const memory2 of memories.filter((candidate) => candidate.status === "permanent").sort(memorySelectionOrder)) {
|
|
175789
176291
|
trySelect(memory2);
|
|
175790
176292
|
}
|
|
175791
|
-
const remainingAfterPermanent = Math.max(0, budgetTokens - usedTokens);
|
|
176293
|
+
const remainingAfterPermanent = Math.max(0, budgetTokens - accounting.usedTokens);
|
|
175792
176294
|
const floorTokens = remainingAfterPermanent / Math.max(1, workspace.identities.length);
|
|
175793
176295
|
const byIdentity = new Map;
|
|
175794
176296
|
for (const memory2 of memories) {
|
|
@@ -175807,15 +176309,15 @@ function trimWorkspaceMemoriesToBudgetV2(sessionId, memories, budgetTokens, work
|
|
|
175807
176309
|
for (const memory2 of candidates2) {
|
|
175808
176310
|
if (selectedIds.has(memory2.id))
|
|
175809
176311
|
continue;
|
|
175810
|
-
const
|
|
175811
|
-
if (memberTokens +
|
|
176312
|
+
const cost = accounting.candidateCost(memory2);
|
|
176313
|
+
if (memberTokens + cost > floorTokens)
|
|
175812
176314
|
continue;
|
|
175813
|
-
if (usedTokens +
|
|
176315
|
+
if (accounting.usedTokens + cost > budgetTokens)
|
|
175814
176316
|
continue;
|
|
175815
176317
|
selected.push(memory2);
|
|
175816
176318
|
selectedIds.add(memory2.id);
|
|
175817
|
-
|
|
175818
|
-
memberTokens +=
|
|
176319
|
+
accounting.admit(memory2, cost);
|
|
176320
|
+
memberTokens += cost;
|
|
175819
176321
|
}
|
|
175820
176322
|
}
|
|
175821
176323
|
const remaining = memories.filter((memory2) => !selectedIds.has(memory2.id)).sort(memorySelectionOrder);
|
|
@@ -175839,17 +176341,55 @@ function trimUserMemoriesToBudget(memories, budgetTokens) {
|
|
|
175839
176341
|
}
|
|
175840
176342
|
return selected;
|
|
175841
176343
|
}
|
|
176344
|
+
function createMemoryBlockAccounting(renderOptions) {
|
|
176345
|
+
const seenCategories = new Set;
|
|
176346
|
+
const categoryCost = new Map;
|
|
176347
|
+
return {
|
|
176348
|
+
usedTokens: estimateTokens(`<project-memory>
|
|
176349
|
+
</project-memory>`),
|
|
176350
|
+
candidateCost(memory2) {
|
|
176351
|
+
const line = renderMemoryLineV2(memory2, renderOptions.sourceNameByMemoryId?.get(memory2.id));
|
|
176352
|
+
let cost = estimateTokens(`${line}
|
|
176353
|
+
`);
|
|
176354
|
+
if (!seenCategories.has(memory2.category)) {
|
|
176355
|
+
let tags = categoryCost.get(memory2.category);
|
|
176356
|
+
if (tags === undefined) {
|
|
176357
|
+
tags = estimateTokens(`<${escapeXmlAttr(memory2.category)}>
|
|
176358
|
+
</${escapeXmlAttr(memory2.category)}>
|
|
176359
|
+
`);
|
|
176360
|
+
categoryCost.set(memory2.category, tags);
|
|
176361
|
+
}
|
|
176362
|
+
cost += tags;
|
|
176363
|
+
}
|
|
176364
|
+
return cost;
|
|
176365
|
+
},
|
|
176366
|
+
admit(memory2, cost) {
|
|
176367
|
+
this.usedTokens += cost;
|
|
176368
|
+
seenCategories.add(memory2.category);
|
|
176369
|
+
}
|
|
176370
|
+
};
|
|
176371
|
+
}
|
|
175842
176372
|
function renderMemoryLineV2(memory2, sourceName) {
|
|
175843
|
-
const
|
|
175844
|
-
return
|
|
176373
|
+
const source = sourceName ? ` [${escapeXmlContent(sourceName)}]` : "";
|
|
176374
|
+
return `#${memory2.id}${source}: ${escapeXmlContent(memory2.content)}`;
|
|
175845
176375
|
}
|
|
175846
176376
|
function renderMemoryBlockV2(memories, wrapper = "project-memory", renderOptions = {}) {
|
|
175847
176377
|
if (memories.length === 0)
|
|
175848
176378
|
return "";
|
|
176379
|
+
const ordered = [...memories].sort(memoryRenderOrder);
|
|
175849
176380
|
const lines = [`<${wrapper}>`];
|
|
175850
|
-
|
|
176381
|
+
let openCategory;
|
|
176382
|
+
for (const memory2 of ordered) {
|
|
176383
|
+
if (memory2.category !== openCategory) {
|
|
176384
|
+
if (openCategory !== undefined)
|
|
176385
|
+
lines.push(`</${escapeXmlAttr(openCategory)}>`);
|
|
176386
|
+
openCategory = memory2.category;
|
|
176387
|
+
lines.push(`<${escapeXmlAttr(openCategory)}>`);
|
|
176388
|
+
}
|
|
175851
176389
|
lines.push(renderMemoryLineV2(memory2, renderOptions.sourceNameByMemoryId?.get(memory2.id)));
|
|
175852
176390
|
}
|
|
176391
|
+
if (openCategory !== undefined)
|
|
176392
|
+
lines.push(`</${escapeXmlAttr(openCategory)}>`);
|
|
175853
176393
|
lines.push(`</${wrapper}>`);
|
|
175854
176394
|
return lines.join(`
|
|
175855
176395
|
`);
|
|
@@ -176163,6 +176703,8 @@ var STATUS_COLOR = {
|
|
|
176163
176703
|
cancelled: "error"
|
|
176164
176704
|
};
|
|
176165
176705
|
var snapshotsBySession = new Map;
|
|
176706
|
+
var MAX_TODOWRITE_RENDER_CACHE_ENTRIES = 50;
|
|
176707
|
+
var cachedTodowriteTodosByToolCallId = new Map;
|
|
176166
176708
|
function isTodoStatus2(value) {
|
|
176167
176709
|
return TODO_STATUSES.includes(value);
|
|
176168
176710
|
}
|
|
@@ -176172,6 +176714,27 @@ function isTodoPriority2(value) {
|
|
|
176172
176714
|
function cloneTodos(todos) {
|
|
176173
176715
|
return todos.map((todo) => ({ ...todo }));
|
|
176174
176716
|
}
|
|
176717
|
+
function rememberTodowriteToolCallTodos(toolCallId, todos) {
|
|
176718
|
+
if (!toolCallId)
|
|
176719
|
+
return;
|
|
176720
|
+
cachedTodowriteTodosByToolCallId.delete(toolCallId);
|
|
176721
|
+
cachedTodowriteTodosByToolCallId.set(toolCallId, cloneTodos(todos));
|
|
176722
|
+
while (cachedTodowriteTodosByToolCallId.size > MAX_TODOWRITE_RENDER_CACHE_ENTRIES) {
|
|
176723
|
+
const oldestKey = cachedTodowriteTodosByToolCallId.keys().next().value;
|
|
176724
|
+
if (typeof oldestKey !== "string")
|
|
176725
|
+
break;
|
|
176726
|
+
cachedTodowriteTodosByToolCallId.delete(oldestKey);
|
|
176727
|
+
}
|
|
176728
|
+
}
|
|
176729
|
+
function getCachedTodowriteToolCallTodos(toolCallId) {
|
|
176730
|
+
if (!toolCallId)
|
|
176731
|
+
return null;
|
|
176732
|
+
const todos = cachedTodowriteTodosByToolCallId.get(toolCallId);
|
|
176733
|
+
return todos ? cloneTodos(todos) : null;
|
|
176734
|
+
}
|
|
176735
|
+
function clearTodowriteToolCallTodos() {
|
|
176736
|
+
cachedTodowriteTodosByToolCallId.clear();
|
|
176737
|
+
}
|
|
176175
176738
|
function parseTodos(input) {
|
|
176176
176739
|
if (!Array.isArray(input))
|
|
176177
176740
|
return null;
|
|
@@ -176308,25 +176871,27 @@ function capTodoRows(rows) {
|
|
|
176308
176871
|
hiddenCount: rows.length - visibleCount
|
|
176309
176872
|
};
|
|
176310
176873
|
}
|
|
176311
|
-
function renderTodowriteCall(args, theme) {
|
|
176312
|
-
const todos = parseTodos(args.todos) ?? [];
|
|
176874
|
+
function renderTodowriteCall(args, theme, context) {
|
|
176875
|
+
const todos = getCachedTodowriteToolCallTodos(context?.toolCallId) ?? parseTodos(args.todos) ?? [];
|
|
176313
176876
|
const active = activeTitleCount(todos);
|
|
176314
176877
|
const activeColor = active > 0 ? "warning" : "success";
|
|
176315
176878
|
const line = `${theme.fg("toolTitle", theme.bold("Todos"))} ${theme.fg("muted", "—")} ${theme.fg(activeColor, `${active} active`)}`;
|
|
176316
176879
|
return lineComponent((width) => [truncateToWidth(line, width, "…")]);
|
|
176317
176880
|
}
|
|
176318
|
-
function renderTodowriteResult(result, theme) {
|
|
176881
|
+
function renderTodowriteResult(result, theme, context) {
|
|
176319
176882
|
const detailsTodos = result.details?.todos;
|
|
176320
176883
|
let todos = parseTodos(detailsTodos);
|
|
176321
|
-
if (todos === null && Array.isArray(result.content)) {
|
|
176884
|
+
if ((todos === null || todos.length === 0) && Array.isArray(result.content)) {
|
|
176322
176885
|
const text = result.content.find((part) => part !== null && typeof part === "object" && part.type === "text" && typeof part.text === "string")?.text;
|
|
176323
176886
|
if (text) {
|
|
176324
176887
|
try {
|
|
176325
|
-
|
|
176888
|
+
const parsed = parseTodos(JSON.parse(text));
|
|
176889
|
+
if (parsed !== null)
|
|
176890
|
+
todos = parsed;
|
|
176326
176891
|
} catch {}
|
|
176327
176892
|
}
|
|
176328
176893
|
}
|
|
176329
|
-
const renderedTodos = todos ?? [];
|
|
176894
|
+
const renderedTodos = todos !== null && todos.length > 0 ? todos : getCachedTodowriteToolCallTodos(context?.toolCallId) ?? todos ?? [];
|
|
176330
176895
|
return lineComponent((width) => {
|
|
176331
176896
|
if (renderedTodos.length === 0)
|
|
176332
176897
|
return [theme.fg("dim", "No todos")];
|
|
@@ -176527,6 +177092,7 @@ function registerTodoOverlay(pi, deps) {
|
|
|
176527
177092
|
overlay.hideCompletedTasksFromPreviousTurn();
|
|
176528
177093
|
});
|
|
176529
177094
|
pi.on("session_shutdown", async (_event, ctx) => {
|
|
177095
|
+
clearTodowriteToolCallTodos();
|
|
176530
177096
|
const sessionId = getSessionId(ctx);
|
|
176531
177097
|
if (!sessionId)
|
|
176532
177098
|
return;
|
|
@@ -176534,6 +177100,7 @@ function registerTodoOverlay(pi, deps) {
|
|
|
176534
177100
|
overlay.disposeSession(sessionId);
|
|
176535
177101
|
});
|
|
176536
177102
|
pi.on("session_before_switch", async (_event, ctx) => {
|
|
177103
|
+
clearTodowriteToolCallTodos();
|
|
176537
177104
|
const sessionId = getSessionId(ctx);
|
|
176538
177105
|
if (!sessionId)
|
|
176539
177106
|
return;
|
|
@@ -176550,11 +177117,13 @@ function registerTodoStateLifecycle(pi, deps) {
|
|
|
176550
177117
|
seedTodoSnapshotFromStateJson(sessionId, deps.readLastTodoState(sessionId));
|
|
176551
177118
|
});
|
|
176552
177119
|
pi.on("session_shutdown", async (_event, ctx) => {
|
|
177120
|
+
clearTodowriteToolCallTodos();
|
|
176553
177121
|
const sessionId = getSessionId(ctx);
|
|
176554
177122
|
if (sessionId)
|
|
176555
177123
|
clearTodoSnapshot(sessionId);
|
|
176556
177124
|
});
|
|
176557
177125
|
pi.on("session_before_switch", async (_event, ctx) => {
|
|
177126
|
+
clearTodowriteToolCallTodos();
|
|
176558
177127
|
const sessionId = getSessionId(ctx);
|
|
176559
177128
|
if (sessionId)
|
|
176560
177129
|
clearTodoSnapshot(sessionId);
|
|
@@ -176605,11 +177174,11 @@ function createTodowriteTool() {
|
|
|
176605
177174
|
}
|
|
176606
177175
|
};
|
|
176607
177176
|
},
|
|
176608
|
-
renderCall(args, theme) {
|
|
176609
|
-
return renderTodowriteCall(args, theme);
|
|
177177
|
+
renderCall(args, theme, context) {
|
|
177178
|
+
return renderTodowriteCall(args, theme, context);
|
|
176610
177179
|
},
|
|
176611
|
-
renderResult(result, _opts, theme) {
|
|
176612
|
-
return renderTodowriteResult(result, theme);
|
|
177180
|
+
renderResult(result, _opts, theme, context) {
|
|
177181
|
+
return renderTodowriteResult(result, theme, context);
|
|
176613
177182
|
}
|
|
176614
177183
|
};
|
|
176615
177184
|
}
|