@cortexkit/magic-context 0.24.1 → 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 +1187 -443
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11544,6 +11544,14 @@ function buildNodeSqliteDatabaseClass(DatabaseSync) {
|
|
|
11544
11544
|
}
|
|
11545
11545
|
super(typeof filename === "string" ? filename : ":memory:", translated);
|
|
11546
11546
|
}
|
|
11547
|
+
prepare(sql) {
|
|
11548
|
+
const stmt = super.prepare(sql);
|
|
11549
|
+
for (const method of ["run", "get", "all"]) {
|
|
11550
|
+
const original = stmt[method].bind(stmt);
|
|
11551
|
+
stmt[method] = (...args) => args.length === 1 && Array.isArray(args[0]) ? original(...args[0]) : original(...args);
|
|
11552
|
+
}
|
|
11553
|
+
return stmt;
|
|
11554
|
+
}
|
|
11547
11555
|
transaction(fn) {
|
|
11548
11556
|
const self = this;
|
|
11549
11557
|
const wrapped = function(...args) {
|
|
@@ -12204,6 +12212,622 @@ var init_migrate = __esm(async () => {
|
|
|
12204
12212
|
await init_sqlite();
|
|
12205
12213
|
});
|
|
12206
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
|
+
|
|
12207
12831
|
// ../plugin/src/features/magic-context/compartment-lease.ts
|
|
12208
12832
|
var COMPARTMENT_LEASE_TTL_MS, COMPARTMENT_LEASE_RENEWAL_MS;
|
|
12209
12833
|
var init_compartment_lease = __esm(() => {
|
|
@@ -12255,9 +12879,9 @@ var init_compartment_storage = __esm(() => {
|
|
|
12255
12879
|
});
|
|
12256
12880
|
// ../plugin/src/shared/logger.ts
|
|
12257
12881
|
import * as fs from "node:fs";
|
|
12258
|
-
import * as
|
|
12882
|
+
import * as path4 from "node:path";
|
|
12259
12883
|
function ensureDir5(filePath) {
|
|
12260
|
-
const dir =
|
|
12884
|
+
const dir = path4.dirname(filePath);
|
|
12261
12885
|
if (dir === lastEnsuredDir)
|
|
12262
12886
|
return;
|
|
12263
12887
|
try {
|
|
@@ -144790,16 +145414,18 @@ function stripTagPrefix(value) {
|
|
|
144790
145414
|
const prev = stripped;
|
|
144791
145415
|
stripped = stripped.replace(MALFORMED_TAG_PREFIX_REGEX, "");
|
|
144792
145416
|
stripped = stripped.replace(TAG_PREFIX_REGEX, "");
|
|
145417
|
+
stripped = stripped.replace(DANGLING_TAG_PREFIX_REGEX, "");
|
|
144793
145418
|
if (stripped === prev)
|
|
144794
145419
|
break;
|
|
144795
145420
|
}
|
|
144796
145421
|
return stripped;
|
|
144797
145422
|
}
|
|
144798
|
-
var encoder, TAG_PREFIX_REGEX, MALFORMED_TAG_PREFIX_REGEX;
|
|
145423
|
+
var encoder, TAG_PREFIX_REGEX, MALFORMED_TAG_PREFIX_REGEX, DANGLING_TAG_PREFIX_REGEX;
|
|
144799
145424
|
var init_tag_content_primitives = __esm(() => {
|
|
144800
145425
|
encoder = new TextEncoder;
|
|
144801
145426
|
TAG_PREFIX_REGEX = /^(?:§\d+§\s*)+/;
|
|
144802
145427
|
MALFORMED_TAG_PREFIX_REGEX = /^(?:§\d+">§(?:\d+§)?\s*)+/;
|
|
145428
|
+
DANGLING_TAG_PREFIX_REGEX = /^(?:\u00a7\d+(?!\.\d)[^\s\u00a7\w.]?\s*)+/;
|
|
144803
145429
|
});
|
|
144804
145430
|
|
|
144805
145431
|
// ../plugin/src/hooks/magic-context/tag-part-guards.ts
|
|
@@ -144869,13 +145495,14 @@ var init_tool_drop_target = __esm(() => {
|
|
|
144869
145495
|
});
|
|
144870
145496
|
|
|
144871
145497
|
// ../plugin/src/hooks/magic-context/read-session-chunk.ts
|
|
144872
|
-
var sessionProviders;
|
|
145498
|
+
var blockTokenMemo, sessionProviders;
|
|
144873
145499
|
var init_read_session_chunk = __esm(async () => {
|
|
144874
145500
|
init_read_session_formatting();
|
|
144875
145501
|
init_tag_part_guards();
|
|
144876
145502
|
init_tool_drop_target();
|
|
144877
145503
|
init_read_session_formatting();
|
|
144878
145504
|
await init_read_session_db();
|
|
145505
|
+
blockTokenMemo = new Map;
|
|
144879
145506
|
sessionProviders = new Map;
|
|
144880
145507
|
});
|
|
144881
145508
|
|
|
@@ -144898,7 +145525,7 @@ function getErrorMessage(error) {
|
|
|
144898
145525
|
}
|
|
144899
145526
|
|
|
144900
145527
|
// ../plugin/src/features/magic-context/key-files/project-key-files.ts
|
|
144901
|
-
import { existsSync as
|
|
145528
|
+
import { existsSync as existsSync12, readFileSync as readFileSync7, realpathSync as realpathSync2 } from "node:fs";
|
|
144902
145529
|
function deleteOrphanProjectKeyFiles(db, now = Date.now()) {
|
|
144903
145530
|
const cutoff = now - ORPHAN_GRACE_MS;
|
|
144904
145531
|
const rows = db.prepare(`SELECT project_path AS projectPath, MAX(generated_at) AS lastGen
|
|
@@ -144907,7 +145534,7 @@ function deleteOrphanProjectKeyFiles(db, now = Date.now()) {
|
|
|
144907
145534
|
HAVING lastGen < ?`).all(cutoff);
|
|
144908
145535
|
let deletedProjects = 0;
|
|
144909
145536
|
for (const row of rows) {
|
|
144910
|
-
if (
|
|
145537
|
+
if (existsSync12(row.projectPath))
|
|
144911
145538
|
continue;
|
|
144912
145539
|
try {
|
|
144913
145540
|
db.transaction(() => {
|
|
@@ -144960,10 +145587,10 @@ var init_tool_definition_tokens = __esm(() => {
|
|
|
144960
145587
|
});
|
|
144961
145588
|
|
|
144962
145589
|
// ../plugin/src/features/magic-context/tool-owner-backfill.ts
|
|
144963
|
-
import { existsSync as
|
|
144964
|
-
import { join as
|
|
145590
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
145591
|
+
import { join as join11 } from "node:path";
|
|
144965
145592
|
function resolveOpencodeDbPath() {
|
|
144966
|
-
return
|
|
145593
|
+
return join11(getDataDir(), "opencode", "opencode.db");
|
|
144967
145594
|
}
|
|
144968
145595
|
function ensureBackfillStateTable(db) {
|
|
144969
145596
|
db.exec(`
|
|
@@ -144998,7 +145625,7 @@ function runToolOwnerBackfill(db) {
|
|
|
144998
145625
|
return result;
|
|
144999
145626
|
}
|
|
145000
145627
|
const opencodeDbPath = resolveOpencodeDbPath();
|
|
145001
|
-
if (!
|
|
145628
|
+
if (!existsSync13(opencodeDbPath)) {
|
|
145002
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.`);
|
|
145003
145630
|
markAllUnbackfilledSessionsSkipped(db);
|
|
145004
145631
|
result.sessionsSkippedNoOcDb = countSessionsByStatus(db, "skipped");
|
|
@@ -145221,26 +145848,26 @@ var init_tool_owner_backfill = __esm(() => {
|
|
|
145221
145848
|
});
|
|
145222
145849
|
|
|
145223
145850
|
// ../plugin/src/features/magic-context/storage-db.ts
|
|
145224
|
-
import { copyFileSync, cpSync, existsSync as
|
|
145225
|
-
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";
|
|
145226
145853
|
function resolveDatabasePath(dbPathOverride) {
|
|
145227
145854
|
if (dbPathOverride) {
|
|
145228
145855
|
return { dbDir: dirname6(dbPathOverride), dbPath: dbPathOverride };
|
|
145229
145856
|
}
|
|
145230
145857
|
const testDataDir = process.env.MAGIC_CONTEXT_TEST_DATA_DIR;
|
|
145231
145858
|
if (testDataDir && !process.env.XDG_DATA_HOME) {
|
|
145232
|
-
const dbDir2 =
|
|
145233
|
-
return { dbDir: dbDir2, dbPath:
|
|
145859
|
+
const dbDir2 = join12(testDataDir, "cortexkit", "magic-context");
|
|
145860
|
+
return { dbDir: dbDir2, dbPath: join12(dbDir2, "context.db") };
|
|
145234
145861
|
}
|
|
145235
145862
|
const dbDir = getMagicContextStorageDir();
|
|
145236
|
-
return { dbDir, dbPath:
|
|
145863
|
+
return { dbDir, dbPath: join12(dbDir, "context.db") };
|
|
145237
145864
|
}
|
|
145238
145865
|
function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
145239
|
-
if (
|
|
145866
|
+
if (existsSync14(targetDbPath))
|
|
145240
145867
|
return;
|
|
145241
145868
|
const legacyDir = getLegacyOpenCodeMagicContextStorageDir();
|
|
145242
|
-
const legacyDbPath =
|
|
145243
|
-
if (!
|
|
145869
|
+
const legacyDbPath = join12(legacyDir, "context.db");
|
|
145870
|
+
if (!existsSync14(legacyDbPath))
|
|
145244
145871
|
return;
|
|
145245
145872
|
log2(`[magic-context] migrating legacy plugin storage: ${legacyDir} -> ${targetDbDir} (legacy left in place as backup)`);
|
|
145246
145873
|
mkdirSync5(targetDbDir, { recursive: true });
|
|
@@ -145256,18 +145883,18 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
|
145256
145883
|
}
|
|
145257
145884
|
for (const suffix of ["", "-wal", "-shm"]) {
|
|
145258
145885
|
const src = `${legacyDbPath}${suffix}`;
|
|
145259
|
-
const dst =
|
|
145260
|
-
if (
|
|
145886
|
+
const dst = join12(targetDbDir, `context.db${suffix}`);
|
|
145887
|
+
if (existsSync14(src)) {
|
|
145261
145888
|
try {
|
|
145262
|
-
|
|
145889
|
+
copyFileSync2(src, dst);
|
|
145263
145890
|
} catch (error) {
|
|
145264
145891
|
log2(`[magic-context] failed to copy ${src}:`, getErrorMessage(error));
|
|
145265
145892
|
}
|
|
145266
145893
|
}
|
|
145267
145894
|
}
|
|
145268
|
-
const legacyModelsDir =
|
|
145269
|
-
const targetModelsDir =
|
|
145270
|
-
if (
|
|
145895
|
+
const legacyModelsDir = join12(legacyDir, "models");
|
|
145896
|
+
const targetModelsDir = join12(targetDbDir, "models");
|
|
145897
|
+
if (existsSync14(legacyModelsDir) && !existsSync14(targetModelsDir)) {
|
|
145271
145898
|
try {
|
|
145272
145899
|
cpSync(legacyModelsDir, targetModelsDir, { recursive: true });
|
|
145273
145900
|
} catch (error) {
|
|
@@ -145736,6 +146363,8 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
145736
146363
|
recovery_no_eligible_head_count INTEGER NOT NULL DEFAULT 0,
|
|
145737
146364
|
force_emergency_bypass_window_start INTEGER NOT NULL DEFAULT 0,
|
|
145738
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,
|
|
145739
146368
|
cached_m0_materialized_at INTEGER,
|
|
145740
146369
|
cached_m0_session_facts_version INTEGER,
|
|
145741
146370
|
cached_m0_upgrade_state TEXT,
|
|
@@ -145799,6 +146428,23 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
145799
146428
|
CREATE INDEX IF NOT EXISTS idx_historian_runs_status
|
|
145800
146429
|
ON historian_runs(status, created_at DESC);
|
|
145801
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
|
+
|
|
145802
146448
|
CREATE INDEX IF NOT EXISTS idx_tags_session_tag_number ON tags(session_id, tag_number);
|
|
145803
146449
|
CREATE INDEX IF NOT EXISTS idx_tags_session_message_id ON tags(session_id, message_id);
|
|
145804
146450
|
CREATE INDEX IF NOT EXISTS idx_pending_ops_session ON pending_ops(session_id);
|
|
@@ -145876,6 +146522,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
145876
146522
|
ensureColumn(db, "session_meta", "historian_last_failure_at", "INTEGER DEFAULT NULL");
|
|
145877
146523
|
ensureColumn(db, "session_meta", "system_prompt_hash", "TEXT DEFAULT ''");
|
|
145878
146524
|
ensureColumn(db, "session_meta", "cleared_reasoning_through_tag", "INTEGER DEFAULT 0");
|
|
146525
|
+
ensureColumn(db, "session_meta", "tool_reclaim_watermark", "INTEGER DEFAULT 0");
|
|
145879
146526
|
ensureColumn(db, "session_meta", "stripped_placeholder_ids", "TEXT DEFAULT ''");
|
|
145880
146527
|
ensureColumn(db, "session_meta", "stale_reduce_stripped_ids", "TEXT DEFAULT ''");
|
|
145881
146528
|
ensureColumn(db, "session_meta", "processed_image_stripped_ids", "TEXT DEFAULT ''");
|
|
@@ -145949,6 +146596,8 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
145949
146596
|
ensureColumn(db, "session_meta", "recovery_no_eligible_head_count", "INTEGER NOT NULL DEFAULT 0");
|
|
145950
146597
|
ensureColumn(db, "session_meta", "force_emergency_bypass_window_start", "INTEGER NOT NULL DEFAULT 0");
|
|
145951
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");
|
|
145952
146601
|
ensureColumn(db, "session_meta", "cached_m0_materialized_at", "INTEGER");
|
|
145953
146602
|
ensureColumn(db, "session_meta", "cached_m0_session_facts_version", "INTEGER");
|
|
145954
146603
|
ensureColumn(db, "session_meta", "cached_m0_upgrade_state", "TEXT");
|
|
@@ -146027,6 +146676,22 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
146027
146676
|
failed_at INTEGER NOT NULL,
|
|
146028
146677
|
UNIQUE(table_name, row_id)
|
|
146029
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);
|
|
146030
146695
|
`);
|
|
146031
146696
|
ensureColumn(db, "tags", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
146032
146697
|
ensureColumn(db, "pending_ops", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
@@ -146112,7 +146777,9 @@ function healNullIntegerColumns(db) {
|
|
|
146112
146777
|
["protected_tail_drain_tokens", 0],
|
|
146113
146778
|
["recovery_no_eligible_head_count", 0],
|
|
146114
146779
|
["force_emergency_bypass_window_start", 0],
|
|
146115
|
-
["force_emergency_bypass_used", 0]
|
|
146780
|
+
["force_emergency_bypass_used", 0],
|
|
146781
|
+
["emergency_drain_active", 0],
|
|
146782
|
+
["historian_drain_failure_at", 0]
|
|
146116
146783
|
];
|
|
146117
146784
|
for (const [column, fallback] of columns) {
|
|
146118
146785
|
try {
|
|
@@ -146188,6 +146855,7 @@ function openDatabase(dbPathOrOptions) {
|
|
|
146188
146855
|
setDatabase(db);
|
|
146189
146856
|
loadToolDefinitionMeasurements(db);
|
|
146190
146857
|
databases.set(dbPath, db);
|
|
146858
|
+
pathByDatabase.set(db, dbPath);
|
|
146191
146859
|
persistenceByDatabase.set(db, true);
|
|
146192
146860
|
persistenceErrorByDatabase.delete(db);
|
|
146193
146861
|
return db;
|
|
@@ -146213,7 +146881,7 @@ function closeDatabase() {
|
|
|
146213
146881
|
}
|
|
146214
146882
|
}
|
|
146215
146883
|
}
|
|
146216
|
-
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;
|
|
146217
146885
|
var init_storage_db = __esm(async () => {
|
|
146218
146886
|
init_data_path();
|
|
146219
146887
|
init_logger();
|
|
@@ -146227,6 +146895,7 @@ var init_storage_db = __esm(async () => {
|
|
|
146227
146895
|
databases = new Map;
|
|
146228
146896
|
persistenceByDatabase = new WeakMap;
|
|
146229
146897
|
persistenceErrorByDatabase = new WeakMap;
|
|
146898
|
+
pathByDatabase = new WeakMap;
|
|
146230
146899
|
sqlitePragmaConfig = {
|
|
146231
146900
|
cacheSizeMb: 64,
|
|
146232
146901
|
mmapSizeMb: 0
|
|
@@ -146268,172 +146937,6 @@ var init_constants = __esm(() => {
|
|
|
146268
146937
|
};
|
|
146269
146938
|
});
|
|
146270
146939
|
|
|
146271
|
-
// ../plugin/src/features/magic-context/memory/project-identity.ts
|
|
146272
|
-
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
146273
|
-
import { createHash } from "node:crypto";
|
|
146274
|
-
import { statSync as statSync3 } from "node:fs";
|
|
146275
|
-
import path3 from "node:path";
|
|
146276
|
-
function asError(error) {
|
|
146277
|
-
return error instanceof Error ? error : undefined;
|
|
146278
|
-
}
|
|
146279
|
-
function getErrorCode(error) {
|
|
146280
|
-
if (error === null || typeof error !== "object" || !("code" in error)) {
|
|
146281
|
-
return;
|
|
146282
|
-
}
|
|
146283
|
-
const code = error.code;
|
|
146284
|
-
return typeof code === "string" ? code : undefined;
|
|
146285
|
-
}
|
|
146286
|
-
function getErrorSignal(error) {
|
|
146287
|
-
if (error === null || typeof error !== "object" || !("signal" in error)) {
|
|
146288
|
-
return;
|
|
146289
|
-
}
|
|
146290
|
-
const signal = error.signal;
|
|
146291
|
-
return typeof signal === "string" ? signal : undefined;
|
|
146292
|
-
}
|
|
146293
|
-
function getErrorKilled(error) {
|
|
146294
|
-
if (error === null || typeof error !== "object" || !("killed" in error)) {
|
|
146295
|
-
return false;
|
|
146296
|
-
}
|
|
146297
|
-
return error.killed === true;
|
|
146298
|
-
}
|
|
146299
|
-
function getErrorStderr(error) {
|
|
146300
|
-
if (error === null || typeof error !== "object" || !("stderr" in error)) {
|
|
146301
|
-
return "";
|
|
146302
|
-
}
|
|
146303
|
-
const stderr = error.stderr;
|
|
146304
|
-
if (typeof stderr === "string") {
|
|
146305
|
-
return stderr;
|
|
146306
|
-
}
|
|
146307
|
-
if (Buffer.isBuffer(stderr)) {
|
|
146308
|
-
return stderr.toString("utf8");
|
|
146309
|
-
}
|
|
146310
|
-
return "";
|
|
146311
|
-
}
|
|
146312
|
-
function directoryFallback(directory) {
|
|
146313
|
-
const canonical = path3.resolve(directory);
|
|
146314
|
-
const hash = createHash("md5").update(canonical, "utf8").digest("hex").slice(0, 12);
|
|
146315
|
-
return `dir:${hash}`;
|
|
146316
|
-
}
|
|
146317
|
-
function assertDirectoryUsable(canonicalDirectory, rawDirectory) {
|
|
146318
|
-
try {
|
|
146319
|
-
const stat = statSync3(canonicalDirectory);
|
|
146320
|
-
if (!stat.isDirectory()) {
|
|
146321
|
-
throw new ProjectIdentityError("unknown", rawDirectory, `Project path is not a directory: ${canonicalDirectory}`);
|
|
146322
|
-
}
|
|
146323
|
-
} catch (error) {
|
|
146324
|
-
if (error instanceof ProjectIdentityError) {
|
|
146325
|
-
throw error;
|
|
146326
|
-
}
|
|
146327
|
-
const code = getErrorCode(error);
|
|
146328
|
-
if (code === "EACCES" || code === "EPERM") {
|
|
146329
|
-
throw new ProjectIdentityError("permission_denied", rawDirectory, `Permission denied while accessing project directory: ${canonicalDirectory}`, asError(error));
|
|
146330
|
-
}
|
|
146331
|
-
throw new ProjectIdentityError("unknown", rawDirectory, `Unable to access project directory: ${canonicalDirectory}`, asError(error));
|
|
146332
|
-
}
|
|
146333
|
-
}
|
|
146334
|
-
function isGitTimeoutError(error) {
|
|
146335
|
-
const code = getErrorCode(error);
|
|
146336
|
-
const signal = getErrorSignal(error);
|
|
146337
|
-
return code === "ETIMEDOUT" || signal === "SIGTERM" || signal === "SIGKILL" || getErrorKilled(error);
|
|
146338
|
-
}
|
|
146339
|
-
function classifyGitError(error, rawDirectory) {
|
|
146340
|
-
if (isGitTimeoutError(error)) {
|
|
146341
|
-
return new ProjectIdentityError("git_timeout", rawDirectory, `git rev-list timed out after ${GIT_TIMEOUT_MS}ms`, asError(error));
|
|
146342
|
-
}
|
|
146343
|
-
const code = getErrorCode(error);
|
|
146344
|
-
if (code === "ENOENT") {
|
|
146345
|
-
return new ProjectIdentityError("git_missing", rawDirectory, "git binary is not available in PATH", asError(error));
|
|
146346
|
-
}
|
|
146347
|
-
if (code === "EACCES" || code === "EPERM") {
|
|
146348
|
-
return new ProjectIdentityError("permission_denied", rawDirectory, "Permission denied while spawning git", asError(error));
|
|
146349
|
-
}
|
|
146350
|
-
const stderr = getErrorStderr(error).toLowerCase();
|
|
146351
|
-
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")) {
|
|
146352
|
-
return new ProjectIdentityError("not_git_repo", rawDirectory, "Directory has no git root commit; caller may use directory fallback", asError(error));
|
|
146353
|
-
}
|
|
146354
|
-
return new ProjectIdentityError("unknown", rawDirectory, "git rev-list failed while resolving project identity", asError(error));
|
|
146355
|
-
}
|
|
146356
|
-
function resolveProjectIdentityStrict(directory) {
|
|
146357
|
-
const canonical = path3.resolve(directory);
|
|
146358
|
-
const cached = identityCache.get(canonical);
|
|
146359
|
-
if (cached !== undefined) {
|
|
146360
|
-
return cached;
|
|
146361
|
-
}
|
|
146362
|
-
assertDirectoryUsable(canonical, directory);
|
|
146363
|
-
let output;
|
|
146364
|
-
try {
|
|
146365
|
-
output = execFileSync3("git", ["rev-list", "--max-parents=0", "HEAD"], {
|
|
146366
|
-
cwd: canonical,
|
|
146367
|
-
encoding: "utf8",
|
|
146368
|
-
env: { ...process.env, LC_ALL: "C", LANG: "C" },
|
|
146369
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
146370
|
-
timeout: GIT_TIMEOUT_MS
|
|
146371
|
-
});
|
|
146372
|
-
} catch (error) {
|
|
146373
|
-
throw classifyGitError(error, directory);
|
|
146374
|
-
}
|
|
146375
|
-
const firstLine = output.split(`
|
|
146376
|
-
`)[0]?.trim() ?? "";
|
|
146377
|
-
const rootCommit = firstLine.slice(0, 64);
|
|
146378
|
-
if (rootCommit.length < 7) {
|
|
146379
|
-
throw new ProjectIdentityError("unknown", directory, "git rev-list returned no valid root commit hash");
|
|
146380
|
-
}
|
|
146381
|
-
const identity = `git:${rootCommit}`;
|
|
146382
|
-
identityCache.set(canonical, identity);
|
|
146383
|
-
return identity;
|
|
146384
|
-
}
|
|
146385
|
-
function shouldUseDirectoryFallback(error) {
|
|
146386
|
-
return error.errorClass === "not_git_repo" || error.errorClass === "unknown" && error.message.startsWith("Unable to access project directory:");
|
|
146387
|
-
}
|
|
146388
|
-
function resolveProjectIdentity(directory) {
|
|
146389
|
-
const canonical = path3.resolve(directory);
|
|
146390
|
-
const cachedFallback = directoryFallbackCache.get(canonical);
|
|
146391
|
-
if (cachedFallback !== undefined) {
|
|
146392
|
-
if (!hasGitDir(canonical)) {
|
|
146393
|
-
return cachedFallback;
|
|
146394
|
-
}
|
|
146395
|
-
directoryFallbackCache.delete(canonical);
|
|
146396
|
-
}
|
|
146397
|
-
try {
|
|
146398
|
-
return resolveProjectIdentityStrict(directory);
|
|
146399
|
-
} catch (error) {
|
|
146400
|
-
if (error instanceof ProjectIdentityError && shouldUseDirectoryFallback(error)) {
|
|
146401
|
-
const fallback = directoryFallback(canonical);
|
|
146402
|
-
if (!hasGitDir(canonical)) {
|
|
146403
|
-
directoryFallbackCache.set(canonical, fallback);
|
|
146404
|
-
}
|
|
146405
|
-
return fallback;
|
|
146406
|
-
}
|
|
146407
|
-
throw error;
|
|
146408
|
-
}
|
|
146409
|
-
}
|
|
146410
|
-
function hasGitDir(canonical) {
|
|
146411
|
-
try {
|
|
146412
|
-
statSync3(path3.join(canonical, ".git"));
|
|
146413
|
-
return true;
|
|
146414
|
-
} catch {
|
|
146415
|
-
return false;
|
|
146416
|
-
}
|
|
146417
|
-
}
|
|
146418
|
-
var GIT_TIMEOUT_MS = 5000, identityCache, directoryFallbackCache, ProjectIdentityError;
|
|
146419
|
-
var init_project_identity = __esm(() => {
|
|
146420
|
-
identityCache = new Map;
|
|
146421
|
-
directoryFallbackCache = new Map;
|
|
146422
|
-
ProjectIdentityError = class ProjectIdentityError extends Error {
|
|
146423
|
-
errorClass;
|
|
146424
|
-
rawDirectory;
|
|
146425
|
-
constructor(errorClass, rawDirectory, message, cause) {
|
|
146426
|
-
super(message);
|
|
146427
|
-
this.name = "ProjectIdentityError";
|
|
146428
|
-
this.errorClass = errorClass;
|
|
146429
|
-
this.rawDirectory = rawDirectory;
|
|
146430
|
-
if (cause) {
|
|
146431
|
-
this.cause = cause;
|
|
146432
|
-
}
|
|
146433
|
-
}
|
|
146434
|
-
};
|
|
146435
|
-
});
|
|
146436
|
-
|
|
146437
146940
|
// ../plugin/src/features/magic-context/project-identity.ts
|
|
146438
146941
|
var init_project_identity2 = __esm(() => {
|
|
146439
146942
|
init_project_identity();
|
|
@@ -147506,6 +148009,41 @@ var init_migrations = __esm(async () => {
|
|
|
147506
148009
|
`);
|
|
147507
148010
|
}
|
|
147508
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
|
+
}
|
|
147509
148047
|
}
|
|
147510
148048
|
];
|
|
147511
148049
|
LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
|
|
@@ -147537,7 +148075,7 @@ var init_storage_memory_mutation_log = __esm(() => {
|
|
|
147537
148075
|
});
|
|
147538
148076
|
|
|
147539
148077
|
// ../plugin/src/features/magic-context/storage-meta-persisted.ts
|
|
147540
|
-
var AUTO_SEARCH_NO_HINT_REASONS, DRAIN_WINDOW_MS;
|
|
148078
|
+
var AUTO_SEARCH_NO_HINT_REASONS, DRAIN_WINDOW_MS, EMERGENCY_DRAIN_MAX_LATCH_MS;
|
|
147541
148079
|
var init_storage_meta_persisted = __esm(() => {
|
|
147542
148080
|
init_logger();
|
|
147543
148081
|
init_storage_meta_shared();
|
|
@@ -147550,6 +148088,7 @@ var init_storage_meta_persisted = __esm(() => {
|
|
|
147550
148088
|
"too-short"
|
|
147551
148089
|
]);
|
|
147552
148090
|
DRAIN_WINDOW_MS = 10 * 60 * 1000;
|
|
148091
|
+
EMERGENCY_DRAIN_MAX_LATCH_MS = 30 * 60 * 1000;
|
|
147553
148092
|
});
|
|
147554
148093
|
|
|
147555
148094
|
// ../plugin/src/features/magic-context/resolve-subagent-fallback.ts
|
|
@@ -147593,10 +148132,11 @@ var init_storage_ops = __esm(() => {
|
|
|
147593
148132
|
clearPendingOpsStatements = new WeakMap;
|
|
147594
148133
|
removePendingOpStatements = new WeakMap;
|
|
147595
148134
|
});
|
|
148135
|
+
|
|
147596
148136
|
// ../plugin/src/features/magic-context/storage-source.ts
|
|
147597
148137
|
var init_storage_source = () => {};
|
|
147598
148138
|
// ../plugin/src/features/magic-context/storage-tags.ts
|
|
147599
|
-
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;
|
|
147600
148140
|
var init_storage_tags = __esm(() => {
|
|
147601
148141
|
insertTagStatements = new WeakMap;
|
|
147602
148142
|
updateTagStatusStatements = new WeakMap;
|
|
@@ -147611,6 +148151,7 @@ var init_storage_tags = __esm(() => {
|
|
|
147611
148151
|
updateTagTokenCountStatements = new WeakMap;
|
|
147612
148152
|
updateTagInputTokenCountStatements = new WeakMap;
|
|
147613
148153
|
getOwnerScopedToolTagNumbersStatements = new WeakMap;
|
|
148154
|
+
getMinMessageTagNumberForRawIdStatements = new WeakMap;
|
|
147614
148155
|
getActiveTagsBySessionStatements = new WeakMap;
|
|
147615
148156
|
getMaxDroppedTagNumberStatements = new WeakMap;
|
|
147616
148157
|
getToolTagNumberByOwnerStatements = new WeakMap;
|
|
@@ -147656,8 +148197,8 @@ var init_storage = __esm(async () => {
|
|
|
147656
148197
|
|
|
147657
148198
|
// ../plugin/src/features/magic-context/v22-deferred-backfill.ts
|
|
147658
148199
|
import { createHash as createHash2 } from "node:crypto";
|
|
147659
|
-
import { realpathSync as
|
|
147660
|
-
import
|
|
148200
|
+
import { realpathSync as realpathSync3 } from "node:fs";
|
|
148201
|
+
import path5 from "node:path";
|
|
147661
148202
|
function readMeta(db, key) {
|
|
147662
148203
|
const row = db.prepare("SELECT value FROM schema_migrations_meta WHERE key = ?").get(key);
|
|
147663
148204
|
return row?.value ?? null;
|
|
@@ -147697,9 +148238,9 @@ function resolveBackfillIdentity(rawProjectPath) {
|
|
|
147697
148238
|
function computeLegacyRustDirIdentity(rawProjectPath) {
|
|
147698
148239
|
let canonical;
|
|
147699
148240
|
try {
|
|
147700
|
-
canonical =
|
|
148241
|
+
canonical = realpathSync3(rawProjectPath);
|
|
147701
148242
|
} catch {
|
|
147702
|
-
canonical =
|
|
148243
|
+
canonical = path5.isAbsolute(rawProjectPath) ? rawProjectPath : path5.join(process.cwd(), rawProjectPath);
|
|
147703
148244
|
}
|
|
147704
148245
|
return `dir:${createHash2("sha256").update(canonical, "utf8").digest("hex")}`;
|
|
147705
148246
|
}
|
|
@@ -147740,24 +148281,6 @@ function getV22BackfillStatus(db) {
|
|
|
147740
148281
|
maxLegacyMemoryId: maxLegacyRow.m
|
|
147741
148282
|
};
|
|
147742
148283
|
}
|
|
147743
|
-
function rekeyMemoryRowWithCollisionMerge(db, rowId, fromProjectPath, toIdentity) {
|
|
147744
|
-
const row = db.prepare("SELECT category, normalized_hash, seen_count FROM memories WHERE id = ?").get(rowId);
|
|
147745
|
-
if (!row)
|
|
147746
|
-
return false;
|
|
147747
|
-
const collision = db.prepare(`SELECT id, seen_count FROM memories
|
|
147748
|
-
WHERE project_path = ? AND category = ? AND normalized_hash = ?
|
|
147749
|
-
LIMIT 1`).get(toIdentity, row.category, row.normalized_hash);
|
|
147750
|
-
if (collision && collision.id !== rowId) {
|
|
147751
|
-
const mergedSeen = Math.max(collision.seen_count ?? 1, row.seen_count ?? 1);
|
|
147752
|
-
if (mergedSeen !== (collision.seen_count ?? 1)) {
|
|
147753
|
-
db.prepare("UPDATE memories SET seen_count = ? WHERE id = ?").run(mergedSeen, collision.id);
|
|
147754
|
-
}
|
|
147755
|
-
db.prepare("DELETE FROM memories WHERE id = ?").run(rowId);
|
|
147756
|
-
return true;
|
|
147757
|
-
}
|
|
147758
|
-
const result = db.prepare("UPDATE memories SET project_path = ? WHERE id = ? AND project_path = ?").run(toIdentity, rowId, fromProjectPath);
|
|
147759
|
-
return (result.changes ?? 0) > 0;
|
|
147760
|
-
}
|
|
147761
148284
|
async function doctorRetryV22Backfill(db) {
|
|
147762
148285
|
const failures = db.prepare(`SELECT row_id, raw_project_path
|
|
147763
148286
|
FROM v22_backfill_failures
|
|
@@ -147837,6 +148360,7 @@ var BACKFILL_META_KEY = "v22_legacy_memory_backfill", BACKFILL_CURSOR_META_KEY =
|
|
|
147837
148360
|
var init_v22_deferred_backfill = __esm(() => {
|
|
147838
148361
|
init_logger();
|
|
147839
148362
|
init_project_identity();
|
|
148363
|
+
init_relocate_memory();
|
|
147840
148364
|
});
|
|
147841
148365
|
|
|
147842
148366
|
// src/lib/v22-backfill-commands.ts
|
|
@@ -148365,10 +148889,10 @@ function mergeDefs(...defs) {
|
|
|
148365
148889
|
function cloneDef(schema) {
|
|
148366
148890
|
return mergeDefs(schema._zod.def);
|
|
148367
148891
|
}
|
|
148368
|
-
function getElementAtPath(obj,
|
|
148369
|
-
if (!
|
|
148892
|
+
function getElementAtPath(obj, path6) {
|
|
148893
|
+
if (!path6)
|
|
148370
148894
|
return obj;
|
|
148371
|
-
return
|
|
148895
|
+
return path6.reduce((acc, key) => acc?.[key], obj);
|
|
148372
148896
|
}
|
|
148373
148897
|
function promiseAllObject(promisesObj) {
|
|
148374
148898
|
const keys = Object.keys(promisesObj);
|
|
@@ -148696,11 +149220,11 @@ function explicitlyAborted(x2, startIndex = 0) {
|
|
|
148696
149220
|
}
|
|
148697
149221
|
return false;
|
|
148698
149222
|
}
|
|
148699
|
-
function prefixIssues(
|
|
149223
|
+
function prefixIssues(path6, issues) {
|
|
148700
149224
|
return issues.map((iss) => {
|
|
148701
149225
|
var _a2;
|
|
148702
149226
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
148703
|
-
iss.path.unshift(
|
|
149227
|
+
iss.path.unshift(path6);
|
|
148704
149228
|
return iss;
|
|
148705
149229
|
});
|
|
148706
149230
|
}
|
|
@@ -148913,16 +149437,16 @@ function flattenError(error, mapper = (issue2) => issue2.message) {
|
|
|
148913
149437
|
}
|
|
148914
149438
|
function formatError(error, mapper = (issue2) => issue2.message) {
|
|
148915
149439
|
const fieldErrors = { _errors: [] };
|
|
148916
|
-
const processError = (error2,
|
|
149440
|
+
const processError = (error2, path6 = []) => {
|
|
148917
149441
|
for (const issue2 of error2.issues) {
|
|
148918
149442
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
148919
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
149443
|
+
issue2.errors.map((issues) => processError({ issues }, [...path6, ...issue2.path]));
|
|
148920
149444
|
} else if (issue2.code === "invalid_key") {
|
|
148921
|
-
processError({ issues: issue2.issues }, [...
|
|
149445
|
+
processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
|
|
148922
149446
|
} else if (issue2.code === "invalid_element") {
|
|
148923
|
-
processError({ issues: issue2.issues }, [...
|
|
149447
|
+
processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
|
|
148924
149448
|
} else {
|
|
148925
|
-
const fullpath = [...
|
|
149449
|
+
const fullpath = [...path6, ...issue2.path];
|
|
148926
149450
|
if (fullpath.length === 0) {
|
|
148927
149451
|
fieldErrors._errors.push(mapper(issue2));
|
|
148928
149452
|
} else {
|
|
@@ -148949,17 +149473,17 @@ function formatError(error, mapper = (issue2) => issue2.message) {
|
|
|
148949
149473
|
}
|
|
148950
149474
|
function treeifyError(error, mapper = (issue2) => issue2.message) {
|
|
148951
149475
|
const result = { errors: [] };
|
|
148952
|
-
const processError = (error2,
|
|
149476
|
+
const processError = (error2, path6 = []) => {
|
|
148953
149477
|
var _a2, _b;
|
|
148954
149478
|
for (const issue2 of error2.issues) {
|
|
148955
149479
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
148956
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
149480
|
+
issue2.errors.map((issues) => processError({ issues }, [...path6, ...issue2.path]));
|
|
148957
149481
|
} else if (issue2.code === "invalid_key") {
|
|
148958
|
-
processError({ issues: issue2.issues }, [...
|
|
149482
|
+
processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
|
|
148959
149483
|
} else if (issue2.code === "invalid_element") {
|
|
148960
|
-
processError({ issues: issue2.issues }, [...
|
|
149484
|
+
processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
|
|
148961
149485
|
} else {
|
|
148962
|
-
const fullpath = [...
|
|
149486
|
+
const fullpath = [...path6, ...issue2.path];
|
|
148963
149487
|
if (fullpath.length === 0) {
|
|
148964
149488
|
result.errors.push(mapper(issue2));
|
|
148965
149489
|
continue;
|
|
@@ -148991,8 +149515,8 @@ function treeifyError(error, mapper = (issue2) => issue2.message) {
|
|
|
148991
149515
|
}
|
|
148992
149516
|
function toDotPath(_path) {
|
|
148993
149517
|
const segs = [];
|
|
148994
|
-
const
|
|
148995
|
-
for (const seg of
|
|
149518
|
+
const path6 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
149519
|
+
for (const seg of path6) {
|
|
148996
149520
|
if (typeof seg === "number")
|
|
148997
149521
|
segs.push(`[${seg}]`);
|
|
148998
149522
|
else if (typeof seg === "symbol")
|
|
@@ -161995,13 +162519,13 @@ function resolveRef(ref, ctx) {
|
|
|
161995
162519
|
if (!ref.startsWith("#")) {
|
|
161996
162520
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
161997
162521
|
}
|
|
161998
|
-
const
|
|
161999
|
-
if (
|
|
162522
|
+
const path6 = ref.slice(1).split("/").filter(Boolean);
|
|
162523
|
+
if (path6.length === 0) {
|
|
162000
162524
|
return ctx.rootSchema;
|
|
162001
162525
|
}
|
|
162002
162526
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
162003
|
-
if (
|
|
162004
|
-
const key =
|
|
162527
|
+
if (path6[0] === defsKey) {
|
|
162528
|
+
const key = path6[1];
|
|
162005
162529
|
if (!key || !ctx.defs[key]) {
|
|
162006
162530
|
throw new Error(`Reference not found: ${ref}`);
|
|
162007
162531
|
}
|
|
@@ -162825,14 +163349,16 @@ var init_magic_context = __esm(() => {
|
|
|
162825
163349
|
}).optional();
|
|
162826
163350
|
HistorianConfigSchema = AgentOverrideConfigSchema.extend({
|
|
162827
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)"),
|
|
162828
|
-
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: [])`)
|
|
162829
163354
|
}).optional();
|
|
162830
163355
|
BaseEmbeddingConfigSchema = exports_external.object({
|
|
162831
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."),
|
|
162832
163357
|
model: exports_external.string().optional().describe("Embedding model name. Required for openai-compatible, ignored for local."),
|
|
162833
163358
|
endpoint: exports_external.string().optional().describe("API endpoint URL. Required when provider is openai-compatible."),
|
|
162834
163359
|
api_key: exports_external.string().optional().describe("API key for remote embedding provider (optional)"),
|
|
162835
|
-
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."),
|
|
162836
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."),
|
|
162837
163363
|
max_input_tokens: exports_external.number().int().positive().optional().describe("Optional maximum input tokens for chunk embeddings. Defaults conservatively to 512 when omitted.")
|
|
162838
163364
|
}).superRefine((data, ctx) => {
|
|
@@ -162862,6 +163388,7 @@ var init_magic_context = __esm(() => {
|
|
|
162862
163388
|
if (data.provider === "openai-compatible") {
|
|
162863
163389
|
const apiKey = data.api_key?.trim();
|
|
162864
163390
|
const inputType = data.input_type?.trim();
|
|
163391
|
+
const queryInputType = data.query_input_type?.trim();
|
|
162865
163392
|
const truncate = data.truncate?.trim();
|
|
162866
163393
|
return {
|
|
162867
163394
|
provider: "openai-compatible",
|
|
@@ -162869,6 +163396,7 @@ var init_magic_context = __esm(() => {
|
|
|
162869
163396
|
endpoint: data.endpoint?.trim() ?? "",
|
|
162870
163397
|
...apiKey ? { api_key: apiKey } : {},
|
|
162871
163398
|
...inputType ? { input_type: inputType } : {},
|
|
163399
|
+
...queryInputType ? { query_input_type: queryInputType } : {},
|
|
162872
163400
|
...truncate ? { truncate } : {},
|
|
162873
163401
|
...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}
|
|
162874
163402
|
};
|
|
@@ -162951,11 +163479,11 @@ var init_magic_context = __esm(() => {
|
|
|
162951
163479
|
});
|
|
162952
163480
|
|
|
162953
163481
|
// ../plugin/src/config/variable.ts
|
|
162954
|
-
import { existsSync as
|
|
162955
|
-
import { homedir as
|
|
163482
|
+
import { existsSync as existsSync15, readFileSync as readFileSync8 } from "node:fs";
|
|
163483
|
+
import { homedir as homedir8 } from "node:os";
|
|
162956
163484
|
import { dirname as dirname7, isAbsolute, resolve as resolve2 } from "node:path";
|
|
162957
163485
|
function sensitiveFilePathReason(resolvedPath) {
|
|
162958
|
-
const home =
|
|
163486
|
+
const home = homedir8();
|
|
162959
163487
|
const sensitiveDirs = [
|
|
162960
163488
|
{ dir: resolve2(home, ".ssh"), label: "SSH keys" },
|
|
162961
163489
|
{ dir: resolve2(home, ".aws"), label: "AWS credentials" },
|
|
@@ -163018,7 +163546,7 @@ function substituteConfigVariables(input) {
|
|
|
163018
163546
|
}
|
|
163019
163547
|
let filePath = rawPath.trim();
|
|
163020
163548
|
if (filePath.startsWith("~/")) {
|
|
163021
|
-
filePath = resolve2(
|
|
163549
|
+
filePath = resolve2(homedir8(), filePath.slice(2));
|
|
163022
163550
|
} else if (!isAbsolute(filePath)) {
|
|
163023
163551
|
filePath = resolve2(configDir, filePath);
|
|
163024
163552
|
}
|
|
@@ -163026,7 +163554,7 @@ function substituteConfigVariables(input) {
|
|
|
163026
163554
|
if (sensitiveReason) {
|
|
163027
163555
|
warnings.push(`${token} resolves to a sensitive path (${sensitiveReason}: ${filePath}); ` + "inlining its contents into config — make sure this is intentional.");
|
|
163028
163556
|
}
|
|
163029
|
-
if (!
|
|
163557
|
+
if (!existsSync15(filePath)) {
|
|
163030
163558
|
warnings.push(`File not found for ${token} (resolved to ${filePath}); using empty string`);
|
|
163031
163559
|
continue;
|
|
163032
163560
|
}
|
|
@@ -163051,19 +163579,19 @@ var init_variable = __esm(() => {
|
|
|
163051
163579
|
});
|
|
163052
163580
|
|
|
163053
163581
|
// ../plugin/src/config/index.ts
|
|
163054
|
-
import { existsSync as
|
|
163055
|
-
import { homedir as
|
|
163056
|
-
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";
|
|
163057
163585
|
function getUserConfigBasePath() {
|
|
163058
|
-
const configRoot = process.env.XDG_CONFIG_HOME ??
|
|
163059
|
-
return
|
|
163586
|
+
const configRoot = process.env.XDG_CONFIG_HOME ?? join13(homedir9(), ".config");
|
|
163587
|
+
return join13(configRoot, "opencode", CONFIG_FILE_BASENAME);
|
|
163060
163588
|
}
|
|
163061
163589
|
function getProjectConfigBasePath(directory) {
|
|
163062
|
-
return
|
|
163590
|
+
return join13(directory, ".opencode", CONFIG_FILE_BASENAME);
|
|
163063
163591
|
}
|
|
163064
163592
|
function loadConfigFile(configPath, isProjectConfig = false) {
|
|
163065
163593
|
try {
|
|
163066
|
-
if (!
|
|
163594
|
+
if (!existsSync16(configPath)) {
|
|
163067
163595
|
return null;
|
|
163068
163596
|
}
|
|
163069
163597
|
const rawText = readFileSync9(configPath, "utf-8");
|
|
@@ -163207,7 +163735,7 @@ function parsePluginConfig(rawConfig, recoveredTopLevelKeys = []) {
|
|
|
163207
163735
|
}
|
|
163208
163736
|
function loadPluginConfig(directory) {
|
|
163209
163737
|
const userDetected = detectConfigFile(getUserConfigBasePath());
|
|
163210
|
-
const rootDetected = detectConfigFile(
|
|
163738
|
+
const rootDetected = detectConfigFile(join13(directory, CONFIG_FILE_BASENAME));
|
|
163211
163739
|
const dotOpenCodeDetected = detectConfigFile(getProjectConfigBasePath(directory));
|
|
163212
163740
|
const projectDetected = rootDetected.format !== "none" ? rootDetected : dotOpenCodeDetected;
|
|
163213
163741
|
const userLoaded = userDetected.format === "none" ? null : loadConfigFile(userDetected.path);
|
|
@@ -163255,14 +163783,14 @@ var init_config = __esm(() => {
|
|
|
163255
163783
|
});
|
|
163256
163784
|
|
|
163257
163785
|
// ../plugin/src/features/magic-context/key-files/aft-availability.ts
|
|
163258
|
-
import { existsSync as
|
|
163259
|
-
import { homedir as
|
|
163260
|
-
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";
|
|
163261
163789
|
import { fileURLToPath } from "node:url";
|
|
163262
|
-
function parseConfig(
|
|
163263
|
-
if (!
|
|
163790
|
+
function parseConfig(path6) {
|
|
163791
|
+
if (!existsSync17(path6))
|
|
163264
163792
|
return null;
|
|
163265
|
-
return import_comment_json6.parse(readFileSync10(
|
|
163793
|
+
return import_comment_json6.parse(readFileSync10(path6, "utf-8"));
|
|
163266
163794
|
}
|
|
163267
163795
|
function stringMentionsAft(value) {
|
|
163268
163796
|
return AFT_NAME_NEEDLES.some((needle) => value.includes(needle));
|
|
@@ -163276,14 +163804,14 @@ function resolveLocalEntryPackageName(value, configDir) {
|
|
|
163276
163804
|
return null;
|
|
163277
163805
|
}
|
|
163278
163806
|
} else if (value.startsWith("~/")) {
|
|
163279
|
-
dir =
|
|
163807
|
+
dir = join14(homedir10(), value.slice(2));
|
|
163280
163808
|
} else if (value.startsWith("/") || value.startsWith("./") || value.startsWith("../")) {
|
|
163281
163809
|
dir = isAbsolute2(value) ? value : resolve3(configDir, value);
|
|
163282
163810
|
} else {
|
|
163283
163811
|
return null;
|
|
163284
163812
|
}
|
|
163285
163813
|
try {
|
|
163286
|
-
const pkg = JSON.parse(readFileSync10(
|
|
163814
|
+
const pkg = JSON.parse(readFileSync10(join14(dir, "package.json"), "utf-8"));
|
|
163287
163815
|
return typeof pkg.name === "string" ? pkg.name : null;
|
|
163288
163816
|
} catch {
|
|
163289
163817
|
return null;
|
|
@@ -163312,18 +163840,18 @@ function hasAftAtKeys(value, keys, configDir) {
|
|
|
163312
163840
|
return false;
|
|
163313
163841
|
}
|
|
163314
163842
|
function getAftAvailability() {
|
|
163315
|
-
const home = process.env.HOME ||
|
|
163843
|
+
const home = process.env.HOME || homedir10();
|
|
163316
163844
|
const opencodePaths = [
|
|
163317
|
-
|
|
163318
|
-
|
|
163845
|
+
join14(home, ".config", "opencode", "opencode.jsonc"),
|
|
163846
|
+
join14(home, ".config", "opencode", "opencode.json")
|
|
163319
163847
|
];
|
|
163320
|
-
const piPaths = [
|
|
163848
|
+
const piPaths = [join14(home, ".pi", "agent", "settings.json")];
|
|
163321
163849
|
const checkedPaths = [...opencodePaths, ...piPaths];
|
|
163322
163850
|
let opencode = false;
|
|
163323
|
-
for (const
|
|
163851
|
+
for (const path6 of opencodePaths) {
|
|
163324
163852
|
try {
|
|
163325
|
-
const config2 = parseConfig(
|
|
163326
|
-
const configDir =
|
|
163853
|
+
const config2 = parseConfig(path6);
|
|
163854
|
+
const configDir = join14(path6, "..");
|
|
163327
163855
|
if (hasAftAtKeys(config2, ["plugin", "plugins", "mcp", "mcp_servers"], configDir)) {
|
|
163328
163856
|
opencode = true;
|
|
163329
163857
|
break;
|
|
@@ -163331,10 +163859,10 @@ function getAftAvailability() {
|
|
|
163331
163859
|
} catch {}
|
|
163332
163860
|
}
|
|
163333
163861
|
let pi = false;
|
|
163334
|
-
for (const
|
|
163862
|
+
for (const path6 of piPaths) {
|
|
163335
163863
|
try {
|
|
163336
|
-
const config2 = parseConfig(
|
|
163337
|
-
const configDir =
|
|
163864
|
+
const config2 = parseConfig(path6);
|
|
163865
|
+
const configDir = join14(path6, "..");
|
|
163338
163866
|
if (hasAftAtKeys(config2, ["packages", "extensions"], configDir)) {
|
|
163339
163867
|
pi = true;
|
|
163340
163868
|
break;
|
|
@@ -163472,8 +164000,8 @@ function truncate(text2) {
|
|
|
163472
164000
|
var DEFAULT_TIMEOUT_MS = 1e4, MAX_PREVIEW_CHARS = 240;
|
|
163473
164001
|
|
|
163474
164002
|
// ../plugin/src/shared/tui-config.ts
|
|
163475
|
-
import { existsSync as
|
|
163476
|
-
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";
|
|
163477
164005
|
function isMagicContextEntry(entry) {
|
|
163478
164006
|
if (!entry)
|
|
163479
164007
|
return false;
|
|
@@ -163487,11 +164015,11 @@ function isMagicContextEntry(entry) {
|
|
|
163487
164015
|
}
|
|
163488
164016
|
function resolveTuiConfigPath() {
|
|
163489
164017
|
const configDir = getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
|
|
163490
|
-
const jsoncPath =
|
|
163491
|
-
const jsonPath =
|
|
163492
|
-
if (
|
|
164018
|
+
const jsoncPath = join15(configDir, "tui.jsonc");
|
|
164019
|
+
const jsonPath = join15(configDir, "tui.json");
|
|
164020
|
+
if (existsSync18(jsoncPath))
|
|
163493
164021
|
return jsoncPath;
|
|
163494
|
-
if (
|
|
164022
|
+
if (existsSync18(jsonPath))
|
|
163495
164023
|
return jsonPath;
|
|
163496
164024
|
return jsonPath;
|
|
163497
164025
|
}
|
|
@@ -163499,7 +164027,7 @@ function ensureTuiPluginEntry() {
|
|
|
163499
164027
|
try {
|
|
163500
164028
|
const configPath = resolveTuiConfigPath();
|
|
163501
164029
|
let config2 = {};
|
|
163502
|
-
if (
|
|
164030
|
+
if (existsSync18(configPath)) {
|
|
163503
164031
|
const raw = readFileSync11(configPath, "utf-8");
|
|
163504
164032
|
config2 = import_comment_json7.parse(raw) ?? {};
|
|
163505
164033
|
}
|
|
@@ -163670,7 +164198,7 @@ var init_compartment_parser = __esm(() => {
|
|
|
163670
164198
|
});
|
|
163671
164199
|
|
|
163672
164200
|
// src/lib/redaction.ts
|
|
163673
|
-
import { homedir as
|
|
164201
|
+
import { homedir as homedir11, userInfo } from "node:os";
|
|
163674
164202
|
function escapeRegex3(value) {
|
|
163675
164203
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
163676
164204
|
}
|
|
@@ -163714,7 +164242,7 @@ function isSecretKey(key) {
|
|
|
163714
164242
|
return false;
|
|
163715
164243
|
}
|
|
163716
164244
|
function sanitizePathString(value) {
|
|
163717
|
-
const home =
|
|
164245
|
+
const home = homedir11();
|
|
163718
164246
|
const username = userInfo().username;
|
|
163719
164247
|
let sanitized = value;
|
|
163720
164248
|
if (home) {
|
|
@@ -163848,10 +164376,10 @@ var init_redaction = __esm(() => {
|
|
|
163848
164376
|
});
|
|
163849
164377
|
|
|
163850
164378
|
// src/lib/diagnostics-opencode.ts
|
|
163851
|
-
import { existsSync as
|
|
164379
|
+
import { existsSync as existsSync19, readdirSync as readdirSync2, readFileSync as readFileSync12, statSync as statSync4 } from "node:fs";
|
|
163852
164380
|
import { createRequire as createRequire2 } from "node:module";
|
|
163853
|
-
import { homedir as
|
|
163854
|
-
import { join as
|
|
164381
|
+
import { homedir as homedir12 } from "node:os";
|
|
164382
|
+
import { join as join16 } from "node:path";
|
|
163855
164383
|
function getSelfVersion() {
|
|
163856
164384
|
const require2 = createRequire2(import.meta.url);
|
|
163857
164385
|
for (const relPath of ["../../package.json", "../package.json"]) {
|
|
@@ -163865,26 +164393,26 @@ function getSelfVersion() {
|
|
|
163865
164393
|
return "unknown";
|
|
163866
164394
|
}
|
|
163867
164395
|
function getPluginCacheInfo() {
|
|
163868
|
-
const
|
|
164396
|
+
const path6 = join16(getOpenCodeCacheDir(), "packages", PLUGIN_ENTRY_WITH_VERSION);
|
|
163869
164397
|
let cached2;
|
|
163870
164398
|
try {
|
|
163871
|
-
const installedPkgPath =
|
|
163872
|
-
if (
|
|
164399
|
+
const installedPkgPath = join16(path6, "node_modules", "@cortexkit", "opencode-magic-context", "package.json");
|
|
164400
|
+
if (existsSync19(installedPkgPath)) {
|
|
163873
164401
|
const pkg = JSON.parse(readFileSync12(installedPkgPath, "utf-8"));
|
|
163874
164402
|
cached2 = typeof pkg.version === "string" ? pkg.version : undefined;
|
|
163875
164403
|
}
|
|
163876
164404
|
} catch {
|
|
163877
164405
|
cached2 = undefined;
|
|
163878
164406
|
}
|
|
163879
|
-
return { path:
|
|
164407
|
+
return { path: path6, cached: cached2, latest: getSelfVersion() };
|
|
163880
164408
|
}
|
|
163881
164409
|
function getStorageDir() {
|
|
163882
|
-
const dataHome = process.env.XDG_DATA_HOME ||
|
|
163883
|
-
return
|
|
164410
|
+
const dataHome = process.env.XDG_DATA_HOME || join16(homedir12(), ".local", "share");
|
|
164411
|
+
return join16(dataHome, "cortexkit", "magic-context");
|
|
163884
164412
|
}
|
|
163885
|
-
function fileSize(
|
|
164413
|
+
function fileSize(path6) {
|
|
163886
164414
|
try {
|
|
163887
|
-
return
|
|
164415
|
+
return existsSync19(path6) ? statSync4(path6).size : 0;
|
|
163888
164416
|
} catch {
|
|
163889
164417
|
return 0;
|
|
163890
164418
|
}
|
|
@@ -163895,11 +164423,11 @@ function sanitizeString(value) {
|
|
|
163895
164423
|
function sanitizeValue(value) {
|
|
163896
164424
|
return sanitizeConfigValue(value);
|
|
163897
164425
|
}
|
|
163898
|
-
function readConfig2(
|
|
163899
|
-
if (!
|
|
164426
|
+
function readConfig2(path6) {
|
|
164427
|
+
if (!existsSync19(path6))
|
|
163900
164428
|
return { value: null };
|
|
163901
164429
|
try {
|
|
163902
|
-
const raw = readFileSync12(
|
|
164430
|
+
const raw = readFileSync12(path6, "utf-8");
|
|
163903
164431
|
const value = import_comment_json8.parse(raw);
|
|
163904
164432
|
return { value };
|
|
163905
164433
|
} catch (error51) {
|
|
@@ -163920,9 +164448,9 @@ function configHasPluginEntry(config2) {
|
|
|
163920
164448
|
return false;
|
|
163921
164449
|
});
|
|
163922
164450
|
}
|
|
163923
|
-
function parseHistorianDumpMeta(
|
|
164451
|
+
function parseHistorianDumpMeta(path6) {
|
|
163924
164452
|
try {
|
|
163925
|
-
const xml = readFileSync12(
|
|
164453
|
+
const xml = readFileSync12(path6, "utf-8");
|
|
163926
164454
|
const parsed = parseCompartmentOutput(xml);
|
|
163927
164455
|
const factCountByCategory = {};
|
|
163928
164456
|
for (const fact of parsed.facts) {
|
|
@@ -163955,11 +164483,11 @@ function parseHistorianDumpMeta(path5) {
|
|
|
163955
164483
|
}
|
|
163956
164484
|
}
|
|
163957
164485
|
function listDumpsInDir(dir, limit) {
|
|
163958
|
-
if (!
|
|
164486
|
+
if (!existsSync19(dir))
|
|
163959
164487
|
return { count: 0, recent: [] };
|
|
163960
164488
|
try {
|
|
163961
164489
|
const entries = readdirSync2(dir).filter((name2) => name2.endsWith(".xml")).map((name2) => {
|
|
163962
|
-
const stat = statSync4(
|
|
164490
|
+
const stat = statSync4(join16(dir, name2));
|
|
163963
164491
|
return {
|
|
163964
164492
|
name: name2,
|
|
163965
164493
|
mtime: stat.mtimeMs,
|
|
@@ -163968,7 +164496,7 @@ function listDumpsInDir(dir, limit) {
|
|
|
163968
164496
|
}).sort((a, b2) => b2.mtime - a.mtime);
|
|
163969
164497
|
const now = Date.now();
|
|
163970
164498
|
const recent = entries.slice(0, limit).map((entry) => {
|
|
163971
|
-
const meta3 = parseHistorianDumpMeta(
|
|
164499
|
+
const meta3 = parseHistorianDumpMeta(join16(dir, entry.name));
|
|
163972
164500
|
const summary = {
|
|
163973
164501
|
name: entry.name,
|
|
163974
164502
|
ageMinutes: Math.round((now - entry.mtime) / 60000),
|
|
@@ -164023,8 +164551,8 @@ function collectHistorianDumps(recentSessions) {
|
|
|
164023
164551
|
};
|
|
164024
164552
|
}
|
|
164025
164553
|
async function collectRecentSessions() {
|
|
164026
|
-
const opencodeDbPath =
|
|
164027
|
-
if (!
|
|
164554
|
+
const opencodeDbPath = join16(homedir12(), ".local", "share", "opencode", "opencode.db");
|
|
164555
|
+
if (!existsSync19(opencodeDbPath))
|
|
164028
164556
|
return [];
|
|
164029
164557
|
if (typeof globalThis.Bun === "undefined") {
|
|
164030
164558
|
return [];
|
|
@@ -164058,8 +164586,8 @@ async function collectRecentSessions() {
|
|
|
164058
164586
|
}
|
|
164059
164587
|
}
|
|
164060
164588
|
async function collectHistorianFailures(storageDirPath) {
|
|
164061
|
-
const contextDbPath =
|
|
164062
|
-
if (!
|
|
164589
|
+
const contextDbPath = join16(storageDirPath, "context.db");
|
|
164590
|
+
if (!existsSync19(contextDbPath))
|
|
164063
164591
|
return [];
|
|
164064
164592
|
if (typeof globalThis.Bun === "undefined") {
|
|
164065
164593
|
return [];
|
|
@@ -164091,6 +164619,70 @@ async function collectHistorianFailures(storageDirPath) {
|
|
|
164091
164619
|
} catch {}
|
|
164092
164620
|
}
|
|
164093
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
|
+
}
|
|
164094
164686
|
async function collectDiagnostics() {
|
|
164095
164687
|
const pluginVersion = getSelfVersion();
|
|
164096
164688
|
const configPaths = detectConfigPaths();
|
|
@@ -164098,9 +164690,9 @@ async function collectDiagnostics() {
|
|
|
164098
164690
|
const tuiConfig = readConfig2(configPaths.tuiConfig);
|
|
164099
164691
|
const magicContextConfig = readConfig2(configPaths.magicContextConfig);
|
|
164100
164692
|
const storageDirPath = getStorageDir();
|
|
164101
|
-
const contextDbPath =
|
|
164693
|
+
const contextDbPath = join16(storageDirPath, "context.db");
|
|
164102
164694
|
const logPath = getMagicContextLogPath2("opencode");
|
|
164103
|
-
const logFileSize =
|
|
164695
|
+
const logFileSize = existsSync19(logPath) ? statSync4(logPath).size : 0;
|
|
164104
164696
|
const conflictResult = detectConflicts(process.cwd());
|
|
164105
164697
|
const recentSessions = await collectRecentSessions();
|
|
164106
164698
|
return {
|
|
@@ -164115,7 +164707,7 @@ async function collectDiagnostics() {
|
|
|
164115
164707
|
opencodeConfigHasPlugin: configHasPluginEntry(opencodeConfig.value),
|
|
164116
164708
|
tuiConfigHasPlugin: configHasPluginEntry(tuiConfig.value),
|
|
164117
164709
|
magicContextConfig: {
|
|
164118
|
-
exists:
|
|
164710
|
+
exists: existsSync19(configPaths.magicContextConfig),
|
|
164119
164711
|
...magicContextConfig.error ? { parseError: magicContextConfig.error } : {},
|
|
164120
164712
|
flags: sanitizeValue(magicContextConfig.value ?? {}) ?? {}
|
|
164121
164713
|
},
|
|
@@ -164123,7 +164715,7 @@ async function collectDiagnostics() {
|
|
|
164123
164715
|
pluginCache: getPluginCacheInfo(),
|
|
164124
164716
|
storageDir: {
|
|
164125
164717
|
path: storageDirPath,
|
|
164126
|
-
exists:
|
|
164718
|
+
exists: existsSync19(storageDirPath),
|
|
164127
164719
|
contextDbSizeBytes: fileSize(contextDbPath)
|
|
164128
164720
|
},
|
|
164129
164721
|
conflicts: {
|
|
@@ -164132,12 +164724,13 @@ async function collectDiagnostics() {
|
|
|
164132
164724
|
},
|
|
164133
164725
|
logFile: {
|
|
164134
164726
|
path: logPath,
|
|
164135
|
-
exists:
|
|
164727
|
+
exists: existsSync19(logPath),
|
|
164136
164728
|
sizeKb: Math.round(logFileSize / 1024)
|
|
164137
164729
|
},
|
|
164138
164730
|
recentSessions,
|
|
164139
164731
|
historianDumps: collectHistorianDumps(recentSessions),
|
|
164140
|
-
historianFailures: await collectHistorianFailures(storageDirPath)
|
|
164732
|
+
historianFailures: await collectHistorianFailures(storageDirPath),
|
|
164733
|
+
historianRuns: await collectHistorianRuns(storageDirPath)
|
|
164141
164734
|
};
|
|
164142
164735
|
}
|
|
164143
164736
|
function formatBytes(bytes) {
|
|
@@ -164233,11 +164826,21 @@ function renderDiagnosticsMarkdown(report) {
|
|
|
164233
164826
|
"```",
|
|
164234
164827
|
"",
|
|
164235
164828
|
"### Historian failures (session_meta)",
|
|
164829
|
+
"_Note: this counter RESETS to 0 on every successful run — see 'Historian runs' below for the durable history._",
|
|
164236
164830
|
report.historianFailures.length === 0 ? "_No sessions with historian failures._" : [
|
|
164237
164831
|
"```json",
|
|
164238
164832
|
JSON.stringify(sanitizeConfigValue(report.historianFailures), null, 2),
|
|
164239
164833
|
"```"
|
|
164240
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(`
|
|
164241
164844
|
`),
|
|
164242
164845
|
"",
|
|
164243
164846
|
"### Log file",
|
|
@@ -164260,6 +164863,99 @@ var init_diagnostics_opencode = __esm(() => {
|
|
|
164260
164863
|
PLUGIN_ENTRY_WITH_VERSION = `${PLUGIN_NAME5}@latest`;
|
|
164261
164864
|
});
|
|
164262
164865
|
|
|
164866
|
+
// src/lib/embedding-runtime.ts
|
|
164867
|
+
import { existsSync as existsSync20 } from "node:fs";
|
|
164868
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
164869
|
+
import { dirname as dirname9, join as join17, sep } from "node:path";
|
|
164870
|
+
function expectedBinaryRelPath(platform, arch) {
|
|
164871
|
+
const supportedPlatform = platform === "linux" || platform === "darwin" || platform === "win32";
|
|
164872
|
+
const supportedArch = arch === "x64" || arch === "arm64";
|
|
164873
|
+
if (!supportedPlatform || !supportedArch)
|
|
164874
|
+
return null;
|
|
164875
|
+
return join17("bin", "napi-v6", platform, arch, "onnxruntime_binding.node");
|
|
164876
|
+
}
|
|
164877
|
+
function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform, arch = process.arch) {
|
|
164878
|
+
const packageDir = join17(installRoot, "node_modules", "onnxruntime-node");
|
|
164879
|
+
if (!existsSync20(join17(packageDir, "package.json"))) {
|
|
164880
|
+
return { state: "package-missing", packageDir };
|
|
164881
|
+
}
|
|
164882
|
+
const rel = expectedBinaryRelPath(platform, arch);
|
|
164883
|
+
if (rel === null) {
|
|
164884
|
+
return { state: "ok", binaryPath: packageDir };
|
|
164885
|
+
}
|
|
164886
|
+
const binaryPath = join17(packageDir, rel);
|
|
164887
|
+
if (!existsSync20(binaryPath)) {
|
|
164888
|
+
return { state: "binary-missing", packageDir, expectedBinary: binaryPath };
|
|
164889
|
+
}
|
|
164890
|
+
return { state: "ok", binaryPath };
|
|
164891
|
+
}
|
|
164892
|
+
function checkLocalEmbeddingRuntime(installRoots, platform = process.platform, arch = process.arch) {
|
|
164893
|
+
const existing = installRoots.filter((root) => existsSync20(root));
|
|
164894
|
+
if (existing.length === 0) {
|
|
164895
|
+
return {
|
|
164896
|
+
state: "unknown",
|
|
164897
|
+
reason: "no installed plugin tree found to inspect"
|
|
164898
|
+
};
|
|
164899
|
+
}
|
|
164900
|
+
let firstFailure = null;
|
|
164901
|
+
for (const root of existing) {
|
|
164902
|
+
const status = checkLocalEmbeddingRuntimeAt(root, platform, arch);
|
|
164903
|
+
if (status.state === "ok")
|
|
164904
|
+
return status;
|
|
164905
|
+
if (firstFailure === null)
|
|
164906
|
+
firstFailure = status;
|
|
164907
|
+
}
|
|
164908
|
+
return firstFailure ?? { state: "unknown", reason: "no candidate roots" };
|
|
164909
|
+
}
|
|
164910
|
+
function packageDirFromResolved(resolvedPath, packageName) {
|
|
164911
|
+
const marker = `node_modules${sep}${packageName.split("/").join(sep)}`;
|
|
164912
|
+
const idx = resolvedPath.indexOf(marker);
|
|
164913
|
+
return idx >= 0 ? resolvedPath.slice(0, idx + marker.length) : dirname9(resolvedPath);
|
|
164914
|
+
}
|
|
164915
|
+
function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.platform, arch = process.arch) {
|
|
164916
|
+
if (!existsSync20(join17(pluginDir, "package.json"))) {
|
|
164917
|
+
return { state: "unknown", reason: "plugin package dir not found" };
|
|
164918
|
+
}
|
|
164919
|
+
let onnxDir = null;
|
|
164920
|
+
let resolveError;
|
|
164921
|
+
try {
|
|
164922
|
+
const reqPlugin = createRequire3(join17(pluginDir, "package.json"));
|
|
164923
|
+
try {
|
|
164924
|
+
onnxDir = packageDirFromResolved(reqPlugin.resolve("onnxruntime-node"), "onnxruntime-node");
|
|
164925
|
+
} catch {
|
|
164926
|
+
const tfResolved = reqPlugin.resolve("@huggingface/transformers");
|
|
164927
|
+
const tfDir = packageDirFromResolved(tfResolved, "@huggingface/transformers");
|
|
164928
|
+
const reqTf = createRequire3(join17(tfDir, "package.json"));
|
|
164929
|
+
onnxDir = packageDirFromResolved(reqTf.resolve("onnxruntime-node"), "onnxruntime-node");
|
|
164930
|
+
}
|
|
164931
|
+
} catch (error51) {
|
|
164932
|
+
resolveError = error51?.code;
|
|
164933
|
+
if (resolveError === "ERR_MODULE_NOT_FOUND" || resolveError === "MODULE_NOT_FOUND") {
|
|
164934
|
+
return {
|
|
164935
|
+
state: "package-missing",
|
|
164936
|
+
packageDir: join17(pluginDir, "node_modules", "onnxruntime-node")
|
|
164937
|
+
};
|
|
164938
|
+
}
|
|
164939
|
+
return {
|
|
164940
|
+
state: "unknown",
|
|
164941
|
+
reason: `could not resolve onnxruntime-node (${resolveError ?? "unknown error"})`
|
|
164942
|
+
};
|
|
164943
|
+
}
|
|
164944
|
+
if (!onnxDir) {
|
|
164945
|
+
return { state: "unknown", reason: "onnxruntime-node resolution produced no path" };
|
|
164946
|
+
}
|
|
164947
|
+
const rel = expectedBinaryRelPath(platform, arch);
|
|
164948
|
+
if (rel === null) {
|
|
164949
|
+
return { state: "ok", binaryPath: onnxDir };
|
|
164950
|
+
}
|
|
164951
|
+
const binaryPath = join17(onnxDir, rel);
|
|
164952
|
+
if (!existsSync20(binaryPath)) {
|
|
164953
|
+
return { state: "binary-missing", packageDir: onnxDir, expectedBinary: binaryPath };
|
|
164954
|
+
}
|
|
164955
|
+
return { state: "ok", binaryPath };
|
|
164956
|
+
}
|
|
164957
|
+
var init_embedding_runtime = () => {};
|
|
164958
|
+
|
|
164263
164959
|
// src/lib/issue-body.ts
|
|
164264
164960
|
function isErrorLogLine(line) {
|
|
164265
164961
|
return ERROR_LOG_PATTERNS.some((rx) => rx.test(line));
|
|
@@ -164347,8 +165043,8 @@ var init_issue_body = __esm(() => {
|
|
|
164347
165043
|
|
|
164348
165044
|
// src/lib/logs-opencode.ts
|
|
164349
165045
|
import { readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "node:fs";
|
|
164350
|
-
import { homedir as
|
|
164351
|
-
import { join as
|
|
165046
|
+
import { homedir as homedir13 } from "node:os";
|
|
165047
|
+
import { join as join18 } from "node:path";
|
|
164352
165048
|
function sanitizeLogContent(content) {
|
|
164353
165049
|
return sanitizeDiagnosticText(content);
|
|
164354
165050
|
}
|
|
@@ -164401,7 +165097,7 @@ async function bundleIssueReport(report, description, _title, sessionFilter = nu
|
|
|
164401
165097
|
`));
|
|
164402
165098
|
const recentErrorLines = extractRecentErrors(errorScanWindow, 20);
|
|
164403
165099
|
const configBody = JSON.stringify(sanitizeConfigValue(report.magicContextConfig.flags), null, 2);
|
|
164404
|
-
const sanitizedConfigPath = report.configPaths.magicContextConfig.replace(
|
|
165100
|
+
const sanitizedConfigPath = report.configPaths.magicContextConfig.replace(homedir13(), "~");
|
|
164405
165101
|
const rawBodyMarkdown = [
|
|
164406
165102
|
"## Description",
|
|
164407
165103
|
description,
|
|
@@ -164438,10 +165134,10 @@ async function bundleIssueReport(report, description, _title, sessionFilter = nu
|
|
|
164438
165134
|
].join(`
|
|
164439
165135
|
`);
|
|
164440
165136
|
const bodyMarkdown = capBodyToGithubLimit(rawBodyMarkdown);
|
|
164441
|
-
const
|
|
164442
|
-
writeFileSync8(
|
|
165137
|
+
const path6 = join18(process.cwd(), `magic-context-issue-${formatTimestamp(new Date)}.md`);
|
|
165138
|
+
writeFileSync8(path6, `${bodyMarkdown}
|
|
164443
165139
|
`);
|
|
164444
|
-
return { path:
|
|
165140
|
+
return { path: path6, bodyMarkdown };
|
|
164445
165141
|
}
|
|
164446
165142
|
var HISTORIAN_LOG_PATTERNS;
|
|
164447
165143
|
var init_logs_opencode = __esm(() => {
|
|
@@ -164461,10 +165157,10 @@ var init_logs_opencode = __esm(() => {
|
|
|
164461
165157
|
|
|
164462
165158
|
// src/commands/doctor-opencode.ts
|
|
164463
165159
|
import { execSync as execSync2, spawnSync as spawnSync2 } from "node:child_process";
|
|
164464
|
-
import { existsSync as
|
|
164465
|
-
import { createRequire as
|
|
164466
|
-
import { homedir as
|
|
164467
|
-
import { join as
|
|
165160
|
+
import { existsSync as existsSync21, readFileSync as readFileSync14, rmSync, statSync as statSync5, writeFileSync as writeFileSync9 } from "node:fs";
|
|
165161
|
+
import { createRequire as createRequire4 } from "node:module";
|
|
165162
|
+
import { homedir as homedir14 } from "node:os";
|
|
165163
|
+
import { join as join19 } from "node:path";
|
|
164468
165164
|
function migrateLegacyAgentEnabledConfigForDoctor(mcConfig, logs) {
|
|
164469
165165
|
let changed = false;
|
|
164470
165166
|
let fixes = 0;
|
|
@@ -164523,7 +165219,7 @@ async function fetchNpmLatest(pkg, timeoutMs = 5000) {
|
|
|
164523
165219
|
}
|
|
164524
165220
|
}
|
|
164525
165221
|
function getSelfVersion2() {
|
|
164526
|
-
const req =
|
|
165222
|
+
const req = createRequire4(import.meta.url);
|
|
164527
165223
|
for (const relPath of ["../../package.json", "../package.json"]) {
|
|
164528
165224
|
try {
|
|
164529
165225
|
const pkg = req(relPath);
|
|
@@ -164551,21 +165247,21 @@ function compareVersions(a, b2) {
|
|
|
164551
165247
|
}
|
|
164552
165248
|
async function clearPluginCache(force = false) {
|
|
164553
165249
|
const cacheDir = getOpenCodeCacheDir();
|
|
164554
|
-
const pluginCacheDir =
|
|
164555
|
-
if (!
|
|
165250
|
+
const pluginCacheDir = join19(cacheDir, "packages", PLUGIN_ENTRY_WITH_VERSION2);
|
|
165251
|
+
if (!existsSync21(pluginCacheDir)) {
|
|
164556
165252
|
return { action: "not_found", path: pluginCacheDir };
|
|
164557
165253
|
}
|
|
164558
165254
|
let cachedVersion;
|
|
164559
165255
|
try {
|
|
164560
|
-
const installedPkgPath =
|
|
164561
|
-
if (
|
|
165256
|
+
const installedPkgPath = join19(pluginCacheDir, "node_modules", "@cortexkit", "opencode-magic-context", "package.json");
|
|
165257
|
+
if (existsSync21(installedPkgPath)) {
|
|
164562
165258
|
const pkg = JSON.parse(readFileSync14(installedPkgPath, "utf-8"));
|
|
164563
165259
|
if (typeof pkg?.version === "string") {
|
|
164564
165260
|
cachedVersion = pkg.version;
|
|
164565
165261
|
}
|
|
164566
165262
|
}
|
|
164567
165263
|
} catch {}
|
|
164568
|
-
const require2 =
|
|
165264
|
+
const require2 = createRequire4(import.meta.url);
|
|
164569
165265
|
let selfVersion;
|
|
164570
165266
|
for (const relPath of ["../../package.json", "../package.json"]) {
|
|
164571
165267
|
try {
|
|
@@ -164690,9 +165386,21 @@ async function runIssueFlow() {
|
|
|
164690
165386
|
return 1;
|
|
164691
165387
|
}
|
|
164692
165388
|
}
|
|
165389
|
+
function checkLocalEmbeddingRuntimeForDoctor() {
|
|
165390
|
+
const runtime = checkLocalEmbeddingRuntime([
|
|
165391
|
+
join19(getOpenCodeCacheDir(), "packages", PLUGIN_ENTRY_WITH_VERSION2),
|
|
165392
|
+
join19(getOpenCodeCacheDir(), "packages", PLUGIN_NAME6)
|
|
165393
|
+
]);
|
|
165394
|
+
if (runtime.state === "package-missing" || runtime.state === "binary-missing") {
|
|
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.");
|
|
165396
|
+
return { issues: 1, localRuntimeBroken: true };
|
|
165397
|
+
}
|
|
165398
|
+
log.success("Embedding provider: local (Xenova/all-MiniLM-L6-v2 bundled)");
|
|
165399
|
+
return { issues: 0 };
|
|
165400
|
+
}
|
|
164693
165401
|
async function checkEmbeddingConfig(magicContextConfigPath) {
|
|
164694
|
-
if (!
|
|
164695
|
-
return
|
|
165402
|
+
if (!existsSync21(magicContextConfigPath)) {
|
|
165403
|
+
return checkLocalEmbeddingRuntimeForDoctor();
|
|
164696
165404
|
}
|
|
164697
165405
|
let rawText;
|
|
164698
165406
|
try {
|
|
@@ -164719,8 +165427,7 @@ async function checkEmbeddingConfig(magicContextConfigPath) {
|
|
|
164719
165427
|
return { issues: 0 };
|
|
164720
165428
|
}
|
|
164721
165429
|
if (provider === undefined || provider === "local") {
|
|
164722
|
-
|
|
164723
|
-
return { issues: 0 };
|
|
165430
|
+
return checkLocalEmbeddingRuntimeForDoctor();
|
|
164724
165431
|
}
|
|
164725
165432
|
if (provider !== "openai-compatible") {
|
|
164726
165433
|
log.warn(`Unknown embedding provider: ${String(provider)} (expected local | openai-compatible | off)`);
|
|
@@ -164859,7 +165566,7 @@ async function runDoctor(options = {}) {
|
|
|
164859
165566
|
} else {
|
|
164860
165567
|
pass(`OpenCode config: ${paths.opencodeConfig}`);
|
|
164861
165568
|
}
|
|
164862
|
-
if (
|
|
165569
|
+
if (existsSync21(paths.magicContextConfig)) {
|
|
164863
165570
|
pass(`Magic Context config: ${paths.magicContextConfig}`);
|
|
164864
165571
|
try {
|
|
164865
165572
|
const raw = readFileSync14(paths.magicContextConfig, "utf-8");
|
|
@@ -164887,7 +165594,7 @@ async function runDoctor(options = {}) {
|
|
|
164887
165594
|
warn(`No magic-context.jsonc found — using defaults`);
|
|
164888
165595
|
log.info(" Run 'setup' to create one with model recommendations");
|
|
164889
165596
|
}
|
|
164890
|
-
if (
|
|
165597
|
+
if (existsSync21(paths.magicContextConfig)) {
|
|
164891
165598
|
try {
|
|
164892
165599
|
const mcRaw = readFileSync14(paths.magicContextConfig, "utf-8");
|
|
164893
165600
|
const mcConfig = import_comment_json9.parse(mcRaw);
|
|
@@ -165094,7 +165801,7 @@ async function runDoctor(options = {}) {
|
|
|
165094
165801
|
pass("Added TUI sidebar plugin to tui.json");
|
|
165095
165802
|
warn("Restart OpenCode to see the sidebar");
|
|
165096
165803
|
fixed++;
|
|
165097
|
-
} else if (
|
|
165804
|
+
} else if (existsSync21(paths.tuiConfig)) {
|
|
165098
165805
|
try {
|
|
165099
165806
|
const tuiRaw = readFileSync14(paths.tuiConfig, "utf-8");
|
|
165100
165807
|
const tuiConfig = import_comment_json9.parse(tuiRaw);
|
|
@@ -165142,7 +165849,7 @@ async function runDoctor(options = {}) {
|
|
|
165142
165849
|
} else {
|
|
165143
165850
|
pass("TUI sidebar plugin configured (tui.json created)");
|
|
165144
165851
|
}
|
|
165145
|
-
if (
|
|
165852
|
+
if (existsSync21(paths.magicContextConfig)) {
|
|
165146
165853
|
try {
|
|
165147
165854
|
const mcRaw = readFileSync14(paths.magicContextConfig, "utf-8");
|
|
165148
165855
|
const mcConfig = import_comment_json9.parse(mcRaw);
|
|
@@ -165171,8 +165878,8 @@ async function runDoctor(options = {}) {
|
|
|
165171
165878
|
failCount += embeddingCheck.issues;
|
|
165172
165879
|
else
|
|
165173
165880
|
passCount++;
|
|
165174
|
-
const dbPath =
|
|
165175
|
-
if (!
|
|
165881
|
+
const dbPath = join19(getMagicContextStorageDir(), "context.db");
|
|
165882
|
+
if (!existsSync21(dbPath)) {
|
|
165176
165883
|
log.info(`Shared context DB not yet created at ${dbPath} (will be created on first run)`);
|
|
165177
165884
|
} else {
|
|
165178
165885
|
pass(`Shared context DB exists at ${dbPath}`);
|
|
@@ -165233,8 +165940,8 @@ async function runDoctor(options = {}) {
|
|
|
165233
165940
|
}
|
|
165234
165941
|
{
|
|
165235
165942
|
const ageWarnings = [];
|
|
165236
|
-
const npmrcPath =
|
|
165237
|
-
if (
|
|
165943
|
+
const npmrcPath = join19(homedir14(), ".npmrc");
|
|
165944
|
+
if (existsSync21(npmrcPath)) {
|
|
165238
165945
|
try {
|
|
165239
165946
|
const npmrc = readFileSync14(npmrcPath, "utf-8");
|
|
165240
165947
|
for (const line of npmrc.split(`
|
|
@@ -165260,7 +165967,7 @@ async function runDoctor(options = {}) {
|
|
|
165260
165967
|
}
|
|
165261
165968
|
}
|
|
165262
165969
|
const logPath = getMagicContextLogPath2("opencode");
|
|
165263
|
-
if (
|
|
165970
|
+
if (existsSync21(logPath)) {
|
|
165264
165971
|
const logStat = statSync5(logPath);
|
|
165265
165972
|
const sizeKb = (logStat.size / 1024).toFixed(0);
|
|
165266
165973
|
log.info(`Log file: ${logPath} (${sizeKb} KB)`);
|
|
@@ -165317,6 +166024,7 @@ var init_doctor_opencode = __esm(async () => {
|
|
|
165317
166024
|
init_tui_config();
|
|
165318
166025
|
init_opencode();
|
|
165319
166026
|
init_diagnostics_opencode();
|
|
166027
|
+
init_embedding_runtime();
|
|
165320
166028
|
init_logs_opencode();
|
|
165321
166029
|
init_opencode_helpers();
|
|
165322
166030
|
init_paths();
|
|
@@ -165331,44 +166039,44 @@ var init_doctor_opencode = __esm(async () => {
|
|
|
165331
166039
|
});
|
|
165332
166040
|
|
|
165333
166041
|
// ../pi-plugin/src/config/index.ts
|
|
165334
|
-
import { existsSync as
|
|
165335
|
-
import { homedir as
|
|
165336
|
-
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";
|
|
165337
166045
|
function getProjectConfigPaths(cwd) {
|
|
165338
|
-
const basePath =
|
|
166046
|
+
const basePath = join20(cwd, ".pi", CONFIG_FILE_NAME);
|
|
165339
166047
|
return [`${basePath}.jsonc`, `${basePath}.json`];
|
|
165340
166048
|
}
|
|
165341
166049
|
function getUserConfigPaths() {
|
|
165342
|
-
const home = process.env.HOME ??
|
|
165343
|
-
const basePath =
|
|
166050
|
+
const home = process.env.HOME ?? homedir15();
|
|
166051
|
+
const basePath = join20(home, ".pi", "agent", CONFIG_FILE_NAME);
|
|
165344
166052
|
return [`${basePath}.jsonc`, `${basePath}.json`];
|
|
165345
166053
|
}
|
|
165346
166054
|
function resolveFirstExisting(paths) {
|
|
165347
|
-
return paths.find((
|
|
166055
|
+
return paths.find((path6) => existsSync22(path6));
|
|
165348
166056
|
}
|
|
165349
|
-
function loadConfigFile2(
|
|
166057
|
+
function loadConfigFile2(path6, scope) {
|
|
165350
166058
|
try {
|
|
165351
|
-
const rawText = readFileSync15(
|
|
166059
|
+
const rawText = readFileSync15(path6, "utf-8");
|
|
165352
166060
|
const substituted = substituteConfigVariables({
|
|
165353
166061
|
text: rawText,
|
|
165354
|
-
configPath:
|
|
166062
|
+
configPath: path6,
|
|
165355
166063
|
isProjectConfig: scope === "project"
|
|
165356
166064
|
});
|
|
165357
166065
|
return {
|
|
165358
|
-
path:
|
|
166066
|
+
path: path6,
|
|
165359
166067
|
scope,
|
|
165360
166068
|
config: import_comment_json10.parse(substituted.text),
|
|
165361
|
-
warnings: substituted.warnings.map((warning) => `${
|
|
166069
|
+
warnings: substituted.warnings.map((warning) => `${path6}: ${warning}`),
|
|
165362
166070
|
loadOutcome: substituted.warnings.length > 0 ? "substitution-failure" : "ok"
|
|
165363
166071
|
};
|
|
165364
166072
|
} catch (error51) {
|
|
165365
166073
|
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
165366
166074
|
return {
|
|
165367
|
-
path:
|
|
166075
|
+
path: path6,
|
|
165368
166076
|
scope,
|
|
165369
166077
|
config: {},
|
|
165370
166078
|
warnings: [
|
|
165371
|
-
`${
|
|
166079
|
+
`${path6}: failed to load config: ${message}; using defaults for this file.`
|
|
165372
166080
|
],
|
|
165373
166081
|
loadOutcome: typeof error51.code === "string" ? "project-file-io-error" : "project-file-parse-error"
|
|
165374
166082
|
};
|
|
@@ -165524,12 +166232,12 @@ var init_config2 = __esm(() => {
|
|
|
165524
166232
|
|
|
165525
166233
|
// src/lib/diagnostics-pi.ts
|
|
165526
166234
|
import { createHash as createHash3 } from "node:crypto";
|
|
165527
|
-
import { existsSync as
|
|
165528
|
-
import { createRequire as
|
|
165529
|
-
import { homedir as
|
|
165530
|
-
import { join as
|
|
166235
|
+
import { existsSync as existsSync23, readdirSync as readdirSync3, readFileSync as readFileSync16, statSync as statSync6 } from "node:fs";
|
|
166236
|
+
import { createRequire as createRequire5 } from "node:module";
|
|
166237
|
+
import { homedir as homedir16, userInfo as userInfo2 } from "node:os";
|
|
166238
|
+
import { join as join21 } from "node:path";
|
|
165531
166239
|
function getSelfVersion3() {
|
|
165532
|
-
const req =
|
|
166240
|
+
const req = createRequire5(import.meta.url);
|
|
165533
166241
|
for (const relPath of ["../../package.json", "../package.json"]) {
|
|
165534
166242
|
try {
|
|
165535
166243
|
const pkg = req(relPath);
|
|
@@ -165540,9 +166248,9 @@ function getSelfVersion3() {
|
|
|
165540
166248
|
}
|
|
165541
166249
|
return "unknown";
|
|
165542
166250
|
}
|
|
165543
|
-
function fileSize2(
|
|
166251
|
+
function fileSize2(path6) {
|
|
165544
166252
|
try {
|
|
165545
|
-
return
|
|
166253
|
+
return existsSync23(path6) ? statSync6(path6).size : 0;
|
|
165546
166254
|
} catch {
|
|
165547
166255
|
return 0;
|
|
165548
166256
|
}
|
|
@@ -165558,7 +166266,7 @@ function redactSecretString(value) {
|
|
|
165558
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>");
|
|
165559
166267
|
}
|
|
165560
166268
|
function sanitizeString2(value) {
|
|
165561
|
-
const home = process.env.HOME ||
|
|
166269
|
+
const home = process.env.HOME || homedir16();
|
|
165562
166270
|
const username = userInfo2().username;
|
|
165563
166271
|
const userHash = `<USER:${currentUserHash()}>`;
|
|
165564
166272
|
let sanitized = redactSecretString(value);
|
|
@@ -165591,12 +166299,12 @@ function sanitizeValue2(value, key = "") {
|
|
|
165591
166299
|
}
|
|
165592
166300
|
return value;
|
|
165593
166301
|
}
|
|
165594
|
-
function readJsonc3(
|
|
165595
|
-
if (!
|
|
166302
|
+
function readJsonc3(path6) {
|
|
166303
|
+
if (!existsSync23(path6))
|
|
165596
166304
|
return { value: {} };
|
|
165597
166305
|
try {
|
|
165598
166306
|
return {
|
|
165599
|
-
value: import_comment_json11.parse(readFileSync16(
|
|
166307
|
+
value: import_comment_json11.parse(readFileSync16(path6, "utf-8"))
|
|
165600
166308
|
};
|
|
165601
166309
|
} catch (error51) {
|
|
165602
166310
|
return {
|
|
@@ -165606,13 +166314,13 @@ function readJsonc3(path5) {
|
|
|
165606
166314
|
}
|
|
165607
166315
|
}
|
|
165608
166316
|
function getProjectConfigPath(cwd) {
|
|
165609
|
-
return
|
|
166317
|
+
return join21(cwd, ".pi", "magic-context.jsonc");
|
|
165610
166318
|
}
|
|
165611
|
-
function readConfigDiagnostic(
|
|
165612
|
-
const parsed = readJsonc3(
|
|
166319
|
+
function readConfigDiagnostic(path6) {
|
|
166320
|
+
const parsed = readJsonc3(path6);
|
|
165613
166321
|
return {
|
|
165614
|
-
path:
|
|
165615
|
-
exists:
|
|
166322
|
+
path: path6,
|
|
166323
|
+
exists: existsSync23(path6),
|
|
165616
166324
|
...parsed.parseError ? { parseError: parsed.parseError } : {},
|
|
165617
166325
|
flags: sanitizeValue2(parsed.value)
|
|
165618
166326
|
};
|
|
@@ -165629,8 +166337,8 @@ function reverseSlugToDirectory(slug) {
|
|
|
165629
166337
|
return `/${inner.replace(/-/g, "/")}`;
|
|
165630
166338
|
}
|
|
165631
166339
|
function collectPiRecentSessions() {
|
|
165632
|
-
const sessionsRoot =
|
|
165633
|
-
if (!
|
|
166340
|
+
const sessionsRoot = join21(homedir16(), ".pi", "agent", "sessions");
|
|
166341
|
+
if (!existsSync23(sessionsRoot))
|
|
165634
166342
|
return [];
|
|
165635
166343
|
try {
|
|
165636
166344
|
const slugs = readdirSync3(sessionsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
@@ -165639,7 +166347,7 @@ function collectPiRecentSessions() {
|
|
|
165639
166347
|
const directory = reverseSlugToDirectory(slug);
|
|
165640
166348
|
if (!directory)
|
|
165641
166349
|
continue;
|
|
165642
|
-
const slugDir =
|
|
166350
|
+
const slugDir = join21(sessionsRoot, slug);
|
|
165643
166351
|
let files;
|
|
165644
166352
|
try {
|
|
165645
166353
|
files = readdirSync3(slugDir).filter((name2) => name2.endsWith(".jsonl"));
|
|
@@ -165648,7 +166356,7 @@ function collectPiRecentSessions() {
|
|
|
165648
166356
|
}
|
|
165649
166357
|
for (const file2 of files) {
|
|
165650
166358
|
try {
|
|
165651
|
-
const mtime = statSync6(
|
|
166359
|
+
const mtime = statSync6(join21(slugDir, file2)).mtimeMs;
|
|
165652
166360
|
const sessionId = file2.replace(/\.jsonl$/, "");
|
|
165653
166361
|
candidates.push({ sessionId, directory, mtime });
|
|
165654
166362
|
} catch {}
|
|
@@ -165664,9 +166372,9 @@ function collectPiRecentSessions() {
|
|
|
165664
166372
|
return [];
|
|
165665
166373
|
}
|
|
165666
166374
|
}
|
|
165667
|
-
function parseHistorianDumpMeta2(
|
|
166375
|
+
function parseHistorianDumpMeta2(path6) {
|
|
165668
166376
|
try {
|
|
165669
|
-
const xml = readFileSync16(
|
|
166377
|
+
const xml = readFileSync16(path6, "utf-8");
|
|
165670
166378
|
const parsed = parseCompartmentOutput(xml);
|
|
165671
166379
|
const factCountByCategory = {};
|
|
165672
166380
|
for (const fact of parsed.facts) {
|
|
@@ -165699,11 +166407,11 @@ function parseHistorianDumpMeta2(path5) {
|
|
|
165699
166407
|
}
|
|
165700
166408
|
}
|
|
165701
166409
|
function listDumpsInDir2(dir, limit) {
|
|
165702
|
-
if (!
|
|
166410
|
+
if (!existsSync23(dir))
|
|
165703
166411
|
return { count: 0, recent: [] };
|
|
165704
166412
|
try {
|
|
165705
166413
|
const entries = readdirSync3(dir).filter((name2) => name2.endsWith(".xml")).map((name2) => {
|
|
165706
|
-
const stat = statSync6(
|
|
166414
|
+
const stat = statSync6(join21(dir, name2));
|
|
165707
166415
|
return {
|
|
165708
166416
|
name: name2,
|
|
165709
166417
|
mtime: stat.mtimeMs,
|
|
@@ -165712,7 +166420,7 @@ function listDumpsInDir2(dir, limit) {
|
|
|
165712
166420
|
}).sort((a, b2) => b2.mtime - a.mtime);
|
|
165713
166421
|
const now = Date.now();
|
|
165714
166422
|
const recent = entries.slice(0, limit).map((entry) => {
|
|
165715
|
-
const meta3 = parseHistorianDumpMeta2(
|
|
166423
|
+
const meta3 = parseHistorianDumpMeta2(join21(dir, entry.name));
|
|
165716
166424
|
const summary = {
|
|
165717
166425
|
name: entry.name,
|
|
165718
166426
|
ageMinutes: Math.round((now - entry.mtime) / 60000),
|
|
@@ -165775,9 +166483,9 @@ async function collectDiagnostics2(cwd = process.cwd()) {
|
|
|
165775
166483
|
const projectConfigPath = getProjectConfigPath(cwd);
|
|
165776
166484
|
const loaded = loadPiConfig({ cwd });
|
|
165777
166485
|
const storageDirPath = getMagicContextStorageDir();
|
|
165778
|
-
const dbPath =
|
|
166486
|
+
const dbPath = join21(storageDirPath, "context.db");
|
|
165779
166487
|
const logPath = getMagicContextLogPath2("pi");
|
|
165780
|
-
const logFileSize =
|
|
166488
|
+
const logFileSize = existsSync23(logPath) ? statSync6(logPath).size : 0;
|
|
165781
166489
|
const otherPiExtensions = packages.filter((entry) => !isPiMagicContextPackageEntry(entry)).map(describePiPackageEntry);
|
|
165782
166490
|
const recentSessions = collectPiRecentSessions();
|
|
165783
166491
|
const historianDumps = collectPiHistorianDumps(recentSessions);
|
|
@@ -165792,7 +166500,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
|
|
|
165792
166500
|
piVersion: pi ? getPiVersion(pi.path) : null,
|
|
165793
166501
|
settings: {
|
|
165794
166502
|
path: settingsPath,
|
|
165795
|
-
exists:
|
|
166503
|
+
exists: existsSync23(settingsPath),
|
|
165796
166504
|
...settingsParsed.parseError ? { parseError: settingsParsed.parseError } : {},
|
|
165797
166505
|
hasMagicContextPackage: hasPiMagicContextPackage(packages),
|
|
165798
166506
|
packages: sanitizeValue2(packages)
|
|
@@ -165808,7 +166516,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
|
|
|
165808
166516
|
loadWarnings: loaded.warnings.map(sanitizeString2),
|
|
165809
166517
|
storageDir: {
|
|
165810
166518
|
path: storageDirPath,
|
|
165811
|
-
exists:
|
|
166519
|
+
exists: existsSync23(storageDirPath),
|
|
165812
166520
|
contextDbSizeBytes: fileSize2(dbPath)
|
|
165813
166521
|
},
|
|
165814
166522
|
conflicts: {
|
|
@@ -165817,7 +166525,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
|
|
|
165817
166525
|
},
|
|
165818
166526
|
logFile: {
|
|
165819
166527
|
path: logPath,
|
|
165820
|
-
exists:
|
|
166528
|
+
exists: existsSync23(logPath),
|
|
165821
166529
|
sizeKb: Math.round(logFileSize / 1024)
|
|
165822
166530
|
},
|
|
165823
166531
|
recentSessions,
|
|
@@ -165873,7 +166581,7 @@ function renderDiagnosticsMarkdown2(report) {
|
|
|
165873
166581
|
"```",
|
|
165874
166582
|
"",
|
|
165875
166583
|
"### Loaded config paths",
|
|
165876
|
-
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(`
|
|
165877
166585
|
`),
|
|
165878
166586
|
"",
|
|
165879
166587
|
"### Config load warnings",
|
|
@@ -165911,7 +166619,7 @@ var init_diagnostics_pi = __esm(() => {
|
|
|
165911
166619
|
|
|
165912
166620
|
// src/lib/logs-pi.ts
|
|
165913
166621
|
import { readFileSync as readFileSync17, writeFileSync as writeFileSync10 } from "node:fs";
|
|
165914
|
-
import { join as
|
|
166622
|
+
import { join as join22 } from "node:path";
|
|
165915
166623
|
function sanitizeLogContent2(content) {
|
|
165916
166624
|
return sanitizeString2(content);
|
|
165917
166625
|
}
|
|
@@ -165976,10 +166684,10 @@ async function bundleIssueReport2(report, description, title, options = {}) {
|
|
|
165976
166684
|
`);
|
|
165977
166685
|
const bodyMarkdown = capBodyToGithubLimit(rawBodyMarkdown);
|
|
165978
166686
|
const cwd = options.cwd ?? process.cwd();
|
|
165979
|
-
const
|
|
165980
|
-
writeFileSync10(
|
|
166687
|
+
const path6 = join22(cwd, `magic-context-pi-issue-${formatTimestamp2(options.now ?? new Date)}.md`);
|
|
166688
|
+
writeFileSync10(path6, `${bodyMarkdown}
|
|
165981
166689
|
`);
|
|
165982
|
-
return { path:
|
|
166690
|
+
return { path: path6, bodyMarkdown };
|
|
165983
166691
|
}
|
|
165984
166692
|
var init_logs_pi = __esm(() => {
|
|
165985
166693
|
init_diagnostics_pi();
|
|
@@ -165989,7 +166697,7 @@ var init_logs_pi = __esm(() => {
|
|
|
165989
166697
|
// src/commands/doctor-pi.ts
|
|
165990
166698
|
import { execFileSync as execFileSync4, spawnSync as spawnSync3 } from "node:child_process";
|
|
165991
166699
|
import {
|
|
165992
|
-
existsSync as
|
|
166700
|
+
existsSync as existsSync24,
|
|
165993
166701
|
mkdirSync as mkdirSync7,
|
|
165994
166702
|
readdirSync as readdirSync4,
|
|
165995
166703
|
readFileSync as readFileSync18,
|
|
@@ -165997,9 +166705,9 @@ import {
|
|
|
165997
166705
|
statSync as statSync7,
|
|
165998
166706
|
writeFileSync as writeFileSync11
|
|
165999
166707
|
} from "node:fs";
|
|
166000
|
-
import { createRequire as
|
|
166001
|
-
import { homedir as
|
|
166002
|
-
import { dirname as
|
|
166708
|
+
import { createRequire as createRequire6 } from "node:module";
|
|
166709
|
+
import { homedir as homedir17 } from "node:os";
|
|
166710
|
+
import { dirname as dirname10, isAbsolute as isAbsolute3, join as join23 } from "node:path";
|
|
166003
166711
|
function depsFrom(options) {
|
|
166004
166712
|
return {
|
|
166005
166713
|
...DEFAULT_DEPS,
|
|
@@ -166023,7 +166731,7 @@ function printDoctorHelp() {
|
|
|
166023
166731
|
console.log("");
|
|
166024
166732
|
}
|
|
166025
166733
|
function selfVersion() {
|
|
166026
|
-
const req =
|
|
166734
|
+
const req = createRequire6(import.meta.url);
|
|
166027
166735
|
for (const relPath of ["../../package.json", "../package.json"]) {
|
|
166028
166736
|
try {
|
|
166029
166737
|
const pkg = req(relPath);
|
|
@@ -166086,10 +166794,10 @@ function summarize(results) {
|
|
|
166086
166794
|
fail: results.filter((result) => result.status === "fail").length
|
|
166087
166795
|
};
|
|
166088
166796
|
}
|
|
166089
|
-
function readJsonc4(
|
|
166797
|
+
function readJsonc4(path6) {
|
|
166090
166798
|
try {
|
|
166091
166799
|
return {
|
|
166092
|
-
value: import_comment_json12.parse(readFileSync18(
|
|
166800
|
+
value: import_comment_json12.parse(readFileSync18(path6, "utf-8"))
|
|
166093
166801
|
};
|
|
166094
166802
|
} catch (error51) {
|
|
166095
166803
|
return {
|
|
@@ -166101,17 +166809,31 @@ function readJsonc4(path5) {
|
|
|
166101
166809
|
function packagesFrom(settings) {
|
|
166102
166810
|
return Array.isArray(settings.packages) ? settings.packages : [];
|
|
166103
166811
|
}
|
|
166812
|
+
function piPluginDirCandidates(packages, cwd) {
|
|
166813
|
+
const dirs = [];
|
|
166814
|
+
const agentDir = getPiAgentConfigDir();
|
|
166815
|
+
for (const entry of packages) {
|
|
166816
|
+
const spec = typeof entry === "string" ? entry.trim() : "";
|
|
166817
|
+
if (!spec || spec.startsWith("npm:"))
|
|
166818
|
+
continue;
|
|
166819
|
+
const resolved = isAbsolute3(spec) ? spec : join23(agentDir, spec);
|
|
166820
|
+
dirs.push(resolved);
|
|
166821
|
+
}
|
|
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")));
|
|
166825
|
+
}
|
|
166104
166826
|
function projectConfigPath(cwd) {
|
|
166105
|
-
return
|
|
166827
|
+
return join23(cwd, ".pi", "magic-context.jsonc");
|
|
166106
166828
|
}
|
|
166107
|
-
function readConfigForEmbedding(
|
|
166108
|
-
if (!
|
|
166829
|
+
function readConfigForEmbedding(path6) {
|
|
166830
|
+
if (!existsSync24(path6))
|
|
166109
166831
|
return null;
|
|
166110
166832
|
try {
|
|
166111
|
-
const rawText = readFileSync18(
|
|
166833
|
+
const rawText = readFileSync18(path6, "utf-8");
|
|
166112
166834
|
const substituted = substituteConfigVariables({
|
|
166113
166835
|
text: rawText,
|
|
166114
|
-
configPath:
|
|
166836
|
+
configPath: path6
|
|
166115
166837
|
});
|
|
166116
166838
|
return import_comment_json12.parse(substituted.text);
|
|
166117
166839
|
} catch {
|
|
@@ -166166,52 +166888,52 @@ function countTable(db, table) {
|
|
|
166166
166888
|
}
|
|
166167
166889
|
}
|
|
166168
166890
|
function cacheRoots() {
|
|
166169
|
-
const home =
|
|
166170
|
-
const cacheHome = process.env.XDG_CACHE_HOME ||
|
|
166891
|
+
const home = homedir17();
|
|
166892
|
+
const cacheHome = process.env.XDG_CACHE_HOME || join23(home, ".cache");
|
|
166171
166893
|
return [
|
|
166172
|
-
|
|
166173
|
-
|
|
166174
|
-
|
|
166175
|
-
|
|
166176
|
-
|
|
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")
|
|
166177
166899
|
];
|
|
166178
166900
|
}
|
|
166179
166901
|
function findPiMagicContextCacheDirs(self, force = false) {
|
|
166180
166902
|
const found = new Map;
|
|
166181
|
-
const visit = (
|
|
166182
|
-
if (depth < 0 || !
|
|
166903
|
+
const visit = (path6, depth) => {
|
|
166904
|
+
if (depth < 0 || !existsSync24(path6))
|
|
166183
166905
|
return;
|
|
166184
166906
|
let stat;
|
|
166185
166907
|
try {
|
|
166186
|
-
stat = statSync7(
|
|
166908
|
+
stat = statSync7(path6);
|
|
166187
166909
|
} catch {
|
|
166188
166910
|
return;
|
|
166189
166911
|
}
|
|
166190
166912
|
if (!stat.isDirectory())
|
|
166191
166913
|
return;
|
|
166192
|
-
const packageJson =
|
|
166193
|
-
if (
|
|
166914
|
+
const packageJson = join23(path6, "package.json");
|
|
166915
|
+
if (existsSync24(packageJson)) {
|
|
166194
166916
|
try {
|
|
166195
166917
|
const pkg = JSON.parse(readFileSync18(packageJson, "utf-8"));
|
|
166196
166918
|
const name2 = typeof pkg.name === "string" ? pkg.name : "";
|
|
166197
166919
|
const version2 = typeof pkg.version === "string" ? pkg.version : undefined;
|
|
166198
|
-
if (name2 === PACKAGE_NAME ||
|
|
166920
|
+
if (name2 === PACKAGE_NAME || path6.includes("pi-magic-context")) {
|
|
166199
166921
|
if (force || !version2 || version2 !== self)
|
|
166200
|
-
found.set(
|
|
166922
|
+
found.set(path6, { path: path6, version: version2 });
|
|
166201
166923
|
}
|
|
166202
166924
|
} catch {
|
|
166203
|
-
if (
|
|
166204
|
-
found.set(
|
|
166925
|
+
if (path6.includes("pi-magic-context"))
|
|
166926
|
+
found.set(path6, { path: path6 });
|
|
166205
166927
|
}
|
|
166206
166928
|
}
|
|
166207
166929
|
let entries = [];
|
|
166208
166930
|
try {
|
|
166209
|
-
entries = readdirSync4(
|
|
166931
|
+
entries = readdirSync4(path6);
|
|
166210
166932
|
} catch {
|
|
166211
166933
|
return;
|
|
166212
166934
|
}
|
|
166213
166935
|
for (const entry of entries)
|
|
166214
|
-
visit(
|
|
166936
|
+
visit(join23(path6, entry), depth - 1);
|
|
166215
166937
|
};
|
|
166216
166938
|
for (const root of cacheRoots())
|
|
166217
166939
|
visit(root, 5);
|
|
@@ -166248,7 +166970,7 @@ async function runHealthChecks(options) {
|
|
|
166248
166970
|
}
|
|
166249
166971
|
const settingsPath = getPiUserExtensionsPath();
|
|
166250
166972
|
let packages = [];
|
|
166251
|
-
if (!
|
|
166973
|
+
if (!existsSync24(settingsPath)) {
|
|
166252
166974
|
add(results, "warn", `Pi settings not found at ${settingsPath}`);
|
|
166253
166975
|
repairPlan.addPackageEntry = true;
|
|
166254
166976
|
} else {
|
|
@@ -166268,24 +166990,24 @@ async function runHealthChecks(options) {
|
|
|
166268
166990
|
}
|
|
166269
166991
|
const userConfigPath = getPiUserConfigPath();
|
|
166270
166992
|
const projectPath = projectConfigPath(options.cwd);
|
|
166271
|
-
for (const [label,
|
|
166993
|
+
for (const [label, path6, required2] of [
|
|
166272
166994
|
["user", userConfigPath, true],
|
|
166273
166995
|
["project", projectPath, false]
|
|
166274
166996
|
]) {
|
|
166275
|
-
if (!
|
|
166997
|
+
if (!existsSync24(path6)) {
|
|
166276
166998
|
if (required2) {
|
|
166277
|
-
add(results, "warn", `No ${label} magic-context.jsonc found at ${
|
|
166999
|
+
add(results, "warn", `No ${label} magic-context.jsonc found at ${path6}`);
|
|
166278
167000
|
repairPlan.writeUserConfig = true;
|
|
166279
167001
|
} else {
|
|
166280
|
-
add(results, "info", `No project Pi magic-context.jsonc found at ${
|
|
167002
|
+
add(results, "info", `No project Pi magic-context.jsonc found at ${path6}`);
|
|
166281
167003
|
}
|
|
166282
167004
|
continue;
|
|
166283
167005
|
}
|
|
166284
|
-
const parsed = readJsonc4(
|
|
167006
|
+
const parsed = readJsonc4(path6);
|
|
166285
167007
|
if (parsed.error)
|
|
166286
167008
|
add(results, "fail", `${label} magic-context.jsonc is invalid JSONC: ${parsed.error}`);
|
|
166287
167009
|
else
|
|
166288
|
-
add(results, "pass", `${label} magic-context.jsonc is valid JSONC: ${
|
|
167010
|
+
add(results, "pass", `${label} magic-context.jsonc is valid JSONC: ${path6}`);
|
|
166289
167011
|
}
|
|
166290
167012
|
const loadedConfig = loadPiConfig({ cwd: options.cwd });
|
|
166291
167013
|
if (loadedConfig.warnings.length > 0) {
|
|
@@ -166305,8 +167027,8 @@ async function runHealthChecks(options) {
|
|
|
166305
167027
|
add(results, "pass", `historian.model "${historianModel}" has thinking_level "${historianThinkingLevel}" configured`);
|
|
166306
167028
|
}
|
|
166307
167029
|
const storageDir = getMagicContextStorageDir();
|
|
166308
|
-
const dbPath =
|
|
166309
|
-
const existedBeforeOpen =
|
|
167030
|
+
const dbPath = join23(storageDir, "context.db");
|
|
167031
|
+
const existedBeforeOpen = existsSync24(dbPath);
|
|
166310
167032
|
if (existedBeforeOpen)
|
|
166311
167033
|
add(results, "pass", `Shared context DB exists at ${dbPath}`);
|
|
166312
167034
|
else
|
|
@@ -166369,7 +167091,23 @@ async function runHealthChecks(options) {
|
|
|
166369
167091
|
} else if (loadedConfig.config.embedding.provider === "off") {
|
|
166370
167092
|
add(results, "info", "Embedding provider disabled");
|
|
166371
167093
|
} else {
|
|
166372
|
-
|
|
167094
|
+
let runtimeReported = false;
|
|
167095
|
+
for (const pluginDir of piPluginDirCandidates(packages, options.cwd)) {
|
|
167096
|
+
const runtime = checkLocalEmbeddingRuntimeByResolution(pluginDir);
|
|
167097
|
+
if (runtime.state === "ok") {
|
|
167098
|
+
add(results, "pass", `Embedding provider: ${loadedConfig.config.embedding.provider} (native runtime present)`);
|
|
167099
|
+
runtimeReported = true;
|
|
167100
|
+
break;
|
|
167101
|
+
}
|
|
167102
|
+
if (runtime.state === "package-missing" || runtime.state === "binary-missing") {
|
|
167103
|
+
add(results, "warn", `Embedding provider: local — native runtime (onnxruntime-node) is ${runtime.state === "package-missing" ? "not installed" : "missing its platform binary"}. Local embeddings won't work. Fix: reinstall the plugin, or set ` + "`embedding.provider` to `openai-compatible` (LM Studio / Ollama) or `off`. " + "Existing memories are unaffected.");
|
|
167104
|
+
runtimeReported = true;
|
|
167105
|
+
break;
|
|
167106
|
+
}
|
|
167107
|
+
}
|
|
167108
|
+
if (!runtimeReported) {
|
|
167109
|
+
add(results, "pass", `Embedding provider: ${loadedConfig.config.embedding.provider}`);
|
|
167110
|
+
}
|
|
166373
167111
|
}
|
|
166374
167112
|
const piEntries = packages.filter(isPiMagicContextPackageEntry).map(describePiPackageEntry);
|
|
166375
167113
|
if (piEntries.length > 1) {
|
|
@@ -166391,7 +167129,7 @@ async function runHealthChecks(options) {
|
|
|
166391
167129
|
add(results, "pass", "Pi extension cache clean (no stale cached package found)");
|
|
166392
167130
|
}
|
|
166393
167131
|
const logPath = getMagicContextLogPath2("pi");
|
|
166394
|
-
if (
|
|
167132
|
+
if (existsSync24(logPath)) {
|
|
166395
167133
|
const stat = statSync7(logPath);
|
|
166396
167134
|
const sizeKb = (stat.size / 1024).toFixed(0);
|
|
166397
167135
|
const lines = readFileSync18(logPath, "utf-8").split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
@@ -166427,13 +167165,13 @@ async function runHealthChecks(options) {
|
|
|
166427
167165
|
}
|
|
166428
167166
|
return { results, repairPlan, ...summarize(results) };
|
|
166429
167167
|
}
|
|
166430
|
-
function writeDefaultMagicContextConfig(
|
|
166431
|
-
mkdirSync7(
|
|
167168
|
+
function writeDefaultMagicContextConfig(path6) {
|
|
167169
|
+
mkdirSync7(dirname10(path6), { recursive: true });
|
|
166432
167170
|
const config2 = {
|
|
166433
167171
|
$schema: "https://raw.githubusercontent.com/cortexkit/magic-context/master/assets/magic-context.schema.json",
|
|
166434
167172
|
...MagicContextConfigSchema.parse({})
|
|
166435
167173
|
};
|
|
166436
|
-
writeFileSync11(
|
|
167174
|
+
writeFileSync11(path6, `${import_comment_json12.stringify(config2, null, 2)}
|
|
166437
167175
|
`);
|
|
166438
167176
|
}
|
|
166439
167177
|
function repair(plan, prompts) {
|
|
@@ -166450,7 +167188,7 @@ function repair(plan, prompts) {
|
|
|
166450
167188
|
}
|
|
166451
167189
|
if (plan.writeUserConfig) {
|
|
166452
167190
|
const configPath = getPiUserConfigPath();
|
|
166453
|
-
if (!
|
|
167191
|
+
if (!existsSync24(configPath)) {
|
|
166454
167192
|
try {
|
|
166455
167193
|
writeDefaultMagicContextConfig(configPath);
|
|
166456
167194
|
prompts.log.success(`Wrote default Magic Context config to ${configPath}`);
|
|
@@ -166460,13 +167198,13 @@ function repair(plan, prompts) {
|
|
|
166460
167198
|
}
|
|
166461
167199
|
}
|
|
166462
167200
|
}
|
|
166463
|
-
for (const
|
|
167201
|
+
for (const path6 of plan.clearCachePaths) {
|
|
166464
167202
|
try {
|
|
166465
|
-
rmSync2(
|
|
166466
|
-
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}`);
|
|
166467
167205
|
fixed += 1;
|
|
166468
167206
|
} catch (error51) {
|
|
166469
|
-
console.error(`FAIL Could not clear ${
|
|
167207
|
+
console.error(`FAIL Could not clear ${path6}: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
166470
167208
|
}
|
|
166471
167209
|
}
|
|
166472
167210
|
return fixed;
|
|
@@ -166591,7 +167329,7 @@ async function runDoctor2(options = {}) {
|
|
|
166591
167329
|
prompts.outro(first.fail > 0 ? "Doctor found failures" : "Doctor complete");
|
|
166592
167330
|
return first.fail > 0 ? 1 : 0;
|
|
166593
167331
|
}
|
|
166594
|
-
function
|
|
167332
|
+
function valueAfter2(args, flag) {
|
|
166595
167333
|
const index = args.indexOf(flag);
|
|
166596
167334
|
if (index === -1)
|
|
166597
167335
|
return null;
|
|
@@ -166601,7 +167339,7 @@ function valueAfter(args, flag) {
|
|
|
166601
167339
|
return next;
|
|
166602
167340
|
}
|
|
166603
167341
|
function parseDoctorArgs(args) {
|
|
166604
|
-
const rekeyV22DirIdentity =
|
|
167342
|
+
const rekeyV22DirIdentity = valueAfter2(args, "--rekey-v22-dir-identity");
|
|
166605
167343
|
return {
|
|
166606
167344
|
force: args.includes("--force"),
|
|
166607
167345
|
issue: args.includes("--issue"),
|
|
@@ -166621,6 +167359,7 @@ var init_doctor_pi = __esm(async () => {
|
|
|
166621
167359
|
init_data_path();
|
|
166622
167360
|
init_config2();
|
|
166623
167361
|
init_diagnostics_pi();
|
|
167362
|
+
init_embedding_runtime();
|
|
166624
167363
|
init_logs_pi();
|
|
166625
167364
|
init_paths();
|
|
166626
167365
|
init_pi_helpers();
|
|
@@ -166652,7 +167391,7 @@ var exports_doctor = {};
|
|
|
166652
167391
|
__export(exports_doctor, {
|
|
166653
167392
|
runDoctor: () => runDoctor3
|
|
166654
167393
|
});
|
|
166655
|
-
import { existsSync as
|
|
167394
|
+
import { existsSync as existsSync25, rmSync as rmSync3 } from "node:fs";
|
|
166656
167395
|
async function runDoctor3(options) {
|
|
166657
167396
|
if (options.clear)
|
|
166658
167397
|
return runClear();
|
|
@@ -166741,7 +167480,7 @@ async function runClear() {
|
|
|
166741
167480
|
const s = spinner();
|
|
166742
167481
|
s.start(`Clearing ${item.path}`);
|
|
166743
167482
|
try {
|
|
166744
|
-
if (
|
|
167483
|
+
if (existsSync25(item.path)) {
|
|
166745
167484
|
rmSync3(item.path, { recursive: true, force: true });
|
|
166746
167485
|
}
|
|
166747
167486
|
s.stop(`Cleared ${item.path}`);
|
|
@@ -166776,9 +167515,9 @@ var init_doctor = __esm(async () => {
|
|
|
166776
167515
|
});
|
|
166777
167516
|
|
|
166778
167517
|
// src/index.ts
|
|
166779
|
-
import { createRequire as
|
|
167518
|
+
import { createRequire as createRequire7 } from "node:module";
|
|
166780
167519
|
function getVersion() {
|
|
166781
|
-
const req =
|
|
167520
|
+
const req = createRequire7(import.meta.url);
|
|
166782
167521
|
for (const relPath of ["../../package.json", "../package.json"]) {
|
|
166783
167522
|
try {
|
|
166784
167523
|
const pkg = req(relPath);
|
|
@@ -166789,7 +167528,7 @@ function getVersion() {
|
|
|
166789
167528
|
}
|
|
166790
167529
|
return "0.0.0";
|
|
166791
167530
|
}
|
|
166792
|
-
function
|
|
167531
|
+
function valueAfter3(args, flag) {
|
|
166793
167532
|
const index = args.indexOf(flag);
|
|
166794
167533
|
if (index === -1)
|
|
166795
167534
|
return null;
|
|
@@ -166813,6 +167552,7 @@ function printUsage() {
|
|
|
166813
167552
|
console.log(" doctor --retry-v22-backfill Retry failed v22 memory backfill rows");
|
|
166814
167553
|
console.log(" doctor --rekey-v22-dir-identity <path> Re-key legacy dir identity rows");
|
|
166815
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");
|
|
166816
167556
|
console.log("");
|
|
166817
167557
|
console.log(" Harness selection:");
|
|
166818
167558
|
console.log(" --harness opencode Target OpenCode only");
|
|
@@ -166848,8 +167588,12 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
166848
167588
|
const { runMigrateCli: runMigrateCli2 } = await init_migrate().then(() => exports_migrate);
|
|
166849
167589
|
return runMigrateCli2(rest.slice(1));
|
|
166850
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
|
+
}
|
|
166851
167595
|
const { runDoctor: runDoctor4 } = await init_doctor().then(() => exports_doctor);
|
|
166852
|
-
const rekeyV22DirIdentity =
|
|
167596
|
+
const rekeyV22DirIdentity = valueAfter3(rest, "--rekey-v22-dir-identity");
|
|
166853
167597
|
return runDoctor4({
|
|
166854
167598
|
force: rest.includes("--force"),
|
|
166855
167599
|
issue: rest.includes("--issue"),
|