@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.
- package/dist/index.js +1046 -449
- 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
|
|
12882
|
+
import * as path4 from "node:path";
|
|
12267
12883
|
function ensureDir5(filePath) {
|
|
12268
|
-
const dir =
|
|
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
|
|
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 (
|
|
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
|
|
144974
|
-
import { join as
|
|
145590
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
145591
|
+
import { join as join11 } from "node:path";
|
|
144975
145592
|
function resolveOpencodeDbPath() {
|
|
144976
|
-
return
|
|
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 (!
|
|
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
|
|
145235
|
-
import { dirname as dirname6, join as
|
|
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 =
|
|
145243
|
-
return { dbDir: dbDir2, dbPath:
|
|
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:
|
|
145863
|
+
return { dbDir, dbPath: join12(dbDir, "context.db") };
|
|
145247
145864
|
}
|
|
145248
145865
|
function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
145249
|
-
if (
|
|
145866
|
+
if (existsSync14(targetDbPath))
|
|
145250
145867
|
return;
|
|
145251
145868
|
const legacyDir = getLegacyOpenCodeMagicContextStorageDir();
|
|
145252
|
-
const legacyDbPath =
|
|
145253
|
-
if (!
|
|
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 =
|
|
145270
|
-
if (
|
|
145886
|
+
const dst = join12(targetDbDir, `context.db${suffix}`);
|
|
145887
|
+
if (existsSync14(src)) {
|
|
145271
145888
|
try {
|
|
145272
|
-
|
|
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 =
|
|
145279
|
-
const targetModelsDir =
|
|
145280
|
-
if (
|
|
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 =
|
|
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
|
|
147671
|
-
import
|
|
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 =
|
|
148241
|
+
canonical = realpathSync3(rawProjectPath);
|
|
147712
148242
|
} catch {
|
|
147713
|
-
canonical =
|
|
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,
|
|
148380
|
-
if (!
|
|
148892
|
+
function getElementAtPath(obj, path6) {
|
|
148893
|
+
if (!path6)
|
|
148381
148894
|
return obj;
|
|
148382
|
-
return
|
|
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(
|
|
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(
|
|
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,
|
|
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 }, [...
|
|
149443
|
+
issue2.errors.map((issues) => processError({ issues }, [...path6, ...issue2.path]));
|
|
148931
149444
|
} else if (issue2.code === "invalid_key") {
|
|
148932
|
-
processError({ issues: issue2.issues }, [...
|
|
149445
|
+
processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
|
|
148933
149446
|
} else if (issue2.code === "invalid_element") {
|
|
148934
|
-
processError({ issues: issue2.issues }, [...
|
|
149447
|
+
processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
|
|
148935
149448
|
} else {
|
|
148936
|
-
const fullpath = [...
|
|
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,
|
|
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 }, [...
|
|
149480
|
+
issue2.errors.map((issues) => processError({ issues }, [...path6, ...issue2.path]));
|
|
148968
149481
|
} else if (issue2.code === "invalid_key") {
|
|
148969
|
-
processError({ issues: issue2.issues }, [...
|
|
149482
|
+
processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
|
|
148970
149483
|
} else if (issue2.code === "invalid_element") {
|
|
148971
|
-
processError({ issues: issue2.issues }, [...
|
|
149484
|
+
processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
|
|
148972
149485
|
} else {
|
|
148973
|
-
const fullpath = [...
|
|
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
|
|
149006
|
-
for (const seg of
|
|
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
|
|
162010
|
-
if (
|
|
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 (
|
|
162015
|
-
const key =
|
|
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("
|
|
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
|
|
162966
|
-
import { homedir as
|
|
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 =
|
|
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(
|
|
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 (!
|
|
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
|
|
163066
|
-
import { homedir as
|
|
163067
|
-
import { join as
|
|
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 ??
|
|
163070
|
-
return
|
|
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
|
|
163590
|
+
return join13(directory, ".opencode", CONFIG_FILE_BASENAME);
|
|
163074
163591
|
}
|
|
163075
163592
|
function loadConfigFile(configPath, isProjectConfig = false) {
|
|
163076
163593
|
try {
|
|
163077
|
-
if (!
|
|
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(
|
|
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
|
|
163270
|
-
import { homedir as
|
|
163271
|
-
import { isAbsolute as isAbsolute2, join as
|
|
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(
|
|
163274
|
-
if (!
|
|
163790
|
+
function parseConfig(path6) {
|
|
163791
|
+
if (!existsSync17(path6))
|
|
163275
163792
|
return null;
|
|
163276
|
-
return import_comment_json6.parse(readFileSync10(
|
|
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 =
|
|
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(
|
|
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 ||
|
|
163843
|
+
const home = process.env.HOME || homedir10();
|
|
163327
163844
|
const opencodePaths = [
|
|
163328
|
-
|
|
163329
|
-
|
|
163845
|
+
join14(home, ".config", "opencode", "opencode.jsonc"),
|
|
163846
|
+
join14(home, ".config", "opencode", "opencode.json")
|
|
163330
163847
|
];
|
|
163331
|
-
const piPaths = [
|
|
163848
|
+
const piPaths = [join14(home, ".pi", "agent", "settings.json")];
|
|
163332
163849
|
const checkedPaths = [...opencodePaths, ...piPaths];
|
|
163333
163850
|
let opencode = false;
|
|
163334
|
-
for (const
|
|
163851
|
+
for (const path6 of opencodePaths) {
|
|
163335
163852
|
try {
|
|
163336
|
-
const config2 = parseConfig(
|
|
163337
|
-
const configDir =
|
|
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
|
|
163862
|
+
for (const path6 of piPaths) {
|
|
163346
163863
|
try {
|
|
163347
|
-
const config2 = parseConfig(
|
|
163348
|
-
const configDir =
|
|
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
|
|
163487
|
-
import { dirname as dirname8, join as
|
|
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 =
|
|
163502
|
-
const jsonPath =
|
|
163503
|
-
if (
|
|
164018
|
+
const jsoncPath = join15(configDir, "tui.jsonc");
|
|
164019
|
+
const jsonPath = join15(configDir, "tui.json");
|
|
164020
|
+
if (existsSync18(jsoncPath))
|
|
163504
164021
|
return jsoncPath;
|
|
163505
|
-
if (
|
|
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 (
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
163865
|
-
import { join as
|
|
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
|
|
164396
|
+
const path6 = join16(getOpenCodeCacheDir(), "packages", PLUGIN_ENTRY_WITH_VERSION);
|
|
163880
164397
|
let cached2;
|
|
163881
164398
|
try {
|
|
163882
|
-
const installedPkgPath =
|
|
163883
|
-
if (
|
|
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:
|
|
164407
|
+
return { path: path6, cached: cached2, latest: getSelfVersion() };
|
|
163891
164408
|
}
|
|
163892
164409
|
function getStorageDir() {
|
|
163893
|
-
const dataHome = process.env.XDG_DATA_HOME ||
|
|
163894
|
-
return
|
|
164410
|
+
const dataHome = process.env.XDG_DATA_HOME || join16(homedir12(), ".local", "share");
|
|
164411
|
+
return join16(dataHome, "cortexkit", "magic-context");
|
|
163895
164412
|
}
|
|
163896
|
-
function fileSize(
|
|
164413
|
+
function fileSize(path6) {
|
|
163897
164414
|
try {
|
|
163898
|
-
return
|
|
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(
|
|
163910
|
-
if (!
|
|
164426
|
+
function readConfig2(path6) {
|
|
164427
|
+
if (!existsSync19(path6))
|
|
163911
164428
|
return { value: null };
|
|
163912
164429
|
try {
|
|
163913
|
-
const raw = readFileSync12(
|
|
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(
|
|
164451
|
+
function parseHistorianDumpMeta(path6) {
|
|
163935
164452
|
try {
|
|
163936
|
-
const xml = readFileSync12(
|
|
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 (!
|
|
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(
|
|
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(
|
|
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 =
|
|
164038
|
-
if (!
|
|
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 =
|
|
164073
|
-
if (!
|
|
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 =
|
|
164693
|
+
const contextDbPath = join16(storageDirPath, "context.db");
|
|
164113
164694
|
const logPath = getMagicContextLogPath2("opencode");
|
|
164114
|
-
const logFileSize =
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
|
164867
|
+
import { existsSync as existsSync20 } from "node:fs";
|
|
164276
164868
|
import { createRequire as createRequire3 } from "node:module";
|
|
164277
|
-
import { dirname as dirname9, join as
|
|
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
|
|
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 =
|
|
164287
|
-
if (!
|
|
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 =
|
|
164295
|
-
if (!
|
|
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) =>
|
|
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 (!
|
|
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(
|
|
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(
|
|
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:
|
|
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 =
|
|
164360
|
-
if (!
|
|
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
|
|
164455
|
-
import { join as
|
|
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(
|
|
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
|
|
164546
|
-
writeFileSync8(
|
|
165137
|
+
const path6 = join18(process.cwd(), `magic-context-issue-${formatTimestamp(new Date)}.md`);
|
|
165138
|
+
writeFileSync8(path6, `${bodyMarkdown}
|
|
164547
165139
|
`);
|
|
164548
|
-
return { path:
|
|
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
|
|
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
|
|
164571
|
-
import { join as
|
|
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 =
|
|
164659
|
-
if (!
|
|
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 =
|
|
164665
|
-
if (
|
|
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
|
-
|
|
164800
|
-
|
|
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 (!
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 =
|
|
165290
|
-
if (!
|
|
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 =
|
|
165352
|
-
if (
|
|
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 (
|
|
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
|
|
165451
|
-
import { homedir as
|
|
165452
|
-
import { join as
|
|
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 =
|
|
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 ??
|
|
165459
|
-
const basePath =
|
|
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((
|
|
166055
|
+
return paths.find((path6) => existsSync22(path6));
|
|
165464
166056
|
}
|
|
165465
|
-
function loadConfigFile2(
|
|
166057
|
+
function loadConfigFile2(path6, scope) {
|
|
165466
166058
|
try {
|
|
165467
|
-
const rawText = readFileSync15(
|
|
166059
|
+
const rawText = readFileSync15(path6, "utf-8");
|
|
165468
166060
|
const substituted = substituteConfigVariables({
|
|
165469
166061
|
text: rawText,
|
|
165470
|
-
configPath:
|
|
166062
|
+
configPath: path6,
|
|
165471
166063
|
isProjectConfig: scope === "project"
|
|
165472
166064
|
});
|
|
165473
166065
|
return {
|
|
165474
|
-
path:
|
|
166066
|
+
path: path6,
|
|
165475
166067
|
scope,
|
|
165476
166068
|
config: import_comment_json10.parse(substituted.text),
|
|
165477
|
-
warnings: substituted.warnings.map((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:
|
|
166075
|
+
path: path6,
|
|
165484
166076
|
scope,
|
|
165485
166077
|
config: {},
|
|
165486
166078
|
warnings: [
|
|
165487
|
-
`${
|
|
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
|
|
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
|
|
165646
|
-
import { join as
|
|
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(
|
|
166251
|
+
function fileSize2(path6) {
|
|
165660
166252
|
try {
|
|
165661
|
-
return
|
|
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 ||
|
|
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(
|
|
165711
|
-
if (!
|
|
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(
|
|
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
|
|
166317
|
+
return join21(cwd, ".pi", "magic-context.jsonc");
|
|
165726
166318
|
}
|
|
165727
|
-
function readConfigDiagnostic(
|
|
165728
|
-
const parsed = readJsonc3(
|
|
166319
|
+
function readConfigDiagnostic(path6) {
|
|
166320
|
+
const parsed = readJsonc3(path6);
|
|
165729
166321
|
return {
|
|
165730
|
-
path:
|
|
165731
|
-
exists:
|
|
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 =
|
|
165749
|
-
if (!
|
|
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 =
|
|
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(
|
|
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(
|
|
166375
|
+
function parseHistorianDumpMeta2(path6) {
|
|
165784
166376
|
try {
|
|
165785
|
-
const xml = readFileSync16(
|
|
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 (!
|
|
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(
|
|
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(
|
|
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 =
|
|
166486
|
+
const dbPath = join21(storageDirPath, "context.db");
|
|
165895
166487
|
const logPath = getMagicContextLogPath2("pi");
|
|
165896
|
-
const logFileSize =
|
|
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:
|
|
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:
|
|
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:
|
|
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((
|
|
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
|
|
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
|
|
166096
|
-
writeFileSync10(
|
|
166687
|
+
const path6 = join22(cwd, `magic-context-pi-issue-${formatTimestamp2(options.now ?? new Date)}.md`);
|
|
166688
|
+
writeFileSync10(path6, `${bodyMarkdown}
|
|
166097
166689
|
`);
|
|
166098
|
-
return { path:
|
|
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
|
|
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
|
|
166118
|
-
import { dirname as dirname10, isAbsolute as isAbsolute3, join as
|
|
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(
|
|
166797
|
+
function readJsonc4(path6) {
|
|
166206
166798
|
try {
|
|
166207
166799
|
return {
|
|
166208
|
-
value: import_comment_json12.parse(readFileSync18(
|
|
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 :
|
|
166819
|
+
const resolved = isAbsolute3(spec) ? spec : join23(agentDir, spec);
|
|
166228
166820
|
dirs.push(resolved);
|
|
166229
166821
|
}
|
|
166230
|
-
dirs.push(
|
|
166231
|
-
dirs.push(
|
|
166232
|
-
return dirs.filter((dir) =>
|
|
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
|
|
166827
|
+
return join23(cwd, ".pi", "magic-context.jsonc");
|
|
166236
166828
|
}
|
|
166237
|
-
function readConfigForEmbedding(
|
|
166238
|
-
if (!
|
|
166829
|
+
function readConfigForEmbedding(path6) {
|
|
166830
|
+
if (!existsSync24(path6))
|
|
166239
166831
|
return null;
|
|
166240
166832
|
try {
|
|
166241
|
-
const rawText = readFileSync18(
|
|
166833
|
+
const rawText = readFileSync18(path6, "utf-8");
|
|
166242
166834
|
const substituted = substituteConfigVariables({
|
|
166243
166835
|
text: rawText,
|
|
166244
|
-
configPath:
|
|
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 =
|
|
166300
|
-
const cacheHome = process.env.XDG_CACHE_HOME ||
|
|
166891
|
+
const home = homedir17();
|
|
166892
|
+
const cacheHome = process.env.XDG_CACHE_HOME || join23(home, ".cache");
|
|
166301
166893
|
return [
|
|
166302
|
-
|
|
166303
|
-
|
|
166304
|
-
|
|
166305
|
-
|
|
166306
|
-
|
|
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 = (
|
|
166312
|
-
if (depth < 0 || !
|
|
166903
|
+
const visit = (path6, depth) => {
|
|
166904
|
+
if (depth < 0 || !existsSync24(path6))
|
|
166313
166905
|
return;
|
|
166314
166906
|
let stat;
|
|
166315
166907
|
try {
|
|
166316
|
-
stat = statSync7(
|
|
166908
|
+
stat = statSync7(path6);
|
|
166317
166909
|
} catch {
|
|
166318
166910
|
return;
|
|
166319
166911
|
}
|
|
166320
166912
|
if (!stat.isDirectory())
|
|
166321
166913
|
return;
|
|
166322
|
-
const packageJson =
|
|
166323
|
-
if (
|
|
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 ||
|
|
166920
|
+
if (name2 === PACKAGE_NAME || path6.includes("pi-magic-context")) {
|
|
166329
166921
|
if (force || !version2 || version2 !== self)
|
|
166330
|
-
found.set(
|
|
166922
|
+
found.set(path6, { path: path6, version: version2 });
|
|
166331
166923
|
}
|
|
166332
166924
|
} catch {
|
|
166333
|
-
if (
|
|
166334
|
-
found.set(
|
|
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(
|
|
166931
|
+
entries = readdirSync4(path6);
|
|
166340
166932
|
} catch {
|
|
166341
166933
|
return;
|
|
166342
166934
|
}
|
|
166343
166935
|
for (const entry of entries)
|
|
166344
|
-
visit(
|
|
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 (!
|
|
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,
|
|
166993
|
+
for (const [label, path6, required2] of [
|
|
166402
166994
|
["user", userConfigPath, true],
|
|
166403
166995
|
["project", projectPath, false]
|
|
166404
166996
|
]) {
|
|
166405
|
-
if (!
|
|
166997
|
+
if (!existsSync24(path6)) {
|
|
166406
166998
|
if (required2) {
|
|
166407
|
-
add(results, "warn", `No ${label} magic-context.jsonc found at ${
|
|
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 ${
|
|
167002
|
+
add(results, "info", `No project Pi magic-context.jsonc found at ${path6}`);
|
|
166411
167003
|
}
|
|
166412
167004
|
continue;
|
|
166413
167005
|
}
|
|
166414
|
-
const parsed = readJsonc4(
|
|
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: ${
|
|
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 =
|
|
166439
|
-
const existedBeforeOpen =
|
|
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 (
|
|
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(
|
|
166577
|
-
mkdirSync7(dirname10(
|
|
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(
|
|
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 (!
|
|
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
|
|
167201
|
+
for (const path6 of plan.clearCachePaths) {
|
|
166610
167202
|
try {
|
|
166611
|
-
rmSync2(
|
|
166612
|
-
prompts.log.success(`Cleared stale Pi extension cache: ${
|
|
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 ${
|
|
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
|
|
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 =
|
|
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
|
|
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 (
|
|
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
|
|
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 =
|
|
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"),
|