@cortexkit/aft-pi 0.39.0 → 0.39.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
@@ -7728,10 +7728,10 @@ var require_stringify = __commonJS((exports, module) => {
7728
7728
  replacer = null;
7729
7729
  indent = EMPTY;
7730
7730
  };
7731
- var join9 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(one)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two)), gap) : EMPTY;
7731
+ var join10 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(one)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two)), gap) : EMPTY;
7732
7732
  var join_content = (inside, value, gap) => {
7733
7733
  const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
7734
- return join9(comment, inside, gap);
7734
+ return join10(comment, inside, gap);
7735
7735
  };
7736
7736
  var stringify_string = (holder, key, value) => {
7737
7737
  const raw = get_raw_string_literal(holder, key);
@@ -7753,13 +7753,13 @@ var require_stringify = __commonJS((exports, module) => {
7753
7753
  if (i !== 0) {
7754
7754
  inside += COMMA;
7755
7755
  }
7756
- const before = join9(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
7756
+ const before = join10(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
7757
7757
  inside += before || LF + deeper_gap;
7758
7758
  inside += stringify(i, value, deeper_gap) || STR_NULL;
7759
7759
  inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
7760
7760
  after_comma = process_comments(value, AFTER(i), deeper_gap);
7761
7761
  }
7762
- inside += join9(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
7762
+ inside += join10(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
7763
7763
  return BRACKET_OPEN + join_content(inside, value, gap) + BRACKET_CLOSE;
7764
7764
  };
7765
7765
  var object_stringify = (value, gap) => {
@@ -7780,13 +7780,13 @@ var require_stringify = __commonJS((exports, module) => {
7780
7780
  inside += COMMA;
7781
7781
  }
7782
7782
  first = false;
7783
- const before = join9(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
7783
+ const before = join10(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
7784
7784
  inside += before || LF + deeper_gap;
7785
7785
  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);
7786
7786
  after_comma = process_comments(value, AFTER(key), deeper_gap);
7787
7787
  };
7788
7788
  keys.forEach(iteratee);
7789
- inside += join9(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
7789
+ inside += join10(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
7790
7790
  return CURLY_BRACKET_OPEN + join_content(inside, value, gap) + CURLY_BRACKET_CLOSE;
7791
7791
  };
7792
7792
  function stringify(key, holder, gap) {
@@ -11674,7 +11674,45 @@ function error(message, meta) {
11674
11674
  console.error(`[aft-bridge] ERROR: ${message}`);
11675
11675
  }
11676
11676
  }
11677
+ // ../aft-bridge/dist/bash-format.js
11678
+ function appendPipeStripNote(output, note) {
11679
+ return note ? `${output}
11680
+
11681
+ ${note}` : output;
11682
+ }
11683
+ function formatSeconds(ms) {
11684
+ return `${Number((ms / 1000).toFixed(1))}s`;
11685
+ }
11686
+ function formatForegroundResult(data) {
11687
+ const output = data.output_preview ?? "";
11688
+ const outputPath = data.output_path;
11689
+ const truncated = data.output_truncated === true;
11690
+ const status = data.status;
11691
+ const exit = data.exit_code;
11692
+ let rendered = output;
11693
+ if (truncated && outputPath) {
11694
+ rendered += `
11695
+ [output truncated; full output at ${outputPath}]`;
11696
+ }
11697
+ if (status === "timed_out") {
11698
+ rendered += `
11699
+ [command timed out]`;
11700
+ }
11701
+ if (typeof exit === "number" && exit !== 0) {
11702
+ rendered += `
11703
+ [exit code: ${exit}]`;
11704
+ }
11705
+ return rendered;
11706
+ }
11707
+ function isTerminalStatus(status) {
11708
+ return status === "completed" || status === "failed" || status === "killed" || status === "timed_out";
11709
+ }
11710
+ function sleep(ms) {
11711
+ return new Promise((resolve) => setTimeout(resolve, ms));
11712
+ }
11677
11713
  // ../aft-bridge/dist/bash-hints.js
11714
+ import * as os from "node:os";
11715
+ import * as path from "node:path";
11678
11716
  var CONFLICT_HINT = `
11679
11717
 
11680
11718
  [Hint] Use aft_conflicts to see all conflict regions across files in a single call.`;
@@ -11704,18 +11742,87 @@ function commandInvokesCodeSearch(command) {
11704
11742
  }
11705
11743
  return false;
11706
11744
  }
11707
- function maybeAppendGrepSearchHint(output, command, aftSearchRegistered) {
11745
+ function maybeAppendGrepSearchHint(output, command, aftSearchRegistered, projectRoot) {
11708
11746
  if (output === "")
11709
11747
  return output;
11710
11748
  if (!commandInvokesCodeSearch(command))
11711
11749
  return output;
11712
11750
  if (output.includes(GREP_SEARCH_HINT_PREFIX))
11713
11751
  return output;
11752
+ if (shouldSuppressGrepSearchHint(command, projectRoot))
11753
+ return output;
11714
11754
  const hint = aftSearchRegistered ? GREP_SEARCH_AFT_SEARCH_HINT : GREP_SEARCH_GREP_HINT;
11715
11755
  return `${output}
11716
11756
 
11717
11757
  ${hint}`;
11718
11758
  }
11759
+ function shouldSuppressGrepSearchHint(command, projectRoot) {
11760
+ const root = projectRoot?.trim();
11761
+ if (!root)
11762
+ return false;
11763
+ const statements = splitTopLevelStatements(command);
11764
+ if (statements === null)
11765
+ return false;
11766
+ let sawCodeSearchStatement = false;
11767
+ for (const statement of statements) {
11768
+ const firstStage = firstPipelineStage(statement);
11769
+ if (firstStage === null)
11770
+ continue;
11771
+ const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0));
11772
+ if (firstToken === null)
11773
+ continue;
11774
+ if (firstToken.token !== "grep" && firstToken.token !== "rg")
11775
+ continue;
11776
+ sawCodeSearchStatement = true;
11777
+ const operands = collectPathOperands(firstStage, firstToken.end);
11778
+ if (operands.length === 0)
11779
+ return false;
11780
+ for (const operand of operands) {
11781
+ if (isPathInsideProject(root, operand))
11782
+ return false;
11783
+ }
11784
+ }
11785
+ return sawCodeSearchStatement;
11786
+ }
11787
+ function collectPathOperands(firstStage, startAfterCommand) {
11788
+ const operands = [];
11789
+ let index = skipSpaces(firstStage, startAfterCommand);
11790
+ while (index < firstStage.length) {
11791
+ const tokenResult = readShellToken(firstStage, index);
11792
+ if (tokenResult === null)
11793
+ break;
11794
+ const { token, end } = tokenResult;
11795
+ if (end <= index)
11796
+ break;
11797
+ index = skipSpaces(firstStage, end);
11798
+ if (token.startsWith("-"))
11799
+ continue;
11800
+ if (looksLikePathOperand(token))
11801
+ operands.push(token);
11802
+ }
11803
+ return operands;
11804
+ }
11805
+ function looksLikePathOperand(token) {
11806
+ return token.includes("/") || token.startsWith("~") || token.startsWith("./") || token.startsWith("../");
11807
+ }
11808
+ function expandTilde(target) {
11809
+ if (!target.startsWith("~"))
11810
+ return target;
11811
+ if (target === "~" || target.startsWith("~/")) {
11812
+ return path.join(os.homedir(), target.slice(1));
11813
+ }
11814
+ return target;
11815
+ }
11816
+ function resolvePathOperand(projectRoot, operand) {
11817
+ const expanded = expandTilde(operand);
11818
+ return path.isAbsolute(expanded) ? path.resolve(expanded) : path.resolve(projectRoot, expanded);
11819
+ }
11820
+ function isPathInsideProject(projectRoot, operand) {
11821
+ const root = path.resolve(projectRoot);
11822
+ const resolved = resolvePathOperand(root, operand);
11823
+ const rel = path.relative(root, resolved);
11824
+ return rel === "" || !rel.startsWith("..") && !path.isAbsolute(rel);
11825
+ }
11719
11826
  function splitTopLevelStatements(command) {
11720
11827
  const statements = [];
11721
11828
  let start = 0;
@@ -11895,8 +12002,8 @@ function resolveBashKillTimeout(modelTimeout, foregroundWaitMs) {
11895
12002
  }
11896
12003
  // ../aft-bridge/dist/bridge.js
11897
12004
  import { spawn } from "node:child_process";
11898
- import { homedir } from "node:os";
11899
- import { join } from "node:path";
12005
+ import { homedir as homedir2 } from "node:os";
12006
+ import { join as join2 } from "node:path";
11900
12007
  import { StringDecoder } from "node:string_decoder";
11901
12008
 
11902
12009
  // ../aft-bridge/dist/command-timeouts.js
@@ -12269,7 +12376,7 @@ class BinaryBridge {
12269
12376
  `;
12270
12377
  const keepBridgeOnTimeout = options?.keepBridgeOnTimeout === true;
12271
12378
  let requestSentAt = Date.now();
12272
- const response = await new Promise((resolve, reject) => {
12379
+ const response = await new Promise((resolve2, reject) => {
12273
12380
  const timer = setTimeout(() => {
12274
12381
  const entry = this.pending.get(id);
12275
12382
  if (!entry)
@@ -12304,7 +12411,7 @@ class BinaryBridge {
12304
12411
  entry.reject(new Error(`${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`));
12305
12412
  this.handleTimeout(requestSessionId);
12306
12413
  }, effectiveTimeoutMs);
12307
- this.pending.set(id, { resolve, reject, timer, onProgress: options?.onProgress, command });
12414
+ this.pending.set(id, { resolve: resolve2, reject, timer, onProgress: options?.onProgress, command });
12308
12415
  if (!this.process?.stdin?.writable) {
12309
12416
  this.pending.delete(id);
12310
12417
  clearTimeout(timer);
@@ -12402,15 +12509,15 @@ class BinaryBridge {
12402
12509
  if (this.process) {
12403
12510
  const proc = this.process;
12404
12511
  this.process = null;
12405
- return new Promise((resolve) => {
12512
+ return new Promise((resolve2) => {
12406
12513
  const forceKillTimer = setTimeout(() => {
12407
12514
  proc.kill("SIGKILL");
12408
- resolve();
12515
+ resolve2();
12409
12516
  }, 5000);
12410
12517
  proc.once("exit", () => {
12411
12518
  clearTimeout(forceKillTimer);
12412
12519
  this.logVia("Process exited during shutdown");
12413
- resolve();
12520
+ resolve2();
12414
12521
  });
12415
12522
  proc.kill("SIGTERM");
12416
12523
  });
@@ -12455,15 +12562,15 @@ class BinaryBridge {
12455
12562
  return;
12456
12563
  const proc = this.process;
12457
12564
  this.process = null;
12458
- await new Promise((resolve) => {
12565
+ await new Promise((resolve2) => {
12459
12566
  const forceKillTimer = setTimeout(() => {
12460
12567
  proc.kill("SIGKILL");
12461
- resolve();
12568
+ resolve2();
12462
12569
  }, 5000);
12463
12570
  proc.once("exit", () => {
12464
12571
  clearTimeout(forceKillTimer);
12465
12572
  this.logVia("Process exited during coordinated binary replacement");
12466
- resolve();
12573
+ resolve2();
12467
12574
  });
12468
12575
  proc.kill("SIGTERM");
12469
12576
  });
@@ -12490,7 +12597,7 @@ class BinaryBridge {
12490
12597
  })();
12491
12598
  const useFastembedBackend = semanticBackend === undefined || semanticBackend === "fastembed" || semanticBackend === "";
12492
12599
  const ortDir = typeof this.configOverrides._ort_dylib_dir === "string" && useFastembedBackend ? this.configOverrides._ort_dylib_dir : null;
12493
- const ortLibraryPath = ortDir == null ? null : join(ortDir, process.platform === "win32" ? "onnxruntime.dll" : process.platform === "darwin" ? "libonnxruntime.dylib" : "libonnxruntime.so");
12600
+ const ortLibraryPath = ortDir == null ? null : join2(ortDir, process.platform === "win32" ? "onnxruntime.dll" : process.platform === "darwin" ? "libonnxruntime.dylib" : "libonnxruntime.so");
12494
12601
  const envPath = process.platform === "win32" && ortDir ? `${ortDir};${process.env.PATH ?? ""}` : process.env.PATH;
12495
12602
  const env = {
12496
12603
  ...process.env,
@@ -12498,7 +12605,7 @@ class BinaryBridge {
12498
12605
  };
12499
12606
  this.logVia(`bridge.spawnProcess: useFastembedBackend=${useFastembedBackend}, ` + `parentORT=${process.env.ORT_DYLIB_PATH ?? "(unset)"}, ` + `ortLibraryPath=${ortLibraryPath ?? "(none)"}`);
12500
12607
  if (useFastembedBackend) {
12501
- env.FASTEMBED_CACHE_DIR = process.env.FASTEMBED_CACHE_DIR || (typeof this.configOverrides.storage_dir === "string" ? join(this.configOverrides.storage_dir, "semantic", "models") : join(homedir() || "", ".cache", "fastembed"));
12608
+ env.FASTEMBED_CACHE_DIR = process.env.FASTEMBED_CACHE_DIR || (typeof this.configOverrides.storage_dir === "string" ? join2(this.configOverrides.storage_dir, "semantic", "models") : join2(homedir2() || "", ".cache", "fastembed"));
12502
12609
  if (process.env.ORT_DYLIB_PATH) {
12503
12610
  this.logVia(`ORT_DYLIB_PATH inherited from parent env: ${process.env.ORT_DYLIB_PATH}`);
12504
12611
  } else if (ortLibraryPath) {
@@ -12840,12 +12947,37 @@ function coerceStringArray(value) {
12840
12947
  }
12841
12948
  return [];
12842
12949
  }
12950
+ function coerceOptionalInt(v, paramName, min, max) {
12951
+ if (v === undefined || v === null || v === "")
12952
+ return;
12953
+ if (typeof v === "number" && (!Number.isFinite(v) || v === 0 && min > 0))
12954
+ return;
12955
+ const n = typeof v === "string" ? Number(v) : v;
12956
+ if (typeof n !== "number" || !Number.isInteger(n)) {
12957
+ throw new Error(`${paramName} must be an integer between ${min} and ${max}`);
12958
+ }
12959
+ if (n < min || n > max) {
12960
+ throw new Error(`${paramName} must be between ${min} and ${max}`);
12961
+ }
12962
+ return n;
12963
+ }
12964
+ function isEmptyParam(value) {
12965
+ if (value === undefined || value === null)
12966
+ return true;
12967
+ if (typeof value === "string")
12968
+ return value.length === 0;
12969
+ if (Array.isArray(value))
12970
+ return value.length === 0;
12971
+ if (typeof value === "object")
12972
+ return Object.keys(value).length === 0;
12973
+ return false;
12974
+ }
12843
12975
  // ../aft-bridge/dist/downloader.js
12844
12976
  import { spawnSync } from "node:child_process";
12845
12977
  import { createHash, randomUUID } from "node:crypto";
12846
12978
  import { chmodSync, closeSync, copyFileSync, createWriteStream, existsSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, unlinkSync, writeSync } from "node:fs";
12847
- import { homedir as homedir2 } from "node:os";
12848
- import { join as join2 } from "node:path";
12979
+ import { homedir as homedir3 } from "node:os";
12980
+ import { join as join3 } from "node:path";
12849
12981
  import { Readable } from "node:stream";
12850
12982
  import { pipeline } from "node:stream/promises";
12851
12983
 
@@ -12902,11 +13034,11 @@ function isExpectedCachedBinary(binaryPath, tag) {
12902
13034
  function getCacheDir() {
12903
13035
  if (process.platform === "win32") {
12904
13036
  const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
12905
- const base2 = localAppData || join2(homedir2(), "AppData", "Local");
12906
- return join2(base2, "aft", "bin");
13037
+ const base2 = localAppData || join3(homedir3(), "AppData", "Local");
13038
+ return join3(base2, "aft", "bin");
12907
13039
  }
12908
- const base = process.env.XDG_CACHE_HOME || join2(homedir2(), ".cache");
12909
- return join2(base, "aft", "bin");
13040
+ const base = process.env.XDG_CACHE_HOME || join3(homedir3(), ".cache");
13041
+ return join3(base, "aft", "bin");
12910
13042
  }
12911
13043
  function getBinaryName() {
12912
13044
  return process.platform === "win32" ? "aft.exe" : "aft";
@@ -12914,7 +13046,7 @@ function getBinaryName() {
12914
13046
  function getCachedBinaryPath(version) {
12915
13047
  if (!version)
12916
13048
  return null;
12917
- const binaryPath = join2(getCacheDir(), version, getBinaryName());
13049
+ const binaryPath = join3(getCacheDir(), version, getBinaryName());
12918
13050
  return existsSync(binaryPath) ? binaryPath : null;
12919
13051
  }
12920
13052
  async function downloadBinary(version) {
@@ -12931,16 +13063,16 @@ async function downloadBinary(version) {
12931
13063
  return null;
12932
13064
  }
12933
13065
  const tag = rawTag.startsWith("v") ? rawTag : `v${rawTag}`;
12934
- const versionedCacheDir = join2(getCacheDir(), tag);
13066
+ const versionedCacheDir = join3(getCacheDir(), tag);
12935
13067
  const binaryName = getBinaryName();
12936
- const binaryPath = join2(versionedCacheDir, binaryName);
13068
+ const binaryPath = join3(versionedCacheDir, binaryName);
12937
13069
  if (existsSync(binaryPath) && isExpectedCachedBinary(binaryPath, tag)) {
12938
13070
  return binaryPath;
12939
13071
  }
12940
13072
  const downloadUrl = `https://github.com/${REPO}/releases/download/${tag}/${assetName}`;
12941
13073
  const checksumUrl = `https://github.com/${REPO}/releases/download/${tag}/checksums.sha256`;
12942
13074
  log(`Downloading AFT binary (${tag}) for ${platformKey}...`);
12943
- const lockPath = join2(versionedCacheDir, ".download.lock");
13075
+ const lockPath = join3(versionedCacheDir, ".download.lock");
12944
13076
  let releaseLock = null;
12945
13077
  let binaryController = null;
12946
13078
  let checksumController = null;
@@ -13092,7 +13224,7 @@ async function acquireDownloadLock(lockPath) {
13092
13224
  if (Date.now() - startedAt > DOWNLOAD_LOCK_TIMEOUT_MS) {
13093
13225
  throw new Error(`Timed out waiting for download lock: ${lockPath}`);
13094
13226
  }
13095
- await new Promise((resolve) => setTimeout(resolve, 100));
13227
+ await new Promise((resolve2) => setTimeout(resolve2, 100));
13096
13228
  }
13097
13229
  }
13098
13230
  }
@@ -13185,18 +13317,18 @@ function stripJsoncSymbols(value) {
13185
13317
  // ../aft-bridge/dist/migration.js
13186
13318
  import { spawnSync as spawnSync2 } from "node:child_process";
13187
13319
  import { existsSync as existsSync4, mkdirSync as mkdirSync4 } from "node:fs";
13188
- import { homedir as homedir4, tmpdir } from "node:os";
13189
- import { dirname as dirname2, join as join5 } from "node:path";
13320
+ import { homedir as homedir5, tmpdir } from "node:os";
13321
+ import { dirname as dirname2, join as join6 } from "node:path";
13190
13322
 
13191
13323
  // ../aft-bridge/dist/paths.js
13192
13324
  import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync as renameSync2, writeFileSync } from "node:fs";
13193
- import { dirname, join as join3 } from "node:path";
13325
+ import { dirname, join as join4 } from "node:path";
13194
13326
  function resolveHarnessStoragePath(storageRoot, harness, ...segments) {
13195
- return join3(storageRoot, harness, ...segments);
13327
+ return join4(storageRoot, harness, ...segments);
13196
13328
  }
13197
13329
  function repairRootScopedStorageFile(storageRoot, harness, fileName) {
13198
13330
  const harnessPath = resolveHarnessStoragePath(storageRoot, harness, fileName);
13199
- const rootPath = join3(storageRoot, fileName);
13331
+ const rootPath = join4(storageRoot, fileName);
13200
13332
  if (existsSync2(harnessPath) || !existsSync2(rootPath))
13201
13333
  return harnessPath;
13202
13334
  try {
@@ -13242,8 +13374,8 @@ function markAnnouncementSeen(storageRoot, harness, currentVersion) {
13242
13374
  import { execSync } from "node:child_process";
13243
13375
  import { chmodSync as chmodSync2, closeSync as closeSync2, copyFileSync as copyFileSync2, existsSync as existsSync3, mkdirSync as mkdirSync3, openSync as openSync2, readSync, renameSync as renameSync3, unlinkSync as unlinkSync2 } from "node:fs";
13244
13376
  import { createRequire as createRequire2 } from "node:module";
13245
- import { homedir as homedir3 } from "node:os";
13246
- import { join as join4 } from "node:path";
13377
+ import { homedir as homedir4 } from "node:os";
13378
+ import { join as join5 } from "node:path";
13247
13379
  var ensureBinaryForResolver = ensureBinary;
13248
13380
  function copyToVersionedCache(npmBinaryPath, knownVersion) {
13249
13381
  try {
@@ -13252,9 +13384,9 @@ function copyToVersionedCache(npmBinaryPath, knownVersion) {
13252
13384
  return null;
13253
13385
  const tag = version.startsWith("v") ? version : `v${version}`;
13254
13386
  const cacheDir = getCacheDir();
13255
- const versionedDir = join4(cacheDir, tag);
13387
+ const versionedDir = join5(cacheDir, tag);
13256
13388
  const ext = process.platform === "win32" ? ".exe" : "";
13257
- const cachedPath = join4(versionedDir, `aft${ext}`);
13389
+ const cachedPath = join5(versionedDir, `aft${ext}`);
13258
13390
  if (existsSync3(cachedPath)) {
13259
13391
  const cachedVersion = readBinaryVersion(cachedPath);
13260
13392
  if (cachedVersion === version)
@@ -13284,18 +13416,18 @@ function normalizeBareVersion(version) {
13284
13416
  return version.startsWith("v") ? version.slice(1) : version;
13285
13417
  }
13286
13418
  function homeDirFromEnv(env) {
13287
- return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir3();
13419
+ return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir4();
13288
13420
  }
13289
13421
  function cacheDirFromEnv(env) {
13290
13422
  if (process.platform === "win32") {
13291
- const base2 = env.LOCALAPPDATA || env.APPDATA || join4(homeDirFromEnv(env), "AppData", "Local");
13292
- return join4(base2, "aft", "bin");
13423
+ const base2 = env.LOCALAPPDATA || env.APPDATA || join5(homeDirFromEnv(env), "AppData", "Local");
13424
+ return join5(base2, "aft", "bin");
13293
13425
  }
13294
- const base = env.XDG_CACHE_HOME || join4(homeDirFromEnv(env), ".cache");
13295
- return join4(base, "aft", "bin");
13426
+ const base = env.XDG_CACHE_HOME || join5(homeDirFromEnv(env), ".cache");
13427
+ return join5(base, "aft", "bin");
13296
13428
  }
13297
13429
  function cachedBinaryPathFromEnv(version, env, ext) {
13298
- const binaryPath = join4(cacheDirFromEnv(env), version, `aft${ext}`);
13430
+ const binaryPath = join5(cacheDirFromEnv(env), version, `aft${ext}`);
13299
13431
  return existsSync3(binaryPath) ? binaryPath : null;
13300
13432
  }
13301
13433
  function isExpectedCachedBinary2(binaryPath, expectedVersion) {
@@ -13414,7 +13546,7 @@ function findBinarySync(expectedVersion) {
13414
13546
  return usable;
13415
13547
  }
13416
13548
  } catch {}
13417
- const cargoPath = join4(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
13549
+ const cargoPath = join5(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
13418
13550
  if (existsSync3(cargoPath)) {
13419
13551
  const usable = probeBinaryCandidate(cargoPath, "cargo", expectedVersion);
13420
13552
  if (usable)
@@ -13460,22 +13592,22 @@ function dataHome() {
13460
13592
  if (process.env.XDG_DATA_HOME)
13461
13593
  return process.env.XDG_DATA_HOME;
13462
13594
  if (process.platform === "win32") {
13463
- return process.env.LOCALAPPDATA || process.env.APPDATA || join5(homeDir(), "AppData", "Local");
13595
+ return process.env.LOCALAPPDATA || process.env.APPDATA || join6(homeDir(), "AppData", "Local");
13464
13596
  }
13465
- return join5(homeDir(), ".local", "share");
13597
+ return join6(homeDir(), ".local", "share");
13466
13598
  }
13467
13599
  function homeDir() {
13468
13600
  if (process.platform === "win32")
13469
- return process.env.USERPROFILE || process.env.HOME || homedir4();
13470
- return process.env.HOME || homedir4();
13601
+ return process.env.USERPROFILE || process.env.HOME || homedir5();
13602
+ return process.env.HOME || homedir5();
13471
13603
  }
13472
13604
  function resolveLegacyStorageRoot(harness) {
13473
13605
  if (harness === "pi")
13474
- return join5(homeDir(), ".pi", "agent", "aft");
13475
- return join5(dataHome(), "opencode", "storage", "plugin", "aft");
13606
+ return join6(homeDir(), ".pi", "agent", "aft");
13607
+ return join6(dataHome(), "opencode", "storage", "plugin", "aft");
13476
13608
  }
13477
13609
  function resolveCortexKitStorageRoot() {
13478
- return join5(dataHome(), "cortexkit", "aft");
13610
+ return join6(dataHome(), "cortexkit", "aft");
13479
13611
  }
13480
13612
  function tail(value) {
13481
13613
  if (!value)
@@ -13489,12 +13621,12 @@ function spawnErrorLabel(error2) {
13489
13621
  return [code, error2.message].filter(Boolean).join(": ");
13490
13622
  }
13491
13623
  function migrationLogPath(newRoot, harness, logger) {
13492
- const desired = join5(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
13624
+ const desired = join6(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
13493
13625
  try {
13494
13626
  mkdirSync4(dirname2(desired), { recursive: true });
13495
13627
  return desired;
13496
13628
  } catch (err) {
13497
- const fallback = join5(tmpdir(), `aft-migration-${harness}-${Date.now()}.jsonl`);
13629
+ const fallback = join6(tmpdir(), `aft-migration-${harness}-${Date.now()}.jsonl`);
13498
13630
  logger?.warn?.(`Failed to create AFT migration log directory ${dirname2(desired)}: ${err instanceof Error ? err.message : String(err)}. ` + `Using fallback log path ${fallback}.`);
13499
13631
  return fallback;
13500
13632
  }
@@ -13557,13 +13689,13 @@ async function ensureStorageMigrated(opts) {
13557
13689
  }
13558
13690
  // ../aft-bridge/dist/npm-resolver.js
13559
13691
  import { readdirSync, statSync as statSync2 } from "node:fs";
13560
- import { homedir as homedir5 } from "node:os";
13561
- import { delimiter, dirname as dirname3, isAbsolute, join as join6 } from "node:path";
13692
+ import { homedir as homedir6 } from "node:os";
13693
+ import { delimiter, dirname as dirname3, isAbsolute as isAbsolute2, join as join7 } from "node:path";
13562
13694
  function defaultDeps() {
13563
13695
  return {
13564
13696
  platform: process.platform,
13565
13697
  env: process.env,
13566
- home: homedir5(),
13698
+ home: homedir6(),
13567
13699
  execPath: process.execPath
13568
13700
  };
13569
13701
  }
@@ -13582,16 +13714,16 @@ function npmFromPath(deps) {
13582
13714
  const raw = deps.env.PATH ?? deps.env.Path ?? "";
13583
13715
  for (const entry of raw.split(delimiter)) {
13584
13716
  const dir = entry.trim().replace(/^"|"$/g, "");
13585
- if (!dir || !isAbsolute(dir))
13717
+ if (!dir || !isAbsolute2(dir))
13586
13718
  continue;
13587
- if (isFile(join6(dir, name)))
13719
+ if (isFile(join7(dir, name)))
13588
13720
  return dir;
13589
13721
  }
13590
13722
  return null;
13591
13723
  }
13592
13724
  function npmAdjacentToNode(deps) {
13593
13725
  const dir = dirname3(deps.execPath);
13594
- return isFile(join6(dir, npmBinaryName(deps.platform))) ? dir : null;
13726
+ return isFile(join7(dir, npmBinaryName(deps.platform))) ? dir : null;
13595
13727
  }
13596
13728
  function highestVersionedNodeBin(installsDir, name) {
13597
13729
  let entries;
@@ -13600,8 +13732,8 @@ function highestVersionedNodeBin(installsDir, name) {
13600
13732
  } catch {
13601
13733
  return null;
13602
13734
  }
13603
- const candidates = entries.filter((v) => isFile(join6(installsDir, v, "bin", name))).sort((a, b) => compareVersionsDesc(a, b));
13604
- return candidates.length > 0 ? join6(installsDir, candidates[0], "bin") : null;
13735
+ const candidates = entries.filter((v) => isFile(join7(installsDir, v, "bin", name))).sort((a, b) => compareVersionsDesc(a, b));
13736
+ return candidates.length > 0 ? join7(installsDir, candidates[0], "bin") : null;
13605
13737
  }
13606
13738
  function compareVersionsDesc(a, b) {
13607
13739
  const pa = a.replace(/^v/, "").split(".").map((n) => Number.parseInt(n, 10));
@@ -13626,22 +13758,22 @@ function wellKnownNpmDirs(deps) {
13626
13758
  const programFiles = env.ProgramFiles || "C:\\Program Files";
13627
13759
  const appData = env.APPDATA;
13628
13760
  const localAppData = env.LOCALAPPDATA;
13629
- push(join6(programFiles, "nodejs"));
13761
+ push(join7(programFiles, "nodejs"));
13630
13762
  if (appData)
13631
- push(join6(appData, "npm"));
13763
+ push(join7(appData, "npm"));
13632
13764
  if (localAppData)
13633
- push(join6(localAppData, "Volta", "bin"));
13765
+ push(join7(localAppData, "Volta", "bin"));
13634
13766
  if (env.NVM_SYMLINK)
13635
13767
  push(env.NVM_SYMLINK);
13636
13768
  } else {
13637
13769
  if (env.NVM_BIN)
13638
13770
  push(env.NVM_BIN);
13639
- push(highestVersionedNodeBin(join6(home, ".nvm", "versions", "node"), name));
13640
- push(highestVersionedNodeBin(join6(home, ".local", "share", "mise", "installs", "node"), name));
13641
- push(highestVersionedNodeBin(join6(home, ".asdf", "installs", "nodejs"), name));
13642
- push(join6(home, ".volta", "bin"));
13643
- push(join6(home, ".asdf", "shims"));
13644
- const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin", join6(home, ".local", "bin")]);
13771
+ push(highestVersionedNodeBin(join7(home, ".nvm", "versions", "node"), name));
13772
+ push(highestVersionedNodeBin(join7(home, ".local", "share", "mise", "installs", "node"), name));
13773
+ push(highestVersionedNodeBin(join7(home, ".asdf", "installs", "nodejs"), name));
13774
+ push(join7(home, ".volta", "bin"));
13775
+ push(join7(home, ".asdf", "shims"));
13776
+ const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin", join7(home, ".local", "bin")]);
13645
13777
  for (const dir of systemDirs)
13646
13778
  push(dir);
13647
13779
  }
@@ -13651,12 +13783,12 @@ function resolveNpm(deps = defaultDeps()) {
13651
13783
  const name = npmBinaryName(deps.platform);
13652
13784
  const onPath = npmFromPath(deps);
13653
13785
  if (onPath)
13654
- return { command: join6(onPath, name), binDir: onPath };
13786
+ return { command: join7(onPath, name), binDir: onPath };
13655
13787
  const adjacent = npmAdjacentToNode(deps);
13656
13788
  if (adjacent)
13657
- return { command: join6(adjacent, name), binDir: adjacent };
13789
+ return { command: join7(adjacent, name), binDir: adjacent };
13658
13790
  for (const dir of wellKnownNpmDirs(deps)) {
13659
- const candidate = join6(dir, name);
13791
+ const candidate = join7(dir, name);
13660
13792
  if (isFile(candidate))
13661
13793
  return { command: candidate, binDir: dir };
13662
13794
  }
@@ -13673,7 +13805,7 @@ function npmSpawnEnv(resolved, baseEnv = process.env) {
13673
13805
  import { execFileSync } from "node:child_process";
13674
13806
  import { createHash as createHash2 } from "node:crypto";
13675
13807
  import { chmodSync as chmodSync3, closeSync as closeSync3, copyFileSync as copyFileSync3, createWriteStream as createWriteStream2, existsSync as existsSync5, lstatSync, mkdirSync as mkdirSync5, openSync as openSync3, readdirSync as readdirSync2, readFileSync as readFileSync3, readlinkSync, realpathSync, rmSync as rmSync2, statSync as statSync3, symlinkSync, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "node:fs";
13676
- import { basename, dirname as dirname4, isAbsolute as isAbsolute2, join as join7, relative, resolve, win32 } from "node:path";
13808
+ import { basename, dirname as dirname4, isAbsolute as isAbsolute3, join as join8, relative as relative2, resolve as resolve2, win32 } from "node:path";
13677
13809
  import { Readable as Readable2 } from "node:stream";
13678
13810
  import { pipeline as pipeline2 } from "node:stream/promises";
13679
13811
  var ORT_VERSION = "1.24.4";
@@ -13736,10 +13868,10 @@ function getManualInstallHint() {
13736
13868
  }
13737
13869
  async function ensureOnnxRuntime(storageDir) {
13738
13870
  const info = getPlatformInfo();
13739
- const ortVersionDir = join7(storageDir, "onnxruntime", ORT_VERSION);
13871
+ const ortVersionDir = join8(storageDir, "onnxruntime", ORT_VERSION);
13740
13872
  const libName = info?.libName ?? "libonnxruntime.dylib";
13741
13873
  const resolvedOrtDir = resolveCachedOnnxRuntimeDir(ortVersionDir, libName);
13742
- const libPath = join7(resolvedOrtDir, libName);
13874
+ const libPath = join8(resolvedOrtDir, libName);
13743
13875
  if (existsSync5(libPath)) {
13744
13876
  const meta = readOnnxInstalledMeta(ortVersionDir);
13745
13877
  if (meta?.sha256) {
@@ -13769,9 +13901,9 @@ async function ensureOnnxRuntime(storageDir) {
13769
13901
  warn(`ONNX Runtime auto-download not available for ${process.platform}/${process.arch}. Install manually: ${getManualInstallHint()}`);
13770
13902
  return null;
13771
13903
  }
13772
- const onnxBaseDir = join7(storageDir, "onnxruntime");
13904
+ const onnxBaseDir = join8(storageDir, "onnxruntime");
13773
13905
  mkdirSync5(onnxBaseDir, { recursive: true });
13774
- const lockPath = join7(onnxBaseDir, ONNX_LOCK_FILE);
13906
+ const lockPath = join8(onnxBaseDir, ONNX_LOCK_FILE);
13775
13907
  cleanupAbandonedStagingDirs(onnxBaseDir);
13776
13908
  if (!acquireLock(lockPath)) {
13777
13909
  warn(`ONNX Runtime install already in progress in another process (lock: ${lockPath}). Skipping.`);
@@ -13790,7 +13922,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
13790
13922
  for (const entry of entries) {
13791
13923
  if (!entry.startsWith(`${ORT_VERSION}.tmp.`))
13792
13924
  continue;
13793
- const stagingDir = join7(onnxBaseDir, entry);
13925
+ const stagingDir = join8(onnxBaseDir, entry);
13794
13926
  const parts = entry.split(".");
13795
13927
  const pidStr = parts[parts.length - 2];
13796
13928
  const pid = pidStr ? Number.parseInt(pidStr, 10) : NaN;
@@ -13827,7 +13959,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
13827
13959
  }
13828
13960
  function cleanupIncompleteTargetIfUnowned(ortDir) {
13829
13961
  try {
13830
- if (existsSync5(ortDir) && !existsSync5(join7(ortDir, ONNX_INSTALLED_META_FILE))) {
13962
+ if (existsSync5(ortDir) && !existsSync5(join8(ortDir, ONNX_INSTALLED_META_FILE))) {
13831
13963
  log(`[onnx] removing half-populated install dir ${ortDir} (no meta file)`);
13832
13964
  rmSync2(ortDir, { recursive: true, force: true });
13833
13965
  }
@@ -13855,8 +13987,8 @@ function parseOnnxVersionFromDirectoryPath(value) {
13855
13987
  return null;
13856
13988
  }
13857
13989
  function isPathInsideRoot(root, candidate) {
13858
- const rel = relative(root, candidate);
13859
- return rel === "" || !rel.startsWith("../") && !rel.startsWith("..\\") && rel !== ".." && !isAbsolute2(rel) && !win32.isAbsolute(rel);
13990
+ const rel = relative2(root, candidate);
13991
+ return rel === "" || !rel.startsWith("../") && !rel.startsWith("..\\") && rel !== ".." && !isAbsolute3(rel) && !win32.isAbsolute(rel);
13860
13992
  }
13861
13993
  function detectOnnxVersion(libDir, libName) {
13862
13994
  try {
@@ -13871,7 +14003,7 @@ function detectOnnxVersion(libDir, libName) {
13871
14003
  if (version)
13872
14004
  return version;
13873
14005
  }
13874
- const base = join7(libDir, libName);
14006
+ const base = join8(libDir, libName);
13875
14007
  if (existsSync5(base)) {
13876
14008
  try {
13877
14009
  const real = realpathSync(base);
@@ -13907,7 +14039,7 @@ function pathEntriesForPlatform() {
13907
14039
  return pathEnvValue().split(delimiter2).map((entry) => entry.trim().replace(/^"|"$/g, "")).filter((entry) => {
13908
14040
  if (!entry || entry === "." || entry.includes("\x00"))
13909
14041
  return false;
13910
- return isAbsolute2(entry) || win32.isAbsolute(entry);
14042
+ return isAbsolute3(entry) || win32.isAbsolute(entry);
13911
14043
  });
13912
14044
  }
13913
14045
  function directoryContainsLibrary(dir, libName) {
@@ -13923,10 +14055,10 @@ function directoryContainsLibrary(dir, libName) {
13923
14055
  }
13924
14056
  }
13925
14057
  function resolveCachedOnnxRuntimeDir(ortVersionDir, libName) {
13926
- if (existsSync5(join7(ortVersionDir, libName)))
14058
+ if (existsSync5(join8(ortVersionDir, libName)))
13927
14059
  return ortVersionDir;
13928
- const libSubdir = join7(ortVersionDir, "lib");
13929
- if (existsSync5(join7(libSubdir, libName)))
14060
+ const libSubdir = join8(ortVersionDir, "lib");
14061
+ if (existsSync5(join8(libSubdir, libName)))
13930
14062
  return libSubdir;
13931
14063
  return ortVersionDir;
13932
14064
  }
@@ -13941,12 +14073,12 @@ function findSystemOnnxRuntime(libName) {
13941
14073
  } else if (process.platform === "win32") {
13942
14074
  const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
13943
14075
  const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
13944
- searchPaths.push(join7(programFiles, "onnxruntime", "lib"), join7(programFiles, "Microsoft ONNX Runtime", "lib"), join7(programFiles, "Microsoft Machine Learning", "lib"), join7(programFilesX86, "onnxruntime", "lib"), ...(() => {
14076
+ searchPaths.push(join8(programFiles, "onnxruntime", "lib"), join8(programFiles, "Microsoft ONNX Runtime", "lib"), join8(programFiles, "Microsoft Machine Learning", "lib"), join8(programFilesX86, "onnxruntime", "lib"), ...(() => {
13945
14077
  const nugetPaths = [];
13946
14078
  const userProfile = process.env.USERPROFILE ?? "";
13947
14079
  if (!userProfile)
13948
14080
  return nugetPaths;
13949
- const nugetPackageDir = join7(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
14081
+ const nugetPackageDir = join8(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
13950
14082
  if (!existsSync5(nugetPackageDir))
13951
14083
  return nugetPaths;
13952
14084
  try {
@@ -13955,7 +14087,7 @@ function findSystemOnnxRuntime(libName) {
13955
14087
  continue;
13956
14088
  if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
13957
14089
  continue;
13958
- nugetPaths.push(join7(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join7(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
14090
+ nugetPaths.push(join8(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join8(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
13959
14091
  }
13960
14092
  } catch (err) {
13961
14093
  warn(`Failed to scan NuGet ONNX Runtime cache ${nugetPackageDir}: ${err instanceof Error ? err.message : String(err)}`);
@@ -13967,7 +14099,7 @@ function findSystemOnnxRuntime(libName) {
13967
14099
  const normalizeCase = process.platform === "win32" || process.platform === "darwin";
13968
14100
  const seen = new Set;
13969
14101
  const uniquePaths = searchPaths.filter((p) => {
13970
- let key = resolve(p).replace(/[/\\]+$/, "");
14102
+ let key = resolve2(p).replace(/[/\\]+$/, "");
13971
14103
  if (normalizeCase)
13972
14104
  key = key.toLowerCase();
13973
14105
  if (seen.has(key))
@@ -13977,7 +14109,7 @@ function findSystemOnnxRuntime(libName) {
13977
14109
  });
13978
14110
  const unknownVersionPaths = [];
13979
14111
  for (const dir of uniquePaths) {
13980
- const libPath = join7(dir, libName);
14112
+ const libPath = join8(dir, libName);
13981
14113
  if (process.platform === "win32") {
13982
14114
  if (!directoryContainsLibrary(dir, libName))
13983
14115
  continue;
@@ -14043,19 +14175,19 @@ function validateExtractedTree(stagingRoot) {
14043
14175
  const walk = (dir) => {
14044
14176
  const entries = readdirSync2(dir);
14045
14177
  for (const entry of entries) {
14046
- const fullPath = join7(dir, entry);
14178
+ const fullPath = join8(dir, entry);
14047
14179
  const lst = lstatSync(fullPath);
14048
14180
  if (lst.isSymbolicLink()) {
14049
14181
  const linkTarget = readlinkSync(fullPath);
14050
- const resolvedTarget = resolve(dirname4(fullPath), linkTarget);
14051
- const rel2 = relative(realRoot, resolvedTarget);
14052
- if (rel2.startsWith("..") || isAbsolute2(rel2) || win32.isAbsolute(rel2)) {
14182
+ const resolvedTarget = resolve2(dirname4(fullPath), linkTarget);
14183
+ const rel2 = relative2(realRoot, resolvedTarget);
14184
+ if (rel2.startsWith("..") || isAbsolute3(rel2) || win32.isAbsolute(rel2)) {
14053
14185
  throw new Error(`extracted symlink ${fullPath} points outside staging root: ${linkTarget}`);
14054
14186
  }
14055
14187
  continue;
14056
14188
  }
14057
- const rel = relative(realRoot, fullPath);
14058
- if (rel.startsWith("..") || isAbsolute2(rel) || win32.isAbsolute(rel)) {
14189
+ const rel = relative2(realRoot, fullPath);
14190
+ if (rel.startsWith("..") || isAbsolute3(rel) || win32.isAbsolute(rel)) {
14059
14191
  throw new Error(`extracted entry ${fullPath} escapes staging root`);
14060
14192
  }
14061
14193
  if (lst.isDirectory()) {
@@ -14078,7 +14210,7 @@ async function downloadOnnxRuntime(info, targetDir) {
14078
14210
  const tmpDir = `${targetDir}.tmp.${process.pid}.${Date.now().toString(36)}`;
14079
14211
  try {
14080
14212
  mkdirSync5(tmpDir, { recursive: true });
14081
- const archivePath = join7(tmpDir, `onnxruntime.${info.archiveType}`);
14213
+ const archivePath = join8(tmpDir, `onnxruntime.${info.archiveType}`);
14082
14214
  await downloadFileWithCap(url, archivePath);
14083
14215
  const archiveSha256 = sha256File(archivePath);
14084
14216
  log(`ONNX Runtime archive sha256=${archiveSha256}`);
@@ -14094,7 +14226,7 @@ async function downloadOnnxRuntime(info, targetDir) {
14094
14226
  unlinkSync3(archivePath);
14095
14227
  } catch {}
14096
14228
  validateExtractedTree(tmpDir);
14097
- const extractedDir = join7(tmpDir, info.assetName, "lib");
14229
+ const extractedDir = join8(tmpDir, info.assetName, "lib");
14098
14230
  if (!existsSync5(extractedDir)) {
14099
14231
  throw new Error(`Expected directory not found: ${extractedDir}`);
14100
14232
  }
@@ -14103,7 +14235,7 @@ async function downloadOnnxRuntime(info, targetDir) {
14103
14235
  const realFiles = [];
14104
14236
  const symlinks = [];
14105
14237
  for (const libFile of libFiles) {
14106
- const src = join7(extractedDir, libFile);
14238
+ const src = join8(extractedDir, libFile);
14107
14239
  try {
14108
14240
  const stat = lstatSync(src);
14109
14241
  log(`ORT extract: ${libFile} — isSymlink=${stat.isSymbolicLink()}, isFile=${stat.isFile()}, size=${stat.size}`);
@@ -14118,7 +14250,7 @@ async function downloadOnnxRuntime(info, targetDir) {
14118
14250
  }
14119
14251
  }
14120
14252
  copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks);
14121
- const libPath = join7(targetDir, info.libName);
14253
+ const libPath = join8(targetDir, info.libName);
14122
14254
  let libHash = null;
14123
14255
  try {
14124
14256
  libHash = sha256File(libPath);
@@ -14143,8 +14275,8 @@ async function downloadOnnxRuntime(info, targetDir) {
14143
14275
  function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, copyFile = copyFileSync3) {
14144
14276
  const requiredLibs = new Set([info.libName]);
14145
14277
  for (const libFile of realFiles) {
14146
- const src = join7(extractedDir, libFile);
14147
- const dst = join7(targetDir, libFile);
14278
+ const src = join8(extractedDir, libFile);
14279
+ const dst = join8(targetDir, libFile);
14148
14280
  try {
14149
14281
  copyFile(src, dst);
14150
14282
  if (process.platform !== "win32") {
@@ -14160,12 +14292,12 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
14160
14292
  }
14161
14293
  const targetRoot = realpathSync(targetDir);
14162
14294
  for (const link of symlinks) {
14163
- const dst = join7(targetDir, link.name);
14295
+ const dst = join8(targetDir, link.name);
14164
14296
  try {
14165
14297
  unlinkSync3(dst);
14166
14298
  } catch {}
14167
- const dstForContainment = join7(targetRoot, link.name);
14168
- const resolvedTarget = resolve(dirname4(dstForContainment), link.target);
14299
+ const dstForContainment = join8(targetRoot, link.name);
14300
+ const resolvedTarget = resolve2(dirname4(dstForContainment), link.target);
14169
14301
  if (!isPathInsideRoot(targetRoot, resolvedTarget)) {
14170
14302
  const message = `ONNX Runtime symlink ${link.name} points outside install dir: ${link.target}`;
14171
14303
  if (requiredLibs.has(link.name)) {
@@ -14185,7 +14317,7 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
14185
14317
  log(`ORT extract: failed to symlink optional ${link.name}: ${symlinkErr}`);
14186
14318
  }
14187
14319
  }
14188
- const requiredPath = join7(targetDir, info.libName);
14320
+ const requiredPath = join8(targetDir, info.libName);
14189
14321
  if (!existsSync5(requiredPath)) {
14190
14322
  rmSync2(targetDir, { recursive: true, force: true });
14191
14323
  throw new Error(`Required ONNX Runtime library missing after install: ${requiredPath}`);
@@ -14212,17 +14344,17 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
14212
14344
  ...sha256 ? { sha256 } : {},
14213
14345
  archiveSha256
14214
14346
  };
14215
- writeFileSync2(join7(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
14347
+ writeFileSync2(join8(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
14216
14348
  } catch (err) {
14217
14349
  log(`[onnx] failed to write installed-meta in ${installDir}: ${err}`);
14218
14350
  }
14219
14351
  }
14220
14352
  function readOnnxInstalledMeta(installDir) {
14221
- const path = join7(installDir, ONNX_INSTALLED_META_FILE);
14353
+ const path2 = join8(installDir, ONNX_INSTALLED_META_FILE);
14222
14354
  try {
14223
- if (!statSync3(path).isFile())
14355
+ if (!statSync3(path2).isFile())
14224
14356
  return null;
14225
- const raw = readFileSync3(path, "utf8");
14357
+ const raw = readFileSync3(path2, "utf8");
14226
14358
  const parsed = JSON.parse(raw);
14227
14359
  if (typeof parsed.version !== "string" || parsed.version.length === 0)
14228
14360
  return null;
@@ -14236,9 +14368,9 @@ function readOnnxInstalledMeta(installDir) {
14236
14368
  return null;
14237
14369
  }
14238
14370
  }
14239
- function sha256File(path) {
14371
+ function sha256File(path2) {
14240
14372
  const hash = createHash2("sha256");
14241
- hash.update(readFileSync3(path));
14373
+ hash.update(readFileSync3(path2));
14242
14374
  return hash.digest("hex");
14243
14375
  }
14244
14376
  function acquireLock(lockPath) {
@@ -14898,13 +15030,13 @@ function tokenizeStage(stage) {
14898
15030
  }
14899
15031
  // ../aft-bridge/dist/pool.js
14900
15032
  import { realpathSync as realpathSync2 } from "node:fs";
14901
- import { homedir as homedir6 } from "node:os";
15033
+ import { homedir as homedir7 } from "node:os";
14902
15034
  var DEFAULT_IDLE_TIMEOUT_MS = 30 * 60 * 1000;
14903
15035
  var DEFAULT_MAX_POOL_SIZE = 8;
14904
15036
  var CLEANUP_INTERVAL_MS = 60 * 1000;
14905
15037
  function canonicalHomeDir() {
14906
15038
  try {
14907
- const home = homedir6();
15039
+ const home = homedir7();
14908
15040
  if (!home)
14909
15041
  return null;
14910
15042
  try {
@@ -15096,6 +15228,91 @@ function normalizeKey(projectRoot) {
15096
15228
  return stripped;
15097
15229
  }
15098
15230
  }
15231
+ // ../aft-bridge/dist/tool-format.js
15232
+ function asPlainObject(value) {
15233
+ if (!value || typeof value !== "object" || Array.isArray(value))
15234
+ return;
15235
+ return value;
15236
+ }
15237
+ function candidateLocation(candidate) {
15238
+ const file = typeof candidate.file === "string" && candidate.file.length > 0 ? candidate.file : undefined;
15239
+ if (!file)
15240
+ return;
15241
+ const line = typeof candidate.line === "number" && Number.isFinite(candidate.line) ? candidate.line : undefined;
15242
+ return line === undefined ? file : `${file}:${line}`;
15243
+ }
15244
+ function stringifyData(data) {
15245
+ if (data === undefined)
15246
+ return;
15247
+ try {
15248
+ return JSON.stringify(data, null, 2);
15249
+ } catch {
15250
+ return String(data);
15251
+ }
15252
+ }
15253
+ function formatBridgeErrorMessage(command, response, params = {}) {
15254
+ const code = typeof response.code === "string" && response.code.length > 0 ? response.code : undefined;
15255
+ const message = typeof response.message === "string" && response.message.length > 0 ? response.message : `${command} failed`;
15256
+ const data = asPlainObject(response.data);
15257
+ const rawCandidates = Array.isArray(response.candidates) ? response.candidates : Array.isArray(data?.candidates) ? data.candidates : undefined;
15258
+ const rawSymbol = typeof response.symbol === "string" && response.symbol.length > 0 ? response.symbol : typeof data?.symbol === "string" && data.symbol.length > 0 ? data.symbol : undefined;
15259
+ if (code === "ambiguous_target" || code === "target_symbol_not_in_file") {
15260
+ const candidates = (rawCandidates ?? []).map(asPlainObject).filter((candidate) => candidate !== undefined).map(candidateLocation).filter((candidate) => candidate !== undefined);
15261
+ if (candidates.length > 0) {
15262
+ const symbol = typeof params.toSymbol === "string" && params.toSymbol.length > 0 ? params.toSymbol : rawSymbol;
15263
+ const target = symbol ? `multiple symbols named "${symbol}"` : message.replace(/[.!?]+$/, "");
15264
+ const action = code === "ambiguous_target" ? "Pass toFile to disambiguate" : "Try one of these files for toFile";
15265
+ return `${command}: ${code} — ${target}. ${action}:
15266
+ ${candidates.map((candidate) => ` - ${candidate}`).join(`
15267
+ `)}`;
15268
+ }
15269
+ }
15270
+ if (!code)
15271
+ return message;
15272
+ const lines = [`${command}: ${code} — ${message}`];
15273
+ const extras = collectStructuredExtras(response);
15274
+ if (extras)
15275
+ lines.push(`data: ${extras}`);
15276
+ return lines.join(`
15277
+ `);
15278
+ }
15279
+ function collectStructuredExtras(response) {
15280
+ const reserved = new Set([
15281
+ "id",
15282
+ "success",
15283
+ "code",
15284
+ "message",
15285
+ "data",
15286
+ "status_bar",
15287
+ "bg_completions"
15288
+ ]);
15289
+ const extras = {};
15290
+ for (const [key, value] of Object.entries(response)) {
15291
+ if (reserved.has(key))
15292
+ continue;
15293
+ extras[key] = value;
15294
+ }
15295
+ if (Object.keys(extras).length === 0) {
15296
+ return stringifyData(response.data);
15297
+ }
15298
+ if (response.data !== undefined)
15299
+ extras.data = response.data;
15300
+ return stringifyData(extras);
15301
+ }
15302
+ function formatReadFooter(agentSpecifiedRange, data, options) {
15303
+ if (agentSpecifiedRange)
15304
+ return "";
15305
+ if (!data.truncated)
15306
+ return "";
15307
+ const startLine = data.start_line;
15308
+ const endLine = data.end_line;
15309
+ const totalLines = data.total_lines;
15310
+ if (startLine === undefined || endLine === undefined || totalLines === undefined) {
15311
+ return "";
15312
+ }
15313
+ return `
15314
+ (Showing lines ${startLine}-${endLine} of ${totalLines}. Use ${options.rangeHint} to read other sections.)`;
15315
+ }
15099
15316
  // ../aft-bridge/dist/zoom-format.js
15100
15317
  function formatZoomText(targetLabel, response) {
15101
15318
  const range = response.range;
@@ -15176,13 +15393,36 @@ function formatZoomMultiTargetResult(entries) {
15176
15393
 
15177
15394
  `) };
15178
15395
  }
15396
+ function isRustZoomBatchEnvelope(response) {
15397
+ if (!Array.isArray(response.symbols) || response.symbols.length === 0) {
15398
+ return false;
15399
+ }
15400
+ return response.symbols.every((entry) => {
15401
+ if (!entry || typeof entry !== "object")
15402
+ return false;
15403
+ const row = entry;
15404
+ return typeof row.name === "string" && row.response !== undefined && row.response !== null;
15405
+ });
15406
+ }
15407
+ function unwrapRustZoomBatchEnvelope(response) {
15408
+ if (!isRustZoomBatchEnvelope(response)) {
15409
+ return null;
15410
+ }
15411
+ const names = [];
15412
+ const responses = [];
15413
+ for (const entry of response.symbols) {
15414
+ names.push(entry.name);
15415
+ responses.push(entry.response);
15416
+ }
15417
+ return { names, responses };
15418
+ }
15179
15419
  // src/logger.ts
15180
15420
  import * as fs from "node:fs";
15181
- import * as os from "node:os";
15182
- import * as path from "node:path";
15421
+ import * as os2 from "node:os";
15422
+ import * as path2 from "node:path";
15183
15423
  var TAG = "[aft-pi]";
15184
15424
  var isTestEnv = process.env.BUN_TEST === "1" || false;
15185
- var logFile = path.join(os.tmpdir(), isTestEnv ? "aft-pi-test.log" : "aft-pi.log");
15425
+ var logFile = path2.join(os2.tmpdir(), isTestEnv ? "aft-pi-test.log" : "aft-pi.log");
15186
15426
  var useStderr = process.env.AFT_LOG_STDERR === "1";
15187
15427
  var buffer = [];
15188
15428
  var flushTimer = null;
@@ -15818,7 +16058,7 @@ import {
15818
16058
  // package.json
15819
16059
  var package_default = {
15820
16060
  name: "@cortexkit/aft-pi",
15821
- version: "0.39.0",
16061
+ version: "0.39.1",
15822
16062
  type: "module",
15823
16063
  description: "Pi coding agent extension for Agent File Tools (AFT) — tree-sitter and LSP-powered code analysis",
15824
16064
  main: "dist/index.js",
@@ -15841,7 +16081,7 @@ var package_default = {
15841
16081
  "test:unit": "bun test src/__tests__ --path-ignore-patterns 'src/__tests__/e2e/**'"
15842
16082
  },
15843
16083
  dependencies: {
15844
- "@cortexkit/aft-bridge": "0.39.0",
16084
+ "@cortexkit/aft-bridge": "0.39.1",
15845
16085
  "@xterm/headless": "^5.5.0",
15846
16086
  "comment-json": "^5.0.0",
15847
16087
  diff: "^8.0.4",
@@ -15849,12 +16089,12 @@ var package_default = {
15849
16089
  zod: "^4.1.8"
15850
16090
  },
15851
16091
  optionalDependencies: {
15852
- "@cortexkit/aft-darwin-arm64": "0.39.0",
15853
- "@cortexkit/aft-darwin-x64": "0.39.0",
15854
- "@cortexkit/aft-linux-arm64": "0.39.0",
15855
- "@cortexkit/aft-linux-x64": "0.39.0",
15856
- "@cortexkit/aft-win32-arm64": "0.39.0",
15857
- "@cortexkit/aft-win32-x64": "0.39.0"
16092
+ "@cortexkit/aft-darwin-arm64": "0.39.1",
16093
+ "@cortexkit/aft-darwin-x64": "0.39.1",
16094
+ "@cortexkit/aft-linux-arm64": "0.39.1",
16095
+ "@cortexkit/aft-linux-x64": "0.39.1",
16096
+ "@cortexkit/aft-win32-arm64": "0.39.1",
16097
+ "@cortexkit/aft-win32-x64": "0.39.1"
15858
16098
  },
15859
16099
  devDependencies: {
15860
16100
  "@earendil-works/pi-coding-agent": "*",
@@ -16087,101 +16327,6 @@ function formatStatusDialogMessage(status) {
16087
16327
  // src/tools/_shared.ts
16088
16328
  import { Type } from "typebox";
16089
16329
  var optionalInt = (_min, _max) => Type.Optional(Type.Any({ description: "(integer)" }));
16090
- function coerceOptionalInt(v, paramName, min, max) {
16091
- if (v === undefined || v === null || v === "")
16092
- return;
16093
- if (typeof v === "number" && (!Number.isFinite(v) || v === 0 && min > 0))
16094
- return;
16095
- const n = typeof v === "string" ? Number(v) : v;
16096
- if (typeof n !== "number" || !Number.isInteger(n)) {
16097
- throw new Error(`${paramName} must be an integer between ${min} and ${max}`);
16098
- }
16099
- if (n < min || n > max) {
16100
- throw new Error(`${paramName} must be between ${min} and ${max}`);
16101
- }
16102
- return n;
16103
- }
16104
- function isEmptyParam(value) {
16105
- if (value === undefined || value === null)
16106
- return true;
16107
- if (typeof value === "string")
16108
- return value.length === 0;
16109
- if (Array.isArray(value))
16110
- return value.length === 0;
16111
- if (typeof value === "object")
16112
- return Object.keys(value).length === 0;
16113
- return false;
16114
- }
16115
- function asPlainObject(value) {
16116
- if (!value || typeof value !== "object" || Array.isArray(value))
16117
- return;
16118
- return value;
16119
- }
16120
- function candidateLocation(candidate) {
16121
- const file = typeof candidate.file === "string" && candidate.file.length > 0 ? candidate.file : undefined;
16122
- if (!file)
16123
- return;
16124
- const line = typeof candidate.line === "number" && Number.isFinite(candidate.line) ? candidate.line : undefined;
16125
- return line === undefined ? file : `${file}:${line}`;
16126
- }
16127
- function stringifyData(data) {
16128
- if (data === undefined)
16129
- return;
16130
- try {
16131
- return JSON.stringify(data, null, 2);
16132
- } catch {
16133
- return String(data);
16134
- }
16135
- }
16136
- function formatBridgeErrorMessage(command, response, params = {}) {
16137
- const code = typeof response.code === "string" && response.code.length > 0 ? response.code : undefined;
16138
- const message = typeof response.message === "string" && response.message.length > 0 ? response.message : `${command} failed`;
16139
- const data = asPlainObject(response.data);
16140
- const rawCandidates = Array.isArray(response.candidates) ? response.candidates : Array.isArray(data?.candidates) ? data.candidates : undefined;
16141
- const rawSymbol = typeof response.symbol === "string" && response.symbol.length > 0 ? response.symbol : typeof data?.symbol === "string" && data.symbol.length > 0 ? data.symbol : undefined;
16142
- if (code === "ambiguous_target" || code === "target_symbol_not_in_file") {
16143
- const candidates = (rawCandidates ?? []).map(asPlainObject).filter((candidate) => candidate !== undefined).map(candidateLocation).filter((candidate) => candidate !== undefined);
16144
- if (candidates.length > 0) {
16145
- const symbol = typeof params.toSymbol === "string" && params.toSymbol.length > 0 ? params.toSymbol : rawSymbol;
16146
- const target = symbol ? `multiple symbols named "${symbol}"` : message.replace(/[.!?]+$/, "");
16147
- const action = code === "ambiguous_target" ? "Pass toFile to disambiguate" : "Try one of these files for toFile";
16148
- return `${command}: ${code} — ${target}. ${action}:
16149
- ${candidates.map((candidate) => ` - ${candidate}`).join(`
16150
- `)}`;
16151
- }
16152
- }
16153
- if (!code)
16154
- return message;
16155
- const lines = [`${command}: ${code} — ${message}`];
16156
- const extras = collectStructuredExtras(response);
16157
- if (extras)
16158
- lines.push(`data: ${extras}`);
16159
- return lines.join(`
16160
- `);
16161
- }
16162
- function collectStructuredExtras(response) {
16163
- const reserved = new Set([
16164
- "id",
16165
- "success",
16166
- "code",
16167
- "message",
16168
- "data",
16169
- "status_bar",
16170
- "bg_completions"
16171
- ]);
16172
- const extras = {};
16173
- for (const [key, value] of Object.entries(response)) {
16174
- if (reserved.has(key))
16175
- continue;
16176
- extras[key] = value;
16177
- }
16178
- if (Object.keys(extras).length === 0) {
16179
- return stringifyData(response.data);
16180
- }
16181
- if (response.data !== undefined)
16182
- extras.data = response.data;
16183
- return stringifyData(extras);
16184
- }
16185
16330
  function bridgeFor(ctx, cwd) {
16186
16331
  return ctx.pool.getBridge(cwd);
16187
16332
  }
@@ -16524,8 +16669,8 @@ function registerStatusCommand(pi, ctx) {
16524
16669
 
16525
16670
  // src/config.ts
16526
16671
  import { existsSync as existsSync6, readFileSync as readFileSync4, renameSync as renameSync4, unlinkSync as unlinkSync4, writeFileSync as writeFileSync3 } from "node:fs";
16527
- import { homedir as homedir7 } from "node:os";
16528
- import { join as join9 } from "node:path";
16672
+ import { homedir as homedir8 } from "node:os";
16673
+ import { join as join10 } from "node:path";
16529
16674
  var import_comment_json = __toESM(require_src2(), 1);
16530
16675
 
16531
16676
  // ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
@@ -17293,10 +17438,10 @@ function mergeDefs(...defs) {
17293
17438
  function cloneDef(schema) {
17294
17439
  return mergeDefs(schema._zod.def);
17295
17440
  }
17296
- function getElementAtPath(obj, path2) {
17297
- if (!path2)
17441
+ function getElementAtPath(obj, path3) {
17442
+ if (!path3)
17298
17443
  return obj;
17299
- return path2.reduce((acc, key) => acc?.[key], obj);
17444
+ return path3.reduce((acc, key) => acc?.[key], obj);
17300
17445
  }
17301
17446
  function promiseAllObject(promisesObj) {
17302
17447
  const keys = Object.keys(promisesObj);
@@ -17677,11 +17822,11 @@ function aborted(x, startIndex = 0) {
17677
17822
  }
17678
17823
  return false;
17679
17824
  }
17680
- function prefixIssues(path2, issues) {
17825
+ function prefixIssues(path3, issues) {
17681
17826
  return issues.map((iss) => {
17682
17827
  var _a;
17683
17828
  (_a = iss).path ?? (_a.path = []);
17684
- iss.path.unshift(path2);
17829
+ iss.path.unshift(path3);
17685
17830
  return iss;
17686
17831
  });
17687
17832
  }
@@ -17864,7 +18009,7 @@ function formatError(error3, mapper = (issue2) => issue2.message) {
17864
18009
  }
17865
18010
  function treeifyError(error3, mapper = (issue2) => issue2.message) {
17866
18011
  const result = { errors: [] };
17867
- const processError = (error4, path2 = []) => {
18012
+ const processError = (error4, path3 = []) => {
17868
18013
  var _a, _b;
17869
18014
  for (const issue2 of error4.issues) {
17870
18015
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -17874,7 +18019,7 @@ function treeifyError(error3, mapper = (issue2) => issue2.message) {
17874
18019
  } else if (issue2.code === "invalid_element") {
17875
18020
  processError({ issues: issue2.issues }, issue2.path);
17876
18021
  } else {
17877
- const fullpath = [...path2, ...issue2.path];
18022
+ const fullpath = [...path3, ...issue2.path];
17878
18023
  if (fullpath.length === 0) {
17879
18024
  result.errors.push(mapper(issue2));
17880
18025
  continue;
@@ -17906,8 +18051,8 @@ function treeifyError(error3, mapper = (issue2) => issue2.message) {
17906
18051
  }
17907
18052
  function toDotPath(_path) {
17908
18053
  const segs = [];
17909
- const path2 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
17910
- for (const seg of path2) {
18054
+ const path3 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
18055
+ for (const seg of path3) {
17911
18056
  if (typeof seg === "number")
17912
18057
  segs.push(`[${seg}]`);
17913
18058
  else if (typeof seg === "symbol")
@@ -29654,13 +29799,13 @@ function resolveRef(ref, ctx) {
29654
29799
  if (!ref.startsWith("#")) {
29655
29800
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
29656
29801
  }
29657
- const path2 = ref.slice(1).split("/").filter(Boolean);
29658
- if (path2.length === 0) {
29802
+ const path3 = ref.slice(1).split("/").filter(Boolean);
29803
+ if (path3.length === 0) {
29659
29804
  return ctx.rootSchema;
29660
29805
  }
29661
29806
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
29662
- if (path2[0] === defsKey) {
29663
- const key = path2[1];
29807
+ if (path3[0] === defsKey) {
29808
+ const key = path3[1];
29664
29809
  if (!key || !ctx.defs[key]) {
29665
29810
  throw new Error(`Reference not found: ${ref}`);
29666
29811
  }
@@ -30317,9 +30462,9 @@ function extractCommentsForPreservation(content) {
30317
30462
  }
30318
30463
  return comments;
30319
30464
  }
30320
- function ensureRecordAtPath(root, path2) {
30465
+ function ensureRecordAtPath(root, path3) {
30321
30466
  let current = root;
30322
- for (const segment of path2) {
30467
+ for (const segment of path3) {
30323
30468
  const existing = current[segment];
30324
30469
  if (!existing || typeof existing !== "object" || Array.isArray(existing)) {
30325
30470
  current[segment] = {};
@@ -30328,9 +30473,9 @@ function ensureRecordAtPath(root, path2) {
30328
30473
  }
30329
30474
  return current;
30330
30475
  }
30331
- function hasPath(root, path2) {
30476
+ function hasPath(root, path3) {
30332
30477
  let current = root;
30333
- for (const segment of path2) {
30478
+ for (const segment of path3) {
30334
30479
  if (!current || typeof current !== "object" || Array.isArray(current))
30335
30480
  return false;
30336
30481
  const record2 = current;
@@ -30340,9 +30485,9 @@ function hasPath(root, path2) {
30340
30485
  }
30341
30486
  return true;
30342
30487
  }
30343
- function setPath(root, path2, value) {
30344
- const parent = ensureRecordAtPath(root, path2.slice(0, -1));
30345
- parent[path2[path2.length - 1]] = value;
30488
+ function setPath(root, path3, value) {
30489
+ const parent = ensureRecordAtPath(root, path3.slice(0, -1));
30490
+ parent[path3[path3.length - 1]] = value;
30346
30491
  }
30347
30492
  function migrateRawConfig(rawConfig, configPath, logger) {
30348
30493
  const oldKeys = [];
@@ -30659,15 +30804,15 @@ function mergeConfigs(base, override) {
30659
30804
  };
30660
30805
  }
30661
30806
  function getGlobalPiDir() {
30662
- return join9(homedir7(), ".pi", "agent");
30807
+ return join10(homedir8(), ".pi", "agent");
30663
30808
  }
30664
30809
  function loadAftConfig(projectDirectory) {
30665
- const userBasePath = join9(getGlobalPiDir(), "aft");
30810
+ const userBasePath = join10(getGlobalPiDir(), "aft");
30666
30811
  migrateAftConfigFile(`${userBasePath}.jsonc`);
30667
30812
  migrateAftConfigFile(`${userBasePath}.json`);
30668
30813
  const userDetected = detectConfigFile(userBasePath);
30669
30814
  const userConfigPath = userDetected.format !== "none" ? userDetected.path : `${userBasePath}.json`;
30670
- const projectBasePath = join9(projectDirectory, ".pi", "aft");
30815
+ const projectBasePath = join10(projectDirectory, ".pi", "aft");
30671
30816
  migrateAftConfigFile(`${projectBasePath}.jsonc`);
30672
30817
  migrateAftConfigFile(`${projectBasePath}.json`);
30673
30818
  const projectDetected = detectConfigFile(projectBasePath);
@@ -30704,7 +30849,7 @@ import {
30704
30849
  statSync as statSync5,
30705
30850
  writeFileSync as writeFileSync5
30706
30851
  } from "node:fs";
30707
- import { join as join12 } from "node:path";
30852
+ import { join as join13 } from "node:path";
30708
30853
 
30709
30854
  // src/lsp-cache.ts
30710
30855
  import {
@@ -30716,36 +30861,36 @@ import {
30716
30861
  unlinkSync as unlinkSync5,
30717
30862
  writeFileSync as writeFileSync4
30718
30863
  } from "node:fs";
30719
- import { homedir as homedir8 } from "node:os";
30720
- import { join as join10 } from "node:path";
30864
+ import { homedir as homedir9 } from "node:os";
30865
+ import { join as join11 } from "node:path";
30721
30866
  function aftCacheBase() {
30722
30867
  const override = process.env.AFT_CACHE_DIR;
30723
30868
  if (override && override.length > 0)
30724
30869
  return override;
30725
30870
  if (process.platform === "win32") {
30726
30871
  const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
30727
- const base2 = localAppData || join10(homedir8(), "AppData", "Local");
30728
- return join10(base2, "aft");
30872
+ const base2 = localAppData || join11(homedir9(), "AppData", "Local");
30873
+ return join11(base2, "aft");
30729
30874
  }
30730
- const base = process.env.XDG_CACHE_HOME || join10(homedir8(), ".cache");
30731
- return join10(base, "aft");
30875
+ const base = process.env.XDG_CACHE_HOME || join11(homedir9(), ".cache");
30876
+ return join11(base, "aft");
30732
30877
  }
30733
30878
  function lspCacheRoot() {
30734
- return join10(aftCacheBase(), "lsp-packages");
30879
+ return join11(aftCacheBase(), "lsp-packages");
30735
30880
  }
30736
30881
  function lspPackageDir(npmPackage) {
30737
- return join10(lspCacheRoot(), encodeURIComponent(npmPackage));
30882
+ return join11(lspCacheRoot(), encodeURIComponent(npmPackage));
30738
30883
  }
30739
30884
  function lspBinaryPath(npmPackage, binary) {
30740
- return join10(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
30885
+ return join11(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
30741
30886
  }
30742
30887
  function lspBinDir(npmPackage) {
30743
- return join10(lspPackageDir(npmPackage), "node_modules", ".bin");
30888
+ return join11(lspPackageDir(npmPackage), "node_modules", ".bin");
30744
30889
  }
30745
30890
  function isInstalled(npmPackage, binary) {
30746
30891
  for (const candidate of lspBinaryCandidates(binary)) {
30747
30892
  try {
30748
- if (statSync4(join10(lspBinDir(npmPackage), candidate)).isFile())
30893
+ if (statSync4(join11(lspBinDir(npmPackage), candidate)).isFile())
30749
30894
  return true;
30750
30895
  } catch {}
30751
30896
  }
@@ -30765,17 +30910,17 @@ function writeInstalledMetaIn(installDir, version2, sha256) {
30765
30910
  installedAt: new Date().toISOString(),
30766
30911
  ...sha256 ? { sha256 } : {}
30767
30912
  };
30768
- writeFileSync4(join10(installDir, INSTALLED_META_FILE), JSON.stringify(meta3), "utf8");
30913
+ writeFileSync4(join11(installDir, INSTALLED_META_FILE), JSON.stringify(meta3), "utf8");
30769
30914
  } catch (err) {
30770
30915
  log2(`[lsp-cache] failed to write installed-meta in ${installDir}: ${err}`);
30771
30916
  }
30772
30917
  }
30773
30918
  function readInstalledMetaIn(installDir) {
30774
- const path2 = join10(installDir, INSTALLED_META_FILE);
30919
+ const path3 = join11(installDir, INSTALLED_META_FILE);
30775
30920
  try {
30776
- if (!statSync4(path2).isFile())
30921
+ if (!statSync4(path3).isFile())
30777
30922
  return null;
30778
- const raw = readFileSync5(path2, "utf8");
30923
+ const raw = readFileSync5(path3, "utf8");
30779
30924
  const parsed = JSON.parse(raw);
30780
30925
  if (typeof parsed.version !== "string" || parsed.version.length === 0)
30781
30926
  return null;
@@ -30795,7 +30940,7 @@ function readInstalledMeta(packageKey) {
30795
30940
  return readInstalledMetaIn(lspPackageDir(packageKey));
30796
30941
  }
30797
30942
  function lockPath(npmPackage) {
30798
- return join10(lspPackageDir(npmPackage), ".aft-installing");
30943
+ return join11(lspPackageDir(npmPackage), ".aft-installing");
30799
30944
  }
30800
30945
  var STALE_LOCK_MS2 = 30 * 60 * 1000;
30801
30946
  function acquireInstallLock(lockKey) {
@@ -30902,7 +31047,7 @@ async function withInstallLock(lockKey, task) {
30902
31047
  }
30903
31048
  var VERSION_CHECK_FILE = ".aft-version-check";
30904
31049
  function readVersionCheck(npmPackage) {
30905
- const file2 = join10(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
31050
+ const file2 = join11(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
30906
31051
  try {
30907
31052
  const raw = readFileSync5(file2, "utf8");
30908
31053
  const parsed = JSON.parse(raw);
@@ -30919,7 +31064,7 @@ function readVersionCheck(npmPackage) {
30919
31064
  }
30920
31065
  function writeVersionCheck(npmPackage, latest) {
30921
31066
  mkdirSync6(lspPackageDir(npmPackage), { recursive: true });
30922
- const file2 = join10(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
31067
+ const file2 = join11(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
30923
31068
  const record2 = {
30924
31069
  last_checked: new Date().toISOString(),
30925
31070
  latest_eligible: latest
@@ -31082,7 +31227,7 @@ var NPM_LSP_TABLE = [
31082
31227
 
31083
31228
  // src/lsp-project-relevance.ts
31084
31229
  import { existsSync as existsSync7, readdirSync as readdirSync3, readFileSync as readFileSync6 } from "node:fs";
31085
- import { join as join11 } from "node:path";
31230
+ import { join as join12 } from "node:path";
31086
31231
  var MAX_WALK_DIRS = 200;
31087
31232
  var MAX_WALK_DEPTH = 4;
31088
31233
  var NOISE_DIRS = new Set([
@@ -31099,7 +31244,7 @@ function hasRootMarker(projectRoot, rootMarkers) {
31099
31244
  if (!rootMarkers)
31100
31245
  return false;
31101
31246
  for (const marker of rootMarkers) {
31102
- if (existsSync7(join11(projectRoot, marker)))
31247
+ if (existsSync7(join12(projectRoot, marker)))
31103
31248
  return true;
31104
31249
  }
31105
31250
  return false;
@@ -31123,7 +31268,7 @@ function hasPackageJsonDep(projectRoot, depNames) {
31123
31268
  }
31124
31269
  function readPackageJson(projectRoot) {
31125
31270
  try {
31126
- const raw = readFileSync6(join11(projectRoot, "package.json"), "utf8");
31271
+ const raw = readFileSync6(join12(projectRoot, "package.json"), "utf8");
31127
31272
  const parsed = JSON.parse(raw);
31128
31273
  if (typeof parsed !== "object" || parsed === null)
31129
31274
  return null;
@@ -31153,7 +31298,7 @@ function relevantExtensionsInProject(projectRoot, extToServer) {
31153
31298
  for (const entry of entries) {
31154
31299
  if (entry.isDirectory()) {
31155
31300
  if (current.depth < MAX_WALK_DEPTH && !NOISE_DIRS.has(entry.name.toLowerCase())) {
31156
- queue.push({ dir: join11(current.dir, entry.name), depth: current.depth + 1 });
31301
+ queue.push({ dir: join12(current.dir, entry.name), depth: current.depth + 1 });
31157
31302
  }
31158
31303
  continue;
31159
31304
  }
@@ -31280,7 +31425,7 @@ async function resolveTargetVersion(spec, config2, fetchImpl = fetch) {
31280
31425
  }
31281
31426
  function ensureInstallAnchor(cwd) {
31282
31427
  try {
31283
- const stub = join12(cwd, "package.json");
31428
+ const stub = join13(cwd, "package.json");
31284
31429
  if (!existsSync8(stub)) {
31285
31430
  writeFileSync5(stub, `${JSON.stringify({ name: "aft-lsp-cache", version: "0.0.0", private: true })}
31286
31431
  `);
@@ -31290,18 +31435,18 @@ function ensureInstallAnchor(cwd) {
31290
31435
  }
31291
31436
  }
31292
31437
  function runInstall(spec, version2, cwd, signal) {
31293
- return new Promise((resolve2) => {
31438
+ return new Promise((resolve3) => {
31294
31439
  const target = `${spec.npm}@${version2}`;
31295
31440
  log2(`[lsp] installing ${target} to ${cwd}`);
31296
31441
  if (signal?.aborted) {
31297
31442
  warn2(`[lsp] install ${target} aborted before spawn`);
31298
- resolve2(false);
31443
+ resolve3(false);
31299
31444
  return;
31300
31445
  }
31301
31446
  const npm = resolveNpm();
31302
31447
  if (!npm) {
31303
31448
  warn2(`[lsp] npm not found on PATH or known locations; cannot install ${target}`);
31304
- resolve2(false);
31449
+ resolve3(false);
31305
31450
  return;
31306
31451
  }
31307
31452
  ensureInstallAnchor(cwd);
@@ -31324,7 +31469,7 @@ function runInstall(spec, version2, cwd, signal) {
31324
31469
  return;
31325
31470
  settled = true;
31326
31471
  cleanup();
31327
- resolve2(ok);
31472
+ resolve3(ok);
31328
31473
  };
31329
31474
  const onAbort = () => {
31330
31475
  warn2(`[lsp] install ${target} aborted during shutdown`);
@@ -31425,7 +31570,7 @@ function cachedPackageDir(npmPackage) {
31425
31570
  return lspBinDir(npmPackage).replace(/[\\/]node_modules[\\/]\.bin[\\/]?$/, "");
31426
31571
  }
31427
31572
  function hashInstalledBinary(spec) {
31428
- return new Promise((resolve2, reject) => {
31573
+ return new Promise((resolve3, reject) => {
31429
31574
  const candidates = process.platform === "win32" ? [
31430
31575
  lspBinaryPath(spec.npm, spec.binary),
31431
31576
  lspBinaryPath(spec.npm, `${spec.binary}.cmd`),
@@ -31449,7 +31594,7 @@ function hashInstalledBinary(spec) {
31449
31594
  const stream = createReadStream(pathToHash);
31450
31595
  stream.on("error", reject);
31451
31596
  stream.on("data", (chunk) => hash2.update(chunk));
31452
- stream.on("end", () => resolve2(hash2.digest("hex")));
31597
+ stream.on("end", () => resolve3(hash2.digest("hex")));
31453
31598
  });
31454
31599
  }
31455
31600
  function installedBinaryPath(spec) {
@@ -31467,15 +31612,15 @@ function installedBinaryPath(spec) {
31467
31612
  }
31468
31613
  return null;
31469
31614
  }
31470
- function sha256OfFileSync(path2) {
31471
- return createHash3("sha256").update(readFileSync7(path2)).digest("hex");
31615
+ function sha256OfFileSync(path3) {
31616
+ return createHash3("sha256").update(readFileSync7(path3)).digest("hex");
31472
31617
  }
31473
31618
  function quarantineCachedNpmInstall(spec, reason) {
31474
31619
  const packageDir = lspPackageDir(spec.npm);
31475
- const dest = join12(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
31620
+ const dest = join13(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
31476
31621
  warn2(`[lsp] tofu_mismatch ${spec.npm}: ${reason}; quarantining ${packageDir} -> ${dest}`);
31477
31622
  try {
31478
- mkdirSync7(join12(dest, ".."), { recursive: true });
31623
+ mkdirSync7(join13(dest, ".."), { recursive: true });
31479
31624
  rmSync3(dest, { recursive: true, force: true });
31480
31625
  renameSync5(packageDir, dest);
31481
31626
  } catch (err) {
@@ -31570,7 +31715,7 @@ import {
31570
31715
  unlinkSync as unlinkSync6,
31571
31716
  writeFileSync as writeFileSync6
31572
31717
  } from "node:fs";
31573
- import { dirname as dirname5, join as join13, relative as relative2, resolve as resolve2 } from "node:path";
31718
+ import { dirname as dirname5, join as join14, relative as relative3, resolve as resolve3 } from "node:path";
31574
31719
  import { Readable as Readable3 } from "node:stream";
31575
31720
  import { pipeline as pipeline3 } from "node:stream/promises";
31576
31721
 
@@ -31660,26 +31805,26 @@ function detectHostPlatform() {
31660
31805
 
31661
31806
  // src/lsp-github-install.ts
31662
31807
  function ghCacheRoot() {
31663
- return join13(aftCacheBase(), "lsp-binaries");
31808
+ return join14(aftCacheBase(), "lsp-binaries");
31664
31809
  }
31665
31810
  function ghPackageDir(spec) {
31666
- return join13(ghCacheRoot(), spec.id);
31811
+ return join14(ghCacheRoot(), spec.id);
31667
31812
  }
31668
31813
  function ghBinDir(spec) {
31669
- return join13(ghPackageDir(spec), "bin");
31814
+ return join14(ghPackageDir(spec), "bin");
31670
31815
  }
31671
31816
  function ghExtractDir(spec) {
31672
- return join13(ghPackageDir(spec), "extracted");
31817
+ return join14(ghPackageDir(spec), "extracted");
31673
31818
  }
31674
31819
  var INSTALLED_META_FILE2 = ".aft-installed";
31675
31820
  function ghBinaryPath(spec, platform) {
31676
31821
  const ext = platform === "win32" ? ".exe" : "";
31677
- return join13(ghBinDir(spec), `${spec.binary}${ext}`);
31822
+ return join14(ghBinDir(spec), `${spec.binary}${ext}`);
31678
31823
  }
31679
31824
  function isGithubInstalled(spec, platform) {
31680
31825
  for (const candidate of ghBinaryCandidates(spec, platform)) {
31681
31826
  try {
31682
- if (statSync6(join13(ghBinDir(spec), candidate)).isFile())
31827
+ if (statSync6(join14(ghBinDir(spec), candidate)).isFile())
31683
31828
  return true;
31684
31829
  } catch {}
31685
31830
  }
@@ -31692,10 +31837,10 @@ function ghBinaryCandidates(spec, platform) {
31692
31837
  }
31693
31838
  function readGithubInstalledMetaIn(installDir) {
31694
31839
  try {
31695
- const path2 = join13(installDir, INSTALLED_META_FILE2);
31696
- if (!statSync6(path2).isFile())
31840
+ const path3 = join14(installDir, INSTALLED_META_FILE2);
31841
+ if (!statSync6(path3).isFile())
31697
31842
  return null;
31698
- const parsed = JSON.parse(readFileSync8(path2, "utf8"));
31843
+ const parsed = JSON.parse(readFileSync8(path3, "utf8"));
31699
31844
  if (typeof parsed.version !== "string" || parsed.version.length === 0)
31700
31845
  return null;
31701
31846
  return {
@@ -31719,24 +31864,24 @@ function writeGithubInstalledMetaIn(installDir, version2, binarySha256, archiveS
31719
31864
  binarySha256,
31720
31865
  ...archiveSha256 ? { archiveSha256 } : {}
31721
31866
  };
31722
- writeFileSync6(join13(installDir, INSTALLED_META_FILE2), JSON.stringify(meta3), "utf8");
31867
+ writeFileSync6(join14(installDir, INSTALLED_META_FILE2), JSON.stringify(meta3), "utf8");
31723
31868
  } catch (err) {
31724
31869
  warn2(`[lsp] failed to write github installed metadata in ${installDir}: ${err}`);
31725
31870
  }
31726
31871
  }
31727
31872
  var MAX_DOWNLOAD_BYTES3 = 256 * 1024 * 1024;
31728
31873
  var MAX_EXTRACT_BYTES2 = 1024 * 1024 * 1024;
31729
- function sha256OfFile(path2) {
31730
- return new Promise((resolve3, reject) => {
31874
+ function sha256OfFile(path3) {
31875
+ return new Promise((resolve4, reject) => {
31731
31876
  const hash2 = createHash4("sha256");
31732
- const stream = createReadStream2(path2);
31877
+ const stream = createReadStream2(path3);
31733
31878
  stream.on("error", reject);
31734
31879
  stream.on("data", (chunk) => hash2.update(chunk));
31735
- stream.on("end", () => resolve3(hash2.digest("hex")));
31880
+ stream.on("end", () => resolve4(hash2.digest("hex")));
31736
31881
  });
31737
31882
  }
31738
- function sha256OfFileSync2(path2) {
31739
- return createHash4("sha256").update(readFileSync8(path2)).digest("hex");
31883
+ function sha256OfFileSync2(path3) {
31884
+ return createHash4("sha256").update(readFileSync8(path3)).digest("hex");
31740
31885
  }
31741
31886
  async function fetchReleaseByTag(githubRepo, tag, fetchImpl, signal) {
31742
31887
  const candidates = [];
@@ -31968,7 +32113,7 @@ function validateExtraction(stagingRoot) {
31968
32113
  throw new Error(`failed to read staging dir ${dir}: ${err}`);
31969
32114
  }
31970
32115
  for (const entry of entries) {
31971
- const full = join13(dir, entry);
32116
+ const full = join14(dir, entry);
31972
32117
  let lst;
31973
32118
  try {
31974
32119
  lst = lstatSync2(full);
@@ -31980,7 +32125,7 @@ function validateExtraction(stagingRoot) {
31980
32125
  try {
31981
32126
  target = readlinkSync2(full);
31982
32127
  } catch {}
31983
- throw new Error(`archive contains symlink ${relative2(realStagingRoot, full)} → ${target}; rejecting (zip-slip defense)`);
32128
+ throw new Error(`archive contains symlink ${relative3(realStagingRoot, full)} → ${target}; rejecting (zip-slip defense)`);
31984
32129
  }
31985
32130
  let realFull;
31986
32131
  try {
@@ -31988,8 +32133,8 @@ function validateExtraction(stagingRoot) {
31988
32133
  } catch (err) {
31989
32134
  throw new Error(`failed to realpath ${full}: ${err}`);
31990
32135
  }
31991
- const rel = relative2(realStagingRoot, realFull);
31992
- if (rel.startsWith("..") || resolve2(realStagingRoot, rel) !== realFull) {
32136
+ const rel = relative3(realStagingRoot, realFull);
32137
+ if (rel.startsWith("..") || resolve3(realStagingRoot, rel) !== realFull) {
31993
32138
  throw new Error(`archive entry escapes staging root: ${full} → ${realFull} (zip-slip defense)`);
31994
32139
  }
31995
32140
  if (lst.isDirectory()) {
@@ -32056,7 +32201,7 @@ function extractArchiveSafely(archivePath, destDir, archiveType) {
32056
32201
  }
32057
32202
  function quarantineCachedGithubInstall(spec, reason) {
32058
32203
  const packageDir = ghPackageDir(spec);
32059
- const dest = join13(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
32204
+ const dest = join14(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
32060
32205
  warn2(`[lsp] tofu_mismatch ${spec.id}: ${reason}; quarantining ${packageDir} -> ${dest}`);
32061
32206
  try {
32062
32207
  mkdirSync8(dirname5(dest), { recursive: true });
@@ -32069,7 +32214,7 @@ function quarantineCachedGithubInstall(spec, reason) {
32069
32214
  function validateCachedGithubInstall(spec, platform) {
32070
32215
  const packageDir = ghPackageDir(spec);
32071
32216
  const meta3 = readGithubInstalledMetaIn(packageDir);
32072
- const binaryPath = ghBinaryCandidates(spec, platform).map((candidate) => join13(ghBinDir(spec), candidate)).find((candidate) => {
32217
+ const binaryPath = ghBinaryCandidates(spec, platform).map((candidate) => join14(ghBinDir(spec), candidate)).find((candidate) => {
32073
32218
  try {
32074
32219
  return statSync6(candidate).isFile();
32075
32220
  } catch {
@@ -32147,7 +32292,7 @@ async function downloadAndInstall(spec, tag, assets, platform, arch, fetchImpl,
32147
32292
  }
32148
32293
  const pkgDir = ghPackageDir(spec);
32149
32294
  const extractDir = ghExtractDir(spec);
32150
- const archivePath = join13(pkgDir, expected.name);
32295
+ const archivePath = join14(pkgDir, expected.name);
32151
32296
  log2(`[lsp] downloading ${spec.id} ${tag} → ${matchingAsset.url}`);
32152
32297
  try {
32153
32298
  await downloadFile(matchingAsset.url, archivePath, fetchImpl, matchingAsset.size, signal);
@@ -32187,7 +32332,7 @@ async function downloadAndInstall(spec, tag, assets, platform, arch, fetchImpl,
32187
32332
  unlinkSync6(archivePath);
32188
32333
  } catch {}
32189
32334
  }
32190
- const innerBinaryPath = join13(extractDir, spec.binaryPathInArchive(platform, arch, version2));
32335
+ const innerBinaryPath = join14(extractDir, spec.binaryPathInArchive(platform, arch, version2));
32191
32336
  if (!existsSync9(innerBinaryPath)) {
32192
32337
  error2(`[lsp] ${spec.id}: extracted binary not found at ${innerBinaryPath}`);
32193
32338
  return null;
@@ -32585,7 +32730,7 @@ function renderScreen(state, rows = state.rows, cols = state.cols) {
32585
32730
  `);
32586
32731
  }
32587
32732
  function writeTerminal(terminal, data) {
32588
- return new Promise((resolve3) => terminal.write(data, resolve3));
32733
+ return new Promise((resolve4) => terminal.write(data, resolve4));
32589
32734
  }
32590
32735
 
32591
32736
  // src/shutdown-hooks.ts
@@ -32642,8 +32787,8 @@ function installProcessHandlers() {
32642
32787
  }
32643
32788
  signalShutdownStarted = true;
32644
32789
  process.exitCode = SIGNAL_EXIT_CODES[sig];
32645
- const timeout = new Promise((resolve3) => {
32646
- setTimeout(resolve3, SIGNAL_CLEANUP_TIMEOUT_MS);
32790
+ const timeout = new Promise((resolve4) => {
32791
+ setTimeout(resolve4, SIGNAL_CLEANUP_TIMEOUT_MS);
32647
32792
  });
32648
32793
  Promise.race([runCleanups(sig), timeout]).finally(() => {
32649
32794
  process.exit(SIGNAL_EXIT_CODES[sig]);
@@ -32685,8 +32830,8 @@ import { Type as Type3 } from "typebox";
32685
32830
 
32686
32831
  // src/tools/hoisted.ts
32687
32832
  import { stat } from "node:fs/promises";
32688
- import { homedir as homedir9 } from "node:os";
32689
- import { isAbsolute as isAbsolute3, relative as relative3, resolve as resolve3, sep } from "node:path";
32833
+ import { homedir as homedir10 } from "node:os";
32834
+ import { isAbsolute as isAbsolute4, relative as relative4, resolve as resolve4, sep } from "node:path";
32690
32835
  import {
32691
32836
  renderDiff
32692
32837
  } from "@earendil-works/pi-coding-agent";
@@ -32800,18 +32945,18 @@ function diagnosticsOnEditDefault(ctx) {
32800
32945
  return ctx.config.lsp?.diagnostics_on_edit ?? false;
32801
32946
  }
32802
32947
  function containsPath(parent, child) {
32803
- const rel = relative3(parent, child);
32804
- return rel === "" || !rel.startsWith("..") && !isAbsolute3(rel);
32948
+ const rel = relative4(parent, child);
32949
+ return rel === "" || !rel.startsWith("..") && !isAbsolute4(rel);
32805
32950
  }
32806
- function expandTilde(path2) {
32807
- if (!path2 || !path2.startsWith("~"))
32808
- return path2;
32809
- if (path2 === "~")
32810
- return homedir9();
32811
- if (path2.startsWith(`~${sep}`) || path2.startsWith("~/")) {
32812
- return resolve3(homedir9(), path2.slice(2));
32951
+ function expandTilde2(path3) {
32952
+ if (!path3 || !path3.startsWith("~"))
32953
+ return path3;
32954
+ if (path3 === "~")
32955
+ return homedir10();
32956
+ if (path3.startsWith(`~${sep}`) || path3.startsWith("~/")) {
32957
+ return resolve4(homedir10(), path3.slice(2));
32813
32958
  }
32814
- return path2;
32959
+ return path3;
32815
32960
  }
32816
32961
  function externalDirectoryPromptTimeoutMs() {
32817
32962
  const raw = process.env.AFT_PI_EXTERNAL_PROMPT_TIMEOUT_MS;
@@ -32823,8 +32968,8 @@ function externalDirectoryPromptTimeoutMs() {
32823
32968
  async function assertExternalDirectoryPermission(extCtx, target, action = "modify", options = {}) {
32824
32969
  if (!target)
32825
32970
  return;
32826
- const expanded = expandTilde(target);
32827
- const absoluteTarget = isAbsolute3(expanded) ? expanded : resolve3(extCtx.cwd, expanded);
32971
+ const expanded = expandTilde2(target);
32972
+ const absoluteTarget = isAbsolute4(expanded) ? expanded : resolve4(extCtx.cwd, expanded);
32828
32973
  if (containsPath(extCtx.cwd, absoluteTarget))
32829
32974
  return;
32830
32975
  if (options.restrictToProjectRoot === false)
@@ -32835,8 +32980,8 @@ async function assertExternalDirectoryPermission(extCtx, target, action = "modif
32835
32980
  }
32836
32981
  const timeoutMs = externalDirectoryPromptTimeoutMs();
32837
32982
  let timer;
32838
- const timeoutPromise = new Promise((resolve4) => {
32839
- timer = setTimeout(() => resolve4("timeout"), timeoutMs);
32983
+ const timeoutPromise = new Promise((resolve5) => {
32984
+ timer = setTimeout(() => resolve5("timeout"), timeoutMs);
32840
32985
  });
32841
32986
  try {
32842
32987
  const result = await Promise.race([
@@ -32900,8 +33045,12 @@ function registerHoistedTools(pi, ctx, surface) {
32900
33045
  const bridge = bridgeFor(ctx, extCtx.cwd);
32901
33046
  const offset = coerceOptionalInt(params.offset, "offset", 1, Number.MAX_SAFE_INTEGER);
32902
33047
  const limit = coerceOptionalInt(params.limit, "limit", 1, Number.MAX_SAFE_INTEGER);
33048
+ const filePath = await resolvePathArg(extCtx.cwd, params.path);
33049
+ await assertExternalDirectoryPermission(extCtx, filePath, "read", {
33050
+ restrictToProjectRoot: surface.restrictToProjectRoot
33051
+ });
32903
33052
  const req = {
32904
- file: await resolvePathArg(extCtx.cwd, params.path)
33053
+ file: filePath
32905
33054
  };
32906
33055
  if (offset !== undefined) {
32907
33056
  req.start_line = offset;
@@ -32918,7 +33067,7 @@ function registerHoistedTools(pi, ctx, surface) {
32918
33067
  }
32919
33068
  let text = response.content ?? "";
32920
33069
  const agentSpecifiedRange = offset !== undefined || limit !== undefined;
32921
- const footer = formatReadFooter(agentSpecifiedRange, response);
33070
+ const footer = formatReadFooter2(agentSpecifiedRange, response);
32922
33071
  if (footer)
32923
33072
  text += footer;
32924
33073
  return textResult(text);
@@ -33174,15 +33323,15 @@ ${summary}${suffix}`);
33174
33323
  container.addChild(new Text(renderDiff(diff), 1, 0));
33175
33324
  return container;
33176
33325
  }
33177
- function shortenPath(path2) {
33178
- const home = homedir9();
33179
- if (path2.startsWith(home))
33180
- return `~${path2.slice(home.length)}`;
33181
- return path2;
33326
+ function shortenPath(path3) {
33327
+ const home = homedir10();
33328
+ if (path3.startsWith(home))
33329
+ return `~${path3.slice(home.length)}`;
33330
+ return path3;
33182
33331
  }
33183
- async function resolvePathArg(cwd, path2) {
33184
- const expanded = expandTilde(path2);
33185
- const abs = isAbsolute3(expanded) ? expanded : resolve3(cwd, expanded);
33332
+ async function resolvePathArg(cwd, path3) {
33333
+ const expanded = expandTilde2(path3);
33334
+ const abs = isAbsolute4(expanded) ? expanded : resolve4(cwd, expanded);
33186
33335
  try {
33187
33336
  await stat(abs);
33188
33337
  return abs;
@@ -33220,23 +33369,12 @@ function splitIncludeGlobs(include) {
33220
33369
  out.push(tail2);
33221
33370
  return out;
33222
33371
  }
33223
- function formatReadFooter(agentSpecifiedRange, data) {
33224
- if (agentSpecifiedRange)
33225
- return "";
33226
- if (!data.truncated)
33227
- return "";
33228
- const startLine = data.start_line;
33229
- const endLine = data.end_line;
33230
- const totalLines = data.total_lines;
33231
- if (startLine === undefined || endLine === undefined || totalLines === undefined) {
33232
- return "";
33233
- }
33234
- return `
33235
- (Showing lines ${startLine}-${endLine} of ${totalLines}. Use offset/limit to read other sections.)`;
33372
+ function formatReadFooter2(agentSpecifiedRange, data) {
33373
+ return formatReadFooter(agentSpecifiedRange, data, { rangeHint: "offset/limit" });
33236
33374
  }
33237
33375
 
33238
33376
  // src/tools/render-helpers.ts
33239
- import { homedir as homedir10 } from "node:os";
33377
+ import { homedir as homedir11 } from "node:os";
33240
33378
  import { renderDiff as renderDiff2 } from "@earendil-works/pi-coding-agent";
33241
33379
  import { Container as Container2, Spacer as Spacer2, Text as Text2 } from "@earendil-works/pi-tui";
33242
33380
  function reuseText2(last) {
@@ -33245,11 +33383,11 @@ function reuseText2(last) {
33245
33383
  function reuseContainer2(last) {
33246
33384
  return last instanceof Container2 ? last : new Container2;
33247
33385
  }
33248
- function shortenPath2(path2) {
33249
- const home = homedir10();
33250
- if (path2.startsWith(home))
33251
- return `~${path2.slice(home.length)}`;
33252
- return path2;
33386
+ function shortenPath2(path3) {
33387
+ const home = homedir11();
33388
+ if (path3.startsWith(home))
33389
+ return `~${path3.slice(home.length)}`;
33390
+ return path3;
33253
33391
  }
33254
33392
  function renderToolCall(toolName, summary, theme, context) {
33255
33393
  const text = reuseText2(context.lastComponent);
@@ -33257,10 +33395,10 @@ function renderToolCall(toolName, summary, theme, context) {
33257
33395
  text.setText(`${theme.fg("toolTitle", theme.bold(toolName))}${suffix}`);
33258
33396
  return text;
33259
33397
  }
33260
- function accentPath(theme, path2) {
33261
- if (!path2)
33398
+ function accentPath(theme, path3) {
33399
+ if (!path3)
33262
33400
  return theme.fg("toolOutput", "...");
33263
- return theme.fg("accent", shortenPath2(path2));
33401
+ return theme.fg("accent", shortenPath2(path3));
33264
33402
  }
33265
33403
  function collectTextContent(result) {
33266
33404
  return result.content.filter((part) => part.type === "text").map((part) => part.text ?? "").join(`
@@ -33407,7 +33545,7 @@ function renderUnifiedDiff(unifiedDiff) {
33407
33545
  }
33408
33546
 
33409
33547
  // src/tools/ast.ts
33410
- var AstLang = StringEnum(["typescript", "tsx", "javascript", "python", "rust", "go", "pascal"], {
33548
+ var AstLang = StringEnum(["typescript", "tsx", "javascript", "python", "rust", "go", "pascal", "r"], {
33411
33549
  description: "Target language"
33412
33550
  });
33413
33551
  var SearchParams = Type3.Object({
@@ -33448,17 +33586,17 @@ ${warningStrings.map((w) => ` ${w}`).join(`
33448
33586
  async function resolveAstPaths(extCtx, paths) {
33449
33587
  if (isEmptyParam(paths) || !Array.isArray(paths))
33450
33588
  return;
33451
- return Promise.all(paths.filter((path2) => typeof path2 === "string").map((path2) => resolvePathArg(extCtx.cwd, path2)));
33589
+ return Promise.all(paths.filter((path3) => typeof path3 === "string").map((path3) => resolvePathArg(extCtx.cwd, path3)));
33452
33590
  }
33453
33591
  async function assertAstPathsPermission(extCtx, paths, action, restrictToProjectRoot) {
33454
33592
  if (paths === undefined || paths.length === 0)
33455
33593
  return;
33456
33594
  const checked = new Set;
33457
- for (const path2 of paths) {
33458
- if (checked.has(path2))
33595
+ for (const path3 of paths) {
33596
+ if (checked.has(path3))
33459
33597
  continue;
33460
- checked.add(path2);
33461
- await assertExternalDirectoryPermission(extCtx, path2, action, { restrictToProjectRoot });
33598
+ checked.add(path3);
33599
+ await assertExternalDirectoryPermission(extCtx, path3, action, { restrictToProjectRoot });
33462
33600
  }
33463
33601
  }
33464
33602
  function buildAstSearchSections(payload, theme) {
@@ -33641,6 +33779,7 @@ var FOREGROUND_POLL_INTERVAL_MS = 100;
33641
33779
  var BASH_WAIT_POLL_INTERVAL_MS = 100;
33642
33780
  var DEFAULT_BASH_STATUS_WAIT_TIMEOUT_MS = 30000;
33643
33781
  var MAX_BASH_STATUS_WAIT_TIMEOUT_MS = 300000;
33782
+ var REGEX_WAIT_SCAN_WINDOW_BYTES = 64 * 1024;
33644
33783
  function resolveForegroundWaitMs(configured) {
33645
33784
  const override = process.env.AFT_TEST_FOREGROUND_WAIT_MS;
33646
33785
  if (override !== undefined) {
@@ -33825,7 +33964,7 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
33825
33964
  throw new Error(status.message ?? "bash_status failed");
33826
33965
  }
33827
33966
  if (isTerminalStatus(status.status)) {
33828
- return bashResult(appendPipeStripNote(withBashHints(formatForegroundResult(status), bridgeCommand, aftSearchRegistered), pipeStrip.note), {
33967
+ return bashResult(appendPipeStripNote(withBashHints(formatForegroundResult(status), bridgeCommand, aftSearchRegistered, extCtx.cwd), pipeStrip.note), {
33829
33968
  exit_code: status.exit_code,
33830
33969
  duration_ms: status.duration_ms,
33831
33970
  truncated: status.output_truncated,
@@ -33852,7 +33991,7 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
33852
33991
  task_id: taskId
33853
33992
  };
33854
33993
  const output = response.output ?? "";
33855
- return bashResult(appendPipeStripNote(withBashHints(output, bridgeCommand, aftSearchRegistered), pipeStrip.note), details);
33994
+ return bashResult(appendPipeStripNote(withBashHints(output, bridgeCommand, aftSearchRegistered, extCtx.cwd), pipeStrip.note), details);
33856
33995
  },
33857
33996
  renderCall(args, theme, context) {
33858
33997
  return renderBashCall(args?.command, args?.description, theme, context);
@@ -33866,11 +34005,6 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
33866
34005
  pi.registerTool(createBashWriteTool(ctx));
33867
34006
  pi.registerTool(createBashKillTool(ctx));
33868
34007
  }
33869
- function appendPipeStripNote(output, note) {
33870
- return note ? `${output}
33871
-
33872
- ${note}` : output;
33873
- }
33874
34008
  function formatBackgroundLaunch(taskId, isPty) {
33875
34009
  if (isPty) {
33876
34010
  return `PTY task started: ${taskId}. Use bash_status({ task_id: "${taskId}", output_mode: "screen" }) to see the visible terminal, bash_write({ task_id: "${taskId}", input: ... }) to send keystrokes. A completion reminder fires automatically when the task exits.`;
@@ -33881,35 +34015,8 @@ function formatPromotionMessage(taskId, timeout, waitWindowMs) {
33881
34015
  const waited = timeout !== undefined ? Math.min(timeout, waitWindowMs) : waitWindowMs;
33882
34016
  return `Foreground bash didn't finish within ${formatSeconds(waited)} and was promoted to background: ${taskId}. A completion reminder will be delivered automatically; use bash_status({ task_id: "${taskId}" }) to inspect output or bash_kill({ task_id: "${taskId}" }) to terminate.`;
33883
34017
  }
33884
- function formatSeconds(ms) {
33885
- return `${Number((ms / 1000).toFixed(1))}s`;
33886
- }
33887
- function withBashHints(output, command, aftSearchRegistered) {
33888
- return maybeAppendGrepSearchHint(maybeAppendConflictsHint(output), command, aftSearchRegistered);
33889
- }
33890
- function formatForegroundResult(data) {
33891
- const output = data.output_preview ?? "";
33892
- const outputPath = data.output_path;
33893
- const truncated = data.output_truncated === true;
33894
- const status = data.status;
33895
- const exit = data.exit_code;
33896
- let rendered = output;
33897
- if (truncated && outputPath) {
33898
- rendered += `
33899
- [output truncated; full output at ${outputPath}]`;
33900
- }
33901
- if (status === "timed_out") {
33902
- rendered += `
33903
- [command timed out]`;
33904
- }
33905
- if (typeof exit === "number" && exit !== 0) {
33906
- rendered += `
33907
- [exit code: ${exit}]`;
33908
- }
33909
- return rendered;
33910
- }
33911
- function sleep(ms) {
33912
- return new Promise((resolve4) => setTimeout(resolve4, ms));
34018
+ function withBashHints(output, command, aftSearchRegistered, projectRoot) {
34019
+ return maybeAppendGrepSearchHint(maybeAppendConflictsHint(output), command, aftSearchRegistered, projectRoot);
33913
34020
  }
33914
34021
  function createBashStatusTool(ctx) {
33915
34022
  return {
@@ -34076,6 +34183,9 @@ async function waitForBashStatus(ctx, bridge, extCtx, taskId, outputMode, waitFo
34076
34183
  keepBridgeOnTimeout: true,
34077
34184
  transportTimeoutMs: BASH_TRANSPORT_TIMEOUT_MS
34078
34185
  };
34186
+ if (waitFor?.kind === "regex") {
34187
+ await validateWaitRegex(bridge, extCtx, waitFor);
34188
+ }
34079
34189
  const sessionId = resolveSessionId(extCtx);
34080
34190
  clearSyncWatchAbort(sessionId);
34081
34191
  if (waitForExit)
@@ -34092,7 +34202,12 @@ async function waitForBashStatus(ctx, bridge, extCtx, taskId, outputMode, waitFo
34092
34202
  if (scanText.length === 0)
34093
34203
  scanBaseOffset = scan.baseOffset;
34094
34204
  scanText += scan.text;
34095
- const match = findWaitMatch(scanText, waitFor);
34205
+ if (waitFor.kind === "regex") {
34206
+ const trimmed = trimWaitScanBuffer(scanText, scanBaseOffset, waitFor);
34207
+ scanText = trimmed.text;
34208
+ scanBaseOffset = trimmed.baseOffset;
34209
+ }
34210
+ const match = await findWaitMatch(bridge, extCtx, scanText, waitFor);
34096
34211
  if (match) {
34097
34212
  if (waitForExit && terminal) {
34098
34213
  sawTerminal = true;
@@ -34103,9 +34218,14 @@ async function waitForBashStatus(ctx, bridge, extCtx, taskId, outputMode, waitFo
34103
34218
  reason: "matched",
34104
34219
  elapsed_ms: Date.now() - startedAt,
34105
34220
  match: match.text,
34106
- match_offset: scanBaseOffset + Buffer.byteLength(scanText.slice(0, match.index), "utf8")
34221
+ match_offset: scanBaseOffset + match.byteOffset
34107
34222
  });
34108
34223
  }
34224
+ if (waitFor.kind === "substring") {
34225
+ const trimmed = trimWaitScanBuffer(scanText, scanBaseOffset, waitFor);
34226
+ scanText = trimmed.text;
34227
+ scanBaseOffset = trimmed.baseOffset;
34228
+ }
34109
34229
  }
34110
34230
  }
34111
34231
  if (terminal) {
@@ -34191,20 +34311,69 @@ function parseWaitPattern(value) {
34191
34311
  if (typeof value === "string")
34192
34312
  return { kind: "substring", value };
34193
34313
  if (isRegexWaitObject(value))
34194
- return { kind: "regex", value: new RegExp(value.regex), source: value.regex };
34314
+ return { kind: "regex", source: value.regex };
34195
34315
  return;
34196
34316
  }
34197
34317
  function isRegexWaitObject(value) {
34198
34318
  return typeof value === "object" && value !== null && "regex" in value && typeof value.regex === "string";
34199
34319
  }
34200
- function findWaitMatch(text, pattern) {
34320
+ async function validateWaitRegex(bridge, extCtx, pattern) {
34321
+ await matchRegexWithBridge(bridge, extCtx, pattern.source, "");
34322
+ }
34323
+ async function findWaitMatch(bridge, extCtx, text, pattern) {
34201
34324
  if (pattern.kind === "substring") {
34202
34325
  const index = text.indexOf(pattern.value);
34203
- return index >= 0 ? { text: pattern.value, index } : undefined;
34326
+ return index >= 0 ? { text: pattern.value, byteOffset: Buffer.byteLength(text.slice(0, index), "utf8") } : undefined;
34204
34327
  }
34205
- pattern.value.lastIndex = 0;
34206
- const match = pattern.value.exec(text);
34207
- return match ? { text: match[0], index: match.index } : undefined;
34328
+ return await matchRegexWithBridge(bridge, extCtx, pattern.source, text);
34329
+ }
34330
+ async function matchRegexWithBridge(bridge, extCtx, pattern, text) {
34331
+ try {
34332
+ const result = await callBashBridge(bridge, "bash_regex_match", { pattern, text }, extCtx);
34333
+ if (result.matched !== true)
34334
+ return;
34335
+ return {
34336
+ text: typeof result.match_text === "string" ? result.match_text : "",
34337
+ byteOffset: coerceMatchOffset(result.match_offset)
34338
+ };
34339
+ } catch (err) {
34340
+ if (err instanceof BridgeError && err.code === "invalid_regex") {
34341
+ throw new Error(`invalid_request: invalid_regex: ${err.message}`);
34342
+ }
34343
+ throw err;
34344
+ }
34345
+ }
34346
+ function coerceMatchOffset(value) {
34347
+ const offset = typeof value === "number" ? value : Number(value ?? 0);
34348
+ return Number.isFinite(offset) && offset >= 0 ? offset : 0;
34349
+ }
34350
+ function trimWaitScanBuffer(text, baseOffset, pattern) {
34351
+ const keepFrom = pattern.kind === "substring" ? substringKeepStart(text, pattern.value) : regexKeepStart(text, REGEX_WAIT_SCAN_WINDOW_BYTES);
34352
+ if (keepFrom <= 0)
34353
+ return { text, baseOffset };
34354
+ return {
34355
+ text: text.slice(keepFrom),
34356
+ baseOffset: baseOffset + Buffer.byteLength(text.slice(0, keepFrom), "utf8")
34357
+ };
34358
+ }
34359
+ function substringKeepStart(text, pattern) {
34360
+ const keepChars = Math.max(0, pattern.length - 1);
34361
+ return text.length > keepChars ? text.length - keepChars : 0;
34362
+ }
34363
+ function regexKeepStart(text, maxBytes) {
34364
+ if (Buffer.byteLength(text, "utf8") <= maxBytes)
34365
+ return 0;
34366
+ let low = 0;
34367
+ let high = text.length;
34368
+ while (low < high) {
34369
+ const mid = Math.floor((low + high) / 2);
34370
+ if (Buffer.byteLength(text.slice(mid), "utf8") > maxBytes) {
34371
+ low = mid + 1;
34372
+ } else {
34373
+ high = mid;
34374
+ }
34375
+ }
34376
+ return low;
34208
34377
  }
34209
34378
  function withWaited(data, waited) {
34210
34379
  return { ...data, waited };
@@ -34280,9 +34449,6 @@ function ptyCacheKey(extCtx, taskId) {
34280
34449
  function watchPtyCacheKey(extCtx, taskId) {
34281
34450
  return `${ptyCacheKey(extCtx, taskId)}::watch`;
34282
34451
  }
34283
- function isTerminalStatus(status) {
34284
- return status === "completed" || status === "failed" || status === "killed" || status === "timed_out";
34285
- }
34286
34452
  function renderBashCall(command, description, theme, context) {
34287
34453
  const text = reuseText3(context.lastComponent);
34288
34454
  const display = description ?? (command ? shortenCommand(command) : "...");
@@ -34386,12 +34552,12 @@ function registerConflictsTool(pi, ctx) {
34386
34552
  async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
34387
34553
  const bridge = bridgeFor(ctx, extCtx.cwd);
34388
34554
  const reqParams = {};
34389
- const path2 = params?.path;
34390
- if (typeof path2 === "string" && path2.trim() !== "") {
34391
- await assertExternalDirectoryPermission(extCtx, path2, "inspect", {
34555
+ const path3 = params?.path;
34556
+ if (typeof path3 === "string" && path3.trim() !== "") {
34557
+ await assertExternalDirectoryPermission(extCtx, path3, "inspect", {
34392
34558
  restrictToProjectRoot: ctx.config.restrict_to_project_root ?? false
34393
34559
  });
34394
- reqParams.path = await resolvePathArg(extCtx.cwd, path2);
34560
+ reqParams.path = await resolvePathArg(extCtx.cwd, path3);
34395
34561
  }
34396
34562
  const response = await callBridge(bridge, "git_conflicts", reqParams, extCtx);
34397
34563
  return textResult(response.text ?? JSON.stringify(response, null, 2));
@@ -34790,8 +34956,8 @@ function tier2SummaryPart(summary, key, label) {
34790
34956
  return `${label} ${status ?? "unavailable"}`;
34791
34957
  }
34792
34958
  function shortDupOccurrence(entry) {
34793
- const [path2] = entry.split(":");
34794
- return path2?.split("/").pop() ?? entry;
34959
+ const [path3] = entry.split(":");
34960
+ return path3?.split("/").pop() ?? entry;
34795
34961
  }
34796
34962
  function tier2TopPreview(summary, theme) {
34797
34963
  const lines = [];
@@ -35000,9 +35166,9 @@ function depthWarning(response, theme, depthField = "depth_limited", truncatedFi
35000
35166
  const detail = truncated > 0 ? `, ${truncated} truncated` : "";
35001
35167
  return theme.fg("warning", `(depth limited${detail})`);
35002
35168
  }
35003
- function renderTracePath(path2, index, lines) {
35169
+ function renderTracePath(path3, index, lines) {
35004
35170
  lines.push(`Path ${index + 1}`);
35005
- asRecords(path2.hops).forEach((hop, hopIndex) => {
35171
+ asRecords(path3.hops).forEach((hop, hopIndex) => {
35006
35172
  const symbol2 = asString(hop.symbol) ?? "(unknown)";
35007
35173
  const file2 = shortenPath2(asString(hop.file) ?? "(unknown file)");
35008
35174
  const line = asNumber(hop.line);
@@ -35040,15 +35206,15 @@ function buildNavigateSections(args, payload, theme) {
35040
35206
  return sections2;
35041
35207
  }
35042
35208
  if (args.op === "trace_to_symbol") {
35043
- const path2 = asRecords(response.path);
35209
+ const path3 = asRecords(response.path);
35044
35210
  const complete = asBoolean(response.complete);
35045
35211
  const reason = asString(response.reason);
35046
- if (path2.length === 0) {
35212
+ if (path3.length === 0) {
35047
35213
  const prefix = complete === false ? theme.fg("warning", "No complete path") : theme.fg("muted", "No path");
35048
35214
  return [`${prefix}${reason ? ` (${reason})` : ""}`];
35049
35215
  }
35050
- const lines = [theme.fg("success", `${path2.length} hop${path2.length === 1 ? "" : "s"}`)];
35051
- path2.forEach((hop, index) => {
35216
+ const lines = [theme.fg("success", `${path3.length} hop${path3.length === 1 ? "" : "s"}`)];
35217
+ path3.forEach((hop, index) => {
35052
35218
  const symbol2 = asString(hop.symbol) ?? "(unknown)";
35053
35219
  const file2 = shortenPath2(asString(hop.file) ?? "(unknown file)");
35054
35220
  const line = asNumber(hop.line);
@@ -35064,9 +35230,9 @@ function buildNavigateSections(args, payload, theme) {
35064
35230
  ];
35065
35231
  if (paths.length === 0)
35066
35232
  sections2.push(theme.fg("muted", "No entry paths found."));
35067
- paths.forEach((path2, index) => {
35233
+ paths.forEach((path3, index) => {
35068
35234
  const lines = [];
35069
- renderTracePath(path2, index, lines);
35235
+ renderTracePath(path3, index, lines);
35070
35236
  sections2.push(lines.join(`
35071
35237
  `));
35072
35238
  });
@@ -35524,6 +35690,11 @@ Pass a single \`target\`:
35524
35690
  }));
35525
35691
  if (symbolsArray.length === 1) {
35526
35692
  const response2 = results[0] ?? { success: false, message: "missing zoom response" };
35693
+ const rustBatch = unwrapRustZoomBatchEnvelope(response2);
35694
+ if (rustBatch) {
35695
+ const batch2 = formatZoomBatchResult(targetLabel, rustBatch.names, rustBatch.responses);
35696
+ return textResult(batch2.text, batch2);
35697
+ }
35527
35698
  if (response2.success === false) {
35528
35699
  throw new Error(response2.message || "zoom failed");
35529
35700
  }
@@ -35759,7 +35930,7 @@ function registerRefactorTool(pi, ctx) {
35759
35930
  import { StringEnum as StringEnum5 } from "@earendil-works/pi-ai";
35760
35931
  import { Type as Type12 } from "typebox";
35761
35932
  function responsePaths(response) {
35762
- return Array.isArray(response.paths) ? response.paths.filter((path2) => typeof path2 === "string" && path2.length > 0) : [];
35933
+ return Array.isArray(response.paths) ? response.paths.filter((path3) => typeof path3 === "string" && path3.length > 0) : [];
35763
35934
  }
35764
35935
  var SafetyParams = Type12.Object({
35765
35936
  op: StringEnum5(["undo", "history", "checkpoint", "restore", "list"], {
@@ -36225,18 +36396,18 @@ function createVersionMismatchHandler(getPool, ensureCompatibleBinary = ensureBi
36225
36396
  const upgradePromise = (async () => {
36226
36397
  warn2(`WARNING: aft binary v${binaryVersion} is older than plugin v${minVersion}. ` + "Some features may not work. Attempting to download a compatible binary...");
36227
36398
  try {
36228
- const path2 = await ensureCompatibleBinary(`v${minVersion}`);
36229
- if (!path2) {
36399
+ const path3 = await ensureCompatibleBinary(`v${minVersion}`);
36400
+ if (!path3) {
36230
36401
  warn2(`Could not find or download v${minVersion}. Continuing with v${binaryVersion}.`);
36231
36402
  return null;
36232
36403
  }
36233
36404
  const pool = getPool();
36234
36405
  if (!pool) {
36235
- warn2(`Found/downloaded compatible binary at ${path2}, but bridge pool is not ready.`);
36406
+ warn2(`Found/downloaded compatible binary at ${path3}, but bridge pool is not ready.`);
36236
36407
  return null;
36237
36408
  }
36238
- log2(`Found/downloaded compatible binary at ${path2}. Replacing running bridges...`);
36239
- const replaced = await pool.replaceBinary(path2);
36409
+ log2(`Found/downloaded compatible binary at ${path3}. Replacing running bridges...`);
36410
+ const replaced = await pool.replaceBinary(path3);
36240
36411
  log2("Binary replaced successfully. New bridges will use the updated binary.");
36241
36412
  return replaced;
36242
36413
  } catch (err) {
@@ -36561,7 +36732,7 @@ ${lines}
36561
36732
  if (onnxRuntimePromise) {
36562
36733
  await Promise.race([
36563
36734
  onnxRuntimePromise,
36564
- new Promise((resolve4) => setTimeout(() => resolve4(null), 60000))
36735
+ new Promise((resolve5) => setTimeout(() => resolve5(null), 60000))
36565
36736
  ]);
36566
36737
  }
36567
36738
  const bridge = pool.getBridge(cwd);