@cortexkit/magic-context 0.18.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1198 -553
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -7805,26 +7805,70 @@ var require_src2 = __commonJS((exports, module) => {
|
|
|
7805
7805
|
};
|
|
7806
7806
|
});
|
|
7807
7807
|
|
|
7808
|
+
// ../plugin/src/shared/harness.ts
|
|
7809
|
+
function getHarness() {
|
|
7810
|
+
return currentHarness;
|
|
7811
|
+
}
|
|
7812
|
+
var currentHarness = "opencode";
|
|
7813
|
+
|
|
7814
|
+
// ../plugin/src/shared/data-path.ts
|
|
7815
|
+
import * as os from "node:os";
|
|
7816
|
+
import * as path from "node:path";
|
|
7817
|
+
function getDataDir() {
|
|
7818
|
+
return process.env.XDG_DATA_HOME ?? path.join(os.homedir(), ".local", "share");
|
|
7819
|
+
}
|
|
7820
|
+
function getMagicContextTempDir(harness = getHarness()) {
|
|
7821
|
+
return path.join(os.tmpdir(), harness, "magic-context");
|
|
7822
|
+
}
|
|
7823
|
+
function getMagicContextLogPath(harness = getHarness()) {
|
|
7824
|
+
return path.join(getMagicContextTempDir(harness), "magic-context.log");
|
|
7825
|
+
}
|
|
7826
|
+
function getMagicContextHistorianDir(harness = getHarness()) {
|
|
7827
|
+
return path.join(getMagicContextTempDir(harness), "historian");
|
|
7828
|
+
}
|
|
7829
|
+
function getProjectMagicContextDir(directory) {
|
|
7830
|
+
return path.join(directory, ".opencode", "magic-context");
|
|
7831
|
+
}
|
|
7832
|
+
function getProjectMagicContextHistorianDir(directory) {
|
|
7833
|
+
return path.join(getProjectMagicContextDir(directory), "historian");
|
|
7834
|
+
}
|
|
7835
|
+
function getOpenCodeStorageDir() {
|
|
7836
|
+
return path.join(getDataDir(), "opencode", "storage");
|
|
7837
|
+
}
|
|
7838
|
+
function getMagicContextStorageDir() {
|
|
7839
|
+
return path.join(getDataDir(), "cortexkit", "magic-context");
|
|
7840
|
+
}
|
|
7841
|
+
function getLegacyOpenCodeMagicContextStorageDir() {
|
|
7842
|
+
return path.join(getOpenCodeStorageDir(), "plugin", "magic-context");
|
|
7843
|
+
}
|
|
7844
|
+
function getCacheDir() {
|
|
7845
|
+
return process.env.XDG_CACHE_HOME ?? path.join(os.homedir(), ".cache");
|
|
7846
|
+
}
|
|
7847
|
+
function getOpenCodeCacheDir() {
|
|
7848
|
+
return path.join(getCacheDir(), "opencode");
|
|
7849
|
+
}
|
|
7850
|
+
var init_data_path = () => {};
|
|
7851
|
+
|
|
7808
7852
|
// src/lib/paths.ts
|
|
7809
7853
|
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
7810
|
-
import { homedir
|
|
7811
|
-
import { join } from "node:path";
|
|
7854
|
+
import { homedir as homedir2 } from "node:os";
|
|
7855
|
+
import { join as join2 } from "node:path";
|
|
7812
7856
|
function getOpenCodeConfigDir() {
|
|
7813
7857
|
const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
7814
7858
|
if (envDir)
|
|
7815
7859
|
return envDir;
|
|
7816
7860
|
if (process.platform === "win32") {
|
|
7817
|
-
return
|
|
7861
|
+
return join2(homedir2(), ".config", "opencode");
|
|
7818
7862
|
}
|
|
7819
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME ||
|
|
7820
|
-
return
|
|
7863
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME || join2(homedir2(), ".config");
|
|
7864
|
+
return join2(xdgConfig, "opencode");
|
|
7821
7865
|
}
|
|
7822
7866
|
function findOmoConfig(configDir) {
|
|
7823
7867
|
const locations = [
|
|
7824
|
-
|
|
7825
|
-
|
|
7826
|
-
|
|
7827
|
-
|
|
7868
|
+
join2(configDir, "oh-my-openagent.jsonc"),
|
|
7869
|
+
join2(configDir, "oh-my-openagent.json"),
|
|
7870
|
+
join2(configDir, "oh-my-opencode.jsonc"),
|
|
7871
|
+
join2(configDir, "oh-my-opencode.json")
|
|
7828
7872
|
];
|
|
7829
7873
|
for (const loc of locations) {
|
|
7830
7874
|
if (existsSync(loc))
|
|
@@ -7838,8 +7882,8 @@ function detectConfigPaths() {
|
|
|
7838
7882
|
let opencodeConfigFormat;
|
|
7839
7883
|
let tuiConfig;
|
|
7840
7884
|
let tuiConfigFormat;
|
|
7841
|
-
const jsoncPath =
|
|
7842
|
-
const jsonPath =
|
|
7885
|
+
const jsoncPath = join2(configDir, "opencode.jsonc");
|
|
7886
|
+
const jsonPath = join2(configDir, "opencode.json");
|
|
7843
7887
|
if (existsSync(jsoncPath)) {
|
|
7844
7888
|
opencodeConfig = jsoncPath;
|
|
7845
7889
|
opencodeConfigFormat = "jsonc";
|
|
@@ -7850,8 +7894,8 @@ function detectConfigPaths() {
|
|
|
7850
7894
|
opencodeConfig = jsonPath;
|
|
7851
7895
|
opencodeConfigFormat = "none";
|
|
7852
7896
|
}
|
|
7853
|
-
const tuiJsoncPath =
|
|
7854
|
-
const tuiJsonPath =
|
|
7897
|
+
const tuiJsoncPath = join2(configDir, "tui.jsonc");
|
|
7898
|
+
const tuiJsonPath = join2(configDir, "tui.json");
|
|
7855
7899
|
if (existsSync(tuiJsoncPath)) {
|
|
7856
7900
|
tuiConfig = tuiJsoncPath;
|
|
7857
7901
|
tuiConfigFormat = "jsonc";
|
|
@@ -7866,7 +7910,7 @@ function detectConfigPaths() {
|
|
|
7866
7910
|
configDir,
|
|
7867
7911
|
opencodeConfig,
|
|
7868
7912
|
opencodeConfigFormat,
|
|
7869
|
-
magicContextConfig:
|
|
7913
|
+
magicContextConfig: join2(configDir, "magic-context.jsonc"),
|
|
7870
7914
|
omoConfig: findOmoConfig(configDir),
|
|
7871
7915
|
tuiConfig,
|
|
7872
7916
|
tuiConfigFormat
|
|
@@ -7876,33 +7920,36 @@ function getPiAgentConfigDir() {
|
|
|
7876
7920
|
const envDir = process.env.PI_CODING_AGENT_DIR?.trim();
|
|
7877
7921
|
if (envDir)
|
|
7878
7922
|
return envDir;
|
|
7879
|
-
return
|
|
7923
|
+
return join2(homedir2(), ".pi", "agent");
|
|
7880
7924
|
}
|
|
7881
7925
|
function getPiUserConfigPath() {
|
|
7882
|
-
return
|
|
7926
|
+
return join2(getPiAgentConfigDir(), "magic-context.jsonc");
|
|
7883
7927
|
}
|
|
7884
7928
|
function getPiUserExtensionsPath() {
|
|
7885
|
-
return
|
|
7929
|
+
return join2(getPiAgentConfigDir(), "settings.json");
|
|
7930
|
+
}
|
|
7931
|
+
function getMagicContextLogPath2(harness) {
|
|
7932
|
+
return getMagicContextLogPath(harness);
|
|
7886
7933
|
}
|
|
7887
|
-
function
|
|
7888
|
-
return
|
|
7934
|
+
function getMagicContextHistorianDir2(harness) {
|
|
7935
|
+
return getMagicContextHistorianDir(harness);
|
|
7889
7936
|
}
|
|
7890
7937
|
function getOpenCodePluginCacheDir() {
|
|
7891
|
-
const xdg = process.env.XDG_CACHE_HOME ||
|
|
7892
|
-
return
|
|
7938
|
+
const xdg = process.env.XDG_CACHE_HOME || join2(homedir2(), ".cache");
|
|
7939
|
+
return join2(xdg, "opencode", "packages");
|
|
7893
7940
|
}
|
|
7894
|
-
function isDir(
|
|
7941
|
+
function isDir(path2) {
|
|
7895
7942
|
try {
|
|
7896
|
-
return statSync(
|
|
7943
|
+
return statSync(path2).isDirectory();
|
|
7897
7944
|
} catch {
|
|
7898
7945
|
return false;
|
|
7899
7946
|
}
|
|
7900
7947
|
}
|
|
7901
|
-
function dirSizeBytes(
|
|
7902
|
-
if (!isDir(
|
|
7948
|
+
function dirSizeBytes(path2) {
|
|
7949
|
+
if (!isDir(path2))
|
|
7903
7950
|
return 0;
|
|
7904
7951
|
let total = 0;
|
|
7905
|
-
const stack = [
|
|
7952
|
+
const stack = [path2];
|
|
7906
7953
|
while (stack.length > 0) {
|
|
7907
7954
|
const cur = stack.pop();
|
|
7908
7955
|
if (cur === undefined)
|
|
@@ -7910,7 +7957,7 @@ function dirSizeBytes(path) {
|
|
|
7910
7957
|
try {
|
|
7911
7958
|
const entries = readdirSync(cur, { withFileTypes: true });
|
|
7912
7959
|
for (const entry of entries) {
|
|
7913
|
-
const child =
|
|
7960
|
+
const child = join2(cur, entry.name);
|
|
7914
7961
|
if (entry.isDirectory()) {
|
|
7915
7962
|
stack.push(child);
|
|
7916
7963
|
} else if (entry.isFile()) {
|
|
@@ -7923,13 +7970,15 @@ function dirSizeBytes(path) {
|
|
|
7923
7970
|
}
|
|
7924
7971
|
return total;
|
|
7925
7972
|
}
|
|
7926
|
-
var init_paths = () => {
|
|
7973
|
+
var init_paths = __esm(() => {
|
|
7974
|
+
init_data_path();
|
|
7975
|
+
});
|
|
7927
7976
|
|
|
7928
7977
|
// src/adapters/opencode.ts
|
|
7929
7978
|
import { execFileSync } from "node:child_process";
|
|
7930
7979
|
import { existsSync as existsSync2, readFileSync, writeFileSync } from "node:fs";
|
|
7931
|
-
import { homedir as
|
|
7932
|
-
import { dirname, join as
|
|
7980
|
+
import { homedir as homedir3 } from "node:os";
|
|
7981
|
+
import { dirname, join as join3 } from "node:path";
|
|
7933
7982
|
|
|
7934
7983
|
class OpenCodeAdapter {
|
|
7935
7984
|
kind = "opencode";
|
|
@@ -7937,7 +7986,7 @@ class OpenCodeAdapter {
|
|
|
7937
7986
|
pluginPackageName = PLUGIN_NAME;
|
|
7938
7987
|
isInstalled() {
|
|
7939
7988
|
const isWindows = process.platform === "win32";
|
|
7940
|
-
const stockBin = isWindows ?
|
|
7989
|
+
const stockBin = isWindows ? join3(homedir3(), ".opencode", "bin", "opencode.exe") : join3(homedir3(), ".opencode", "bin", "opencode");
|
|
7941
7990
|
if (existsSync2(stockBin))
|
|
7942
7991
|
return true;
|
|
7943
7992
|
const probe = isWindows ? { cmd: "where", args: ["opencode"] } : { cmd: "command", args: ["-v", "opencode"] };
|
|
@@ -8112,15 +8161,15 @@ class OpenCodeAdapter {
|
|
|
8112
8161
|
return "Install OpenCode: curl -fsSL https://opencode.ai/install | bash";
|
|
8113
8162
|
}
|
|
8114
8163
|
getPluginCacheInfo() {
|
|
8115
|
-
const
|
|
8164
|
+
const path2 = getOpenCodePluginCacheDir();
|
|
8116
8165
|
return {
|
|
8117
|
-
path,
|
|
8118
|
-
exists: existsSync2(
|
|
8119
|
-
sizeBytes: dirSizeBytes(
|
|
8166
|
+
path: path2,
|
|
8167
|
+
exists: existsSync2(path2),
|
|
8168
|
+
sizeBytes: dirSizeBytes(path2)
|
|
8120
8169
|
};
|
|
8121
8170
|
}
|
|
8122
8171
|
getLogPath() {
|
|
8123
|
-
return
|
|
8172
|
+
return getMagicContextLogPath2("opencode");
|
|
8124
8173
|
}
|
|
8125
8174
|
getInstalledPluginVersion() {
|
|
8126
8175
|
const cacheDir = getOpenCodePluginCacheDir();
|
|
@@ -8185,8 +8234,8 @@ var init_opencode = __esm(() => {
|
|
|
8185
8234
|
// src/lib/pi-helpers.ts
|
|
8186
8235
|
import { execFileSync as execFileSync2, spawnSync } from "node:child_process";
|
|
8187
8236
|
import { existsSync as existsSync3 } from "node:fs";
|
|
8188
|
-
import { homedir as
|
|
8189
|
-
import { join as
|
|
8237
|
+
import { homedir as homedir4 } from "node:os";
|
|
8238
|
+
import { join as join4 } from "node:path";
|
|
8190
8239
|
function getStaticModels() {
|
|
8191
8240
|
return [...STATIC_MODELS];
|
|
8192
8241
|
}
|
|
@@ -8208,7 +8257,7 @@ function detectPiBinary() {
|
|
|
8208
8257
|
if (first)
|
|
8209
8258
|
return { path: first, source: "path" };
|
|
8210
8259
|
}
|
|
8211
|
-
const homeCandidate = process.platform === "win32" ?
|
|
8260
|
+
const homeCandidate = process.platform === "win32" ? join4(homedir4(), ".pi", "bin", "pi.cmd") : join4(homedir4(), ".pi", "bin", "pi");
|
|
8212
8261
|
if (existsSync3(homeCandidate))
|
|
8213
8262
|
return { path: homeCandidate, source: "home" };
|
|
8214
8263
|
return null;
|
|
@@ -8251,7 +8300,7 @@ function parseModelListOutput(output) {
|
|
|
8251
8300
|
if (!line || line.toLowerCase().includes("usage:"))
|
|
8252
8301
|
continue;
|
|
8253
8302
|
const token = line.split(/\s+/)[0]?.trim().replace(/,$/, "");
|
|
8254
|
-
if (!token
|
|
8303
|
+
if (!token?.includes("/"))
|
|
8255
8304
|
continue;
|
|
8256
8305
|
if (/^https?:\/\//.test(token))
|
|
8257
8306
|
continue;
|
|
@@ -8457,13 +8506,13 @@ class PiAdapter {
|
|
|
8457
8506
|
}
|
|
8458
8507
|
}
|
|
8459
8508
|
getInstallHint() {
|
|
8460
|
-
return "Install Pi: https://pi.coding/install (npm: @
|
|
8509
|
+
return "Install Pi: https://pi.coding/install (npm: @earendil-works/pi-coding-agent)";
|
|
8461
8510
|
}
|
|
8462
8511
|
getPluginCacheInfo() {
|
|
8463
8512
|
return { path: null, exists: false, sizeBytes: 0 };
|
|
8464
8513
|
}
|
|
8465
8514
|
getLogPath() {
|
|
8466
|
-
return
|
|
8515
|
+
return getMagicContextLogPath2("pi");
|
|
8467
8516
|
}
|
|
8468
8517
|
getInstalledPluginVersion() {
|
|
8469
8518
|
const piBin = detectPiBinary();
|
|
@@ -10327,17 +10376,17 @@ function detectConfigFile(basePath) {
|
|
|
10327
10376
|
var init_jsonc_parser = () => {};
|
|
10328
10377
|
|
|
10329
10378
|
// ../plugin/src/shared/opencode-config-dir.ts
|
|
10330
|
-
import { homedir as
|
|
10331
|
-
import { join as
|
|
10379
|
+
import { homedir as homedir5 } from "node:os";
|
|
10380
|
+
import { join as join5, resolve } from "node:path";
|
|
10332
10381
|
function getCliConfigDir() {
|
|
10333
10382
|
const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
10334
10383
|
if (envConfigDir) {
|
|
10335
10384
|
return resolve(envConfigDir);
|
|
10336
10385
|
}
|
|
10337
10386
|
if (process.platform === "win32") {
|
|
10338
|
-
return
|
|
10387
|
+
return join5(homedir5(), ".config", "opencode");
|
|
10339
10388
|
}
|
|
10340
|
-
return
|
|
10389
|
+
return join5(process.env.XDG_CONFIG_HOME || join5(homedir5(), ".config"), "opencode");
|
|
10341
10390
|
}
|
|
10342
10391
|
function getOpenCodeConfigDir2(_options) {
|
|
10343
10392
|
return getCliConfigDir();
|
|
@@ -10346,16 +10395,16 @@ function getOpenCodeConfigPaths(options) {
|
|
|
10346
10395
|
const configDir = getOpenCodeConfigDir2(options);
|
|
10347
10396
|
return {
|
|
10348
10397
|
configDir,
|
|
10349
|
-
configJson:
|
|
10350
|
-
configJsonc:
|
|
10351
|
-
packageJson:
|
|
10352
|
-
omoConfig:
|
|
10398
|
+
configJson: join5(configDir, "opencode.json"),
|
|
10399
|
+
configJsonc: join5(configDir, "opencode.jsonc"),
|
|
10400
|
+
packageJson: join5(configDir, "package.json"),
|
|
10401
|
+
omoConfig: join5(configDir, "magic-context.jsonc")
|
|
10353
10402
|
};
|
|
10354
10403
|
}
|
|
10355
10404
|
var init_opencode_config_dir = () => {};
|
|
10356
10405
|
|
|
10357
10406
|
// ../plugin/src/shared/conflict-detector.ts
|
|
10358
|
-
import { join as
|
|
10407
|
+
import { join as join6 } from "node:path";
|
|
10359
10408
|
function detectConflicts(directory) {
|
|
10360
10409
|
const conflicts = {
|
|
10361
10410
|
compactionAuto: false,
|
|
@@ -10412,8 +10461,8 @@ function checkCompaction(directory) {
|
|
|
10412
10461
|
return { auto: true, prune: false };
|
|
10413
10462
|
}
|
|
10414
10463
|
function readProjectCompaction(directory) {
|
|
10415
|
-
const dotOcJsonc =
|
|
10416
|
-
const dotOcJson =
|
|
10464
|
+
const dotOcJsonc = join6(directory, ".opencode", "opencode.jsonc");
|
|
10465
|
+
const dotOcJson = join6(directory, ".opencode", "opencode.json");
|
|
10417
10466
|
const dotOcConfig = readJsoncFile(dotOcJsonc) ?? readJsoncFile(dotOcJson);
|
|
10418
10467
|
if (dotOcConfig?.compaction) {
|
|
10419
10468
|
const c2 = dotOcConfig.compaction;
|
|
@@ -10421,8 +10470,8 @@ function readProjectCompaction(directory) {
|
|
|
10421
10470
|
return { auto: c2.auto === true, prune: c2.prune === true, resolved: true };
|
|
10422
10471
|
}
|
|
10423
10472
|
}
|
|
10424
|
-
const rootJsonc =
|
|
10425
|
-
const rootJson =
|
|
10473
|
+
const rootJsonc = join6(directory, "opencode.jsonc");
|
|
10474
|
+
const rootJson = join6(directory, "opencode.json");
|
|
10426
10475
|
const rootConfig = readJsoncFile(rootJsonc) ?? readJsoncFile(rootJson);
|
|
10427
10476
|
if (rootConfig?.compaction) {
|
|
10428
10477
|
const c2 = rootConfig.compaction;
|
|
@@ -10476,10 +10525,10 @@ function collectPluginEntries(directory) {
|
|
|
10476
10525
|
}
|
|
10477
10526
|
};
|
|
10478
10527
|
for (const configPath of [
|
|
10479
|
-
|
|
10480
|
-
|
|
10481
|
-
|
|
10482
|
-
|
|
10528
|
+
join6(directory, ".opencode", "opencode.jsonc"),
|
|
10529
|
+
join6(directory, ".opencode", "opencode.json"),
|
|
10530
|
+
join6(directory, "opencode.jsonc"),
|
|
10531
|
+
join6(directory, "opencode.json")
|
|
10483
10532
|
]) {
|
|
10484
10533
|
const config = readJsoncFile(configPath);
|
|
10485
10534
|
pushFrom(config?.plugin);
|
|
@@ -10520,7 +10569,7 @@ function readOmoDisabledHooks(directory) {
|
|
|
10520
10569
|
try {
|
|
10521
10570
|
const paths = getOpenCodeConfigPaths({ binary: "opencode" });
|
|
10522
10571
|
for (const name of configNames) {
|
|
10523
|
-
const configPath =
|
|
10572
|
+
const configPath = join6(paths.configDir, name);
|
|
10524
10573
|
const config = readJsoncFile(configPath);
|
|
10525
10574
|
if (config?.disabled_hooks) {
|
|
10526
10575
|
for (const hook of config.disabled_hooks) {
|
|
@@ -10530,7 +10579,7 @@ function readOmoDisabledHooks(directory) {
|
|
|
10530
10579
|
}
|
|
10531
10580
|
} catch {}
|
|
10532
10581
|
for (const name of configNames) {
|
|
10533
|
-
const config = readJsoncFile(
|
|
10582
|
+
const config = readJsoncFile(join6(directory, name));
|
|
10534
10583
|
if (config?.disabled_hooks) {
|
|
10535
10584
|
for (const hook of config.disabled_hooks) {
|
|
10536
10585
|
disabled.add(hook);
|
|
@@ -10548,11 +10597,8 @@ var init_conflict_detector = __esm(() => {
|
|
|
10548
10597
|
});
|
|
10549
10598
|
|
|
10550
10599
|
// ../plugin/src/shared/conflict-fixer.ts
|
|
10551
|
-
import { existsSync as existsSync6,
|
|
10552
|
-
import {
|
|
10553
|
-
function ensureParentDir(filePath) {
|
|
10554
|
-
mkdirSync(dirname3(filePath), { recursive: true });
|
|
10555
|
-
}
|
|
10600
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
10601
|
+
import { join as join7 } from "node:path";
|
|
10556
10602
|
function isRecord(value) {
|
|
10557
10603
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10558
10604
|
}
|
|
@@ -10561,13 +10607,17 @@ function asStringArray(value) {
|
|
|
10561
10607
|
}
|
|
10562
10608
|
function readConfig(filePath) {
|
|
10563
10609
|
if (!existsSync6(filePath)) {
|
|
10564
|
-
return
|
|
10610
|
+
return null;
|
|
10611
|
+
}
|
|
10612
|
+
try {
|
|
10613
|
+
const parsed = import_comment_json3.parse(readFileSync4(filePath, "utf-8"));
|
|
10614
|
+
return isRecord(parsed) ? parsed : null;
|
|
10615
|
+
} catch {
|
|
10616
|
+
return null;
|
|
10565
10617
|
}
|
|
10566
|
-
return readJsoncFile(filePath);
|
|
10567
10618
|
}
|
|
10568
10619
|
function writeConfig(filePath, config) {
|
|
10569
|
-
|
|
10570
|
-
writeFileSync3(filePath, `${JSON.stringify(config, null, 2)}
|
|
10620
|
+
writeFileSync3(filePath, `${import_comment_json3.stringify(config, null, 2)}
|
|
10571
10621
|
`);
|
|
10572
10622
|
}
|
|
10573
10623
|
function resolveUserOpenCodeConfigPath() {
|
|
@@ -10579,12 +10629,14 @@ function resolveUserOpenCodeConfigPath() {
|
|
|
10579
10629
|
function collectOpenCodeConfigPaths(directory) {
|
|
10580
10630
|
const paths = new Set;
|
|
10581
10631
|
const userConfig = resolveUserOpenCodeConfigPath();
|
|
10582
|
-
|
|
10632
|
+
if (existsSync6(userConfig)) {
|
|
10633
|
+
paths.add(userConfig);
|
|
10634
|
+
}
|
|
10583
10635
|
for (const filePath of [
|
|
10584
|
-
|
|
10585
|
-
|
|
10586
|
-
|
|
10587
|
-
|
|
10636
|
+
join7(directory, ".opencode", "opencode.jsonc"),
|
|
10637
|
+
join7(directory, ".opencode", "opencode.json"),
|
|
10638
|
+
join7(directory, "opencode.jsonc"),
|
|
10639
|
+
join7(directory, "opencode.json")
|
|
10588
10640
|
]) {
|
|
10589
10641
|
if (existsSync6(filePath)) {
|
|
10590
10642
|
paths.add(filePath);
|
|
@@ -10596,8 +10648,8 @@ function collectOmoConfigPaths(directory) {
|
|
|
10596
10648
|
const paths = new Set;
|
|
10597
10649
|
const configDir = getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
|
|
10598
10650
|
for (const fileName of OMO_CONFIG_NAMES) {
|
|
10599
|
-
const userPath =
|
|
10600
|
-
const projectPath =
|
|
10651
|
+
const userPath = join7(configDir, fileName);
|
|
10652
|
+
const projectPath = join7(directory, fileName);
|
|
10601
10653
|
if (existsSync6(userPath)) {
|
|
10602
10654
|
paths.add(userPath);
|
|
10603
10655
|
}
|
|
@@ -10605,11 +10657,15 @@ function collectOmoConfigPaths(directory) {
|
|
|
10605
10657
|
paths.add(projectPath);
|
|
10606
10658
|
}
|
|
10607
10659
|
}
|
|
10608
|
-
if (paths.size === 0) {
|
|
10609
|
-
paths.add(join6(configDir, "oh-my-openagent.json"));
|
|
10610
|
-
}
|
|
10611
10660
|
return [...paths];
|
|
10612
10661
|
}
|
|
10662
|
+
function filterDcpPluginEntries(entries) {
|
|
10663
|
+
const plugins = entries.filter((entry) => {
|
|
10664
|
+
const name = extractPluginName(entry);
|
|
10665
|
+
return name ? !matchesPackageName(name, DCP_PACKAGE_NAMES) : true;
|
|
10666
|
+
});
|
|
10667
|
+
return { plugins, removed: plugins.length !== entries.length };
|
|
10668
|
+
}
|
|
10613
10669
|
function fixConflicts(directory, conflicts) {
|
|
10614
10670
|
const actions = [];
|
|
10615
10671
|
let updatedCompaction = false;
|
|
@@ -10623,7 +10679,7 @@ function fixConflicts(directory, conflicts) {
|
|
|
10623
10679
|
}
|
|
10624
10680
|
let changed = false;
|
|
10625
10681
|
if (conflicts.compactionAuto || conflicts.compactionPrune) {
|
|
10626
|
-
const compaction = isRecord(config.compaction) ?
|
|
10682
|
+
const compaction = isRecord(config.compaction) ? config.compaction : {};
|
|
10627
10683
|
if (compaction.auto !== false) {
|
|
10628
10684
|
compaction.auto = false;
|
|
10629
10685
|
changed = true;
|
|
@@ -10637,10 +10693,10 @@ function fixConflicts(directory, conflicts) {
|
|
|
10637
10693
|
config.compaction = compaction;
|
|
10638
10694
|
}
|
|
10639
10695
|
if (conflicts.dcpPlugin) {
|
|
10640
|
-
const plugins =
|
|
10641
|
-
const
|
|
10642
|
-
if (
|
|
10643
|
-
config.plugin =
|
|
10696
|
+
const plugins = Array.isArray(config.plugin) ? config.plugin : [];
|
|
10697
|
+
const filtered = filterDcpPluginEntries(plugins);
|
|
10698
|
+
if (filtered.removed) {
|
|
10699
|
+
config.plugin = filtered.plugins;
|
|
10644
10700
|
changed = true;
|
|
10645
10701
|
removedDcpPlugin = true;
|
|
10646
10702
|
}
|
|
@@ -10695,10 +10751,11 @@ function fixConflicts(directory, conflicts) {
|
|
|
10695
10751
|
}
|
|
10696
10752
|
return actions;
|
|
10697
10753
|
}
|
|
10698
|
-
var CONFLICTING_OMO_HOOKS, OMO_CONFIG_NAMES;
|
|
10754
|
+
var import_comment_json3, CONFLICTING_OMO_HOOKS, OMO_CONFIG_NAMES;
|
|
10699
10755
|
var init_conflict_fixer = __esm(() => {
|
|
10700
|
-
|
|
10756
|
+
init_conflict_detector();
|
|
10701
10757
|
init_opencode_config_dir();
|
|
10758
|
+
import_comment_json3 = __toESM(require_src2(), 1);
|
|
10702
10759
|
CONFLICTING_OMO_HOOKS = [
|
|
10703
10760
|
"context-window-monitor",
|
|
10704
10761
|
"preemptive-compaction",
|
|
@@ -10790,30 +10847,30 @@ function buildModelSelection2(allModels, role) {
|
|
|
10790
10847
|
var init_opencode_helpers = () => {};
|
|
10791
10848
|
|
|
10792
10849
|
// src/commands/setup-opencode.ts
|
|
10793
|
-
import { existsSync as existsSync7, mkdirSync
|
|
10794
|
-
import { dirname as
|
|
10850
|
+
import { existsSync as existsSync7, mkdirSync, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "node:fs";
|
|
10851
|
+
import { dirname as dirname3 } from "node:path";
|
|
10795
10852
|
function ensureDir3(dir) {
|
|
10796
10853
|
if (!existsSync7(dir)) {
|
|
10797
|
-
|
|
10854
|
+
mkdirSync(dir, { recursive: true });
|
|
10798
10855
|
}
|
|
10799
10856
|
}
|
|
10800
|
-
function readJsonc(
|
|
10801
|
-
const content =
|
|
10857
|
+
function readJsonc(path2) {
|
|
10858
|
+
const content = readFileSync5(path2, "utf-8");
|
|
10802
10859
|
try {
|
|
10803
|
-
return
|
|
10860
|
+
return import_comment_json4.parse(content);
|
|
10804
10861
|
} catch (err) {
|
|
10805
|
-
console.error(` ⚠ Failed to parse ${
|
|
10862
|
+
console.error(` ⚠ Failed to parse ${path2}: ${err instanceof Error ? err.message : err}`);
|
|
10806
10863
|
return null;
|
|
10807
10864
|
}
|
|
10808
10865
|
}
|
|
10809
10866
|
function addPluginToOpenCodeConfig(configPath, format) {
|
|
10810
|
-
ensureDir3(
|
|
10867
|
+
ensureDir3(dirname3(configPath));
|
|
10811
10868
|
if (format === "none") {
|
|
10812
10869
|
const config = {
|
|
10813
10870
|
plugin: [PLUGIN_ENTRY2],
|
|
10814
10871
|
compaction: { auto: false, prune: false }
|
|
10815
10872
|
};
|
|
10816
|
-
writeFileSync4(configPath, `${
|
|
10873
|
+
writeFileSync4(configPath, `${import_comment_json4.stringify(config, null, 2)}
|
|
10817
10874
|
`);
|
|
10818
10875
|
return;
|
|
10819
10876
|
}
|
|
@@ -10833,13 +10890,13 @@ function addPluginToOpenCodeConfig(configPath, format) {
|
|
|
10833
10890
|
compaction.auto = false;
|
|
10834
10891
|
compaction.prune = false;
|
|
10835
10892
|
existing.compaction = compaction;
|
|
10836
|
-
writeFileSync4(configPath, `${
|
|
10893
|
+
writeFileSync4(configPath, `${import_comment_json4.stringify(existing, null, 2)}
|
|
10837
10894
|
`);
|
|
10838
10895
|
}
|
|
10839
10896
|
function addPluginToTuiConfig(configPath, format) {
|
|
10840
|
-
ensureDir3(
|
|
10897
|
+
ensureDir3(dirname3(configPath));
|
|
10841
10898
|
if (format === "none") {
|
|
10842
|
-
writeFileSync4(configPath, `${
|
|
10899
|
+
writeFileSync4(configPath, `${import_comment_json4.stringify({ plugin: [PLUGIN_ENTRY2] }, null, 2)}
|
|
10843
10900
|
`);
|
|
10844
10901
|
return;
|
|
10845
10902
|
}
|
|
@@ -10855,9 +10912,42 @@ function addPluginToTuiConfig(configPath, format) {
|
|
|
10855
10912
|
rawPlugins.push(PLUGIN_ENTRY2);
|
|
10856
10913
|
}
|
|
10857
10914
|
existing.plugin = rawPlugins;
|
|
10858
|
-
writeFileSync4(configPath, `${
|
|
10915
|
+
writeFileSync4(configPath, `${import_comment_json4.stringify(existing, null, 2)}
|
|
10859
10916
|
`);
|
|
10860
10917
|
}
|
|
10918
|
+
function findDcpPluginIndexes(plugins) {
|
|
10919
|
+
return plugins.map((plugin, index) => matchesPluginEntry(plugin, DCP_PLUGIN_NAME) ? index : -1).filter((index) => index >= 0);
|
|
10920
|
+
}
|
|
10921
|
+
function pluginEntryName(entry) {
|
|
10922
|
+
if (typeof entry === "string")
|
|
10923
|
+
return entry;
|
|
10924
|
+
if (Array.isArray(entry) && typeof entry[0] === "string")
|
|
10925
|
+
return entry[0];
|
|
10926
|
+
return String(entry);
|
|
10927
|
+
}
|
|
10928
|
+
async function resolveDcpConflictBeforeSetup(configPath, format) {
|
|
10929
|
+
if (format === "none")
|
|
10930
|
+
return;
|
|
10931
|
+
const ocConfig = readJsonc(configPath);
|
|
10932
|
+
if (!ocConfig)
|
|
10933
|
+
return;
|
|
10934
|
+
const plugins = Array.isArray(ocConfig.plugin) ? ocConfig.plugin : [];
|
|
10935
|
+
const dcpIndexes = findDcpPluginIndexes(plugins);
|
|
10936
|
+
if (dcpIndexes.length === 0)
|
|
10937
|
+
return;
|
|
10938
|
+
log.warn(`Found conflicting plugin: ${pluginEntryName(plugins[dcpIndexes[0]])}`);
|
|
10939
|
+
log.message(`opencode-dcp (Dynamic Context Pruning) and Magic Context both manage context.
|
|
10940
|
+
` + "Running both simultaneously will cause unpredictable behavior.");
|
|
10941
|
+
const shouldRemove = await confirm("Remove opencode-dcp from your config?", true);
|
|
10942
|
+
if (shouldRemove) {
|
|
10943
|
+
ocConfig.plugin = plugins.filter((_plugin, index) => !dcpIndexes.includes(index));
|
|
10944
|
+
writeFileSync4(configPath, `${import_comment_json4.stringify(ocConfig, null, 2)}
|
|
10945
|
+
`);
|
|
10946
|
+
log.success("Removed opencode-dcp from plugin list");
|
|
10947
|
+
} else {
|
|
10948
|
+
log.warn("Skipped — you may experience context management conflicts");
|
|
10949
|
+
}
|
|
10950
|
+
}
|
|
10861
10951
|
function writeMagicContextConfig(configPath, options) {
|
|
10862
10952
|
const config = (existsSync7(configPath) ? readJsonc(configPath) : null) ?? {};
|
|
10863
10953
|
if (!config.$schema) {
|
|
@@ -10896,7 +10986,7 @@ function writeMagicContextConfig(configPath, options) {
|
|
|
10896
10986
|
cacheTtl["anthropic/claude-opus-4-6"] = "59m";
|
|
10897
10987
|
config.cache_ttl = cacheTtl;
|
|
10898
10988
|
}
|
|
10899
|
-
writeFileSync4(configPath, `${
|
|
10989
|
+
writeFileSync4(configPath, `${import_comment_json4.stringify(config, null, 2)}
|
|
10900
10990
|
`);
|
|
10901
10991
|
}
|
|
10902
10992
|
async function runSetup() {
|
|
@@ -10926,32 +11016,11 @@ async function runSetup() {
|
|
|
10926
11016
|
}
|
|
10927
11017
|
const paths = detectConfigPaths();
|
|
10928
11018
|
const hadExistingSetup = paths.opencodeConfigFormat !== "none" || existsSync7(paths.magicContextConfig) || paths.tuiConfigFormat !== "none";
|
|
11019
|
+
await resolveDcpConflictBeforeSetup(paths.opencodeConfig, paths.opencodeConfigFormat);
|
|
10929
11020
|
addPluginToOpenCodeConfig(paths.opencodeConfig, paths.opencodeConfigFormat);
|
|
10930
11021
|
log.success(`Plugin added to ${paths.opencodeConfig}`);
|
|
10931
11022
|
log.info("Disabled built-in compaction (auto=false, prune=false)");
|
|
10932
11023
|
log.message("Magic Context handles context management — built-in compaction would interfere");
|
|
10933
|
-
if (paths.opencodeConfigFormat !== "none") {
|
|
10934
|
-
const ocConfig = readJsonc(paths.opencodeConfig);
|
|
10935
|
-
if (ocConfig) {
|
|
10936
|
-
const plugins = ocConfig.plugin ?? [];
|
|
10937
|
-
const dcpIndex = plugins.findIndex((p2) => p2.startsWith("@tarquinen/opencode-dcp"));
|
|
10938
|
-
if (dcpIndex !== -1) {
|
|
10939
|
-
log.warn(`Found conflicting plugin: ${plugins[dcpIndex]}`);
|
|
10940
|
-
log.message(`opencode-dcp (Dynamic Context Pruning) and Magic Context both manage context.
|
|
10941
|
-
` + "Running both simultaneously will cause unpredictable behavior.");
|
|
10942
|
-
const shouldRemove = await confirm("Remove opencode-dcp from your config?", true);
|
|
10943
|
-
if (shouldRemove) {
|
|
10944
|
-
plugins.splice(dcpIndex, 1);
|
|
10945
|
-
ocConfig.plugin = plugins;
|
|
10946
|
-
writeFileSync4(paths.opencodeConfig, `${import_comment_json3.stringify(ocConfig, null, 2)}
|
|
10947
|
-
`);
|
|
10948
|
-
log.success("Removed opencode-dcp from plugin list");
|
|
10949
|
-
} else {
|
|
10950
|
-
log.warn("Skipped — you may experience context management conflicts");
|
|
10951
|
-
}
|
|
10952
|
-
}
|
|
10953
|
-
}
|
|
10954
|
-
}
|
|
10955
11024
|
if (hadExistingSetup) {
|
|
10956
11025
|
const conflicts = detectConflicts(process.cwd());
|
|
10957
11026
|
if (conflicts.hasConflict) {
|
|
@@ -11084,7 +11153,7 @@ async function runSetup() {
|
|
|
11084
11153
|
outro("Run 'opencode' to start!");
|
|
11085
11154
|
return 0;
|
|
11086
11155
|
}
|
|
11087
|
-
var
|
|
11156
|
+
var import_comment_json4, PLUGIN_NAME3 = "@cortexkit/opencode-magic-context", PLUGIN_ENTRY2 = "@cortexkit/opencode-magic-context@latest", DCP_PLUGIN_NAME = "@tarquinen/opencode-dcp";
|
|
11088
11157
|
var init_setup_opencode = __esm(() => {
|
|
11089
11158
|
init_conflict_detector();
|
|
11090
11159
|
init_conflict_fixer();
|
|
@@ -11092,26 +11161,77 @@ var init_setup_opencode = __esm(() => {
|
|
|
11092
11161
|
init_opencode_helpers();
|
|
11093
11162
|
init_paths();
|
|
11094
11163
|
init_prompts();
|
|
11095
|
-
|
|
11164
|
+
import_comment_json4 = __toESM(require_src2(), 1);
|
|
11165
|
+
});
|
|
11166
|
+
|
|
11167
|
+
// src/lib/pi-package-entry.ts
|
|
11168
|
+
function stripNpmPrefix(value) {
|
|
11169
|
+
return value.startsWith("npm:") ? value.slice("npm:".length) : value;
|
|
11170
|
+
}
|
|
11171
|
+
function packageNameFromSpecifier(value) {
|
|
11172
|
+
const normalized = stripNpmPrefix(value.trim());
|
|
11173
|
+
if (!normalized)
|
|
11174
|
+
return normalized;
|
|
11175
|
+
if (normalized.startsWith("@")) {
|
|
11176
|
+
const slash = normalized.indexOf("/");
|
|
11177
|
+
if (slash < 0)
|
|
11178
|
+
return normalized;
|
|
11179
|
+
const versionAt2 = normalized.indexOf("@", slash + 1);
|
|
11180
|
+
return versionAt2 > 0 ? normalized.slice(0, versionAt2) : normalized;
|
|
11181
|
+
}
|
|
11182
|
+
const versionAt = normalized.indexOf("@");
|
|
11183
|
+
return versionAt > 0 ? normalized.slice(0, versionAt) : normalized;
|
|
11184
|
+
}
|
|
11185
|
+
function getPiPackageEntryName(entry) {
|
|
11186
|
+
if (typeof entry === "string")
|
|
11187
|
+
return packageNameFromSpecifier(entry);
|
|
11188
|
+
if (entry && typeof entry === "object" && !Array.isArray(entry)) {
|
|
11189
|
+
const name = entry.name;
|
|
11190
|
+
if (typeof name === "string")
|
|
11191
|
+
return packageNameFromSpecifier(name);
|
|
11192
|
+
}
|
|
11193
|
+
return null;
|
|
11194
|
+
}
|
|
11195
|
+
function isPiMagicContextPackageEntry(entry) {
|
|
11196
|
+
return getPiPackageEntryName(entry) === PI_MAGIC_CONTEXT_PACKAGE_NAME;
|
|
11197
|
+
}
|
|
11198
|
+
function hasPiMagicContextPackage(entries) {
|
|
11199
|
+
return entries.some(isPiMagicContextPackageEntry);
|
|
11200
|
+
}
|
|
11201
|
+
function describePiPackageEntry(entry) {
|
|
11202
|
+
if (typeof entry === "string")
|
|
11203
|
+
return entry;
|
|
11204
|
+
const name = getPiPackageEntryName(entry);
|
|
11205
|
+
if (name)
|
|
11206
|
+
return name;
|
|
11207
|
+
try {
|
|
11208
|
+
return JSON.stringify(entry);
|
|
11209
|
+
} catch {
|
|
11210
|
+
return String(entry);
|
|
11211
|
+
}
|
|
11212
|
+
}
|
|
11213
|
+
var PI_MAGIC_CONTEXT_PACKAGE_NAME = "@cortexkit/pi-magic-context";
|
|
11214
|
+
var init_pi_package_entry = __esm(() => {
|
|
11215
|
+
init_pi_helpers();
|
|
11096
11216
|
});
|
|
11097
11217
|
|
|
11098
11218
|
// src/commands/setup-pi.ts
|
|
11099
|
-
import { existsSync as existsSync8, mkdirSync as
|
|
11100
|
-
import { dirname as
|
|
11101
|
-
function ensureDir4(
|
|
11102
|
-
if (!existsSync8(
|
|
11103
|
-
|
|
11219
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync2, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "node:fs";
|
|
11220
|
+
import { dirname as dirname4 } from "node:path";
|
|
11221
|
+
function ensureDir4(path2) {
|
|
11222
|
+
if (!existsSync8(path2))
|
|
11223
|
+
mkdirSync2(path2, { recursive: true });
|
|
11104
11224
|
}
|
|
11105
11225
|
async function getDefaultPrompts() {
|
|
11106
11226
|
const { promptIO: promptIO2 } = await Promise.resolve().then(() => (init_prompts(), exports_prompts));
|
|
11107
11227
|
return promptIO2;
|
|
11108
11228
|
}
|
|
11109
|
-
function readJsonc2(
|
|
11229
|
+
function readJsonc2(path2) {
|
|
11110
11230
|
try {
|
|
11111
|
-
return
|
|
11231
|
+
return import_comment_json5.parse(readFileSync6(path2, "utf-8"));
|
|
11112
11232
|
} catch (error) {
|
|
11113
11233
|
const message = error instanceof Error ? error.message : String(error);
|
|
11114
|
-
console.warn(`Could not parse ${
|
|
11234
|
+
console.warn(`Could not parse ${path2}: ${message}`);
|
|
11115
11235
|
return null;
|
|
11116
11236
|
}
|
|
11117
11237
|
}
|
|
@@ -11123,12 +11243,12 @@ function compactObject(obj) {
|
|
|
11123
11243
|
return obj;
|
|
11124
11244
|
}
|
|
11125
11245
|
function comparePiVersion(a, b2) {
|
|
11126
|
-
const
|
|
11246
|
+
const parse2 = (v2) => {
|
|
11127
11247
|
const match = v2.match(/(\d+)\.(\d+)\.(\d+)/);
|
|
11128
11248
|
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
|
|
11129
11249
|
};
|
|
11130
|
-
const left =
|
|
11131
|
-
const right =
|
|
11250
|
+
const left = parse2(a);
|
|
11251
|
+
const right = parse2(b2);
|
|
11132
11252
|
if (!left || !right)
|
|
11133
11253
|
return 0;
|
|
11134
11254
|
for (let i = 0;i < 3; i += 1) {
|
|
@@ -11140,19 +11260,19 @@ function comparePiVersion(a, b2) {
|
|
|
11140
11260
|
return 0;
|
|
11141
11261
|
}
|
|
11142
11262
|
function writePiSettingsPackage(settingsPath, packageSource = PI_PACKAGE_SOURCE) {
|
|
11143
|
-
ensureDir4(
|
|
11263
|
+
ensureDir4(dirname4(settingsPath));
|
|
11144
11264
|
const settings = existsSync8(settingsPath) ? readJsonc2(settingsPath) ?? {} : {};
|
|
11145
|
-
const packages = Array.isArray(settings.packages) ? settings.packages
|
|
11146
|
-
const hasPackage = packages
|
|
11265
|
+
const packages = Array.isArray(settings.packages) ? settings.packages : [];
|
|
11266
|
+
const hasPackage = hasPiMagicContextPackage(packages);
|
|
11147
11267
|
if (!hasPackage)
|
|
11148
11268
|
packages.push(packageSource);
|
|
11149
11269
|
settings.packages = packages;
|
|
11150
|
-
writeFileSync5(settingsPath, `${
|
|
11270
|
+
writeFileSync5(settingsPath, `${import_comment_json5.stringify(settings, null, 2)}
|
|
11151
11271
|
`);
|
|
11152
11272
|
return !hasPackage;
|
|
11153
11273
|
}
|
|
11154
11274
|
function writeMagicContextConfig2(configPath, options) {
|
|
11155
|
-
ensureDir4(
|
|
11275
|
+
ensureDir4(dirname4(configPath));
|
|
11156
11276
|
const config = existsSync8(configPath) ? readJsonc2(configPath) ?? {} : {};
|
|
11157
11277
|
if (!config.$schema) {
|
|
11158
11278
|
config.$schema = "https://raw.githubusercontent.com/cortexkit/magic-context/master/assets/magic-context.schema.json";
|
|
@@ -11180,7 +11300,7 @@ function writeMagicContextConfig2(configPath, options) {
|
|
|
11180
11300
|
};
|
|
11181
11301
|
}
|
|
11182
11302
|
config.embedding = options.embedding;
|
|
11183
|
-
writeFileSync5(configPath, `${
|
|
11303
|
+
writeFileSync5(configPath, `${import_comment_json5.stringify(config, null, 2)}
|
|
11184
11304
|
`);
|
|
11185
11305
|
}
|
|
11186
11306
|
async function chooseModel(prompts, allModels, role, message) {
|
|
@@ -11233,11 +11353,11 @@ async function runSetup2(options = {}) {
|
|
|
11233
11353
|
}
|
|
11234
11354
|
const version = env.getPiVersion(pi.path);
|
|
11235
11355
|
spinner2.stop(version ? `Pi ${version} detected at ${pi.path}` : `Pi detected at ${pi.path}`);
|
|
11236
|
-
const MIN_PI_VERSION = "0.
|
|
11356
|
+
const MIN_PI_VERSION = "0.74.0";
|
|
11237
11357
|
if (version && comparePiVersion(version, MIN_PI_VERSION) < 0) {
|
|
11238
11358
|
prompts.log.warn(`Pi ${version} is older than the required ${MIN_PI_VERSION}.
|
|
11239
|
-
|
|
11240
|
-
Run \`pi update\` (or \`npm install -g @
|
|
11359
|
+
Pi 0.74.0 renamed the npm package from \`@mariozechner/pi-coding-agent\` to \`@earendil-works/pi-coding-agent\`. Magic Context's peer dependency targets the new scope, so older Pi installs cannot load this extension.
|
|
11360
|
+
Run \`pi update --self\` (or \`npm install -g @earendil-works/pi-coding-agent@latest\`) before continuing.`);
|
|
11241
11361
|
const proceed = await prompts.confirm("Continue with setup anyway? (subagents will fail at runtime)", false);
|
|
11242
11362
|
if (!proceed) {
|
|
11243
11363
|
prompts.outro("Setup cancelled — upgrade Pi and try again.");
|
|
@@ -11306,11 +11426,12 @@ Run \`pi update\` (or \`npm install -g @mariozechner/pi-coding-agent@latest\`) b
|
|
|
11306
11426
|
prompts.outro("Start a Pi session and try /ctx-aug");
|
|
11307
11427
|
return 0;
|
|
11308
11428
|
}
|
|
11309
|
-
var
|
|
11429
|
+
var import_comment_json5, DEFAULT_ENV;
|
|
11310
11430
|
var init_setup_pi = __esm(() => {
|
|
11311
11431
|
init_paths();
|
|
11312
11432
|
init_pi_helpers();
|
|
11313
|
-
|
|
11433
|
+
init_pi_package_entry();
|
|
11434
|
+
import_comment_json5 = __toESM(require_src2(), 1);
|
|
11314
11435
|
DEFAULT_ENV = {
|
|
11315
11436
|
detectPiBinary,
|
|
11316
11437
|
getPiVersion,
|
|
@@ -11390,29 +11511,6 @@ var init_setup = __esm(() => {
|
|
|
11390
11511
|
init_setup_pi();
|
|
11391
11512
|
});
|
|
11392
11513
|
|
|
11393
|
-
// ../plugin/src/shared/data-path.ts
|
|
11394
|
-
import * as os from "node:os";
|
|
11395
|
-
import * as path from "node:path";
|
|
11396
|
-
function getDataDir() {
|
|
11397
|
-
return process.env.XDG_DATA_HOME ?? path.join(os.homedir(), ".local", "share");
|
|
11398
|
-
}
|
|
11399
|
-
function getOpenCodeStorageDir() {
|
|
11400
|
-
return path.join(getDataDir(), "opencode", "storage");
|
|
11401
|
-
}
|
|
11402
|
-
function getMagicContextStorageDir() {
|
|
11403
|
-
return path.join(getDataDir(), "cortexkit", "magic-context");
|
|
11404
|
-
}
|
|
11405
|
-
function getLegacyOpenCodeMagicContextStorageDir() {
|
|
11406
|
-
return path.join(getOpenCodeStorageDir(), "plugin", "magic-context");
|
|
11407
|
-
}
|
|
11408
|
-
function getCacheDir() {
|
|
11409
|
-
return process.env.XDG_CACHE_HOME ?? path.join(os.homedir(), ".cache");
|
|
11410
|
-
}
|
|
11411
|
-
function getOpenCodeCacheDir() {
|
|
11412
|
-
return path.join(getCacheDir(), "opencode");
|
|
11413
|
-
}
|
|
11414
|
-
var init_data_path = () => {};
|
|
11415
|
-
|
|
11416
11514
|
// ../../node_modules/.bun/nanotar@0.3.0/node_modules/nanotar/dist/index.mjs
|
|
11417
11515
|
function parseTar(data, opts) {
|
|
11418
11516
|
const buffer = data.buffer || data;
|
|
@@ -11591,8 +11689,16 @@ var init_dist5 = __esm(() => {
|
|
|
11591
11689
|
|
|
11592
11690
|
// ../plugin/src/shared/logger.ts
|
|
11593
11691
|
import * as fs from "node:fs";
|
|
11594
|
-
import * as os2 from "node:os";
|
|
11595
11692
|
import * as path2 from "node:path";
|
|
11693
|
+
function ensureDir5(filePath) {
|
|
11694
|
+
const dir = path2.dirname(filePath);
|
|
11695
|
+
if (dir === lastEnsuredDir)
|
|
11696
|
+
return;
|
|
11697
|
+
try {
|
|
11698
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
11699
|
+
lastEnsuredDir = dir;
|
|
11700
|
+
} catch {}
|
|
11701
|
+
}
|
|
11596
11702
|
function flush() {
|
|
11597
11703
|
if (flushTimer) {
|
|
11598
11704
|
clearTimeout(flushTimer);
|
|
@@ -11603,6 +11709,8 @@ function flush() {
|
|
|
11603
11709
|
const data = buffer.join("");
|
|
11604
11710
|
buffer = [];
|
|
11605
11711
|
try {
|
|
11712
|
+
const logFile = getMagicContextLogPath();
|
|
11713
|
+
ensureDir5(logFile);
|
|
11606
11714
|
fs.appendFileSync(logFile, data);
|
|
11607
11715
|
} catch {}
|
|
11608
11716
|
}
|
|
@@ -11630,9 +11738,9 @@ ${data.stack}` : ""}` : ` ${JSON.stringify(data)}`;
|
|
|
11630
11738
|
}
|
|
11631
11739
|
} catch {}
|
|
11632
11740
|
}
|
|
11633
|
-
var
|
|
11741
|
+
var isTestEnv = false, buffer, flushTimer = null, FLUSH_INTERVAL_MS = 500, BUFFER_SIZE_LIMIT = 50, lastEnsuredDir = null;
|
|
11634
11742
|
var init_logger = __esm(() => {
|
|
11635
|
-
|
|
11743
|
+
init_data_path();
|
|
11636
11744
|
buffer = [];
|
|
11637
11745
|
if (!isTestEnv) {
|
|
11638
11746
|
process.on("exit", flush);
|
|
@@ -11808,15 +11916,15 @@ __export(exports_migrate, {
|
|
|
11808
11916
|
import { randomBytes } from "node:crypto";
|
|
11809
11917
|
import { existsSync as existsSync10, mkdirSync as mkdirSync5, writeFileSync as writeFileSync7 } from "node:fs";
|
|
11810
11918
|
import { homedir as homedir6 } from "node:os";
|
|
11811
|
-
import { join as
|
|
11919
|
+
import { join as join9 } from "node:path";
|
|
11812
11920
|
function defaultOpenCodeDbPath() {
|
|
11813
|
-
return
|
|
11921
|
+
return join9(homedir6(), ".local", "share", "opencode", "opencode.db");
|
|
11814
11922
|
}
|
|
11815
11923
|
function defaultCortexkitDbPath() {
|
|
11816
|
-
return
|
|
11924
|
+
return join9(getMagicContextStorageDir(), "context.db");
|
|
11817
11925
|
}
|
|
11818
11926
|
function defaultPiSessionsRoot() {
|
|
11819
|
-
return
|
|
11927
|
+
return join9(homedir6(), ".pi", "agent", "sessions");
|
|
11820
11928
|
}
|
|
11821
11929
|
function defaultFs() {
|
|
11822
11930
|
return { existsSync: existsSync10, mkdirSync: mkdirSync5, writeFileSync: writeFileSync7 };
|
|
@@ -12242,7 +12350,7 @@ function migrateOpenCodeSessionToPi(opts) {
|
|
|
12242
12350
|
const provider = opts.provider ?? model.provider;
|
|
12243
12351
|
const modelId = opts.modelId ?? model.modelId;
|
|
12244
12352
|
const cwd = session.directory ?? session.path ?? process.cwd();
|
|
12245
|
-
const outputDir =
|
|
12353
|
+
const outputDir = join9(piSessionsRoot, projectPathToPiDirSlug(cwd));
|
|
12246
12354
|
const buildResult = buildPiEntries({
|
|
12247
12355
|
session,
|
|
12248
12356
|
messages,
|
|
@@ -12268,7 +12376,7 @@ function migrateOpenCodeSessionToPi(opts) {
|
|
|
12268
12376
|
});
|
|
12269
12377
|
}
|
|
12270
12378
|
const compactionMarker = insertCompactionMarker(buildResult.entries, copyResult.lastCompartmentEndPiEntryId);
|
|
12271
|
-
const outputPath =
|
|
12379
|
+
const outputPath = join9(outputDir, `${formatPiFilenameTimestamp(now)}_${buildResult.piSessionId}.jsonl`);
|
|
12272
12380
|
const jsonl = `${buildResult.entries.map((entry) => JSON.stringify(entry)).join(`
|
|
12273
12381
|
`)}
|
|
12274
12382
|
`;
|
|
@@ -13326,7 +13434,7 @@ var _parse = (_Err) => (schema, value, _ctx, _params) => {
|
|
|
13326
13434
|
throw e2;
|
|
13327
13435
|
}
|
|
13328
13436
|
return result.value;
|
|
13329
|
-
},
|
|
13437
|
+
}, parse2, _parseAsync = (_Err) => async (schema, value, _ctx, params) => {
|
|
13330
13438
|
const ctx = _ctx ? { ..._ctx, async: true } : { async: true };
|
|
13331
13439
|
let result = schema._zod.run({ value, issues: [] }, ctx);
|
|
13332
13440
|
if (result instanceof Promise)
|
|
@@ -13381,7 +13489,7 @@ var init_parse = __esm(() => {
|
|
|
13381
13489
|
init_core();
|
|
13382
13490
|
init_errors();
|
|
13383
13491
|
init_util();
|
|
13384
|
-
|
|
13492
|
+
parse2 = /* @__PURE__ */ _parse($ZodRealError);
|
|
13385
13493
|
parseAsync = /* @__PURE__ */ _parseAsync($ZodRealError);
|
|
13386
13494
|
safeParse = /* @__PURE__ */ _safeParse($ZodRealError);
|
|
13387
13495
|
safeParseAsync = /* @__PURE__ */ _safeParseAsync($ZodRealError);
|
|
@@ -16140,10 +16248,10 @@ var init_schemas = __esm(() => {
|
|
|
16140
16248
|
throw new Error("implement() must be called with a function");
|
|
16141
16249
|
}
|
|
16142
16250
|
return function(...args) {
|
|
16143
|
-
const parsedArgs = inst._def.input ?
|
|
16251
|
+
const parsedArgs = inst._def.input ? parse2(inst._def.input, args) : args;
|
|
16144
16252
|
const result = Reflect.apply(func, this, parsedArgs);
|
|
16145
16253
|
if (inst._def.output) {
|
|
16146
|
-
return
|
|
16254
|
+
return parse2(inst._def.output, result);
|
|
16147
16255
|
}
|
|
16148
16256
|
return result;
|
|
16149
16257
|
};
|
|
@@ -23628,7 +23736,7 @@ function finalize(ctx, schema) {
|
|
|
23628
23736
|
result.$schema = "http://json-schema.org/draft-07/schema#";
|
|
23629
23737
|
} else if (ctx.target === "draft-04") {
|
|
23630
23738
|
result.$schema = "http://json-schema.org/draft-04/schema#";
|
|
23631
|
-
} else if (ctx.target === "openapi-3.0") {}
|
|
23739
|
+
} else if (ctx.target === "openapi-3.0") {}
|
|
23632
23740
|
if (ctx.external?.uri) {
|
|
23633
23741
|
const id = ctx.external.registry.get(schema)?.id;
|
|
23634
23742
|
if (!id)
|
|
@@ -23889,7 +23997,7 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
23889
23997
|
if (val === undefined) {
|
|
23890
23998
|
if (ctx.unrepresentable === "throw") {
|
|
23891
23999
|
throw new Error("Literal `undefined` cannot be represented in JSON Schema");
|
|
23892
|
-
}
|
|
24000
|
+
}
|
|
23893
24001
|
} else if (typeof val === "bigint") {
|
|
23894
24002
|
if (ctx.unrepresentable === "throw") {
|
|
23895
24003
|
throw new Error("BigInt literals cannot be represented in JSON Schema");
|
|
@@ -24336,7 +24444,7 @@ __export(exports_core2, {
|
|
|
24336
24444
|
process: () => process2,
|
|
24337
24445
|
prettifyError: () => prettifyError,
|
|
24338
24446
|
parseAsync: () => parseAsync,
|
|
24339
|
-
parse: () =>
|
|
24447
|
+
parse: () => parse2,
|
|
24340
24448
|
meta: () => meta,
|
|
24341
24449
|
locales: () => exports_locales,
|
|
24342
24450
|
isValidJWT: () => isValidJWT,
|
|
@@ -24737,11 +24845,11 @@ var init_errors2 = __esm(() => {
|
|
|
24737
24845
|
});
|
|
24738
24846
|
|
|
24739
24847
|
// ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/parse.js
|
|
24740
|
-
var
|
|
24848
|
+
var parse4, parseAsync2, safeParse2, safeParseAsync2, encode2, decode2, encodeAsync2, decodeAsync2, safeEncode2, safeDecode2, safeEncodeAsync2, safeDecodeAsync2;
|
|
24741
24849
|
var init_parse2 = __esm(() => {
|
|
24742
24850
|
init_core2();
|
|
24743
24851
|
init_errors2();
|
|
24744
|
-
|
|
24852
|
+
parse4 = /* @__PURE__ */ _parse(ZodRealError);
|
|
24745
24853
|
parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
|
|
24746
24854
|
safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
|
|
24747
24855
|
safeParseAsync2 = /* @__PURE__ */ _safeParseAsync(ZodRealError);
|
|
@@ -25461,7 +25569,7 @@ var init_schemas2 = __esm(() => {
|
|
|
25461
25569
|
inst.def = def;
|
|
25462
25570
|
inst.type = def.type;
|
|
25463
25571
|
Object.defineProperty(inst, "_def", { value: def });
|
|
25464
|
-
inst.parse = (data, params) =>
|
|
25572
|
+
inst.parse = (data, params) => parse4(inst, data, params, { callee: inst.parse });
|
|
25465
25573
|
inst.safeParse = (data, params) => safeParse2(inst, data, params);
|
|
25466
25574
|
inst.parseAsync = async (data, params) => parseAsync2(inst, data, params, { callee: inst.parseAsync });
|
|
25467
25575
|
inst.safeParseAsync = async (data, params) => safeParseAsync2(inst, data, params);
|
|
@@ -26813,7 +26921,7 @@ __export(exports_external, {
|
|
|
26813
26921
|
pipe: () => pipe,
|
|
26814
26922
|
partialRecord: () => partialRecord,
|
|
26815
26923
|
parseAsync: () => parseAsync2,
|
|
26816
|
-
parse: () =>
|
|
26924
|
+
parse: () => parse4,
|
|
26817
26925
|
overwrite: () => _overwrite,
|
|
26818
26926
|
optional: () => optional,
|
|
26819
26927
|
object: () => object,
|
|
@@ -27236,7 +27344,7 @@ var init_magic_context = __esm(() => {
|
|
|
27236
27344
|
});
|
|
27237
27345
|
|
|
27238
27346
|
// ../plugin/src/config/variable.ts
|
|
27239
|
-
import { existsSync as existsSync11, readFileSync as
|
|
27347
|
+
import { existsSync as existsSync11, readFileSync as readFileSync7 } from "node:fs";
|
|
27240
27348
|
import { homedir as homedir7 } from "node:os";
|
|
27241
27349
|
import { dirname as dirname7, isAbsolute, resolve as resolve2 } from "node:path";
|
|
27242
27350
|
function substituteConfigVariables(input) {
|
|
@@ -27283,7 +27391,7 @@ function substituteConfigVariables(input) {
|
|
|
27283
27391
|
}
|
|
27284
27392
|
let contents;
|
|
27285
27393
|
try {
|
|
27286
|
-
contents =
|
|
27394
|
+
contents = readFileSync7(filePath, "utf-8").trim();
|
|
27287
27395
|
} catch (error51) {
|
|
27288
27396
|
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
27289
27397
|
warnings.push(`Failed to read file for ${token} (${filePath}): ${message}; using empty string`);
|
|
@@ -27301,22 +27409,22 @@ var init_variable = __esm(() => {
|
|
|
27301
27409
|
});
|
|
27302
27410
|
|
|
27303
27411
|
// ../plugin/src/config/index.ts
|
|
27304
|
-
import { existsSync as existsSync12, readFileSync as
|
|
27412
|
+
import { existsSync as existsSync12, readFileSync as readFileSync8 } from "node:fs";
|
|
27305
27413
|
import { homedir as homedir8 } from "node:os";
|
|
27306
|
-
import { join as
|
|
27414
|
+
import { join as join10 } from "node:path";
|
|
27307
27415
|
function getUserConfigBasePath() {
|
|
27308
|
-
const configRoot = process.env.XDG_CONFIG_HOME ??
|
|
27309
|
-
return
|
|
27416
|
+
const configRoot = process.env.XDG_CONFIG_HOME ?? join10(homedir8(), ".config");
|
|
27417
|
+
return join10(configRoot, "opencode", CONFIG_FILE_BASENAME);
|
|
27310
27418
|
}
|
|
27311
27419
|
function getProjectConfigBasePath(directory) {
|
|
27312
|
-
return
|
|
27420
|
+
return join10(directory, ".opencode", CONFIG_FILE_BASENAME);
|
|
27313
27421
|
}
|
|
27314
27422
|
function loadConfigFile(configPath) {
|
|
27315
27423
|
try {
|
|
27316
27424
|
if (!existsSync12(configPath)) {
|
|
27317
27425
|
return null;
|
|
27318
27426
|
}
|
|
27319
|
-
const rawText =
|
|
27427
|
+
const rawText = readFileSync8(configPath, "utf-8");
|
|
27320
27428
|
const substituted = substituteConfigVariables({ text: rawText, configPath });
|
|
27321
27429
|
return {
|
|
27322
27430
|
config: parseJsonc3(substituted.text),
|
|
@@ -27327,34 +27435,20 @@ function loadConfigFile(configPath) {
|
|
|
27327
27435
|
return null;
|
|
27328
27436
|
}
|
|
27329
27437
|
}
|
|
27330
|
-
function
|
|
27331
|
-
const
|
|
27332
|
-
|
|
27333
|
-
|
|
27334
|
-
|
|
27335
|
-
|
|
27336
|
-
|
|
27337
|
-
|
|
27338
|
-
|
|
27339
|
-
|
|
27340
|
-
|
|
27341
|
-
dreamer: override.dreamer ? {
|
|
27342
|
-
...base.dreamer ?? {},
|
|
27343
|
-
...override.dreamer
|
|
27344
|
-
} : base.dreamer,
|
|
27345
|
-
sidekick: override.sidekick ? {
|
|
27346
|
-
...base.sidekick ?? {},
|
|
27347
|
-
...override.sidekick
|
|
27348
|
-
} : base.sidekick,
|
|
27349
|
-
disabled_hooks: [
|
|
27350
|
-
...new Set([...base.disabled_hooks ?? [], ...override.disabled_hooks ?? []])
|
|
27351
|
-
],
|
|
27352
|
-
command: {
|
|
27353
|
-
...base.command ?? {},
|
|
27354
|
-
...override.command ?? {}
|
|
27438
|
+
function deepMergeRawConfig(base, override) {
|
|
27439
|
+
const result = { ...base };
|
|
27440
|
+
for (const key of Object.keys(override)) {
|
|
27441
|
+
const baseVal = base[key];
|
|
27442
|
+
const overrideVal = override[key];
|
|
27443
|
+
if (baseVal !== null && typeof baseVal === "object" && !Array.isArray(baseVal) && overrideVal !== null && typeof overrideVal === "object" && !Array.isArray(overrideVal)) {
|
|
27444
|
+
result[key] = deepMergeRawConfig(baseVal, overrideVal);
|
|
27445
|
+
} else if (key === "disabled_hooks" && Array.isArray(baseVal) && Array.isArray(overrideVal)) {
|
|
27446
|
+
result[key] = [...new Set([...baseVal, ...overrideVal])];
|
|
27447
|
+
} else {
|
|
27448
|
+
result[key] = overrideVal;
|
|
27355
27449
|
}
|
|
27356
|
-
}
|
|
27357
|
-
return
|
|
27450
|
+
}
|
|
27451
|
+
return result;
|
|
27358
27452
|
}
|
|
27359
27453
|
function getProjectUserOnlyFields(config2) {
|
|
27360
27454
|
return "auto_update" in config2 ? ["auto_update"] : [];
|
|
@@ -27490,35 +27584,43 @@ function parsePluginConfig(rawConfig) {
|
|
|
27490
27584
|
}
|
|
27491
27585
|
function loadPluginConfig(directory) {
|
|
27492
27586
|
const userDetected = detectConfigFile(getUserConfigBasePath());
|
|
27493
|
-
const rootDetected = detectConfigFile(
|
|
27587
|
+
const rootDetected = detectConfigFile(join10(directory, CONFIG_FILE_BASENAME));
|
|
27494
27588
|
const dotOpenCodeDetected = detectConfigFile(getProjectConfigBasePath(directory));
|
|
27495
27589
|
const projectDetected = rootDetected.format !== "none" ? rootDetected : dotOpenCodeDetected;
|
|
27496
27590
|
const userLoaded = userDetected.format === "none" ? null : loadConfigFile(userDetected.path);
|
|
27497
27591
|
const projectLoaded = projectDetected.format === "none" ? null : loadConfigFile(projectDetected.path);
|
|
27498
|
-
let config2 = parsePluginConfig({});
|
|
27499
27592
|
const allWarnings = [];
|
|
27593
|
+
let mergedRaw = {};
|
|
27500
27594
|
if (userLoaded) {
|
|
27501
27595
|
allWarnings.push(...userLoaded.warnings.map((w3) => `[user config] ${w3}`));
|
|
27502
|
-
|
|
27503
|
-
if (parsed.configWarnings?.length) {
|
|
27504
|
-
allWarnings.push(...parsed.configWarnings.map((w3) => `[user config] ${w3}`));
|
|
27505
|
-
}
|
|
27506
|
-
config2 = mergeConfigs(config2, parsed, { allowUserOnlyFields: true });
|
|
27596
|
+
mergedRaw = deepMergeRawConfig(mergedRaw, userLoaded.config);
|
|
27507
27597
|
}
|
|
27508
27598
|
if (projectLoaded) {
|
|
27509
27599
|
allWarnings.push(...projectLoaded.warnings.map((w3) => `[project config] ${w3}`));
|
|
27510
|
-
const
|
|
27511
|
-
|
|
27512
|
-
allWarnings.push(...parsed.configWarnings.map((w3) => `[project config] ${w3}`));
|
|
27513
|
-
}
|
|
27514
|
-
const strippedUserOnlyFields = getProjectUserOnlyFields(projectLoaded.config);
|
|
27600
|
+
const projectRaw = { ...projectLoaded.config };
|
|
27601
|
+
const strippedUserOnlyFields = getProjectUserOnlyFields(projectRaw);
|
|
27515
27602
|
if (strippedUserOnlyFields.length > 0) {
|
|
27603
|
+
for (const key of strippedUserOnlyFields) {
|
|
27604
|
+
delete projectRaw[key];
|
|
27605
|
+
}
|
|
27516
27606
|
allWarnings.push(`[project config] Ignoring ${strippedUserOnlyFields.join(", ")} from project config (security: these settings only honor user-level config)`);
|
|
27517
27607
|
}
|
|
27518
|
-
|
|
27608
|
+
mergedRaw = deepMergeRawConfig(mergedRaw, projectRaw);
|
|
27609
|
+
}
|
|
27610
|
+
const config2 = parsePluginConfig(mergedRaw);
|
|
27611
|
+
if (config2.configWarnings?.length) {
|
|
27612
|
+
allWarnings.push(...config2.configWarnings.map((w3) => {
|
|
27613
|
+
if (userLoaded && projectLoaded)
|
|
27614
|
+
return `[config] ${w3}`;
|
|
27615
|
+
if (userLoaded)
|
|
27616
|
+
return `[user config] ${w3}`;
|
|
27617
|
+
return `[project config] ${w3}`;
|
|
27618
|
+
}));
|
|
27519
27619
|
}
|
|
27520
27620
|
if (allWarnings.length > 0) {
|
|
27521
27621
|
config2.configWarnings = allWarnings;
|
|
27622
|
+
} else if ("configWarnings" in config2) {
|
|
27623
|
+
config2.configWarnings = undefined;
|
|
27522
27624
|
}
|
|
27523
27625
|
return config2;
|
|
27524
27626
|
}
|
|
@@ -27529,6 +27631,78 @@ var init_config = __esm(() => {
|
|
|
27529
27631
|
init_variable();
|
|
27530
27632
|
});
|
|
27531
27633
|
|
|
27634
|
+
// ../plugin/src/features/magic-context/key-files/aft-availability.ts
|
|
27635
|
+
import { existsSync as existsSync13, readFileSync as readFileSync9 } from "node:fs";
|
|
27636
|
+
import { homedir as homedir9 } from "node:os";
|
|
27637
|
+
import { join as join11 } from "node:path";
|
|
27638
|
+
function parseConfig(path4) {
|
|
27639
|
+
if (!existsSync13(path4))
|
|
27640
|
+
return null;
|
|
27641
|
+
return import_comment_json6.parse(readFileSync9(path4, "utf-8"));
|
|
27642
|
+
}
|
|
27643
|
+
function entryMatchesAft(entry) {
|
|
27644
|
+
const value = Array.isArray(entry) ? entry[0] : entry;
|
|
27645
|
+
return typeof value === "string" && (value.includes("@cortexkit/aft") || value.includes("aft-opencode") || value.includes("aft-pi"));
|
|
27646
|
+
}
|
|
27647
|
+
function hasAftInArray(value) {
|
|
27648
|
+
return Array.isArray(value) && value.some(entryMatchesAft);
|
|
27649
|
+
}
|
|
27650
|
+
function hasAftAtKeys(value, keys) {
|
|
27651
|
+
if (!value || typeof value !== "object")
|
|
27652
|
+
return false;
|
|
27653
|
+
const record2 = value;
|
|
27654
|
+
for (const key of keys) {
|
|
27655
|
+
if (hasAftInArray(record2[key]))
|
|
27656
|
+
return true;
|
|
27657
|
+
}
|
|
27658
|
+
return false;
|
|
27659
|
+
}
|
|
27660
|
+
function getAftAvailability() {
|
|
27661
|
+
const home = process.env.HOME || homedir9();
|
|
27662
|
+
const opencodePaths = [
|
|
27663
|
+
join11(home, ".config", "opencode", "opencode.jsonc"),
|
|
27664
|
+
join11(home, ".config", "opencode", "opencode.json")
|
|
27665
|
+
];
|
|
27666
|
+
const piPaths = [join11(home, ".pi", "agent", "settings.json")];
|
|
27667
|
+
const checkedPaths = [...opencodePaths, ...piPaths];
|
|
27668
|
+
let opencode = false;
|
|
27669
|
+
for (const path4 of opencodePaths) {
|
|
27670
|
+
try {
|
|
27671
|
+
const config2 = parseConfig(path4);
|
|
27672
|
+
if (hasAftAtKeys(config2, ["plugin", "plugins", "mcp", "mcp_servers"])) {
|
|
27673
|
+
opencode = true;
|
|
27674
|
+
break;
|
|
27675
|
+
}
|
|
27676
|
+
} catch {}
|
|
27677
|
+
}
|
|
27678
|
+
let pi = false;
|
|
27679
|
+
for (const path4 of piPaths) {
|
|
27680
|
+
try {
|
|
27681
|
+
const config2 = parseConfig(path4);
|
|
27682
|
+
if (hasAftAtKeys(config2, ["packages", "extensions"])) {
|
|
27683
|
+
pi = true;
|
|
27684
|
+
break;
|
|
27685
|
+
}
|
|
27686
|
+
const agent = config2?.agent;
|
|
27687
|
+
if (hasAftAtKeys(agent, ["packages", "extensions"])) {
|
|
27688
|
+
pi = true;
|
|
27689
|
+
break;
|
|
27690
|
+
}
|
|
27691
|
+
} catch {}
|
|
27692
|
+
}
|
|
27693
|
+
const detected = opencode || pi;
|
|
27694
|
+
return {
|
|
27695
|
+
available: overrideAvailability ?? detected,
|
|
27696
|
+
opencode,
|
|
27697
|
+
pi,
|
|
27698
|
+
checkedPaths
|
|
27699
|
+
};
|
|
27700
|
+
}
|
|
27701
|
+
var import_comment_json6, overrideAvailability = null;
|
|
27702
|
+
var init_aft_availability = __esm(() => {
|
|
27703
|
+
import_comment_json6 = __toESM(require_src2(), 1);
|
|
27704
|
+
});
|
|
27705
|
+
|
|
27532
27706
|
// ../plugin/src/features/magic-context/memory/embedding-probe.ts
|
|
27533
27707
|
async function probeEmbeddingEndpoint(options) {
|
|
27534
27708
|
const endpoint = options.endpoint.trim().replace(/\/+$/, "");
|
|
@@ -27634,7 +27808,7 @@ function truncate(text2) {
|
|
|
27634
27808
|
var DEFAULT_TIMEOUT_MS = 1e4, MAX_PREVIEW_CHARS = 240;
|
|
27635
27809
|
|
|
27636
27810
|
// ../plugin/src/shared/tui-config.ts
|
|
27637
|
-
import { existsSync as
|
|
27811
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "node:fs";
|
|
27638
27812
|
import { dirname as dirname8, join as join12 } from "node:path";
|
|
27639
27813
|
function isMagicContextEntry(entry) {
|
|
27640
27814
|
if (!entry)
|
|
@@ -27651,9 +27825,9 @@ function resolveTuiConfigPath() {
|
|
|
27651
27825
|
const configDir = getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
|
|
27652
27826
|
const jsoncPath = join12(configDir, "tui.jsonc");
|
|
27653
27827
|
const jsonPath = join12(configDir, "tui.json");
|
|
27654
|
-
if (
|
|
27828
|
+
if (existsSync14(jsoncPath))
|
|
27655
27829
|
return jsoncPath;
|
|
27656
|
-
if (
|
|
27830
|
+
if (existsSync14(jsonPath))
|
|
27657
27831
|
return jsonPath;
|
|
27658
27832
|
return jsonPath;
|
|
27659
27833
|
}
|
|
@@ -27661,9 +27835,9 @@ function ensureTuiPluginEntry() {
|
|
|
27661
27835
|
try {
|
|
27662
27836
|
const configPath = resolveTuiConfigPath();
|
|
27663
27837
|
let config2 = {};
|
|
27664
|
-
if (
|
|
27665
|
-
const raw =
|
|
27666
|
-
config2 =
|
|
27838
|
+
if (existsSync14(configPath)) {
|
|
27839
|
+
const raw = readFileSync10(configPath, "utf-8");
|
|
27840
|
+
config2 = import_comment_json7.parse(raw) ?? {};
|
|
27667
27841
|
}
|
|
27668
27842
|
const plugins = Array.isArray(config2.plugin) ? config2.plugin.filter((p2) => typeof p2 === "string") : [];
|
|
27669
27843
|
const existingIdx = plugins.findIndex(isMagicContextEntry);
|
|
@@ -27682,7 +27856,7 @@ function ensureTuiPluginEntry() {
|
|
|
27682
27856
|
}
|
|
27683
27857
|
config2.plugin = plugins;
|
|
27684
27858
|
mkdirSync6(dirname8(configPath), { recursive: true });
|
|
27685
|
-
writeFileSync8(configPath, `${
|
|
27859
|
+
writeFileSync8(configPath, `${import_comment_json7.stringify(config2, null, 2)}
|
|
27686
27860
|
`);
|
|
27687
27861
|
log2(`[magic-context] updated TUI plugin entry in ${configPath}`);
|
|
27688
27862
|
return true;
|
|
@@ -27691,11 +27865,11 @@ function ensureTuiPluginEntry() {
|
|
|
27691
27865
|
return false;
|
|
27692
27866
|
}
|
|
27693
27867
|
}
|
|
27694
|
-
var
|
|
27868
|
+
var import_comment_json7, PLUGIN_NAME4 = "@cortexkit/opencode-magic-context", PLUGIN_ENTRY3;
|
|
27695
27869
|
var init_tui_config = __esm(() => {
|
|
27696
27870
|
init_logger();
|
|
27697
27871
|
init_opencode_config_dir();
|
|
27698
|
-
|
|
27872
|
+
import_comment_json7 = __toESM(require_src2(), 1);
|
|
27699
27873
|
PLUGIN_ENTRY3 = `${PLUGIN_NAME4}@latest`;
|
|
27700
27874
|
});
|
|
27701
27875
|
|
|
@@ -27749,10 +27923,125 @@ var init_compartment_parser = __esm(() => {
|
|
|
27749
27923
|
USER_OBS_ITEM_REGEX = /^\s*\*\s*(.+)$/gm;
|
|
27750
27924
|
});
|
|
27751
27925
|
|
|
27926
|
+
// src/lib/redaction.ts
|
|
27927
|
+
import { homedir as homedir10, userInfo } from "node:os";
|
|
27928
|
+
function escapeRegex2(value) {
|
|
27929
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
27930
|
+
}
|
|
27931
|
+
function redactionTypeForKey(key) {
|
|
27932
|
+
const normalized = key.trim().toLowerCase().replace(/[^a-z0-9_.-]+/g, "_");
|
|
27933
|
+
const suffix = normalized.split(".").filter(Boolean).at(-1) ?? normalized;
|
|
27934
|
+
return suffix || "secret";
|
|
27935
|
+
}
|
|
27936
|
+
function isSecretKey(key) {
|
|
27937
|
+
return SECRET_KEY_PATTERN.test(key);
|
|
27938
|
+
}
|
|
27939
|
+
function sanitizePathString(value) {
|
|
27940
|
+
const home = homedir10();
|
|
27941
|
+
const username = userInfo().username;
|
|
27942
|
+
let sanitized = value;
|
|
27943
|
+
if (home) {
|
|
27944
|
+
sanitized = sanitized.replace(new RegExp(escapeRegex2(home), "g"), "~");
|
|
27945
|
+
}
|
|
27946
|
+
sanitized = sanitized.replace(/\/Users\/[^/]+\//g, "/Users/<USER>/");
|
|
27947
|
+
sanitized = sanitized.replace(/\/home\/[^/]+\//g, "/home/<USER>/");
|
|
27948
|
+
sanitized = sanitized.replace(/C:\\Users\\[^\\]+\\/g, "C:\\Users\\<USER>\\");
|
|
27949
|
+
if (username) {
|
|
27950
|
+
sanitized = sanitized.replace(new RegExp(escapeRegex2(username), "g"), "<USER>");
|
|
27951
|
+
}
|
|
27952
|
+
return sanitized;
|
|
27953
|
+
}
|
|
27954
|
+
function redactSecretText(value) {
|
|
27955
|
+
let redacted = value;
|
|
27956
|
+
for (const { pattern, replacement } of SECRET_TEXT_PATTERNS) {
|
|
27957
|
+
if (typeof replacement === "string") {
|
|
27958
|
+
redacted = redacted.replace(pattern, replacement);
|
|
27959
|
+
} else {
|
|
27960
|
+
redacted = redacted.replace(pattern, replacement);
|
|
27961
|
+
}
|
|
27962
|
+
}
|
|
27963
|
+
return redacted;
|
|
27964
|
+
}
|
|
27965
|
+
function sanitizeDiagnosticText(value) {
|
|
27966
|
+
return redactSecretText(sanitizePathString(value));
|
|
27967
|
+
}
|
|
27968
|
+
function sanitizeConfigValue(value, keyPath = []) {
|
|
27969
|
+
const key = keyPath.at(-1) ?? "";
|
|
27970
|
+
if (key && isSecretKey(key)) {
|
|
27971
|
+
return `<REDACTED:${redactionTypeForKey(key)}>`;
|
|
27972
|
+
}
|
|
27973
|
+
if (typeof value === "string")
|
|
27974
|
+
return sanitizeDiagnosticText(value);
|
|
27975
|
+
if (Array.isArray(value)) {
|
|
27976
|
+
return value.map((entry, index) => sanitizeConfigValue(entry, [...keyPath, String(index)]));
|
|
27977
|
+
}
|
|
27978
|
+
if (value && typeof value === "object") {
|
|
27979
|
+
return Object.fromEntries(Object.entries(value).map(([entryKey, entry]) => [
|
|
27980
|
+
entryKey,
|
|
27981
|
+
sanitizeConfigValue(entry, [...keyPath, entryKey])
|
|
27982
|
+
]));
|
|
27983
|
+
}
|
|
27984
|
+
return value;
|
|
27985
|
+
}
|
|
27986
|
+
var SECRET_KEY_PATTERN, SECRET_TEXT_PATTERNS;
|
|
27987
|
+
var init_redaction = __esm(() => {
|
|
27988
|
+
SECRET_KEY_PATTERN = /(?:key|token|secret|password|auth|bearer|credential)/i;
|
|
27989
|
+
SECRET_TEXT_PATTERNS = [
|
|
27990
|
+
{
|
|
27991
|
+
pattern: /\bsk-ant-(?:api03-)?[A-Za-z0-9_-]{32,}/g,
|
|
27992
|
+
replacement: "<ANTHROPIC_API_KEY_REDACTED>"
|
|
27993
|
+
},
|
|
27994
|
+
{
|
|
27995
|
+
pattern: /\bsk-(?:proj-)?[A-Za-z0-9_-]{32,}/g,
|
|
27996
|
+
replacement: "<OPENAI_API_KEY_REDACTED>"
|
|
27997
|
+
},
|
|
27998
|
+
{
|
|
27999
|
+
pattern: /\bgithub_pat_[A-Za-z0-9_]{20,}/g,
|
|
28000
|
+
replacement: "<GITHUB_PAT_REDACTED>"
|
|
28001
|
+
},
|
|
28002
|
+
{
|
|
28003
|
+
pattern: /\b(?:gh[opsu]|ghr)_[A-Za-z0-9]{30,}/g,
|
|
28004
|
+
replacement: "<GITHUB_TOKEN_REDACTED>"
|
|
28005
|
+
},
|
|
28006
|
+
{
|
|
28007
|
+
pattern: /\bhf_[A-Za-z0-9]{30,}/g,
|
|
28008
|
+
replacement: "<HUGGINGFACE_TOKEN_REDACTED>"
|
|
28009
|
+
},
|
|
28010
|
+
{
|
|
28011
|
+
pattern: /\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g,
|
|
28012
|
+
replacement: "<AWS_ACCESS_KEY_ID_REDACTED>"
|
|
28013
|
+
},
|
|
28014
|
+
{
|
|
28015
|
+
pattern: /\bxox[abprsuvc]-[A-Za-z0-9-]{10,}/g,
|
|
28016
|
+
replacement: "<SLACK_TOKEN_REDACTED>"
|
|
28017
|
+
},
|
|
28018
|
+
{
|
|
28019
|
+
pattern: /\bAIza[A-Za-z0-9_-]{35}\b/g,
|
|
28020
|
+
replacement: "<GOOGLE_API_KEY_REDACTED>"
|
|
28021
|
+
},
|
|
28022
|
+
{
|
|
28023
|
+
pattern: /\b(Authorization\s*:\s*Bearer\s+)([A-Za-z0-9._~+/=-]{8,})/gi,
|
|
28024
|
+
replacement: (_full, prefix) => `${prefix}<REDACTED:bearer>`
|
|
28025
|
+
},
|
|
28026
|
+
{
|
|
28027
|
+
pattern: /\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,
|
|
28028
|
+
replacement: "<JWT_REDACTED>"
|
|
28029
|
+
},
|
|
28030
|
+
{
|
|
28031
|
+
pattern: /(["'])([^"']*(?:key|token|secret|password|auth|bearer|credential)[^"']*)\1(\s*:\s*)(["'])([^"']*)\4/gi,
|
|
28032
|
+
replacement: (_full, quote, key, separator, valueQuote) => `${quote}${key}${quote}${separator}${valueQuote}<REDACTED:${redactionTypeForKey(key)}>${valueQuote}`
|
|
28033
|
+
},
|
|
28034
|
+
{
|
|
28035
|
+
pattern: /\b([A-Za-z0-9_.-]*(?:key|token|secret|password|auth|bearer|credential)[A-Za-z0-9_.-]*)\s*=\s*([^\s'"`]+)/gi,
|
|
28036
|
+
replacement: (_full, key) => `${key}=<REDACTED:${redactionTypeForKey(key)}>`
|
|
28037
|
+
}
|
|
28038
|
+
];
|
|
28039
|
+
});
|
|
28040
|
+
|
|
27752
28041
|
// src/lib/diagnostics-opencode.ts
|
|
27753
|
-
import { existsSync as
|
|
28042
|
+
import { existsSync as existsSync15, readdirSync as readdirSync2, readFileSync as readFileSync11, statSync as statSync2 } from "node:fs";
|
|
27754
28043
|
import { createRequire as createRequire3 } from "node:module";
|
|
27755
|
-
import { homedir as
|
|
28044
|
+
import { homedir as homedir11 } from "node:os";
|
|
27756
28045
|
import { join as join13 } from "node:path";
|
|
27757
28046
|
function getSelfVersion() {
|
|
27758
28047
|
const require2 = createRequire3(import.meta.url);
|
|
@@ -27771,8 +28060,8 @@ function getPluginCacheInfo() {
|
|
|
27771
28060
|
let cached2;
|
|
27772
28061
|
try {
|
|
27773
28062
|
const installedPkgPath = join13(path4, "node_modules", "@cortexkit", "opencode-magic-context", "package.json");
|
|
27774
|
-
if (
|
|
27775
|
-
const pkg = JSON.parse(
|
|
28063
|
+
if (existsSync15(installedPkgPath)) {
|
|
28064
|
+
const pkg = JSON.parse(readFileSync11(installedPkgPath, "utf-8"));
|
|
27776
28065
|
cached2 = typeof pkg.version === "string" ? pkg.version : undefined;
|
|
27777
28066
|
}
|
|
27778
28067
|
} catch {
|
|
@@ -27781,50 +28070,28 @@ function getPluginCacheInfo() {
|
|
|
27781
28070
|
return { path: path4, cached: cached2, latest: getSelfVersion() };
|
|
27782
28071
|
}
|
|
27783
28072
|
function getStorageDir() {
|
|
27784
|
-
const dataHome = process.env.XDG_DATA_HOME || join13(
|
|
28073
|
+
const dataHome = process.env.XDG_DATA_HOME || join13(homedir11(), ".local", "share");
|
|
27785
28074
|
return join13(dataHome, "cortexkit", "magic-context");
|
|
27786
28075
|
}
|
|
27787
28076
|
function fileSize(path4) {
|
|
27788
28077
|
try {
|
|
27789
|
-
return
|
|
28078
|
+
return existsSync15(path4) ? statSync2(path4).size : 0;
|
|
27790
28079
|
} catch {
|
|
27791
28080
|
return 0;
|
|
27792
28081
|
}
|
|
27793
28082
|
}
|
|
27794
|
-
function escapeRegex2(value) {
|
|
27795
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
27796
|
-
}
|
|
27797
28083
|
function sanitizeString(value) {
|
|
27798
|
-
|
|
27799
|
-
const username = userInfo().username;
|
|
27800
|
-
let sanitized = value;
|
|
27801
|
-
if (home) {
|
|
27802
|
-
sanitized = sanitized.replace(new RegExp(escapeRegex2(home), "g"), "~");
|
|
27803
|
-
}
|
|
27804
|
-
sanitized = sanitized.replace(/\/Users\/[^/]+\//g, "/Users/<USER>/");
|
|
27805
|
-
sanitized = sanitized.replace(/\/home\/[^/]+\//g, "/home/<USER>/");
|
|
27806
|
-
sanitized = sanitized.replace(/C:\\Users\\[^\\]+\\/g, "C:\\Users\\<USER>\\");
|
|
27807
|
-
if (username) {
|
|
27808
|
-
sanitized = sanitized.replace(new RegExp(escapeRegex2(username), "g"), "<USER>");
|
|
27809
|
-
}
|
|
27810
|
-
return sanitized;
|
|
28084
|
+
return sanitizePathString(value);
|
|
27811
28085
|
}
|
|
27812
28086
|
function sanitizeValue(value) {
|
|
27813
|
-
|
|
27814
|
-
return sanitizeString(value);
|
|
27815
|
-
if (Array.isArray(value))
|
|
27816
|
-
return value.map(sanitizeValue);
|
|
27817
|
-
if (value && typeof value === "object") {
|
|
27818
|
-
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, sanitizeValue(entry)]));
|
|
27819
|
-
}
|
|
27820
|
-
return value;
|
|
28087
|
+
return sanitizeConfigValue(value);
|
|
27821
28088
|
}
|
|
27822
28089
|
function readConfig2(path4) {
|
|
27823
|
-
if (!
|
|
28090
|
+
if (!existsSync15(path4))
|
|
27824
28091
|
return { value: null };
|
|
27825
28092
|
try {
|
|
27826
|
-
const raw =
|
|
27827
|
-
const value =
|
|
28093
|
+
const raw = readFileSync11(path4, "utf-8");
|
|
28094
|
+
const value = import_comment_json8.parse(raw);
|
|
27828
28095
|
return { value };
|
|
27829
28096
|
} catch (error51) {
|
|
27830
28097
|
return { value: null, error: error51 instanceof Error ? error51.message : String(error51) };
|
|
@@ -27846,7 +28113,7 @@ function configHasPluginEntry(config2) {
|
|
|
27846
28113
|
}
|
|
27847
28114
|
function parseHistorianDumpMeta(path4) {
|
|
27848
28115
|
try {
|
|
27849
|
-
const xml =
|
|
28116
|
+
const xml = readFileSync11(path4, "utf-8");
|
|
27850
28117
|
const parsed = parseCompartmentOutput(xml);
|
|
27851
28118
|
const factCountByCategory = {};
|
|
27852
28119
|
for (const fact of parsed.facts) {
|
|
@@ -27878,11 +28145,9 @@ function parseHistorianDumpMeta(path4) {
|
|
|
27878
28145
|
return { error: error51 instanceof Error ? error51.message : String(error51) };
|
|
27879
28146
|
}
|
|
27880
28147
|
}
|
|
27881
|
-
function
|
|
27882
|
-
|
|
27883
|
-
|
|
27884
|
-
return { dir, count: 0, recent: [] };
|
|
27885
|
-
}
|
|
28148
|
+
function listDumpsInDir(dir, limit) {
|
|
28149
|
+
if (!existsSync15(dir))
|
|
28150
|
+
return { count: 0, recent: [] };
|
|
27886
28151
|
try {
|
|
27887
28152
|
const entries = readdirSync2(dir).filter((name) => name.endsWith(".xml")).map((name) => {
|
|
27888
28153
|
const stat = statSync2(join13(dir, name));
|
|
@@ -27893,7 +28158,7 @@ function collectHistorianDumps() {
|
|
|
27893
28158
|
};
|
|
27894
28159
|
}).sort((a, b2) => b2.mtime - a.mtime);
|
|
27895
28160
|
const now = Date.now();
|
|
27896
|
-
const recent = entries.slice(0,
|
|
28161
|
+
const recent = entries.slice(0, limit).map((entry) => {
|
|
27897
28162
|
const meta3 = parseHistorianDumpMeta(join13(dir, entry.name));
|
|
27898
28163
|
const summary = {
|
|
27899
28164
|
name: entry.name,
|
|
@@ -27907,14 +28172,85 @@ function collectHistorianDumps() {
|
|
|
27907
28172
|
}
|
|
27908
28173
|
return summary;
|
|
27909
28174
|
});
|
|
27910
|
-
return {
|
|
28175
|
+
return { count: entries.length, recent };
|
|
28176
|
+
} catch {
|
|
28177
|
+
return { count: 0, recent: [] };
|
|
28178
|
+
}
|
|
28179
|
+
}
|
|
28180
|
+
function collectHistorianDumps(recentSessions) {
|
|
28181
|
+
const buckets = new Map;
|
|
28182
|
+
for (const session of recentSessions) {
|
|
28183
|
+
const dir = session.directory;
|
|
28184
|
+
if (!dir)
|
|
28185
|
+
continue;
|
|
28186
|
+
const projectHistorianDir = getProjectMagicContextHistorianDir(dir);
|
|
28187
|
+
const listing = listDumpsInDir(projectHistorianDir, 5);
|
|
28188
|
+
const existing = buckets.get(dir);
|
|
28189
|
+
if (existing) {
|
|
28190
|
+
if (!existing.sessionIds.includes(session.sessionId)) {
|
|
28191
|
+
existing.sessionIds.push(session.sessionId);
|
|
28192
|
+
}
|
|
28193
|
+
continue;
|
|
28194
|
+
}
|
|
28195
|
+
if (listing.count === 0)
|
|
28196
|
+
continue;
|
|
28197
|
+
buckets.set(dir, {
|
|
28198
|
+
directory: dir,
|
|
28199
|
+
primarySessionId: session.sessionId,
|
|
28200
|
+
sessionIds: [session.sessionId],
|
|
28201
|
+
count: listing.count,
|
|
28202
|
+
recent: listing.recent
|
|
28203
|
+
});
|
|
28204
|
+
}
|
|
28205
|
+
const legacyDir = getMagicContextHistorianDir2("opencode");
|
|
28206
|
+
const legacyListing = listDumpsInDir(legacyDir, 5);
|
|
28207
|
+
return {
|
|
28208
|
+
byProject: [...buckets.values()],
|
|
28209
|
+
legacyDumps: {
|
|
28210
|
+
dir: legacyDir,
|
|
28211
|
+
count: legacyListing.count,
|
|
28212
|
+
recent: legacyListing.recent
|
|
28213
|
+
}
|
|
28214
|
+
};
|
|
28215
|
+
}
|
|
28216
|
+
async function collectRecentSessions() {
|
|
28217
|
+
const opencodeDbPath = join13(homedir11(), ".local", "share", "opencode", "opencode.db");
|
|
28218
|
+
if (!existsSync15(opencodeDbPath))
|
|
28219
|
+
return [];
|
|
28220
|
+
if (typeof globalThis.Bun === "undefined") {
|
|
28221
|
+
return [];
|
|
28222
|
+
}
|
|
28223
|
+
let DatabaseClass;
|
|
28224
|
+
try {
|
|
28225
|
+
const mod = await new Function("p", "return import(p)")("bun:sqlite");
|
|
28226
|
+
DatabaseClass = mod.Database;
|
|
28227
|
+
} catch {
|
|
28228
|
+
return [];
|
|
28229
|
+
}
|
|
28230
|
+
let db = null;
|
|
28231
|
+
try {
|
|
28232
|
+
db = new DatabaseClass(opencodeDbPath, { readonly: true });
|
|
28233
|
+
const rows = db.prepare("SELECT id, directory, title, time_updated FROM session " + "WHERE time_archived IS NULL AND parent_id IS NULL " + "ORDER BY time_updated DESC LIMIT 5").all();
|
|
28234
|
+
return rows.flatMap((row) => {
|
|
28235
|
+
const sessionId = typeof row.id === "string" ? row.id : null;
|
|
28236
|
+
const directory = typeof row.directory === "string" ? row.directory : null;
|
|
28237
|
+
if (!sessionId || !directory)
|
|
28238
|
+
return [];
|
|
28239
|
+
const title = typeof row.title === "string" ? row.title : "";
|
|
28240
|
+
const lastActiveAt = typeof row.time_updated === "number" ? new Date(row.time_updated).toISOString() : "";
|
|
28241
|
+
return [{ sessionId, title, directory, lastActiveAt }];
|
|
28242
|
+
});
|
|
27911
28243
|
} catch {
|
|
27912
|
-
return
|
|
28244
|
+
return [];
|
|
28245
|
+
} finally {
|
|
28246
|
+
try {
|
|
28247
|
+
db?.close();
|
|
28248
|
+
} catch {}
|
|
27913
28249
|
}
|
|
27914
28250
|
}
|
|
27915
28251
|
async function collectHistorianFailures(storageDirPath) {
|
|
27916
28252
|
const contextDbPath = join13(storageDirPath, "context.db");
|
|
27917
|
-
if (!
|
|
28253
|
+
if (!existsSync15(contextDbPath))
|
|
27918
28254
|
return [];
|
|
27919
28255
|
if (typeof globalThis.Bun === "undefined") {
|
|
27920
28256
|
return [];
|
|
@@ -27935,7 +28271,7 @@ async function collectHistorianFailures(storageDirPath) {
|
|
|
27935
28271
|
const failureCount = typeof row.historian_failure_count === "number" ? row.historian_failure_count : 0;
|
|
27936
28272
|
const rawError = typeof row.historian_last_error === "string" ? row.historian_last_error : "";
|
|
27937
28273
|
const lastAt = typeof row.historian_last_failure_at === "number" ? new Date(row.historian_last_failure_at).toISOString() : "";
|
|
27938
|
-
const lastError =
|
|
28274
|
+
const lastError = sanitizeDiagnosticText(rawError.replace(/\s+/g, " ").trim().slice(0, 400));
|
|
27939
28275
|
return { sessionId, failureCount, lastError, lastFailureAt: lastAt };
|
|
27940
28276
|
});
|
|
27941
28277
|
} catch {
|
|
@@ -27954,9 +28290,10 @@ async function collectDiagnostics() {
|
|
|
27954
28290
|
const magicContextConfig = readConfig2(configPaths.magicContextConfig);
|
|
27955
28291
|
const storageDirPath = getStorageDir();
|
|
27956
28292
|
const contextDbPath = join13(storageDirPath, "context.db");
|
|
27957
|
-
const logPath =
|
|
27958
|
-
const logFileSize =
|
|
28293
|
+
const logPath = getMagicContextLogPath2("opencode");
|
|
28294
|
+
const logFileSize = existsSync15(logPath) ? statSync2(logPath).size : 0;
|
|
27959
28295
|
const conflictResult = detectConflicts(process.cwd());
|
|
28296
|
+
const recentSessions = await collectRecentSessions();
|
|
27960
28297
|
return {
|
|
27961
28298
|
timestamp: new Date().toISOString(),
|
|
27962
28299
|
platform: process.platform,
|
|
@@ -27969,14 +28306,15 @@ async function collectDiagnostics() {
|
|
|
27969
28306
|
opencodeConfigHasPlugin: configHasPluginEntry(opencodeConfig.value),
|
|
27970
28307
|
tuiConfigHasPlugin: configHasPluginEntry(tuiConfig.value),
|
|
27971
28308
|
magicContextConfig: {
|
|
27972
|
-
exists:
|
|
28309
|
+
exists: existsSync15(configPaths.magicContextConfig),
|
|
27973
28310
|
...magicContextConfig.error ? { parseError: magicContextConfig.error } : {},
|
|
27974
28311
|
flags: sanitizeValue(magicContextConfig.value ?? {}) ?? {}
|
|
27975
28312
|
},
|
|
28313
|
+
aft: getAftAvailability(),
|
|
27976
28314
|
pluginCache: getPluginCacheInfo(),
|
|
27977
28315
|
storageDir: {
|
|
27978
28316
|
path: storageDirPath,
|
|
27979
|
-
exists:
|
|
28317
|
+
exists: existsSync15(storageDirPath),
|
|
27980
28318
|
contextDbSizeBytes: fileSize(contextDbPath)
|
|
27981
28319
|
},
|
|
27982
28320
|
conflicts: {
|
|
@@ -27985,10 +28323,11 @@ async function collectDiagnostics() {
|
|
|
27985
28323
|
},
|
|
27986
28324
|
logFile: {
|
|
27987
28325
|
path: logPath,
|
|
27988
|
-
exists:
|
|
28326
|
+
exists: existsSync15(logPath),
|
|
27989
28327
|
sizeKb: Math.round(logFileSize / 1024)
|
|
27990
28328
|
},
|
|
27991
|
-
|
|
28329
|
+
recentSessions,
|
|
28330
|
+
historianDumps: collectHistorianDumps(recentSessions),
|
|
27992
28331
|
historianFailures: await collectHistorianFailures(storageDirPath)
|
|
27993
28332
|
};
|
|
27994
28333
|
}
|
|
@@ -28022,10 +28361,25 @@ function renderDiagnosticsMarkdown(report) {
|
|
|
28022
28361
|
context_db_size: formatBytes(report.storageDir.contextDbSizeBytes)
|
|
28023
28362
|
};
|
|
28024
28363
|
const historianDumps = {
|
|
28025
|
-
|
|
28026
|
-
|
|
28027
|
-
|
|
28364
|
+
byProject: report.historianDumps.byProject.map((bucket) => ({
|
|
28365
|
+
directory: sanitizeString(bucket.directory),
|
|
28366
|
+
primarySessionId: bucket.primarySessionId,
|
|
28367
|
+
sessionIds: bucket.sessionIds,
|
|
28368
|
+
count: bucket.count,
|
|
28369
|
+
recent: bucket.recent
|
|
28370
|
+
})),
|
|
28371
|
+
legacyDumps: {
|
|
28372
|
+
dir: sanitizeString(report.historianDumps.legacyDumps.dir),
|
|
28373
|
+
count: report.historianDumps.legacyDumps.count,
|
|
28374
|
+
recent: report.historianDumps.legacyDumps.recent
|
|
28375
|
+
}
|
|
28028
28376
|
};
|
|
28377
|
+
const recentSessions = report.recentSessions.map((session) => ({
|
|
28378
|
+
sessionId: session.sessionId,
|
|
28379
|
+
title: session.title,
|
|
28380
|
+
directory: sanitizeString(session.directory),
|
|
28381
|
+
lastActiveAt: session.lastActiveAt
|
|
28382
|
+
}));
|
|
28029
28383
|
return [
|
|
28030
28384
|
`- Timestamp: ${report.timestamp}`,
|
|
28031
28385
|
`- Plugin: v${report.pluginVersion}`,
|
|
@@ -28035,6 +28389,7 @@ function renderDiagnosticsMarkdown(report) {
|
|
|
28035
28389
|
`- Plugin registered in opencode config: ${report.opencodeConfigHasPlugin}`,
|
|
28036
28390
|
`- Plugin registered in tui config: ${report.tuiConfigHasPlugin}`,
|
|
28037
28391
|
`- magic-context.jsonc parse error: ${report.magicContextConfig.parseError ?? "none"}`,
|
|
28392
|
+
`- AFT available: ${report.aft?.available ?? false} (opencode=${report.aft?.opencode ?? false}, pi=${report.aft?.pi ?? false})`,
|
|
28038
28393
|
`- Conflicts detected: ${report.conflicts.hasConflict ? report.conflicts.reasons.join("; ") : "none"}`,
|
|
28039
28394
|
"",
|
|
28040
28395
|
"### Config paths",
|
|
@@ -28044,7 +28399,7 @@ function renderDiagnosticsMarkdown(report) {
|
|
|
28044
28399
|
"",
|
|
28045
28400
|
"### magic-context.jsonc flags",
|
|
28046
28401
|
"```jsonc",
|
|
28047
|
-
JSON.stringify(report.magicContextConfig.flags, null, 2),
|
|
28402
|
+
JSON.stringify(sanitizeConfigValue(report.magicContextConfig.flags), null, 2),
|
|
28048
28403
|
"```",
|
|
28049
28404
|
"",
|
|
28050
28405
|
"### Plugin cache",
|
|
@@ -28056,15 +28411,24 @@ function renderDiagnosticsMarkdown(report) {
|
|
|
28056
28411
|
"```json",
|
|
28057
28412
|
JSON.stringify(storage, null, 2),
|
|
28058
28413
|
"```",
|
|
28414
|
+
"",
|
|
28415
|
+
"### Recent sessions",
|
|
28416
|
+
recentSessions.length === 0 ? "_No recent OpenCode sessions found (or OpenCode DB unavailable on this runtime)._" : ["```json", JSON.stringify(recentSessions, null, 2), "```"].join(`
|
|
28417
|
+
`),
|
|
28059
28418
|
"",
|
|
28060
28419
|
"### Historian dumps",
|
|
28061
28420
|
"(Metadata only — XML content is not included in this report.)",
|
|
28421
|
+
"Dumps are stored per-project under `<project>/.opencode/magic-context/historian/`.",
|
|
28062
28422
|
"```json",
|
|
28063
28423
|
JSON.stringify(historianDumps, null, 2),
|
|
28064
28424
|
"```",
|
|
28065
28425
|
"",
|
|
28066
28426
|
"### Historian failures (session_meta)",
|
|
28067
|
-
report.historianFailures.length === 0 ? "_No sessions with historian failures._" : [
|
|
28427
|
+
report.historianFailures.length === 0 ? "_No sessions with historian failures._" : [
|
|
28428
|
+
"```json",
|
|
28429
|
+
JSON.stringify(sanitizeConfigValue(report.historianFailures), null, 2),
|
|
28430
|
+
"```"
|
|
28431
|
+
].join(`
|
|
28068
28432
|
`),
|
|
28069
28433
|
"",
|
|
28070
28434
|
"### Log file",
|
|
@@ -28074,45 +28438,25 @@ function renderDiagnosticsMarkdown(report) {
|
|
|
28074
28438
|
].join(`
|
|
28075
28439
|
`);
|
|
28076
28440
|
}
|
|
28077
|
-
var
|
|
28441
|
+
var import_comment_json8, PLUGIN_NAME5 = "@cortexkit/opencode-magic-context", PLUGIN_ENTRY_WITH_VERSION;
|
|
28078
28442
|
var init_diagnostics_opencode = __esm(() => {
|
|
28443
|
+
init_aft_availability();
|
|
28079
28444
|
init_compartment_parser();
|
|
28080
28445
|
init_conflict_detector();
|
|
28081
28446
|
init_data_path();
|
|
28082
28447
|
init_opencode_helpers();
|
|
28083
28448
|
init_paths();
|
|
28084
|
-
|
|
28449
|
+
init_redaction();
|
|
28450
|
+
import_comment_json8 = __toESM(require_src2(), 1);
|
|
28085
28451
|
PLUGIN_ENTRY_WITH_VERSION = `${PLUGIN_NAME5}@latest`;
|
|
28086
28452
|
});
|
|
28087
28453
|
|
|
28088
28454
|
// src/lib/logs-opencode.ts
|
|
28089
|
-
import { readFileSync as
|
|
28090
|
-
import { homedir as
|
|
28455
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "node:fs";
|
|
28456
|
+
import { homedir as homedir12 } from "node:os";
|
|
28091
28457
|
import { join as join14 } from "node:path";
|
|
28092
|
-
function escapeRegex3(value) {
|
|
28093
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
28094
|
-
}
|
|
28095
28458
|
function sanitizeLogContent(content) {
|
|
28096
|
-
|
|
28097
|
-
const username = userInfo2().username;
|
|
28098
|
-
let sanitized = content;
|
|
28099
|
-
if (home) {
|
|
28100
|
-
sanitized = sanitized.replace(new RegExp(escapeRegex3(home), "g"), "~");
|
|
28101
|
-
}
|
|
28102
|
-
sanitized = sanitized.replace(/\/Users\/[^/]+\//g, "/Users/<USER>/");
|
|
28103
|
-
sanitized = sanitized.replace(/\/home\/[^/]+\//g, "/home/<USER>/");
|
|
28104
|
-
sanitized = sanitized.replace(/C:\\Users\\[^\\]+\\/g, "C:\\Users\\<USER>\\");
|
|
28105
|
-
if (username) {
|
|
28106
|
-
sanitized = sanitized.replace(new RegExp(escapeRegex3(username), "g"), "<USER>");
|
|
28107
|
-
}
|
|
28108
|
-
for (const { pattern, replacement } of SECRET_PATTERNS) {
|
|
28109
|
-
if (typeof replacement === "string") {
|
|
28110
|
-
sanitized = sanitized.replace(pattern, replacement);
|
|
28111
|
-
} else {
|
|
28112
|
-
sanitized = sanitized.replace(pattern, replacement);
|
|
28113
|
-
}
|
|
28114
|
-
}
|
|
28115
|
-
return sanitized;
|
|
28459
|
+
return sanitizeDiagnosticText(content);
|
|
28116
28460
|
}
|
|
28117
28461
|
function formatTimestamp(date5) {
|
|
28118
28462
|
const pad = (value) => String(value).padStart(2, "0");
|
|
@@ -28139,16 +28483,28 @@ function extractHistorianFailureLines(sanitized, limit = 30) {
|
|
|
28139
28483
|
}
|
|
28140
28484
|
return matches.reverse();
|
|
28141
28485
|
}
|
|
28142
|
-
|
|
28486
|
+
function filterLogLinesBySession(lines, sessionId) {
|
|
28487
|
+
if (!sessionId)
|
|
28488
|
+
return lines;
|
|
28489
|
+
const otherSessionPattern = /\bses_[A-Za-z0-9]{8,32}\b/g;
|
|
28490
|
+
return lines.filter((line) => {
|
|
28491
|
+
const matches = line.match(otherSessionPattern);
|
|
28492
|
+
if (!matches)
|
|
28493
|
+
return true;
|
|
28494
|
+
return matches.every((id) => id === sessionId);
|
|
28495
|
+
});
|
|
28496
|
+
}
|
|
28497
|
+
async function bundleIssueReport(report, description, _title, sessionFilter = null) {
|
|
28143
28498
|
const LOG_TAIL_LINES = 400;
|
|
28144
|
-
const
|
|
28499
|
+
const allLogLines = report.logFile.exists ? readFileSync12(report.logFile.path, "utf-8").split(/\r?\n/) : [];
|
|
28500
|
+
const logLines = filterLogLinesBySession(allLogLines, sessionFilter);
|
|
28145
28501
|
const recentLog = sanitizeLogContent(logLines.slice(-LOG_TAIL_LINES).join(`
|
|
28146
28502
|
`)).trim();
|
|
28147
28503
|
const historianScanWindow = sanitizeLogContent(logLines.slice(-4000).join(`
|
|
28148
28504
|
`));
|
|
28149
28505
|
const historianFailureLines = extractHistorianFailureLines(historianScanWindow, 30);
|
|
28150
|
-
const configBody = JSON.stringify(report.magicContextConfig.flags, null, 2);
|
|
28151
|
-
const sanitizedConfigPath = report.configPaths.magicContextConfig.replace(
|
|
28506
|
+
const configBody = JSON.stringify(sanitizeConfigValue(report.magicContextConfig.flags), null, 2);
|
|
28507
|
+
const sanitizedConfigPath = report.configPaths.magicContextConfig.replace(homedir12(), "~");
|
|
28152
28508
|
const bodyMarkdown = [
|
|
28153
28509
|
"## Description",
|
|
28154
28510
|
description,
|
|
@@ -28184,76 +28540,10 @@ async function bundleIssueReport(report, description, _title) {
|
|
|
28184
28540
|
`);
|
|
28185
28541
|
return { path: path4, bodyMarkdown };
|
|
28186
28542
|
}
|
|
28187
|
-
var
|
|
28543
|
+
var HISTORIAN_LOG_PATTERNS;
|
|
28188
28544
|
var init_logs_opencode = __esm(() => {
|
|
28189
28545
|
init_diagnostics_opencode();
|
|
28190
|
-
|
|
28191
|
-
{
|
|
28192
|
-
name: "anthropic_api_key",
|
|
28193
|
-
pattern: /\bsk-ant-(?:api03-)?[A-Za-z0-9_-]{32,}/g,
|
|
28194
|
-
replacement: "<ANTHROPIC_API_KEY_REDACTED>"
|
|
28195
|
-
},
|
|
28196
|
-
{
|
|
28197
|
-
name: "openai_api_key",
|
|
28198
|
-
pattern: /\bsk-(?:proj-)?[A-Za-z0-9_-]{32,}/g,
|
|
28199
|
-
replacement: "<OPENAI_API_KEY_REDACTED>"
|
|
28200
|
-
},
|
|
28201
|
-
{
|
|
28202
|
-
name: "github_pat_fine_grained",
|
|
28203
|
-
pattern: /\bgithub_pat_[A-Za-z0-9_]{20,}/g,
|
|
28204
|
-
replacement: "<GITHUB_PAT_REDACTED>"
|
|
28205
|
-
},
|
|
28206
|
-
{
|
|
28207
|
-
name: "github_token_classic",
|
|
28208
|
-
pattern: /\b(?:gh[opsu]|ghr)_[A-Za-z0-9]{30,}/g,
|
|
28209
|
-
replacement: "<GITHUB_TOKEN_REDACTED>"
|
|
28210
|
-
},
|
|
28211
|
-
{
|
|
28212
|
-
name: "huggingface_token",
|
|
28213
|
-
pattern: /\bhf_[A-Za-z0-9]{30,}/g,
|
|
28214
|
-
replacement: "<HUGGINGFACE_TOKEN_REDACTED>"
|
|
28215
|
-
},
|
|
28216
|
-
{
|
|
28217
|
-
name: "aws_access_key_id",
|
|
28218
|
-
pattern: /\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g,
|
|
28219
|
-
replacement: "<AWS_ACCESS_KEY_ID_REDACTED>"
|
|
28220
|
-
},
|
|
28221
|
-
{
|
|
28222
|
-
name: "aws_secret_access_key",
|
|
28223
|
-
pattern: /\b(aws[_-]?secret[_-]?access[_-]?key\s*[=:]\s*)([A-Za-z0-9/+=]{40})\b/gi,
|
|
28224
|
-
replacement: (_full, prefix) => `${prefix}<AWS_SECRET_REDACTED>`
|
|
28225
|
-
},
|
|
28226
|
-
{
|
|
28227
|
-
name: "slack_token",
|
|
28228
|
-
pattern: /\bxox[abprsuvc]-[A-Za-z0-9-]{10,}/g,
|
|
28229
|
-
replacement: "<SLACK_TOKEN_REDACTED>"
|
|
28230
|
-
},
|
|
28231
|
-
{
|
|
28232
|
-
name: "google_api_key",
|
|
28233
|
-
pattern: /\bAIza[A-Za-z0-9_-]{35}\b/g,
|
|
28234
|
-
replacement: "<GOOGLE_API_KEY_REDACTED>"
|
|
28235
|
-
},
|
|
28236
|
-
{
|
|
28237
|
-
name: "secret_env_assignment",
|
|
28238
|
-
pattern: /\b([A-Z][A-Z0-9_]*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD|CREDENTIAL|PRIVATE[_-]?KEY))\s*=\s*([^\s'"]+)/g,
|
|
28239
|
-
replacement: (_full, key) => `${key}=<REDACTED>`
|
|
28240
|
-
},
|
|
28241
|
-
{
|
|
28242
|
-
name: "secret_json_assignment",
|
|
28243
|
-
pattern: /("(?:api[_-]?key|access[_-]?token|auth[_-]?token|bearer[_-]?token|client[_-]?secret|password|private[_-]?key|secret[_-]?key)"\s*:\s*)"([^"]+)"/gi,
|
|
28244
|
-
replacement: (_full, prefix) => `${prefix}"<REDACTED>"`
|
|
28245
|
-
},
|
|
28246
|
-
{
|
|
28247
|
-
name: "bearer_token",
|
|
28248
|
-
pattern: /\b(Authorization\s*:\s*Bearer\s+)([A-Za-z0-9._~+/=-]{16,})/gi,
|
|
28249
|
-
replacement: (_full, prefix) => `${prefix}<BEARER_TOKEN_REDACTED>`
|
|
28250
|
-
},
|
|
28251
|
-
{
|
|
28252
|
-
name: "jwt_token",
|
|
28253
|
-
pattern: /\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,
|
|
28254
|
-
replacement: "<JWT_REDACTED>"
|
|
28255
|
-
}
|
|
28256
|
-
];
|
|
28546
|
+
init_redaction();
|
|
28257
28547
|
HISTORIAN_LOG_PATTERNS = [
|
|
28258
28548
|
/historian failure:/,
|
|
28259
28549
|
/historian failure recorded:/,
|
|
@@ -28267,9 +28557,9 @@ var init_logs_opencode = __esm(() => {
|
|
|
28267
28557
|
|
|
28268
28558
|
// src/commands/doctor-opencode.ts
|
|
28269
28559
|
import { execSync as execSync2, spawnSync as spawnSync2 } from "node:child_process";
|
|
28270
|
-
import { existsSync as
|
|
28560
|
+
import { existsSync as existsSync16, readFileSync as readFileSync13, rmSync, statSync as statSync3, writeFileSync as writeFileSync10 } from "node:fs";
|
|
28271
28561
|
import { createRequire as createRequire4 } from "node:module";
|
|
28272
|
-
import { homedir as
|
|
28562
|
+
import { homedir as homedir13 } from "node:os";
|
|
28273
28563
|
import { join as join15 } from "node:path";
|
|
28274
28564
|
async function fetchNpmLatest(pkg, timeoutMs = 5000) {
|
|
28275
28565
|
try {
|
|
@@ -28321,14 +28611,14 @@ function compareVersions(a, b2) {
|
|
|
28321
28611
|
async function clearPluginCache(force = false) {
|
|
28322
28612
|
const cacheDir = getOpenCodeCacheDir();
|
|
28323
28613
|
const pluginCacheDir = join15(cacheDir, "packages", PLUGIN_ENTRY_WITH_VERSION2);
|
|
28324
|
-
if (!
|
|
28614
|
+
if (!existsSync16(pluginCacheDir)) {
|
|
28325
28615
|
return { action: "not_found", path: pluginCacheDir };
|
|
28326
28616
|
}
|
|
28327
28617
|
let cachedVersion;
|
|
28328
28618
|
try {
|
|
28329
28619
|
const installedPkgPath = join15(pluginCacheDir, "node_modules", "@cortexkit", "opencode-magic-context", "package.json");
|
|
28330
|
-
if (
|
|
28331
|
-
const pkg = JSON.parse(
|
|
28620
|
+
if (existsSync16(installedPkgPath)) {
|
|
28621
|
+
const pkg = JSON.parse(readFileSync13(installedPkgPath, "utf-8"));
|
|
28332
28622
|
if (typeof pkg?.version === "string") {
|
|
28333
28623
|
cachedVersion = pkg.version;
|
|
28334
28624
|
}
|
|
@@ -28403,7 +28693,27 @@ async function runIssueFlow() {
|
|
|
28403
28693
|
s.start("Collecting diagnostics");
|
|
28404
28694
|
try {
|
|
28405
28695
|
const report = await collectDiagnostics();
|
|
28406
|
-
|
|
28696
|
+
s.stop("Diagnostics collected");
|
|
28697
|
+
let sessionFilter = null;
|
|
28698
|
+
if (report.recentSessions.length > 1) {
|
|
28699
|
+
const choice = await selectOne("Which session is this issue about? (filters log lines from other sessions)", [
|
|
28700
|
+
...report.recentSessions.map((session, index) => {
|
|
28701
|
+
const displayTitle = session.title.trim() || "(no title)";
|
|
28702
|
+
const truncatedTitle = displayTitle.length > 50 ? `${displayTitle.slice(0, 47)}...` : displayTitle;
|
|
28703
|
+
return {
|
|
28704
|
+
label: `${truncatedTitle} — ${session.sessionId}${index === 0 ? " (most recent)" : ""}`,
|
|
28705
|
+
value: session.sessionId
|
|
28706
|
+
};
|
|
28707
|
+
}),
|
|
28708
|
+
{
|
|
28709
|
+
label: "All sessions (no filtering)",
|
|
28710
|
+
value: "__all__"
|
|
28711
|
+
}
|
|
28712
|
+
]);
|
|
28713
|
+
sessionFilter = choice === "__all__" ? null : choice;
|
|
28714
|
+
}
|
|
28715
|
+
s.start("Bundling issue report");
|
|
28716
|
+
const bundled = await bundleIssueReport(report, description, title, sessionFilter);
|
|
28407
28717
|
s.stop(`Report written to ${bundled.path}`);
|
|
28408
28718
|
const shouldSubmit = await confirm("Submit this issue on GitHub now?", true);
|
|
28409
28719
|
if (shouldSubmit && isGhInstalled()) {
|
|
@@ -28440,12 +28750,12 @@ async function runIssueFlow() {
|
|
|
28440
28750
|
}
|
|
28441
28751
|
}
|
|
28442
28752
|
async function checkEmbeddingConfig(magicContextConfigPath) {
|
|
28443
|
-
if (!
|
|
28753
|
+
if (!existsSync16(magicContextConfigPath)) {
|
|
28444
28754
|
return { issues: 0 };
|
|
28445
28755
|
}
|
|
28446
28756
|
let rawText;
|
|
28447
28757
|
try {
|
|
28448
|
-
rawText =
|
|
28758
|
+
rawText = readFileSync13(magicContextConfigPath, "utf-8");
|
|
28449
28759
|
} catch {
|
|
28450
28760
|
log.warn("Could not read magic-context.jsonc for embedding check");
|
|
28451
28761
|
return { issues: 1 };
|
|
@@ -28456,7 +28766,7 @@ async function checkEmbeddingConfig(magicContextConfigPath) {
|
|
|
28456
28766
|
});
|
|
28457
28767
|
let parsedConfig;
|
|
28458
28768
|
try {
|
|
28459
|
-
parsedConfig =
|
|
28769
|
+
parsedConfig = import_comment_json9.parse(substituted.text);
|
|
28460
28770
|
} catch (error51) {
|
|
28461
28771
|
log.warn(`Embedding check skipped — could not parse magic-context.jsonc: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
28462
28772
|
return { issues: 1 };
|
|
@@ -28593,15 +28903,15 @@ async function runDoctor(options = {}) {
|
|
|
28593
28903
|
} else {
|
|
28594
28904
|
pass(`OpenCode config: ${paths.opencodeConfig}`);
|
|
28595
28905
|
}
|
|
28596
|
-
if (
|
|
28906
|
+
if (existsSync16(paths.magicContextConfig)) {
|
|
28597
28907
|
pass(`Magic Context config: ${paths.magicContextConfig}`);
|
|
28598
28908
|
try {
|
|
28599
|
-
const raw =
|
|
28909
|
+
const raw = readFileSync13(paths.magicContextConfig, "utf-8");
|
|
28600
28910
|
const substituted = substituteConfigVariables({
|
|
28601
28911
|
text: raw,
|
|
28602
28912
|
configPath: paths.magicContextConfig
|
|
28603
28913
|
}).text;
|
|
28604
|
-
|
|
28914
|
+
import_comment_json9.parse(substituted);
|
|
28605
28915
|
pass("magic-context.jsonc parses as valid JSONC");
|
|
28606
28916
|
} catch (err) {
|
|
28607
28917
|
fail(`magic-context.jsonc parse failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -28621,10 +28931,10 @@ async function runDoctor(options = {}) {
|
|
|
28621
28931
|
warn(`No magic-context.jsonc found — using defaults`);
|
|
28622
28932
|
log.info(" Run 'setup' to create one with model recommendations");
|
|
28623
28933
|
}
|
|
28624
|
-
if (
|
|
28934
|
+
if (existsSync16(paths.magicContextConfig)) {
|
|
28625
28935
|
try {
|
|
28626
|
-
const mcRaw =
|
|
28627
|
-
const mcConfig =
|
|
28936
|
+
const mcRaw = readFileSync13(paths.magicContextConfig, "utf-8");
|
|
28937
|
+
const mcConfig = import_comment_json9.parse(mcRaw);
|
|
28628
28938
|
let mcChanged = false;
|
|
28629
28939
|
const experimental = mcConfig.experimental;
|
|
28630
28940
|
if (experimental && "compaction_markers" in experimental) {
|
|
@@ -28699,7 +29009,7 @@ async function runDoctor(options = {}) {
|
|
|
28699
29009
|
fixed++;
|
|
28700
29010
|
}
|
|
28701
29011
|
if (mcChanged) {
|
|
28702
|
-
writeFileSync10(paths.magicContextConfig, `${
|
|
29012
|
+
writeFileSync10(paths.magicContextConfig, `${import_comment_json9.stringify(mcConfig, null, 2)}
|
|
28703
29013
|
`);
|
|
28704
29014
|
}
|
|
28705
29015
|
} catch {
|
|
@@ -28708,8 +29018,8 @@ async function runDoctor(options = {}) {
|
|
|
28708
29018
|
}
|
|
28709
29019
|
if (paths.opencodeConfigFormat !== "none") {
|
|
28710
29020
|
try {
|
|
28711
|
-
const raw =
|
|
28712
|
-
const config2 =
|
|
29021
|
+
const raw = readFileSync13(paths.opencodeConfig, "utf-8");
|
|
29022
|
+
const config2 = import_comment_json9.parse(raw);
|
|
28713
29023
|
const rawPlugins = Array.isArray(config2?.plugin) ? config2.plugin : [];
|
|
28714
29024
|
const existingIdx = rawPlugins.findIndex((entry) => matchesPluginEntry(entry, PLUGIN_NAME6) || isDevPathPluginEntry(entry));
|
|
28715
29025
|
const configName = paths.opencodeConfigFormat === "jsonc" ? "opencode.jsonc" : "opencode.json";
|
|
@@ -28740,7 +29050,7 @@ async function runDoctor(options = {}) {
|
|
|
28740
29050
|
rawPlugins[existingIdx] = PLUGIN_ENTRY_WITH_VERSION2;
|
|
28741
29051
|
}
|
|
28742
29052
|
config2.plugin = rawPlugins;
|
|
28743
|
-
writeFileSync10(paths.opencodeConfig, `${
|
|
29053
|
+
writeFileSync10(paths.opencodeConfig, `${import_comment_json9.stringify(config2, null, 2)}
|
|
28744
29054
|
`);
|
|
28745
29055
|
pass(`Upgraded plugin entry in ${configName}: ${oldEntryStr} → ${PLUGIN_ENTRY_WITH_VERSION2}`);
|
|
28746
29056
|
fixed++;
|
|
@@ -28749,7 +29059,7 @@ async function runDoctor(options = {}) {
|
|
|
28749
29059
|
} else {
|
|
28750
29060
|
rawPlugins.push(PLUGIN_ENTRY_WITH_VERSION2);
|
|
28751
29061
|
config2.plugin = rawPlugins;
|
|
28752
|
-
writeFileSync10(paths.opencodeConfig, `${
|
|
29062
|
+
writeFileSync10(paths.opencodeConfig, `${import_comment_json9.stringify(config2, null, 2)}
|
|
28753
29063
|
`);
|
|
28754
29064
|
pass(`Added plugin to ${configName}`);
|
|
28755
29065
|
fixed++;
|
|
@@ -28780,10 +29090,10 @@ async function runDoctor(options = {}) {
|
|
|
28780
29090
|
pass("Added TUI sidebar plugin to tui.json");
|
|
28781
29091
|
warn("Restart OpenCode to see the sidebar");
|
|
28782
29092
|
fixed++;
|
|
28783
|
-
} else if (
|
|
29093
|
+
} else if (existsSync16(paths.tuiConfig)) {
|
|
28784
29094
|
try {
|
|
28785
|
-
const tuiRaw =
|
|
28786
|
-
const tuiConfig =
|
|
29095
|
+
const tuiRaw = readFileSync13(paths.tuiConfig, "utf-8");
|
|
29096
|
+
const tuiConfig = import_comment_json9.parse(tuiRaw);
|
|
28787
29097
|
const tuiRawPlugins = Array.isArray(tuiConfig?.plugin) ? tuiConfig.plugin : [];
|
|
28788
29098
|
const tuiIdx = tuiRawPlugins.findIndex((entry) => matchesPluginEntry(entry, PLUGIN_NAME6) || isDevPathPluginEntry(entry));
|
|
28789
29099
|
const tuiEntryAsString = (entry) => {
|
|
@@ -28811,7 +29121,7 @@ async function runDoctor(options = {}) {
|
|
|
28811
29121
|
tuiRawPlugins[tuiIdx] = PLUGIN_ENTRY_WITH_VERSION2;
|
|
28812
29122
|
}
|
|
28813
29123
|
tuiConfig.plugin = tuiRawPlugins;
|
|
28814
|
-
writeFileSync10(paths.tuiConfig, `${
|
|
29124
|
+
writeFileSync10(paths.tuiConfig, `${import_comment_json9.stringify(tuiConfig, null, 2)}
|
|
28815
29125
|
`);
|
|
28816
29126
|
pass(`Upgraded TUI plugin: ${tuiEntryStr} → ${PLUGIN_ENTRY_WITH_VERSION2}`);
|
|
28817
29127
|
fixed++;
|
|
@@ -28828,10 +29138,10 @@ async function runDoctor(options = {}) {
|
|
|
28828
29138
|
} else {
|
|
28829
29139
|
pass("TUI sidebar plugin configured (tui.json created)");
|
|
28830
29140
|
}
|
|
28831
|
-
if (
|
|
29141
|
+
if (existsSync16(paths.magicContextConfig)) {
|
|
28832
29142
|
try {
|
|
28833
|
-
const mcRaw =
|
|
28834
|
-
const mcConfig =
|
|
29143
|
+
const mcRaw = readFileSync13(paths.magicContextConfig, "utf-8");
|
|
29144
|
+
const mcConfig = import_comment_json9.parse(mcRaw);
|
|
28835
29145
|
const dreamerObj = mcConfig?.dreamer;
|
|
28836
29146
|
const dreamerEnabled = dreamerObj?.enabled === true;
|
|
28837
29147
|
const userMemObj = dreamerObj?.user_memories;
|
|
@@ -28840,6 +29150,15 @@ async function runDoctor(options = {}) {
|
|
|
28840
29150
|
log.warn("dreamer.user_memories is enabled (default) but dreamer itself is disabled — user memory candidates will be collected but never promoted to stable memories. Enable `dreamer.enabled: true` or set `dreamer.user_memories.enabled: false` to silence this.");
|
|
28841
29151
|
issues++;
|
|
28842
29152
|
}
|
|
29153
|
+
const pinKeyFilesObj = dreamerObj?.pin_key_files;
|
|
29154
|
+
if (pinKeyFilesObj?.enabled === true) {
|
|
29155
|
+
const aft = getAftAvailability();
|
|
29156
|
+
if (aft.available) {
|
|
29157
|
+
pass("AFT detected for dreamer.pin_key_files");
|
|
29158
|
+
} else {
|
|
29159
|
+
fail(`dreamer.pin_key_files is enabled but AFT is not configured. Install/register AFT (checked: ${aft.checkedPaths.join(", ")})`);
|
|
29160
|
+
}
|
|
29161
|
+
}
|
|
28843
29162
|
} catch {}
|
|
28844
29163
|
}
|
|
28845
29164
|
const embeddingCheck = await checkEmbeddingConfig(paths.magicContextConfig);
|
|
@@ -28849,7 +29168,7 @@ async function runDoctor(options = {}) {
|
|
|
28849
29168
|
else
|
|
28850
29169
|
passCount++;
|
|
28851
29170
|
const dbPath = join15(getMagicContextStorageDir(), "context.db");
|
|
28852
|
-
if (!
|
|
29171
|
+
if (!existsSync16(dbPath)) {
|
|
28853
29172
|
log.info(`Shared context DB not yet created at ${dbPath} (will be created on first run)`);
|
|
28854
29173
|
} else {
|
|
28855
29174
|
pass(`Shared context DB exists at ${dbPath}`);
|
|
@@ -28910,10 +29229,10 @@ async function runDoctor(options = {}) {
|
|
|
28910
29229
|
}
|
|
28911
29230
|
{
|
|
28912
29231
|
const ageWarnings = [];
|
|
28913
|
-
const npmrcPath = join15(
|
|
28914
|
-
if (
|
|
29232
|
+
const npmrcPath = join15(homedir13(), ".npmrc");
|
|
29233
|
+
if (existsSync16(npmrcPath)) {
|
|
28915
29234
|
try {
|
|
28916
|
-
const npmrc =
|
|
29235
|
+
const npmrc = readFileSync13(npmrcPath, "utf-8");
|
|
28917
29236
|
for (const line of npmrc.split(`
|
|
28918
29237
|
`)) {
|
|
28919
29238
|
const trimmed = line.trim();
|
|
@@ -28936,33 +29255,35 @@ async function runDoctor(options = {}) {
|
|
|
28936
29255
|
issues++;
|
|
28937
29256
|
}
|
|
28938
29257
|
}
|
|
28939
|
-
const logPath =
|
|
28940
|
-
if (
|
|
29258
|
+
const logPath = getMagicContextLogPath2("opencode");
|
|
29259
|
+
if (existsSync16(logPath)) {
|
|
28941
29260
|
const logStat = statSync3(logPath);
|
|
28942
29261
|
const sizeKb = (logStat.size / 1024).toFixed(0);
|
|
28943
29262
|
log.info(`Log file: ${logPath} (${sizeKb} KB)`);
|
|
28944
29263
|
} else {
|
|
28945
29264
|
log.info(`Log file: ${logPath} (not yet created)`);
|
|
28946
29265
|
}
|
|
28947
|
-
const
|
|
28948
|
-
|
|
28949
|
-
|
|
28950
|
-
|
|
28951
|
-
|
|
28952
|
-
|
|
28953
|
-
|
|
28954
|
-
|
|
28955
|
-
|
|
28956
|
-
|
|
28957
|
-
|
|
28958
|
-
|
|
28959
|
-
log.info(` ${dump.name} (${ageStr})`);
|
|
28960
|
-
}
|
|
28961
|
-
if (dumps.length > 3) {
|
|
28962
|
-
log.info(` ... and ${dumps.length - 3} more`);
|
|
28963
|
-
}
|
|
29266
|
+
const diagnostics = await collectDiagnostics();
|
|
29267
|
+
const dumpBuckets = diagnostics.historianDumps.byProject;
|
|
29268
|
+
if (dumpBuckets.length > 0) {
|
|
29269
|
+
const totalCount = dumpBuckets.reduce((sum, b2) => sum + b2.count, 0);
|
|
29270
|
+
const sessionCount = dumpBuckets.length;
|
|
29271
|
+
warn(`Historian debug dumps: ${totalCount} file(s) across ${sessionCount} project(s)`);
|
|
29272
|
+
for (const bucket of dumpBuckets) {
|
|
29273
|
+
log.info(` [${bucket.directory}] ${bucket.count} file(s)`);
|
|
29274
|
+
for (const dump of bucket.recent.slice(0, 3)) {
|
|
29275
|
+
const age = dump.ageMinutes;
|
|
29276
|
+
const ageStr = age < 60 ? `${age}m ago` : `${Math.round(age / 60)}h ago`;
|
|
29277
|
+
log.info(` ${dump.name} (${ageStr})`);
|
|
28964
29278
|
}
|
|
28965
|
-
|
|
29279
|
+
if (bucket.count > 3) {
|
|
29280
|
+
log.info(` ... and ${bucket.count - 3} more`);
|
|
29281
|
+
}
|
|
29282
|
+
}
|
|
29283
|
+
}
|
|
29284
|
+
const legacy = diagnostics.historianDumps.legacyDumps;
|
|
29285
|
+
if (legacy.count > 0) {
|
|
29286
|
+
log.info(`Legacy historian dumps (pre-v0.18.x): ${legacy.count} file(s) in ${legacy.dir}`);
|
|
28966
29287
|
}
|
|
28967
29288
|
if (paths.omoConfig) {
|
|
28968
29289
|
log.info(`OMO config found: ${paths.omoConfig}`);
|
|
@@ -28981,10 +29302,11 @@ async function runDoctor(options = {}) {
|
|
|
28981
29302
|
}
|
|
28982
29303
|
return 0;
|
|
28983
29304
|
}
|
|
28984
|
-
var
|
|
29305
|
+
var import_comment_json9, PLUGIN_NAME6 = "@cortexkit/opencode-magic-context", PLUGIN_ENTRY_WITH_VERSION2, CLI_PACKAGE_NAME = "@cortexkit/magic-context";
|
|
28985
29306
|
var init_doctor_opencode = __esm(async () => {
|
|
28986
29307
|
init_config();
|
|
28987
29308
|
init_variable();
|
|
29309
|
+
init_aft_availability();
|
|
28988
29310
|
init_conflict_detector();
|
|
28989
29311
|
init_conflict_fixer();
|
|
28990
29312
|
init_data_path();
|
|
@@ -28996,9 +29318,10 @@ var init_doctor_opencode = __esm(async () => {
|
|
|
28996
29318
|
init_paths();
|
|
28997
29319
|
init_prompts();
|
|
28998
29320
|
await init_sqlite();
|
|
28999
|
-
|
|
29321
|
+
import_comment_json9 = __toESM(require_src2(), 1);
|
|
29000
29322
|
PLUGIN_ENTRY_WITH_VERSION2 = `${PLUGIN_NAME6}@latest`;
|
|
29001
29323
|
});
|
|
29324
|
+
|
|
29002
29325
|
// ../plugin/src/features/magic-context/compartment-storage.ts
|
|
29003
29326
|
var insertCompartmentStatements, insertFactStatements;
|
|
29004
29327
|
var init_compartment_storage = __esm(() => {
|
|
@@ -29138,7 +29461,7 @@ function binarySearchBytes(sortedArray, key) {
|
|
|
29138
29461
|
}
|
|
29139
29462
|
return -1;
|
|
29140
29463
|
}
|
|
29141
|
-
function
|
|
29464
|
+
function escapeRegex3(str) {
|
|
29142
29465
|
return str.replace(/[\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
29143
29466
|
}
|
|
29144
29467
|
function bytePairMerge(piece, stringRanks, binaryFirstByteIndex) {
|
|
@@ -29248,7 +29571,7 @@ var Tokenizer = class {
|
|
|
29248
29571
|
};
|
|
29249
29572
|
this.specialTokenKeys = Object.keys(this.specialTokens);
|
|
29250
29573
|
this.hasSpecialTokens = this.specialTokenKeys.length > 0;
|
|
29251
|
-
this.specialTokensRegex = this.hasSpecialTokens ? new RegExp(this.specialTokenKeys.map(
|
|
29574
|
+
this.specialTokensRegex = this.hasSpecialTokens ? new RegExp(this.specialTokenKeys.map(escapeRegex3).join("|"), "g") : null;
|
|
29252
29575
|
this.inverseSpecialTokens = {};
|
|
29253
29576
|
for (const [text2, rank] of Object.entries(this.specialTokens))
|
|
29254
29577
|
this.inverseSpecialTokens[rank] = textEncoder.encode(text2);
|
|
@@ -29278,7 +29601,7 @@ var Tokenizer = class {
|
|
|
29278
29601
|
const allowedSet = new Set(allowedSpecial === "all" ? this.specialTokenKeys : allowedSpecial);
|
|
29279
29602
|
const disallowedSet = new Set(disallowedSpecial === "all" ? this.specialTokenKeys.filter((x2) => !allowedSet.has(x2)) : disallowedSpecial);
|
|
29280
29603
|
if (disallowedSet.size > 0) {
|
|
29281
|
-
const disallowedRegex = new RegExp([...disallowedSet].map(
|
|
29604
|
+
const disallowedRegex = new RegExp([...disallowedSet].map(escapeRegex3).join("|"), "g");
|
|
29282
29605
|
const match = text2.match(disallowedRegex);
|
|
29283
29606
|
if (match)
|
|
29284
29607
|
throw new Error(`Text contains disallowed special token: ${match[0]}`);
|
|
@@ -161582,6 +161905,34 @@ function getErrorMessage(error51) {
|
|
|
161582
161905
|
return error51 instanceof Error ? error51.message : String(error51);
|
|
161583
161906
|
}
|
|
161584
161907
|
|
|
161908
|
+
// ../plugin/src/features/magic-context/key-files/project-key-files.ts
|
|
161909
|
+
import { existsSync as existsSync17, readFileSync as readFileSync14, realpathSync } from "node:fs";
|
|
161910
|
+
function deleteOrphanProjectKeyFiles(db, now = Date.now()) {
|
|
161911
|
+
const cutoff = now - ORPHAN_GRACE_MS;
|
|
161912
|
+
const rows = db.prepare(`SELECT project_path AS projectPath, MAX(generated_at) AS lastGen
|
|
161913
|
+
FROM project_key_files
|
|
161914
|
+
GROUP BY project_path
|
|
161915
|
+
HAVING lastGen < ?`).all(cutoff);
|
|
161916
|
+
let deletedProjects = 0;
|
|
161917
|
+
for (const row of rows) {
|
|
161918
|
+
if (existsSync17(row.projectPath))
|
|
161919
|
+
continue;
|
|
161920
|
+
try {
|
|
161921
|
+
db.prepare("DELETE FROM project_key_files WHERE project_path = ?").run(row.projectPath);
|
|
161922
|
+
db.prepare("DELETE FROM project_key_files_version WHERE project_path = ?").run(row.projectPath);
|
|
161923
|
+
deletedProjects++;
|
|
161924
|
+
} catch (error51) {
|
|
161925
|
+
log2(`[key-files] orphan GC failed for ${row.projectPath}:`, error51);
|
|
161926
|
+
}
|
|
161927
|
+
}
|
|
161928
|
+
return deletedProjects;
|
|
161929
|
+
}
|
|
161930
|
+
var ORPHAN_GRACE_MS;
|
|
161931
|
+
var init_project_key_files = __esm(() => {
|
|
161932
|
+
init_logger();
|
|
161933
|
+
ORPHAN_GRACE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
161934
|
+
});
|
|
161935
|
+
|
|
161585
161936
|
// ../plugin/src/features/magic-context/migrations.ts
|
|
161586
161937
|
function ensureMigrationsTable(db) {
|
|
161587
161938
|
db.exec(`
|
|
@@ -161784,6 +162135,9 @@ var init_migrations = __esm(async () => {
|
|
|
161784
162135
|
embedding BLOB NOT NULL,
|
|
161785
162136
|
model_id TEXT NOT NULL,
|
|
161786
162137
|
created_at INTEGER NOT NULL,
|
|
162138
|
+
-- FK-cascade audit (v12): git_commit_embeddings.sha -> git_commits.sha
|
|
162139
|
+
-- uses ON DELETE CASCADE, so SQLite PRAGMA foreign_keys must be ON on
|
|
162140
|
+
-- every connection and v12 cleans historical orphan rows.
|
|
161787
162141
|
FOREIGN KEY(sha) REFERENCES git_commits(sha) ON DELETE CASCADE
|
|
161788
162142
|
);
|
|
161789
162143
|
|
|
@@ -161923,10 +162277,72 @@ var init_migrations = __esm(async () => {
|
|
|
161923
162277
|
db.exec("ALTER TABLE session_meta ADD COLUMN todo_synthetic_state_json TEXT DEFAULT ''");
|
|
161924
162278
|
}
|
|
161925
162279
|
}
|
|
162280
|
+
},
|
|
162281
|
+
{
|
|
162282
|
+
version: 12,
|
|
162283
|
+
description: "Clean orphan rows from FK-cascade embedding tables",
|
|
162284
|
+
up: (db) => {
|
|
162285
|
+
const hasTable = (name2) => Boolean(db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name = ?").get(name2));
|
|
162286
|
+
const memoryEmbeddings = hasTable("memory_embeddings") ? db.prepare(`DELETE FROM memory_embeddings
|
|
162287
|
+
WHERE memory_id NOT IN (SELECT id FROM memories)`).run().changes : 0;
|
|
162288
|
+
log2(`[migrations] v12 cleaned ${memoryEmbeddings} orphan memory_embeddings row(s)`);
|
|
162289
|
+
const gitCommitEmbeddings = hasTable("git_commit_embeddings") ? db.prepare(`DELETE FROM git_commit_embeddings
|
|
162290
|
+
WHERE sha NOT IN (SELECT sha FROM git_commits)`).run().changes : 0;
|
|
162291
|
+
log2(`[migrations] v12 cleaned ${gitCommitEmbeddings} orphan git_commit_embeddings row(s)`);
|
|
162292
|
+
}
|
|
162293
|
+
},
|
|
162294
|
+
{
|
|
162295
|
+
version: 13,
|
|
162296
|
+
description: "Add pending_compaction_marker_state column for deferred marker drain",
|
|
162297
|
+
up: (db) => {
|
|
162298
|
+
const cols = db.prepare("PRAGMA table_info(session_meta)").all();
|
|
162299
|
+
if (!cols.some((c2) => c2.name === "pending_compaction_marker_state")) {
|
|
162300
|
+
db.exec("ALTER TABLE session_meta ADD COLUMN pending_compaction_marker_state TEXT");
|
|
162301
|
+
}
|
|
162302
|
+
}
|
|
162303
|
+
},
|
|
162304
|
+
{
|
|
162305
|
+
version: 14,
|
|
162306
|
+
description: "Add project-scoped key files and version counter",
|
|
162307
|
+
up: (db) => {
|
|
162308
|
+
db.exec(`
|
|
162309
|
+
CREATE TABLE IF NOT EXISTS project_key_files (
|
|
162310
|
+
project_path TEXT NOT NULL,
|
|
162311
|
+
path TEXT NOT NULL,
|
|
162312
|
+
content TEXT NOT NULL,
|
|
162313
|
+
content_hash TEXT NOT NULL,
|
|
162314
|
+
local_token_estimate INTEGER NOT NULL,
|
|
162315
|
+
generated_at INTEGER NOT NULL,
|
|
162316
|
+
generated_by_model TEXT,
|
|
162317
|
+
generation_config_hash TEXT NOT NULL,
|
|
162318
|
+
stale_reason TEXT,
|
|
162319
|
+
PRIMARY KEY (project_path, path)
|
|
162320
|
+
);
|
|
162321
|
+
|
|
162322
|
+
CREATE INDEX IF NOT EXISTS idx_project_key_files_project
|
|
162323
|
+
ON project_key_files(project_path);
|
|
162324
|
+
CREATE INDEX IF NOT EXISTS idx_project_key_files_generated_at
|
|
162325
|
+
ON project_key_files(project_path, generated_at);
|
|
162326
|
+
|
|
162327
|
+
CREATE TABLE IF NOT EXISTS project_key_files_version (
|
|
162328
|
+
project_path TEXT PRIMARY KEY,
|
|
162329
|
+
version INTEGER NOT NULL DEFAULT 0
|
|
162330
|
+
);
|
|
162331
|
+
`);
|
|
162332
|
+
}
|
|
162333
|
+
},
|
|
162334
|
+
{
|
|
162335
|
+
version: 15,
|
|
162336
|
+
description: "Add deferred_execute_state column for boundary execution drain",
|
|
162337
|
+
up: (db) => {
|
|
162338
|
+
const cols = db.prepare("PRAGMA table_info(session_meta)").all();
|
|
162339
|
+
if (!cols.some((c2) => c2.name === "deferred_execute_state")) {
|
|
162340
|
+
db.exec("ALTER TABLE session_meta ADD COLUMN deferred_execute_state TEXT");
|
|
162341
|
+
}
|
|
162342
|
+
}
|
|
161926
162343
|
}
|
|
161927
162344
|
];
|
|
161928
162345
|
});
|
|
161929
|
-
|
|
161930
162346
|
// ../plugin/src/features/magic-context/tool-definition-tokens.ts
|
|
161931
162347
|
function keyFor(providerID, modelID, agentName) {
|
|
161932
162348
|
const agent = agentName && agentName.length > 0 ? agentName : "default";
|
|
@@ -161961,7 +162377,7 @@ var init_tool_definition_tokens = __esm(() => {
|
|
|
161961
162377
|
});
|
|
161962
162378
|
|
|
161963
162379
|
// ../plugin/src/features/magic-context/tool-owner-backfill.ts
|
|
161964
|
-
import { existsSync as
|
|
162380
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
161965
162381
|
import { join as join16 } from "node:path";
|
|
161966
162382
|
function resolveOpencodeDbPath() {
|
|
161967
162383
|
return join16(getDataDir(), "opencode", "opencode.db");
|
|
@@ -161999,7 +162415,7 @@ function runToolOwnerBackfill(db) {
|
|
|
161999
162415
|
return result;
|
|
162000
162416
|
}
|
|
162001
162417
|
const opencodeDbPath = resolveOpencodeDbPath();
|
|
162002
|
-
if (!
|
|
162418
|
+
if (!existsSync18(opencodeDbPath)) {
|
|
162003
162419
|
log2(`[backfill] OpenCode DB not found at ${opencodeDbPath} — marking all unbackfilled sessions as skipped. Lazy adoption (defense-in-depth) handles legacy rows at runtime.`);
|
|
162004
162420
|
markAllUnbackfilledSessionsSkipped(db);
|
|
162005
162421
|
result.sessionsSkippedNoOcDb = countSessionsByStatus(db, "skipped");
|
|
@@ -162209,25 +162625,25 @@ var init_tool_owner_backfill = __esm(() => {
|
|
|
162209
162625
|
});
|
|
162210
162626
|
|
|
162211
162627
|
// ../plugin/src/features/magic-context/storage-db.ts
|
|
162212
|
-
import { copyFileSync, cpSync, existsSync as
|
|
162628
|
+
import { copyFileSync, cpSync, existsSync as existsSync19, mkdirSync as mkdirSync7 } from "node:fs";
|
|
162213
162629
|
import { join as join17 } from "node:path";
|
|
162214
162630
|
function resolveDatabasePath() {
|
|
162215
162631
|
const dbDir = getMagicContextStorageDir();
|
|
162216
162632
|
return { dbDir, dbPath: join17(dbDir, "context.db") };
|
|
162217
162633
|
}
|
|
162218
162634
|
function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
162219
|
-
if (
|
|
162635
|
+
if (existsSync19(targetDbPath))
|
|
162220
162636
|
return;
|
|
162221
162637
|
const legacyDir = getLegacyOpenCodeMagicContextStorageDir();
|
|
162222
162638
|
const legacyDbPath = join17(legacyDir, "context.db");
|
|
162223
|
-
if (!
|
|
162639
|
+
if (!existsSync19(legacyDbPath))
|
|
162224
162640
|
return;
|
|
162225
162641
|
log2(`[magic-context] migrating legacy plugin storage: ${legacyDir} -> ${targetDbDir} (legacy left in place as backup)`);
|
|
162226
162642
|
mkdirSync7(targetDbDir, { recursive: true });
|
|
162227
162643
|
for (const suffix of ["", "-wal", "-shm"]) {
|
|
162228
162644
|
const src = `${legacyDbPath}${suffix}`;
|
|
162229
162645
|
const dst = join17(targetDbDir, `context.db${suffix}`);
|
|
162230
|
-
if (
|
|
162646
|
+
if (existsSync19(src)) {
|
|
162231
162647
|
try {
|
|
162232
162648
|
copyFileSync(src, dst);
|
|
162233
162649
|
} catch (error51) {
|
|
@@ -162237,7 +162653,7 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
|
162237
162653
|
}
|
|
162238
162654
|
const legacyModelsDir = join17(legacyDir, "models");
|
|
162239
162655
|
const targetModelsDir = join17(targetDbDir, "models");
|
|
162240
|
-
if (
|
|
162656
|
+
if (existsSync19(legacyModelsDir) && !existsSync19(targetModelsDir)) {
|
|
162241
162657
|
try {
|
|
162242
162658
|
cpSync(legacyModelsDir, targetModelsDir, { recursive: true });
|
|
162243
162659
|
} catch (error51) {
|
|
@@ -162246,9 +162662,9 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
|
162246
162662
|
}
|
|
162247
162663
|
}
|
|
162248
162664
|
function initializeDatabase(db) {
|
|
162665
|
+
db.exec("PRAGMA foreign_keys=ON");
|
|
162249
162666
|
db.exec("PRAGMA journal_mode=WAL");
|
|
162250
162667
|
db.exec("PRAGMA busy_timeout=5000");
|
|
162251
|
-
db.exec("PRAGMA foreign_keys=ON");
|
|
162252
162668
|
db.exec(`
|
|
162253
162669
|
CREATE TABLE IF NOT EXISTS tags (
|
|
162254
162670
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -162346,6 +162762,9 @@ function initializeDatabase(db) {
|
|
|
162346
162762
|
);
|
|
162347
162763
|
|
|
162348
162764
|
CREATE TABLE IF NOT EXISTS memory_embeddings (
|
|
162765
|
+
-- FK-cascade audit (v12): memory_embeddings.memory_id -> memories.id
|
|
162766
|
+
-- uses ON DELETE CASCADE, so SQLite PRAGMA foreign_keys must be ON on
|
|
162767
|
+
-- every connection and v12 cleans historical orphan rows.
|
|
162349
162768
|
memory_id INTEGER PRIMARY KEY REFERENCES memories(id) ON DELETE CASCADE,
|
|
162350
162769
|
embedding BLOB NOT NULL,
|
|
162351
162770
|
model_id TEXT
|
|
@@ -162382,6 +162801,26 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
162382
162801
|
);
|
|
162383
162802
|
CREATE INDEX IF NOT EXISTS idx_dream_runs_project ON dream_runs(project_path, finished_at DESC);
|
|
162384
162803
|
|
|
162804
|
+
CREATE TABLE IF NOT EXISTS project_key_files (
|
|
162805
|
+
project_path TEXT NOT NULL,
|
|
162806
|
+
path TEXT NOT NULL,
|
|
162807
|
+
content TEXT NOT NULL,
|
|
162808
|
+
content_hash TEXT NOT NULL,
|
|
162809
|
+
local_token_estimate INTEGER NOT NULL,
|
|
162810
|
+
generated_at INTEGER NOT NULL,
|
|
162811
|
+
generated_by_model TEXT,
|
|
162812
|
+
generation_config_hash TEXT NOT NULL,
|
|
162813
|
+
stale_reason TEXT,
|
|
162814
|
+
PRIMARY KEY (project_path, path)
|
|
162815
|
+
);
|
|
162816
|
+
CREATE INDEX IF NOT EXISTS idx_project_key_files_project ON project_key_files(project_path);
|
|
162817
|
+
CREATE INDEX IF NOT EXISTS idx_project_key_files_generated_at ON project_key_files(project_path, generated_at);
|
|
162818
|
+
|
|
162819
|
+
CREATE TABLE IF NOT EXISTS project_key_files_version (
|
|
162820
|
+
project_path TEXT PRIMARY KEY,
|
|
162821
|
+
version INTEGER NOT NULL DEFAULT 0
|
|
162822
|
+
);
|
|
162823
|
+
|
|
162385
162824
|
-- (smart_notes: see note above; merged into unified notes table by migration v1)
|
|
162386
162825
|
|
|
162387
162826
|
CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
|
|
@@ -162453,7 +162892,17 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
162453
162892
|
system_prompt_hash TEXT DEFAULT '',
|
|
162454
162893
|
memory_block_cache TEXT DEFAULT '',
|
|
162455
162894
|
memory_block_count INTEGER DEFAULT 0,
|
|
162456
|
-
memory_block_ids TEXT DEFAULT ''
|
|
162895
|
+
memory_block_ids TEXT DEFAULT '',
|
|
162896
|
+
-- pending_compaction_marker_state: intentionally NULLABLE without a
|
|
162897
|
+
-- default. Absence of a deferred marker is SQL NULL; presence is a
|
|
162898
|
+
-- valid JSON blob written via setPendingCompactionMarkerState.
|
|
162899
|
+
-- Excluded from healNullTextColumns. Readers filter IS NOT NULL AND
|
|
162900
|
+
-- != empty-string defensively. Plan v6 section 3.
|
|
162901
|
+
pending_compaction_marker_state TEXT,
|
|
162902
|
+
-- deferred_execute_state: intentionally NULLABLE without a default.
|
|
162903
|
+
-- Absence is SQL NULL; presence is a JSON blob written via
|
|
162904
|
+
-- setDeferredExecutePendingIfAbsent. Excluded from healNullTextColumns.
|
|
162905
|
+
deferred_execute_state TEXT
|
|
162457
162906
|
);
|
|
162458
162907
|
|
|
162459
162908
|
CREATE INDEX IF NOT EXISTS idx_tags_session_tag_number ON tags(session_id, tag_number);
|
|
@@ -162541,6 +162990,8 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
162541
162990
|
ensureColumn(db, "session_meta", "recomp_partial_range_end", "INTEGER DEFAULT 0");
|
|
162542
162991
|
ensureColumn(db, "session_meta", "detected_context_limit", "INTEGER DEFAULT 0");
|
|
162543
162992
|
ensureColumn(db, "session_meta", "needs_emergency_recovery", "INTEGER DEFAULT 0");
|
|
162993
|
+
ensureColumn(db, "session_meta", "pending_compaction_marker_state", "TEXT");
|
|
162994
|
+
ensureColumn(db, "session_meta", "deferred_execute_state", "TEXT");
|
|
162544
162995
|
ensureColumn(db, "tags", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
162545
162996
|
ensureColumn(db, "pending_ops", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
162546
162997
|
ensureColumn(db, "source_contents", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
@@ -162617,7 +163068,15 @@ function ensureColumn(db, table, column, definition) {
|
|
|
162617
163068
|
if (rows.some((row) => row.name === column)) {
|
|
162618
163069
|
return;
|
|
162619
163070
|
}
|
|
162620
|
-
|
|
163071
|
+
try {
|
|
163072
|
+
db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
|
|
163073
|
+
} catch (err) {
|
|
163074
|
+
const recheck = db.prepare(`PRAGMA table_info(${table})`).all();
|
|
163075
|
+
if (recheck.some((row) => row.name === column)) {
|
|
163076
|
+
return;
|
|
163077
|
+
}
|
|
163078
|
+
throw err;
|
|
163079
|
+
}
|
|
162621
163080
|
}
|
|
162622
163081
|
function openDatabase() {
|
|
162623
163082
|
const { dbDir, dbPath } = resolveDatabasePath();
|
|
@@ -162634,6 +163093,11 @@ function openDatabase() {
|
|
|
162634
163093
|
const db = new Database(dbPath);
|
|
162635
163094
|
initializeDatabase(db);
|
|
162636
163095
|
runMigrations(db);
|
|
163096
|
+
try {
|
|
163097
|
+
deleteOrphanProjectKeyFiles(db);
|
|
163098
|
+
} catch (error51) {
|
|
163099
|
+
log2(`[magic-context] key-files orphan GC failed: ${getErrorMessage(error51)}`);
|
|
163100
|
+
}
|
|
162637
163101
|
try {
|
|
162638
163102
|
runToolOwnerBackfill(db);
|
|
162639
163103
|
} catch (error51) {
|
|
@@ -162669,6 +163133,7 @@ var databases, persistenceByDatabase, persistenceErrorByDatabase;
|
|
|
162669
163133
|
var init_storage_db = __esm(async () => {
|
|
162670
163134
|
init_data_path();
|
|
162671
163135
|
init_logger();
|
|
163136
|
+
init_project_key_files();
|
|
162672
163137
|
init_tool_definition_tokens();
|
|
162673
163138
|
init_tool_owner_backfill();
|
|
162674
163139
|
await __promiseAll([
|
|
@@ -162772,24 +163237,24 @@ var init_storage = __esm(async () => {
|
|
|
162772
163237
|
});
|
|
162773
163238
|
|
|
162774
163239
|
// ../pi-plugin/src/config/index.ts
|
|
162775
|
-
import { existsSync as
|
|
162776
|
-
import { homedir as
|
|
163240
|
+
import { existsSync as existsSync20, readFileSync as readFileSync15 } from "node:fs";
|
|
163241
|
+
import { homedir as homedir14 } from "node:os";
|
|
162777
163242
|
import { join as join18 } from "node:path";
|
|
162778
163243
|
function getProjectConfigPaths(cwd) {
|
|
162779
163244
|
const basePath = join18(cwd, ".pi", CONFIG_FILE_NAME);
|
|
162780
163245
|
return [`${basePath}.jsonc`, `${basePath}.json`];
|
|
162781
163246
|
}
|
|
162782
163247
|
function getUserConfigPaths() {
|
|
162783
|
-
const home = process.env.HOME ??
|
|
163248
|
+
const home = process.env.HOME ?? homedir14();
|
|
162784
163249
|
const basePath = join18(home, ".pi", "agent", CONFIG_FILE_NAME);
|
|
162785
163250
|
return [`${basePath}.jsonc`, `${basePath}.json`];
|
|
162786
163251
|
}
|
|
162787
163252
|
function resolveFirstExisting(paths) {
|
|
162788
|
-
return paths.find((path4) =>
|
|
163253
|
+
return paths.find((path4) => existsSync20(path4));
|
|
162789
163254
|
}
|
|
162790
163255
|
function loadConfigFile2(path4, scope) {
|
|
162791
163256
|
try {
|
|
162792
|
-
const rawText =
|
|
163257
|
+
const rawText = readFileSync15(path4, "utf-8");
|
|
162793
163258
|
const substituted = substituteConfigVariables({
|
|
162794
163259
|
text: rawText,
|
|
162795
163260
|
configPath: path4
|
|
@@ -162797,7 +163262,7 @@ function loadConfigFile2(path4, scope) {
|
|
|
162797
163262
|
return {
|
|
162798
163263
|
path: path4,
|
|
162799
163264
|
scope,
|
|
162800
|
-
config:
|
|
163265
|
+
config: import_comment_json10.parse(substituted.text),
|
|
162801
163266
|
warnings: substituted.warnings.map((warning) => `${path4}: ${warning}`)
|
|
162802
163267
|
};
|
|
162803
163268
|
} catch (error51) {
|
|
@@ -162910,18 +163375,18 @@ function loadPiConfig(opts = {}) {
|
|
|
162910
163375
|
loadedFromPaths: loadedFiles.map((loaded) => loaded.path)
|
|
162911
163376
|
};
|
|
162912
163377
|
}
|
|
162913
|
-
var
|
|
163378
|
+
var import_comment_json10, CONFIG_FILE_NAME = "magic-context";
|
|
162914
163379
|
var init_config2 = __esm(() => {
|
|
162915
163380
|
init_magic_context();
|
|
162916
163381
|
init_variable();
|
|
162917
|
-
|
|
163382
|
+
import_comment_json10 = __toESM(require_src2(), 1);
|
|
162918
163383
|
});
|
|
162919
163384
|
|
|
162920
163385
|
// src/lib/diagnostics-pi.ts
|
|
162921
163386
|
import { createHash } from "node:crypto";
|
|
162922
|
-
import { existsSync as
|
|
163387
|
+
import { existsSync as existsSync21, readdirSync as readdirSync3, readFileSync as readFileSync16, statSync as statSync4 } from "node:fs";
|
|
162923
163388
|
import { createRequire as createRequire5 } from "node:module";
|
|
162924
|
-
import { homedir as
|
|
163389
|
+
import { homedir as homedir15, userInfo as userInfo2 } from "node:os";
|
|
162925
163390
|
import { join as join19 } from "node:path";
|
|
162926
163391
|
function getSelfVersion3() {
|
|
162927
163392
|
const req = createRequire5(import.meta.url);
|
|
@@ -162937,34 +163402,34 @@ function getSelfVersion3() {
|
|
|
162937
163402
|
}
|
|
162938
163403
|
function fileSize2(path4) {
|
|
162939
163404
|
try {
|
|
162940
|
-
return
|
|
163405
|
+
return existsSync21(path4) ? statSync4(path4).size : 0;
|
|
162941
163406
|
} catch {
|
|
162942
163407
|
return 0;
|
|
162943
163408
|
}
|
|
162944
163409
|
}
|
|
162945
|
-
function
|
|
163410
|
+
function escapeRegex4(value) {
|
|
162946
163411
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
162947
163412
|
}
|
|
162948
163413
|
function currentUserHash() {
|
|
162949
|
-
const username =
|
|
163414
|
+
const username = userInfo2().username || "unknown";
|
|
162950
163415
|
return createHash("sha256").update(username).digest("hex").slice(0, 12);
|
|
162951
163416
|
}
|
|
162952
163417
|
function redactSecretString(value) {
|
|
162953
163418
|
return value.replace(/Bearer\s+[A-Za-z0-9._~+\-/=]+/g, "Bearer <REDACTED>").replace(/sk-[A-Za-z0-9_-]{12,}/g, "sk-<REDACTED>").replace(/api[_-]?key=([^\s&]+)/gi, "api_key=<REDACTED>").replace(/token=([^\s&]+)/gi, "token=<REDACTED>");
|
|
162954
163419
|
}
|
|
162955
163420
|
function sanitizeString2(value) {
|
|
162956
|
-
const home = process.env.HOME ||
|
|
162957
|
-
const username =
|
|
163421
|
+
const home = process.env.HOME || homedir15();
|
|
163422
|
+
const username = userInfo2().username;
|
|
162958
163423
|
const userHash = `<USER:${currentUserHash()}>`;
|
|
162959
163424
|
let sanitized = redactSecretString(value);
|
|
162960
163425
|
if (home) {
|
|
162961
|
-
sanitized = sanitized.replace(new RegExp(
|
|
163426
|
+
sanitized = sanitized.replace(new RegExp(escapeRegex4(home), "g"), "<HOME>");
|
|
162962
163427
|
}
|
|
162963
163428
|
sanitized = sanitized.replace(/\/Users\/[^/]+\//g, `/Users/${userHash}/`);
|
|
162964
163429
|
sanitized = sanitized.replace(/\/home\/[^/]+\//g, `/home/${userHash}/`);
|
|
162965
163430
|
sanitized = sanitized.replace(/C:\\Users\\[^\\]+\\/g, `C:\\Users\\${userHash}\\`);
|
|
162966
163431
|
if (username) {
|
|
162967
|
-
sanitized = sanitized.replace(new RegExp(
|
|
163432
|
+
sanitized = sanitized.replace(new RegExp(escapeRegex4(username), "g"), userHash);
|
|
162968
163433
|
}
|
|
162969
163434
|
return sanitized;
|
|
162970
163435
|
}
|
|
@@ -162987,11 +163452,11 @@ function sanitizeValue2(value, key = "") {
|
|
|
162987
163452
|
return value;
|
|
162988
163453
|
}
|
|
162989
163454
|
function readJsonc3(path4) {
|
|
162990
|
-
if (!
|
|
163455
|
+
if (!existsSync21(path4))
|
|
162991
163456
|
return { value: {} };
|
|
162992
163457
|
try {
|
|
162993
163458
|
return {
|
|
162994
|
-
value:
|
|
163459
|
+
value: import_comment_json11.parse(readFileSync16(path4, "utf-8"))
|
|
162995
163460
|
};
|
|
162996
163461
|
} catch (error51) {
|
|
162997
163462
|
return {
|
|
@@ -163007,16 +163472,159 @@ function readConfigDiagnostic(path4) {
|
|
|
163007
163472
|
const parsed = readJsonc3(path4);
|
|
163008
163473
|
return {
|
|
163009
163474
|
path: path4,
|
|
163010
|
-
exists:
|
|
163475
|
+
exists: existsSync21(path4),
|
|
163011
163476
|
...parsed.parseError ? { parseError: parsed.parseError } : {},
|
|
163012
163477
|
flags: sanitizeValue2(parsed.value)
|
|
163013
163478
|
};
|
|
163014
163479
|
}
|
|
163015
163480
|
function packageEntries(settings) {
|
|
163016
|
-
return Array.isArray(settings.packages) ? settings.packages
|
|
163481
|
+
return Array.isArray(settings.packages) ? settings.packages : [];
|
|
163482
|
+
}
|
|
163483
|
+
function reverseSlugToDirectory(slug) {
|
|
163484
|
+
if (!slug.startsWith("--") || !slug.endsWith("--"))
|
|
163485
|
+
return null;
|
|
163486
|
+
const inner = slug.slice(2, -2);
|
|
163487
|
+
if (!inner)
|
|
163488
|
+
return null;
|
|
163489
|
+
return `/${inner.replace(/-/g, "/")}`;
|
|
163490
|
+
}
|
|
163491
|
+
function collectPiRecentSessions() {
|
|
163492
|
+
const sessionsRoot = join19(homedir15(), ".pi", "agent", "sessions");
|
|
163493
|
+
if (!existsSync21(sessionsRoot))
|
|
163494
|
+
return [];
|
|
163495
|
+
try {
|
|
163496
|
+
const slugs = readdirSync3(sessionsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
163497
|
+
const candidates = [];
|
|
163498
|
+
for (const slug of slugs) {
|
|
163499
|
+
const directory = reverseSlugToDirectory(slug);
|
|
163500
|
+
if (!directory)
|
|
163501
|
+
continue;
|
|
163502
|
+
const slugDir = join19(sessionsRoot, slug);
|
|
163503
|
+
let files;
|
|
163504
|
+
try {
|
|
163505
|
+
files = readdirSync3(slugDir).filter((name2) => name2.endsWith(".jsonl"));
|
|
163506
|
+
} catch {
|
|
163507
|
+
continue;
|
|
163508
|
+
}
|
|
163509
|
+
for (const file2 of files) {
|
|
163510
|
+
try {
|
|
163511
|
+
const mtime = statSync4(join19(slugDir, file2)).mtimeMs;
|
|
163512
|
+
const sessionId = file2.replace(/\.jsonl$/, "");
|
|
163513
|
+
candidates.push({ sessionId, directory, mtime });
|
|
163514
|
+
} catch {}
|
|
163515
|
+
}
|
|
163516
|
+
}
|
|
163517
|
+
candidates.sort((a, b2) => b2.mtime - a.mtime);
|
|
163518
|
+
return candidates.slice(0, 5).map((entry) => ({
|
|
163519
|
+
sessionId: entry.sessionId,
|
|
163520
|
+
directory: entry.directory,
|
|
163521
|
+
lastActiveAt: new Date(entry.mtime).toISOString()
|
|
163522
|
+
}));
|
|
163523
|
+
} catch {
|
|
163524
|
+
return [];
|
|
163525
|
+
}
|
|
163526
|
+
}
|
|
163527
|
+
function parseHistorianDumpMeta2(path4) {
|
|
163528
|
+
try {
|
|
163529
|
+
const xml = readFileSync16(path4, "utf-8");
|
|
163530
|
+
const parsed = parseCompartmentOutput(xml);
|
|
163531
|
+
const factCountByCategory = {};
|
|
163532
|
+
for (const fact of parsed.facts) {
|
|
163533
|
+
factCountByCategory[fact.category] = (factCountByCategory[fact.category] ?? 0) + 1;
|
|
163534
|
+
}
|
|
163535
|
+
const starts = parsed.compartments.map((c2) => c2.startMessage);
|
|
163536
|
+
const ends = parsed.compartments.map((c2) => c2.endMessage);
|
|
163537
|
+
let gaps = 0;
|
|
163538
|
+
let overlaps = 0;
|
|
163539
|
+
for (let i = 1;i < parsed.compartments.length; i++) {
|
|
163540
|
+
const prev = parsed.compartments[i - 1];
|
|
163541
|
+
const curr = parsed.compartments[i];
|
|
163542
|
+
if (curr.startMessage > prev.endMessage + 1)
|
|
163543
|
+
gaps += 1;
|
|
163544
|
+
else if (curr.startMessage <= prev.endMessage)
|
|
163545
|
+
overlaps += 1;
|
|
163546
|
+
}
|
|
163547
|
+
return {
|
|
163548
|
+
compartmentCount: parsed.compartments.length,
|
|
163549
|
+
minStart: starts.length > 0 ? Math.min(...starts) : null,
|
|
163550
|
+
maxEnd: ends.length > 0 ? Math.max(...ends) : null,
|
|
163551
|
+
unprocessedFrom: parsed.unprocessedFrom,
|
|
163552
|
+
factCountByCategory,
|
|
163553
|
+
userObservationCount: parsed.userObservations.length,
|
|
163554
|
+
ordinalGapCount: gaps,
|
|
163555
|
+
ordinalOverlapCount: overlaps
|
|
163556
|
+
};
|
|
163557
|
+
} catch (error51) {
|
|
163558
|
+
return { error: error51 instanceof Error ? error51.message : String(error51) };
|
|
163559
|
+
}
|
|
163017
163560
|
}
|
|
163018
|
-
function
|
|
163019
|
-
|
|
163561
|
+
function listDumpsInDir2(dir, limit) {
|
|
163562
|
+
if (!existsSync21(dir))
|
|
163563
|
+
return { count: 0, recent: [] };
|
|
163564
|
+
try {
|
|
163565
|
+
const entries = readdirSync3(dir).filter((name2) => name2.endsWith(".xml")).map((name2) => {
|
|
163566
|
+
const stat = statSync4(join19(dir, name2));
|
|
163567
|
+
return {
|
|
163568
|
+
name: name2,
|
|
163569
|
+
mtime: stat.mtimeMs,
|
|
163570
|
+
sizeKb: Math.round(stat.size / 1024)
|
|
163571
|
+
};
|
|
163572
|
+
}).sort((a, b2) => b2.mtime - a.mtime);
|
|
163573
|
+
const now = Date.now();
|
|
163574
|
+
const recent = entries.slice(0, limit).map((entry) => {
|
|
163575
|
+
const meta3 = parseHistorianDumpMeta2(join19(dir, entry.name));
|
|
163576
|
+
const summary = {
|
|
163577
|
+
name: entry.name,
|
|
163578
|
+
ageMinutes: Math.round((now - entry.mtime) / 60000),
|
|
163579
|
+
sizeKb: entry.sizeKb
|
|
163580
|
+
};
|
|
163581
|
+
if ("error" in meta3) {
|
|
163582
|
+
summary.parseError = meta3.error;
|
|
163583
|
+
} else {
|
|
163584
|
+
summary.meta = meta3;
|
|
163585
|
+
}
|
|
163586
|
+
return summary;
|
|
163587
|
+
});
|
|
163588
|
+
return { count: entries.length, recent };
|
|
163589
|
+
} catch {
|
|
163590
|
+
return { count: 0, recent: [] };
|
|
163591
|
+
}
|
|
163592
|
+
}
|
|
163593
|
+
function collectPiHistorianDumps(recentSessions) {
|
|
163594
|
+
const buckets = new Map;
|
|
163595
|
+
for (const session of recentSessions) {
|
|
163596
|
+
const dir = session.directory;
|
|
163597
|
+
if (!dir)
|
|
163598
|
+
continue;
|
|
163599
|
+
const projectHistorianDir = getProjectMagicContextHistorianDir(dir);
|
|
163600
|
+
const listing = listDumpsInDir2(projectHistorianDir, 5);
|
|
163601
|
+
const existing = buckets.get(dir);
|
|
163602
|
+
if (existing) {
|
|
163603
|
+
if (!existing.sessionIds.includes(session.sessionId)) {
|
|
163604
|
+
existing.sessionIds.push(session.sessionId);
|
|
163605
|
+
}
|
|
163606
|
+
continue;
|
|
163607
|
+
}
|
|
163608
|
+
if (listing.count === 0)
|
|
163609
|
+
continue;
|
|
163610
|
+
buckets.set(dir, {
|
|
163611
|
+
directory: dir,
|
|
163612
|
+
primarySessionId: session.sessionId,
|
|
163613
|
+
sessionIds: [session.sessionId],
|
|
163614
|
+
count: listing.count,
|
|
163615
|
+
recent: listing.recent
|
|
163616
|
+
});
|
|
163617
|
+
}
|
|
163618
|
+
const legacyDir = getMagicContextHistorianDir2("pi");
|
|
163619
|
+
const legacyListing = listDumpsInDir2(legacyDir, 5);
|
|
163620
|
+
return {
|
|
163621
|
+
byProject: [...buckets.values()],
|
|
163622
|
+
legacyDumps: {
|
|
163623
|
+
dir: legacyDir,
|
|
163624
|
+
count: legacyListing.count,
|
|
163625
|
+
recent: legacyListing.recent
|
|
163626
|
+
}
|
|
163627
|
+
};
|
|
163020
163628
|
}
|
|
163021
163629
|
async function collectDiagnostics2(cwd = process.cwd()) {
|
|
163022
163630
|
const pi = detectPiBinary();
|
|
@@ -163028,9 +163636,11 @@ async function collectDiagnostics2(cwd = process.cwd()) {
|
|
|
163028
163636
|
const loaded = loadPiConfig({ cwd });
|
|
163029
163637
|
const storageDirPath = getMagicContextStorageDir();
|
|
163030
163638
|
const dbPath = join19(storageDirPath, "context.db");
|
|
163031
|
-
const logPath =
|
|
163032
|
-
const logFileSize =
|
|
163033
|
-
const otherPiExtensions = packages.filter((entry) => !
|
|
163639
|
+
const logPath = getMagicContextLogPath2("pi");
|
|
163640
|
+
const logFileSize = existsSync21(logPath) ? statSync4(logPath).size : 0;
|
|
163641
|
+
const otherPiExtensions = packages.filter((entry) => !isPiMagicContextPackageEntry(entry)).map(describePiPackageEntry);
|
|
163642
|
+
const recentSessions = collectPiRecentSessions();
|
|
163643
|
+
const historianDumps = collectPiHistorianDumps(recentSessions);
|
|
163034
163644
|
return {
|
|
163035
163645
|
timestamp: new Date().toISOString(),
|
|
163036
163646
|
platform: process.platform,
|
|
@@ -163042,10 +163652,10 @@ async function collectDiagnostics2(cwd = process.cwd()) {
|
|
|
163042
163652
|
piVersion: pi ? getPiVersion(pi.path) : null,
|
|
163043
163653
|
settings: {
|
|
163044
163654
|
path: settingsPath,
|
|
163045
|
-
exists:
|
|
163655
|
+
exists: existsSync21(settingsPath),
|
|
163046
163656
|
...settingsParsed.parseError ? { parseError: settingsParsed.parseError } : {},
|
|
163047
|
-
hasMagicContextPackage:
|
|
163048
|
-
packages: packages
|
|
163657
|
+
hasMagicContextPackage: hasPiMagicContextPackage(packages),
|
|
163658
|
+
packages: sanitizeValue2(packages)
|
|
163049
163659
|
},
|
|
163050
163660
|
configPaths: {
|
|
163051
163661
|
agentDir: getPiAgentConfigDir(),
|
|
@@ -163058,7 +163668,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
|
|
|
163058
163668
|
loadWarnings: loaded.warnings.map(sanitizeString2),
|
|
163059
163669
|
storageDir: {
|
|
163060
163670
|
path: storageDirPath,
|
|
163061
|
-
exists:
|
|
163671
|
+
exists: existsSync21(storageDirPath),
|
|
163062
163672
|
contextDbSizeBytes: fileSize2(dbPath)
|
|
163063
163673
|
},
|
|
163064
163674
|
conflicts: {
|
|
@@ -163067,9 +163677,11 @@ async function collectDiagnostics2(cwd = process.cwd()) {
|
|
|
163067
163677
|
},
|
|
163068
163678
|
logFile: {
|
|
163069
163679
|
path: logPath,
|
|
163070
|
-
exists:
|
|
163680
|
+
exists: existsSync21(logPath),
|
|
163071
163681
|
sizeKb: Math.round(logFileSize / 1024)
|
|
163072
|
-
}
|
|
163682
|
+
},
|
|
163683
|
+
recentSessions,
|
|
163684
|
+
historianDumps
|
|
163073
163685
|
};
|
|
163074
163686
|
}
|
|
163075
163687
|
function formatBytes2(bytes) {
|
|
@@ -163146,17 +163758,19 @@ function renderDiagnosticsMarkdown2(report) {
|
|
|
163146
163758
|
].join(`
|
|
163147
163759
|
`);
|
|
163148
163760
|
}
|
|
163149
|
-
var
|
|
163761
|
+
var import_comment_json11;
|
|
163150
163762
|
var init_diagnostics_pi = __esm(() => {
|
|
163763
|
+
init_compartment_parser();
|
|
163151
163764
|
init_data_path();
|
|
163152
163765
|
init_config2();
|
|
163153
163766
|
init_paths();
|
|
163154
163767
|
init_pi_helpers();
|
|
163155
|
-
|
|
163768
|
+
init_pi_package_entry();
|
|
163769
|
+
import_comment_json11 = __toESM(require_src2(), 1);
|
|
163156
163770
|
});
|
|
163157
163771
|
|
|
163158
163772
|
// src/lib/logs-pi.ts
|
|
163159
|
-
import { readFileSync as
|
|
163773
|
+
import { readFileSync as readFileSync17, writeFileSync as writeFileSync11 } from "node:fs";
|
|
163160
163774
|
import { join as join20 } from "node:path";
|
|
163161
163775
|
function sanitizeLogContent2(content) {
|
|
163162
163776
|
return sanitizeString2(content);
|
|
@@ -163173,9 +163787,21 @@ function formatTimestamp2(date5) {
|
|
|
163173
163787
|
pad(date5.getSeconds())
|
|
163174
163788
|
].join("");
|
|
163175
163789
|
}
|
|
163790
|
+
function filterLogLinesBySession2(lines, sessionId) {
|
|
163791
|
+
if (!sessionId)
|
|
163792
|
+
return lines;
|
|
163793
|
+
const otherSessionPattern = /\bses_[A-Za-z0-9]{8,32}\b/g;
|
|
163794
|
+
return lines.filter((line) => {
|
|
163795
|
+
const matches = line.match(otherSessionPattern);
|
|
163796
|
+
if (!matches)
|
|
163797
|
+
return true;
|
|
163798
|
+
return matches.every((id) => id === sessionId);
|
|
163799
|
+
});
|
|
163800
|
+
}
|
|
163176
163801
|
async function bundleIssueReport2(report, description, title, options = {}) {
|
|
163177
163802
|
const LOG_TAIL_LINES = 400;
|
|
163178
|
-
const
|
|
163803
|
+
const allLogLines = report.logFile.exists ? readFileSync17(report.logFile.path, "utf-8").split(/\r?\n/) : [];
|
|
163804
|
+
const logLines = filterLogLinesBySession2(allLogLines, options.sessionFilter ?? null);
|
|
163179
163805
|
const recentLog = sanitizeLogContent2(logLines.slice(-LOG_TAIL_LINES).join(`
|
|
163180
163806
|
`)).trim();
|
|
163181
163807
|
const bodyMarkdown = [
|
|
@@ -163213,16 +163839,16 @@ var init_logs_pi = __esm(() => {
|
|
|
163213
163839
|
// src/commands/doctor-pi.ts
|
|
163214
163840
|
import { execFileSync as execFileSync4, spawnSync as spawnSync3 } from "node:child_process";
|
|
163215
163841
|
import {
|
|
163216
|
-
existsSync as
|
|
163842
|
+
existsSync as existsSync22,
|
|
163217
163843
|
mkdirSync as mkdirSync8,
|
|
163218
163844
|
readdirSync as readdirSync4,
|
|
163219
|
-
readFileSync as
|
|
163845
|
+
readFileSync as readFileSync18,
|
|
163220
163846
|
rmSync as rmSync2,
|
|
163221
163847
|
statSync as statSync5,
|
|
163222
163848
|
writeFileSync as writeFileSync12
|
|
163223
163849
|
} from "node:fs";
|
|
163224
163850
|
import { createRequire as createRequire6 } from "node:module";
|
|
163225
|
-
import { homedir as
|
|
163851
|
+
import { homedir as homedir16 } from "node:os";
|
|
163226
163852
|
import { dirname as dirname9, join as join21 } from "node:path";
|
|
163227
163853
|
function depsFrom(options) {
|
|
163228
163854
|
return {
|
|
@@ -163310,7 +163936,7 @@ function summarize(results) {
|
|
|
163310
163936
|
function readJsonc4(path4) {
|
|
163311
163937
|
try {
|
|
163312
163938
|
return {
|
|
163313
|
-
value:
|
|
163939
|
+
value: import_comment_json12.parse(readFileSync18(path4, "utf-8"))
|
|
163314
163940
|
};
|
|
163315
163941
|
} catch (error51) {
|
|
163316
163942
|
return {
|
|
@@ -163320,24 +163946,21 @@ function readJsonc4(path4) {
|
|
|
163320
163946
|
}
|
|
163321
163947
|
}
|
|
163322
163948
|
function packagesFrom(settings) {
|
|
163323
|
-
return Array.isArray(settings.packages) ? settings.packages
|
|
163324
|
-
}
|
|
163325
|
-
function hasPiPackage(packages) {
|
|
163326
|
-
return packages.some((entry) => entry === PI_PACKAGE_SOURCE || entry === PACKAGE_NAME2 || entry.includes("pi-magic-context"));
|
|
163949
|
+
return Array.isArray(settings.packages) ? settings.packages : [];
|
|
163327
163950
|
}
|
|
163328
163951
|
function projectConfigPath(cwd) {
|
|
163329
163952
|
return join21(cwd, ".pi", "magic-context.jsonc");
|
|
163330
163953
|
}
|
|
163331
163954
|
function readConfigForEmbedding(path4) {
|
|
163332
|
-
if (!
|
|
163955
|
+
if (!existsSync22(path4))
|
|
163333
163956
|
return null;
|
|
163334
163957
|
try {
|
|
163335
|
-
const rawText =
|
|
163958
|
+
const rawText = readFileSync18(path4, "utf-8");
|
|
163336
163959
|
const substituted = substituteConfigVariables({
|
|
163337
163960
|
text: rawText,
|
|
163338
163961
|
configPath: path4
|
|
163339
163962
|
});
|
|
163340
|
-
return
|
|
163963
|
+
return import_comment_json12.parse(substituted.text);
|
|
163341
163964
|
} catch {
|
|
163342
163965
|
return null;
|
|
163343
163966
|
}
|
|
@@ -163390,7 +164013,7 @@ function countTable(db, table) {
|
|
|
163390
164013
|
}
|
|
163391
164014
|
}
|
|
163392
164015
|
function cacheRoots() {
|
|
163393
|
-
const home =
|
|
164016
|
+
const home = homedir16();
|
|
163394
164017
|
const cacheHome = process.env.XDG_CACHE_HOME || join21(home, ".cache");
|
|
163395
164018
|
return [
|
|
163396
164019
|
join21(home, ".pi", "cache", "extensions"),
|
|
@@ -163403,7 +164026,7 @@ function cacheRoots() {
|
|
|
163403
164026
|
function findPiMagicContextCacheDirs(self, force = false) {
|
|
163404
164027
|
const found = new Map;
|
|
163405
164028
|
const visit = (path4, depth) => {
|
|
163406
|
-
if (depth < 0 || !
|
|
164029
|
+
if (depth < 0 || !existsSync22(path4))
|
|
163407
164030
|
return;
|
|
163408
164031
|
let stat;
|
|
163409
164032
|
try {
|
|
@@ -163414,12 +164037,12 @@ function findPiMagicContextCacheDirs(self, force = false) {
|
|
|
163414
164037
|
if (!stat.isDirectory())
|
|
163415
164038
|
return;
|
|
163416
164039
|
const packageJson = join21(path4, "package.json");
|
|
163417
|
-
if (
|
|
164040
|
+
if (existsSync22(packageJson)) {
|
|
163418
164041
|
try {
|
|
163419
|
-
const pkg = JSON.parse(
|
|
164042
|
+
const pkg = JSON.parse(readFileSync18(packageJson, "utf-8"));
|
|
163420
164043
|
const name2 = typeof pkg.name === "string" ? pkg.name : "";
|
|
163421
164044
|
const version2 = typeof pkg.version === "string" ? pkg.version : undefined;
|
|
163422
|
-
if (name2 ===
|
|
164045
|
+
if (name2 === PACKAGE_NAME || path4.includes("pi-magic-context")) {
|
|
163423
164046
|
if (force || !version2 || version2 !== self)
|
|
163424
164047
|
found.set(path4, { path: path4, version: version2 });
|
|
163425
164048
|
}
|
|
@@ -163457,7 +164080,7 @@ async function runHealthChecks(options) {
|
|
|
163457
164080
|
add(results, "pass", version2 ? `Pi ${version2} detected at ${pi.path}` : `Pi detected at ${pi.path}`);
|
|
163458
164081
|
const compare = compareSemver(version2, MIN_PI_VERSION);
|
|
163459
164082
|
if (compare !== null && compare < 0) {
|
|
163460
|
-
add(results, "fail", `Pi ${version2} is older than required ${MIN_PI_VERSION}. Subagents (historian/dreamer/sidekick) use the long-form \`--extension\` flag introduced in Pi 0.71.0; older versions hard-fail with "Unknown option". Run \`pi update\` (or \`npm install -g @
|
|
164083
|
+
add(results, "fail", `Pi ${version2} is older than required ${MIN_PI_VERSION}. Subagents (historian/dreamer/sidekick) use the long-form \`--extension\` flag introduced in Pi 0.71.0; older versions hard-fail with "Unknown option". Run \`pi update\` (or \`npm install -g @earendil-works/pi-coding-agent@latest\`).`);
|
|
163461
164084
|
} else if (version2) {
|
|
163462
164085
|
add(results, "pass", `Pi version meets minimum ${MIN_PI_VERSION} requirement`);
|
|
163463
164086
|
}
|
|
@@ -163472,7 +164095,7 @@ async function runHealthChecks(options) {
|
|
|
163472
164095
|
}
|
|
163473
164096
|
const settingsPath = getPiUserExtensionsPath();
|
|
163474
164097
|
let packages = [];
|
|
163475
|
-
if (!
|
|
164098
|
+
if (!existsSync22(settingsPath)) {
|
|
163476
164099
|
add(results, "warn", `Pi settings not found at ${settingsPath}`);
|
|
163477
164100
|
repairPlan.addPackageEntry = true;
|
|
163478
164101
|
} else {
|
|
@@ -163482,7 +164105,7 @@ async function runHealthChecks(options) {
|
|
|
163482
164105
|
} else {
|
|
163483
164106
|
packages = packagesFrom(parsed.value);
|
|
163484
164107
|
add(results, "pass", `Pi settings found at ${settingsPath}`);
|
|
163485
|
-
if (
|
|
164108
|
+
if (hasPiMagicContextPackage(packages)) {
|
|
163486
164109
|
add(results, "pass", `${PI_PACKAGE_SOURCE} is registered in packages[]`);
|
|
163487
164110
|
} else {
|
|
163488
164111
|
add(results, "warn", `${PI_PACKAGE_SOURCE} is missing from packages[]`);
|
|
@@ -163496,7 +164119,7 @@ async function runHealthChecks(options) {
|
|
|
163496
164119
|
["user", userConfigPath, true],
|
|
163497
164120
|
["project", projectPath, false]
|
|
163498
164121
|
]) {
|
|
163499
|
-
if (!
|
|
164122
|
+
if (!existsSync22(path4)) {
|
|
163500
164123
|
if (required2) {
|
|
163501
164124
|
add(results, "warn", `No ${label} magic-context.jsonc found at ${path4}`);
|
|
163502
164125
|
repairPlan.writeUserConfig = true;
|
|
@@ -163530,7 +164153,7 @@ async function runHealthChecks(options) {
|
|
|
163530
164153
|
}
|
|
163531
164154
|
const storageDir = getMagicContextStorageDir();
|
|
163532
164155
|
const dbPath = join21(storageDir, "context.db");
|
|
163533
|
-
const existedBeforeOpen =
|
|
164156
|
+
const existedBeforeOpen = existsSync22(dbPath);
|
|
163534
164157
|
if (existedBeforeOpen)
|
|
163535
164158
|
add(results, "pass", `Shared context DB exists at ${dbPath}`);
|
|
163536
164159
|
else
|
|
@@ -163587,13 +164210,13 @@ async function runHealthChecks(options) {
|
|
|
163587
164210
|
} else {
|
|
163588
164211
|
add(results, "pass", `Embedding provider: ${loadedConfig.config.embedding.provider}`);
|
|
163589
164212
|
}
|
|
163590
|
-
const piEntries = packages.filter(
|
|
164213
|
+
const piEntries = packages.filter(isPiMagicContextPackageEntry).map(describePiPackageEntry);
|
|
163591
164214
|
if (piEntries.length > 1) {
|
|
163592
164215
|
add(results, "fail", `Multiple magic-context entries in Pi packages[] — this loads the plugin twice: ${piEntries.join(", ")}`);
|
|
163593
164216
|
} else {
|
|
163594
164217
|
add(results, "pass", "No conflicting magic-context entries in Pi packages[]");
|
|
163595
164218
|
}
|
|
163596
|
-
const otherExtensions = packages.filter((entry) => !
|
|
164219
|
+
const otherExtensions = packages.filter((entry) => !isPiMagicContextPackageEntry(entry)).map(describePiPackageEntry);
|
|
163597
164220
|
if (otherExtensions.length > 0) {
|
|
163598
164221
|
add(results, "info", `Other Pi extensions registered: ${otherExtensions.join(", ")}`);
|
|
163599
164222
|
} else {
|
|
@@ -163606,32 +164229,36 @@ async function runHealthChecks(options) {
|
|
|
163606
164229
|
} else {
|
|
163607
164230
|
add(results, "pass", "Pi extension cache clean (no stale cached package found)");
|
|
163608
164231
|
}
|
|
163609
|
-
const logPath =
|
|
163610
|
-
if (
|
|
164232
|
+
const logPath = getMagicContextLogPath2("pi");
|
|
164233
|
+
if (existsSync22(logPath)) {
|
|
163611
164234
|
const stat = statSync5(logPath);
|
|
163612
164235
|
const sizeKb = (stat.size / 1024).toFixed(0);
|
|
163613
|
-
const lines =
|
|
164236
|
+
const lines = readFileSync18(logPath, "utf-8").split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
163614
164237
|
add(results, "info", `Log file: ${logPath} (${sizeKb} KB)`);
|
|
163615
164238
|
add(results, "info", `Last plugin log line: ${lines.at(-1) ?? "<empty log>"}`);
|
|
163616
164239
|
} else {
|
|
163617
164240
|
add(results, "info", `No plugin log file yet at ${logPath}`);
|
|
163618
164241
|
}
|
|
163619
|
-
const
|
|
163620
|
-
|
|
163621
|
-
|
|
163622
|
-
|
|
163623
|
-
|
|
163624
|
-
|
|
163625
|
-
|
|
163626
|
-
|
|
163627
|
-
|
|
163628
|
-
|
|
163629
|
-
}
|
|
163630
|
-
if (dumps.length > 3) {
|
|
163631
|
-
add(results, "info", ` ... and ${dumps.length - 3} more`);
|
|
163632
|
-
}
|
|
164242
|
+
const diagnosticsForDumps = await collectDiagnostics2(options.cwd);
|
|
164243
|
+
const dumpBuckets = diagnosticsForDumps.historianDumps.byProject;
|
|
164244
|
+
if (dumpBuckets.length > 0) {
|
|
164245
|
+
const totalCount = dumpBuckets.reduce((sum, b2) => sum + b2.count, 0);
|
|
164246
|
+
add(results, "warn", `Historian debug dumps: ${totalCount} file(s) across ${dumpBuckets.length} project(s)`);
|
|
164247
|
+
for (const bucket of dumpBuckets) {
|
|
164248
|
+
add(results, "info", ` [${bucket.directory}] ${bucket.count} file(s)`);
|
|
164249
|
+
for (const dump of bucket.recent.slice(0, 3)) {
|
|
164250
|
+
const age = dump.ageMinutes;
|
|
164251
|
+
const ageStr = age < 60 ? `${age}m ago` : `${Math.round(age / 60)}h ago`;
|
|
164252
|
+
add(results, "info", ` ${dump.name} (${ageStr})`);
|
|
163633
164253
|
}
|
|
163634
|
-
|
|
164254
|
+
if (bucket.count > 3) {
|
|
164255
|
+
add(results, "info", ` ... and ${bucket.count - 3} more`);
|
|
164256
|
+
}
|
|
164257
|
+
}
|
|
164258
|
+
}
|
|
164259
|
+
const legacyDumps = diagnosticsForDumps.historianDumps.legacyDumps;
|
|
164260
|
+
if (legacyDumps.count > 0) {
|
|
164261
|
+
add(results, "info", `Legacy historian dumps (pre-v0.18.x): ${legacyDumps.count} file(s) in ${legacyDumps.dir}`);
|
|
163635
164262
|
}
|
|
163636
164263
|
if (!options.quiet) {
|
|
163637
164264
|
for (const result of results)
|
|
@@ -163645,7 +164272,7 @@ function writeDefaultMagicContextConfig(path4) {
|
|
|
163645
164272
|
$schema: "https://raw.githubusercontent.com/cortexkit/magic-context/master/assets/magic-context.schema.json",
|
|
163646
164273
|
...MagicContextConfigSchema.parse({})
|
|
163647
164274
|
};
|
|
163648
|
-
writeFileSync12(path4, `${
|
|
164275
|
+
writeFileSync12(path4, `${import_comment_json12.stringify(config2, null, 2)}
|
|
163649
164276
|
`);
|
|
163650
164277
|
}
|
|
163651
164278
|
function repair(plan, prompts) {
|
|
@@ -163662,7 +164289,7 @@ function repair(plan, prompts) {
|
|
|
163662
164289
|
}
|
|
163663
164290
|
if (plan.writeUserConfig) {
|
|
163664
164291
|
const configPath = getPiUserConfigPath();
|
|
163665
|
-
if (!
|
|
164292
|
+
if (!existsSync22(configPath)) {
|
|
163666
164293
|
try {
|
|
163667
164294
|
writeDefaultMagicContextConfig(configPath);
|
|
163668
164295
|
prompts.log.success(`Wrote default Magic Context config to ${configPath}`);
|
|
@@ -163710,9 +164337,26 @@ async function runIssueFlow2(options) {
|
|
|
163710
164337
|
spinner2.start("Collecting sanitized Pi diagnostics");
|
|
163711
164338
|
try {
|
|
163712
164339
|
const report = await options.deps.collectDiagnostics(options.cwd);
|
|
164340
|
+
spinner2.stop("Diagnostics collected");
|
|
164341
|
+
let sessionFilter = null;
|
|
164342
|
+
if (report.recentSessions.length > 1) {
|
|
164343
|
+
const choice = await options.prompts.selectOne("Which Pi session is this issue about? (filters log lines from other sessions)", [
|
|
164344
|
+
...report.recentSessions.map((session, index) => ({
|
|
164345
|
+
label: `${session.directory} — ${session.sessionId}${index === 0 ? " (most recent)" : ""}`,
|
|
164346
|
+
value: session.sessionId
|
|
164347
|
+
})),
|
|
164348
|
+
{
|
|
164349
|
+
label: "All sessions (no filtering)",
|
|
164350
|
+
value: "__all__"
|
|
164351
|
+
}
|
|
164352
|
+
]);
|
|
164353
|
+
sessionFilter = choice === "__all__" ? null : choice;
|
|
164354
|
+
}
|
|
164355
|
+
spinner2.start("Bundling Pi issue report");
|
|
163713
164356
|
const bundled = await bundleIssueReport2(report, description, title, {
|
|
163714
164357
|
cwd: options.cwd,
|
|
163715
|
-
now: options.deps.now()
|
|
164358
|
+
now: options.deps.now(),
|
|
164359
|
+
sessionFilter
|
|
163716
164360
|
});
|
|
163717
164361
|
spinner2.stop(`Report written to ${bundled.path}`);
|
|
163718
164362
|
if (ghAvailableAndAuthed(options.deps)) {
|
|
@@ -163787,7 +164431,7 @@ function parseDoctorArgs(args) {
|
|
|
163787
164431
|
function doctor(args = []) {
|
|
163788
164432
|
return runDoctor2(parseDoctorArgs(args));
|
|
163789
164433
|
}
|
|
163790
|
-
var
|
|
164434
|
+
var import_comment_json12, PACKAGE_NAME = "@cortexkit/pi-magic-context", MIN_PI_VERSION = "0.74.0", ROW_COUNT_TABLES, DEFAULT_DEPS;
|
|
163791
164435
|
var init_doctor_pi = __esm(async () => {
|
|
163792
164436
|
init_magic_context();
|
|
163793
164437
|
init_variable();
|
|
@@ -163797,17 +164441,18 @@ var init_doctor_pi = __esm(async () => {
|
|
|
163797
164441
|
init_logs_pi();
|
|
163798
164442
|
init_paths();
|
|
163799
164443
|
init_pi_helpers();
|
|
164444
|
+
init_pi_package_entry();
|
|
163800
164445
|
init_prompts();
|
|
163801
164446
|
init_setup_pi();
|
|
163802
164447
|
await init_storage();
|
|
163803
|
-
|
|
164448
|
+
import_comment_json12 = __toESM(require_src2(), 1);
|
|
163804
164449
|
ROW_COUNT_TABLES = ["tags", "compartments", "memories", "notes", "dream_runs"];
|
|
163805
164450
|
DEFAULT_DEPS = {
|
|
163806
164451
|
prompts: promptIO,
|
|
163807
164452
|
collectDiagnostics: collectDiagnostics2,
|
|
163808
164453
|
detectPiBinary,
|
|
163809
164454
|
getPiVersion,
|
|
163810
|
-
getLatestNpmVersion: () => getLatestNpmVersion(
|
|
164455
|
+
getLatestNpmVersion: () => getLatestNpmVersion(PACKAGE_NAME),
|
|
163811
164456
|
probeEmbeddingEndpoint,
|
|
163812
164457
|
openDatabase,
|
|
163813
164458
|
isDatabasePersisted,
|
|
@@ -163823,7 +164468,7 @@ var exports_doctor = {};
|
|
|
163823
164468
|
__export(exports_doctor, {
|
|
163824
164469
|
runDoctor: () => runDoctor3
|
|
163825
164470
|
});
|
|
163826
|
-
import { existsSync as
|
|
164471
|
+
import { existsSync as existsSync23, rmSync as rmSync3 } from "node:fs";
|
|
163827
164472
|
async function runDoctor3(options) {
|
|
163828
164473
|
if (options.clear)
|
|
163829
164474
|
return runClear();
|
|
@@ -163907,7 +164552,7 @@ async function runClear() {
|
|
|
163907
164552
|
const s = spinner();
|
|
163908
164553
|
s.start(`Clearing ${item.path}`);
|
|
163909
164554
|
try {
|
|
163910
|
-
if (
|
|
164555
|
+
if (existsSync23(item.path)) {
|
|
163911
164556
|
rmSync3(item.path, { recursive: true, force: true });
|
|
163912
164557
|
}
|
|
163913
164558
|
s.stop(`Cleared ${item.path}`);
|