@cortexkit/aft-opencode 0.26.4 → 0.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1607,10 +1607,10 @@ var require_esprima = __commonJS((exports, module) => {
1607
1607
  }();
1608
1608
  exports2.TaggedTemplateExpression = TaggedTemplateExpression;
1609
1609
  var TemplateElement = function() {
1610
- function TemplateElement2(value, tail) {
1610
+ function TemplateElement2(value, tail2) {
1611
1611
  this.type = syntax_1.Syntax.TemplateElement;
1612
1612
  this.value = value;
1613
- this.tail = tail;
1613
+ this.tail = tail2;
1614
1614
  }
1615
1615
  return TemplateElement2;
1616
1616
  }();
@@ -5450,14 +5450,14 @@ var require_esprima = __commonJS((exports, module) => {
5450
5450
  var terminated = false;
5451
5451
  var start = this.index;
5452
5452
  var head = this.source[start] === "`";
5453
- var tail = false;
5453
+ var tail2 = false;
5454
5454
  var rawOffset = 2;
5455
5455
  ++this.index;
5456
5456
  while (!this.eof()) {
5457
5457
  var ch = this.source[this.index++];
5458
5458
  if (ch === "`") {
5459
5459
  rawOffset = 1;
5460
- tail = true;
5460
+ tail2 = true;
5461
5461
  terminated = true;
5462
5462
  break;
5463
5463
  } else if (ch === "$") {
@@ -5558,7 +5558,7 @@ var require_esprima = __commonJS((exports, module) => {
5558
5558
  value: this.source.slice(start + 1, this.index - rawOffset),
5559
5559
  cooked,
5560
5560
  head,
5561
- tail,
5561
+ tail: tail2,
5562
5562
  lineNumber: this.lineNumber,
5563
5563
  lineStart: this.lineStart,
5564
5564
  start,
@@ -7652,10 +7652,10 @@ var require_stringify = __commonJS((exports, module) => {
7652
7652
  replacer = null;
7653
7653
  indent = EMPTY;
7654
7654
  };
7655
- var join7 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(one, gap)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two, gap)), gap) : EMPTY;
7655
+ var join8 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(one, gap)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two, gap)), gap) : EMPTY;
7656
7656
  var join_content = (inside, value, gap) => {
7657
7657
  const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
7658
- return join7(comment, inside, gap);
7658
+ return join8(comment, inside, gap);
7659
7659
  };
7660
7660
  var stringify_string = (holder, key, value) => {
7661
7661
  const raw = get_raw_string_literal(holder, key);
@@ -7677,13 +7677,13 @@ var require_stringify = __commonJS((exports, module) => {
7677
7677
  if (i !== 0) {
7678
7678
  inside += COMMA;
7679
7679
  }
7680
- const before = join7(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
7680
+ const before = join8(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
7681
7681
  inside += before || LF + deeper_gap;
7682
7682
  inside += stringify(i, value, deeper_gap) || STR_NULL;
7683
7683
  inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
7684
7684
  after_comma = process_comments(value, AFTER(i), deeper_gap);
7685
7685
  }
7686
- inside += join7(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
7686
+ inside += join8(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
7687
7687
  return BRACKET_OPEN + join_content(inside, value, gap) + BRACKET_CLOSE;
7688
7688
  };
7689
7689
  var object_stringify = (value, gap) => {
@@ -7704,13 +7704,13 @@ var require_stringify = __commonJS((exports, module) => {
7704
7704
  inside += COMMA;
7705
7705
  }
7706
7706
  first = false;
7707
- const before = join7(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
7707
+ const before = join8(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
7708
7708
  inside += before || LF + deeper_gap;
7709
7709
  inside += quote(key) + process_comments(value, AFTER_PROP(key), deeper_gap) + COLON + process_comments(value, AFTER_COLON(key), deeper_gap) + SPACE + sv + process_comments(value, AFTER_VALUE(key), deeper_gap);
7710
7710
  after_comma = process_comments(value, AFTER(key), deeper_gap);
7711
7711
  };
7712
7712
  keys.forEach(iteratee);
7713
- inside += join7(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
7713
+ inside += join8(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
7714
7714
  return CURLY_BRACKET_OPEN + join_content(inside, value, gap) + CURLY_BRACKET_CLOSE;
7715
7715
  };
7716
7716
  function stringify(key, holder, gap) {
@@ -7803,10 +7803,9 @@ var require_src2 = __commonJS((exports, module) => {
7803
7803
  });
7804
7804
 
7805
7805
  // src/index.ts
7806
- import { existsSync as existsSync14, mkdirSync as mkdirSync12, readFileSync as readFileSync12, writeFileSync as writeFileSync12 } from "fs";
7806
+ import { existsSync as existsSync15, mkdirSync as mkdirSync13, readFileSync as readFileSync12, writeFileSync as writeFileSync12 } from "fs";
7807
7807
  import { createRequire as createRequire2 } from "module";
7808
- import { homedir as homedir10 } from "os";
7809
- import { join as join21 } from "path";
7808
+ import { join as join22 } from "path";
7810
7809
 
7811
7810
  // ../aft-bridge/dist/active-logger.js
7812
7811
  var ACTIVE_LOGGER_SYMBOL = Symbol.for("aft-bridge-active-logger");
@@ -8831,11 +8830,288 @@ async function fetchLatestTag() {
8831
8830
  clearTimeout(timeout);
8832
8831
  }
8833
8832
  }
8833
+ // ../aft-bridge/dist/migration.js
8834
+ import { spawnSync as spawnSync2 } from "child_process";
8835
+ import { existsSync as existsSync3, mkdirSync as mkdirSync3 } from "fs";
8836
+ import { homedir as homedir4, tmpdir } from "os";
8837
+ import { dirname, join as join4 } from "path";
8838
+
8839
+ // ../aft-bridge/dist/resolver.js
8840
+ import { execSync, spawnSync } from "child_process";
8841
+ import { chmodSync as chmodSync2, copyFileSync, existsSync as existsSync2, mkdirSync as mkdirSync2, renameSync as renameSync2 } from "fs";
8842
+ import { createRequire } from "module";
8843
+ import { homedir as homedir3 } from "os";
8844
+ import { join as join3 } from "path";
8845
+ function readBinaryVersion(binaryPath) {
8846
+ try {
8847
+ const result = spawnSync(binaryPath, ["--version"], {
8848
+ encoding: "utf-8",
8849
+ stdio: ["pipe", "pipe", "pipe"],
8850
+ timeout: 5000
8851
+ });
8852
+ const stdoutVersion = result.stdout?.trim();
8853
+ const stderrVersion = result.stderr?.trim();
8854
+ const rawVersion = stdoutVersion || stderrVersion;
8855
+ if (!rawVersion)
8856
+ return null;
8857
+ return rawVersion.replace(/^aft\s+/, "");
8858
+ } catch {
8859
+ return null;
8860
+ }
8861
+ }
8862
+ function copyToVersionedCache(npmBinaryPath, knownVersion) {
8863
+ try {
8864
+ const version = knownVersion ?? readBinaryVersion(npmBinaryPath);
8865
+ if (!version)
8866
+ return null;
8867
+ const tag = version.startsWith("v") ? version : `v${version}`;
8868
+ const cacheDir = getCacheDir();
8869
+ const versionedDir = join3(cacheDir, tag);
8870
+ const ext = process.platform === "win32" ? ".exe" : "";
8871
+ const cachedPath = join3(versionedDir, `aft${ext}`);
8872
+ if (existsSync2(cachedPath)) {
8873
+ const cachedVersion = readBinaryVersion(cachedPath);
8874
+ if (cachedVersion === version)
8875
+ return cachedPath;
8876
+ warn(`Cached binary at ${cachedPath} reports ${cachedVersion ?? "no version"}, expected ${version}; refreshing from npm package`);
8877
+ }
8878
+ mkdirSync2(versionedDir, { recursive: true });
8879
+ const tmpPath = `${cachedPath}.${process.pid}.${Date.now()}.tmp`;
8880
+ copyFileSync(npmBinaryPath, tmpPath);
8881
+ if (process.platform !== "win32") {
8882
+ chmodSync2(tmpPath, 493);
8883
+ }
8884
+ renameSync2(tmpPath, cachedPath);
8885
+ log(`Copied npm binary to versioned cache: ${cachedPath}`);
8886
+ return cachedPath;
8887
+ } catch (err) {
8888
+ warn(`Failed to copy binary to cache: ${err instanceof Error ? err.message : String(err)}`);
8889
+ return null;
8890
+ }
8891
+ }
8892
+ function normalizeBareVersion(version) {
8893
+ return version.startsWith("v") ? version.slice(1) : version;
8894
+ }
8895
+ function homeDirFromEnv(env) {
8896
+ return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir3();
8897
+ }
8898
+ function cacheDirFromEnv(env) {
8899
+ if (process.platform === "win32") {
8900
+ const base2 = env.LOCALAPPDATA || env.APPDATA || join3(homeDirFromEnv(env), "AppData", "Local");
8901
+ return join3(base2, "aft", "bin");
8902
+ }
8903
+ const base = env.XDG_CACHE_HOME || join3(homeDirFromEnv(env), ".cache");
8904
+ return join3(base, "aft", "bin");
8905
+ }
8906
+ function cachedBinaryPathFromEnv(version, env, ext) {
8907
+ const binaryPath = join3(cacheDirFromEnv(env), version, `aft${ext}`);
8908
+ return existsSync2(binaryPath) ? binaryPath : null;
8909
+ }
8910
+ function isExpectedCachedBinary(binaryPath, expectedVersion) {
8911
+ const expected = normalizeBareVersion(expectedVersion);
8912
+ const actual = readBinaryVersion(binaryPath);
8913
+ if (actual === expected)
8914
+ return true;
8915
+ warn(`Cached binary at ${binaryPath} reports ${actual ?? "no version"}, expected ${expected}; skipping cache candidate`);
8916
+ return false;
8917
+ }
8918
+ function platformKey(platform = process.platform, arch = process.arch) {
8919
+ const archMap = PLATFORM_ARCH_MAP[platform];
8920
+ if (!archMap) {
8921
+ throw new Error(`Unsupported platform: ${platform} (arch: ${arch}). ` + `Supported platforms: ${Object.keys(PLATFORM_ARCH_MAP).join(", ")}`);
8922
+ }
8923
+ const key = archMap[arch];
8924
+ if (!key) {
8925
+ throw new Error(`Unsupported architecture: ${arch} on platform ${platform}. ` + `Supported architectures for ${platform}: ${Object.keys(archMap).join(", ")}`);
8926
+ }
8927
+ return key;
8928
+ }
8929
+ function findBinarySync(expectedVersion) {
8930
+ const ext = process.platform === "win32" ? ".exe" : "";
8931
+ const env = { ...process.env };
8932
+ const pluginVersion = expectedVersion ?? (() => {
8933
+ try {
8934
+ const req = createRequire(import.meta.url);
8935
+ return req("../package.json").version;
8936
+ } catch {
8937
+ return null;
8938
+ }
8939
+ })();
8940
+ if (pluginVersion) {
8941
+ const tag = pluginVersion.startsWith("v") ? pluginVersion : `v${pluginVersion}`;
8942
+ const versionCached = cachedBinaryPathFromEnv(tag, env, ext);
8943
+ if (versionCached && isExpectedCachedBinary(versionCached, pluginVersion))
8944
+ return versionCached;
8945
+ }
8946
+ try {
8947
+ const key = platformKey();
8948
+ const packageBin = `@cortexkit/aft-${key}/bin/aft${ext}`;
8949
+ const req = createRequire(import.meta.url);
8950
+ const resolved = req.resolve(packageBin);
8951
+ if (existsSync2(resolved)) {
8952
+ const npmVersion = readBinaryVersion(resolved);
8953
+ if (npmVersion === null) {
8954
+ warn(`npm platform package binary at ${resolved} did not report a version; skipping (continuing to PATH lookup)`);
8955
+ } else if (pluginVersion && npmVersion !== normalizeBareVersion(pluginVersion)) {
8956
+ warn(`npm platform package binary v${npmVersion} does not match plugin v${pluginVersion}; skipping (continuing to PATH lookup)`);
8957
+ } else {
8958
+ const copied = copyToVersionedCache(resolved, npmVersion);
8959
+ return copied ?? resolved;
8960
+ }
8961
+ }
8962
+ } catch {}
8963
+ try {
8964
+ const whichCmd = process.platform === "win32" ? "where aft" : "which aft";
8965
+ const result = execSync(whichCmd, {
8966
+ encoding: "utf-8",
8967
+ env,
8968
+ stdio: ["pipe", "pipe", "pipe"]
8969
+ }).trim();
8970
+ if (result)
8971
+ return result;
8972
+ } catch {}
8973
+ const cargoPath = join3(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
8974
+ if (existsSync2(cargoPath))
8975
+ return cargoPath;
8976
+ return null;
8977
+ }
8978
+ async function findBinary(expectedVersion) {
8979
+ const syncResult = findBinarySync(expectedVersion);
8980
+ if (syncResult) {
8981
+ log(`Resolved binary: ${syncResult}`);
8982
+ return syncResult;
8983
+ }
8984
+ log("Binary not found locally, attempting auto-download...");
8985
+ const downloaded = await ensureBinary(expectedVersion);
8986
+ if (downloaded)
8987
+ return downloaded;
8988
+ throw new Error([
8989
+ "Could not find the `aft` binary.",
8990
+ "",
8991
+ "Attempted sources:",
8992
+ " - Cache directory (~/.cache/aft/bin/)",
8993
+ " - npm platform package (@cortexkit/aft-<platform>)",
8994
+ " - PATH lookup (which aft)",
8995
+ " - ~/.cargo/bin/aft",
8996
+ " - Auto-download from GitHub releases (failed)",
8997
+ "",
8998
+ "Install it using one of these methods:",
8999
+ " npm install @cortexkit/aft-opencode # installs platform-specific binary via npm",
9000
+ " cargo install agent-file-tools # from crates.io",
9001
+ " cargo build --release # from source (binary at target/release/aft)",
9002
+ "",
9003
+ "Or add the aft directory to your PATH."
9004
+ ].join(`
9005
+ `));
9006
+ }
9007
+
9008
+ // ../aft-bridge/dist/migration.js
9009
+ var TARGET_MARKER = ".migrated_from_legacy";
9010
+ var DEFAULT_TIMEOUT_MS = 30 * 60 * 1000;
9011
+ function dataHome() {
9012
+ if (process.env.XDG_DATA_HOME)
9013
+ return process.env.XDG_DATA_HOME;
9014
+ if (process.platform === "win32") {
9015
+ return process.env.LOCALAPPDATA || process.env.APPDATA || join4(homeDir(), "AppData", "Local");
9016
+ }
9017
+ return join4(homeDir(), ".local", "share");
9018
+ }
9019
+ function homeDir() {
9020
+ if (process.platform === "win32")
9021
+ return process.env.USERPROFILE || process.env.HOME || homedir4();
9022
+ return process.env.HOME || homedir4();
9023
+ }
9024
+ function resolveLegacyStorageRoot(harness) {
9025
+ if (harness === "pi")
9026
+ return join4(homeDir(), ".pi", "agent", "aft");
9027
+ return join4(dataHome(), "opencode", "storage", "plugin", "aft");
9028
+ }
9029
+ function resolveCortexKitStorageRoot() {
9030
+ return join4(dataHome(), "cortexkit", "aft");
9031
+ }
9032
+ function tail(value) {
9033
+ if (!value)
9034
+ return "";
9035
+ return value.split(`
9036
+ `).slice(-20).join(`
9037
+ `).trim();
9038
+ }
9039
+ function spawnErrorLabel(error2) {
9040
+ const code = "code" in error2 ? String(error2.code ?? "") : "";
9041
+ return [code, error2.message].filter(Boolean).join(": ");
9042
+ }
9043
+ function migrationLogPath(newRoot, harness, logger) {
9044
+ const desired = join4(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
9045
+ try {
9046
+ mkdirSync3(dirname(desired), { recursive: true });
9047
+ return desired;
9048
+ } catch (err) {
9049
+ const fallback = join4(tmpdir(), `aft-migration-${harness}-${Date.now()}.jsonl`);
9050
+ logger?.warn?.(`Failed to create AFT migration log directory ${dirname(desired)}: ${err instanceof Error ? err.message : String(err)}. ` + `Using fallback log path ${fallback}.`);
9051
+ return fallback;
9052
+ }
9053
+ }
9054
+ async function ensureStorageMigrated(opts) {
9055
+ const legacyRoot = resolveLegacyStorageRoot(opts.harness);
9056
+ const newRoot = resolveCortexKitStorageRoot();
9057
+ const targetMarker = join4(newRoot, opts.harness, TARGET_MARKER);
9058
+ const info = opts.logger?.info ?? opts.logger?.log;
9059
+ if (existsSync3(targetMarker)) {
9060
+ info?.(`AFT storage already migrated for ${opts.harness}; using ${newRoot}`);
9061
+ return;
9062
+ }
9063
+ if (!existsSync3(legacyRoot)) {
9064
+ info?.(`AFT storage migration skipped for ${opts.harness}: no legacy data at ${legacyRoot}; ` + `using ${newRoot} for fresh install`);
9065
+ return;
9066
+ }
9067
+ const logPath = migrationLogPath(newRoot, opts.harness, opts.logger);
9068
+ const binaryPath = opts.binaryPath ?? await findBinary();
9069
+ const startMs = Date.now();
9070
+ info?.(`AFT storage migration starting for ${opts.harness}: ${legacyRoot} -> ${newRoot} ` + `(binary=${binaryPath}, log=${logPath})`);
9071
+ try {
9072
+ process.stderr.write(`
9073
+ [AFT] Migrating ${opts.harness} storage to ${newRoot}.
9074
+ ` + `[AFT] This may take several minutes for large indexes \u2014 please do not close ${opts.harness === "pi" ? "Pi" : "OpenCode"}.
9075
+ ` + `[AFT] Source: ${legacyRoot}
9076
+ ` + `[AFT] Log: ${logPath}
9077
+
9078
+ `);
9079
+ } catch {}
9080
+ const result = spawnSync2(binaryPath, [
9081
+ "migrate-storage",
9082
+ "--from",
9083
+ legacyRoot,
9084
+ "--to",
9085
+ newRoot,
9086
+ "--harness",
9087
+ opts.harness,
9088
+ "--log",
9089
+ logPath
9090
+ ], {
9091
+ encoding: "utf8",
9092
+ stdio: ["ignore", "pipe", "pipe"],
9093
+ timeout: opts.timeoutMs ?? DEFAULT_TIMEOUT_MS
9094
+ });
9095
+ if (!result.error && result.status === 0) {
9096
+ const elapsedMs = Date.now() - startMs;
9097
+ info?.(`AFT storage migration completed for ${opts.harness} in ${elapsedMs}ms (log=${logPath})`);
9098
+ try {
9099
+ process.stderr.write(`[AFT] Migration complete (${(elapsedMs / 1000).toFixed(1)}s).
9100
+
9101
+ `);
9102
+ } catch {}
9103
+ return;
9104
+ }
9105
+ const detail = result.error ? `spawn error ${spawnErrorLabel(result.error)}` : result.status === null ? `terminated by signal ${result.signal ?? "unknown"}` : `exit ${result.status}`;
9106
+ const stderrTail = tail(result.stderr);
9107
+ const stdoutTail = tail(result.stdout);
9108
+ throw new Error(`AFT storage migration failed (${detail}). ` + `Harness: ${opts.harness}. Legacy: ${legacyRoot}. Target: ${newRoot}. ` + `See log: ${logPath}. ` + `Plugin load aborted to prevent legacy/new state divergence.` + (stderrTail ? ` Stderr tail: ${stderrTail}` : "") + (stdoutTail ? ` Stdout tail: ${stdoutTail}` : ""));
9109
+ }
8834
9110
  // ../aft-bridge/dist/onnx-runtime.js
8835
9111
  import { execFileSync } from "child_process";
8836
9112
  import { createHash as createHash2 } from "crypto";
8837
- import { chmodSync as chmodSync2, closeSync as closeSync2, copyFileSync, createWriteStream as createWriteStream2, existsSync as existsSync2, lstatSync, mkdirSync as mkdirSync2, openSync as openSync2, readdirSync, readFileSync, readlinkSync, realpathSync, rmSync as rmSync2, statSync as statSync2, symlinkSync, unlinkSync as unlinkSync2, writeFileSync } from "fs";
8838
- import { dirname, join as join3, relative, resolve } from "path";
9113
+ import { chmodSync as chmodSync3, closeSync as closeSync2, copyFileSync as copyFileSync2, createWriteStream as createWriteStream2, existsSync as existsSync4, lstatSync, mkdirSync as mkdirSync4, openSync as openSync2, readdirSync, readFileSync, readlinkSync, realpathSync, rmSync as rmSync2, statSync as statSync2, symlinkSync, unlinkSync as unlinkSync2, writeFileSync } from "fs";
9114
+ import { dirname as dirname2, join as join5, relative, resolve } from "path";
8839
9115
  import { Readable as Readable2 } from "stream";
8840
9116
  import { pipeline as pipeline2 } from "stream/promises";
8841
9117
  var ORT_VERSION = "1.24.4";
@@ -8883,8 +9159,8 @@ function getPlatformInfo() {
8883
9159
  if (!platformMap)
8884
9160
  return null;
8885
9161
  const archMap = PLATFORM_ARCH_MAP[process.platform] ?? {};
8886
- const platformKey = archMap[process.arch];
8887
- const ortArch = platformKey ? platformKey.split("-")[1] : process.arch;
9162
+ const platformKey2 = archMap[process.arch];
9163
+ const ortArch = platformKey2 ? platformKey2.split("-")[1] : process.arch;
8888
9164
  return platformMap[ortArch] || null;
8889
9165
  }
8890
9166
  function isOrtAutoDownloadSupported() {
@@ -8901,9 +9177,9 @@ function getManualInstallHint() {
8901
9177
  }
8902
9178
  async function ensureOnnxRuntime(storageDir) {
8903
9179
  const info = getPlatformInfo();
8904
- const ortDir = join3(storageDir, "onnxruntime", ORT_VERSION);
8905
- const libPath = join3(ortDir, info?.libName ?? "libonnxruntime.dylib");
8906
- if (existsSync2(libPath)) {
9180
+ const ortDir = join5(storageDir, "onnxruntime", ORT_VERSION);
9181
+ const libPath = join5(ortDir, info?.libName ?? "libonnxruntime.dylib");
9182
+ if (existsSync4(libPath)) {
8907
9183
  const meta = readOnnxInstalledMeta(ortDir);
8908
9184
  if (meta?.sha256) {
8909
9185
  try {
@@ -8932,9 +9208,9 @@ async function ensureOnnxRuntime(storageDir) {
8932
9208
  warn(`ONNX Runtime auto-download not available for ${process.platform}/${process.arch}. Install manually: ${getManualInstallHint()}`);
8933
9209
  return null;
8934
9210
  }
8935
- const onnxBaseDir = join3(storageDir, "onnxruntime");
8936
- mkdirSync2(onnxBaseDir, { recursive: true });
8937
- const lockPath = join3(onnxBaseDir, ONNX_LOCK_FILE);
9211
+ const onnxBaseDir = join5(storageDir, "onnxruntime");
9212
+ mkdirSync4(onnxBaseDir, { recursive: true });
9213
+ const lockPath = join5(onnxBaseDir, ONNX_LOCK_FILE);
8938
9214
  cleanupAbandonedStagingDirs(onnxBaseDir);
8939
9215
  if (!acquireLock(lockPath)) {
8940
9216
  warn(`ONNX Runtime install already in progress in another process (lock: ${lockPath}). Skipping.`);
@@ -8953,7 +9229,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
8953
9229
  for (const entry of entries) {
8954
9230
  if (!entry.startsWith(`${ORT_VERSION}.tmp.`))
8955
9231
  continue;
8956
- const stagingDir = join3(onnxBaseDir, entry);
9232
+ const stagingDir = join5(onnxBaseDir, entry);
8957
9233
  const parts = entry.split(".");
8958
9234
  const pidStr = parts[parts.length - 2];
8959
9235
  const pid = pidStr ? Number.parseInt(pidStr, 10) : NaN;
@@ -8985,7 +9261,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
8985
9261
  }
8986
9262
  function cleanupIncompleteTargetIfUnowned(ortDir) {
8987
9263
  try {
8988
- if (existsSync2(ortDir) && !existsSync2(join3(ortDir, ONNX_INSTALLED_META_FILE))) {
9264
+ if (existsSync4(ortDir) && !existsSync4(join5(ortDir, ONNX_INSTALLED_META_FILE))) {
8989
9265
  log(`[onnx] removing half-populated install dir ${ortDir} (no meta file)`);
8990
9266
  rmSync2(ortDir, { recursive: true, force: true });
8991
9267
  }
@@ -9006,8 +9282,8 @@ function detectOnnxVersion(libDir, libName) {
9006
9282
  if (match)
9007
9283
  return match[1];
9008
9284
  }
9009
- const base = join3(libDir, libName);
9010
- if (existsSync2(base)) {
9285
+ const base = join5(libDir, libName);
9286
+ if (existsSync4(base)) {
9011
9287
  try {
9012
9288
  const real = realpathSync(base);
9013
9289
  const m = real.match(/\.(\d+\.\d+\.\d+)(?:\.dylib)?$/);
@@ -9043,7 +9319,7 @@ function findSystemOnnxRuntime(libName) {
9043
9319
  searchPaths.push("/usr/lib", "/usr/lib/x86_64-linux-gnu", "/usr/lib/aarch64-linux-gnu", "/usr/local/lib");
9044
9320
  }
9045
9321
  for (const dir of searchPaths) {
9046
- if (!existsSync2(join3(dir, libName)))
9322
+ if (!existsSync4(join5(dir, libName)))
9047
9323
  continue;
9048
9324
  const version = detectOnnxVersion(dir, libName);
9049
9325
  if (version && !isOnnxVersionCompatible(version)) {
@@ -9070,7 +9346,7 @@ async function downloadFileWithCap(url, destPath) {
9070
9346
  if (Number.isFinite(advertised) && advertised > MAX_DOWNLOAD_BYTES2) {
9071
9347
  throw new Error(`Content-Length ${advertised} exceeds max ${MAX_DOWNLOAD_BYTES2}`);
9072
9348
  }
9073
- mkdirSync2(dirname(destPath), { recursive: true });
9349
+ mkdirSync4(dirname2(destPath), { recursive: true });
9074
9350
  let bytesWritten = 0;
9075
9351
  const guard = new TransformStream({
9076
9352
  transform(chunk, transformController) {
@@ -9100,11 +9376,11 @@ function validateExtractedTree(stagingRoot) {
9100
9376
  const walk = (dir) => {
9101
9377
  const entries = readdirSync(dir);
9102
9378
  for (const entry of entries) {
9103
- const fullPath = join3(dir, entry);
9379
+ const fullPath = join5(dir, entry);
9104
9380
  const lst = lstatSync(fullPath);
9105
9381
  if (lst.isSymbolicLink()) {
9106
9382
  const linkTarget = readlinkSync(fullPath);
9107
- const resolvedTarget = resolve(dirname(fullPath), linkTarget);
9383
+ const resolvedTarget = resolve(dirname2(fullPath), linkTarget);
9108
9384
  const rel2 = relative(realRoot, resolvedTarget);
9109
9385
  if (rel2.startsWith("..") || process.platform !== "win32" && rel2.startsWith("/")) {
9110
9386
  throw new Error(`extracted symlink ${fullPath} points outside staging root: ${linkTarget}`);
@@ -9134,8 +9410,8 @@ async function downloadOnnxRuntime(info, targetDir) {
9134
9410
  log(`Downloading ONNX Runtime v${ORT_VERSION} for ${process.platform}/${process.arch}...`);
9135
9411
  const tmpDir = `${targetDir}.tmp.${process.pid}.${Date.now().toString(36)}`;
9136
9412
  try {
9137
- mkdirSync2(tmpDir, { recursive: true });
9138
- const archivePath = join3(tmpDir, `onnxruntime.${info.archiveType}`);
9413
+ mkdirSync4(tmpDir, { recursive: true });
9414
+ const archivePath = join5(tmpDir, `onnxruntime.${info.archiveType}`);
9139
9415
  await downloadFileWithCap(url, archivePath);
9140
9416
  const archiveSha256 = sha256File(archivePath);
9141
9417
  log(`ONNX Runtime archive sha256=${archiveSha256}`);
@@ -9151,16 +9427,16 @@ async function downloadOnnxRuntime(info, targetDir) {
9151
9427
  unlinkSync2(archivePath);
9152
9428
  } catch {}
9153
9429
  validateExtractedTree(tmpDir);
9154
- const extractedDir = join3(tmpDir, info.assetName, "lib");
9155
- if (!existsSync2(extractedDir)) {
9430
+ const extractedDir = join5(tmpDir, info.assetName, "lib");
9431
+ if (!existsSync4(extractedDir)) {
9156
9432
  throw new Error(`Expected directory not found: ${extractedDir}`);
9157
9433
  }
9158
- mkdirSync2(targetDir, { recursive: true });
9434
+ mkdirSync4(targetDir, { recursive: true });
9159
9435
  const libFiles = readdirSync(extractedDir).filter((f) => f.startsWith("libonnxruntime") || f.startsWith("onnxruntime"));
9160
9436
  const realFiles = [];
9161
9437
  const symlinks = [];
9162
9438
  for (const libFile of libFiles) {
9163
- const src = join3(extractedDir, libFile);
9439
+ const src = join5(extractedDir, libFile);
9164
9440
  try {
9165
9441
  const stat = lstatSync(src);
9166
9442
  log(`ORT extract: ${libFile} \u2014 isSymlink=${stat.isSymbolicLink()}, isFile=${stat.isFile()}, size=${stat.size}`);
@@ -9175,7 +9451,7 @@ async function downloadOnnxRuntime(info, targetDir) {
9175
9451
  }
9176
9452
  }
9177
9453
  copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks);
9178
- const libPath = join3(targetDir, info.libName);
9454
+ const libPath = join5(targetDir, info.libName);
9179
9455
  let libHash = null;
9180
9456
  try {
9181
9457
  libHash = sha256File(libPath);
@@ -9197,15 +9473,15 @@ async function downloadOnnxRuntime(info, targetDir) {
9197
9473
  return null;
9198
9474
  }
9199
9475
  }
9200
- function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, copyFile = copyFileSync) {
9476
+ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, copyFile = copyFileSync2) {
9201
9477
  const requiredLibs = new Set([info.libName]);
9202
9478
  for (const libFile of realFiles) {
9203
- const src = join3(extractedDir, libFile);
9204
- const dst = join3(targetDir, libFile);
9479
+ const src = join5(extractedDir, libFile);
9480
+ const dst = join5(targetDir, libFile);
9205
9481
  try {
9206
9482
  copyFile(src, dst);
9207
9483
  if (process.platform !== "win32") {
9208
- chmodSync2(dst, 493);
9484
+ chmodSync3(dst, 493);
9209
9485
  }
9210
9486
  } catch (copyErr) {
9211
9487
  if (requiredLibs.has(libFile)) {
@@ -9216,7 +9492,7 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
9216
9492
  }
9217
9493
  }
9218
9494
  for (const link of symlinks) {
9219
- const dst = join3(targetDir, link.name);
9495
+ const dst = join5(targetDir, link.name);
9220
9496
  try {
9221
9497
  unlinkSync2(dst);
9222
9498
  } catch {}
@@ -9230,8 +9506,8 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
9230
9506
  log(`ORT extract: failed to symlink optional ${link.name}: ${symlinkErr}`);
9231
9507
  }
9232
9508
  }
9233
- const requiredPath = join3(targetDir, info.libName);
9234
- if (!existsSync2(requiredPath)) {
9509
+ const requiredPath = join5(targetDir, info.libName);
9510
+ if (!existsSync4(requiredPath)) {
9235
9511
  rmSync2(targetDir, { recursive: true, force: true });
9236
9512
  throw new Error(`Required ONNX Runtime library missing after install: ${requiredPath}`);
9237
9513
  }
@@ -9257,13 +9533,13 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
9257
9533
  ...sha256 ? { sha256 } : {},
9258
9534
  archiveSha256
9259
9535
  };
9260
- writeFileSync(join3(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
9536
+ writeFileSync(join5(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
9261
9537
  } catch (err) {
9262
9538
  log(`[onnx] failed to write installed-meta in ${installDir}: ${err}`);
9263
9539
  }
9264
9540
  }
9265
9541
  function readOnnxInstalledMeta(installDir) {
9266
- const path = join3(installDir, ONNX_INSTALLED_META_FILE);
9542
+ const path = join5(installDir, ONNX_INSTALLED_META_FILE);
9267
9543
  try {
9268
9544
  if (!statSync2(path).isFile())
9269
9545
  return null;
@@ -9388,6 +9664,7 @@ class BridgePool {
9388
9664
  idleTimeoutMs;
9389
9665
  bridgeOptions;
9390
9666
  configOverrides;
9667
+ projectConfigLoader;
9391
9668
  logger;
9392
9669
  cleanupTimer = null;
9393
9670
  constructor(binaryPath, options = {}, configOverrides = {}) {
@@ -9395,6 +9672,7 @@ class BridgePool {
9395
9672
  this.maxPoolSize = options.maxPoolSize ?? DEFAULT_MAX_POOL_SIZE;
9396
9673
  this.idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
9397
9674
  this.logger = options.logger;
9675
+ this.projectConfigLoader = options.projectConfigLoader;
9398
9676
  this.bridgeOptions = {
9399
9677
  timeoutMs: options.timeoutMs,
9400
9678
  maxRestarts: options.maxRestarts,
@@ -9430,7 +9708,17 @@ class BridgePool {
9430
9708
  if (this.bridges.size >= this.maxPoolSize) {
9431
9709
  this.evictLRU();
9432
9710
  }
9433
- const bridge = new BinaryBridge(this.binaryPath, key, this.bridgeOptions, this.configOverrides);
9711
+ let projectOverrides = {};
9712
+ if (this.projectConfigLoader) {
9713
+ try {
9714
+ projectOverrides = this.projectConfigLoader(key) ?? {};
9715
+ } catch (err) {
9716
+ const message = err instanceof Error ? err.message : String(err);
9717
+ this.error(`projectConfigLoader failed; using global overrides only: ${message}`);
9718
+ }
9719
+ }
9720
+ const mergedOverrides = { ...this.configOverrides, ...projectOverrides };
9721
+ const bridge = new BinaryBridge(this.binaryPath, key, this.bridgeOptions, mergedOverrides);
9434
9722
  this.bridges.set(key, { bridge, lastUsed: Date.now() });
9435
9723
  return bridge;
9436
9724
  }
@@ -9523,196 +9811,28 @@ function normalizeKey(projectRoot) {
9523
9811
  return stripped;
9524
9812
  }
9525
9813
  }
9526
- // ../aft-bridge/dist/resolver.js
9527
- import { execSync, spawnSync } from "child_process";
9528
- import { chmodSync as chmodSync3, copyFileSync as copyFileSync2, existsSync as existsSync3, mkdirSync as mkdirSync3, renameSync as renameSync2 } from "fs";
9529
- import { createRequire } from "module";
9530
- import { homedir as homedir3 } from "os";
9531
- import { join as join4 } from "path";
9532
- function readBinaryVersion(binaryPath) {
9533
- try {
9534
- const result = spawnSync(binaryPath, ["--version"], {
9535
- encoding: "utf-8",
9536
- stdio: ["pipe", "pipe", "pipe"],
9537
- timeout: 5000
9538
- });
9539
- const stdoutVersion = result.stdout?.trim();
9540
- const stderrVersion = result.stderr?.trim();
9541
- const rawVersion = stdoutVersion || stderrVersion;
9542
- if (!rawVersion)
9543
- return null;
9544
- return rawVersion.replace(/^aft\s+/, "");
9545
- } catch {
9546
- return null;
9547
- }
9548
- }
9549
- function copyToVersionedCache(npmBinaryPath, knownVersion) {
9550
- try {
9551
- const version = knownVersion ?? readBinaryVersion(npmBinaryPath);
9552
- if (!version)
9553
- return null;
9554
- const tag = version.startsWith("v") ? version : `v${version}`;
9555
- const cacheDir = getCacheDir();
9556
- const versionedDir = join4(cacheDir, tag);
9557
- const ext = process.platform === "win32" ? ".exe" : "";
9558
- const cachedPath = join4(versionedDir, `aft${ext}`);
9559
- if (existsSync3(cachedPath)) {
9560
- const cachedVersion = readBinaryVersion(cachedPath);
9561
- if (cachedVersion === version)
9562
- return cachedPath;
9563
- warn(`Cached binary at ${cachedPath} reports ${cachedVersion ?? "no version"}, expected ${version}; refreshing from npm package`);
9564
- }
9565
- mkdirSync3(versionedDir, { recursive: true });
9566
- const tmpPath = `${cachedPath}.${process.pid}.${Date.now()}.tmp`;
9567
- copyFileSync2(npmBinaryPath, tmpPath);
9568
- if (process.platform !== "win32") {
9569
- chmodSync3(tmpPath, 493);
9570
- }
9571
- renameSync2(tmpPath, cachedPath);
9572
- log(`Copied npm binary to versioned cache: ${cachedPath}`);
9573
- return cachedPath;
9574
- } catch (err) {
9575
- warn(`Failed to copy binary to cache: ${err instanceof Error ? err.message : String(err)}`);
9576
- return null;
9577
- }
9578
- }
9579
- function normalizeBareVersion(version) {
9580
- return version.startsWith("v") ? version.slice(1) : version;
9581
- }
9582
- function homeDirFromEnv(env) {
9583
- return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir3();
9584
- }
9585
- function cacheDirFromEnv(env) {
9586
- if (process.platform === "win32") {
9587
- const base2 = env.LOCALAPPDATA || env.APPDATA || join4(homeDirFromEnv(env), "AppData", "Local");
9588
- return join4(base2, "aft", "bin");
9589
- }
9590
- const base = env.XDG_CACHE_HOME || join4(homeDirFromEnv(env), ".cache");
9591
- return join4(base, "aft", "bin");
9592
- }
9593
- function cachedBinaryPathFromEnv(version, env, ext) {
9594
- const binaryPath = join4(cacheDirFromEnv(env), version, `aft${ext}`);
9595
- return existsSync3(binaryPath) ? binaryPath : null;
9596
- }
9597
- function isExpectedCachedBinary(binaryPath, expectedVersion) {
9598
- const expected = normalizeBareVersion(expectedVersion);
9599
- const actual = readBinaryVersion(binaryPath);
9600
- if (actual === expected)
9601
- return true;
9602
- warn(`Cached binary at ${binaryPath} reports ${actual ?? "no version"}, expected ${expected}; skipping cache candidate`);
9603
- return false;
9604
- }
9605
- function platformKey(platform = process.platform, arch = process.arch) {
9606
- const archMap = PLATFORM_ARCH_MAP[platform];
9607
- if (!archMap) {
9608
- throw new Error(`Unsupported platform: ${platform} (arch: ${arch}). ` + `Supported platforms: ${Object.keys(PLATFORM_ARCH_MAP).join(", ")}`);
9609
- }
9610
- const key = archMap[arch];
9611
- if (!key) {
9612
- throw new Error(`Unsupported architecture: ${arch} on platform ${platform}. ` + `Supported architectures for ${platform}: ${Object.keys(archMap).join(", ")}`);
9613
- }
9614
- return key;
9615
- }
9616
- function findBinarySync(expectedVersion) {
9617
- const ext = process.platform === "win32" ? ".exe" : "";
9618
- const env = { ...process.env };
9619
- const pluginVersion = expectedVersion ?? (() => {
9620
- try {
9621
- const req = createRequire(import.meta.url);
9622
- return req("../package.json").version;
9623
- } catch {
9624
- return null;
9625
- }
9626
- })();
9627
- if (pluginVersion) {
9628
- const tag = pluginVersion.startsWith("v") ? pluginVersion : `v${pluginVersion}`;
9629
- const versionCached = cachedBinaryPathFromEnv(tag, env, ext);
9630
- if (versionCached && isExpectedCachedBinary(versionCached, pluginVersion))
9631
- return versionCached;
9632
- }
9633
- try {
9634
- const key = platformKey();
9635
- const packageBin = `@cortexkit/aft-${key}/bin/aft${ext}`;
9636
- const req = createRequire(import.meta.url);
9637
- const resolved = req.resolve(packageBin);
9638
- if (existsSync3(resolved)) {
9639
- const npmVersion = readBinaryVersion(resolved);
9640
- if (npmVersion === null) {
9641
- warn(`npm platform package binary at ${resolved} did not report a version; skipping (continuing to PATH lookup)`);
9642
- } else if (pluginVersion && npmVersion !== normalizeBareVersion(pluginVersion)) {
9643
- warn(`npm platform package binary v${npmVersion} does not match plugin v${pluginVersion}; skipping (continuing to PATH lookup)`);
9644
- } else {
9645
- const copied = copyToVersionedCache(resolved, npmVersion);
9646
- return copied ?? resolved;
9647
- }
9648
- }
9649
- } catch {}
9650
- try {
9651
- const whichCmd = process.platform === "win32" ? "where aft" : "which aft";
9652
- const result = execSync(whichCmd, {
9653
- encoding: "utf-8",
9654
- env,
9655
- stdio: ["pipe", "pipe", "pipe"]
9656
- }).trim();
9657
- if (result)
9658
- return result;
9659
- } catch {}
9660
- const cargoPath = join4(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
9661
- if (existsSync3(cargoPath))
9662
- return cargoPath;
9663
- return null;
9664
- }
9665
- async function findBinary(expectedVersion) {
9666
- const syncResult = findBinarySync(expectedVersion);
9667
- if (syncResult) {
9668
- log(`Resolved binary: ${syncResult}`);
9669
- return syncResult;
9670
- }
9671
- log("Binary not found locally, attempting auto-download...");
9672
- const downloaded = await ensureBinary(expectedVersion);
9673
- if (downloaded)
9674
- return downloaded;
9675
- throw new Error([
9676
- "Could not find the `aft` binary.",
9677
- "",
9678
- "Attempted sources:",
9679
- " - Cache directory (~/.cache/aft/bin/)",
9680
- " - npm platform package (@cortexkit/aft-<platform>)",
9681
- " - PATH lookup (which aft)",
9682
- " - ~/.cargo/bin/aft",
9683
- " - Auto-download from GitHub releases (failed)",
9684
- "",
9685
- "Install it using one of these methods:",
9686
- " npm install @cortexkit/aft-opencode # installs platform-specific binary via npm",
9687
- " cargo install agent-file-tools # from crates.io",
9688
- " cargo build --release # from source (binary at target/release/aft)",
9689
- "",
9690
- "Or add the aft directory to your PATH."
9691
- ].join(`
9692
- `));
9693
- }
9694
9814
  // ../aft-bridge/dist/url-fetch.js
9695
9815
  import { createHash as createHash3 } from "crypto";
9696
9816
  import { lookup } from "dns/promises";
9697
- import { existsSync as existsSync4, mkdirSync as mkdirSync4, readdirSync as readdirSync2, readFileSync as readFileSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "fs";
9817
+ import { existsSync as existsSync5, mkdirSync as mkdirSync5, readdirSync as readdirSync2, readFileSync as readFileSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "fs";
9698
9818
  import { isIP } from "net";
9699
- import { join as join5 } from "path";
9819
+ import { join as join6 } from "path";
9700
9820
  import { Agent, fetch as undiciFetch } from "undici";
9701
9821
  var MAX_RESPONSE_BYTES = 10 * 1024 * 1024;
9702
9822
  var CACHE_TTL_MS = 24 * 60 * 60 * 1000;
9703
9823
  var FETCH_TIMEOUT_MS = 30000;
9704
9824
  var MAX_REDIRECTS = 5;
9705
9825
  function cacheDir(storageDir) {
9706
- return join5(storageDir, "url_cache");
9826
+ return join6(storageDir, "url_cache");
9707
9827
  }
9708
9828
  function hashUrl(url) {
9709
9829
  return createHash3("sha256").update(url).digest("hex").slice(0, 16);
9710
9830
  }
9711
9831
  function metaPath(storageDir, hash) {
9712
- return join5(cacheDir(storageDir), `${hash}.meta.json`);
9832
+ return join6(cacheDir(storageDir), `${hash}.meta.json`);
9713
9833
  }
9714
9834
  function contentPath(storageDir, hash, extension) {
9715
- return join5(cacheDir(storageDir), `${hash}${extension}`);
9835
+ return join6(cacheDir(storageDir), `${hash}${extension}`);
9716
9836
  }
9717
9837
  function _isPrivateIpv4(address) {
9718
9838
  const parts = address.split(".").map((part) => Number.parseInt(part, 10));
@@ -9730,9 +9850,9 @@ function expandIpv6(addr) {
9730
9850
  let normalized = addr;
9731
9851
  const lastColon = normalized.lastIndexOf(":");
9732
9852
  if (lastColon !== -1) {
9733
- const tail = normalized.slice(lastColon + 1);
9734
- if (tail.includes(".")) {
9735
- const octets = tail.split(".").map((p) => Number.parseInt(p, 10));
9853
+ const tail2 = normalized.slice(lastColon + 1);
9854
+ if (tail2.includes(".")) {
9855
+ const octets = tail2.split(".").map((p) => Number.parseInt(p, 10));
9736
9856
  if (octets.length !== 4 || octets.some((o) => Number.isNaN(o) || o < 0 || o > 255)) {
9737
9857
  return null;
9738
9858
  }
@@ -9910,15 +10030,15 @@ async function fetchUrlToTempFile(url, storageDir, options = {}) {
9910
10030
  const allowPrivate = options.allowPrivate === true;
9911
10031
  await assertPublicUrl(parsed, allowPrivate, options.lookup);
9912
10032
  const dir = cacheDir(storageDir);
9913
- mkdirSync4(dir, { recursive: true });
10033
+ mkdirSync5(dir, { recursive: true });
9914
10034
  const hash = hashUrl(url);
9915
10035
  const metaFile = metaPath(storageDir, hash);
9916
- if (existsSync4(metaFile)) {
10036
+ if (existsSync5(metaFile)) {
9917
10037
  try {
9918
10038
  const meta2 = JSON.parse(readFileSync2(metaFile, "utf8"));
9919
10039
  const age = Date.now() - meta2.fetchedAt;
9920
10040
  const cached = contentPath(storageDir, hash, meta2.extension);
9921
- if (age < CACHE_TTL_MS && existsSync4(cached)) {
10041
+ if (age < CACHE_TTL_MS && existsSync5(cached)) {
9922
10042
  log(`URL cache hit: ${url} (${Math.round(age / 1000)}s old)`);
9923
10043
  return cached;
9924
10044
  }
@@ -9980,21 +10100,21 @@ async function fetchUrlToTempFile(url, storageDir, options = {}) {
9980
10100
  }
9981
10101
  function cleanupUrlCache(storageDir) {
9982
10102
  const dir = cacheDir(storageDir);
9983
- if (!existsSync4(dir))
10103
+ if (!existsSync5(dir))
9984
10104
  return;
9985
10105
  let removed = 0;
9986
10106
  try {
9987
10107
  for (const entry of readdirSync2(dir)) {
9988
10108
  if (!entry.endsWith(".meta.json"))
9989
10109
  continue;
9990
- const metaFile = join5(dir, entry);
10110
+ const metaFile = join6(dir, entry);
9991
10111
  try {
9992
10112
  const meta = JSON.parse(readFileSync2(metaFile, "utf8"));
9993
10113
  const age = Date.now() - meta.fetchedAt;
9994
10114
  if (age > CACHE_TTL_MS) {
9995
10115
  const hash = entry.slice(0, -".meta.json".length);
9996
10116
  const content = contentPath(storageDir, hash, meta.extension);
9997
- if (existsSync4(content))
10117
+ if (existsSync5(content))
9998
10118
  unlinkSync3(content);
9999
10119
  unlinkSync3(metaFile);
10000
10120
  removed++;
@@ -10366,12 +10486,12 @@ function formatSystemReminder(completions) {
10366
10486
  const bullets = completions.map((completion) => formatCompletion(completion)).join(`
10367
10487
  `);
10368
10488
  const anyTruncated = completions.some((c) => c.output_truncated === true);
10369
- const tail = anyTruncated ? `
10489
+ const tail2 = anyTruncated ? `
10370
10490
 
10371
10491
  For truncated tasks, use bash_status({ taskId: "..." }) to retrieve full output.` : "";
10372
10492
  return `<system-reminder>
10373
10493
  [BACKGROUND BASH COMPLETED]
10374
- ${bullets}${tail}
10494
+ ${bullets}${tail2}
10375
10495
  </system-reminder>`;
10376
10496
  }
10377
10497
  function formatLongRunningReminder(reminders) {
@@ -10626,9 +10746,9 @@ function formatDuration(completion) {
10626
10746
 
10627
10747
  // src/config.ts
10628
10748
  var import_comment_json = __toESM(require_src2(), 1);
10629
- import { existsSync as existsSync5, readFileSync as readFileSync3, renameSync as renameSync3, unlinkSync as unlinkSync4, writeFileSync as writeFileSync3 } from "fs";
10630
- import { homedir as homedir4 } from "os";
10631
- import { join as join7 } from "path";
10749
+ import { existsSync as existsSync6, readFileSync as readFileSync3, renameSync as renameSync3, unlinkSync as unlinkSync4, writeFileSync as writeFileSync3 } from "fs";
10750
+ import { homedir as homedir5 } from "os";
10751
+ import { join as join8 } from "path";
10632
10752
 
10633
10753
  // ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
10634
10754
  var exports_external = {};
@@ -24227,6 +24347,7 @@ var ExperimentalConfigSchema = exports_external.object({
24227
24347
  lsp_ty: exports_external.boolean().optional()
24228
24348
  });
24229
24349
  var AftConfigSchema = exports_external.object({
24350
+ $schema: exports_external.string().optional(),
24230
24351
  format_on_edit: exports_external.boolean().optional(),
24231
24352
  formatter_timeout_secs: exports_external.number().int().min(1).max(600).optional(),
24232
24353
  validate_on_edit: exports_external.enum(["syntax", "full"]).optional(),
@@ -24292,6 +24413,31 @@ function resolveLspConfigForConfigure(config2) {
24292
24413
  }
24293
24414
  return overrides;
24294
24415
  }
24416
+ function resolveProjectOverridesForConfigure(config2) {
24417
+ const overrides = {};
24418
+ if (config2.format_on_edit !== undefined)
24419
+ overrides.format_on_edit = config2.format_on_edit;
24420
+ if (config2.formatter_timeout_secs !== undefined)
24421
+ overrides.formatter_timeout_secs = config2.formatter_timeout_secs;
24422
+ if (config2.validate_on_edit !== undefined)
24423
+ overrides.validate_on_edit = config2.validate_on_edit;
24424
+ if (config2.formatter !== undefined)
24425
+ overrides.formatter = config2.formatter;
24426
+ if (config2.checker !== undefined)
24427
+ overrides.checker = config2.checker;
24428
+ overrides.restrict_to_project_root = config2.restrict_to_project_root ?? false;
24429
+ if (config2.search_index !== undefined)
24430
+ overrides.search_index = config2.search_index;
24431
+ if (config2.semantic_search !== undefined)
24432
+ overrides.semantic_search = config2.semantic_search;
24433
+ Object.assign(overrides, resolveExperimentalConfigForConfigure(config2));
24434
+ Object.assign(overrides, resolveLspConfigForConfigure(config2));
24435
+ if (config2.semantic !== undefined)
24436
+ overrides.semantic = config2.semantic;
24437
+ if (config2.max_callgraph_files !== undefined)
24438
+ overrides.max_callgraph_files = config2.max_callgraph_files;
24439
+ return overrides;
24440
+ }
24295
24441
  function resolveExperimentalConfigForConfigure(config2) {
24296
24442
  const overrides = {};
24297
24443
  if (config2.experimental?.bash?.rewrite !== undefined) {
@@ -24381,7 +24527,7 @@ function migrateRawConfig(rawConfig, configPath, logger) {
24381
24527
  return oldKeys;
24382
24528
  }
24383
24529
  function migrateAftConfigFile(configPath, logger = { log: log2, warn: warn2 }) {
24384
- if (!existsSync5(configPath)) {
24530
+ if (!existsSync6(configPath)) {
24385
24531
  return { migrated: false, oldKeys: [] };
24386
24532
  }
24387
24533
  let tmpPath = null;
@@ -24425,10 +24571,10 @@ ${serialized}` : serialized;
24425
24571
  function detectConfigFile(basePath) {
24426
24572
  const jsoncPath = `${basePath}.jsonc`;
24427
24573
  const jsonPath = `${basePath}.json`;
24428
- if (existsSync5(jsoncPath)) {
24574
+ if (existsSync6(jsoncPath)) {
24429
24575
  return { format: "jsonc", path: jsoncPath };
24430
24576
  }
24431
- if (existsSync5(jsonPath)) {
24577
+ if (existsSync6(jsonPath)) {
24432
24578
  return { format: "json", path: jsonPath };
24433
24579
  }
24434
24580
  return { format: "none", path: jsonPath };
@@ -24461,7 +24607,7 @@ function parseConfigPartially(rawConfig) {
24461
24607
  }
24462
24608
  function loadConfigFromPath(configPath) {
24463
24609
  try {
24464
- if (!existsSync5(configPath)) {
24610
+ if (!existsSync6(configPath)) {
24465
24611
  return null;
24466
24612
  }
24467
24613
  const content = readFileSync3(configPath, "utf-8");
@@ -24605,17 +24751,17 @@ function getOpenCodeConfigDir() {
24605
24751
  if (envDir) {
24606
24752
  return envDir;
24607
24753
  }
24608
- const xdgConfig = process.env.XDG_CONFIG_HOME || join7(homedir4(), ".config");
24609
- return join7(xdgConfig, "opencode");
24754
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join8(homedir5(), ".config");
24755
+ return join8(xdgConfig, "opencode");
24610
24756
  }
24611
24757
  function loadAftConfig(projectDirectory) {
24612
24758
  const configDir = getOpenCodeConfigDir();
24613
- const userBasePath = join7(configDir, "aft");
24759
+ const userBasePath = join8(configDir, "aft");
24614
24760
  migrateAftConfigFile(`${userBasePath}.jsonc`);
24615
24761
  migrateAftConfigFile(`${userBasePath}.json`);
24616
24762
  const userDetected = detectConfigFile(userBasePath);
24617
24763
  const userConfigPath = userDetected.format !== "none" ? userDetected.path : `${userBasePath}.json`;
24618
- const projectBasePath = join7(projectDirectory, ".opencode", "aft");
24764
+ const projectBasePath = join8(projectDirectory, ".opencode", "aft");
24619
24765
  migrateAftConfigFile(`${projectBasePath}.jsonc`);
24620
24766
  migrateAftConfigFile(`${projectBasePath}.json`);
24621
24767
  const projectDetected = detectConfigFile(projectBasePath);
@@ -24640,44 +24786,44 @@ function loadAftConfig(projectDirectory) {
24640
24786
  }
24641
24787
 
24642
24788
  // src/hooks/auto-update-checker/index.ts
24643
- import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync6, renameSync as renameSync4, writeFileSync as writeFileSync6 } from "fs";
24644
- import { dirname as dirname4, join as join11 } from "path";
24789
+ import { existsSync as existsSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync6, renameSync as renameSync4, writeFileSync as writeFileSync6 } from "fs";
24790
+ import { dirname as dirname5, join as join12 } from "path";
24645
24791
 
24646
24792
  // src/hooks/auto-update-checker/cache.ts
24647
24793
  var import_comment_json3 = __toESM(require_src2(), 1);
24648
24794
  import { spawn as spawn2 } from "child_process";
24649
- import { cpSync, existsSync as existsSync7, mkdtempSync, readFileSync as readFileSync5, rmSync as rmSync3, writeFileSync as writeFileSync5 } from "fs";
24650
- import { tmpdir as tmpdir2 } from "os";
24651
- import { basename, dirname as dirname3, join as join10 } from "path";
24795
+ import { cpSync, existsSync as existsSync8, mkdtempSync, readFileSync as readFileSync5, rmSync as rmSync3, writeFileSync as writeFileSync5 } from "fs";
24796
+ import { tmpdir as tmpdir3 } from "os";
24797
+ import { basename, dirname as dirname4, join as join11 } from "path";
24652
24798
 
24653
24799
  // src/hooks/auto-update-checker/checker.ts
24654
24800
  var import_comment_json2 = __toESM(require_src2(), 1);
24655
- import { existsSync as existsSync6, readFileSync as readFileSync4, statSync as statSync3, writeFileSync as writeFileSync4 } from "fs";
24656
- import { homedir as homedir6 } from "os";
24657
- import { dirname as dirname2, isAbsolute, join as join9, resolve as resolve2 } from "path";
24801
+ import { existsSync as existsSync7, readFileSync as readFileSync4, statSync as statSync3, writeFileSync as writeFileSync4 } from "fs";
24802
+ import { homedir as homedir7 } from "os";
24803
+ import { dirname as dirname3, isAbsolute, join as join10, resolve as resolve2 } from "path";
24658
24804
  import { fileURLToPath } from "url";
24659
24805
 
24660
24806
  // src/hooks/auto-update-checker/constants.ts
24661
- import { homedir as homedir5, platform } from "os";
24662
- import { join as join8 } from "path";
24807
+ import { homedir as homedir6, platform } from "os";
24808
+ import { join as join9 } from "path";
24663
24809
  var PACKAGE_NAME = "@cortexkit/aft-opencode";
24664
24810
  var NPM_REGISTRY_URL = "https://registry.npmjs.org";
24665
24811
  var NPM_FETCH_TIMEOUT = 1e4;
24666
24812
  function getOpenCodeCacheRoot() {
24667
24813
  if (platform() === "win32") {
24668
- return join8(process.env.LOCALAPPDATA ?? homedir5(), "opencode");
24814
+ return join9(process.env.LOCALAPPDATA ?? homedir6(), "opencode");
24669
24815
  }
24670
- return join8(homedir5(), ".cache", "opencode");
24816
+ return join9(homedir6(), ".cache", "opencode");
24671
24817
  }
24672
24818
  function getOpenCodeConfigRoot() {
24673
24819
  if (platform() === "win32") {
24674
- return join8(process.env.APPDATA ?? join8(homedir5(), "AppData", "Roaming"), "opencode");
24820
+ return join9(process.env.APPDATA ?? join9(homedir6(), "AppData", "Roaming"), "opencode");
24675
24821
  }
24676
- return join8(process.env.XDG_CONFIG_HOME ?? join8(homedir5(), ".config"), "opencode");
24822
+ return join9(process.env.XDG_CONFIG_HOME ?? join9(homedir6(), ".config"), "opencode");
24677
24823
  }
24678
- var CACHE_DIR = join8(getOpenCodeCacheRoot(), "packages");
24679
- var USER_OPENCODE_CONFIG = join8(getOpenCodeConfigRoot(), "opencode.json");
24680
- var USER_OPENCODE_CONFIG_JSONC = join8(getOpenCodeConfigRoot(), "opencode.jsonc");
24824
+ var CACHE_DIR = join9(getOpenCodeCacheRoot(), "packages");
24825
+ var USER_OPENCODE_CONFIG = join9(getOpenCodeConfigRoot(), "opencode.json");
24826
+ var USER_OPENCODE_CONFIG_JSONC = join9(getOpenCodeConfigRoot(), "opencode.jsonc");
24681
24827
 
24682
24828
  // src/hooks/auto-update-checker/types.ts
24683
24829
  var NpmPackageEnvelopeSchema = exports_external.object({
@@ -24735,8 +24881,8 @@ function extractChannel(version2) {
24735
24881
  }
24736
24882
  function getConfigPaths(directory) {
24737
24883
  return [
24738
- join9(directory, ".opencode", "opencode.json"),
24739
- join9(directory, ".opencode", "opencode.jsonc"),
24884
+ join10(directory, ".opencode", "opencode.json"),
24885
+ join10(directory, ".opencode", "opencode.jsonc"),
24740
24886
  USER_OPENCODE_CONFIG,
24741
24887
  USER_OPENCODE_CONFIG_JSONC
24742
24888
  ];
@@ -24751,12 +24897,12 @@ function resolvePathPluginSpec(spec, configPath) {
24751
24897
  }
24752
24898
  if (isAbsolute(spec) || /^[A-Za-z]:[\\/]/.test(spec))
24753
24899
  return spec;
24754
- return resolve2(dirname2(configPath), spec);
24900
+ return resolve2(dirname3(configPath), spec);
24755
24901
  }
24756
24902
  function getLocalDevPath(directory) {
24757
24903
  for (const configPath of getConfigPaths(directory)) {
24758
24904
  try {
24759
- if (!existsSync6(configPath))
24905
+ if (!existsSync7(configPath))
24760
24906
  continue;
24761
24907
  const rawConfig = parseJsonConfig(readFileSync4(configPath, "utf-8"));
24762
24908
  const plugins = getPluginEntries(rawConfig);
@@ -24780,17 +24926,17 @@ function getLocalDevPath(directory) {
24780
24926
  function findPackageJsonUp(startPath) {
24781
24927
  try {
24782
24928
  const stat = statSync3(startPath);
24783
- let dir = stat.isDirectory() ? startPath : dirname2(startPath);
24929
+ let dir = stat.isDirectory() ? startPath : dirname3(startPath);
24784
24930
  for (let i = 0;i < 10; i++) {
24785
- const pkgPath = join9(dir, "package.json");
24786
- if (existsSync6(pkgPath)) {
24931
+ const pkgPath = join10(dir, "package.json");
24932
+ if (existsSync7(pkgPath)) {
24787
24933
  try {
24788
24934
  const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync4(pkgPath, "utf-8")));
24789
24935
  if (pkg.success && pkg.data.name === PACKAGE_NAME)
24790
24936
  return pkgPath;
24791
24937
  } catch {}
24792
24938
  }
24793
- const parent = dirname2(dir);
24939
+ const parent = dirname3(dir);
24794
24940
  if (parent === dir)
24795
24941
  break;
24796
24942
  dir = parent;
@@ -24814,7 +24960,7 @@ function getLocalDevVersion(directory) {
24814
24960
  }
24815
24961
  function getCurrentRuntimePackageJsonPath(currentModuleUrl = import.meta.url) {
24816
24962
  try {
24817
- return findPackageJsonUp(dirname2(fileURLToPath(currentModuleUrl)));
24963
+ return findPackageJsonUp(dirname3(fileURLToPath(currentModuleUrl)));
24818
24964
  } catch (err) {
24819
24965
  warn2(`[auto-update-checker] Failed to resolve runtime package path: ${String(err)}`);
24820
24966
  return null;
@@ -24823,7 +24969,7 @@ function getCurrentRuntimePackageJsonPath(currentModuleUrl = import.meta.url) {
24823
24969
  function findPluginEntry(directory) {
24824
24970
  for (const configPath of getConfigPaths(directory)) {
24825
24971
  try {
24826
- if (!existsSync6(configPath))
24972
+ if (!existsSync7(configPath))
24827
24973
  continue;
24828
24974
  const rawConfig = parseJsonConfig(readFileSync4(configPath, "utf-8"));
24829
24975
  const plugins = getPluginEntries(rawConfig);
@@ -24843,7 +24989,7 @@ function findPluginEntry(directory) {
24843
24989
  }
24844
24990
  var cachedPackageVersion = null;
24845
24991
  function getSpecCachePackageJsonPath(spec) {
24846
- return join9(CACHE_DIR, spec, "node_modules", PACKAGE_NAME, "package.json");
24992
+ return join10(CACHE_DIR, spec, "node_modules", PACKAGE_NAME, "package.json");
24847
24993
  }
24848
24994
  function getCachedVersion(spec) {
24849
24995
  if (!spec && cachedPackageVersion)
@@ -24852,11 +24998,11 @@ function getCachedVersion(spec) {
24852
24998
  getCurrentRuntimePackageJsonPath(),
24853
24999
  spec ? getSpecCachePackageJsonPath(spec) : null,
24854
25000
  getSpecCachePackageJsonPath(`${PACKAGE_NAME}@latest`),
24855
- join9(homedir6(), ".cache", "opencode", "node_modules", PACKAGE_NAME, "package.json")
25001
+ join10(homedir7(), ".cache", "opencode", "node_modules", PACKAGE_NAME, "package.json")
24856
25002
  ].filter(isString);
24857
25003
  for (const packageJsonPath of candidates) {
24858
25004
  try {
24859
- if (!existsSync6(packageJsonPath))
25005
+ if (!existsSync7(packageJsonPath))
24860
25006
  continue;
24861
25007
  const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync4(packageJsonPath, "utf-8")));
24862
25008
  if (pkg.success && pkg.data.version) {
@@ -24900,17 +25046,17 @@ async function getLatestVersion(channel = "latest", options = {}) {
24900
25046
  // src/hooks/auto-update-checker/cache.ts
24901
25047
  var pendingSnapshots = new Map;
24902
25048
  function createAutoUpdateSnapshot(installDir, packageJsonPath, packageName) {
24903
- const packageDir = join10(installDir, "node_modules", packageName);
24904
- const lockfilePath = join10(installDir, "package-lock.json");
24905
- const tempDir = mkdtempSync(join10(tmpdir2(), "aft-auto-update-"));
24906
- const stagedPackageDir = existsSync7(packageDir) ? join10(tempDir, "package") : null;
25049
+ const packageDir = join11(installDir, "node_modules", packageName);
25050
+ const lockfilePath = join11(installDir, "package-lock.json");
25051
+ const tempDir = mkdtempSync(join11(tmpdir3(), "aft-auto-update-"));
25052
+ const stagedPackageDir = existsSync8(packageDir) ? join11(tempDir, "package") : null;
24907
25053
  if (stagedPackageDir)
24908
25054
  cpSync(packageDir, stagedPackageDir, { recursive: true });
24909
25055
  return {
24910
25056
  packageJsonPath,
24911
- packageJson: existsSync7(packageJsonPath) ? readFileSync5(packageJsonPath, "utf-8") : null,
25057
+ packageJson: existsSync8(packageJsonPath) ? readFileSync5(packageJsonPath, "utf-8") : null,
24912
25058
  lockfilePath,
24913
- lockfile: existsSync7(lockfilePath) ? readFileSync5(lockfilePath, "utf-8") : null,
25059
+ lockfile: existsSync8(lockfilePath) ? readFileSync5(lockfilePath, "utf-8") : null,
24914
25060
  packageDir,
24915
25061
  stagedPackageDir,
24916
25062
  tempDir
@@ -24939,13 +25085,13 @@ function stripPackageNameFromPath(pathValue, packageName) {
24939
25085
  for (const segment of [...packageName.split("/")].reverse()) {
24940
25086
  if (basename(current) !== segment)
24941
25087
  return null;
24942
- current = dirname3(current);
25088
+ current = dirname4(current);
24943
25089
  }
24944
25090
  return current;
24945
25091
  }
24946
25092
  function removeFromPackageLock(installDir, packageName) {
24947
- const lockPath = join10(installDir, "package-lock.json");
24948
- if (!existsSync7(lockPath))
25093
+ const lockPath = join11(installDir, "package-lock.json");
25094
+ if (!existsSync8(lockPath))
24949
25095
  return false;
24950
25096
  try {
24951
25097
  const lock = import_comment_json3.parse(readFileSync5(lockPath, "utf-8"));
@@ -24971,7 +25117,7 @@ function removeFromPackageLock(installDir, packageName) {
24971
25117
  }
24972
25118
  }
24973
25119
  function ensureDependencyVersion(packageJsonPath, packageName, version2) {
24974
- if (!existsSync7(packageJsonPath))
25120
+ if (!existsSync8(packageJsonPath))
24975
25121
  return false;
24976
25122
  try {
24977
25123
  const raw = import_comment_json3.parse(readFileSync5(packageJsonPath, "utf-8"));
@@ -24993,8 +25139,8 @@ function ensureDependencyVersion(packageJsonPath, packageName, version2) {
24993
25139
  }
24994
25140
  }
24995
25141
  function removeInstalledPackage(installDir, packageName) {
24996
- const packageDir = join10(installDir, "node_modules", packageName);
24997
- if (!existsSync7(packageDir))
25142
+ const packageDir = join11(installDir, "node_modules", packageName);
25143
+ if (!existsSync8(packageDir))
24998
25144
  return false;
24999
25145
  rmSync3(packageDir, { recursive: true, force: true });
25000
25146
  log2(`[auto-update-checker] Package removed: ${packageDir}`);
@@ -25002,19 +25148,19 @@ function removeInstalledPackage(installDir, packageName) {
25002
25148
  }
25003
25149
  function resolveInstallContext(runtimePackageJsonPath = getCurrentRuntimePackageJsonPath()) {
25004
25150
  if (runtimePackageJsonPath) {
25005
- const packageDir = dirname3(runtimePackageJsonPath);
25151
+ const packageDir = dirname4(runtimePackageJsonPath);
25006
25152
  const nodeModulesDir = stripPackageNameFromPath(packageDir, PACKAGE_NAME);
25007
25153
  if (nodeModulesDir && basename(nodeModulesDir) === "node_modules") {
25008
- const installDir = dirname3(nodeModulesDir);
25009
- const packageJsonPath = join10(installDir, "package.json");
25010
- if (existsSync7(packageJsonPath))
25154
+ const installDir = dirname4(nodeModulesDir);
25155
+ const packageJsonPath = join11(installDir, "package.json");
25156
+ if (existsSync8(packageJsonPath))
25011
25157
  return { installDir, packageJsonPath };
25012
25158
  }
25013
25159
  return null;
25014
25160
  }
25015
- const legacyPackageJsonPath = join10(dirname3(CACHE_DIR), "package.json");
25016
- if (existsSync7(legacyPackageJsonPath)) {
25017
- return { installDir: dirname3(CACHE_DIR), packageJsonPath: legacyPackageJsonPath };
25161
+ const legacyPackageJsonPath = join11(dirname4(CACHE_DIR), "package.json");
25162
+ if (existsSync8(legacyPackageJsonPath)) {
25163
+ return { installDir: dirname4(CACHE_DIR), packageJsonPath: legacyPackageJsonPath };
25018
25164
  }
25019
25165
  return null;
25020
25166
  }
@@ -25152,8 +25298,8 @@ function claimCheckSlot(storageDir, intervalMs) {
25152
25298
  if (!storageDir)
25153
25299
  return true;
25154
25300
  try {
25155
- const file2 = join11(storageDir, TIMESTAMP_FILENAME);
25156
- if (existsSync8(file2)) {
25301
+ const file2 = join12(storageDir, TIMESTAMP_FILENAME);
25302
+ if (existsSync9(file2)) {
25157
25303
  try {
25158
25304
  const raw = JSON.parse(readFileSync6(file2, "utf-8"));
25159
25305
  const last = typeof raw.lastCheckedMs === "number" ? raw.lastCheckedMs : 0;
@@ -25162,7 +25308,7 @@ function claimCheckSlot(storageDir, intervalMs) {
25162
25308
  }
25163
25309
  } catch {}
25164
25310
  }
25165
- mkdirSync5(dirname4(file2), { recursive: true });
25311
+ mkdirSync6(dirname5(file2), { recursive: true });
25166
25312
  const tmp = `${file2}.tmp.${process.pid}`;
25167
25313
  writeFileSync6(tmp, JSON.stringify({ lastCheckedMs: Date.now() }), "utf-8");
25168
25314
  renameSync4(tmp, file2);
@@ -25253,49 +25399,49 @@ function showToast(ctx, title, message, variant = "info", duration3 = 3000) {
25253
25399
  // src/lsp-auto-install.ts
25254
25400
  import { spawn as spawn3 } from "child_process";
25255
25401
  import { createHash as createHash4 } from "crypto";
25256
- import { createReadStream, mkdirSync as mkdirSync7, readFileSync as readFileSync8, renameSync as renameSync5, rmSync as rmSync4, statSync as statSync5 } from "fs";
25257
- import { join as join14 } from "path";
25402
+ import { createReadStream, mkdirSync as mkdirSync8, readFileSync as readFileSync8, renameSync as renameSync5, rmSync as rmSync4, statSync as statSync5 } from "fs";
25403
+ import { join as join15 } from "path";
25258
25404
 
25259
25405
  // src/lsp-cache.ts
25260
25406
  import {
25261
25407
  closeSync as closeSync3,
25262
- mkdirSync as mkdirSync6,
25408
+ mkdirSync as mkdirSync7,
25263
25409
  openSync as openSync3,
25264
25410
  readFileSync as readFileSync7,
25265
25411
  statSync as statSync4,
25266
25412
  unlinkSync as unlinkSync5,
25267
25413
  writeFileSync as writeFileSync7
25268
25414
  } from "fs";
25269
- import { homedir as homedir7 } from "os";
25270
- import { join as join12 } from "path";
25415
+ import { homedir as homedir8 } from "os";
25416
+ import { join as join13 } from "path";
25271
25417
  function aftCacheBase() {
25272
25418
  const override = process.env.AFT_CACHE_DIR;
25273
25419
  if (override && override.length > 0)
25274
25420
  return override;
25275
25421
  if (process.platform === "win32") {
25276
25422
  const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
25277
- const base2 = localAppData || join12(homedir7(), "AppData", "Local");
25278
- return join12(base2, "aft");
25423
+ const base2 = localAppData || join13(homedir8(), "AppData", "Local");
25424
+ return join13(base2, "aft");
25279
25425
  }
25280
- const base = process.env.XDG_CACHE_HOME || join12(homedir7(), ".cache");
25281
- return join12(base, "aft");
25426
+ const base = process.env.XDG_CACHE_HOME || join13(homedir8(), ".cache");
25427
+ return join13(base, "aft");
25282
25428
  }
25283
25429
  function lspCacheRoot() {
25284
- return join12(aftCacheBase(), "lsp-packages");
25430
+ return join13(aftCacheBase(), "lsp-packages");
25285
25431
  }
25286
25432
  function lspPackageDir(npmPackage) {
25287
- return join12(lspCacheRoot(), encodeURIComponent(npmPackage));
25433
+ return join13(lspCacheRoot(), encodeURIComponent(npmPackage));
25288
25434
  }
25289
25435
  function lspBinaryPath(npmPackage, binary) {
25290
- return join12(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
25436
+ return join13(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
25291
25437
  }
25292
25438
  function lspBinDir(npmPackage) {
25293
- return join12(lspPackageDir(npmPackage), "node_modules", ".bin");
25439
+ return join13(lspPackageDir(npmPackage), "node_modules", ".bin");
25294
25440
  }
25295
25441
  function isInstalled(npmPackage, binary) {
25296
25442
  for (const candidate of lspBinaryCandidates(binary)) {
25297
25443
  try {
25298
- if (statSync4(join12(lspBinDir(npmPackage), candidate)).isFile())
25444
+ if (statSync4(join13(lspBinDir(npmPackage), candidate)).isFile())
25299
25445
  return true;
25300
25446
  } catch {}
25301
25447
  }
@@ -25309,19 +25455,19 @@ function lspBinaryCandidates(binary) {
25309
25455
  var INSTALLED_META_FILE = ".aft-installed";
25310
25456
  function writeInstalledMetaIn(installDir, version2, sha256) {
25311
25457
  try {
25312
- mkdirSync6(installDir, { recursive: true });
25458
+ mkdirSync7(installDir, { recursive: true });
25313
25459
  const meta3 = {
25314
25460
  version: version2,
25315
25461
  installedAt: new Date().toISOString(),
25316
25462
  ...sha256 ? { sha256 } : {}
25317
25463
  };
25318
- writeFileSync7(join12(installDir, INSTALLED_META_FILE), JSON.stringify(meta3), "utf8");
25464
+ writeFileSync7(join13(installDir, INSTALLED_META_FILE), JSON.stringify(meta3), "utf8");
25319
25465
  } catch (err) {
25320
25466
  log2(`[lsp-cache] failed to write installed-meta in ${installDir}: ${err}`);
25321
25467
  }
25322
25468
  }
25323
25469
  function readInstalledMetaIn(installDir) {
25324
- const path2 = join12(installDir, INSTALLED_META_FILE);
25470
+ const path2 = join13(installDir, INSTALLED_META_FILE);
25325
25471
  try {
25326
25472
  if (!statSync4(path2).isFile())
25327
25473
  return null;
@@ -25345,11 +25491,11 @@ function readInstalledMeta(packageKey) {
25345
25491
  return readInstalledMetaIn(lspPackageDir(packageKey));
25346
25492
  }
25347
25493
  function lockPath(npmPackage) {
25348
- return join12(lspPackageDir(npmPackage), ".aft-installing");
25494
+ return join13(lspPackageDir(npmPackage), ".aft-installing");
25349
25495
  }
25350
25496
  var STALE_LOCK_MS2 = 30 * 60 * 1000;
25351
25497
  function acquireInstallLock(lockKey) {
25352
- mkdirSync6(lspPackageDir(lockKey), { recursive: true });
25498
+ mkdirSync7(lspPackageDir(lockKey), { recursive: true });
25353
25499
  const lock = lockPath(lockKey);
25354
25500
  const tryClaim = () => {
25355
25501
  try {
@@ -25452,7 +25598,7 @@ async function withInstallLock(lockKey, task) {
25452
25598
  }
25453
25599
  var VERSION_CHECK_FILE = ".aft-version-check";
25454
25600
  function readVersionCheck(npmPackage) {
25455
- const file2 = join12(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
25601
+ const file2 = join13(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
25456
25602
  try {
25457
25603
  const raw = readFileSync7(file2, "utf8");
25458
25604
  const parsed = JSON.parse(raw);
@@ -25468,8 +25614,8 @@ function readVersionCheck(npmPackage) {
25468
25614
  }
25469
25615
  }
25470
25616
  function writeVersionCheck(npmPackage, latest) {
25471
- mkdirSync6(lspPackageDir(npmPackage), { recursive: true });
25472
- const file2 = join12(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
25617
+ mkdirSync7(lspPackageDir(npmPackage), { recursive: true });
25618
+ const file2 = join13(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
25473
25619
  const record2 = {
25474
25620
  last_checked: new Date().toISOString(),
25475
25621
  latest_eligible: latest
@@ -25617,8 +25763,8 @@ var NPM_LSP_TABLE = [
25617
25763
  ];
25618
25764
 
25619
25765
  // src/lsp-project-relevance.ts
25620
- import { existsSync as existsSync9, readdirSync as readdirSync3 } from "fs";
25621
- import { join as join13 } from "path";
25766
+ import { existsSync as existsSync10, readdirSync as readdirSync3 } from "fs";
25767
+ import { join as join14 } from "path";
25622
25768
  var MAX_WALK_DIRS = 200;
25623
25769
  var MAX_WALK_DEPTH = 4;
25624
25770
  var NOISE_DIRS = new Set([
@@ -25635,7 +25781,7 @@ function hasRootMarker(projectRoot, rootMarkers) {
25635
25781
  if (!rootMarkers)
25636
25782
  return false;
25637
25783
  for (const marker of rootMarkers) {
25638
- if (existsSync9(join13(projectRoot, marker)))
25784
+ if (existsSync10(join14(projectRoot, marker)))
25639
25785
  return true;
25640
25786
  }
25641
25787
  return false;
@@ -25661,7 +25807,7 @@ function relevantExtensionsInProject(projectRoot, extToServer) {
25661
25807
  for (const entry of entries) {
25662
25808
  if (entry.isDirectory()) {
25663
25809
  if (current.depth < MAX_WALK_DEPTH && !NOISE_DIRS.has(entry.name.toLowerCase())) {
25664
- queue.push({ dir: join13(current.dir, entry.name), depth: current.depth + 1 });
25810
+ queue.push({ dir: join14(current.dir, entry.name), depth: current.depth + 1 });
25665
25811
  }
25666
25812
  continue;
25667
25813
  }
@@ -25793,8 +25939,9 @@ function runInstall(spec, version2, cwd, signal) {
25793
25939
  resolve3(false);
25794
25940
  return;
25795
25941
  }
25796
- const child = spawn3("bun", ["add", target, "--cwd", cwd, "--ignore-scripts", "--silent"], {
25797
- stdio: ["ignore", "pipe", "pipe"]
25942
+ const child = spawn3("npm", ["install", "--no-save", "--ignore-scripts", "--silent", target], {
25943
+ stdio: ["ignore", "pipe", "pipe"],
25944
+ cwd
25798
25945
  });
25799
25946
  child.unref();
25800
25947
  let stderrBuf = "";
@@ -25958,10 +26105,10 @@ function sha256OfFileSync(path2) {
25958
26105
  }
25959
26106
  function quarantineCachedNpmInstall(spec, reason) {
25960
26107
  const packageDir = lspPackageDir(spec.npm);
25961
- const dest = join14(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
26108
+ const dest = join15(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
25962
26109
  warn2(`[lsp] tofu_mismatch ${spec.npm}: ${reason}; quarantining ${packageDir} -> ${dest}`);
25963
26110
  try {
25964
- mkdirSync7(join14(dest, ".."), { recursive: true });
26111
+ mkdirSync8(join15(dest, ".."), { recursive: true });
25965
26112
  rmSync4(dest, { recursive: true, force: true });
25966
26113
  renameSync5(packageDir, dest);
25967
26114
  } catch (err) {
@@ -26044,9 +26191,9 @@ import {
26044
26191
  copyFileSync as copyFileSync3,
26045
26192
  createReadStream as createReadStream2,
26046
26193
  createWriteStream as createWriteStream3,
26047
- existsSync as existsSync10,
26194
+ existsSync as existsSync11,
26048
26195
  lstatSync as lstatSync2,
26049
- mkdirSync as mkdirSync8,
26196
+ mkdirSync as mkdirSync9,
26050
26197
  readdirSync as readdirSync4,
26051
26198
  readFileSync as readFileSync9,
26052
26199
  readlinkSync as readlinkSync2,
@@ -26057,7 +26204,7 @@ import {
26057
26204
  unlinkSync as unlinkSync6,
26058
26205
  writeFileSync as writeFileSync8
26059
26206
  } from "fs";
26060
- import { dirname as dirname5, join as join15, relative as relative2, resolve as resolve3 } from "path";
26207
+ import { dirname as dirname6, join as join16, relative as relative2, resolve as resolve3 } from "path";
26061
26208
  import { Readable as Readable3 } from "stream";
26062
26209
  import { pipeline as pipeline3 } from "stream/promises";
26063
26210
 
@@ -26147,26 +26294,26 @@ function detectHostPlatform() {
26147
26294
 
26148
26295
  // src/lsp-github-install.ts
26149
26296
  function ghCacheRoot() {
26150
- return join15(aftCacheBase(), "lsp-binaries");
26297
+ return join16(aftCacheBase(), "lsp-binaries");
26151
26298
  }
26152
26299
  function ghPackageDir(spec) {
26153
- return join15(ghCacheRoot(), spec.id);
26300
+ return join16(ghCacheRoot(), spec.id);
26154
26301
  }
26155
26302
  function ghBinDir(spec) {
26156
- return join15(ghPackageDir(spec), "bin");
26303
+ return join16(ghPackageDir(spec), "bin");
26157
26304
  }
26158
26305
  function ghExtractDir(spec) {
26159
- return join15(ghPackageDir(spec), "extracted");
26306
+ return join16(ghPackageDir(spec), "extracted");
26160
26307
  }
26161
26308
  var INSTALLED_META_FILE2 = ".aft-installed";
26162
26309
  function ghBinaryPath(spec, platform2) {
26163
26310
  const ext = platform2 === "win32" ? ".exe" : "";
26164
- return join15(ghBinDir(spec), `${spec.binary}${ext}`);
26311
+ return join16(ghBinDir(spec), `${spec.binary}${ext}`);
26165
26312
  }
26166
26313
  function isGithubInstalled(spec, platform2) {
26167
26314
  for (const candidate of ghBinaryCandidates(spec, platform2)) {
26168
26315
  try {
26169
- if (statSync6(join15(ghBinDir(spec), candidate)).isFile())
26316
+ if (statSync6(join16(ghBinDir(spec), candidate)).isFile())
26170
26317
  return true;
26171
26318
  } catch {}
26172
26319
  }
@@ -26179,7 +26326,7 @@ function ghBinaryCandidates(spec, platform2) {
26179
26326
  }
26180
26327
  function readGithubInstalledMetaIn(installDir) {
26181
26328
  try {
26182
- const path2 = join15(installDir, INSTALLED_META_FILE2);
26329
+ const path2 = join16(installDir, INSTALLED_META_FILE2);
26183
26330
  if (!statSync6(path2).isFile())
26184
26331
  return null;
26185
26332
  const parsed = JSON.parse(readFileSync9(path2, "utf8"));
@@ -26198,7 +26345,7 @@ function readGithubInstalledMetaIn(installDir) {
26198
26345
  }
26199
26346
  function writeGithubInstalledMetaIn(installDir, version2, binarySha256, archiveSha256) {
26200
26347
  try {
26201
- mkdirSync8(installDir, { recursive: true });
26348
+ mkdirSync9(installDir, { recursive: true });
26202
26349
  const meta3 = {
26203
26350
  version: version2,
26204
26351
  installedAt: new Date().toISOString(),
@@ -26206,7 +26353,7 @@ function writeGithubInstalledMetaIn(installDir, version2, binarySha256, archiveS
26206
26353
  binarySha256,
26207
26354
  ...archiveSha256 ? { archiveSha256 } : {}
26208
26355
  };
26209
- writeFileSync8(join15(installDir, INSTALLED_META_FILE2), JSON.stringify(meta3), "utf8");
26356
+ writeFileSync8(join16(installDir, INSTALLED_META_FILE2), JSON.stringify(meta3), "utf8");
26210
26357
  } catch (err) {
26211
26358
  warn2(`[lsp] failed to write github installed metadata in ${installDir}: ${err}`);
26212
26359
  }
@@ -26399,7 +26546,7 @@ async function downloadFile(url2, destPath, fetchImpl, assetSize, signal) {
26399
26546
  if (Number.isFinite(advertised) && advertised > MAX_DOWNLOAD_BYTES3) {
26400
26547
  throw new Error(`Content-Length ${advertised} exceeds max ${MAX_DOWNLOAD_BYTES3}`);
26401
26548
  }
26402
- mkdirSync8(dirname5(destPath), { recursive: true });
26549
+ mkdirSync9(dirname6(destPath), { recursive: true });
26403
26550
  let bytesWritten = 0;
26404
26551
  const guard = new TransformStream({
26405
26552
  transform(chunk, controller) {
@@ -26455,7 +26602,7 @@ function validateExtraction(stagingRoot) {
26455
26602
  throw new Error(`failed to read staging dir ${dir}: ${err}`);
26456
26603
  }
26457
26604
  for (const entry of entries) {
26458
- const full = join15(dir, entry);
26605
+ const full = join16(dir, entry);
26459
26606
  let lst;
26460
26607
  try {
26461
26608
  lst = lstatSync2(full);
@@ -26525,7 +26672,7 @@ function extractArchiveSafely(archivePath, destDir, archiveType) {
26525
26672
  try {
26526
26673
  rmSync5(stagingDir, { recursive: true, force: true });
26527
26674
  } catch {}
26528
- mkdirSync8(stagingDir, { recursive: true });
26675
+ mkdirSync9(stagingDir, { recursive: true });
26529
26676
  try {
26530
26677
  precheckArchiveContents(archivePath, archiveType);
26531
26678
  runPlatformExtractor(archivePath, stagingDir, archiveType);
@@ -26543,10 +26690,10 @@ function extractArchiveSafely(archivePath, destDir, archiveType) {
26543
26690
  }
26544
26691
  function quarantineCachedGithubInstall(spec, reason) {
26545
26692
  const packageDir = ghPackageDir(spec);
26546
- const dest = join15(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
26693
+ const dest = join16(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
26547
26694
  warn2(`[lsp] tofu_mismatch ${spec.id}: ${reason}; quarantining ${packageDir} -> ${dest}`);
26548
26695
  try {
26549
- mkdirSync8(dirname5(dest), { recursive: true });
26696
+ mkdirSync9(dirname6(dest), { recursive: true });
26550
26697
  rmSync5(dest, { recursive: true, force: true });
26551
26698
  renameSync6(packageDir, dest);
26552
26699
  } catch (err) {
@@ -26556,7 +26703,7 @@ function quarantineCachedGithubInstall(spec, reason) {
26556
26703
  function validateCachedGithubInstall(spec, platform2) {
26557
26704
  const packageDir = ghPackageDir(spec);
26558
26705
  const meta3 = readGithubInstalledMetaIn(packageDir);
26559
- const binaryPath = ghBinaryCandidates(spec, platform2).map((candidate) => join15(ghBinDir(spec), candidate)).find((candidate) => {
26706
+ const binaryPath = ghBinaryCandidates(spec, platform2).map((candidate) => join16(ghBinDir(spec), candidate)).find((candidate) => {
26560
26707
  try {
26561
26708
  return statSync6(candidate).isFile();
26562
26709
  } catch {
@@ -26634,7 +26781,7 @@ async function downloadAndInstall(spec, tag, assets, platform2, arch, fetchImpl,
26634
26781
  }
26635
26782
  const pkgDir = ghPackageDir(spec);
26636
26783
  const extractDir = ghExtractDir(spec);
26637
- const archivePath = join15(pkgDir, expected.name);
26784
+ const archivePath = join16(pkgDir, expected.name);
26638
26785
  log2(`[lsp] downloading ${spec.id} ${tag} \u2192 ${matchingAsset.url}`);
26639
26786
  try {
26640
26787
  await downloadFile(matchingAsset.url, archivePath, fetchImpl, matchingAsset.size, signal);
@@ -26674,13 +26821,13 @@ async function downloadAndInstall(spec, tag, assets, platform2, arch, fetchImpl,
26674
26821
  unlinkSync6(archivePath);
26675
26822
  } catch {}
26676
26823
  }
26677
- const innerBinaryPath = join15(extractDir, spec.binaryPathInArchive(platform2, arch, version2));
26678
- if (!existsSync10(innerBinaryPath)) {
26824
+ const innerBinaryPath = join16(extractDir, spec.binaryPathInArchive(platform2, arch, version2));
26825
+ if (!existsSync11(innerBinaryPath)) {
26679
26826
  error2(`[lsp] ${spec.id}: extracted binary not found at ${innerBinaryPath}`);
26680
26827
  return null;
26681
26828
  }
26682
26829
  const targetBinary = ghBinaryPath(spec, platform2);
26683
- mkdirSync8(dirname5(targetBinary), { recursive: true });
26830
+ mkdirSync9(dirname6(targetBinary), { recursive: true });
26684
26831
  try {
26685
26832
  copyFileSync3(innerBinaryPath, targetBinary);
26686
26833
  if (platform2 !== "win32") {
@@ -26759,7 +26906,7 @@ function runGithubAutoInstall(relevantServers, config2, fetchImpl = fetch) {
26759
26906
  if (!host) {
26760
26907
  for (const spec of GITHUB_LSP_TABLE) {
26761
26908
  try {
26762
- if (existsSync10(ghBinDir(spec))) {
26909
+ if (existsSync11(ghBinDir(spec))) {
26763
26910
  cachedBinDirs.push(ghBinDir(spec));
26764
26911
  }
26765
26912
  } catch {}
@@ -26922,9 +27069,9 @@ function normalizeToolMap(tools) {
26922
27069
  }
26923
27070
 
26924
27071
  // src/notifications.ts
26925
- import { existsSync as existsSync11, mkdirSync as mkdirSync9, readFileSync as readFileSync10, renameSync as renameSync7, rmSync as rmSync6, writeFileSync as writeFileSync9 } from "fs";
26926
- import { homedir as homedir8, platform as platform2 } from "os";
26927
- import { join as join16 } from "path";
27072
+ import { existsSync as existsSync12, mkdirSync as mkdirSync10, readFileSync as readFileSync10, writeFileSync as writeFileSync9 } from "fs";
27073
+ import { homedir as homedir9, platform as platform2 } from "os";
27074
+ import { join as join17 } from "path";
26928
27075
  function isTuiMode() {
26929
27076
  return process.env.OPENCODE_CLIENT === "cli";
26930
27077
  }
@@ -26943,26 +27090,25 @@ var AFT_MARKER = "\uD83D\uDD27 AFT:";
26943
27090
  var FEATURE_MARKER = `${AFT_MARKER} New in`;
26944
27091
  var WARNING_MARKER = `${AFT_MARKER} \u26A0\uFE0F`;
26945
27092
  var STATUS_MARKER = `${AFT_MARKER} \u2705`;
26946
- var WARNED_TOOLS_FILE = "warned_tools.json";
26947
27093
  function getDesktopStatePath() {
26948
27094
  const os2 = platform2();
26949
- const home = homedir8();
27095
+ const home = homedir9();
26950
27096
  if (os2 === "darwin") {
26951
- return join16(home, "Library", "Application Support", "ai.opencode.desktop", "opencode.global.dat");
27097
+ return join17(home, "Library", "Application Support", "ai.opencode.desktop", "opencode.global.dat");
26952
27098
  }
26953
27099
  if (os2 === "linux") {
26954
- const xdgConfig = process.env.XDG_CONFIG_HOME || join16(home, ".config");
26955
- return join16(xdgConfig, "ai.opencode.desktop", "opencode.global.dat");
27100
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join17(home, ".config");
27101
+ return join17(xdgConfig, "ai.opencode.desktop", "opencode.global.dat");
26956
27102
  }
26957
27103
  if (os2 === "win32") {
26958
- const appData = process.env.APPDATA || join16(home, "AppData", "Roaming");
26959
- return join16(appData, "ai.opencode.desktop", "opencode.global.dat");
27104
+ const appData = process.env.APPDATA || join17(home, "AppData", "Roaming");
27105
+ return join17(appData, "ai.opencode.desktop", "opencode.global.dat");
26960
27106
  }
26961
27107
  return null;
26962
27108
  }
26963
27109
  function readDesktopState(directory) {
26964
27110
  const statePath = getDesktopStatePath();
26965
- if (!statePath || !existsSync11(statePath)) {
27111
+ if (!statePath || !existsSync12(statePath)) {
26966
27112
  return { sessionId: null, serverUrl: null };
26967
27113
  }
26968
27114
  try {
@@ -27064,9 +27210,9 @@ async function sendWarning(opts, message) {
27064
27210
  }
27065
27211
  async function sendFeatureAnnouncement(opts, version2, features, storageDir) {
27066
27212
  if (storageDir) {
27067
- const versionFile = join16(storageDir, "last_announced_version");
27213
+ const versionFile = join17(storageDir, "last_announced_version");
27068
27214
  try {
27069
- if (existsSync11(versionFile)) {
27215
+ if (existsSync12(versionFile)) {
27070
27216
  const lastVersion = readFileSync10(versionFile, "utf-8").trim();
27071
27217
  if (lastVersion === version2)
27072
27218
  return;
@@ -27087,60 +27233,41 @@ async function sendFeatureAnnouncement(opts, version2, features, storageDir) {
27087
27233
  }
27088
27234
  if (storageDir) {
27089
27235
  try {
27090
- mkdirSync9(storageDir, { recursive: true });
27091
- writeFileSync9(join16(storageDir, "last_announced_version"), version2);
27236
+ mkdirSync10(storageDir, { recursive: true });
27237
+ writeFileSync9(join17(storageDir, "last_announced_version"), version2);
27092
27238
  } catch {}
27093
27239
  }
27094
27240
  }
27095
- function readWarnedTools(storageDir) {
27241
+ async function readWarnedTools(bridge) {
27096
27242
  try {
27097
- const warnedToolsPath = join16(storageDir, WARNED_TOOLS_FILE);
27098
- if (!existsSync11(warnedToolsPath))
27243
+ const resp = await bridge.send("db_get_state", { key: "warned_tools" });
27244
+ if (resp.success === false)
27245
+ return {};
27246
+ const value = resp.data?.value;
27247
+ if (typeof value !== "string")
27099
27248
  return {};
27100
- const parsed = JSON.parse(readFileSync10(warnedToolsPath, "utf-8"));
27249
+ const parsed = JSON.parse(value);
27101
27250
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
27102
27251
  return {};
27103
- const warned = {};
27104
- for (const [key, version2] of Object.entries(parsed)) {
27105
- if (typeof version2 === "string") {
27106
- warned[key] = version2;
27107
- }
27108
- }
27109
- return warned;
27252
+ return parsed;
27110
27253
  } catch {
27111
27254
  return {};
27112
27255
  }
27113
27256
  }
27114
- function writeWarnedTools(storageDir, warned) {
27257
+ async function hasWarnedFor(bridge, key) {
27258
+ const warned = await readWarnedTools(bridge);
27259
+ return warned[key] === true || typeof warned[key] === "string";
27260
+ }
27261
+ async function recordWarning(bridge, key) {
27262
+ const warned = await readWarnedTools(bridge);
27263
+ warned[key] = true;
27115
27264
  try {
27116
- mkdirSync9(storageDir, { recursive: true });
27117
- const warnedToolsPath = join16(storageDir, WARNED_TOOLS_FILE);
27118
- const tmpPath = join16(storageDir, `${WARNED_TOOLS_FILE}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
27119
- writeFileSync9(tmpPath, `${JSON.stringify(warned, null, 2)}
27120
- `);
27121
- renameSync7(tmpPath, warnedToolsPath);
27265
+ await bridge.send("db_set_state", {
27266
+ key: "warned_tools",
27267
+ value: JSON.stringify(warned)
27268
+ });
27122
27269
  } catch {}
27123
27270
  }
27124
- async function withWarnedToolsLock(storageDir, fn) {
27125
- const lockDir = join16(storageDir, "warned_tools.lock");
27126
- for (let attempt = 0;attempt < 5; attempt++) {
27127
- try {
27128
- mkdirSync9(storageDir, { recursive: true });
27129
- mkdirSync9(lockDir, { mode: 448 });
27130
- try {
27131
- return await fn();
27132
- } finally {
27133
- rmSync6(lockDir, { recursive: true, force: true });
27134
- }
27135
- } catch (err) {
27136
- const code = err.code;
27137
- if (code !== "EEXIST")
27138
- return null;
27139
- await new Promise((resolve4) => setTimeout(resolve4, 10 * (attempt + 1)));
27140
- }
27141
- }
27142
- return null;
27143
- }
27144
27271
  function warningKey(warning, projectRoot) {
27145
27272
  const scope = warning.kind === "lsp_binary_missing" ? "_" : projectRoot ?? "_";
27146
27273
  return [
@@ -27179,29 +27306,14 @@ ${warning.hint}`;
27179
27306
  async function deliverConfigureWarnings(opts, warnings) {
27180
27307
  if (warnings.length === 0)
27181
27308
  return;
27182
- const deliveredWithLock = await withWarnedToolsLock(opts.storageDir, async () => {
27183
- const warned = readWarnedTools(opts.storageDir);
27184
- let changed = false;
27185
- for (const warning of warnings) {
27186
- const key = warningKey(warning, opts.projectRoot);
27187
- if (Object.hasOwn(warned, key))
27188
- continue;
27189
- const delivered = await sendIgnoredMessage(opts.client, opts.sessionId, formatConfigureWarning(warning));
27190
- if (!delivered)
27191
- continue;
27192
- warned[key] = opts.pluginVersion;
27193
- changed = true;
27194
- }
27195
- if (changed) {
27196
- const merged = { ...readWarnedTools(opts.storageDir), ...warned };
27197
- writeWarnedTools(opts.storageDir, merged);
27198
- }
27199
- return true;
27200
- });
27201
- if (deliveredWithLock)
27202
- return;
27203
27309
  for (const warning of warnings) {
27204
- await sendIgnoredMessage(opts.client, opts.sessionId, formatConfigureWarning(warning));
27310
+ const key = warningKey(warning, opts.projectRoot);
27311
+ if (await hasWarnedFor(opts.bridge, key))
27312
+ continue;
27313
+ const delivered = await sendIgnoredMessage(opts.client, opts.sessionId, formatConfigureWarning(warning));
27314
+ if (!delivered)
27315
+ continue;
27316
+ await recordWarning(opts.bridge, key);
27205
27317
  }
27206
27318
  }
27207
27319
  async function cleanupWarnings(opts) {
@@ -27239,20 +27351,20 @@ async function cleanupWarnings(opts) {
27239
27351
 
27240
27352
  // src/shared/rpc-server.ts
27241
27353
  import { randomBytes as randomBytes2 } from "crypto";
27242
- import { mkdirSync as mkdirSync10, renameSync as renameSync8, unlinkSync as unlinkSync7, writeFileSync as writeFileSync10 } from "fs";
27354
+ import { mkdirSync as mkdirSync11, renameSync as renameSync7, unlinkSync as unlinkSync7, writeFileSync as writeFileSync10 } from "fs";
27243
27355
  import { createServer } from "http";
27244
- import { dirname as dirname6 } from "path";
27356
+ import { dirname as dirname7 } from "path";
27245
27357
 
27246
27358
  // src/shared/rpc-utils.ts
27247
27359
  import { createHash as createHash6 } from "crypto";
27248
- import { join as join17 } from "path";
27360
+ import { join as join18 } from "path";
27249
27361
  function projectHash(directory) {
27250
27362
  const normalized = directory.replace(/\/+$/, "");
27251
27363
  return createHash6("sha256").update(normalized).digest("hex").slice(0, 16);
27252
27364
  }
27253
27365
  function rpcPortFilePath(storageDir, directory) {
27254
27366
  const hash2 = projectHash(directory);
27255
- return join17(storageDir, "rpc", hash2, "port");
27367
+ return join18(storageDir, "rpc", hash2, "port");
27256
27368
  }
27257
27369
 
27258
27370
  // src/shared/rpc-server.ts
@@ -27285,14 +27397,14 @@ class AftRpcServer {
27285
27397
  this.token = randomBytes2(32).toString("hex");
27286
27398
  this.server = server;
27287
27399
  try {
27288
- const dir = dirname6(this.portFilePath);
27289
- mkdirSync10(dir, { recursive: true, mode: 448 });
27400
+ const dir = dirname7(this.portFilePath);
27401
+ mkdirSync11(dir, { recursive: true, mode: 448 });
27290
27402
  const tmpPath = `${this.portFilePath}.tmp`;
27291
27403
  writeFileSync10(tmpPath, JSON.stringify({ port: this.port, token: this.token }), {
27292
27404
  encoding: "utf-8",
27293
27405
  mode: 384
27294
27406
  });
27295
- renameSync8(tmpPath, this.portFilePath);
27407
+ renameSync7(tmpPath, this.portFilePath);
27296
27408
  log2(`RPC server listening on 127.0.0.1:${this.port}`);
27297
27409
  } catch (err) {
27298
27410
  warn2(`Failed to write RPC port file: ${err}`);
@@ -27446,6 +27558,24 @@ function readNumber(value, fallback = 0) {
27446
27558
  function readOptionalNumber(value) {
27447
27559
  return typeof value === "number" && Number.isFinite(value) ? value : null;
27448
27560
  }
27561
+ function readCompressionAggregate(value) {
27562
+ const aggregate = asRecord(value);
27563
+ return {
27564
+ events: readNumber(aggregate.events),
27565
+ original_tokens: readNumber(aggregate.original_tokens),
27566
+ compressed_tokens: readNumber(aggregate.compressed_tokens),
27567
+ savings_tokens: readNumber(aggregate.savings_tokens)
27568
+ };
27569
+ }
27570
+ function readCompression(value) {
27571
+ if (typeof value !== "object" || value === null)
27572
+ return;
27573
+ const compression = asRecord(value);
27574
+ return {
27575
+ project: readCompressionAggregate(compression.project),
27576
+ session: readCompressionAggregate(compression.session)
27577
+ };
27578
+ }
27449
27579
  function formatFlag(enabled) {
27450
27580
  return enabled ? "enabled" : "disabled";
27451
27581
  }
@@ -27524,6 +27654,7 @@ function coerceAftStatus(response) {
27524
27654
  tracked_files: readNumber(session.tracked_files),
27525
27655
  checkpoints: readNumber(session.checkpoints)
27526
27656
  },
27657
+ compression: readCompression(response.compression),
27527
27658
  message: readString(response.message, "")
27528
27659
  };
27529
27660
  }
@@ -27582,21 +27713,21 @@ function formatStatusMarkdown(status) {
27582
27713
 
27583
27714
  // src/shared/tui-config.ts
27584
27715
  var import_comment_json4 = __toESM(require_src2(), 1);
27585
- import { existsSync as existsSync12, mkdirSync as mkdirSync11, readFileSync as readFileSync11, writeFileSync as writeFileSync11 } from "fs";
27586
- import { dirname as dirname7, join as join19 } from "path";
27716
+ import { existsSync as existsSync13, mkdirSync as mkdirSync12, readFileSync as readFileSync11, writeFileSync as writeFileSync11 } from "fs";
27717
+ import { dirname as dirname8, join as join20 } from "path";
27587
27718
 
27588
27719
  // src/shared/opencode-config-dir.ts
27589
- import { homedir as homedir9 } from "os";
27590
- import { join as join18, resolve as resolve4 } from "path";
27720
+ import { homedir as homedir10 } from "os";
27721
+ import { join as join19, resolve as resolve4 } from "path";
27591
27722
  function getCliConfigDir() {
27592
27723
  const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
27593
27724
  if (envConfigDir) {
27594
27725
  return resolve4(envConfigDir);
27595
27726
  }
27596
27727
  if (process.platform === "win32") {
27597
- return join18(homedir9(), ".config", "opencode");
27728
+ return join19(homedir10(), ".config", "opencode");
27598
27729
  }
27599
- return join18(process.env.XDG_CONFIG_HOME || join18(homedir9(), ".config"), "opencode");
27730
+ return join19(process.env.XDG_CONFIG_HOME || join19(homedir10(), ".config"), "opencode");
27600
27731
  }
27601
27732
  function getOpenCodeConfigDir2(_options) {
27602
27733
  return getCliConfigDir();
@@ -27605,10 +27736,10 @@ function getOpenCodeConfigPaths(options) {
27605
27736
  const configDir = getOpenCodeConfigDir2(options);
27606
27737
  return {
27607
27738
  configDir,
27608
- configJson: join18(configDir, "opencode.json"),
27609
- configJsonc: join18(configDir, "opencode.jsonc"),
27610
- packageJson: join18(configDir, "package.json"),
27611
- omoConfig: join18(configDir, "magic-context.jsonc")
27739
+ configJson: join19(configDir, "opencode.json"),
27740
+ configJsonc: join19(configDir, "opencode.jsonc"),
27741
+ packageJson: join19(configDir, "package.json"),
27742
+ omoConfig: join19(configDir, "magic-context.jsonc")
27612
27743
  };
27613
27744
  }
27614
27745
 
@@ -27617,11 +27748,11 @@ var PLUGIN_NAME = "@cortexkit/aft-opencode";
27617
27748
  var PLUGIN_ENTRY = `${PLUGIN_NAME}@latest`;
27618
27749
  function resolveTuiConfigPath() {
27619
27750
  const configDir = getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
27620
- const jsoncPath = join19(configDir, "tui.jsonc");
27621
- const jsonPath = join19(configDir, "tui.json");
27622
- if (existsSync12(jsoncPath))
27751
+ const jsoncPath = join20(configDir, "tui.jsonc");
27752
+ const jsonPath = join20(configDir, "tui.json");
27753
+ if (existsSync13(jsoncPath))
27623
27754
  return jsoncPath;
27624
- if (existsSync12(jsonPath))
27755
+ if (existsSync13(jsonPath))
27625
27756
  return jsonPath;
27626
27757
  return jsonPath;
27627
27758
  }
@@ -27629,7 +27760,7 @@ function ensureTuiPluginEntry() {
27629
27760
  try {
27630
27761
  const configPath = resolveTuiConfigPath();
27631
27762
  let config2 = {};
27632
- if (existsSync12(configPath)) {
27763
+ if (existsSync13(configPath)) {
27633
27764
  config2 = import_comment_json4.parse(readFileSync11(configPath, "utf-8")) ?? {};
27634
27765
  }
27635
27766
  const plugins = Array.isArray(config2.plugin) ? config2.plugin.filter((value) => typeof value === "string") : [];
@@ -27638,7 +27769,7 @@ function ensureTuiPluginEntry() {
27638
27769
  }
27639
27770
  plugins.push(PLUGIN_ENTRY);
27640
27771
  config2.plugin = plugins;
27641
- mkdirSync11(dirname7(configPath), { recursive: true });
27772
+ mkdirSync12(dirname8(configPath), { recursive: true });
27642
27773
  writeFileSync11(configPath, `${import_comment_json4.stringify(config2, null, 2)}
27643
27774
  `);
27644
27775
  log2(`[aft-plugin] added TUI plugin entry to ${configPath}`);
@@ -29235,6 +29366,9 @@ function createWriteTool(ctx, editToolName = "edit") {
29235
29366
  let output = data.created ? "Created new file." : "File updated.";
29236
29367
  if (data.formatted)
29237
29368
  output += " Auto-formatted.";
29369
+ if (data.no_op === true) {
29370
+ output += " No net change \u2014 the written content is byte-identical to what was already on disk.";
29371
+ }
29238
29372
  const diags = data.lsp_diagnostics;
29239
29373
  if (diags && diags.length > 0) {
29240
29374
  const errors3 = diags.filter((d) => d.severity === "error");
@@ -29483,6 +29617,11 @@ function createEditTool(ctx, writeToolName = "write") {
29483
29617
  result += `
29484
29618
 
29485
29619
  ${globSkipNote}`;
29620
+ if (data.no_op === true) {
29621
+ result += `
29622
+
29623
+ Note: no net file change \u2014 the match was found and applied, but the file content is byte-identical to before. Likely causes: oldString and newString are identical, or a formatter normalized the change away.`;
29624
+ }
29486
29625
  const diags = data.lsp_diagnostics;
29487
29626
  if (diags && diags.length > 0) {
29488
29627
  const errors3 = diags.filter((d) => d.severity === "error");
@@ -30662,9 +30801,9 @@ function splitIncludeArg(raw) {
30662
30801
  }
30663
30802
  buf += ch;
30664
30803
  }
30665
- const tail = buf.trim();
30666
- if (tail.length > 0)
30667
- out.push(tail);
30804
+ const tail2 = buf.trim();
30805
+ if (tail2.length > 0)
30806
+ out.push(tail2);
30668
30807
  return out;
30669
30808
  }
30670
30809
  function searchTools(ctx) {
@@ -31024,6 +31163,7 @@ async function handleConfigureWarningsForSession(context) {
31024
31163
  await deliverConfigureWarnings({
31025
31164
  client: context.client ?? context.fallbackClient,
31026
31165
  sessionId: context.sessionId,
31166
+ bridge: context.bridge,
31027
31167
  storageDir: context.storageDir,
31028
31168
  pluginVersion: context.pluginVersion,
31029
31169
  projectRoot: context.projectRoot
@@ -31065,47 +31205,25 @@ var PLUGIN_VERSION = (() => {
31065
31205
  return "0.0.0";
31066
31206
  }
31067
31207
  })();
31068
- var ANNOUNCEMENT_VERSION = "0.18.0";
31208
+ var ANNOUNCEMENT_VERSION = "0.27.0";
31069
31209
  var ANNOUNCEMENT_FEATURES = [
31070
- `New experimental features \u2014 AFT now optionally hoists bash:
31071
- - Run bash scripts in the background.
31072
- - Initial output compression for git, cargo, npm, bun, pnpm, pytest, tsc (more in 0.19).
31073
- - Rewrite cat/grep/find/sed/ls into AFT counterparts for faster, formatted output.
31074
- Check GitHub for how to enable.`,
31075
- "Trigram grep/glob and semantic search (aft_search) graduated out of experimental.",
31076
- "Lots of bugfixes and new end-to-end test coverage."
31210
+ "Storage moved to ~/.local/share/cortexkit/aft (~/Library/Application Support/cortexkit/aft on macOS, %APPDATA%/cortexkit/aft on Windows). Your existing data migrated automatically on first launch.",
31211
+ "Bash output compression now reports token savings \u2014 visible in /aft-status and the TUI sidebar (Session + Project totals).",
31212
+ "Seven new languages supported by aft_outline / aft_zoom / aft_search / ast_grep: Java, Ruby, Kotlin, Swift, PHP, Lua, Perl.",
31213
+ "Join us on Discord: https://discord.gg/F2uWxjGnU"
31077
31214
  ];
31078
31215
  var plugin = async (input) => initializePluginForDirectory(input);
31079
31216
  async function initializePluginForDirectory(input) {
31080
31217
  const binaryPath = await findBinary(PLUGIN_VERSION);
31218
+ await ensureStorageMigrated({ harness: "opencode", binaryPath, logger: bridgeLogger });
31081
31219
  const aftConfig = loadAftConfig(input.directory);
31082
31220
  const autoUpdateAbort = new AbortController;
31083
- const configOverrides = {};
31084
- if (aftConfig.format_on_edit !== undefined)
31085
- configOverrides.format_on_edit = aftConfig.format_on_edit;
31086
- if (aftConfig.formatter_timeout_secs !== undefined)
31087
- configOverrides.formatter_timeout_secs = aftConfig.formatter_timeout_secs;
31088
- if (aftConfig.validate_on_edit !== undefined)
31089
- configOverrides.validate_on_edit = aftConfig.validate_on_edit;
31090
- if (aftConfig.formatter !== undefined)
31091
- configOverrides.formatter = aftConfig.formatter;
31092
- if (aftConfig.checker !== undefined)
31093
- configOverrides.checker = aftConfig.checker;
31094
- configOverrides.restrict_to_project_root = aftConfig.restrict_to_project_root ?? false;
31095
- configOverrides.bash_permissions = true;
31096
- if (aftConfig.search_index !== undefined)
31097
- configOverrides.search_index = aftConfig.search_index;
31098
- if (aftConfig.semantic_search !== undefined)
31099
- configOverrides.semantic_search = aftConfig.semantic_search;
31100
- Object.assign(configOverrides, resolveExperimentalConfigForConfigure(aftConfig));
31101
- Object.assign(configOverrides, resolveLspConfigForConfigure(aftConfig));
31102
- if (aftConfig.semantic !== undefined)
31103
- configOverrides.semantic = aftConfig.semantic;
31104
- if (aftConfig.max_callgraph_files !== undefined)
31105
- configOverrides.max_callgraph_files = aftConfig.max_callgraph_files;
31221
+ const configOverrides = {
31222
+ ...resolveProjectOverridesForConfigure(aftConfig),
31223
+ bash_permissions: true
31224
+ };
31106
31225
  const isFastembedSemanticBackend = (aftConfig.semantic?.backend ?? "fastembed") === "fastembed";
31107
- const dataHome = process.env.XDG_DATA_HOME || join21(homedir10(), ".local", "share");
31108
- configOverrides.storage_dir = join21(dataHome, "opencode", "storage", "plugin", "aft");
31226
+ configOverrides.storage_dir = resolveCortexKitStorageRoot();
31109
31227
  let onnxRuntimePromise = null;
31110
31228
  if (aftConfig.semantic_search && isFastembedSemanticBackend) {
31111
31229
  const storageDir2 = configOverrides.storage_dir;
@@ -31184,6 +31302,15 @@ ${lines}
31184
31302
  const poolOptions = {
31185
31303
  errorPrefix: "[aft-plugin]",
31186
31304
  minVersion: PLUGIN_VERSION,
31305
+ projectConfigLoader: (projectRoot) => {
31306
+ try {
31307
+ const projectConfig = loadAftConfig(projectRoot);
31308
+ return resolveProjectOverridesForConfigure(projectConfig);
31309
+ } catch (err) {
31310
+ warn2(`loadAftConfig(${projectRoot}) failed; falling back to plugin-init config: ${err instanceof Error ? err.message : String(err)}`);
31311
+ return {};
31312
+ }
31313
+ },
31187
31314
  onVersionMismatch: async (binaryVersion, minVersion) => {
31188
31315
  const existing = versionUpgradePromises.get(minVersion);
31189
31316
  if (existing) {
@@ -31212,17 +31339,23 @@ ${lines}
31212
31339
  versionUpgradePromises.set(minVersion, upgradePromise);
31213
31340
  return upgradePromise;
31214
31341
  },
31215
- onConfigureWarnings: async ({ projectRoot, sessionId, client, warnings }) => {
31342
+ onConfigureWarnings: ({ projectRoot, sessionId, client, warnings }) => {
31343
+ const bridge = pool.getActiveBridgeForRoot(projectRoot);
31344
+ if (!bridge)
31345
+ return;
31216
31346
  const pendingWarnings = sessionId ? drainPendingEagerWarnings(projectRoot) : [];
31217
- await handleConfigureWarningsForSession({
31218
- projectRoot,
31219
- sessionId,
31220
- client,
31221
- warnings: [...pendingWarnings, ...warnings],
31222
- fallbackClient: input.client,
31223
- storageDir: configOverrides.storage_dir,
31224
- pluginVersion: PLUGIN_VERSION
31225
- });
31347
+ setTimeout(() => {
31348
+ handleConfigureWarningsForSession({
31349
+ projectRoot,
31350
+ sessionId,
31351
+ client,
31352
+ bridge,
31353
+ warnings: [...pendingWarnings, ...warnings],
31354
+ fallbackClient: input.client,
31355
+ storageDir: configOverrides.storage_dir,
31356
+ pluginVersion: PLUGIN_VERSION
31357
+ });
31358
+ }, 0);
31226
31359
  },
31227
31360
  onBashCompletion: (completion) => {
31228
31361
  const sessionDir = getSessionDirectoryCached(completion.session_id) ?? input.directory;
@@ -31244,6 +31377,7 @@ ${lines}
31244
31377
  }
31245
31378
  };
31246
31379
  const pool = new BridgePool(binaryPath, poolOptions, configOverrides);
31380
+ pool.setConfigureOverride("harness", "opencode");
31247
31381
  const ctx = {
31248
31382
  pool,
31249
31383
  client: input.client,
@@ -31293,7 +31427,9 @@ ${lines}
31293
31427
  };
31294
31428
  }
31295
31429
  const cached2 = bridge.getCachedStatus();
31296
- if (cached2 !== null) {
31430
+ const cachedSessionId = cached2?.session;
31431
+ const cachedId = cachedSessionId?.id;
31432
+ if (cached2 !== null && cachedId === sessionID) {
31297
31433
  return { success: true, ...cached2 };
31298
31434
  }
31299
31435
  const response = await bridge.send("status", { session_id: sessionID });
@@ -31308,9 +31444,9 @@ ${lines}
31308
31444
  return { show: false };
31309
31445
  }
31310
31446
  if (storageDir) {
31311
- const versionFile = join21(storageDir, "last_announced_version");
31447
+ const versionFile = join22(storageDir, "last_announced_version");
31312
31448
  try {
31313
- if (existsSync14(versionFile)) {
31449
+ if (existsSync15(versionFile)) {
31314
31450
  const lastVersion = readFileSync12(versionFile, "utf-8").trim();
31315
31451
  if (lastVersion === ANNOUNCEMENT_VERSION)
31316
31452
  return { show: false };
@@ -31322,8 +31458,8 @@ ${lines}
31322
31458
  rpcServer.handle("mark-announced", async () => {
31323
31459
  if (storageDir && ANNOUNCEMENT_VERSION) {
31324
31460
  try {
31325
- mkdirSync12(storageDir, { recursive: true });
31326
- writeFileSync12(join21(storageDir, "last_announced_version"), ANNOUNCEMENT_VERSION);
31461
+ mkdirSync13(storageDir, { recursive: true });
31462
+ writeFileSync12(join22(storageDir, "last_announced_version"), ANNOUNCEMENT_VERSION);
31327
31463
  } catch {}
31328
31464
  }
31329
31465
  return { success: true };
@@ -31464,8 +31600,11 @@ Install: ${getManualInstallHint()}`).catch(() => {});
31464
31600
  const sessionDir = await getSessionDirectory(input.client, commandInput.sessionID, input.directory) ?? input.directory;
31465
31601
  const bridge = ctx.pool.getActiveBridgeForRoot(sessionDir) ?? ctx.pool.getBridge(sessionDir);
31466
31602
  const cached2 = bridge.getCachedStatus();
31467
- const response = cached2 ? { success: true, ...cached2 } : await bridge.send("status", { session_id: commandInput.sessionID });
31468
- if (!cached2 && response.success !== false) {
31603
+ const cachedSessionId = cached2?.session;
31604
+ const cachedId = cachedSessionId?.id;
31605
+ const cacheUsable = cached2 !== null && cachedId === commandInput.sessionID;
31606
+ const response = cacheUsable ? { success: true, ...cached2 } : await bridge.send("status", { session_id: commandInput.sessionID });
31607
+ if (!cacheUsable && response.success !== false) {
31469
31608
  bridge.cacheStatusSnapshot(response);
31470
31609
  }
31471
31610
  if (response.success === false) {