@cortexkit/magic-context 0.43.1 → 0.43.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +940 -391
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4203,6 +4203,10 @@ function getOpenCodePluginCacheDir() {
4203
4203
  const xdg = process.env.XDG_CACHE_HOME || join5(homedir3(), ".cache");
4204
4204
  return join5(xdg, "opencode", "packages");
4205
4205
  }
4206
+ function getOpenCodeV2NpmCacheDir() {
4207
+ const xdg = process.env.XDG_CACHE_HOME || join5(homedir3(), ".cache");
4208
+ return join5(xdg, "opencode", "npm");
4209
+ }
4206
4210
  function isDir(path) {
4207
4211
  try {
4208
4212
  return statSync3(path).isDirectory();
@@ -4603,7 +4607,7 @@ class OmpAdapter {
4603
4607
  }
4604
4608
  getPluginCacheInfo() {
4605
4609
  const path = join8(getOmpPluginsDir(), "cache");
4606
- return { path, exists: existsSync6(path), sizeBytes: dirSizeBytes(path) };
4610
+ return [{ path, exists: existsSync6(path), sizeBytes: dirSizeBytes(path) }];
4607
4611
  }
4608
4612
  getLogPath() {
4609
4613
  return getMagicContextLogPath2("omp");
@@ -4646,7 +4650,7 @@ var init_omp = __esm(() => {
4646
4650
  // ../plugin/src/shared/opencode-db-path.ts
4647
4651
  import { existsSync as existsSync7, readdirSync as readdirSync2, statSync as statSync4 } from "node:fs";
4648
4652
  import { homedir as homedir6 } from "node:os";
4649
- import { isAbsolute as isAbsolute3, join as join9 } from "node:path";
4653
+ import { isAbsolute as isAbsolute3, join as join9, resolve as resolve3 } from "node:path";
4650
4654
  function openCodeHostGenerationFromVersion(version) {
4651
4655
  const text = version ?? "";
4652
4656
  if (/(?:^|\s|v)0\.0\.0-(?:beta|dev)-/.test(text))
@@ -4733,7 +4737,7 @@ function resolveV2Fresh(dataDir, channel, env) {
4733
4737
  const filename = sourceOpenCodeDatabaseFilename("v2", channel, env);
4734
4738
  const explicit = env.OPENCODE_DB !== undefined;
4735
4739
  return {
4736
- path: filename === ":memory:" ? filename : join9(dataDir, filename),
4740
+ path: filename === ":memory:" ? filename : resolve3(dataDir, filename),
4737
4741
  source: explicit ? "OPENCODE_DB" : env.OPENCODE_CHANNEL ? "channel" : "default",
4738
4742
  channel: explicit ? null : channel
4739
4743
  };
@@ -12652,6 +12656,323 @@ var require_src3 = __commonJS(function(exports, module) {
12652
12656
  };
12653
12657
  });
12654
12658
 
12659
+ // ../plugin/src/hooks/auto-update-checker/semver.ts
12660
+ function isValidSemver(version) {
12661
+ return /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(version);
12662
+ }
12663
+ function compareSemverCore(a, b) {
12664
+ if (!isValidSemver(a) || !isValidSemver(b))
12665
+ return null;
12666
+ const core = (v) => v.split(/[-+]/, 1)[0].split(".").map((n) => Number.parseInt(n, 10));
12667
+ const [a0, a1, a2] = core(a);
12668
+ const [b0, b1, b2] = core(b);
12669
+ return a0 - b0 || a1 - b1 || a2 - b2;
12670
+ }
12671
+
12672
+ // src/lib/opencode-plugin-registration.ts
12673
+ function pluginConfigKeyFor(hostGeneration) {
12674
+ return hostGeneration === "v2" ? "plugins" : "plugin";
12675
+ }
12676
+ function readPluginEntries(config) {
12677
+ const out = [];
12678
+ for (const key of OPENCODE_PLUGIN_CONFIG_KEYS) {
12679
+ const list = config?.[key];
12680
+ if (!Array.isArray(list))
12681
+ continue;
12682
+ for (const [index, entry] of list.entries())
12683
+ out.push({ key, index, entry });
12684
+ }
12685
+ return out;
12686
+ }
12687
+ var OPENCODE_PLUGIN_CONFIG_KEYS;
12688
+ var init_opencode_plugin_registration = __esm(() => {
12689
+ OPENCODE_PLUGIN_CONFIG_KEYS = ["plugin", "plugins"];
12690
+ });
12691
+
12692
+ // src/lib/opencode-plugin-cache.ts
12693
+ import { readdirSync as readdirSync3, readFileSync as readFileSync5 } from "node:fs";
12694
+ import { join as join10 } from "node:path";
12695
+ function getOpenCodePluginCacheRoots() {
12696
+ const cacheDir = getOpenCodePluginCacheDir();
12697
+ return [
12698
+ join10(cacheDir, OPENCODE_PLUGIN_ENTRY_WITH_VERSION),
12699
+ join10(cacheDir, OPENCODE_PLUGIN_NAME)
12700
+ ];
12701
+ }
12702
+ function getOpenCodePluginPackageJsonPath(pluginCacheRoot) {
12703
+ return join10(pluginCacheRoot, "node_modules", ...OPENCODE_PLUGIN_NAME.split("/"), "package.json");
12704
+ }
12705
+ function getOpenCodePluginPackageJsonPaths() {
12706
+ return getOpenCodePluginCacheRoots().map(getOpenCodePluginPackageJsonPath);
12707
+ }
12708
+ function getOpenCodeV2PluginCacheSlot(npmCacheDir = getOpenCodeV2NpmCacheDir(), spec = "latest") {
12709
+ return join10(npmCacheDir, ...`${OPENCODE_PLUGIN_NAME}@${spec}`.split("/"));
12710
+ }
12711
+ function openCodeV2PluginSpecOf(specifier) {
12712
+ if (specifier === OPENCODE_PLUGIN_NAME)
12713
+ return "latest";
12714
+ const prefix = `${OPENCODE_PLUGIN_NAME}@`;
12715
+ if (!specifier.startsWith(prefix))
12716
+ return;
12717
+ const spec = specifier.slice(prefix.length);
12718
+ return spec.length > 0 ? spec : "latest";
12719
+ }
12720
+ function isOpenCodePluginDistTag(spec) {
12721
+ return /^[A-Za-z][A-Za-z0-9._-]*$/.test(spec) && !/^(v\d|[xX]$)/.test(spec);
12722
+ }
12723
+ function readConfiguredOpenCodePluginSpec(config) {
12724
+ for (const { entry } of readPluginEntries(config)) {
12725
+ const specifier = pluginEntrySpecifier(entry);
12726
+ const spec = specifier === undefined ? undefined : openCodeV2PluginSpecOf(specifier);
12727
+ if (spec !== undefined)
12728
+ return spec;
12729
+ }
12730
+ return "latest";
12731
+ }
12732
+ function pluginEntrySpecifier(entry) {
12733
+ if (typeof entry === "string")
12734
+ return entry;
12735
+ if (Array.isArray(entry) && typeof entry[0] === "string")
12736
+ return entry[0];
12737
+ if (entry !== null && typeof entry === "object") {
12738
+ const pkg = entry.package;
12739
+ if (typeof pkg === "string")
12740
+ return pkg;
12741
+ }
12742
+ return;
12743
+ }
12744
+ function listOpenCodeV2PluginCacheSlots(npmCacheDir = getOpenCodeV2NpmCacheDir()) {
12745
+ const [scope = "", name = ""] = OPENCODE_PLUGIN_NAME.split("/");
12746
+ const scopeDir = join10(npmCacheDir, scope);
12747
+ let names;
12748
+ try {
12749
+ names = readdirSync3(scopeDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.startsWith(`${name}@`)).map((entry) => entry.name);
12750
+ } catch {
12751
+ return [];
12752
+ }
12753
+ return names.map((dirName) => {
12754
+ const slot = join10(scopeDir, dirName);
12755
+ return {
12756
+ spec: dirName.slice(name.length + 1),
12757
+ slot,
12758
+ version: readOpenCodeV2CachedPluginVersion(slot)
12759
+ };
12760
+ }).sort((a, b) => {
12761
+ if (a.spec === "latest" || b.spec === "latest")
12762
+ return a.spec === "latest" ? -1 : 1;
12763
+ return a.spec.localeCompare(b.spec);
12764
+ });
12765
+ }
12766
+ function getOpenCodeV2ActiveGeneration(slot) {
12767
+ try {
12768
+ const generations = readdirSync3(slot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && /^\d+$/.test(entry.name)).map((entry) => entry.name).sort((a, b) => Number(a) - Number(b));
12769
+ const newest = generations.at(-1);
12770
+ return newest === undefined ? undefined : join10(slot, newest);
12771
+ } catch {
12772
+ return;
12773
+ }
12774
+ }
12775
+ function readOpenCodeV2CachedPluginVersion(slot) {
12776
+ const generation = getOpenCodeV2ActiveGeneration(slot);
12777
+ if (!generation)
12778
+ return;
12779
+ try {
12780
+ const pkg = JSON.parse(readFileSync5(getOpenCodePluginPackageJsonPath(generation), "utf-8"));
12781
+ return typeof pkg.version === "string" ? pkg.version : undefined;
12782
+ } catch {
12783
+ return;
12784
+ }
12785
+ }
12786
+ var OPENCODE_PLUGIN_NAME = "@cortexkit/opencode-magic-context", OPENCODE_PLUGIN_ENTRY_WITH_VERSION;
12787
+ var init_opencode_plugin_cache = __esm(() => {
12788
+ init_opencode_plugin_registration();
12789
+ init_paths();
12790
+ OPENCODE_PLUGIN_ENTRY_WITH_VERSION = `${OPENCODE_PLUGIN_NAME}@latest`;
12791
+ });
12792
+
12793
+ // src/commands/doctor-opencode2-cache.ts
12794
+ import { spawnSync as spawnSync3 } from "node:child_process";
12795
+ import { existsSync as existsSync8, rmSync as rmSync2 } from "node:fs";
12796
+ function runLsof(args, spawn) {
12797
+ const result = spawn("lsof", args, { encoding: "utf-8", timeout: 15000 });
12798
+ if (result.error)
12799
+ return { error: result.error.message };
12800
+ if (result.status !== 0 && result.status !== 1) {
12801
+ return { error: `lsof exited with status ${String(result.status)}` };
12802
+ }
12803
+ const pids = (result.stdout ?? "").split(/\s+/).filter((token) => /^\d+$/.test(token)).map((token) => Number(token)).filter((pid) => pid !== process.pid);
12804
+ return { pids };
12805
+ }
12806
+ function probeHostProcessesUsing(targets, spawn = spawnSync3) {
12807
+ const files = targets.files.filter((file) => existsSync8(file));
12808
+ const directories = targets.directories.filter((directory) => existsSync8(directory));
12809
+ const queries = [];
12810
+ if (files.length > 0)
12811
+ queries.push(["-w", "-t", "--", ...files]);
12812
+ for (const directory of directories)
12813
+ queries.push(["-w", "-t", "+D", directory]);
12814
+ const pids = new Set;
12815
+ for (const args of queries) {
12816
+ const result = runLsof(args, spawn);
12817
+ if ("error" in result) {
12818
+ return { status: "unknown", reason: `could not run lsof (${result.error})` };
12819
+ }
12820
+ for (const pid of result.pids)
12821
+ pids.add(pid);
12822
+ }
12823
+ if (pids.size > 0)
12824
+ return { status: "in_use", pids: [...pids].sort((a, b) => a - b) };
12825
+ return { status: "free" };
12826
+ }
12827
+ function comparePrerelease(a, b) {
12828
+ if (a === b)
12829
+ return 0;
12830
+ if (a === "")
12831
+ return 1;
12832
+ if (b === "")
12833
+ return -1;
12834
+ const left = a.split(".");
12835
+ const right = b.split(".");
12836
+ for (let i = 0;i < Math.max(left.length, right.length); i++) {
12837
+ const x = left[i];
12838
+ const y = right[i];
12839
+ if (x === undefined)
12840
+ return -1;
12841
+ if (y === undefined)
12842
+ return 1;
12843
+ if (x === y)
12844
+ continue;
12845
+ const xNumeric = /^\d+$/.test(x);
12846
+ const yNumeric = /^\d+$/.test(y);
12847
+ if (xNumeric && yNumeric)
12848
+ return Number(x) - Number(y);
12849
+ if (xNumeric !== yNumeric)
12850
+ return xNumeric ? -1 : 1;
12851
+ return x < y ? -1 : 1;
12852
+ }
12853
+ return 0;
12854
+ }
12855
+ function prereleaseOf(version) {
12856
+ const withoutBuild = version.split("+", 1)[0] ?? "";
12857
+ const dash = withoutBuild.indexOf("-");
12858
+ return dash === -1 ? "" : withoutBuild.slice(dash + 1);
12859
+ }
12860
+ function isStale(cached, latest) {
12861
+ if (cached === undefined)
12862
+ return true;
12863
+ if (cached === latest)
12864
+ return false;
12865
+ const comparison = compareSemverCore(cached, latest);
12866
+ if (comparison === null)
12867
+ return true;
12868
+ if (comparison !== 0)
12869
+ return comparison < 0;
12870
+ return comparePrerelease(prereleaseOf(cached), prereleaseOf(latest)) < 0;
12871
+ }
12872
+ function removeOpenCodeV2PluginCacheSlot(slot, hostFiles, deps = {}) {
12873
+ const probe = deps.probe ?? probeHostProcessesUsing;
12874
+ const use = probe({ files: hostFiles, directories: [slot] });
12875
+ if (use.status === "in_use")
12876
+ return { action: "in_use", pids: use.pids };
12877
+ if (use.status === "unknown")
12878
+ return { action: "in_use_unknown", reason: use.reason };
12879
+ const remove = deps.remove ?? ((path) => rmSync2(path, { recursive: true, force: true }));
12880
+ try {
12881
+ remove(slot);
12882
+ } catch (err) {
12883
+ return { action: "error", error: err instanceof Error ? err.message : String(err) };
12884
+ }
12885
+ return { action: "cleared" };
12886
+ }
12887
+ function openCodeHostDatabaseFiles(databasePaths) {
12888
+ return databasePaths.filter((path) => path !== ":memory:").flatMap((path) => ["", "-wal", "-shm"].map((suffix) => `${path}${suffix}`));
12889
+ }
12890
+ function configuredOpenCodeV2DistTag(config) {
12891
+ const spec = readConfiguredOpenCodePluginSpec(config);
12892
+ return spec !== "latest" && isOpenCodePluginDistTag(spec) ? spec : undefined;
12893
+ }
12894
+ function checkOpenCodeV2PluginCache(options, deps = {}) {
12895
+ const distTag = options.distTag && options.distTag !== "latest" ? options.distTag : undefined;
12896
+ const slot = deps.slot ?? getOpenCodeV2PluginCacheSlot(undefined, distTag ?? "latest");
12897
+ const tagged = distTag ? { distTag } : {};
12898
+ if (!existsSync8(slot))
12899
+ return { action: "not_found", slot, ...tagged };
12900
+ const cached = readOpenCodeV2CachedPluginVersion(slot);
12901
+ const latest = options.latestVersion ?? undefined;
12902
+ const force = options.force === true;
12903
+ if (latest === undefined && !force) {
12904
+ return { action: "check_unavailable", slot, cached, ...tagged };
12905
+ }
12906
+ const stale = latest !== undefined && isStale(cached, latest);
12907
+ if (!stale && !force)
12908
+ return { action: "up_to_date", slot, cached, latest, ...tagged };
12909
+ if (!force && options.fix !== true) {
12910
+ return { action: "stale", slot, cached, latest, ...tagged };
12911
+ }
12912
+ const removal = removeOpenCodeV2PluginCacheSlot(slot, options.hostFiles, deps);
12913
+ switch (removal.action) {
12914
+ case "in_use":
12915
+ return { action: "in_use", slot, cached, latest, pids: removal.pids, ...tagged };
12916
+ case "in_use_unknown":
12917
+ return {
12918
+ action: "in_use_unknown",
12919
+ slot,
12920
+ cached,
12921
+ latest,
12922
+ reason: removal.reason,
12923
+ ...tagged
12924
+ };
12925
+ case "error":
12926
+ return { action: "error", slot, cached, latest, error: removal.error, ...tagged };
12927
+ case "cleared":
12928
+ return { action: "cleared", slot, cached, latest, forced: !stale, ...tagged };
12929
+ }
12930
+ }
12931
+ function reportOpenCodeV2PluginCache(result, report, options) {
12932
+ const tag = result.distTag ?? "latest";
12933
+ const versions = `cached: ${result.cached ?? "unreadable"}${result.latest ? `, ${tag}: ${result.latest}` : ""}`;
12934
+ const slotName = result.distTag ? ` @${result.distTag}` : "";
12935
+ switch (result.action) {
12936
+ case "not_found":
12937
+ if (options.reportMissing) {
12938
+ report.pass(`OpenCode 2 plugin cache has no Magic Context${slotName} install yet (OpenCode installs it on next start)`);
12939
+ }
12940
+ return { fixed: false, issue: false };
12941
+ case "up_to_date":
12942
+ report.pass(`OpenCode 2 plugin cache${slotName} up to date (v${result.cached})`);
12943
+ return { fixed: false, issue: false };
12944
+ case "check_unavailable":
12945
+ report.warn(`OpenCode 2 plugin cache${slotName} version check unavailable; preserving cached plugin${result.cached ? ` (cached: ${result.cached})` : ""}. Use doctor --force to reinstall it.`);
12946
+ return { fixed: false, issue: false };
12947
+ case "stale":
12948
+ report.warn(`OpenCode 2 is running an outdated Magic Context${slotName} (${versions}); OpenCode does not install new releases on its own`);
12949
+ report.info(` To upgrade, ${OPENCODE_V2_PLUGIN_UPDATE_HINT},`);
12950
+ report.info(" or quit OpenCode (including `opencode service stop`) and run `magic-context doctor --fix`.");
12951
+ return { fixed: false, issue: false };
12952
+ case "in_use":
12953
+ report.warn(`Outdated Magic Context in the OpenCode 2 plugin cache (${versions}) was not cleared: OpenCode is running (pid ${result.pids?.join(", ")})`);
12954
+ report.info(` Quit OpenCode (and \`opencode service stop\`) and rerun doctor --fix, or ${OPENCODE_V2_PLUGIN_UPDATE_HINT}.`);
12955
+ report.info(` ${result.slot}`);
12956
+ return { fixed: false, issue: false };
12957
+ case "in_use_unknown":
12958
+ report.warn(`Outdated Magic Context in the OpenCode 2 plugin cache (${versions}) was not cleared: ${result.reason ?? "could not tell whether OpenCode is running"}`);
12959
+ report.info(` Quit OpenCode and delete ${result.slot} by hand, or ${OPENCODE_V2_PLUGIN_UPDATE_HINT}.`);
12960
+ return { fixed: false, issue: false };
12961
+ case "cleared":
12962
+ report.pass(`Cleared ${result.forced ? "" : "outdated "}Magic Context${slotName} from the OpenCode 2 plugin cache (${versions}${result.forced ? ", --force" : ""}) — OpenCode installs the ${result.distTag ? `current ${tag} release` : "latest"} on next start`);
12963
+ report.info(` ${result.slot}`);
12964
+ return { fixed: true, issue: false };
12965
+ case "error":
12966
+ report.warn(`Could not clear the OpenCode 2 plugin cache: ${result.error}`);
12967
+ report.info(` Manually delete: ${result.slot}`);
12968
+ return { fixed: false, issue: true };
12969
+ }
12970
+ }
12971
+ var OPENCODE_V2_PLUGIN_UPDATE_HINT = "update it from OpenCode: open /plugins, select Magic Context and press ctrl+u (ctrl+r only re-checks), or run `opencode plugin update`";
12972
+ var init_doctor_opencode2_cache = __esm(() => {
12973
+ init_opencode_plugin_cache();
12974
+ });
12975
+
12655
12976
  // src/lib/atomic-write.ts
12656
12977
  import { chmodSync, mkdirSync as mkdirSync2, renameSync as renameSync2, statSync as statSync5, writeFileSync as writeFileSync2 } from "node:fs";
12657
12978
  import { dirname as dirname3 } from "node:path";
@@ -12670,13 +12991,13 @@ function writeFileAtomic(targetPath, data) {
12670
12991
  var init_atomic_write = () => {};
12671
12992
 
12672
12993
  // src/lib/opencode-detect.ts
12673
- import { existsSync as existsSync8, realpathSync } from "node:fs";
12994
+ import { existsSync as existsSync9, realpathSync } from "node:fs";
12674
12995
  import { homedir as homedir7 } from "node:os";
12675
- import { join as join10 } from "node:path";
12996
+ import { join as join11 } from "node:path";
12676
12997
  function defaultDeps(overrides = {}) {
12677
12998
  const env = overrides.env ?? process.env;
12678
12999
  return {
12679
- exists: overrides.exists ?? existsSync8,
13000
+ exists: overrides.exists ?? existsSync9,
12680
13001
  isExecutable: overrides.isExecutable ?? isExecutableFile,
12681
13002
  home: overrides.home ?? (env.HOME?.trim() || homedir7()),
12682
13003
  platform: overrides.platform ?? process.platform,
@@ -12686,7 +13007,7 @@ function defaultDeps(overrides = {}) {
12686
13007
  };
12687
13008
  }
12688
13009
  function stockCliBinary(d) {
12689
- return d.platform === "win32" ? join10(d.home, ".opencode", "bin", "opencode.exe") : join10(d.home, ".opencode", "bin", "opencode");
13010
+ return d.platform === "win32" ? join11(d.home, ".opencode", "bin", "opencode.exe") : join11(d.home, ".opencode", "bin", "opencode");
12690
13011
  }
12691
13012
  function extraCliCandidates(d) {
12692
13013
  if (d.platform === "win32") {
@@ -12695,25 +13016,25 @@ function extraCliCandidates(d) {
12695
13016
  const userprofile = d.env.USERPROFILE ?? d.home;
12696
13017
  const out = [];
12697
13018
  if (appdata) {
12698
- out.push(join10(appdata, "npm", "opencode.cmd"));
12699
- out.push(join10(appdata, "npm", "opencode.exe"));
13019
+ out.push(join11(appdata, "npm", "opencode.cmd"));
13020
+ out.push(join11(appdata, "npm", "opencode.exe"));
12700
13021
  }
12701
13022
  if (localappdata) {
12702
- out.push(join10(localappdata, "Microsoft", "WinGet", "Links", "opencode.exe"));
12703
- out.push(join10(localappdata, "opencode", "bin", "opencode.exe"));
13023
+ out.push(join11(localappdata, "Microsoft", "WinGet", "Links", "opencode.exe"));
13024
+ out.push(join11(localappdata, "opencode", "bin", "opencode.exe"));
12704
13025
  }
12705
13026
  if (userprofile) {
12706
- out.push(join10(userprofile, "scoop", "shims", "opencode.exe"));
13027
+ out.push(join11(userprofile, "scoop", "shims", "opencode.exe"));
12707
13028
  }
12708
13029
  return out;
12709
13030
  }
12710
13031
  return [
12711
13032
  "/usr/local/bin/opencode",
12712
13033
  "/opt/homebrew/bin/opencode",
12713
- join10(d.home, ".local", "bin", "opencode"),
12714
- join10(d.home, ".local", "share", "mise", "shims", "opencode"),
12715
- join10(d.home, ".asdf", "shims", "opencode"),
12716
- join10(d.home, ".volta", "bin", "opencode")
13034
+ join11(d.home, ".local", "bin", "opencode"),
13035
+ join11(d.home, ".local", "share", "mise", "shims", "opencode"),
13036
+ join11(d.home, ".asdf", "shims", "opencode"),
13037
+ join11(d.home, ".volta", "bin", "opencode")
12717
13038
  ];
12718
13039
  }
12719
13040
  function canonicalPath(d, path) {
@@ -12734,29 +13055,29 @@ function xdgConfigHome(d) {
12734
13055
  const xdg = d.env.XDG_CONFIG_HOME;
12735
13056
  if (xdg && xdg.length > 0)
12736
13057
  return xdg;
12737
- return join10(d.home, ".config");
13058
+ return join11(d.home, ".config");
12738
13059
  }
12739
13060
  function desktopUserDataDir(d, appId) {
12740
13061
  switch (d.platform) {
12741
13062
  case "darwin":
12742
- return join10(d.home, "Library", "Application Support", appId);
13063
+ return join11(d.home, "Library", "Application Support", appId);
12743
13064
  case "win32":
12744
- return join10(d.env.APPDATA ?? join10(d.home, "AppData", "Roaming"), appId);
13065
+ return join11(d.env.APPDATA ?? join11(d.home, "AppData", "Roaming"), appId);
12745
13066
  default:
12746
- return join10(xdgConfigHome(d), appId);
13067
+ return join11(xdgConfigHome(d), appId);
12747
13068
  }
12748
13069
  }
12749
13070
  function desktopAppPaths(d) {
12750
13071
  switch (d.platform) {
12751
13072
  case "darwin":
12752
- return ["/Applications/OpenCode.app", join10(d.home, "Applications", "OpenCode.app")];
13073
+ return ["/Applications/OpenCode.app", join11(d.home, "Applications", "OpenCode.app")];
12753
13074
  case "win32": {
12754
- const localappdata = d.env.LOCALAPPDATA ?? join10(d.home, "AppData", "Local");
12755
- return [join10(localappdata, "Programs", "OpenCode", "OpenCode.exe")];
13075
+ const localappdata = d.env.LOCALAPPDATA ?? join11(d.home, "AppData", "Local");
13076
+ return [join11(localappdata, "Programs", "OpenCode", "OpenCode.exe")];
12756
13077
  }
12757
13078
  default: {
12758
- const dataHome = d.env.XDG_DATA_HOME && d.env.XDG_DATA_HOME.length > 0 ? d.env.XDG_DATA_HOME : join10(d.home, ".local", "share");
12759
- return OPENCODE_DESKTOP_APP_IDS.map((appId) => join10(dataHome, "applications", `${appId}.desktop`));
13079
+ const dataHome = d.env.XDG_DATA_HOME && d.env.XDG_DATA_HOME.length > 0 ? d.env.XDG_DATA_HOME : join11(d.home, ".local", "share");
13080
+ return OPENCODE_DESKTOP_APP_IDS.map((appId) => join11(dataHome, "applications", `${appId}.desktop`));
12760
13081
  }
12761
13082
  }
12762
13083
  }
@@ -12778,7 +13099,7 @@ function detectOpenCodeInstallations(deps) {
12778
13099
  }
12779
13100
  }
12780
13101
  for (const appId of OPENCODE_DESKTOP_APP_IDS) {
12781
- const marker = join10(desktopUserDataDir(d, appId), OPENCODE_DESKTOP_SETTINGS_FILE);
13102
+ const marker = join11(desktopUserDataDir(d, appId), OPENCODE_DESKTOP_SETTINGS_FILE);
12782
13103
  if (d.exists(marker)) {
12783
13104
  addCandidate(installations, seenRealpaths, d, marker, "desktop", "desktop");
12784
13105
  }
@@ -12860,50 +13181,9 @@ function getAvailableModels2(binary) {
12860
13181
  var OPENCODE_BINARY_ENV = "MAGIC_CONTEXT_OPENCODE_BINARY", OPENCODE_VERSION_PROBE_TIMEOUT_MS = 2000;
12861
13182
  var init_opencode_helpers = () => {};
12862
13183
 
12863
- // src/lib/opencode-plugin-cache.ts
12864
- import { join as join11 } from "node:path";
12865
- function getOpenCodePluginCacheRoots() {
12866
- const cacheDir = getOpenCodePluginCacheDir();
12867
- return [
12868
- join11(cacheDir, OPENCODE_PLUGIN_ENTRY_WITH_VERSION),
12869
- join11(cacheDir, OPENCODE_PLUGIN_NAME)
12870
- ];
12871
- }
12872
- function getOpenCodePluginPackageJsonPath(pluginCacheRoot) {
12873
- return join11(pluginCacheRoot, "node_modules", ...OPENCODE_PLUGIN_NAME.split("/"), "package.json");
12874
- }
12875
- function getOpenCodePluginPackageJsonPaths() {
12876
- return getOpenCodePluginCacheRoots().map(getOpenCodePluginPackageJsonPath);
12877
- }
12878
- var OPENCODE_PLUGIN_NAME = "@cortexkit/opencode-magic-context", OPENCODE_PLUGIN_ENTRY_WITH_VERSION;
12879
- var init_opencode_plugin_cache = __esm(() => {
12880
- init_paths();
12881
- OPENCODE_PLUGIN_ENTRY_WITH_VERSION = `${OPENCODE_PLUGIN_NAME}@latest`;
12882
- });
12883
-
12884
- // src/lib/opencode-plugin-registration.ts
12885
- function pluginConfigKeyFor(hostGeneration) {
12886
- return hostGeneration === "v2" ? "plugins" : "plugin";
12887
- }
12888
- function readPluginEntries(config) {
12889
- const out = [];
12890
- for (const key of OPENCODE_PLUGIN_CONFIG_KEYS) {
12891
- const list = config?.[key];
12892
- if (!Array.isArray(list))
12893
- continue;
12894
- for (const [index, entry] of list.entries())
12895
- out.push({ key, index, entry });
12896
- }
12897
- return out;
12898
- }
12899
- var OPENCODE_PLUGIN_CONFIG_KEYS;
12900
- var init_opencode_plugin_registration = __esm(() => {
12901
- OPENCODE_PLUGIN_CONFIG_KEYS = ["plugin", "plugins"];
12902
- });
12903
-
12904
13184
  // src/adapters/opencode.ts
12905
- import { existsSync as existsSync9, readFileSync as readFileSync5, statSync as statSync6 } from "node:fs";
12906
- import { dirname as dirname4, isAbsolute as isAbsolute4, parse as parsePath, resolve as resolve3 } from "node:path";
13185
+ import { existsSync as existsSync10, readFileSync as readFileSync6, statSync as statSync6 } from "node:fs";
13186
+ import { dirname as dirname4, isAbsolute as isAbsolute4, parse as parsePath, resolve as resolve4 } from "node:path";
12907
13187
  import { fileURLToPath } from "node:url";
12908
13188
 
12909
13189
  class OpenCodeAdapter {
@@ -12911,21 +13191,20 @@ class OpenCodeAdapter {
12911
13191
  displayName = "OpenCode";
12912
13192
  pluginPackageName = OPENCODE_PLUGIN_NAME;
12913
13193
  hostGeneration;
12914
- resolvedWriteKey;
13194
+ probeHostUse;
12915
13195
  constructor(options = {}) {
12916
13196
  this.hostGeneration = options.hostGeneration;
13197
+ this.probeHostUse = options.probeHostUse;
13198
+ }
13199
+ get resolvedHostGeneration() {
13200
+ if (this.hostGeneration)
13201
+ return this.hostGeneration;
13202
+ const detection = detectOpenCode();
13203
+ this.hostGeneration = detection.kind === "cli" ? openCodeHostGenerationFromVersion(getOpenCodeVersion(detection.binary)) : "v1";
13204
+ return this.hostGeneration;
12917
13205
  }
12918
13206
  get writeKey() {
12919
- if (this.resolvedWriteKey)
12920
- return this.resolvedWriteKey;
12921
- const generation = this.hostGeneration ?? (() => {
12922
- const detection = detectOpenCode();
12923
- if (detection.kind !== "cli")
12924
- return "v1";
12925
- return openCodeHostGenerationFromVersion(getOpenCodeVersion(detection.binary));
12926
- })();
12927
- this.resolvedWriteKey = pluginConfigKeyFor(generation);
12928
- return this.resolvedWriteKey;
13207
+ return pluginConfigKeyFor(this.resolvedHostGeneration);
12929
13208
  }
12930
13209
  isInstalled() {
12931
13210
  return detectOpenCode().kind !== "none";
@@ -12935,7 +13214,7 @@ class OpenCodeAdapter {
12935
13214
  if (paths.opencodeConfigFormat === "none")
12936
13215
  return false;
12937
13216
  try {
12938
- const raw = readFileSync5(paths.opencodeConfig, "utf-8");
13217
+ const raw = readFileSync6(paths.opencodeConfig, "utf-8");
12939
13218
  const cfg = import_comment_json.parse(raw);
12940
13219
  return readPluginEntries(cfg).some(({ entry }) => matchesPluginEntry(entry, OPENCODE_PLUGIN_NAME));
12941
13220
  } catch {
@@ -12971,7 +13250,7 @@ class OpenCodeAdapter {
12971
13250
  configPath: target
12972
13251
  };
12973
13252
  }
12974
- const raw = readFileSync5(target, "utf-8");
13253
+ const raw = readFileSync6(target, "utf-8");
12975
13254
  const cfg = import_comment_json.parse(raw);
12976
13255
  if (cfg === null || typeof cfg !== "object") {
12977
13256
  return {
@@ -13046,7 +13325,7 @@ class OpenCodeAdapter {
13046
13325
  };
13047
13326
  }
13048
13327
  try {
13049
- const raw = readFileSync5(target, "utf-8");
13328
+ const raw = readFileSync6(target, "utf-8");
13050
13329
  const cfg = import_comment_json.parse(raw);
13051
13330
  if (cfg === null || typeof cfg !== "object") {
13052
13331
  return {
@@ -13096,22 +13375,83 @@ class OpenCodeAdapter {
13096
13375
  return "Install OpenCode: curl -fsSL https://opencode.ai/install | bash";
13097
13376
  }
13098
13377
  getPluginCacheInfo() {
13099
- const path = getOpenCodePluginCacheDir();
13100
- return {
13101
- path,
13102
- exists: existsSync9(path),
13103
- sizeBytes: dirSizeBytes(path)
13104
- };
13378
+ const legacyPath = getOpenCodePluginCacheDir();
13379
+ const legacyExists = existsSync10(legacyPath);
13380
+ const slot = getOpenCodeV2PluginCacheSlot();
13381
+ const slotExists = existsSync10(slot);
13382
+ const caches = [];
13383
+ if (legacyExists || !slotExists) {
13384
+ caches.push({
13385
+ path: legacyPath,
13386
+ exists: legacyExists,
13387
+ sizeBytes: dirSizeBytes(legacyPath),
13388
+ label: "OpenCode 1 plugin packages"
13389
+ });
13390
+ }
13391
+ if (slotExists) {
13392
+ caches.push({
13393
+ path: slot,
13394
+ exists: true,
13395
+ sizeBytes: dirSizeBytes(slot),
13396
+ label: "OpenCode 2 Magic Context @latest install",
13397
+ clear: () => this.clearOpenCodeV2Slot(slot)
13398
+ });
13399
+ }
13400
+ return caches;
13401
+ }
13402
+ clearOpenCodeV2Slot(slot) {
13403
+ let databases;
13404
+ try {
13405
+ databases = [
13406
+ ...new Set([resolveOpenCodeDbPath("v1").path, resolveOpenCodeDbPath("v2").path])
13407
+ ];
13408
+ } catch (err) {
13409
+ return {
13410
+ cleared: false,
13411
+ reason: `could not locate the OpenCode database to check whether OpenCode is running (${err instanceof Error ? err.message : String(err)})`
13412
+ };
13413
+ }
13414
+ const removal = removeOpenCodeV2PluginCacheSlot(slot, openCodeHostDatabaseFiles(databases), {
13415
+ probe: this.probeHostUse
13416
+ });
13417
+ switch (removal.action) {
13418
+ case "cleared":
13419
+ return { cleared: true };
13420
+ case "in_use":
13421
+ return {
13422
+ cleared: false,
13423
+ reason: `OpenCode is running (pid ${removal.pids.join(", ")}); quit it (and \`opencode service stop\`) first`
13424
+ };
13425
+ case "in_use_unknown":
13426
+ return { cleared: false, reason: removal.reason };
13427
+ case "error":
13428
+ return { cleared: false, reason: removal.error };
13429
+ }
13105
13430
  }
13106
13431
  getLogPath() {
13107
13432
  return getMagicContextLogPath2("opencode");
13108
13433
  }
13434
+ configuredPluginSpec() {
13435
+ const paths = detectConfigPaths();
13436
+ if (paths.opencodeConfigFormat === "none")
13437
+ return "latest";
13438
+ try {
13439
+ const cfg = import_comment_json.parse(readFileSync6(paths.opencodeConfig, "utf-8"));
13440
+ return readConfiguredOpenCodePluginSpec(cfg);
13441
+ } catch {
13442
+ return "latest";
13443
+ }
13444
+ }
13109
13445
  getInstalledPluginVersion() {
13446
+ if (this.resolvedHostGeneration === "v2") {
13447
+ const slot = getOpenCodeV2PluginCacheSlot(undefined, this.configuredPluginSpec());
13448
+ return readOpenCodeV2CachedPluginVersion(slot) ?? null;
13449
+ }
13110
13450
  for (const candidate of getOpenCodePluginPackageJsonPaths()) {
13111
- if (!existsSync9(candidate))
13451
+ if (!existsSync10(candidate))
13112
13452
  continue;
13113
13453
  try {
13114
- const raw = readFileSync5(candidate, "utf-8");
13454
+ const raw = readFileSync6(candidate, "utf-8");
13115
13455
  const pkg = JSON.parse(raw);
13116
13456
  if (typeof pkg.version === "string")
13117
13457
  return pkg.version;
@@ -13147,15 +13487,15 @@ function isDevPathPluginEntry(entry) {
13147
13487
  if (candidate.startsWith("file://")) {
13148
13488
  localPath = fileURLToPath(candidate);
13149
13489
  } else {
13150
- localPath = resolve3(candidate);
13490
+ localPath = resolve4(candidate);
13151
13491
  }
13152
13492
  if (statSync6(localPath).isFile())
13153
13493
  localPath = dirname4(localPath);
13154
13494
  const root = parsePath(localPath).root;
13155
13495
  while (localPath !== root) {
13156
- const packagePath = resolve3(localPath, "package.json");
13157
- if (existsSync9(packagePath)) {
13158
- const pkg = JSON.parse(readFileSync5(packagePath, "utf8"));
13496
+ const packagePath = resolve4(localPath, "package.json");
13497
+ if (existsSync10(packagePath)) {
13498
+ const pkg = JSON.parse(readFileSync6(packagePath, "utf8"));
13159
13499
  return pkg.name === OPENCODE_PLUGIN_NAME;
13160
13500
  }
13161
13501
  localPath = dirname4(localPath);
@@ -13175,7 +13515,7 @@ function matchesPluginEntry(entry, pkgName) {
13175
13515
  }
13176
13516
  function ensureDir(filePath) {
13177
13517
  const dir = dirname4(filePath);
13178
- if (!existsSync9(dir)) {
13518
+ if (!existsSync10(dir)) {
13179
13519
  const { mkdirSync } = __require("node:fs");
13180
13520
  mkdirSync(dir, { recursive: true });
13181
13521
  }
@@ -13183,6 +13523,7 @@ function ensureDir(filePath) {
13183
13523
  var import_comment_json;
13184
13524
  var init_opencode = __esm(() => {
13185
13525
  init_opencode_db_path();
13526
+ init_doctor_opencode2_cache();
13186
13527
  init_atomic_write();
13187
13528
  init_opencode_detect();
13188
13529
  init_opencode_helpers();
@@ -13193,7 +13534,7 @@ var init_opencode = __esm(() => {
13193
13534
  });
13194
13535
 
13195
13536
  // ../plugin/src/shared/jsonc-parser.ts
13196
- import { existsSync as existsSync10, readFileSync as readFileSync6 } from "node:fs";
13537
+ import { existsSync as existsSync11, readFileSync as readFileSync7 } from "node:fs";
13197
13538
  function stripJsonComments(content) {
13198
13539
  let result = "";
13199
13540
  let inString = false;
@@ -13368,7 +13709,7 @@ function parseJsonc2(content, options = {}) {
13368
13709
  }
13369
13710
  function readJsoncFile(filePath) {
13370
13711
  try {
13371
- return parseJsonc2(readFileSync6(filePath, "utf-8"));
13712
+ return parseJsonc2(readFileSync7(filePath, "utf-8"));
13372
13713
  } catch (_error) {
13373
13714
  return null;
13374
13715
  }
@@ -13376,10 +13717,10 @@ function readJsoncFile(filePath) {
13376
13717
  function detectConfigFile(basePath) {
13377
13718
  const jsoncPath = `${basePath}.jsonc`;
13378
13719
  const jsonPath = `${basePath}.json`;
13379
- if (existsSync10(jsoncPath)) {
13720
+ if (existsSync11(jsoncPath)) {
13380
13721
  return { format: "jsonc", path: jsoncPath };
13381
13722
  }
13382
- if (existsSync10(jsonPath)) {
13723
+ if (existsSync11(jsonPath)) {
13383
13724
  return { format: "json", path: jsonPath };
13384
13725
  }
13385
13726
  return { format: "none", path: jsoncPath };
@@ -13391,7 +13732,7 @@ var init_jsonc_parser = __esm(() => {
13391
13732
  });
13392
13733
 
13393
13734
  // src/lib/jsonc-config.ts
13394
- import { existsSync as existsSync11, readFileSync as readFileSync7 } from "node:fs";
13735
+ import { existsSync as existsSync12, readFileSync as readFileSync8 } from "node:fs";
13395
13736
  function parseErrorLocation(content, error) {
13396
13737
  const lines = content.split(`
13397
13738
  `);
@@ -13407,9 +13748,9 @@ function parseErrorLocation(content, error) {
13407
13748
  return { line: messageLine ? Number.parseInt(messageLine, 10) : 1, column: 1 };
13408
13749
  }
13409
13750
  function readJsoncConfig(path) {
13410
- if (!existsSync11(path))
13751
+ if (!existsSync12(path))
13411
13752
  return { kind: "missing" };
13412
- const content = readFileSync7(path, "utf-8");
13753
+ const content = readFileSync8(path, "utf-8");
13413
13754
  try {
13414
13755
  const rejectedKeyPaths = [];
13415
13756
  const parsed = sanitizeParsedJson(import_comment_json2.parse(content), {
@@ -13458,7 +13799,7 @@ var init_jsonc_config = __esm(() => {
13458
13799
  });
13459
13800
 
13460
13801
  // src/lib/pi-package-entry.ts
13461
- import { existsSync as existsSync12, readFileSync as readFileSync8 } from "node:fs";
13802
+ import { existsSync as existsSync13, readFileSync as readFileSync9 } from "node:fs";
13462
13803
  import { isAbsolute as isAbsolute5, join as join12 } from "node:path";
13463
13804
  function stripNpmPrefix(value) {
13464
13805
  return value.startsWith("npm:") ? value.slice("npm:".length) : value;
@@ -13515,10 +13856,10 @@ function hasPiMagicContextPackage(entries, agentDir = getPiAgentConfigDir()) {
13515
13856
  }
13516
13857
  function isPiMagicContextPackageDir(dir) {
13517
13858
  const packageJson = join12(dir, "package.json");
13518
- if (!existsSync12(packageJson))
13859
+ if (!existsSync13(packageJson))
13519
13860
  return false;
13520
13861
  try {
13521
- const pkg = JSON.parse(readFileSync8(packageJson, "utf-8"));
13862
+ const pkg = JSON.parse(readFileSync9(packageJson, "utf-8"));
13522
13863
  return typeof pkg.name === "string" && pkg.name === PI_MAGIC_CONTEXT_PACKAGE_NAME;
13523
13864
  } catch {
13524
13865
  return false;
@@ -13554,7 +13895,7 @@ var init_pi_package_entry = __esm(() => {
13554
13895
  });
13555
13896
 
13556
13897
  // src/adapters/pi.ts
13557
- import { existsSync as existsSync13 } from "node:fs";
13898
+ import { existsSync as existsSync14 } from "node:fs";
13558
13899
  import { dirname as dirname5 } from "node:path";
13559
13900
 
13560
13901
  class PiAdapter {
@@ -13656,7 +13997,7 @@ class PiAdapter {
13656
13997
  return "Install Pi: https://pi.coding/install (npm: @earendil-works/pi-coding-agent)";
13657
13998
  }
13658
13999
  getPluginCacheInfo() {
13659
- return { path: null, exists: false, sizeBytes: 0 };
14000
+ return [{ path: null, exists: false, sizeBytes: 0 }];
13660
14001
  }
13661
14002
  getLogPath() {
13662
14003
  return getMagicContextLogPath2("pi");
@@ -13693,7 +14034,7 @@ function writePiSettings(settings) {
13693
14034
  }
13694
14035
  function ensureDir2(filePath) {
13695
14036
  const dir = dirname5(filePath);
13696
- if (!existsSync13(dir)) {
14037
+ if (!existsSync14(dir)) {
13697
14038
  const { mkdirSync } = __require("node:fs");
13698
14039
  mkdirSync(dir, { recursive: true });
13699
14040
  }
@@ -13823,10 +14164,10 @@ var init_harness_provider_map = __esm(() => {
13823
14164
  // ../plugin/src/config/raw-loader.ts
13824
14165
  import {
13825
14166
  closeSync as closeSync2,
13826
- existsSync as existsSync14,
14167
+ existsSync as existsSync15,
13827
14168
  linkSync,
13828
14169
  openSync as openSync2,
13829
- readFileSync as readFileSync9,
14170
+ readFileSync as readFileSync10,
13830
14171
  renameSync as renameSync3,
13831
14172
  statSync as statSync7,
13832
14173
  unlinkSync as unlinkSync2,
@@ -14026,7 +14367,7 @@ function writeExclusiveBackup(backupPath, bytes, mode) {
14026
14367
  if (error.code !== "EEXIST")
14027
14368
  throw error;
14028
14369
  }
14029
- const existingBytes = readFileSync9(backupPath);
14370
+ const existingBytes = readFileSync10(backupPath);
14030
14371
  if (existingBytes.equals(bytes))
14031
14372
  return;
14032
14373
  if (bytes.subarray(0, existingBytes.length).equals(existingBytes)) {
@@ -14070,11 +14411,11 @@ function migrationWarning(diagnostic) {
14070
14411
  return diagnostic.message;
14071
14412
  }
14072
14413
  function loadRawConfigFile(options) {
14073
- if (!existsSync14(options.configPath))
14414
+ if (!existsSync15(options.configPath))
14074
14415
  return null;
14075
14416
  let observedBytes;
14076
14417
  try {
14077
- observedBytes = readFileSync9(options.configPath);
14418
+ observedBytes = readFileSync10(options.configPath);
14078
14419
  } catch (error) {
14079
14420
  throw new Error(`failed to read config: ${error instanceof Error ? error.message : String(error)}`);
14080
14421
  }
@@ -14118,7 +14459,7 @@ function loadRawConfigFile(options) {
14118
14459
  writeExclusiveBackup(backupPath, observedBytes, mode);
14119
14460
  temporaryPath = writeTemporaryCandidate(options.configPath, migration.bytes, mode);
14120
14461
  options.afterTemporaryWrite?.();
14121
- const currentBytes = readFileSync9(options.configPath);
14462
+ const currentBytes = readFileSync10(options.configPath);
14122
14463
  if (!hasFlatKeys(currentBytes)) {
14123
14464
  unlinkSync2(temporaryPath);
14124
14465
  return {
@@ -14490,10 +14831,10 @@ var init_dreamer_setup = __esm(() => {
14490
14831
  });
14491
14832
 
14492
14833
  // src/commands/setup-pi.ts
14493
- import { existsSync as existsSync15, mkdirSync as mkdirSync3 } from "node:fs";
14834
+ import { existsSync as existsSync16, mkdirSync as mkdirSync3 } from "node:fs";
14494
14835
  import { dirname as dirname7 } from "node:path";
14495
14836
  function ensureDir3(path) {
14496
- if (!existsSync15(path))
14837
+ if (!existsSync16(path))
14497
14838
  mkdirSync3(path, { recursive: true });
14498
14839
  }
14499
14840
  async function getDefaultPrompts() {
@@ -21919,16 +22260,16 @@ function resolveTransformMode(args) {
21919
22260
  var RUST_COMPACTION_OFF_WARNING = "compaction-off mode does not support rust transform mode; using the TypeScript transform.", RUST_REQUIRES_USER_SUBC_WARNING = "rust mode requires user-level subc configuration; running ts.";
21920
22261
 
21921
22262
  // ../plugin/src/config/variable.ts
21922
- import { existsSync as existsSync16, readFileSync as readFileSync10 } from "node:fs";
22263
+ import { existsSync as existsSync17, readFileSync as readFileSync11 } from "node:fs";
21923
22264
  import { homedir as homedir10 } from "node:os";
21924
- import { dirname as dirname9, isAbsolute as isAbsolute6, resolve as resolve4 } from "node:path";
22265
+ import { dirname as dirname9, isAbsolute as isAbsolute6, resolve as resolve5 } from "node:path";
21925
22266
  function sensitiveFilePathReason(resolvedPath) {
21926
22267
  const home = homedir10();
21927
22268
  const sensitiveDirs = [
21928
- { dir: resolve4(home, ".ssh"), label: "SSH keys" },
21929
- { dir: resolve4(home, ".aws"), label: "AWS credentials" },
21930
- { dir: resolve4(home, ".gnupg"), label: "GnuPG keyring" },
21931
- { dir: resolve4(home, ".config", "gh"), label: "GitHub CLI auth" }
22269
+ { dir: resolve5(home, ".ssh"), label: "SSH keys" },
22270
+ { dir: resolve5(home, ".aws"), label: "AWS credentials" },
22271
+ { dir: resolve5(home, ".gnupg"), label: "GnuPG keyring" },
22272
+ { dir: resolve5(home, ".config", "gh"), label: "GitHub CLI auth" }
21932
22273
  ];
21933
22274
  for (const { dir, label } of sensitiveDirs) {
21934
22275
  if (resolvedPath === dir || resolvedPath.startsWith(`${dir}/`)) {
@@ -21986,21 +22327,21 @@ function substituteConfigVariables(input) {
21986
22327
  }
21987
22328
  let filePath = rawPath.trim();
21988
22329
  if (filePath.startsWith("~/")) {
21989
- filePath = resolve4(homedir10(), filePath.slice(2));
22330
+ filePath = resolve5(homedir10(), filePath.slice(2));
21990
22331
  } else if (!isAbsolute6(filePath)) {
21991
- filePath = resolve4(configDir, filePath);
22332
+ filePath = resolve5(configDir, filePath);
21992
22333
  }
21993
22334
  const sensitiveReason = sensitiveFilePathReason(filePath);
21994
22335
  if (sensitiveReason) {
21995
22336
  warnings.push(`${token} resolves to a sensitive path (${sensitiveReason}: ${filePath}); ` + "inlining its contents into config — make sure this is intentional.");
21996
22337
  }
21997
- if (!existsSync16(filePath)) {
22338
+ if (!existsSync17(filePath)) {
21998
22339
  warnings.push(`File not found for ${token} (resolved to ${filePath}); using empty string`);
21999
22340
  continue;
22000
22341
  }
22001
22342
  let contents;
22002
22343
  try {
22003
- contents = readFileSync10(filePath, "utf-8").trim();
22344
+ contents = readFileSync11(filePath, "utf-8").trim();
22004
22345
  } catch (error) {
22005
22346
  const message = error instanceof Error ? error.message : String(error);
22006
22347
  warnings.push(`Failed to read file for ${token} (${filePath}): ${message}; using empty string`);
@@ -22019,7 +22360,7 @@ var init_variable = __esm(() => {
22019
22360
  });
22020
22361
 
22021
22362
  // ../plugin/src/config/index.ts
22022
- import { existsSync as existsSync17 } from "node:fs";
22363
+ import { existsSync as existsSync18 } from "node:fs";
22023
22364
  function getUserConfigBasePath() {
22024
22365
  return cortexKitUserConfigBasePath();
22025
22366
  }
@@ -22027,10 +22368,10 @@ function getProjectConfigBasePath(directory) {
22027
22368
  return cortexKitProjectConfigBasePath(directory);
22028
22369
  }
22029
22370
  function resolveLegacyReadFallback(sources) {
22030
- return { source: sources.find((s) => existsSync17(s.path)) ?? null };
22371
+ return { source: sources.find((s) => existsSync18(s.path)) ?? null };
22031
22372
  }
22032
22373
  function loadConfigFileDetailed(configPath, source) {
22033
- if (!existsSync17(configPath)) {
22374
+ if (!existsSync18(configPath)) {
22034
22375
  return null;
22035
22376
  }
22036
22377
  let rawText;
@@ -22343,8 +22684,8 @@ function loadPluginConfigDetailed(directory, applyRuntimeGlobals = true) {
22343
22684
  const harnessLegacy = resolveLegacyConfigSourcesForHarness(directory, "opencode");
22344
22685
  const userLegacyFallback = userDetected.format === "none" ? resolveLegacyReadFallback(harnessLegacy.user) : { source: null };
22345
22686
  const projectLegacyFallback = projectDetected.format === "none" ? resolveLegacyReadFallback(harnessLegacy.project) : { source: null };
22346
- const legacyUserUnmigrated = userDetected.format === "none" && !userLegacyFallback.source && legacySources.user.some((source) => existsSync17(source.path));
22347
- const legacyProjectUnmigrated = projectDetected.format === "none" && !projectLegacyFallback.source && legacySources.project.some((source) => existsSync17(source.path));
22687
+ const legacyUserUnmigrated = userDetected.format === "none" && !userLegacyFallback.source && legacySources.user.some((source) => existsSync18(source.path));
22688
+ const legacyProjectUnmigrated = projectDetected.format === "none" && !projectLegacyFallback.source && legacySources.project.some((source) => existsSync18(source.path));
22348
22689
  const userLoaded = userDetected.format !== "none" ? loadConfigFileDetailed(userDetected.path, "user") : userLegacyFallback.source ? loadConfigFileDetailed(userLegacyFallback.source.path, "user") : null;
22349
22690
  const projectLoaded = projectDetected.format !== "none" ? loadConfigFileDetailed(projectDetected.path, "project") : projectLegacyFallback.source ? loadConfigFileDetailed(projectLegacyFallback.source.path, "project") : null;
22350
22691
  const allWarnings = [];
@@ -22482,7 +22823,7 @@ var init_config = __esm(() => {
22482
22823
 
22483
22824
  // ../plugin/src/shared/opencode-config-dir.ts
22484
22825
  import { homedir as homedir11 } from "node:os";
22485
- import { join as join14, resolve as resolve5 } from "node:path";
22826
+ import { join as join14, resolve as resolve6 } from "node:path";
22486
22827
  function resolveHomeDir() {
22487
22828
  return process.env.HOME?.trim() || homedir11();
22488
22829
  }
@@ -22494,7 +22835,7 @@ function getOpenCodeGlobalConfigDir() {
22494
22835
  }
22495
22836
  function getEnvConfigDir() {
22496
22837
  const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
22497
- return envConfigDir ? resolve5(envConfigDir) : undefined;
22838
+ return envConfigDir ? resolve6(envConfigDir) : undefined;
22498
22839
  }
22499
22840
  function getCliConfigDir() {
22500
22841
  return getEnvConfigDir() ?? getOpenCodeGlobalConfigDir();
@@ -22781,7 +23122,7 @@ var init_conflict_detector = __esm(() => {
22781
23122
  });
22782
23123
 
22783
23124
  // ../plugin/src/shared/conflict-fixer.ts
22784
- import { existsSync as existsSync18, readFileSync as readFileSync11, writeFileSync as writeFileSync4 } from "node:fs";
23125
+ import { existsSync as existsSync19, readFileSync as readFileSync12, writeFileSync as writeFileSync4 } from "node:fs";
22785
23126
  import { homedir as homedir13 } from "node:os";
22786
23127
  import { join as join16 } from "node:path";
22787
23128
  function isRecord2(value) {
@@ -22791,11 +23132,11 @@ function asStringArray(value) {
22791
23132
  return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
22792
23133
  }
22793
23134
  function readConfig(filePath) {
22794
- if (!existsSync18(filePath)) {
23135
+ if (!existsSync19(filePath)) {
22795
23136
  return null;
22796
23137
  }
22797
23138
  try {
22798
- const text = readFileSync11(filePath, "utf-8");
23139
+ const text = readFileSync12(filePath, "utf-8");
22799
23140
  const parsed = import_comment_json5.parse(text);
22800
23141
  return isRecord2(parsed) ? { config: parsed, text } : null;
22801
23142
  } catch {
@@ -22807,14 +23148,14 @@ function writeConfig(filePath, text) {
22807
23148
  }
22808
23149
  function resolveUserOpenCodeConfigPath() {
22809
23150
  const paths = getOpenCodeConfigPaths({ binary: "opencode" });
22810
- if (existsSync18(paths.configJsonc))
23151
+ if (existsSync19(paths.configJsonc))
22811
23152
  return paths.configJsonc;
22812
23153
  return paths.configJson;
22813
23154
  }
22814
23155
  function collectOpenCodeConfigPaths(directory) {
22815
23156
  const paths = new Set;
22816
23157
  const userConfig = resolveUserOpenCodeConfigPath();
22817
- if (existsSync18(userConfig)) {
23158
+ if (existsSync19(userConfig)) {
22818
23159
  paths.add(userConfig);
22819
23160
  }
22820
23161
  for (const filePath of [
@@ -22823,7 +23164,7 @@ function collectOpenCodeConfigPaths(directory) {
22823
23164
  join16(directory, "opencode.jsonc"),
22824
23165
  join16(directory, "opencode.json")
22825
23166
  ]) {
22826
- if (existsSync18(filePath)) {
23167
+ if (existsSync19(filePath)) {
22827
23168
  paths.add(filePath);
22828
23169
  }
22829
23170
  }
@@ -22835,10 +23176,10 @@ function collectOmoConfigPaths(directory) {
22835
23176
  for (const fileName of OMO_CONFIG_NAMES) {
22836
23177
  const userPath = join16(configDir, fileName);
22837
23178
  const projectPath = join16(directory, fileName);
22838
- if (existsSync18(userPath)) {
23179
+ if (existsSync19(userPath)) {
22839
23180
  paths.add(userPath);
22840
23181
  }
22841
- if (existsSync18(projectPath)) {
23182
+ if (existsSync19(projectPath)) {
22842
23183
  paths.add(projectPath);
22843
23184
  }
22844
23185
  }
@@ -22846,13 +23187,13 @@ function collectOmoConfigPaths(directory) {
22846
23187
  const omoHomeDir = join16(homeDir, ".omo");
22847
23188
  for (const name of OMO_UNIFIED_NAMES) {
22848
23189
  const userPath = join16(omoHomeDir, name);
22849
- if (existsSync18(userPath)) {
23190
+ if (existsSync19(userPath)) {
22850
23191
  paths.add(userPath);
22851
23192
  }
22852
23193
  }
22853
23194
  for (const name of OMO_UNIFIED_NAMES) {
22854
23195
  const projectPath = join16(directory, ".omo", name);
22855
- if (existsSync18(projectPath)) {
23196
+ if (existsSync19(projectPath)) {
22856
23197
  paths.add(projectPath);
22857
23198
  }
22858
23199
  }
@@ -22980,7 +23321,7 @@ var init_conflict_fixer = __esm(() => {
22980
23321
  });
22981
23322
 
22982
23323
  // src/commands/setup-opencode.ts
22983
- import { existsSync as existsSync19, mkdirSync as mkdirSync5, readFileSync as readFileSync12 } from "node:fs";
23324
+ import { existsSync as existsSync20, mkdirSync as mkdirSync5, readFileSync as readFileSync13 } from "node:fs";
22984
23325
  import { basename as basename3, dirname as dirname10 } from "node:path";
22985
23326
  function resolveCompactionEnabledForWriter() {
22986
23327
  try {
@@ -22992,7 +23333,7 @@ function resolveCompactionEnabledForWriter() {
22992
23333
  }
22993
23334
  }
22994
23335
  function ensureDir5(dir) {
22995
- if (!existsSync19(dir)) {
23336
+ if (!existsSync20(dir)) {
22996
23337
  mkdirSync5(dir, { recursive: true });
22997
23338
  }
22998
23339
  }
@@ -23021,7 +23362,7 @@ function readMagicContextConfigForSetup2(configPath) {
23021
23362
  }
23022
23363
  function addPluginToOpenCodeConfig(configPath, _format, removeDcp = false, compactionEnabled = true, hostGeneration = "v1") {
23023
23364
  const registrationKey = pluginConfigKeyFor(hostGeneration);
23024
- const existsAtCommit = existsSync19(configPath);
23365
+ const existsAtCommit = existsSync20(configPath);
23025
23366
  const existing = existsAtCommit ? readJsoncConfigForUpdate(configPath) : {};
23026
23367
  if (!existsAtCommit) {
23027
23368
  ensureDir5(dirname10(configPath));
@@ -23033,7 +23374,7 @@ function addPluginToOpenCodeConfig(configPath, _format, removeDcp = false, compa
23033
23374
  `);
23034
23375
  return;
23035
23376
  }
23036
- let text = readFileSync12(configPath, "utf-8");
23377
+ let text = readFileSync13(configPath, "utf-8");
23037
23378
  let changed = false;
23038
23379
  const rawPlugins = readPluginEntries(existing).map(({ entry }) => entry);
23039
23380
  const retainedPlugins = removeDcp ? rawPlugins.filter((plugin) => !matchesPluginEntry(plugin, DCP_PLUGIN_NAME)) : rawPlugins;
@@ -23079,7 +23420,7 @@ function addPluginToOpenCodeConfig(configPath, _format, removeDcp = false, compa
23079
23420
  writeFileAtomic(configPath, text);
23080
23421
  }
23081
23422
  function addPluginToTuiConfig(configPath, _format) {
23082
- const existsAtCommit = existsSync19(configPath);
23423
+ const existsAtCommit = existsSync20(configPath);
23083
23424
  const existing = existsAtCommit ? readJsoncConfigForUpdate(configPath) : {};
23084
23425
  if (!existsAtCommit) {
23085
23426
  ensureDir5(dirname10(configPath));
@@ -23095,7 +23436,7 @@ function addPluginToTuiConfig(configPath, _format) {
23095
23436
  const hasDevEntry = rawPlugins.some((plugin) => isDevPathPluginEntry(plugin));
23096
23437
  if (hasNpmEntry || hasDevEntry)
23097
23438
  return;
23098
- const text = Array.isArray(existing.plugin) ? appendJsoncArrayValues(readFileSync12(configPath, "utf-8"), ["plugin"], [OPENCODE_PLUGIN_ENTRY_WITH_VERSION]) : setJsoncValue(readFileSync12(configPath, "utf-8"), ["plugin"], [OPENCODE_PLUGIN_ENTRY_WITH_VERSION]);
23439
+ const text = Array.isArray(existing.plugin) ? appendJsoncArrayValues(readFileSync13(configPath, "utf-8"), ["plugin"], [OPENCODE_PLUGIN_ENTRY_WITH_VERSION]) : setJsoncValue(readFileSync13(configPath, "utf-8"), ["plugin"], [OPENCODE_PLUGIN_ENTRY_WITH_VERSION]);
23099
23440
  writeFileAtomic(configPath, text);
23100
23441
  }
23101
23442
  function findDcpPluginIndexes(plugins) {
@@ -23201,7 +23542,7 @@ async function runSetup3(dryRun = false) {
23201
23542
  log2.warn("You can configure models manually in magic-context.jsonc later");
23202
23543
  }
23203
23544
  const paths = detectConfigPaths();
23204
- const hadExistingSetup = paths.opencodeConfigFormat !== "none" || existsSync19(paths.magicContextConfig) || paths.tuiConfigFormat !== "none";
23545
+ const hadExistingSetup = paths.opencodeConfigFormat !== "none" || existsSync20(paths.magicContextConfig) || paths.tuiConfigFormat !== "none";
23205
23546
  if (!dryRun) {
23206
23547
  try {
23207
23548
  assertJsoncConfigsParseable([
@@ -24491,7 +24832,7 @@ var init_context_authority = __esm(async () => {
24491
24832
  // ../plugin/src/features/magic-context/memory/project-identity.ts
24492
24833
  import { execFileSync as execFileSync3 } from "node:child_process";
24493
24834
  import { createHash as createHash2 } from "node:crypto";
24494
- import { existsSync as existsSync20, realpathSync as realpathSync2, statSync as statSync9 } from "node:fs";
24835
+ import { existsSync as existsSync21, realpathSync as realpathSync2, statSync as statSync9 } from "node:fs";
24495
24836
  import path3 from "node:path";
24496
24837
  function asError(error) {
24497
24838
  return error instanceof Error ? error : undefined;
@@ -24729,7 +25070,7 @@ function hasGitDir(canonical) {
24729
25070
  function gitRootInAncestorChain(startDirectory) {
24730
25071
  let current = startDirectory;
24731
25072
  while (true) {
24732
- if (existsSync20(path3.join(current, ".git"))) {
25073
+ if (existsSync21(path3.join(current, ".git"))) {
24733
25074
  try {
24734
25075
  return realpathSync2.native(current);
24735
25076
  } catch {
@@ -27064,7 +27405,7 @@ var init_pi_executable = __esm(() => {
27064
27405
 
27065
27406
  // ../plugin/src/shared/rpc-utils.ts
27066
27407
  import { execFileSync as execFileSync4 } from "node:child_process";
27067
- import { readFileSync as readFileSync13 } from "node:fs";
27408
+ import { readFileSync as readFileSync14 } from "node:fs";
27068
27409
  function isPidAlive(pid) {
27069
27410
  if (!Number.isInteger(pid) || pid <= 0)
27070
27411
  return "dead";
@@ -27600,7 +27941,7 @@ var init_rpc_utils = __esm(() => {
27600
27941
  "cljs/dist",
27601
27942
  "dist/bundle/cli"
27602
27943
  ];
27603
- rpcIdentityReadFileSync = readFileSync13;
27944
+ rpcIdentityReadFileSync = readFileSync14;
27604
27945
  rpcIdentityExecFileSync = execFileSync4;
27605
27946
  rpcIdentityProcessKill = process.kill;
27606
27947
  rpcProcessListExecFileSync = execFileSync4;
@@ -30892,14 +31233,14 @@ import {
30892
31233
  chmodSync as chmodSync3,
30893
31234
  copyFileSync,
30894
31235
  cpSync,
30895
- existsSync as existsSync21,
31236
+ existsSync as existsSync22,
30896
31237
  mkdirSync as mkdirSync6,
30897
- readdirSync as readdirSync3,
30898
- readFileSync as readFileSync14,
31238
+ readdirSync as readdirSync4,
31239
+ readFileSync as readFileSync15,
30899
31240
  statSync as statSync10,
30900
31241
  unlinkSync as unlinkSync3
30901
31242
  } from "node:fs";
30902
- import { basename as basename4, dirname as dirname11, join as join18, resolve as resolve6 } from "node:path";
31243
+ import { basename as basename4, dirname as dirname11, join as join18, resolve as resolve7 } from "node:path";
30903
31244
  function resolveBootBusyTimeoutMs(value) {
30904
31245
  if (value === undefined)
30905
31246
  return BOOT_SQLITE_BUSY_TIMEOUT_MS;
@@ -32338,8 +32679,8 @@ var init_storage_db = __esm(async () => {
32338
32679
  PERMISSIONS_ENFORCEABLE = process.platform !== "win32";
32339
32680
  RPC_DISCOVERY_PARSE_GRACE_MS = 10 * 60 * 1000;
32340
32681
  defaultRpcDiscoveryFs = {
32341
- readdirSync: (path, options) => options?.withFileTypes ? readdirSync3(path, { withFileTypes: true }) : readdirSync3(path),
32342
- readFileSync: (path, encoding) => String(readFileSync14(path, encoding)),
32682
+ readdirSync: (path, options) => options?.withFileTypes ? readdirSync4(path, { withFileTypes: true }) : readdirSync4(path),
32683
+ readFileSync: (path, encoding) => String(readFileSync15(path, encoding)),
32343
32684
  statSync: (path) => ({ mtimeMs: statSync10(path).mtimeMs }),
32344
32685
  unlinkSync: (path) => unlinkSync3(path)
32345
32686
  };
@@ -32352,13 +32693,13 @@ var init_storage_db = __esm(async () => {
32352
32693
  });
32353
32694
 
32354
32695
  // src/lib/database-access.ts
32355
- import { existsSync as existsSync22, writeFileSync as writeFileSync5 } from "node:fs";
32696
+ import { existsSync as existsSync23, writeFileSync as writeFileSync5 } from "node:fs";
32356
32697
  import { pathToFileURL } from "node:url";
32357
32698
  function getPersistedSchemaVersion2(db) {
32358
32699
  return getPersistedSchemaVersion(db);
32359
32700
  }
32360
32701
  function openExistingDatabase(path, options) {
32361
- if (!existsSync22(path))
32702
+ if (!existsSync23(path))
32362
32703
  return null;
32363
32704
  if (options.readonly) {
32364
32705
  const db = new Database(path, { readonly: true });
@@ -32969,16 +33310,16 @@ var init_doctor_merge_identity = __esm(async () => {
32969
33310
  });
32970
33311
 
32971
33312
  // src/commands/doctor-repair-db.ts
32972
- import { spawnSync as spawnSync3 } from "node:child_process";
33313
+ import { spawnSync as spawnSync4 } from "node:child_process";
32973
33314
  import {
32974
33315
  chmodSync as chmodSync4,
32975
33316
  closeSync as closeSync4,
32976
33317
  constants as constants2,
32977
33318
  copyFileSync as copyFileSync2,
32978
- existsSync as existsSync23,
33319
+ existsSync as existsSync24,
32979
33320
  openSync as openSync4,
32980
33321
  renameSync as renameSync4,
32981
- rmSync as rmSync2,
33322
+ rmSync as rmSync3,
32982
33323
  statSync as statSync11
32983
33324
  } from "node:fs";
32984
33325
  import { dirname as dirname12, join as join20 } from "node:path";
@@ -33011,11 +33352,11 @@ function timestamp(date) {
33011
33352
  return date.toISOString().replaceAll("-", "").replaceAll(":", "").replace(".", "");
33012
33353
  }
33013
33354
  function uniqueBase(preferred) {
33014
- if (!DATABASE_SUFFIXES.some((suffix) => existsSync23(`${preferred}${suffix}`)))
33355
+ if (!DATABASE_SUFFIXES.some((suffix) => existsSync24(`${preferred}${suffix}`)))
33015
33356
  return preferred;
33016
33357
  for (let attempt = 1;attempt < 1e4; attempt++) {
33017
33358
  const candidate = `${preferred}-${attempt}`;
33018
- if (!DATABASE_SUFFIXES.some((suffix) => existsSync23(`${candidate}${suffix}`)))
33359
+ if (!DATABASE_SUFFIXES.some((suffix) => existsSync24(`${candidate}${suffix}`)))
33019
33360
  return candidate;
33020
33361
  }
33021
33362
  throw new Error(`Could not allocate a unique recovery path beside ${preferred}`);
@@ -33029,7 +33370,7 @@ function copyDatabaseBundle(sourceBase, destinationBase) {
33029
33370
  const copiedPaths = [];
33030
33371
  for (const suffix of DATABASE_SUFFIXES) {
33031
33372
  const source = `${sourceBase}${suffix}`;
33032
- if (!existsSync23(source))
33373
+ if (!existsSync24(source))
33033
33374
  continue;
33034
33375
  const destination = `${destinationBase}${suffix}`;
33035
33376
  copyFileSync2(source, destination, constants2.COPYFILE_EXCL);
@@ -33097,7 +33438,7 @@ function runRecoverShell(sqliteExecutable, sourcePath, recoveredPath, dumpPath)
33097
33438
  let dumpWriteFd = null;
33098
33439
  try {
33099
33440
  dumpWriteFd = openSync4(dumpPath, "wx", 384);
33100
- const recovered = spawnSync3(sqliteExecutable, [sourcePath, ".recover"], {
33441
+ const recovered = spawnSync4(sqliteExecutable, [sourcePath, ".recover"], {
33101
33442
  stdio: ["ignore", dumpWriteFd, "pipe"],
33102
33443
  encoding: "utf8",
33103
33444
  windowsHide: true
@@ -33116,7 +33457,7 @@ function runRecoverShell(sqliteExecutable, sourcePath, recoveredPath, dumpPath)
33116
33457
  }
33117
33458
  const dumpReadFd = openSync4(dumpPath, "r");
33118
33459
  try {
33119
- const replayed = spawnSync3(sqliteExecutable, [recoveredPath], {
33460
+ const replayed = spawnSync4(sqliteExecutable, [recoveredPath], {
33120
33461
  stdio: [dumpReadFd, "ignore", "pipe"],
33121
33462
  encoding: "utf8",
33122
33463
  windowsHide: true
@@ -33143,7 +33484,7 @@ function runRecoverShell(sqliteExecutable, sourcePath, recoveredPath, dumpPath)
33143
33484
  } finally {
33144
33485
  if (dumpWriteFd !== null)
33145
33486
  closeSync4(dumpWriteFd);
33146
- rmSync2(dumpPath, { force: true });
33487
+ rmSync3(dumpPath, { force: true });
33147
33488
  }
33148
33489
  }
33149
33490
  function migrateAndCheckRecoveredDatabase(path) {
@@ -33222,14 +33563,14 @@ function prepareFreshDatabase(path) {
33222
33563
  }
33223
33564
  function removeRecoveryBundle(basePath) {
33224
33565
  for (const suffix of DATABASE_SUFFIXES)
33225
- rmSync2(`${basePath}${suffix}`, { force: true });
33566
+ rmSync3(`${basePath}${suffix}`, { force: true });
33226
33567
  }
33227
33568
  function activateReplacement(dbPath, replacementPath, originalAsidePath) {
33228
33569
  const movedOriginals = [];
33229
33570
  try {
33230
33571
  for (const suffix of DATABASE_SUFFIXES) {
33231
33572
  const from = `${dbPath}${suffix}`;
33232
- if (!existsSync23(from))
33573
+ if (!existsSync24(from))
33233
33574
  continue;
33234
33575
  const to = `${originalAsidePath}${suffix}`;
33235
33576
  renameSync4(from, to);
@@ -33239,7 +33580,7 @@ function activateReplacement(dbPath, replacementPath, originalAsidePath) {
33239
33580
  return movedOriginals.map(({ to }) => to);
33240
33581
  } catch (error) {
33241
33582
  for (const moved of movedOriginals.reverse()) {
33242
- if (existsSync23(moved.to) && !existsSync23(moved.from))
33583
+ if (existsSync24(moved.to) && !existsSync24(moved.from))
33243
33584
  renameSync4(moved.to, moved.from);
33244
33585
  }
33245
33586
  throw error;
@@ -33275,7 +33616,7 @@ async function runRepairDb(options = {}) {
33275
33616
  const stamp = timestamp(deps.now());
33276
33617
  prompts.intro("Magic Context — Repair shared database");
33277
33618
  prompts.log.info(`Database: ${dbPath}`);
33278
- if (!existsSync23(dbPath)) {
33619
+ if (!existsSync24(dbPath)) {
33279
33620
  prompts.log.error(`Database not found: ${dbPath}`);
33280
33621
  prompts.log.info("Backup: not created (database does not exist)");
33281
33622
  prompts.outro("Database repair failed");
@@ -33562,7 +33903,7 @@ var init_migration_paths = __esm(() => {
33562
33903
 
33563
33904
  // src/commands/migrate.ts
33564
33905
  import { createHash as createHash4, randomBytes as randomBytes2 } from "node:crypto";
33565
- import { existsSync as existsSync24, mkdirSync as mkdirSync7, renameSync as renameSync5, unlinkSync as unlinkSync4 } from "node:fs";
33906
+ import { existsSync as existsSync25, mkdirSync as mkdirSync7, renameSync as renameSync5, unlinkSync as unlinkSync4 } from "node:fs";
33566
33907
  import { dirname as dirname13, join as join21 } from "node:path";
33567
33908
  function defaultOpenCodeDbPath() {
33568
33909
  return getOpenCodeDatabasePath();
@@ -33574,7 +33915,7 @@ function defaultPiSessionsRoot() {
33574
33915
  return getPiSessionsRoot();
33575
33916
  }
33576
33917
  function defaultFs() {
33577
- return { writeFileAtomic, unlinkSync: unlinkSync4, existsSync: existsSync24, renameSync: renameSync5, mkdirSync: mkdirSync7 };
33918
+ return { writeFileAtomic, unlinkSync: unlinkSync4, existsSync: existsSync25, renameSync: renameSync5, mkdirSync: mkdirSync7 };
33578
33919
  }
33579
33920
  function stmt(db, sql) {
33580
33921
  return db.prepare(sql);
@@ -34522,7 +34863,7 @@ var init_relocate_memory = __esm(() => {
34522
34863
  });
34523
34864
 
34524
34865
  // src/commands/migrate-session.ts
34525
- import { existsSync as existsSync25, realpathSync as realpathSync4 } from "node:fs";
34866
+ import { existsSync as existsSync26, realpathSync as realpathSync4 } from "node:fs";
34526
34867
  import { homedir as homedir14 } from "node:os";
34527
34868
  import path4, { join as join22 } from "node:path";
34528
34869
  function existingSessionColumns(db) {
@@ -34741,7 +35082,7 @@ function realDeps(opencodeDb, contextDb) {
34741
35082
  opencodeDb,
34742
35083
  contextDb,
34743
35084
  resolveIdentity: resolveProjectIdentity,
34744
- hasGitDir: (dir) => existsSync25(join22(dir, ".git")),
35085
+ hasGitDir: (dir) => existsSync26(join22(dir, ".git")),
34745
35086
  realpath: (p) => realpathSync4(p)
34746
35087
  };
34747
35088
  }
@@ -34820,7 +35161,7 @@ async function runMigrateSessionCli(args) {
34820
35161
  return 1;
34821
35162
  }
34822
35163
  const expandedTo = toDir.startsWith("~") ? join22(homedir14(), toDir.slice(1).replace(/^[/\\]/, "")) : toDir;
34823
- if (!existsSync25(expandedTo)) {
35164
+ if (!existsSync26(expandedTo)) {
34824
35165
  console.error(`Target directory does not exist: ${expandedTo}`);
34825
35166
  return 1;
34826
35167
  }
@@ -35222,6 +35563,11 @@ var init_user_facing_codes = __esm(() => {
35222
35563
  sentence: "Some finished background sessions could not be removed from this host.",
35223
35564
  action: "They are removed automatically the next time Magic Context runs inside a registered OpenCode service."
35224
35565
  },
35566
+ historian_saved_history_misaligned: {
35567
+ code: "MC-H03",
35568
+ sentence: "History compression is paused because this session's saved summaries no longer line up with its messages.",
35569
+ action: "Run /ctx-recomp to rebuild them."
35570
+ },
35225
35571
  recomp_unavailable: {
35226
35572
  code: "MC-R01",
35227
35573
  sentence: "History compression could not be rebuilt.",
@@ -35392,6 +35738,11 @@ var init_user_facing_codes = __esm(() => {
35392
35738
  sentence: "History compression is paused while the engine syncs.",
35393
35739
  action: "Retry in a moment."
35394
35740
  },
35741
+ history_compression_needs_message: {
35742
+ code: "MC-C12",
35743
+ sentence: "History compression has not seen this session since Magic Context reconnected.",
35744
+ action: "Send a message in this session first, then run /ctx-wrapup again."
35745
+ },
35395
35746
  context_service_unavailable: {
35396
35747
  code: "MC-C10",
35397
35748
  sentence: "Magic Context is temporarily unavailable.",
@@ -35462,7 +35813,7 @@ var init_tick_failure = __esm(() => {
35462
35813
  });
35463
35814
 
35464
35815
  // ../pi-plugin/src/config/index.ts
35465
- import { existsSync as existsSync26 } from "node:fs";
35816
+ import { existsSync as existsSync27 } from "node:fs";
35466
35817
  function getProjectConfigPaths(cwd) {
35467
35818
  const basePath = cortexKitProjectConfigBasePath(cwd);
35468
35819
  return [`${basePath}.jsonc`, `${basePath}.json`];
@@ -35472,10 +35823,10 @@ function getUserConfigPaths() {
35472
35823
  return [`${basePath}.jsonc`, `${basePath}.json`];
35473
35824
  }
35474
35825
  function resolveFirstExisting(paths) {
35475
- return paths.find((path) => existsSync26(path));
35826
+ return paths.find((path) => existsSync27(path));
35476
35827
  }
35477
35828
  function resolvePiLegacyFallback(sources) {
35478
- return sources.find((source) => existsSync26(source.path)) ?? null;
35829
+ return sources.find((source) => existsSync27(source.path)) ?? null;
35479
35830
  }
35480
35831
  function loadConfigFile(path, scope) {
35481
35832
  let raw;
@@ -35770,7 +36121,7 @@ function loadPiConfigDetailed(opts = {}, applyRuntimeGlobals = true) {
35770
36121
  if (loaded)
35771
36122
  loadedFiles.push(loaded);
35772
36123
  }
35773
- const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) => existsSync26(source.path));
36124
+ const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) => existsSync27(source.path));
35774
36125
  const userPath = resolveFirstExisting(getUserConfigPaths());
35775
36126
  const userLegacyFallback = userPath ? null : resolvePiLegacyFallback(harnessLegacy.user);
35776
36127
  const userReadPath = userPath ?? userLegacyFallback?.path;
@@ -35779,7 +36130,7 @@ function loadPiConfigDetailed(opts = {}, applyRuntimeGlobals = true) {
35779
36130
  if (loaded)
35780
36131
  loadedFiles.push(loaded);
35781
36132
  }
35782
- const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) => existsSync26(source.path));
36133
+ const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) => existsSync27(source.path));
35783
36134
  if (userLegacyFallback) {
35784
36135
  warnings.push(`[user config] reading legacy config from ${userLegacyFallback.path} until migration completes; run \`npx @cortexkit/magic-context doctor\` to consolidate into the shared CortexKit location.`);
35785
36136
  } else if (legacyUserUnmigrated) {
@@ -35900,11 +36251,11 @@ function formatDatabaseRepairGuidance(dbPath) {
35900
36251
  var DATABASE_REPAIR_COMMAND = "bunx @cortexkit/magic-context@latest doctor repair-db";
35901
36252
 
35902
36253
  // src/lib/github-issue.ts
35903
- import { spawnSync as spawnSync4 } from "node:child_process";
35904
- import { readFileSync as readFileSync15 } from "node:fs";
36254
+ import { spawnSync as spawnSync5 } from "node:child_process";
36255
+ import { readFileSync as readFileSync16 } from "node:fs";
35905
36256
  function runGhCommand(args) {
35906
36257
  try {
35907
- const result = spawnSync4("gh", args, {
36258
+ const result = spawnSync5("gh", args, {
35908
36259
  encoding: "utf-8",
35909
36260
  stdio: ["ignore", "pipe", "pipe"]
35910
36261
  });
@@ -35927,7 +36278,7 @@ function failed(result) {
35927
36278
  function submitGithubIssue(title, bodyPath, runner = runGhCommand) {
35928
36279
  let body;
35929
36280
  try {
35930
- body = readFileSync15(bodyPath, "utf-8");
36281
+ body = readFileSync16(bodyPath, "utf-8");
35931
36282
  } catch (error) {
35932
36283
  return {
35933
36284
  ok: false,
@@ -35985,7 +36336,7 @@ var MAX_GITHUB_ISSUE_BODY_CHARS = 65536;
35985
36336
  var init_github_issue = () => {};
35986
36337
 
35987
36338
  // src/lib/log-lines.ts
35988
- import { existsSync as existsSync27, readFileSync as readFileSync16, statSync as statSync12 } from "node:fs";
36339
+ import { existsSync as existsSync28, readFileSync as readFileSync17, statSync as statSync12 } from "node:fs";
35989
36340
  import { tmpdir as tmpdir2 } from "node:os";
35990
36341
  import { join as join23 } from "node:path";
35991
36342
  function tokenize(input, limit = Number.POSITIVE_INFINITY) {
@@ -36282,11 +36633,11 @@ function getMagicContextLogPaths(harness, options = {}) {
36282
36633
  ].filter((path, index, paths) => paths.indexOf(path) === index);
36283
36634
  }
36284
36635
  function inspectLogFile(path) {
36285
- if (!existsSync27(path)) {
36636
+ if (!existsSync28(path)) {
36286
36637
  return { path, exists: false, sizeKb: 0, lineCount: 0, grammar: "unknown" };
36287
36638
  }
36288
36639
  try {
36289
- const content = readFileSync16(path, "utf8");
36640
+ const content = readFileSync17(path, "utf8");
36290
36641
  const lines = content.split(/\r?\n/).filter((line) => line.length > 0);
36291
36642
  const grammars = new Set(lines.flatMap((line) => {
36292
36643
  const parsed = parseLogLine(line);
@@ -36313,7 +36664,7 @@ function readLogLines(files) {
36313
36664
  return [];
36314
36665
  try {
36315
36666
  let precedingTimestamp = "";
36316
- return readFileSync16(file.path, "utf8").split(/\r?\n/).filter((line) => line.length > 0).map((line, lineIndex) => {
36667
+ return readFileSync17(file.path, "utf8").split(/\r?\n/).filter((line) => line.length > 0).map((line, lineIndex) => {
36317
36668
  precedingTimestamp = parseLogLine(line)?.ts ?? precedingTimestamp;
36318
36669
  return { line, timestamp: precedingTimestamp, fileIndex, lineIndex };
36319
36670
  });
@@ -36362,10 +36713,10 @@ var init_redaction2 = __esm(() => {
36362
36713
  });
36363
36714
 
36364
36715
  // src/commands/doctor-omp.ts
36365
- import { execFileSync as execFileSync5, spawnSync as spawnSync5 } from "node:child_process";
36366
- import { existsSync as existsSync28, mkdirSync as mkdirSync8, readFileSync as readFileSync17 } from "node:fs";
36716
+ import { execFileSync as execFileSync5, spawnSync as spawnSync6 } from "node:child_process";
36717
+ import { existsSync as existsSync29, mkdirSync as mkdirSync8, readFileSync as readFileSync18 } from "node:fs";
36367
36718
  import { createRequire as createRequire3 } from "node:module";
36368
- import { dirname as dirname14, join as join24, resolve as resolve7 } from "node:path";
36719
+ import { dirname as dirname14, join as join24, resolve as resolve8 } from "node:path";
36369
36720
  function parseSemver(value) {
36370
36721
  const match = value?.match(/(\d+)\.(\d+)\.(\d+)/);
36371
36722
  return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
@@ -36407,10 +36758,10 @@ function selfVersion() {
36407
36758
  return "unknown";
36408
36759
  }
36409
36760
  function readConfig2(path) {
36410
- if (!existsSync28(path))
36761
+ if (!existsSync29(path))
36411
36762
  return {};
36412
36763
  try {
36413
- const parsed = import_comment_json7.parse(readFileSync17(path, "utf-8"));
36764
+ const parsed = import_comment_json7.parse(readFileSync18(path, "utf-8"));
36414
36765
  return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? {} : { error: "top level is not an object" };
36415
36766
  } catch (error) {
36416
36767
  return { error: error instanceof Error ? error.message : String(error) };
@@ -36420,7 +36771,7 @@ function pluginDeclaresOmp(path) {
36420
36771
  if (!path)
36421
36772
  return null;
36422
36773
  try {
36423
- const pkg = JSON.parse(readFileSync17(join24(path, "package.json"), "utf-8"));
36774
+ const pkg = JSON.parse(readFileSync18(join24(path, "package.json"), "utf-8"));
36424
36775
  return Array.isArray(pkg.omp?.extensions) || Array.isArray(pkg.pi?.extensions);
36425
36776
  } catch {
36426
36777
  return null;
@@ -36491,8 +36842,8 @@ async function runHealthChecks(options) {
36491
36842
  if (!reportedAgentDir.ok) {
36492
36843
  add(results, "warn", "Could not verify OMP active agent directory");
36493
36844
  } else {
36494
- const reportedPath = resolve7(reportedAgentDir.stdout);
36495
- const expectedPath = resolve7(getOmpAgentDir());
36845
+ const reportedPath = resolve8(reportedAgentDir.stdout);
36846
+ const expectedPath = resolve8(getOmpAgentDir());
36496
36847
  if (reportedPath === expectedPath) {
36497
36848
  add(results, "pass", `OMP agent directory resolved to ${getOmpAgentDir()}`);
36498
36849
  } else {
@@ -36501,7 +36852,7 @@ async function runHealthChecks(options) {
36501
36852
  }
36502
36853
  }
36503
36854
  const userConfigPath = getOmpUserConfigPath();
36504
- if (!existsSync28(userConfigPath)) {
36855
+ if (!existsSync29(userConfigPath)) {
36505
36856
  add(results, "warn", `No Magic Context user config at ${userConfigPath}`);
36506
36857
  repairPlan.writeUserConfig = true;
36507
36858
  } else {
@@ -36520,7 +36871,7 @@ async function runHealthChecks(options) {
36520
36871
  const storage = getMagicContextStorageResolution();
36521
36872
  const dbPath = join24(storage.path, "context.db");
36522
36873
  add(results, "info", `Shared storage: ${storage.path} (source: ${storage.source})`);
36523
- if (!existsSync28(dbPath))
36874
+ if (!existsSync29(dbPath))
36524
36875
  add(results, "info", `Shared context DB will be created at ${dbPath}`);
36525
36876
  else {
36526
36877
  let db = null;
@@ -36584,7 +36935,7 @@ function writeDefaultConfig(path) {
36584
36935
  }
36585
36936
  async function repair(plan, deps, prompts, cwd) {
36586
36937
  let fixed = 0;
36587
- if (plan.writeUserConfig && !existsSync28(getOmpUserConfigPath())) {
36938
+ if (plan.writeUserConfig && !existsSync29(getOmpUserConfigPath())) {
36588
36939
  writeDefaultConfig(getOmpUserConfigPath());
36589
36940
  prompts.log.success(`Wrote default Magic Context config to ${getOmpUserConfigPath()}`);
36590
36941
  fixed += 1;
@@ -36741,7 +37092,7 @@ var init_doctor_omp = __esm(async () => {
36741
37092
  now: () => new Date,
36742
37093
  inspectMagicContextLogs,
36743
37094
  execFileSync: execFileSync5,
36744
- spawnSync: spawnSync5
37095
+ spawnSync: spawnSync6
36745
37096
  };
36746
37097
  });
36747
37098
 
@@ -37641,12 +37992,12 @@ function listShadowBackfillStalls(db, projectIdentity) {
37641
37992
  var SHADOW_BACKFILL_PROVENANCE_KEY = "_magicContextShadowBackfill";
37642
37993
 
37643
37994
  // ../plugin/src/shared/auto-update-provenance.ts
37644
- import { existsSync as existsSync29, readFileSync as readFileSync18 } from "node:fs";
37995
+ import { existsSync as existsSync30, readFileSync as readFileSync19 } from "node:fs";
37645
37996
  function readAutoUpdateCheckState(path) {
37646
- if (!existsSync29(path))
37997
+ if (!existsSync30(path))
37647
37998
  return null;
37648
37999
  try {
37649
- const value = JSON.parse(readFileSync18(path, "utf-8"));
38000
+ const value = JSON.parse(readFileSync19(path, "utf-8"));
37650
38001
  if (!value || typeof value !== "object" || Array.isArray(value))
37651
38002
  return null;
37652
38003
  const raw = value;
@@ -37674,9 +38025,9 @@ var init_auto_update_provenance = () => {};
37674
38025
  // ../plugin/src/shared/tui-config.ts
37675
38026
  import {
37676
38027
  chmodSync as chmodSync5,
37677
- existsSync as existsSync30,
38028
+ existsSync as existsSync31,
37678
38029
  mkdirSync as mkdirSync9,
37679
- readFileSync as readFileSync19,
38030
+ readFileSync as readFileSync20,
37680
38031
  renameSync as renameSync6,
37681
38032
  statSync as statSync13,
37682
38033
  writeFileSync as writeFileSync6
@@ -37724,9 +38075,9 @@ function resolveTuiConfigPath(configDirOverride) {
37724
38075
  const configDir = configDirOverride ?? getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
37725
38076
  const jsoncPath = join25(configDir, "tui.jsonc");
37726
38077
  const jsonPath = join25(configDir, "tui.json");
37727
- if (existsSync30(jsoncPath))
38078
+ if (existsSync31(jsoncPath))
37728
38079
  return jsoncPath;
37729
- if (existsSync30(jsonPath))
38080
+ if (existsSync31(jsonPath))
37730
38081
  return jsonPath;
37731
38082
  return jsoncPath;
37732
38083
  }
@@ -37734,8 +38085,8 @@ function ensureTuiPluginEntry(options = {}) {
37734
38085
  try {
37735
38086
  const configPath = resolveTuiConfigPath(options.configDir);
37736
38087
  let config = {};
37737
- if (existsSync30(configPath)) {
37738
- const raw = readFileSync19(configPath, "utf-8");
38088
+ if (existsSync31(configPath)) {
38089
+ const raw = readFileSync20(configPath, "utf-8");
37739
38090
  config = import_comment_json8.parse(raw) ?? {};
37740
38091
  }
37741
38092
  const plugins = Array.isArray(config.plugin) ? [...config.plugin] : [];
@@ -37787,7 +38138,7 @@ var init_tui_config = __esm(() => {
37787
38138
  });
37788
38139
 
37789
38140
  // src/lib/diagnostics-opencode.ts
37790
- import { existsSync as existsSync31, readdirSync as readdirSync4, readFileSync as readFileSync20, statSync as statSync14 } from "node:fs";
38141
+ import { existsSync as existsSync32, readdirSync as readdirSync5, readFileSync as readFileSync21, statSync as statSync14 } from "node:fs";
37791
38142
  import { createRequire as createRequire4 } from "node:module";
37792
38143
  import { join as join26 } from "node:path";
37793
38144
  function getSelfVersion() {
@@ -37802,29 +38153,52 @@ function getSelfVersion() {
37802
38153
  }
37803
38154
  return "unknown";
37804
38155
  }
37805
- function getPluginCacheInfo() {
37806
- const [path = ""] = getOpenCodePluginCacheRoots();
38156
+ function readLegacyCachedVersion(root) {
38157
+ try {
38158
+ const pkg = JSON.parse(readFileSync21(getOpenCodePluginPackageJsonPath(root), "utf-8"));
38159
+ return typeof pkg.version === "string" ? pkg.version : undefined;
38160
+ } catch {
38161
+ return;
38162
+ }
38163
+ }
38164
+ function collectOpenCodePluginCacheReport(hostGeneration, opencodeConfig) {
38165
+ const installs = [];
38166
+ for (const root of getOpenCodePluginCacheRoots()) {
38167
+ if (!existsSync32(root))
38168
+ continue;
38169
+ const spec = root.endsWith("@latest") ? "latest" : "(bare)";
38170
+ installs.push({
38171
+ layout: "opencode1",
38172
+ spec,
38173
+ path: root,
38174
+ cached: readLegacyCachedVersion(root)
38175
+ });
38176
+ }
38177
+ for (const slot of listOpenCodeV2PluginCacheSlots()) {
38178
+ installs.push({
38179
+ layout: "opencode2",
38180
+ spec: slot.spec,
38181
+ path: slot.slot,
38182
+ cached: slot.version
38183
+ });
38184
+ }
38185
+ let path;
37807
38186
  let cached;
37808
- for (const installedPkgPath of getOpenCodePluginPackageJsonPaths()) {
37809
- try {
37810
- if (existsSync31(installedPkgPath)) {
37811
- const pkg = JSON.parse(readFileSync20(installedPkgPath, "utf-8"));
37812
- cached = typeof pkg.version === "string" ? pkg.version : undefined;
37813
- if (cached)
37814
- break;
37815
- }
37816
- } catch {
37817
- cached = undefined;
37818
- }
38187
+ if (hostGeneration === "v2") {
38188
+ path = getOpenCodeV2PluginCacheSlot(undefined, readConfiguredOpenCodePluginSpec(opencodeConfig));
38189
+ cached = readOpenCodeV2CachedPluginVersion(path);
38190
+ } else {
38191
+ [path = ""] = getOpenCodePluginCacheRoots();
38192
+ cached = installs.find((install) => install.layout === "opencode1" && install.cached)?.cached;
37819
38193
  }
37820
- return { path, cached, latest: getSelfVersion() };
38194
+ return { path, cached, latest: getSelfVersion(), installs };
37821
38195
  }
37822
38196
  function getStorageResolution() {
37823
38197
  return getMagicContextStorageResolution();
37824
38198
  }
37825
38199
  function fileSize(path) {
37826
38200
  try {
37827
- return existsSync31(path) ? statSync14(path).size : 0;
38201
+ return existsSync32(path) ? statSync14(path).size : 0;
37828
38202
  } catch {
37829
38203
  return 0;
37830
38204
  }
@@ -37836,10 +38210,10 @@ function sanitizeValue(value) {
37836
38210
  return sanitizeConfigValue(value);
37837
38211
  }
37838
38212
  function readConfig3(path) {
37839
- if (!existsSync31(path))
38213
+ if (!existsSync32(path))
37840
38214
  return { value: null };
37841
38215
  try {
37842
- const raw = readFileSync20(path, "utf-8");
38216
+ const raw = readFileSync21(path, "utf-8");
37843
38217
  const value = import_comment_json9.parse(raw);
37844
38218
  return { value };
37845
38219
  } catch (error) {
@@ -37847,9 +38221,9 @@ function readConfig3(path) {
37847
38221
  }
37848
38222
  }
37849
38223
  function configHasPluginEntry(config) {
37850
- const plugins = readPluginEntries(config).map(({ entry }) => entry);
38224
+ const plugins = readPluginEntries(config).map(({ entry }) => pluginEntryPackage(entry));
37851
38225
  return plugins.some((entry) => {
37852
- if (typeof entry !== "string")
38226
+ if (entry === null)
37853
38227
  return false;
37854
38228
  if (entry === OPENCODE_PLUGIN_NAME)
37855
38229
  return true;
@@ -37864,7 +38238,7 @@ function configHasPluginEntry(config) {
37864
38238
  }
37865
38239
  function parseHistorianDumpMeta(path) {
37866
38240
  try {
37867
- const xml = readFileSync20(path, "utf-8");
38241
+ const xml = readFileSync21(path, "utf-8");
37868
38242
  const parsed = parseCompartmentOutput(xml);
37869
38243
  const factCountByCategory = {};
37870
38244
  for (const fact of parsed.facts) {
@@ -37897,10 +38271,10 @@ function parseHistorianDumpMeta(path) {
37897
38271
  }
37898
38272
  }
37899
38273
  function listDumpsInDir(dir, limit) {
37900
- if (!existsSync31(dir))
38274
+ if (!existsSync32(dir))
37901
38275
  return { count: 0, recent: [] };
37902
38276
  try {
37903
- const entries = readdirSync4(dir).filter((name) => name.endsWith(".xml")).map((name) => {
38277
+ const entries = readdirSync5(dir).filter((name) => name.endsWith(".xml")).map((name) => {
37904
38278
  const stat = statSync14(join26(dir, name));
37905
38279
  return {
37906
38280
  name,
@@ -38049,7 +38423,7 @@ async function collectRecentSessions(resolution, hostGeneration) {
38049
38423
  }
38050
38424
  async function collectHistorianFailures(storageDirPath) {
38051
38425
  const contextDbPath = join26(storageDirPath, "context.db");
38052
- if (!existsSync31(contextDbPath))
38426
+ if (!existsSync32(contextDbPath))
38053
38427
  return [];
38054
38428
  if (typeof globalThis.Bun === "undefined") {
38055
38429
  return [];
@@ -38083,7 +38457,7 @@ async function collectHistorianFailures(storageDirPath) {
38083
38457
  }
38084
38458
  async function collectHistorianRuns(storageDirPath) {
38085
38459
  const contextDbPath = join26(storageDirPath, "context.db");
38086
- if (!existsSync31(contextDbPath))
38460
+ if (!existsSync32(contextDbPath))
38087
38461
  return [];
38088
38462
  if (typeof globalThis.Bun === "undefined")
38089
38463
  return [];
@@ -38185,15 +38559,15 @@ async function collectDiagnostics() {
38185
38559
  opencodeConfigHasPlugin: configHasPluginEntry(opencodeConfig.value),
38186
38560
  tuiConfigHasPlugin: configHasPluginEntry(tuiConfig.value),
38187
38561
  magicContextConfig: {
38188
- exists: existsSync31(configPaths.magicContextConfig),
38562
+ exists: existsSync32(configPaths.magicContextConfig),
38189
38563
  ...magicContextConfig.error ? { parseError: magicContextConfig.error } : {},
38190
38564
  flags: sanitizeValue(magicContextConfig.value ?? {}) ?? {}
38191
38565
  },
38192
- pluginCache: getPluginCacheInfo(),
38566
+ pluginCache: collectOpenCodePluginCacheReport(hostGeneration, opencodeConfig.value),
38193
38567
  storageDir: {
38194
38568
  path: storageDirPath,
38195
38569
  source: storageResolution.source,
38196
- exists: existsSync31(storageDirPath),
38570
+ exists: existsSync32(storageDirPath),
38197
38571
  contextDbSizeBytes: fileSize(contextDbPath)
38198
38572
  },
38199
38573
  openCodeDatabase: {
@@ -38240,7 +38614,12 @@ function renderDiagnosticsMarkdown(report) {
38240
38614
  const pluginCache = {
38241
38615
  path: sanitizeString(report.pluginCache.path),
38242
38616
  cached: report.pluginCache.cached ?? null,
38243
- latest: report.pluginCache.latest ?? null
38617
+ latest: report.pluginCache.latest ?? null,
38618
+ installs: (report.pluginCache.installs ?? []).map((install) => ({
38619
+ ...install,
38620
+ path: sanitizeString(install.path),
38621
+ cached: install.cached ?? null
38622
+ }))
38244
38623
  };
38245
38624
  const storage = {
38246
38625
  path: sanitizeString(report.storageDir.path),
@@ -38356,6 +38735,7 @@ var init_diagnostics_opencode = __esm(() => {
38356
38735
  init_conflict_detector();
38357
38736
  init_data_path();
38358
38737
  init_opencode_db_path();
38738
+ init_opencode();
38359
38739
  init_log_lines();
38360
38740
  init_opencode_detect();
38361
38741
  init_opencode_helpers();
@@ -38419,8 +38799,8 @@ var init_embedding_local = __esm(() => {
38419
38799
  });
38420
38800
 
38421
38801
  // src/lib/embedding-runtime.ts
38422
- import { spawnSync as spawnSync6 } from "node:child_process";
38423
- import { existsSync as existsSync32, readFileSync as readFileSync21 } from "node:fs";
38802
+ import { spawnSync as spawnSync7 } from "node:child_process";
38803
+ import { existsSync as existsSync33, readFileSync as readFileSync22 } from "node:fs";
38424
38804
  import { createRequire as createRequire5 } from "node:module";
38425
38805
  import { dirname as dirname16, join as join27, sep } from "node:path";
38426
38806
  function describeError(error) {
@@ -38429,7 +38809,7 @@ function describeError(error) {
38429
38809
  return typeof code === "string" && code.length > 0 ? `${code}: ${message}` : message;
38430
38810
  }
38431
38811
  function runOnnxRuntimeNodeLoadProbeChild(packageDir) {
38432
- return spawnSync6(process.execPath, ["-e", ONNX_RUNTIME_NODE_LOAD_PROBE_SCRIPT], {
38812
+ return spawnSync7(process.execPath, ["-e", ONNX_RUNTIME_NODE_LOAD_PROBE_SCRIPT], {
38433
38813
  encoding: "utf8",
38434
38814
  env: { ...process.env, [ONNX_LOAD_PROBE_PACKAGE_DIR_ENV]: packageDir },
38435
38815
  stdio: ["ignore", "pipe", "pipe"],
@@ -38567,7 +38947,7 @@ function expectedBinaryRelPath(platform, arch) {
38567
38947
  }
38568
38948
  function onnxRuntimeNodeVersion(packageDir) {
38569
38949
  try {
38570
- const parsed = JSON.parse(readFileSync21(join27(packageDir, "package.json"), "utf8"));
38950
+ const parsed = JSON.parse(readFileSync22(join27(packageDir, "package.json"), "utf8"));
38571
38951
  return typeof parsed.version === "string" ? parsed.version : undefined;
38572
38952
  } catch {
38573
38953
  return;
@@ -38616,7 +38996,7 @@ function formatLocalEmbeddingRuntimeWasmSelected(status) {
38616
38996
  function requireNodeWasmBundle(probe, candidates) {
38617
38997
  if (probe.state === "failed")
38618
38998
  return probe;
38619
- const bundlePath = candidates.find((candidate) => existsSync32(candidate));
38999
+ const bundlePath = candidates.find((candidate) => existsSync33(candidate));
38620
39000
  return bundlePath ? probe : {
38621
39001
  state: "failed",
38622
39002
  reason: `functional Node WASM Transformers bundle is missing (checked ${candidates.join(", ")})`
@@ -38641,7 +39021,7 @@ function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform,
38641
39021
  }
38642
39022
  const packageDir = join27(installRoot, "node_modules", "onnxruntime-node");
38643
39023
  let native;
38644
- if (!existsSync32(join27(packageDir, "package.json"))) {
39024
+ if (!existsSync33(join27(packageDir, "package.json"))) {
38645
39025
  native = { state: "package-missing", packageDir };
38646
39026
  } else {
38647
39027
  const rel = expectedBinaryRelPath(platform, arch);
@@ -38652,7 +39032,7 @@ function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform,
38652
39032
  };
38653
39033
  } else {
38654
39034
  const binaryPath = join27(packageDir, rel);
38655
- native = existsSync32(binaryPath) ? probeOnnxRuntimeNodeLoad(packageDir) ?? { state: "ok", binaryPath } : {
39035
+ native = existsSync33(binaryPath) ? probeOnnxRuntimeNodeLoad(packageDir) ?? { state: "ok", binaryPath } : {
38656
39036
  state: "binary-missing",
38657
39037
  packageDir,
38658
39038
  expectedBinary: binaryPath,
@@ -38663,7 +39043,7 @@ function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform,
38663
39043
  return withWasmFallback(native, () => probeWasmRuntimeAt(installRoot));
38664
39044
  }
38665
39045
  function checkLocalEmbeddingRuntime(installRoots, platform = process.platform, arch = process.arch, runtimePreference = "auto", host) {
38666
- const existing = installRoots.filter((root) => existsSync32(root));
39046
+ const existing = installRoots.filter((root) => existsSync33(root));
38667
39047
  if (existing.length === 0) {
38668
39048
  return {
38669
39049
  state: "unknown",
@@ -38710,7 +39090,7 @@ function probeWasmRuntimeByResolution(pluginDir) {
38710
39090
  }
38711
39091
  }
38712
39092
  function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.platform, arch = process.arch, runtimePreference = "auto", host) {
38713
- if (!existsSync32(join27(pluginDir, "package.json"))) {
39093
+ if (!existsSync33(join27(pluginDir, "package.json"))) {
38714
39094
  return { state: "unknown", reason: "plugin package dir not found" };
38715
39095
  }
38716
39096
  const selectedRuntime = resolveLocalEmbeddingRuntime(runtimePreference, host);
@@ -38752,7 +39132,7 @@ function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.pl
38752
39132
  native = probeOnnxRuntimeNodeLoad(onnxDir) ?? { state: "ok", binaryPath: onnxDir };
38753
39133
  } else {
38754
39134
  const binaryPath = join27(onnxDir, rel);
38755
- native = existsSync32(binaryPath) ? probeOnnxRuntimeNodeLoad(onnxDir) ?? { state: "ok", binaryPath } : {
39135
+ native = existsSync33(binaryPath) ? probeOnnxRuntimeNodeLoad(onnxDir) ?? { state: "ok", binaryPath } : {
38756
39136
  state: "binary-missing",
38757
39137
  packageDir: onnxDir,
38758
39138
  expectedBinary: binaryPath,
@@ -39291,6 +39671,7 @@ var init_constants2 = __esm(() => {
39291
39671
  USER_OPENCODE_CONFIG = join29(getOpenCodeConfigRoot(), "opencode.json");
39292
39672
  USER_OPENCODE_CONFIG_JSONC = join29(getOpenCodeConfigRoot(), "opencode.jsonc");
39293
39673
  });
39674
+
39294
39675
  // ../plugin/src/hooks/auto-update-checker/types.ts
39295
39676
  var NpmPackageEnvelopeSchema, OpencodePluginTupleSchema, OpencodeConfigSchema, PackageJsonSchema;
39296
39677
  var init_types = __esm(() => {
@@ -39312,14 +39693,14 @@ var init_types = __esm(() => {
39312
39693
  // ../plugin/src/hooks/auto-update-checker/checker.ts
39313
39694
  import {
39314
39695
  accessSync as accessSync2,
39315
- existsSync as existsSync33,
39696
+ existsSync as existsSync34,
39316
39697
  constants as fsConstants,
39317
- readFileSync as readFileSync22,
39698
+ readFileSync as readFileSync23,
39318
39699
  renameSync as renameSync7,
39319
39700
  statSync as statSync15,
39320
39701
  writeFileSync as writeFileSync8
39321
39702
  } from "node:fs";
39322
- import { dirname as dirname17, isAbsolute as isAbsolute7, join as join30, resolve as resolve8 } from "node:path";
39703
+ import { dirname as dirname17, isAbsolute as isAbsolute7, join as join30, resolve as resolve9 } from "node:path";
39323
39704
  function warn(message) {
39324
39705
  log3(`WARN: ${message}`);
39325
39706
  }
@@ -39366,9 +39747,9 @@ function getWinningConfig(directory, surface) {
39366
39747
  let winner = null;
39367
39748
  for (const path of getSurfaceConfigPaths(directory, surface)) {
39368
39749
  try {
39369
- if (!existsSync33(path))
39750
+ if (!existsSync34(path))
39370
39751
  continue;
39371
- const parsed = parseJsonConfig(readFileSync22(path, "utf-8"));
39752
+ const parsed = parseJsonConfig(readFileSync23(path, "utf-8"));
39372
39753
  const entries = getPluginEntries(parsed);
39373
39754
  if (entries.some((entry) => entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`))) {
39374
39755
  if (winner) {
@@ -39404,14 +39785,14 @@ var init_checker = __esm(() => {
39404
39785
  });
39405
39786
 
39406
39787
  // src/lib/opencode-plugin-schema-fence.ts
39407
- import { existsSync as existsSync34, readdirSync as readdirSync5, readFileSync as readFileSync23 } from "node:fs";
39788
+ import { existsSync as existsSync35, readdirSync as readdirSync6, readFileSync as readFileSync24 } from "node:fs";
39408
39789
  import { join as join31 } from "node:path";
39409
39790
  import { gunzipSync } from "node:zlib";
39410
39791
  function readPackageVersion(packageJsonPath) {
39411
39792
  try {
39412
- if (!existsSync34(packageJsonPath))
39793
+ if (!existsSync35(packageJsonPath))
39413
39794
  return null;
39414
- const packageJson = JSON.parse(readFileSync23(packageJsonPath, "utf-8"));
39795
+ const packageJson = JSON.parse(readFileSync24(packageJsonPath, "utf-8"));
39415
39796
  if (packageJson.name !== OPENCODE_PLUGIN_NAME || typeof packageJson.version !== "string") {
39416
39797
  return null;
39417
39798
  }
@@ -39431,7 +39812,7 @@ function readFenceValue(text) {
39431
39812
  }
39432
39813
  function readFenceFromDist(packageDirectory) {
39433
39814
  const distDirectory = join31(packageDirectory, "dist");
39434
- if (!existsSync34(distDirectory))
39815
+ if (!existsSync35(distDirectory))
39435
39816
  return null;
39436
39817
  const pending = [distDirectory];
39437
39818
  const fenceValues = new Set;
@@ -39440,7 +39821,7 @@ function readFenceFromDist(packageDirectory) {
39440
39821
  if (!directory)
39441
39822
  continue;
39442
39823
  try {
39443
- for (const entry of readdirSync5(directory, { withFileTypes: true })) {
39824
+ for (const entry of readdirSync6(directory, { withFileTypes: true })) {
39444
39825
  const path = join31(directory, entry.name);
39445
39826
  if (entry.isDirectory()) {
39446
39827
  pending.push(path);
@@ -39448,7 +39829,7 @@ function readFenceFromDist(packageDirectory) {
39448
39829
  }
39449
39830
  if (!entry.isFile() || !/\.(?:[cm]?js|ts)$/.test(entry.name))
39450
39831
  continue;
39451
- const fence = readFenceValue(readFileSync23(path, "utf-8"));
39832
+ const fence = readFenceValue(readFileSync24(path, "utf-8"));
39452
39833
  if (fence !== null)
39453
39834
  fenceValues.add(fence);
39454
39835
  }
@@ -39462,7 +39843,7 @@ function findInstalledPluginPackage(cacheDirectory, specifier, requestedVersion)
39462
39843
  const directCacheRoot = join31(cacheDirectory, specifier);
39463
39844
  const candidates = [directCacheRoot];
39464
39845
  try {
39465
- for (const entry of readdirSync5(cacheDirectory, { withFileTypes: true })) {
39846
+ for (const entry of readdirSync6(cacheDirectory, { withFileTypes: true })) {
39466
39847
  if (!entry.isDirectory())
39467
39848
  continue;
39468
39849
  const candidate = join31(cacheDirectory, entry.name);
@@ -39846,22 +40227,22 @@ var init_doctor_harness_relabel = __esm(async () => {
39846
40227
  });
39847
40228
 
39848
40229
  // src/commands/doctor-opencode-cache.ts
39849
- import { existsSync as existsSync35, readFileSync as readFileSync24, rmSync as rmSync3 } from "node:fs";
40230
+ import { existsSync as existsSync36, readFileSync as readFileSync25, rmSync as rmSync4 } from "node:fs";
39850
40231
  function readCachedPluginVersion(pluginCacheDir) {
39851
40232
  try {
39852
40233
  const installedPkgPath = getOpenCodePluginPackageJsonPath(pluginCacheDir);
39853
- if (!existsSync35(installedPkgPath))
40234
+ if (!existsSync36(installedPkgPath))
39854
40235
  return;
39855
- const pkg = JSON.parse(readFileSync24(installedPkgPath, "utf-8"));
40236
+ const pkg = JSON.parse(readFileSync25(installedPkgPath, "utf-8"));
39856
40237
  return typeof pkg.version === "string" ? pkg.version : undefined;
39857
40238
  } catch {
39858
40239
  return;
39859
40240
  }
39860
40241
  }
39861
40242
  async function clearPluginCache(options = {}, deps = {}) {
39862
- const remove = deps.remove ?? ((path) => rmSync3(path, { recursive: true, force: true }));
40243
+ const remove = deps.remove ?? ((path) => rmSync4(path, { recursive: true, force: true }));
39863
40244
  const pluginCacheRoots = getOpenCodePluginCacheRoots();
39864
- const existingRoots = pluginCacheRoots.filter((root) => existsSync35(root));
40245
+ const existingRoots = pluginCacheRoots.filter((root) => existsSync36(root));
39865
40246
  if (existingRoots.length === 0) {
39866
40247
  return { action: "not_found", path: pluginCacheRoots[0] ?? "" };
39867
40248
  }
@@ -39927,6 +40308,177 @@ var init_doctor_opencode_cache = __esm(() => {
39927
40308
  init_opencode_plugin_cache();
39928
40309
  });
39929
40310
 
40311
+ // src/commands/doctor-opencode-plugin-duplicates.ts
40312
+ import { isDeepStrictEqual } from "node:util";
40313
+ function entryOptions(entry) {
40314
+ if (Array.isArray(entry))
40315
+ return entry[1];
40316
+ if (entry !== null && typeof entry === "object") {
40317
+ return entry.options;
40318
+ }
40319
+ return;
40320
+ }
40321
+ function hasOptions(options) {
40322
+ if (options === undefined || options === null)
40323
+ return false;
40324
+ if (typeof options === "object" && !Array.isArray(options)) {
40325
+ return Object.keys(options).length > 0;
40326
+ }
40327
+ return true;
40328
+ }
40329
+ function followsLatest(specifier) {
40330
+ return specifier === OPENCODE_PLUGIN_NAME || specifier === OPENCODE_PLUGIN_ENTRY_WITH_VERSION;
40331
+ }
40332
+ function listMagicContextPluginEntries(config) {
40333
+ const out = [];
40334
+ for (const { key, index, entry } of readPluginEntries(config)) {
40335
+ const specifier = pluginEntryPackage(entry);
40336
+ if (specifier === null)
40337
+ continue;
40338
+ let kind = null;
40339
+ if (matchesPluginEntry(entry, OPENCODE_PLUGIN_NAME))
40340
+ kind = "npm";
40341
+ else if (isDevPathPluginEntry(entry))
40342
+ kind = "dev-path";
40343
+ if (kind === null)
40344
+ continue;
40345
+ out.push({ key, index, entry, specifier, kind, options: entryOptions(entry) });
40346
+ }
40347
+ return out;
40348
+ }
40349
+ function planPluginDuplicates(config) {
40350
+ const entries = listMagicContextPluginEntries(config);
40351
+ if (entries.length <= 1)
40352
+ return { action: "none", entries };
40353
+ if (entries.some((entry) => entry.kind === "dev-path")) {
40354
+ return { action: "leave", reason: "dev-path", entries };
40355
+ }
40356
+ const optionSets = [];
40357
+ for (const entry of entries) {
40358
+ if (!hasOptions(entry.options))
40359
+ continue;
40360
+ if (!optionSets.some((seen) => isDeepStrictEqual(seen, entry.options))) {
40361
+ optionSets.push(entry.options);
40362
+ }
40363
+ }
40364
+ if (optionSets.length > 1) {
40365
+ return { action: "leave", reason: "conflicting-options", entries };
40366
+ }
40367
+ const rank = (entry) => (followsLatest(entry.specifier) ? 2 : 0) + (hasOptions(entry.options) ? 1 : 0);
40368
+ let keep = entries[0];
40369
+ for (const entry of entries) {
40370
+ if (rank(entry) > rank(keep))
40371
+ keep = entry;
40372
+ }
40373
+ const remove = entries.filter((entry) => entry !== keep);
40374
+ let replacement;
40375
+ const carried = optionSets[0];
40376
+ if (!hasOptions(keep.options) && carried !== undefined) {
40377
+ const donor = entries.find((entry) => isDeepStrictEqual(entry.options, carried));
40378
+ if (Array.isArray(donor?.entry)) {
40379
+ const tuple = [...donor.entry];
40380
+ tuple[0] = keep.specifier;
40381
+ replacement = tuple;
40382
+ } else {
40383
+ replacement = { ...donor?.entry, package: keep.specifier };
40384
+ }
40385
+ }
40386
+ return { action: "dedupe", entries, keep, remove, replacement };
40387
+ }
40388
+ function applyPluginDuplicatePlan(config, plan) {
40389
+ if (plan.replacement !== undefined) {
40390
+ const list = config[plan.keep.key];
40391
+ list[plan.keep.index] = plan.replacement;
40392
+ }
40393
+ const removals = [...plan.remove].sort((a, b) => a.key === b.key ? b.index - a.index : a.key.localeCompare(b.key));
40394
+ for (const entry of removals) {
40395
+ config[entry.key].splice(entry.index, 1);
40396
+ }
40397
+ }
40398
+ function describePluginEntry(entry) {
40399
+ const suffix = hasOptions(entry.options) ? " (with options)" : "";
40400
+ const kind = entry.kind === "dev-path" ? "dev path " : "";
40401
+ return `${entry.key}[${entry.index}]: ${kind}${entry.specifier}${suffix}`;
40402
+ }
40403
+ function checkPluginDuplicates(config, configName, options, report) {
40404
+ const plan = planPluginDuplicates(config);
40405
+ if (plan.action === "none")
40406
+ return false;
40407
+ report.warn(`Magic Context is registered ${plan.entries.length} times in ${configName}; OpenCode loads the first and fails the rest as duplicates`);
40408
+ for (const entry of plan.entries)
40409
+ report.info(` ${describePluginEntry(entry)}`);
40410
+ if (plan.action === "leave") {
40411
+ report.warn(plan.reason === "dev-path" ? "A local development checkout is registered next to another Magic Context entry; leaving every entry in place — remove the one you do not want by hand" : "Two Magic Context entries carry different options; leaving every entry in place — merge the options into one entry by hand");
40412
+ return false;
40413
+ }
40414
+ if (!options.fix) {
40415
+ report.info(` Run 'doctor --fix' to keep ${plan.keep.key}[${plan.keep.index}] (${plan.keep.specifier}) and remove the others`);
40416
+ return false;
40417
+ }
40418
+ applyPluginDuplicatePlan(config, plan);
40419
+ report.pass(`Removed ${plan.remove.length} duplicate Magic Context ${plan.remove.length === 1 ? "entry" : "entries"} from ${configName}; kept ${plan.keep.specifier} under "${plan.keep.key}"${plan.replacement !== undefined ? " with the removed entry's options" : ""}`);
40420
+ return true;
40421
+ }
40422
+ var init_doctor_opencode_plugin_duplicates = __esm(() => {
40423
+ init_opencode();
40424
+ init_opencode_plugin_cache();
40425
+ init_opencode_plugin_registration();
40426
+ });
40427
+
40428
+ // src/commands/doctor-opencode-plugin-entry.ts
40429
+ function isPinnedOpenCodePluginSpecifier(specifier) {
40430
+ if (specifier === OPENCODE_PLUGIN_NAME || specifier === OPENCODE_PLUGIN_ENTRY_WITH_VERSION) {
40431
+ return false;
40432
+ }
40433
+ return specifier.startsWith(`${OPENCODE_PLUGIN_NAME}@`);
40434
+ }
40435
+ function withPluginEntrySpecifier(entry, specifier) {
40436
+ if (Array.isArray(entry) && entry.length >= 1) {
40437
+ const replacement = [...entry];
40438
+ replacement[0] = specifier;
40439
+ return replacement;
40440
+ }
40441
+ if (entry !== null && typeof entry === "object" && !Array.isArray(entry)) {
40442
+ return { ...entry, package: specifier };
40443
+ }
40444
+ return specifier;
40445
+ }
40446
+ function checkOpenCodePluginEntry(config, configName, options, report) {
40447
+ const allEntries = readPluginEntries(config);
40448
+ const found = allEntries.find(({ entry }) => matchesPluginEntry(entry, OPENCODE_PLUGIN_NAME) || isDevPathPluginEntry(entry));
40449
+ if (!found) {
40450
+ const key = options.registrationKey;
40451
+ const list = Array.isArray(config[key]) ? config[key] : [];
40452
+ list.push(OPENCODE_PLUGIN_ENTRY_WITH_VERSION);
40453
+ config[key] = list;
40454
+ report.fixed(`Added plugin to ${configName}`);
40455
+ return true;
40456
+ }
40457
+ const list = config[found.key];
40458
+ const specifier = pluginEntryPackage(found.entry) ?? "";
40459
+ if (specifier === OPENCODE_PLUGIN_ENTRY_WITH_VERSION) {
40460
+ report.pass(`Plugin registered in ${configName}`);
40461
+ return false;
40462
+ }
40463
+ if (isDevPathPluginEntry(found.entry)) {
40464
+ report.pass(`Plugin registered in ${configName} (dev path: ${specifier})`);
40465
+ return false;
40466
+ }
40467
+ if (isPinnedOpenCodePluginSpecifier(specifier) && !options.force) {
40468
+ report.autoUpdateStall(specifier);
40469
+ report.warn(`Plugin pinned to ${specifier} in ${configName} — use 'doctor --force' to upgrade`);
40470
+ return false;
40471
+ }
40472
+ list[found.index] = withPluginEntrySpecifier(found.entry, OPENCODE_PLUGIN_ENTRY_WITH_VERSION);
40473
+ report.fixed(`Upgraded plugin entry in ${configName}: ${specifier} → ${OPENCODE_PLUGIN_ENTRY_WITH_VERSION}`);
40474
+ return true;
40475
+ }
40476
+ var init_doctor_opencode_plugin_entry = __esm(() => {
40477
+ init_opencode();
40478
+ init_opencode_plugin_cache();
40479
+ init_opencode_plugin_registration();
40480
+ });
40481
+
39930
40482
  // src/commands/doctor-store-generation.ts
39931
40483
  function hasColumn(db, table, column) {
39932
40484
  try {
@@ -39982,8 +40534,8 @@ function formatUnresolvedCompartmentSession(session) {
39982
40534
  }
39983
40535
 
39984
40536
  // src/commands/doctor-opencode.ts
39985
- import { spawnSync as spawnSync7 } from "node:child_process";
39986
- import { existsSync as existsSync36, mkdtempSync, readFileSync as readFileSync25, rmSync as rmSync4 } from "node:fs";
40537
+ import { spawnSync as spawnSync8 } from "node:child_process";
40538
+ import { existsSync as existsSync37, mkdtempSync, readFileSync as readFileSync26, rmSync as rmSync5 } from "node:fs";
39987
40539
  import { createRequire as createRequire6 } from "node:module";
39988
40540
  import { homedir as homedir16, tmpdir as tmpdir3 } from "node:os";
39989
40541
  import { join as join32 } from "node:path";
@@ -39994,7 +40546,7 @@ function findUndeclaredConfiguredVariants(configured, catalog) {
39994
40546
  return model !== undefined && !Object.hasOwn(model.variants, entry.variant);
39995
40547
  });
39996
40548
  }
39997
- function checkConfiguredVariantCatalog(config, hostGeneration, warn, run = (args, cwd) => spawnSync7("opencode", args, {
40549
+ function checkConfiguredVariantCatalog(config, hostGeneration, warn, run = (args, cwd) => spawnSync8("opencode", args, {
39998
40550
  cwd,
39999
40551
  encoding: "utf8",
40000
40552
  timeout: hostGeneration === "v2" ? 90000 : 45000,
@@ -40040,7 +40592,7 @@ function checkConfiguredVariantCatalog(config, hostGeneration, warn, run = (args
40040
40592
  warn(`${entry.agent} model ${entry.model} requests variant '${entry.variant}', which this host does not offer. Remove the variant or choose one listed by ${guidance}.`);
40041
40593
  }
40042
40594
  } finally {
40043
- rmSync4(tempRoot, { recursive: true, force: true });
40595
+ rmSync5(tempRoot, { recursive: true, force: true });
40044
40596
  }
40045
40597
  }
40046
40598
  function parseOpenCodeV2ModelCatalog(output) {
@@ -40159,12 +40711,12 @@ function checkUserMemoriesDreamerCompatibility(mcConfig) {
40159
40711
  return null;
40160
40712
  return 'dreamer.tasks["review-user-memories"] is scheduled but dreamer.disable=true, so new promotions will not run. Remove dreamer.disable or set dreamer.tasks["review-user-memories"].schedule="" to disable the task.';
40161
40713
  }
40162
- async function fetchNpmLatest(pkg, timeoutMs = 5000) {
40714
+ async function fetchNpmLatest(pkg, distTag = "latest", timeoutMs = 5000) {
40163
40715
  try {
40164
40716
  const controller = new AbortController;
40165
40717
  const timer = setTimeout(() => controller.abort(), timeoutMs);
40166
40718
  try {
40167
- const res = await fetch(`https://registry.npmjs.org/${pkg}/latest`, {
40719
+ const res = await fetch(`${resolveNpmRegistryUrl()}/${pkg}/${encodeURIComponent(distTag)}`, {
40168
40720
  signal: controller.signal,
40169
40721
  headers: { Accept: "application/json" }
40170
40722
  });
@@ -40179,6 +40731,10 @@ async function fetchNpmLatest(pkg, timeoutMs = 5000) {
40179
40731
  return null;
40180
40732
  }
40181
40733
  }
40734
+ function resolveNpmRegistryUrl(env = process.env) {
40735
+ const configured = (env.npm_config_registry ?? env.NPM_CONFIG_REGISTRY)?.trim();
40736
+ return (configured || "https://registry.npmjs.org").replace(/\/+$/, "");
40737
+ }
40182
40738
  function getSelfVersion2() {
40183
40739
  const req = createRequire6(import.meta.url);
40184
40740
  for (const relPath of ["../../package.json", "../package.json"]) {
@@ -40190,11 +40746,6 @@ function getSelfVersion2() {
40190
40746
  }
40191
40747
  return "0.0.0";
40192
40748
  }
40193
- function isPinnedOpenCodePluginSpecifier(specifier) {
40194
- if (specifier === OPENCODE_PLUGIN_NAME || specifier === OPENCODE_PLUGIN_ENTRY_WITH_VERSION)
40195
- return false;
40196
- return specifier.startsWith(`${OPENCODE_PLUGIN_NAME}@`);
40197
- }
40198
40749
  function describeAutoUpdateStall(specifier, autoUpdateEnabled, storageDir = getMagicContextStorageDir()) {
40199
40750
  if (!autoUpdateEnabled || !isPinnedOpenCodePluginSpecifier(specifier))
40200
40751
  return null;
@@ -40212,10 +40763,10 @@ function getUserNpmrcPath() {
40212
40763
  function collectNpmReleaseAgeWarnings() {
40213
40764
  const ageWarnings = [];
40214
40765
  const npmrcPath = getUserNpmrcPath();
40215
- if (!existsSync36(npmrcPath))
40766
+ if (!existsSync37(npmrcPath))
40216
40767
  return ageWarnings;
40217
40768
  try {
40218
- const npmrc = readFileSync25(npmrcPath, "utf-8");
40769
+ const npmrc = readFileSync26(npmrcPath, "utf-8");
40219
40770
  for (const line of npmrc.split(`
40220
40771
  `)) {
40221
40772
  const trimmed = line.trim();
@@ -40248,15 +40799,15 @@ function compareVersions(a, b) {
40248
40799
  function openBrowser(url) {
40249
40800
  try {
40250
40801
  if (process.platform === "darwin") {
40251
- const child = spawnSync7("open", [url], { stdio: "ignore" });
40802
+ const child = spawnSync8("open", [url], { stdio: "ignore" });
40252
40803
  if (child.status === 0)
40253
40804
  return;
40254
40805
  } else if (process.platform === "linux") {
40255
- const child = spawnSync7("xdg-open", [url], { stdio: "ignore" });
40806
+ const child = spawnSync8("xdg-open", [url], { stdio: "ignore" });
40256
40807
  if (child.status === 0)
40257
40808
  return;
40258
40809
  } else if (process.platform === "win32") {
40259
- const child = spawnSync7("cmd", ["/c", "start", "", url], { stdio: "ignore" });
40810
+ const child = spawnSync8("cmd", ["/c", "start", "", url], { stdio: "ignore" });
40260
40811
  if (child.status === 0)
40261
40812
  return;
40262
40813
  }
@@ -40349,7 +40900,7 @@ function checkLocalEmbeddingRuntimeForDoctor(runtimePreference = "auto") {
40349
40900
  return { issues: 0 };
40350
40901
  }
40351
40902
  async function checkEmbeddingConfig(magicContextConfigPath) {
40352
- if (!existsSync36(magicContextConfigPath)) {
40903
+ if (!existsSync37(magicContextConfigPath)) {
40353
40904
  return checkLocalEmbeddingRuntimeForDoctor();
40354
40905
  }
40355
40906
  let rawText;
@@ -40680,7 +41231,7 @@ async function runDoctor2(options = {}) {
40680
41231
  pass(`OpenCode config: ${paths.opencodeConfig}`);
40681
41232
  }
40682
41233
  let autoUpdateEnabled = true;
40683
- if (existsSync36(paths.magicContextConfig)) {
41234
+ if (existsSync37(paths.magicContextConfig)) {
40684
41235
  pass(`Magic Context config: ${paths.magicContextConfig}`);
40685
41236
  try {
40686
41237
  const raw = loadRawConfigFile({ configPath: paths.magicContextConfig, tier: "user" });
@@ -40716,7 +41267,7 @@ async function runDoctor2(options = {}) {
40716
41267
  warn(`No magic-context.jsonc found — using defaults`);
40717
41268
  log2.info(" Run 'setup' to create one with model recommendations");
40718
41269
  }
40719
- if (existsSync36(paths.magicContextConfig)) {
41270
+ if (existsSync37(paths.magicContextConfig)) {
40720
41271
  try {
40721
41272
  const raw = loadRawConfigFile({ configPath: paths.magicContextConfig, tier: "user" });
40722
41273
  if (!raw)
@@ -40846,59 +41397,35 @@ async function runDoctor2(options = {}) {
40846
41397
  };
40847
41398
  if (paths.opencodeConfigFormat !== "none") {
40848
41399
  try {
40849
- const raw = readFileSync25(paths.opencodeConfig, "utf-8");
41400
+ const raw = readFileSync26(paths.opencodeConfig, "utf-8");
40850
41401
  const config = import_comment_json11.parse(raw);
40851
- const registrationKey = pluginConfigKeyFor(hostGeneration);
41402
+ const configName = paths.opencodeConfigFormat === "jsonc" ? "opencode.jsonc" : "opencode.json";
41403
+ if (checkPluginDuplicates(config, configName, options, {
41404
+ warn,
41405
+ pass: (message) => {
41406
+ pass(message);
41407
+ fixed++;
41408
+ },
41409
+ info: (message) => log2.info(message)
41410
+ })) {
41411
+ writeFileAtomic(paths.opencodeConfig, `${import_comment_json11.stringify(config, null, 2)}
41412
+ `);
41413
+ }
40852
41414
  const allEntries = readPluginEntries(config);
40853
- const found = allEntries.find(({ entry }) => matchesPluginEntry(entry, OPENCODE_PLUGIN_NAME) || isDevPathPluginEntry(entry));
40854
- const targetKey = found?.key ?? registrationKey;
40855
- const rawPlugins = Array.isArray(config?.[targetKey]) ? config[targetKey] : [];
40856
- const existingIdx = found ? found.index : -1;
40857
41415
  if (allEntries.some(({ entry }) => isLocalPathPluginEntry(entry) && String(entry).includes("magic-context") && !isDevPathPluginEntry(entry))) {
40858
41416
  warn("An unverifiable local OpenCode plugin path was ignored because its package name is not Magic Context");
40859
41417
  }
40860
- const configName = paths.opencodeConfigFormat === "jsonc" ? "opencode.jsonc" : "opencode.json";
40861
- const entryAsString = (entry) => {
40862
- if (typeof entry === "string")
40863
- return entry;
40864
- if (Array.isArray(entry) && typeof entry[0] === "string")
40865
- return entry[0];
40866
- return null;
40867
- };
40868
- if (existingIdx >= 0 && entryAsString(rawPlugins[existingIdx]) === OPENCODE_PLUGIN_ENTRY_WITH_VERSION) {
40869
- pass(`Plugin registered in ${configName}`);
40870
- } else if (existingIdx >= 0) {
40871
- const oldEntry = rawPlugins[existingIdx];
40872
- const oldEntryStr = entryAsString(oldEntry) ?? "";
40873
- if (isDevPathPluginEntry(oldEntry)) {
40874
- pass(`Plugin registered in ${configName} (dev path: ${oldEntryStr})`);
40875
- } else {
40876
- const isPinned = isPinnedOpenCodePluginSpecifier(oldEntryStr);
40877
- if (isPinned && !options.force) {
40878
- reportAutoUpdateStall(oldEntryStr);
40879
- warn(`Plugin pinned to ${oldEntryStr} in ${configName} — use 'doctor --force' to upgrade`);
40880
- } else {
40881
- if (Array.isArray(oldEntry) && oldEntry.length >= 1) {
40882
- const replacement = [...oldEntry];
40883
- replacement[0] = OPENCODE_PLUGIN_ENTRY_WITH_VERSION;
40884
- rawPlugins[existingIdx] = replacement;
40885
- } else {
40886
- rawPlugins[existingIdx] = OPENCODE_PLUGIN_ENTRY_WITH_VERSION;
40887
- }
40888
- config[targetKey] = rawPlugins;
40889
- writeFileAtomic(paths.opencodeConfig, `${import_comment_json11.stringify(config, null, 2)}
40890
- `);
40891
- pass(`Upgraded plugin entry in ${configName}: ${oldEntryStr} → ${OPENCODE_PLUGIN_ENTRY_WITH_VERSION}`);
40892
- fixed++;
40893
- }
40894
- }
40895
- } else {
40896
- rawPlugins.push(OPENCODE_PLUGIN_ENTRY_WITH_VERSION);
40897
- config[targetKey] = rawPlugins;
41418
+ if (checkOpenCodePluginEntry(config, configName, { force: options.force, registrationKey: pluginConfigKeyFor(hostGeneration) }, {
41419
+ pass,
41420
+ warn,
41421
+ fixed: (message) => {
41422
+ pass(message);
41423
+ fixed++;
41424
+ },
41425
+ autoUpdateStall: reportAutoUpdateStall
41426
+ })) {
40898
41427
  writeFileAtomic(paths.opencodeConfig, `${import_comment_json11.stringify(config, null, 2)}
40899
41428
  `);
40900
- pass(`Added plugin to ${configName}`);
40901
- fixed++;
40902
41429
  }
40903
41430
  } catch {
40904
41431
  warn("Could not parse opencode config to verify plugin entry");
@@ -40939,25 +41466,18 @@ async function runDoctor2(options = {}) {
40939
41466
  pass("Added TUI sidebar plugin to tui.json");
40940
41467
  warn("Restart OpenCode to see the sidebar");
40941
41468
  fixed++;
40942
- } else if (existsSync36(paths.tuiConfig)) {
41469
+ } else if (existsSync37(paths.tuiConfig)) {
40943
41470
  try {
40944
- const tuiRaw = readFileSync25(paths.tuiConfig, "utf-8");
41471
+ const tuiRaw = readFileSync26(paths.tuiConfig, "utf-8");
40945
41472
  const tuiConfig = import_comment_json11.parse(tuiRaw);
40946
41473
  const tuiRawPlugins = Array.isArray(tuiConfig?.plugin) ? tuiConfig.plugin : [];
40947
41474
  const tuiIdx = tuiRawPlugins.findIndex((entry) => matchesPluginEntry(entry, OPENCODE_PLUGIN_NAME) || isDevPathPluginEntry(entry));
40948
41475
  if (tuiRawPlugins.some((entry) => isLocalPathPluginEntry(entry) && String(entry).includes("magic-context") && !isDevPathPluginEntry(entry))) {
40949
41476
  warn("An unverifiable local TUI plugin path was ignored because its package name is not Magic Context");
40950
41477
  }
40951
- const tuiEntryAsString = (entry) => {
40952
- if (typeof entry === "string")
40953
- return entry;
40954
- if (Array.isArray(entry) && typeof entry[0] === "string")
40955
- return entry[0];
40956
- return "";
40957
- };
40958
41478
  if (tuiIdx >= 0) {
40959
41479
  const tuiEntry = tuiRawPlugins[tuiIdx];
40960
- const tuiEntryStr = tuiEntryAsString(tuiEntry);
41480
+ const tuiEntryStr = pluginEntryPackage(tuiEntry) ?? "";
40961
41481
  if (isDevPathPluginEntry(tuiEntry)) {
40962
41482
  pass(`TUI sidebar plugin configured (dev path: ${tuiEntryStr})`);
40963
41483
  } else {
@@ -40966,13 +41486,7 @@ async function runDoctor2(options = {}) {
40966
41486
  reportAutoUpdateStall(tuiEntryStr);
40967
41487
  warn(`TUI plugin pinned to ${tuiEntryStr} — use 'doctor --force' to upgrade`);
40968
41488
  } else if (tuiPinned && options.force) {
40969
- if (Array.isArray(tuiEntry) && tuiEntry.length >= 1) {
40970
- const replacement = [...tuiEntry];
40971
- replacement[0] = OPENCODE_PLUGIN_ENTRY_WITH_VERSION;
40972
- tuiRawPlugins[tuiIdx] = replacement;
40973
- } else {
40974
- tuiRawPlugins[tuiIdx] = OPENCODE_PLUGIN_ENTRY_WITH_VERSION;
40975
- }
41489
+ tuiRawPlugins[tuiIdx] = withPluginEntrySpecifier(tuiEntry, OPENCODE_PLUGIN_ENTRY_WITH_VERSION);
40976
41490
  tuiConfig.plugin = tuiRawPlugins;
40977
41491
  writeFileAtomic(paths.tuiConfig, `${import_comment_json11.stringify(tuiConfig, null, 2)}
40978
41492
  `);
@@ -40992,7 +41506,7 @@ async function runDoctor2(options = {}) {
40992
41506
  fail("Could not create or verify the TUI sidebar config");
40993
41507
  }
40994
41508
  }
40995
- if (existsSync36(paths.magicContextConfig)) {
41509
+ if (existsSync37(paths.magicContextConfig)) {
40996
41510
  try {
40997
41511
  const raw = loadRawConfigFile({ configPath: paths.magicContextConfig, tier: "user" });
40998
41512
  if (!raw)
@@ -41016,7 +41530,7 @@ async function runDoctor2(options = {}) {
41016
41530
  const storage = getMagicContextStorageResolution();
41017
41531
  const dbPath = join32(storage.path, "context.db");
41018
41532
  log2.info(`Shared storage: ${storage.path} (source: ${storage.source})`);
41019
- if (!existsSync36(dbPath)) {
41533
+ if (!existsSync37(dbPath)) {
41020
41534
  log2.info(`Shared context DB not yet created at ${dbPath} (will be created on first run)`);
41021
41535
  } else {
41022
41536
  log2.info(`Shared context DB exists at ${dbPath}`);
@@ -41130,9 +41644,26 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
41130
41644
  log2.info(` Manually delete: ${cacheResult.path}`);
41131
41645
  }
41132
41646
  issues++;
41133
- } else {
41647
+ } else if (hostGeneration !== "v2") {
41134
41648
  pass("Plugin cache clean (no cached version found)");
41135
41649
  }
41650
+ let v2DistTag;
41651
+ if (paths.opencodeConfigFormat !== "none") {
41652
+ try {
41653
+ v2DistTag = configuredOpenCodeV2DistTag(import_comment_json11.parse(readFileSync26(paths.opencodeConfig, "utf-8")));
41654
+ } catch {}
41655
+ }
41656
+ const v2Cache = reportOpenCodeV2PluginCache(checkOpenCodeV2PluginCache({
41657
+ fix: options.fix,
41658
+ force: options.force,
41659
+ latestVersion: v2DistTag ? await fetchNpmLatest(OPENCODE_PLUGIN_NAME, v2DistTag) : pluginNpmLatest,
41660
+ distTag: v2DistTag,
41661
+ hostFiles: openCodeHostDatabaseFiles([openCodeDbResolution.path])
41662
+ }), { pass, warn, info: (message) => log2.info(message) }, { reportMissing: hostGeneration === "v2" });
41663
+ if (v2Cache.fixed)
41664
+ fixed++;
41665
+ if (v2Cache.issue)
41666
+ issues++;
41136
41667
  {
41137
41668
  const ageWarnings = collectNpmReleaseAgeWarnings();
41138
41669
  if (ageWarnings.length > 0) {
@@ -41227,6 +41758,9 @@ var init_doctor_opencode = __esm(async () => {
41227
41758
  init_prompts();
41228
41759
  init_redaction2();
41229
41760
  init_doctor_opencode_cache();
41761
+ init_doctor_opencode_plugin_duplicates();
41762
+ init_doctor_opencode_plugin_entry();
41763
+ init_doctor_opencode2_cache();
41230
41764
  await __promiseAll([
41231
41765
  init_storage_db(),
41232
41766
  init_sqlite(),
@@ -41240,7 +41774,7 @@ var init_doctor_opencode = __esm(async () => {
41240
41774
  });
41241
41775
 
41242
41776
  // src/lib/diagnostics-pi.ts
41243
- import { existsSync as existsSync37, readdirSync as readdirSync6, readFileSync as readFileSync26, statSync as statSync16 } from "node:fs";
41777
+ import { existsSync as existsSync38, readdirSync as readdirSync7, readFileSync as readFileSync27, statSync as statSync16 } from "node:fs";
41244
41778
  import { createRequire as createRequire7 } from "node:module";
41245
41779
  import { join as join33 } from "node:path";
41246
41780
  function getSelfVersion3() {
@@ -41257,7 +41791,7 @@ function getSelfVersion3() {
41257
41791
  }
41258
41792
  function fileSize2(path) {
41259
41793
  try {
41260
- return existsSync37(path) ? statSync16(path).size : 0;
41794
+ return existsSync38(path) ? statSync16(path).size : 0;
41261
41795
  } catch {
41262
41796
  return 0;
41263
41797
  }
@@ -41269,11 +41803,11 @@ function sanitizeValue2(value) {
41269
41803
  return sanitizeConfigValue(value);
41270
41804
  }
41271
41805
  function readJsonc(path) {
41272
- if (!existsSync37(path))
41806
+ if (!existsSync38(path))
41273
41807
  return { value: {} };
41274
41808
  try {
41275
41809
  return {
41276
- value: import_comment_json12.parse(readFileSync26(path, "utf-8"))
41810
+ value: import_comment_json12.parse(readFileSync27(path, "utf-8"))
41277
41811
  };
41278
41812
  } catch (error) {
41279
41813
  return {
@@ -41289,7 +41823,7 @@ function readConfigDiagnostic(path) {
41289
41823
  const parsed = readJsonc(path);
41290
41824
  return {
41291
41825
  path,
41292
- exists: existsSync37(path),
41826
+ exists: existsSync38(path),
41293
41827
  ...parsed.parseError ? { parseError: parsed.parseError } : {},
41294
41828
  flags: sanitizeValue2(parsed.value)
41295
41829
  };
@@ -41307,10 +41841,10 @@ function reverseSlugToDirectory(slug) {
41307
41841
  }
41308
41842
  function collectPiRecentSessions() {
41309
41843
  const sessionsRoot = getPiSessionsRoot();
41310
- if (!existsSync37(sessionsRoot))
41844
+ if (!existsSync38(sessionsRoot))
41311
41845
  return [];
41312
41846
  try {
41313
- const slugs = readdirSync6(sessionsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
41847
+ const slugs = readdirSync7(sessionsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
41314
41848
  const candidates = [];
41315
41849
  for (const slug of slugs) {
41316
41850
  const directory = reverseSlugToDirectory(slug);
@@ -41319,7 +41853,7 @@ function collectPiRecentSessions() {
41319
41853
  const slugDir = join33(sessionsRoot, slug);
41320
41854
  let files;
41321
41855
  try {
41322
- files = readdirSync6(slugDir).filter((name) => name.endsWith(".jsonl"));
41856
+ files = readdirSync7(slugDir).filter((name) => name.endsWith(".jsonl"));
41323
41857
  } catch {
41324
41858
  continue;
41325
41859
  }
@@ -41343,7 +41877,7 @@ function collectPiRecentSessions() {
41343
41877
  }
41344
41878
  function parseHistorianDumpMeta2(path) {
41345
41879
  try {
41346
- const xml = readFileSync26(path, "utf-8");
41880
+ const xml = readFileSync27(path, "utf-8");
41347
41881
  const parsed = parseCompartmentOutput(xml);
41348
41882
  const factCountByCategory = {};
41349
41883
  for (const fact of parsed.facts) {
@@ -41376,10 +41910,10 @@ function parseHistorianDumpMeta2(path) {
41376
41910
  }
41377
41911
  }
41378
41912
  function listDumpsInDir2(dir, limit) {
41379
- if (!existsSync37(dir))
41913
+ if (!existsSync38(dir))
41380
41914
  return { count: 0, recent: [] };
41381
41915
  try {
41382
- const entries = readdirSync6(dir).filter((name) => name.endsWith(".xml")).map((name) => {
41916
+ const entries = readdirSync7(dir).filter((name) => name.endsWith(".xml")).map((name) => {
41383
41917
  const stat = statSync16(join33(dir, name));
41384
41918
  return {
41385
41919
  name,
@@ -41470,7 +42004,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
41470
42004
  piVersion: pi ? getPiVersion(pi.path) : null,
41471
42005
  settings: {
41472
42006
  path: settingsPath,
41473
- exists: existsSync37(settingsPath),
42007
+ exists: existsSync38(settingsPath),
41474
42008
  ...settingsParsed.parseError ? { parseError: settingsParsed.parseError } : {},
41475
42009
  hasMagicContextPackage: hasPiMagicContextPackage(packages),
41476
42010
  packages: sanitizeValue2(packages)
@@ -41487,7 +42021,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
41487
42021
  storageDir: {
41488
42022
  path: storageDirPath,
41489
42023
  source: storageResolution.source,
41490
- exists: existsSync37(storageDirPath),
42024
+ exists: existsSync38(storageDirPath),
41491
42025
  contextDbSizeBytes: fileSize2(dbPath)
41492
42026
  },
41493
42027
  conflicts: {
@@ -41680,8 +42214,8 @@ var init_logs_pi = __esm(() => {
41680
42214
  });
41681
42215
 
41682
42216
  // src/commands/doctor-pi.ts
41683
- import { execFileSync as execFileSync6, spawnSync as spawnSync8 } from "node:child_process";
41684
- import { existsSync as existsSync38, mkdirSync as mkdirSync11, readdirSync as readdirSync7, readFileSync as readFileSync27, rmSync as rmSync5, statSync as statSync17 } from "node:fs";
42217
+ import { execFileSync as execFileSync6, spawnSync as spawnSync9 } from "node:child_process";
42218
+ import { existsSync as existsSync39, mkdirSync as mkdirSync11, readdirSync as readdirSync8, readFileSync as readFileSync28, rmSync as rmSync6, statSync as statSync17 } from "node:fs";
41685
42219
  import { createRequire as createRequire8 } from "node:module";
41686
42220
  import { homedir as homedir17 } from "node:os";
41687
42221
  import { dirname as dirname19, isAbsolute as isAbsolute8, join as join35 } from "node:path";
@@ -41775,7 +42309,7 @@ function summarize(results) {
41775
42309
  function readJsonc2(path) {
41776
42310
  try {
41777
42311
  return {
41778
- value: import_comment_json13.parse(readFileSync27(path, "utf-8"))
42312
+ value: import_comment_json13.parse(readFileSync28(path, "utf-8"))
41779
42313
  };
41780
42314
  } catch (error) {
41781
42315
  return {
@@ -41827,13 +42361,13 @@ function piPluginDirCandidates(packages, cwd) {
41827
42361
  }
41828
42362
  dirs.push(join35(agentDir, "npm", "node_modules", PACKAGE_NAME2));
41829
42363
  dirs.push(join35(cwd, ".pi", "npm", "node_modules", PACKAGE_NAME2));
41830
- return dirs.filter((dir) => existsSync38(join35(dir, "package.json")));
42364
+ return dirs.filter((dir) => existsSync39(join35(dir, "package.json")));
41831
42365
  }
41832
42366
  function projectConfigPath(cwd) {
41833
42367
  return resolveCortexKitProjectConfigPath(cwd);
41834
42368
  }
41835
42369
  function readConfigForEmbedding(path, isProjectConfig) {
41836
- if (!existsSync38(path))
42370
+ if (!existsSync39(path))
41837
42371
  return null;
41838
42372
  try {
41839
42373
  const raw = loadRawConfigFile({
@@ -41934,7 +42468,7 @@ function cacheRoots(cwd) {
41934
42468
  function findPiMagicContextCacheDirs(cwd, expectedVersion, force = false) {
41935
42469
  const found = new Map;
41936
42470
  const visit = (path, depth) => {
41937
- if (depth < 0 || !existsSync38(path))
42471
+ if (depth < 0 || !existsSync39(path))
41938
42472
  return;
41939
42473
  let stat;
41940
42474
  try {
@@ -41945,9 +42479,9 @@ function findPiMagicContextCacheDirs(cwd, expectedVersion, force = false) {
41945
42479
  if (!stat.isDirectory())
41946
42480
  return;
41947
42481
  const packageJson = join35(path, "package.json");
41948
- if (existsSync38(packageJson)) {
42482
+ if (existsSync39(packageJson)) {
41949
42483
  try {
41950
- const pkg = JSON.parse(readFileSync27(packageJson, "utf-8"));
42484
+ const pkg = JSON.parse(readFileSync28(packageJson, "utf-8"));
41951
42485
  const name = typeof pkg.name === "string" ? pkg.name : "";
41952
42486
  const version = typeof pkg.version === "string" ? pkg.version : undefined;
41953
42487
  if (name === PACKAGE_NAME2) {
@@ -41962,7 +42496,7 @@ function findPiMagicContextCacheDirs(cwd, expectedVersion, force = false) {
41962
42496
  }
41963
42497
  let entries = [];
41964
42498
  try {
41965
- entries = readdirSync7(path);
42499
+ entries = readdirSync8(path);
41966
42500
  } catch {
41967
42501
  return;
41968
42502
  }
@@ -42012,7 +42546,7 @@ async function runHealthChecks2(options) {
42012
42546
  }
42013
42547
  const settingsPath = getPiUserExtensionsPath();
42014
42548
  let packages = [];
42015
- if (!existsSync38(settingsPath)) {
42549
+ if (!existsSync39(settingsPath)) {
42016
42550
  add2(results, "fail", `Pi settings not found at ${settingsPath}`);
42017
42551
  repairPlan.addPackageEntry = true;
42018
42552
  } else {
@@ -42036,7 +42570,7 @@ async function runHealthChecks2(options) {
42036
42570
  ["user", userConfigPath, true],
42037
42571
  ["project", projectPath, false]
42038
42572
  ]) {
42039
- if (!existsSync38(path)) {
42573
+ if (!existsSync39(path)) {
42040
42574
  if (required) {
42041
42575
  add2(results, "warn", `No ${label} magic-context.jsonc found at ${path}`);
42042
42576
  if (userConfigMigrationRefused) {
@@ -42078,7 +42612,7 @@ async function runHealthChecks2(options) {
42078
42612
  const storageDir = storage.path;
42079
42613
  const dbPath = join35(storageDir, "context.db");
42080
42614
  add2(results, "info", `Shared storage: ${storageDir} (source: ${storage.source})`);
42081
- const existedBeforeOpen = existsSync38(dbPath);
42615
+ const existedBeforeOpen = existsSync39(dbPath);
42082
42616
  if (existedBeforeOpen)
42083
42617
  add2(results, "pass", `Shared context DB exists at ${dbPath}`);
42084
42618
  else
@@ -42318,7 +42852,7 @@ function repair2(plan, prompts) {
42318
42852
  }
42319
42853
  if (plan.writeUserConfig) {
42320
42854
  const configPath = getPiUserConfigPath();
42321
- if (!existsSync38(configPath)) {
42855
+ if (!existsSync39(configPath)) {
42322
42856
  try {
42323
42857
  writeDefaultMagicContextConfig(configPath);
42324
42858
  prompts.log.success(`Wrote default Magic Context config to ${configPath}`);
@@ -42330,7 +42864,7 @@ function repair2(plan, prompts) {
42330
42864
  }
42331
42865
  for (const path of plan.clearCachePaths) {
42332
42866
  try {
42333
- rmSync5(path, { recursive: true, force: true });
42867
+ rmSync6(path, { recursive: true, force: true });
42334
42868
  prompts.log.success(`Cleared stale Pi extension cache: ${path}`);
42335
42869
  fixed += 1;
42336
42870
  } catch (error) {
@@ -42565,12 +43099,12 @@ var init_doctor_pi = __esm(async () => {
42565
43099
  openExistingContextDatabase,
42566
43100
  now: () => new Date,
42567
43101
  execFileSync: execFileSync6,
42568
- spawnSync: spawnSync8
43102
+ spawnSync: spawnSync9
42569
43103
  };
42570
43104
  });
42571
43105
 
42572
43106
  // src/commands/doctor.ts
42573
- import { existsSync as existsSync39, rmSync as rmSync6 } from "node:fs";
43107
+ import { existsSync as existsSync40, rmSync as rmSync7 } from "node:fs";
42574
43108
  import { join as join36 } from "node:path";
42575
43109
  async function runDoctor4(options) {
42576
43110
  if (options.clear)
@@ -42668,9 +43202,16 @@ async function runClear() {
42668
43202
  }
42669
43203
  const items = [];
42670
43204
  for (const adapter of installed) {
42671
- const cache = adapter.getPluginCacheInfo();
42672
- if (cache.path && cache.exists) {
42673
- items.push({ adapter, path: cache.path, sizeBytes: cache.sizeBytes });
43205
+ for (const cache of adapter.getPluginCacheInfo()) {
43206
+ if (cache.path && cache.exists) {
43207
+ items.push({
43208
+ adapter,
43209
+ path: cache.path,
43210
+ sizeBytes: cache.sizeBytes,
43211
+ label: cache.label,
43212
+ clear: cache.clear
43213
+ });
43214
+ }
42674
43215
  }
42675
43216
  }
42676
43217
  if (items.length === 0) {
@@ -42679,7 +43220,7 @@ async function runClear() {
42679
43220
  return 0;
42680
43221
  }
42681
43222
  const picks = await selectMany("Select caches to clear:", items.map((item, idx) => ({
42682
- label: `${item.adapter.displayName}: ${formatSize(item.sizeBytes)} — ${item.path}`,
43223
+ label: `${item.adapter.displayName}${item.label ? ` (${item.label})` : ""}: ${formatSize(item.sizeBytes)} — ${item.path}`,
42683
43224
  value: String(idx)
42684
43225
  })));
42685
43226
  if (picks.length === 0) {
@@ -42702,8 +43243,16 @@ async function runClear() {
42702
43243
  const s = spinner2();
42703
43244
  s.start(`Clearing ${item.path}`);
42704
43245
  try {
42705
- if (existsSync39(item.path)) {
42706
- rmSync6(item.path, { recursive: true, force: true });
43246
+ if (item.clear) {
43247
+ const result = item.clear();
43248
+ if (!result.cleared) {
43249
+ s.stop(`Left in place: ${item.path}`);
43250
+ log2.warn(result.reason);
43251
+ failed += 1;
43252
+ continue;
43253
+ }
43254
+ } else if (existsSync40(item.path)) {
43255
+ rmSync7(item.path, { recursive: true, force: true });
42707
43256
  }
42708
43257
  s.stop(`Cleared ${item.path}`);
42709
43258
  } catch (err) {