@cortexkit/magic-context 0.49.2 → 0.49.3
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 +1373 -710
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -13668,9 +13668,549 @@ var init_sqlite = __esm(async () => {
|
|
|
13668
13668
|
indexCoordinationState = new Int32Array(indexCoordinationBuffer);
|
|
13669
13669
|
});
|
|
13670
13670
|
|
|
13671
|
+
// src/lib/dashboard-install.ts
|
|
13672
|
+
import { execFile } from "node:child_process";
|
|
13673
|
+
import { createHash, createPublicKey, verify as cryptoVerify } from "node:crypto";
|
|
13674
|
+
import {
|
|
13675
|
+
accessSync,
|
|
13676
|
+
chmodSync as chmodSync3,
|
|
13677
|
+
constants,
|
|
13678
|
+
existsSync as existsSync6,
|
|
13679
|
+
mkdirSync as mkdirSync3,
|
|
13680
|
+
mkdtempSync,
|
|
13681
|
+
readFileSync as readFileSync5,
|
|
13682
|
+
renameSync as renameSync3,
|
|
13683
|
+
rmSync as rmSync3,
|
|
13684
|
+
statSync as statSync5,
|
|
13685
|
+
writeFileSync as writeFileSync3
|
|
13686
|
+
} from "node:fs";
|
|
13687
|
+
import { homedir as homedir6, tmpdir as tmpdir2 } from "node:os";
|
|
13688
|
+
import { dirname as dirname6, join as join5 } from "node:path";
|
|
13689
|
+
import { promisify } from "node:util";
|
|
13690
|
+
import { gunzipSync } from "node:zlib";
|
|
13691
|
+
function resolveDashboardChoice(argv, interactive) {
|
|
13692
|
+
if (argv.includes("--no-dashboard"))
|
|
13693
|
+
return "skip-flag";
|
|
13694
|
+
if (argv.includes("--dashboard"))
|
|
13695
|
+
return "install";
|
|
13696
|
+
return interactive ? "ask" : "skip-noninteractive";
|
|
13697
|
+
}
|
|
13698
|
+
function selectDashboardTarget(platform, arch) {
|
|
13699
|
+
if (arch !== "x64" && arch !== "arm64")
|
|
13700
|
+
return null;
|
|
13701
|
+
switch (platform) {
|
|
13702
|
+
case "darwin":
|
|
13703
|
+
return {
|
|
13704
|
+
platform: "macos",
|
|
13705
|
+
assetName: `magic-context-dashboard-darwin-${arch}.app.tar.gz`
|
|
13706
|
+
};
|
|
13707
|
+
case "linux":
|
|
13708
|
+
return {
|
|
13709
|
+
platform: "linux",
|
|
13710
|
+
assetName: `magic-context-dashboard-linux-${arch}.AppImage`
|
|
13711
|
+
};
|
|
13712
|
+
case "win32":
|
|
13713
|
+
return {
|
|
13714
|
+
platform: "windows",
|
|
13715
|
+
assetName: `magic-context-dashboard-windows-${arch}.exe`
|
|
13716
|
+
};
|
|
13717
|
+
default:
|
|
13718
|
+
return null;
|
|
13719
|
+
}
|
|
13720
|
+
}
|
|
13721
|
+
function compareVersions(a, b) {
|
|
13722
|
+
const parts = (value) => value.replace(/^v/, "").split(/[-+]/)[0].split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
13723
|
+
const left = parts(a);
|
|
13724
|
+
const right = parts(b);
|
|
13725
|
+
for (let i = 0;i < Math.max(left.length, right.length, 3); i++) {
|
|
13726
|
+
const diff = (left[i] ?? 0) - (right[i] ?? 0);
|
|
13727
|
+
if (diff !== 0)
|
|
13728
|
+
return diff;
|
|
13729
|
+
}
|
|
13730
|
+
return 0;
|
|
13731
|
+
}
|
|
13732
|
+
function formatSize(bytes) {
|
|
13733
|
+
return `${(bytes / 1e6).toFixed(1)} MB`;
|
|
13734
|
+
}
|
|
13735
|
+
function errorMessage(error) {
|
|
13736
|
+
if (error instanceof Error) {
|
|
13737
|
+
if (error.name === "TimeoutError")
|
|
13738
|
+
return "the request timed out";
|
|
13739
|
+
return error.message;
|
|
13740
|
+
}
|
|
13741
|
+
return String(error);
|
|
13742
|
+
}
|
|
13743
|
+
function verifyTauriSignature(data, signatureFile, publicKeyFile) {
|
|
13744
|
+
const decodeLines = (value) => Buffer.from(value.trim(), "base64").toString("utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
13745
|
+
const keyLine = decodeLines(publicKeyFile).find((line) => !line.startsWith("untrusted comment:"));
|
|
13746
|
+
const key = Buffer.from(keyLine ?? "", "base64");
|
|
13747
|
+
if (key.length !== 42 || key.subarray(0, 2).toString("latin1") !== "Ed") {
|
|
13748
|
+
return { ok: false, reason: "the public key is malformed" };
|
|
13749
|
+
}
|
|
13750
|
+
const keyId = key.subarray(2, 10);
|
|
13751
|
+
const publicKey = createPublicKey({
|
|
13752
|
+
key: Buffer.concat([ED25519_SPKI_PREFIX, key.subarray(10)]),
|
|
13753
|
+
format: "der",
|
|
13754
|
+
type: "spki"
|
|
13755
|
+
});
|
|
13756
|
+
const lines = decodeLines(signatureFile);
|
|
13757
|
+
const [untrusted, signatureLine, trustedLine, globalLine] = lines;
|
|
13758
|
+
if (lines.length < 4 || !untrusted?.startsWith("untrusted comment:") || !trustedLine?.startsWith("trusted comment: ")) {
|
|
13759
|
+
return { ok: false, reason: "the signature file is malformed" };
|
|
13760
|
+
}
|
|
13761
|
+
const signatureBlob = Buffer.from(signatureLine ?? "", "base64");
|
|
13762
|
+
const algorithm = signatureBlob.subarray(0, 2).toString("latin1");
|
|
13763
|
+
if (signatureBlob.length !== 74 || algorithm !== "ED" && algorithm !== "Ed") {
|
|
13764
|
+
return { ok: false, reason: "the signature file is malformed" };
|
|
13765
|
+
}
|
|
13766
|
+
if (!signatureBlob.subarray(2, 10).equals(keyId)) {
|
|
13767
|
+
return { ok: false, reason: "it was signed by a different key" };
|
|
13768
|
+
}
|
|
13769
|
+
const signature = signatureBlob.subarray(10);
|
|
13770
|
+
const message = algorithm === "ED" ? createHash("blake2b512").update(data).digest() : Buffer.from(data);
|
|
13771
|
+
if (!cryptoVerify(null, message, publicKey, signature)) {
|
|
13772
|
+
return { ok: false, reason: "the signature does not match the file" };
|
|
13773
|
+
}
|
|
13774
|
+
const trustedComment = Buffer.from(trustedLine.slice("trusted comment: ".length), "utf8");
|
|
13775
|
+
const globalSignature = Buffer.from(globalLine ?? "", "base64");
|
|
13776
|
+
if (globalSignature.length !== 64 || !cryptoVerify(null, Buffer.concat([signature, trustedComment]), publicKey, globalSignature)) {
|
|
13777
|
+
return { ok: false, reason: "the signature's trusted comment does not match" };
|
|
13778
|
+
}
|
|
13779
|
+
return { ok: true };
|
|
13780
|
+
}
|
|
13781
|
+
async function fetchLatestDashboardRelease(deps) {
|
|
13782
|
+
const response = await deps.fetch(deps.releasesApiUrl, {
|
|
13783
|
+
headers: { Accept: "application/vnd.github+json", "User-Agent": USER_AGENT },
|
|
13784
|
+
signal: AbortSignal.timeout(deps.apiTimeoutMs)
|
|
13785
|
+
});
|
|
13786
|
+
if (!response.ok) {
|
|
13787
|
+
throw new Error(`the GitHub releases API answered HTTP ${response.status}`);
|
|
13788
|
+
}
|
|
13789
|
+
const body = await response.json();
|
|
13790
|
+
if (!Array.isArray(body))
|
|
13791
|
+
throw new Error("the GitHub releases API returned an unexpected body");
|
|
13792
|
+
let best = null;
|
|
13793
|
+
for (const entry of body) {
|
|
13794
|
+
if (entry.draft === true || entry.prerelease === true)
|
|
13795
|
+
continue;
|
|
13796
|
+
const tag = typeof entry.tag_name === "string" ? entry.tag_name : "";
|
|
13797
|
+
const match = TAG_PATTERN.exec(tag);
|
|
13798
|
+
if (!match?.[1])
|
|
13799
|
+
continue;
|
|
13800
|
+
const version = match[1];
|
|
13801
|
+
if (best && compareVersions(version, best.version) <= 0)
|
|
13802
|
+
continue;
|
|
13803
|
+
const assets = [];
|
|
13804
|
+
for (const asset of entry.assets ?? []) {
|
|
13805
|
+
if (typeof asset.name !== "string" || typeof asset.browser_download_url !== "string") {
|
|
13806
|
+
continue;
|
|
13807
|
+
}
|
|
13808
|
+
assets.push({
|
|
13809
|
+
name: asset.name,
|
|
13810
|
+
size: typeof asset.size === "number" ? asset.size : 0,
|
|
13811
|
+
url: asset.browser_download_url
|
|
13812
|
+
});
|
|
13813
|
+
}
|
|
13814
|
+
best = {
|
|
13815
|
+
tag,
|
|
13816
|
+
version,
|
|
13817
|
+
htmlUrl: typeof entry.html_url === "string" ? entry.html_url : `${DASHBOARD_RELEASES_PAGE}/tag/${tag}`,
|
|
13818
|
+
assets
|
|
13819
|
+
};
|
|
13820
|
+
}
|
|
13821
|
+
if (!best)
|
|
13822
|
+
throw new Error("no published dashboard-v* release was found");
|
|
13823
|
+
return best;
|
|
13824
|
+
}
|
|
13825
|
+
async function download(deps, asset) {
|
|
13826
|
+
const response = await deps.fetch(asset.url, {
|
|
13827
|
+
headers: { "User-Agent": USER_AGENT },
|
|
13828
|
+
redirect: "follow",
|
|
13829
|
+
signal: AbortSignal.timeout(deps.downloadTimeoutMs)
|
|
13830
|
+
});
|
|
13831
|
+
if (!response.ok)
|
|
13832
|
+
throw new Error(`downloading ${asset.name} failed with HTTP ${response.status}`);
|
|
13833
|
+
return Buffer.from(await response.arrayBuffer());
|
|
13834
|
+
}
|
|
13835
|
+
function readMacAppVersion(appPath) {
|
|
13836
|
+
try {
|
|
13837
|
+
const plist = readFileSync5(join5(appPath, "Contents", "Info.plist"), "utf8");
|
|
13838
|
+
const match = /<key>CFBundleShortVersionString<\/key>\s*<string>([^<]+)<\/string>/.exec(plist);
|
|
13839
|
+
return match?.[1]?.trim() ?? null;
|
|
13840
|
+
} catch {
|
|
13841
|
+
return null;
|
|
13842
|
+
}
|
|
13843
|
+
}
|
|
13844
|
+
function macApplicationDirs(deps) {
|
|
13845
|
+
return [deps.macSystemApplicationsDir, join5(deps.homeDir, "Applications")];
|
|
13846
|
+
}
|
|
13847
|
+
function linuxVersionMarkerPath(homeDir) {
|
|
13848
|
+
return join5(homeDir, ".local", "share", "cortexkit", "dashboard-appimage.json");
|
|
13849
|
+
}
|
|
13850
|
+
function linuxAppImagePath(homeDir) {
|
|
13851
|
+
return join5(homeDir, ".local", "bin", DASHBOARD_APPIMAGE_NAME);
|
|
13852
|
+
}
|
|
13853
|
+
async function detectInstalledDashboard(target, deps) {
|
|
13854
|
+
switch (target.platform) {
|
|
13855
|
+
case "macos":
|
|
13856
|
+
for (const dir of macApplicationDirs(deps)) {
|
|
13857
|
+
const location = join5(dir, DASHBOARD_MAC_APP_NAME);
|
|
13858
|
+
if (existsSync6(location))
|
|
13859
|
+
return { location, version: readMacAppVersion(location) };
|
|
13860
|
+
}
|
|
13861
|
+
return null;
|
|
13862
|
+
case "linux": {
|
|
13863
|
+
const location = linuxAppImagePath(deps.homeDir);
|
|
13864
|
+
if (existsSync6(location)) {
|
|
13865
|
+
let version = null;
|
|
13866
|
+
try {
|
|
13867
|
+
const marker = JSON.parse(readFileSync5(linuxVersionMarkerPath(deps.homeDir), "utf8"));
|
|
13868
|
+
if (typeof marker.version === "string")
|
|
13869
|
+
version = marker.version;
|
|
13870
|
+
} catch {
|
|
13871
|
+
version = null;
|
|
13872
|
+
}
|
|
13873
|
+
return { location, version };
|
|
13874
|
+
}
|
|
13875
|
+
if (existsSync6(deps.linuxSystemBinaryPath)) {
|
|
13876
|
+
return { location: deps.linuxSystemBinaryPath, version: null };
|
|
13877
|
+
}
|
|
13878
|
+
return null;
|
|
13879
|
+
}
|
|
13880
|
+
case "windows":
|
|
13881
|
+
return deps.readWindowsInstall();
|
|
13882
|
+
}
|
|
13883
|
+
}
|
|
13884
|
+
function isWritableDir(path) {
|
|
13885
|
+
try {
|
|
13886
|
+
if (!statSync5(path).isDirectory())
|
|
13887
|
+
return false;
|
|
13888
|
+
accessSync(path, constants.W_OK);
|
|
13889
|
+
return true;
|
|
13890
|
+
} catch {
|
|
13891
|
+
return false;
|
|
13892
|
+
}
|
|
13893
|
+
}
|
|
13894
|
+
function unsafeArchivePath(path) {
|
|
13895
|
+
if (path.startsWith("/") || path.startsWith("\\") || /^[A-Za-z]:/.test(path))
|
|
13896
|
+
return true;
|
|
13897
|
+
return path.split(/[/\\]/).some((segment) => segment === "..");
|
|
13898
|
+
}
|
|
13899
|
+
function tarString(block, start, length) {
|
|
13900
|
+
const field = block.subarray(start, start + length);
|
|
13901
|
+
const end = field.indexOf(0);
|
|
13902
|
+
return field.subarray(0, end === -1 ? field.length : end).toString("utf8");
|
|
13903
|
+
}
|
|
13904
|
+
function tarSize(block) {
|
|
13905
|
+
const field = block.subarray(124, 136);
|
|
13906
|
+
if ((field[0] ?? 0) & 128) {
|
|
13907
|
+
let value = (field[0] ?? 0) & 127;
|
|
13908
|
+
for (const byte of field.subarray(1))
|
|
13909
|
+
value = value * 256 + byte;
|
|
13910
|
+
return value;
|
|
13911
|
+
}
|
|
13912
|
+
const text = tarString(block, 124, 12).trim();
|
|
13913
|
+
return text === "" ? 0 : Number.parseInt(text, 8);
|
|
13914
|
+
}
|
|
13915
|
+
function paxRecords(data) {
|
|
13916
|
+
const records = new Map;
|
|
13917
|
+
let offset = 0;
|
|
13918
|
+
while (offset < data.length) {
|
|
13919
|
+
const space = data.indexOf(32, offset);
|
|
13920
|
+
if (space === -1)
|
|
13921
|
+
break;
|
|
13922
|
+
const length = Number.parseInt(data.subarray(offset, space).toString("utf8"), 10);
|
|
13923
|
+
if (!Number.isFinite(length) || length <= 0)
|
|
13924
|
+
break;
|
|
13925
|
+
const record = data.subarray(space + 1, offset + length - 1).toString("utf8");
|
|
13926
|
+
const equals = record.indexOf("=");
|
|
13927
|
+
if (equals !== -1)
|
|
13928
|
+
records.set(record.slice(0, equals), record.slice(equals + 1));
|
|
13929
|
+
offset += length;
|
|
13930
|
+
}
|
|
13931
|
+
return records;
|
|
13932
|
+
}
|
|
13933
|
+
function findUnsafeTarEntry(tar) {
|
|
13934
|
+
const globalPax = new Map;
|
|
13935
|
+
let nextPax = new Map;
|
|
13936
|
+
let longName = null;
|
|
13937
|
+
let longLink = null;
|
|
13938
|
+
let offset = 0;
|
|
13939
|
+
while (offset + 512 <= tar.length) {
|
|
13940
|
+
const header = tar.subarray(offset, offset + 512);
|
|
13941
|
+
if (header.every((byte) => byte === 0))
|
|
13942
|
+
return null;
|
|
13943
|
+
const size = tarSize(header);
|
|
13944
|
+
if (!Number.isFinite(size) || size < 0)
|
|
13945
|
+
return "an entry has an unreadable size";
|
|
13946
|
+
const dataStart = offset + 512;
|
|
13947
|
+
const data = tar.subarray(dataStart, dataStart + size);
|
|
13948
|
+
offset = dataStart + Math.ceil(size / 512) * 512;
|
|
13949
|
+
const type = String.fromCharCode(header[156] ?? 0);
|
|
13950
|
+
if (type === "x" || type === "g") {
|
|
13951
|
+
const records = paxRecords(data);
|
|
13952
|
+
const target = type === "g" ? globalPax : nextPax;
|
|
13953
|
+
for (const [key, value] of records)
|
|
13954
|
+
target.set(key, value);
|
|
13955
|
+
continue;
|
|
13956
|
+
}
|
|
13957
|
+
if (type === "L" || type === "K") {
|
|
13958
|
+
const value = tarString(data, 0, data.length);
|
|
13959
|
+
if (type === "L")
|
|
13960
|
+
longName = value;
|
|
13961
|
+
else
|
|
13962
|
+
longLink = value;
|
|
13963
|
+
continue;
|
|
13964
|
+
}
|
|
13965
|
+
const prefix = tarString(header, 345, 155);
|
|
13966
|
+
const isUstar = header.subarray(257, 262).toString("latin1") === "ustar";
|
|
13967
|
+
const headerName = tarString(header, 0, 100);
|
|
13968
|
+
const name = nextPax.get("path") ?? longName ?? globalPax.get("path") ?? (isUstar && prefix ? `${prefix}/${headerName}` : headerName);
|
|
13969
|
+
const link = nextPax.get("linkpath") ?? longLink ?? globalPax.get("linkpath") ?? tarString(header, 157, 100);
|
|
13970
|
+
nextPax = new Map;
|
|
13971
|
+
longName = null;
|
|
13972
|
+
longLink = null;
|
|
13973
|
+
if (unsafeArchivePath(name))
|
|
13974
|
+
return `entry "${name}" points outside the archive`;
|
|
13975
|
+
switch (type) {
|
|
13976
|
+
case "0":
|
|
13977
|
+
case "\x00":
|
|
13978
|
+
case "7":
|
|
13979
|
+
case "5":
|
|
13980
|
+
break;
|
|
13981
|
+
case "1":
|
|
13982
|
+
case "2":
|
|
13983
|
+
if (link === "" || unsafeArchivePath(link)) {
|
|
13984
|
+
return `link "${name}" -> "${link}" points outside the archive`;
|
|
13985
|
+
}
|
|
13986
|
+
break;
|
|
13987
|
+
default:
|
|
13988
|
+
return `entry "${name}" has unsupported type "${type}"`;
|
|
13989
|
+
}
|
|
13990
|
+
}
|
|
13991
|
+
return offset === tar.length ? null : "the archive is truncated";
|
|
13992
|
+
}
|
|
13993
|
+
async function installMac(data, deps, installed) {
|
|
13994
|
+
let destinationDir;
|
|
13995
|
+
if (installed) {
|
|
13996
|
+
destinationDir = dirname6(installed.location);
|
|
13997
|
+
} else if (isWritableDir(deps.macSystemApplicationsDir)) {
|
|
13998
|
+
destinationDir = deps.macSystemApplicationsDir;
|
|
13999
|
+
} else {
|
|
14000
|
+
destinationDir = join5(deps.homeDir, "Applications");
|
|
14001
|
+
deps.log.info(`${deps.macSystemApplicationsDir} is not writable, so the app goes to ${destinationDir} (setup never asks for sudo).`);
|
|
14002
|
+
}
|
|
14003
|
+
const unsafe = findUnsafeTarEntry(gunzipSync(data));
|
|
14004
|
+
if (unsafe)
|
|
14005
|
+
throw new Error(`the app archive is unsafe to extract: ${unsafe}`);
|
|
14006
|
+
mkdirSync3(destinationDir, { recursive: true });
|
|
14007
|
+
const staging = mkdtempSync(join5(destinationDir, ".magic-context-dashboard-"));
|
|
14008
|
+
try {
|
|
14009
|
+
const archive = join5(staging, "dashboard.app.tar.gz");
|
|
14010
|
+
writeFileSync3(archive, data);
|
|
14011
|
+
const extractDir = join5(staging, "extracted");
|
|
14012
|
+
mkdirSync3(extractDir);
|
|
14013
|
+
await deps.extractTarGz(archive, extractDir);
|
|
14014
|
+
const extracted = join5(extractDir, DASHBOARD_MAC_APP_NAME);
|
|
14015
|
+
if (!existsSync6(extracted)) {
|
|
14016
|
+
throw new Error(`the archive did not contain ${DASHBOARD_MAC_APP_NAME}`);
|
|
14017
|
+
}
|
|
14018
|
+
const finalPath = join5(destinationDir, DASHBOARD_MAC_APP_NAME);
|
|
14019
|
+
const previous = join5(staging, "previous.app");
|
|
14020
|
+
const hadPrevious = existsSync6(finalPath);
|
|
14021
|
+
if (hadPrevious)
|
|
14022
|
+
renameSync3(finalPath, previous);
|
|
14023
|
+
try {
|
|
14024
|
+
renameSync3(extracted, finalPath);
|
|
14025
|
+
} catch (error) {
|
|
14026
|
+
if (hadPrevious)
|
|
14027
|
+
renameSync3(previous, finalPath);
|
|
14028
|
+
throw error;
|
|
14029
|
+
}
|
|
14030
|
+
return finalPath;
|
|
14031
|
+
} finally {
|
|
14032
|
+
rmSync3(staging, { recursive: true, force: true });
|
|
14033
|
+
}
|
|
14034
|
+
}
|
|
14035
|
+
function installLinux(data, version, deps) {
|
|
14036
|
+
const finalPath = linuxAppImagePath(deps.homeDir);
|
|
14037
|
+
mkdirSync3(dirname6(finalPath), { recursive: true });
|
|
14038
|
+
const partial = `${finalPath}.partial-${process.pid}`;
|
|
14039
|
+
try {
|
|
14040
|
+
writeFileSync3(partial, data, { mode: 493 });
|
|
14041
|
+
chmodSync3(partial, 493);
|
|
14042
|
+
renameSync3(partial, finalPath);
|
|
14043
|
+
} finally {
|
|
14044
|
+
rmSync3(partial, { force: true });
|
|
14045
|
+
}
|
|
14046
|
+
const marker = linuxVersionMarkerPath(deps.homeDir);
|
|
14047
|
+
mkdirSync3(dirname6(marker), { recursive: true });
|
|
14048
|
+
writeFileSync3(marker, `${JSON.stringify({ version, path: finalPath }, null, 2)}
|
|
14049
|
+
`);
|
|
14050
|
+
return finalPath;
|
|
14051
|
+
}
|
|
14052
|
+
async function installWindows(data, asset, deps) {
|
|
14053
|
+
const dir = mkdtempSync(join5(deps.tempRoot, "magic-context-dashboard-"));
|
|
14054
|
+
try {
|
|
14055
|
+
const installer = join5(dir, asset.name);
|
|
14056
|
+
writeFileSync3(installer, data);
|
|
14057
|
+
deps.log.info("Running the dashboard installer (per-user install, no administrator rights).");
|
|
14058
|
+
await deps.runWindowsInstaller(installer);
|
|
14059
|
+
} finally {
|
|
14060
|
+
try {
|
|
14061
|
+
rmSync3(dir, { recursive: true, force: true });
|
|
14062
|
+
} catch {}
|
|
14063
|
+
}
|
|
14064
|
+
const installed = await deps.readWindowsInstall().catch(() => null);
|
|
14065
|
+
return installed?.location ?? "the Start menu";
|
|
14066
|
+
}
|
|
14067
|
+
async function runOffer(argv, deps, state) {
|
|
14068
|
+
const choice = resolveDashboardChoice(argv, deps.interactive);
|
|
14069
|
+
if (choice === "skip-flag") {
|
|
14070
|
+
deps.log.info("Skipping the Magic Context Dashboard (--no-dashboard).");
|
|
14071
|
+
return;
|
|
14072
|
+
}
|
|
14073
|
+
if (choice === "skip-noninteractive") {
|
|
14074
|
+
deps.log.info(`Skipped the Magic Context Dashboard offer (non-interactive run). Pass --dashboard to install it, or download it from ${DASHBOARD_RELEASES_PAGE}`);
|
|
14075
|
+
return;
|
|
14076
|
+
}
|
|
14077
|
+
const target = selectDashboardTarget(deps.platform, deps.arch);
|
|
14078
|
+
if (!target) {
|
|
14079
|
+
deps.log.info(`No Magic Context Dashboard build exists for ${deps.platform}/${deps.arch}; see ${DASHBOARD_RELEASES_PAGE}`);
|
|
14080
|
+
return;
|
|
14081
|
+
}
|
|
14082
|
+
const release = await fetchLatestDashboardRelease(deps);
|
|
14083
|
+
state.link = release.htmlUrl;
|
|
14084
|
+
const asset = release.assets.find((candidate) => candidate.name === target.assetName);
|
|
14085
|
+
if (!asset)
|
|
14086
|
+
throw new Error(`release ${release.tag} has no ${target.assetName}`);
|
|
14087
|
+
const signatureAsset = release.assets.find((candidate) => candidate.name === `${target.assetName}.sig`);
|
|
14088
|
+
if (!signatureAsset) {
|
|
14089
|
+
throw new Error(`release ${release.tag} publishes no signature for ${target.assetName}, so it cannot be verified`);
|
|
14090
|
+
}
|
|
14091
|
+
const installed = await detectInstalledDashboard(target, deps);
|
|
14092
|
+
const size = formatSize(asset.size);
|
|
14093
|
+
let question;
|
|
14094
|
+
if (installed) {
|
|
14095
|
+
if (installed.version === null) {
|
|
14096
|
+
deps.log.info(`Magic Context Dashboard is already installed at ${installed.location} (version unknown); it updates itself from inside the app.`);
|
|
14097
|
+
return;
|
|
14098
|
+
}
|
|
14099
|
+
if (compareVersions(installed.version, release.version) >= 0) {
|
|
14100
|
+
deps.log.info(`Magic Context Dashboard v${installed.version} is already installed at ${installed.location} (latest release: v${release.version}).`);
|
|
14101
|
+
return;
|
|
14102
|
+
}
|
|
14103
|
+
deps.log.info(`Magic Context Dashboard v${installed.version} is installed at ${installed.location}; v${release.version} is available.`);
|
|
14104
|
+
question = `Update the Magic Context Dashboard to v${release.version}? (${size} download)`;
|
|
14105
|
+
} else {
|
|
14106
|
+
question = `Install the Magic Context Dashboard (desktop app for memories, sessions and settings)? v${release.version}, ${size} download`;
|
|
14107
|
+
}
|
|
14108
|
+
if (choice === "ask" && !await deps.confirm(question, true)) {
|
|
14109
|
+
deps.log.info(`Skipped the Magic Context Dashboard. It is available at ${release.htmlUrl}`);
|
|
14110
|
+
return;
|
|
14111
|
+
}
|
|
14112
|
+
deps.log.step(`Downloading ${asset.name} (${size})…`);
|
|
14113
|
+
const [data, signature] = await Promise.all([
|
|
14114
|
+
download(deps, asset),
|
|
14115
|
+
download(deps, signatureAsset)
|
|
14116
|
+
]);
|
|
14117
|
+
const verdict = verifyTauriSignature(data, signature.toString("utf8"), deps.publicKey);
|
|
14118
|
+
if (!verdict.ok) {
|
|
14119
|
+
throw new Error(`${asset.name} failed signature verification (${verdict.reason}); nothing was installed`);
|
|
14120
|
+
}
|
|
14121
|
+
deps.log.info(`Verified ${asset.name} against the dashboard's updater signing key.`);
|
|
14122
|
+
let location;
|
|
14123
|
+
switch (target.platform) {
|
|
14124
|
+
case "macos":
|
|
14125
|
+
location = await installMac(data, deps, installed);
|
|
14126
|
+
break;
|
|
14127
|
+
case "linux":
|
|
14128
|
+
deps.log.info("Installing the AppImage to ~/.local/bin: it needs no root, runs on any distribution, and is what the app's own updater replaces (the .deb/.rpm packages would need sudo).");
|
|
14129
|
+
location = installLinux(data, release.version, deps);
|
|
14130
|
+
break;
|
|
14131
|
+
case "windows":
|
|
14132
|
+
location = await installWindows(data, asset, deps);
|
|
14133
|
+
break;
|
|
14134
|
+
}
|
|
14135
|
+
deps.log.success(`Installed Magic Context Dashboard v${release.version} → ${location}`);
|
|
14136
|
+
}
|
|
14137
|
+
function isInteractiveTerminal(stdinIsTTY, stdoutIsTTY, env) {
|
|
14138
|
+
const ci = env.CI?.trim().toLowerCase();
|
|
14139
|
+
const isCi = ci !== undefined && ci !== "" && ci !== "0" && ci !== "false";
|
|
14140
|
+
return Boolean(stdinIsTTY && stdoutIsTTY) && !isCi;
|
|
14141
|
+
}
|
|
14142
|
+
async function readWindowsInstallFromRegistry() {
|
|
14143
|
+
for (const hive of ["HKCU", "HKLM"]) {
|
|
14144
|
+
const key = `${hive}\\${WINDOWS_UNINSTALL_KEY}`;
|
|
14145
|
+
try {
|
|
14146
|
+
const { stdout } = await execFileAsync("reg", ["query", key], { windowsHide: true });
|
|
14147
|
+
const values = new Map;
|
|
14148
|
+
for (const line of stdout.split(/\r?\n/)) {
|
|
14149
|
+
const match = /^\s+(\S+)\s+REG_\w+\s+(.*)$/.exec(line);
|
|
14150
|
+
if (match?.[1] && match[2] !== undefined)
|
|
14151
|
+
values.set(match[1], match[2].trim());
|
|
14152
|
+
}
|
|
14153
|
+
return {
|
|
14154
|
+
location: values.get("InstallLocation") || key,
|
|
14155
|
+
version: values.get("DisplayVersion") || null
|
|
14156
|
+
};
|
|
14157
|
+
} catch {}
|
|
14158
|
+
}
|
|
14159
|
+
return null;
|
|
14160
|
+
}
|
|
14161
|
+
function defaultDashboardInstallDeps() {
|
|
14162
|
+
return {
|
|
14163
|
+
log: log3,
|
|
14164
|
+
confirm: (message, defaultYes) => confirm2(message, defaultYes),
|
|
14165
|
+
interactive: isInteractiveTerminal(process.stdin.isTTY, process.stdout.isTTY, process.env),
|
|
14166
|
+
platform: process.platform,
|
|
14167
|
+
arch: process.arch,
|
|
14168
|
+
homeDir: homedir6(),
|
|
14169
|
+
fetch: globalThis.fetch,
|
|
14170
|
+
releasesApiUrl: DASHBOARD_RELEASES_API,
|
|
14171
|
+
publicKey: DASHBOARD_UPDATER_PUBLIC_KEY,
|
|
14172
|
+
apiTimeoutMs: 15000,
|
|
14173
|
+
downloadTimeoutMs: 10 * 60000,
|
|
14174
|
+
macSystemApplicationsDir: "/Applications",
|
|
14175
|
+
linuxSystemBinaryPath: "/usr/bin/magic-context-dashboard",
|
|
14176
|
+
tempRoot: tmpdir2(),
|
|
14177
|
+
extractTarGz: async (archive, destinationDir) => {
|
|
14178
|
+
await execFileAsync("tar", ["-xzf", archive, "-C", destinationDir], {
|
|
14179
|
+
windowsHide: true
|
|
14180
|
+
});
|
|
14181
|
+
},
|
|
14182
|
+
runWindowsInstaller: async (installerPath) => {
|
|
14183
|
+
await execFileAsync(installerPath, ["/P"], { windowsHide: false });
|
|
14184
|
+
},
|
|
14185
|
+
readWindowsInstall: readWindowsInstallFromRegistry
|
|
14186
|
+
};
|
|
14187
|
+
}
|
|
14188
|
+
async function offerDashboardInstall(argv, overrides = {}) {
|
|
14189
|
+
const deps = { ...defaultDashboardInstallDeps(), ...overrides };
|
|
14190
|
+
const state = { link: DASHBOARD_RELEASES_PAGE };
|
|
14191
|
+
try {
|
|
14192
|
+
await runOffer(argv, deps, state);
|
|
14193
|
+
} catch (error) {
|
|
14194
|
+
if (isPromptCancelledError(error)) {
|
|
14195
|
+
deps.log.info("Skipped the Magic Context Dashboard.");
|
|
14196
|
+
return;
|
|
14197
|
+
}
|
|
14198
|
+
deps.log.warn(`Magic Context Dashboard was not installed: ${errorMessage(error)}. Install it manually from ${state.link}`);
|
|
14199
|
+
}
|
|
14200
|
+
}
|
|
14201
|
+
var execFileAsync, DASHBOARD_RELEASES_PAGE = "https://github.com/cortexkit/magic-context/releases", DASHBOARD_RELEASES_API = "https://api.github.com/repos/cortexkit/magic-context/releases?per_page=100", DASHBOARD_UPDATER_PUBLIC_KEY = "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDY5MUNBMDIxNjUxMEM2MkYKUldRdnhoQmxJYUFjYVU0SlNNbzRWMGJ3MndKOENIVDR0N0N6b0Jyd1l6TUNFTlpZTzV3RXlRYkEK", DASHBOARD_PRODUCT_NAME = "Magic Context Dashboard", DASHBOARD_MAC_APP_NAME, DASHBOARD_APPIMAGE_NAME = "magic-context-dashboard.AppImage", USER_AGENT = "magic-context-setup", TAG_PATTERN, ED25519_SPKI_PREFIX, WINDOWS_UNINSTALL_KEY;
|
|
14202
|
+
var init_dashboard_install = __esm(() => {
|
|
14203
|
+
init_prompts();
|
|
14204
|
+
execFileAsync = promisify(execFile);
|
|
14205
|
+
DASHBOARD_MAC_APP_NAME = `${DASHBOARD_PRODUCT_NAME}.app`;
|
|
14206
|
+
TAG_PATTERN = /^dashboard-v(\d+\.\d+\.\d+)$/;
|
|
14207
|
+
ED25519_SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex");
|
|
14208
|
+
WINDOWS_UNINSTALL_KEY = `Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${DASHBOARD_PRODUCT_NAME}`;
|
|
14209
|
+
});
|
|
14210
|
+
|
|
13671
14211
|
// src/lib/docs-proposal-gitignore.ts
|
|
13672
|
-
import { appendFileSync as appendFileSync2, existsSync as
|
|
13673
|
-
import { join as
|
|
14212
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync7, readFileSync as readFileSync6 } from "node:fs";
|
|
14213
|
+
import { join as join6 } from "node:path";
|
|
13674
14214
|
function coversProposalState(line) {
|
|
13675
14215
|
const rule = line.trim();
|
|
13676
14216
|
if (rule === "" || rule.startsWith("#") || rule.startsWith("!"))
|
|
@@ -13679,16 +14219,16 @@ function coversProposalState(line) {
|
|
|
13679
14219
|
return COVERING_PATHS.has(normalized);
|
|
13680
14220
|
}
|
|
13681
14221
|
function ensureDocsProposalGitignore(projectDir) {
|
|
13682
|
-
if (!
|
|
14222
|
+
if (!existsSync7(join6(projectDir, ".git")))
|
|
13683
14223
|
return { status: "not-a-repository" };
|
|
13684
|
-
const path =
|
|
14224
|
+
const path = join6(projectDir, ".gitignore");
|
|
13685
14225
|
try {
|
|
13686
|
-
const text =
|
|
14226
|
+
const text = existsSync7(path) ? readFileSync6(path, "utf8") : "";
|
|
13687
14227
|
if (text.split(/\r?\n/).some(coversProposalState))
|
|
13688
14228
|
return { status: "covered" };
|
|
13689
|
-
const nestedPath =
|
|
13690
|
-
if (
|
|
13691
|
-
const nested =
|
|
14229
|
+
const nestedPath = join6(projectDir, ".cortexkit", ".gitignore");
|
|
14230
|
+
if (existsSync7(nestedPath)) {
|
|
14231
|
+
const nested = readFileSync6(nestedPath, "utf8").split(/\r?\n/);
|
|
13692
14232
|
if (nested.some((line) => /^\/?magic-context(\/(\*\*?)?)?$/.test(line.trim()))) {
|
|
13693
14233
|
return { status: "covered" };
|
|
13694
14234
|
}
|
|
@@ -13712,8 +14252,8 @@ var init_docs_proposal_gitignore = __esm(() => {
|
|
|
13712
14252
|
});
|
|
13713
14253
|
|
|
13714
14254
|
// src/lib/find-on-path.ts
|
|
13715
|
-
import { accessSync, constants, existsSync as
|
|
13716
|
-
import { delimiter, join as
|
|
14255
|
+
import { accessSync as accessSync2, constants as constants2, existsSync as existsSync8, statSync as statSync6 } from "node:fs";
|
|
14256
|
+
import { delimiter, join as join7 } from "node:path";
|
|
13717
14257
|
function findOnPath(binary) {
|
|
13718
14258
|
const PATH = process.env.PATH;
|
|
13719
14259
|
if (typeof PATH !== "string" || PATH.length === 0)
|
|
@@ -13725,7 +14265,7 @@ function findOnPath(binary) {
|
|
|
13725
14265
|
if (!dir)
|
|
13726
14266
|
continue;
|
|
13727
14267
|
for (const candidate of candidates) {
|
|
13728
|
-
const fullPath =
|
|
14268
|
+
const fullPath = join7(dir, candidate);
|
|
13729
14269
|
if (isExecutableFile(fullPath, isWindows))
|
|
13730
14270
|
return fullPath;
|
|
13731
14271
|
}
|
|
@@ -13734,15 +14274,15 @@ function findOnPath(binary) {
|
|
|
13734
14274
|
}
|
|
13735
14275
|
function isExecutableFile(path, isWindows = process.platform === "win32") {
|
|
13736
14276
|
try {
|
|
13737
|
-
if (!
|
|
14277
|
+
if (!existsSync8(path))
|
|
13738
14278
|
return false;
|
|
13739
|
-
const st =
|
|
14279
|
+
const st = statSync6(path);
|
|
13740
14280
|
if (!st.isFile())
|
|
13741
14281
|
return false;
|
|
13742
14282
|
if (isWindows) {
|
|
13743
14283
|
return true;
|
|
13744
14284
|
}
|
|
13745
|
-
|
|
14285
|
+
accessSync2(path, constants2.X_OK);
|
|
13746
14286
|
return true;
|
|
13747
14287
|
} catch {
|
|
13748
14288
|
return false;
|
|
@@ -13751,28 +14291,28 @@ function isExecutableFile(path, isWindows = process.platform === "win32") {
|
|
|
13751
14291
|
var init_find_on_path = () => {};
|
|
13752
14292
|
|
|
13753
14293
|
// src/lib/paths.ts
|
|
13754
|
-
import { existsSync as
|
|
13755
|
-
import { homedir as
|
|
13756
|
-
import { delimiter as delimiter2, dirname as
|
|
14294
|
+
import { existsSync as existsSync9, readdirSync as readdirSync2, statSync as statSync7 } from "node:fs";
|
|
14295
|
+
import { homedir as homedir7 } from "node:os";
|
|
14296
|
+
import { delimiter as delimiter2, dirname as dirname7, join as join8, resolve as resolve3 } from "node:path";
|
|
13757
14297
|
function getOpenCodeConfigDir() {
|
|
13758
14298
|
const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
13759
14299
|
if (envDir)
|
|
13760
14300
|
return envDir;
|
|
13761
14301
|
if (process.platform === "win32") {
|
|
13762
|
-
return
|
|
14302
|
+
return join8(homedir7(), ".config", "opencode");
|
|
13763
14303
|
}
|
|
13764
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME ||
|
|
13765
|
-
return
|
|
14304
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME || join8(homedir7(), ".config");
|
|
14305
|
+
return join8(xdgConfig, "opencode");
|
|
13766
14306
|
}
|
|
13767
14307
|
function findOmoConfig(configDir) {
|
|
13768
14308
|
const locations = [
|
|
13769
|
-
|
|
13770
|
-
|
|
13771
|
-
|
|
13772
|
-
|
|
14309
|
+
join8(configDir, "oh-my-openagent.jsonc"),
|
|
14310
|
+
join8(configDir, "oh-my-openagent.json"),
|
|
14311
|
+
join8(configDir, "oh-my-opencode.jsonc"),
|
|
14312
|
+
join8(configDir, "oh-my-opencode.json")
|
|
13773
14313
|
];
|
|
13774
14314
|
for (const loc of locations) {
|
|
13775
|
-
if (
|
|
14315
|
+
if (existsSync9(loc))
|
|
13776
14316
|
return loc;
|
|
13777
14317
|
}
|
|
13778
14318
|
return null;
|
|
@@ -13783,24 +14323,24 @@ function detectConfigPaths() {
|
|
|
13783
14323
|
let opencodeConfigFormat;
|
|
13784
14324
|
let tuiConfig;
|
|
13785
14325
|
let tuiConfigFormat;
|
|
13786
|
-
const jsoncPath =
|
|
13787
|
-
const jsonPath =
|
|
13788
|
-
if (
|
|
14326
|
+
const jsoncPath = join8(configDir, "opencode.jsonc");
|
|
14327
|
+
const jsonPath = join8(configDir, "opencode.json");
|
|
14328
|
+
if (existsSync9(jsoncPath)) {
|
|
13789
14329
|
opencodeConfig = jsoncPath;
|
|
13790
14330
|
opencodeConfigFormat = "jsonc";
|
|
13791
|
-
} else if (
|
|
14331
|
+
} else if (existsSync9(jsonPath)) {
|
|
13792
14332
|
opencodeConfig = jsonPath;
|
|
13793
14333
|
opencodeConfigFormat = "json";
|
|
13794
14334
|
} else {
|
|
13795
14335
|
opencodeConfig = jsoncPath;
|
|
13796
14336
|
opencodeConfigFormat = "none";
|
|
13797
14337
|
}
|
|
13798
|
-
const tuiJsoncPath =
|
|
13799
|
-
const tuiJsonPath =
|
|
13800
|
-
if (
|
|
14338
|
+
const tuiJsoncPath = join8(configDir, "tui.jsonc");
|
|
14339
|
+
const tuiJsonPath = join8(configDir, "tui.json");
|
|
14340
|
+
if (existsSync9(tuiJsoncPath)) {
|
|
13801
14341
|
tuiConfig = tuiJsoncPath;
|
|
13802
14342
|
tuiConfigFormat = "jsonc";
|
|
13803
|
-
} else if (
|
|
14343
|
+
} else if (existsSync9(tuiJsonPath)) {
|
|
13804
14344
|
tuiConfig = tuiJsonPath;
|
|
13805
14345
|
tuiConfigFormat = "json";
|
|
13806
14346
|
} else {
|
|
@@ -13819,37 +14359,37 @@ function detectConfigPaths() {
|
|
|
13819
14359
|
}
|
|
13820
14360
|
function envFirstHomeDir() {
|
|
13821
14361
|
const home = process.env.HOME?.trim();
|
|
13822
|
-
return home ||
|
|
14362
|
+
return home || homedir7();
|
|
13823
14363
|
}
|
|
13824
14364
|
function getPiAgentDir() {
|
|
13825
14365
|
const envDir = process.env.PI_CODING_AGENT_DIR?.trim();
|
|
13826
14366
|
if (envDir)
|
|
13827
14367
|
return envDir;
|
|
13828
|
-
return
|
|
14368
|
+
return join8(envFirstHomeDir(), ".pi", "agent");
|
|
13829
14369
|
}
|
|
13830
14370
|
function getPiAgentConfigDir() {
|
|
13831
14371
|
return getPiAgentDir();
|
|
13832
14372
|
}
|
|
13833
14373
|
function getPiSessionsRoot() {
|
|
13834
|
-
return
|
|
14374
|
+
return join8(getPiAgentDir(), "sessions");
|
|
13835
14375
|
}
|
|
13836
14376
|
function getPiCacheRoot() {
|
|
13837
|
-
return
|
|
14377
|
+
return join8(dirname7(getPiAgentDir()), "cache");
|
|
13838
14378
|
}
|
|
13839
14379
|
function getPiUserConfigPath() {
|
|
13840
14380
|
return resolveCortexKitUserConfigPath();
|
|
13841
14381
|
}
|
|
13842
14382
|
function getPiUserExtensionsPath() {
|
|
13843
|
-
return
|
|
14383
|
+
return join8(getPiAgentConfigDir(), "settings.json");
|
|
13844
14384
|
}
|
|
13845
14385
|
function resolveOmpPaths() {
|
|
13846
14386
|
const rawProfile = process.env.OMP_PROFILE ?? process.env.PI_PROFILE;
|
|
13847
14387
|
const normalizedProfile = rawProfile?.trim();
|
|
13848
14388
|
const profile = normalizedProfile && normalizedProfile !== "default" && /^[a-z0-9][a-z0-9._-]{0,63}$/.test(normalizedProfile) ? normalizedProfile : undefined;
|
|
13849
14389
|
const configDirName = process.env.PI_CONFIG_DIR?.trim() || ".omp";
|
|
13850
|
-
const baseConfigRoot =
|
|
13851
|
-
const configRoot = profile ?
|
|
13852
|
-
const defaultAgentDir =
|
|
14390
|
+
const baseConfigRoot = join8(envFirstHomeDir(), configDirName);
|
|
14391
|
+
const configRoot = profile ? join8(baseConfigRoot, "profiles", profile) : baseConfigRoot;
|
|
14392
|
+
const defaultAgentDir = join8(configRoot, "agent");
|
|
13853
14393
|
const override = profile ? undefined : process.env.PI_CODING_AGENT_DIR?.trim();
|
|
13854
14394
|
const agentDir = override ? resolve3(override) : defaultAgentDir;
|
|
13855
14395
|
const canUseXdg = (process.platform === "linux" || process.platform === "darwin") && agentDir === defaultAgentDir;
|
|
@@ -13857,9 +14397,9 @@ function resolveOmpPaths() {
|
|
|
13857
14397
|
if (canUseXdg) {
|
|
13858
14398
|
const xdgDataHome = process.env.XDG_DATA_HOME?.trim();
|
|
13859
14399
|
if (xdgDataHome) {
|
|
13860
|
-
const appRoot =
|
|
13861
|
-
const candidate = profile ?
|
|
13862
|
-
if (
|
|
14400
|
+
const appRoot = join8(xdgDataHome, "omp");
|
|
14401
|
+
const candidate = profile ? join8(appRoot, "profiles", profile) : appRoot;
|
|
14402
|
+
if (existsSync9(candidate))
|
|
13863
14403
|
dataRoot = candidate;
|
|
13864
14404
|
}
|
|
13865
14405
|
}
|
|
@@ -13869,8 +14409,8 @@ function resolveOmpPaths() {
|
|
|
13869
14409
|
agentDir,
|
|
13870
14410
|
dataRoot,
|
|
13871
14411
|
dataAgentRoot,
|
|
13872
|
-
pluginsDir:
|
|
13873
|
-
sessionsRoot:
|
|
14412
|
+
pluginsDir: join8(dataRoot, "plugins"),
|
|
14413
|
+
sessionsRoot: join8(dataAgentRoot, "sessions")
|
|
13874
14414
|
};
|
|
13875
14415
|
}
|
|
13876
14416
|
function getOmpAgentDir() {
|
|
@@ -13880,7 +14420,7 @@ function getOmpSessionsRoot() {
|
|
|
13880
14420
|
return resolveOmpPaths().sessionsRoot;
|
|
13881
14421
|
}
|
|
13882
14422
|
function getOmpConfigPath() {
|
|
13883
|
-
return
|
|
14423
|
+
return join8(resolveOmpPaths().agentDir, "config.yml");
|
|
13884
14424
|
}
|
|
13885
14425
|
function getOmpPackageDir() {
|
|
13886
14426
|
const value = process.env.PI_PACKAGE_DIR?.trim();
|
|
@@ -13897,11 +14437,11 @@ function getOmpNonGlobalConfigSources(cwd = process.cwd()) {
|
|
|
13897
14437
|
const sources = process.env.PI_CONFIG_FILES?.split(delimiter2).map((entry) => entry.trim()).filter(Boolean).map((entry) => {
|
|
13898
14438
|
if (entry === "~")
|
|
13899
14439
|
return envFirstHomeDir();
|
|
13900
|
-
const expanded = entry.startsWith("~/") || entry.startsWith("~\\") ?
|
|
14440
|
+
const expanded = entry.startsWith("~/") || entry.startsWith("~\\") ? join8(envFirstHomeDir(), entry.slice(2)) : entry;
|
|
13901
14441
|
return resolve3(cwd, expanded);
|
|
13902
14442
|
}) ?? [];
|
|
13903
14443
|
const projectConfig = resolve3(cwd, ".omp", "config.yml");
|
|
13904
|
-
if (
|
|
14444
|
+
if (existsSync9(projectConfig))
|
|
13905
14445
|
sources.push(projectConfig);
|
|
13906
14446
|
return [...new Set(sources)];
|
|
13907
14447
|
}
|
|
@@ -13909,7 +14449,7 @@ function getOmpPluginsDir() {
|
|
|
13909
14449
|
return resolveOmpPaths().pluginsDir;
|
|
13910
14450
|
}
|
|
13911
14451
|
function getOmpPluginsLockPath() {
|
|
13912
|
-
return
|
|
14452
|
+
return join8(resolveOmpPaths().pluginsDir, "omp-plugins.lock.json");
|
|
13913
14453
|
}
|
|
13914
14454
|
function getOmpUserConfigPath() {
|
|
13915
14455
|
return resolveCortexKitUserConfigPath();
|
|
@@ -13921,16 +14461,16 @@ function getMagicContextHistorianDir2(harness) {
|
|
|
13921
14461
|
return getMagicContextHistorianDir(harness);
|
|
13922
14462
|
}
|
|
13923
14463
|
function getOpenCodePluginCacheDir() {
|
|
13924
|
-
const xdg = process.env.XDG_CACHE_HOME ||
|
|
13925
|
-
return
|
|
14464
|
+
const xdg = process.env.XDG_CACHE_HOME || join8(homedir7(), ".cache");
|
|
14465
|
+
return join8(xdg, "opencode", "packages");
|
|
13926
14466
|
}
|
|
13927
14467
|
function getOpenCodeV2NpmCacheDir() {
|
|
13928
|
-
const xdg = process.env.XDG_CACHE_HOME ||
|
|
13929
|
-
return
|
|
14468
|
+
const xdg = process.env.XDG_CACHE_HOME || join8(homedir7(), ".cache");
|
|
14469
|
+
return join8(xdg, "opencode", "npm");
|
|
13930
14470
|
}
|
|
13931
14471
|
function isDir(path) {
|
|
13932
14472
|
try {
|
|
13933
|
-
return
|
|
14473
|
+
return statSync7(path).isDirectory();
|
|
13934
14474
|
} catch {
|
|
13935
14475
|
return false;
|
|
13936
14476
|
}
|
|
@@ -13947,12 +14487,12 @@ function dirSizeBytes(path) {
|
|
|
13947
14487
|
try {
|
|
13948
14488
|
const entries = readdirSync2(cur, { withFileTypes: true });
|
|
13949
14489
|
for (const entry of entries) {
|
|
13950
|
-
const child =
|
|
14490
|
+
const child = join8(cur, entry.name);
|
|
13951
14491
|
if (entry.isDirectory()) {
|
|
13952
14492
|
stack.push(child);
|
|
13953
14493
|
} else if (entry.isFile()) {
|
|
13954
14494
|
try {
|
|
13955
|
-
total +=
|
|
14495
|
+
total += statSync7(child).size;
|
|
13956
14496
|
} catch {}
|
|
13957
14497
|
}
|
|
13958
14498
|
}
|
|
@@ -13967,8 +14507,8 @@ var init_paths = __esm(() => {
|
|
|
13967
14507
|
|
|
13968
14508
|
// src/lib/pi-helpers.ts
|
|
13969
14509
|
import { execFileSync, spawnSync } from "node:child_process";
|
|
13970
|
-
import { homedir as
|
|
13971
|
-
import { extname, join as
|
|
14510
|
+
import { homedir as homedir8 } from "node:os";
|
|
14511
|
+
import { extname, join as join9 } from "node:path";
|
|
13972
14512
|
function getPiCommandInvocation(piPath, args) {
|
|
13973
14513
|
const extension = extname(piPath).toLowerCase();
|
|
13974
14514
|
if (extension !== ".cmd" && extension !== ".bat") {
|
|
@@ -13981,8 +14521,8 @@ function detectPiBinary() {
|
|
|
13981
14521
|
const fromPath = findOnPath("pi");
|
|
13982
14522
|
if (fromPath)
|
|
13983
14523
|
return { path: fromPath, source: "path" };
|
|
13984
|
-
const home = process.env.HOME?.trim() ||
|
|
13985
|
-
const homeCandidate = process.platform === "win32" ?
|
|
14524
|
+
const home = process.env.HOME?.trim() || homedir8();
|
|
14525
|
+
const homeCandidate = process.platform === "win32" ? join9(home, ".pi", "bin", "pi.cmd") : join9(home, ".pi", "bin", "pi");
|
|
13986
14526
|
if (isExecutableFile(homeCandidate))
|
|
13987
14527
|
return { path: homeCandidate, source: "home" };
|
|
13988
14528
|
return null;
|
|
@@ -14071,9 +14611,9 @@ var init_pi_helpers = __esm(() => {
|
|
|
14071
14611
|
|
|
14072
14612
|
// src/lib/omp-helpers.ts
|
|
14073
14613
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
14074
|
-
import { existsSync as
|
|
14075
|
-
import { homedir as
|
|
14076
|
-
import { extname as extname2, join as
|
|
14614
|
+
import { existsSync as existsSync10, readFileSync as readFileSync7 } from "node:fs";
|
|
14615
|
+
import { homedir as homedir9 } from "node:os";
|
|
14616
|
+
import { extname as extname2, join as join10 } from "node:path";
|
|
14077
14617
|
function detectOmpPackageCli() {
|
|
14078
14618
|
const packageDir = getOmpPackageDir();
|
|
14079
14619
|
if (!packageDir)
|
|
@@ -14081,11 +14621,11 @@ function detectOmpPackageCli() {
|
|
|
14081
14621
|
if (!findOnPath("bun"))
|
|
14082
14622
|
return null;
|
|
14083
14623
|
try {
|
|
14084
|
-
const manifest = JSON.parse(
|
|
14624
|
+
const manifest = JSON.parse(readFileSync7(join10(packageDir, "package.json"), "utf-8"));
|
|
14085
14625
|
if (manifest.name !== "@oh-my-pi/pi-coding-agent")
|
|
14086
14626
|
return null;
|
|
14087
|
-
const cli =
|
|
14088
|
-
return
|
|
14627
|
+
const cli = join10(packageDir, "dist", "cli.js");
|
|
14628
|
+
return existsSync10(cli) ? cli : null;
|
|
14089
14629
|
} catch {
|
|
14090
14630
|
return null;
|
|
14091
14631
|
}
|
|
@@ -14100,13 +14640,13 @@ function getOmpCommandInvocation(ompPath, args) {
|
|
|
14100
14640
|
}
|
|
14101
14641
|
function getOmpFallbackCandidates(platform, home, appData) {
|
|
14102
14642
|
if (platform !== "win32") {
|
|
14103
|
-
return [
|
|
14643
|
+
return [join10(home, ".bun", "bin", "omp"), join10(home, ".local", "bin", "omp")];
|
|
14104
14644
|
}
|
|
14105
14645
|
const npmRoot = appData?.trim();
|
|
14106
14646
|
return [
|
|
14107
|
-
...npmRoot ? [
|
|
14108
|
-
|
|
14109
|
-
|
|
14647
|
+
...npmRoot ? [join10(npmRoot, "npm", "omp.cmd"), join10(npmRoot, "npm", "omp.exe")] : [],
|
|
14648
|
+
join10(home, ".bun", "bin", "omp.exe"),
|
|
14649
|
+
join10(home, ".bun", "bin", "omp.cmd")
|
|
14110
14650
|
];
|
|
14111
14651
|
}
|
|
14112
14652
|
function detectOmpBinary() {
|
|
@@ -14116,7 +14656,7 @@ function detectOmpBinary() {
|
|
|
14116
14656
|
const fromPackage = detectOmpPackageCli();
|
|
14117
14657
|
if (fromPackage)
|
|
14118
14658
|
return { path: fromPackage, source: "package" };
|
|
14119
|
-
const home = process.env.HOME?.trim() ||
|
|
14659
|
+
const home = process.env.HOME?.trim() || homedir9();
|
|
14120
14660
|
const candidates = getOmpFallbackCandidates(process.platform, home, process.env.APPDATA);
|
|
14121
14661
|
const candidate = candidates.find((path) => isExecutableFile(path));
|
|
14122
14662
|
return candidate ? { path: candidate, source: "home" } : null;
|
|
@@ -14229,8 +14769,8 @@ var init_omp_helpers = __esm(() => {
|
|
|
14229
14769
|
});
|
|
14230
14770
|
|
|
14231
14771
|
// src/adapters/omp.ts
|
|
14232
|
-
import { existsSync as
|
|
14233
|
-
import { join as
|
|
14772
|
+
import { existsSync as existsSync11, readFileSync as readFileSync8 } from "node:fs";
|
|
14773
|
+
import { join as join11 } from "node:path";
|
|
14234
14774
|
|
|
14235
14775
|
class OmpAdapter {
|
|
14236
14776
|
kind = "omp";
|
|
@@ -14330,8 +14870,8 @@ class OmpAdapter {
|
|
|
14330
14870
|
return "Install OMP: https://omp.sh (npm: @oh-my-pi/pi-coding-agent)";
|
|
14331
14871
|
}
|
|
14332
14872
|
getPluginCacheInfo() {
|
|
14333
|
-
const path =
|
|
14334
|
-
return [{ path, exists:
|
|
14873
|
+
const path = join11(getOmpPluginsDir(), "cache");
|
|
14874
|
+
return [{ path, exists: existsSync11(path), sizeBytes: dirSizeBytes(path) }];
|
|
14335
14875
|
}
|
|
14336
14876
|
getLogPath() {
|
|
14337
14877
|
return getMagicContextLogPath2("omp");
|
|
@@ -14344,7 +14884,7 @@ class OmpAdapter {
|
|
|
14344
14884
|
}
|
|
14345
14885
|
readRuntimeEnabled(configPath) {
|
|
14346
14886
|
try {
|
|
14347
|
-
const lock = JSON.parse(
|
|
14887
|
+
const lock = JSON.parse(readFileSync8(configPath, "utf-8"));
|
|
14348
14888
|
const enabled = lock.plugins?.[OMP_PLUGIN_PACKAGE]?.enabled;
|
|
14349
14889
|
return typeof enabled === "boolean" ? enabled : undefined;
|
|
14350
14890
|
} catch {
|
|
@@ -14372,9 +14912,9 @@ var init_omp = __esm(() => {
|
|
|
14372
14912
|
});
|
|
14373
14913
|
|
|
14374
14914
|
// ../plugin/src/shared/opencode-db-path.ts
|
|
14375
|
-
import { existsSync as
|
|
14376
|
-
import { homedir as
|
|
14377
|
-
import { isAbsolute as isAbsolute4, join as
|
|
14915
|
+
import { existsSync as existsSync12, readdirSync as readdirSync3, statSync as statSync8 } from "node:fs";
|
|
14916
|
+
import { homedir as homedir10 } from "node:os";
|
|
14917
|
+
import { isAbsolute as isAbsolute4, join as join12, resolve as resolve4 } from "node:path";
|
|
14378
14918
|
function openCodeHostGenerationFromVersion(version) {
|
|
14379
14919
|
const text = version ?? "";
|
|
14380
14920
|
if (/(?:^|\s|v)0\.0\.0-(?:beta|dev)-/.test(text))
|
|
@@ -14383,7 +14923,7 @@ function openCodeHostGenerationFromVersion(version) {
|
|
|
14383
14923
|
return Number.isFinite(major) && major >= 2 ? "v2" : "v1";
|
|
14384
14924
|
}
|
|
14385
14925
|
function openCodeDataDir(env = process.env, dataHome) {
|
|
14386
|
-
return
|
|
14926
|
+
return join12(dataHome ?? env.XDG_DATA_HOME ?? join12(homedir10(), ".local", "share"), "opencode");
|
|
14387
14927
|
}
|
|
14388
14928
|
function environmentKey(dataDir, hostGeneration, channel, env) {
|
|
14389
14929
|
return [
|
|
@@ -14395,7 +14935,7 @@ function environmentKey(dataDir, hostGeneration, channel, env) {
|
|
|
14395
14935
|
].join("\x00");
|
|
14396
14936
|
}
|
|
14397
14937
|
function channelPath(dataDir, channel) {
|
|
14398
|
-
return ["latest", "beta", "prod"].includes(channel) ?
|
|
14938
|
+
return ["latest", "beta", "prod"].includes(channel) ? join12(dataDir, "opencode.db") : join12(dataDir, `opencode-${channel}.db`);
|
|
14399
14939
|
}
|
|
14400
14940
|
function discoveredCandidateNames(dataDir) {
|
|
14401
14941
|
const names = ["opencode.db", "opencode-local.db", "opencode-dev.db"];
|
|
@@ -14407,9 +14947,9 @@ function discoveredCandidateNames(dataDir) {
|
|
|
14407
14947
|
}
|
|
14408
14948
|
function discoverOpenCodeDb(dataDir) {
|
|
14409
14949
|
const candidates = discoveredCandidateNames(dataDir).map((name, order) => {
|
|
14410
|
-
const path =
|
|
14950
|
+
const path = join12(dataDir, name);
|
|
14411
14951
|
try {
|
|
14412
|
-
const metadata =
|
|
14952
|
+
const metadata = statSync8(path);
|
|
14413
14953
|
return metadata.isFile() ? { path, order, mtimeMs: metadata.mtimeMs } : null;
|
|
14414
14954
|
} catch {
|
|
14415
14955
|
return null;
|
|
@@ -14417,7 +14957,7 @@ function discoverOpenCodeDb(dataDir) {
|
|
|
14417
14957
|
});
|
|
14418
14958
|
const existing = candidates.filter((candidate) => candidate !== null).sort((left, right) => right.mtimeMs - left.mtimeMs || left.order - right.order)[0];
|
|
14419
14959
|
if (!existing) {
|
|
14420
|
-
return { path:
|
|
14960
|
+
return { path: join12(dataDir, "opencode.db"), source: "default", channel: null };
|
|
14421
14961
|
}
|
|
14422
14962
|
const name = existing.path.slice(dataDir.length + 1);
|
|
14423
14963
|
const channel = name === "opencode.db" ? null : name.slice("opencode-".length, -".db".length) || null;
|
|
@@ -14430,14 +14970,14 @@ function resolveV1Fresh(dataDir, env = process.env) {
|
|
|
14430
14970
|
return { path: explicit, source: "OPENCODE_DB", channel: null };
|
|
14431
14971
|
}
|
|
14432
14972
|
return {
|
|
14433
|
-
path: isAbsolute4(explicit) ? explicit :
|
|
14973
|
+
path: isAbsolute4(explicit) ? explicit : join12(dataDir, explicit),
|
|
14434
14974
|
source: "OPENCODE_DB",
|
|
14435
14975
|
channel: null
|
|
14436
14976
|
};
|
|
14437
14977
|
}
|
|
14438
14978
|
const disableChannelDb = env.OPENCODE_DISABLE_CHANNEL_DB;
|
|
14439
14979
|
if (disableChannelDb === "1" || disableChannelDb === "true") {
|
|
14440
|
-
return { path:
|
|
14980
|
+
return { path: join12(dataDir, "opencode.db"), source: "default", channel: null };
|
|
14441
14981
|
}
|
|
14442
14982
|
const channel = env.OPENCODE_CHANNEL;
|
|
14443
14983
|
if (channel !== undefined && channel.length > 0) {
|
|
@@ -14471,7 +15011,7 @@ function resolveOpenCodeDbPath(hostGeneration = "v1", options = {}) {
|
|
|
14471
15011
|
const dataDir = openCodeDataDir(env, options.dataHome);
|
|
14472
15012
|
const channel = options.channel ?? env.OPENCODE_CHANNEL;
|
|
14473
15013
|
const key = environmentKey(dataDir, hostGeneration, channel, env);
|
|
14474
|
-
if (cachedResolution?.key === key && (!cachedResolution.existed ||
|
|
15014
|
+
if (cachedResolution?.key === key && (!cachedResolution.existed || existsSync12(cachedResolution.resolution.path))) {
|
|
14475
15015
|
if (cachedResolution.existed)
|
|
14476
15016
|
return cachedResolution.resolution;
|
|
14477
15017
|
}
|
|
@@ -14479,7 +15019,7 @@ function resolveOpenCodeDbPath(hostGeneration = "v1", options = {}) {
|
|
|
14479
15019
|
cachedResolution = {
|
|
14480
15020
|
key,
|
|
14481
15021
|
resolution,
|
|
14482
|
-
existed: resolution.path !== ":memory:" &&
|
|
15022
|
+
existed: resolution.path !== ":memory:" && existsSync12(resolution.path)
|
|
14483
15023
|
};
|
|
14484
15024
|
return resolution;
|
|
14485
15025
|
}
|
|
@@ -14519,7 +15059,7 @@ function assertOpenCodeStoreGeneration(db, expected, path, schema = "main") {
|
|
|
14519
15059
|
throw new Error(`OpenCode store generation mismatch at ${path}: expected ${expected}, found ${actual}; refusing generation-specific database access`);
|
|
14520
15060
|
}
|
|
14521
15061
|
function openCodeDbPathExists(resolution = resolveOpenCodeDbPath()) {
|
|
14522
|
-
return resolution.path !== ":memory:" &&
|
|
15062
|
+
return resolution.path !== ":memory:" && existsSync12(resolution.path);
|
|
14523
15063
|
}
|
|
14524
15064
|
function getOpenCodeDbProbeDescriptions(resolution = resolveOpenCodeDbPath()) {
|
|
14525
15065
|
if (resolution.source === "OPENCODE_DB")
|
|
@@ -14529,10 +15069,10 @@ function getOpenCodeDbProbeDescriptions(resolution = resolveOpenCodeDbPath()) {
|
|
|
14529
15069
|
}
|
|
14530
15070
|
const dataDir = openCodeDataDir();
|
|
14531
15071
|
return [
|
|
14532
|
-
|
|
14533
|
-
|
|
14534
|
-
|
|
14535
|
-
|
|
15072
|
+
join12(dataDir, "opencode.db"),
|
|
15073
|
+
join12(dataDir, "opencode-local.db"),
|
|
15074
|
+
join12(dataDir, "opencode-dev.db"),
|
|
15075
|
+
join12(dataDir, "opencode-<channel>.db")
|
|
14536
15076
|
];
|
|
14537
15077
|
}
|
|
14538
15078
|
function lookedForText(resolution) {
|
|
@@ -22437,8 +22977,8 @@ function projectDirectoryKey(directory) {
|
|
|
22437
22977
|
var init_project_directory_key = () => {};
|
|
22438
22978
|
|
|
22439
22979
|
// ../plugin/src/shared/rpc-utils.ts
|
|
22440
|
-
import { execFile, execFileSync as execFileSync2 } from "node:child_process";
|
|
22441
|
-
import { readFileSync as
|
|
22980
|
+
import { execFile as execFile2, execFileSync as execFileSync2 } from "node:child_process";
|
|
22981
|
+
import { readFileSync as readFileSync9 } from "node:fs";
|
|
22442
22982
|
function isOwnRpcServerRecord(record) {
|
|
22443
22983
|
return record.pid === process.pid && record.instance_id !== undefined && ownRpcServerInstanceIds.has(record.instance_id);
|
|
22444
22984
|
}
|
|
@@ -23033,7 +23573,7 @@ var init_rpc_utils = __esm(() => {
|
|
|
23033
23573
|
"cljs/dist",
|
|
23034
23574
|
"dist/bundle/cli"
|
|
23035
23575
|
];
|
|
23036
|
-
rpcIdentityReadFileSync =
|
|
23576
|
+
rpcIdentityReadFileSync = readFileSync9;
|
|
23037
23577
|
rpcIdentityExecFileSync = execFileSync2;
|
|
23038
23578
|
rpcIdentityProcessKill = process.kill;
|
|
23039
23579
|
rpcProcessListExecFileSync = execFileSync2;
|
|
@@ -23074,23 +23614,23 @@ var init_opencode_plugin_registration = __esm(() => {
|
|
|
23074
23614
|
});
|
|
23075
23615
|
|
|
23076
23616
|
// src/lib/opencode-plugin-cache.ts
|
|
23077
|
-
import { readdirSync as readdirSync4, readFileSync as
|
|
23078
|
-
import { join as
|
|
23617
|
+
import { readdirSync as readdirSync4, readFileSync as readFileSync10 } from "node:fs";
|
|
23618
|
+
import { join as join13 } from "node:path";
|
|
23079
23619
|
function getOpenCodePluginCacheRoots() {
|
|
23080
23620
|
const cacheDir = getOpenCodePluginCacheDir();
|
|
23081
23621
|
return [
|
|
23082
|
-
|
|
23083
|
-
|
|
23622
|
+
join13(cacheDir, OPENCODE_PLUGIN_ENTRY_WITH_VERSION),
|
|
23623
|
+
join13(cacheDir, OPENCODE_PLUGIN_NAME)
|
|
23084
23624
|
];
|
|
23085
23625
|
}
|
|
23086
23626
|
function getOpenCodePluginPackageJsonPath(pluginCacheRoot) {
|
|
23087
|
-
return
|
|
23627
|
+
return join13(pluginCacheRoot, "node_modules", ...OPENCODE_PLUGIN_NAME.split("/"), "package.json");
|
|
23088
23628
|
}
|
|
23089
23629
|
function getOpenCodePluginPackageJsonPaths() {
|
|
23090
23630
|
return getOpenCodePluginCacheRoots().map(getOpenCodePluginPackageJsonPath);
|
|
23091
23631
|
}
|
|
23092
23632
|
function getOpenCodeV2PluginCacheSlot(npmCacheDir = getOpenCodeV2NpmCacheDir(), spec = "latest") {
|
|
23093
|
-
return
|
|
23633
|
+
return join13(npmCacheDir, ...`${OPENCODE_PLUGIN_NAME}@${spec}`.split("/"));
|
|
23094
23634
|
}
|
|
23095
23635
|
function openCodeV2PluginSpecOf(specifier) {
|
|
23096
23636
|
if (specifier === OPENCODE_PLUGIN_NAME)
|
|
@@ -23143,7 +23683,7 @@ function pluginEntrySpecifier(entry) {
|
|
|
23143
23683
|
}
|
|
23144
23684
|
function listOpenCodeV2PluginCacheSlots(npmCacheDir = getOpenCodeV2NpmCacheDir()) {
|
|
23145
23685
|
const [scope = "", name = ""] = OPENCODE_PLUGIN_NAME.split("/");
|
|
23146
|
-
const scopeDir =
|
|
23686
|
+
const scopeDir = join13(npmCacheDir, scope);
|
|
23147
23687
|
let names;
|
|
23148
23688
|
try {
|
|
23149
23689
|
names = readdirSync4(scopeDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.startsWith(`${name}@`)).map((entry) => entry.name);
|
|
@@ -23151,7 +23691,7 @@ function listOpenCodeV2PluginCacheSlots(npmCacheDir = getOpenCodeV2NpmCacheDir()
|
|
|
23151
23691
|
return [];
|
|
23152
23692
|
}
|
|
23153
23693
|
return names.map((dirName) => {
|
|
23154
|
-
const slot =
|
|
23694
|
+
const slot = join13(scopeDir, dirName);
|
|
23155
23695
|
return {
|
|
23156
23696
|
spec: dirName.slice(name.length + 1),
|
|
23157
23697
|
slot,
|
|
@@ -23167,7 +23707,7 @@ function getOpenCodeV2ActiveGeneration(slot) {
|
|
|
23167
23707
|
try {
|
|
23168
23708
|
const generations = readdirSync4(slot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && /^\d+$/.test(entry.name)).map((entry) => entry.name).sort((a, b) => Number(a) - Number(b));
|
|
23169
23709
|
const newest = generations.at(-1);
|
|
23170
|
-
return newest === undefined ? undefined :
|
|
23710
|
+
return newest === undefined ? undefined : join13(slot, newest);
|
|
23171
23711
|
} catch {
|
|
23172
23712
|
return;
|
|
23173
23713
|
}
|
|
@@ -23177,7 +23717,7 @@ function readOpenCodeV2CachedPluginVersion(slot) {
|
|
|
23177
23717
|
if (!generation)
|
|
23178
23718
|
return;
|
|
23179
23719
|
try {
|
|
23180
|
-
const pkg = JSON.parse(
|
|
23720
|
+
const pkg = JSON.parse(readFileSync10(getOpenCodePluginPackageJsonPath(generation), "utf-8"));
|
|
23181
23721
|
return typeof pkg.version === "string" ? pkg.version : undefined;
|
|
23182
23722
|
} catch {
|
|
23183
23723
|
return;
|
|
@@ -23191,7 +23731,7 @@ var init_opencode_plugin_cache = __esm(() => {
|
|
|
23191
23731
|
});
|
|
23192
23732
|
|
|
23193
23733
|
// src/commands/doctor-windows-holders.ts
|
|
23194
|
-
import { existsSync as
|
|
23734
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
23195
23735
|
function assertWindowsStoresClosed(paths, processes) {
|
|
23196
23736
|
if (processes.pi.state !== "known" || processes.pi.processIds.length > 0 || (processes.pi.inconclusivePids?.length ?? 0) > 0 || processes.processSnapshot?.source !== "cim") {
|
|
23197
23737
|
throw new Error(`Windows process probe could not rule out OpenCode, Pi or ck-mc holders${processes.pi.processIds.length || processes.pi.inconclusivePids?.length ? ` (PID ${[...processes.pi.processIds, ...processes.pi.inconclusivePids ?? []].join(", ")})` : ""}`);
|
|
@@ -23207,7 +23747,7 @@ function assertWindowsStoresClosed(paths, processes) {
|
|
|
23207
23747
|
if (blockers.length)
|
|
23208
23748
|
throw new Error(`OpenCode, Pi or ck-mc process is running (${blockers.map(({ pid, imageName, commandLine }) => `${imageName ?? commandLine} PID ${pid}`).join(", ")})`);
|
|
23209
23749
|
for (const path of [...new Set(paths)]) {
|
|
23210
|
-
if (!
|
|
23750
|
+
if (!existsSync13(path))
|
|
23211
23751
|
continue;
|
|
23212
23752
|
let db;
|
|
23213
23753
|
let locked = false;
|
|
@@ -23231,7 +23771,7 @@ var init_doctor_windows_holders = __esm(async () => {
|
|
|
23231
23771
|
|
|
23232
23772
|
// src/commands/doctor-opencode2-cache.ts
|
|
23233
23773
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
23234
|
-
import { existsSync as
|
|
23774
|
+
import { existsSync as existsSync14, rmSync as rmSync4 } from "node:fs";
|
|
23235
23775
|
function runLsof(args, spawn) {
|
|
23236
23776
|
const result = spawn("lsof", args, { encoding: "utf-8", timeout: 15000, windowsHide: true });
|
|
23237
23777
|
if (result.error)
|
|
@@ -23246,7 +23786,7 @@ function probeHostProcessesUsing(targets, spawn = spawnSync3) {
|
|
|
23246
23786
|
if (process.platform === "win32") {
|
|
23247
23787
|
try {
|
|
23248
23788
|
assertWindowsStoresClosed(targets.files.filter((path) => !/-(?:wal|shm)$/.test(path)), inspectWindowsProcessesSync());
|
|
23249
|
-
if (targets.directories.some(
|
|
23789
|
+
if (targets.directories.some(existsSync14))
|
|
23250
23790
|
return {
|
|
23251
23791
|
status: "unknown",
|
|
23252
23792
|
reason: "Windows cannot rule out open files in plugin cache directories"
|
|
@@ -23259,8 +23799,8 @@ function probeHostProcessesUsing(targets, spawn = spawnSync3) {
|
|
|
23259
23799
|
};
|
|
23260
23800
|
}
|
|
23261
23801
|
}
|
|
23262
|
-
const files = targets.files.filter((file) =>
|
|
23263
|
-
const directories = targets.directories.filter((directory) =>
|
|
23802
|
+
const files = targets.files.filter((file) => existsSync14(file));
|
|
23803
|
+
const directories = targets.directories.filter((directory) => existsSync14(directory));
|
|
23264
23804
|
const queries = [];
|
|
23265
23805
|
if (files.length > 0)
|
|
23266
23806
|
queries.push(["-w", "-t", "--", ...files]);
|
|
@@ -23335,7 +23875,7 @@ function removeOpenCodeV2PluginCacheSlot(slot, hostFiles, deps = {}) {
|
|
|
23335
23875
|
return { action: "in_use", pids: use.pids };
|
|
23336
23876
|
if (use.status === "unknown")
|
|
23337
23877
|
return { action: "in_use_unknown", reason: use.reason };
|
|
23338
|
-
const remove = deps.remove ?? ((path) =>
|
|
23878
|
+
const remove = deps.remove ?? ((path) => rmSync4(path, { recursive: true, force: true }));
|
|
23339
23879
|
try {
|
|
23340
23880
|
remove(slot);
|
|
23341
23881
|
} catch (err) {
|
|
@@ -23355,9 +23895,9 @@ function checkOpenCodeV2PluginCache(options, deps = {}) {
|
|
|
23355
23895
|
const slot = deps.slot ?? getOpenCodeV2PluginCacheSlot(undefined, distTag ?? "latest");
|
|
23356
23896
|
const tagged = distTag ? { distTag } : {};
|
|
23357
23897
|
if (options.referencedSpecs !== undefined && !options.referencedSpecs.has(distTag ?? "latest")) {
|
|
23358
|
-
return
|
|
23898
|
+
return existsSync14(slot) ? { action: "unused", slot, cached: readOpenCodeV2CachedPluginVersion(slot), ...tagged } : { action: "not_found", slot, unused: true, ...tagged };
|
|
23359
23899
|
}
|
|
23360
|
-
if (!
|
|
23900
|
+
if (!existsSync14(slot))
|
|
23361
23901
|
return { action: "not_found", slot, ...tagged };
|
|
23362
23902
|
const cached = readOpenCodeV2CachedPluginVersion(slot);
|
|
23363
23903
|
const latest = options.latestVersion ?? undefined;
|
|
@@ -23450,21 +23990,21 @@ var init_doctor_opencode2_cache = __esm(async () => {
|
|
|
23450
23990
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
23451
23991
|
import {
|
|
23452
23992
|
lstatSync as lstatSync2,
|
|
23453
|
-
mkdirSync as
|
|
23993
|
+
mkdirSync as mkdirSync4,
|
|
23454
23994
|
readlinkSync as readlinkSync2,
|
|
23455
|
-
renameSync as
|
|
23456
|
-
rmSync as
|
|
23457
|
-
statSync as
|
|
23458
|
-
writeFileSync as
|
|
23995
|
+
renameSync as renameSync4,
|
|
23996
|
+
rmSync as rmSync5,
|
|
23997
|
+
statSync as statSync9,
|
|
23998
|
+
writeFileSync as writeFileSync4
|
|
23459
23999
|
} from "node:fs";
|
|
23460
|
-
import { dirname as
|
|
24000
|
+
import { dirname as dirname8, resolve as resolve5 } from "node:path";
|
|
23461
24001
|
function resolveWriteTarget(targetPath) {
|
|
23462
24002
|
let current = resolve5(targetPath);
|
|
23463
24003
|
for (let hop = 0;hop < MAX_SYMLINK_HOPS; hop++) {
|
|
23464
24004
|
const stat = lstatSync2(current, { throwIfNoEntry: false });
|
|
23465
24005
|
if (!stat?.isSymbolicLink())
|
|
23466
24006
|
return current;
|
|
23467
|
-
current = resolve5(
|
|
24007
|
+
current = resolve5(dirname8(current), readlinkSync2(current));
|
|
23468
24008
|
}
|
|
23469
24009
|
throw new Error(`Too many levels of symbolic links resolving ${targetPath}`);
|
|
23470
24010
|
}
|
|
@@ -23474,19 +24014,19 @@ function writeFileAtomic(targetPath, data, options = {}) {
|
|
|
23474
24014
|
writeStorageFileAtomicSync(finalPath, data, true);
|
|
23475
24015
|
return;
|
|
23476
24016
|
}
|
|
23477
|
-
|
|
23478
|
-
const existing =
|
|
24017
|
+
mkdirSync4(dirname8(finalPath), { recursive: true });
|
|
24018
|
+
const existing = statSync9(finalPath, { throwIfNoEntry: false });
|
|
23479
24019
|
const mode = existing?.isFile() ? existing.mode & 511 : undefined;
|
|
23480
24020
|
const tmpPath = `${finalPath}.${process.pid}.${randomBytes2(6).toString("hex")}.tmp`;
|
|
23481
24021
|
try {
|
|
23482
|
-
|
|
24022
|
+
writeFileSync4(tmpPath, data, {
|
|
23483
24023
|
encoding: "utf-8",
|
|
23484
24024
|
flag: "wx",
|
|
23485
24025
|
...mode !== undefined ? { mode } : {}
|
|
23486
24026
|
});
|
|
23487
|
-
|
|
24027
|
+
renameSync4(tmpPath, finalPath);
|
|
23488
24028
|
} catch (error) {
|
|
23489
|
-
|
|
24029
|
+
rmSync5(tmpPath, { force: true });
|
|
23490
24030
|
throw error;
|
|
23491
24031
|
}
|
|
23492
24032
|
}
|
|
@@ -23496,7 +24036,7 @@ var init_atomic_write = __esm(() => {
|
|
|
23496
24036
|
});
|
|
23497
24037
|
|
|
23498
24038
|
// src/lib/jsonc-config.ts
|
|
23499
|
-
import { existsSync as
|
|
24039
|
+
import { existsSync as existsSync15, readFileSync as readFileSync11 } from "node:fs";
|
|
23500
24040
|
function parseErrorLocation(content, error) {
|
|
23501
24041
|
const lines = content.split(`
|
|
23502
24042
|
`);
|
|
@@ -23512,9 +24052,9 @@ function parseErrorLocation(content, error) {
|
|
|
23512
24052
|
return { line: messageLine ? Number.parseInt(messageLine, 10) : 1, column: 1 };
|
|
23513
24053
|
}
|
|
23514
24054
|
function readJsoncConfig(path) {
|
|
23515
|
-
if (!
|
|
24055
|
+
if (!existsSync15(path))
|
|
23516
24056
|
return { kind: "missing" };
|
|
23517
|
-
const content =
|
|
24057
|
+
const content = readFileSync11(path, "utf-8");
|
|
23518
24058
|
try {
|
|
23519
24059
|
const rejectedKeyPaths = [];
|
|
23520
24060
|
const parsed = sanitizeParsedJson(import_comment_json.parse(content), {
|
|
@@ -23540,7 +24080,7 @@ function readJsoncConfigForUpdate(path) {
|
|
|
23540
24080
|
return result.value;
|
|
23541
24081
|
}
|
|
23542
24082
|
function readJsoncTextForEdit(configPath) {
|
|
23543
|
-
const raw =
|
|
24083
|
+
const raw = readFileSync11(configPath, "utf-8");
|
|
23544
24084
|
return raw.startsWith(BYTE_ORDER_MARK) ? { bom: BYTE_ORDER_MARK, text: raw.slice(BYTE_ORDER_MARK.length) } : { bom: "", text: raw };
|
|
23545
24085
|
}
|
|
23546
24086
|
function assertJsoncConfigsParseable(paths) {
|
|
@@ -23629,15 +24169,15 @@ var init_jsonc_config = __esm(() => {
|
|
|
23629
24169
|
});
|
|
23630
24170
|
|
|
23631
24171
|
// src/lib/opencode-detect.ts
|
|
23632
|
-
import { existsSync as
|
|
23633
|
-
import { homedir as
|
|
23634
|
-
import { join as
|
|
24172
|
+
import { existsSync as existsSync16, realpathSync as realpathSync2 } from "node:fs";
|
|
24173
|
+
import { homedir as homedir11 } from "node:os";
|
|
24174
|
+
import { join as join14 } from "node:path";
|
|
23635
24175
|
function defaultDeps(overrides = {}) {
|
|
23636
24176
|
const env = overrides.env ?? process.env;
|
|
23637
24177
|
return {
|
|
23638
|
-
exists: overrides.exists ??
|
|
24178
|
+
exists: overrides.exists ?? existsSync16,
|
|
23639
24179
|
isExecutable: overrides.isExecutable ?? isExecutableFile,
|
|
23640
|
-
home: overrides.home ?? (env.HOME?.trim() ||
|
|
24180
|
+
home: overrides.home ?? (env.HOME?.trim() || homedir11()),
|
|
23641
24181
|
platform: overrides.platform ?? process.platform,
|
|
23642
24182
|
env,
|
|
23643
24183
|
onPath: overrides.onPath ?? findOnPath,
|
|
@@ -23645,7 +24185,7 @@ function defaultDeps(overrides = {}) {
|
|
|
23645
24185
|
};
|
|
23646
24186
|
}
|
|
23647
24187
|
function stockCliBinary(d) {
|
|
23648
|
-
return d.platform === "win32" ?
|
|
24188
|
+
return d.platform === "win32" ? join14(d.home, ".opencode", "bin", "opencode.exe") : join14(d.home, ".opencode", "bin", "opencode");
|
|
23649
24189
|
}
|
|
23650
24190
|
function extraCliCandidates(d) {
|
|
23651
24191
|
if (d.platform === "win32") {
|
|
@@ -23654,25 +24194,25 @@ function extraCliCandidates(d) {
|
|
|
23654
24194
|
const userprofile = d.env.USERPROFILE ?? d.home;
|
|
23655
24195
|
const out = [];
|
|
23656
24196
|
if (appdata) {
|
|
23657
|
-
out.push(
|
|
23658
|
-
out.push(
|
|
24197
|
+
out.push(join14(appdata, "npm", "opencode.cmd"));
|
|
24198
|
+
out.push(join14(appdata, "npm", "opencode.exe"));
|
|
23659
24199
|
}
|
|
23660
24200
|
if (localappdata) {
|
|
23661
|
-
out.push(
|
|
23662
|
-
out.push(
|
|
24201
|
+
out.push(join14(localappdata, "Microsoft", "WinGet", "Links", "opencode.exe"));
|
|
24202
|
+
out.push(join14(localappdata, "opencode", "bin", "opencode.exe"));
|
|
23663
24203
|
}
|
|
23664
24204
|
if (userprofile) {
|
|
23665
|
-
out.push(
|
|
24205
|
+
out.push(join14(userprofile, "scoop", "shims", "opencode.exe"));
|
|
23666
24206
|
}
|
|
23667
24207
|
return out;
|
|
23668
24208
|
}
|
|
23669
24209
|
return [
|
|
23670
24210
|
"/usr/local/bin/opencode",
|
|
23671
24211
|
"/opt/homebrew/bin/opencode",
|
|
23672
|
-
|
|
23673
|
-
|
|
23674
|
-
|
|
23675
|
-
|
|
24212
|
+
join14(d.home, ".local", "bin", "opencode"),
|
|
24213
|
+
join14(d.home, ".local", "share", "mise", "shims", "opencode"),
|
|
24214
|
+
join14(d.home, ".asdf", "shims", "opencode"),
|
|
24215
|
+
join14(d.home, ".volta", "bin", "opencode")
|
|
23676
24216
|
];
|
|
23677
24217
|
}
|
|
23678
24218
|
function openChamberCliCandidates(d) {
|
|
@@ -23680,8 +24220,8 @@ function openChamberCliCandidates(d) {
|
|
|
23680
24220
|
return [];
|
|
23681
24221
|
const bundled = ["Contents", "Resources", "opencode-cli", "opencode"];
|
|
23682
24222
|
return [
|
|
23683
|
-
|
|
23684
|
-
|
|
24223
|
+
join14("/Applications", "OpenChamber.app", ...bundled),
|
|
24224
|
+
join14(d.home, "Applications", "OpenChamber.app", ...bundled)
|
|
23685
24225
|
];
|
|
23686
24226
|
}
|
|
23687
24227
|
function canonicalPath(d, path) {
|
|
@@ -23702,29 +24242,29 @@ function xdgConfigHome(d) {
|
|
|
23702
24242
|
const xdg = d.env.XDG_CONFIG_HOME;
|
|
23703
24243
|
if (xdg && xdg.length > 0)
|
|
23704
24244
|
return xdg;
|
|
23705
|
-
return
|
|
24245
|
+
return join14(d.home, ".config");
|
|
23706
24246
|
}
|
|
23707
24247
|
function desktopUserDataDir(d, appId) {
|
|
23708
24248
|
switch (d.platform) {
|
|
23709
24249
|
case "darwin":
|
|
23710
|
-
return
|
|
24250
|
+
return join14(d.home, "Library", "Application Support", appId);
|
|
23711
24251
|
case "win32":
|
|
23712
|
-
return
|
|
24252
|
+
return join14(d.env.APPDATA ?? join14(d.home, "AppData", "Roaming"), appId);
|
|
23713
24253
|
default:
|
|
23714
|
-
return
|
|
24254
|
+
return join14(xdgConfigHome(d), appId);
|
|
23715
24255
|
}
|
|
23716
24256
|
}
|
|
23717
24257
|
function desktopAppPaths(d) {
|
|
23718
24258
|
switch (d.platform) {
|
|
23719
24259
|
case "darwin":
|
|
23720
|
-
return ["/Applications/OpenCode.app",
|
|
24260
|
+
return ["/Applications/OpenCode.app", join14(d.home, "Applications", "OpenCode.app")];
|
|
23721
24261
|
case "win32": {
|
|
23722
|
-
const localappdata = d.env.LOCALAPPDATA ??
|
|
23723
|
-
return [
|
|
24262
|
+
const localappdata = d.env.LOCALAPPDATA ?? join14(d.home, "AppData", "Local");
|
|
24263
|
+
return [join14(localappdata, "Programs", "OpenCode", "OpenCode.exe")];
|
|
23724
24264
|
}
|
|
23725
24265
|
default: {
|
|
23726
|
-
const dataHome = d.env.XDG_DATA_HOME && d.env.XDG_DATA_HOME.length > 0 ? d.env.XDG_DATA_HOME :
|
|
23727
|
-
return OPENCODE_DESKTOP_APP_IDS.map((appId) =>
|
|
24266
|
+
const dataHome = d.env.XDG_DATA_HOME && d.env.XDG_DATA_HOME.length > 0 ? d.env.XDG_DATA_HOME : join14(d.home, ".local", "share");
|
|
24267
|
+
return OPENCODE_DESKTOP_APP_IDS.map((appId) => join14(dataHome, "applications", `${appId}.desktop`));
|
|
23728
24268
|
}
|
|
23729
24269
|
}
|
|
23730
24270
|
}
|
|
@@ -23751,7 +24291,7 @@ function detectOpenCodeInstallations(deps) {
|
|
|
23751
24291
|
}
|
|
23752
24292
|
}
|
|
23753
24293
|
for (const appId of OPENCODE_DESKTOP_APP_IDS) {
|
|
23754
|
-
const marker =
|
|
24294
|
+
const marker = join14(desktopUserDataDir(d, appId), OPENCODE_DESKTOP_SETTINGS_FILE);
|
|
23755
24295
|
if (d.exists(marker)) {
|
|
23756
24296
|
addCandidate(installations, seenRealpaths, d, marker, "desktop", "desktop");
|
|
23757
24297
|
}
|
|
@@ -23849,8 +24389,8 @@ var OPENCODE_BINARY_ENV = "MAGIC_CONTEXT_OPENCODE_BINARY", OPENCODE_VERSION_PROB
|
|
|
23849
24389
|
var init_opencode_helpers = () => {};
|
|
23850
24390
|
|
|
23851
24391
|
// src/adapters/opencode.ts
|
|
23852
|
-
import { existsSync as
|
|
23853
|
-
import { dirname as
|
|
24392
|
+
import { existsSync as existsSync17, readFileSync as readFileSync12, statSync as statSync10 } from "node:fs";
|
|
24393
|
+
import { dirname as dirname9, isAbsolute as isAbsolute5, parse as parsePath, resolve as resolve6 } from "node:path";
|
|
23854
24394
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
23855
24395
|
|
|
23856
24396
|
class OpenCodeAdapter {
|
|
@@ -23881,7 +24421,7 @@ class OpenCodeAdapter {
|
|
|
23881
24421
|
if (paths.opencodeConfigFormat === "none")
|
|
23882
24422
|
return false;
|
|
23883
24423
|
try {
|
|
23884
|
-
const raw =
|
|
24424
|
+
const raw = readFileSync12(paths.opencodeConfig, "utf-8");
|
|
23885
24425
|
const cfg = import_comment_json2.parse(raw);
|
|
23886
24426
|
return readPluginEntries(cfg).some(({ entry }) => matchesPluginEntry(entry, OPENCODE_PLUGIN_NAME));
|
|
23887
24427
|
} catch {
|
|
@@ -23917,7 +24457,7 @@ class OpenCodeAdapter {
|
|
|
23917
24457
|
configPath: target
|
|
23918
24458
|
};
|
|
23919
24459
|
}
|
|
23920
|
-
const raw =
|
|
24460
|
+
const raw = readFileSync12(target, "utf-8");
|
|
23921
24461
|
const cfg = import_comment_json2.parse(raw);
|
|
23922
24462
|
if (cfg === null || typeof cfg !== "object") {
|
|
23923
24463
|
return {
|
|
@@ -23929,7 +24469,7 @@ class OpenCodeAdapter {
|
|
|
23929
24469
|
}
|
|
23930
24470
|
const entries = readPluginEntries(cfg);
|
|
23931
24471
|
const existing = entries.find(({ entry }) => matchesPluginEntry(entry, OPENCODE_PLUGIN_NAME));
|
|
23932
|
-
const existingDev = entries.find(({ entry }) => isDevPathPluginEntry(entry,
|
|
24472
|
+
const existingDev = entries.find(({ entry }) => isDevPathPluginEntry(entry, dirname9(target)));
|
|
23933
24473
|
if (!existing && !existingDev) {
|
|
23934
24474
|
const list = Array.isArray(cfg[this.writeKey]) ? cfg[this.writeKey] : [];
|
|
23935
24475
|
list.push(OPENCODE_PLUGIN_ENTRY_WITH_VERSION);
|
|
@@ -23992,7 +24532,7 @@ class OpenCodeAdapter {
|
|
|
23992
24532
|
};
|
|
23993
24533
|
}
|
|
23994
24534
|
try {
|
|
23995
|
-
const raw =
|
|
24535
|
+
const raw = readFileSync12(target, "utf-8");
|
|
23996
24536
|
const cfg = import_comment_json2.parse(raw);
|
|
23997
24537
|
if (cfg === null || typeof cfg !== "object") {
|
|
23998
24538
|
return {
|
|
@@ -24043,9 +24583,9 @@ class OpenCodeAdapter {
|
|
|
24043
24583
|
}
|
|
24044
24584
|
getPluginCacheInfo() {
|
|
24045
24585
|
const legacyPath = getOpenCodePluginCacheDir();
|
|
24046
|
-
const legacyExists =
|
|
24586
|
+
const legacyExists = existsSync17(legacyPath);
|
|
24047
24587
|
const slot = getOpenCodeV2PluginCacheSlot();
|
|
24048
|
-
const slotExists =
|
|
24588
|
+
const slotExists = existsSync17(slot);
|
|
24049
24589
|
const caches = [];
|
|
24050
24590
|
if (legacyExists || !slotExists) {
|
|
24051
24591
|
caches.push({
|
|
@@ -24103,7 +24643,7 @@ class OpenCodeAdapter {
|
|
|
24103
24643
|
if (paths.opencodeConfigFormat === "none")
|
|
24104
24644
|
return "latest";
|
|
24105
24645
|
try {
|
|
24106
|
-
const cfg = import_comment_json2.parse(
|
|
24646
|
+
const cfg = import_comment_json2.parse(readFileSync12(paths.opencodeConfig, "utf-8"));
|
|
24107
24647
|
return readConfiguredOpenCodePluginSpec(cfg);
|
|
24108
24648
|
} catch {
|
|
24109
24649
|
return "latest";
|
|
@@ -24115,10 +24655,10 @@ class OpenCodeAdapter {
|
|
|
24115
24655
|
return readOpenCodeV2CachedPluginVersion(slot) ?? null;
|
|
24116
24656
|
}
|
|
24117
24657
|
for (const candidate of getOpenCodePluginPackageJsonPaths()) {
|
|
24118
|
-
if (!
|
|
24658
|
+
if (!existsSync17(candidate))
|
|
24119
24659
|
continue;
|
|
24120
24660
|
try {
|
|
24121
|
-
const raw =
|
|
24661
|
+
const raw = readFileSync12(candidate, "utf-8");
|
|
24122
24662
|
const pkg = JSON.parse(raw);
|
|
24123
24663
|
if (typeof pkg.version === "string")
|
|
24124
24664
|
return pkg.version;
|
|
@@ -24156,16 +24696,16 @@ function isDevPathPluginEntry(entry, configDir) {
|
|
|
24156
24696
|
} else {
|
|
24157
24697
|
localPath = resolve6(configDir, candidate);
|
|
24158
24698
|
}
|
|
24159
|
-
if (
|
|
24160
|
-
localPath =
|
|
24699
|
+
if (statSync10(localPath).isFile())
|
|
24700
|
+
localPath = dirname9(localPath);
|
|
24161
24701
|
const root = parsePath(localPath).root;
|
|
24162
24702
|
while (localPath !== root) {
|
|
24163
24703
|
const packagePath = resolve6(localPath, "package.json");
|
|
24164
|
-
if (
|
|
24165
|
-
const pkg = JSON.parse(
|
|
24704
|
+
if (existsSync17(packagePath)) {
|
|
24705
|
+
const pkg = JSON.parse(readFileSync12(packagePath, "utf8"));
|
|
24166
24706
|
return pkg.name === OPENCODE_PLUGIN_NAME;
|
|
24167
24707
|
}
|
|
24168
|
-
localPath =
|
|
24708
|
+
localPath = dirname9(localPath);
|
|
24169
24709
|
}
|
|
24170
24710
|
} catch {}
|
|
24171
24711
|
return false;
|
|
@@ -24181,8 +24721,8 @@ function matchesPluginEntry(entry, pkgName) {
|
|
|
24181
24721
|
return head === pkgName;
|
|
24182
24722
|
}
|
|
24183
24723
|
function ensureDir2(filePath) {
|
|
24184
|
-
const dir =
|
|
24185
|
-
if (!
|
|
24724
|
+
const dir = dirname9(filePath);
|
|
24725
|
+
if (!existsSync17(dir)) {
|
|
24186
24726
|
const { mkdirSync } = __require("node:fs");
|
|
24187
24727
|
mkdirSync(dir, { recursive: true });
|
|
24188
24728
|
}
|
|
@@ -24203,8 +24743,8 @@ var init_opencode = __esm(async () => {
|
|
|
24203
24743
|
});
|
|
24204
24744
|
|
|
24205
24745
|
// src/lib/pi-package-entry.ts
|
|
24206
|
-
import { existsSync as
|
|
24207
|
-
import { isAbsolute as isAbsolute6, join as
|
|
24746
|
+
import { existsSync as existsSync18, readFileSync as readFileSync13 } from "node:fs";
|
|
24747
|
+
import { isAbsolute as isAbsolute6, join as join15 } from "node:path";
|
|
24208
24748
|
function stripNpmPrefix(value) {
|
|
24209
24749
|
return value.startsWith("npm:") ? value.slice("npm:".length) : value;
|
|
24210
24750
|
}
|
|
@@ -24259,11 +24799,11 @@ function hasPiMagicContextPackage(entries, agentDir = getPiAgentConfigDir()) {
|
|
|
24259
24799
|
return entries.some((entry) => isConfiguredPiMagicContextEntry(entry, agentDir));
|
|
24260
24800
|
}
|
|
24261
24801
|
function isPiMagicContextPackageDir(dir) {
|
|
24262
|
-
const packageJson =
|
|
24263
|
-
if (!
|
|
24802
|
+
const packageJson = join15(dir, "package.json");
|
|
24803
|
+
if (!existsSync18(packageJson))
|
|
24264
24804
|
return false;
|
|
24265
24805
|
try {
|
|
24266
|
-
const pkg = JSON.parse(
|
|
24806
|
+
const pkg = JSON.parse(readFileSync13(packageJson, "utf-8"));
|
|
24267
24807
|
return typeof pkg.name === "string" && pkg.name === PI_MAGIC_CONTEXT_PACKAGE_NAME;
|
|
24268
24808
|
} catch {
|
|
24269
24809
|
return false;
|
|
@@ -24275,7 +24815,7 @@ function localPiMagicContextPackageDir(entry, agentDir) {
|
|
|
24275
24815
|
if (!spec || spec.startsWith("npm:"))
|
|
24276
24816
|
return null;
|
|
24277
24817
|
const path = spec.startsWith("file:") ? spec.slice("file:".length) : spec;
|
|
24278
|
-
const dir = isAbsolute6(path) ? path :
|
|
24818
|
+
const dir = isAbsolute6(path) ? path : join15(agentDir, path);
|
|
24279
24819
|
return isPiMagicContextPackageDir(dir) ? dir : null;
|
|
24280
24820
|
}
|
|
24281
24821
|
function isConfiguredPiMagicContextEntry(entry, agentDir) {
|
|
@@ -24299,8 +24839,8 @@ var init_pi_package_entry = __esm(() => {
|
|
|
24299
24839
|
});
|
|
24300
24840
|
|
|
24301
24841
|
// src/adapters/pi.ts
|
|
24302
|
-
import { existsSync as
|
|
24303
|
-
import { dirname as
|
|
24842
|
+
import { existsSync as existsSync19 } from "node:fs";
|
|
24843
|
+
import { dirname as dirname10 } from "node:path";
|
|
24304
24844
|
|
|
24305
24845
|
class PiAdapter {
|
|
24306
24846
|
kind = "pi";
|
|
@@ -24437,8 +24977,8 @@ function writePiSettings(settings) {
|
|
|
24437
24977
|
`);
|
|
24438
24978
|
}
|
|
24439
24979
|
function ensureDir3(filePath) {
|
|
24440
|
-
const dir =
|
|
24441
|
-
if (!
|
|
24980
|
+
const dir = dirname10(filePath);
|
|
24981
|
+
if (!existsSync19(dir)) {
|
|
24442
24982
|
const { mkdirSync } = __require("node:fs");
|
|
24443
24983
|
mkdirSync(dir, { recursive: true });
|
|
24444
24984
|
}
|
|
@@ -24756,7 +25296,7 @@ var init_fail_closed_block = __esm(() => {
|
|
|
24756
25296
|
});
|
|
24757
25297
|
|
|
24758
25298
|
// ../plugin/src/features/magic-context/message-fts-rowid-map.ts
|
|
24759
|
-
import { createHash } from "node:crypto";
|
|
25299
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
24760
25300
|
function getUpsertMapStatement(db) {
|
|
24761
25301
|
let statement = upsertMapStatements.get(db);
|
|
24762
25302
|
if (!statement) {
|
|
@@ -24858,7 +25398,7 @@ var MESSAGE_FTS_ROWID_MAP_BACKFILL_BATCH_SIZE = 100, BACKFILL_STATE_ID = 1, EMPT
|
|
|
24858
25398
|
var init_message_fts_rowid_map = __esm(async () => {
|
|
24859
25399
|
init_write_transaction_timing();
|
|
24860
25400
|
await init_sqlite();
|
|
24861
|
-
EMPTY_INDEX_CONTENT_HASH =
|
|
25401
|
+
EMPTY_INDEX_CONTENT_HASH = createHash2("sha256").update("").digest("hex");
|
|
24862
25402
|
upsertMapStatements = new WeakMap;
|
|
24863
25403
|
rangeReadyStatements = new WeakMap;
|
|
24864
25404
|
updateTimeStatements = new WeakMap;
|
|
@@ -24866,7 +25406,7 @@ var init_message_fts_rowid_map = __esm(async () => {
|
|
|
24866
25406
|
});
|
|
24867
25407
|
|
|
24868
25408
|
// ../plugin/src/features/magic-context/lkg-prefix-chunks.ts
|
|
24869
|
-
import { createHash as
|
|
25409
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
24870
25410
|
function splitLkgPrefix(jsonPrefix) {
|
|
24871
25411
|
const chunks = [];
|
|
24872
25412
|
let start = 0;
|
|
@@ -24883,10 +25423,10 @@ function splitLkgPrefix(jsonPrefix) {
|
|
|
24883
25423
|
return chunks;
|
|
24884
25424
|
}
|
|
24885
25425
|
function hashLkgChunk(body) {
|
|
24886
|
-
return
|
|
25426
|
+
return createHash3("sha256").update(body).digest("hex");
|
|
24887
25427
|
}
|
|
24888
25428
|
function hashLkgChunkList(chunkHashes) {
|
|
24889
|
-
return
|
|
25429
|
+
return createHash3("sha256").update(chunkHashes.join(`
|
|
24890
25430
|
`)).digest("hex");
|
|
24891
25431
|
}
|
|
24892
25432
|
function layoutLkgPrefix(jsonPrefix) {
|
|
@@ -26015,11 +26555,11 @@ function installCompartmentHistoryVersions(db) {
|
|
|
26015
26555
|
}
|
|
26016
26556
|
|
|
26017
26557
|
// ../plugin/src/features/magic-context/memory/project-identity-cache.ts
|
|
26018
|
-
import { createHash as
|
|
26019
|
-
import { readFileSync as
|
|
26558
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
26559
|
+
import { readFileSync as readFileSync14 } from "node:fs";
|
|
26020
26560
|
import path4 from "node:path";
|
|
26021
26561
|
function cachePath(directory, storageDir = getMagicContextStorageDir()) {
|
|
26022
|
-
const hash =
|
|
26562
|
+
const hash = createHash4("sha256").update(projectDirectoryKey(directory)).digest("hex");
|
|
26023
26563
|
return path4.join(storageDir, "project-identities", `${hash}.json`);
|
|
26024
26564
|
}
|
|
26025
26565
|
function rememberGitIdentity(directory, identity) {
|
|
@@ -26030,7 +26570,7 @@ function rememberGitIdentity(directory, identity) {
|
|
|
26030
26570
|
}
|
|
26031
26571
|
function readRememberedGitIdentity(directory, storageDir) {
|
|
26032
26572
|
try {
|
|
26033
|
-
const record = JSON.parse(
|
|
26573
|
+
const record = JSON.parse(readFileSync14(cachePath(directory, storageDir), "utf8"));
|
|
26034
26574
|
if (record.directory === projectDirectoryKey(directory) && /^git:[0-9a-f]{7,64}$/.test(record.identity))
|
|
26035
26575
|
return record.identity;
|
|
26036
26576
|
} catch {}
|
|
@@ -26044,9 +26584,9 @@ var init_project_identity_cache = __esm(() => {
|
|
|
26044
26584
|
|
|
26045
26585
|
// ../plugin/src/features/magic-context/memory/project-identity.ts
|
|
26046
26586
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
26047
|
-
import { createHash as
|
|
26048
|
-
import { existsSync as
|
|
26049
|
-
import { homedir as
|
|
26587
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
26588
|
+
import { existsSync as existsSync20, realpathSync as realpathSync3, statSync as statSync11 } from "node:fs";
|
|
26589
|
+
import { homedir as homedir12 } from "node:os";
|
|
26050
26590
|
import path5 from "node:path";
|
|
26051
26591
|
function asError(error) {
|
|
26052
26592
|
return error instanceof Error ? error : undefined;
|
|
@@ -26086,7 +26626,7 @@ function getErrorStderr(error) {
|
|
|
26086
26626
|
}
|
|
26087
26627
|
function directoryFallback(directory) {
|
|
26088
26628
|
const canonical = path5.resolve(directory);
|
|
26089
|
-
const hash =
|
|
26629
|
+
const hash = createHash5("md5").update(canonical, "utf8").digest("hex").slice(0, 12);
|
|
26090
26630
|
return `dir:${hash}`;
|
|
26091
26631
|
}
|
|
26092
26632
|
function rememberedIdentityOrDirectoryFallback(canonical) {
|
|
@@ -26094,7 +26634,7 @@ function rememberedIdentityOrDirectoryFallback(canonical) {
|
|
|
26094
26634
|
}
|
|
26095
26635
|
function assertDirectoryUsable(canonicalDirectory, rawDirectory) {
|
|
26096
26636
|
try {
|
|
26097
|
-
const stat =
|
|
26637
|
+
const stat = statSync11(canonicalDirectory);
|
|
26098
26638
|
if (!stat.isDirectory()) {
|
|
26099
26639
|
throw new ProjectIdentityError("unknown", rawDirectory, `Project path is not a directory: ${canonicalDirectory}`);
|
|
26100
26640
|
}
|
|
@@ -26155,10 +26695,10 @@ function classifyGitError(error, rawDirectory) {
|
|
|
26155
26695
|
}
|
|
26156
26696
|
return new ProjectIdentityError("unknown", rawDirectory, "git rev-list failed while resolving project identity", asError(error));
|
|
26157
26697
|
}
|
|
26158
|
-
function resolveProjectIdentityStrict(directory, allowHomeProject = homeProjectPermission) {
|
|
26698
|
+
function resolveProjectIdentityStrict(directory, allowHomeProject = homeProjectPermission, options = {}) {
|
|
26159
26699
|
assertProjectAllowed(directory, allowHomeProject);
|
|
26160
26700
|
const canonical = path5.resolve(directory);
|
|
26161
|
-
const cached = identityCache.get(canonical);
|
|
26701
|
+
const cached = options.cache === false ? undefined : identityCache.get(canonical);
|
|
26162
26702
|
if (cached !== undefined) {
|
|
26163
26703
|
return cached;
|
|
26164
26704
|
}
|
|
@@ -26189,6 +26729,8 @@ function resolveProjectIdentityStrict(directory, allowHomeProject = homeProjectP
|
|
|
26189
26729
|
throw new ProjectIdentityError("unknown", directory, "git rev-list returned no valid root commit hash");
|
|
26190
26730
|
}
|
|
26191
26731
|
const identity = `git:${rootCommit}`;
|
|
26732
|
+
if (options.cache === false)
|
|
26733
|
+
return identity;
|
|
26192
26734
|
identityCache.set(canonical, identity);
|
|
26193
26735
|
lastKnownGitIdentityCache.set(canonical, identity);
|
|
26194
26736
|
rememberGitIdentity(canonical, identity);
|
|
@@ -26224,7 +26766,7 @@ function nearestLastKnownGitIdentity(canonical) {
|
|
|
26224
26766
|
const cached = lastKnownGitIdentity(current);
|
|
26225
26767
|
if (cached !== undefined)
|
|
26226
26768
|
return { identity: cached, source: current };
|
|
26227
|
-
if (
|
|
26769
|
+
if (existsSync20(path5.join(current, ".git")))
|
|
26228
26770
|
break;
|
|
26229
26771
|
const parent = path5.dirname(current);
|
|
26230
26772
|
if (parent === current)
|
|
@@ -26347,7 +26889,7 @@ function hasGitDir(canonical) {
|
|
|
26347
26889
|
function gitRootInAncestorChain(startDirectory) {
|
|
26348
26890
|
let current = startDirectory;
|
|
26349
26891
|
while (true) {
|
|
26350
|
-
if (
|
|
26892
|
+
if (existsSync20(path5.join(current, ".git"))) {
|
|
26351
26893
|
try {
|
|
26352
26894
|
return realpathSync3.native(current);
|
|
26353
26895
|
} catch {
|
|
@@ -26375,7 +26917,7 @@ function gitRootDirectory(canonical) {
|
|
|
26375
26917
|
return null;
|
|
26376
26918
|
}
|
|
26377
26919
|
}
|
|
26378
|
-
var GIT_TIMEOUT_MS = 5000, TRANSIENT_FAILURE_COOLDOWN_MS, identityCache, linkedGitWorktreeCache, lastKnownGitIdentityCache, directoryFallbackCache, transientFailureCooldown, dubiousOwnershipFallbackDirectories, dubiousOwnershipLoggedDirectories, dubiousOwnershipWarnedDirectories, transientGitIdentityReuseLoggedDirectories, sessionIdentityCache, homeProjectPermission = false, pausedIdentityReasons, pausedIdentityLogged, execFileSyncForIdentity, userHomeDirectoryForIdentity = () =>
|
|
26920
|
+
var GIT_TIMEOUT_MS = 5000, TRANSIENT_FAILURE_COOLDOWN_MS, identityCache, linkedGitWorktreeCache, lastKnownGitIdentityCache, directoryFallbackCache, transientFailureCooldown, dubiousOwnershipFallbackDirectories, dubiousOwnershipLoggedDirectories, dubiousOwnershipWarnedDirectories, transientGitIdentityReuseLoggedDirectories, sessionIdentityCache, homeProjectPermission = false, pausedIdentityReasons, pausedIdentityLogged, execFileSyncForIdentity, userHomeDirectoryForIdentity = () => homedir12(), nowMs = () => Date.now(), ProjectIdentityError;
|
|
26379
26921
|
var init_project_identity = __esm(() => {
|
|
26380
26922
|
init_logger();
|
|
26381
26923
|
init_project_identity_cache();
|
|
@@ -29659,7 +30201,7 @@ var init_tool_definition_tokens = __esm(() => {
|
|
|
29659
30201
|
});
|
|
29660
30202
|
|
|
29661
30203
|
// ../plugin/src/features/magic-context/tool-owner-backfill.ts
|
|
29662
|
-
import { existsSync as
|
|
30204
|
+
import { existsSync as existsSync21 } from "node:fs";
|
|
29663
30205
|
function resolveOpencodeDbPath() {
|
|
29664
30206
|
return resolveOpenCodeDbPath().path;
|
|
29665
30207
|
}
|
|
@@ -29696,7 +30238,7 @@ function runToolOwnerBackfill(db) {
|
|
|
29696
30238
|
return result;
|
|
29697
30239
|
}
|
|
29698
30240
|
const opencodeDbPath = resolveOpencodeDbPath();
|
|
29699
|
-
if (!
|
|
30241
|
+
if (!existsSync21(opencodeDbPath)) {
|
|
29700
30242
|
log(`[backfill] OpenCode DB not found at ${opencodeDbPath} — marking all unbackfilled sessions as skipped. Lazy adoption (defense-in-depth) handles legacy rows at runtime.`);
|
|
29701
30243
|
markAllUnbackfilledSessionsSkipped(db);
|
|
29702
30244
|
result.sessionsSkippedNoOcDb = countSessionsByStatus(db, "skipped");
|
|
@@ -30300,7 +30842,10 @@ function isRecord2(value) {
|
|
|
30300
30842
|
}
|
|
30301
30843
|
|
|
30302
30844
|
// ../plugin/src/shared/tag-owner-id.ts
|
|
30303
|
-
var
|
|
30845
|
+
var PI_FALLBACK_PREFIXES_JSON;
|
|
30846
|
+
var init_tag_owner_id = __esm(() => {
|
|
30847
|
+
PI_FALLBACK_PREFIXES_JSON = JSON.stringify([..."pi-msg-"].reduce((prefixes, char) => prefixes.flatMap((prefix) => /[a-z]/.test(char) ? [prefix + char, prefix + char.toUpperCase()] : [prefix + char]), [""]));
|
|
30848
|
+
});
|
|
30304
30849
|
|
|
30305
30850
|
// ../plugin/src/hooks/magic-context/image-token-estimate.ts
|
|
30306
30851
|
var JPEG_SCAN_LIMIT_BYTES;
|
|
@@ -31666,6 +32211,8 @@ function runSessionWarmupWorker(input, options) {
|
|
|
31666
32211
|
finish({ delta: reply.delta });
|
|
31667
32212
|
else if (reply.kind === "indexed")
|
|
31668
32213
|
finish({ inserted: reply.inserted, measurements: reply.measurements });
|
|
32214
|
+
else if (reply.kind === "orphan-sweep")
|
|
32215
|
+
finish({ orphanSweep: reply.result });
|
|
31669
32216
|
else
|
|
31670
32217
|
finish({ failure: "worker-error", detail: reply.error });
|
|
31671
32218
|
});
|
|
@@ -33193,6 +33740,14 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
|
|
|
33193
33740
|
pinComponentWhenFormattedBudgetCrosses(msg.ordinal, text);
|
|
33194
33741
|
}
|
|
33195
33742
|
if (flushCurrentBlock() && pendingNoiseMeta.length > 0) {
|
|
33743
|
+
const lastNoise = pendingNoiseMeta[pendingNoiseMeta.length - 1];
|
|
33744
|
+
if (messagesProcessed > 0 && lastNoise) {
|
|
33745
|
+
lineMeta.push(...pendingNoiseMeta);
|
|
33746
|
+
messagesProcessed += pendingNoiseMeta.length;
|
|
33747
|
+
lastOrdinal = lastNoise.ordinal;
|
|
33748
|
+
lastMessageId = lastNoise.messageId;
|
|
33749
|
+
pendingNoiseMeta = [];
|
|
33750
|
+
}
|
|
33196
33751
|
highestScannedOrdinal = Math.max(highestScannedOrdinal, pendingNoiseMeta[pendingNoiseMeta.length - 1]?.ordinal ?? highestScannedOrdinal);
|
|
33197
33752
|
}
|
|
33198
33753
|
const toolOnlyRanges = [];
|
|
@@ -33396,14 +33951,14 @@ var init_message_time_backfill = __esm(async () => {
|
|
|
33396
33951
|
|
|
33397
33952
|
// ../plugin/src/features/magic-context/storage-db.ts
|
|
33398
33953
|
import {
|
|
33399
|
-
existsSync as
|
|
33954
|
+
existsSync as existsSync22,
|
|
33400
33955
|
readdirSync as readdirSync5,
|
|
33401
|
-
readFileSync as
|
|
33956
|
+
readFileSync as readFileSync15,
|
|
33402
33957
|
rmdirSync,
|
|
33403
|
-
statSync as
|
|
33958
|
+
statSync as statSync12,
|
|
33404
33959
|
unlinkSync as unlinkSync3
|
|
33405
33960
|
} from "node:fs";
|
|
33406
|
-
import { basename as basename3, dirname as
|
|
33961
|
+
import { basename as basename3, dirname as dirname11, join as join16, resolve as resolve7 } from "node:path";
|
|
33407
33962
|
function ensureSecureStorageDir(dir) {
|
|
33408
33963
|
ensureStorageDirectorySync(dir);
|
|
33409
33964
|
}
|
|
@@ -33424,17 +33979,17 @@ function installBootBusyTimeout(db, dbPath, timeoutMs, report = log) {
|
|
|
33424
33979
|
}
|
|
33425
33980
|
function resolveDatabasePath(dbPathOverride) {
|
|
33426
33981
|
if (dbPathOverride) {
|
|
33427
|
-
return { dbDir:
|
|
33982
|
+
return { dbDir: dirname11(dbPathOverride), dbPath: dbPathOverride };
|
|
33428
33983
|
}
|
|
33429
33984
|
const dbDir = getMagicContextStorageDir();
|
|
33430
|
-
return { dbDir, dbPath:
|
|
33985
|
+
return { dbDir, dbPath: join16(dbDir, "context.db") };
|
|
33431
33986
|
}
|
|
33432
33987
|
function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
33433
|
-
if (
|
|
33988
|
+
if (existsSync22(targetDbPath))
|
|
33434
33989
|
return;
|
|
33435
33990
|
const legacyDir = getLegacyOpenCodeMagicContextStorageDir();
|
|
33436
|
-
const legacyDbPath =
|
|
33437
|
-
if (!
|
|
33991
|
+
const legacyDbPath = join16(legacyDir, "context.db");
|
|
33992
|
+
if (!existsSync22(legacyDbPath))
|
|
33438
33993
|
return;
|
|
33439
33994
|
log(`[magic-context] migrating legacy plugin storage: ${legacyDir} -> ${targetDbDir} (legacy left in place as backup)`);
|
|
33440
33995
|
ensureSecureStorageDir(targetDbDir);
|
|
@@ -33451,8 +34006,8 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
|
33451
34006
|
}
|
|
33452
34007
|
for (const suffix of ["", "-wal", "-shm"]) {
|
|
33453
34008
|
const src = `${legacyDbPath}${suffix}`;
|
|
33454
|
-
const dst =
|
|
33455
|
-
if (
|
|
34009
|
+
const dst = join16(targetDbDir, `context.db${suffix}`);
|
|
34010
|
+
if (existsSync22(src)) {
|
|
33456
34011
|
try {
|
|
33457
34012
|
copyStorageFileSync(src, dst);
|
|
33458
34013
|
} catch (error) {
|
|
@@ -33460,9 +34015,9 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
|
33460
34015
|
}
|
|
33461
34016
|
}
|
|
33462
34017
|
}
|
|
33463
|
-
const legacyModelsDir =
|
|
33464
|
-
const targetModelsDir =
|
|
33465
|
-
if (
|
|
34018
|
+
const legacyModelsDir = join16(legacyDir, "models");
|
|
34019
|
+
const targetModelsDir = join16(targetDbDir, "models");
|
|
34020
|
+
if (existsSync22(legacyModelsDir) && !existsSync22(targetModelsDir)) {
|
|
33466
34021
|
try {
|
|
33467
34022
|
copyStorageTreeSync(legacyModelsDir, targetModelsDir);
|
|
33468
34023
|
} catch (error) {
|
|
@@ -33570,7 +34125,7 @@ function classifyJunkDiscovery(portFile, raw, staleFiles) {
|
|
|
33570
34125
|
function inspectRpcServerDiscovery(storageDir, processes, options) {
|
|
33571
34126
|
const deadline = options?.deadlineMs === undefined ? Number.POSITIVE_INFINITY : Date.now() + options.deadlineMs;
|
|
33572
34127
|
let progressAt = Date.now() + 3000;
|
|
33573
|
-
const rpcRoot =
|
|
34128
|
+
const rpcRoot = join16(storageDir, "rpc");
|
|
33574
34129
|
let projectEntries;
|
|
33575
34130
|
try {
|
|
33576
34131
|
projectEntries = rpcDiscoveryFs.readdirSync(rpcRoot, { withFileTypes: true });
|
|
@@ -33584,7 +34139,7 @@ function inspectRpcServerDiscovery(storageDir, processes, options) {
|
|
|
33584
34139
|
for (const projectEntry of projectEntries) {
|
|
33585
34140
|
if (!projectEntry.isDirectory())
|
|
33586
34141
|
continue;
|
|
33587
|
-
const projectDir =
|
|
34142
|
+
const projectDir = join16(rpcRoot, projectEntry.name);
|
|
33588
34143
|
let entries;
|
|
33589
34144
|
try {
|
|
33590
34145
|
entries = rpcDiscoveryFs.readdirSync(projectDir);
|
|
@@ -33595,7 +34150,7 @@ function inspectRpcServerDiscovery(storageDir, processes, options) {
|
|
|
33595
34150
|
}
|
|
33596
34151
|
for (const entry of entries) {
|
|
33597
34152
|
if (entry === "port" || entry.startsWith("port-") && entry.endsWith(".json")) {
|
|
33598
|
-
portFiles.push(
|
|
34153
|
+
portFiles.push(join16(projectDir, entry));
|
|
33599
34154
|
}
|
|
33600
34155
|
}
|
|
33601
34156
|
}
|
|
@@ -33698,7 +34253,7 @@ function inspectRpcServerDiscovery(storageDir, processes, options) {
|
|
|
33698
34253
|
return { state: "stale", serverPids: [], staleFiles };
|
|
33699
34254
|
}
|
|
33700
34255
|
function pruneEmptyRpcDiscoveryDirs(storageDir) {
|
|
33701
|
-
const rpcRoot =
|
|
34256
|
+
const rpcRoot = join16(storageDir, "rpc");
|
|
33702
34257
|
let entries;
|
|
33703
34258
|
try {
|
|
33704
34259
|
entries = rpcDiscoveryFs.readdirSync(rpcRoot, { withFileTypes: true });
|
|
@@ -33710,7 +34265,7 @@ function pruneEmptyRpcDiscoveryDirs(storageDir) {
|
|
|
33710
34265
|
for (const entry of entries) {
|
|
33711
34266
|
if (!entry.isDirectory())
|
|
33712
34267
|
continue;
|
|
33713
|
-
const projectDir =
|
|
34268
|
+
const projectDir = join16(rpcRoot, entry.name);
|
|
33714
34269
|
try {
|
|
33715
34270
|
if (rpcDiscoveryFs.readdirSync(projectDir).length > 0)
|
|
33716
34271
|
continue;
|
|
@@ -33724,12 +34279,12 @@ function pruneEmptyRpcDiscoveryDirs(storageDir) {
|
|
|
33724
34279
|
return removed;
|
|
33725
34280
|
}
|
|
33726
34281
|
function removeRpcDiscoveryRecords(storageDir, files) {
|
|
33727
|
-
const rpcRoot = resolve7(
|
|
34282
|
+
const rpcRoot = resolve7(join16(storageDir, "rpc"));
|
|
33728
34283
|
const removed = [];
|
|
33729
34284
|
const failed = [];
|
|
33730
34285
|
for (const file of files) {
|
|
33731
|
-
const projectDir =
|
|
33732
|
-
if (
|
|
34286
|
+
const projectDir = dirname11(resolve7(file));
|
|
34287
|
+
if (dirname11(projectDir) !== rpcRoot || !basename3(file).startsWith("port")) {
|
|
33733
34288
|
failed.push({ file, error: "not an RPC discovery record" });
|
|
33734
34289
|
continue;
|
|
33735
34290
|
}
|
|
@@ -33776,7 +34331,7 @@ function isDefaultSharedDatabasePath(dbPath) {
|
|
|
33776
34331
|
if (!process.env.XDG_DATA_HOME && (process.env.MAGIC_CONTEXT_TEST_DATA_DIR || false)) {
|
|
33777
34332
|
return false;
|
|
33778
34333
|
}
|
|
33779
|
-
return resolve7(dbPath) === resolve7(
|
|
34334
|
+
return resolve7(dbPath) === resolve7(join16(getMagicContextStorageDir(), "context.db"));
|
|
33780
34335
|
}
|
|
33781
34336
|
function migrationBlockingPiPids(dbPath, discovery, discoveredPiPids) {
|
|
33782
34337
|
if (isDefaultSharedDatabasePath(dbPath))
|
|
@@ -33886,7 +34441,7 @@ function finishDatabaseOpen(db, dbPath, explicitDbPath, latestSupportedVersion)
|
|
|
33886
34441
|
}
|
|
33887
34442
|
setDatabase(db);
|
|
33888
34443
|
loadToolDefinitionMeasurements(db);
|
|
33889
|
-
tightenStorageTree(
|
|
34444
|
+
tightenStorageTree(dirname11(dbPath));
|
|
33890
34445
|
databases.set(dbPath, db);
|
|
33891
34446
|
pathByDatabase.set(db, dbPath);
|
|
33892
34447
|
persistenceByDatabase.set(db, true);
|
|
@@ -35181,7 +35736,7 @@ function openDatabase(dbPathOrOptions) {
|
|
|
35181
35736
|
}
|
|
35182
35737
|
ensureSecureStorageDir(dbDir);
|
|
35183
35738
|
tightenStorageTree(dbDir);
|
|
35184
|
-
if (!
|
|
35739
|
+
if (!existsSync22(dbPath) && shouldEnforcePrivateStoragePermissions()) {
|
|
35185
35740
|
try {
|
|
35186
35741
|
writeStorageFileSync(dbPath, new Uint8Array, { flag: "wx" });
|
|
35187
35742
|
} catch (error) {
|
|
@@ -35267,8 +35822,8 @@ var init_storage_db = __esm(async () => {
|
|
|
35267
35822
|
RPC_DISCOVERY_PARSE_GRACE_MS = 10 * 60 * 1000;
|
|
35268
35823
|
defaultRpcDiscoveryFs = {
|
|
35269
35824
|
readdirSync: (path, options) => options?.withFileTypes ? readdirSync5(path, { withFileTypes: true }) : readdirSync5(path),
|
|
35270
|
-
readFileSync: (path, encoding) => String(
|
|
35271
|
-
statSync: (path) => ({ mtimeMs:
|
|
35825
|
+
readFileSync: (path, encoding) => String(readFileSync15(path, encoding)),
|
|
35826
|
+
statSync: (path) => ({ mtimeMs: statSync12(path).mtimeMs }),
|
|
35272
35827
|
unlinkSync: (path) => unlinkSync3(path),
|
|
35273
35828
|
rmdirSync: (path) => rmdirSync(path)
|
|
35274
35829
|
};
|
|
@@ -35282,14 +35837,14 @@ var init_storage_db = __esm(async () => {
|
|
|
35282
35837
|
});
|
|
35283
35838
|
|
|
35284
35839
|
// src/lib/database-access.ts
|
|
35285
|
-
import { existsSync as
|
|
35286
|
-
import { dirname as
|
|
35840
|
+
import { existsSync as existsSync23, rmSync as rmSync6 } from "node:fs";
|
|
35841
|
+
import { dirname as dirname12 } from "node:path";
|
|
35287
35842
|
import { pathToFileURL } from "node:url";
|
|
35288
35843
|
function getPersistedSchemaVersion2(db) {
|
|
35289
35844
|
return getPersistedSchemaVersion(db);
|
|
35290
35845
|
}
|
|
35291
35846
|
function openExistingDatabase(path, options) {
|
|
35292
|
-
if (!
|
|
35847
|
+
if (!existsSync23(path))
|
|
35293
35848
|
return null;
|
|
35294
35849
|
if (options.readonly) {
|
|
35295
35850
|
const db = new Database(path, { readonly: true });
|
|
@@ -35338,7 +35893,7 @@ function openExistingContextDatabaseForMutation(path) {
|
|
|
35338
35893
|
async function backupDatabaseSnapshot(db, sourcePath, destination) {
|
|
35339
35894
|
const serializable = db;
|
|
35340
35895
|
if (typeof serializable.serialize === "function") {
|
|
35341
|
-
ensureStorageDirectorySync(
|
|
35896
|
+
ensureStorageDirectorySync(dirname12(destination));
|
|
35342
35897
|
writeStorageFileSync(destination, serializable.serialize(), { flag: "wx" });
|
|
35343
35898
|
return;
|
|
35344
35899
|
}
|
|
@@ -35347,7 +35902,7 @@ async function backupDatabaseSnapshot(db, sourcePath, destination) {
|
|
|
35347
35902
|
if (typeof sqlite.backup !== "function") {
|
|
35348
35903
|
throw new Error("The active SQLite runtime does not provide a snapshot backup API");
|
|
35349
35904
|
}
|
|
35350
|
-
if (
|
|
35905
|
+
if (existsSync23(destination)) {
|
|
35351
35906
|
throw new Error(`Refusing to overwrite existing backup ${destination}`);
|
|
35352
35907
|
}
|
|
35353
35908
|
const reader = new Database(sourcePath, { readonly: true });
|
|
@@ -35355,7 +35910,7 @@ async function backupDatabaseSnapshot(db, sourcePath, destination) {
|
|
|
35355
35910
|
try {
|
|
35356
35911
|
await sqlite.backup(reader, destination);
|
|
35357
35912
|
} catch (error) {
|
|
35358
|
-
|
|
35913
|
+
rmSync6(destination, { force: true });
|
|
35359
35914
|
throw error;
|
|
35360
35915
|
} finally {
|
|
35361
35916
|
reader.close();
|
|
@@ -35633,11 +36188,11 @@ var init_dreamer_setup = __esm(() => {
|
|
|
35633
36188
|
});
|
|
35634
36189
|
|
|
35635
36190
|
// src/commands/setup-pi.ts
|
|
35636
|
-
import { existsSync as
|
|
35637
|
-
import { dirname as
|
|
36191
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync5 } from "node:fs";
|
|
36192
|
+
import { dirname as dirname13 } from "node:path";
|
|
35638
36193
|
function ensureDir4(path) {
|
|
35639
|
-
if (!
|
|
35640
|
-
|
|
36194
|
+
if (!existsSync24(path))
|
|
36195
|
+
mkdirSync5(path, { recursive: true });
|
|
35641
36196
|
}
|
|
35642
36197
|
async function getDefaultPrompts() {
|
|
35643
36198
|
await Promise.resolve().then(() => init_prompts());
|
|
@@ -35669,7 +36224,7 @@ function comparePiVersion(a, b) {
|
|
|
35669
36224
|
}
|
|
35670
36225
|
function writePiSettingsPackage(settingsPath, packageSource = PI_PACKAGE_SOURCE) {
|
|
35671
36226
|
const settings = readJsoncConfigForUpdate(settingsPath);
|
|
35672
|
-
ensureDir4(
|
|
36227
|
+
ensureDir4(dirname13(settingsPath));
|
|
35673
36228
|
if (settings.packages !== undefined && !Array.isArray(settings.packages)) {
|
|
35674
36229
|
throw new Error(`Refusing to rewrite ${settingsPath}: "packages" is ${typeof settings.packages}, expected an array. Fix it by hand, then rerun setup.`);
|
|
35675
36230
|
}
|
|
@@ -35700,7 +36255,7 @@ function removePiSettingsPackage(settingsPath, packageSource = PI_PACKAGE_SOURCE
|
|
|
35700
36255
|
}
|
|
35701
36256
|
function writeMagicContextConfig(configPath, options) {
|
|
35702
36257
|
const config = readMagicContextConfigForSetup(configPath);
|
|
35703
|
-
ensureDir4(
|
|
36258
|
+
ensureDir4(dirname13(configPath));
|
|
35704
36259
|
if (!config.$schema) {
|
|
35705
36260
|
config.$schema = "https://raw.githubusercontent.com/cortexkit/magic-context/master/assets/magic-context.schema.json";
|
|
35706
36261
|
}
|
|
@@ -36091,16 +36646,16 @@ var init_setup_omp = __esm(() => {
|
|
|
36091
36646
|
});
|
|
36092
36647
|
|
|
36093
36648
|
// ../plugin/src/shared/opencode-config-dir.ts
|
|
36094
|
-
import { homedir as
|
|
36095
|
-
import { join as
|
|
36649
|
+
import { homedir as homedir13 } from "node:os";
|
|
36650
|
+
import { join as join17, resolve as resolve8 } from "node:path";
|
|
36096
36651
|
function resolveHomeDir() {
|
|
36097
|
-
return process.env.HOME?.trim() ||
|
|
36652
|
+
return process.env.HOME?.trim() || homedir13();
|
|
36098
36653
|
}
|
|
36099
36654
|
function getOpenCodeGlobalConfigDir() {
|
|
36100
36655
|
if (process.platform === "win32") {
|
|
36101
|
-
return
|
|
36656
|
+
return join17(resolveHomeDir(), ".config", "opencode");
|
|
36102
36657
|
}
|
|
36103
|
-
return
|
|
36658
|
+
return join17(process.env.XDG_CONFIG_HOME || join17(resolveHomeDir(), ".config"), "opencode");
|
|
36104
36659
|
}
|
|
36105
36660
|
function getEnvConfigDir() {
|
|
36106
36661
|
const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
@@ -36116,14 +36671,14 @@ function getOpenCodeConfigPaths(options) {
|
|
|
36116
36671
|
const configDir = getOpenCodeConfigDir2(options);
|
|
36117
36672
|
return {
|
|
36118
36673
|
configDir,
|
|
36119
|
-
configJson:
|
|
36120
|
-
configJsonc:
|
|
36121
|
-
packageJson:
|
|
36122
|
-
omoConfig:
|
|
36674
|
+
configJson: join17(configDir, "opencode.json"),
|
|
36675
|
+
configJsonc: join17(configDir, "opencode.jsonc"),
|
|
36676
|
+
packageJson: join17(configDir, "package.json"),
|
|
36677
|
+
omoConfig: join17(configDir, "magic-context.jsonc")
|
|
36123
36678
|
};
|
|
36124
36679
|
}
|
|
36125
36680
|
function getOpenCodeConfigDirs() {
|
|
36126
|
-
const dirs = [getOpenCodeGlobalConfigDir(),
|
|
36681
|
+
const dirs = [getOpenCodeGlobalConfigDir(), join17(resolveHomeDir(), ".opencode")];
|
|
36127
36682
|
const envDir = getEnvConfigDir();
|
|
36128
36683
|
if (envDir)
|
|
36129
36684
|
dirs.push(envDir);
|
|
@@ -36132,8 +36687,8 @@ function getOpenCodeConfigDirs() {
|
|
|
36132
36687
|
var init_opencode_config_dir = () => {};
|
|
36133
36688
|
|
|
36134
36689
|
// ../plugin/src/shared/conflict-detector.ts
|
|
36135
|
-
import { homedir as
|
|
36136
|
-
import { join as
|
|
36690
|
+
import { homedir as homedir14 } from "node:os";
|
|
36691
|
+
import { join as join18 } from "node:path";
|
|
36137
36692
|
function detectConflicts(directory, options) {
|
|
36138
36693
|
const compactionEnabled = options?.compactionEnabled ?? true;
|
|
36139
36694
|
const hostGeneration = options?.hostGeneration ?? "v1";
|
|
@@ -36200,19 +36755,19 @@ function checkCompaction(directory, hostGeneration) {
|
|
|
36200
36755
|
function openCodeConfigFileChain(directory, hostGeneration) {
|
|
36201
36756
|
const globalDir = getOpenCodeGlobalConfigDir();
|
|
36202
36757
|
const wellKnown = [
|
|
36203
|
-
|
|
36204
|
-
|
|
36205
|
-
|
|
36758
|
+
join18(globalDir, "config.json"),
|
|
36759
|
+
join18(globalDir, "opencode.json"),
|
|
36760
|
+
join18(globalDir, "opencode.jsonc")
|
|
36206
36761
|
];
|
|
36207
|
-
const globalSupplementary = getOpenCodeConfigDirs().filter((dir) => dir !== globalDir).flatMap((dir) => [
|
|
36762
|
+
const globalSupplementary = getOpenCodeConfigDirs().filter((dir) => dir !== globalDir).flatMap((dir) => [join18(dir, "opencode.json"), join18(dir, "opencode.jsonc")]);
|
|
36208
36763
|
const explicitConfig = process.env.OPENCODE_CONFIG?.trim();
|
|
36209
36764
|
const explicit = explicitConfig ? [explicitConfig] : [];
|
|
36210
36765
|
const disableProjectConfig = process.env.OPENCODE_DISABLE_PROJECT_CONFIG?.toLowerCase();
|
|
36211
36766
|
const skipProject = hostGeneration === "v1" && (disableProjectConfig === "true" || disableProjectConfig === "1");
|
|
36212
|
-
const direct = skipProject ? [] : [
|
|
36767
|
+
const direct = skipProject ? [] : [join18(directory, "opencode.json"), join18(directory, "opencode.jsonc")];
|
|
36213
36768
|
const projectSupplementary = skipProject ? [] : [
|
|
36214
|
-
|
|
36215
|
-
|
|
36769
|
+
join18(directory, ".opencode", "opencode.json"),
|
|
36770
|
+
join18(directory, ".opencode", "opencode.jsonc")
|
|
36216
36771
|
];
|
|
36217
36772
|
const files = hostGeneration === "v2" ? [
|
|
36218
36773
|
...wellKnown,
|
|
@@ -36299,10 +36854,10 @@ function collectPluginEntries(directory) {
|
|
|
36299
36854
|
}
|
|
36300
36855
|
};
|
|
36301
36856
|
for (const configPath of [
|
|
36302
|
-
|
|
36303
|
-
|
|
36304
|
-
|
|
36305
|
-
|
|
36857
|
+
join18(directory, ".opencode", "opencode.jsonc"),
|
|
36858
|
+
join18(directory, ".opencode", "opencode.json"),
|
|
36859
|
+
join18(directory, "opencode.jsonc"),
|
|
36860
|
+
join18(directory, "opencode.json")
|
|
36306
36861
|
]) {
|
|
36307
36862
|
const config = readJsoncFile(configPath);
|
|
36308
36863
|
pushFrom(config?.plugin);
|
|
@@ -36312,7 +36867,7 @@ function collectPluginEntries(directory) {
|
|
|
36312
36867
|
for (const dir of getOpenCodeConfigDirs()) {
|
|
36313
36868
|
const names = dir === globalDir ? ["config.json", "opencode.json", "opencode.jsonc"] : ["opencode.json", "opencode.jsonc"];
|
|
36314
36869
|
for (const name of names) {
|
|
36315
|
-
const config = readJsoncFile(
|
|
36870
|
+
const config = readJsoncFile(join18(dir, name));
|
|
36316
36871
|
pushFrom(config?.plugin);
|
|
36317
36872
|
}
|
|
36318
36873
|
}
|
|
@@ -36346,7 +36901,7 @@ function readOmoDisabledHooks(directory) {
|
|
|
36346
36901
|
try {
|
|
36347
36902
|
for (const dir of getOpenCodeConfigDirs()) {
|
|
36348
36903
|
for (const name of configNames) {
|
|
36349
|
-
const config = readJsoncFile(
|
|
36904
|
+
const config = readJsoncFile(join18(dir, name));
|
|
36350
36905
|
if (config?.disabled_hooks) {
|
|
36351
36906
|
for (const hook of config.disabled_hooks) {
|
|
36352
36907
|
disabled.add(hook);
|
|
@@ -36356,17 +36911,17 @@ function readOmoDisabledHooks(directory) {
|
|
|
36356
36911
|
}
|
|
36357
36912
|
} catch {}
|
|
36358
36913
|
for (const name of configNames) {
|
|
36359
|
-
const config = readJsoncFile(
|
|
36914
|
+
const config = readJsoncFile(join18(directory, name));
|
|
36360
36915
|
if (config?.disabled_hooks) {
|
|
36361
36916
|
for (const hook of config.disabled_hooks) {
|
|
36362
36917
|
disabled.add(hook);
|
|
36363
36918
|
}
|
|
36364
36919
|
}
|
|
36365
36920
|
}
|
|
36366
|
-
const homeDir = process.env.HOME ||
|
|
36367
|
-
const omoHomeDir =
|
|
36921
|
+
const homeDir = process.env.HOME || homedir14();
|
|
36922
|
+
const omoHomeDir = join18(homeDir, ".omo");
|
|
36368
36923
|
for (const name of ["omo.jsonc", "omo.json"]) {
|
|
36369
|
-
const config = readJsoncFile(
|
|
36924
|
+
const config = readJsoncFile(join18(omoHomeDir, name));
|
|
36370
36925
|
if (config?.["[opencode]"]?.disabled_hooks) {
|
|
36371
36926
|
for (const hook of config["[opencode]"].disabled_hooks) {
|
|
36372
36927
|
disabled.add(hook);
|
|
@@ -36374,7 +36929,7 @@ function readOmoDisabledHooks(directory) {
|
|
|
36374
36929
|
}
|
|
36375
36930
|
}
|
|
36376
36931
|
for (const name of ["omo.jsonc", "omo.json"]) {
|
|
36377
|
-
const config = readJsoncFile(
|
|
36932
|
+
const config = readJsoncFile(join18(directory, ".omo", name));
|
|
36378
36933
|
if (config?.["[opencode]"]?.disabled_hooks) {
|
|
36379
36934
|
for (const hook of config["[opencode]"].disabled_hooks) {
|
|
36380
36935
|
disabled.add(hook);
|
|
@@ -36393,9 +36948,9 @@ var init_conflict_detector = __esm(() => {
|
|
|
36393
36948
|
});
|
|
36394
36949
|
|
|
36395
36950
|
// ../plugin/src/shared/conflict-fixer.ts
|
|
36396
|
-
import { existsSync as
|
|
36397
|
-
import { homedir as
|
|
36398
|
-
import { join as
|
|
36951
|
+
import { existsSync as existsSync25, readFileSync as readFileSync16, writeFileSync as writeFileSync5 } from "node:fs";
|
|
36952
|
+
import { homedir as homedir15 } from "node:os";
|
|
36953
|
+
import { join as join19 } from "node:path";
|
|
36399
36954
|
function isRecord3(value) {
|
|
36400
36955
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
36401
36956
|
}
|
|
@@ -36403,11 +36958,11 @@ function asStringArray(value) {
|
|
|
36403
36958
|
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
36404
36959
|
}
|
|
36405
36960
|
function readConfig(filePath) {
|
|
36406
|
-
if (!
|
|
36961
|
+
if (!existsSync25(filePath)) {
|
|
36407
36962
|
return null;
|
|
36408
36963
|
}
|
|
36409
36964
|
try {
|
|
36410
|
-
const text =
|
|
36965
|
+
const text = readFileSync16(filePath, "utf-8");
|
|
36411
36966
|
const parsed = import_comment_json5.parse(text);
|
|
36412
36967
|
return isRecord3(parsed) ? { config: parsed, text } : null;
|
|
36413
36968
|
} catch {
|
|
@@ -36415,27 +36970,27 @@ function readConfig(filePath) {
|
|
|
36415
36970
|
}
|
|
36416
36971
|
}
|
|
36417
36972
|
function writeConfig(filePath, text) {
|
|
36418
|
-
|
|
36973
|
+
writeFileSync5(filePath, text);
|
|
36419
36974
|
}
|
|
36420
36975
|
function resolveUserOpenCodeConfigPath() {
|
|
36421
36976
|
const paths = getOpenCodeConfigPaths({ binary: "opencode" });
|
|
36422
|
-
if (
|
|
36977
|
+
if (existsSync25(paths.configJsonc))
|
|
36423
36978
|
return paths.configJsonc;
|
|
36424
36979
|
return paths.configJson;
|
|
36425
36980
|
}
|
|
36426
36981
|
function collectOpenCodeConfigPaths(directory) {
|
|
36427
36982
|
const paths = new Set;
|
|
36428
36983
|
const userConfig = resolveUserOpenCodeConfigPath();
|
|
36429
|
-
if (
|
|
36984
|
+
if (existsSync25(userConfig)) {
|
|
36430
36985
|
paths.add(userConfig);
|
|
36431
36986
|
}
|
|
36432
36987
|
for (const filePath of [
|
|
36433
|
-
|
|
36434
|
-
|
|
36435
|
-
|
|
36436
|
-
|
|
36988
|
+
join19(directory, ".opencode", "opencode.jsonc"),
|
|
36989
|
+
join19(directory, ".opencode", "opencode.json"),
|
|
36990
|
+
join19(directory, "opencode.jsonc"),
|
|
36991
|
+
join19(directory, "opencode.json")
|
|
36437
36992
|
]) {
|
|
36438
|
-
if (
|
|
36993
|
+
if (existsSync25(filePath)) {
|
|
36439
36994
|
paths.add(filePath);
|
|
36440
36995
|
}
|
|
36441
36996
|
}
|
|
@@ -36445,26 +37000,26 @@ function collectOmoConfigPaths(directory) {
|
|
|
36445
37000
|
const paths = new Set;
|
|
36446
37001
|
const configDir = getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
|
|
36447
37002
|
for (const fileName of OMO_CONFIG_NAMES) {
|
|
36448
|
-
const userPath =
|
|
36449
|
-
const projectPath =
|
|
36450
|
-
if (
|
|
37003
|
+
const userPath = join19(configDir, fileName);
|
|
37004
|
+
const projectPath = join19(directory, fileName);
|
|
37005
|
+
if (existsSync25(userPath)) {
|
|
36451
37006
|
paths.add(userPath);
|
|
36452
37007
|
}
|
|
36453
|
-
if (
|
|
37008
|
+
if (existsSync25(projectPath)) {
|
|
36454
37009
|
paths.add(projectPath);
|
|
36455
37010
|
}
|
|
36456
37011
|
}
|
|
36457
|
-
const homeDir = process.env.HOME ||
|
|
36458
|
-
const omoHomeDir =
|
|
37012
|
+
const homeDir = process.env.HOME || homedir15();
|
|
37013
|
+
const omoHomeDir = join19(homeDir, ".omo");
|
|
36459
37014
|
for (const name of OMO_UNIFIED_NAMES) {
|
|
36460
|
-
const userPath =
|
|
36461
|
-
if (
|
|
37015
|
+
const userPath = join19(omoHomeDir, name);
|
|
37016
|
+
if (existsSync25(userPath)) {
|
|
36462
37017
|
paths.add(userPath);
|
|
36463
37018
|
}
|
|
36464
37019
|
}
|
|
36465
37020
|
for (const name of OMO_UNIFIED_NAMES) {
|
|
36466
|
-
const projectPath =
|
|
36467
|
-
if (
|
|
37021
|
+
const projectPath = join19(directory, ".omo", name);
|
|
37022
|
+
if (existsSync25(projectPath)) {
|
|
36468
37023
|
paths.add(projectPath);
|
|
36469
37024
|
}
|
|
36470
37025
|
}
|
|
@@ -36592,8 +37147,8 @@ var init_conflict_fixer = __esm(() => {
|
|
|
36592
37147
|
});
|
|
36593
37148
|
|
|
36594
37149
|
// src/commands/setup-opencode.ts
|
|
36595
|
-
import { existsSync as
|
|
36596
|
-
import { basename as basename4, dirname as
|
|
37150
|
+
import { existsSync as existsSync26 } from "node:fs";
|
|
37151
|
+
import { basename as basename4, dirname as dirname14 } from "node:path";
|
|
36597
37152
|
function resolveCompactionEnabledForWriter() {
|
|
36598
37153
|
try {
|
|
36599
37154
|
const config = loadPluginConfig(process.cwd());
|
|
@@ -36608,7 +37163,7 @@ function isPlainObject5(value) {
|
|
|
36608
37163
|
}
|
|
36609
37164
|
function planOpenCodeConfigUpdate(configPath, removeDcp = false, compactionEnabled = true, hostGeneration = "v1") {
|
|
36610
37165
|
const registrationKey = pluginConfigKeyFor(hostGeneration);
|
|
36611
|
-
const existsAtCommit =
|
|
37166
|
+
const existsAtCommit = existsSync26(configPath);
|
|
36612
37167
|
const existing = existsAtCommit ? readJsoncConfigForUpdate(configPath) : {};
|
|
36613
37168
|
if (!existsAtCommit) {
|
|
36614
37169
|
const created = { [registrationKey]: [OPENCODE_PLUGIN_ENTRY_WITH_VERSION] };
|
|
@@ -36623,7 +37178,7 @@ function planOpenCodeConfigUpdate(configPath, removeDcp = false, compactionEnabl
|
|
|
36623
37178
|
let changed = false;
|
|
36624
37179
|
const rawPlugins = readPluginEntries(existing).map(({ entry }) => entry);
|
|
36625
37180
|
const retainedPlugins = removeDcp ? rawPlugins.filter((plugin) => !matchesPluginEntry(plugin, DCP_PLUGIN_NAME)) : rawPlugins;
|
|
36626
|
-
if (retainedPlugins.some((plugin) => isLocalPathPluginEntry(plugin) && String(plugin).includes("magic-context") && !isDevPathPluginEntry(plugin,
|
|
37181
|
+
if (retainedPlugins.some((plugin) => isLocalPathPluginEntry(plugin) && String(plugin).includes("magic-context") && !isDevPathPluginEntry(plugin, dirname14(configPath)))) {
|
|
36627
37182
|
log3.warn("An unverifiable local OpenCode plugin path was ignored; its package name is not Magic Context.");
|
|
36628
37183
|
}
|
|
36629
37184
|
if (removeDcp) {
|
|
@@ -36638,7 +37193,7 @@ function planOpenCodeConfigUpdate(configPath, removeDcp = false, compactionEnabl
|
|
|
36638
37193
|
}
|
|
36639
37194
|
}
|
|
36640
37195
|
const hasNpmEntry = retainedPlugins.some((plugin) => matchesPluginEntry(plugin, OPENCODE_PLUGIN_NAME));
|
|
36641
|
-
const hasDevEntry = retainedPlugins.some((plugin) => isDevPathPluginEntry(plugin,
|
|
37196
|
+
const hasDevEntry = retainedPlugins.some((plugin) => isDevPathPluginEntry(plugin, dirname14(configPath)));
|
|
36642
37197
|
if (!hasNpmEntry && !hasDevEntry) {
|
|
36643
37198
|
text = Array.isArray(existing[registrationKey]) ? appendJsoncArrayValues(text, [registrationKey], [OPENCODE_PLUGIN_ENTRY_WITH_VERSION]) : setJsoncValue(text, [registrationKey], [OPENCODE_PLUGIN_ENTRY_WITH_VERSION]);
|
|
36644
37199
|
changed = true;
|
|
@@ -36664,18 +37219,18 @@ function planOpenCodeConfigUpdate(configPath, removeDcp = false, compactionEnabl
|
|
|
36664
37219
|
return changed ? document.bom + text : null;
|
|
36665
37220
|
}
|
|
36666
37221
|
function planTuiConfigUpdate(configPath) {
|
|
36667
|
-
const existsAtCommit =
|
|
37222
|
+
const existsAtCommit = existsSync26(configPath);
|
|
36668
37223
|
const existing = existsAtCommit ? readJsoncConfigForUpdate(configPath) : {};
|
|
36669
37224
|
if (!existsAtCommit) {
|
|
36670
37225
|
return `${import_comment_json6.stringify({ plugin: [OPENCODE_PLUGIN_ENTRY_WITH_VERSION] }, null, 2)}
|
|
36671
37226
|
`;
|
|
36672
37227
|
}
|
|
36673
37228
|
const rawPlugins = Array.isArray(existing.plugin) ? existing.plugin : [];
|
|
36674
|
-
if (rawPlugins.some((plugin) => isLocalPathPluginEntry(plugin) && String(plugin).includes("magic-context") && !isDevPathPluginEntry(plugin,
|
|
37229
|
+
if (rawPlugins.some((plugin) => isLocalPathPluginEntry(plugin) && String(plugin).includes("magic-context") && !isDevPathPluginEntry(plugin, dirname14(configPath)))) {
|
|
36675
37230
|
log3.warn("An unverifiable local TUI plugin path was ignored; its package name is not Magic Context.");
|
|
36676
37231
|
}
|
|
36677
37232
|
const hasNpmEntry = rawPlugins.some((plugin) => matchesPluginEntry(plugin, OPENCODE_PLUGIN_NAME));
|
|
36678
|
-
const hasDevEntry = rawPlugins.some((plugin) => isDevPathPluginEntry(plugin,
|
|
37233
|
+
const hasDevEntry = rawPlugins.some((plugin) => isDevPathPluginEntry(plugin, dirname14(configPath)));
|
|
36679
37234
|
if (hasNpmEntry || hasDevEntry)
|
|
36680
37235
|
return null;
|
|
36681
37236
|
const document = readJsoncTextForEdit(configPath);
|
|
@@ -36791,7 +37346,7 @@ async function runSetup3(dryRun = false) {
|
|
|
36791
37346
|
log3.warn("You can configure models manually in magic-context.jsonc later");
|
|
36792
37347
|
}
|
|
36793
37348
|
const paths = detectConfigPaths();
|
|
36794
|
-
const hadExistingSetup = paths.opencodeConfigFormat !== "none" ||
|
|
37349
|
+
const hadExistingSetup = paths.opencodeConfigFormat !== "none" || existsSync26(paths.magicContextConfig) || paths.tuiConfigFormat !== "none";
|
|
36795
37350
|
if (!dryRun) {
|
|
36796
37351
|
try {
|
|
36797
37352
|
assertJsoncConfigsParseable([
|
|
@@ -37031,6 +37586,8 @@ async function runSetup4(argv) {
|
|
|
37031
37586
|
outro2("Setup finished with warnings — see above.");
|
|
37032
37587
|
return 1;
|
|
37033
37588
|
}
|
|
37589
|
+
if (!dryRun)
|
|
37590
|
+
await offerDashboardInstall(argv);
|
|
37034
37591
|
outro2(dryRun ? "Dry run done — no changes were made." : "Done.");
|
|
37035
37592
|
return 0;
|
|
37036
37593
|
}
|
|
@@ -37069,6 +37626,7 @@ function printNextSteps(adapter) {
|
|
|
37069
37626
|
}
|
|
37070
37627
|
}
|
|
37071
37628
|
var init_setup = __esm(async () => {
|
|
37629
|
+
init_dashboard_install();
|
|
37072
37630
|
init_docs_proposal_gitignore();
|
|
37073
37631
|
init_prompts();
|
|
37074
37632
|
init_setup_omp();
|
|
@@ -37080,26 +37638,55 @@ var init_setup = __esm(async () => {
|
|
|
37080
37638
|
]);
|
|
37081
37639
|
});
|
|
37082
37640
|
|
|
37641
|
+
// src/lib/disk-space.ts
|
|
37642
|
+
import { existsSync as existsSync27, statfsSync, statSync as statSync13 } from "node:fs";
|
|
37643
|
+
import { dirname as dirname15, resolve as resolve9 } from "node:path";
|
|
37644
|
+
function availableDiskBytes(path) {
|
|
37645
|
+
const filesystem = statfsSync(path);
|
|
37646
|
+
return filesystem.bavail * filesystem.bsize;
|
|
37647
|
+
}
|
|
37648
|
+
function checkDiskSpace(path, bytes, freeBytes) {
|
|
37649
|
+
const requiredBytes = Math.ceil(bytes * 1.1);
|
|
37650
|
+
const availableBytes = freeBytes(path);
|
|
37651
|
+
return {
|
|
37652
|
+
requiredBytes,
|
|
37653
|
+
availableBytes,
|
|
37654
|
+
sufficient: availableBytes >= requiredBytes
|
|
37655
|
+
};
|
|
37656
|
+
}
|
|
37657
|
+
function existingDirectoryAncestor(path) {
|
|
37658
|
+
let current = resolve9(path);
|
|
37659
|
+
for (;; ) {
|
|
37660
|
+
if (existsSync27(current) && statSync13(current).isDirectory())
|
|
37661
|
+
return current;
|
|
37662
|
+
const parent = dirname15(current);
|
|
37663
|
+
if (parent === current)
|
|
37664
|
+
throw new Error(`No existing directory for ${path}`);
|
|
37665
|
+
current = parent;
|
|
37666
|
+
}
|
|
37667
|
+
}
|
|
37668
|
+
var init_disk_space = () => {};
|
|
37669
|
+
|
|
37083
37670
|
// ../plugin/src/hooks/auto-update-checker/constants.ts
|
|
37084
|
-
import { homedir as
|
|
37085
|
-
import { join as
|
|
37671
|
+
import { homedir as homedir16, platform } from "node:os";
|
|
37672
|
+
import { join as join20 } from "node:path";
|
|
37086
37673
|
function getOpenCodeCacheRoot() {
|
|
37087
37674
|
if (platform() === "win32") {
|
|
37088
|
-
return
|
|
37675
|
+
return join20(process.env.LOCALAPPDATA ?? homedir16(), "opencode");
|
|
37089
37676
|
}
|
|
37090
|
-
return
|
|
37677
|
+
return join20(homedir16(), ".cache", "opencode");
|
|
37091
37678
|
}
|
|
37092
37679
|
function getOpenCodeConfigRoot() {
|
|
37093
37680
|
if (platform() === "win32") {
|
|
37094
|
-
return
|
|
37681
|
+
return join20(process.env.APPDATA ?? join20(homedir16(), "AppData", "Roaming"), "opencode");
|
|
37095
37682
|
}
|
|
37096
|
-
return
|
|
37683
|
+
return join20(process.env.XDG_CONFIG_HOME ?? join20(homedir16(), ".config"), "opencode");
|
|
37097
37684
|
}
|
|
37098
37685
|
var PACKAGE_NAME = "@cortexkit/opencode-magic-context", CACHE_DIR, USER_OPENCODE_CONFIG, USER_OPENCODE_CONFIG_JSONC;
|
|
37099
37686
|
var init_constants2 = __esm(() => {
|
|
37100
|
-
CACHE_DIR =
|
|
37101
|
-
USER_OPENCODE_CONFIG =
|
|
37102
|
-
USER_OPENCODE_CONFIG_JSONC =
|
|
37687
|
+
CACHE_DIR = join20(getOpenCodeCacheRoot(), "packages");
|
|
37688
|
+
USER_OPENCODE_CONFIG = join20(getOpenCodeConfigRoot(), "opencode.json");
|
|
37689
|
+
USER_OPENCODE_CONFIG_JSONC = join20(getOpenCodeConfigRoot(), "opencode.jsonc");
|
|
37103
37690
|
});
|
|
37104
37691
|
|
|
37105
37692
|
// ../plugin/src/hooks/auto-update-checker/types.ts
|
|
@@ -37122,15 +37709,15 @@ var init_types = __esm(() => {
|
|
|
37122
37709
|
|
|
37123
37710
|
// ../plugin/src/hooks/auto-update-checker/checker.ts
|
|
37124
37711
|
import {
|
|
37125
|
-
accessSync as
|
|
37126
|
-
existsSync as
|
|
37712
|
+
accessSync as accessSync3,
|
|
37713
|
+
existsSync as existsSync28,
|
|
37127
37714
|
constants as fsConstants,
|
|
37128
|
-
readFileSync as
|
|
37129
|
-
renameSync as
|
|
37130
|
-
statSync as
|
|
37131
|
-
writeFileSync as
|
|
37715
|
+
readFileSync as readFileSync17,
|
|
37716
|
+
renameSync as renameSync5,
|
|
37717
|
+
statSync as statSync14,
|
|
37718
|
+
writeFileSync as writeFileSync6
|
|
37132
37719
|
} from "node:fs";
|
|
37133
|
-
import { dirname as
|
|
37720
|
+
import { dirname as dirname16, isAbsolute as isAbsolute7, join as join21, resolve as resolve10 } from "node:path";
|
|
37134
37721
|
function warn(message) {
|
|
37135
37722
|
log(`WARN: ${message}`);
|
|
37136
37723
|
}
|
|
@@ -37156,17 +37743,17 @@ function parseJsonConfig(content) {
|
|
|
37156
37743
|
}
|
|
37157
37744
|
function getSurfaceConfigPaths(directory, surface) {
|
|
37158
37745
|
const name = surface === "server" ? "opencode" : "tui";
|
|
37159
|
-
const globalDir =
|
|
37746
|
+
const globalDir = dirname16(USER_OPENCODE_CONFIG);
|
|
37160
37747
|
const dirs = [
|
|
37161
37748
|
globalDir,
|
|
37162
37749
|
directory,
|
|
37163
|
-
|
|
37750
|
+
join21(directory, ".opencode"),
|
|
37164
37751
|
process.env.OPENCODE_CONFIG_DIR
|
|
37165
37752
|
].filter((value) => Boolean(value));
|
|
37166
37753
|
const paths = [];
|
|
37167
37754
|
for (const dir of dirs) {
|
|
37168
37755
|
for (const extension of ["json", "jsonc"]) {
|
|
37169
|
-
const path =
|
|
37756
|
+
const path = join21(dir, `${name}.${extension}`);
|
|
37170
37757
|
if (!paths.includes(path))
|
|
37171
37758
|
paths.push(path);
|
|
37172
37759
|
}
|
|
@@ -37177,9 +37764,9 @@ function getWinningConfig(directory, surface) {
|
|
|
37177
37764
|
let winner = null;
|
|
37178
37765
|
for (const path of getSurfaceConfigPaths(directory, surface)) {
|
|
37179
37766
|
try {
|
|
37180
|
-
if (!
|
|
37767
|
+
if (!existsSync28(path))
|
|
37181
37768
|
continue;
|
|
37182
|
-
const parsed = parseJsonConfig(
|
|
37769
|
+
const parsed = parseJsonConfig(readFileSync17(path, "utf-8"));
|
|
37183
37770
|
const entries = getPluginEntries(parsed);
|
|
37184
37771
|
if (entries.some((entry) => entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`))) {
|
|
37185
37772
|
if (winner) {
|
|
@@ -37215,14 +37802,14 @@ var init_checker = __esm(() => {
|
|
|
37215
37802
|
});
|
|
37216
37803
|
|
|
37217
37804
|
// src/lib/opencode-plugin-schema-fence.ts
|
|
37218
|
-
import { existsSync as
|
|
37219
|
-
import { join as
|
|
37220
|
-
import { gunzipSync } from "node:zlib";
|
|
37805
|
+
import { existsSync as existsSync29, readdirSync as readdirSync6, readFileSync as readFileSync18 } from "node:fs";
|
|
37806
|
+
import { join as join22 } from "node:path";
|
|
37807
|
+
import { gunzipSync as gunzipSync2 } from "node:zlib";
|
|
37221
37808
|
function readPackageVersion(packageJsonPath) {
|
|
37222
37809
|
try {
|
|
37223
|
-
if (!
|
|
37810
|
+
if (!existsSync29(packageJsonPath))
|
|
37224
37811
|
return null;
|
|
37225
|
-
const packageJson = JSON.parse(
|
|
37812
|
+
const packageJson = JSON.parse(readFileSync18(packageJsonPath, "utf-8"));
|
|
37226
37813
|
if (packageJson.name !== OPENCODE_PLUGIN_NAME || typeof packageJson.version !== "string") {
|
|
37227
37814
|
return null;
|
|
37228
37815
|
}
|
|
@@ -37241,8 +37828,8 @@ function readFenceValue(text) {
|
|
|
37241
37828
|
return values.size === 1 ? [...values][0] ?? null : null;
|
|
37242
37829
|
}
|
|
37243
37830
|
function readFenceFromDist(packageDirectory) {
|
|
37244
|
-
const distDirectory =
|
|
37245
|
-
if (!
|
|
37831
|
+
const distDirectory = join22(packageDirectory, "dist");
|
|
37832
|
+
if (!existsSync29(distDirectory))
|
|
37246
37833
|
return null;
|
|
37247
37834
|
const pending = [distDirectory];
|
|
37248
37835
|
const fenceValues = new Set;
|
|
@@ -37252,14 +37839,14 @@ function readFenceFromDist(packageDirectory) {
|
|
|
37252
37839
|
continue;
|
|
37253
37840
|
try {
|
|
37254
37841
|
for (const entry of readdirSync6(directory, { withFileTypes: true })) {
|
|
37255
|
-
const path =
|
|
37842
|
+
const path = join22(directory, entry.name);
|
|
37256
37843
|
if (entry.isDirectory()) {
|
|
37257
37844
|
pending.push(path);
|
|
37258
37845
|
continue;
|
|
37259
37846
|
}
|
|
37260
37847
|
if (!entry.isFile() || !/\.(?:[cm]?js|ts)$/.test(entry.name))
|
|
37261
37848
|
continue;
|
|
37262
|
-
const fence = readFenceValue(
|
|
37849
|
+
const fence = readFenceValue(readFileSync18(path, "utf-8"));
|
|
37263
37850
|
if (fence !== null)
|
|
37264
37851
|
fenceValues.add(fence);
|
|
37265
37852
|
}
|
|
@@ -37270,20 +37857,20 @@ function readFenceFromDist(packageDirectory) {
|
|
|
37270
37857
|
return fenceValues.size === 1 ? [...fenceValues][0] ?? null : null;
|
|
37271
37858
|
}
|
|
37272
37859
|
function findInstalledPluginPackage(cacheDirectory, specifier, requestedVersion) {
|
|
37273
|
-
const directCacheRoot =
|
|
37860
|
+
const directCacheRoot = join22(cacheDirectory, specifier);
|
|
37274
37861
|
const candidates = [directCacheRoot];
|
|
37275
37862
|
try {
|
|
37276
37863
|
for (const entry of readdirSync6(cacheDirectory, { withFileTypes: true })) {
|
|
37277
37864
|
if (!entry.isDirectory())
|
|
37278
37865
|
continue;
|
|
37279
|
-
const candidate =
|
|
37866
|
+
const candidate = join22(cacheDirectory, entry.name);
|
|
37280
37867
|
if (!candidates.includes(candidate))
|
|
37281
37868
|
candidates.push(candidate);
|
|
37282
37869
|
}
|
|
37283
37870
|
} catch {}
|
|
37284
37871
|
for (const cacheRoot of candidates) {
|
|
37285
|
-
const directory =
|
|
37286
|
-
const version = readPackageVersion(
|
|
37872
|
+
const directory = join22(cacheRoot, "node_modules", ...PACKAGE_PATH_SEGMENTS);
|
|
37873
|
+
const version = readPackageVersion(join22(directory, "package.json"));
|
|
37287
37874
|
if (!version)
|
|
37288
37875
|
continue;
|
|
37289
37876
|
if (cacheRoot === directCacheRoot || EXACT_VERSION_PATTERN.test(requestedVersion) && version === requestedVersion) {
|
|
@@ -37309,7 +37896,7 @@ function readTarOctal(bytes, offset, length) {
|
|
|
37309
37896
|
function readFenceFromNpmTarball(tarball) {
|
|
37310
37897
|
let archive;
|
|
37311
37898
|
try {
|
|
37312
|
-
archive =
|
|
37899
|
+
archive = gunzipSync2(tarball);
|
|
37313
37900
|
} catch {
|
|
37314
37901
|
return null;
|
|
37315
37902
|
}
|
|
@@ -37428,13 +38015,13 @@ var init_opencode_plugin_schema_fence = __esm(() => {
|
|
|
37428
38015
|
});
|
|
37429
38016
|
|
|
37430
38017
|
// src/commands/doctor-opencode-cache.ts
|
|
37431
|
-
import { existsSync as
|
|
38018
|
+
import { existsSync as existsSync30, readFileSync as readFileSync19, rmSync as rmSync7 } from "node:fs";
|
|
37432
38019
|
function readCachedPluginVersion(pluginCacheDir) {
|
|
37433
38020
|
try {
|
|
37434
38021
|
const installedPkgPath = getOpenCodePluginPackageJsonPath(pluginCacheDir);
|
|
37435
|
-
if (!
|
|
38022
|
+
if (!existsSync30(installedPkgPath))
|
|
37436
38023
|
return;
|
|
37437
|
-
const pkg = JSON.parse(
|
|
38024
|
+
const pkg = JSON.parse(readFileSync19(installedPkgPath, "utf-8"));
|
|
37438
38025
|
return typeof pkg.version === "string" ? pkg.version : undefined;
|
|
37439
38026
|
} catch {
|
|
37440
38027
|
return;
|
|
@@ -37459,9 +38046,9 @@ function readOpenCodePluginConfigUse(config, configDir) {
|
|
|
37459
38046
|
return use;
|
|
37460
38047
|
}
|
|
37461
38048
|
async function clearPluginCache(options = {}, deps = {}) {
|
|
37462
|
-
const remove = deps.remove ?? ((path) =>
|
|
38049
|
+
const remove = deps.remove ?? ((path) => rmSync7(path, { recursive: true, force: true }));
|
|
37463
38050
|
const pluginCacheRoots = getOpenCodePluginCacheRoots();
|
|
37464
|
-
const existingRoots = pluginCacheRoots.filter((root) =>
|
|
38051
|
+
const existingRoots = pluginCacheRoots.filter((root) => existsSync30(root));
|
|
37465
38052
|
if (existingRoots.length === 0) {
|
|
37466
38053
|
return { action: "not_found", path: pluginCacheRoots[0] ?? "" };
|
|
37467
38054
|
}
|
|
@@ -37558,8 +38145,8 @@ var init_doctor_opencode_cache = __esm(async () => {
|
|
|
37558
38145
|
});
|
|
37559
38146
|
|
|
37560
38147
|
// src/commands/doctor-cached-plugin-fence.ts
|
|
37561
|
-
import { existsSync as
|
|
37562
|
-
import { dirname as
|
|
38148
|
+
import { existsSync as existsSync31 } from "node:fs";
|
|
38149
|
+
import { dirname as dirname17 } from "node:path";
|
|
37563
38150
|
function isReferenced(sources, host, spec) {
|
|
37564
38151
|
const specs = sources.referencedSpecs?.[host];
|
|
37565
38152
|
return specs === undefined || specs.has(spec);
|
|
@@ -37569,13 +38156,13 @@ function listCachedOpenCodePluginFences(sources = {}) {
|
|
|
37569
38156
|
const v1Referenced = isReferenced(sources, "opencode1", "latest");
|
|
37570
38157
|
for (const root of v1Referenced ? sources.openCodeV1Roots ?? getOpenCodePluginCacheRoots() : []) {
|
|
37571
38158
|
const packageJson = getOpenCodePluginPackageJsonPath(root);
|
|
37572
|
-
if (!
|
|
38159
|
+
if (!existsSync31(packageJson))
|
|
37573
38160
|
continue;
|
|
37574
38161
|
fences.push({
|
|
37575
38162
|
host: "opencode1",
|
|
37576
38163
|
directory: root,
|
|
37577
38164
|
version: readCachedPluginVersion(root),
|
|
37578
|
-
supportedVersion: readFenceFromDist(
|
|
38165
|
+
supportedVersion: readFenceFromDist(dirname17(packageJson))
|
|
37579
38166
|
});
|
|
37580
38167
|
}
|
|
37581
38168
|
for (const slot of listOpenCodeV2PluginCacheSlots(sources.openCodeV2NpmCacheDir)) {
|
|
@@ -37591,7 +38178,7 @@ function listCachedOpenCodePluginFences(sources = {}) {
|
|
|
37591
38178
|
directory: slot.slot,
|
|
37592
38179
|
spec: slot.spec,
|
|
37593
38180
|
version: slot.version,
|
|
37594
|
-
supportedVersion: readFenceFromDist(
|
|
38181
|
+
supportedVersion: readFenceFromDist(dirname17(getOpenCodePluginPackageJsonPath(generation)))
|
|
37595
38182
|
});
|
|
37596
38183
|
}
|
|
37597
38184
|
return fences;
|
|
@@ -37774,13 +38361,13 @@ var init_doctor_prune_discovery = __esm(async () => {
|
|
|
37774
38361
|
|
|
37775
38362
|
// src/commands/doctor-storage-holders.ts
|
|
37776
38363
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
37777
|
-
import { readFileSync as
|
|
37778
|
-
import { join as
|
|
38364
|
+
import { readFileSync as readFileSync20, realpathSync as realpathSync4 } from "node:fs";
|
|
38365
|
+
import { join as join23, resolve as resolve11 } from "node:path";
|
|
37779
38366
|
function canonicalStoragePath(path) {
|
|
37780
38367
|
try {
|
|
37781
38368
|
return realpathSync4(path);
|
|
37782
38369
|
} catch {
|
|
37783
|
-
return
|
|
38370
|
+
return resolve11(path);
|
|
37784
38371
|
}
|
|
37785
38372
|
}
|
|
37786
38373
|
function textReferencesStorage(text, storageDir) {
|
|
@@ -37792,7 +38379,7 @@ function textReferencesStorage(text, storageDir) {
|
|
|
37792
38379
|
continue;
|
|
37793
38380
|
if (canonicalStoragePath(value) === target)
|
|
37794
38381
|
return true;
|
|
37795
|
-
if (token.startsWith("XDG_DATA_HOME=") && canonicalStoragePath(
|
|
38382
|
+
if (token.startsWith("XDG_DATA_HOME=") && canonicalStoragePath(join23(value, "cortexkit", "magic-context")) === target)
|
|
37796
38383
|
return true;
|
|
37797
38384
|
}
|
|
37798
38385
|
return false;
|
|
@@ -37802,7 +38389,7 @@ function processReferencesStorage(pid, storageDir) {
|
|
|
37802
38389
|
if (process.platform === "linux") {
|
|
37803
38390
|
for (const name of ["cmdline", "environ"]) {
|
|
37804
38391
|
try {
|
|
37805
|
-
texts.push(
|
|
38392
|
+
texts.push(readFileSync20(`/proc/${pid}/${name}`, "utf8"));
|
|
37806
38393
|
} catch {}
|
|
37807
38394
|
}
|
|
37808
38395
|
} else {
|
|
@@ -37824,12 +38411,12 @@ var init_doctor_storage_holders = () => {};
|
|
|
37824
38411
|
|
|
37825
38412
|
// src/commands/doctor-repair-db.ts
|
|
37826
38413
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
37827
|
-
import { closeSync as closeSync4, existsSync as
|
|
37828
|
-
import { homedir as
|
|
37829
|
-
import { dirname as
|
|
38414
|
+
import { closeSync as closeSync4, existsSync as existsSync32, openSync as openSync4, renameSync as renameSync6, rmSync as rmSync8, statSync as statSync15 } from "node:fs";
|
|
38415
|
+
import { homedir as homedir17 } from "node:os";
|
|
38416
|
+
import { dirname as dirname18, join as join24 } from "node:path";
|
|
37830
38417
|
function defaultInspectHolders(storageDir, overrides = {}) {
|
|
37831
38418
|
const deps = {
|
|
37832
|
-
defaultStorageDir:
|
|
38419
|
+
defaultStorageDir: join24(homedir17(), ".local", "share", "cortexkit", "magic-context"),
|
|
37833
38420
|
inspectRpc: inspectRpcServerDiscovery,
|
|
37834
38421
|
inspectPi: inspectLivePiProcesses,
|
|
37835
38422
|
probeFiles: probeHostProcessesUsing,
|
|
@@ -37846,7 +38433,7 @@ function defaultInspectHolders(storageDir, overrides = {}) {
|
|
|
37846
38433
|
return {
|
|
37847
38434
|
safe: false,
|
|
37848
38435
|
blockers: [],
|
|
37849
|
-
uncertainty: `RPC discovery ${rpc.unreadableFile ??
|
|
38436
|
+
uncertainty: `RPC discovery ${rpc.unreadableFile ?? join24(storageDir, "rpc")} ${arm}`
|
|
37850
38437
|
};
|
|
37851
38438
|
}
|
|
37852
38439
|
const blockers = rpc.state === "live" ? rpc.serverPids.map((pid) => `OpenCode server (PID ${pid})`) : [];
|
|
@@ -37859,7 +38446,7 @@ function defaultInspectHolders(storageDir, overrides = {}) {
|
|
|
37859
38446
|
const pi = overrides.inspectPi ? deps.inspectPi() : processes?.pi ?? deps.inspectPi();
|
|
37860
38447
|
if (canonicalStoragePath(storageDir) !== canonicalStoragePath(deps.defaultStorageDir)) {
|
|
37861
38448
|
const holders = deps.probeFiles({
|
|
37862
|
-
files: ["context.db", "store.db"].flatMap((name) => DATABASE_SUFFIXES.map((suffix) =>
|
|
38449
|
+
files: ["context.db", "store.db"].flatMap((name) => DATABASE_SUFFIXES.map((suffix) => join24(storageDir, `${name}${suffix}`))),
|
|
37863
38450
|
directories: []
|
|
37864
38451
|
});
|
|
37865
38452
|
if (holders.status === "unknown") {
|
|
@@ -37892,11 +38479,11 @@ function timestamp(date) {
|
|
|
37892
38479
|
return date.toISOString().replaceAll("-", "").replaceAll(":", "").replace(".", "");
|
|
37893
38480
|
}
|
|
37894
38481
|
function uniqueBase(preferred) {
|
|
37895
|
-
if (!DATABASE_SUFFIXES.some((suffix) =>
|
|
38482
|
+
if (!DATABASE_SUFFIXES.some((suffix) => existsSync32(`${preferred}${suffix}`)))
|
|
37896
38483
|
return preferred;
|
|
37897
38484
|
for (let attempt = 1;attempt < 1e4; attempt++) {
|
|
37898
38485
|
const candidate = `${preferred}-${attempt}`;
|
|
37899
|
-
if (!DATABASE_SUFFIXES.some((suffix) =>
|
|
38486
|
+
if (!DATABASE_SUFFIXES.some((suffix) => existsSync32(`${candidate}${suffix}`)))
|
|
37900
38487
|
return candidate;
|
|
37901
38488
|
}
|
|
37902
38489
|
throw new Error(`Could not allocate a unique recovery path beside ${preferred}`);
|
|
@@ -37906,14 +38493,23 @@ function copyBackupBundle(dbPath, stamp) {
|
|
|
37906
38493
|
const copiedPaths = copyDatabaseBundle(dbPath, basePath);
|
|
37907
38494
|
return { basePath, copiedPaths };
|
|
37908
38495
|
}
|
|
37909
|
-
function
|
|
38496
|
+
function databaseBundleSizeBytes(sourceBase) {
|
|
38497
|
+
let size = 0;
|
|
38498
|
+
for (const suffix of DATABASE_SUFFIXES) {
|
|
38499
|
+
const source = `${sourceBase}${suffix}`;
|
|
38500
|
+
if (existsSync32(source))
|
|
38501
|
+
size += statSync15(source).size;
|
|
38502
|
+
}
|
|
38503
|
+
return size;
|
|
38504
|
+
}
|
|
38505
|
+
function copyDatabaseBundle(sourceBase, destinationBase, forcePrivate = false) {
|
|
37910
38506
|
const copiedPaths = [];
|
|
37911
38507
|
for (const suffix of DATABASE_SUFFIXES) {
|
|
37912
38508
|
const source = `${sourceBase}${suffix}`;
|
|
37913
|
-
if (!
|
|
38509
|
+
if (!existsSync32(source))
|
|
37914
38510
|
continue;
|
|
37915
38511
|
const destination = `${destinationBase}${suffix}`;
|
|
37916
|
-
copyStorageFileSync(source, destination);
|
|
38512
|
+
copyStorageFileSync(source, destination, forcePrivate);
|
|
37917
38513
|
copiedPaths.push(destination);
|
|
37918
38514
|
}
|
|
37919
38515
|
return copiedPaths;
|
|
@@ -38026,7 +38622,7 @@ function runRecoverShell(sqliteExecutable, sourcePath, recoveredPath, dumpPath)
|
|
|
38026
38622
|
} finally {
|
|
38027
38623
|
if (dumpWriteFd !== null)
|
|
38028
38624
|
closeSync4(dumpWriteFd);
|
|
38029
|
-
|
|
38625
|
+
rmSync8(dumpPath, { force: true });
|
|
38030
38626
|
}
|
|
38031
38627
|
}
|
|
38032
38628
|
function schemaMigrationWarning(schemaVersionBefore, fences) {
|
|
@@ -38125,25 +38721,25 @@ function prepareFreshDatabase(path) {
|
|
|
38125
38721
|
}
|
|
38126
38722
|
function removeRecoveryBundle(basePath) {
|
|
38127
38723
|
for (const suffix of DATABASE_SUFFIXES)
|
|
38128
|
-
|
|
38724
|
+
rmSync8(`${basePath}${suffix}`, { force: true });
|
|
38129
38725
|
}
|
|
38130
38726
|
function activateReplacement(dbPath, replacementPath, originalAsidePath) {
|
|
38131
38727
|
const movedOriginals = [];
|
|
38132
38728
|
try {
|
|
38133
38729
|
for (const suffix of DATABASE_SUFFIXES) {
|
|
38134
38730
|
const from = `${dbPath}${suffix}`;
|
|
38135
|
-
if (!
|
|
38731
|
+
if (!existsSync32(from))
|
|
38136
38732
|
continue;
|
|
38137
38733
|
const to = `${originalAsidePath}${suffix}`;
|
|
38138
|
-
|
|
38734
|
+
renameSync6(from, to);
|
|
38139
38735
|
movedOriginals.push({ from, to });
|
|
38140
38736
|
}
|
|
38141
|
-
|
|
38737
|
+
renameSync6(replacementPath, dbPath);
|
|
38142
38738
|
return movedOriginals.map(({ to }) => to);
|
|
38143
38739
|
} catch (error) {
|
|
38144
38740
|
for (const moved of movedOriginals.reverse()) {
|
|
38145
|
-
if (
|
|
38146
|
-
|
|
38741
|
+
if (existsSync32(moved.to) && !existsSync32(moved.from))
|
|
38742
|
+
renameSync6(moved.to, moved.from);
|
|
38147
38743
|
}
|
|
38148
38744
|
throw error;
|
|
38149
38745
|
}
|
|
@@ -38173,12 +38769,12 @@ function printHelp() {
|
|
|
38173
38769
|
async function runRepairDb(options = {}) {
|
|
38174
38770
|
const prompts = options.prompts ?? promptIO;
|
|
38175
38771
|
const deps = { ...DEFAULT_DEPS3, ...options.deps };
|
|
38176
|
-
const storageDir = options.storageDir ??
|
|
38177
|
-
const dbPath = options.dbPath ??
|
|
38772
|
+
const storageDir = options.storageDir ?? dirname18(options.dbPath ?? join24(getMagicContextStorageDir(), "context.db"));
|
|
38773
|
+
const dbPath = options.dbPath ?? join24(storageDir, "context.db");
|
|
38178
38774
|
const stamp = timestamp(deps.now());
|
|
38179
38775
|
prompts.intro("Magic Context — Repair shared database");
|
|
38180
38776
|
prompts.log.info(`Database: ${dbPath}`);
|
|
38181
|
-
if (!
|
|
38777
|
+
if (!existsSync32(dbPath)) {
|
|
38182
38778
|
prompts.log.error(`Database not found: ${dbPath}`);
|
|
38183
38779
|
prompts.log.info("Backup: not created (database does not exist)");
|
|
38184
38780
|
prompts.outro("Database repair failed");
|
|
@@ -38388,13 +38984,13 @@ var init_doctor_repair_db = __esm(async () => {
|
|
|
38388
38984
|
|
|
38389
38985
|
// src/commands/doctor-single-store-repair.ts
|
|
38390
38986
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
38391
|
-
import { existsSync as
|
|
38392
|
-
import { homedir as
|
|
38393
|
-
import { dirname as
|
|
38987
|
+
import { existsSync as existsSync33, statfsSync as statfsSync2, statSync as statSync16 } from "node:fs";
|
|
38988
|
+
import { homedir as homedir18 } from "node:os";
|
|
38989
|
+
import { dirname as dirname19, join as join25, resolve as resolve12 } from "node:path";
|
|
38394
38990
|
function existingAncestor(path) {
|
|
38395
|
-
let current =
|
|
38396
|
-
while (!
|
|
38397
|
-
current =
|
|
38991
|
+
let current = resolve12(path);
|
|
38992
|
+
while (!existsSync33(current))
|
|
38993
|
+
current = dirname19(current);
|
|
38398
38994
|
return current;
|
|
38399
38995
|
}
|
|
38400
38996
|
function describe2(plan, print) {
|
|
@@ -38417,7 +39013,7 @@ function runDoctorSingleStoreRepair(options, overrides = {}) {
|
|
|
38417
39013
|
inspectHolders: defaultInspectHolders,
|
|
38418
39014
|
lsofSpawn: spawnSync5,
|
|
38419
39015
|
freeBytes: (path) => {
|
|
38420
|
-
const fs =
|
|
39016
|
+
const fs = statfsSync2(path);
|
|
38421
39017
|
return fs.bavail * fs.bsize;
|
|
38422
39018
|
},
|
|
38423
39019
|
print: console.log,
|
|
@@ -38429,15 +39025,15 @@ function runDoctorSingleStoreRepair(options, overrides = {}) {
|
|
|
38429
39025
|
};
|
|
38430
39026
|
try {
|
|
38431
39027
|
const { dbPath: context, dbDir: data } = resolveDatabasePath();
|
|
38432
|
-
const store =
|
|
38433
|
-
if (!
|
|
39028
|
+
const store = join25(data, "store.db");
|
|
39029
|
+
if (!existsSync33(context) || !existsSync33(store))
|
|
38434
39030
|
return refuse("repair_missing_database", `Both ${context} and ${store} must exist.`);
|
|
38435
39031
|
if (!options.fromBackup)
|
|
38436
39032
|
return refuse("repair_usage", "--from-backup <dir> is required");
|
|
38437
|
-
const fromBackup =
|
|
39033
|
+
const fromBackup = resolve12(options.fromBackup);
|
|
38438
39034
|
for (const name of ["context.db", "store.db"])
|
|
38439
|
-
if (!
|
|
38440
|
-
return refuse("repair_backup_missing", `${
|
|
39035
|
+
if (!existsSync33(join25(fromBackup, name)))
|
|
39036
|
+
return refuse("repair_backup_missing", `${join25(fromBackup, name)} does not exist`);
|
|
38441
39037
|
const sessions = options.sessions ?? [];
|
|
38442
39038
|
if (options.live && sessions.length === 0)
|
|
38443
39039
|
return refuse("repair_usage", "--live repairs named sessions only; pass --session <id>");
|
|
@@ -38464,16 +39060,16 @@ function runDoctorSingleStoreRepair(options, overrides = {}) {
|
|
|
38464
39060
|
`));
|
|
38465
39061
|
deps.print(`Repairing while hosts hold the stores (--live): ${blockers.join("; ") || "holders unknown"}`);
|
|
38466
39062
|
}
|
|
38467
|
-
const backupRoot =
|
|
38468
|
-
const need = Math.ceil((
|
|
39063
|
+
const backupRoot = resolve12(options.backupRoot ?? join25(data, "backups"));
|
|
39064
|
+
const need = Math.ceil((statSync16(context).size + statSync16(store).size) * 1.1);
|
|
38469
39065
|
const volume = existingAncestor(backupRoot);
|
|
38470
39066
|
const have = deps.freeBytes(volume);
|
|
38471
39067
|
if (have < need)
|
|
38472
39068
|
return refuse("repair_disk_space", `the backup needs ${need} bytes; have ${have} bytes on ${volume}`);
|
|
38473
|
-
backupDir =
|
|
39069
|
+
backupDir = join25(backupRoot, `repair-history-${deps.now().toISOString().replaceAll(":", "-")}`);
|
|
38474
39070
|
deps.print(`Backing up the live stores to ${backupDir} before any write.`);
|
|
38475
39071
|
}
|
|
38476
|
-
const binary = options.ckMc ??
|
|
39072
|
+
const binary = options.ckMc ?? join25(homedir18(), ".local", "share", "cortexkit", "bin", "ck-mc");
|
|
38477
39073
|
const args = [
|
|
38478
39074
|
"single-store-repair-history",
|
|
38479
39075
|
"--context-db",
|
|
@@ -38561,28 +39157,22 @@ var init_doctor_single_store_repair = __esm(async () => {
|
|
|
38561
39157
|
|
|
38562
39158
|
// src/commands/doctor-single-store.ts
|
|
38563
39159
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
38564
|
-
import { existsSync as
|
|
38565
|
-
import { homedir as
|
|
38566
|
-
import {
|
|
39160
|
+
import { existsSync as existsSync34, realpathSync as realpathSync5, statSync as statSync17 } from "node:fs";
|
|
39161
|
+
import { homedir as homedir19 } from "node:os";
|
|
39162
|
+
import { join as join26, resolve as resolve13 } from "node:path";
|
|
38567
39163
|
function engineContextPath() {
|
|
38568
39164
|
const value = (key) => process.env[key]?.trim() || undefined;
|
|
38569
39165
|
const test = value("MAGIC_CONTEXT_TEST_DATA_DIR");
|
|
38570
39166
|
const xdg = value("XDG_DATA_HOME");
|
|
38571
|
-
const dir = test ?
|
|
38572
|
-
return
|
|
38573
|
-
}
|
|
38574
|
-
function existingAncestor2(path) {
|
|
38575
|
-
let current = resolve12(path);
|
|
38576
|
-
while (!existsSync32(current))
|
|
38577
|
-
current = dirname18(current);
|
|
38578
|
-
return current;
|
|
39167
|
+
const dir = test ? join26(xdg && xdg !== test ? xdg : test, "cortexkit", "magic-context") : value("MAGIC_CONTEXT_STORAGE_DIR") ?? join26(xdg ?? join26(value("HOME") ?? ".", ".local", "share"), "cortexkit", "magic-context");
|
|
39168
|
+
return join26(dir, "context.db");
|
|
38579
39169
|
}
|
|
38580
39170
|
function undo(backup, data, print) {
|
|
38581
39171
|
const quote = (s) => `'${s.replaceAll("'", "'\\''")}'`;
|
|
38582
39172
|
print(`Backup: ${backup}`);
|
|
38583
39173
|
print("To undo: quit every host, then");
|
|
38584
|
-
print(` rm -f ${["context.db-wal", "context.db-shm", "store.db-wal", "store.db-shm"].map((name) => quote(
|
|
38585
|
-
print(` cp ${quote(
|
|
39174
|
+
print(` rm -f ${["context.db-wal", "context.db-shm", "store.db-wal", "store.db-shm"].map((name) => quote(join26(data, name))).join(" ")}`);
|
|
39175
|
+
print(` cp ${quote(join26(backup, "context.db"))} ${quote(join26(backup, "store.db"))} ${quote(data + "/")}`);
|
|
38586
39176
|
print("This restores the unmigrated stores. Keep the current plugin and ck-mc: TypeScript mode works as before, and Rust mode will refuse with MC-C14 until you run this command again.");
|
|
38587
39177
|
}
|
|
38588
39178
|
function runDoctorSingleStore(options = {}, overrides = {}) {
|
|
@@ -38590,10 +39180,7 @@ function runDoctorSingleStore(options = {}, overrides = {}) {
|
|
|
38590
39180
|
now: () => new Date,
|
|
38591
39181
|
inspectHolders: defaultInspectHolders,
|
|
38592
39182
|
lsofSpawn: spawnSync6,
|
|
38593
|
-
freeBytes:
|
|
38594
|
-
const fs = statfsSync2(path);
|
|
38595
|
-
return fs.bavail * fs.bsize;
|
|
38596
|
-
},
|
|
39183
|
+
freeBytes: availableDiskBytes,
|
|
38597
39184
|
print: console.log,
|
|
38598
39185
|
...overrides
|
|
38599
39186
|
};
|
|
@@ -38603,8 +39190,8 @@ function runDoctorSingleStore(options = {}, overrides = {}) {
|
|
|
38603
39190
|
};
|
|
38604
39191
|
try {
|
|
38605
39192
|
const { dbPath: context, dbDir: data } = resolveDatabasePath();
|
|
38606
|
-
const store =
|
|
38607
|
-
if (!
|
|
39193
|
+
const store = join26(data, "store.db");
|
|
39194
|
+
if (!existsSync34(context) || !existsSync34(store))
|
|
38608
39195
|
return refuse("single_store_missing_database", `Both ${context} and ${store} must exist.`);
|
|
38609
39196
|
const probe = probeHostProcessesUsing({ files: [context, store].flatMap((p) => SUFFIXES2.map((s) => p + s)), directories: [] }, deps.lsofSpawn);
|
|
38610
39197
|
const holders = deps.inspectHolders(data);
|
|
@@ -38619,9 +39206,9 @@ function runDoctorSingleStore(options = {}, overrides = {}) {
|
|
|
38619
39206
|
return refuse("single_store_files_in_use", [...lines, STOP].join(`
|
|
38620
39207
|
`));
|
|
38621
39208
|
}
|
|
38622
|
-
if (!
|
|
39209
|
+
if (!existsSync34(engineContextPath()) || realpathSync5(context) !== realpathSync5(engineContextPath()))
|
|
38623
39210
|
return refuse("single_store_path_mismatch", `CLI ${context}; engine ${engineContextPath()}`);
|
|
38624
|
-
const backupRoot =
|
|
39211
|
+
const backupRoot = resolve13(options.backupRoot ?? join26(data, "backups"));
|
|
38625
39212
|
const contextDb = new Database(context, { readonly: true });
|
|
38626
39213
|
const storeDb = new Database(store, { readonly: true });
|
|
38627
39214
|
let contextVersion;
|
|
@@ -38648,17 +39235,17 @@ function runDoctorSingleStore(options = {}, overrides = {}) {
|
|
|
38648
39235
|
}
|
|
38649
39236
|
if (contextVersion > LATEST_SUPPORTED_VERSION || storeVersion !== 60)
|
|
38650
39237
|
return refuse("single_store_version_mismatch", `context.db v${contextVersion}; store.db v${storeVersion}; need context.db v${LATEST_SUPPORTED_VERSION} and store.db v60 (apply current plugin migrations to context.db; upgrade store.db with ck-mc first)`);
|
|
38651
|
-
const backupBytes =
|
|
38652
|
-
const workingBytes = 2 *
|
|
38653
|
-
const backupVolume =
|
|
38654
|
-
const sameVolume =
|
|
38655
|
-
const
|
|
38656
|
-
|
|
38657
|
-
|
|
38658
|
-
|
|
38659
|
-
if (
|
|
38660
|
-
return refuse("single_store_disk_space", `backup needs ${
|
|
38661
|
-
const backupDir =
|
|
39238
|
+
const backupBytes = statSync17(context).size + statSync17(store).size;
|
|
39239
|
+
const workingBytes = 2 * statSync17(store).size;
|
|
39240
|
+
const backupVolume = existingDirectoryAncestor(backupRoot);
|
|
39241
|
+
const sameVolume = statSync17(data).dev === statSync17(backupVolume).dev;
|
|
39242
|
+
const dataSpace = checkDiskSpace(data, workingBytes + (sameVolume ? backupBytes : 0), deps.freeBytes);
|
|
39243
|
+
if (!dataSpace.sufficient)
|
|
39244
|
+
return refuse("single_store_disk_space", `need ${dataSpace.requiredBytes} bytes; have ${dataSpace.availableBytes} bytes on ${data}`);
|
|
39245
|
+
const backupSpace = sameVolume ? undefined : checkDiskSpace(backupVolume, backupBytes, deps.freeBytes);
|
|
39246
|
+
if (backupSpace && !backupSpace.sufficient)
|
|
39247
|
+
return refuse("single_store_disk_space", `backup needs ${backupSpace.requiredBytes} bytes; have ${backupSpace.availableBytes} bytes on ${backupVolume}`);
|
|
39248
|
+
const backupDir = join26(backupRoot, `single-store-${deps.now().toISOString().replaceAll(":", "-")}`);
|
|
38662
39249
|
undo(backupDir, data, deps.print);
|
|
38663
39250
|
const opened = openDatabase(context);
|
|
38664
39251
|
if (!opened)
|
|
@@ -38670,7 +39257,7 @@ function runDoctorSingleStore(options = {}, overrides = {}) {
|
|
|
38670
39257
|
}
|
|
38671
39258
|
if (contextVersion !== LATEST_SUPPORTED_VERSION)
|
|
38672
39259
|
return refuse("single_store_version_mismatch", `context.db v${contextVersion}; store.db v${storeVersion}`);
|
|
38673
|
-
const binary = options.ckMc ??
|
|
39260
|
+
const binary = options.ckMc ?? join26(homedir19(), ".local", "share", "cortexkit", "bin", "ck-mc");
|
|
38674
39261
|
const args = [
|
|
38675
39262
|
"single-store-migrate",
|
|
38676
39263
|
"--context-db",
|
|
@@ -38786,6 +39373,7 @@ function runDoctorSingleStoreCli(args) {
|
|
|
38786
39373
|
}
|
|
38787
39374
|
var STOP = "quit OpenCode, Pi and ck-mc (`ck stop magic-context`) and run again", SUFFIXES2;
|
|
38788
39375
|
var init_doctor_single_store = __esm(async () => {
|
|
39376
|
+
init_disk_space();
|
|
38789
39377
|
await __promiseAll([
|
|
38790
39378
|
init_storage_db(),
|
|
38791
39379
|
init_sqlite(),
|
|
@@ -39160,18 +39748,18 @@ var init_storage_identity_merge = __esm(() => {
|
|
|
39160
39748
|
|
|
39161
39749
|
// src/commands/doctor-identity-splits.ts
|
|
39162
39750
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
39163
|
-
import { createHash as
|
|
39164
|
-
import { existsSync as
|
|
39165
|
-
import { dirname as
|
|
39751
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
39752
|
+
import { existsSync as existsSync35, readdirSync as readdirSync7, realpathSync as realpathSync6, statSync as statSync18 } from "node:fs";
|
|
39753
|
+
import { dirname as dirname20, join as join27, resolve as resolve14 } from "node:path";
|
|
39166
39754
|
function tableExists5(db, table) {
|
|
39167
39755
|
return !!db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(table);
|
|
39168
39756
|
}
|
|
39169
39757
|
function hasGitMetadataInAncestors(directory) {
|
|
39170
|
-
let current =
|
|
39758
|
+
let current = resolve14(directory);
|
|
39171
39759
|
while (true) {
|
|
39172
|
-
if (
|
|
39760
|
+
if (existsSync35(join27(current, ".git")))
|
|
39173
39761
|
return true;
|
|
39174
|
-
const parent =
|
|
39762
|
+
const parent = dirname20(current);
|
|
39175
39763
|
if (parent === current)
|
|
39176
39764
|
return false;
|
|
39177
39765
|
current = parent;
|
|
@@ -39180,7 +39768,7 @@ function hasGitMetadataInAncestors(directory) {
|
|
|
39180
39768
|
function orphanedPathReason(directory) {
|
|
39181
39769
|
let entries;
|
|
39182
39770
|
try {
|
|
39183
|
-
if (!
|
|
39771
|
+
if (!statSync18(directory).isDirectory())
|
|
39184
39772
|
return "path is no longer a directory";
|
|
39185
39773
|
entries = readdirSync7(directory);
|
|
39186
39774
|
} catch (error) {
|
|
@@ -39255,7 +39843,7 @@ function findIdentitySplits(db, host, includeSingles = false) {
|
|
|
39255
39843
|
const gitIdentities = new Map;
|
|
39256
39844
|
for (const [directoryKey, spellings] of directorySpellings) {
|
|
39257
39845
|
for (const directory of spellings) {
|
|
39258
|
-
const dirIdentity = `dir:${
|
|
39846
|
+
const dirIdentity = `dir:${createHash6("md5").update(resolve14(directory), "utf8").digest("hex").slice(0, 12)}`;
|
|
39259
39847
|
const hasData = [
|
|
39260
39848
|
"memories",
|
|
39261
39849
|
"notes",
|
|
@@ -39324,7 +39912,7 @@ function identityLines(split) {
|
|
|
39324
39912
|
return split.identities.map((row) => ` ${row.identity}: ${row.sessions} sessions, ${row.memories} memories, ${row.notes} notes, ${row.dreamer} dreamer rows (identity-wide counts)`);
|
|
39325
39913
|
}
|
|
39326
39914
|
function diagnoseIdentitySplits() {
|
|
39327
|
-
const db = openExistingContextDatabase(
|
|
39915
|
+
const db = openExistingContextDatabase(join27(getMagicContextStorageDir(), "context.db"), {
|
|
39328
39916
|
readonly: true
|
|
39329
39917
|
});
|
|
39330
39918
|
if (!db)
|
|
@@ -39349,15 +39937,15 @@ var init_doctor_identity_splits = __esm(async () => {
|
|
|
39349
39937
|
|
|
39350
39938
|
// src/commands/doctor-merge-identity.ts
|
|
39351
39939
|
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
39352
|
-
import { createHash as
|
|
39353
|
-
import { existsSync as
|
|
39354
|
-
import { dirname as
|
|
39940
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
39941
|
+
import { existsSync as existsSync36, mkdtempSync as mkdtempSync2, readdirSync as readdirSync8, readFileSync as readFileSync21, statSync as statSync19 } from "node:fs";
|
|
39942
|
+
import { dirname as dirname21, join as join28, resolve as resolve15 } from "node:path";
|
|
39355
39943
|
function parseMergeIdentityArgs(args) {
|
|
39356
39944
|
const values = {};
|
|
39357
|
-
const switches = new Set(["--apply", "--force", "--dry-run", "--yes"]);
|
|
39945
|
+
const switches = new Set(["--apply", "--force", "--dry-run", "--yes", "--verbose"]);
|
|
39358
39946
|
for (let i = 0;i < args.length; i++) {
|
|
39359
39947
|
const flag = args[i];
|
|
39360
|
-
if (["--from", "--to", "--db", "--host-db"].includes(flag)) {
|
|
39948
|
+
if (["--from", "--to", "--db", "--host-db", "--backup-root"].includes(flag)) {
|
|
39361
39949
|
const value = args[++i];
|
|
39362
39950
|
if (!value || value.startsWith("--"))
|
|
39363
39951
|
throw new Error(`${flag} requires a value`);
|
|
@@ -39377,9 +39965,11 @@ function parseMergeIdentityArgs(args) {
|
|
|
39377
39965
|
to: values["--to"],
|
|
39378
39966
|
dbPath: values["--db"],
|
|
39379
39967
|
hostPath: values["--host-db"],
|
|
39968
|
+
backupRoot: values["--backup-root"],
|
|
39380
39969
|
dryRun: !apply,
|
|
39381
39970
|
yes: apply,
|
|
39382
|
-
force: args.includes("--force")
|
|
39971
|
+
force: args.includes("--force"),
|
|
39972
|
+
verbose: args.includes("--verbose")
|
|
39383
39973
|
};
|
|
39384
39974
|
}
|
|
39385
39975
|
function printReport(report) {
|
|
@@ -39399,7 +39989,7 @@ function printReport(report) {
|
|
|
39399
39989
|
console.log(" No writes. Review this preview, then repeat with --apply to confirm.");
|
|
39400
39990
|
}
|
|
39401
39991
|
function resolveReadOnly(directory) {
|
|
39402
|
-
if (!
|
|
39992
|
+
if (!existsSync36(directory))
|
|
39403
39993
|
return;
|
|
39404
39994
|
try {
|
|
39405
39995
|
const roots = execFileSync7("git", ["rev-list", "--max-parents=0", "HEAD"], {
|
|
@@ -39424,14 +40014,23 @@ function resolveReadOnly(directory) {
|
|
|
39424
40014
|
return;
|
|
39425
40015
|
} catch (error) {
|
|
39426
40016
|
if (String(error.stderr).includes("not a git repository"))
|
|
39427
|
-
return `dir:${
|
|
40017
|
+
return `dir:${createHash7("md5").update(projectDirectoryKey(directory)).digest("hex").slice(0, 12)}`;
|
|
39428
40018
|
}
|
|
39429
40019
|
return;
|
|
39430
40020
|
}
|
|
39431
40021
|
function canonicalIdentity(directory, storageDir) {
|
|
39432
40022
|
return readRememberedGitIdentity(directory, storageDir) ?? (orphanedPathReason(directory) ? undefined : resolveReadOnly(directory));
|
|
39433
40023
|
}
|
|
40024
|
+
function directoryDoesNotExist(directory) {
|
|
40025
|
+
try {
|
|
40026
|
+
statSync19(directory);
|
|
40027
|
+
} catch (error) {
|
|
40028
|
+
return error.code === "ENOENT";
|
|
40029
|
+
}
|
|
40030
|
+
return false;
|
|
40031
|
+
}
|
|
39434
40032
|
function assertMergePairSafe(db, observed, storageDir, from, to) {
|
|
40033
|
+
const allowances = [];
|
|
39435
40034
|
if (from.startsWith("git:") && !to.startsWith("git:"))
|
|
39436
40035
|
throw new Error(`Refusing merge: ${from} is a repository-wide identity shared by every checkout and worktree of its repository. It can only be a merge target, never merged into the directory identity ${to}.`);
|
|
39437
40036
|
const sourceRows = countIdentityRows(db, from);
|
|
@@ -39444,11 +40043,54 @@ function assertMergePairSafe(db, observed, storageDir, from, to) {
|
|
|
39444
40043
|
const persisted = readRememberedGitIdentity(row.directory, storageDir);
|
|
39445
40044
|
if (!persisted)
|
|
39446
40045
|
continue;
|
|
39447
|
-
if (persisted === from)
|
|
40046
|
+
if (persisted === from) {
|
|
40047
|
+
let live;
|
|
40048
|
+
const orphaned = directoryDoesNotExist(row.directory);
|
|
40049
|
+
if (!orphaned) {
|
|
40050
|
+
try {
|
|
40051
|
+
live = resolveProjectIdentityStrict(row.directory, undefined, { cache: false });
|
|
40052
|
+
} catch {}
|
|
40053
|
+
}
|
|
40054
|
+
if (orphaned || live === to) {
|
|
40055
|
+
allowances.push({
|
|
40056
|
+
directory: row.directory,
|
|
40057
|
+
reason: orphaned ? "orphaned" : `live root now resolves to ${to}`,
|
|
40058
|
+
liveIdentity: live
|
|
40059
|
+
});
|
|
40060
|
+
continue;
|
|
40061
|
+
}
|
|
39448
40062
|
throw new Error(`Refusing merge: ${from} is the identity the plugin persisted for ${row.directory}; merging away from it would contradict the plugin's own resolution of that path.`);
|
|
40063
|
+
}
|
|
39449
40064
|
if (persisted !== to)
|
|
39450
40065
|
throw new Error(`Refusing merge: the plugin persisted ${persisted} for ${row.directory}, where ${involved.map((item) => item.identity).join(" and ")} was observed. That persisted identity is canonical for the path; merge into ${persisted} instead of ${to}.`);
|
|
39451
40066
|
}
|
|
40067
|
+
return allowances;
|
|
40068
|
+
}
|
|
40069
|
+
function assertMergeDirectoriesSafe(db, from, to, sourceDirs, targetDirs, allowances) {
|
|
40070
|
+
const alreadyMerged = auditIdentityMerge(db, from, to).changedRows === 0 && db.prepare("SELECT 1 FROM v22_identity_rekey_map WHERE old_project_path = ? AND new_project_path = ?").get(from, to);
|
|
40071
|
+
const allowedDirs = new Set(allowances.map((item) => item.directory));
|
|
40072
|
+
const missingSourceDirs = sourceDirs.filter((directory) => !targetDirs.includes(directory) && directoryDoesNotExist(directory));
|
|
40073
|
+
for (const directory of missingSourceDirs)
|
|
40074
|
+
allowedDirs.add(directory);
|
|
40075
|
+
const sourceDirsAllowed = allowedDirs.size > 0 && sourceDirs.every((directory) => targetDirs.includes(directory) || allowedDirs.has(directory));
|
|
40076
|
+
if (!alreadyMerged && from.startsWith("git:") && to.startsWith("git:") && (!sourceDirs.length || !targetDirs.length || !sourceDirsAllowed && (sourceDirs.some((dir) => !targetDirs.includes(dir)) || targetDirs.some((dir) => !sourceDirs.includes(dir)))))
|
|
40077
|
+
throw new Error(`Refusing different directories for ${from} (${sourceDirs.join(", ") || "unknown"}) and ${to} (${targetDirs.join(", ") || "unknown"})`);
|
|
40078
|
+
return missingSourceDirs;
|
|
40079
|
+
}
|
|
40080
|
+
function printSidecarPreview(allowances, missingSourceDirs, to, verbose) {
|
|
40081
|
+
const missing = new Set(missingSourceDirs);
|
|
40082
|
+
const orphanPins = allowances.filter((item) => missing.has(item.directory));
|
|
40083
|
+
if (missingSourceDirs.length) {
|
|
40084
|
+
console.log(` ${missingSourceDirs.length} source-only folders no longer exist: allowed${orphanPins.length ? ` (${orphanPins.length} orphaned sidecar(s) will be rewritten to ${to})` : ""}.${verbose ? "" : " Use --verbose for the full list."}`);
|
|
40085
|
+
if (verbose) {
|
|
40086
|
+
for (const directory of missingSourceDirs)
|
|
40087
|
+
if (!orphanPins.some((item) => item.directory === directory))
|
|
40088
|
+
console.log(` ${directory} (orphaned; no persisted sidecar)`);
|
|
40089
|
+
}
|
|
40090
|
+
}
|
|
40091
|
+
for (const item of allowances)
|
|
40092
|
+
if (verbose || !missing.has(item.directory))
|
|
40093
|
+
console.log(` Sidecar for ${item.directory}: overwrite with ${to} (${item.reason}; sidecar will be rewritten).`);
|
|
39452
40094
|
}
|
|
39453
40095
|
function printSuggestion(db, split, storageDir) {
|
|
39454
40096
|
const rows = new Map(split.identities.map((row) => [row.identity, countIdentityRows(db, row.identity)]));
|
|
@@ -39503,13 +40145,13 @@ function observations(db, hostPath, storageDir) {
|
|
|
39503
40145
|
if (!row.identities.some((item) => item.identity === identity))
|
|
39504
40146
|
row.identities.push({ identity, sessions: 0, memories: 0, notes: 0, dreamer: 0 });
|
|
39505
40147
|
};
|
|
39506
|
-
const sidecars =
|
|
39507
|
-
if (
|
|
40148
|
+
const sidecars = join28(storageDir, "project-identities");
|
|
40149
|
+
if (existsSync36(sidecars))
|
|
39508
40150
|
for (const file of readdirSync8(sidecars)) {
|
|
39509
40151
|
if (!file.endsWith(".json"))
|
|
39510
40152
|
continue;
|
|
39511
40153
|
try {
|
|
39512
|
-
const record = JSON.parse(
|
|
40154
|
+
const record = JSON.parse(readFileSync21(join28(sidecars, file), "utf8"));
|
|
39513
40155
|
if (typeof record.directory === "string" && typeof record.identity === "string")
|
|
39514
40156
|
add(record.directory, record.identity);
|
|
39515
40157
|
} catch {}
|
|
@@ -39520,9 +40162,9 @@ function observations(db, hostPath, storageDir) {
|
|
|
39520
40162
|
}
|
|
39521
40163
|
function runMergeIdentityCli(args, deps = {}) {
|
|
39522
40164
|
const options = parseMergeIdentityArgs(args);
|
|
39523
|
-
const dbPath = options.dbPath ??
|
|
39524
|
-
const storageDir =
|
|
39525
|
-
const hostPath = options.hostPath ?? (options.dbPath ?
|
|
40165
|
+
const dbPath = options.dbPath ?? join28(getMagicContextStorageDir(), "context.db");
|
|
40166
|
+
const storageDir = dirname21(dbPath);
|
|
40167
|
+
const hostPath = options.hostPath ?? (options.dbPath ? join28(storageDir, "host.db") : resolveOpenCodeDbPath().path);
|
|
39526
40168
|
let db = openExistingContextDatabase(dbPath, {
|
|
39527
40169
|
readonly: true,
|
|
39528
40170
|
minimumSupportedVersion: CLI_SCHEMA_FLOOR_VERSION
|
|
@@ -39542,7 +40184,7 @@ function runMergeIdentityCli(args, deps = {}) {
|
|
|
39542
40184
|
}
|
|
39543
40185
|
if (options.from === options.to)
|
|
39544
40186
|
throw new Error(`Source and target identities must differ: ${options.from}`);
|
|
39545
|
-
assertMergePairSafe(db, observed, storageDir, options.from, options.to);
|
|
40187
|
+
const allowances = assertMergePairSafe(db, observed, storageDir, options.from, options.to);
|
|
39546
40188
|
for (const identity of [options.from, options.to]) {
|
|
39547
40189
|
const known = auditIdentityMerge(db, identity, options.to).changedRows > 0 || db.prepare("SELECT 1 FROM v22_identity_rekey_map WHERE old_project_path = ? OR new_project_path = ?").get(identity, identity);
|
|
39548
40190
|
if (!known)
|
|
@@ -39551,12 +40193,11 @@ function runMergeIdentityCli(args, deps = {}) {
|
|
|
39551
40193
|
const sourceDirs = observed.filter((row) => row.identities.some((item) => item.identity === options.from)).map((row) => row.directory);
|
|
39552
40194
|
const targetDirs = observed.filter((row) => row.identities.some((item) => item.identity === options.to)).map((row) => row.directory);
|
|
39553
40195
|
directories = [...new Set([...sourceDirs, ...targetDirs])];
|
|
39554
|
-
const
|
|
39555
|
-
if (!
|
|
39556
|
-
throw new Error(`Refusing different directories for ${options.from} (${sourceDirs.join(", ") || "unknown"}) and ${options.to} (${targetDirs.join(", ") || "unknown"})`);
|
|
39557
|
-
if (!options.force && !directories.some((directory) => canonicalIdentity(directory, storageDir) === options.to))
|
|
40196
|
+
const missingSourceDirs = assertMergeDirectoriesSafe(db, options.from, options.to, sourceDirs, targetDirs, allowances);
|
|
40197
|
+
if (!options.force && !directories.some((directory) => canonicalIdentity(directory, storageDir) === options.to || allowances.some((item) => item.directory === directory && item.liveIdentity === options.to)))
|
|
39558
40198
|
throw new Error(`Target ${options.to} does not resolve for any observed directory on this machine; use --force only after reviewing the identity.`);
|
|
39559
40199
|
const preview = mergeProjectIdentities(db, options.from, options.to, { dryRun: true });
|
|
40200
|
+
printSidecarPreview(allowances, missingSourceDirs, options.to, options.verbose);
|
|
39560
40201
|
printReport(preview);
|
|
39561
40202
|
if (options.dryRun)
|
|
39562
40203
|
return 0;
|
|
@@ -39574,47 +40215,64 @@ function runMergeIdentityCli(args, deps = {}) {
|
|
|
39574
40215
|
});
|
|
39575
40216
|
if (!holders.safe || probe.status !== "free")
|
|
39576
40217
|
throw new Error(`Refusing merge: close OpenCode, Pi, OpenCode 2 and ck-mc. ${holders.blockers.join(", ")} ${holders.uncertainty ?? ""} ${probe.status === "in_use" ? `context.db holders: ${probe.pids.join(", ")}` : probe.status === "unknown" ? probe.reason : ""}`);
|
|
39577
|
-
const
|
|
40218
|
+
const backupRoot = resolve15(options.backupRoot ?? storageDir);
|
|
40219
|
+
const backupVolume = existingDirectoryAncestor(backupRoot);
|
|
40220
|
+
const sidecarRoot = join28(storageDir, "project-identities");
|
|
40221
|
+
const sidecarEntries = existsSync36(sidecarRoot) ? readdirSync8(sidecarRoot).filter((entry) => entry.endsWith(".json")) : [];
|
|
40222
|
+
const sidecarBytes = sidecarEntries.reduce((size, entry) => size + statSync19(join28(sidecarRoot, entry)).size, 0);
|
|
40223
|
+
const diskSpace = checkDiskSpace(backupVolume, databaseBundleSizeBytes(dbPath) + sidecarBytes, deps.freeBytes ?? availableDiskBytes);
|
|
40224
|
+
if (!diskSpace.sufficient)
|
|
40225
|
+
throw new Error(`merge_identity_disk_space: refusing identity merge: backup needs ${diskSpace.requiredBytes} bytes; have ${diskSpace.availableBytes} bytes on ${backupVolume}. Use --backup-root <dir> to choose a volume with enough free space.`);
|
|
40226
|
+
ensureStorageDirectorySync(backupRoot, true);
|
|
40227
|
+
const backup = mkdtempSync2(join28(backupRoot, "identity-merge-backup-"));
|
|
39578
40228
|
const quote = (value) => `'${value.replaceAll("'", "'\\''")}'`;
|
|
39579
40229
|
console.log(`Backup directory: ${backup}`);
|
|
39580
|
-
console.log(`Restore with hosts closed: rm -f ${quote(`${dbPath}-wal`)} ${quote(`${dbPath}-shm`)}; cp ${quote(
|
|
39581
|
-
const
|
|
39582
|
-
|
|
39583
|
-
|
|
39584
|
-
|
|
39585
|
-
|
|
39586
|
-
|
|
39587
|
-
|
|
39588
|
-
writeStorageFileAtomicSync(join27(sidecarBackup, entry), readFileSync20(join27(sidecarRoot, entry)));
|
|
39589
|
-
}
|
|
40230
|
+
console.log(`Restore with hosts closed: rm -f ${quote(`${dbPath}-wal`)} ${quote(`${dbPath}-shm`)}; cp ${quote(join28(backup, "context.db"))} ${quote(dbPath)}; if test -f ${quote(join28(backup, "context.db-wal"))}; then cp ${quote(join28(backup, "context.db-wal"))} ${quote(`${dbPath}-wal`)}; fi`);
|
|
40231
|
+
const sidecarBackup = join28(backup, "project-identities");
|
|
40232
|
+
ensureStorageDirectorySync(sidecarBackup, true);
|
|
40233
|
+
let backupBytes = 0;
|
|
40234
|
+
for (const entry of sidecarEntries) {
|
|
40235
|
+
const content = readFileSync21(join28(sidecarRoot, entry));
|
|
40236
|
+
writeStorageFileAtomicSync(join28(sidecarBackup, entry), content, true);
|
|
40237
|
+
backupBytes += content.byteLength;
|
|
39590
40238
|
}
|
|
39591
40239
|
console.log(`Restore identity sidecars too: rm -rf ${quote(sidecarRoot)}; cp -R ${quote(sidecarBackup)} ${quote(sidecarRoot)}`);
|
|
39592
|
-
copyDatabaseBundle(dbPath,
|
|
40240
|
+
const copiedDatabaseFiles = copyDatabaseBundle(dbPath, join28(backup, "context.db"), true);
|
|
40241
|
+
backupBytes += copiedDatabaseFiles.reduce((size, path) => size + statSync19(path).size, 0);
|
|
39593
40242
|
db = openExistingDatabase(dbPath, { readonly: false });
|
|
39594
40243
|
if (!db)
|
|
39595
40244
|
throw new Error(`Context database disappeared: ${dbPath}`);
|
|
39596
40245
|
try {
|
|
39597
40246
|
configureContextDatabasePragmas(db);
|
|
39598
|
-
|
|
40247
|
+
observed = observations(db, hostPath, storageDir);
|
|
40248
|
+
const allowances = assertMergePairSafe(db, observed, storageDir, from, to);
|
|
40249
|
+
const sourceDirs = observed.filter((row) => row.identities.some((item) => item.identity === from)).map((row) => row.directory);
|
|
40250
|
+
const targetDirs = observed.filter((row) => row.identities.some((item) => item.identity === to)).map((row) => row.directory);
|
|
40251
|
+
assertMergeDirectoriesSafe(db, from, to, sourceDirs, targetDirs, allowances);
|
|
40252
|
+
directories = [...new Set([...sourceDirs, ...targetDirs])];
|
|
39599
40253
|
printReport(mergeProjectIdentities(db, from, to));
|
|
39600
40254
|
} finally {
|
|
39601
40255
|
db.close();
|
|
39602
40256
|
}
|
|
39603
40257
|
if (to.startsWith("git:"))
|
|
39604
40258
|
for (const directory of directories) {
|
|
39605
|
-
const root =
|
|
40259
|
+
const root = join28(storageDir, "project-identities");
|
|
39606
40260
|
ensureStorageDirectorySync(root);
|
|
39607
|
-
const path =
|
|
40261
|
+
const path = join28(root, `${createHash7("sha256").update(projectDirectoryKey(directory)).digest("hex")}.json`);
|
|
39608
40262
|
writeStorageFileAtomicSync(path, JSON.stringify({ directory: projectDirectoryKey(directory), identity: options.to }));
|
|
39609
40263
|
}
|
|
40264
|
+
console.log(`Backup: ${backup} (${backupBytes} bytes)`);
|
|
40265
|
+
console.log("This backup can be deleted once the merge has been confirmed.");
|
|
39610
40266
|
return 0;
|
|
39611
40267
|
}
|
|
39612
40268
|
var init_doctor_merge_identity = __esm(async () => {
|
|
40269
|
+
init_project_identity();
|
|
39613
40270
|
init_project_identity_cache();
|
|
39614
40271
|
init_storage_identity_merge();
|
|
39615
40272
|
init_data_path();
|
|
39616
40273
|
init_opencode_db_path();
|
|
39617
40274
|
init_storage_permissions();
|
|
40275
|
+
init_disk_space();
|
|
39618
40276
|
await __promiseAll([
|
|
39619
40277
|
init_database_access(),
|
|
39620
40278
|
init_doctor_identity_splits(),
|
|
@@ -39624,8 +40282,8 @@ var init_doctor_merge_identity = __esm(async () => {
|
|
|
39624
40282
|
});
|
|
39625
40283
|
|
|
39626
40284
|
// src/commands/doctor-git-fts-map.ts
|
|
39627
|
-
import { existsSync as
|
|
39628
|
-
import { join as
|
|
40285
|
+
import { existsSync as existsSync37, mkdtempSync as mkdtempSync3, statSync as statSync20 } from "node:fs";
|
|
40286
|
+
import { join as join29, resolve as resolve16 } from "node:path";
|
|
39629
40287
|
function inspectGitFtsMap(db) {
|
|
39630
40288
|
const has = (name) => Boolean(db.prepare("SELECT 1 FROM sqlite_master WHERE name=? AND type='table'").get(name));
|
|
39631
40289
|
const indexed = has("git_commits_fts");
|
|
@@ -39678,8 +40336,8 @@ function runDoctorGitFtsMap(options = {}, overrides = {}) {
|
|
|
39678
40336
|
verify: verifyInventory,
|
|
39679
40337
|
...overrides
|
|
39680
40338
|
};
|
|
39681
|
-
const context =
|
|
39682
|
-
const store =
|
|
40339
|
+
const context = join29(deps.storageDir, "context.db");
|
|
40340
|
+
const store = join29(deps.storageDir, "store.db");
|
|
39683
40341
|
let db = null, storeDb = null;
|
|
39684
40342
|
let contextLocked = false, storeLocked = false;
|
|
39685
40343
|
try {
|
|
@@ -39701,9 +40359,9 @@ function runDoctorGitFtsMap(options = {}, overrides = {}) {
|
|
|
39701
40359
|
deps.print(`Stop every host, then run \`${GIT_FTS_MAP_REPAIR_COMMAND}\`. The repair backs up context.db and store.db first.`);
|
|
39702
40360
|
return damaged ? 1 : 0;
|
|
39703
40361
|
}
|
|
39704
|
-
if (!
|
|
40362
|
+
if (!existsSync37(context) || !existsSync37(store))
|
|
39705
40363
|
throw new Error("Both context.db and store.db must exist before paired-backup repair; no replacement store will be created");
|
|
39706
|
-
const cstat =
|
|
40364
|
+
const cstat = statSync20(context), sstat = statSync20(store);
|
|
39707
40365
|
if (cstat.dev === sstat.dev && cstat.ino === sstat.ino)
|
|
39708
40366
|
throw new Error("context.db and store.db must be distinct files");
|
|
39709
40367
|
const holders = deps.inspectHolders(deps.storageDir);
|
|
@@ -39731,12 +40389,12 @@ function runDoctorGitFtsMap(options = {}, overrides = {}) {
|
|
|
39731
40389
|
const stillFree = deps.inspectHolders(deps.storageDir);
|
|
39732
40390
|
if (!stillFree.safe)
|
|
39733
40391
|
throw new Error(`A host appeared before backup: ${[...stillFree.blockers, stillFree.uncertainty].filter(Boolean).join("; ")}`);
|
|
39734
|
-
const backupRoot =
|
|
40392
|
+
const backupRoot = resolve16(options.backupRoot ?? join29(deps.storageDir, "backups"));
|
|
39735
40393
|
ensureStorageDirectorySync(backupRoot, true);
|
|
39736
|
-
const backup =
|
|
39737
|
-
snapshot(context,
|
|
39738
|
-
snapshot(store,
|
|
39739
|
-
writeStorageFileSync(
|
|
40394
|
+
const backup = mkdtempSync3(join29(backupRoot, "git-fts-map-"));
|
|
40395
|
+
snapshot(context, join29(backup, "context.db"));
|
|
40396
|
+
snapshot(store, join29(backup, "store.db"));
|
|
40397
|
+
writeStorageFileSync(join29(backup, "manifest.json"), JSON.stringify({
|
|
39740
40398
|
contextVersion: version,
|
|
39741
40399
|
createdAt: new Date().toISOString(),
|
|
39742
40400
|
repair: "git-fts-map",
|
|
@@ -39903,20 +40561,20 @@ function assertNoUnmigratedAuthority(db) {
|
|
|
39903
40561
|
var SINGLE_STORE_REQUIRED = "Magic Context's Rust mode needs a one-time migration of its store. Quit OpenCode and every ck-mc process, then run `magic-context doctor single-store migrate`. (MC-C14)";
|
|
39904
40562
|
|
|
39905
40563
|
// src/commands/migrate.ts
|
|
39906
|
-
import { createHash as
|
|
39907
|
-
import { existsSync as
|
|
39908
|
-
import { dirname as
|
|
40564
|
+
import { createHash as createHash8, randomBytes as randomBytes3 } from "node:crypto";
|
|
40565
|
+
import { existsSync as existsSync38, mkdirSync as mkdirSync6, renameSync as renameSync7, unlinkSync as unlinkSync4 } from "node:fs";
|
|
40566
|
+
import { dirname as dirname22, join as join30 } from "node:path";
|
|
39909
40567
|
function defaultOpenCodeDbPath() {
|
|
39910
40568
|
return getOpenCodeDatabasePath();
|
|
39911
40569
|
}
|
|
39912
40570
|
function defaultCortexkitDbPath() {
|
|
39913
|
-
return
|
|
40571
|
+
return join30(getMagicContextStorageDir(), "context.db");
|
|
39914
40572
|
}
|
|
39915
40573
|
function defaultPiSessionsRoot() {
|
|
39916
40574
|
return getPiSessionsRoot();
|
|
39917
40575
|
}
|
|
39918
40576
|
function defaultFs() {
|
|
39919
|
-
return { writeFileAtomic, unlinkSync: unlinkSync4, existsSync:
|
|
40577
|
+
return { writeFileAtomic, unlinkSync: unlinkSync4, existsSync: existsSync38, renameSync: renameSync7, mkdirSync: mkdirSync6 };
|
|
39920
40578
|
}
|
|
39921
40579
|
function stmt(db, sql) {
|
|
39922
40580
|
return db.prepare(sql);
|
|
@@ -39943,7 +40601,7 @@ function shortId() {
|
|
|
39943
40601
|
return randomBytes3(4).toString("hex");
|
|
39944
40602
|
}
|
|
39945
40603
|
function migrationKeyFor(sourceSessionId, targetHarness) {
|
|
39946
|
-
return
|
|
40604
|
+
return createHash8("sha256").update(`${sourceSessionId}
|
|
39947
40605
|
${targetHarness}`).digest("hex");
|
|
39948
40606
|
}
|
|
39949
40607
|
function hasMigrationJournal(db) {
|
|
@@ -39970,7 +40628,7 @@ function sweepPendingMigrations(db, fs = defaultFs()) {
|
|
|
39970
40628
|
}
|
|
39971
40629
|
if (row.phase === "db_committed") {
|
|
39972
40630
|
if (fs.existsSync(row.stage_path)) {
|
|
39973
|
-
fs.mkdirSync(
|
|
40631
|
+
fs.mkdirSync(dirname22(row.final_path), { recursive: true });
|
|
39974
40632
|
fs.renameSync(row.stage_path, row.final_path);
|
|
39975
40633
|
stmt(db, "DELETE FROM migration_pending WHERE migration_key = ?").run(row.migration_key);
|
|
39976
40634
|
report.rolledForward += 1;
|
|
@@ -40000,7 +40658,7 @@ function claimJournalIdentity(args) {
|
|
|
40000
40658
|
migration_key, source_session_id, target_harness, pi_session_id,
|
|
40001
40659
|
final_path, stage_path, content_sha256, phase, created_at
|
|
40002
40660
|
) VALUES (?, ?, ?, ?, ?, ?, '', 'staged', ?)
|
|
40003
|
-
ON CONFLICT(migration_key) DO NOTHING`).run(args.migrationKey, args.sourceSessionId, args.targetHarness, piSessionId, args.finalPathFor(piSessionId),
|
|
40661
|
+
ON CONFLICT(migration_key) DO NOTHING`).run(args.migrationKey, args.sourceSessionId, args.targetHarness, piSessionId, args.finalPathFor(piSessionId), join30(args.stageDir, `${args.migrationKey}.jsonl`), args.now);
|
|
40004
40662
|
const row = readPendingMigration(args.db, args.migrationKey);
|
|
40005
40663
|
if (!row) {
|
|
40006
40664
|
throw new Error("migration journal row disappeared during insert; aborting migration");
|
|
@@ -40508,7 +41166,7 @@ function migrateOpenCodeSessionToPi(opts) {
|
|
|
40508
41166
|
const provider = opts.provider ?? model.provider;
|
|
40509
41167
|
const modelId = opts.modelId ?? model.modelId;
|
|
40510
41168
|
const cwd = session.directory ?? session.path ?? process.cwd();
|
|
40511
|
-
const outputDir =
|
|
41169
|
+
const outputDir = join30(piSessionsRoot, projectPathToPiDirSlug(cwd));
|
|
40512
41170
|
const targetHarness = opts.targetHarness ?? "pi";
|
|
40513
41171
|
if (cortexkitDb !== null) {
|
|
40514
41172
|
assertNoUnmigratedAuthority(cortexkitDb);
|
|
@@ -40535,8 +41193,8 @@ function migrateOpenCodeSessionToPi(opts) {
|
|
|
40535
41193
|
migrationKey,
|
|
40536
41194
|
sourceSessionId: session.id,
|
|
40537
41195
|
targetHarness,
|
|
40538
|
-
finalPathFor: (id) =>
|
|
40539
|
-
stageDir:
|
|
41196
|
+
finalPathFor: (id) => join30(outputDir, `${formatPiFilenameTimestamp(now)}_${id}.jsonl`),
|
|
41197
|
+
stageDir: join30(dirname22(piSessionsRoot), MIGRATION_STAGE_DIRNAME),
|
|
40540
41198
|
now: now.getTime()
|
|
40541
41199
|
});
|
|
40542
41200
|
piSessionId = claimed.row.pi_session_id;
|
|
@@ -40545,7 +41203,7 @@ function migrateOpenCodeSessionToPi(opts) {
|
|
|
40545
41203
|
journalResumed = claimed.resumed;
|
|
40546
41204
|
} else {
|
|
40547
41205
|
piSessionId = generateUuidV7(now);
|
|
40548
|
-
finalPath =
|
|
41206
|
+
finalPath = join30(outputDir, `${formatPiFilenameTimestamp(now)}_${piSessionId}.jsonl`);
|
|
40549
41207
|
stagePath = "";
|
|
40550
41208
|
}
|
|
40551
41209
|
const buildResult = buildPiEntries({
|
|
@@ -40584,11 +41242,11 @@ function migrateOpenCodeSessionToPi(opts) {
|
|
|
40584
41242
|
`;
|
|
40585
41243
|
if (!opts.dryRun) {
|
|
40586
41244
|
if (journalActive && cortexkitDb !== null && migrationKey !== undefined && plan) {
|
|
40587
|
-
const contentSha256 =
|
|
41245
|
+
const contentSha256 = createHash8("sha256").update(jsonl, "utf8").digest("hex");
|
|
40588
41246
|
commitStagedChecksum(cortexkitDb, migrationKey, contentSha256);
|
|
40589
41247
|
fs.writeFileAtomic(stagePath, jsonl);
|
|
40590
41248
|
plan.commit(migrationKey);
|
|
40591
|
-
fs.mkdirSync(
|
|
41249
|
+
fs.mkdirSync(dirname22(finalPath), { recursive: true });
|
|
40592
41250
|
fs.renameSync(stagePath, finalPath);
|
|
40593
41251
|
stmt(cortexkitDb, "DELETE FROM migration_pending WHERE migration_key = ?").run(migrationKey);
|
|
40594
41252
|
} else {
|
|
@@ -42483,7 +43141,7 @@ var init_dist5 = __esm(() => {
|
|
|
42483
43141
|
});
|
|
42484
43142
|
|
|
42485
43143
|
// ../plugin/src/hooks/magic-context/reply-pages.ts
|
|
42486
|
-
import { createHash as
|
|
43144
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
42487
43145
|
function fail() {
|
|
42488
43146
|
throw Object.assign(new Error("Incomplete or invalid module reply; abandon this pass"), {
|
|
42489
43147
|
code: "reply_page_invalid"
|
|
@@ -42518,7 +43176,7 @@ async function assembleReplyPages(response, fetchPage) {
|
|
|
42518
43176
|
if (received !== bytes)
|
|
42519
43177
|
fail();
|
|
42520
43178
|
const rebuilt = Buffer.concat(chunks, received);
|
|
42521
|
-
if (
|
|
43179
|
+
if (createHash9("sha256").update(rebuilt).digest("hex") !== id)
|
|
42522
43180
|
fail();
|
|
42523
43181
|
return JSON.parse(rebuilt.toString("utf8"));
|
|
42524
43182
|
}
|
|
@@ -42894,9 +43552,9 @@ var init_store_ahead_refusal = __esm(() => {
|
|
|
42894
43552
|
|
|
42895
43553
|
// ../plugin/src/hooks/magic-context/module-transport.ts
|
|
42896
43554
|
import { realpathSync as realpathSync7 } from "node:fs";
|
|
42897
|
-
import { join as
|
|
43555
|
+
import { join as join31 } from "node:path";
|
|
42898
43556
|
function getDefaultSubcConnectionFile() {
|
|
42899
|
-
return
|
|
43557
|
+
return join31(getDataDir(), "cortexkit", "run", "subc-connection.json");
|
|
42900
43558
|
}
|
|
42901
43559
|
function errorChainSome(error, predicate) {
|
|
42902
43560
|
let current = error;
|
|
@@ -43504,9 +44162,9 @@ var init_module_transport = __esm(() => {
|
|
|
43504
44162
|
});
|
|
43505
44163
|
|
|
43506
44164
|
// src/commands/migrate-session.ts
|
|
43507
|
-
import { existsSync as
|
|
43508
|
-
import { homedir as
|
|
43509
|
-
import path6, { join as
|
|
44165
|
+
import { existsSync as existsSync39, realpathSync as realpathSync8 } from "node:fs";
|
|
44166
|
+
import { homedir as homedir20 } from "node:os";
|
|
44167
|
+
import path6, { join as join32 } from "node:path";
|
|
43510
44168
|
function existingSessionColumns(db) {
|
|
43511
44169
|
const rows = db.prepare("PRAGMA table_info(session)").all();
|
|
43512
44170
|
return new Set(rows.map((r) => r.name).filter((n) => typeof n === "string"));
|
|
@@ -43687,14 +44345,14 @@ function defaultOpenCodeDbPath2() {
|
|
|
43687
44345
|
return getOpenCodeDatabasePath();
|
|
43688
44346
|
}
|
|
43689
44347
|
function defaultContextDbPath() {
|
|
43690
|
-
return
|
|
44348
|
+
return join32(getMagicContextStorageDir(), "context.db");
|
|
43691
44349
|
}
|
|
43692
44350
|
function realDeps(opencodeDb, contextDb) {
|
|
43693
44351
|
return {
|
|
43694
44352
|
opencodeDb,
|
|
43695
44353
|
contextDb,
|
|
43696
44354
|
resolveIdentity: resolveProjectIdentity,
|
|
43697
|
-
hasGitDir: (dir) =>
|
|
44355
|
+
hasGitDir: (dir) => existsSync39(join32(dir, ".git")),
|
|
43698
44356
|
realpath: (p) => realpathSync8(p)
|
|
43699
44357
|
};
|
|
43700
44358
|
}
|
|
@@ -43772,8 +44430,8 @@ async function runMigrateSessionCli(args) {
|
|
|
43772
44430
|
printMigrateSessionHelp();
|
|
43773
44431
|
return 1;
|
|
43774
44432
|
}
|
|
43775
|
-
const expandedTo = toDir.startsWith("~") ?
|
|
43776
|
-
if (!
|
|
44433
|
+
const expandedTo = toDir.startsWith("~") ? join32(homedir20(), toDir.slice(1).replace(/^[/\\]/, "")) : toDir;
|
|
44434
|
+
if (!existsSync39(expandedTo)) {
|
|
43777
44435
|
console.error(`Target directory does not exist: ${expandedTo}`);
|
|
43778
44436
|
return 1;
|
|
43779
44437
|
}
|
|
@@ -43924,7 +44582,7 @@ var init_migrate_session = __esm(async () => {
|
|
|
43924
44582
|
});
|
|
43925
44583
|
|
|
43926
44584
|
// ../plugin/src/features/magic-context/v22-deferred-backfill.ts
|
|
43927
|
-
import { createHash as
|
|
44585
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
43928
44586
|
import { realpathSync as realpathSync9 } from "node:fs";
|
|
43929
44587
|
import path7 from "node:path";
|
|
43930
44588
|
function readMeta(db, key) {
|
|
@@ -43973,7 +44631,7 @@ function computeLegacyRustDirIdentity(rawProjectPath) {
|
|
|
43973
44631
|
} catch {
|
|
43974
44632
|
canonical = path7.isAbsolute(rawProjectPath) ? rawProjectPath : path7.join(process.cwd(), rawProjectPath);
|
|
43975
44633
|
}
|
|
43976
|
-
return `dir:${
|
|
44634
|
+
return `dir:${createHash10("sha256").update(canonical, "utf8").digest("hex")}`;
|
|
43977
44635
|
}
|
|
43978
44636
|
function upsertRekeyMap(db, oldProjectPath, newProjectPath, rekeyedAt) {
|
|
43979
44637
|
db.prepare(`INSERT INTO v22_identity_rekey_map (old_project_path, new_project_path, rekeyed_at)
|
|
@@ -44194,7 +44852,7 @@ var init_tick_failure = __esm(() => {
|
|
|
44194
44852
|
});
|
|
44195
44853
|
|
|
44196
44854
|
// ../pi-plugin/src/config/index.ts
|
|
44197
|
-
import { existsSync as
|
|
44855
|
+
import { existsSync as existsSync40 } from "node:fs";
|
|
44198
44856
|
function getProjectConfigPaths(cwd) {
|
|
44199
44857
|
const basePath = cortexKitProjectConfigBasePath(cwd);
|
|
44200
44858
|
return [`${basePath}.jsonc`, `${basePath}.json`];
|
|
@@ -44204,10 +44862,10 @@ function getUserConfigPaths() {
|
|
|
44204
44862
|
return [`${basePath}.jsonc`, `${basePath}.json`];
|
|
44205
44863
|
}
|
|
44206
44864
|
function resolveFirstExisting(paths) {
|
|
44207
|
-
return paths.find((path) =>
|
|
44865
|
+
return paths.find((path) => existsSync40(path));
|
|
44208
44866
|
}
|
|
44209
44867
|
function resolvePiLegacyFallback(sources) {
|
|
44210
|
-
return sources.find((source) =>
|
|
44868
|
+
return sources.find((source) => existsSync40(source.path)) ?? null;
|
|
44211
44869
|
}
|
|
44212
44870
|
function loadConfigFile(path, scope) {
|
|
44213
44871
|
let raw;
|
|
@@ -44518,7 +45176,7 @@ function loadPiConfigDetailed(opts = {}, applyRuntimeGlobals = true) {
|
|
|
44518
45176
|
if (loaded)
|
|
44519
45177
|
loadedFiles.push(loaded);
|
|
44520
45178
|
}
|
|
44521
|
-
const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) =>
|
|
45179
|
+
const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) => existsSync40(source.path));
|
|
44522
45180
|
const userPath = resolveFirstExisting(getUserConfigPaths());
|
|
44523
45181
|
const userLegacyFallback = userPath ? null : resolvePiLegacyFallback(harnessLegacy.user);
|
|
44524
45182
|
const userReadPath = userPath ?? userLegacyFallback?.path;
|
|
@@ -44527,7 +45185,7 @@ function loadPiConfigDetailed(opts = {}, applyRuntimeGlobals = true) {
|
|
|
44527
45185
|
if (loaded)
|
|
44528
45186
|
loadedFiles.push(loaded);
|
|
44529
45187
|
}
|
|
44530
|
-
const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) =>
|
|
45188
|
+
const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) => existsSync40(source.path));
|
|
44531
45189
|
if (userLegacyFallback) {
|
|
44532
45190
|
warnings.push(`[user config] reading legacy config from ${userLegacyFallback.path} until migration completes; run \`npx @cortexkit/magic-context doctor\` to consolidate into the shared CortexKit location.`);
|
|
44533
45191
|
} else if (legacyUserUnmigrated) {
|
|
@@ -44665,7 +45323,7 @@ var DATABASE_REPAIR_COMMAND = "bunx @cortexkit/magic-context@latest doctor repai
|
|
|
44665
45323
|
|
|
44666
45324
|
// src/lib/github-issue.ts
|
|
44667
45325
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
44668
|
-
import { readFileSync as
|
|
45326
|
+
import { readFileSync as readFileSync22 } from "node:fs";
|
|
44669
45327
|
function runGhCommand(args) {
|
|
44670
45328
|
try {
|
|
44671
45329
|
const result = spawnSync7("gh", args, {
|
|
@@ -44692,7 +45350,7 @@ function failed(result) {
|
|
|
44692
45350
|
function submitGithubIssue(title, bodyPath, runner = runGhCommand) {
|
|
44693
45351
|
let body;
|
|
44694
45352
|
try {
|
|
44695
|
-
body =
|
|
45353
|
+
body = readFileSync22(bodyPath, "utf-8");
|
|
44696
45354
|
} catch (error) {
|
|
44697
45355
|
return {
|
|
44698
45356
|
ok: false,
|
|
@@ -44750,9 +45408,9 @@ var MAX_GITHUB_ISSUE_BODY_CHARS = 65536;
|
|
|
44750
45408
|
var init_github_issue = () => {};
|
|
44751
45409
|
|
|
44752
45410
|
// src/lib/log-lines.ts
|
|
44753
|
-
import { existsSync as
|
|
44754
|
-
import { tmpdir as
|
|
44755
|
-
import { join as
|
|
45411
|
+
import { existsSync as existsSync41, readFileSync as readFileSync23, statSync as statSync21 } from "node:fs";
|
|
45412
|
+
import { tmpdir as tmpdir3 } from "node:os";
|
|
45413
|
+
import { join as join33 } from "node:path";
|
|
44756
45414
|
function tokenize(input, limit = Number.POSITIVE_INFINITY) {
|
|
44757
45415
|
const tokens = [];
|
|
44758
45416
|
let index = 0;
|
|
@@ -45038,20 +45696,20 @@ function parseLogLine(line) {
|
|
|
45038
45696
|
}
|
|
45039
45697
|
function getMagicContextLogPaths(harness, options = {}) {
|
|
45040
45698
|
const override = options.override === undefined ? process.env.MAGIC_CONTEXT_LOG_PATH?.trim() : options.override?.trim();
|
|
45041
|
-
const storageLogs =
|
|
45699
|
+
const storageLogs = join33(options.storageDir ?? getMagicContextStorageDir(), "logs");
|
|
45042
45700
|
return [
|
|
45043
45701
|
...override ? [override] : [],
|
|
45044
|
-
|
|
45045
|
-
|
|
45046
|
-
|
|
45702
|
+
join33(options.tempDir ?? tmpdir3(), harness, "magic-context", "magic-context.log"),
|
|
45703
|
+
join33(storageLogs, `magic-context.${harness}.log`),
|
|
45704
|
+
join33(storageLogs, "magic-context.log")
|
|
45047
45705
|
].filter((path, index, paths) => paths.indexOf(path) === index);
|
|
45048
45706
|
}
|
|
45049
45707
|
function inspectLogFile(path) {
|
|
45050
|
-
if (!
|
|
45708
|
+
if (!existsSync41(path)) {
|
|
45051
45709
|
return { path, exists: false, sizeKb: 0, lineCount: 0, grammar: "unknown" };
|
|
45052
45710
|
}
|
|
45053
45711
|
try {
|
|
45054
|
-
const content =
|
|
45712
|
+
const content = readFileSync23(path, "utf8");
|
|
45055
45713
|
const lines = content.split(/\r?\n/).filter((line) => line.length > 0);
|
|
45056
45714
|
const grammars = new Set(lines.flatMap((line) => {
|
|
45057
45715
|
const parsed = parseLogLine(line);
|
|
@@ -45061,7 +45719,7 @@ function inspectLogFile(path) {
|
|
|
45061
45719
|
return {
|
|
45062
45720
|
path,
|
|
45063
45721
|
exists: true,
|
|
45064
|
-
sizeKb: Math.round(
|
|
45722
|
+
sizeKb: Math.round(statSync21(path).size / 1024),
|
|
45065
45723
|
lineCount: lines.length,
|
|
45066
45724
|
grammar
|
|
45067
45725
|
};
|
|
@@ -45078,7 +45736,7 @@ function readLogLines(files) {
|
|
|
45078
45736
|
return [];
|
|
45079
45737
|
try {
|
|
45080
45738
|
let precedingTimestamp = "";
|
|
45081
|
-
return
|
|
45739
|
+
return readFileSync23(file.path, "utf8").split(/\r?\n/).filter((line) => line.length > 0).map((line, lineIndex) => {
|
|
45082
45740
|
precedingTimestamp = parseLogLine(line)?.ts ?? precedingTimestamp;
|
|
45083
45741
|
return { line, timestamp: precedingTimestamp, fileIndex, lineIndex };
|
|
45084
45742
|
});
|
|
@@ -45273,9 +45931,9 @@ var init_redaction2 = __esm(() => {
|
|
|
45273
45931
|
|
|
45274
45932
|
// src/commands/doctor-omp.ts
|
|
45275
45933
|
import { execFileSync as execFileSync8, spawnSync as spawnSync8 } from "node:child_process";
|
|
45276
|
-
import { existsSync as
|
|
45934
|
+
import { existsSync as existsSync42, readFileSync as readFileSync24 } from "node:fs";
|
|
45277
45935
|
import { createRequire as createRequire3 } from "node:module";
|
|
45278
|
-
import { isAbsolute as isAbsolute8, join as
|
|
45936
|
+
import { isAbsolute as isAbsolute8, join as join34, resolve as resolve17 } from "node:path";
|
|
45279
45937
|
function parseSemver(value) {
|
|
45280
45938
|
const match = value?.match(/(\d+)\.(\d+)\.(\d+)/);
|
|
45281
45939
|
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
|
|
@@ -45317,10 +45975,10 @@ function selfVersion() {
|
|
|
45317
45975
|
return "unknown";
|
|
45318
45976
|
}
|
|
45319
45977
|
function readConfig2(path) {
|
|
45320
|
-
if (!
|
|
45978
|
+
if (!existsSync42(path))
|
|
45321
45979
|
return {};
|
|
45322
45980
|
try {
|
|
45323
|
-
const parsed = import_comment_json8.parse(
|
|
45981
|
+
const parsed = import_comment_json8.parse(readFileSync24(path, "utf-8"));
|
|
45324
45982
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? {} : { error: "top level is not an object" };
|
|
45325
45983
|
} catch (error) {
|
|
45326
45984
|
return { error: error instanceof Error ? error.message : String(error) };
|
|
@@ -45330,7 +45988,7 @@ function pluginDeclaresOmp(path) {
|
|
|
45330
45988
|
if (!path)
|
|
45331
45989
|
return null;
|
|
45332
45990
|
try {
|
|
45333
|
-
const pkg = JSON.parse(
|
|
45991
|
+
const pkg = JSON.parse(readFileSync24(join34(path, "package.json"), "utf-8"));
|
|
45334
45992
|
return Array.isArray(pkg.omp?.extensions) || Array.isArray(pkg.pi?.extensions);
|
|
45335
45993
|
} catch {
|
|
45336
45994
|
return null;
|
|
@@ -45405,8 +46063,8 @@ async function runHealthChecks(options) {
|
|
|
45405
46063
|
if (!reportedAgentDir.ok) {
|
|
45406
46064
|
add(results, "warn", "Could not verify OMP active agent directory");
|
|
45407
46065
|
} else {
|
|
45408
|
-
const reportedPath =
|
|
45409
|
-
const expectedPath =
|
|
46066
|
+
const reportedPath = resolve17(reportedAgentDir.stdout);
|
|
46067
|
+
const expectedPath = resolve17(getOmpAgentDir());
|
|
45410
46068
|
if (reportedPath === expectedPath) {
|
|
45411
46069
|
add(results, "pass", `OMP agent directory resolved to ${getOmpAgentDir()}`);
|
|
45412
46070
|
} else {
|
|
@@ -45417,7 +46075,7 @@ async function runHealthChecks(options) {
|
|
|
45417
46075
|
}
|
|
45418
46076
|
}
|
|
45419
46077
|
const userConfigPath = getOmpUserConfigPath();
|
|
45420
|
-
if (!
|
|
46078
|
+
if (!existsSync42(userConfigPath)) {
|
|
45421
46079
|
add(results, "warn", `No Magic Context user config at ${userConfigPath}`);
|
|
45422
46080
|
repairPlan.writeUserConfig = true;
|
|
45423
46081
|
} else {
|
|
@@ -45434,9 +46092,9 @@ async function runHealthChecks(options) {
|
|
|
45434
46092
|
for (const warning of loaded.warnings.slice(0, 5))
|
|
45435
46093
|
add(results, "warn", warning);
|
|
45436
46094
|
const storage = getMagicContextStorageResolution();
|
|
45437
|
-
const dbPath =
|
|
46095
|
+
const dbPath = join34(storage.path, "context.db");
|
|
45438
46096
|
add(results, "info", `Shared storage: ${storage.path} (source: ${storage.source})`);
|
|
45439
|
-
if (!
|
|
46097
|
+
if (!existsSync42(dbPath))
|
|
45440
46098
|
add(results, "info", `Shared context DB will be created at ${dbPath}`);
|
|
45441
46099
|
else {
|
|
45442
46100
|
let db = null;
|
|
@@ -45501,7 +46159,7 @@ function writeDefaultConfig(path) {
|
|
|
45501
46159
|
}
|
|
45502
46160
|
async function repair(plan, deps, prompts, cwd) {
|
|
45503
46161
|
let fixed = 0;
|
|
45504
|
-
if (plan.writeUserConfig && !
|
|
46162
|
+
if (plan.writeUserConfig && !existsSync42(getOmpUserConfigPath())) {
|
|
45505
46163
|
writeDefaultConfig(getOmpUserConfigPath());
|
|
45506
46164
|
prompts.log.success(`Wrote default Magic Context config to ${getOmpUserConfigPath()}`);
|
|
45507
46165
|
fixed += 1;
|
|
@@ -45617,7 +46275,7 @@ function runGhCommandWithDeps(deps, args) {
|
|
|
45617
46275
|
async function runIssueFlow(options) {
|
|
45618
46276
|
if (options.reportPath) {
|
|
45619
46277
|
const report = await runHealthChecks({ ...options, quiet: true });
|
|
45620
|
-
const path = isAbsolute8(options.reportPath) ? options.reportPath :
|
|
46278
|
+
const path = isAbsolute8(options.reportPath) ? options.reportPath : join34(options.cwd, options.reportPath);
|
|
45621
46279
|
const bundle = writeOmpIssueReport(path, ompIssueBody("Generated non-interactively by `doctor --issue --report`.", report, readLogLines(report.logFiles), null));
|
|
45622
46280
|
options.prompts.log.success(bundle.fullPath ? `Sanitized report written to ${bundle.path}; full report at ${bundle.fullPath}` : `Sanitized report written to ${bundle.path}`);
|
|
45623
46281
|
return 0;
|
|
@@ -45644,7 +46302,7 @@ async function runIssueFlow(options) {
|
|
|
45644
46302
|
]);
|
|
45645
46303
|
sessionFilter = choice === "__all__" ? null : choice;
|
|
45646
46304
|
}
|
|
45647
|
-
const path =
|
|
46305
|
+
const path = join34(options.cwd, `magic-context-omp-issue-${timestamp2(options.deps.now())}.md`);
|
|
45648
46306
|
const bundle = writeOmpIssueReport(path, ompIssueBody(description, report, logLines, sessionFilter));
|
|
45649
46307
|
options.prompts.log.success(bundle.fullPath ? `Sanitized report written to ${bundle.path}; full report at ${bundle.fullPath}` : `Sanitized report written to ${bundle.path}`);
|
|
45650
46308
|
if (await options.prompts.confirm("Submit this issue on GitHub now?", false)) {
|
|
@@ -45831,7 +46489,7 @@ function truncate2(text) {
|
|
|
45831
46489
|
var DEFAULT_TIMEOUT_MS = 1e4, MAX_PREVIEW_CHARS = 240;
|
|
45832
46490
|
|
|
45833
46491
|
// ../plugin/src/features/magic-context/memory/embedding-synapse.ts
|
|
45834
|
-
import { createHash as
|
|
46492
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
45835
46493
|
function toSynapseLaneDescriptor(metadata) {
|
|
45836
46494
|
const tokenBudget = metadata.recommended_token_budget;
|
|
45837
46495
|
return {
|
|
@@ -45971,7 +46629,7 @@ function wait(ms) {
|
|
|
45971
46629
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
45972
46630
|
}
|
|
45973
46631
|
function sha256(value) {
|
|
45974
|
-
return
|
|
46632
|
+
return createHash11("sha256").update(value).digest("hex");
|
|
45975
46633
|
}
|
|
45976
46634
|
function stableJson2(value) {
|
|
45977
46635
|
if (Array.isArray(value))
|
|
@@ -46615,12 +47273,12 @@ function listShadowBackfillStalls(db, projectIdentity) {
|
|
|
46615
47273
|
var SHADOW_BACKFILL_PROVENANCE_KEY = "_magicContextShadowBackfill";
|
|
46616
47274
|
|
|
46617
47275
|
// ../plugin/src/shared/auto-update-provenance.ts
|
|
46618
|
-
import { existsSync as
|
|
47276
|
+
import { existsSync as existsSync43, readFileSync as readFileSync25 } from "node:fs";
|
|
46619
47277
|
function readAutoUpdateCheckState(path) {
|
|
46620
|
-
if (!
|
|
47278
|
+
if (!existsSync43(path))
|
|
46621
47279
|
return null;
|
|
46622
47280
|
try {
|
|
46623
|
-
const value = JSON.parse(
|
|
47281
|
+
const value = JSON.parse(readFileSync25(path, "utf-8"));
|
|
46624
47282
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
46625
47283
|
return null;
|
|
46626
47284
|
const raw = value;
|
|
@@ -46647,15 +47305,15 @@ var init_auto_update_provenance = () => {};
|
|
|
46647
47305
|
|
|
46648
47306
|
// ../plugin/src/shared/tui-config.ts
|
|
46649
47307
|
import {
|
|
46650
|
-
chmodSync as
|
|
46651
|
-
existsSync as
|
|
46652
|
-
mkdirSync as
|
|
46653
|
-
readFileSync as
|
|
46654
|
-
renameSync as
|
|
46655
|
-
statSync as
|
|
46656
|
-
writeFileSync as
|
|
47308
|
+
chmodSync as chmodSync4,
|
|
47309
|
+
existsSync as existsSync44,
|
|
47310
|
+
mkdirSync as mkdirSync7,
|
|
47311
|
+
readFileSync as readFileSync26,
|
|
47312
|
+
renameSync as renameSync8,
|
|
47313
|
+
statSync as statSync22,
|
|
47314
|
+
writeFileSync as writeFileSync7
|
|
46657
47315
|
} from "node:fs";
|
|
46658
|
-
import { dirname as
|
|
47316
|
+
import { dirname as dirname23, join as join35 } from "node:path";
|
|
46659
47317
|
function pluginEntryId(entry) {
|
|
46660
47318
|
if (typeof entry === "string")
|
|
46661
47319
|
return entry;
|
|
@@ -46686,21 +47344,21 @@ function writeTuiConfigAtomic(configPath, config) {
|
|
|
46686
47344
|
const body = `${import_comment_json9.stringify(config, null, 2)}
|
|
46687
47345
|
`;
|
|
46688
47346
|
const tmpPath = `${configPath}.tmp`;
|
|
46689
|
-
|
|
47347
|
+
writeFileSync7(tmpPath, body);
|
|
46690
47348
|
try {
|
|
46691
|
-
if (
|
|
46692
|
-
|
|
47349
|
+
if (statSync22(configPath, { throwIfNoEntry: false })?.isFile()) {
|
|
47350
|
+
chmodSync4(tmpPath, statSync22(configPath).mode & 511);
|
|
46693
47351
|
}
|
|
46694
47352
|
} catch {}
|
|
46695
|
-
|
|
47353
|
+
renameSync8(tmpPath, configPath);
|
|
46696
47354
|
}
|
|
46697
47355
|
function resolveTuiConfigPath(configDirOverride) {
|
|
46698
47356
|
const configDir = configDirOverride ?? getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
|
|
46699
|
-
const jsoncPath =
|
|
46700
|
-
const jsonPath =
|
|
46701
|
-
if (
|
|
47357
|
+
const jsoncPath = join35(configDir, "tui.jsonc");
|
|
47358
|
+
const jsonPath = join35(configDir, "tui.json");
|
|
47359
|
+
if (existsSync44(jsoncPath))
|
|
46702
47360
|
return jsoncPath;
|
|
46703
|
-
if (
|
|
47361
|
+
if (existsSync44(jsonPath))
|
|
46704
47362
|
return jsonPath;
|
|
46705
47363
|
return jsoncPath;
|
|
46706
47364
|
}
|
|
@@ -46708,8 +47366,8 @@ function ensureTuiPluginEntry(options = {}) {
|
|
|
46708
47366
|
try {
|
|
46709
47367
|
const configPath = resolveTuiConfigPath(options.configDir);
|
|
46710
47368
|
let config = {};
|
|
46711
|
-
if (
|
|
46712
|
-
const raw =
|
|
47369
|
+
if (existsSync44(configPath)) {
|
|
47370
|
+
const raw = readFileSync26(configPath, "utf-8");
|
|
46713
47371
|
config = import_comment_json9.parse(raw) ?? {};
|
|
46714
47372
|
}
|
|
46715
47373
|
const plugins = Array.isArray(config.plugin) ? [...config.plugin] : [];
|
|
@@ -46743,7 +47401,7 @@ function ensureTuiPluginEntry(options = {}) {
|
|
|
46743
47401
|
}
|
|
46744
47402
|
}
|
|
46745
47403
|
config.plugin = plugins;
|
|
46746
|
-
|
|
47404
|
+
mkdirSync7(dirname23(configPath), { recursive: true });
|
|
46747
47405
|
writeTuiConfigAtomic(configPath, config);
|
|
46748
47406
|
log(`[magic-context] updated TUI plugin entry in ${configPath}`);
|
|
46749
47407
|
return true;
|
|
@@ -46761,9 +47419,9 @@ var init_tui_config = __esm(() => {
|
|
|
46761
47419
|
});
|
|
46762
47420
|
|
|
46763
47421
|
// src/lib/diagnostics-opencode.ts
|
|
46764
|
-
import { existsSync as
|
|
47422
|
+
import { existsSync as existsSync45, readdirSync as readdirSync9, readFileSync as readFileSync27, statSync as statSync23 } from "node:fs";
|
|
46765
47423
|
import { createRequire as createRequire4 } from "node:module";
|
|
46766
|
-
import { join as
|
|
47424
|
+
import { join as join36 } from "node:path";
|
|
46767
47425
|
function getSelfVersion() {
|
|
46768
47426
|
const require2 = createRequire4(import.meta.url);
|
|
46769
47427
|
for (const relPath of ["../../package.json", "../package.json"]) {
|
|
@@ -46778,7 +47436,7 @@ function getSelfVersion() {
|
|
|
46778
47436
|
}
|
|
46779
47437
|
function readLegacyCachedVersion(root) {
|
|
46780
47438
|
try {
|
|
46781
|
-
const pkg = JSON.parse(
|
|
47439
|
+
const pkg = JSON.parse(readFileSync27(getOpenCodePluginPackageJsonPath(root), "utf-8"));
|
|
46782
47440
|
return typeof pkg.version === "string" ? pkg.version : undefined;
|
|
46783
47441
|
} catch {
|
|
46784
47442
|
return;
|
|
@@ -46787,7 +47445,7 @@ function readLegacyCachedVersion(root) {
|
|
|
46787
47445
|
function collectOpenCodePluginCacheReport(hostGeneration, opencodeConfig) {
|
|
46788
47446
|
const installs = [];
|
|
46789
47447
|
for (const root of getOpenCodePluginCacheRoots()) {
|
|
46790
|
-
if (!
|
|
47448
|
+
if (!existsSync45(root))
|
|
46791
47449
|
continue;
|
|
46792
47450
|
const spec = root.endsWith("@latest") ? "latest" : "(bare)";
|
|
46793
47451
|
installs.push({
|
|
@@ -46821,7 +47479,7 @@ function getStorageResolution() {
|
|
|
46821
47479
|
}
|
|
46822
47480
|
function fileSize(path) {
|
|
46823
47481
|
try {
|
|
46824
|
-
return
|
|
47482
|
+
return existsSync45(path) ? statSync23(path).size : 0;
|
|
46825
47483
|
} catch {
|
|
46826
47484
|
return 0;
|
|
46827
47485
|
}
|
|
@@ -46833,10 +47491,10 @@ function sanitizeValue(value) {
|
|
|
46833
47491
|
return sanitizeConfigValue(value);
|
|
46834
47492
|
}
|
|
46835
47493
|
function readConfig3(path) {
|
|
46836
|
-
if (!
|
|
47494
|
+
if (!existsSync45(path))
|
|
46837
47495
|
return { value: null };
|
|
46838
47496
|
try {
|
|
46839
|
-
const raw =
|
|
47497
|
+
const raw = readFileSync27(path, "utf-8");
|
|
46840
47498
|
const value = import_comment_json10.parse(raw);
|
|
46841
47499
|
return { value };
|
|
46842
47500
|
} catch (error) {
|
|
@@ -46861,7 +47519,7 @@ function configHasPluginEntry(config) {
|
|
|
46861
47519
|
}
|
|
46862
47520
|
function parseHistorianDumpMeta(path) {
|
|
46863
47521
|
try {
|
|
46864
|
-
const xml =
|
|
47522
|
+
const xml = readFileSync27(path, "utf-8");
|
|
46865
47523
|
const parsed = parseCompartmentOutput(xml);
|
|
46866
47524
|
const factCountByCategory = {};
|
|
46867
47525
|
for (const fact of parsed.facts) {
|
|
@@ -46894,11 +47552,11 @@ function parseHistorianDumpMeta(path) {
|
|
|
46894
47552
|
}
|
|
46895
47553
|
}
|
|
46896
47554
|
function listDumpsInDir(dir, limit) {
|
|
46897
|
-
if (!
|
|
47555
|
+
if (!existsSync45(dir))
|
|
46898
47556
|
return { count: 0, recent: [] };
|
|
46899
47557
|
try {
|
|
46900
47558
|
const entries = readdirSync9(dir).filter((name) => name.endsWith(".xml")).map((name) => {
|
|
46901
|
-
const stat =
|
|
47559
|
+
const stat = statSync23(join36(dir, name));
|
|
46902
47560
|
return {
|
|
46903
47561
|
name,
|
|
46904
47562
|
mtime: stat.mtimeMs,
|
|
@@ -46907,7 +47565,7 @@ function listDumpsInDir(dir, limit) {
|
|
|
46907
47565
|
}).sort((a, b) => b.mtime - a.mtime);
|
|
46908
47566
|
const now = Date.now();
|
|
46909
47567
|
const recent = entries.slice(0, limit).map((entry) => {
|
|
46910
|
-
const meta = parseHistorianDumpMeta(
|
|
47568
|
+
const meta = parseHistorianDumpMeta(join36(dir, entry.name));
|
|
46911
47569
|
const summary = {
|
|
46912
47570
|
name: entry.name,
|
|
46913
47571
|
ageMinutes: Math.round((now - entry.mtime) / 60000),
|
|
@@ -47018,7 +47676,7 @@ function collectRecentSessionsFromDatabase(database) {
|
|
|
47018
47676
|
});
|
|
47019
47677
|
}
|
|
47020
47678
|
async function collectDatabaseRows(path, read) {
|
|
47021
|
-
if (!
|
|
47679
|
+
if (!existsSync45(path))
|
|
47022
47680
|
return { available: false, reason: "path missing" };
|
|
47023
47681
|
let backend;
|
|
47024
47682
|
try {
|
|
@@ -47050,7 +47708,7 @@ async function collectRecentSessions(resolution, hostGeneration) {
|
|
|
47050
47708
|
});
|
|
47051
47709
|
}
|
|
47052
47710
|
async function collectHistorianFailures(storageDirPath) {
|
|
47053
|
-
return collectDatabaseRows(
|
|
47711
|
+
return collectDatabaseRows(join36(storageDirPath, "context.db"), (db) => {
|
|
47054
47712
|
const rows = db.prepare("SELECT session_id, historian_failure_count, historian_last_error, historian_last_failure_at FROM session_meta WHERE historian_failure_count > 0 ORDER BY historian_last_failure_at DESC LIMIT 10").all();
|
|
47055
47713
|
return rows.map((row) => {
|
|
47056
47714
|
const sessionId = typeof row.session_id === "string" ? row.session_id : "<unknown>";
|
|
@@ -47063,7 +47721,7 @@ async function collectHistorianFailures(storageDirPath) {
|
|
|
47063
47721
|
});
|
|
47064
47722
|
}
|
|
47065
47723
|
async function collectHistorianRuns(storageDirPath) {
|
|
47066
|
-
return collectDatabaseRows(
|
|
47724
|
+
return collectDatabaseRows(join36(storageDirPath, "context.db"), (db) => {
|
|
47067
47725
|
const aggRows = db.prepare(`SELECT session_id,
|
|
47068
47726
|
COUNT(*) AS total,
|
|
47069
47727
|
SUM(CASE WHEN status='success' THEN 1 ELSE 0 END) AS success,
|
|
@@ -47117,7 +47775,7 @@ async function collectDiagnostics() {
|
|
|
47117
47775
|
const magicContextConfig = readConfig3(configPaths.magicContextConfig);
|
|
47118
47776
|
const storageResolution = getStorageResolution();
|
|
47119
47777
|
const storageDirPath = storageResolution.path;
|
|
47120
|
-
const contextDbPath =
|
|
47778
|
+
const contextDbPath = join36(storageDirPath, "context.db");
|
|
47121
47779
|
let compactionEnabled = false;
|
|
47122
47780
|
try {
|
|
47123
47781
|
compactionEnabled = isCompactionEnabled(loadPluginConfig(process.cwd()));
|
|
@@ -47149,7 +47807,7 @@ async function collectDiagnostics() {
|
|
|
47149
47807
|
opencodeConfigHasPlugin: configHasPluginEntry(opencodeConfig.value),
|
|
47150
47808
|
tuiConfigHasPlugin: configHasPluginEntry(tuiConfig.value),
|
|
47151
47809
|
magicContextConfig: {
|
|
47152
|
-
exists:
|
|
47810
|
+
exists: existsSync45(configPaths.magicContextConfig),
|
|
47153
47811
|
...magicContextConfig.error ? { parseError: magicContextConfig.error } : {},
|
|
47154
47812
|
flags: sanitizeValue(magicContextConfig.value ?? {}) ?? {}
|
|
47155
47813
|
},
|
|
@@ -47157,7 +47815,7 @@ async function collectDiagnostics() {
|
|
|
47157
47815
|
storageDir: {
|
|
47158
47816
|
path: storageDirPath,
|
|
47159
47817
|
source: storageResolution.source,
|
|
47160
|
-
exists:
|
|
47818
|
+
exists: existsSync45(storageDirPath),
|
|
47161
47819
|
contextDbSizeBytes: fileSize(contextDbPath)
|
|
47162
47820
|
},
|
|
47163
47821
|
openCodeDatabase: {
|
|
@@ -47407,9 +48065,9 @@ var init_embedding_local = __esm(() => {
|
|
|
47407
48065
|
|
|
47408
48066
|
// src/lib/embedding-runtime.ts
|
|
47409
48067
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
47410
|
-
import { existsSync as
|
|
48068
|
+
import { existsSync as existsSync46, readFileSync as readFileSync28 } from "node:fs";
|
|
47411
48069
|
import { createRequire as createRequire5 } from "node:module";
|
|
47412
|
-
import { dirname as
|
|
48070
|
+
import { dirname as dirname24, join as join37, sep } from "node:path";
|
|
47413
48071
|
function describeError(error) {
|
|
47414
48072
|
const message = error instanceof Error ? error.message : String(error ?? "unknown error");
|
|
47415
48073
|
const code = error?.code;
|
|
@@ -47551,11 +48209,11 @@ function expectedBinaryRelPath(platform, arch) {
|
|
|
47551
48209
|
const supportedArch = arch === "x64" || arch === "arm64";
|
|
47552
48210
|
if (!supportedPlatform || !supportedArch)
|
|
47553
48211
|
return null;
|
|
47554
|
-
return
|
|
48212
|
+
return join37("bin", "napi-v6", platform, arch, "onnxruntime_binding.node");
|
|
47555
48213
|
}
|
|
47556
48214
|
function onnxRuntimeNodeVersion(packageDir) {
|
|
47557
48215
|
try {
|
|
47558
|
-
const parsed = JSON.parse(
|
|
48216
|
+
const parsed = JSON.parse(readFileSync28(join37(packageDir, "package.json"), "utf8"));
|
|
47559
48217
|
return typeof parsed.version === "string" ? parsed.version : undefined;
|
|
47560
48218
|
} catch {
|
|
47561
48219
|
return;
|
|
@@ -47604,7 +48262,7 @@ function formatLocalEmbeddingRuntimeWasmSelected(status) {
|
|
|
47604
48262
|
function requireNodeWasmBundle(probe, candidates) {
|
|
47605
48263
|
if (probe.state === "failed")
|
|
47606
48264
|
return probe;
|
|
47607
|
-
const bundlePath = candidates.find((candidate) =>
|
|
48265
|
+
const bundlePath = candidates.find((candidate) => existsSync46(candidate));
|
|
47608
48266
|
return bundlePath ? probe : {
|
|
47609
48267
|
state: "failed",
|
|
47610
48268
|
reason: `functional Node WASM Transformers bundle is missing (checked ${candidates.join(", ")})`
|
|
@@ -47612,13 +48270,13 @@ function requireNodeWasmBundle(probe, candidates) {
|
|
|
47612
48270
|
}
|
|
47613
48271
|
function nodeWasmBundleCandidates(installRoot) {
|
|
47614
48272
|
return [
|
|
47615
|
-
|
|
47616
|
-
|
|
47617
|
-
|
|
48273
|
+
join37(installRoot, "dist", "transformers-node-wasm.js"),
|
|
48274
|
+
join37(installRoot, "node_modules", "@cortexkit", "opencode-magic-context", "dist", "transformers-node-wasm.js"),
|
|
48275
|
+
join37(installRoot, "node_modules", "@cortexkit", "pi-magic-context", "dist", "transformers-node-wasm.js")
|
|
47618
48276
|
];
|
|
47619
48277
|
}
|
|
47620
48278
|
function probeWasmRuntimeAt(installRoot) {
|
|
47621
|
-
const requireFn = createRequire5(
|
|
48279
|
+
const requireFn = createRequire5(join37(installRoot, "package.json"));
|
|
47622
48280
|
return requireNodeWasmBundle(probeWasmRuntimeFromRequire(requireFn), nodeWasmBundleCandidates(installRoot));
|
|
47623
48281
|
}
|
|
47624
48282
|
function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform, arch = process.arch, runtimePreference = "auto", host) {
|
|
@@ -47627,9 +48285,9 @@ function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform,
|
|
|
47627
48285
|
const wasm = probeWasmRuntimeAt(installRoot);
|
|
47628
48286
|
return wasm.state === "ok" ? { state: "wasm-selected", wasmPath: wasm.wasmPath } : { state: "wasm-broken", wasmReason: wasm.reason };
|
|
47629
48287
|
}
|
|
47630
|
-
const packageDir =
|
|
48288
|
+
const packageDir = join37(installRoot, "node_modules", "onnxruntime-node");
|
|
47631
48289
|
let native;
|
|
47632
|
-
if (!
|
|
48290
|
+
if (!existsSync46(join37(packageDir, "package.json"))) {
|
|
47633
48291
|
native = { state: "package-missing", packageDir };
|
|
47634
48292
|
} else {
|
|
47635
48293
|
const rel = expectedBinaryRelPath(platform, arch);
|
|
@@ -47639,8 +48297,8 @@ function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform,
|
|
|
47639
48297
|
binaryPath: packageDir
|
|
47640
48298
|
};
|
|
47641
48299
|
} else {
|
|
47642
|
-
const binaryPath =
|
|
47643
|
-
native =
|
|
48300
|
+
const binaryPath = join37(packageDir, rel);
|
|
48301
|
+
native = existsSync46(binaryPath) ? probeOnnxRuntimeNodeLoad(packageDir) ?? { state: "ok", binaryPath } : {
|
|
47644
48302
|
state: "binary-missing",
|
|
47645
48303
|
packageDir,
|
|
47646
48304
|
expectedBinary: binaryPath,
|
|
@@ -47651,7 +48309,7 @@ function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform,
|
|
|
47651
48309
|
return withWasmFallback(native, () => probeWasmRuntimeAt(installRoot));
|
|
47652
48310
|
}
|
|
47653
48311
|
function checkLocalEmbeddingRuntime(installRoots, platform = process.platform, arch = process.arch, runtimePreference = "auto", host) {
|
|
47654
|
-
const existing = installRoots.filter((root) =>
|
|
48312
|
+
const existing = installRoots.filter((root) => existsSync46(root));
|
|
47655
48313
|
if (existing.length === 0) {
|
|
47656
48314
|
return {
|
|
47657
48315
|
state: "unknown",
|
|
@@ -47677,19 +48335,19 @@ function checkLocalEmbeddingRuntime(installRoots, platform = process.platform, a
|
|
|
47677
48335
|
function packageDirFromResolved(resolvedPath, packageName) {
|
|
47678
48336
|
const marker = `node_modules${sep}${packageName.split("/").join(sep)}`;
|
|
47679
48337
|
const idx = resolvedPath.indexOf(marker);
|
|
47680
|
-
return idx >= 0 ? resolvedPath.slice(0, idx + marker.length) :
|
|
48338
|
+
return idx >= 0 ? resolvedPath.slice(0, idx + marker.length) : dirname24(resolvedPath);
|
|
47681
48339
|
}
|
|
47682
48340
|
function probeWasmRuntimeByResolution(pluginDir) {
|
|
47683
48341
|
try {
|
|
47684
|
-
const reqPlugin = createRequire5(
|
|
48342
|
+
const reqPlugin = createRequire5(join37(pluginDir, "package.json"));
|
|
47685
48343
|
const direct = probeWasmRuntimeFromRequire(reqPlugin);
|
|
47686
48344
|
let probe = direct;
|
|
47687
48345
|
if (direct.state === "failed" && direct.reason.startsWith("onnxruntime-web is not resolvable")) {
|
|
47688
48346
|
const tfResolved = reqPlugin.resolve("@huggingface/transformers");
|
|
47689
48347
|
const tfDir = packageDirFromResolved(tfResolved, "@huggingface/transformers");
|
|
47690
|
-
probe = probeWasmRuntimeFromRequire(createRequire5(
|
|
48348
|
+
probe = probeWasmRuntimeFromRequire(createRequire5(join37(tfDir, "package.json")));
|
|
47691
48349
|
}
|
|
47692
|
-
return requireNodeWasmBundle(probe, [
|
|
48350
|
+
return requireNodeWasmBundle(probe, [join37(pluginDir, "dist", "transformers-node-wasm.js")]);
|
|
47693
48351
|
} catch (error) {
|
|
47694
48352
|
return {
|
|
47695
48353
|
state: "failed",
|
|
@@ -47698,7 +48356,7 @@ function probeWasmRuntimeByResolution(pluginDir) {
|
|
|
47698
48356
|
}
|
|
47699
48357
|
}
|
|
47700
48358
|
function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.platform, arch = process.arch, runtimePreference = "auto", host) {
|
|
47701
|
-
if (!
|
|
48359
|
+
if (!existsSync46(join37(pluginDir, "package.json"))) {
|
|
47702
48360
|
return { state: "unknown", reason: "plugin package dir not found" };
|
|
47703
48361
|
}
|
|
47704
48362
|
const selectedRuntime = resolveLocalEmbeddingWorkerRuntime(runtimePreference, host);
|
|
@@ -47709,13 +48367,13 @@ function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.pl
|
|
|
47709
48367
|
let onnxDir = null;
|
|
47710
48368
|
let resolveError;
|
|
47711
48369
|
try {
|
|
47712
|
-
const reqPlugin = createRequire5(
|
|
48370
|
+
const reqPlugin = createRequire5(join37(pluginDir, "package.json"));
|
|
47713
48371
|
try {
|
|
47714
48372
|
onnxDir = packageDirFromResolved(reqPlugin.resolve("onnxruntime-node"), "onnxruntime-node");
|
|
47715
48373
|
} catch {
|
|
47716
48374
|
const tfResolved = reqPlugin.resolve("@huggingface/transformers");
|
|
47717
48375
|
const tfDir = packageDirFromResolved(tfResolved, "@huggingface/transformers");
|
|
47718
|
-
const reqTf = createRequire5(
|
|
48376
|
+
const reqTf = createRequire5(join37(tfDir, "package.json"));
|
|
47719
48377
|
onnxDir = packageDirFromResolved(reqTf.resolve("onnxruntime-node"), "onnxruntime-node");
|
|
47720
48378
|
}
|
|
47721
48379
|
} catch (error) {
|
|
@@ -47723,7 +48381,7 @@ function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.pl
|
|
|
47723
48381
|
if (resolveError === "ERR_MODULE_NOT_FOUND" || resolveError === "MODULE_NOT_FOUND") {
|
|
47724
48382
|
return withWasmFallback({
|
|
47725
48383
|
state: "package-missing",
|
|
47726
|
-
packageDir:
|
|
48384
|
+
packageDir: join37(pluginDir, "node_modules", "onnxruntime-node")
|
|
47727
48385
|
}, () => probeWasmRuntimeByResolution(pluginDir));
|
|
47728
48386
|
}
|
|
47729
48387
|
return {
|
|
@@ -47739,8 +48397,8 @@ function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.pl
|
|
|
47739
48397
|
if (rel === null) {
|
|
47740
48398
|
native = probeOnnxRuntimeNodeLoad(onnxDir) ?? { state: "ok", binaryPath: onnxDir };
|
|
47741
48399
|
} else {
|
|
47742
|
-
const binaryPath =
|
|
47743
|
-
native =
|
|
48400
|
+
const binaryPath = join37(onnxDir, rel);
|
|
48401
|
+
native = existsSync46(binaryPath) ? probeOnnxRuntimeNodeLoad(onnxDir) ?? { state: "ok", binaryPath } : {
|
|
47744
48402
|
state: "binary-missing",
|
|
47745
48403
|
packageDir: onnxDir,
|
|
47746
48404
|
expectedBinary: binaryPath,
|
|
@@ -47775,8 +48433,8 @@ var init_embedding_runtime = __esm(() => {
|
|
|
47775
48433
|
});
|
|
47776
48434
|
|
|
47777
48435
|
// src/lib/logs-opencode.ts
|
|
47778
|
-
import { mkdirSync as
|
|
47779
|
-
import { dirname as
|
|
48436
|
+
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync8 } from "node:fs";
|
|
48437
|
+
import { dirname as dirname25, join as join38 } from "node:path";
|
|
47780
48438
|
function sanitizeLogContent(content) {
|
|
47781
48439
|
return sanitizeDiagnosticText(content);
|
|
47782
48440
|
}
|
|
@@ -47869,13 +48527,13 @@ async function bundleIssueReport(report, description, title, sessionFilter = nul
|
|
|
47869
48527
|
const bodyMarkdown = capBodyToGithubLimit(rawBodyMarkdown);
|
|
47870
48528
|
const truncated = bodyMarkdown !== rawBodyMarkdown;
|
|
47871
48529
|
const timestamp = formatTimestamp(new Date);
|
|
47872
|
-
const path = options.outputPath ??
|
|
47873
|
-
|
|
47874
|
-
|
|
48530
|
+
const path = options.outputPath ?? join38(process.cwd(), `magic-context-issue-${timestamp}.md`);
|
|
48531
|
+
mkdirSync8(dirname25(path), { recursive: true });
|
|
48532
|
+
writeFileSync8(path, `${bodyMarkdown}
|
|
47875
48533
|
`);
|
|
47876
|
-
const fullPath = truncated ? options.outputPath ? `${options.outputPath}.full.md` :
|
|
48534
|
+
const fullPath = truncated ? options.outputPath ? `${options.outputPath}.full.md` : join38(process.cwd(), `magic-context-issue-${timestamp}-full.md`) : undefined;
|
|
47877
48535
|
if (fullPath)
|
|
47878
|
-
|
|
48536
|
+
writeFileSync8(fullPath, `${rawBodyMarkdown}
|
|
47879
48537
|
`);
|
|
47880
48538
|
return { path, bodyMarkdown, ...fullPath ? { fullPath } : {}, truncated };
|
|
47881
48539
|
}
|
|
@@ -48686,10 +49344,10 @@ function removeDeprecatedReasoningAge(config) {
|
|
|
48686
49344
|
|
|
48687
49345
|
// src/commands/doctor-opencode.ts
|
|
48688
49346
|
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
48689
|
-
import { existsSync as
|
|
49347
|
+
import { existsSync as existsSync47, mkdtempSync as mkdtempSync4, readFileSync as readFileSync29, rmSync as rmSync9 } from "node:fs";
|
|
48690
49348
|
import { createRequire as createRequire6 } from "node:module";
|
|
48691
|
-
import { homedir as
|
|
48692
|
-
import { dirname as
|
|
49349
|
+
import { homedir as homedir21, tmpdir as tmpdir4 } from "node:os";
|
|
49350
|
+
import { dirname as dirname26, join as join39, resolve as resolve18 } from "node:path";
|
|
48693
49351
|
function formatSharedDbRowCounts(db) {
|
|
48694
49352
|
return SHARED_DB_ROW_COUNT_TABLES.map((table) => {
|
|
48695
49353
|
try {
|
|
@@ -48758,7 +49416,7 @@ function checkConfiguredVariantCatalog(config, hostGeneration, warn, run = (args
|
|
|
48758
49416
|
}
|
|
48759
49417
|
if (models.length === 0)
|
|
48760
49418
|
return;
|
|
48761
|
-
const tempRoot =
|
|
49419
|
+
const tempRoot = mkdtempSync4(join39(tmpdir4(), "magic-context-opencode-catalog-"));
|
|
48762
49420
|
try {
|
|
48763
49421
|
const command = hostGeneration === "v2" ? ["api", "model.list", "--param", `directory=${projectDir}`] : ["models", "--verbose"];
|
|
48764
49422
|
const guidance = `opencode ${command.join(" ")}`;
|
|
@@ -48777,7 +49435,7 @@ function checkConfiguredVariantCatalog(config, hostGeneration, warn, run = (args
|
|
|
48777
49435
|
warn(`${entry.agent} model ${entry.model} requests variant '${entry.variant}', which this host does not offer. Remove the variant or choose one listed by ${guidance}.`);
|
|
48778
49436
|
}
|
|
48779
49437
|
} finally {
|
|
48780
|
-
|
|
49438
|
+
rmSync9(tempRoot, { recursive: true, force: true });
|
|
48781
49439
|
}
|
|
48782
49440
|
}
|
|
48783
49441
|
function parseOpenCodeV2ModelCatalog(output) {
|
|
@@ -48934,7 +49592,7 @@ function getSelfVersion2() {
|
|
|
48934
49592
|
function describeAutoUpdateStall(specifier, autoUpdateEnabled, storageDir = getMagicContextStorageDir()) {
|
|
48935
49593
|
if (!autoUpdateEnabled || !isPinnedOpenCodePluginSpecifier(specifier))
|
|
48936
49594
|
return null;
|
|
48937
|
-
const state = readAutoUpdateCheckState(
|
|
49595
|
+
const state = readAutoUpdateCheckState(join39(storageDir, AUTO_UPDATE_CHECK_STATE_FILENAME));
|
|
48938
49596
|
const owner = isUpdaterPinnedSpec(state, specifier) ? "updater" : "you";
|
|
48939
49597
|
return `auto-update: stalled — config pinned to ${specifier} (by ${owner})`;
|
|
48940
49598
|
}
|
|
@@ -48943,15 +49601,15 @@ function getUserNpmrcPath() {
|
|
|
48943
49601
|
if (custom)
|
|
48944
49602
|
return custom;
|
|
48945
49603
|
const home = process.env.HOME?.trim();
|
|
48946
|
-
return
|
|
49604
|
+
return join39(home || homedir21(), ".npmrc");
|
|
48947
49605
|
}
|
|
48948
49606
|
function collectNpmReleaseAgeWarnings() {
|
|
48949
49607
|
const ageWarnings = [];
|
|
48950
49608
|
const npmrcPath = getUserNpmrcPath();
|
|
48951
|
-
if (!
|
|
49609
|
+
if (!existsSync47(npmrcPath))
|
|
48952
49610
|
return ageWarnings;
|
|
48953
49611
|
try {
|
|
48954
|
-
const npmrc =
|
|
49612
|
+
const npmrc = readFileSync29(npmrcPath, "utf-8");
|
|
48955
49613
|
for (const line of npmrc.split(`
|
|
48956
49614
|
`)) {
|
|
48957
49615
|
const trimmed = line.trim();
|
|
@@ -48965,7 +49623,7 @@ function collectNpmReleaseAgeWarnings() {
|
|
|
48965
49623
|
} catch {}
|
|
48966
49624
|
return ageWarnings;
|
|
48967
49625
|
}
|
|
48968
|
-
function
|
|
49626
|
+
function compareVersions2(a, b) {
|
|
48969
49627
|
return compareSemverPrecedence(a, b);
|
|
48970
49628
|
}
|
|
48971
49629
|
function openBrowser(url) {
|
|
@@ -48992,7 +49650,7 @@ async function runIssueFlow2(options = {}, deps = { collectDiagnostics }) {
|
|
|
48992
49650
|
if (options.reportPath) {
|
|
48993
49651
|
try {
|
|
48994
49652
|
const report = await deps.collectDiagnostics();
|
|
48995
|
-
const bundled = await bundleIssueReport(report, "Generated non-interactively by `doctor --issue --report`.", "Magic Context diagnostic report", null, { outputPath:
|
|
49653
|
+
const bundled = await bundleIssueReport(report, "Generated non-interactively by `doctor --issue --report`.", "Magic Context diagnostic report", null, { outputPath: resolve18(process.cwd(), options.reportPath) });
|
|
48996
49654
|
log3.info(bundled.fullPath ? `Report written to ${bundled.path}; full bundle at ${bundled.fullPath}` : `Report written to ${bundled.path}`);
|
|
48997
49655
|
return 0;
|
|
48998
49656
|
} catch (error) {
|
|
@@ -49086,7 +49744,7 @@ function checkLocalEmbeddingRuntimeForDoctor(runtimePreference = "auto") {
|
|
|
49086
49744
|
return { issues: 0 };
|
|
49087
49745
|
}
|
|
49088
49746
|
async function checkEmbeddingConfig(magicContextConfigPath) {
|
|
49089
|
-
if (!
|
|
49747
|
+
if (!existsSync47(magicContextConfigPath)) {
|
|
49090
49748
|
return checkLocalEmbeddingRuntimeForDoctor();
|
|
49091
49749
|
}
|
|
49092
49750
|
let rawText;
|
|
@@ -49244,7 +49902,7 @@ function getOpenCodePluginHostStatus(hostLabel, hostVersion, installed) {
|
|
|
49244
49902
|
message: `${hostLabel} found; Magic Context is not installed there (run setup to add it)`
|
|
49245
49903
|
};
|
|
49246
49904
|
}
|
|
49247
|
-
if (openCodeHostGenerationFromVersion(hostVersion) === "v2" &&
|
|
49905
|
+
if (openCodeHostGenerationFromVersion(hostVersion) === "v2" && compareVersions2(hostVersion, "2.0.22") === -1) {
|
|
49248
49906
|
return {
|
|
49249
49907
|
status: "fail",
|
|
49250
49908
|
message: describeOpenCode2SessionAPIRequirement(hostVersion)
|
|
@@ -49261,7 +49919,7 @@ async function runDoctor2(options = {}) {
|
|
|
49261
49919
|
const v22Result = await runV22BackfillCommands({
|
|
49262
49920
|
name: "OpenCode",
|
|
49263
49921
|
openDatabase: (readonly = true) => {
|
|
49264
|
-
const dbPath =
|
|
49922
|
+
const dbPath = join39(getMagicContextStorageDir(), "context.db");
|
|
49265
49923
|
v22Db = readonly ? openExistingContextDatabase(dbPath, { readonly: true }) : openExistingContextDatabaseForMutation(dbPath);
|
|
49266
49924
|
return v22Db;
|
|
49267
49925
|
},
|
|
@@ -49293,7 +49951,7 @@ async function runDoctor2(options = {}) {
|
|
|
49293
49951
|
failCount++;
|
|
49294
49952
|
issues++;
|
|
49295
49953
|
};
|
|
49296
|
-
const authorityDbPath =
|
|
49954
|
+
const authorityDbPath = join39(getMagicContextStorageDir(), "context.db");
|
|
49297
49955
|
let authorityDb = null;
|
|
49298
49956
|
try {
|
|
49299
49957
|
authorityDb = openExistingContextDatabase(authorityDbPath, { readonly: true });
|
|
@@ -49332,8 +49990,8 @@ async function runDoctor2(options = {}) {
|
|
|
49332
49990
|
let magicContextStatusKnown = paths.opencodeConfigFormat === "none";
|
|
49333
49991
|
if (!magicContextStatusKnown) {
|
|
49334
49992
|
try {
|
|
49335
|
-
const config = import_comment_json11.parse(
|
|
49336
|
-
magicContextInstalled = isOpenCodePluginRegistered(config,
|
|
49993
|
+
const config = import_comment_json11.parse(readFileSync29(paths.opencodeConfig, "utf-8"));
|
|
49994
|
+
magicContextInstalled = isOpenCodePluginRegistered(config, dirname26(paths.opencodeConfig));
|
|
49337
49995
|
magicContextStatusKnown = true;
|
|
49338
49996
|
} catch {}
|
|
49339
49997
|
}
|
|
@@ -49452,7 +50110,7 @@ async function runDoctor2(options = {}) {
|
|
|
49452
50110
|
}
|
|
49453
50111
|
const selfVersion = getSelfVersion2();
|
|
49454
50112
|
const npmLatest = await fetchNpmLatest(CLI_PACKAGE_NAME);
|
|
49455
|
-
const cliComparison = npmLatest ?
|
|
50113
|
+
const cliComparison = npmLatest ? compareVersions2(selfVersion, npmLatest) : null;
|
|
49456
50114
|
if (!npmLatest) {
|
|
49457
50115
|
log3.info(`Magic Context CLI v${selfVersion}; npm latest check unavailable`);
|
|
49458
50116
|
} else if (cliComparison === null) {
|
|
@@ -49468,7 +50126,7 @@ async function runDoctor2(options = {}) {
|
|
|
49468
50126
|
pass(`OpenCode config: ${paths.opencodeConfig}`);
|
|
49469
50127
|
}
|
|
49470
50128
|
let autoUpdateEnabled = true;
|
|
49471
|
-
if (
|
|
50129
|
+
if (existsSync47(paths.magicContextConfig)) {
|
|
49472
50130
|
pass(`Magic Context config: ${paths.magicContextConfig}`);
|
|
49473
50131
|
try {
|
|
49474
50132
|
const raw = loadRawConfigFile({ configPath: paths.magicContextConfig, tier: "user" });
|
|
@@ -49504,7 +50162,7 @@ async function runDoctor2(options = {}) {
|
|
|
49504
50162
|
warn(`No magic-context.jsonc found — using defaults`);
|
|
49505
50163
|
log3.info(" Run 'setup' to create one with model recommendations");
|
|
49506
50164
|
}
|
|
49507
|
-
if (
|
|
50165
|
+
if (existsSync47(paths.magicContextConfig)) {
|
|
49508
50166
|
try {
|
|
49509
50167
|
const raw = loadRawConfigFile({ configPath: paths.magicContextConfig, tier: "user" });
|
|
49510
50168
|
if (!raw)
|
|
@@ -49644,10 +50302,10 @@ async function runDoctor2(options = {}) {
|
|
|
49644
50302
|
};
|
|
49645
50303
|
if (paths.opencodeConfigFormat !== "none") {
|
|
49646
50304
|
try {
|
|
49647
|
-
const raw =
|
|
50305
|
+
const raw = readFileSync29(paths.opencodeConfig, "utf-8");
|
|
49648
50306
|
const config = import_comment_json11.parse(raw);
|
|
49649
50307
|
const configName = paths.opencodeConfigFormat === "jsonc" ? "opencode.jsonc" : "opencode.json";
|
|
49650
|
-
const configDir =
|
|
50308
|
+
const configDir = dirname26(paths.opencodeConfig);
|
|
49651
50309
|
magicContextInstalled = isOpenCodePluginRegistered(config, configDir);
|
|
49652
50310
|
magicContextStatusKnown = true;
|
|
49653
50311
|
if (magicContextInstalled) {
|
|
@@ -49737,11 +50395,11 @@ async function runDoctor2(options = {}) {
|
|
|
49737
50395
|
pass("Added TUI sidebar plugin to tui.json");
|
|
49738
50396
|
warn("Restart OpenCode to see the sidebar");
|
|
49739
50397
|
fixed++;
|
|
49740
|
-
} else if (
|
|
50398
|
+
} else if (existsSync47(paths.tuiConfig)) {
|
|
49741
50399
|
try {
|
|
49742
|
-
const tuiRaw =
|
|
50400
|
+
const tuiRaw = readFileSync29(paths.tuiConfig, "utf-8");
|
|
49743
50401
|
const tuiConfig = import_comment_json11.parse(tuiRaw);
|
|
49744
|
-
const tuiConfigDir =
|
|
50402
|
+
const tuiConfigDir = dirname26(paths.tuiConfig);
|
|
49745
50403
|
const tuiRawPlugins = Array.isArray(tuiConfig?.plugin) ? tuiConfig.plugin : [];
|
|
49746
50404
|
const tuiIdx = tuiRawPlugins.findIndex((entry) => matchesPluginEntry(entry, OPENCODE_PLUGIN_NAME) || isDevPathPluginEntry(entry, tuiConfigDir));
|
|
49747
50405
|
if (tuiRawPlugins.some((entry) => isLocalPathPluginEntry(entry) && String(entry).includes("magic-context") && !isDevPathPluginEntry(entry, tuiConfigDir))) {
|
|
@@ -49778,7 +50436,7 @@ async function runDoctor2(options = {}) {
|
|
|
49778
50436
|
fail("Could not create or verify the TUI sidebar config");
|
|
49779
50437
|
}
|
|
49780
50438
|
}
|
|
49781
|
-
if (
|
|
50439
|
+
if (existsSync47(paths.magicContextConfig)) {
|
|
49782
50440
|
try {
|
|
49783
50441
|
const raw = loadRawConfigFile({ configPath: paths.magicContextConfig, tier: "user" });
|
|
49784
50442
|
if (!raw)
|
|
@@ -49800,9 +50458,9 @@ async function runDoctor2(options = {}) {
|
|
|
49800
50458
|
else
|
|
49801
50459
|
passCount++;
|
|
49802
50460
|
const storage = getMagicContextStorageResolution();
|
|
49803
|
-
const dbPath =
|
|
50461
|
+
const dbPath = join39(storage.path, "context.db");
|
|
49804
50462
|
log3.info(`Shared storage: ${storage.path} (source: ${storage.source})`);
|
|
49805
|
-
if (!
|
|
50463
|
+
if (!existsSync47(dbPath)) {
|
|
49806
50464
|
log3.info(`Shared context DB not yet created at ${dbPath} (will be created on first run)`);
|
|
49807
50465
|
} else {
|
|
49808
50466
|
log3.info(`Shared context DB exists at ${dbPath}`);
|
|
@@ -49885,7 +50543,7 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
|
|
|
49885
50543
|
let pluginConfigUse;
|
|
49886
50544
|
if (paths.opencodeConfigFormat !== "none") {
|
|
49887
50545
|
try {
|
|
49888
|
-
pluginConfigUse = readOpenCodePluginConfigUse(import_comment_json11.parse(
|
|
50546
|
+
pluginConfigUse = readOpenCodePluginConfigUse(import_comment_json11.parse(readFileSync29(paths.opencodeConfig, "utf-8")), dirname26(paths.opencodeConfig));
|
|
49889
50547
|
} catch {}
|
|
49890
50548
|
}
|
|
49891
50549
|
const cacheResult = await clearPluginCache({
|
|
@@ -49937,7 +50595,7 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
|
|
|
49937
50595
|
let v2DistTag;
|
|
49938
50596
|
if (paths.opencodeConfigFormat !== "none") {
|
|
49939
50597
|
try {
|
|
49940
|
-
v2DistTag = configuredOpenCodeV2DistTag(import_comment_json11.parse(
|
|
50598
|
+
v2DistTag = configuredOpenCodeV2DistTag(import_comment_json11.parse(readFileSync29(paths.opencodeConfig, "utf-8")));
|
|
49941
50599
|
} catch {}
|
|
49942
50600
|
}
|
|
49943
50601
|
const v2Cache = reportOpenCodeV2PluginCache(checkOpenCodeV2PluginCache({
|
|
@@ -50318,9 +50976,9 @@ var init_model_chain_health = __esm(() => {
|
|
|
50318
50976
|
});
|
|
50319
50977
|
|
|
50320
50978
|
// src/lib/diagnostics-pi.ts
|
|
50321
|
-
import { existsSync as
|
|
50979
|
+
import { existsSync as existsSync48, readdirSync as readdirSync10, readFileSync as readFileSync30, statSync as statSync24 } from "node:fs";
|
|
50322
50980
|
import { createRequire as createRequire7 } from "node:module";
|
|
50323
|
-
import { join as
|
|
50981
|
+
import { join as join40 } from "node:path";
|
|
50324
50982
|
function getSelfVersion3() {
|
|
50325
50983
|
const req = createRequire7(import.meta.url);
|
|
50326
50984
|
for (const relPath of ["../../package.json", "../package.json"]) {
|
|
@@ -50335,7 +50993,7 @@ function getSelfVersion3() {
|
|
|
50335
50993
|
}
|
|
50336
50994
|
function fileSize2(path) {
|
|
50337
50995
|
try {
|
|
50338
|
-
return
|
|
50996
|
+
return existsSync48(path) ? statSync24(path).size : 0;
|
|
50339
50997
|
} catch {
|
|
50340
50998
|
return 0;
|
|
50341
50999
|
}
|
|
@@ -50347,11 +51005,11 @@ function sanitizeValue2(value) {
|
|
|
50347
51005
|
return sanitizeConfigValue(value);
|
|
50348
51006
|
}
|
|
50349
51007
|
function readJsonc(path) {
|
|
50350
|
-
if (!
|
|
51008
|
+
if (!existsSync48(path))
|
|
50351
51009
|
return { value: {} };
|
|
50352
51010
|
try {
|
|
50353
51011
|
return {
|
|
50354
|
-
value: import_comment_json12.parse(
|
|
51012
|
+
value: import_comment_json12.parse(readFileSync30(path, "utf-8"))
|
|
50355
51013
|
};
|
|
50356
51014
|
} catch (error) {
|
|
50357
51015
|
return {
|
|
@@ -50367,7 +51025,7 @@ function readConfigDiagnostic(path) {
|
|
|
50367
51025
|
const parsed = readJsonc(path);
|
|
50368
51026
|
return {
|
|
50369
51027
|
path,
|
|
50370
|
-
exists:
|
|
51028
|
+
exists: existsSync48(path),
|
|
50371
51029
|
...parsed.parseError ? { parseError: parsed.parseError } : {},
|
|
50372
51030
|
flags: sanitizeValue2(parsed.value)
|
|
50373
51031
|
};
|
|
@@ -50385,7 +51043,7 @@ function reverseSlugToDirectory(slug) {
|
|
|
50385
51043
|
}
|
|
50386
51044
|
function collectPiRecentSessions() {
|
|
50387
51045
|
const sessionsRoot = getPiSessionsRoot();
|
|
50388
|
-
if (!
|
|
51046
|
+
if (!existsSync48(sessionsRoot))
|
|
50389
51047
|
return [];
|
|
50390
51048
|
try {
|
|
50391
51049
|
const slugs = readdirSync10(sessionsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
@@ -50394,7 +51052,7 @@ function collectPiRecentSessions() {
|
|
|
50394
51052
|
const directory = reverseSlugToDirectory(slug);
|
|
50395
51053
|
if (!directory)
|
|
50396
51054
|
continue;
|
|
50397
|
-
const slugDir =
|
|
51055
|
+
const slugDir = join40(sessionsRoot, slug);
|
|
50398
51056
|
let files;
|
|
50399
51057
|
try {
|
|
50400
51058
|
files = readdirSync10(slugDir).filter((name) => name.endsWith(".jsonl"));
|
|
@@ -50403,7 +51061,7 @@ function collectPiRecentSessions() {
|
|
|
50403
51061
|
}
|
|
50404
51062
|
for (const file of files) {
|
|
50405
51063
|
try {
|
|
50406
|
-
const mtime =
|
|
51064
|
+
const mtime = statSync24(join40(slugDir, file)).mtimeMs;
|
|
50407
51065
|
const sessionId = file.replace(/\.jsonl$/, "");
|
|
50408
51066
|
candidates.push({ sessionId, directory, mtime });
|
|
50409
51067
|
} catch {}
|
|
@@ -50421,7 +51079,7 @@ function collectPiRecentSessions() {
|
|
|
50421
51079
|
}
|
|
50422
51080
|
function parseHistorianDumpMeta2(path) {
|
|
50423
51081
|
try {
|
|
50424
|
-
const xml =
|
|
51082
|
+
const xml = readFileSync30(path, "utf-8");
|
|
50425
51083
|
const parsed = parseCompartmentOutput(xml);
|
|
50426
51084
|
const factCountByCategory = {};
|
|
50427
51085
|
for (const fact of parsed.facts) {
|
|
@@ -50454,11 +51112,11 @@ function parseHistorianDumpMeta2(path) {
|
|
|
50454
51112
|
}
|
|
50455
51113
|
}
|
|
50456
51114
|
function listDumpsInDir2(dir, limit) {
|
|
50457
|
-
if (!
|
|
51115
|
+
if (!existsSync48(dir))
|
|
50458
51116
|
return { count: 0, recent: [] };
|
|
50459
51117
|
try {
|
|
50460
51118
|
const entries = readdirSync10(dir).filter((name) => name.endsWith(".xml")).map((name) => {
|
|
50461
|
-
const stat =
|
|
51119
|
+
const stat = statSync24(join40(dir, name));
|
|
50462
51120
|
return {
|
|
50463
51121
|
name,
|
|
50464
51122
|
mtime: stat.mtimeMs,
|
|
@@ -50467,7 +51125,7 @@ function listDumpsInDir2(dir, limit) {
|
|
|
50467
51125
|
}).sort((a, b) => b.mtime - a.mtime);
|
|
50468
51126
|
const now = Date.now();
|
|
50469
51127
|
const recent = entries.slice(0, limit).map((entry) => {
|
|
50470
|
-
const meta = parseHistorianDumpMeta2(
|
|
51128
|
+
const meta = parseHistorianDumpMeta2(join40(dir, entry.name));
|
|
50471
51129
|
const summary = {
|
|
50472
51130
|
name: entry.name,
|
|
50473
51131
|
ageMinutes: Math.round((now - entry.mtime) / 60000),
|
|
@@ -50531,7 +51189,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
|
|
|
50531
51189
|
const loaded = loadPiConfig({ cwd });
|
|
50532
51190
|
const storageResolution = getMagicContextStorageResolution();
|
|
50533
51191
|
const storageDirPath = storageResolution.path;
|
|
50534
|
-
const dbPath =
|
|
51192
|
+
const dbPath = join40(storageDirPath, "context.db");
|
|
50535
51193
|
const logFiles = inspectMagicContextLogs("pi");
|
|
50536
51194
|
const primaryLog = logFiles.find((file) => file.exists) ?? logFiles[0];
|
|
50537
51195
|
const otherPiExtensions = packages.filter((entry) => !isPiMagicContextPackageEntry(entry)).map(describePiPackageEntry);
|
|
@@ -50548,7 +51206,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
|
|
|
50548
51206
|
piVersion: pi ? getPiVersion(pi.path) : null,
|
|
50549
51207
|
settings: {
|
|
50550
51208
|
path: settingsPath,
|
|
50551
|
-
exists:
|
|
51209
|
+
exists: existsSync48(settingsPath),
|
|
50552
51210
|
...settingsParsed.parseError ? { parseError: settingsParsed.parseError } : {},
|
|
50553
51211
|
hasMagicContextPackage: hasPiMagicContextPackage(packages),
|
|
50554
51212
|
packages: sanitizeValue2(packages)
|
|
@@ -50565,7 +51223,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
|
|
|
50565
51223
|
storageDir: {
|
|
50566
51224
|
path: storageDirPath,
|
|
50567
51225
|
source: storageResolution.source,
|
|
50568
|
-
exists:
|
|
51226
|
+
exists: existsSync48(storageDirPath),
|
|
50569
51227
|
contextDbSizeBytes: fileSize2(dbPath)
|
|
50570
51228
|
},
|
|
50571
51229
|
conflicts: {
|
|
@@ -50670,8 +51328,8 @@ var init_diagnostics_pi = __esm(() => {
|
|
|
50670
51328
|
});
|
|
50671
51329
|
|
|
50672
51330
|
// src/lib/logs-pi.ts
|
|
50673
|
-
import { mkdirSync as
|
|
50674
|
-
import { dirname as
|
|
51331
|
+
import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "node:fs";
|
|
51332
|
+
import { dirname as dirname27, join as join41 } from "node:path";
|
|
50675
51333
|
function sanitizeLogContent2(content) {
|
|
50676
51334
|
return sanitizeString2(content);
|
|
50677
51335
|
}
|
|
@@ -50727,13 +51385,13 @@ async function bundleIssueReport2(report, description, title, options = {}) {
|
|
|
50727
51385
|
const truncated = bodyMarkdown !== rawBodyMarkdown;
|
|
50728
51386
|
const cwd = options.cwd ?? process.cwd();
|
|
50729
51387
|
const timestamp = formatTimestamp2(options.now ?? new Date);
|
|
50730
|
-
const path = options.outputPath ??
|
|
50731
|
-
|
|
50732
|
-
|
|
51388
|
+
const path = options.outputPath ?? join41(cwd, `magic-context-pi-issue-${timestamp}.md`);
|
|
51389
|
+
mkdirSync9(dirname27(path), { recursive: true });
|
|
51390
|
+
writeFileSync9(path, `${bodyMarkdown}
|
|
50733
51391
|
`);
|
|
50734
|
-
const fullPath = truncated ? options.outputPath ? `${options.outputPath}.full.md` :
|
|
51392
|
+
const fullPath = truncated ? options.outputPath ? `${options.outputPath}.full.md` : join41(cwd, `magic-context-pi-issue-${timestamp}-full.md`) : undefined;
|
|
50735
51393
|
if (fullPath)
|
|
50736
|
-
|
|
51394
|
+
writeFileSync9(fullPath, `${rawBodyMarkdown}
|
|
50737
51395
|
`);
|
|
50738
51396
|
return { path, bodyMarkdown, ...fullPath ? { fullPath } : {}, truncated };
|
|
50739
51397
|
}
|
|
@@ -50745,10 +51403,10 @@ var init_logs_pi = __esm(() => {
|
|
|
50745
51403
|
|
|
50746
51404
|
// src/commands/doctor-pi.ts
|
|
50747
51405
|
import { execFileSync as execFileSync9, spawnSync as spawnSync11 } from "node:child_process";
|
|
50748
|
-
import { existsSync as
|
|
51406
|
+
import { existsSync as existsSync49, readdirSync as readdirSync11, readFileSync as readFileSync31, rmSync as rmSync10, statSync as statSync25 } from "node:fs";
|
|
50749
51407
|
import { createRequire as createRequire8 } from "node:module";
|
|
50750
|
-
import { homedir as
|
|
50751
|
-
import { isAbsolute as isAbsolute9, join as
|
|
51408
|
+
import { homedir as homedir22 } from "node:os";
|
|
51409
|
+
import { isAbsolute as isAbsolute9, join as join42 } from "node:path";
|
|
50752
51410
|
function depsFrom(options) {
|
|
50753
51411
|
return {
|
|
50754
51412
|
...DEFAULT_DEPS5,
|
|
@@ -50840,7 +51498,7 @@ function summarize(results) {
|
|
|
50840
51498
|
function readJsonc2(path) {
|
|
50841
51499
|
try {
|
|
50842
51500
|
return {
|
|
50843
|
-
value: import_comment_json13.parse(
|
|
51501
|
+
value: import_comment_json13.parse(readFileSync31(path, "utf-8"))
|
|
50844
51502
|
};
|
|
50845
51503
|
} catch (error) {
|
|
50846
51504
|
return {
|
|
@@ -50890,15 +51548,15 @@ function piPluginDirCandidates(packages, cwd) {
|
|
|
50890
51548
|
if (resolved)
|
|
50891
51549
|
dirs.push(resolved);
|
|
50892
51550
|
}
|
|
50893
|
-
dirs.push(
|
|
50894
|
-
dirs.push(
|
|
50895
|
-
return dirs.filter((dir) =>
|
|
51551
|
+
dirs.push(join42(agentDir, "npm", "node_modules", PACKAGE_NAME2));
|
|
51552
|
+
dirs.push(join42(cwd, ".pi", "npm", "node_modules", PACKAGE_NAME2));
|
|
51553
|
+
return dirs.filter((dir) => existsSync49(join42(dir, "package.json")));
|
|
50896
51554
|
}
|
|
50897
51555
|
function projectConfigPath(cwd) {
|
|
50898
51556
|
return resolveCortexKitProjectConfigPath(cwd);
|
|
50899
51557
|
}
|
|
50900
51558
|
function readConfigForEmbedding(path, isProjectConfig) {
|
|
50901
|
-
if (!
|
|
51559
|
+
if (!existsSync49(path))
|
|
50902
51560
|
return null;
|
|
50903
51561
|
try {
|
|
50904
51562
|
const raw = loadRawConfigFile({
|
|
@@ -50984,35 +51642,35 @@ function pinnedVersionFromPackageSpecifier(specifier) {
|
|
|
50984
51642
|
}
|
|
50985
51643
|
function cacheRoots(cwd) {
|
|
50986
51644
|
const home = process.env.HOME?.trim();
|
|
50987
|
-
const cacheHome = process.env.XDG_CACHE_HOME ||
|
|
51645
|
+
const cacheHome = process.env.XDG_CACHE_HOME || join42(home || homedir22(), ".cache");
|
|
50988
51646
|
const piCacheRoot = getPiCacheRoot();
|
|
50989
51647
|
return [
|
|
50990
|
-
|
|
50991
|
-
|
|
50992
|
-
|
|
50993
|
-
|
|
50994
|
-
|
|
50995
|
-
|
|
50996
|
-
|
|
51648
|
+
join42(piCacheRoot, "extensions"),
|
|
51649
|
+
join42(piCacheRoot, "packages"),
|
|
51650
|
+
join42(cacheHome, "pi", "extensions"),
|
|
51651
|
+
join42(cacheHome, "pi", "packages"),
|
|
51652
|
+
join42(getPiAgentConfigDir(), "cache", "extensions"),
|
|
51653
|
+
join42(getPiAgentConfigDir(), "npm", "node_modules", PACKAGE_NAME2),
|
|
51654
|
+
join42(cwd, ".pi", "npm", "node_modules", PACKAGE_NAME2)
|
|
50997
51655
|
];
|
|
50998
51656
|
}
|
|
50999
51657
|
function findPiMagicContextCacheDirs(cwd, expectedVersion, force = false) {
|
|
51000
51658
|
const found = new Map;
|
|
51001
51659
|
const visit = (path, depth) => {
|
|
51002
|
-
if (depth < 0 || !
|
|
51660
|
+
if (depth < 0 || !existsSync49(path))
|
|
51003
51661
|
return;
|
|
51004
51662
|
let stat;
|
|
51005
51663
|
try {
|
|
51006
|
-
stat =
|
|
51664
|
+
stat = statSync25(path);
|
|
51007
51665
|
} catch {
|
|
51008
51666
|
return;
|
|
51009
51667
|
}
|
|
51010
51668
|
if (!stat.isDirectory())
|
|
51011
51669
|
return;
|
|
51012
|
-
const packageJson =
|
|
51013
|
-
if (
|
|
51670
|
+
const packageJson = join42(path, "package.json");
|
|
51671
|
+
if (existsSync49(packageJson)) {
|
|
51014
51672
|
try {
|
|
51015
|
-
const pkg = JSON.parse(
|
|
51673
|
+
const pkg = JSON.parse(readFileSync31(packageJson, "utf-8"));
|
|
51016
51674
|
const name = typeof pkg.name === "string" ? pkg.name : "";
|
|
51017
51675
|
const version = typeof pkg.version === "string" ? pkg.version : undefined;
|
|
51018
51676
|
if (name === PACKAGE_NAME2) {
|
|
@@ -51032,7 +51690,7 @@ function findPiMagicContextCacheDirs(cwd, expectedVersion, force = false) {
|
|
|
51032
51690
|
return;
|
|
51033
51691
|
}
|
|
51034
51692
|
for (const entry of entries)
|
|
51035
|
-
visit(
|
|
51693
|
+
visit(join42(path, entry), depth - 1);
|
|
51036
51694
|
};
|
|
51037
51695
|
for (const root of cacheRoots(cwd))
|
|
51038
51696
|
visit(root, 5);
|
|
@@ -51093,7 +51751,7 @@ async function runHealthChecks2(options) {
|
|
|
51093
51751
|
const settingsPath = getPiUserExtensionsPath();
|
|
51094
51752
|
let packages = [];
|
|
51095
51753
|
let piPluginInstalled = false;
|
|
51096
|
-
if (!
|
|
51754
|
+
if (!existsSync49(settingsPath)) {
|
|
51097
51755
|
if (pi) {
|
|
51098
51756
|
add2(results, "info", `${piVersion ? `Pi ${piVersion}` : "Pi"} found; Magic Context is not installed there (run setup to add it)`);
|
|
51099
51757
|
}
|
|
@@ -51135,7 +51793,7 @@ async function runHealthChecks2(options) {
|
|
|
51135
51793
|
["user", userConfigPath, true],
|
|
51136
51794
|
["project", projectPath, false]
|
|
51137
51795
|
]) {
|
|
51138
|
-
if (!
|
|
51796
|
+
if (!existsSync49(path)) {
|
|
51139
51797
|
if (required) {
|
|
51140
51798
|
add2(results, "warn", `No ${label} magic-context.jsonc found at ${path}`);
|
|
51141
51799
|
if (userConfigMigrationRefused) {
|
|
@@ -51181,9 +51839,9 @@ async function runHealthChecks2(options) {
|
|
|
51181
51839
|
checkPiModelChains(results, pi, loadedConfig.config, options.deps);
|
|
51182
51840
|
const storage = getMagicContextStorageResolution();
|
|
51183
51841
|
const storageDir = storage.path;
|
|
51184
|
-
const dbPath =
|
|
51842
|
+
const dbPath = join42(storageDir, "context.db");
|
|
51185
51843
|
add2(results, "info", `Shared storage: ${storageDir} (source: ${storage.source})`);
|
|
51186
|
-
const existedBeforeOpen =
|
|
51844
|
+
const existedBeforeOpen = existsSync49(dbPath);
|
|
51187
51845
|
if (existedBeforeOpen)
|
|
51188
51846
|
add2(results, "pass", `Shared context DB exists at ${dbPath}`);
|
|
51189
51847
|
else
|
|
@@ -51412,7 +52070,7 @@ function writeDefaultMagicContextConfig(path) {
|
|
|
51412
52070
|
function repair2(plan, prompts) {
|
|
51413
52071
|
let fixed = 0;
|
|
51414
52072
|
for (const path of plan.reasoningAgeConfigPaths) {
|
|
51415
|
-
const content =
|
|
52073
|
+
const content = readFileSync31(path, "utf8");
|
|
51416
52074
|
const parsed = readJsonc2(path);
|
|
51417
52075
|
if (parsed.error)
|
|
51418
52076
|
continue;
|
|
@@ -51438,7 +52096,7 @@ function repair2(plan, prompts) {
|
|
|
51438
52096
|
}
|
|
51439
52097
|
if (plan.writeUserConfig) {
|
|
51440
52098
|
const configPath = getPiUserConfigPath();
|
|
51441
|
-
if (!
|
|
52099
|
+
if (!existsSync49(configPath)) {
|
|
51442
52100
|
try {
|
|
51443
52101
|
writeDefaultMagicContextConfig(configPath);
|
|
51444
52102
|
prompts.log.success(`Wrote default Magic Context config to ${configPath}`);
|
|
@@ -51450,7 +52108,7 @@ function repair2(plan, prompts) {
|
|
|
51450
52108
|
}
|
|
51451
52109
|
for (const path of plan.clearCachePaths) {
|
|
51452
52110
|
try {
|
|
51453
|
-
|
|
52111
|
+
rmSync10(path, { recursive: true, force: true });
|
|
51454
52112
|
prompts.log.success(`Cleared stale Pi extension cache: ${path}`);
|
|
51455
52113
|
fixed += 1;
|
|
51456
52114
|
} catch (error) {
|
|
@@ -51492,7 +52150,7 @@ async function runIssueFlow3(options) {
|
|
|
51492
52150
|
if (options.reportPath) {
|
|
51493
52151
|
try {
|
|
51494
52152
|
const report = await options.deps.collectDiagnostics(options.cwd);
|
|
51495
|
-
const outputPath = isAbsolute9(options.reportPath) ? options.reportPath :
|
|
52153
|
+
const outputPath = isAbsolute9(options.reportPath) ? options.reportPath : join42(options.cwd, options.reportPath);
|
|
51496
52154
|
const bundled = await bundleIssueReport2(report, "Generated non-interactively by `doctor --issue --report`.", "Magic Context diagnostic report", { cwd: options.cwd, now: options.deps.now(), outputPath });
|
|
51497
52155
|
options.prompts.log.info(`Report written to ${bundled.path}`);
|
|
51498
52156
|
return 0;
|
|
@@ -51576,7 +52234,7 @@ async function runDoctor3(options = {}) {
|
|
|
51576
52234
|
const v22Result = await runV22BackfillCommands({
|
|
51577
52235
|
name: "Pi",
|
|
51578
52236
|
openDatabase: (readonly = true) => {
|
|
51579
|
-
const dbPath =
|
|
52237
|
+
const dbPath = join42(getMagicContextStorageDir(), "context.db");
|
|
51580
52238
|
v22Db = readonly ? openExistingContextDatabase(dbPath, { readonly: true }) : openExistingContextDatabaseForMutation(dbPath);
|
|
51581
52239
|
return v22Db;
|
|
51582
52240
|
},
|
|
@@ -51694,8 +52352,8 @@ var init_doctor_pi = __esm(async () => {
|
|
|
51694
52352
|
});
|
|
51695
52353
|
|
|
51696
52354
|
// src/commands/doctor.ts
|
|
51697
|
-
import { existsSync as
|
|
51698
|
-
import { join as
|
|
52355
|
+
import { existsSync as existsSync50, rmSync as rmSync11 } from "node:fs";
|
|
52356
|
+
import { join as join43 } from "node:path";
|
|
51699
52357
|
async function runDoctor4(options) {
|
|
51700
52358
|
if (options.clear)
|
|
51701
52359
|
return runClear();
|
|
@@ -51713,7 +52371,7 @@ async function runDoctor4(options) {
|
|
|
51713
52371
|
const result = await runV22BackfillCommands({
|
|
51714
52372
|
name: "Magic Context",
|
|
51715
52373
|
openDatabase: (readonly = true) => {
|
|
51716
|
-
const dbPath =
|
|
52374
|
+
const dbPath = join43(getMagicContextStorageDir(), "context.db");
|
|
51717
52375
|
v22Db = readonly ? openExistingContextDatabase(dbPath, { readonly: true }) : openExistingContextDatabaseForMutation(dbPath);
|
|
51718
52376
|
return v22Db;
|
|
51719
52377
|
},
|
|
@@ -51733,7 +52391,7 @@ async function runDoctor4(options) {
|
|
|
51733
52391
|
log3.warn(`Identity split check unavailable: ${error instanceof Error ? error.message : String(error)}`);
|
|
51734
52392
|
}
|
|
51735
52393
|
await init_migrate();
|
|
51736
|
-
const sweepDbPath =
|
|
52394
|
+
const sweepDbPath = join43(getMagicContextStorageDir(), "context.db");
|
|
51737
52395
|
let sweepDb = null;
|
|
51738
52396
|
try {
|
|
51739
52397
|
sweepDb = openExistingContextDatabaseForMutation(sweepDbPath);
|
|
@@ -51819,7 +52477,7 @@ async function runClear() {
|
|
|
51819
52477
|
return 0;
|
|
51820
52478
|
}
|
|
51821
52479
|
const picks = await selectMany("Select caches to clear:", items.map((item, idx) => ({
|
|
51822
|
-
label: `${item.adapter.displayName}${item.label ? ` (${item.label})` : ""}: ${
|
|
52480
|
+
label: `${item.adapter.displayName}${item.label ? ` (${item.label})` : ""}: ${formatSize2(item.sizeBytes)} — ${item.path}`,
|
|
51823
52481
|
value: String(idx)
|
|
51824
52482
|
})));
|
|
51825
52483
|
if (picks.length === 0) {
|
|
@@ -51850,8 +52508,8 @@ async function runClear() {
|
|
|
51850
52508
|
failed += 1;
|
|
51851
52509
|
continue;
|
|
51852
52510
|
}
|
|
51853
|
-
} else if (
|
|
51854
|
-
|
|
52511
|
+
} else if (existsSync50(item.path)) {
|
|
52512
|
+
rmSync11(item.path, { recursive: true, force: true });
|
|
51855
52513
|
}
|
|
51856
52514
|
s.stop(`Cleared ${item.path}`);
|
|
51857
52515
|
} catch (err) {
|
|
@@ -51863,7 +52521,7 @@ async function runClear() {
|
|
|
51863
52521
|
outro2(failed === 0 ? "Done." : `Done with ${failed} failure(s).`);
|
|
51864
52522
|
return failed === 0 ? 0 : 1;
|
|
51865
52523
|
}
|
|
51866
|
-
function
|
|
52524
|
+
function formatSize2(bytes) {
|
|
51867
52525
|
if (bytes < 1024)
|
|
51868
52526
|
return `${bytes} B`;
|
|
51869
52527
|
if (bytes < 1048576)
|
|
@@ -51912,13 +52570,16 @@ var HARNESS_LINES = [
|
|
|
51912
52570
|
];
|
|
51913
52571
|
var SETUP_HELP = [
|
|
51914
52572
|
"",
|
|
51915
|
-
" Usage: magic-context setup [--harness opencode|pi|omp] [--dry-run]",
|
|
52573
|
+
" Usage: magic-context setup [--harness opencode|pi|omp] [--dry-run] [--dashboard|--no-dashboard]",
|
|
51916
52574
|
"",
|
|
51917
52575
|
" Interactive setup wizard: registers the Magic Context plugin with the",
|
|
51918
|
-
" selected harness and writes its Magic Context config.",
|
|
52576
|
+
" selected harness and writes its Magic Context config. Afterwards it offers",
|
|
52577
|
+
" to install the Magic Context Dashboard desktop app (interactive runs only).",
|
|
51919
52578
|
"",
|
|
51920
52579
|
" Options:",
|
|
51921
52580
|
" --dry-run Preview the wizard without writing any files",
|
|
52581
|
+
" --dashboard Install or update the dashboard without asking",
|
|
52582
|
+
" --no-dashboard Skip the dashboard offer",
|
|
51922
52583
|
...HARNESS_LINES,
|
|
51923
52584
|
""
|
|
51924
52585
|
].join(`
|
|
@@ -51971,7 +52632,7 @@ var SINGLE_STORE_HELP = [
|
|
|
51971
52632
|
`);
|
|
51972
52633
|
var MERGE_IDENTITY_HELP = [
|
|
51973
52634
|
"",
|
|
51974
|
-
" Usage: magic-context doctor merge-identities [--from <identity> --to <identity>] [--apply] [--force] [--db <path>]",
|
|
52635
|
+
" Usage: magic-context doctor merge-identities [--from <identity> --to <identity>] [--apply] [--force] [--verbose] [--db <path>] [--backup-root <dir>]",
|
|
51975
52636
|
"",
|
|
51976
52637
|
" Merge every project-scoped row from one project identity into another.",
|
|
51977
52638
|
"",
|
|
@@ -51981,8 +52642,10 @@ var MERGE_IDENTITY_HELP = [
|
|
|
51981
52642
|
" (no flags) List splits; --from/--to previews without writing",
|
|
51982
52643
|
" --apply Confirm the reviewed preview; hosts must be closed",
|
|
51983
52644
|
" --force Permit a target not resolving on this machine",
|
|
52645
|
+
" --verbose List every missing source-only folder and orphaned sidecar",
|
|
51984
52646
|
" --db <path> Use this context.db instead of the shared one",
|
|
51985
52647
|
" --host-db <path> Read session directories from this host database",
|
|
52648
|
+
" --backup-root <dir> Store the backup under this directory",
|
|
51986
52649
|
" Legacy alias: doctor merge-identity; --dry-run previews, --yes applies",
|
|
51987
52650
|
""
|
|
51988
52651
|
].join(`
|