@cortexkit/magic-context 0.25.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +1046 -449
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -12212,6 +12212,622 @@ var init_migrate = __esm(async () => {
12212
12212
  await init_sqlite();
12213
12213
  });
12214
12214
 
12215
+ // ../plugin/src/features/magic-context/memory/project-identity.ts
12216
+ import { execFileSync as execFileSync3 } from "node:child_process";
12217
+ import { createHash } from "node:crypto";
12218
+ import { statSync as statSync3 } from "node:fs";
12219
+ import path2 from "node:path";
12220
+ function asError(error) {
12221
+ return error instanceof Error ? error : undefined;
12222
+ }
12223
+ function getErrorCode(error) {
12224
+ if (error === null || typeof error !== "object" || !("code" in error)) {
12225
+ return;
12226
+ }
12227
+ const code = error.code;
12228
+ return typeof code === "string" ? code : undefined;
12229
+ }
12230
+ function getErrorSignal(error) {
12231
+ if (error === null || typeof error !== "object" || !("signal" in error)) {
12232
+ return;
12233
+ }
12234
+ const signal = error.signal;
12235
+ return typeof signal === "string" ? signal : undefined;
12236
+ }
12237
+ function getErrorKilled(error) {
12238
+ if (error === null || typeof error !== "object" || !("killed" in error)) {
12239
+ return false;
12240
+ }
12241
+ return error.killed === true;
12242
+ }
12243
+ function getErrorStderr(error) {
12244
+ if (error === null || typeof error !== "object" || !("stderr" in error)) {
12245
+ return "";
12246
+ }
12247
+ const stderr = error.stderr;
12248
+ if (typeof stderr === "string") {
12249
+ return stderr;
12250
+ }
12251
+ if (Buffer.isBuffer(stderr)) {
12252
+ return stderr.toString("utf8");
12253
+ }
12254
+ return "";
12255
+ }
12256
+ function directoryFallback(directory) {
12257
+ const canonical = path2.resolve(directory);
12258
+ const hash = createHash("md5").update(canonical, "utf8").digest("hex").slice(0, 12);
12259
+ return `dir:${hash}`;
12260
+ }
12261
+ function assertDirectoryUsable(canonicalDirectory, rawDirectory) {
12262
+ try {
12263
+ const stat = statSync3(canonicalDirectory);
12264
+ if (!stat.isDirectory()) {
12265
+ throw new ProjectIdentityError("unknown", rawDirectory, `Project path is not a directory: ${canonicalDirectory}`);
12266
+ }
12267
+ } catch (error) {
12268
+ if (error instanceof ProjectIdentityError) {
12269
+ throw error;
12270
+ }
12271
+ const code = getErrorCode(error);
12272
+ if (code === "EACCES" || code === "EPERM") {
12273
+ throw new ProjectIdentityError("permission_denied", rawDirectory, `Permission denied while accessing project directory: ${canonicalDirectory}`, asError(error));
12274
+ }
12275
+ throw new ProjectIdentityError("unknown", rawDirectory, `Unable to access project directory: ${canonicalDirectory}`, asError(error));
12276
+ }
12277
+ }
12278
+ function isGitTimeoutError(error) {
12279
+ const code = getErrorCode(error);
12280
+ const signal = getErrorSignal(error);
12281
+ return code === "ETIMEDOUT" || signal === "SIGTERM" || signal === "SIGKILL" || getErrorKilled(error);
12282
+ }
12283
+ function classifyGitError(error, rawDirectory) {
12284
+ if (isGitTimeoutError(error)) {
12285
+ return new ProjectIdentityError("git_timeout", rawDirectory, `git rev-list timed out after ${GIT_TIMEOUT_MS}ms`, asError(error));
12286
+ }
12287
+ const code = getErrorCode(error);
12288
+ if (code === "ENOENT") {
12289
+ return new ProjectIdentityError("git_missing", rawDirectory, "git binary is not available in PATH", asError(error));
12290
+ }
12291
+ if (code === "EACCES" || code === "EPERM") {
12292
+ return new ProjectIdentityError("permission_denied", rawDirectory, "Permission denied while spawning git", asError(error));
12293
+ }
12294
+ const stderr = getErrorStderr(error).toLowerCase();
12295
+ if (stderr.includes("not a git repository") || stderr.includes("does not have any commits yet") || stderr.includes("ambiguous argument 'head'") || stderr.includes("unknown revision or path")) {
12296
+ return new ProjectIdentityError("not_git_repo", rawDirectory, "Directory has no git root commit; caller may use directory fallback", asError(error));
12297
+ }
12298
+ return new ProjectIdentityError("unknown", rawDirectory, "git rev-list failed while resolving project identity", asError(error));
12299
+ }
12300
+ function resolveProjectIdentityStrict(directory) {
12301
+ const canonical = path2.resolve(directory);
12302
+ const cached = identityCache.get(canonical);
12303
+ if (cached !== undefined) {
12304
+ return cached;
12305
+ }
12306
+ assertDirectoryUsable(canonical, directory);
12307
+ let output;
12308
+ try {
12309
+ output = execFileSync3("git", ["rev-list", "--max-parents=0", "HEAD"], {
12310
+ cwd: canonical,
12311
+ encoding: "utf8",
12312
+ env: { ...process.env, LC_ALL: "C", LANG: "C" },
12313
+ stdio: ["ignore", "pipe", "pipe"],
12314
+ timeout: GIT_TIMEOUT_MS
12315
+ });
12316
+ } catch (error) {
12317
+ throw classifyGitError(error, directory);
12318
+ }
12319
+ const firstLine = output.split(`
12320
+ `)[0]?.trim() ?? "";
12321
+ const rootCommit = firstLine.slice(0, 64);
12322
+ if (rootCommit.length < 7) {
12323
+ throw new ProjectIdentityError("unknown", directory, "git rev-list returned no valid root commit hash");
12324
+ }
12325
+ const identity = `git:${rootCommit}`;
12326
+ identityCache.set(canonical, identity);
12327
+ return identity;
12328
+ }
12329
+ function shouldUseDirectoryFallback(error) {
12330
+ return error.errorClass === "not_git_repo" || error.errorClass === "unknown" && error.message.startsWith("Unable to access project directory:");
12331
+ }
12332
+ function resolveProjectIdentity(directory) {
12333
+ const canonical = path2.resolve(directory);
12334
+ const cachedFallback = directoryFallbackCache.get(canonical);
12335
+ if (cachedFallback !== undefined) {
12336
+ if (!hasGitDir(canonical)) {
12337
+ return cachedFallback;
12338
+ }
12339
+ directoryFallbackCache.delete(canonical);
12340
+ }
12341
+ try {
12342
+ return resolveProjectIdentityStrict(directory);
12343
+ } catch (error) {
12344
+ if (error instanceof ProjectIdentityError && shouldUseDirectoryFallback(error)) {
12345
+ const fallback = directoryFallback(canonical);
12346
+ if (!hasGitDir(canonical)) {
12347
+ directoryFallbackCache.set(canonical, fallback);
12348
+ }
12349
+ return fallback;
12350
+ }
12351
+ throw error;
12352
+ }
12353
+ }
12354
+ function hasGitDir(canonical) {
12355
+ try {
12356
+ statSync3(path2.join(canonical, ".git"));
12357
+ return true;
12358
+ } catch {
12359
+ return false;
12360
+ }
12361
+ }
12362
+ var GIT_TIMEOUT_MS = 5000, identityCache, directoryFallbackCache, ProjectIdentityError;
12363
+ var init_project_identity = __esm(() => {
12364
+ identityCache = new Map;
12365
+ directoryFallbackCache = new Map;
12366
+ ProjectIdentityError = class ProjectIdentityError extends Error {
12367
+ errorClass;
12368
+ rawDirectory;
12369
+ constructor(errorClass, rawDirectory, message, cause) {
12370
+ super(message);
12371
+ this.name = "ProjectIdentityError";
12372
+ this.errorClass = errorClass;
12373
+ this.rawDirectory = rawDirectory;
12374
+ if (cause) {
12375
+ this.cause = cause;
12376
+ }
12377
+ }
12378
+ };
12379
+ });
12380
+
12381
+ // ../plugin/src/features/magic-context/memory/relocate-memory.ts
12382
+ function selectRelocatableMemoryIds(db, fromProjectPath, selection = {}) {
12383
+ const statuses = selection.statuses ?? DEFAULT_STATUSES;
12384
+ if (statuses.length === 0)
12385
+ return [];
12386
+ const statusPlaceholders = statuses.map(() => "?").join(", ");
12387
+ const params = [fromProjectPath, ...statuses];
12388
+ let sql = `SELECT id FROM memories WHERE project_path = ? AND status IN (${statusPlaceholders})`;
12389
+ if (selection.sourceSessionId !== undefined) {
12390
+ sql += " AND source_session_id = ?";
12391
+ params.push(selection.sourceSessionId);
12392
+ }
12393
+ sql += " ORDER BY id ASC";
12394
+ const rows = db.prepare(sql).all(...params);
12395
+ return rows.map((row) => row.id);
12396
+ }
12397
+ function rekeyMemoryRowWithCollisionMerge(db, rowId, fromProjectPath, toIdentity) {
12398
+ const row = db.prepare("SELECT category, normalized_hash, seen_count FROM memories WHERE id = ?").get(rowId);
12399
+ if (!row)
12400
+ return false;
12401
+ const collision = db.prepare(`SELECT id, seen_count FROM memories
12402
+ WHERE project_path = ? AND category = ? AND normalized_hash = ?
12403
+ LIMIT 1`).get(toIdentity, row.category, row.normalized_hash);
12404
+ if (collision && collision.id !== rowId) {
12405
+ const mergedSeen = Math.max(collision.seen_count ?? 1, row.seen_count ?? 1);
12406
+ if (mergedSeen !== (collision.seen_count ?? 1)) {
12407
+ db.prepare("UPDATE memories SET seen_count = ? WHERE id = ?").run(mergedSeen, collision.id);
12408
+ }
12409
+ db.prepare(`INSERT OR IGNORE INTO memory_embeddings (memory_id, embedding, model_id)
12410
+ SELECT ?, embedding, model_id FROM memory_embeddings WHERE memory_id = ?`).run(collision.id, rowId);
12411
+ db.prepare("DELETE FROM memories WHERE id = ?").run(rowId);
12412
+ return true;
12413
+ }
12414
+ const result = db.prepare("UPDATE memories SET project_path = ? WHERE id = ? AND project_path = ?").run(toIdentity, rowId, fromProjectPath);
12415
+ return (result.changes ?? 0) > 0;
12416
+ }
12417
+ function moveMemoriesToProject(db, ids, fromProjectPath, toIdentity) {
12418
+ let relocated = 0;
12419
+ let merged = 0;
12420
+ for (const id of ids) {
12421
+ const row = db.prepare("SELECT category, normalized_hash FROM memories WHERE id = ?").get(id);
12422
+ if (!row)
12423
+ continue;
12424
+ const collision = db.prepare(`SELECT id FROM memories WHERE project_path = ? AND category = ? AND normalized_hash = ? LIMIT 1`).get(toIdentity, row.category, row.normalized_hash);
12425
+ const changed = rekeyMemoryRowWithCollisionMerge(db, id, fromProjectPath, toIdentity);
12426
+ if (!changed)
12427
+ continue;
12428
+ if (collision && collision.id !== id)
12429
+ merged += 1;
12430
+ else
12431
+ relocated += 1;
12432
+ }
12433
+ return { relocated, merged, skipped: 0 };
12434
+ }
12435
+ function getMemoryCopyColumns(db) {
12436
+ const cached = memoryCopyColumnsCache.get(db);
12437
+ if (cached)
12438
+ return cached;
12439
+ const columns = db.prepare("PRAGMA table_info(memories)").all();
12440
+ const names = columns.map((c2) => c2.name).filter((n) => typeof n === "string" && n !== "id");
12441
+ memoryCopyColumnsCache.set(db, names);
12442
+ return names;
12443
+ }
12444
+ function copyMemoriesToProject(db, ids, toIdentity) {
12445
+ const columns = getMemoryCopyColumns(db);
12446
+ const selectExprs = columns.map((c2) => c2 === "project_path" ? "? AS project_path" : c2);
12447
+ const insertSql = `INSERT OR IGNORE INTO memories (${columns.join(", ")})
12448
+ SELECT ${selectExprs.join(", ")} FROM memories WHERE id = ?`;
12449
+ const insertStmt = db.prepare(insertSql);
12450
+ const copyEmbeddingStmt = db.prepare(`INSERT OR IGNORE INTO memory_embeddings (memory_id, embedding, model_id)
12451
+ SELECT ?, embedding, model_id FROM memory_embeddings WHERE memory_id = ?`);
12452
+ let relocated = 0;
12453
+ let skipped = 0;
12454
+ for (const id of ids) {
12455
+ const result = insertStmt.run(toIdentity, id);
12456
+ if ((result.changes ?? 0) > 0) {
12457
+ relocated += 1;
12458
+ copyEmbeddingStmt.run(Number(result.lastInsertRowid), id);
12459
+ } else {
12460
+ skipped += 1;
12461
+ }
12462
+ }
12463
+ return { relocated, merged: 0, skipped };
12464
+ }
12465
+ var DEFAULT_STATUSES, memoryCopyColumnsCache;
12466
+ var init_relocate_memory = __esm(() => {
12467
+ DEFAULT_STATUSES = ["active", "permanent"];
12468
+ memoryCopyColumnsCache = new WeakMap;
12469
+ });
12470
+
12471
+ // ../plugin/src/features/magic-context/storage-project-state.ts
12472
+ function toProjectState(row) {
12473
+ return {
12474
+ projectPath: row.project_path,
12475
+ projectMemoryEpoch: row.project_memory_epoch,
12476
+ projectUserProfileVersion: row.project_user_profile_version,
12477
+ updatedAt: row.updated_at
12478
+ };
12479
+ }
12480
+ function getProjectState(db, projectPath) {
12481
+ const row = db.prepare(`SELECT project_path, project_memory_epoch, project_user_profile_version, updated_at
12482
+ FROM project_state
12483
+ WHERE project_path = ?`).get(projectPath);
12484
+ return row ? toProjectState(row) : null;
12485
+ }
12486
+ function bumpProjectMemoryEpoch(db, projectPath, now = Date.now()) {
12487
+ db.prepare(`INSERT INTO project_state
12488
+ (project_path, project_memory_epoch, project_user_profile_version, updated_at)
12489
+ VALUES (?, 1, 0, ?)
12490
+ ON CONFLICT(project_path) DO UPDATE SET
12491
+ project_memory_epoch = project_memory_epoch + 1,
12492
+ updated_at = excluded.updated_at`).run(projectPath, now);
12493
+ const state = getProjectState(db, projectPath);
12494
+ if (!state) {
12495
+ throw new Error(`Failed to bump project memory epoch for ${projectPath}`);
12496
+ }
12497
+ return state;
12498
+ }
12499
+
12500
+ // src/commands/migrate-session.ts
12501
+ var exports_migrate_session = {};
12502
+ __export(exports_migrate_session, {
12503
+ runMigrateSessionCli: () => runMigrateSessionCli,
12504
+ planMigrateSession: () => planMigrateSession,
12505
+ applyMigrateSession: () => applyMigrateSession
12506
+ });
12507
+ import { copyFileSync, existsSync as existsSync11, realpathSync } from "node:fs";
12508
+ import { homedir as homedir7 } from "node:os";
12509
+ import path3, { join as join10 } from "node:path";
12510
+ function existingSessionColumns(db) {
12511
+ const rows = db.prepare("PRAGMA table_info(session)").all();
12512
+ return new Set(rows.map((r) => r.name).filter((n) => typeof n === "string"));
12513
+ }
12514
+ function planMigrateSession(sessionId, rawTargetDirectory, deps) {
12515
+ const sessionRow = deps.opencodeDb.prepare("SELECT id, directory FROM session WHERE id = ?").get(sessionId);
12516
+ if (!sessionRow) {
12517
+ throw new Error(`Session ${sessionId} not found in opencode.db.`);
12518
+ }
12519
+ const targetDirectory = deps.realpath(rawTargetDirectory);
12520
+ const targetIsGit = deps.hasGitDir(targetDirectory);
12521
+ const projectRow = deps.opencodeDb.prepare("SELECT id, worktree FROM project WHERE worktree = ?").get(targetDirectory);
12522
+ let ocProjectId;
12523
+ let ocWorktree;
12524
+ const ocProjectResolvedFromRow = projectRow != null;
12525
+ if (projectRow) {
12526
+ ocProjectId = projectRow.id;
12527
+ ocWorktree = projectRow.worktree;
12528
+ } else {
12529
+ const globalRow = deps.opencodeDb.prepare("SELECT id, worktree FROM project WHERE id = 'global'").get();
12530
+ if (!globalRow) {
12531
+ throw new Error(`The OpenCode 'global' project row is missing.
12532
+ ` + "Open any folder in OpenCode once to create it, then re-run.");
12533
+ }
12534
+ ocProjectId = "global";
12535
+ ocWorktree = globalRow.worktree || "/";
12536
+ }
12537
+ const sessionPath = path3.relative(ocWorktree, targetDirectory);
12538
+ const ownershipRow = deps.contextDb.prepare("SELECT project_path FROM session_projects WHERE session_id = ? AND harness = 'opencode'").get(sessionId);
12539
+ const fromMcIdentity = ownershipRow?.project_path ?? (sessionRow.directory ? deps.resolveIdentity(sessionRow.directory) : "");
12540
+ const toMcIdentity = deps.resolveIdentity(targetDirectory);
12541
+ const injectableMemoryCount = deps.contextDb.prepare("SELECT COUNT(*) AS c FROM memories WHERE project_path = ? AND status IN ('active','permanent')").get(fromMcIdentity).c;
12542
+ const originatedMemoryCount = deps.contextDb.prepare("SELECT COUNT(*) AS c FROM memories WHERE project_path = ? AND status IN ('active','permanent') AND source_session_id = ?").get(fromMcIdentity, sessionId).c;
12543
+ return {
12544
+ sessionId,
12545
+ currentDirectory: sessionRow.directory,
12546
+ targetDirectory,
12547
+ ocProjectId,
12548
+ ocWorktree,
12549
+ ocProjectResolvedFromRow,
12550
+ sessionPath,
12551
+ fromMcIdentity,
12552
+ toMcIdentity,
12553
+ targetIsGit,
12554
+ injectableMemoryCount,
12555
+ originatedMemoryCount
12556
+ };
12557
+ }
12558
+ function applyMigrateSession(plan, memoryAction, deps) {
12559
+ const now = deps.now ?? Date.now();
12560
+ const cols = existingSessionColumns(deps.opencodeDb);
12561
+ const sets = ["directory = ?"];
12562
+ const params = [plan.targetDirectory];
12563
+ if (cols.has("project_id")) {
12564
+ sets.push("project_id = ?");
12565
+ params.push(plan.ocProjectId);
12566
+ }
12567
+ if (cols.has("path")) {
12568
+ sets.push("path = ?");
12569
+ params.push(plan.sessionPath);
12570
+ }
12571
+ if (cols.has("workspace_id")) {
12572
+ sets.push("workspace_id = ?");
12573
+ params.push(null);
12574
+ }
12575
+ const restoreCols = ["directory", ...sets.map((s) => s.split(" = ")[0]).slice(1)];
12576
+ const priorRow = deps.opencodeDb.prepare(`SELECT ${restoreCols.join(", ")} FROM session WHERE id = ?`).get(plan.sessionId);
12577
+ deps.opencodeDb.exec("BEGIN IMMEDIATE");
12578
+ try {
12579
+ deps.opencodeDb.prepare(`UPDATE session SET ${sets.join(", ")} WHERE id = ?`).run(...params, plan.sessionId);
12580
+ deps.opencodeDb.exec("COMMIT");
12581
+ } catch (error) {
12582
+ deps.opencodeDb.exec("ROLLBACK");
12583
+ throw error;
12584
+ }
12585
+ const compensateOpenCode = () => {
12586
+ if (!priorRow)
12587
+ return;
12588
+ try {
12589
+ const restoreSets = restoreCols.map((c2) => `${c2} = ?`).join(", ");
12590
+ const restoreParams = restoreCols.map((c2) => priorRow[c2] ?? null);
12591
+ deps.opencodeDb.exec("BEGIN IMMEDIATE");
12592
+ deps.opencodeDb.prepare(`UPDATE session SET ${restoreSets} WHERE id = ?`).run(...restoreParams, plan.sessionId);
12593
+ deps.opencodeDb.exec("COMMIT");
12594
+ } catch {
12595
+ try {
12596
+ deps.opencodeDb.exec("ROLLBACK");
12597
+ } catch {}
12598
+ }
12599
+ };
12600
+ let memoriesRelocated = 0;
12601
+ let memoriesMerged = 0;
12602
+ let memoriesSkipped = 0;
12603
+ let chunkEmbeddingsRestamped = 0;
12604
+ const epochsBumped = [];
12605
+ deps.contextDb.exec("BEGIN IMMEDIATE");
12606
+ try {
12607
+ deps.contextDb.prepare(`INSERT INTO session_projects (session_id, harness, project_path, updated_at)
12608
+ VALUES (?, 'opencode', ?, ?)
12609
+ ON CONFLICT(session_id, harness)
12610
+ DO UPDATE SET project_path = excluded.project_path, updated_at = excluded.updated_at`).run(plan.sessionId, plan.toMcIdentity, now);
12611
+ const chunkResult = deps.contextDb.prepare("UPDATE compartment_chunk_embeddings SET project_path = ? WHERE session_id = ?").run(plan.toMcIdentity, plan.sessionId);
12612
+ chunkEmbeddingsRestamped = chunkResult.changes ?? 0;
12613
+ deps.contextDb.prepare("UPDATE session_meta SET cached_m0_bytes = NULL, cached_m1_bytes = NULL WHERE session_id = ?").run(plan.sessionId);
12614
+ if (memoryAction !== "leave" && plan.fromMcIdentity && plan.fromMcIdentity !== plan.toMcIdentity) {
12615
+ const originatedOnly = memoryAction === "move-originated" || memoryAction === "copy-originated";
12616
+ const ids = selectRelocatableMemoryIds(deps.contextDb, plan.fromMcIdentity, originatedOnly ? { sourceSessionId: plan.sessionId } : {});
12617
+ const isMove = memoryAction === "move-all" || memoryAction === "move-originated";
12618
+ const result = isMove ? moveMemoriesToProject(deps.contextDb, ids, plan.fromMcIdentity, plan.toMcIdentity) : copyMemoriesToProject(deps.contextDb, ids, plan.toMcIdentity);
12619
+ memoriesRelocated = result.relocated;
12620
+ memoriesMerged = result.merged;
12621
+ memoriesSkipped = result.skipped;
12622
+ if (result.relocated > 0 || result.merged > 0) {
12623
+ bumpProjectMemoryEpoch(deps.contextDb, plan.toMcIdentity, now);
12624
+ epochsBumped.push(plan.toMcIdentity);
12625
+ if (isMove) {
12626
+ bumpProjectMemoryEpoch(deps.contextDb, plan.fromMcIdentity, now);
12627
+ epochsBumped.push(plan.fromMcIdentity);
12628
+ }
12629
+ }
12630
+ }
12631
+ deps.contextDb.exec("COMMIT");
12632
+ } catch (error) {
12633
+ deps.contextDb.exec("ROLLBACK");
12634
+ compensateOpenCode();
12635
+ throw error;
12636
+ }
12637
+ return {
12638
+ plan,
12639
+ memoryAction,
12640
+ dryRun: false,
12641
+ memoriesRelocated,
12642
+ memoriesMerged,
12643
+ memoriesSkipped,
12644
+ chunkEmbeddingsRestamped,
12645
+ epochsBumped
12646
+ };
12647
+ }
12648
+ function defaultOpenCodeDbPath2() {
12649
+ return join10(homedir7(), ".local", "share", "opencode", "opencode.db");
12650
+ }
12651
+ function defaultContextDbPath() {
12652
+ return join10(getMagicContextStorageDir(), "context.db");
12653
+ }
12654
+ function realDeps(opencodeDb, contextDb) {
12655
+ return {
12656
+ opencodeDb,
12657
+ contextDb,
12658
+ resolveIdentity: resolveProjectIdentity,
12659
+ hasGitDir: (dir) => existsSync11(join10(dir, ".git")),
12660
+ realpath: (p2) => realpathSync(p2)
12661
+ };
12662
+ }
12663
+ function valueAfter(args, flag) {
12664
+ const index = args.indexOf(flag);
12665
+ if (index === -1)
12666
+ return null;
12667
+ const next = args[index + 1];
12668
+ if (next === undefined || next.startsWith("--"))
12669
+ return null;
12670
+ return next;
12671
+ }
12672
+ function printMigrateSessionHelp() {
12673
+ console.log("");
12674
+ console.log(" doctor migrate-session — re-home an OpenCode session to another directory");
12675
+ console.log("");
12676
+ console.log(" Required:");
12677
+ console.log(" --session <id> OpenCode session id (ses_...)");
12678
+ console.log(" --to <dir> Target working directory");
12679
+ console.log("");
12680
+ console.log(" Optional:");
12681
+ console.log(" --memories <a> Non-interactive memory action:");
12682
+ console.log(" move-all | move-originated | copy-all |");
12683
+ console.log(" copy-originated | leave");
12684
+ console.log(" --dry-run Show the plan; write nothing");
12685
+ console.log(" --yes Skip the 'OpenCode stopped?' confirmation");
12686
+ console.log("");
12687
+ console.log(" Example:");
12688
+ console.log(" npx @cortexkit/magic-context@latest doctor migrate-session \\");
12689
+ console.log(" --session ses_xxx --to ~/Work/Projects/CortexKit/benchmarks --dry-run");
12690
+ console.log("");
12691
+ }
12692
+ async function promptMemoryAction(plan) {
12693
+ const all = plan.injectableMemoryCount;
12694
+ const originated = plan.originatedMemoryCount;
12695
+ promptIO.note(`${all} memory${all === 1 ? "" : "ies"} live under the current project ` + `(${plan.fromMcIdentity}); ${originated} of them originated from this session.`, "Memories");
12696
+ const choice = await promptIO.selectOne("How should memories be handled?", [
12697
+ {
12698
+ label: `Move only memories originated from this session (${originated})`,
12699
+ value: "move-originated",
12700
+ recommended: true
12701
+ },
12702
+ { label: `Move all memories of this project (${all})`, value: "move-all" },
12703
+ {
12704
+ label: `Copy only memories originated from this session (${originated})`,
12705
+ value: "copy-originated"
12706
+ },
12707
+ { label: `Copy all memories of this project (${all})`, value: "copy-all" },
12708
+ { label: "Leave memories as is", value: "leave" }
12709
+ ]);
12710
+ return choice;
12711
+ }
12712
+ async function runMigrateSessionCli(args) {
12713
+ if (args.includes("--help") || args.includes("-h")) {
12714
+ printMigrateSessionHelp();
12715
+ return 0;
12716
+ }
12717
+ const sessionId = valueAfter(args, "--session");
12718
+ const toDir = valueAfter(args, "--to");
12719
+ const dryRun = args.includes("--dry-run");
12720
+ const skipConfirm = args.includes("--yes");
12721
+ const memoriesFlag = valueAfter(args, "--memories");
12722
+ if (!sessionId) {
12723
+ console.error("Missing required flag: --session <id>");
12724
+ printMigrateSessionHelp();
12725
+ return 1;
12726
+ }
12727
+ if (!toDir) {
12728
+ console.error("Missing required flag: --to <dir>");
12729
+ printMigrateSessionHelp();
12730
+ return 1;
12731
+ }
12732
+ if (memoriesFlag !== null && !VALID_MEMORY_ACTIONS.has(memoriesFlag)) {
12733
+ console.error(`Invalid --memories value: ${memoriesFlag}`);
12734
+ printMigrateSessionHelp();
12735
+ return 1;
12736
+ }
12737
+ const expandedTo = toDir.startsWith("~") ? join10(homedir7(), toDir.slice(1).replace(/^[/\\]/, "")) : toDir;
12738
+ if (!existsSync11(expandedTo)) {
12739
+ console.error(`Target directory does not exist: ${expandedTo}`);
12740
+ return 1;
12741
+ }
12742
+ const opencodeDbPath = defaultOpenCodeDbPath2();
12743
+ const contextDbPath = defaultContextDbPath();
12744
+ const opencodeDb = new Database(opencodeDbPath);
12745
+ const contextDb = new Database(contextDbPath);
12746
+ try {
12747
+ const deps = realDeps(opencodeDb, contextDb);
12748
+ const plan = planMigrateSession(sessionId, expandedTo, deps);
12749
+ promptIO.note([
12750
+ `session: ${plan.sessionId}`,
12751
+ `from: ${plan.currentDirectory ?? "(unknown)"}`,
12752
+ `to: ${plan.targetDirectory}`,
12753
+ `OpenCode project: ${plan.ocProjectId}${plan.targetIsGit ? " (git)" : " (global / non-git)"}`,
12754
+ `MC identity: ${plan.fromMcIdentity} → ${plan.toMcIdentity}`
12755
+ ].join(`
12756
+ `), "Session move plan");
12757
+ if (plan.targetIsGit && !plan.ocProjectResolvedFromRow) {
12758
+ promptIO.log.warn(`${plan.targetDirectory} is a git repo, but OpenCode has no dedicated project for it ` + `(an empty repo with no commits/remote resolves to the shared 'global' project). ` + `For a dedicated project: make a commit (or add a remote), open OpenCode there once, then re-run.`);
12759
+ if (!dryRun) {
12760
+ if (skipConfirm) {
12761
+ promptIO.log.warn("Proceeding — the session will attach to 'global'.");
12762
+ } else {
12763
+ const proceed = await promptIO.confirm("Proceed attaching the session to the shared 'global' project?", false);
12764
+ if (!proceed) {
12765
+ promptIO.log.warn("Aborted. Make a commit / add a remote, then re-run.");
12766
+ return 1;
12767
+ }
12768
+ }
12769
+ }
12770
+ }
12771
+ const memoryAction = memoriesFlag ?? await promptMemoryAction(plan);
12772
+ if (dryRun) {
12773
+ const willMove = memoryAction === "move-all" || memoryAction === "move-originated";
12774
+ const willCopy = memoryAction === "copy-all" || memoryAction === "copy-originated";
12775
+ const count = memoryAction.endsWith("originated") ? plan.originatedMemoryCount : plan.injectableMemoryCount;
12776
+ promptIO.log.info(`[dry-run] Would update opencode.db session row → project ${plan.ocProjectId}, dir ${plan.targetDirectory}.`);
12777
+ promptIO.log.info(`[dry-run] Would re-stamp session_projects + chunk embeddings to ${plan.toMcIdentity} and clear cached m[0]/m[1].`);
12778
+ promptIO.log.info(`[dry-run] Memories: ${memoryAction === "leave" ? "left as is" : `${willMove ? "move" : willCopy ? "copy" : "?"} ${count}`}.`);
12779
+ promptIO.log.info("[dry-run] No changes written.");
12780
+ return 0;
12781
+ }
12782
+ if (!skipConfirm) {
12783
+ const ok = await promptIO.confirm("This edits opencode.db + context.db directly. Is OpenCode (TUI / Desktop / serve) fully stopped?", false);
12784
+ if (!ok) {
12785
+ promptIO.log.warn("Aborted. Stop OpenCode, then re-run.");
12786
+ return 1;
12787
+ }
12788
+ }
12789
+ const stamp = new Date().toISOString().replace(/[:.]/g, "-");
12790
+ const ocBackup = `${opencodeDbPath}.bak-${stamp}`;
12791
+ const ctxBackup = `${contextDbPath}.bak-${stamp}`;
12792
+ copyFileSync(opencodeDbPath, ocBackup);
12793
+ copyFileSync(contextDbPath, ctxBackup);
12794
+ promptIO.log.info(`Backed up: ${ocBackup}`);
12795
+ promptIO.log.info(`Backed up: ${ctxBackup}`);
12796
+ const result = applyMigrateSession(plan, memoryAction, deps);
12797
+ promptIO.log.success("Session re-homed.");
12798
+ console.log(` OpenCode: project ${plan.ocProjectId}, directory ${plan.targetDirectory}`);
12799
+ console.log(` MC identity: ${plan.fromMcIdentity} → ${plan.toMcIdentity}`);
12800
+ console.log(` chunk embeddings re-stamped: ${result.chunkEmbeddingsRestamped}`);
12801
+ console.log(` memories: ${result.memoriesRelocated} ${memoryAction.startsWith("copy") ? "copied" : "moved"}` + (result.memoriesMerged ? `, ${result.memoriesMerged} merged` : "") + (result.memoriesSkipped ? `, ${result.memoriesSkipped} skipped (already present)` : ""));
12802
+ if (result.epochsBumped.length > 0) {
12803
+ console.log(` memory epoch bumped: ${result.epochsBumped.join(", ")}`);
12804
+ }
12805
+ console.log("Restart OpenCode to pick up the moved session.");
12806
+ return 0;
12807
+ } catch (error) {
12808
+ console.error(error instanceof Error ? error.message : String(error));
12809
+ return 1;
12810
+ } finally {
12811
+ opencodeDb.close();
12812
+ contextDb.close();
12813
+ }
12814
+ }
12815
+ var VALID_MEMORY_ACTIONS;
12816
+ var init_migrate_session = __esm(async () => {
12817
+ init_project_identity();
12818
+ init_relocate_memory();
12819
+ init_data_path();
12820
+ init_prompts();
12821
+ await init_sqlite();
12822
+ VALID_MEMORY_ACTIONS = new Set([
12823
+ "move-all",
12824
+ "move-originated",
12825
+ "copy-all",
12826
+ "copy-originated",
12827
+ "leave"
12828
+ ]);
12829
+ });
12830
+
12215
12831
  // ../plugin/src/features/magic-context/compartment-lease.ts
12216
12832
  var COMPARTMENT_LEASE_TTL_MS, COMPARTMENT_LEASE_RENEWAL_MS;
12217
12833
  var init_compartment_lease = __esm(() => {
@@ -12263,9 +12879,9 @@ var init_compartment_storage = __esm(() => {
12263
12879
  });
12264
12880
  // ../plugin/src/shared/logger.ts
12265
12881
  import * as fs from "node:fs";
12266
- import * as path2 from "node:path";
12882
+ import * as path4 from "node:path";
12267
12883
  function ensureDir5(filePath) {
12268
- const dir = path2.dirname(filePath);
12884
+ const dir = path4.dirname(filePath);
12269
12885
  if (dir === lastEnsuredDir)
12270
12886
  return;
12271
12887
  try {
@@ -144879,13 +145495,14 @@ var init_tool_drop_target = __esm(() => {
144879
145495
  });
144880
145496
 
144881
145497
  // ../plugin/src/hooks/magic-context/read-session-chunk.ts
144882
- var sessionProviders;
145498
+ var blockTokenMemo, sessionProviders;
144883
145499
  var init_read_session_chunk = __esm(async () => {
144884
145500
  init_read_session_formatting();
144885
145501
  init_tag_part_guards();
144886
145502
  init_tool_drop_target();
144887
145503
  init_read_session_formatting();
144888
145504
  await init_read_session_db();
145505
+ blockTokenMemo = new Map;
144889
145506
  sessionProviders = new Map;
144890
145507
  });
144891
145508
 
@@ -144908,7 +145525,7 @@ function getErrorMessage(error) {
144908
145525
  }
144909
145526
 
144910
145527
  // ../plugin/src/features/magic-context/key-files/project-key-files.ts
144911
- import { existsSync as existsSync11, readFileSync as readFileSync7, realpathSync } from "node:fs";
145528
+ import { existsSync as existsSync12, readFileSync as readFileSync7, realpathSync as realpathSync2 } from "node:fs";
144912
145529
  function deleteOrphanProjectKeyFiles(db, now = Date.now()) {
144913
145530
  const cutoff = now - ORPHAN_GRACE_MS;
144914
145531
  const rows = db.prepare(`SELECT project_path AS projectPath, MAX(generated_at) AS lastGen
@@ -144917,7 +145534,7 @@ function deleteOrphanProjectKeyFiles(db, now = Date.now()) {
144917
145534
  HAVING lastGen < ?`).all(cutoff);
144918
145535
  let deletedProjects = 0;
144919
145536
  for (const row of rows) {
144920
- if (existsSync11(row.projectPath))
145537
+ if (existsSync12(row.projectPath))
144921
145538
  continue;
144922
145539
  try {
144923
145540
  db.transaction(() => {
@@ -144970,10 +145587,10 @@ var init_tool_definition_tokens = __esm(() => {
144970
145587
  });
144971
145588
 
144972
145589
  // ../plugin/src/features/magic-context/tool-owner-backfill.ts
144973
- import { existsSync as existsSync12 } from "node:fs";
144974
- import { join as join10 } from "node:path";
145590
+ import { existsSync as existsSync13 } from "node:fs";
145591
+ import { join as join11 } from "node:path";
144975
145592
  function resolveOpencodeDbPath() {
144976
- return join10(getDataDir(), "opencode", "opencode.db");
145593
+ return join11(getDataDir(), "opencode", "opencode.db");
144977
145594
  }
144978
145595
  function ensureBackfillStateTable(db) {
144979
145596
  db.exec(`
@@ -145008,7 +145625,7 @@ function runToolOwnerBackfill(db) {
145008
145625
  return result;
145009
145626
  }
145010
145627
  const opencodeDbPath = resolveOpencodeDbPath();
145011
- if (!existsSync12(opencodeDbPath)) {
145628
+ if (!existsSync13(opencodeDbPath)) {
145012
145629
  log2(`[backfill] OpenCode DB not found at ${opencodeDbPath} — marking all unbackfilled sessions as skipped. Lazy adoption (defense-in-depth) handles legacy rows at runtime.`);
145013
145630
  markAllUnbackfilledSessionsSkipped(db);
145014
145631
  result.sessionsSkippedNoOcDb = countSessionsByStatus(db, "skipped");
@@ -145231,26 +145848,26 @@ var init_tool_owner_backfill = __esm(() => {
145231
145848
  });
145232
145849
 
145233
145850
  // ../plugin/src/features/magic-context/storage-db.ts
145234
- import { copyFileSync, cpSync, existsSync as existsSync13, mkdirSync as mkdirSync5 } from "node:fs";
145235
- import { dirname as dirname6, join as join11 } from "node:path";
145851
+ import { copyFileSync as copyFileSync2, cpSync, existsSync as existsSync14, mkdirSync as mkdirSync5 } from "node:fs";
145852
+ import { dirname as dirname6, join as join12 } from "node:path";
145236
145853
  function resolveDatabasePath(dbPathOverride) {
145237
145854
  if (dbPathOverride) {
145238
145855
  return { dbDir: dirname6(dbPathOverride), dbPath: dbPathOverride };
145239
145856
  }
145240
145857
  const testDataDir = process.env.MAGIC_CONTEXT_TEST_DATA_DIR;
145241
145858
  if (testDataDir && !process.env.XDG_DATA_HOME) {
145242
- const dbDir2 = join11(testDataDir, "cortexkit", "magic-context");
145243
- return { dbDir: dbDir2, dbPath: join11(dbDir2, "context.db") };
145859
+ const dbDir2 = join12(testDataDir, "cortexkit", "magic-context");
145860
+ return { dbDir: dbDir2, dbPath: join12(dbDir2, "context.db") };
145244
145861
  }
145245
145862
  const dbDir = getMagicContextStorageDir();
145246
- return { dbDir, dbPath: join11(dbDir, "context.db") };
145863
+ return { dbDir, dbPath: join12(dbDir, "context.db") };
145247
145864
  }
145248
145865
  function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
145249
- if (existsSync13(targetDbPath))
145866
+ if (existsSync14(targetDbPath))
145250
145867
  return;
145251
145868
  const legacyDir = getLegacyOpenCodeMagicContextStorageDir();
145252
- const legacyDbPath = join11(legacyDir, "context.db");
145253
- if (!existsSync13(legacyDbPath))
145869
+ const legacyDbPath = join12(legacyDir, "context.db");
145870
+ if (!existsSync14(legacyDbPath))
145254
145871
  return;
145255
145872
  log2(`[magic-context] migrating legacy plugin storage: ${legacyDir} -> ${targetDbDir} (legacy left in place as backup)`);
145256
145873
  mkdirSync5(targetDbDir, { recursive: true });
@@ -145266,18 +145883,18 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
145266
145883
  }
145267
145884
  for (const suffix of ["", "-wal", "-shm"]) {
145268
145885
  const src = `${legacyDbPath}${suffix}`;
145269
- const dst = join11(targetDbDir, `context.db${suffix}`);
145270
- if (existsSync13(src)) {
145886
+ const dst = join12(targetDbDir, `context.db${suffix}`);
145887
+ if (existsSync14(src)) {
145271
145888
  try {
145272
- copyFileSync(src, dst);
145889
+ copyFileSync2(src, dst);
145273
145890
  } catch (error) {
145274
145891
  log2(`[magic-context] failed to copy ${src}:`, getErrorMessage(error));
145275
145892
  }
145276
145893
  }
145277
145894
  }
145278
- const legacyModelsDir = join11(legacyDir, "models");
145279
- const targetModelsDir = join11(targetDbDir, "models");
145280
- if (existsSync13(legacyModelsDir) && !existsSync13(targetModelsDir)) {
145895
+ const legacyModelsDir = join12(legacyDir, "models");
145896
+ const targetModelsDir = join12(targetDbDir, "models");
145897
+ if (existsSync14(legacyModelsDir) && !existsSync14(targetModelsDir)) {
145281
145898
  try {
145282
145899
  cpSync(legacyModelsDir, targetModelsDir, { recursive: true });
145283
145900
  } catch (error) {
@@ -145746,6 +146363,8 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
145746
146363
  recovery_no_eligible_head_count INTEGER NOT NULL DEFAULT 0,
145747
146364
  force_emergency_bypass_window_start INTEGER NOT NULL DEFAULT 0,
145748
146365
  force_emergency_bypass_used INTEGER NOT NULL DEFAULT 0,
146366
+ emergency_drain_active INTEGER NOT NULL DEFAULT 0,
146367
+ historian_drain_failure_at INTEGER NOT NULL DEFAULT 0,
145749
146368
  cached_m0_materialized_at INTEGER,
145750
146369
  cached_m0_session_facts_version INTEGER,
145751
146370
  cached_m0_upgrade_state TEXT,
@@ -145809,6 +146428,23 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
145809
146428
  CREATE INDEX IF NOT EXISTS idx_historian_runs_status
145810
146429
  ON historian_runs(status, created_at DESC);
145811
146430
 
146431
+ CREATE TABLE IF NOT EXISTS transform_decisions (
146432
+ session_id TEXT NOT NULL,
146433
+ harness TEXT NOT NULL DEFAULT 'opencode',
146434
+ message_id TEXT NOT NULL,
146435
+ ts_ms INTEGER NOT NULL,
146436
+ decision TEXT NOT NULL,
146437
+ materialized INTEGER NOT NULL DEFAULT 0,
146438
+ materialize_reason TEXT,
146439
+ emergency INTEGER NOT NULL DEFAULT 0,
146440
+ dropped_tokens INTEGER NOT NULL DEFAULT 0,
146441
+ dropped_count INTEGER NOT NULL DEFAULT 0,
146442
+ input_tokens INTEGER NOT NULL DEFAULT 0,
146443
+ PRIMARY KEY (session_id, harness, message_id)
146444
+ );
146445
+ CREATE INDEX IF NOT EXISTS idx_transform_decisions_session_harness
146446
+ ON transform_decisions(session_id, harness);
146447
+
145812
146448
  CREATE INDEX IF NOT EXISTS idx_tags_session_tag_number ON tags(session_id, tag_number);
145813
146449
  CREATE INDEX IF NOT EXISTS idx_tags_session_message_id ON tags(session_id, message_id);
145814
146450
  CREATE INDEX IF NOT EXISTS idx_pending_ops_session ON pending_ops(session_id);
@@ -145960,6 +146596,8 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
145960
146596
  ensureColumn(db, "session_meta", "recovery_no_eligible_head_count", "INTEGER NOT NULL DEFAULT 0");
145961
146597
  ensureColumn(db, "session_meta", "force_emergency_bypass_window_start", "INTEGER NOT NULL DEFAULT 0");
145962
146598
  ensureColumn(db, "session_meta", "force_emergency_bypass_used", "INTEGER NOT NULL DEFAULT 0");
146599
+ ensureColumn(db, "session_meta", "emergency_drain_active", "INTEGER NOT NULL DEFAULT 0");
146600
+ ensureColumn(db, "session_meta", "historian_drain_failure_at", "INTEGER NOT NULL DEFAULT 0");
145963
146601
  ensureColumn(db, "session_meta", "cached_m0_materialized_at", "INTEGER");
145964
146602
  ensureColumn(db, "session_meta", "cached_m0_session_facts_version", "INTEGER");
145965
146603
  ensureColumn(db, "session_meta", "cached_m0_upgrade_state", "TEXT");
@@ -146038,6 +146676,22 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
146038
146676
  failed_at INTEGER NOT NULL,
146039
146677
  UNIQUE(table_name, row_id)
146040
146678
  );
146679
+ CREATE TABLE IF NOT EXISTS transform_decisions (
146680
+ session_id TEXT NOT NULL,
146681
+ harness TEXT NOT NULL DEFAULT 'opencode',
146682
+ message_id TEXT NOT NULL,
146683
+ ts_ms INTEGER NOT NULL,
146684
+ decision TEXT NOT NULL,
146685
+ materialized INTEGER NOT NULL DEFAULT 0,
146686
+ materialize_reason TEXT,
146687
+ emergency INTEGER NOT NULL DEFAULT 0,
146688
+ dropped_tokens INTEGER NOT NULL DEFAULT 0,
146689
+ dropped_count INTEGER NOT NULL DEFAULT 0,
146690
+ input_tokens INTEGER NOT NULL DEFAULT 0,
146691
+ PRIMARY KEY (session_id, harness, message_id)
146692
+ );
146693
+ CREATE INDEX IF NOT EXISTS idx_transform_decisions_session_harness
146694
+ ON transform_decisions(session_id, harness);
146041
146695
  `);
146042
146696
  ensureColumn(db, "tags", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
146043
146697
  ensureColumn(db, "pending_ops", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
@@ -146123,7 +146777,9 @@ function healNullIntegerColumns(db) {
146123
146777
  ["protected_tail_drain_tokens", 0],
146124
146778
  ["recovery_no_eligible_head_count", 0],
146125
146779
  ["force_emergency_bypass_window_start", 0],
146126
- ["force_emergency_bypass_used", 0]
146780
+ ["force_emergency_bypass_used", 0],
146781
+ ["emergency_drain_active", 0],
146782
+ ["historian_drain_failure_at", 0]
146127
146783
  ];
146128
146784
  for (const [column, fallback] of columns) {
146129
146785
  try {
@@ -146199,6 +146855,7 @@ function openDatabase(dbPathOrOptions) {
146199
146855
  setDatabase(db);
146200
146856
  loadToolDefinitionMeasurements(db);
146201
146857
  databases.set(dbPath, db);
146858
+ pathByDatabase.set(db, dbPath);
146202
146859
  persistenceByDatabase.set(db, true);
146203
146860
  persistenceErrorByDatabase.delete(db);
146204
146861
  return db;
@@ -146224,7 +146881,7 @@ function closeDatabase() {
146224
146881
  }
146225
146882
  }
146226
146883
  }
146227
- var databases, persistenceByDatabase, persistenceErrorByDatabase, lastSchemaFenceRejection = null, LATEST_SUPPORTED_VERSION = 36, sqlitePragmaConfig, CHANNEL2_CLAIM_TTL_MS = 120000;
146884
+ var databases, persistenceByDatabase, persistenceErrorByDatabase, pathByDatabase, lastSchemaFenceRejection = null, LATEST_SUPPORTED_VERSION = 38, sqlitePragmaConfig, CHANNEL2_CLAIM_TTL_MS = 120000;
146228
146885
  var init_storage_db = __esm(async () => {
146229
146886
  init_data_path();
146230
146887
  init_logger();
@@ -146238,6 +146895,7 @@ var init_storage_db = __esm(async () => {
146238
146895
  databases = new Map;
146239
146896
  persistenceByDatabase = new WeakMap;
146240
146897
  persistenceErrorByDatabase = new WeakMap;
146898
+ pathByDatabase = new WeakMap;
146241
146899
  sqlitePragmaConfig = {
146242
146900
  cacheSizeMb: 64,
146243
146901
  mmapSizeMb: 0
@@ -146279,172 +146937,6 @@ var init_constants = __esm(() => {
146279
146937
  };
146280
146938
  });
146281
146939
 
146282
- // ../plugin/src/features/magic-context/memory/project-identity.ts
146283
- import { execFileSync as execFileSync3 } from "node:child_process";
146284
- import { createHash } from "node:crypto";
146285
- import { statSync as statSync3 } from "node:fs";
146286
- import path3 from "node:path";
146287
- function asError(error) {
146288
- return error instanceof Error ? error : undefined;
146289
- }
146290
- function getErrorCode(error) {
146291
- if (error === null || typeof error !== "object" || !("code" in error)) {
146292
- return;
146293
- }
146294
- const code = error.code;
146295
- return typeof code === "string" ? code : undefined;
146296
- }
146297
- function getErrorSignal(error) {
146298
- if (error === null || typeof error !== "object" || !("signal" in error)) {
146299
- return;
146300
- }
146301
- const signal = error.signal;
146302
- return typeof signal === "string" ? signal : undefined;
146303
- }
146304
- function getErrorKilled(error) {
146305
- if (error === null || typeof error !== "object" || !("killed" in error)) {
146306
- return false;
146307
- }
146308
- return error.killed === true;
146309
- }
146310
- function getErrorStderr(error) {
146311
- if (error === null || typeof error !== "object" || !("stderr" in error)) {
146312
- return "";
146313
- }
146314
- const stderr = error.stderr;
146315
- if (typeof stderr === "string") {
146316
- return stderr;
146317
- }
146318
- if (Buffer.isBuffer(stderr)) {
146319
- return stderr.toString("utf8");
146320
- }
146321
- return "";
146322
- }
146323
- function directoryFallback(directory) {
146324
- const canonical = path3.resolve(directory);
146325
- const hash = createHash("md5").update(canonical, "utf8").digest("hex").slice(0, 12);
146326
- return `dir:${hash}`;
146327
- }
146328
- function assertDirectoryUsable(canonicalDirectory, rawDirectory) {
146329
- try {
146330
- const stat = statSync3(canonicalDirectory);
146331
- if (!stat.isDirectory()) {
146332
- throw new ProjectIdentityError("unknown", rawDirectory, `Project path is not a directory: ${canonicalDirectory}`);
146333
- }
146334
- } catch (error) {
146335
- if (error instanceof ProjectIdentityError) {
146336
- throw error;
146337
- }
146338
- const code = getErrorCode(error);
146339
- if (code === "EACCES" || code === "EPERM") {
146340
- throw new ProjectIdentityError("permission_denied", rawDirectory, `Permission denied while accessing project directory: ${canonicalDirectory}`, asError(error));
146341
- }
146342
- throw new ProjectIdentityError("unknown", rawDirectory, `Unable to access project directory: ${canonicalDirectory}`, asError(error));
146343
- }
146344
- }
146345
- function isGitTimeoutError(error) {
146346
- const code = getErrorCode(error);
146347
- const signal = getErrorSignal(error);
146348
- return code === "ETIMEDOUT" || signal === "SIGTERM" || signal === "SIGKILL" || getErrorKilled(error);
146349
- }
146350
- function classifyGitError(error, rawDirectory) {
146351
- if (isGitTimeoutError(error)) {
146352
- return new ProjectIdentityError("git_timeout", rawDirectory, `git rev-list timed out after ${GIT_TIMEOUT_MS}ms`, asError(error));
146353
- }
146354
- const code = getErrorCode(error);
146355
- if (code === "ENOENT") {
146356
- return new ProjectIdentityError("git_missing", rawDirectory, "git binary is not available in PATH", asError(error));
146357
- }
146358
- if (code === "EACCES" || code === "EPERM") {
146359
- return new ProjectIdentityError("permission_denied", rawDirectory, "Permission denied while spawning git", asError(error));
146360
- }
146361
- const stderr = getErrorStderr(error).toLowerCase();
146362
- if (stderr.includes("not a git repository") || stderr.includes("does not have any commits yet") || stderr.includes("ambiguous argument 'head'") || stderr.includes("unknown revision or path")) {
146363
- return new ProjectIdentityError("not_git_repo", rawDirectory, "Directory has no git root commit; caller may use directory fallback", asError(error));
146364
- }
146365
- return new ProjectIdentityError("unknown", rawDirectory, "git rev-list failed while resolving project identity", asError(error));
146366
- }
146367
- function resolveProjectIdentityStrict(directory) {
146368
- const canonical = path3.resolve(directory);
146369
- const cached = identityCache.get(canonical);
146370
- if (cached !== undefined) {
146371
- return cached;
146372
- }
146373
- assertDirectoryUsable(canonical, directory);
146374
- let output;
146375
- try {
146376
- output = execFileSync3("git", ["rev-list", "--max-parents=0", "HEAD"], {
146377
- cwd: canonical,
146378
- encoding: "utf8",
146379
- env: { ...process.env, LC_ALL: "C", LANG: "C" },
146380
- stdio: ["ignore", "pipe", "pipe"],
146381
- timeout: GIT_TIMEOUT_MS
146382
- });
146383
- } catch (error) {
146384
- throw classifyGitError(error, directory);
146385
- }
146386
- const firstLine = output.split(`
146387
- `)[0]?.trim() ?? "";
146388
- const rootCommit = firstLine.slice(0, 64);
146389
- if (rootCommit.length < 7) {
146390
- throw new ProjectIdentityError("unknown", directory, "git rev-list returned no valid root commit hash");
146391
- }
146392
- const identity = `git:${rootCommit}`;
146393
- identityCache.set(canonical, identity);
146394
- return identity;
146395
- }
146396
- function shouldUseDirectoryFallback(error) {
146397
- return error.errorClass === "not_git_repo" || error.errorClass === "unknown" && error.message.startsWith("Unable to access project directory:");
146398
- }
146399
- function resolveProjectIdentity(directory) {
146400
- const canonical = path3.resolve(directory);
146401
- const cachedFallback = directoryFallbackCache.get(canonical);
146402
- if (cachedFallback !== undefined) {
146403
- if (!hasGitDir(canonical)) {
146404
- return cachedFallback;
146405
- }
146406
- directoryFallbackCache.delete(canonical);
146407
- }
146408
- try {
146409
- return resolveProjectIdentityStrict(directory);
146410
- } catch (error) {
146411
- if (error instanceof ProjectIdentityError && shouldUseDirectoryFallback(error)) {
146412
- const fallback = directoryFallback(canonical);
146413
- if (!hasGitDir(canonical)) {
146414
- directoryFallbackCache.set(canonical, fallback);
146415
- }
146416
- return fallback;
146417
- }
146418
- throw error;
146419
- }
146420
- }
146421
- function hasGitDir(canonical) {
146422
- try {
146423
- statSync3(path3.join(canonical, ".git"));
146424
- return true;
146425
- } catch {
146426
- return false;
146427
- }
146428
- }
146429
- var GIT_TIMEOUT_MS = 5000, identityCache, directoryFallbackCache, ProjectIdentityError;
146430
- var init_project_identity = __esm(() => {
146431
- identityCache = new Map;
146432
- directoryFallbackCache = new Map;
146433
- ProjectIdentityError = class ProjectIdentityError extends Error {
146434
- errorClass;
146435
- rawDirectory;
146436
- constructor(errorClass, rawDirectory, message, cause) {
146437
- super(message);
146438
- this.name = "ProjectIdentityError";
146439
- this.errorClass = errorClass;
146440
- this.rawDirectory = rawDirectory;
146441
- if (cause) {
146442
- this.cause = cause;
146443
- }
146444
- }
146445
- };
146446
- });
146447
-
146448
146940
  // ../plugin/src/features/magic-context/project-identity.ts
146449
146941
  var init_project_identity2 = __esm(() => {
146450
146942
  init_project_identity();
@@ -147517,6 +148009,41 @@ var init_migrations = __esm(async () => {
147517
148009
  `);
147518
148010
  }
147519
148011
  }
148012
+ },
148013
+ {
148014
+ version: 37,
148015
+ description: "emergency drain catch-up latch + historian drain failure backoff",
148016
+ up: (db) => {
148017
+ const hasSessionMeta = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='session_meta'").get();
148018
+ if (!hasSessionMeta)
148019
+ return;
148020
+ ensureColumn(db, "session_meta", "emergency_drain_active", "INTEGER NOT NULL DEFAULT 0");
148021
+ ensureColumn(db, "session_meta", "historian_drain_failure_at", "INTEGER NOT NULL DEFAULT 0");
148022
+ }
148023
+ },
148024
+ {
148025
+ version: 38,
148026
+ description: "durable transform decisions for cache-event cause attribution",
148027
+ up: (db) => {
148028
+ db.exec(`
148029
+ CREATE TABLE IF NOT EXISTS transform_decisions (
148030
+ session_id TEXT NOT NULL,
148031
+ harness TEXT NOT NULL DEFAULT 'opencode',
148032
+ message_id TEXT NOT NULL,
148033
+ ts_ms INTEGER NOT NULL,
148034
+ decision TEXT NOT NULL,
148035
+ materialized INTEGER NOT NULL DEFAULT 0,
148036
+ materialize_reason TEXT,
148037
+ emergency INTEGER NOT NULL DEFAULT 0,
148038
+ dropped_tokens INTEGER NOT NULL DEFAULT 0,
148039
+ dropped_count INTEGER NOT NULL DEFAULT 0,
148040
+ input_tokens INTEGER NOT NULL DEFAULT 0,
148041
+ PRIMARY KEY (session_id, harness, message_id)
148042
+ );
148043
+ CREATE INDEX IF NOT EXISTS idx_transform_decisions_session_harness
148044
+ ON transform_decisions(session_id, harness);
148045
+ `);
148046
+ }
147520
148047
  }
147521
148048
  ];
147522
148049
  LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
@@ -147548,7 +148075,7 @@ var init_storage_memory_mutation_log = __esm(() => {
147548
148075
  });
147549
148076
 
147550
148077
  // ../plugin/src/features/magic-context/storage-meta-persisted.ts
147551
- var AUTO_SEARCH_NO_HINT_REASONS, DRAIN_WINDOW_MS;
148078
+ var AUTO_SEARCH_NO_HINT_REASONS, DRAIN_WINDOW_MS, EMERGENCY_DRAIN_MAX_LATCH_MS;
147552
148079
  var init_storage_meta_persisted = __esm(() => {
147553
148080
  init_logger();
147554
148081
  init_storage_meta_shared();
@@ -147561,6 +148088,7 @@ var init_storage_meta_persisted = __esm(() => {
147561
148088
  "too-short"
147562
148089
  ]);
147563
148090
  DRAIN_WINDOW_MS = 10 * 60 * 1000;
148091
+ EMERGENCY_DRAIN_MAX_LATCH_MS = 30 * 60 * 1000;
147564
148092
  });
147565
148093
 
147566
148094
  // ../plugin/src/features/magic-context/resolve-subagent-fallback.ts
@@ -147604,10 +148132,11 @@ var init_storage_ops = __esm(() => {
147604
148132
  clearPendingOpsStatements = new WeakMap;
147605
148133
  removePendingOpStatements = new WeakMap;
147606
148134
  });
148135
+
147607
148136
  // ../plugin/src/features/magic-context/storage-source.ts
147608
148137
  var init_storage_source = () => {};
147609
148138
  // ../plugin/src/features/magic-context/storage-tags.ts
147610
- var insertTagStatements, updateTagStatusStatements, updateTagDropModeStatements, updateTagMessageIdStatements, getTagNumbersByMessageIdStatements, deleteTagsByMessageIdStatements, getMaxTagNumberBySessionStatements, getTagNumberByMessageIdStatements, updateTagByteSizeStatements, updateTagInputByteSizeStatements, updateTagTokenCountStatements, updateTagInputTokenCountStatements, getOwnerScopedToolTagNumbersStatements, getActiveTagsBySessionStatements, getMaxDroppedTagNumberStatements, getToolTagNumberByOwnerStatements, getNullOwnerToolTagStatements, adoptNullOwnerToolTagStatements, deleteToolTagsByOwnerStatements;
148139
+ var insertTagStatements, updateTagStatusStatements, updateTagDropModeStatements, updateTagMessageIdStatements, getTagNumbersByMessageIdStatements, deleteTagsByMessageIdStatements, getMaxTagNumberBySessionStatements, getTagNumberByMessageIdStatements, updateTagByteSizeStatements, updateTagInputByteSizeStatements, updateTagTokenCountStatements, updateTagInputTokenCountStatements, getOwnerScopedToolTagNumbersStatements, getMinMessageTagNumberForRawIdStatements, getActiveTagsBySessionStatements, getMaxDroppedTagNumberStatements, getToolTagNumberByOwnerStatements, getNullOwnerToolTagStatements, adoptNullOwnerToolTagStatements, deleteToolTagsByOwnerStatements;
147611
148140
  var init_storage_tags = __esm(() => {
147612
148141
  insertTagStatements = new WeakMap;
147613
148142
  updateTagStatusStatements = new WeakMap;
@@ -147622,6 +148151,7 @@ var init_storage_tags = __esm(() => {
147622
148151
  updateTagTokenCountStatements = new WeakMap;
147623
148152
  updateTagInputTokenCountStatements = new WeakMap;
147624
148153
  getOwnerScopedToolTagNumbersStatements = new WeakMap;
148154
+ getMinMessageTagNumberForRawIdStatements = new WeakMap;
147625
148155
  getActiveTagsBySessionStatements = new WeakMap;
147626
148156
  getMaxDroppedTagNumberStatements = new WeakMap;
147627
148157
  getToolTagNumberByOwnerStatements = new WeakMap;
@@ -147667,8 +148197,8 @@ var init_storage = __esm(async () => {
147667
148197
 
147668
148198
  // ../plugin/src/features/magic-context/v22-deferred-backfill.ts
147669
148199
  import { createHash as createHash2 } from "node:crypto";
147670
- import { realpathSync as realpathSync2 } from "node:fs";
147671
- import path4 from "node:path";
148200
+ import { realpathSync as realpathSync3 } from "node:fs";
148201
+ import path5 from "node:path";
147672
148202
  function readMeta(db, key) {
147673
148203
  const row = db.prepare("SELECT value FROM schema_migrations_meta WHERE key = ?").get(key);
147674
148204
  return row?.value ?? null;
@@ -147708,9 +148238,9 @@ function resolveBackfillIdentity(rawProjectPath) {
147708
148238
  function computeLegacyRustDirIdentity(rawProjectPath) {
147709
148239
  let canonical;
147710
148240
  try {
147711
- canonical = realpathSync2(rawProjectPath);
148241
+ canonical = realpathSync3(rawProjectPath);
147712
148242
  } catch {
147713
- canonical = path4.isAbsolute(rawProjectPath) ? rawProjectPath : path4.join(process.cwd(), rawProjectPath);
148243
+ canonical = path5.isAbsolute(rawProjectPath) ? rawProjectPath : path5.join(process.cwd(), rawProjectPath);
147714
148244
  }
147715
148245
  return `dir:${createHash2("sha256").update(canonical, "utf8").digest("hex")}`;
147716
148246
  }
@@ -147751,24 +148281,6 @@ function getV22BackfillStatus(db) {
147751
148281
  maxLegacyMemoryId: maxLegacyRow.m
147752
148282
  };
147753
148283
  }
147754
- function rekeyMemoryRowWithCollisionMerge(db, rowId, fromProjectPath, toIdentity) {
147755
- const row = db.prepare("SELECT category, normalized_hash, seen_count FROM memories WHERE id = ?").get(rowId);
147756
- if (!row)
147757
- return false;
147758
- const collision = db.prepare(`SELECT id, seen_count FROM memories
147759
- WHERE project_path = ? AND category = ? AND normalized_hash = ?
147760
- LIMIT 1`).get(toIdentity, row.category, row.normalized_hash);
147761
- if (collision && collision.id !== rowId) {
147762
- const mergedSeen = Math.max(collision.seen_count ?? 1, row.seen_count ?? 1);
147763
- if (mergedSeen !== (collision.seen_count ?? 1)) {
147764
- db.prepare("UPDATE memories SET seen_count = ? WHERE id = ?").run(mergedSeen, collision.id);
147765
- }
147766
- db.prepare("DELETE FROM memories WHERE id = ?").run(rowId);
147767
- return true;
147768
- }
147769
- const result = db.prepare("UPDATE memories SET project_path = ? WHERE id = ? AND project_path = ?").run(toIdentity, rowId, fromProjectPath);
147770
- return (result.changes ?? 0) > 0;
147771
- }
147772
148284
  async function doctorRetryV22Backfill(db) {
147773
148285
  const failures = db.prepare(`SELECT row_id, raw_project_path
147774
148286
  FROM v22_backfill_failures
@@ -147848,6 +148360,7 @@ var BACKFILL_META_KEY = "v22_legacy_memory_backfill", BACKFILL_CURSOR_META_KEY =
147848
148360
  var init_v22_deferred_backfill = __esm(() => {
147849
148361
  init_logger();
147850
148362
  init_project_identity();
148363
+ init_relocate_memory();
147851
148364
  });
147852
148365
 
147853
148366
  // src/lib/v22-backfill-commands.ts
@@ -148376,10 +148889,10 @@ function mergeDefs(...defs) {
148376
148889
  function cloneDef(schema) {
148377
148890
  return mergeDefs(schema._zod.def);
148378
148891
  }
148379
- function getElementAtPath(obj, path5) {
148380
- if (!path5)
148892
+ function getElementAtPath(obj, path6) {
148893
+ if (!path6)
148381
148894
  return obj;
148382
- return path5.reduce((acc, key) => acc?.[key], obj);
148895
+ return path6.reduce((acc, key) => acc?.[key], obj);
148383
148896
  }
148384
148897
  function promiseAllObject(promisesObj) {
148385
148898
  const keys = Object.keys(promisesObj);
@@ -148707,11 +149220,11 @@ function explicitlyAborted(x2, startIndex = 0) {
148707
149220
  }
148708
149221
  return false;
148709
149222
  }
148710
- function prefixIssues(path5, issues) {
149223
+ function prefixIssues(path6, issues) {
148711
149224
  return issues.map((iss) => {
148712
149225
  var _a2;
148713
149226
  (_a2 = iss).path ?? (_a2.path = []);
148714
- iss.path.unshift(path5);
149227
+ iss.path.unshift(path6);
148715
149228
  return iss;
148716
149229
  });
148717
149230
  }
@@ -148924,16 +149437,16 @@ function flattenError(error, mapper = (issue2) => issue2.message) {
148924
149437
  }
148925
149438
  function formatError(error, mapper = (issue2) => issue2.message) {
148926
149439
  const fieldErrors = { _errors: [] };
148927
- const processError = (error2, path5 = []) => {
149440
+ const processError = (error2, path6 = []) => {
148928
149441
  for (const issue2 of error2.issues) {
148929
149442
  if (issue2.code === "invalid_union" && issue2.errors.length) {
148930
- issue2.errors.map((issues) => processError({ issues }, [...path5, ...issue2.path]));
149443
+ issue2.errors.map((issues) => processError({ issues }, [...path6, ...issue2.path]));
148931
149444
  } else if (issue2.code === "invalid_key") {
148932
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
149445
+ processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
148933
149446
  } else if (issue2.code === "invalid_element") {
148934
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
149447
+ processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
148935
149448
  } else {
148936
- const fullpath = [...path5, ...issue2.path];
149449
+ const fullpath = [...path6, ...issue2.path];
148937
149450
  if (fullpath.length === 0) {
148938
149451
  fieldErrors._errors.push(mapper(issue2));
148939
149452
  } else {
@@ -148960,17 +149473,17 @@ function formatError(error, mapper = (issue2) => issue2.message) {
148960
149473
  }
148961
149474
  function treeifyError(error, mapper = (issue2) => issue2.message) {
148962
149475
  const result = { errors: [] };
148963
- const processError = (error2, path5 = []) => {
149476
+ const processError = (error2, path6 = []) => {
148964
149477
  var _a2, _b;
148965
149478
  for (const issue2 of error2.issues) {
148966
149479
  if (issue2.code === "invalid_union" && issue2.errors.length) {
148967
- issue2.errors.map((issues) => processError({ issues }, [...path5, ...issue2.path]));
149480
+ issue2.errors.map((issues) => processError({ issues }, [...path6, ...issue2.path]));
148968
149481
  } else if (issue2.code === "invalid_key") {
148969
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
149482
+ processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
148970
149483
  } else if (issue2.code === "invalid_element") {
148971
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
149484
+ processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
148972
149485
  } else {
148973
- const fullpath = [...path5, ...issue2.path];
149486
+ const fullpath = [...path6, ...issue2.path];
148974
149487
  if (fullpath.length === 0) {
148975
149488
  result.errors.push(mapper(issue2));
148976
149489
  continue;
@@ -149002,8 +149515,8 @@ function treeifyError(error, mapper = (issue2) => issue2.message) {
149002
149515
  }
149003
149516
  function toDotPath(_path) {
149004
149517
  const segs = [];
149005
- const path5 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
149006
- for (const seg of path5) {
149518
+ const path6 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
149519
+ for (const seg of path6) {
149007
149520
  if (typeof seg === "number")
149008
149521
  segs.push(`[${seg}]`);
149009
149522
  else if (typeof seg === "symbol")
@@ -162006,13 +162519,13 @@ function resolveRef(ref, ctx) {
162006
162519
  if (!ref.startsWith("#")) {
162007
162520
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
162008
162521
  }
162009
- const path5 = ref.slice(1).split("/").filter(Boolean);
162010
- if (path5.length === 0) {
162522
+ const path6 = ref.slice(1).split("/").filter(Boolean);
162523
+ if (path6.length === 0) {
162011
162524
  return ctx.rootSchema;
162012
162525
  }
162013
162526
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
162014
- if (path5[0] === defsKey) {
162015
- const key = path5[1];
162527
+ if (path6[0] === defsKey) {
162528
+ const key = path6[1];
162016
162529
  if (!key || !ctx.defs[key]) {
162017
162530
  throw new Error(`Reference not found: ${ref}`);
162018
162531
  }
@@ -162836,14 +163349,16 @@ var init_magic_context = __esm(() => {
162836
163349
  }).optional();
162837
163350
  HistorianConfigSchema = AgentOverrideConfigSchema.extend({
162838
163351
  two_pass: exports_external.boolean().default(false).describe("Run a second editor pass over historian output to clean low-signal U: lines and cross-compartment duplicates. Adds ~1 extra API call and ~1.3x cost per historian run. Useful for models without extended thinking support. (default: false)"),
162839
- thinking_level: PiThinkingLevelSchema.describe("Pi only: explicit thinking level passed as --thinking <level> to Pi historian subagent invocations. Required when using reasoning models (e.g. github-copilot/gpt-5.4) because Pi's default thinking-level resolution can pick a value the provider rejects. OpenCode users set variant instead. Valid: off | minimal | low | medium | high | xhigh")
163352
+ thinking_level: PiThinkingLevelSchema.describe("Pi only: explicit thinking level passed as --thinking <level> to Pi historian subagent invocations. Required when using reasoning models (e.g. github-copilot/gpt-5.4) because Pi's default thinking-level resolution can pick a value the provider rejects. OpenCode users set variant instead. Valid: off | minimal | low | medium | high | xhigh"),
163353
+ disallowed_tools: exports_external.array(exports_external.enum(["*", "read", "aft_outline", "aft_zoom", "aft_search"])).default([]).describe(`OpenCode only. Tools to REMOVE from the historian's default allow-list [read, aft_outline, aft_zoom, aft_search]. Applies to both historian and historian-editor agents. Use ["*"] to strip all tool definitions from the model request — this prevents weak instruction-following models (e.g. mistral-small-latest) from entering tool-calling loops. Individual tool names remove just that tool. Note: a user-supplied historian.permission override can re-allow a tool that disallowed_tools removed — disallowed_tools sets the baseline, permission overrides take precedence. (default: [])`)
162840
163354
  }).optional();
162841
163355
  BaseEmbeddingConfigSchema = exports_external.object({
162842
163356
  provider: exports_external.enum(["local", "openai-compatible", "off"]).default("local").describe("Embedding provider. 'local' uses Xenova/all-MiniLM-L6-v2, 'openai-compatible' requires endpoint and model, 'off' disables embeddings."),
162843
163357
  model: exports_external.string().optional().describe("Embedding model name. Required for openai-compatible, ignored for local."),
162844
163358
  endpoint: exports_external.string().optional().describe("API endpoint URL. Required when provider is openai-compatible."),
162845
163359
  api_key: exports_external.string().optional().describe("API key for remote embedding provider (optional)"),
162846
- input_type: exports_external.string().optional().describe("Optional input_type sent in the embedding request body. Required by some openai-compatible providers (e.g. NVIDIA NIM expects 'query' or 'passage'). Omitted from the request when unset."),
163360
+ input_type: exports_external.string().optional().describe("Default input_type for stored/indexed (passage) embeddings in the request body. Required by some openai-compatible providers (e.g. NVIDIA NIM). Omitted from the request when unset."),
163361
+ query_input_type: exports_external.string().optional().describe("Optional input_type for query (search) embeddings on asymmetric models (e.g. NVIDIA NIM 'query'). When unset, query embeddings use embedding.input_type. Passage/stored content always uses embedding.input_type."),
162847
163362
  truncate: exports_external.string().optional().describe("Optional truncate mode sent in the embedding request body (e.g. NVIDIA NIM accepts 'NONE' | 'START' | 'END'). Omitted from the request when unset."),
162848
163363
  max_input_tokens: exports_external.number().int().positive().optional().describe("Optional maximum input tokens for chunk embeddings. Defaults conservatively to 512 when omitted.")
162849
163364
  }).superRefine((data, ctx) => {
@@ -162873,6 +163388,7 @@ var init_magic_context = __esm(() => {
162873
163388
  if (data.provider === "openai-compatible") {
162874
163389
  const apiKey = data.api_key?.trim();
162875
163390
  const inputType = data.input_type?.trim();
163391
+ const queryInputType = data.query_input_type?.trim();
162876
163392
  const truncate = data.truncate?.trim();
162877
163393
  return {
162878
163394
  provider: "openai-compatible",
@@ -162880,6 +163396,7 @@ var init_magic_context = __esm(() => {
162880
163396
  endpoint: data.endpoint?.trim() ?? "",
162881
163397
  ...apiKey ? { api_key: apiKey } : {},
162882
163398
  ...inputType ? { input_type: inputType } : {},
163399
+ ...queryInputType ? { query_input_type: queryInputType } : {},
162883
163400
  ...truncate ? { truncate } : {},
162884
163401
  ...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}
162885
163402
  };
@@ -162962,11 +163479,11 @@ var init_magic_context = __esm(() => {
162962
163479
  });
162963
163480
 
162964
163481
  // ../plugin/src/config/variable.ts
162965
- import { existsSync as existsSync14, readFileSync as readFileSync8 } from "node:fs";
162966
- import { homedir as homedir7 } from "node:os";
163482
+ import { existsSync as existsSync15, readFileSync as readFileSync8 } from "node:fs";
163483
+ import { homedir as homedir8 } from "node:os";
162967
163484
  import { dirname as dirname7, isAbsolute, resolve as resolve2 } from "node:path";
162968
163485
  function sensitiveFilePathReason(resolvedPath) {
162969
- const home = homedir7();
163486
+ const home = homedir8();
162970
163487
  const sensitiveDirs = [
162971
163488
  { dir: resolve2(home, ".ssh"), label: "SSH keys" },
162972
163489
  { dir: resolve2(home, ".aws"), label: "AWS credentials" },
@@ -163029,7 +163546,7 @@ function substituteConfigVariables(input) {
163029
163546
  }
163030
163547
  let filePath = rawPath.trim();
163031
163548
  if (filePath.startsWith("~/")) {
163032
- filePath = resolve2(homedir7(), filePath.slice(2));
163549
+ filePath = resolve2(homedir8(), filePath.slice(2));
163033
163550
  } else if (!isAbsolute(filePath)) {
163034
163551
  filePath = resolve2(configDir, filePath);
163035
163552
  }
@@ -163037,7 +163554,7 @@ function substituteConfigVariables(input) {
163037
163554
  if (sensitiveReason) {
163038
163555
  warnings.push(`${token} resolves to a sensitive path (${sensitiveReason}: ${filePath}); ` + "inlining its contents into config — make sure this is intentional.");
163039
163556
  }
163040
- if (!existsSync14(filePath)) {
163557
+ if (!existsSync15(filePath)) {
163041
163558
  warnings.push(`File not found for ${token} (resolved to ${filePath}); using empty string`);
163042
163559
  continue;
163043
163560
  }
@@ -163062,19 +163579,19 @@ var init_variable = __esm(() => {
163062
163579
  });
163063
163580
 
163064
163581
  // ../plugin/src/config/index.ts
163065
- import { existsSync as existsSync15, readFileSync as readFileSync9 } from "node:fs";
163066
- import { homedir as homedir8 } from "node:os";
163067
- import { join as join12 } from "node:path";
163582
+ import { existsSync as existsSync16, readFileSync as readFileSync9 } from "node:fs";
163583
+ import { homedir as homedir9 } from "node:os";
163584
+ import { join as join13 } from "node:path";
163068
163585
  function getUserConfigBasePath() {
163069
- const configRoot = process.env.XDG_CONFIG_HOME ?? join12(homedir8(), ".config");
163070
- return join12(configRoot, "opencode", CONFIG_FILE_BASENAME);
163586
+ const configRoot = process.env.XDG_CONFIG_HOME ?? join13(homedir9(), ".config");
163587
+ return join13(configRoot, "opencode", CONFIG_FILE_BASENAME);
163071
163588
  }
163072
163589
  function getProjectConfigBasePath(directory) {
163073
- return join12(directory, ".opencode", CONFIG_FILE_BASENAME);
163590
+ return join13(directory, ".opencode", CONFIG_FILE_BASENAME);
163074
163591
  }
163075
163592
  function loadConfigFile(configPath, isProjectConfig = false) {
163076
163593
  try {
163077
- if (!existsSync15(configPath)) {
163594
+ if (!existsSync16(configPath)) {
163078
163595
  return null;
163079
163596
  }
163080
163597
  const rawText = readFileSync9(configPath, "utf-8");
@@ -163218,7 +163735,7 @@ function parsePluginConfig(rawConfig, recoveredTopLevelKeys = []) {
163218
163735
  }
163219
163736
  function loadPluginConfig(directory) {
163220
163737
  const userDetected = detectConfigFile(getUserConfigBasePath());
163221
- const rootDetected = detectConfigFile(join12(directory, CONFIG_FILE_BASENAME));
163738
+ const rootDetected = detectConfigFile(join13(directory, CONFIG_FILE_BASENAME));
163222
163739
  const dotOpenCodeDetected = detectConfigFile(getProjectConfigBasePath(directory));
163223
163740
  const projectDetected = rootDetected.format !== "none" ? rootDetected : dotOpenCodeDetected;
163224
163741
  const userLoaded = userDetected.format === "none" ? null : loadConfigFile(userDetected.path);
@@ -163266,14 +163783,14 @@ var init_config = __esm(() => {
163266
163783
  });
163267
163784
 
163268
163785
  // ../plugin/src/features/magic-context/key-files/aft-availability.ts
163269
- import { existsSync as existsSync16, readFileSync as readFileSync10 } from "node:fs";
163270
- import { homedir as homedir9 } from "node:os";
163271
- import { isAbsolute as isAbsolute2, join as join13, resolve as resolve3 } from "node:path";
163786
+ import { existsSync as existsSync17, readFileSync as readFileSync10 } from "node:fs";
163787
+ import { homedir as homedir10 } from "node:os";
163788
+ import { isAbsolute as isAbsolute2, join as join14, resolve as resolve3 } from "node:path";
163272
163789
  import { fileURLToPath } from "node:url";
163273
- function parseConfig(path5) {
163274
- if (!existsSync16(path5))
163790
+ function parseConfig(path6) {
163791
+ if (!existsSync17(path6))
163275
163792
  return null;
163276
- return import_comment_json6.parse(readFileSync10(path5, "utf-8"));
163793
+ return import_comment_json6.parse(readFileSync10(path6, "utf-8"));
163277
163794
  }
163278
163795
  function stringMentionsAft(value) {
163279
163796
  return AFT_NAME_NEEDLES.some((needle) => value.includes(needle));
@@ -163287,14 +163804,14 @@ function resolveLocalEntryPackageName(value, configDir) {
163287
163804
  return null;
163288
163805
  }
163289
163806
  } else if (value.startsWith("~/")) {
163290
- dir = join13(homedir9(), value.slice(2));
163807
+ dir = join14(homedir10(), value.slice(2));
163291
163808
  } else if (value.startsWith("/") || value.startsWith("./") || value.startsWith("../")) {
163292
163809
  dir = isAbsolute2(value) ? value : resolve3(configDir, value);
163293
163810
  } else {
163294
163811
  return null;
163295
163812
  }
163296
163813
  try {
163297
- const pkg = JSON.parse(readFileSync10(join13(dir, "package.json"), "utf-8"));
163814
+ const pkg = JSON.parse(readFileSync10(join14(dir, "package.json"), "utf-8"));
163298
163815
  return typeof pkg.name === "string" ? pkg.name : null;
163299
163816
  } catch {
163300
163817
  return null;
@@ -163323,18 +163840,18 @@ function hasAftAtKeys(value, keys, configDir) {
163323
163840
  return false;
163324
163841
  }
163325
163842
  function getAftAvailability() {
163326
- const home = process.env.HOME || homedir9();
163843
+ const home = process.env.HOME || homedir10();
163327
163844
  const opencodePaths = [
163328
- join13(home, ".config", "opencode", "opencode.jsonc"),
163329
- join13(home, ".config", "opencode", "opencode.json")
163845
+ join14(home, ".config", "opencode", "opencode.jsonc"),
163846
+ join14(home, ".config", "opencode", "opencode.json")
163330
163847
  ];
163331
- const piPaths = [join13(home, ".pi", "agent", "settings.json")];
163848
+ const piPaths = [join14(home, ".pi", "agent", "settings.json")];
163332
163849
  const checkedPaths = [...opencodePaths, ...piPaths];
163333
163850
  let opencode = false;
163334
- for (const path5 of opencodePaths) {
163851
+ for (const path6 of opencodePaths) {
163335
163852
  try {
163336
- const config2 = parseConfig(path5);
163337
- const configDir = join13(path5, "..");
163853
+ const config2 = parseConfig(path6);
163854
+ const configDir = join14(path6, "..");
163338
163855
  if (hasAftAtKeys(config2, ["plugin", "plugins", "mcp", "mcp_servers"], configDir)) {
163339
163856
  opencode = true;
163340
163857
  break;
@@ -163342,10 +163859,10 @@ function getAftAvailability() {
163342
163859
  } catch {}
163343
163860
  }
163344
163861
  let pi = false;
163345
- for (const path5 of piPaths) {
163862
+ for (const path6 of piPaths) {
163346
163863
  try {
163347
- const config2 = parseConfig(path5);
163348
- const configDir = join13(path5, "..");
163864
+ const config2 = parseConfig(path6);
163865
+ const configDir = join14(path6, "..");
163349
163866
  if (hasAftAtKeys(config2, ["packages", "extensions"], configDir)) {
163350
163867
  pi = true;
163351
163868
  break;
@@ -163483,8 +164000,8 @@ function truncate(text2) {
163483
164000
  var DEFAULT_TIMEOUT_MS = 1e4, MAX_PREVIEW_CHARS = 240;
163484
164001
 
163485
164002
  // ../plugin/src/shared/tui-config.ts
163486
- import { existsSync as existsSync17, mkdirSync as mkdirSync6, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "node:fs";
163487
- import { dirname as dirname8, join as join14 } from "node:path";
164003
+ import { existsSync as existsSync18, mkdirSync as mkdirSync6, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "node:fs";
164004
+ import { dirname as dirname8, join as join15 } from "node:path";
163488
164005
  function isMagicContextEntry(entry) {
163489
164006
  if (!entry)
163490
164007
  return false;
@@ -163498,11 +164015,11 @@ function isMagicContextEntry(entry) {
163498
164015
  }
163499
164016
  function resolveTuiConfigPath() {
163500
164017
  const configDir = getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
163501
- const jsoncPath = join14(configDir, "tui.jsonc");
163502
- const jsonPath = join14(configDir, "tui.json");
163503
- if (existsSync17(jsoncPath))
164018
+ const jsoncPath = join15(configDir, "tui.jsonc");
164019
+ const jsonPath = join15(configDir, "tui.json");
164020
+ if (existsSync18(jsoncPath))
163504
164021
  return jsoncPath;
163505
- if (existsSync17(jsonPath))
164022
+ if (existsSync18(jsonPath))
163506
164023
  return jsonPath;
163507
164024
  return jsonPath;
163508
164025
  }
@@ -163510,7 +164027,7 @@ function ensureTuiPluginEntry() {
163510
164027
  try {
163511
164028
  const configPath = resolveTuiConfigPath();
163512
164029
  let config2 = {};
163513
- if (existsSync17(configPath)) {
164030
+ if (existsSync18(configPath)) {
163514
164031
  const raw = readFileSync11(configPath, "utf-8");
163515
164032
  config2 = import_comment_json7.parse(raw) ?? {};
163516
164033
  }
@@ -163681,7 +164198,7 @@ var init_compartment_parser = __esm(() => {
163681
164198
  });
163682
164199
 
163683
164200
  // src/lib/redaction.ts
163684
- import { homedir as homedir10, userInfo } from "node:os";
164201
+ import { homedir as homedir11, userInfo } from "node:os";
163685
164202
  function escapeRegex3(value) {
163686
164203
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
163687
164204
  }
@@ -163725,7 +164242,7 @@ function isSecretKey(key) {
163725
164242
  return false;
163726
164243
  }
163727
164244
  function sanitizePathString(value) {
163728
- const home = homedir10();
164245
+ const home = homedir11();
163729
164246
  const username = userInfo().username;
163730
164247
  let sanitized = value;
163731
164248
  if (home) {
@@ -163859,10 +164376,10 @@ var init_redaction = __esm(() => {
163859
164376
  });
163860
164377
 
163861
164378
  // src/lib/diagnostics-opencode.ts
163862
- import { existsSync as existsSync18, readdirSync as readdirSync2, readFileSync as readFileSync12, statSync as statSync4 } from "node:fs";
164379
+ import { existsSync as existsSync19, readdirSync as readdirSync2, readFileSync as readFileSync12, statSync as statSync4 } from "node:fs";
163863
164380
  import { createRequire as createRequire2 } from "node:module";
163864
- import { homedir as homedir11 } from "node:os";
163865
- import { join as join15 } from "node:path";
164381
+ import { homedir as homedir12 } from "node:os";
164382
+ import { join as join16 } from "node:path";
163866
164383
  function getSelfVersion() {
163867
164384
  const require2 = createRequire2(import.meta.url);
163868
164385
  for (const relPath of ["../../package.json", "../package.json"]) {
@@ -163876,26 +164393,26 @@ function getSelfVersion() {
163876
164393
  return "unknown";
163877
164394
  }
163878
164395
  function getPluginCacheInfo() {
163879
- const path5 = join15(getOpenCodeCacheDir(), "packages", PLUGIN_ENTRY_WITH_VERSION);
164396
+ const path6 = join16(getOpenCodeCacheDir(), "packages", PLUGIN_ENTRY_WITH_VERSION);
163880
164397
  let cached2;
163881
164398
  try {
163882
- const installedPkgPath = join15(path5, "node_modules", "@cortexkit", "opencode-magic-context", "package.json");
163883
- if (existsSync18(installedPkgPath)) {
164399
+ const installedPkgPath = join16(path6, "node_modules", "@cortexkit", "opencode-magic-context", "package.json");
164400
+ if (existsSync19(installedPkgPath)) {
163884
164401
  const pkg = JSON.parse(readFileSync12(installedPkgPath, "utf-8"));
163885
164402
  cached2 = typeof pkg.version === "string" ? pkg.version : undefined;
163886
164403
  }
163887
164404
  } catch {
163888
164405
  cached2 = undefined;
163889
164406
  }
163890
- return { path: path5, cached: cached2, latest: getSelfVersion() };
164407
+ return { path: path6, cached: cached2, latest: getSelfVersion() };
163891
164408
  }
163892
164409
  function getStorageDir() {
163893
- const dataHome = process.env.XDG_DATA_HOME || join15(homedir11(), ".local", "share");
163894
- return join15(dataHome, "cortexkit", "magic-context");
164410
+ const dataHome = process.env.XDG_DATA_HOME || join16(homedir12(), ".local", "share");
164411
+ return join16(dataHome, "cortexkit", "magic-context");
163895
164412
  }
163896
- function fileSize(path5) {
164413
+ function fileSize(path6) {
163897
164414
  try {
163898
- return existsSync18(path5) ? statSync4(path5).size : 0;
164415
+ return existsSync19(path6) ? statSync4(path6).size : 0;
163899
164416
  } catch {
163900
164417
  return 0;
163901
164418
  }
@@ -163906,11 +164423,11 @@ function sanitizeString(value) {
163906
164423
  function sanitizeValue(value) {
163907
164424
  return sanitizeConfigValue(value);
163908
164425
  }
163909
- function readConfig2(path5) {
163910
- if (!existsSync18(path5))
164426
+ function readConfig2(path6) {
164427
+ if (!existsSync19(path6))
163911
164428
  return { value: null };
163912
164429
  try {
163913
- const raw = readFileSync12(path5, "utf-8");
164430
+ const raw = readFileSync12(path6, "utf-8");
163914
164431
  const value = import_comment_json8.parse(raw);
163915
164432
  return { value };
163916
164433
  } catch (error51) {
@@ -163931,9 +164448,9 @@ function configHasPluginEntry(config2) {
163931
164448
  return false;
163932
164449
  });
163933
164450
  }
163934
- function parseHistorianDumpMeta(path5) {
164451
+ function parseHistorianDumpMeta(path6) {
163935
164452
  try {
163936
- const xml = readFileSync12(path5, "utf-8");
164453
+ const xml = readFileSync12(path6, "utf-8");
163937
164454
  const parsed = parseCompartmentOutput(xml);
163938
164455
  const factCountByCategory = {};
163939
164456
  for (const fact of parsed.facts) {
@@ -163966,11 +164483,11 @@ function parseHistorianDumpMeta(path5) {
163966
164483
  }
163967
164484
  }
163968
164485
  function listDumpsInDir(dir, limit) {
163969
- if (!existsSync18(dir))
164486
+ if (!existsSync19(dir))
163970
164487
  return { count: 0, recent: [] };
163971
164488
  try {
163972
164489
  const entries = readdirSync2(dir).filter((name2) => name2.endsWith(".xml")).map((name2) => {
163973
- const stat = statSync4(join15(dir, name2));
164490
+ const stat = statSync4(join16(dir, name2));
163974
164491
  return {
163975
164492
  name: name2,
163976
164493
  mtime: stat.mtimeMs,
@@ -163979,7 +164496,7 @@ function listDumpsInDir(dir, limit) {
163979
164496
  }).sort((a, b2) => b2.mtime - a.mtime);
163980
164497
  const now = Date.now();
163981
164498
  const recent = entries.slice(0, limit).map((entry) => {
163982
- const meta3 = parseHistorianDumpMeta(join15(dir, entry.name));
164499
+ const meta3 = parseHistorianDumpMeta(join16(dir, entry.name));
163983
164500
  const summary = {
163984
164501
  name: entry.name,
163985
164502
  ageMinutes: Math.round((now - entry.mtime) / 60000),
@@ -164034,8 +164551,8 @@ function collectHistorianDumps(recentSessions) {
164034
164551
  };
164035
164552
  }
164036
164553
  async function collectRecentSessions() {
164037
- const opencodeDbPath = join15(homedir11(), ".local", "share", "opencode", "opencode.db");
164038
- if (!existsSync18(opencodeDbPath))
164554
+ const opencodeDbPath = join16(homedir12(), ".local", "share", "opencode", "opencode.db");
164555
+ if (!existsSync19(opencodeDbPath))
164039
164556
  return [];
164040
164557
  if (typeof globalThis.Bun === "undefined") {
164041
164558
  return [];
@@ -164069,8 +164586,8 @@ async function collectRecentSessions() {
164069
164586
  }
164070
164587
  }
164071
164588
  async function collectHistorianFailures(storageDirPath) {
164072
- const contextDbPath = join15(storageDirPath, "context.db");
164073
- if (!existsSync18(contextDbPath))
164589
+ const contextDbPath = join16(storageDirPath, "context.db");
164590
+ if (!existsSync19(contextDbPath))
164074
164591
  return [];
164075
164592
  if (typeof globalThis.Bun === "undefined") {
164076
164593
  return [];
@@ -164102,6 +164619,70 @@ async function collectHistorianFailures(storageDirPath) {
164102
164619
  } catch {}
164103
164620
  }
164104
164621
  }
164622
+ async function collectHistorianRuns(storageDirPath) {
164623
+ const contextDbPath = join16(storageDirPath, "context.db");
164624
+ if (!existsSync19(contextDbPath))
164625
+ return [];
164626
+ if (typeof globalThis.Bun === "undefined")
164627
+ return [];
164628
+ let DatabaseClass;
164629
+ try {
164630
+ const mod = await new Function("p", "return import(p)")("bun:sqlite");
164631
+ DatabaseClass = mod.Database;
164632
+ } catch {
164633
+ return [];
164634
+ }
164635
+ let db = null;
164636
+ try {
164637
+ db = new DatabaseClass(contextDbPath, { readonly: true });
164638
+ const aggRows = db.prepare(`SELECT session_id,
164639
+ COUNT(*) AS total,
164640
+ SUM(CASE WHEN status='success' THEN 1 ELSE 0 END) AS success,
164641
+ SUM(CASE WHEN status='failed' THEN 1 ELSE 0 END) AS failed,
164642
+ SUM(CASE WHEN status='noop' THEN 1 ELSE 0 END) AS noop,
164643
+ MAX(created_at) AS last_run_at
164644
+ FROM historian_runs
164645
+ GROUP BY session_id
164646
+ ORDER BY last_run_at DESC
164647
+ LIMIT 10`).all();
164648
+ if (aggRows.length === 0)
164649
+ return [];
164650
+ const reasonRows = db.prepare(`SELECT session_id, failure_reason, created_at
164651
+ FROM historian_runs
164652
+ WHERE status='failed' AND failure_reason IS NOT NULL
164653
+ ORDER BY created_at DESC
164654
+ LIMIT 200`).all();
164655
+ const latestReasonBySession = new Map;
164656
+ for (const row of reasonRows) {
164657
+ const sid = typeof row.session_id === "string" ? row.session_id : "";
164658
+ if (!sid || latestReasonBySession.has(sid))
164659
+ continue;
164660
+ if (typeof row.failure_reason === "string") {
164661
+ latestReasonBySession.set(sid, row.failure_reason);
164662
+ }
164663
+ }
164664
+ const asNum = (v2) => typeof v2 === "number" ? v2 : 0;
164665
+ return aggRows.map((row) => {
164666
+ const sessionId = typeof row.session_id === "string" ? row.session_id : "<unknown>";
164667
+ const rawReason = latestReasonBySession.get(sessionId) ?? "";
164668
+ return {
164669
+ sessionId,
164670
+ total: asNum(row.total),
164671
+ success: asNum(row.success),
164672
+ failed: asNum(row.failed),
164673
+ noop: asNum(row.noop),
164674
+ lastFailureReason: sanitizeDiagnosticText(rawReason.replace(/\s+/g, " ").trim().slice(0, 400)),
164675
+ lastRunAt: typeof row.last_run_at === "number" ? new Date(row.last_run_at).toISOString() : ""
164676
+ };
164677
+ });
164678
+ } catch {
164679
+ return [];
164680
+ } finally {
164681
+ try {
164682
+ db?.close();
164683
+ } catch {}
164684
+ }
164685
+ }
164105
164686
  async function collectDiagnostics() {
164106
164687
  const pluginVersion = getSelfVersion();
164107
164688
  const configPaths = detectConfigPaths();
@@ -164109,9 +164690,9 @@ async function collectDiagnostics() {
164109
164690
  const tuiConfig = readConfig2(configPaths.tuiConfig);
164110
164691
  const magicContextConfig = readConfig2(configPaths.magicContextConfig);
164111
164692
  const storageDirPath = getStorageDir();
164112
- const contextDbPath = join15(storageDirPath, "context.db");
164693
+ const contextDbPath = join16(storageDirPath, "context.db");
164113
164694
  const logPath = getMagicContextLogPath2("opencode");
164114
- const logFileSize = existsSync18(logPath) ? statSync4(logPath).size : 0;
164695
+ const logFileSize = existsSync19(logPath) ? statSync4(logPath).size : 0;
164115
164696
  const conflictResult = detectConflicts(process.cwd());
164116
164697
  const recentSessions = await collectRecentSessions();
164117
164698
  return {
@@ -164126,7 +164707,7 @@ async function collectDiagnostics() {
164126
164707
  opencodeConfigHasPlugin: configHasPluginEntry(opencodeConfig.value),
164127
164708
  tuiConfigHasPlugin: configHasPluginEntry(tuiConfig.value),
164128
164709
  magicContextConfig: {
164129
- exists: existsSync18(configPaths.magicContextConfig),
164710
+ exists: existsSync19(configPaths.magicContextConfig),
164130
164711
  ...magicContextConfig.error ? { parseError: magicContextConfig.error } : {},
164131
164712
  flags: sanitizeValue(magicContextConfig.value ?? {}) ?? {}
164132
164713
  },
@@ -164134,7 +164715,7 @@ async function collectDiagnostics() {
164134
164715
  pluginCache: getPluginCacheInfo(),
164135
164716
  storageDir: {
164136
164717
  path: storageDirPath,
164137
- exists: existsSync18(storageDirPath),
164718
+ exists: existsSync19(storageDirPath),
164138
164719
  contextDbSizeBytes: fileSize(contextDbPath)
164139
164720
  },
164140
164721
  conflicts: {
@@ -164143,12 +164724,13 @@ async function collectDiagnostics() {
164143
164724
  },
164144
164725
  logFile: {
164145
164726
  path: logPath,
164146
- exists: existsSync18(logPath),
164727
+ exists: existsSync19(logPath),
164147
164728
  sizeKb: Math.round(logFileSize / 1024)
164148
164729
  },
164149
164730
  recentSessions,
164150
164731
  historianDumps: collectHistorianDumps(recentSessions),
164151
- historianFailures: await collectHistorianFailures(storageDirPath)
164732
+ historianFailures: await collectHistorianFailures(storageDirPath),
164733
+ historianRuns: await collectHistorianRuns(storageDirPath)
164152
164734
  };
164153
164735
  }
164154
164736
  function formatBytes(bytes) {
@@ -164244,11 +164826,21 @@ function renderDiagnosticsMarkdown(report) {
164244
164826
  "```",
164245
164827
  "",
164246
164828
  "### Historian failures (session_meta)",
164829
+ "_Note: this counter RESETS to 0 on every successful run — see 'Historian runs' below for the durable history._",
164247
164830
  report.historianFailures.length === 0 ? "_No sessions with historian failures._" : [
164248
164831
  "```json",
164249
164832
  JSON.stringify(sanitizeConfigValue(report.historianFailures), null, 2),
164250
164833
  "```"
164251
164834
  ].join(`
164835
+ `),
164836
+ "",
164837
+ "### Historian runs (durable telemetry)",
164838
+ "Per-session success/failure/no-op counts from `historian_runs` (never reset).",
164839
+ report.historianRuns.length === 0 ? "_No historian runs recorded (or schema predates v24)._" : [
164840
+ "```json",
164841
+ JSON.stringify(sanitizeConfigValue(report.historianRuns), null, 2),
164842
+ "```"
164843
+ ].join(`
164252
164844
  `),
164253
164845
  "",
164254
164846
  "### Log file",
@@ -164272,33 +164864,33 @@ var init_diagnostics_opencode = __esm(() => {
164272
164864
  });
164273
164865
 
164274
164866
  // src/lib/embedding-runtime.ts
164275
- import { existsSync as existsSync19 } from "node:fs";
164867
+ import { existsSync as existsSync20 } from "node:fs";
164276
164868
  import { createRequire as createRequire3 } from "node:module";
164277
- import { dirname as dirname9, join as join16, sep } from "node:path";
164869
+ import { dirname as dirname9, join as join17, sep } from "node:path";
164278
164870
  function expectedBinaryRelPath(platform, arch) {
164279
164871
  const supportedPlatform = platform === "linux" || platform === "darwin" || platform === "win32";
164280
164872
  const supportedArch = arch === "x64" || arch === "arm64";
164281
164873
  if (!supportedPlatform || !supportedArch)
164282
164874
  return null;
164283
- return join16("bin", "napi-v6", platform, arch, "onnxruntime_binding.node");
164875
+ return join17("bin", "napi-v6", platform, arch, "onnxruntime_binding.node");
164284
164876
  }
164285
164877
  function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform, arch = process.arch) {
164286
- const packageDir = join16(installRoot, "node_modules", "onnxruntime-node");
164287
- if (!existsSync19(join16(packageDir, "package.json"))) {
164878
+ const packageDir = join17(installRoot, "node_modules", "onnxruntime-node");
164879
+ if (!existsSync20(join17(packageDir, "package.json"))) {
164288
164880
  return { state: "package-missing", packageDir };
164289
164881
  }
164290
164882
  const rel = expectedBinaryRelPath(platform, arch);
164291
164883
  if (rel === null) {
164292
164884
  return { state: "ok", binaryPath: packageDir };
164293
164885
  }
164294
- const binaryPath = join16(packageDir, rel);
164295
- if (!existsSync19(binaryPath)) {
164886
+ const binaryPath = join17(packageDir, rel);
164887
+ if (!existsSync20(binaryPath)) {
164296
164888
  return { state: "binary-missing", packageDir, expectedBinary: binaryPath };
164297
164889
  }
164298
164890
  return { state: "ok", binaryPath };
164299
164891
  }
164300
164892
  function checkLocalEmbeddingRuntime(installRoots, platform = process.platform, arch = process.arch) {
164301
- const existing = installRoots.filter((root) => existsSync19(root));
164893
+ const existing = installRoots.filter((root) => existsSync20(root));
164302
164894
  if (existing.length === 0) {
164303
164895
  return {
164304
164896
  state: "unknown",
@@ -164321,19 +164913,19 @@ function packageDirFromResolved(resolvedPath, packageName) {
164321
164913
  return idx >= 0 ? resolvedPath.slice(0, idx + marker.length) : dirname9(resolvedPath);
164322
164914
  }
164323
164915
  function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.platform, arch = process.arch) {
164324
- if (!existsSync19(join16(pluginDir, "package.json"))) {
164916
+ if (!existsSync20(join17(pluginDir, "package.json"))) {
164325
164917
  return { state: "unknown", reason: "plugin package dir not found" };
164326
164918
  }
164327
164919
  let onnxDir = null;
164328
164920
  let resolveError;
164329
164921
  try {
164330
- const reqPlugin = createRequire3(join16(pluginDir, "package.json"));
164922
+ const reqPlugin = createRequire3(join17(pluginDir, "package.json"));
164331
164923
  try {
164332
164924
  onnxDir = packageDirFromResolved(reqPlugin.resolve("onnxruntime-node"), "onnxruntime-node");
164333
164925
  } catch {
164334
164926
  const tfResolved = reqPlugin.resolve("@huggingface/transformers");
164335
164927
  const tfDir = packageDirFromResolved(tfResolved, "@huggingface/transformers");
164336
- const reqTf = createRequire3(join16(tfDir, "package.json"));
164928
+ const reqTf = createRequire3(join17(tfDir, "package.json"));
164337
164929
  onnxDir = packageDirFromResolved(reqTf.resolve("onnxruntime-node"), "onnxruntime-node");
164338
164930
  }
164339
164931
  } catch (error51) {
@@ -164341,7 +164933,7 @@ function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.pl
164341
164933
  if (resolveError === "ERR_MODULE_NOT_FOUND" || resolveError === "MODULE_NOT_FOUND") {
164342
164934
  return {
164343
164935
  state: "package-missing",
164344
- packageDir: join16(pluginDir, "node_modules", "onnxruntime-node")
164936
+ packageDir: join17(pluginDir, "node_modules", "onnxruntime-node")
164345
164937
  };
164346
164938
  }
164347
164939
  return {
@@ -164356,8 +164948,8 @@ function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.pl
164356
164948
  if (rel === null) {
164357
164949
  return { state: "ok", binaryPath: onnxDir };
164358
164950
  }
164359
- const binaryPath = join16(onnxDir, rel);
164360
- if (!existsSync19(binaryPath)) {
164951
+ const binaryPath = join17(onnxDir, rel);
164952
+ if (!existsSync20(binaryPath)) {
164361
164953
  return { state: "binary-missing", packageDir: onnxDir, expectedBinary: binaryPath };
164362
164954
  }
164363
164955
  return { state: "ok", binaryPath };
@@ -164451,8 +165043,8 @@ var init_issue_body = __esm(() => {
164451
165043
 
164452
165044
  // src/lib/logs-opencode.ts
164453
165045
  import { readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "node:fs";
164454
- import { homedir as homedir12 } from "node:os";
164455
- import { join as join17 } from "node:path";
165046
+ import { homedir as homedir13 } from "node:os";
165047
+ import { join as join18 } from "node:path";
164456
165048
  function sanitizeLogContent(content) {
164457
165049
  return sanitizeDiagnosticText(content);
164458
165050
  }
@@ -164505,7 +165097,7 @@ async function bundleIssueReport(report, description, _title, sessionFilter = nu
164505
165097
  `));
164506
165098
  const recentErrorLines = extractRecentErrors(errorScanWindow, 20);
164507
165099
  const configBody = JSON.stringify(sanitizeConfigValue(report.magicContextConfig.flags), null, 2);
164508
- const sanitizedConfigPath = report.configPaths.magicContextConfig.replace(homedir12(), "~");
165100
+ const sanitizedConfigPath = report.configPaths.magicContextConfig.replace(homedir13(), "~");
164509
165101
  const rawBodyMarkdown = [
164510
165102
  "## Description",
164511
165103
  description,
@@ -164542,10 +165134,10 @@ async function bundleIssueReport(report, description, _title, sessionFilter = nu
164542
165134
  ].join(`
164543
165135
  `);
164544
165136
  const bodyMarkdown = capBodyToGithubLimit(rawBodyMarkdown);
164545
- const path5 = join17(process.cwd(), `magic-context-issue-${formatTimestamp(new Date)}.md`);
164546
- writeFileSync8(path5, `${bodyMarkdown}
165137
+ const path6 = join18(process.cwd(), `magic-context-issue-${formatTimestamp(new Date)}.md`);
165138
+ writeFileSync8(path6, `${bodyMarkdown}
164547
165139
  `);
164548
- return { path: path5, bodyMarkdown };
165140
+ return { path: path6, bodyMarkdown };
164549
165141
  }
164550
165142
  var HISTORIAN_LOG_PATTERNS;
164551
165143
  var init_logs_opencode = __esm(() => {
@@ -164565,10 +165157,10 @@ var init_logs_opencode = __esm(() => {
164565
165157
 
164566
165158
  // src/commands/doctor-opencode.ts
164567
165159
  import { execSync as execSync2, spawnSync as spawnSync2 } from "node:child_process";
164568
- import { existsSync as existsSync20, readFileSync as readFileSync14, rmSync, statSync as statSync5, writeFileSync as writeFileSync9 } from "node:fs";
165160
+ import { existsSync as existsSync21, readFileSync as readFileSync14, rmSync, statSync as statSync5, writeFileSync as writeFileSync9 } from "node:fs";
164569
165161
  import { createRequire as createRequire4 } from "node:module";
164570
- import { homedir as homedir13 } from "node:os";
164571
- import { join as join18 } from "node:path";
165162
+ import { homedir as homedir14 } from "node:os";
165163
+ import { join as join19 } from "node:path";
164572
165164
  function migrateLegacyAgentEnabledConfigForDoctor(mcConfig, logs) {
164573
165165
  let changed = false;
164574
165166
  let fixes = 0;
@@ -164655,14 +165247,14 @@ function compareVersions(a, b2) {
164655
165247
  }
164656
165248
  async function clearPluginCache(force = false) {
164657
165249
  const cacheDir = getOpenCodeCacheDir();
164658
- const pluginCacheDir = join18(cacheDir, "packages", PLUGIN_ENTRY_WITH_VERSION2);
164659
- if (!existsSync20(pluginCacheDir)) {
165250
+ const pluginCacheDir = join19(cacheDir, "packages", PLUGIN_ENTRY_WITH_VERSION2);
165251
+ if (!existsSync21(pluginCacheDir)) {
164660
165252
  return { action: "not_found", path: pluginCacheDir };
164661
165253
  }
164662
165254
  let cachedVersion;
164663
165255
  try {
164664
- const installedPkgPath = join18(pluginCacheDir, "node_modules", "@cortexkit", "opencode-magic-context", "package.json");
164665
- if (existsSync20(installedPkgPath)) {
165256
+ const installedPkgPath = join19(pluginCacheDir, "node_modules", "@cortexkit", "opencode-magic-context", "package.json");
165257
+ if (existsSync21(installedPkgPath)) {
164666
165258
  const pkg = JSON.parse(readFileSync14(installedPkgPath, "utf-8"));
164667
165259
  if (typeof pkg?.version === "string") {
164668
165260
  cachedVersion = pkg.version;
@@ -164796,8 +165388,8 @@ async function runIssueFlow() {
164796
165388
  }
164797
165389
  function checkLocalEmbeddingRuntimeForDoctor() {
164798
165390
  const runtime = checkLocalEmbeddingRuntime([
164799
- join18(getOpenCodeCacheDir(), "packages", PLUGIN_ENTRY_WITH_VERSION2),
164800
- join18(getOpenCodeCacheDir(), "packages", PLUGIN_NAME6)
165391
+ join19(getOpenCodeCacheDir(), "packages", PLUGIN_ENTRY_WITH_VERSION2),
165392
+ join19(getOpenCodeCacheDir(), "packages", PLUGIN_NAME6)
164801
165393
  ]);
164802
165394
  if (runtime.state === "package-missing" || runtime.state === "binary-missing") {
164803
165395
  log.warn("Embedding provider: local — but the native runtime (onnxruntime-node) " + `is ${runtime.state === "package-missing" ? "not installed" : "missing its platform binary"}. ` + "Local embeddings won't work. Fix: re-run with `doctor --force` to reinstall " + "the plugin, or set `embedding.provider` to `openai-compatible` (LM Studio / " + "Ollama) or `off`. Existing memories are unaffected.");
@@ -164807,7 +165399,7 @@ function checkLocalEmbeddingRuntimeForDoctor() {
164807
165399
  return { issues: 0 };
164808
165400
  }
164809
165401
  async function checkEmbeddingConfig(magicContextConfigPath) {
164810
- if (!existsSync20(magicContextConfigPath)) {
165402
+ if (!existsSync21(magicContextConfigPath)) {
164811
165403
  return checkLocalEmbeddingRuntimeForDoctor();
164812
165404
  }
164813
165405
  let rawText;
@@ -164974,7 +165566,7 @@ async function runDoctor(options = {}) {
164974
165566
  } else {
164975
165567
  pass(`OpenCode config: ${paths.opencodeConfig}`);
164976
165568
  }
164977
- if (existsSync20(paths.magicContextConfig)) {
165569
+ if (existsSync21(paths.magicContextConfig)) {
164978
165570
  pass(`Magic Context config: ${paths.magicContextConfig}`);
164979
165571
  try {
164980
165572
  const raw = readFileSync14(paths.magicContextConfig, "utf-8");
@@ -165002,7 +165594,7 @@ async function runDoctor(options = {}) {
165002
165594
  warn(`No magic-context.jsonc found — using defaults`);
165003
165595
  log.info(" Run 'setup' to create one with model recommendations");
165004
165596
  }
165005
- if (existsSync20(paths.magicContextConfig)) {
165597
+ if (existsSync21(paths.magicContextConfig)) {
165006
165598
  try {
165007
165599
  const mcRaw = readFileSync14(paths.magicContextConfig, "utf-8");
165008
165600
  const mcConfig = import_comment_json9.parse(mcRaw);
@@ -165209,7 +165801,7 @@ async function runDoctor(options = {}) {
165209
165801
  pass("Added TUI sidebar plugin to tui.json");
165210
165802
  warn("Restart OpenCode to see the sidebar");
165211
165803
  fixed++;
165212
- } else if (existsSync20(paths.tuiConfig)) {
165804
+ } else if (existsSync21(paths.tuiConfig)) {
165213
165805
  try {
165214
165806
  const tuiRaw = readFileSync14(paths.tuiConfig, "utf-8");
165215
165807
  const tuiConfig = import_comment_json9.parse(tuiRaw);
@@ -165257,7 +165849,7 @@ async function runDoctor(options = {}) {
165257
165849
  } else {
165258
165850
  pass("TUI sidebar plugin configured (tui.json created)");
165259
165851
  }
165260
- if (existsSync20(paths.magicContextConfig)) {
165852
+ if (existsSync21(paths.magicContextConfig)) {
165261
165853
  try {
165262
165854
  const mcRaw = readFileSync14(paths.magicContextConfig, "utf-8");
165263
165855
  const mcConfig = import_comment_json9.parse(mcRaw);
@@ -165286,8 +165878,8 @@ async function runDoctor(options = {}) {
165286
165878
  failCount += embeddingCheck.issues;
165287
165879
  else
165288
165880
  passCount++;
165289
- const dbPath = join18(getMagicContextStorageDir(), "context.db");
165290
- if (!existsSync20(dbPath)) {
165881
+ const dbPath = join19(getMagicContextStorageDir(), "context.db");
165882
+ if (!existsSync21(dbPath)) {
165291
165883
  log.info(`Shared context DB not yet created at ${dbPath} (will be created on first run)`);
165292
165884
  } else {
165293
165885
  pass(`Shared context DB exists at ${dbPath}`);
@@ -165348,8 +165940,8 @@ async function runDoctor(options = {}) {
165348
165940
  }
165349
165941
  {
165350
165942
  const ageWarnings = [];
165351
- const npmrcPath = join18(homedir13(), ".npmrc");
165352
- if (existsSync20(npmrcPath)) {
165943
+ const npmrcPath = join19(homedir14(), ".npmrc");
165944
+ if (existsSync21(npmrcPath)) {
165353
165945
  try {
165354
165946
  const npmrc = readFileSync14(npmrcPath, "utf-8");
165355
165947
  for (const line of npmrc.split(`
@@ -165375,7 +165967,7 @@ async function runDoctor(options = {}) {
165375
165967
  }
165376
165968
  }
165377
165969
  const logPath = getMagicContextLogPath2("opencode");
165378
- if (existsSync20(logPath)) {
165970
+ if (existsSync21(logPath)) {
165379
165971
  const logStat = statSync5(logPath);
165380
165972
  const sizeKb = (logStat.size / 1024).toFixed(0);
165381
165973
  log.info(`Log file: ${logPath} (${sizeKb} KB)`);
@@ -165447,44 +166039,44 @@ var init_doctor_opencode = __esm(async () => {
165447
166039
  });
165448
166040
 
165449
166041
  // ../pi-plugin/src/config/index.ts
165450
- import { existsSync as existsSync21, readFileSync as readFileSync15 } from "node:fs";
165451
- import { homedir as homedir14 } from "node:os";
165452
- import { join as join19 } from "node:path";
166042
+ import { existsSync as existsSync22, readFileSync as readFileSync15 } from "node:fs";
166043
+ import { homedir as homedir15 } from "node:os";
166044
+ import { join as join20 } from "node:path";
165453
166045
  function getProjectConfigPaths(cwd) {
165454
- const basePath = join19(cwd, ".pi", CONFIG_FILE_NAME);
166046
+ const basePath = join20(cwd, ".pi", CONFIG_FILE_NAME);
165455
166047
  return [`${basePath}.jsonc`, `${basePath}.json`];
165456
166048
  }
165457
166049
  function getUserConfigPaths() {
165458
- const home = process.env.HOME ?? homedir14();
165459
- const basePath = join19(home, ".pi", "agent", CONFIG_FILE_NAME);
166050
+ const home = process.env.HOME ?? homedir15();
166051
+ const basePath = join20(home, ".pi", "agent", CONFIG_FILE_NAME);
165460
166052
  return [`${basePath}.jsonc`, `${basePath}.json`];
165461
166053
  }
165462
166054
  function resolveFirstExisting(paths) {
165463
- return paths.find((path5) => existsSync21(path5));
166055
+ return paths.find((path6) => existsSync22(path6));
165464
166056
  }
165465
- function loadConfigFile2(path5, scope) {
166057
+ function loadConfigFile2(path6, scope) {
165466
166058
  try {
165467
- const rawText = readFileSync15(path5, "utf-8");
166059
+ const rawText = readFileSync15(path6, "utf-8");
165468
166060
  const substituted = substituteConfigVariables({
165469
166061
  text: rawText,
165470
- configPath: path5,
166062
+ configPath: path6,
165471
166063
  isProjectConfig: scope === "project"
165472
166064
  });
165473
166065
  return {
165474
- path: path5,
166066
+ path: path6,
165475
166067
  scope,
165476
166068
  config: import_comment_json10.parse(substituted.text),
165477
- warnings: substituted.warnings.map((warning) => `${path5}: ${warning}`),
166069
+ warnings: substituted.warnings.map((warning) => `${path6}: ${warning}`),
165478
166070
  loadOutcome: substituted.warnings.length > 0 ? "substitution-failure" : "ok"
165479
166071
  };
165480
166072
  } catch (error51) {
165481
166073
  const message = error51 instanceof Error ? error51.message : String(error51);
165482
166074
  return {
165483
- path: path5,
166075
+ path: path6,
165484
166076
  scope,
165485
166077
  config: {},
165486
166078
  warnings: [
165487
- `${path5}: failed to load config: ${message}; using defaults for this file.`
166079
+ `${path6}: failed to load config: ${message}; using defaults for this file.`
165488
166080
  ],
165489
166081
  loadOutcome: typeof error51.code === "string" ? "project-file-io-error" : "project-file-parse-error"
165490
166082
  };
@@ -165640,10 +166232,10 @@ var init_config2 = __esm(() => {
165640
166232
 
165641
166233
  // src/lib/diagnostics-pi.ts
165642
166234
  import { createHash as createHash3 } from "node:crypto";
165643
- import { existsSync as existsSync22, readdirSync as readdirSync3, readFileSync as readFileSync16, statSync as statSync6 } from "node:fs";
166235
+ import { existsSync as existsSync23, readdirSync as readdirSync3, readFileSync as readFileSync16, statSync as statSync6 } from "node:fs";
165644
166236
  import { createRequire as createRequire5 } from "node:module";
165645
- import { homedir as homedir15, userInfo as userInfo2 } from "node:os";
165646
- import { join as join20 } from "node:path";
166237
+ import { homedir as homedir16, userInfo as userInfo2 } from "node:os";
166238
+ import { join as join21 } from "node:path";
165647
166239
  function getSelfVersion3() {
165648
166240
  const req = createRequire5(import.meta.url);
165649
166241
  for (const relPath of ["../../package.json", "../package.json"]) {
@@ -165656,9 +166248,9 @@ function getSelfVersion3() {
165656
166248
  }
165657
166249
  return "unknown";
165658
166250
  }
165659
- function fileSize2(path5) {
166251
+ function fileSize2(path6) {
165660
166252
  try {
165661
- return existsSync22(path5) ? statSync6(path5).size : 0;
166253
+ return existsSync23(path6) ? statSync6(path6).size : 0;
165662
166254
  } catch {
165663
166255
  return 0;
165664
166256
  }
@@ -165674,7 +166266,7 @@ function redactSecretString(value) {
165674
166266
  return value.replace(/Bearer\s+[A-Za-z0-9._~+\-/=]+/g, "Bearer <REDACTED>").replace(/sk-[A-Za-z0-9_-]{12,}/g, "sk-<REDACTED>").replace(/api[_-]?key=([^\s&]+)/gi, "api_key=<REDACTED>").replace(/token=([^\s&]+)/gi, "token=<REDACTED>");
165675
166267
  }
165676
166268
  function sanitizeString2(value) {
165677
- const home = process.env.HOME || homedir15();
166269
+ const home = process.env.HOME || homedir16();
165678
166270
  const username = userInfo2().username;
165679
166271
  const userHash = `<USER:${currentUserHash()}>`;
165680
166272
  let sanitized = redactSecretString(value);
@@ -165707,12 +166299,12 @@ function sanitizeValue2(value, key = "") {
165707
166299
  }
165708
166300
  return value;
165709
166301
  }
165710
- function readJsonc3(path5) {
165711
- if (!existsSync22(path5))
166302
+ function readJsonc3(path6) {
166303
+ if (!existsSync23(path6))
165712
166304
  return { value: {} };
165713
166305
  try {
165714
166306
  return {
165715
- value: import_comment_json11.parse(readFileSync16(path5, "utf-8"))
166307
+ value: import_comment_json11.parse(readFileSync16(path6, "utf-8"))
165716
166308
  };
165717
166309
  } catch (error51) {
165718
166310
  return {
@@ -165722,13 +166314,13 @@ function readJsonc3(path5) {
165722
166314
  }
165723
166315
  }
165724
166316
  function getProjectConfigPath(cwd) {
165725
- return join20(cwd, ".pi", "magic-context.jsonc");
166317
+ return join21(cwd, ".pi", "magic-context.jsonc");
165726
166318
  }
165727
- function readConfigDiagnostic(path5) {
165728
- const parsed = readJsonc3(path5);
166319
+ function readConfigDiagnostic(path6) {
166320
+ const parsed = readJsonc3(path6);
165729
166321
  return {
165730
- path: path5,
165731
- exists: existsSync22(path5),
166322
+ path: path6,
166323
+ exists: existsSync23(path6),
165732
166324
  ...parsed.parseError ? { parseError: parsed.parseError } : {},
165733
166325
  flags: sanitizeValue2(parsed.value)
165734
166326
  };
@@ -165745,8 +166337,8 @@ function reverseSlugToDirectory(slug) {
165745
166337
  return `/${inner.replace(/-/g, "/")}`;
165746
166338
  }
165747
166339
  function collectPiRecentSessions() {
165748
- const sessionsRoot = join20(homedir15(), ".pi", "agent", "sessions");
165749
- if (!existsSync22(sessionsRoot))
166340
+ const sessionsRoot = join21(homedir16(), ".pi", "agent", "sessions");
166341
+ if (!existsSync23(sessionsRoot))
165750
166342
  return [];
165751
166343
  try {
165752
166344
  const slugs = readdirSync3(sessionsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
@@ -165755,7 +166347,7 @@ function collectPiRecentSessions() {
165755
166347
  const directory = reverseSlugToDirectory(slug);
165756
166348
  if (!directory)
165757
166349
  continue;
165758
- const slugDir = join20(sessionsRoot, slug);
166350
+ const slugDir = join21(sessionsRoot, slug);
165759
166351
  let files;
165760
166352
  try {
165761
166353
  files = readdirSync3(slugDir).filter((name2) => name2.endsWith(".jsonl"));
@@ -165764,7 +166356,7 @@ function collectPiRecentSessions() {
165764
166356
  }
165765
166357
  for (const file2 of files) {
165766
166358
  try {
165767
- const mtime = statSync6(join20(slugDir, file2)).mtimeMs;
166359
+ const mtime = statSync6(join21(slugDir, file2)).mtimeMs;
165768
166360
  const sessionId = file2.replace(/\.jsonl$/, "");
165769
166361
  candidates.push({ sessionId, directory, mtime });
165770
166362
  } catch {}
@@ -165780,9 +166372,9 @@ function collectPiRecentSessions() {
165780
166372
  return [];
165781
166373
  }
165782
166374
  }
165783
- function parseHistorianDumpMeta2(path5) {
166375
+ function parseHistorianDumpMeta2(path6) {
165784
166376
  try {
165785
- const xml = readFileSync16(path5, "utf-8");
166377
+ const xml = readFileSync16(path6, "utf-8");
165786
166378
  const parsed = parseCompartmentOutput(xml);
165787
166379
  const factCountByCategory = {};
165788
166380
  for (const fact of parsed.facts) {
@@ -165815,11 +166407,11 @@ function parseHistorianDumpMeta2(path5) {
165815
166407
  }
165816
166408
  }
165817
166409
  function listDumpsInDir2(dir, limit) {
165818
- if (!existsSync22(dir))
166410
+ if (!existsSync23(dir))
165819
166411
  return { count: 0, recent: [] };
165820
166412
  try {
165821
166413
  const entries = readdirSync3(dir).filter((name2) => name2.endsWith(".xml")).map((name2) => {
165822
- const stat = statSync6(join20(dir, name2));
166414
+ const stat = statSync6(join21(dir, name2));
165823
166415
  return {
165824
166416
  name: name2,
165825
166417
  mtime: stat.mtimeMs,
@@ -165828,7 +166420,7 @@ function listDumpsInDir2(dir, limit) {
165828
166420
  }).sort((a, b2) => b2.mtime - a.mtime);
165829
166421
  const now = Date.now();
165830
166422
  const recent = entries.slice(0, limit).map((entry) => {
165831
- const meta3 = parseHistorianDumpMeta2(join20(dir, entry.name));
166423
+ const meta3 = parseHistorianDumpMeta2(join21(dir, entry.name));
165832
166424
  const summary = {
165833
166425
  name: entry.name,
165834
166426
  ageMinutes: Math.round((now - entry.mtime) / 60000),
@@ -165891,9 +166483,9 @@ async function collectDiagnostics2(cwd = process.cwd()) {
165891
166483
  const projectConfigPath = getProjectConfigPath(cwd);
165892
166484
  const loaded = loadPiConfig({ cwd });
165893
166485
  const storageDirPath = getMagicContextStorageDir();
165894
- const dbPath = join20(storageDirPath, "context.db");
166486
+ const dbPath = join21(storageDirPath, "context.db");
165895
166487
  const logPath = getMagicContextLogPath2("pi");
165896
- const logFileSize = existsSync22(logPath) ? statSync6(logPath).size : 0;
166488
+ const logFileSize = existsSync23(logPath) ? statSync6(logPath).size : 0;
165897
166489
  const otherPiExtensions = packages.filter((entry) => !isPiMagicContextPackageEntry(entry)).map(describePiPackageEntry);
165898
166490
  const recentSessions = collectPiRecentSessions();
165899
166491
  const historianDumps = collectPiHistorianDumps(recentSessions);
@@ -165908,7 +166500,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
165908
166500
  piVersion: pi ? getPiVersion(pi.path) : null,
165909
166501
  settings: {
165910
166502
  path: settingsPath,
165911
- exists: existsSync22(settingsPath),
166503
+ exists: existsSync23(settingsPath),
165912
166504
  ...settingsParsed.parseError ? { parseError: settingsParsed.parseError } : {},
165913
166505
  hasMagicContextPackage: hasPiMagicContextPackage(packages),
165914
166506
  packages: sanitizeValue2(packages)
@@ -165924,7 +166516,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
165924
166516
  loadWarnings: loaded.warnings.map(sanitizeString2),
165925
166517
  storageDir: {
165926
166518
  path: storageDirPath,
165927
- exists: existsSync22(storageDirPath),
166519
+ exists: existsSync23(storageDirPath),
165928
166520
  contextDbSizeBytes: fileSize2(dbPath)
165929
166521
  },
165930
166522
  conflicts: {
@@ -165933,7 +166525,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
165933
166525
  },
165934
166526
  logFile: {
165935
166527
  path: logPath,
165936
- exists: existsSync22(logPath),
166528
+ exists: existsSync23(logPath),
165937
166529
  sizeKb: Math.round(logFileSize / 1024)
165938
166530
  },
165939
166531
  recentSessions,
@@ -165989,7 +166581,7 @@ function renderDiagnosticsMarkdown2(report) {
165989
166581
  "```",
165990
166582
  "",
165991
166583
  "### Loaded config paths",
165992
- report.loadedConfigPaths.length === 0 ? "_No config files loaded; defaults are in use._" : report.loadedConfigPaths.map((path5) => `- ${path5}`).join(`
166584
+ report.loadedConfigPaths.length === 0 ? "_No config files loaded; defaults are in use._" : report.loadedConfigPaths.map((path6) => `- ${path6}`).join(`
165993
166585
  `),
165994
166586
  "",
165995
166587
  "### Config load warnings",
@@ -166027,7 +166619,7 @@ var init_diagnostics_pi = __esm(() => {
166027
166619
 
166028
166620
  // src/lib/logs-pi.ts
166029
166621
  import { readFileSync as readFileSync17, writeFileSync as writeFileSync10 } from "node:fs";
166030
- import { join as join21 } from "node:path";
166622
+ import { join as join22 } from "node:path";
166031
166623
  function sanitizeLogContent2(content) {
166032
166624
  return sanitizeString2(content);
166033
166625
  }
@@ -166092,10 +166684,10 @@ async function bundleIssueReport2(report, description, title, options = {}) {
166092
166684
  `);
166093
166685
  const bodyMarkdown = capBodyToGithubLimit(rawBodyMarkdown);
166094
166686
  const cwd = options.cwd ?? process.cwd();
166095
- const path5 = join21(cwd, `magic-context-pi-issue-${formatTimestamp2(options.now ?? new Date)}.md`);
166096
- writeFileSync10(path5, `${bodyMarkdown}
166687
+ const path6 = join22(cwd, `magic-context-pi-issue-${formatTimestamp2(options.now ?? new Date)}.md`);
166688
+ writeFileSync10(path6, `${bodyMarkdown}
166097
166689
  `);
166098
- return { path: path5, bodyMarkdown };
166690
+ return { path: path6, bodyMarkdown };
166099
166691
  }
166100
166692
  var init_logs_pi = __esm(() => {
166101
166693
  init_diagnostics_pi();
@@ -166105,7 +166697,7 @@ var init_logs_pi = __esm(() => {
166105
166697
  // src/commands/doctor-pi.ts
166106
166698
  import { execFileSync as execFileSync4, spawnSync as spawnSync3 } from "node:child_process";
166107
166699
  import {
166108
- existsSync as existsSync23,
166700
+ existsSync as existsSync24,
166109
166701
  mkdirSync as mkdirSync7,
166110
166702
  readdirSync as readdirSync4,
166111
166703
  readFileSync as readFileSync18,
@@ -166114,8 +166706,8 @@ import {
166114
166706
  writeFileSync as writeFileSync11
166115
166707
  } from "node:fs";
166116
166708
  import { createRequire as createRequire6 } from "node:module";
166117
- import { homedir as homedir16 } from "node:os";
166118
- import { dirname as dirname10, isAbsolute as isAbsolute3, join as join22 } from "node:path";
166709
+ import { homedir as homedir17 } from "node:os";
166710
+ import { dirname as dirname10, isAbsolute as isAbsolute3, join as join23 } from "node:path";
166119
166711
  function depsFrom(options) {
166120
166712
  return {
166121
166713
  ...DEFAULT_DEPS,
@@ -166202,10 +166794,10 @@ function summarize(results) {
166202
166794
  fail: results.filter((result) => result.status === "fail").length
166203
166795
  };
166204
166796
  }
166205
- function readJsonc4(path5) {
166797
+ function readJsonc4(path6) {
166206
166798
  try {
166207
166799
  return {
166208
- value: import_comment_json12.parse(readFileSync18(path5, "utf-8"))
166800
+ value: import_comment_json12.parse(readFileSync18(path6, "utf-8"))
166209
166801
  };
166210
166802
  } catch (error51) {
166211
166803
  return {
@@ -166224,24 +166816,24 @@ function piPluginDirCandidates(packages, cwd) {
166224
166816
  const spec = typeof entry === "string" ? entry.trim() : "";
166225
166817
  if (!spec || spec.startsWith("npm:"))
166226
166818
  continue;
166227
- const resolved = isAbsolute3(spec) ? spec : join22(agentDir, spec);
166819
+ const resolved = isAbsolute3(spec) ? spec : join23(agentDir, spec);
166228
166820
  dirs.push(resolved);
166229
166821
  }
166230
- dirs.push(join22(agentDir, "npm", "node_modules", PACKAGE_NAME));
166231
- dirs.push(join22(cwd, ".pi", "npm", "node_modules", PACKAGE_NAME));
166232
- return dirs.filter((dir) => existsSync23(join22(dir, "package.json")));
166822
+ dirs.push(join23(agentDir, "npm", "node_modules", PACKAGE_NAME));
166823
+ dirs.push(join23(cwd, ".pi", "npm", "node_modules", PACKAGE_NAME));
166824
+ return dirs.filter((dir) => existsSync24(join23(dir, "package.json")));
166233
166825
  }
166234
166826
  function projectConfigPath(cwd) {
166235
- return join22(cwd, ".pi", "magic-context.jsonc");
166827
+ return join23(cwd, ".pi", "magic-context.jsonc");
166236
166828
  }
166237
- function readConfigForEmbedding(path5) {
166238
- if (!existsSync23(path5))
166829
+ function readConfigForEmbedding(path6) {
166830
+ if (!existsSync24(path6))
166239
166831
  return null;
166240
166832
  try {
166241
- const rawText = readFileSync18(path5, "utf-8");
166833
+ const rawText = readFileSync18(path6, "utf-8");
166242
166834
  const substituted = substituteConfigVariables({
166243
166835
  text: rawText,
166244
- configPath: path5
166836
+ configPath: path6
166245
166837
  });
166246
166838
  return import_comment_json12.parse(substituted.text);
166247
166839
  } catch {
@@ -166296,52 +166888,52 @@ function countTable(db, table) {
166296
166888
  }
166297
166889
  }
166298
166890
  function cacheRoots() {
166299
- const home = homedir16();
166300
- const cacheHome = process.env.XDG_CACHE_HOME || join22(home, ".cache");
166891
+ const home = homedir17();
166892
+ const cacheHome = process.env.XDG_CACHE_HOME || join23(home, ".cache");
166301
166893
  return [
166302
- join22(home, ".pi", "cache", "extensions"),
166303
- join22(home, ".pi", "cache", "packages"),
166304
- join22(cacheHome, "pi", "extensions"),
166305
- join22(cacheHome, "pi", "packages"),
166306
- join22(getPiAgentConfigDir(), "cache", "extensions")
166894
+ join23(home, ".pi", "cache", "extensions"),
166895
+ join23(home, ".pi", "cache", "packages"),
166896
+ join23(cacheHome, "pi", "extensions"),
166897
+ join23(cacheHome, "pi", "packages"),
166898
+ join23(getPiAgentConfigDir(), "cache", "extensions")
166307
166899
  ];
166308
166900
  }
166309
166901
  function findPiMagicContextCacheDirs(self, force = false) {
166310
166902
  const found = new Map;
166311
- const visit = (path5, depth) => {
166312
- if (depth < 0 || !existsSync23(path5))
166903
+ const visit = (path6, depth) => {
166904
+ if (depth < 0 || !existsSync24(path6))
166313
166905
  return;
166314
166906
  let stat;
166315
166907
  try {
166316
- stat = statSync7(path5);
166908
+ stat = statSync7(path6);
166317
166909
  } catch {
166318
166910
  return;
166319
166911
  }
166320
166912
  if (!stat.isDirectory())
166321
166913
  return;
166322
- const packageJson = join22(path5, "package.json");
166323
- if (existsSync23(packageJson)) {
166914
+ const packageJson = join23(path6, "package.json");
166915
+ if (existsSync24(packageJson)) {
166324
166916
  try {
166325
166917
  const pkg = JSON.parse(readFileSync18(packageJson, "utf-8"));
166326
166918
  const name2 = typeof pkg.name === "string" ? pkg.name : "";
166327
166919
  const version2 = typeof pkg.version === "string" ? pkg.version : undefined;
166328
- if (name2 === PACKAGE_NAME || path5.includes("pi-magic-context")) {
166920
+ if (name2 === PACKAGE_NAME || path6.includes("pi-magic-context")) {
166329
166921
  if (force || !version2 || version2 !== self)
166330
- found.set(path5, { path: path5, version: version2 });
166922
+ found.set(path6, { path: path6, version: version2 });
166331
166923
  }
166332
166924
  } catch {
166333
- if (path5.includes("pi-magic-context"))
166334
- found.set(path5, { path: path5 });
166925
+ if (path6.includes("pi-magic-context"))
166926
+ found.set(path6, { path: path6 });
166335
166927
  }
166336
166928
  }
166337
166929
  let entries = [];
166338
166930
  try {
166339
- entries = readdirSync4(path5);
166931
+ entries = readdirSync4(path6);
166340
166932
  } catch {
166341
166933
  return;
166342
166934
  }
166343
166935
  for (const entry of entries)
166344
- visit(join22(path5, entry), depth - 1);
166936
+ visit(join23(path6, entry), depth - 1);
166345
166937
  };
166346
166938
  for (const root of cacheRoots())
166347
166939
  visit(root, 5);
@@ -166378,7 +166970,7 @@ async function runHealthChecks(options) {
166378
166970
  }
166379
166971
  const settingsPath = getPiUserExtensionsPath();
166380
166972
  let packages = [];
166381
- if (!existsSync23(settingsPath)) {
166973
+ if (!existsSync24(settingsPath)) {
166382
166974
  add(results, "warn", `Pi settings not found at ${settingsPath}`);
166383
166975
  repairPlan.addPackageEntry = true;
166384
166976
  } else {
@@ -166398,24 +166990,24 @@ async function runHealthChecks(options) {
166398
166990
  }
166399
166991
  const userConfigPath = getPiUserConfigPath();
166400
166992
  const projectPath = projectConfigPath(options.cwd);
166401
- for (const [label, path5, required2] of [
166993
+ for (const [label, path6, required2] of [
166402
166994
  ["user", userConfigPath, true],
166403
166995
  ["project", projectPath, false]
166404
166996
  ]) {
166405
- if (!existsSync23(path5)) {
166997
+ if (!existsSync24(path6)) {
166406
166998
  if (required2) {
166407
- add(results, "warn", `No ${label} magic-context.jsonc found at ${path5}`);
166999
+ add(results, "warn", `No ${label} magic-context.jsonc found at ${path6}`);
166408
167000
  repairPlan.writeUserConfig = true;
166409
167001
  } else {
166410
- add(results, "info", `No project Pi magic-context.jsonc found at ${path5}`);
167002
+ add(results, "info", `No project Pi magic-context.jsonc found at ${path6}`);
166411
167003
  }
166412
167004
  continue;
166413
167005
  }
166414
- const parsed = readJsonc4(path5);
167006
+ const parsed = readJsonc4(path6);
166415
167007
  if (parsed.error)
166416
167008
  add(results, "fail", `${label} magic-context.jsonc is invalid JSONC: ${parsed.error}`);
166417
167009
  else
166418
- add(results, "pass", `${label} magic-context.jsonc is valid JSONC: ${path5}`);
167010
+ add(results, "pass", `${label} magic-context.jsonc is valid JSONC: ${path6}`);
166419
167011
  }
166420
167012
  const loadedConfig = loadPiConfig({ cwd: options.cwd });
166421
167013
  if (loadedConfig.warnings.length > 0) {
@@ -166435,8 +167027,8 @@ async function runHealthChecks(options) {
166435
167027
  add(results, "pass", `historian.model "${historianModel}" has thinking_level "${historianThinkingLevel}" configured`);
166436
167028
  }
166437
167029
  const storageDir = getMagicContextStorageDir();
166438
- const dbPath = join22(storageDir, "context.db");
166439
- const existedBeforeOpen = existsSync23(dbPath);
167030
+ const dbPath = join23(storageDir, "context.db");
167031
+ const existedBeforeOpen = existsSync24(dbPath);
166440
167032
  if (existedBeforeOpen)
166441
167033
  add(results, "pass", `Shared context DB exists at ${dbPath}`);
166442
167034
  else
@@ -166537,7 +167129,7 @@ async function runHealthChecks(options) {
166537
167129
  add(results, "pass", "Pi extension cache clean (no stale cached package found)");
166538
167130
  }
166539
167131
  const logPath = getMagicContextLogPath2("pi");
166540
- if (existsSync23(logPath)) {
167132
+ if (existsSync24(logPath)) {
166541
167133
  const stat = statSync7(logPath);
166542
167134
  const sizeKb = (stat.size / 1024).toFixed(0);
166543
167135
  const lines = readFileSync18(logPath, "utf-8").split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
@@ -166573,13 +167165,13 @@ async function runHealthChecks(options) {
166573
167165
  }
166574
167166
  return { results, repairPlan, ...summarize(results) };
166575
167167
  }
166576
- function writeDefaultMagicContextConfig(path5) {
166577
- mkdirSync7(dirname10(path5), { recursive: true });
167168
+ function writeDefaultMagicContextConfig(path6) {
167169
+ mkdirSync7(dirname10(path6), { recursive: true });
166578
167170
  const config2 = {
166579
167171
  $schema: "https://raw.githubusercontent.com/cortexkit/magic-context/master/assets/magic-context.schema.json",
166580
167172
  ...MagicContextConfigSchema.parse({})
166581
167173
  };
166582
- writeFileSync11(path5, `${import_comment_json12.stringify(config2, null, 2)}
167174
+ writeFileSync11(path6, `${import_comment_json12.stringify(config2, null, 2)}
166583
167175
  `);
166584
167176
  }
166585
167177
  function repair(plan, prompts) {
@@ -166596,7 +167188,7 @@ function repair(plan, prompts) {
166596
167188
  }
166597
167189
  if (plan.writeUserConfig) {
166598
167190
  const configPath = getPiUserConfigPath();
166599
- if (!existsSync23(configPath)) {
167191
+ if (!existsSync24(configPath)) {
166600
167192
  try {
166601
167193
  writeDefaultMagicContextConfig(configPath);
166602
167194
  prompts.log.success(`Wrote default Magic Context config to ${configPath}`);
@@ -166606,13 +167198,13 @@ function repair(plan, prompts) {
166606
167198
  }
166607
167199
  }
166608
167200
  }
166609
- for (const path5 of plan.clearCachePaths) {
167201
+ for (const path6 of plan.clearCachePaths) {
166610
167202
  try {
166611
- rmSync2(path5, { recursive: true, force: true });
166612
- prompts.log.success(`Cleared stale Pi extension cache: ${path5}`);
167203
+ rmSync2(path6, { recursive: true, force: true });
167204
+ prompts.log.success(`Cleared stale Pi extension cache: ${path6}`);
166613
167205
  fixed += 1;
166614
167206
  } catch (error51) {
166615
- console.error(`FAIL Could not clear ${path5}: ${error51 instanceof Error ? error51.message : String(error51)}`);
167207
+ console.error(`FAIL Could not clear ${path6}: ${error51 instanceof Error ? error51.message : String(error51)}`);
166616
167208
  }
166617
167209
  }
166618
167210
  return fixed;
@@ -166737,7 +167329,7 @@ async function runDoctor2(options = {}) {
166737
167329
  prompts.outro(first.fail > 0 ? "Doctor found failures" : "Doctor complete");
166738
167330
  return first.fail > 0 ? 1 : 0;
166739
167331
  }
166740
- function valueAfter(args, flag) {
167332
+ function valueAfter2(args, flag) {
166741
167333
  const index = args.indexOf(flag);
166742
167334
  if (index === -1)
166743
167335
  return null;
@@ -166747,7 +167339,7 @@ function valueAfter(args, flag) {
166747
167339
  return next;
166748
167340
  }
166749
167341
  function parseDoctorArgs(args) {
166750
- const rekeyV22DirIdentity = valueAfter(args, "--rekey-v22-dir-identity");
167342
+ const rekeyV22DirIdentity = valueAfter2(args, "--rekey-v22-dir-identity");
166751
167343
  return {
166752
167344
  force: args.includes("--force"),
166753
167345
  issue: args.includes("--issue"),
@@ -166799,7 +167391,7 @@ var exports_doctor = {};
166799
167391
  __export(exports_doctor, {
166800
167392
  runDoctor: () => runDoctor3
166801
167393
  });
166802
- import { existsSync as existsSync24, rmSync as rmSync3 } from "node:fs";
167394
+ import { existsSync as existsSync25, rmSync as rmSync3 } from "node:fs";
166803
167395
  async function runDoctor3(options) {
166804
167396
  if (options.clear)
166805
167397
  return runClear();
@@ -166888,7 +167480,7 @@ async function runClear() {
166888
167480
  const s = spinner();
166889
167481
  s.start(`Clearing ${item.path}`);
166890
167482
  try {
166891
- if (existsSync24(item.path)) {
167483
+ if (existsSync25(item.path)) {
166892
167484
  rmSync3(item.path, { recursive: true, force: true });
166893
167485
  }
166894
167486
  s.stop(`Cleared ${item.path}`);
@@ -166936,7 +167528,7 @@ function getVersion() {
166936
167528
  }
166937
167529
  return "0.0.0";
166938
167530
  }
166939
- function valueAfter2(args, flag) {
167531
+ function valueAfter3(args, flag) {
166940
167532
  const index = args.indexOf(flag);
166941
167533
  if (index === -1)
166942
167534
  return null;
@@ -166960,6 +167552,7 @@ function printUsage() {
166960
167552
  console.log(" doctor --retry-v22-backfill Retry failed v22 memory backfill rows");
166961
167553
  console.log(" doctor --rekey-v22-dir-identity <path> Re-key legacy dir identity rows");
166962
167554
  console.log(" doctor migrate Migrate OpenCode session to Pi JSONL");
167555
+ console.log(" doctor migrate-session Re-home an OpenCode session to another directory");
166963
167556
  console.log("");
166964
167557
  console.log(" Harness selection:");
166965
167558
  console.log(" --harness opencode Target OpenCode only");
@@ -166995,8 +167588,12 @@ async function main(argv = process.argv.slice(2)) {
166995
167588
  const { runMigrateCli: runMigrateCli2 } = await init_migrate().then(() => exports_migrate);
166996
167589
  return runMigrateCli2(rest.slice(1));
166997
167590
  }
167591
+ if (rest[0] === "migrate-session") {
167592
+ const { runMigrateSessionCli: runMigrateSessionCli2 } = await init_migrate_session().then(() => exports_migrate_session);
167593
+ return runMigrateSessionCli2(rest.slice(1));
167594
+ }
166998
167595
  const { runDoctor: runDoctor4 } = await init_doctor().then(() => exports_doctor);
166999
- const rekeyV22DirIdentity = valueAfter2(rest, "--rekey-v22-dir-identity");
167596
+ const rekeyV22DirIdentity = valueAfter3(rest, "--rekey-v22-dir-identity");
167000
167597
  return runDoctor4({
167001
167598
  force: rest.includes("--force"),
167002
167599
  issue: rest.includes("--issue"),