@cortexkit/magic-context 0.43.0 → 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 +950 -392
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3940,6 +3940,13 @@ function getHarness() {
3940
3940
  }
3941
3941
  var currentHarness = "opencode";
3942
3942
 
3943
+ // ../plugin/src/shared/test-temp-dir.ts
3944
+ var STALE_TEMP_DIR_AGE_MS, registeredTempDirs;
3945
+ var init_test_temp_dir = __esm(() => {
3946
+ STALE_TEMP_DIR_AGE_MS = 60 * 60 * 1000;
3947
+ registeredTempDirs = new Set;
3948
+ });
3949
+
3943
3950
  // ../plugin/src/shared/data-path.ts
3944
3951
  var exports_data_path = {};
3945
3952
  __export(exports_data_path, {
@@ -4018,7 +4025,9 @@ function getMagicContextStorageDir() {
4018
4025
  function getLegacyOpenCodeMagicContextStorageDir() {
4019
4026
  return path.join(getOpenCodeStorageDir(), "plugin", "magic-context");
4020
4027
  }
4021
- var init_data_path = () => {};
4028
+ var init_data_path = __esm(() => {
4029
+ init_test_temp_dir();
4030
+ });
4022
4031
 
4023
4032
  // src/lib/paths.ts
4024
4033
  import { existsSync as existsSync4, readdirSync, statSync as statSync3 } from "node:fs";
@@ -4194,6 +4203,10 @@ function getOpenCodePluginCacheDir() {
4194
4203
  const xdg = process.env.XDG_CACHE_HOME || join5(homedir3(), ".cache");
4195
4204
  return join5(xdg, "opencode", "packages");
4196
4205
  }
4206
+ function getOpenCodeV2NpmCacheDir() {
4207
+ const xdg = process.env.XDG_CACHE_HOME || join5(homedir3(), ".cache");
4208
+ return join5(xdg, "opencode", "npm");
4209
+ }
4197
4210
  function isDir(path) {
4198
4211
  try {
4199
4212
  return statSync3(path).isDirectory();
@@ -4594,7 +4607,7 @@ class OmpAdapter {
4594
4607
  }
4595
4608
  getPluginCacheInfo() {
4596
4609
  const path = join8(getOmpPluginsDir(), "cache");
4597
- return { path, exists: existsSync6(path), sizeBytes: dirSizeBytes(path) };
4610
+ return [{ path, exists: existsSync6(path), sizeBytes: dirSizeBytes(path) }];
4598
4611
  }
4599
4612
  getLogPath() {
4600
4613
  return getMagicContextLogPath2("omp");
@@ -4637,7 +4650,7 @@ var init_omp = __esm(() => {
4637
4650
  // ../plugin/src/shared/opencode-db-path.ts
4638
4651
  import { existsSync as existsSync7, readdirSync as readdirSync2, statSync as statSync4 } from "node:fs";
4639
4652
  import { homedir as homedir6 } from "node:os";
4640
- import { isAbsolute as isAbsolute3, join as join9 } from "node:path";
4653
+ import { isAbsolute as isAbsolute3, join as join9, resolve as resolve3 } from "node:path";
4641
4654
  function openCodeHostGenerationFromVersion(version) {
4642
4655
  const text = version ?? "";
4643
4656
  if (/(?:^|\s|v)0\.0\.0-(?:beta|dev)-/.test(text))
@@ -4724,7 +4737,7 @@ function resolveV2Fresh(dataDir, channel, env) {
4724
4737
  const filename = sourceOpenCodeDatabaseFilename("v2", channel, env);
4725
4738
  const explicit = env.OPENCODE_DB !== undefined;
4726
4739
  return {
4727
- path: filename === ":memory:" ? filename : join9(dataDir, filename),
4740
+ path: filename === ":memory:" ? filename : resolve3(dataDir, filename),
4728
4741
  source: explicit ? "OPENCODE_DB" : env.OPENCODE_CHANNEL ? "channel" : "default",
4729
4742
  channel: explicit ? null : channel
4730
4743
  };
@@ -12643,6 +12656,323 @@ var require_src3 = __commonJS(function(exports, module) {
12643
12656
  };
12644
12657
  });
12645
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
+
12646
12976
  // src/lib/atomic-write.ts
12647
12977
  import { chmodSync, mkdirSync as mkdirSync2, renameSync as renameSync2, statSync as statSync5, writeFileSync as writeFileSync2 } from "node:fs";
12648
12978
  import { dirname as dirname3 } from "node:path";
@@ -12661,13 +12991,13 @@ function writeFileAtomic(targetPath, data) {
12661
12991
  var init_atomic_write = () => {};
12662
12992
 
12663
12993
  // src/lib/opencode-detect.ts
12664
- import { existsSync as existsSync8, realpathSync } from "node:fs";
12994
+ import { existsSync as existsSync9, realpathSync } from "node:fs";
12665
12995
  import { homedir as homedir7 } from "node:os";
12666
- import { join as join10 } from "node:path";
12996
+ import { join as join11 } from "node:path";
12667
12997
  function defaultDeps(overrides = {}) {
12668
12998
  const env = overrides.env ?? process.env;
12669
12999
  return {
12670
- exists: overrides.exists ?? existsSync8,
13000
+ exists: overrides.exists ?? existsSync9,
12671
13001
  isExecutable: overrides.isExecutable ?? isExecutableFile,
12672
13002
  home: overrides.home ?? (env.HOME?.trim() || homedir7()),
12673
13003
  platform: overrides.platform ?? process.platform,
@@ -12677,7 +13007,7 @@ function defaultDeps(overrides = {}) {
12677
13007
  };
12678
13008
  }
12679
13009
  function stockCliBinary(d) {
12680
- 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");
12681
13011
  }
12682
13012
  function extraCliCandidates(d) {
12683
13013
  if (d.platform === "win32") {
@@ -12686,25 +13016,25 @@ function extraCliCandidates(d) {
12686
13016
  const userprofile = d.env.USERPROFILE ?? d.home;
12687
13017
  const out = [];
12688
13018
  if (appdata) {
12689
- out.push(join10(appdata, "npm", "opencode.cmd"));
12690
- out.push(join10(appdata, "npm", "opencode.exe"));
13019
+ out.push(join11(appdata, "npm", "opencode.cmd"));
13020
+ out.push(join11(appdata, "npm", "opencode.exe"));
12691
13021
  }
12692
13022
  if (localappdata) {
12693
- out.push(join10(localappdata, "Microsoft", "WinGet", "Links", "opencode.exe"));
12694
- 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"));
12695
13025
  }
12696
13026
  if (userprofile) {
12697
- out.push(join10(userprofile, "scoop", "shims", "opencode.exe"));
13027
+ out.push(join11(userprofile, "scoop", "shims", "opencode.exe"));
12698
13028
  }
12699
13029
  return out;
12700
13030
  }
12701
13031
  return [
12702
13032
  "/usr/local/bin/opencode",
12703
13033
  "/opt/homebrew/bin/opencode",
12704
- join10(d.home, ".local", "bin", "opencode"),
12705
- join10(d.home, ".local", "share", "mise", "shims", "opencode"),
12706
- join10(d.home, ".asdf", "shims", "opencode"),
12707
- 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")
12708
13038
  ];
12709
13039
  }
12710
13040
  function canonicalPath(d, path) {
@@ -12725,29 +13055,29 @@ function xdgConfigHome(d) {
12725
13055
  const xdg = d.env.XDG_CONFIG_HOME;
12726
13056
  if (xdg && xdg.length > 0)
12727
13057
  return xdg;
12728
- return join10(d.home, ".config");
13058
+ return join11(d.home, ".config");
12729
13059
  }
12730
13060
  function desktopUserDataDir(d, appId) {
12731
13061
  switch (d.platform) {
12732
13062
  case "darwin":
12733
- return join10(d.home, "Library", "Application Support", appId);
13063
+ return join11(d.home, "Library", "Application Support", appId);
12734
13064
  case "win32":
12735
- return join10(d.env.APPDATA ?? join10(d.home, "AppData", "Roaming"), appId);
13065
+ return join11(d.env.APPDATA ?? join11(d.home, "AppData", "Roaming"), appId);
12736
13066
  default:
12737
- return join10(xdgConfigHome(d), appId);
13067
+ return join11(xdgConfigHome(d), appId);
12738
13068
  }
12739
13069
  }
12740
13070
  function desktopAppPaths(d) {
12741
13071
  switch (d.platform) {
12742
13072
  case "darwin":
12743
- return ["/Applications/OpenCode.app", join10(d.home, "Applications", "OpenCode.app")];
13073
+ return ["/Applications/OpenCode.app", join11(d.home, "Applications", "OpenCode.app")];
12744
13074
  case "win32": {
12745
- const localappdata = d.env.LOCALAPPDATA ?? join10(d.home, "AppData", "Local");
12746
- 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")];
12747
13077
  }
12748
13078
  default: {
12749
- const dataHome = d.env.XDG_DATA_HOME && d.env.XDG_DATA_HOME.length > 0 ? d.env.XDG_DATA_HOME : join10(d.home, ".local", "share");
12750
- 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`));
12751
13081
  }
12752
13082
  }
12753
13083
  }
@@ -12769,7 +13099,7 @@ function detectOpenCodeInstallations(deps) {
12769
13099
  }
12770
13100
  }
12771
13101
  for (const appId of OPENCODE_DESKTOP_APP_IDS) {
12772
- const marker = join10(desktopUserDataDir(d, appId), OPENCODE_DESKTOP_SETTINGS_FILE);
13102
+ const marker = join11(desktopUserDataDir(d, appId), OPENCODE_DESKTOP_SETTINGS_FILE);
12773
13103
  if (d.exists(marker)) {
12774
13104
  addCandidate(installations, seenRealpaths, d, marker, "desktop", "desktop");
12775
13105
  }
@@ -12851,50 +13181,9 @@ function getAvailableModels2(binary) {
12851
13181
  var OPENCODE_BINARY_ENV = "MAGIC_CONTEXT_OPENCODE_BINARY", OPENCODE_VERSION_PROBE_TIMEOUT_MS = 2000;
12852
13182
  var init_opencode_helpers = () => {};
12853
13183
 
12854
- // src/lib/opencode-plugin-cache.ts
12855
- import { join as join11 } from "node:path";
12856
- function getOpenCodePluginCacheRoots() {
12857
- const cacheDir = getOpenCodePluginCacheDir();
12858
- return [
12859
- join11(cacheDir, OPENCODE_PLUGIN_ENTRY_WITH_VERSION),
12860
- join11(cacheDir, OPENCODE_PLUGIN_NAME)
12861
- ];
12862
- }
12863
- function getOpenCodePluginPackageJsonPath(pluginCacheRoot) {
12864
- return join11(pluginCacheRoot, "node_modules", ...OPENCODE_PLUGIN_NAME.split("/"), "package.json");
12865
- }
12866
- function getOpenCodePluginPackageJsonPaths() {
12867
- return getOpenCodePluginCacheRoots().map(getOpenCodePluginPackageJsonPath);
12868
- }
12869
- var OPENCODE_PLUGIN_NAME = "@cortexkit/opencode-magic-context", OPENCODE_PLUGIN_ENTRY_WITH_VERSION;
12870
- var init_opencode_plugin_cache = __esm(() => {
12871
- init_paths();
12872
- OPENCODE_PLUGIN_ENTRY_WITH_VERSION = `${OPENCODE_PLUGIN_NAME}@latest`;
12873
- });
12874
-
12875
- // src/lib/opencode-plugin-registration.ts
12876
- function pluginConfigKeyFor(hostGeneration) {
12877
- return hostGeneration === "v2" ? "plugins" : "plugin";
12878
- }
12879
- function readPluginEntries(config) {
12880
- const out = [];
12881
- for (const key of OPENCODE_PLUGIN_CONFIG_KEYS) {
12882
- const list = config?.[key];
12883
- if (!Array.isArray(list))
12884
- continue;
12885
- for (const [index, entry] of list.entries())
12886
- out.push({ key, index, entry });
12887
- }
12888
- return out;
12889
- }
12890
- var OPENCODE_PLUGIN_CONFIG_KEYS;
12891
- var init_opencode_plugin_registration = __esm(() => {
12892
- OPENCODE_PLUGIN_CONFIG_KEYS = ["plugin", "plugins"];
12893
- });
12894
-
12895
13184
  // src/adapters/opencode.ts
12896
- import { existsSync as existsSync9, readFileSync as readFileSync5, statSync as statSync6 } from "node:fs";
12897
- 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";
12898
13187
  import { fileURLToPath } from "node:url";
12899
13188
 
12900
13189
  class OpenCodeAdapter {
@@ -12902,21 +13191,20 @@ class OpenCodeAdapter {
12902
13191
  displayName = "OpenCode";
12903
13192
  pluginPackageName = OPENCODE_PLUGIN_NAME;
12904
13193
  hostGeneration;
12905
- resolvedWriteKey;
13194
+ probeHostUse;
12906
13195
  constructor(options = {}) {
12907
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;
12908
13205
  }
12909
13206
  get writeKey() {
12910
- if (this.resolvedWriteKey)
12911
- return this.resolvedWriteKey;
12912
- const generation = this.hostGeneration ?? (() => {
12913
- const detection = detectOpenCode();
12914
- if (detection.kind !== "cli")
12915
- return "v1";
12916
- return openCodeHostGenerationFromVersion(getOpenCodeVersion(detection.binary));
12917
- })();
12918
- this.resolvedWriteKey = pluginConfigKeyFor(generation);
12919
- return this.resolvedWriteKey;
13207
+ return pluginConfigKeyFor(this.resolvedHostGeneration);
12920
13208
  }
12921
13209
  isInstalled() {
12922
13210
  return detectOpenCode().kind !== "none";
@@ -12926,7 +13214,7 @@ class OpenCodeAdapter {
12926
13214
  if (paths.opencodeConfigFormat === "none")
12927
13215
  return false;
12928
13216
  try {
12929
- const raw = readFileSync5(paths.opencodeConfig, "utf-8");
13217
+ const raw = readFileSync6(paths.opencodeConfig, "utf-8");
12930
13218
  const cfg = import_comment_json.parse(raw);
12931
13219
  return readPluginEntries(cfg).some(({ entry }) => matchesPluginEntry(entry, OPENCODE_PLUGIN_NAME));
12932
13220
  } catch {
@@ -12962,7 +13250,7 @@ class OpenCodeAdapter {
12962
13250
  configPath: target
12963
13251
  };
12964
13252
  }
12965
- const raw = readFileSync5(target, "utf-8");
13253
+ const raw = readFileSync6(target, "utf-8");
12966
13254
  const cfg = import_comment_json.parse(raw);
12967
13255
  if (cfg === null || typeof cfg !== "object") {
12968
13256
  return {
@@ -13037,7 +13325,7 @@ class OpenCodeAdapter {
13037
13325
  };
13038
13326
  }
13039
13327
  try {
13040
- const raw = readFileSync5(target, "utf-8");
13328
+ const raw = readFileSync6(target, "utf-8");
13041
13329
  const cfg = import_comment_json.parse(raw);
13042
13330
  if (cfg === null || typeof cfg !== "object") {
13043
13331
  return {
@@ -13087,22 +13375,83 @@ class OpenCodeAdapter {
13087
13375
  return "Install OpenCode: curl -fsSL https://opencode.ai/install | bash";
13088
13376
  }
13089
13377
  getPluginCacheInfo() {
13090
- const path = getOpenCodePluginCacheDir();
13091
- return {
13092
- path,
13093
- exists: existsSync9(path),
13094
- sizeBytes: dirSizeBytes(path)
13095
- };
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
+ }
13096
13430
  }
13097
13431
  getLogPath() {
13098
13432
  return getMagicContextLogPath2("opencode");
13099
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
+ }
13100
13445
  getInstalledPluginVersion() {
13446
+ if (this.resolvedHostGeneration === "v2") {
13447
+ const slot = getOpenCodeV2PluginCacheSlot(undefined, this.configuredPluginSpec());
13448
+ return readOpenCodeV2CachedPluginVersion(slot) ?? null;
13449
+ }
13101
13450
  for (const candidate of getOpenCodePluginPackageJsonPaths()) {
13102
- if (!existsSync9(candidate))
13451
+ if (!existsSync10(candidate))
13103
13452
  continue;
13104
13453
  try {
13105
- const raw = readFileSync5(candidate, "utf-8");
13454
+ const raw = readFileSync6(candidate, "utf-8");
13106
13455
  const pkg = JSON.parse(raw);
13107
13456
  if (typeof pkg.version === "string")
13108
13457
  return pkg.version;
@@ -13138,15 +13487,15 @@ function isDevPathPluginEntry(entry) {
13138
13487
  if (candidate.startsWith("file://")) {
13139
13488
  localPath = fileURLToPath(candidate);
13140
13489
  } else {
13141
- localPath = resolve3(candidate);
13490
+ localPath = resolve4(candidate);
13142
13491
  }
13143
13492
  if (statSync6(localPath).isFile())
13144
13493
  localPath = dirname4(localPath);
13145
13494
  const root = parsePath(localPath).root;
13146
13495
  while (localPath !== root) {
13147
- const packagePath = resolve3(localPath, "package.json");
13148
- if (existsSync9(packagePath)) {
13149
- 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"));
13150
13499
  return pkg.name === OPENCODE_PLUGIN_NAME;
13151
13500
  }
13152
13501
  localPath = dirname4(localPath);
@@ -13166,7 +13515,7 @@ function matchesPluginEntry(entry, pkgName) {
13166
13515
  }
13167
13516
  function ensureDir(filePath) {
13168
13517
  const dir = dirname4(filePath);
13169
- if (!existsSync9(dir)) {
13518
+ if (!existsSync10(dir)) {
13170
13519
  const { mkdirSync } = __require("node:fs");
13171
13520
  mkdirSync(dir, { recursive: true });
13172
13521
  }
@@ -13174,6 +13523,7 @@ function ensureDir(filePath) {
13174
13523
  var import_comment_json;
13175
13524
  var init_opencode = __esm(() => {
13176
13525
  init_opencode_db_path();
13526
+ init_doctor_opencode2_cache();
13177
13527
  init_atomic_write();
13178
13528
  init_opencode_detect();
13179
13529
  init_opencode_helpers();
@@ -13184,7 +13534,7 @@ var init_opencode = __esm(() => {
13184
13534
  });
13185
13535
 
13186
13536
  // ../plugin/src/shared/jsonc-parser.ts
13187
- import { existsSync as existsSync10, readFileSync as readFileSync6 } from "node:fs";
13537
+ import { existsSync as existsSync11, readFileSync as readFileSync7 } from "node:fs";
13188
13538
  function stripJsonComments(content) {
13189
13539
  let result = "";
13190
13540
  let inString = false;
@@ -13359,7 +13709,7 @@ function parseJsonc2(content, options = {}) {
13359
13709
  }
13360
13710
  function readJsoncFile(filePath) {
13361
13711
  try {
13362
- return parseJsonc2(readFileSync6(filePath, "utf-8"));
13712
+ return parseJsonc2(readFileSync7(filePath, "utf-8"));
13363
13713
  } catch (_error) {
13364
13714
  return null;
13365
13715
  }
@@ -13367,10 +13717,10 @@ function readJsoncFile(filePath) {
13367
13717
  function detectConfigFile(basePath) {
13368
13718
  const jsoncPath = `${basePath}.jsonc`;
13369
13719
  const jsonPath = `${basePath}.json`;
13370
- if (existsSync10(jsoncPath)) {
13720
+ if (existsSync11(jsoncPath)) {
13371
13721
  return { format: "jsonc", path: jsoncPath };
13372
13722
  }
13373
- if (existsSync10(jsonPath)) {
13723
+ if (existsSync11(jsonPath)) {
13374
13724
  return { format: "json", path: jsonPath };
13375
13725
  }
13376
13726
  return { format: "none", path: jsoncPath };
@@ -13382,7 +13732,7 @@ var init_jsonc_parser = __esm(() => {
13382
13732
  });
13383
13733
 
13384
13734
  // src/lib/jsonc-config.ts
13385
- import { existsSync as existsSync11, readFileSync as readFileSync7 } from "node:fs";
13735
+ import { existsSync as existsSync12, readFileSync as readFileSync8 } from "node:fs";
13386
13736
  function parseErrorLocation(content, error) {
13387
13737
  const lines = content.split(`
13388
13738
  `);
@@ -13398,9 +13748,9 @@ function parseErrorLocation(content, error) {
13398
13748
  return { line: messageLine ? Number.parseInt(messageLine, 10) : 1, column: 1 };
13399
13749
  }
13400
13750
  function readJsoncConfig(path) {
13401
- if (!existsSync11(path))
13751
+ if (!existsSync12(path))
13402
13752
  return { kind: "missing" };
13403
- const content = readFileSync7(path, "utf-8");
13753
+ const content = readFileSync8(path, "utf-8");
13404
13754
  try {
13405
13755
  const rejectedKeyPaths = [];
13406
13756
  const parsed = sanitizeParsedJson(import_comment_json2.parse(content), {
@@ -13449,7 +13799,7 @@ var init_jsonc_config = __esm(() => {
13449
13799
  });
13450
13800
 
13451
13801
  // src/lib/pi-package-entry.ts
13452
- import { existsSync as existsSync12, readFileSync as readFileSync8 } from "node:fs";
13802
+ import { existsSync as existsSync13, readFileSync as readFileSync9 } from "node:fs";
13453
13803
  import { isAbsolute as isAbsolute5, join as join12 } from "node:path";
13454
13804
  function stripNpmPrefix(value) {
13455
13805
  return value.startsWith("npm:") ? value.slice("npm:".length) : value;
@@ -13506,10 +13856,10 @@ function hasPiMagicContextPackage(entries, agentDir = getPiAgentConfigDir()) {
13506
13856
  }
13507
13857
  function isPiMagicContextPackageDir(dir) {
13508
13858
  const packageJson = join12(dir, "package.json");
13509
- if (!existsSync12(packageJson))
13859
+ if (!existsSync13(packageJson))
13510
13860
  return false;
13511
13861
  try {
13512
- const pkg = JSON.parse(readFileSync8(packageJson, "utf-8"));
13862
+ const pkg = JSON.parse(readFileSync9(packageJson, "utf-8"));
13513
13863
  return typeof pkg.name === "string" && pkg.name === PI_MAGIC_CONTEXT_PACKAGE_NAME;
13514
13864
  } catch {
13515
13865
  return false;
@@ -13545,7 +13895,7 @@ var init_pi_package_entry = __esm(() => {
13545
13895
  });
13546
13896
 
13547
13897
  // src/adapters/pi.ts
13548
- import { existsSync as existsSync13 } from "node:fs";
13898
+ import { existsSync as existsSync14 } from "node:fs";
13549
13899
  import { dirname as dirname5 } from "node:path";
13550
13900
 
13551
13901
  class PiAdapter {
@@ -13647,7 +13997,7 @@ class PiAdapter {
13647
13997
  return "Install Pi: https://pi.coding/install (npm: @earendil-works/pi-coding-agent)";
13648
13998
  }
13649
13999
  getPluginCacheInfo() {
13650
- return { path: null, exists: false, sizeBytes: 0 };
14000
+ return [{ path: null, exists: false, sizeBytes: 0 }];
13651
14001
  }
13652
14002
  getLogPath() {
13653
14003
  return getMagicContextLogPath2("pi");
@@ -13684,7 +14034,7 @@ function writePiSettings(settings) {
13684
14034
  }
13685
14035
  function ensureDir2(filePath) {
13686
14036
  const dir = dirname5(filePath);
13687
- if (!existsSync13(dir)) {
14037
+ if (!existsSync14(dir)) {
13688
14038
  const { mkdirSync } = __require("node:fs");
13689
14039
  mkdirSync(dir, { recursive: true });
13690
14040
  }
@@ -13814,10 +14164,10 @@ var init_harness_provider_map = __esm(() => {
13814
14164
  // ../plugin/src/config/raw-loader.ts
13815
14165
  import {
13816
14166
  closeSync as closeSync2,
13817
- existsSync as existsSync14,
14167
+ existsSync as existsSync15,
13818
14168
  linkSync,
13819
14169
  openSync as openSync2,
13820
- readFileSync as readFileSync9,
14170
+ readFileSync as readFileSync10,
13821
14171
  renameSync as renameSync3,
13822
14172
  statSync as statSync7,
13823
14173
  unlinkSync as unlinkSync2,
@@ -14017,7 +14367,7 @@ function writeExclusiveBackup(backupPath, bytes, mode) {
14017
14367
  if (error.code !== "EEXIST")
14018
14368
  throw error;
14019
14369
  }
14020
- const existingBytes = readFileSync9(backupPath);
14370
+ const existingBytes = readFileSync10(backupPath);
14021
14371
  if (existingBytes.equals(bytes))
14022
14372
  return;
14023
14373
  if (bytes.subarray(0, existingBytes.length).equals(existingBytes)) {
@@ -14061,11 +14411,11 @@ function migrationWarning(diagnostic) {
14061
14411
  return diagnostic.message;
14062
14412
  }
14063
14413
  function loadRawConfigFile(options) {
14064
- if (!existsSync14(options.configPath))
14414
+ if (!existsSync15(options.configPath))
14065
14415
  return null;
14066
14416
  let observedBytes;
14067
14417
  try {
14068
- observedBytes = readFileSync9(options.configPath);
14418
+ observedBytes = readFileSync10(options.configPath);
14069
14419
  } catch (error) {
14070
14420
  throw new Error(`failed to read config: ${error instanceof Error ? error.message : String(error)}`);
14071
14421
  }
@@ -14109,7 +14459,7 @@ function loadRawConfigFile(options) {
14109
14459
  writeExclusiveBackup(backupPath, observedBytes, mode);
14110
14460
  temporaryPath = writeTemporaryCandidate(options.configPath, migration.bytes, mode);
14111
14461
  options.afterTemporaryWrite?.();
14112
- const currentBytes = readFileSync9(options.configPath);
14462
+ const currentBytes = readFileSync10(options.configPath);
14113
14463
  if (!hasFlatKeys(currentBytes)) {
14114
14464
  unlinkSync2(temporaryPath);
14115
14465
  return {
@@ -14481,10 +14831,10 @@ var init_dreamer_setup = __esm(() => {
14481
14831
  });
14482
14832
 
14483
14833
  // src/commands/setup-pi.ts
14484
- import { existsSync as existsSync15, mkdirSync as mkdirSync3 } from "node:fs";
14834
+ import { existsSync as existsSync16, mkdirSync as mkdirSync3 } from "node:fs";
14485
14835
  import { dirname as dirname7 } from "node:path";
14486
14836
  function ensureDir3(path) {
14487
- if (!existsSync15(path))
14837
+ if (!existsSync16(path))
14488
14838
  mkdirSync3(path, { recursive: true });
14489
14839
  }
14490
14840
  async function getDefaultPrompts() {
@@ -21910,16 +22260,16 @@ function resolveTransformMode(args) {
21910
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.";
21911
22261
 
21912
22262
  // ../plugin/src/config/variable.ts
21913
- import { existsSync as existsSync16, readFileSync as readFileSync10 } from "node:fs";
22263
+ import { existsSync as existsSync17, readFileSync as readFileSync11 } from "node:fs";
21914
22264
  import { homedir as homedir10 } from "node:os";
21915
- 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";
21916
22266
  function sensitiveFilePathReason(resolvedPath) {
21917
22267
  const home = homedir10();
21918
22268
  const sensitiveDirs = [
21919
- { dir: resolve4(home, ".ssh"), label: "SSH keys" },
21920
- { dir: resolve4(home, ".aws"), label: "AWS credentials" },
21921
- { dir: resolve4(home, ".gnupg"), label: "GnuPG keyring" },
21922
- { 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" }
21923
22273
  ];
21924
22274
  for (const { dir, label } of sensitiveDirs) {
21925
22275
  if (resolvedPath === dir || resolvedPath.startsWith(`${dir}/`)) {
@@ -21977,21 +22327,21 @@ function substituteConfigVariables(input) {
21977
22327
  }
21978
22328
  let filePath = rawPath.trim();
21979
22329
  if (filePath.startsWith("~/")) {
21980
- filePath = resolve4(homedir10(), filePath.slice(2));
22330
+ filePath = resolve5(homedir10(), filePath.slice(2));
21981
22331
  } else if (!isAbsolute6(filePath)) {
21982
- filePath = resolve4(configDir, filePath);
22332
+ filePath = resolve5(configDir, filePath);
21983
22333
  }
21984
22334
  const sensitiveReason = sensitiveFilePathReason(filePath);
21985
22335
  if (sensitiveReason) {
21986
22336
  warnings.push(`${token} resolves to a sensitive path (${sensitiveReason}: ${filePath}); ` + "inlining its contents into config — make sure this is intentional.");
21987
22337
  }
21988
- if (!existsSync16(filePath)) {
22338
+ if (!existsSync17(filePath)) {
21989
22339
  warnings.push(`File not found for ${token} (resolved to ${filePath}); using empty string`);
21990
22340
  continue;
21991
22341
  }
21992
22342
  let contents;
21993
22343
  try {
21994
- contents = readFileSync10(filePath, "utf-8").trim();
22344
+ contents = readFileSync11(filePath, "utf-8").trim();
21995
22345
  } catch (error) {
21996
22346
  const message = error instanceof Error ? error.message : String(error);
21997
22347
  warnings.push(`Failed to read file for ${token} (${filePath}): ${message}; using empty string`);
@@ -22010,7 +22360,7 @@ var init_variable = __esm(() => {
22010
22360
  });
22011
22361
 
22012
22362
  // ../plugin/src/config/index.ts
22013
- import { existsSync as existsSync17 } from "node:fs";
22363
+ import { existsSync as existsSync18 } from "node:fs";
22014
22364
  function getUserConfigBasePath() {
22015
22365
  return cortexKitUserConfigBasePath();
22016
22366
  }
@@ -22018,10 +22368,10 @@ function getProjectConfigBasePath(directory) {
22018
22368
  return cortexKitProjectConfigBasePath(directory);
22019
22369
  }
22020
22370
  function resolveLegacyReadFallback(sources) {
22021
- return { source: sources.find((s) => existsSync17(s.path)) ?? null };
22371
+ return { source: sources.find((s) => existsSync18(s.path)) ?? null };
22022
22372
  }
22023
22373
  function loadConfigFileDetailed(configPath, source) {
22024
- if (!existsSync17(configPath)) {
22374
+ if (!existsSync18(configPath)) {
22025
22375
  return null;
22026
22376
  }
22027
22377
  let rawText;
@@ -22334,8 +22684,8 @@ function loadPluginConfigDetailed(directory, applyRuntimeGlobals = true) {
22334
22684
  const harnessLegacy = resolveLegacyConfigSourcesForHarness(directory, "opencode");
22335
22685
  const userLegacyFallback = userDetected.format === "none" ? resolveLegacyReadFallback(harnessLegacy.user) : { source: null };
22336
22686
  const projectLegacyFallback = projectDetected.format === "none" ? resolveLegacyReadFallback(harnessLegacy.project) : { source: null };
22337
- const legacyUserUnmigrated = userDetected.format === "none" && !userLegacyFallback.source && legacySources.user.some((source) => existsSync17(source.path));
22338
- 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));
22339
22689
  const userLoaded = userDetected.format !== "none" ? loadConfigFileDetailed(userDetected.path, "user") : userLegacyFallback.source ? loadConfigFileDetailed(userLegacyFallback.source.path, "user") : null;
22340
22690
  const projectLoaded = projectDetected.format !== "none" ? loadConfigFileDetailed(projectDetected.path, "project") : projectLegacyFallback.source ? loadConfigFileDetailed(projectLegacyFallback.source.path, "project") : null;
22341
22691
  const allWarnings = [];
@@ -22473,7 +22823,7 @@ var init_config = __esm(() => {
22473
22823
 
22474
22824
  // ../plugin/src/shared/opencode-config-dir.ts
22475
22825
  import { homedir as homedir11 } from "node:os";
22476
- import { join as join14, resolve as resolve5 } from "node:path";
22826
+ import { join as join14, resolve as resolve6 } from "node:path";
22477
22827
  function resolveHomeDir() {
22478
22828
  return process.env.HOME?.trim() || homedir11();
22479
22829
  }
@@ -22485,7 +22835,7 @@ function getOpenCodeGlobalConfigDir() {
22485
22835
  }
22486
22836
  function getEnvConfigDir() {
22487
22837
  const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
22488
- return envConfigDir ? resolve5(envConfigDir) : undefined;
22838
+ return envConfigDir ? resolve6(envConfigDir) : undefined;
22489
22839
  }
22490
22840
  function getCliConfigDir() {
22491
22841
  return getEnvConfigDir() ?? getOpenCodeGlobalConfigDir();
@@ -22772,7 +23122,7 @@ var init_conflict_detector = __esm(() => {
22772
23122
  });
22773
23123
 
22774
23124
  // ../plugin/src/shared/conflict-fixer.ts
22775
- 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";
22776
23126
  import { homedir as homedir13 } from "node:os";
22777
23127
  import { join as join16 } from "node:path";
22778
23128
  function isRecord2(value) {
@@ -22782,11 +23132,11 @@ function asStringArray(value) {
22782
23132
  return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
22783
23133
  }
22784
23134
  function readConfig(filePath) {
22785
- if (!existsSync18(filePath)) {
23135
+ if (!existsSync19(filePath)) {
22786
23136
  return null;
22787
23137
  }
22788
23138
  try {
22789
- const text = readFileSync11(filePath, "utf-8");
23139
+ const text = readFileSync12(filePath, "utf-8");
22790
23140
  const parsed = import_comment_json5.parse(text);
22791
23141
  return isRecord2(parsed) ? { config: parsed, text } : null;
22792
23142
  } catch {
@@ -22798,14 +23148,14 @@ function writeConfig(filePath, text) {
22798
23148
  }
22799
23149
  function resolveUserOpenCodeConfigPath() {
22800
23150
  const paths = getOpenCodeConfigPaths({ binary: "opencode" });
22801
- if (existsSync18(paths.configJsonc))
23151
+ if (existsSync19(paths.configJsonc))
22802
23152
  return paths.configJsonc;
22803
23153
  return paths.configJson;
22804
23154
  }
22805
23155
  function collectOpenCodeConfigPaths(directory) {
22806
23156
  const paths = new Set;
22807
23157
  const userConfig = resolveUserOpenCodeConfigPath();
22808
- if (existsSync18(userConfig)) {
23158
+ if (existsSync19(userConfig)) {
22809
23159
  paths.add(userConfig);
22810
23160
  }
22811
23161
  for (const filePath of [
@@ -22814,7 +23164,7 @@ function collectOpenCodeConfigPaths(directory) {
22814
23164
  join16(directory, "opencode.jsonc"),
22815
23165
  join16(directory, "opencode.json")
22816
23166
  ]) {
22817
- if (existsSync18(filePath)) {
23167
+ if (existsSync19(filePath)) {
22818
23168
  paths.add(filePath);
22819
23169
  }
22820
23170
  }
@@ -22826,10 +23176,10 @@ function collectOmoConfigPaths(directory) {
22826
23176
  for (const fileName of OMO_CONFIG_NAMES) {
22827
23177
  const userPath = join16(configDir, fileName);
22828
23178
  const projectPath = join16(directory, fileName);
22829
- if (existsSync18(userPath)) {
23179
+ if (existsSync19(userPath)) {
22830
23180
  paths.add(userPath);
22831
23181
  }
22832
- if (existsSync18(projectPath)) {
23182
+ if (existsSync19(projectPath)) {
22833
23183
  paths.add(projectPath);
22834
23184
  }
22835
23185
  }
@@ -22837,13 +23187,13 @@ function collectOmoConfigPaths(directory) {
22837
23187
  const omoHomeDir = join16(homeDir, ".omo");
22838
23188
  for (const name of OMO_UNIFIED_NAMES) {
22839
23189
  const userPath = join16(omoHomeDir, name);
22840
- if (existsSync18(userPath)) {
23190
+ if (existsSync19(userPath)) {
22841
23191
  paths.add(userPath);
22842
23192
  }
22843
23193
  }
22844
23194
  for (const name of OMO_UNIFIED_NAMES) {
22845
23195
  const projectPath = join16(directory, ".omo", name);
22846
- if (existsSync18(projectPath)) {
23196
+ if (existsSync19(projectPath)) {
22847
23197
  paths.add(projectPath);
22848
23198
  }
22849
23199
  }
@@ -22971,7 +23321,7 @@ var init_conflict_fixer = __esm(() => {
22971
23321
  });
22972
23322
 
22973
23323
  // src/commands/setup-opencode.ts
22974
- 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";
22975
23325
  import { basename as basename3, dirname as dirname10 } from "node:path";
22976
23326
  function resolveCompactionEnabledForWriter() {
22977
23327
  try {
@@ -22983,7 +23333,7 @@ function resolveCompactionEnabledForWriter() {
22983
23333
  }
22984
23334
  }
22985
23335
  function ensureDir5(dir) {
22986
- if (!existsSync19(dir)) {
23336
+ if (!existsSync20(dir)) {
22987
23337
  mkdirSync5(dir, { recursive: true });
22988
23338
  }
22989
23339
  }
@@ -23012,7 +23362,7 @@ function readMagicContextConfigForSetup2(configPath) {
23012
23362
  }
23013
23363
  function addPluginToOpenCodeConfig(configPath, _format, removeDcp = false, compactionEnabled = true, hostGeneration = "v1") {
23014
23364
  const registrationKey = pluginConfigKeyFor(hostGeneration);
23015
- const existsAtCommit = existsSync19(configPath);
23365
+ const existsAtCommit = existsSync20(configPath);
23016
23366
  const existing = existsAtCommit ? readJsoncConfigForUpdate(configPath) : {};
23017
23367
  if (!existsAtCommit) {
23018
23368
  ensureDir5(dirname10(configPath));
@@ -23024,7 +23374,7 @@ function addPluginToOpenCodeConfig(configPath, _format, removeDcp = false, compa
23024
23374
  `);
23025
23375
  return;
23026
23376
  }
23027
- let text = readFileSync12(configPath, "utf-8");
23377
+ let text = readFileSync13(configPath, "utf-8");
23028
23378
  let changed = false;
23029
23379
  const rawPlugins = readPluginEntries(existing).map(({ entry }) => entry);
23030
23380
  const retainedPlugins = removeDcp ? rawPlugins.filter((plugin) => !matchesPluginEntry(plugin, DCP_PLUGIN_NAME)) : rawPlugins;
@@ -23070,7 +23420,7 @@ function addPluginToOpenCodeConfig(configPath, _format, removeDcp = false, compa
23070
23420
  writeFileAtomic(configPath, text);
23071
23421
  }
23072
23422
  function addPluginToTuiConfig(configPath, _format) {
23073
- const existsAtCommit = existsSync19(configPath);
23423
+ const existsAtCommit = existsSync20(configPath);
23074
23424
  const existing = existsAtCommit ? readJsoncConfigForUpdate(configPath) : {};
23075
23425
  if (!existsAtCommit) {
23076
23426
  ensureDir5(dirname10(configPath));
@@ -23086,7 +23436,7 @@ function addPluginToTuiConfig(configPath, _format) {
23086
23436
  const hasDevEntry = rawPlugins.some((plugin) => isDevPathPluginEntry(plugin));
23087
23437
  if (hasNpmEntry || hasDevEntry)
23088
23438
  return;
23089
- 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]);
23090
23440
  writeFileAtomic(configPath, text);
23091
23441
  }
23092
23442
  function findDcpPluginIndexes(plugins) {
@@ -23192,7 +23542,7 @@ async function runSetup3(dryRun = false) {
23192
23542
  log2.warn("You can configure models manually in magic-context.jsonc later");
23193
23543
  }
23194
23544
  const paths = detectConfigPaths();
23195
- const hadExistingSetup = paths.opencodeConfigFormat !== "none" || existsSync19(paths.magicContextConfig) || paths.tuiConfigFormat !== "none";
23545
+ const hadExistingSetup = paths.opencodeConfigFormat !== "none" || existsSync20(paths.magicContextConfig) || paths.tuiConfigFormat !== "none";
23196
23546
  if (!dryRun) {
23197
23547
  try {
23198
23548
  assertJsoncConfigsParseable([
@@ -24482,7 +24832,7 @@ var init_context_authority = __esm(async () => {
24482
24832
  // ../plugin/src/features/magic-context/memory/project-identity.ts
24483
24833
  import { execFileSync as execFileSync3 } from "node:child_process";
24484
24834
  import { createHash as createHash2 } from "node:crypto";
24485
- 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";
24486
24836
  import path3 from "node:path";
24487
24837
  function asError(error) {
24488
24838
  return error instanceof Error ? error : undefined;
@@ -24720,7 +25070,7 @@ function hasGitDir(canonical) {
24720
25070
  function gitRootInAncestorChain(startDirectory) {
24721
25071
  let current = startDirectory;
24722
25072
  while (true) {
24723
- if (existsSync20(path3.join(current, ".git"))) {
25073
+ if (existsSync21(path3.join(current, ".git"))) {
24724
25074
  try {
24725
25075
  return realpathSync2.native(current);
24726
25076
  } catch {
@@ -27055,7 +27405,7 @@ var init_pi_executable = __esm(() => {
27055
27405
 
27056
27406
  // ../plugin/src/shared/rpc-utils.ts
27057
27407
  import { execFileSync as execFileSync4 } from "node:child_process";
27058
- import { readFileSync as readFileSync13 } from "node:fs";
27408
+ import { readFileSync as readFileSync14 } from "node:fs";
27059
27409
  function isPidAlive(pid) {
27060
27410
  if (!Number.isInteger(pid) || pid <= 0)
27061
27411
  return "dead";
@@ -27591,7 +27941,7 @@ var init_rpc_utils = __esm(() => {
27591
27941
  "cljs/dist",
27592
27942
  "dist/bundle/cli"
27593
27943
  ];
27594
- rpcIdentityReadFileSync = readFileSync13;
27944
+ rpcIdentityReadFileSync = readFileSync14;
27595
27945
  rpcIdentityExecFileSync = execFileSync4;
27596
27946
  rpcIdentityProcessKill = process.kill;
27597
27947
  rpcProcessListExecFileSync = execFileSync4;
@@ -30883,14 +31233,14 @@ import {
30883
31233
  chmodSync as chmodSync3,
30884
31234
  copyFileSync,
30885
31235
  cpSync,
30886
- existsSync as existsSync21,
31236
+ existsSync as existsSync22,
30887
31237
  mkdirSync as mkdirSync6,
30888
- readdirSync as readdirSync3,
30889
- readFileSync as readFileSync14,
31238
+ readdirSync as readdirSync4,
31239
+ readFileSync as readFileSync15,
30890
31240
  statSync as statSync10,
30891
31241
  unlinkSync as unlinkSync3
30892
31242
  } from "node:fs";
30893
- 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";
30894
31244
  function resolveBootBusyTimeoutMs(value) {
30895
31245
  if (value === undefined)
30896
31246
  return BOOT_SQLITE_BUSY_TIMEOUT_MS;
@@ -32329,8 +32679,8 @@ var init_storage_db = __esm(async () => {
32329
32679
  PERMISSIONS_ENFORCEABLE = process.platform !== "win32";
32330
32680
  RPC_DISCOVERY_PARSE_GRACE_MS = 10 * 60 * 1000;
32331
32681
  defaultRpcDiscoveryFs = {
32332
- readdirSync: (path, options) => options?.withFileTypes ? readdirSync3(path, { withFileTypes: true }) : readdirSync3(path),
32333
- 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)),
32334
32684
  statSync: (path) => ({ mtimeMs: statSync10(path).mtimeMs }),
32335
32685
  unlinkSync: (path) => unlinkSync3(path)
32336
32686
  };
@@ -32343,13 +32693,13 @@ var init_storage_db = __esm(async () => {
32343
32693
  });
32344
32694
 
32345
32695
  // src/lib/database-access.ts
32346
- import { existsSync as existsSync22, writeFileSync as writeFileSync5 } from "node:fs";
32696
+ import { existsSync as existsSync23, writeFileSync as writeFileSync5 } from "node:fs";
32347
32697
  import { pathToFileURL } from "node:url";
32348
32698
  function getPersistedSchemaVersion2(db) {
32349
32699
  return getPersistedSchemaVersion(db);
32350
32700
  }
32351
32701
  function openExistingDatabase(path, options) {
32352
- if (!existsSync22(path))
32702
+ if (!existsSync23(path))
32353
32703
  return null;
32354
32704
  if (options.readonly) {
32355
32705
  const db = new Database(path, { readonly: true });
@@ -32960,16 +33310,16 @@ var init_doctor_merge_identity = __esm(async () => {
32960
33310
  });
32961
33311
 
32962
33312
  // src/commands/doctor-repair-db.ts
32963
- import { spawnSync as spawnSync3 } from "node:child_process";
33313
+ import { spawnSync as spawnSync4 } from "node:child_process";
32964
33314
  import {
32965
33315
  chmodSync as chmodSync4,
32966
33316
  closeSync as closeSync4,
32967
33317
  constants as constants2,
32968
33318
  copyFileSync as copyFileSync2,
32969
- existsSync as existsSync23,
33319
+ existsSync as existsSync24,
32970
33320
  openSync as openSync4,
32971
33321
  renameSync as renameSync4,
32972
- rmSync as rmSync2,
33322
+ rmSync as rmSync3,
32973
33323
  statSync as statSync11
32974
33324
  } from "node:fs";
32975
33325
  import { dirname as dirname12, join as join20 } from "node:path";
@@ -33002,11 +33352,11 @@ function timestamp(date) {
33002
33352
  return date.toISOString().replaceAll("-", "").replaceAll(":", "").replace(".", "");
33003
33353
  }
33004
33354
  function uniqueBase(preferred) {
33005
- if (!DATABASE_SUFFIXES.some((suffix) => existsSync23(`${preferred}${suffix}`)))
33355
+ if (!DATABASE_SUFFIXES.some((suffix) => existsSync24(`${preferred}${suffix}`)))
33006
33356
  return preferred;
33007
33357
  for (let attempt = 1;attempt < 1e4; attempt++) {
33008
33358
  const candidate = `${preferred}-${attempt}`;
33009
- if (!DATABASE_SUFFIXES.some((suffix) => existsSync23(`${candidate}${suffix}`)))
33359
+ if (!DATABASE_SUFFIXES.some((suffix) => existsSync24(`${candidate}${suffix}`)))
33010
33360
  return candidate;
33011
33361
  }
33012
33362
  throw new Error(`Could not allocate a unique recovery path beside ${preferred}`);
@@ -33020,7 +33370,7 @@ function copyDatabaseBundle(sourceBase, destinationBase) {
33020
33370
  const copiedPaths = [];
33021
33371
  for (const suffix of DATABASE_SUFFIXES) {
33022
33372
  const source = `${sourceBase}${suffix}`;
33023
- if (!existsSync23(source))
33373
+ if (!existsSync24(source))
33024
33374
  continue;
33025
33375
  const destination = `${destinationBase}${suffix}`;
33026
33376
  copyFileSync2(source, destination, constants2.COPYFILE_EXCL);
@@ -33088,7 +33438,7 @@ function runRecoverShell(sqliteExecutable, sourcePath, recoveredPath, dumpPath)
33088
33438
  let dumpWriteFd = null;
33089
33439
  try {
33090
33440
  dumpWriteFd = openSync4(dumpPath, "wx", 384);
33091
- const recovered = spawnSync3(sqliteExecutable, [sourcePath, ".recover"], {
33441
+ const recovered = spawnSync4(sqliteExecutable, [sourcePath, ".recover"], {
33092
33442
  stdio: ["ignore", dumpWriteFd, "pipe"],
33093
33443
  encoding: "utf8",
33094
33444
  windowsHide: true
@@ -33107,7 +33457,7 @@ function runRecoverShell(sqliteExecutable, sourcePath, recoveredPath, dumpPath)
33107
33457
  }
33108
33458
  const dumpReadFd = openSync4(dumpPath, "r");
33109
33459
  try {
33110
- const replayed = spawnSync3(sqliteExecutable, [recoveredPath], {
33460
+ const replayed = spawnSync4(sqliteExecutable, [recoveredPath], {
33111
33461
  stdio: [dumpReadFd, "ignore", "pipe"],
33112
33462
  encoding: "utf8",
33113
33463
  windowsHide: true
@@ -33134,7 +33484,7 @@ function runRecoverShell(sqliteExecutable, sourcePath, recoveredPath, dumpPath)
33134
33484
  } finally {
33135
33485
  if (dumpWriteFd !== null)
33136
33486
  closeSync4(dumpWriteFd);
33137
- rmSync2(dumpPath, { force: true });
33487
+ rmSync3(dumpPath, { force: true });
33138
33488
  }
33139
33489
  }
33140
33490
  function migrateAndCheckRecoveredDatabase(path) {
@@ -33213,14 +33563,14 @@ function prepareFreshDatabase(path) {
33213
33563
  }
33214
33564
  function removeRecoveryBundle(basePath) {
33215
33565
  for (const suffix of DATABASE_SUFFIXES)
33216
- rmSync2(`${basePath}${suffix}`, { force: true });
33566
+ rmSync3(`${basePath}${suffix}`, { force: true });
33217
33567
  }
33218
33568
  function activateReplacement(dbPath, replacementPath, originalAsidePath) {
33219
33569
  const movedOriginals = [];
33220
33570
  try {
33221
33571
  for (const suffix of DATABASE_SUFFIXES) {
33222
33572
  const from = `${dbPath}${suffix}`;
33223
- if (!existsSync23(from))
33573
+ if (!existsSync24(from))
33224
33574
  continue;
33225
33575
  const to = `${originalAsidePath}${suffix}`;
33226
33576
  renameSync4(from, to);
@@ -33230,7 +33580,7 @@ function activateReplacement(dbPath, replacementPath, originalAsidePath) {
33230
33580
  return movedOriginals.map(({ to }) => to);
33231
33581
  } catch (error) {
33232
33582
  for (const moved of movedOriginals.reverse()) {
33233
- if (existsSync23(moved.to) && !existsSync23(moved.from))
33583
+ if (existsSync24(moved.to) && !existsSync24(moved.from))
33234
33584
  renameSync4(moved.to, moved.from);
33235
33585
  }
33236
33586
  throw error;
@@ -33266,7 +33616,7 @@ async function runRepairDb(options = {}) {
33266
33616
  const stamp = timestamp(deps.now());
33267
33617
  prompts.intro("Magic Context — Repair shared database");
33268
33618
  prompts.log.info(`Database: ${dbPath}`);
33269
- if (!existsSync23(dbPath)) {
33619
+ if (!existsSync24(dbPath)) {
33270
33620
  prompts.log.error(`Database not found: ${dbPath}`);
33271
33621
  prompts.log.info("Backup: not created (database does not exist)");
33272
33622
  prompts.outro("Database repair failed");
@@ -33553,7 +33903,7 @@ var init_migration_paths = __esm(() => {
33553
33903
 
33554
33904
  // src/commands/migrate.ts
33555
33905
  import { createHash as createHash4, randomBytes as randomBytes2 } from "node:crypto";
33556
- 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";
33557
33907
  import { dirname as dirname13, join as join21 } from "node:path";
33558
33908
  function defaultOpenCodeDbPath() {
33559
33909
  return getOpenCodeDatabasePath();
@@ -33565,7 +33915,7 @@ function defaultPiSessionsRoot() {
33565
33915
  return getPiSessionsRoot();
33566
33916
  }
33567
33917
  function defaultFs() {
33568
- return { writeFileAtomic, unlinkSync: unlinkSync4, existsSync: existsSync24, renameSync: renameSync5, mkdirSync: mkdirSync7 };
33918
+ return { writeFileAtomic, unlinkSync: unlinkSync4, existsSync: existsSync25, renameSync: renameSync5, mkdirSync: mkdirSync7 };
33569
33919
  }
33570
33920
  function stmt(db, sql) {
33571
33921
  return db.prepare(sql);
@@ -34513,7 +34863,7 @@ var init_relocate_memory = __esm(() => {
34513
34863
  });
34514
34864
 
34515
34865
  // src/commands/migrate-session.ts
34516
- import { existsSync as existsSync25, realpathSync as realpathSync4 } from "node:fs";
34866
+ import { existsSync as existsSync26, realpathSync as realpathSync4 } from "node:fs";
34517
34867
  import { homedir as homedir14 } from "node:os";
34518
34868
  import path4, { join as join22 } from "node:path";
34519
34869
  function existingSessionColumns(db) {
@@ -34732,7 +35082,7 @@ function realDeps(opencodeDb, contextDb) {
34732
35082
  opencodeDb,
34733
35083
  contextDb,
34734
35084
  resolveIdentity: resolveProjectIdentity,
34735
- hasGitDir: (dir) => existsSync25(join22(dir, ".git")),
35085
+ hasGitDir: (dir) => existsSync26(join22(dir, ".git")),
34736
35086
  realpath: (p) => realpathSync4(p)
34737
35087
  };
34738
35088
  }
@@ -34811,7 +35161,7 @@ async function runMigrateSessionCli(args) {
34811
35161
  return 1;
34812
35162
  }
34813
35163
  const expandedTo = toDir.startsWith("~") ? join22(homedir14(), toDir.slice(1).replace(/^[/\\]/, "")) : toDir;
34814
- if (!existsSync25(expandedTo)) {
35164
+ if (!existsSync26(expandedTo)) {
34815
35165
  console.error(`Target directory does not exist: ${expandedTo}`);
34816
35166
  return 1;
34817
35167
  }
@@ -35213,6 +35563,11 @@ var init_user_facing_codes = __esm(() => {
35213
35563
  sentence: "Some finished background sessions could not be removed from this host.",
35214
35564
  action: "They are removed automatically the next time Magic Context runs inside a registered OpenCode service."
35215
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
+ },
35216
35571
  recomp_unavailable: {
35217
35572
  code: "MC-R01",
35218
35573
  sentence: "History compression could not be rebuilt.",
@@ -35383,6 +35738,11 @@ var init_user_facing_codes = __esm(() => {
35383
35738
  sentence: "History compression is paused while the engine syncs.",
35384
35739
  action: "Retry in a moment."
35385
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
+ },
35386
35746
  context_service_unavailable: {
35387
35747
  code: "MC-C10",
35388
35748
  sentence: "Magic Context is temporarily unavailable.",
@@ -35453,7 +35813,7 @@ var init_tick_failure = __esm(() => {
35453
35813
  });
35454
35814
 
35455
35815
  // ../pi-plugin/src/config/index.ts
35456
- import { existsSync as existsSync26 } from "node:fs";
35816
+ import { existsSync as existsSync27 } from "node:fs";
35457
35817
  function getProjectConfigPaths(cwd) {
35458
35818
  const basePath = cortexKitProjectConfigBasePath(cwd);
35459
35819
  return [`${basePath}.jsonc`, `${basePath}.json`];
@@ -35463,10 +35823,10 @@ function getUserConfigPaths() {
35463
35823
  return [`${basePath}.jsonc`, `${basePath}.json`];
35464
35824
  }
35465
35825
  function resolveFirstExisting(paths) {
35466
- return paths.find((path) => existsSync26(path));
35826
+ return paths.find((path) => existsSync27(path));
35467
35827
  }
35468
35828
  function resolvePiLegacyFallback(sources) {
35469
- return sources.find((source) => existsSync26(source.path)) ?? null;
35829
+ return sources.find((source) => existsSync27(source.path)) ?? null;
35470
35830
  }
35471
35831
  function loadConfigFile(path, scope) {
35472
35832
  let raw;
@@ -35761,7 +36121,7 @@ function loadPiConfigDetailed(opts = {}, applyRuntimeGlobals = true) {
35761
36121
  if (loaded)
35762
36122
  loadedFiles.push(loaded);
35763
36123
  }
35764
- const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) => existsSync26(source.path));
36124
+ const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) => existsSync27(source.path));
35765
36125
  const userPath = resolveFirstExisting(getUserConfigPaths());
35766
36126
  const userLegacyFallback = userPath ? null : resolvePiLegacyFallback(harnessLegacy.user);
35767
36127
  const userReadPath = userPath ?? userLegacyFallback?.path;
@@ -35770,7 +36130,7 @@ function loadPiConfigDetailed(opts = {}, applyRuntimeGlobals = true) {
35770
36130
  if (loaded)
35771
36131
  loadedFiles.push(loaded);
35772
36132
  }
35773
- const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) => existsSync26(source.path));
36133
+ const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) => existsSync27(source.path));
35774
36134
  if (userLegacyFallback) {
35775
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.`);
35776
36136
  } else if (legacyUserUnmigrated) {
@@ -35891,11 +36251,11 @@ function formatDatabaseRepairGuidance(dbPath) {
35891
36251
  var DATABASE_REPAIR_COMMAND = "bunx @cortexkit/magic-context@latest doctor repair-db";
35892
36252
 
35893
36253
  // src/lib/github-issue.ts
35894
- import { spawnSync as spawnSync4 } from "node:child_process";
35895
- import { readFileSync as readFileSync15 } from "node:fs";
36254
+ import { spawnSync as spawnSync5 } from "node:child_process";
36255
+ import { readFileSync as readFileSync16 } from "node:fs";
35896
36256
  function runGhCommand(args) {
35897
36257
  try {
35898
- const result = spawnSync4("gh", args, {
36258
+ const result = spawnSync5("gh", args, {
35899
36259
  encoding: "utf-8",
35900
36260
  stdio: ["ignore", "pipe", "pipe"]
35901
36261
  });
@@ -35918,7 +36278,7 @@ function failed(result) {
35918
36278
  function submitGithubIssue(title, bodyPath, runner = runGhCommand) {
35919
36279
  let body;
35920
36280
  try {
35921
- body = readFileSync15(bodyPath, "utf-8");
36281
+ body = readFileSync16(bodyPath, "utf-8");
35922
36282
  } catch (error) {
35923
36283
  return {
35924
36284
  ok: false,
@@ -35976,7 +36336,7 @@ var MAX_GITHUB_ISSUE_BODY_CHARS = 65536;
35976
36336
  var init_github_issue = () => {};
35977
36337
 
35978
36338
  // src/lib/log-lines.ts
35979
- 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";
35980
36340
  import { tmpdir as tmpdir2 } from "node:os";
35981
36341
  import { join as join23 } from "node:path";
35982
36342
  function tokenize(input, limit = Number.POSITIVE_INFINITY) {
@@ -36273,11 +36633,11 @@ function getMagicContextLogPaths(harness, options = {}) {
36273
36633
  ].filter((path, index, paths) => paths.indexOf(path) === index);
36274
36634
  }
36275
36635
  function inspectLogFile(path) {
36276
- if (!existsSync27(path)) {
36636
+ if (!existsSync28(path)) {
36277
36637
  return { path, exists: false, sizeKb: 0, lineCount: 0, grammar: "unknown" };
36278
36638
  }
36279
36639
  try {
36280
- const content = readFileSync16(path, "utf8");
36640
+ const content = readFileSync17(path, "utf8");
36281
36641
  const lines = content.split(/\r?\n/).filter((line) => line.length > 0);
36282
36642
  const grammars = new Set(lines.flatMap((line) => {
36283
36643
  const parsed = parseLogLine(line);
@@ -36304,7 +36664,7 @@ function readLogLines(files) {
36304
36664
  return [];
36305
36665
  try {
36306
36666
  let precedingTimestamp = "";
36307
- 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) => {
36308
36668
  precedingTimestamp = parseLogLine(line)?.ts ?? precedingTimestamp;
36309
36669
  return { line, timestamp: precedingTimestamp, fileIndex, lineIndex };
36310
36670
  });
@@ -36353,10 +36713,10 @@ var init_redaction2 = __esm(() => {
36353
36713
  });
36354
36714
 
36355
36715
  // src/commands/doctor-omp.ts
36356
- import { execFileSync as execFileSync5, spawnSync as spawnSync5 } from "node:child_process";
36357
- 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";
36358
36718
  import { createRequire as createRequire3 } from "node:module";
36359
- 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";
36360
36720
  function parseSemver(value) {
36361
36721
  const match = value?.match(/(\d+)\.(\d+)\.(\d+)/);
36362
36722
  return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
@@ -36398,10 +36758,10 @@ function selfVersion() {
36398
36758
  return "unknown";
36399
36759
  }
36400
36760
  function readConfig2(path) {
36401
- if (!existsSync28(path))
36761
+ if (!existsSync29(path))
36402
36762
  return {};
36403
36763
  try {
36404
- const parsed = import_comment_json7.parse(readFileSync17(path, "utf-8"));
36764
+ const parsed = import_comment_json7.parse(readFileSync18(path, "utf-8"));
36405
36765
  return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? {} : { error: "top level is not an object" };
36406
36766
  } catch (error) {
36407
36767
  return { error: error instanceof Error ? error.message : String(error) };
@@ -36411,7 +36771,7 @@ function pluginDeclaresOmp(path) {
36411
36771
  if (!path)
36412
36772
  return null;
36413
36773
  try {
36414
- const pkg = JSON.parse(readFileSync17(join24(path, "package.json"), "utf-8"));
36774
+ const pkg = JSON.parse(readFileSync18(join24(path, "package.json"), "utf-8"));
36415
36775
  return Array.isArray(pkg.omp?.extensions) || Array.isArray(pkg.pi?.extensions);
36416
36776
  } catch {
36417
36777
  return null;
@@ -36482,8 +36842,8 @@ async function runHealthChecks(options) {
36482
36842
  if (!reportedAgentDir.ok) {
36483
36843
  add(results, "warn", "Could not verify OMP active agent directory");
36484
36844
  } else {
36485
- const reportedPath = resolve7(reportedAgentDir.stdout);
36486
- const expectedPath = resolve7(getOmpAgentDir());
36845
+ const reportedPath = resolve8(reportedAgentDir.stdout);
36846
+ const expectedPath = resolve8(getOmpAgentDir());
36487
36847
  if (reportedPath === expectedPath) {
36488
36848
  add(results, "pass", `OMP agent directory resolved to ${getOmpAgentDir()}`);
36489
36849
  } else {
@@ -36492,7 +36852,7 @@ async function runHealthChecks(options) {
36492
36852
  }
36493
36853
  }
36494
36854
  const userConfigPath = getOmpUserConfigPath();
36495
- if (!existsSync28(userConfigPath)) {
36855
+ if (!existsSync29(userConfigPath)) {
36496
36856
  add(results, "warn", `No Magic Context user config at ${userConfigPath}`);
36497
36857
  repairPlan.writeUserConfig = true;
36498
36858
  } else {
@@ -36511,7 +36871,7 @@ async function runHealthChecks(options) {
36511
36871
  const storage = getMagicContextStorageResolution();
36512
36872
  const dbPath = join24(storage.path, "context.db");
36513
36873
  add(results, "info", `Shared storage: ${storage.path} (source: ${storage.source})`);
36514
- if (!existsSync28(dbPath))
36874
+ if (!existsSync29(dbPath))
36515
36875
  add(results, "info", `Shared context DB will be created at ${dbPath}`);
36516
36876
  else {
36517
36877
  let db = null;
@@ -36575,7 +36935,7 @@ function writeDefaultConfig(path) {
36575
36935
  }
36576
36936
  async function repair(plan, deps, prompts, cwd) {
36577
36937
  let fixed = 0;
36578
- if (plan.writeUserConfig && !existsSync28(getOmpUserConfigPath())) {
36938
+ if (plan.writeUserConfig && !existsSync29(getOmpUserConfigPath())) {
36579
36939
  writeDefaultConfig(getOmpUserConfigPath());
36580
36940
  prompts.log.success(`Wrote default Magic Context config to ${getOmpUserConfigPath()}`);
36581
36941
  fixed += 1;
@@ -36732,7 +37092,7 @@ var init_doctor_omp = __esm(async () => {
36732
37092
  now: () => new Date,
36733
37093
  inspectMagicContextLogs,
36734
37094
  execFileSync: execFileSync5,
36735
- spawnSync: spawnSync5
37095
+ spawnSync: spawnSync6
36736
37096
  };
36737
37097
  });
36738
37098
 
@@ -37632,12 +37992,12 @@ function listShadowBackfillStalls(db, projectIdentity) {
37632
37992
  var SHADOW_BACKFILL_PROVENANCE_KEY = "_magicContextShadowBackfill";
37633
37993
 
37634
37994
  // ../plugin/src/shared/auto-update-provenance.ts
37635
- import { existsSync as existsSync29, readFileSync as readFileSync18 } from "node:fs";
37995
+ import { existsSync as existsSync30, readFileSync as readFileSync19 } from "node:fs";
37636
37996
  function readAutoUpdateCheckState(path) {
37637
- if (!existsSync29(path))
37997
+ if (!existsSync30(path))
37638
37998
  return null;
37639
37999
  try {
37640
- const value = JSON.parse(readFileSync18(path, "utf-8"));
38000
+ const value = JSON.parse(readFileSync19(path, "utf-8"));
37641
38001
  if (!value || typeof value !== "object" || Array.isArray(value))
37642
38002
  return null;
37643
38003
  const raw = value;
@@ -37665,9 +38025,9 @@ var init_auto_update_provenance = () => {};
37665
38025
  // ../plugin/src/shared/tui-config.ts
37666
38026
  import {
37667
38027
  chmodSync as chmodSync5,
37668
- existsSync as existsSync30,
38028
+ existsSync as existsSync31,
37669
38029
  mkdirSync as mkdirSync9,
37670
- readFileSync as readFileSync19,
38030
+ readFileSync as readFileSync20,
37671
38031
  renameSync as renameSync6,
37672
38032
  statSync as statSync13,
37673
38033
  writeFileSync as writeFileSync6
@@ -37715,9 +38075,9 @@ function resolveTuiConfigPath(configDirOverride) {
37715
38075
  const configDir = configDirOverride ?? getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
37716
38076
  const jsoncPath = join25(configDir, "tui.jsonc");
37717
38077
  const jsonPath = join25(configDir, "tui.json");
37718
- if (existsSync30(jsoncPath))
38078
+ if (existsSync31(jsoncPath))
37719
38079
  return jsoncPath;
37720
- if (existsSync30(jsonPath))
38080
+ if (existsSync31(jsonPath))
37721
38081
  return jsonPath;
37722
38082
  return jsoncPath;
37723
38083
  }
@@ -37725,8 +38085,8 @@ function ensureTuiPluginEntry(options = {}) {
37725
38085
  try {
37726
38086
  const configPath = resolveTuiConfigPath(options.configDir);
37727
38087
  let config = {};
37728
- if (existsSync30(configPath)) {
37729
- const raw = readFileSync19(configPath, "utf-8");
38088
+ if (existsSync31(configPath)) {
38089
+ const raw = readFileSync20(configPath, "utf-8");
37730
38090
  config = import_comment_json8.parse(raw) ?? {};
37731
38091
  }
37732
38092
  const plugins = Array.isArray(config.plugin) ? [...config.plugin] : [];
@@ -37778,7 +38138,7 @@ var init_tui_config = __esm(() => {
37778
38138
  });
37779
38139
 
37780
38140
  // src/lib/diagnostics-opencode.ts
37781
- 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";
37782
38142
  import { createRequire as createRequire4 } from "node:module";
37783
38143
  import { join as join26 } from "node:path";
37784
38144
  function getSelfVersion() {
@@ -37793,29 +38153,52 @@ function getSelfVersion() {
37793
38153
  }
37794
38154
  return "unknown";
37795
38155
  }
37796
- function getPluginCacheInfo() {
37797
- 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;
37798
38186
  let cached;
37799
- for (const installedPkgPath of getOpenCodePluginPackageJsonPaths()) {
37800
- try {
37801
- if (existsSync31(installedPkgPath)) {
37802
- const pkg = JSON.parse(readFileSync20(installedPkgPath, "utf-8"));
37803
- cached = typeof pkg.version === "string" ? pkg.version : undefined;
37804
- if (cached)
37805
- break;
37806
- }
37807
- } catch {
37808
- cached = undefined;
37809
- }
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;
37810
38193
  }
37811
- return { path, cached, latest: getSelfVersion() };
38194
+ return { path, cached, latest: getSelfVersion(), installs };
37812
38195
  }
37813
38196
  function getStorageResolution() {
37814
38197
  return getMagicContextStorageResolution();
37815
38198
  }
37816
38199
  function fileSize(path) {
37817
38200
  try {
37818
- return existsSync31(path) ? statSync14(path).size : 0;
38201
+ return existsSync32(path) ? statSync14(path).size : 0;
37819
38202
  } catch {
37820
38203
  return 0;
37821
38204
  }
@@ -37827,10 +38210,10 @@ function sanitizeValue(value) {
37827
38210
  return sanitizeConfigValue(value);
37828
38211
  }
37829
38212
  function readConfig3(path) {
37830
- if (!existsSync31(path))
38213
+ if (!existsSync32(path))
37831
38214
  return { value: null };
37832
38215
  try {
37833
- const raw = readFileSync20(path, "utf-8");
38216
+ const raw = readFileSync21(path, "utf-8");
37834
38217
  const value = import_comment_json9.parse(raw);
37835
38218
  return { value };
37836
38219
  } catch (error) {
@@ -37838,9 +38221,9 @@ function readConfig3(path) {
37838
38221
  }
37839
38222
  }
37840
38223
  function configHasPluginEntry(config) {
37841
- const plugins = readPluginEntries(config).map(({ entry }) => entry);
38224
+ const plugins = readPluginEntries(config).map(({ entry }) => pluginEntryPackage(entry));
37842
38225
  return plugins.some((entry) => {
37843
- if (typeof entry !== "string")
38226
+ if (entry === null)
37844
38227
  return false;
37845
38228
  if (entry === OPENCODE_PLUGIN_NAME)
37846
38229
  return true;
@@ -37855,7 +38238,7 @@ function configHasPluginEntry(config) {
37855
38238
  }
37856
38239
  function parseHistorianDumpMeta(path) {
37857
38240
  try {
37858
- const xml = readFileSync20(path, "utf-8");
38241
+ const xml = readFileSync21(path, "utf-8");
37859
38242
  const parsed = parseCompartmentOutput(xml);
37860
38243
  const factCountByCategory = {};
37861
38244
  for (const fact of parsed.facts) {
@@ -37888,10 +38271,10 @@ function parseHistorianDumpMeta(path) {
37888
38271
  }
37889
38272
  }
37890
38273
  function listDumpsInDir(dir, limit) {
37891
- if (!existsSync31(dir))
38274
+ if (!existsSync32(dir))
37892
38275
  return { count: 0, recent: [] };
37893
38276
  try {
37894
- const entries = readdirSync4(dir).filter((name) => name.endsWith(".xml")).map((name) => {
38277
+ const entries = readdirSync5(dir).filter((name) => name.endsWith(".xml")).map((name) => {
37895
38278
  const stat = statSync14(join26(dir, name));
37896
38279
  return {
37897
38280
  name,
@@ -38040,7 +38423,7 @@ async function collectRecentSessions(resolution, hostGeneration) {
38040
38423
  }
38041
38424
  async function collectHistorianFailures(storageDirPath) {
38042
38425
  const contextDbPath = join26(storageDirPath, "context.db");
38043
- if (!existsSync31(contextDbPath))
38426
+ if (!existsSync32(contextDbPath))
38044
38427
  return [];
38045
38428
  if (typeof globalThis.Bun === "undefined") {
38046
38429
  return [];
@@ -38074,7 +38457,7 @@ async function collectHistorianFailures(storageDirPath) {
38074
38457
  }
38075
38458
  async function collectHistorianRuns(storageDirPath) {
38076
38459
  const contextDbPath = join26(storageDirPath, "context.db");
38077
- if (!existsSync31(contextDbPath))
38460
+ if (!existsSync32(contextDbPath))
38078
38461
  return [];
38079
38462
  if (typeof globalThis.Bun === "undefined")
38080
38463
  return [];
@@ -38176,15 +38559,15 @@ async function collectDiagnostics() {
38176
38559
  opencodeConfigHasPlugin: configHasPluginEntry(opencodeConfig.value),
38177
38560
  tuiConfigHasPlugin: configHasPluginEntry(tuiConfig.value),
38178
38561
  magicContextConfig: {
38179
- exists: existsSync31(configPaths.magicContextConfig),
38562
+ exists: existsSync32(configPaths.magicContextConfig),
38180
38563
  ...magicContextConfig.error ? { parseError: magicContextConfig.error } : {},
38181
38564
  flags: sanitizeValue(magicContextConfig.value ?? {}) ?? {}
38182
38565
  },
38183
- pluginCache: getPluginCacheInfo(),
38566
+ pluginCache: collectOpenCodePluginCacheReport(hostGeneration, opencodeConfig.value),
38184
38567
  storageDir: {
38185
38568
  path: storageDirPath,
38186
38569
  source: storageResolution.source,
38187
- exists: existsSync31(storageDirPath),
38570
+ exists: existsSync32(storageDirPath),
38188
38571
  contextDbSizeBytes: fileSize(contextDbPath)
38189
38572
  },
38190
38573
  openCodeDatabase: {
@@ -38231,7 +38614,12 @@ function renderDiagnosticsMarkdown(report) {
38231
38614
  const pluginCache = {
38232
38615
  path: sanitizeString(report.pluginCache.path),
38233
38616
  cached: report.pluginCache.cached ?? null,
38234
- 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
+ }))
38235
38623
  };
38236
38624
  const storage = {
38237
38625
  path: sanitizeString(report.storageDir.path),
@@ -38347,6 +38735,7 @@ var init_diagnostics_opencode = __esm(() => {
38347
38735
  init_conflict_detector();
38348
38736
  init_data_path();
38349
38737
  init_opencode_db_path();
38738
+ init_opencode();
38350
38739
  init_log_lines();
38351
38740
  init_opencode_detect();
38352
38741
  init_opencode_helpers();
@@ -38410,8 +38799,8 @@ var init_embedding_local = __esm(() => {
38410
38799
  });
38411
38800
 
38412
38801
  // src/lib/embedding-runtime.ts
38413
- import { spawnSync as spawnSync6 } from "node:child_process";
38414
- 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";
38415
38804
  import { createRequire as createRequire5 } from "node:module";
38416
38805
  import { dirname as dirname16, join as join27, sep } from "node:path";
38417
38806
  function describeError(error) {
@@ -38420,7 +38809,7 @@ function describeError(error) {
38420
38809
  return typeof code === "string" && code.length > 0 ? `${code}: ${message}` : message;
38421
38810
  }
38422
38811
  function runOnnxRuntimeNodeLoadProbeChild(packageDir) {
38423
- return spawnSync6(process.execPath, ["-e", ONNX_RUNTIME_NODE_LOAD_PROBE_SCRIPT], {
38812
+ return spawnSync7(process.execPath, ["-e", ONNX_RUNTIME_NODE_LOAD_PROBE_SCRIPT], {
38424
38813
  encoding: "utf8",
38425
38814
  env: { ...process.env, [ONNX_LOAD_PROBE_PACKAGE_DIR_ENV]: packageDir },
38426
38815
  stdio: ["ignore", "pipe", "pipe"],
@@ -38558,7 +38947,7 @@ function expectedBinaryRelPath(platform, arch) {
38558
38947
  }
38559
38948
  function onnxRuntimeNodeVersion(packageDir) {
38560
38949
  try {
38561
- const parsed = JSON.parse(readFileSync21(join27(packageDir, "package.json"), "utf8"));
38950
+ const parsed = JSON.parse(readFileSync22(join27(packageDir, "package.json"), "utf8"));
38562
38951
  return typeof parsed.version === "string" ? parsed.version : undefined;
38563
38952
  } catch {
38564
38953
  return;
@@ -38607,7 +38996,7 @@ function formatLocalEmbeddingRuntimeWasmSelected(status) {
38607
38996
  function requireNodeWasmBundle(probe, candidates) {
38608
38997
  if (probe.state === "failed")
38609
38998
  return probe;
38610
- const bundlePath = candidates.find((candidate) => existsSync32(candidate));
38999
+ const bundlePath = candidates.find((candidate) => existsSync33(candidate));
38611
39000
  return bundlePath ? probe : {
38612
39001
  state: "failed",
38613
39002
  reason: `functional Node WASM Transformers bundle is missing (checked ${candidates.join(", ")})`
@@ -38632,7 +39021,7 @@ function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform,
38632
39021
  }
38633
39022
  const packageDir = join27(installRoot, "node_modules", "onnxruntime-node");
38634
39023
  let native;
38635
- if (!existsSync32(join27(packageDir, "package.json"))) {
39024
+ if (!existsSync33(join27(packageDir, "package.json"))) {
38636
39025
  native = { state: "package-missing", packageDir };
38637
39026
  } else {
38638
39027
  const rel = expectedBinaryRelPath(platform, arch);
@@ -38643,7 +39032,7 @@ function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform,
38643
39032
  };
38644
39033
  } else {
38645
39034
  const binaryPath = join27(packageDir, rel);
38646
- native = existsSync32(binaryPath) ? probeOnnxRuntimeNodeLoad(packageDir) ?? { state: "ok", binaryPath } : {
39035
+ native = existsSync33(binaryPath) ? probeOnnxRuntimeNodeLoad(packageDir) ?? { state: "ok", binaryPath } : {
38647
39036
  state: "binary-missing",
38648
39037
  packageDir,
38649
39038
  expectedBinary: binaryPath,
@@ -38654,7 +39043,7 @@ function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform,
38654
39043
  return withWasmFallback(native, () => probeWasmRuntimeAt(installRoot));
38655
39044
  }
38656
39045
  function checkLocalEmbeddingRuntime(installRoots, platform = process.platform, arch = process.arch, runtimePreference = "auto", host) {
38657
- const existing = installRoots.filter((root) => existsSync32(root));
39046
+ const existing = installRoots.filter((root) => existsSync33(root));
38658
39047
  if (existing.length === 0) {
38659
39048
  return {
38660
39049
  state: "unknown",
@@ -38701,7 +39090,7 @@ function probeWasmRuntimeByResolution(pluginDir) {
38701
39090
  }
38702
39091
  }
38703
39092
  function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.platform, arch = process.arch, runtimePreference = "auto", host) {
38704
- if (!existsSync32(join27(pluginDir, "package.json"))) {
39093
+ if (!existsSync33(join27(pluginDir, "package.json"))) {
38705
39094
  return { state: "unknown", reason: "plugin package dir not found" };
38706
39095
  }
38707
39096
  const selectedRuntime = resolveLocalEmbeddingRuntime(runtimePreference, host);
@@ -38743,7 +39132,7 @@ function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.pl
38743
39132
  native = probeOnnxRuntimeNodeLoad(onnxDir) ?? { state: "ok", binaryPath: onnxDir };
38744
39133
  } else {
38745
39134
  const binaryPath = join27(onnxDir, rel);
38746
- native = existsSync32(binaryPath) ? probeOnnxRuntimeNodeLoad(onnxDir) ?? { state: "ok", binaryPath } : {
39135
+ native = existsSync33(binaryPath) ? probeOnnxRuntimeNodeLoad(onnxDir) ?? { state: "ok", binaryPath } : {
38747
39136
  state: "binary-missing",
38748
39137
  packageDir: onnxDir,
38749
39138
  expectedBinary: binaryPath,
@@ -39282,6 +39671,7 @@ var init_constants2 = __esm(() => {
39282
39671
  USER_OPENCODE_CONFIG = join29(getOpenCodeConfigRoot(), "opencode.json");
39283
39672
  USER_OPENCODE_CONFIG_JSONC = join29(getOpenCodeConfigRoot(), "opencode.jsonc");
39284
39673
  });
39674
+
39285
39675
  // ../plugin/src/hooks/auto-update-checker/types.ts
39286
39676
  var NpmPackageEnvelopeSchema, OpencodePluginTupleSchema, OpencodeConfigSchema, PackageJsonSchema;
39287
39677
  var init_types = __esm(() => {
@@ -39303,14 +39693,14 @@ var init_types = __esm(() => {
39303
39693
  // ../plugin/src/hooks/auto-update-checker/checker.ts
39304
39694
  import {
39305
39695
  accessSync as accessSync2,
39306
- existsSync as existsSync33,
39696
+ existsSync as existsSync34,
39307
39697
  constants as fsConstants,
39308
- readFileSync as readFileSync22,
39698
+ readFileSync as readFileSync23,
39309
39699
  renameSync as renameSync7,
39310
39700
  statSync as statSync15,
39311
39701
  writeFileSync as writeFileSync8
39312
39702
  } from "node:fs";
39313
- 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";
39314
39704
  function warn(message) {
39315
39705
  log3(`WARN: ${message}`);
39316
39706
  }
@@ -39357,9 +39747,9 @@ function getWinningConfig(directory, surface) {
39357
39747
  let winner = null;
39358
39748
  for (const path of getSurfaceConfigPaths(directory, surface)) {
39359
39749
  try {
39360
- if (!existsSync33(path))
39750
+ if (!existsSync34(path))
39361
39751
  continue;
39362
- const parsed = parseJsonConfig(readFileSync22(path, "utf-8"));
39752
+ const parsed = parseJsonConfig(readFileSync23(path, "utf-8"));
39363
39753
  const entries = getPluginEntries(parsed);
39364
39754
  if (entries.some((entry) => entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`))) {
39365
39755
  if (winner) {
@@ -39395,14 +39785,14 @@ var init_checker = __esm(() => {
39395
39785
  });
39396
39786
 
39397
39787
  // src/lib/opencode-plugin-schema-fence.ts
39398
- 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";
39399
39789
  import { join as join31 } from "node:path";
39400
39790
  import { gunzipSync } from "node:zlib";
39401
39791
  function readPackageVersion(packageJsonPath) {
39402
39792
  try {
39403
- if (!existsSync34(packageJsonPath))
39793
+ if (!existsSync35(packageJsonPath))
39404
39794
  return null;
39405
- const packageJson = JSON.parse(readFileSync23(packageJsonPath, "utf-8"));
39795
+ const packageJson = JSON.parse(readFileSync24(packageJsonPath, "utf-8"));
39406
39796
  if (packageJson.name !== OPENCODE_PLUGIN_NAME || typeof packageJson.version !== "string") {
39407
39797
  return null;
39408
39798
  }
@@ -39422,7 +39812,7 @@ function readFenceValue(text) {
39422
39812
  }
39423
39813
  function readFenceFromDist(packageDirectory) {
39424
39814
  const distDirectory = join31(packageDirectory, "dist");
39425
- if (!existsSync34(distDirectory))
39815
+ if (!existsSync35(distDirectory))
39426
39816
  return null;
39427
39817
  const pending = [distDirectory];
39428
39818
  const fenceValues = new Set;
@@ -39431,7 +39821,7 @@ function readFenceFromDist(packageDirectory) {
39431
39821
  if (!directory)
39432
39822
  continue;
39433
39823
  try {
39434
- for (const entry of readdirSync5(directory, { withFileTypes: true })) {
39824
+ for (const entry of readdirSync6(directory, { withFileTypes: true })) {
39435
39825
  const path = join31(directory, entry.name);
39436
39826
  if (entry.isDirectory()) {
39437
39827
  pending.push(path);
@@ -39439,7 +39829,7 @@ function readFenceFromDist(packageDirectory) {
39439
39829
  }
39440
39830
  if (!entry.isFile() || !/\.(?:[cm]?js|ts)$/.test(entry.name))
39441
39831
  continue;
39442
- const fence = readFenceValue(readFileSync23(path, "utf-8"));
39832
+ const fence = readFenceValue(readFileSync24(path, "utf-8"));
39443
39833
  if (fence !== null)
39444
39834
  fenceValues.add(fence);
39445
39835
  }
@@ -39453,7 +39843,7 @@ function findInstalledPluginPackage(cacheDirectory, specifier, requestedVersion)
39453
39843
  const directCacheRoot = join31(cacheDirectory, specifier);
39454
39844
  const candidates = [directCacheRoot];
39455
39845
  try {
39456
- for (const entry of readdirSync5(cacheDirectory, { withFileTypes: true })) {
39846
+ for (const entry of readdirSync6(cacheDirectory, { withFileTypes: true })) {
39457
39847
  if (!entry.isDirectory())
39458
39848
  continue;
39459
39849
  const candidate = join31(cacheDirectory, entry.name);
@@ -39837,22 +40227,22 @@ var init_doctor_harness_relabel = __esm(async () => {
39837
40227
  });
39838
40228
 
39839
40229
  // src/commands/doctor-opencode-cache.ts
39840
- 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";
39841
40231
  function readCachedPluginVersion(pluginCacheDir) {
39842
40232
  try {
39843
40233
  const installedPkgPath = getOpenCodePluginPackageJsonPath(pluginCacheDir);
39844
- if (!existsSync35(installedPkgPath))
40234
+ if (!existsSync36(installedPkgPath))
39845
40235
  return;
39846
- const pkg = JSON.parse(readFileSync24(installedPkgPath, "utf-8"));
40236
+ const pkg = JSON.parse(readFileSync25(installedPkgPath, "utf-8"));
39847
40237
  return typeof pkg.version === "string" ? pkg.version : undefined;
39848
40238
  } catch {
39849
40239
  return;
39850
40240
  }
39851
40241
  }
39852
40242
  async function clearPluginCache(options = {}, deps = {}) {
39853
- const remove = deps.remove ?? ((path) => rmSync3(path, { recursive: true, force: true }));
40243
+ const remove = deps.remove ?? ((path) => rmSync4(path, { recursive: true, force: true }));
39854
40244
  const pluginCacheRoots = getOpenCodePluginCacheRoots();
39855
- const existingRoots = pluginCacheRoots.filter((root) => existsSync35(root));
40245
+ const existingRoots = pluginCacheRoots.filter((root) => existsSync36(root));
39856
40246
  if (existingRoots.length === 0) {
39857
40247
  return { action: "not_found", path: pluginCacheRoots[0] ?? "" };
39858
40248
  }
@@ -39918,6 +40308,177 @@ var init_doctor_opencode_cache = __esm(() => {
39918
40308
  init_opencode_plugin_cache();
39919
40309
  });
39920
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
+
39921
40482
  // src/commands/doctor-store-generation.ts
39922
40483
  function hasColumn(db, table, column) {
39923
40484
  try {
@@ -39973,8 +40534,8 @@ function formatUnresolvedCompartmentSession(session) {
39973
40534
  }
39974
40535
 
39975
40536
  // src/commands/doctor-opencode.ts
39976
- import { spawnSync as spawnSync7 } from "node:child_process";
39977
- 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";
39978
40539
  import { createRequire as createRequire6 } from "node:module";
39979
40540
  import { homedir as homedir16, tmpdir as tmpdir3 } from "node:os";
39980
40541
  import { join as join32 } from "node:path";
@@ -39985,7 +40546,7 @@ function findUndeclaredConfiguredVariants(configured, catalog) {
39985
40546
  return model !== undefined && !Object.hasOwn(model.variants, entry.variant);
39986
40547
  });
39987
40548
  }
39988
- function checkConfiguredVariantCatalog(config, hostGeneration, warn, run = (args, cwd) => spawnSync7("opencode", args, {
40549
+ function checkConfiguredVariantCatalog(config, hostGeneration, warn, run = (args, cwd) => spawnSync8("opencode", args, {
39989
40550
  cwd,
39990
40551
  encoding: "utf8",
39991
40552
  timeout: hostGeneration === "v2" ? 90000 : 45000,
@@ -40031,7 +40592,7 @@ function checkConfiguredVariantCatalog(config, hostGeneration, warn, run = (args
40031
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}.`);
40032
40593
  }
40033
40594
  } finally {
40034
- rmSync4(tempRoot, { recursive: true, force: true });
40595
+ rmSync5(tempRoot, { recursive: true, force: true });
40035
40596
  }
40036
40597
  }
40037
40598
  function parseOpenCodeV2ModelCatalog(output) {
@@ -40150,12 +40711,12 @@ function checkUserMemoriesDreamerCompatibility(mcConfig) {
40150
40711
  return null;
40151
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.';
40152
40713
  }
40153
- async function fetchNpmLatest(pkg, timeoutMs = 5000) {
40714
+ async function fetchNpmLatest(pkg, distTag = "latest", timeoutMs = 5000) {
40154
40715
  try {
40155
40716
  const controller = new AbortController;
40156
40717
  const timer = setTimeout(() => controller.abort(), timeoutMs);
40157
40718
  try {
40158
- const res = await fetch(`https://registry.npmjs.org/${pkg}/latest`, {
40719
+ const res = await fetch(`${resolveNpmRegistryUrl()}/${pkg}/${encodeURIComponent(distTag)}`, {
40159
40720
  signal: controller.signal,
40160
40721
  headers: { Accept: "application/json" }
40161
40722
  });
@@ -40170,6 +40731,10 @@ async function fetchNpmLatest(pkg, timeoutMs = 5000) {
40170
40731
  return null;
40171
40732
  }
40172
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
+ }
40173
40738
  function getSelfVersion2() {
40174
40739
  const req = createRequire6(import.meta.url);
40175
40740
  for (const relPath of ["../../package.json", "../package.json"]) {
@@ -40181,11 +40746,6 @@ function getSelfVersion2() {
40181
40746
  }
40182
40747
  return "0.0.0";
40183
40748
  }
40184
- function isPinnedOpenCodePluginSpecifier(specifier) {
40185
- if (specifier === OPENCODE_PLUGIN_NAME || specifier === OPENCODE_PLUGIN_ENTRY_WITH_VERSION)
40186
- return false;
40187
- return specifier.startsWith(`${OPENCODE_PLUGIN_NAME}@`);
40188
- }
40189
40749
  function describeAutoUpdateStall(specifier, autoUpdateEnabled, storageDir = getMagicContextStorageDir()) {
40190
40750
  if (!autoUpdateEnabled || !isPinnedOpenCodePluginSpecifier(specifier))
40191
40751
  return null;
@@ -40203,10 +40763,10 @@ function getUserNpmrcPath() {
40203
40763
  function collectNpmReleaseAgeWarnings() {
40204
40764
  const ageWarnings = [];
40205
40765
  const npmrcPath = getUserNpmrcPath();
40206
- if (!existsSync36(npmrcPath))
40766
+ if (!existsSync37(npmrcPath))
40207
40767
  return ageWarnings;
40208
40768
  try {
40209
- const npmrc = readFileSync25(npmrcPath, "utf-8");
40769
+ const npmrc = readFileSync26(npmrcPath, "utf-8");
40210
40770
  for (const line of npmrc.split(`
40211
40771
  `)) {
40212
40772
  const trimmed = line.trim();
@@ -40239,15 +40799,15 @@ function compareVersions(a, b) {
40239
40799
  function openBrowser(url) {
40240
40800
  try {
40241
40801
  if (process.platform === "darwin") {
40242
- const child = spawnSync7("open", [url], { stdio: "ignore" });
40802
+ const child = spawnSync8("open", [url], { stdio: "ignore" });
40243
40803
  if (child.status === 0)
40244
40804
  return;
40245
40805
  } else if (process.platform === "linux") {
40246
- const child = spawnSync7("xdg-open", [url], { stdio: "ignore" });
40806
+ const child = spawnSync8("xdg-open", [url], { stdio: "ignore" });
40247
40807
  if (child.status === 0)
40248
40808
  return;
40249
40809
  } else if (process.platform === "win32") {
40250
- const child = spawnSync7("cmd", ["/c", "start", "", url], { stdio: "ignore" });
40810
+ const child = spawnSync8("cmd", ["/c", "start", "", url], { stdio: "ignore" });
40251
40811
  if (child.status === 0)
40252
40812
  return;
40253
40813
  }
@@ -40340,7 +40900,7 @@ function checkLocalEmbeddingRuntimeForDoctor(runtimePreference = "auto") {
40340
40900
  return { issues: 0 };
40341
40901
  }
40342
40902
  async function checkEmbeddingConfig(magicContextConfigPath) {
40343
- if (!existsSync36(magicContextConfigPath)) {
40903
+ if (!existsSync37(magicContextConfigPath)) {
40344
40904
  return checkLocalEmbeddingRuntimeForDoctor();
40345
40905
  }
40346
40906
  let rawText;
@@ -40671,7 +41231,7 @@ async function runDoctor2(options = {}) {
40671
41231
  pass(`OpenCode config: ${paths.opencodeConfig}`);
40672
41232
  }
40673
41233
  let autoUpdateEnabled = true;
40674
- if (existsSync36(paths.magicContextConfig)) {
41234
+ if (existsSync37(paths.magicContextConfig)) {
40675
41235
  pass(`Magic Context config: ${paths.magicContextConfig}`);
40676
41236
  try {
40677
41237
  const raw = loadRawConfigFile({ configPath: paths.magicContextConfig, tier: "user" });
@@ -40707,7 +41267,7 @@ async function runDoctor2(options = {}) {
40707
41267
  warn(`No magic-context.jsonc found — using defaults`);
40708
41268
  log2.info(" Run 'setup' to create one with model recommendations");
40709
41269
  }
40710
- if (existsSync36(paths.magicContextConfig)) {
41270
+ if (existsSync37(paths.magicContextConfig)) {
40711
41271
  try {
40712
41272
  const raw = loadRawConfigFile({ configPath: paths.magicContextConfig, tier: "user" });
40713
41273
  if (!raw)
@@ -40837,59 +41397,35 @@ async function runDoctor2(options = {}) {
40837
41397
  };
40838
41398
  if (paths.opencodeConfigFormat !== "none") {
40839
41399
  try {
40840
- const raw = readFileSync25(paths.opencodeConfig, "utf-8");
41400
+ const raw = readFileSync26(paths.opencodeConfig, "utf-8");
40841
41401
  const config = import_comment_json11.parse(raw);
40842
- 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
+ }
40843
41414
  const allEntries = readPluginEntries(config);
40844
- const found = allEntries.find(({ entry }) => matchesPluginEntry(entry, OPENCODE_PLUGIN_NAME) || isDevPathPluginEntry(entry));
40845
- const targetKey = found?.key ?? registrationKey;
40846
- const rawPlugins = Array.isArray(config?.[targetKey]) ? config[targetKey] : [];
40847
- const existingIdx = found ? found.index : -1;
40848
41415
  if (allEntries.some(({ entry }) => isLocalPathPluginEntry(entry) && String(entry).includes("magic-context") && !isDevPathPluginEntry(entry))) {
40849
41416
  warn("An unverifiable local OpenCode plugin path was ignored because its package name is not Magic Context");
40850
41417
  }
40851
- const configName = paths.opencodeConfigFormat === "jsonc" ? "opencode.jsonc" : "opencode.json";
40852
- const entryAsString = (entry) => {
40853
- if (typeof entry === "string")
40854
- return entry;
40855
- if (Array.isArray(entry) && typeof entry[0] === "string")
40856
- return entry[0];
40857
- return null;
40858
- };
40859
- if (existingIdx >= 0 && entryAsString(rawPlugins[existingIdx]) === OPENCODE_PLUGIN_ENTRY_WITH_VERSION) {
40860
- pass(`Plugin registered in ${configName}`);
40861
- } else if (existingIdx >= 0) {
40862
- const oldEntry = rawPlugins[existingIdx];
40863
- const oldEntryStr = entryAsString(oldEntry) ?? "";
40864
- if (isDevPathPluginEntry(oldEntry)) {
40865
- pass(`Plugin registered in ${configName} (dev path: ${oldEntryStr})`);
40866
- } else {
40867
- const isPinned = isPinnedOpenCodePluginSpecifier(oldEntryStr);
40868
- if (isPinned && !options.force) {
40869
- reportAutoUpdateStall(oldEntryStr);
40870
- warn(`Plugin pinned to ${oldEntryStr} in ${configName} — use 'doctor --force' to upgrade`);
40871
- } else {
40872
- if (Array.isArray(oldEntry) && oldEntry.length >= 1) {
40873
- const replacement = [...oldEntry];
40874
- replacement[0] = OPENCODE_PLUGIN_ENTRY_WITH_VERSION;
40875
- rawPlugins[existingIdx] = replacement;
40876
- } else {
40877
- rawPlugins[existingIdx] = OPENCODE_PLUGIN_ENTRY_WITH_VERSION;
40878
- }
40879
- config[targetKey] = rawPlugins;
40880
- writeFileAtomic(paths.opencodeConfig, `${import_comment_json11.stringify(config, null, 2)}
40881
- `);
40882
- pass(`Upgraded plugin entry in ${configName}: ${oldEntryStr} → ${OPENCODE_PLUGIN_ENTRY_WITH_VERSION}`);
40883
- fixed++;
40884
- }
40885
- }
40886
- } else {
40887
- rawPlugins.push(OPENCODE_PLUGIN_ENTRY_WITH_VERSION);
40888
- 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
+ })) {
40889
41427
  writeFileAtomic(paths.opencodeConfig, `${import_comment_json11.stringify(config, null, 2)}
40890
41428
  `);
40891
- pass(`Added plugin to ${configName}`);
40892
- fixed++;
40893
41429
  }
40894
41430
  } catch {
40895
41431
  warn("Could not parse opencode config to verify plugin entry");
@@ -40930,25 +41466,18 @@ async function runDoctor2(options = {}) {
40930
41466
  pass("Added TUI sidebar plugin to tui.json");
40931
41467
  warn("Restart OpenCode to see the sidebar");
40932
41468
  fixed++;
40933
- } else if (existsSync36(paths.tuiConfig)) {
41469
+ } else if (existsSync37(paths.tuiConfig)) {
40934
41470
  try {
40935
- const tuiRaw = readFileSync25(paths.tuiConfig, "utf-8");
41471
+ const tuiRaw = readFileSync26(paths.tuiConfig, "utf-8");
40936
41472
  const tuiConfig = import_comment_json11.parse(tuiRaw);
40937
41473
  const tuiRawPlugins = Array.isArray(tuiConfig?.plugin) ? tuiConfig.plugin : [];
40938
41474
  const tuiIdx = tuiRawPlugins.findIndex((entry) => matchesPluginEntry(entry, OPENCODE_PLUGIN_NAME) || isDevPathPluginEntry(entry));
40939
41475
  if (tuiRawPlugins.some((entry) => isLocalPathPluginEntry(entry) && String(entry).includes("magic-context") && !isDevPathPluginEntry(entry))) {
40940
41476
  warn("An unverifiable local TUI plugin path was ignored because its package name is not Magic Context");
40941
41477
  }
40942
- const tuiEntryAsString = (entry) => {
40943
- if (typeof entry === "string")
40944
- return entry;
40945
- if (Array.isArray(entry) && typeof entry[0] === "string")
40946
- return entry[0];
40947
- return "";
40948
- };
40949
41478
  if (tuiIdx >= 0) {
40950
41479
  const tuiEntry = tuiRawPlugins[tuiIdx];
40951
- const tuiEntryStr = tuiEntryAsString(tuiEntry);
41480
+ const tuiEntryStr = pluginEntryPackage(tuiEntry) ?? "";
40952
41481
  if (isDevPathPluginEntry(tuiEntry)) {
40953
41482
  pass(`TUI sidebar plugin configured (dev path: ${tuiEntryStr})`);
40954
41483
  } else {
@@ -40957,13 +41486,7 @@ async function runDoctor2(options = {}) {
40957
41486
  reportAutoUpdateStall(tuiEntryStr);
40958
41487
  warn(`TUI plugin pinned to ${tuiEntryStr} — use 'doctor --force' to upgrade`);
40959
41488
  } else if (tuiPinned && options.force) {
40960
- if (Array.isArray(tuiEntry) && tuiEntry.length >= 1) {
40961
- const replacement = [...tuiEntry];
40962
- replacement[0] = OPENCODE_PLUGIN_ENTRY_WITH_VERSION;
40963
- tuiRawPlugins[tuiIdx] = replacement;
40964
- } else {
40965
- tuiRawPlugins[tuiIdx] = OPENCODE_PLUGIN_ENTRY_WITH_VERSION;
40966
- }
41489
+ tuiRawPlugins[tuiIdx] = withPluginEntrySpecifier(tuiEntry, OPENCODE_PLUGIN_ENTRY_WITH_VERSION);
40967
41490
  tuiConfig.plugin = tuiRawPlugins;
40968
41491
  writeFileAtomic(paths.tuiConfig, `${import_comment_json11.stringify(tuiConfig, null, 2)}
40969
41492
  `);
@@ -40983,7 +41506,7 @@ async function runDoctor2(options = {}) {
40983
41506
  fail("Could not create or verify the TUI sidebar config");
40984
41507
  }
40985
41508
  }
40986
- if (existsSync36(paths.magicContextConfig)) {
41509
+ if (existsSync37(paths.magicContextConfig)) {
40987
41510
  try {
40988
41511
  const raw = loadRawConfigFile({ configPath: paths.magicContextConfig, tier: "user" });
40989
41512
  if (!raw)
@@ -41007,7 +41530,7 @@ async function runDoctor2(options = {}) {
41007
41530
  const storage = getMagicContextStorageResolution();
41008
41531
  const dbPath = join32(storage.path, "context.db");
41009
41532
  log2.info(`Shared storage: ${storage.path} (source: ${storage.source})`);
41010
- if (!existsSync36(dbPath)) {
41533
+ if (!existsSync37(dbPath)) {
41011
41534
  log2.info(`Shared context DB not yet created at ${dbPath} (will be created on first run)`);
41012
41535
  } else {
41013
41536
  log2.info(`Shared context DB exists at ${dbPath}`);
@@ -41121,9 +41644,26 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
41121
41644
  log2.info(` Manually delete: ${cacheResult.path}`);
41122
41645
  }
41123
41646
  issues++;
41124
- } else {
41647
+ } else if (hostGeneration !== "v2") {
41125
41648
  pass("Plugin cache clean (no cached version found)");
41126
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++;
41127
41667
  {
41128
41668
  const ageWarnings = collectNpmReleaseAgeWarnings();
41129
41669
  if (ageWarnings.length > 0) {
@@ -41218,6 +41758,9 @@ var init_doctor_opencode = __esm(async () => {
41218
41758
  init_prompts();
41219
41759
  init_redaction2();
41220
41760
  init_doctor_opencode_cache();
41761
+ init_doctor_opencode_plugin_duplicates();
41762
+ init_doctor_opencode_plugin_entry();
41763
+ init_doctor_opencode2_cache();
41221
41764
  await __promiseAll([
41222
41765
  init_storage_db(),
41223
41766
  init_sqlite(),
@@ -41231,7 +41774,7 @@ var init_doctor_opencode = __esm(async () => {
41231
41774
  });
41232
41775
 
41233
41776
  // src/lib/diagnostics-pi.ts
41234
- 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";
41235
41778
  import { createRequire as createRequire7 } from "node:module";
41236
41779
  import { join as join33 } from "node:path";
41237
41780
  function getSelfVersion3() {
@@ -41248,7 +41791,7 @@ function getSelfVersion3() {
41248
41791
  }
41249
41792
  function fileSize2(path) {
41250
41793
  try {
41251
- return existsSync37(path) ? statSync16(path).size : 0;
41794
+ return existsSync38(path) ? statSync16(path).size : 0;
41252
41795
  } catch {
41253
41796
  return 0;
41254
41797
  }
@@ -41260,11 +41803,11 @@ function sanitizeValue2(value) {
41260
41803
  return sanitizeConfigValue(value);
41261
41804
  }
41262
41805
  function readJsonc(path) {
41263
- if (!existsSync37(path))
41806
+ if (!existsSync38(path))
41264
41807
  return { value: {} };
41265
41808
  try {
41266
41809
  return {
41267
- value: import_comment_json12.parse(readFileSync26(path, "utf-8"))
41810
+ value: import_comment_json12.parse(readFileSync27(path, "utf-8"))
41268
41811
  };
41269
41812
  } catch (error) {
41270
41813
  return {
@@ -41280,7 +41823,7 @@ function readConfigDiagnostic(path) {
41280
41823
  const parsed = readJsonc(path);
41281
41824
  return {
41282
41825
  path,
41283
- exists: existsSync37(path),
41826
+ exists: existsSync38(path),
41284
41827
  ...parsed.parseError ? { parseError: parsed.parseError } : {},
41285
41828
  flags: sanitizeValue2(parsed.value)
41286
41829
  };
@@ -41298,10 +41841,10 @@ function reverseSlugToDirectory(slug) {
41298
41841
  }
41299
41842
  function collectPiRecentSessions() {
41300
41843
  const sessionsRoot = getPiSessionsRoot();
41301
- if (!existsSync37(sessionsRoot))
41844
+ if (!existsSync38(sessionsRoot))
41302
41845
  return [];
41303
41846
  try {
41304
- 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);
41305
41848
  const candidates = [];
41306
41849
  for (const slug of slugs) {
41307
41850
  const directory = reverseSlugToDirectory(slug);
@@ -41310,7 +41853,7 @@ function collectPiRecentSessions() {
41310
41853
  const slugDir = join33(sessionsRoot, slug);
41311
41854
  let files;
41312
41855
  try {
41313
- files = readdirSync6(slugDir).filter((name) => name.endsWith(".jsonl"));
41856
+ files = readdirSync7(slugDir).filter((name) => name.endsWith(".jsonl"));
41314
41857
  } catch {
41315
41858
  continue;
41316
41859
  }
@@ -41334,7 +41877,7 @@ function collectPiRecentSessions() {
41334
41877
  }
41335
41878
  function parseHistorianDumpMeta2(path) {
41336
41879
  try {
41337
- const xml = readFileSync26(path, "utf-8");
41880
+ const xml = readFileSync27(path, "utf-8");
41338
41881
  const parsed = parseCompartmentOutput(xml);
41339
41882
  const factCountByCategory = {};
41340
41883
  for (const fact of parsed.facts) {
@@ -41367,10 +41910,10 @@ function parseHistorianDumpMeta2(path) {
41367
41910
  }
41368
41911
  }
41369
41912
  function listDumpsInDir2(dir, limit) {
41370
- if (!existsSync37(dir))
41913
+ if (!existsSync38(dir))
41371
41914
  return { count: 0, recent: [] };
41372
41915
  try {
41373
- const entries = readdirSync6(dir).filter((name) => name.endsWith(".xml")).map((name) => {
41916
+ const entries = readdirSync7(dir).filter((name) => name.endsWith(".xml")).map((name) => {
41374
41917
  const stat = statSync16(join33(dir, name));
41375
41918
  return {
41376
41919
  name,
@@ -41461,7 +42004,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
41461
42004
  piVersion: pi ? getPiVersion(pi.path) : null,
41462
42005
  settings: {
41463
42006
  path: settingsPath,
41464
- exists: existsSync37(settingsPath),
42007
+ exists: existsSync38(settingsPath),
41465
42008
  ...settingsParsed.parseError ? { parseError: settingsParsed.parseError } : {},
41466
42009
  hasMagicContextPackage: hasPiMagicContextPackage(packages),
41467
42010
  packages: sanitizeValue2(packages)
@@ -41478,7 +42021,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
41478
42021
  storageDir: {
41479
42022
  path: storageDirPath,
41480
42023
  source: storageResolution.source,
41481
- exists: existsSync37(storageDirPath),
42024
+ exists: existsSync38(storageDirPath),
41482
42025
  contextDbSizeBytes: fileSize2(dbPath)
41483
42026
  },
41484
42027
  conflicts: {
@@ -41671,8 +42214,8 @@ var init_logs_pi = __esm(() => {
41671
42214
  });
41672
42215
 
41673
42216
  // src/commands/doctor-pi.ts
41674
- import { execFileSync as execFileSync6, spawnSync as spawnSync8 } from "node:child_process";
41675
- 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";
41676
42219
  import { createRequire as createRequire8 } from "node:module";
41677
42220
  import { homedir as homedir17 } from "node:os";
41678
42221
  import { dirname as dirname19, isAbsolute as isAbsolute8, join as join35 } from "node:path";
@@ -41766,7 +42309,7 @@ function summarize(results) {
41766
42309
  function readJsonc2(path) {
41767
42310
  try {
41768
42311
  return {
41769
- value: import_comment_json13.parse(readFileSync27(path, "utf-8"))
42312
+ value: import_comment_json13.parse(readFileSync28(path, "utf-8"))
41770
42313
  };
41771
42314
  } catch (error) {
41772
42315
  return {
@@ -41818,13 +42361,13 @@ function piPluginDirCandidates(packages, cwd) {
41818
42361
  }
41819
42362
  dirs.push(join35(agentDir, "npm", "node_modules", PACKAGE_NAME2));
41820
42363
  dirs.push(join35(cwd, ".pi", "npm", "node_modules", PACKAGE_NAME2));
41821
- return dirs.filter((dir) => existsSync38(join35(dir, "package.json")));
42364
+ return dirs.filter((dir) => existsSync39(join35(dir, "package.json")));
41822
42365
  }
41823
42366
  function projectConfigPath(cwd) {
41824
42367
  return resolveCortexKitProjectConfigPath(cwd);
41825
42368
  }
41826
42369
  function readConfigForEmbedding(path, isProjectConfig) {
41827
- if (!existsSync38(path))
42370
+ if (!existsSync39(path))
41828
42371
  return null;
41829
42372
  try {
41830
42373
  const raw = loadRawConfigFile({
@@ -41925,7 +42468,7 @@ function cacheRoots(cwd) {
41925
42468
  function findPiMagicContextCacheDirs(cwd, expectedVersion, force = false) {
41926
42469
  const found = new Map;
41927
42470
  const visit = (path, depth) => {
41928
- if (depth < 0 || !existsSync38(path))
42471
+ if (depth < 0 || !existsSync39(path))
41929
42472
  return;
41930
42473
  let stat;
41931
42474
  try {
@@ -41936,9 +42479,9 @@ function findPiMagicContextCacheDirs(cwd, expectedVersion, force = false) {
41936
42479
  if (!stat.isDirectory())
41937
42480
  return;
41938
42481
  const packageJson = join35(path, "package.json");
41939
- if (existsSync38(packageJson)) {
42482
+ if (existsSync39(packageJson)) {
41940
42483
  try {
41941
- const pkg = JSON.parse(readFileSync27(packageJson, "utf-8"));
42484
+ const pkg = JSON.parse(readFileSync28(packageJson, "utf-8"));
41942
42485
  const name = typeof pkg.name === "string" ? pkg.name : "";
41943
42486
  const version = typeof pkg.version === "string" ? pkg.version : undefined;
41944
42487
  if (name === PACKAGE_NAME2) {
@@ -41953,7 +42496,7 @@ function findPiMagicContextCacheDirs(cwd, expectedVersion, force = false) {
41953
42496
  }
41954
42497
  let entries = [];
41955
42498
  try {
41956
- entries = readdirSync7(path);
42499
+ entries = readdirSync8(path);
41957
42500
  } catch {
41958
42501
  return;
41959
42502
  }
@@ -42003,7 +42546,7 @@ async function runHealthChecks2(options) {
42003
42546
  }
42004
42547
  const settingsPath = getPiUserExtensionsPath();
42005
42548
  let packages = [];
42006
- if (!existsSync38(settingsPath)) {
42549
+ if (!existsSync39(settingsPath)) {
42007
42550
  add2(results, "fail", `Pi settings not found at ${settingsPath}`);
42008
42551
  repairPlan.addPackageEntry = true;
42009
42552
  } else {
@@ -42027,7 +42570,7 @@ async function runHealthChecks2(options) {
42027
42570
  ["user", userConfigPath, true],
42028
42571
  ["project", projectPath, false]
42029
42572
  ]) {
42030
- if (!existsSync38(path)) {
42573
+ if (!existsSync39(path)) {
42031
42574
  if (required) {
42032
42575
  add2(results, "warn", `No ${label} magic-context.jsonc found at ${path}`);
42033
42576
  if (userConfigMigrationRefused) {
@@ -42069,7 +42612,7 @@ async function runHealthChecks2(options) {
42069
42612
  const storageDir = storage.path;
42070
42613
  const dbPath = join35(storageDir, "context.db");
42071
42614
  add2(results, "info", `Shared storage: ${storageDir} (source: ${storage.source})`);
42072
- const existedBeforeOpen = existsSync38(dbPath);
42615
+ const existedBeforeOpen = existsSync39(dbPath);
42073
42616
  if (existedBeforeOpen)
42074
42617
  add2(results, "pass", `Shared context DB exists at ${dbPath}`);
42075
42618
  else
@@ -42309,7 +42852,7 @@ function repair2(plan, prompts) {
42309
42852
  }
42310
42853
  if (plan.writeUserConfig) {
42311
42854
  const configPath = getPiUserConfigPath();
42312
- if (!existsSync38(configPath)) {
42855
+ if (!existsSync39(configPath)) {
42313
42856
  try {
42314
42857
  writeDefaultMagicContextConfig(configPath);
42315
42858
  prompts.log.success(`Wrote default Magic Context config to ${configPath}`);
@@ -42321,7 +42864,7 @@ function repair2(plan, prompts) {
42321
42864
  }
42322
42865
  for (const path of plan.clearCachePaths) {
42323
42866
  try {
42324
- rmSync5(path, { recursive: true, force: true });
42867
+ rmSync6(path, { recursive: true, force: true });
42325
42868
  prompts.log.success(`Cleared stale Pi extension cache: ${path}`);
42326
42869
  fixed += 1;
42327
42870
  } catch (error) {
@@ -42556,12 +43099,12 @@ var init_doctor_pi = __esm(async () => {
42556
43099
  openExistingContextDatabase,
42557
43100
  now: () => new Date,
42558
43101
  execFileSync: execFileSync6,
42559
- spawnSync: spawnSync8
43102
+ spawnSync: spawnSync9
42560
43103
  };
42561
43104
  });
42562
43105
 
42563
43106
  // src/commands/doctor.ts
42564
- import { existsSync as existsSync39, rmSync as rmSync6 } from "node:fs";
43107
+ import { existsSync as existsSync40, rmSync as rmSync7 } from "node:fs";
42565
43108
  import { join as join36 } from "node:path";
42566
43109
  async function runDoctor4(options) {
42567
43110
  if (options.clear)
@@ -42659,9 +43202,16 @@ async function runClear() {
42659
43202
  }
42660
43203
  const items = [];
42661
43204
  for (const adapter of installed) {
42662
- const cache = adapter.getPluginCacheInfo();
42663
- if (cache.path && cache.exists) {
42664
- 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
+ }
42665
43215
  }
42666
43216
  }
42667
43217
  if (items.length === 0) {
@@ -42670,7 +43220,7 @@ async function runClear() {
42670
43220
  return 0;
42671
43221
  }
42672
43222
  const picks = await selectMany("Select caches to clear:", items.map((item, idx) => ({
42673
- label: `${item.adapter.displayName}: ${formatSize(item.sizeBytes)} — ${item.path}`,
43223
+ label: `${item.adapter.displayName}${item.label ? ` (${item.label})` : ""}: ${formatSize(item.sizeBytes)} — ${item.path}`,
42674
43224
  value: String(idx)
42675
43225
  })));
42676
43226
  if (picks.length === 0) {
@@ -42693,8 +43243,16 @@ async function runClear() {
42693
43243
  const s = spinner2();
42694
43244
  s.start(`Clearing ${item.path}`);
42695
43245
  try {
42696
- if (existsSync39(item.path)) {
42697
- 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 });
42698
43256
  }
42699
43257
  s.stop(`Cleared ${item.path}`);
42700
43258
  } catch (err) {