@cortexkit/aft-pi 0.39.0 → 0.39.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -11913,6 +12020,11 @@ var LONG_RUNNING_COMMAND_TIMEOUT_MS = {
11913
12020
  function timeoutForCommand(command) {
11914
12021
  return LONG_RUNNING_COMMAND_TIMEOUT_MS[command];
11915
12022
  }
12023
+ var PASSIVE_COMMANDS = new Set(["status"]);
12024
+ var PASSIVE_COMMAND_TIMEOUT_MS = 5000;
12025
+ function isPassiveCommand(command) {
12026
+ return PASSIVE_COMMANDS.has(command);
12027
+ }
11916
12028
 
11917
12029
  // ../aft-bridge/dist/status-bar.js
11918
12030
  var STATUS_BAR_HEARTBEAT_CALLS = 15;
@@ -11985,6 +12097,11 @@ function bashTaskIdFrom(response) {
11985
12097
  function tagStderrLine(line) {
11986
12098
  return /^\[aft(-\w+)?\] /.test(line) ? line : `[aft] ${line}`;
11987
12099
  }
12100
+ var BENIGN_CPUINFO_PROC_CPUINFO_PARSE_FAILURE = "failed to parse processor information from /proc/cpuinfo";
12101
+ function shouldSurfaceStderrLine(line) {
12102
+ const normalized = line.trim();
12103
+ return !(normalized === `Error in cpuinfo: ${BENIGN_CPUINFO_PROC_CPUINFO_PARSE_FAILURE}` || normalized === BENIGN_CPUINFO_PROC_CPUINFO_PARSE_FAILURE);
12104
+ }
11988
12105
  function compareSemver(a, b) {
11989
12106
  const [aMain, aPre] = a.split("-", 2);
11990
12107
  const [bMain, bPre] = b.split("-", 2);
@@ -12076,6 +12193,7 @@ class BinaryBridge {
12076
12193
  _restartCount = 0;
12077
12194
  _shuttingDown = false;
12078
12195
  timeoutMs;
12196
+ hangThreshold;
12079
12197
  maxRestarts;
12080
12198
  configured = false;
12081
12199
  _configurePromise = null;
@@ -12100,6 +12218,7 @@ class BinaryBridge {
12100
12218
  this.binaryPath = binaryPath;
12101
12219
  this.cwd = cwd;
12102
12220
  this.timeoutMs = options?.timeoutMs ?? DEFAULT_BRIDGE_TIMEOUT_MS;
12221
+ this.hangThreshold = options?.hangThreshold ?? BRIDGE_HANG_TIMEOUT_THRESHOLD;
12103
12222
  this.maxRestarts = options?.maxRestarts ?? 3;
12104
12223
  this.configOverrides = clampSemanticTimeout(configOverrides ?? {}, this.timeoutMs);
12105
12224
  this.minVersion = options?.minVersion;
@@ -12217,7 +12336,9 @@ class BinaryBridge {
12217
12336
  if (requestSessionId && options?.configureWarningClient !== undefined) {
12218
12337
  this.configureWarningClients.set(requestSessionId, options.configureWarningClient);
12219
12338
  }
12220
- const effectiveTimeoutMs = options?.transportTimeoutMs ?? options?.timeoutMs ?? this.timeoutMs;
12339
+ const passive = isPassiveCommand(command);
12340
+ const resolvedTimeoutMs = options?.transportTimeoutMs ?? options?.timeoutMs ?? this.timeoutMs;
12341
+ const effectiveTimeoutMs = passive ? Math.min(resolvedTimeoutMs, PASSIVE_COMMAND_TIMEOUT_MS) : resolvedTimeoutMs;
12221
12342
  const implicitTransportOptions = {
12222
12343
  ...options?.transportTimeoutMs !== undefined || options?.timeoutMs !== undefined ? { transportTimeoutMs: effectiveTimeoutMs } : {},
12223
12344
  markConfiguredOnSuccess: false
@@ -12267,9 +12388,9 @@ class BinaryBridge {
12267
12388
  }
12268
12389
  const line = `${JSON.stringify(request)}
12269
12390
  `;
12270
- const keepBridgeOnTimeout = options?.keepBridgeOnTimeout === true;
12391
+ const keepBridgeOnTimeout = passive || options?.keepBridgeOnTimeout === true;
12271
12392
  let requestSentAt = Date.now();
12272
- const response = await new Promise((resolve, reject) => {
12393
+ const response = await new Promise((resolve2, reject) => {
12273
12394
  const timer = setTimeout(() => {
12274
12395
  const entry = this.pending.get(id);
12275
12396
  if (!entry)
@@ -12289,7 +12410,7 @@ class BinaryBridge {
12289
12410
  const childActiveSinceRequest = this.lastChildActivityAt > requestSentAt;
12290
12411
  const consecutiveTimeouts = this.consecutiveRequestTimeouts + 1;
12291
12412
  this.consecutiveRequestTimeouts = consecutiveTimeouts;
12292
- const keepWarm = childActiveSinceRequest || consecutiveTimeouts < BRIDGE_HANG_TIMEOUT_THRESHOLD;
12413
+ const keepWarm = childActiveSinceRequest || consecutiveTimeouts < this.hangThreshold;
12293
12414
  const restartSuffix = keepWarm ? " — bridge kept warm" : " — restarting bridge";
12294
12415
  const timeoutMsg = `Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms${restartSuffix}`;
12295
12416
  if (requestSessionId) {
@@ -12304,7 +12425,7 @@ class BinaryBridge {
12304
12425
  entry.reject(new Error(`${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`));
12305
12426
  this.handleTimeout(requestSessionId);
12306
12427
  }, effectiveTimeoutMs);
12307
- this.pending.set(id, { resolve, reject, timer, onProgress: options?.onProgress, command });
12428
+ this.pending.set(id, { resolve: resolve2, reject, timer, onProgress: options?.onProgress, command });
12308
12429
  if (!this.process?.stdin?.writable) {
12309
12430
  this.pending.delete(id);
12310
12431
  clearTimeout(timer);
@@ -12402,15 +12523,15 @@ class BinaryBridge {
12402
12523
  if (this.process) {
12403
12524
  const proc = this.process;
12404
12525
  this.process = null;
12405
- return new Promise((resolve) => {
12526
+ return new Promise((resolve2) => {
12406
12527
  const forceKillTimer = setTimeout(() => {
12407
12528
  proc.kill("SIGKILL");
12408
- resolve();
12529
+ resolve2();
12409
12530
  }, 5000);
12410
12531
  proc.once("exit", () => {
12411
12532
  clearTimeout(forceKillTimer);
12412
12533
  this.logVia("Process exited during shutdown");
12413
- resolve();
12534
+ resolve2();
12414
12535
  });
12415
12536
  proc.kill("SIGTERM");
12416
12537
  });
@@ -12455,15 +12576,15 @@ class BinaryBridge {
12455
12576
  return;
12456
12577
  const proc = this.process;
12457
12578
  this.process = null;
12458
- await new Promise((resolve) => {
12579
+ await new Promise((resolve2) => {
12459
12580
  const forceKillTimer = setTimeout(() => {
12460
12581
  proc.kill("SIGKILL");
12461
- resolve();
12582
+ resolve2();
12462
12583
  }, 5000);
12463
12584
  proc.once("exit", () => {
12464
12585
  clearTimeout(forceKillTimer);
12465
12586
  this.logVia("Process exited during coordinated binary replacement");
12466
- resolve();
12587
+ resolve2();
12467
12588
  });
12468
12589
  proc.kill("SIGTERM");
12469
12590
  });
@@ -12490,7 +12611,7 @@ class BinaryBridge {
12490
12611
  })();
12491
12612
  const useFastembedBackend = semanticBackend === undefined || semanticBackend === "fastembed" || semanticBackend === "";
12492
12613
  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");
12614
+ const ortLibraryPath = ortDir == null ? null : join2(ortDir, process.platform === "win32" ? "onnxruntime.dll" : process.platform === "darwin" ? "libonnxruntime.dylib" : "libonnxruntime.so");
12494
12615
  const envPath = process.platform === "win32" && ortDir ? `${ortDir};${process.env.PATH ?? ""}` : process.env.PATH;
12495
12616
  const env = {
12496
12617
  ...process.env,
@@ -12498,7 +12619,7 @@ class BinaryBridge {
12498
12619
  };
12499
12620
  this.logVia(`bridge.spawnProcess: useFastembedBackend=${useFastembedBackend}, ` + `parentORT=${process.env.ORT_DYLIB_PATH ?? "(unset)"}, ` + `ortLibraryPath=${ortLibraryPath ?? "(none)"}`);
12500
12621
  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"));
12622
+ 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
12623
  if (process.env.ORT_DYLIB_PATH) {
12503
12624
  this.logVia(`ORT_DYLIB_PATH inherited from parent env: ${process.env.ORT_DYLIB_PATH}`);
12504
12625
  } else if (ortLibraryPath) {
@@ -12584,7 +12705,7 @@ class BinaryBridge {
12584
12705
  `)) !== -1) {
12585
12706
  const line = this.stderrBuffer.slice(0, newlineIdx).replace(/\r$/, "");
12586
12707
  this.stderrBuffer = this.stderrBuffer.slice(newlineIdx + 1);
12587
- if (!line)
12708
+ if (!line || !shouldSurfaceStderrLine(line))
12588
12709
  continue;
12589
12710
  const tagged = tagStderrLine(line);
12590
12711
  this.logVia(tagged);
@@ -12594,7 +12715,7 @@ class BinaryBridge {
12594
12715
  flushStderrBuffer() {
12595
12716
  const line = this.stderrBuffer.replace(/\r$/, "");
12596
12717
  this.stderrBuffer = "";
12597
- if (!line)
12718
+ if (!line || !shouldSurfaceStderrLine(line))
12598
12719
  return;
12599
12720
  const tagged = tagStderrLine(line);
12600
12721
  this.logVia(tagged);
@@ -12840,12 +12961,37 @@ function coerceStringArray(value) {
12840
12961
  }
12841
12962
  return [];
12842
12963
  }
12964
+ function coerceOptionalInt(v, paramName, min, max) {
12965
+ if (v === undefined || v === null || v === "")
12966
+ return;
12967
+ if (typeof v === "number" && (!Number.isFinite(v) || v === 0 && min > 0))
12968
+ return;
12969
+ const n = typeof v === "string" ? Number(v) : v;
12970
+ if (typeof n !== "number" || !Number.isInteger(n)) {
12971
+ throw new Error(`${paramName} must be an integer between ${min} and ${max}`);
12972
+ }
12973
+ if (n < min || n > max) {
12974
+ throw new Error(`${paramName} must be between ${min} and ${max}`);
12975
+ }
12976
+ return n;
12977
+ }
12978
+ function isEmptyParam(value) {
12979
+ if (value === undefined || value === null)
12980
+ return true;
12981
+ if (typeof value === "string")
12982
+ return value.length === 0;
12983
+ if (Array.isArray(value))
12984
+ return value.length === 0;
12985
+ if (typeof value === "object")
12986
+ return Object.keys(value).length === 0;
12987
+ return false;
12988
+ }
12843
12989
  // ../aft-bridge/dist/downloader.js
12844
12990
  import { spawnSync } from "node:child_process";
12845
12991
  import { createHash, randomUUID } from "node:crypto";
12846
12992
  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";
12993
+ import { homedir as homedir3 } from "node:os";
12994
+ import { join as join3 } from "node:path";
12849
12995
  import { Readable } from "node:stream";
12850
12996
  import { pipeline } from "node:stream/promises";
12851
12997
 
@@ -12902,11 +13048,11 @@ function isExpectedCachedBinary(binaryPath, tag) {
12902
13048
  function getCacheDir() {
12903
13049
  if (process.platform === "win32") {
12904
13050
  const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
12905
- const base2 = localAppData || join2(homedir2(), "AppData", "Local");
12906
- return join2(base2, "aft", "bin");
13051
+ const base2 = localAppData || join3(homedir3(), "AppData", "Local");
13052
+ return join3(base2, "aft", "bin");
12907
13053
  }
12908
- const base = process.env.XDG_CACHE_HOME || join2(homedir2(), ".cache");
12909
- return join2(base, "aft", "bin");
13054
+ const base = process.env.XDG_CACHE_HOME || join3(homedir3(), ".cache");
13055
+ return join3(base, "aft", "bin");
12910
13056
  }
12911
13057
  function getBinaryName() {
12912
13058
  return process.platform === "win32" ? "aft.exe" : "aft";
@@ -12914,7 +13060,7 @@ function getBinaryName() {
12914
13060
  function getCachedBinaryPath(version) {
12915
13061
  if (!version)
12916
13062
  return null;
12917
- const binaryPath = join2(getCacheDir(), version, getBinaryName());
13063
+ const binaryPath = join3(getCacheDir(), version, getBinaryName());
12918
13064
  return existsSync(binaryPath) ? binaryPath : null;
12919
13065
  }
12920
13066
  async function downloadBinary(version) {
@@ -12931,16 +13077,16 @@ async function downloadBinary(version) {
12931
13077
  return null;
12932
13078
  }
12933
13079
  const tag = rawTag.startsWith("v") ? rawTag : `v${rawTag}`;
12934
- const versionedCacheDir = join2(getCacheDir(), tag);
13080
+ const versionedCacheDir = join3(getCacheDir(), tag);
12935
13081
  const binaryName = getBinaryName();
12936
- const binaryPath = join2(versionedCacheDir, binaryName);
13082
+ const binaryPath = join3(versionedCacheDir, binaryName);
12937
13083
  if (existsSync(binaryPath) && isExpectedCachedBinary(binaryPath, tag)) {
12938
13084
  return binaryPath;
12939
13085
  }
12940
13086
  const downloadUrl = `https://github.com/${REPO}/releases/download/${tag}/${assetName}`;
12941
13087
  const checksumUrl = `https://github.com/${REPO}/releases/download/${tag}/checksums.sha256`;
12942
13088
  log(`Downloading AFT binary (${tag}) for ${platformKey}...`);
12943
- const lockPath = join2(versionedCacheDir, ".download.lock");
13089
+ const lockPath = join3(versionedCacheDir, ".download.lock");
12944
13090
  let releaseLock = null;
12945
13091
  let binaryController = null;
12946
13092
  let checksumController = null;
@@ -13092,7 +13238,7 @@ async function acquireDownloadLock(lockPath) {
13092
13238
  if (Date.now() - startedAt > DOWNLOAD_LOCK_TIMEOUT_MS) {
13093
13239
  throw new Error(`Timed out waiting for download lock: ${lockPath}`);
13094
13240
  }
13095
- await new Promise((resolve) => setTimeout(resolve, 100));
13241
+ await new Promise((resolve2) => setTimeout(resolve2, 100));
13096
13242
  }
13097
13243
  }
13098
13244
  }
@@ -13185,18 +13331,18 @@ function stripJsoncSymbols(value) {
13185
13331
  // ../aft-bridge/dist/migration.js
13186
13332
  import { spawnSync as spawnSync2 } from "node:child_process";
13187
13333
  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";
13334
+ import { homedir as homedir5, tmpdir } from "node:os";
13335
+ import { dirname as dirname2, join as join6 } from "node:path";
13190
13336
 
13191
13337
  // ../aft-bridge/dist/paths.js
13192
13338
  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";
13339
+ import { dirname, join as join4 } from "node:path";
13194
13340
  function resolveHarnessStoragePath(storageRoot, harness, ...segments) {
13195
- return join3(storageRoot, harness, ...segments);
13341
+ return join4(storageRoot, harness, ...segments);
13196
13342
  }
13197
13343
  function repairRootScopedStorageFile(storageRoot, harness, fileName) {
13198
13344
  const harnessPath = resolveHarnessStoragePath(storageRoot, harness, fileName);
13199
- const rootPath = join3(storageRoot, fileName);
13345
+ const rootPath = join4(storageRoot, fileName);
13200
13346
  if (existsSync2(harnessPath) || !existsSync2(rootPath))
13201
13347
  return harnessPath;
13202
13348
  try {
@@ -13242,8 +13388,8 @@ function markAnnouncementSeen(storageRoot, harness, currentVersion) {
13242
13388
  import { execSync } from "node:child_process";
13243
13389
  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
13390
  import { createRequire as createRequire2 } from "node:module";
13245
- import { homedir as homedir3 } from "node:os";
13246
- import { join as join4 } from "node:path";
13391
+ import { homedir as homedir4 } from "node:os";
13392
+ import { join as join5 } from "node:path";
13247
13393
  var ensureBinaryForResolver = ensureBinary;
13248
13394
  function copyToVersionedCache(npmBinaryPath, knownVersion) {
13249
13395
  try {
@@ -13252,9 +13398,9 @@ function copyToVersionedCache(npmBinaryPath, knownVersion) {
13252
13398
  return null;
13253
13399
  const tag = version.startsWith("v") ? version : `v${version}`;
13254
13400
  const cacheDir = getCacheDir();
13255
- const versionedDir = join4(cacheDir, tag);
13401
+ const versionedDir = join5(cacheDir, tag);
13256
13402
  const ext = process.platform === "win32" ? ".exe" : "";
13257
- const cachedPath = join4(versionedDir, `aft${ext}`);
13403
+ const cachedPath = join5(versionedDir, `aft${ext}`);
13258
13404
  if (existsSync3(cachedPath)) {
13259
13405
  const cachedVersion = readBinaryVersion(cachedPath);
13260
13406
  if (cachedVersion === version)
@@ -13284,18 +13430,18 @@ function normalizeBareVersion(version) {
13284
13430
  return version.startsWith("v") ? version.slice(1) : version;
13285
13431
  }
13286
13432
  function homeDirFromEnv(env) {
13287
- return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir3();
13433
+ return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir4();
13288
13434
  }
13289
13435
  function cacheDirFromEnv(env) {
13290
13436
  if (process.platform === "win32") {
13291
- const base2 = env.LOCALAPPDATA || env.APPDATA || join4(homeDirFromEnv(env), "AppData", "Local");
13292
- return join4(base2, "aft", "bin");
13437
+ const base2 = env.LOCALAPPDATA || env.APPDATA || join5(homeDirFromEnv(env), "AppData", "Local");
13438
+ return join5(base2, "aft", "bin");
13293
13439
  }
13294
- const base = env.XDG_CACHE_HOME || join4(homeDirFromEnv(env), ".cache");
13295
- return join4(base, "aft", "bin");
13440
+ const base = env.XDG_CACHE_HOME || join5(homeDirFromEnv(env), ".cache");
13441
+ return join5(base, "aft", "bin");
13296
13442
  }
13297
13443
  function cachedBinaryPathFromEnv(version, env, ext) {
13298
- const binaryPath = join4(cacheDirFromEnv(env), version, `aft${ext}`);
13444
+ const binaryPath = join5(cacheDirFromEnv(env), version, `aft${ext}`);
13299
13445
  return existsSync3(binaryPath) ? binaryPath : null;
13300
13446
  }
13301
13447
  function isExpectedCachedBinary2(binaryPath, expectedVersion) {
@@ -13414,7 +13560,7 @@ function findBinarySync(expectedVersion) {
13414
13560
  return usable;
13415
13561
  }
13416
13562
  } catch {}
13417
- const cargoPath = join4(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
13563
+ const cargoPath = join5(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
13418
13564
  if (existsSync3(cargoPath)) {
13419
13565
  const usable = probeBinaryCandidate(cargoPath, "cargo", expectedVersion);
13420
13566
  if (usable)
@@ -13460,22 +13606,22 @@ function dataHome() {
13460
13606
  if (process.env.XDG_DATA_HOME)
13461
13607
  return process.env.XDG_DATA_HOME;
13462
13608
  if (process.platform === "win32") {
13463
- return process.env.LOCALAPPDATA || process.env.APPDATA || join5(homeDir(), "AppData", "Local");
13609
+ return process.env.LOCALAPPDATA || process.env.APPDATA || join6(homeDir(), "AppData", "Local");
13464
13610
  }
13465
- return join5(homeDir(), ".local", "share");
13611
+ return join6(homeDir(), ".local", "share");
13466
13612
  }
13467
13613
  function homeDir() {
13468
13614
  if (process.platform === "win32")
13469
- return process.env.USERPROFILE || process.env.HOME || homedir4();
13470
- return process.env.HOME || homedir4();
13615
+ return process.env.USERPROFILE || process.env.HOME || homedir5();
13616
+ return process.env.HOME || homedir5();
13471
13617
  }
13472
13618
  function resolveLegacyStorageRoot(harness) {
13473
13619
  if (harness === "pi")
13474
- return join5(homeDir(), ".pi", "agent", "aft");
13475
- return join5(dataHome(), "opencode", "storage", "plugin", "aft");
13620
+ return join6(homeDir(), ".pi", "agent", "aft");
13621
+ return join6(dataHome(), "opencode", "storage", "plugin", "aft");
13476
13622
  }
13477
13623
  function resolveCortexKitStorageRoot() {
13478
- return join5(dataHome(), "cortexkit", "aft");
13624
+ return join6(dataHome(), "cortexkit", "aft");
13479
13625
  }
13480
13626
  function tail(value) {
13481
13627
  if (!value)
@@ -13489,12 +13635,12 @@ function spawnErrorLabel(error2) {
13489
13635
  return [code, error2.message].filter(Boolean).join(": ");
13490
13636
  }
13491
13637
  function migrationLogPath(newRoot, harness, logger) {
13492
- const desired = join5(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
13638
+ const desired = join6(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
13493
13639
  try {
13494
13640
  mkdirSync4(dirname2(desired), { recursive: true });
13495
13641
  return desired;
13496
13642
  } catch (err) {
13497
- const fallback = join5(tmpdir(), `aft-migration-${harness}-${Date.now()}.jsonl`);
13643
+ const fallback = join6(tmpdir(), `aft-migration-${harness}-${Date.now()}.jsonl`);
13498
13644
  logger?.warn?.(`Failed to create AFT migration log directory ${dirname2(desired)}: ${err instanceof Error ? err.message : String(err)}. ` + `Using fallback log path ${fallback}.`);
13499
13645
  return fallback;
13500
13646
  }
@@ -13557,13 +13703,13 @@ async function ensureStorageMigrated(opts) {
13557
13703
  }
13558
13704
  // ../aft-bridge/dist/npm-resolver.js
13559
13705
  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";
13706
+ import { homedir as homedir6 } from "node:os";
13707
+ import { delimiter, dirname as dirname3, isAbsolute as isAbsolute2, join as join7 } from "node:path";
13562
13708
  function defaultDeps() {
13563
13709
  return {
13564
13710
  platform: process.platform,
13565
13711
  env: process.env,
13566
- home: homedir5(),
13712
+ home: homedir6(),
13567
13713
  execPath: process.execPath
13568
13714
  };
13569
13715
  }
@@ -13582,16 +13728,16 @@ function npmFromPath(deps) {
13582
13728
  const raw = deps.env.PATH ?? deps.env.Path ?? "";
13583
13729
  for (const entry of raw.split(delimiter)) {
13584
13730
  const dir = entry.trim().replace(/^"|"$/g, "");
13585
- if (!dir || !isAbsolute(dir))
13731
+ if (!dir || !isAbsolute2(dir))
13586
13732
  continue;
13587
- if (isFile(join6(dir, name)))
13733
+ if (isFile(join7(dir, name)))
13588
13734
  return dir;
13589
13735
  }
13590
13736
  return null;
13591
13737
  }
13592
13738
  function npmAdjacentToNode(deps) {
13593
13739
  const dir = dirname3(deps.execPath);
13594
- return isFile(join6(dir, npmBinaryName(deps.platform))) ? dir : null;
13740
+ return isFile(join7(dir, npmBinaryName(deps.platform))) ? dir : null;
13595
13741
  }
13596
13742
  function highestVersionedNodeBin(installsDir, name) {
13597
13743
  let entries;
@@ -13600,8 +13746,8 @@ function highestVersionedNodeBin(installsDir, name) {
13600
13746
  } catch {
13601
13747
  return null;
13602
13748
  }
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;
13749
+ const candidates = entries.filter((v) => isFile(join7(installsDir, v, "bin", name))).sort((a, b) => compareVersionsDesc(a, b));
13750
+ return candidates.length > 0 ? join7(installsDir, candidates[0], "bin") : null;
13605
13751
  }
13606
13752
  function compareVersionsDesc(a, b) {
13607
13753
  const pa = a.replace(/^v/, "").split(".").map((n) => Number.parseInt(n, 10));
@@ -13626,22 +13772,22 @@ function wellKnownNpmDirs(deps) {
13626
13772
  const programFiles = env.ProgramFiles || "C:\\Program Files";
13627
13773
  const appData = env.APPDATA;
13628
13774
  const localAppData = env.LOCALAPPDATA;
13629
- push(join6(programFiles, "nodejs"));
13775
+ push(join7(programFiles, "nodejs"));
13630
13776
  if (appData)
13631
- push(join6(appData, "npm"));
13777
+ push(join7(appData, "npm"));
13632
13778
  if (localAppData)
13633
- push(join6(localAppData, "Volta", "bin"));
13779
+ push(join7(localAppData, "Volta", "bin"));
13634
13780
  if (env.NVM_SYMLINK)
13635
13781
  push(env.NVM_SYMLINK);
13636
13782
  } else {
13637
13783
  if (env.NVM_BIN)
13638
13784
  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")]);
13785
+ push(highestVersionedNodeBin(join7(home, ".nvm", "versions", "node"), name));
13786
+ push(highestVersionedNodeBin(join7(home, ".local", "share", "mise", "installs", "node"), name));
13787
+ push(highestVersionedNodeBin(join7(home, ".asdf", "installs", "nodejs"), name));
13788
+ push(join7(home, ".volta", "bin"));
13789
+ push(join7(home, ".asdf", "shims"));
13790
+ const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin", join7(home, ".local", "bin")]);
13645
13791
  for (const dir of systemDirs)
13646
13792
  push(dir);
13647
13793
  }
@@ -13651,12 +13797,12 @@ function resolveNpm(deps = defaultDeps()) {
13651
13797
  const name = npmBinaryName(deps.platform);
13652
13798
  const onPath = npmFromPath(deps);
13653
13799
  if (onPath)
13654
- return { command: join6(onPath, name), binDir: onPath };
13800
+ return { command: join7(onPath, name), binDir: onPath };
13655
13801
  const adjacent = npmAdjacentToNode(deps);
13656
13802
  if (adjacent)
13657
- return { command: join6(adjacent, name), binDir: adjacent };
13803
+ return { command: join7(adjacent, name), binDir: adjacent };
13658
13804
  for (const dir of wellKnownNpmDirs(deps)) {
13659
- const candidate = join6(dir, name);
13805
+ const candidate = join7(dir, name);
13660
13806
  if (isFile(candidate))
13661
13807
  return { command: candidate, binDir: dir };
13662
13808
  }
@@ -13673,7 +13819,7 @@ function npmSpawnEnv(resolved, baseEnv = process.env) {
13673
13819
  import { execFileSync } from "node:child_process";
13674
13820
  import { createHash as createHash2 } from "node:crypto";
13675
13821
  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";
13822
+ import { basename, dirname as dirname4, isAbsolute as isAbsolute3, join as join8, relative as relative2, resolve as resolve2, win32 } from "node:path";
13677
13823
  import { Readable as Readable2 } from "node:stream";
13678
13824
  import { pipeline as pipeline2 } from "node:stream/promises";
13679
13825
  var ORT_VERSION = "1.24.4";
@@ -13736,10 +13882,10 @@ function getManualInstallHint() {
13736
13882
  }
13737
13883
  async function ensureOnnxRuntime(storageDir) {
13738
13884
  const info = getPlatformInfo();
13739
- const ortVersionDir = join7(storageDir, "onnxruntime", ORT_VERSION);
13885
+ const ortVersionDir = join8(storageDir, "onnxruntime", ORT_VERSION);
13740
13886
  const libName = info?.libName ?? "libonnxruntime.dylib";
13741
13887
  const resolvedOrtDir = resolveCachedOnnxRuntimeDir(ortVersionDir, libName);
13742
- const libPath = join7(resolvedOrtDir, libName);
13888
+ const libPath = join8(resolvedOrtDir, libName);
13743
13889
  if (existsSync5(libPath)) {
13744
13890
  const meta = readOnnxInstalledMeta(ortVersionDir);
13745
13891
  if (meta?.sha256) {
@@ -13769,9 +13915,9 @@ async function ensureOnnxRuntime(storageDir) {
13769
13915
  warn(`ONNX Runtime auto-download not available for ${process.platform}/${process.arch}. Install manually: ${getManualInstallHint()}`);
13770
13916
  return null;
13771
13917
  }
13772
- const onnxBaseDir = join7(storageDir, "onnxruntime");
13918
+ const onnxBaseDir = join8(storageDir, "onnxruntime");
13773
13919
  mkdirSync5(onnxBaseDir, { recursive: true });
13774
- const lockPath = join7(onnxBaseDir, ONNX_LOCK_FILE);
13920
+ const lockPath = join8(onnxBaseDir, ONNX_LOCK_FILE);
13775
13921
  cleanupAbandonedStagingDirs(onnxBaseDir);
13776
13922
  if (!acquireLock(lockPath)) {
13777
13923
  warn(`ONNX Runtime install already in progress in another process (lock: ${lockPath}). Skipping.`);
@@ -13790,7 +13936,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
13790
13936
  for (const entry of entries) {
13791
13937
  if (!entry.startsWith(`${ORT_VERSION}.tmp.`))
13792
13938
  continue;
13793
- const stagingDir = join7(onnxBaseDir, entry);
13939
+ const stagingDir = join8(onnxBaseDir, entry);
13794
13940
  const parts = entry.split(".");
13795
13941
  const pidStr = parts[parts.length - 2];
13796
13942
  const pid = pidStr ? Number.parseInt(pidStr, 10) : NaN;
@@ -13827,7 +13973,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
13827
13973
  }
13828
13974
  function cleanupIncompleteTargetIfUnowned(ortDir) {
13829
13975
  try {
13830
- if (existsSync5(ortDir) && !existsSync5(join7(ortDir, ONNX_INSTALLED_META_FILE))) {
13976
+ if (existsSync5(ortDir) && !existsSync5(join8(ortDir, ONNX_INSTALLED_META_FILE))) {
13831
13977
  log(`[onnx] removing half-populated install dir ${ortDir} (no meta file)`);
13832
13978
  rmSync2(ortDir, { recursive: true, force: true });
13833
13979
  }
@@ -13855,8 +14001,8 @@ function parseOnnxVersionFromDirectoryPath(value) {
13855
14001
  return null;
13856
14002
  }
13857
14003
  function isPathInsideRoot(root, candidate) {
13858
- const rel = relative(root, candidate);
13859
- return rel === "" || !rel.startsWith("../") && !rel.startsWith("..\\") && rel !== ".." && !isAbsolute2(rel) && !win32.isAbsolute(rel);
14004
+ const rel = relative2(root, candidate);
14005
+ return rel === "" || !rel.startsWith("../") && !rel.startsWith("..\\") && rel !== ".." && !isAbsolute3(rel) && !win32.isAbsolute(rel);
13860
14006
  }
13861
14007
  function detectOnnxVersion(libDir, libName) {
13862
14008
  try {
@@ -13871,7 +14017,7 @@ function detectOnnxVersion(libDir, libName) {
13871
14017
  if (version)
13872
14018
  return version;
13873
14019
  }
13874
- const base = join7(libDir, libName);
14020
+ const base = join8(libDir, libName);
13875
14021
  if (existsSync5(base)) {
13876
14022
  try {
13877
14023
  const real = realpathSync(base);
@@ -13907,7 +14053,7 @@ function pathEntriesForPlatform() {
13907
14053
  return pathEnvValue().split(delimiter2).map((entry) => entry.trim().replace(/^"|"$/g, "")).filter((entry) => {
13908
14054
  if (!entry || entry === "." || entry.includes("\x00"))
13909
14055
  return false;
13910
- return isAbsolute2(entry) || win32.isAbsolute(entry);
14056
+ return isAbsolute3(entry) || win32.isAbsolute(entry);
13911
14057
  });
13912
14058
  }
13913
14059
  function directoryContainsLibrary(dir, libName) {
@@ -13923,10 +14069,10 @@ function directoryContainsLibrary(dir, libName) {
13923
14069
  }
13924
14070
  }
13925
14071
  function resolveCachedOnnxRuntimeDir(ortVersionDir, libName) {
13926
- if (existsSync5(join7(ortVersionDir, libName)))
14072
+ if (existsSync5(join8(ortVersionDir, libName)))
13927
14073
  return ortVersionDir;
13928
- const libSubdir = join7(ortVersionDir, "lib");
13929
- if (existsSync5(join7(libSubdir, libName)))
14074
+ const libSubdir = join8(ortVersionDir, "lib");
14075
+ if (existsSync5(join8(libSubdir, libName)))
13930
14076
  return libSubdir;
13931
14077
  return ortVersionDir;
13932
14078
  }
@@ -13941,12 +14087,12 @@ function findSystemOnnxRuntime(libName) {
13941
14087
  } else if (process.platform === "win32") {
13942
14088
  const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
13943
14089
  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"), ...(() => {
14090
+ searchPaths.push(join8(programFiles, "onnxruntime", "lib"), join8(programFiles, "Microsoft ONNX Runtime", "lib"), join8(programFiles, "Microsoft Machine Learning", "lib"), join8(programFilesX86, "onnxruntime", "lib"), ...(() => {
13945
14091
  const nugetPaths = [];
13946
14092
  const userProfile = process.env.USERPROFILE ?? "";
13947
14093
  if (!userProfile)
13948
14094
  return nugetPaths;
13949
- const nugetPackageDir = join7(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
14095
+ const nugetPackageDir = join8(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
13950
14096
  if (!existsSync5(nugetPackageDir))
13951
14097
  return nugetPaths;
13952
14098
  try {
@@ -13955,7 +14101,7 @@ function findSystemOnnxRuntime(libName) {
13955
14101
  continue;
13956
14102
  if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
13957
14103
  continue;
13958
- nugetPaths.push(join7(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join7(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
14104
+ nugetPaths.push(join8(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join8(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
13959
14105
  }
13960
14106
  } catch (err) {
13961
14107
  warn(`Failed to scan NuGet ONNX Runtime cache ${nugetPackageDir}: ${err instanceof Error ? err.message : String(err)}`);
@@ -13967,7 +14113,7 @@ function findSystemOnnxRuntime(libName) {
13967
14113
  const normalizeCase = process.platform === "win32" || process.platform === "darwin";
13968
14114
  const seen = new Set;
13969
14115
  const uniquePaths = searchPaths.filter((p) => {
13970
- let key = resolve(p).replace(/[/\\]+$/, "");
14116
+ let key = resolve2(p).replace(/[/\\]+$/, "");
13971
14117
  if (normalizeCase)
13972
14118
  key = key.toLowerCase();
13973
14119
  if (seen.has(key))
@@ -13977,7 +14123,7 @@ function findSystemOnnxRuntime(libName) {
13977
14123
  });
13978
14124
  const unknownVersionPaths = [];
13979
14125
  for (const dir of uniquePaths) {
13980
- const libPath = join7(dir, libName);
14126
+ const libPath = join8(dir, libName);
13981
14127
  if (process.platform === "win32") {
13982
14128
  if (!directoryContainsLibrary(dir, libName))
13983
14129
  continue;
@@ -14043,19 +14189,19 @@ function validateExtractedTree(stagingRoot) {
14043
14189
  const walk = (dir) => {
14044
14190
  const entries = readdirSync2(dir);
14045
14191
  for (const entry of entries) {
14046
- const fullPath = join7(dir, entry);
14192
+ const fullPath = join8(dir, entry);
14047
14193
  const lst = lstatSync(fullPath);
14048
14194
  if (lst.isSymbolicLink()) {
14049
14195
  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)) {
14196
+ const resolvedTarget = resolve2(dirname4(fullPath), linkTarget);
14197
+ const rel2 = relative2(realRoot, resolvedTarget);
14198
+ if (rel2.startsWith("..") || isAbsolute3(rel2) || win32.isAbsolute(rel2)) {
14053
14199
  throw new Error(`extracted symlink ${fullPath} points outside staging root: ${linkTarget}`);
14054
14200
  }
14055
14201
  continue;
14056
14202
  }
14057
- const rel = relative(realRoot, fullPath);
14058
- if (rel.startsWith("..") || isAbsolute2(rel) || win32.isAbsolute(rel)) {
14203
+ const rel = relative2(realRoot, fullPath);
14204
+ if (rel.startsWith("..") || isAbsolute3(rel) || win32.isAbsolute(rel)) {
14059
14205
  throw new Error(`extracted entry ${fullPath} escapes staging root`);
14060
14206
  }
14061
14207
  if (lst.isDirectory()) {
@@ -14078,7 +14224,7 @@ async function downloadOnnxRuntime(info, targetDir) {
14078
14224
  const tmpDir = `${targetDir}.tmp.${process.pid}.${Date.now().toString(36)}`;
14079
14225
  try {
14080
14226
  mkdirSync5(tmpDir, { recursive: true });
14081
- const archivePath = join7(tmpDir, `onnxruntime.${info.archiveType}`);
14227
+ const archivePath = join8(tmpDir, `onnxruntime.${info.archiveType}`);
14082
14228
  await downloadFileWithCap(url, archivePath);
14083
14229
  const archiveSha256 = sha256File(archivePath);
14084
14230
  log(`ONNX Runtime archive sha256=${archiveSha256}`);
@@ -14094,7 +14240,7 @@ async function downloadOnnxRuntime(info, targetDir) {
14094
14240
  unlinkSync3(archivePath);
14095
14241
  } catch {}
14096
14242
  validateExtractedTree(tmpDir);
14097
- const extractedDir = join7(tmpDir, info.assetName, "lib");
14243
+ const extractedDir = join8(tmpDir, info.assetName, "lib");
14098
14244
  if (!existsSync5(extractedDir)) {
14099
14245
  throw new Error(`Expected directory not found: ${extractedDir}`);
14100
14246
  }
@@ -14103,7 +14249,7 @@ async function downloadOnnxRuntime(info, targetDir) {
14103
14249
  const realFiles = [];
14104
14250
  const symlinks = [];
14105
14251
  for (const libFile of libFiles) {
14106
- const src = join7(extractedDir, libFile);
14252
+ const src = join8(extractedDir, libFile);
14107
14253
  try {
14108
14254
  const stat = lstatSync(src);
14109
14255
  log(`ORT extract: ${libFile} — isSymlink=${stat.isSymbolicLink()}, isFile=${stat.isFile()}, size=${stat.size}`);
@@ -14118,7 +14264,7 @@ async function downloadOnnxRuntime(info, targetDir) {
14118
14264
  }
14119
14265
  }
14120
14266
  copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks);
14121
- const libPath = join7(targetDir, info.libName);
14267
+ const libPath = join8(targetDir, info.libName);
14122
14268
  let libHash = null;
14123
14269
  try {
14124
14270
  libHash = sha256File(libPath);
@@ -14143,8 +14289,8 @@ async function downloadOnnxRuntime(info, targetDir) {
14143
14289
  function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, copyFile = copyFileSync3) {
14144
14290
  const requiredLibs = new Set([info.libName]);
14145
14291
  for (const libFile of realFiles) {
14146
- const src = join7(extractedDir, libFile);
14147
- const dst = join7(targetDir, libFile);
14292
+ const src = join8(extractedDir, libFile);
14293
+ const dst = join8(targetDir, libFile);
14148
14294
  try {
14149
14295
  copyFile(src, dst);
14150
14296
  if (process.platform !== "win32") {
@@ -14160,12 +14306,12 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
14160
14306
  }
14161
14307
  const targetRoot = realpathSync(targetDir);
14162
14308
  for (const link of symlinks) {
14163
- const dst = join7(targetDir, link.name);
14309
+ const dst = join8(targetDir, link.name);
14164
14310
  try {
14165
14311
  unlinkSync3(dst);
14166
14312
  } catch {}
14167
- const dstForContainment = join7(targetRoot, link.name);
14168
- const resolvedTarget = resolve(dirname4(dstForContainment), link.target);
14313
+ const dstForContainment = join8(targetRoot, link.name);
14314
+ const resolvedTarget = resolve2(dirname4(dstForContainment), link.target);
14169
14315
  if (!isPathInsideRoot(targetRoot, resolvedTarget)) {
14170
14316
  const message = `ONNX Runtime symlink ${link.name} points outside install dir: ${link.target}`;
14171
14317
  if (requiredLibs.has(link.name)) {
@@ -14185,7 +14331,7 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
14185
14331
  log(`ORT extract: failed to symlink optional ${link.name}: ${symlinkErr}`);
14186
14332
  }
14187
14333
  }
14188
- const requiredPath = join7(targetDir, info.libName);
14334
+ const requiredPath = join8(targetDir, info.libName);
14189
14335
  if (!existsSync5(requiredPath)) {
14190
14336
  rmSync2(targetDir, { recursive: true, force: true });
14191
14337
  throw new Error(`Required ONNX Runtime library missing after install: ${requiredPath}`);
@@ -14212,17 +14358,17 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
14212
14358
  ...sha256 ? { sha256 } : {},
14213
14359
  archiveSha256
14214
14360
  };
14215
- writeFileSync2(join7(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
14361
+ writeFileSync2(join8(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
14216
14362
  } catch (err) {
14217
14363
  log(`[onnx] failed to write installed-meta in ${installDir}: ${err}`);
14218
14364
  }
14219
14365
  }
14220
14366
  function readOnnxInstalledMeta(installDir) {
14221
- const path = join7(installDir, ONNX_INSTALLED_META_FILE);
14367
+ const path2 = join8(installDir, ONNX_INSTALLED_META_FILE);
14222
14368
  try {
14223
- if (!statSync3(path).isFile())
14369
+ if (!statSync3(path2).isFile())
14224
14370
  return null;
14225
- const raw = readFileSync3(path, "utf8");
14371
+ const raw = readFileSync3(path2, "utf8");
14226
14372
  const parsed = JSON.parse(raw);
14227
14373
  if (typeof parsed.version !== "string" || parsed.version.length === 0)
14228
14374
  return null;
@@ -14236,9 +14382,9 @@ function readOnnxInstalledMeta(installDir) {
14236
14382
  return null;
14237
14383
  }
14238
14384
  }
14239
- function sha256File(path) {
14385
+ function sha256File(path2) {
14240
14386
  const hash = createHash2("sha256");
14241
- hash.update(readFileSync3(path));
14387
+ hash.update(readFileSync3(path2));
14242
14388
  return hash.digest("hex");
14243
14389
  }
14244
14390
  function acquireLock(lockPath) {
@@ -14898,13 +15044,13 @@ function tokenizeStage(stage) {
14898
15044
  }
14899
15045
  // ../aft-bridge/dist/pool.js
14900
15046
  import { realpathSync as realpathSync2 } from "node:fs";
14901
- import { homedir as homedir6 } from "node:os";
15047
+ import { homedir as homedir7 } from "node:os";
14902
15048
  var DEFAULT_IDLE_TIMEOUT_MS = 30 * 60 * 1000;
14903
15049
  var DEFAULT_MAX_POOL_SIZE = 8;
14904
15050
  var CLEANUP_INTERVAL_MS = 60 * 1000;
14905
15051
  function canonicalHomeDir() {
14906
15052
  try {
14907
- const home = homedir6();
15053
+ const home = homedir7();
14908
15054
  if (!home)
14909
15055
  return null;
14910
15056
  try {
@@ -14942,6 +15088,7 @@ class BridgePool {
14942
15088
  this.projectConfigLoader = options.projectConfigLoader;
14943
15089
  this.bridgeOptions = {
14944
15090
  timeoutMs: options.timeoutMs,
15091
+ hangThreshold: options.hangThreshold,
14945
15092
  maxRestarts: options.maxRestarts,
14946
15093
  minVersion: options.minVersion,
14947
15094
  onVersionMismatch: options.onVersionMismatch,
@@ -15096,6 +15243,91 @@ function normalizeKey(projectRoot) {
15096
15243
  return stripped;
15097
15244
  }
15098
15245
  }
15246
+ // ../aft-bridge/dist/tool-format.js
15247
+ function asPlainObject(value) {
15248
+ if (!value || typeof value !== "object" || Array.isArray(value))
15249
+ return;
15250
+ return value;
15251
+ }
15252
+ function candidateLocation(candidate) {
15253
+ const file = typeof candidate.file === "string" && candidate.file.length > 0 ? candidate.file : undefined;
15254
+ if (!file)
15255
+ return;
15256
+ const line = typeof candidate.line === "number" && Number.isFinite(candidate.line) ? candidate.line : undefined;
15257
+ return line === undefined ? file : `${file}:${line}`;
15258
+ }
15259
+ function stringifyData(data) {
15260
+ if (data === undefined)
15261
+ return;
15262
+ try {
15263
+ return JSON.stringify(data, null, 2);
15264
+ } catch {
15265
+ return String(data);
15266
+ }
15267
+ }
15268
+ function formatBridgeErrorMessage(command, response, params = {}) {
15269
+ const code = typeof response.code === "string" && response.code.length > 0 ? response.code : undefined;
15270
+ const message = typeof response.message === "string" && response.message.length > 0 ? response.message : `${command} failed`;
15271
+ const data = asPlainObject(response.data);
15272
+ const rawCandidates = Array.isArray(response.candidates) ? response.candidates : Array.isArray(data?.candidates) ? data.candidates : undefined;
15273
+ const rawSymbol = typeof response.symbol === "string" && response.symbol.length > 0 ? response.symbol : typeof data?.symbol === "string" && data.symbol.length > 0 ? data.symbol : undefined;
15274
+ if (code === "ambiguous_target" || code === "target_symbol_not_in_file") {
15275
+ const candidates = (rawCandidates ?? []).map(asPlainObject).filter((candidate) => candidate !== undefined).map(candidateLocation).filter((candidate) => candidate !== undefined);
15276
+ if (candidates.length > 0) {
15277
+ const symbol = typeof params.toSymbol === "string" && params.toSymbol.length > 0 ? params.toSymbol : rawSymbol;
15278
+ const target = symbol ? `multiple symbols named "${symbol}"` : message.replace(/[.!?]+$/, "");
15279
+ const action = code === "ambiguous_target" ? "Pass toFile to disambiguate" : "Try one of these files for toFile";
15280
+ return `${command}: ${code} — ${target}. ${action}:
15281
+ ${candidates.map((candidate) => ` - ${candidate}`).join(`
15282
+ `)}`;
15283
+ }
15284
+ }
15285
+ if (!code)
15286
+ return message;
15287
+ const lines = [`${command}: ${code} — ${message}`];
15288
+ const extras = collectStructuredExtras(response);
15289
+ if (extras)
15290
+ lines.push(`data: ${extras}`);
15291
+ return lines.join(`
15292
+ `);
15293
+ }
15294
+ function collectStructuredExtras(response) {
15295
+ const reserved = new Set([
15296
+ "id",
15297
+ "success",
15298
+ "code",
15299
+ "message",
15300
+ "data",
15301
+ "status_bar",
15302
+ "bg_completions"
15303
+ ]);
15304
+ const extras = {};
15305
+ for (const [key, value] of Object.entries(response)) {
15306
+ if (reserved.has(key))
15307
+ continue;
15308
+ extras[key] = value;
15309
+ }
15310
+ if (Object.keys(extras).length === 0) {
15311
+ return stringifyData(response.data);
15312
+ }
15313
+ if (response.data !== undefined)
15314
+ extras.data = response.data;
15315
+ return stringifyData(extras);
15316
+ }
15317
+ function formatReadFooter(agentSpecifiedRange, data, options) {
15318
+ if (agentSpecifiedRange)
15319
+ return "";
15320
+ if (!data.truncated)
15321
+ return "";
15322
+ const startLine = data.start_line;
15323
+ const endLine = data.end_line;
15324
+ const totalLines = data.total_lines;
15325
+ if (startLine === undefined || endLine === undefined || totalLines === undefined) {
15326
+ return "";
15327
+ }
15328
+ return `
15329
+ (Showing lines ${startLine}-${endLine} of ${totalLines}. Use ${options.rangeHint} to read other sections.)`;
15330
+ }
15099
15331
  // ../aft-bridge/dist/zoom-format.js
15100
15332
  function formatZoomText(targetLabel, response) {
15101
15333
  const range = response.range;
@@ -15176,13 +15408,36 @@ function formatZoomMultiTargetResult(entries) {
15176
15408
 
15177
15409
  `) };
15178
15410
  }
15411
+ function isRustZoomBatchEnvelope(response) {
15412
+ if (!Array.isArray(response.symbols) || response.symbols.length === 0) {
15413
+ return false;
15414
+ }
15415
+ return response.symbols.every((entry) => {
15416
+ if (!entry || typeof entry !== "object")
15417
+ return false;
15418
+ const row = entry;
15419
+ return typeof row.name === "string" && row.response !== undefined && row.response !== null;
15420
+ });
15421
+ }
15422
+ function unwrapRustZoomBatchEnvelope(response) {
15423
+ if (!isRustZoomBatchEnvelope(response)) {
15424
+ return null;
15425
+ }
15426
+ const names = [];
15427
+ const responses = [];
15428
+ for (const entry of response.symbols) {
15429
+ names.push(entry.name);
15430
+ responses.push(entry.response);
15431
+ }
15432
+ return { names, responses };
15433
+ }
15179
15434
  // src/logger.ts
15180
15435
  import * as fs from "node:fs";
15181
- import * as os from "node:os";
15182
- import * as path from "node:path";
15436
+ import * as os2 from "node:os";
15437
+ import * as path2 from "node:path";
15183
15438
  var TAG = "[aft-pi]";
15184
15439
  var isTestEnv = process.env.BUN_TEST === "1" || false;
15185
- var logFile = path.join(os.tmpdir(), isTestEnv ? "aft-pi-test.log" : "aft-pi.log");
15440
+ var logFile = path2.join(os2.tmpdir(), isTestEnv ? "aft-pi-test.log" : "aft-pi.log");
15186
15441
  var useStderr = process.env.AFT_LOG_STDERR === "1";
15187
15442
  var buffer = [];
15188
15443
  var flushTimer = null;
@@ -15818,7 +16073,7 @@ import {
15818
16073
  // package.json
15819
16074
  var package_default = {
15820
16075
  name: "@cortexkit/aft-pi",
15821
- version: "0.39.0",
16076
+ version: "0.39.2",
15822
16077
  type: "module",
15823
16078
  description: "Pi coding agent extension for Agent File Tools (AFT) — tree-sitter and LSP-powered code analysis",
15824
16079
  main: "dist/index.js",
@@ -15841,7 +16096,7 @@ var package_default = {
15841
16096
  "test:unit": "bun test src/__tests__ --path-ignore-patterns 'src/__tests__/e2e/**'"
15842
16097
  },
15843
16098
  dependencies: {
15844
- "@cortexkit/aft-bridge": "0.39.0",
16099
+ "@cortexkit/aft-bridge": "0.39.2",
15845
16100
  "@xterm/headless": "^5.5.0",
15846
16101
  "comment-json": "^5.0.0",
15847
16102
  diff: "^8.0.4",
@@ -15849,12 +16104,12 @@ var package_default = {
15849
16104
  zod: "^4.1.8"
15850
16105
  },
15851
16106
  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"
16107
+ "@cortexkit/aft-darwin-arm64": "0.39.2",
16108
+ "@cortexkit/aft-darwin-x64": "0.39.2",
16109
+ "@cortexkit/aft-linux-arm64": "0.39.2",
16110
+ "@cortexkit/aft-linux-x64": "0.39.2",
16111
+ "@cortexkit/aft-win32-arm64": "0.39.2",
16112
+ "@cortexkit/aft-win32-x64": "0.39.2"
15858
16113
  },
15859
16114
  devDependencies: {
15860
16115
  "@earendil-works/pi-coding-agent": "*",
@@ -16087,101 +16342,6 @@ function formatStatusDialogMessage(status) {
16087
16342
  // src/tools/_shared.ts
16088
16343
  import { Type } from "typebox";
16089
16344
  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
16345
  function bridgeFor(ctx, cwd) {
16186
16346
  return ctx.pool.getBridge(cwd);
16187
16347
  }
@@ -16524,8 +16684,8 @@ function registerStatusCommand(pi, ctx) {
16524
16684
 
16525
16685
  // src/config.ts
16526
16686
  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";
16687
+ import { homedir as homedir8 } from "node:os";
16688
+ import { join as join10 } from "node:path";
16529
16689
  var import_comment_json = __toESM(require_src2(), 1);
16530
16690
 
16531
16691
  // ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
@@ -17293,10 +17453,10 @@ function mergeDefs(...defs) {
17293
17453
  function cloneDef(schema) {
17294
17454
  return mergeDefs(schema._zod.def);
17295
17455
  }
17296
- function getElementAtPath(obj, path2) {
17297
- if (!path2)
17456
+ function getElementAtPath(obj, path3) {
17457
+ if (!path3)
17298
17458
  return obj;
17299
- return path2.reduce((acc, key) => acc?.[key], obj);
17459
+ return path3.reduce((acc, key) => acc?.[key], obj);
17300
17460
  }
17301
17461
  function promiseAllObject(promisesObj) {
17302
17462
  const keys = Object.keys(promisesObj);
@@ -17677,11 +17837,11 @@ function aborted(x, startIndex = 0) {
17677
17837
  }
17678
17838
  return false;
17679
17839
  }
17680
- function prefixIssues(path2, issues) {
17840
+ function prefixIssues(path3, issues) {
17681
17841
  return issues.map((iss) => {
17682
17842
  var _a;
17683
17843
  (_a = iss).path ?? (_a.path = []);
17684
- iss.path.unshift(path2);
17844
+ iss.path.unshift(path3);
17685
17845
  return iss;
17686
17846
  });
17687
17847
  }
@@ -17864,7 +18024,7 @@ function formatError(error3, mapper = (issue2) => issue2.message) {
17864
18024
  }
17865
18025
  function treeifyError(error3, mapper = (issue2) => issue2.message) {
17866
18026
  const result = { errors: [] };
17867
- const processError = (error4, path2 = []) => {
18027
+ const processError = (error4, path3 = []) => {
17868
18028
  var _a, _b;
17869
18029
  for (const issue2 of error4.issues) {
17870
18030
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -17874,7 +18034,7 @@ function treeifyError(error3, mapper = (issue2) => issue2.message) {
17874
18034
  } else if (issue2.code === "invalid_element") {
17875
18035
  processError({ issues: issue2.issues }, issue2.path);
17876
18036
  } else {
17877
- const fullpath = [...path2, ...issue2.path];
18037
+ const fullpath = [...path3, ...issue2.path];
17878
18038
  if (fullpath.length === 0) {
17879
18039
  result.errors.push(mapper(issue2));
17880
18040
  continue;
@@ -17906,8 +18066,8 @@ function treeifyError(error3, mapper = (issue2) => issue2.message) {
17906
18066
  }
17907
18067
  function toDotPath(_path) {
17908
18068
  const segs = [];
17909
- const path2 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
17910
- for (const seg of path2) {
18069
+ const path3 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
18070
+ for (const seg of path3) {
17911
18071
  if (typeof seg === "number")
17912
18072
  segs.push(`[${seg}]`);
17913
18073
  else if (typeof seg === "symbol")
@@ -29654,13 +29814,13 @@ function resolveRef(ref, ctx) {
29654
29814
  if (!ref.startsWith("#")) {
29655
29815
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
29656
29816
  }
29657
- const path2 = ref.slice(1).split("/").filter(Boolean);
29658
- if (path2.length === 0) {
29817
+ const path3 = ref.slice(1).split("/").filter(Boolean);
29818
+ if (path3.length === 0) {
29659
29819
  return ctx.rootSchema;
29660
29820
  }
29661
29821
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
29662
- if (path2[0] === defsKey) {
29663
- const key = path2[1];
29822
+ if (path3[0] === defsKey) {
29823
+ const key = path3[1];
29664
29824
  if (!key || !ctx.defs[key]) {
29665
29825
  throw new Error(`Reference not found: ${ref}`);
29666
29826
  }
@@ -30186,6 +30346,10 @@ var BashFeaturesSchema = exports_external.object({
30186
30346
  foreground_wait_window_ms: exports_external.number().int().positive().optional()
30187
30347
  });
30188
30348
  var BashConfigSchema = exports_external.union([exports_external.boolean(), BashFeaturesSchema]);
30349
+ var BridgeConfigSchema = exports_external.object({
30350
+ request_timeout_ms: exports_external.number().int().min(1000, { message: "bridge.request_timeout_ms must be at least 1000" }).optional(),
30351
+ hang_threshold: exports_external.number().int().min(1, { message: "bridge.hang_threshold must be at least 1" }).optional()
30352
+ });
30189
30353
  var InspectConfigSchema = exports_external.object({
30190
30354
  enabled: exports_external.boolean().optional(),
30191
30355
  tier2_idle_minutes: exports_external.number().min(0).optional(),
@@ -30223,7 +30387,8 @@ var AftConfigSchema = exports_external.object({
30223
30387
  lsp: LspConfigSchema.optional(),
30224
30388
  url_fetch_allow_private: exports_external.boolean().optional(),
30225
30389
  semantic: SemanticConfigSchema.optional(),
30226
- max_callgraph_files: exports_external.number().int().positive().optional()
30390
+ max_callgraph_files: exports_external.number().int().positive().optional(),
30391
+ bridge: BridgeConfigSchema.optional()
30227
30392
  }).strict();
30228
30393
  function normalizeLspExtension(extension) {
30229
30394
  return extension.trim().replace(/^\.+/, "");
@@ -30317,9 +30482,9 @@ function extractCommentsForPreservation(content) {
30317
30482
  }
30318
30483
  return comments;
30319
30484
  }
30320
- function ensureRecordAtPath(root, path2) {
30485
+ function ensureRecordAtPath(root, path3) {
30321
30486
  let current = root;
30322
- for (const segment of path2) {
30487
+ for (const segment of path3) {
30323
30488
  const existing = current[segment];
30324
30489
  if (!existing || typeof existing !== "object" || Array.isArray(existing)) {
30325
30490
  current[segment] = {};
@@ -30328,9 +30493,9 @@ function ensureRecordAtPath(root, path2) {
30328
30493
  }
30329
30494
  return current;
30330
30495
  }
30331
- function hasPath(root, path2) {
30496
+ function hasPath(root, path3) {
30332
30497
  let current = root;
30333
- for (const segment of path2) {
30498
+ for (const segment of path3) {
30334
30499
  if (!current || typeof current !== "object" || Array.isArray(current))
30335
30500
  return false;
30336
30501
  const record2 = current;
@@ -30340,9 +30505,9 @@ function hasPath(root, path2) {
30340
30505
  }
30341
30506
  return true;
30342
30507
  }
30343
- function setPath(root, path2, value) {
30344
- const parent = ensureRecordAtPath(root, path2.slice(0, -1));
30345
- parent[path2[path2.length - 1]] = value;
30508
+ function setPath(root, path3, value) {
30509
+ const parent = ensureRecordAtPath(root, path3.slice(0, -1));
30510
+ parent[path3[path3.length - 1]] = value;
30346
30511
  }
30347
30512
  function migrateRawConfig(rawConfig, configPath, logger) {
30348
30513
  const oldKeys = [];
@@ -30631,6 +30796,8 @@ function getStrippedTopLevelKeys(override) {
30631
30796
  stripped.push("url_fetch_allow_private");
30632
30797
  if (override.max_callgraph_files !== undefined)
30633
30798
  stripped.push("max_callgraph_files");
30799
+ if (override.bridge !== undefined)
30800
+ stripped.push("bridge");
30634
30801
  return stripped;
30635
30802
  }
30636
30803
  function mergeConfigs(base, override) {
@@ -30642,6 +30809,7 @@ function mergeConfigs(base, override) {
30642
30809
  const experimental = mergeExperimentalConfig(base.experimental, override.experimental);
30643
30810
  const bash = mergeBashConfig(base.bash, override.bash);
30644
30811
  const inspect = mergeInspectConfig(base.inspect, override.inspect);
30812
+ const bridge = base.bridge;
30645
30813
  const safeOverride = pickProjectSafeFields(override);
30646
30814
  delete safeOverride.bash;
30647
30815
  delete safeOverride.inspect;
@@ -30655,19 +30823,28 @@ function mergeConfigs(base, override) {
30655
30823
  ...inspect !== undefined ? { inspect } : {},
30656
30824
  experimental,
30657
30825
  semantic,
30826
+ ...bridge !== undefined ? { bridge } : {},
30658
30827
  ...disabledTools.length > 0 ? { disabled_tools: [...new Set(disabledTools)] } : {}
30659
30828
  };
30660
30829
  }
30830
+ var DEFAULT_BRIDGE_REQUEST_TIMEOUT_MS = 30000;
30831
+ var DEFAULT_BRIDGE_HANG_THRESHOLD = 2;
30832
+ function resolveBridgePoolTransportOptions(config2) {
30833
+ return {
30834
+ timeoutMs: config2.bridge?.request_timeout_ms ?? DEFAULT_BRIDGE_REQUEST_TIMEOUT_MS,
30835
+ hangThreshold: config2.bridge?.hang_threshold ?? DEFAULT_BRIDGE_HANG_THRESHOLD
30836
+ };
30837
+ }
30661
30838
  function getGlobalPiDir() {
30662
- return join9(homedir7(), ".pi", "agent");
30839
+ return join10(homedir8(), ".pi", "agent");
30663
30840
  }
30664
30841
  function loadAftConfig(projectDirectory) {
30665
- const userBasePath = join9(getGlobalPiDir(), "aft");
30842
+ const userBasePath = join10(getGlobalPiDir(), "aft");
30666
30843
  migrateAftConfigFile(`${userBasePath}.jsonc`);
30667
30844
  migrateAftConfigFile(`${userBasePath}.json`);
30668
30845
  const userDetected = detectConfigFile(userBasePath);
30669
30846
  const userConfigPath = userDetected.format !== "none" ? userDetected.path : `${userBasePath}.json`;
30670
- const projectBasePath = join9(projectDirectory, ".pi", "aft");
30847
+ const projectBasePath = join10(projectDirectory, ".pi", "aft");
30671
30848
  migrateAftConfigFile(`${projectBasePath}.jsonc`);
30672
30849
  migrateAftConfigFile(`${projectBasePath}.json`);
30673
30850
  const projectDetected = detectConfigFile(projectBasePath);
@@ -30704,7 +30881,7 @@ import {
30704
30881
  statSync as statSync5,
30705
30882
  writeFileSync as writeFileSync5
30706
30883
  } from "node:fs";
30707
- import { join as join12 } from "node:path";
30884
+ import { join as join13 } from "node:path";
30708
30885
 
30709
30886
  // src/lsp-cache.ts
30710
30887
  import {
@@ -30716,36 +30893,36 @@ import {
30716
30893
  unlinkSync as unlinkSync5,
30717
30894
  writeFileSync as writeFileSync4
30718
30895
  } from "node:fs";
30719
- import { homedir as homedir8 } from "node:os";
30720
- import { join as join10 } from "node:path";
30896
+ import { homedir as homedir9 } from "node:os";
30897
+ import { join as join11 } from "node:path";
30721
30898
  function aftCacheBase() {
30722
30899
  const override = process.env.AFT_CACHE_DIR;
30723
30900
  if (override && override.length > 0)
30724
30901
  return override;
30725
30902
  if (process.platform === "win32") {
30726
30903
  const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
30727
- const base2 = localAppData || join10(homedir8(), "AppData", "Local");
30728
- return join10(base2, "aft");
30904
+ const base2 = localAppData || join11(homedir9(), "AppData", "Local");
30905
+ return join11(base2, "aft");
30729
30906
  }
30730
- const base = process.env.XDG_CACHE_HOME || join10(homedir8(), ".cache");
30731
- return join10(base, "aft");
30907
+ const base = process.env.XDG_CACHE_HOME || join11(homedir9(), ".cache");
30908
+ return join11(base, "aft");
30732
30909
  }
30733
30910
  function lspCacheRoot() {
30734
- return join10(aftCacheBase(), "lsp-packages");
30911
+ return join11(aftCacheBase(), "lsp-packages");
30735
30912
  }
30736
30913
  function lspPackageDir(npmPackage) {
30737
- return join10(lspCacheRoot(), encodeURIComponent(npmPackage));
30914
+ return join11(lspCacheRoot(), encodeURIComponent(npmPackage));
30738
30915
  }
30739
30916
  function lspBinaryPath(npmPackage, binary) {
30740
- return join10(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
30917
+ return join11(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
30741
30918
  }
30742
30919
  function lspBinDir(npmPackage) {
30743
- return join10(lspPackageDir(npmPackage), "node_modules", ".bin");
30920
+ return join11(lspPackageDir(npmPackage), "node_modules", ".bin");
30744
30921
  }
30745
30922
  function isInstalled(npmPackage, binary) {
30746
30923
  for (const candidate of lspBinaryCandidates(binary)) {
30747
30924
  try {
30748
- if (statSync4(join10(lspBinDir(npmPackage), candidate)).isFile())
30925
+ if (statSync4(join11(lspBinDir(npmPackage), candidate)).isFile())
30749
30926
  return true;
30750
30927
  } catch {}
30751
30928
  }
@@ -30765,17 +30942,17 @@ function writeInstalledMetaIn(installDir, version2, sha256) {
30765
30942
  installedAt: new Date().toISOString(),
30766
30943
  ...sha256 ? { sha256 } : {}
30767
30944
  };
30768
- writeFileSync4(join10(installDir, INSTALLED_META_FILE), JSON.stringify(meta3), "utf8");
30945
+ writeFileSync4(join11(installDir, INSTALLED_META_FILE), JSON.stringify(meta3), "utf8");
30769
30946
  } catch (err) {
30770
30947
  log2(`[lsp-cache] failed to write installed-meta in ${installDir}: ${err}`);
30771
30948
  }
30772
30949
  }
30773
30950
  function readInstalledMetaIn(installDir) {
30774
- const path2 = join10(installDir, INSTALLED_META_FILE);
30951
+ const path3 = join11(installDir, INSTALLED_META_FILE);
30775
30952
  try {
30776
- if (!statSync4(path2).isFile())
30953
+ if (!statSync4(path3).isFile())
30777
30954
  return null;
30778
- const raw = readFileSync5(path2, "utf8");
30955
+ const raw = readFileSync5(path3, "utf8");
30779
30956
  const parsed = JSON.parse(raw);
30780
30957
  if (typeof parsed.version !== "string" || parsed.version.length === 0)
30781
30958
  return null;
@@ -30795,7 +30972,7 @@ function readInstalledMeta(packageKey) {
30795
30972
  return readInstalledMetaIn(lspPackageDir(packageKey));
30796
30973
  }
30797
30974
  function lockPath(npmPackage) {
30798
- return join10(lspPackageDir(npmPackage), ".aft-installing");
30975
+ return join11(lspPackageDir(npmPackage), ".aft-installing");
30799
30976
  }
30800
30977
  var STALE_LOCK_MS2 = 30 * 60 * 1000;
30801
30978
  function acquireInstallLock(lockKey) {
@@ -30902,7 +31079,7 @@ async function withInstallLock(lockKey, task) {
30902
31079
  }
30903
31080
  var VERSION_CHECK_FILE = ".aft-version-check";
30904
31081
  function readVersionCheck(npmPackage) {
30905
- const file2 = join10(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
31082
+ const file2 = join11(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
30906
31083
  try {
30907
31084
  const raw = readFileSync5(file2, "utf8");
30908
31085
  const parsed = JSON.parse(raw);
@@ -30919,7 +31096,7 @@ function readVersionCheck(npmPackage) {
30919
31096
  }
30920
31097
  function writeVersionCheck(npmPackage, latest) {
30921
31098
  mkdirSync6(lspPackageDir(npmPackage), { recursive: true });
30922
- const file2 = join10(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
31099
+ const file2 = join11(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
30923
31100
  const record2 = {
30924
31101
  last_checked: new Date().toISOString(),
30925
31102
  latest_eligible: latest
@@ -31082,7 +31259,7 @@ var NPM_LSP_TABLE = [
31082
31259
 
31083
31260
  // src/lsp-project-relevance.ts
31084
31261
  import { existsSync as existsSync7, readdirSync as readdirSync3, readFileSync as readFileSync6 } from "node:fs";
31085
- import { join as join11 } from "node:path";
31262
+ import { join as join12 } from "node:path";
31086
31263
  var MAX_WALK_DIRS = 200;
31087
31264
  var MAX_WALK_DEPTH = 4;
31088
31265
  var NOISE_DIRS = new Set([
@@ -31099,7 +31276,7 @@ function hasRootMarker(projectRoot, rootMarkers) {
31099
31276
  if (!rootMarkers)
31100
31277
  return false;
31101
31278
  for (const marker of rootMarkers) {
31102
- if (existsSync7(join11(projectRoot, marker)))
31279
+ if (existsSync7(join12(projectRoot, marker)))
31103
31280
  return true;
31104
31281
  }
31105
31282
  return false;
@@ -31123,7 +31300,7 @@ function hasPackageJsonDep(projectRoot, depNames) {
31123
31300
  }
31124
31301
  function readPackageJson(projectRoot) {
31125
31302
  try {
31126
- const raw = readFileSync6(join11(projectRoot, "package.json"), "utf8");
31303
+ const raw = readFileSync6(join12(projectRoot, "package.json"), "utf8");
31127
31304
  const parsed = JSON.parse(raw);
31128
31305
  if (typeof parsed !== "object" || parsed === null)
31129
31306
  return null;
@@ -31153,7 +31330,7 @@ function relevantExtensionsInProject(projectRoot, extToServer) {
31153
31330
  for (const entry of entries) {
31154
31331
  if (entry.isDirectory()) {
31155
31332
  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 });
31333
+ queue.push({ dir: join12(current.dir, entry.name), depth: current.depth + 1 });
31157
31334
  }
31158
31335
  continue;
31159
31336
  }
@@ -31280,7 +31457,7 @@ async function resolveTargetVersion(spec, config2, fetchImpl = fetch) {
31280
31457
  }
31281
31458
  function ensureInstallAnchor(cwd) {
31282
31459
  try {
31283
- const stub = join12(cwd, "package.json");
31460
+ const stub = join13(cwd, "package.json");
31284
31461
  if (!existsSync8(stub)) {
31285
31462
  writeFileSync5(stub, `${JSON.stringify({ name: "aft-lsp-cache", version: "0.0.0", private: true })}
31286
31463
  `);
@@ -31290,18 +31467,18 @@ function ensureInstallAnchor(cwd) {
31290
31467
  }
31291
31468
  }
31292
31469
  function runInstall(spec, version2, cwd, signal) {
31293
- return new Promise((resolve2) => {
31470
+ return new Promise((resolve3) => {
31294
31471
  const target = `${spec.npm}@${version2}`;
31295
31472
  log2(`[lsp] installing ${target} to ${cwd}`);
31296
31473
  if (signal?.aborted) {
31297
31474
  warn2(`[lsp] install ${target} aborted before spawn`);
31298
- resolve2(false);
31475
+ resolve3(false);
31299
31476
  return;
31300
31477
  }
31301
31478
  const npm = resolveNpm();
31302
31479
  if (!npm) {
31303
31480
  warn2(`[lsp] npm not found on PATH or known locations; cannot install ${target}`);
31304
- resolve2(false);
31481
+ resolve3(false);
31305
31482
  return;
31306
31483
  }
31307
31484
  ensureInstallAnchor(cwd);
@@ -31324,7 +31501,7 @@ function runInstall(spec, version2, cwd, signal) {
31324
31501
  return;
31325
31502
  settled = true;
31326
31503
  cleanup();
31327
- resolve2(ok);
31504
+ resolve3(ok);
31328
31505
  };
31329
31506
  const onAbort = () => {
31330
31507
  warn2(`[lsp] install ${target} aborted during shutdown`);
@@ -31425,7 +31602,7 @@ function cachedPackageDir(npmPackage) {
31425
31602
  return lspBinDir(npmPackage).replace(/[\\/]node_modules[\\/]\.bin[\\/]?$/, "");
31426
31603
  }
31427
31604
  function hashInstalledBinary(spec) {
31428
- return new Promise((resolve2, reject) => {
31605
+ return new Promise((resolve3, reject) => {
31429
31606
  const candidates = process.platform === "win32" ? [
31430
31607
  lspBinaryPath(spec.npm, spec.binary),
31431
31608
  lspBinaryPath(spec.npm, `${spec.binary}.cmd`),
@@ -31449,7 +31626,7 @@ function hashInstalledBinary(spec) {
31449
31626
  const stream = createReadStream(pathToHash);
31450
31627
  stream.on("error", reject);
31451
31628
  stream.on("data", (chunk) => hash2.update(chunk));
31452
- stream.on("end", () => resolve2(hash2.digest("hex")));
31629
+ stream.on("end", () => resolve3(hash2.digest("hex")));
31453
31630
  });
31454
31631
  }
31455
31632
  function installedBinaryPath(spec) {
@@ -31467,15 +31644,15 @@ function installedBinaryPath(spec) {
31467
31644
  }
31468
31645
  return null;
31469
31646
  }
31470
- function sha256OfFileSync(path2) {
31471
- return createHash3("sha256").update(readFileSync7(path2)).digest("hex");
31647
+ function sha256OfFileSync(path3) {
31648
+ return createHash3("sha256").update(readFileSync7(path3)).digest("hex");
31472
31649
  }
31473
31650
  function quarantineCachedNpmInstall(spec, reason) {
31474
31651
  const packageDir = lspPackageDir(spec.npm);
31475
- const dest = join12(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
31652
+ const dest = join13(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
31476
31653
  warn2(`[lsp] tofu_mismatch ${spec.npm}: ${reason}; quarantining ${packageDir} -> ${dest}`);
31477
31654
  try {
31478
- mkdirSync7(join12(dest, ".."), { recursive: true });
31655
+ mkdirSync7(join13(dest, ".."), { recursive: true });
31479
31656
  rmSync3(dest, { recursive: true, force: true });
31480
31657
  renameSync5(packageDir, dest);
31481
31658
  } catch (err) {
@@ -31570,7 +31747,7 @@ import {
31570
31747
  unlinkSync as unlinkSync6,
31571
31748
  writeFileSync as writeFileSync6
31572
31749
  } from "node:fs";
31573
- import { dirname as dirname5, join as join13, relative as relative2, resolve as resolve2 } from "node:path";
31750
+ import { dirname as dirname5, join as join14, relative as relative3, resolve as resolve3 } from "node:path";
31574
31751
  import { Readable as Readable3 } from "node:stream";
31575
31752
  import { pipeline as pipeline3 } from "node:stream/promises";
31576
31753
 
@@ -31660,26 +31837,26 @@ function detectHostPlatform() {
31660
31837
 
31661
31838
  // src/lsp-github-install.ts
31662
31839
  function ghCacheRoot() {
31663
- return join13(aftCacheBase(), "lsp-binaries");
31840
+ return join14(aftCacheBase(), "lsp-binaries");
31664
31841
  }
31665
31842
  function ghPackageDir(spec) {
31666
- return join13(ghCacheRoot(), spec.id);
31843
+ return join14(ghCacheRoot(), spec.id);
31667
31844
  }
31668
31845
  function ghBinDir(spec) {
31669
- return join13(ghPackageDir(spec), "bin");
31846
+ return join14(ghPackageDir(spec), "bin");
31670
31847
  }
31671
31848
  function ghExtractDir(spec) {
31672
- return join13(ghPackageDir(spec), "extracted");
31849
+ return join14(ghPackageDir(spec), "extracted");
31673
31850
  }
31674
31851
  var INSTALLED_META_FILE2 = ".aft-installed";
31675
31852
  function ghBinaryPath(spec, platform) {
31676
31853
  const ext = platform === "win32" ? ".exe" : "";
31677
- return join13(ghBinDir(spec), `${spec.binary}${ext}`);
31854
+ return join14(ghBinDir(spec), `${spec.binary}${ext}`);
31678
31855
  }
31679
31856
  function isGithubInstalled(spec, platform) {
31680
31857
  for (const candidate of ghBinaryCandidates(spec, platform)) {
31681
31858
  try {
31682
- if (statSync6(join13(ghBinDir(spec), candidate)).isFile())
31859
+ if (statSync6(join14(ghBinDir(spec), candidate)).isFile())
31683
31860
  return true;
31684
31861
  } catch {}
31685
31862
  }
@@ -31692,10 +31869,10 @@ function ghBinaryCandidates(spec, platform) {
31692
31869
  }
31693
31870
  function readGithubInstalledMetaIn(installDir) {
31694
31871
  try {
31695
- const path2 = join13(installDir, INSTALLED_META_FILE2);
31696
- if (!statSync6(path2).isFile())
31872
+ const path3 = join14(installDir, INSTALLED_META_FILE2);
31873
+ if (!statSync6(path3).isFile())
31697
31874
  return null;
31698
- const parsed = JSON.parse(readFileSync8(path2, "utf8"));
31875
+ const parsed = JSON.parse(readFileSync8(path3, "utf8"));
31699
31876
  if (typeof parsed.version !== "string" || parsed.version.length === 0)
31700
31877
  return null;
31701
31878
  return {
@@ -31719,24 +31896,24 @@ function writeGithubInstalledMetaIn(installDir, version2, binarySha256, archiveS
31719
31896
  binarySha256,
31720
31897
  ...archiveSha256 ? { archiveSha256 } : {}
31721
31898
  };
31722
- writeFileSync6(join13(installDir, INSTALLED_META_FILE2), JSON.stringify(meta3), "utf8");
31899
+ writeFileSync6(join14(installDir, INSTALLED_META_FILE2), JSON.stringify(meta3), "utf8");
31723
31900
  } catch (err) {
31724
31901
  warn2(`[lsp] failed to write github installed metadata in ${installDir}: ${err}`);
31725
31902
  }
31726
31903
  }
31727
31904
  var MAX_DOWNLOAD_BYTES3 = 256 * 1024 * 1024;
31728
31905
  var MAX_EXTRACT_BYTES2 = 1024 * 1024 * 1024;
31729
- function sha256OfFile(path2) {
31730
- return new Promise((resolve3, reject) => {
31906
+ function sha256OfFile(path3) {
31907
+ return new Promise((resolve4, reject) => {
31731
31908
  const hash2 = createHash4("sha256");
31732
- const stream = createReadStream2(path2);
31909
+ const stream = createReadStream2(path3);
31733
31910
  stream.on("error", reject);
31734
31911
  stream.on("data", (chunk) => hash2.update(chunk));
31735
- stream.on("end", () => resolve3(hash2.digest("hex")));
31912
+ stream.on("end", () => resolve4(hash2.digest("hex")));
31736
31913
  });
31737
31914
  }
31738
- function sha256OfFileSync2(path2) {
31739
- return createHash4("sha256").update(readFileSync8(path2)).digest("hex");
31915
+ function sha256OfFileSync2(path3) {
31916
+ return createHash4("sha256").update(readFileSync8(path3)).digest("hex");
31740
31917
  }
31741
31918
  async function fetchReleaseByTag(githubRepo, tag, fetchImpl, signal) {
31742
31919
  const candidates = [];
@@ -31968,7 +32145,7 @@ function validateExtraction(stagingRoot) {
31968
32145
  throw new Error(`failed to read staging dir ${dir}: ${err}`);
31969
32146
  }
31970
32147
  for (const entry of entries) {
31971
- const full = join13(dir, entry);
32148
+ const full = join14(dir, entry);
31972
32149
  let lst;
31973
32150
  try {
31974
32151
  lst = lstatSync2(full);
@@ -31980,7 +32157,7 @@ function validateExtraction(stagingRoot) {
31980
32157
  try {
31981
32158
  target = readlinkSync2(full);
31982
32159
  } catch {}
31983
- throw new Error(`archive contains symlink ${relative2(realStagingRoot, full)} → ${target}; rejecting (zip-slip defense)`);
32160
+ throw new Error(`archive contains symlink ${relative3(realStagingRoot, full)} → ${target}; rejecting (zip-slip defense)`);
31984
32161
  }
31985
32162
  let realFull;
31986
32163
  try {
@@ -31988,8 +32165,8 @@ function validateExtraction(stagingRoot) {
31988
32165
  } catch (err) {
31989
32166
  throw new Error(`failed to realpath ${full}: ${err}`);
31990
32167
  }
31991
- const rel = relative2(realStagingRoot, realFull);
31992
- if (rel.startsWith("..") || resolve2(realStagingRoot, rel) !== realFull) {
32168
+ const rel = relative3(realStagingRoot, realFull);
32169
+ if (rel.startsWith("..") || resolve3(realStagingRoot, rel) !== realFull) {
31993
32170
  throw new Error(`archive entry escapes staging root: ${full} → ${realFull} (zip-slip defense)`);
31994
32171
  }
31995
32172
  if (lst.isDirectory()) {
@@ -32056,7 +32233,7 @@ function extractArchiveSafely(archivePath, destDir, archiveType) {
32056
32233
  }
32057
32234
  function quarantineCachedGithubInstall(spec, reason) {
32058
32235
  const packageDir = ghPackageDir(spec);
32059
- const dest = join13(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
32236
+ const dest = join14(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
32060
32237
  warn2(`[lsp] tofu_mismatch ${spec.id}: ${reason}; quarantining ${packageDir} -> ${dest}`);
32061
32238
  try {
32062
32239
  mkdirSync8(dirname5(dest), { recursive: true });
@@ -32069,7 +32246,7 @@ function quarantineCachedGithubInstall(spec, reason) {
32069
32246
  function validateCachedGithubInstall(spec, platform) {
32070
32247
  const packageDir = ghPackageDir(spec);
32071
32248
  const meta3 = readGithubInstalledMetaIn(packageDir);
32072
- const binaryPath = ghBinaryCandidates(spec, platform).map((candidate) => join13(ghBinDir(spec), candidate)).find((candidate) => {
32249
+ const binaryPath = ghBinaryCandidates(spec, platform).map((candidate) => join14(ghBinDir(spec), candidate)).find((candidate) => {
32073
32250
  try {
32074
32251
  return statSync6(candidate).isFile();
32075
32252
  } catch {
@@ -32147,7 +32324,7 @@ async function downloadAndInstall(spec, tag, assets, platform, arch, fetchImpl,
32147
32324
  }
32148
32325
  const pkgDir = ghPackageDir(spec);
32149
32326
  const extractDir = ghExtractDir(spec);
32150
- const archivePath = join13(pkgDir, expected.name);
32327
+ const archivePath = join14(pkgDir, expected.name);
32151
32328
  log2(`[lsp] downloading ${spec.id} ${tag} → ${matchingAsset.url}`);
32152
32329
  try {
32153
32330
  await downloadFile(matchingAsset.url, archivePath, fetchImpl, matchingAsset.size, signal);
@@ -32187,7 +32364,7 @@ async function downloadAndInstall(spec, tag, assets, platform, arch, fetchImpl,
32187
32364
  unlinkSync6(archivePath);
32188
32365
  } catch {}
32189
32366
  }
32190
- const innerBinaryPath = join13(extractDir, spec.binaryPathInArchive(platform, arch, version2));
32367
+ const innerBinaryPath = join14(extractDir, spec.binaryPathInArchive(platform, arch, version2));
32191
32368
  if (!existsSync9(innerBinaryPath)) {
32192
32369
  error2(`[lsp] ${spec.id}: extracted binary not found at ${innerBinaryPath}`);
32193
32370
  return null;
@@ -32585,7 +32762,7 @@ function renderScreen(state, rows = state.rows, cols = state.cols) {
32585
32762
  `);
32586
32763
  }
32587
32764
  function writeTerminal(terminal, data) {
32588
- return new Promise((resolve3) => terminal.write(data, resolve3));
32765
+ return new Promise((resolve4) => terminal.write(data, resolve4));
32589
32766
  }
32590
32767
 
32591
32768
  // src/shutdown-hooks.ts
@@ -32642,8 +32819,8 @@ function installProcessHandlers() {
32642
32819
  }
32643
32820
  signalShutdownStarted = true;
32644
32821
  process.exitCode = SIGNAL_EXIT_CODES[sig];
32645
- const timeout = new Promise((resolve3) => {
32646
- setTimeout(resolve3, SIGNAL_CLEANUP_TIMEOUT_MS);
32822
+ const timeout = new Promise((resolve4) => {
32823
+ setTimeout(resolve4, SIGNAL_CLEANUP_TIMEOUT_MS);
32647
32824
  });
32648
32825
  Promise.race([runCleanups(sig), timeout]).finally(() => {
32649
32826
  process.exit(SIGNAL_EXIT_CODES[sig]);
@@ -32685,8 +32862,8 @@ import { Type as Type3 } from "typebox";
32685
32862
 
32686
32863
  // src/tools/hoisted.ts
32687
32864
  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";
32865
+ import { homedir as homedir10 } from "node:os";
32866
+ import { isAbsolute as isAbsolute4, relative as relative4, resolve as resolve4, sep } from "node:path";
32690
32867
  import {
32691
32868
  renderDiff
32692
32869
  } from "@earendil-works/pi-coding-agent";
@@ -32800,18 +32977,72 @@ function diagnosticsOnEditDefault(ctx) {
32800
32977
  return ctx.config.lsp?.diagnostics_on_edit ?? false;
32801
32978
  }
32802
32979
  function containsPath(parent, child) {
32803
- const rel = relative3(parent, child);
32804
- return rel === "" || !rel.startsWith("..") && !isAbsolute3(rel);
32980
+ const rel = relative4(parent, child);
32981
+ return rel === "" || !rel.startsWith("..") && !isAbsolute4(rel);
32982
+ }
32983
+ function expandTilde2(path3) {
32984
+ if (!path3 || !path3.startsWith("~"))
32985
+ return path3;
32986
+ if (path3 === "~")
32987
+ return homedir10();
32988
+ if (path3.startsWith(`~${sep}`) || path3.startsWith("~/")) {
32989
+ return resolve4(homedir10(), path3.slice(2));
32990
+ }
32991
+ return path3;
32992
+ }
32993
+ function absoluteSearchPath(cwd, target) {
32994
+ const expanded = expandTilde2(target);
32995
+ return isAbsolute4(expanded) ? expanded : resolve4(cwd, expanded);
32996
+ }
32997
+ async function searchPathExists(cwd, target) {
32998
+ try {
32999
+ await stat(absoluteSearchPath(cwd, target));
33000
+ return true;
33001
+ } catch {
33002
+ return false;
33003
+ }
33004
+ }
33005
+ async function splitSearchPathArg(cwd, raw) {
33006
+ if (await searchPathExists(cwd, raw) || !/\s/.test(raw)) {
33007
+ return { paths: [raw], missing: [] };
33008
+ }
33009
+ const fragments = raw.trim().split(/\s+/).filter(Boolean);
33010
+ if (fragments.length < 2) {
33011
+ return { paths: [raw], missing: [] };
33012
+ }
33013
+ const existing = [];
33014
+ const missing = [];
33015
+ for (const fragment of fragments) {
33016
+ if (await searchPathExists(cwd, fragment)) {
33017
+ existing.push(fragment);
33018
+ } else {
33019
+ missing.push(fragment);
33020
+ }
33021
+ }
33022
+ if (existing.length === 0) {
33023
+ return { paths: [raw], missing: [] };
33024
+ }
33025
+ return { paths: existing, missing };
32805
33026
  }
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));
33027
+ async function bridgeSearchPathArg(cwd, split) {
33028
+ if (split.paths.length === 1 && split.missing.length === 0) {
33029
+ return await resolvePathArg(cwd, split.paths[0]);
32813
33030
  }
32814
- return path2;
33031
+ return split.paths.map((target) => absoluteSearchPath(cwd, target)).join(" ");
33032
+ }
33033
+ function formatSkippedSearchPaths(missing) {
33034
+ if (missing.length === 0)
33035
+ return;
33036
+ const noun = missing.length === 1 ? "path" : "paths";
33037
+ return `Skipped ${missing.length} ${noun} not found: ${missing.join(", ")}`;
33038
+ }
33039
+ function appendSkippedSearchPaths(text, missing) {
33040
+ const note = formatSkippedSearchPaths(missing);
33041
+ if (!note)
33042
+ return text;
33043
+ return text.length > 0 ? `${text}
33044
+
33045
+ ${note}` : note;
32815
33046
  }
32816
33047
  function externalDirectoryPromptTimeoutMs() {
32817
33048
  const raw = process.env.AFT_PI_EXTERNAL_PROMPT_TIMEOUT_MS;
@@ -32823,8 +33054,8 @@ function externalDirectoryPromptTimeoutMs() {
32823
33054
  async function assertExternalDirectoryPermission(extCtx, target, action = "modify", options = {}) {
32824
33055
  if (!target)
32825
33056
  return;
32826
- const expanded = expandTilde(target);
32827
- const absoluteTarget = isAbsolute3(expanded) ? expanded : resolve3(extCtx.cwd, expanded);
33057
+ const expanded = expandTilde2(target);
33058
+ const absoluteTarget = isAbsolute4(expanded) ? expanded : resolve4(extCtx.cwd, expanded);
32828
33059
  if (containsPath(extCtx.cwd, absoluteTarget))
32829
33060
  return;
32830
33061
  if (options.restrictToProjectRoot === false)
@@ -32835,8 +33066,8 @@ async function assertExternalDirectoryPermission(extCtx, target, action = "modif
32835
33066
  }
32836
33067
  const timeoutMs = externalDirectoryPromptTimeoutMs();
32837
33068
  let timer;
32838
- const timeoutPromise = new Promise((resolve4) => {
32839
- timer = setTimeout(() => resolve4("timeout"), timeoutMs);
33069
+ const timeoutPromise = new Promise((resolve5) => {
33070
+ timer = setTimeout(() => resolve5("timeout"), timeoutMs);
32840
33071
  });
32841
33072
  try {
32842
33073
  const result = await Promise.race([
@@ -32900,8 +33131,12 @@ function registerHoistedTools(pi, ctx, surface) {
32900
33131
  const bridge = bridgeFor(ctx, extCtx.cwd);
32901
33132
  const offset = coerceOptionalInt(params.offset, "offset", 1, Number.MAX_SAFE_INTEGER);
32902
33133
  const limit = coerceOptionalInt(params.limit, "limit", 1, Number.MAX_SAFE_INTEGER);
33134
+ const filePath = await resolvePathArg(extCtx.cwd, params.path);
33135
+ await assertExternalDirectoryPermission(extCtx, filePath, "read", {
33136
+ restrictToProjectRoot: surface.restrictToProjectRoot
33137
+ });
32903
33138
  const req = {
32904
- file: await resolvePathArg(extCtx.cwd, params.path)
33139
+ file: filePath
32905
33140
  };
32906
33141
  if (offset !== undefined) {
32907
33142
  req.start_line = offset;
@@ -32918,7 +33153,7 @@ function registerHoistedTools(pi, ctx, surface) {
32918
33153
  }
32919
33154
  let text = response.content ?? "";
32920
33155
  const agentSpecifiedRange = offset !== undefined || limit !== undefined;
32921
- const footer = formatReadFooter(agentSpecifiedRange, response);
33156
+ const footer = formatReadFooter2(agentSpecifiedRange, response);
32922
33157
  if (footer)
32923
33158
  text += footer;
32924
33159
  return textResult(text);
@@ -33018,19 +33253,26 @@ function registerHoistedTools(pi, ctx, surface) {
33018
33253
  async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
33019
33254
  const bridge = bridgeFor(ctx, extCtx.cwd);
33020
33255
  const req = { pattern: params.pattern };
33256
+ let pathSplit;
33021
33257
  if (params.path) {
33022
- await assertExternalDirectoryPermission(extCtx, params.path, "search", {
33023
- restrictToProjectRoot: surface.restrictToProjectRoot
33024
- });
33025
- req.path = await resolvePathArg(extCtx.cwd, params.path);
33258
+ pathSplit = await splitSearchPathArg(extCtx.cwd, params.path);
33259
+ for (const target of pathSplit.paths) {
33260
+ await assertExternalDirectoryPermission(extCtx, absoluteSearchPath(extCtx.cwd, target), "search", {
33261
+ restrictToProjectRoot: surface.restrictToProjectRoot
33262
+ });
33263
+ }
33264
+ req.path = await bridgeSearchPathArg(extCtx.cwd, pathSplit);
33026
33265
  }
33027
33266
  if (params.include)
33028
33267
  req.include = splitIncludeGlobs(params.include);
33029
33268
  if (params.caseSensitive !== undefined)
33030
33269
  req.case_sensitive = params.caseSensitive;
33031
33270
  const response = await callBridge(bridge, "grep", req, extCtx);
33032
- const text = response.text ?? "";
33033
- return textResult(text);
33271
+ if (pathSplit && pathSplit.missing.length > 0) {
33272
+ response.complete = false;
33273
+ }
33274
+ const text = appendSkippedSearchPaths(response.text ?? "", pathSplit?.missing ?? []);
33275
+ return textResult(text, response);
33034
33276
  }
33035
33277
  });
33036
33278
  }
@@ -33174,15 +33416,15 @@ ${summary}${suffix}`);
33174
33416
  container.addChild(new Text(renderDiff(diff), 1, 0));
33175
33417
  return container;
33176
33418
  }
33177
- function shortenPath(path2) {
33178
- const home = homedir9();
33179
- if (path2.startsWith(home))
33180
- return `~${path2.slice(home.length)}`;
33181
- return path2;
33419
+ function shortenPath(path3) {
33420
+ const home = homedir10();
33421
+ if (path3.startsWith(home))
33422
+ return `~${path3.slice(home.length)}`;
33423
+ return path3;
33182
33424
  }
33183
- async function resolvePathArg(cwd, path2) {
33184
- const expanded = expandTilde(path2);
33185
- const abs = isAbsolute3(expanded) ? expanded : resolve3(cwd, expanded);
33425
+ async function resolvePathArg(cwd, path3) {
33426
+ const expanded = expandTilde2(path3);
33427
+ const abs = absoluteSearchPath(cwd, path3);
33186
33428
  try {
33187
33429
  await stat(abs);
33188
33430
  return abs;
@@ -33220,23 +33462,12 @@ function splitIncludeGlobs(include) {
33220
33462
  out.push(tail2);
33221
33463
  return out;
33222
33464
  }
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.)`;
33465
+ function formatReadFooter2(agentSpecifiedRange, data) {
33466
+ return formatReadFooter(agentSpecifiedRange, data, { rangeHint: "offset/limit" });
33236
33467
  }
33237
33468
 
33238
33469
  // src/tools/render-helpers.ts
33239
- import { homedir as homedir10 } from "node:os";
33470
+ import { homedir as homedir11 } from "node:os";
33240
33471
  import { renderDiff as renderDiff2 } from "@earendil-works/pi-coding-agent";
33241
33472
  import { Container as Container2, Spacer as Spacer2, Text as Text2 } from "@earendil-works/pi-tui";
33242
33473
  function reuseText2(last) {
@@ -33245,11 +33476,11 @@ function reuseText2(last) {
33245
33476
  function reuseContainer2(last) {
33246
33477
  return last instanceof Container2 ? last : new Container2;
33247
33478
  }
33248
- function shortenPath2(path2) {
33249
- const home = homedir10();
33250
- if (path2.startsWith(home))
33251
- return `~${path2.slice(home.length)}`;
33252
- return path2;
33479
+ function shortenPath2(path3) {
33480
+ const home = homedir11();
33481
+ if (path3.startsWith(home))
33482
+ return `~${path3.slice(home.length)}`;
33483
+ return path3;
33253
33484
  }
33254
33485
  function renderToolCall(toolName, summary, theme, context) {
33255
33486
  const text = reuseText2(context.lastComponent);
@@ -33257,10 +33488,10 @@ function renderToolCall(toolName, summary, theme, context) {
33257
33488
  text.setText(`${theme.fg("toolTitle", theme.bold(toolName))}${suffix}`);
33258
33489
  return text;
33259
33490
  }
33260
- function accentPath(theme, path2) {
33261
- if (!path2)
33491
+ function accentPath(theme, path3) {
33492
+ if (!path3)
33262
33493
  return theme.fg("toolOutput", "...");
33263
- return theme.fg("accent", shortenPath2(path2));
33494
+ return theme.fg("accent", shortenPath2(path3));
33264
33495
  }
33265
33496
  function collectTextContent(result) {
33266
33497
  return result.content.filter((part) => part.type === "text").map((part) => part.text ?? "").join(`
@@ -33407,7 +33638,7 @@ function renderUnifiedDiff(unifiedDiff) {
33407
33638
  }
33408
33639
 
33409
33640
  // src/tools/ast.ts
33410
- var AstLang = StringEnum(["typescript", "tsx", "javascript", "python", "rust", "go", "pascal"], {
33641
+ var AstLang = StringEnum(["typescript", "tsx", "javascript", "python", "rust", "go", "pascal", "r"], {
33411
33642
  description: "Target language"
33412
33643
  });
33413
33644
  var SearchParams = Type3.Object({
@@ -33448,17 +33679,17 @@ ${warningStrings.map((w) => ` ${w}`).join(`
33448
33679
  async function resolveAstPaths(extCtx, paths) {
33449
33680
  if (isEmptyParam(paths) || !Array.isArray(paths))
33450
33681
  return;
33451
- return Promise.all(paths.filter((path2) => typeof path2 === "string").map((path2) => resolvePathArg(extCtx.cwd, path2)));
33682
+ return Promise.all(paths.filter((path3) => typeof path3 === "string").map((path3) => resolvePathArg(extCtx.cwd, path3)));
33452
33683
  }
33453
33684
  async function assertAstPathsPermission(extCtx, paths, action, restrictToProjectRoot) {
33454
33685
  if (paths === undefined || paths.length === 0)
33455
33686
  return;
33456
33687
  const checked = new Set;
33457
- for (const path2 of paths) {
33458
- if (checked.has(path2))
33688
+ for (const path3 of paths) {
33689
+ if (checked.has(path3))
33459
33690
  continue;
33460
- checked.add(path2);
33461
- await assertExternalDirectoryPermission(extCtx, path2, action, { restrictToProjectRoot });
33691
+ checked.add(path3);
33692
+ await assertExternalDirectoryPermission(extCtx, path3, action, { restrictToProjectRoot });
33462
33693
  }
33463
33694
  }
33464
33695
  function buildAstSearchSections(payload, theme) {
@@ -33641,6 +33872,7 @@ var FOREGROUND_POLL_INTERVAL_MS = 100;
33641
33872
  var BASH_WAIT_POLL_INTERVAL_MS = 100;
33642
33873
  var DEFAULT_BASH_STATUS_WAIT_TIMEOUT_MS = 30000;
33643
33874
  var MAX_BASH_STATUS_WAIT_TIMEOUT_MS = 300000;
33875
+ var REGEX_WAIT_SCAN_WINDOW_BYTES = 64 * 1024;
33644
33876
  function resolveForegroundWaitMs(configured) {
33645
33877
  const override = process.env.AFT_TEST_FOREGROUND_WAIT_MS;
33646
33878
  if (override !== undefined) {
@@ -33825,7 +34057,7 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
33825
34057
  throw new Error(status.message ?? "bash_status failed");
33826
34058
  }
33827
34059
  if (isTerminalStatus(status.status)) {
33828
- return bashResult(appendPipeStripNote(withBashHints(formatForegroundResult(status), bridgeCommand, aftSearchRegistered), pipeStrip.note), {
34060
+ return bashResult(appendPipeStripNote(withBashHints(formatForegroundResult(status), bridgeCommand, aftSearchRegistered, extCtx.cwd), pipeStrip.note), {
33829
34061
  exit_code: status.exit_code,
33830
34062
  duration_ms: status.duration_ms,
33831
34063
  truncated: status.output_truncated,
@@ -33852,7 +34084,7 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
33852
34084
  task_id: taskId
33853
34085
  };
33854
34086
  const output = response.output ?? "";
33855
- return bashResult(appendPipeStripNote(withBashHints(output, bridgeCommand, aftSearchRegistered), pipeStrip.note), details);
34087
+ return bashResult(appendPipeStripNote(withBashHints(output, bridgeCommand, aftSearchRegistered, extCtx.cwd), pipeStrip.note), details);
33856
34088
  },
33857
34089
  renderCall(args, theme, context) {
33858
34090
  return renderBashCall(args?.command, args?.description, theme, context);
@@ -33866,11 +34098,6 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
33866
34098
  pi.registerTool(createBashWriteTool(ctx));
33867
34099
  pi.registerTool(createBashKillTool(ctx));
33868
34100
  }
33869
- function appendPipeStripNote(output, note) {
33870
- return note ? `${output}
33871
-
33872
- ${note}` : output;
33873
- }
33874
34101
  function formatBackgroundLaunch(taskId, isPty) {
33875
34102
  if (isPty) {
33876
34103
  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 +34108,8 @@ function formatPromotionMessage(taskId, timeout, waitWindowMs) {
33881
34108
  const waited = timeout !== undefined ? Math.min(timeout, waitWindowMs) : waitWindowMs;
33882
34109
  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
34110
  }
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));
34111
+ function withBashHints(output, command, aftSearchRegistered, projectRoot) {
34112
+ return maybeAppendGrepSearchHint(maybeAppendConflictsHint(output), command, aftSearchRegistered, projectRoot);
33913
34113
  }
33914
34114
  function createBashStatusTool(ctx) {
33915
34115
  return {
@@ -34076,6 +34276,9 @@ async function waitForBashStatus(ctx, bridge, extCtx, taskId, outputMode, waitFo
34076
34276
  keepBridgeOnTimeout: true,
34077
34277
  transportTimeoutMs: BASH_TRANSPORT_TIMEOUT_MS
34078
34278
  };
34279
+ if (waitFor?.kind === "regex") {
34280
+ await validateWaitRegex(bridge, extCtx, waitFor);
34281
+ }
34079
34282
  const sessionId = resolveSessionId(extCtx);
34080
34283
  clearSyncWatchAbort(sessionId);
34081
34284
  if (waitForExit)
@@ -34092,7 +34295,12 @@ async function waitForBashStatus(ctx, bridge, extCtx, taskId, outputMode, waitFo
34092
34295
  if (scanText.length === 0)
34093
34296
  scanBaseOffset = scan.baseOffset;
34094
34297
  scanText += scan.text;
34095
- const match = findWaitMatch(scanText, waitFor);
34298
+ if (waitFor.kind === "regex") {
34299
+ const trimmed = trimWaitScanBuffer(scanText, scanBaseOffset, waitFor);
34300
+ scanText = trimmed.text;
34301
+ scanBaseOffset = trimmed.baseOffset;
34302
+ }
34303
+ const match = await findWaitMatch(bridge, extCtx, scanText, waitFor);
34096
34304
  if (match) {
34097
34305
  if (waitForExit && terminal) {
34098
34306
  sawTerminal = true;
@@ -34103,9 +34311,14 @@ async function waitForBashStatus(ctx, bridge, extCtx, taskId, outputMode, waitFo
34103
34311
  reason: "matched",
34104
34312
  elapsed_ms: Date.now() - startedAt,
34105
34313
  match: match.text,
34106
- match_offset: scanBaseOffset + Buffer.byteLength(scanText.slice(0, match.index), "utf8")
34314
+ match_offset: scanBaseOffset + match.byteOffset
34107
34315
  });
34108
34316
  }
34317
+ if (waitFor.kind === "substring") {
34318
+ const trimmed = trimWaitScanBuffer(scanText, scanBaseOffset, waitFor);
34319
+ scanText = trimmed.text;
34320
+ scanBaseOffset = trimmed.baseOffset;
34321
+ }
34109
34322
  }
34110
34323
  }
34111
34324
  if (terminal) {
@@ -34191,20 +34404,69 @@ function parseWaitPattern(value) {
34191
34404
  if (typeof value === "string")
34192
34405
  return { kind: "substring", value };
34193
34406
  if (isRegexWaitObject(value))
34194
- return { kind: "regex", value: new RegExp(value.regex), source: value.regex };
34407
+ return { kind: "regex", source: value.regex };
34195
34408
  return;
34196
34409
  }
34197
34410
  function isRegexWaitObject(value) {
34198
34411
  return typeof value === "object" && value !== null && "regex" in value && typeof value.regex === "string";
34199
34412
  }
34200
- function findWaitMatch(text, pattern) {
34413
+ async function validateWaitRegex(bridge, extCtx, pattern) {
34414
+ await matchRegexWithBridge(bridge, extCtx, pattern.source, "");
34415
+ }
34416
+ async function findWaitMatch(bridge, extCtx, text, pattern) {
34201
34417
  if (pattern.kind === "substring") {
34202
34418
  const index = text.indexOf(pattern.value);
34203
- return index >= 0 ? { text: pattern.value, index } : undefined;
34419
+ return index >= 0 ? { text: pattern.value, byteOffset: Buffer.byteLength(text.slice(0, index), "utf8") } : undefined;
34204
34420
  }
34205
- pattern.value.lastIndex = 0;
34206
- const match = pattern.value.exec(text);
34207
- return match ? { text: match[0], index: match.index } : undefined;
34421
+ return await matchRegexWithBridge(bridge, extCtx, pattern.source, text);
34422
+ }
34423
+ async function matchRegexWithBridge(bridge, extCtx, pattern, text) {
34424
+ try {
34425
+ const result = await callBashBridge(bridge, "bash_regex_match", { pattern, text }, extCtx);
34426
+ if (result.matched !== true)
34427
+ return;
34428
+ return {
34429
+ text: typeof result.match_text === "string" ? result.match_text : "",
34430
+ byteOffset: coerceMatchOffset(result.match_offset)
34431
+ };
34432
+ } catch (err) {
34433
+ if (err instanceof BridgeError && err.code === "invalid_regex") {
34434
+ throw new Error(`invalid_request: invalid_regex: ${err.message}`);
34435
+ }
34436
+ throw err;
34437
+ }
34438
+ }
34439
+ function coerceMatchOffset(value) {
34440
+ const offset = typeof value === "number" ? value : Number(value ?? 0);
34441
+ return Number.isFinite(offset) && offset >= 0 ? offset : 0;
34442
+ }
34443
+ function trimWaitScanBuffer(text, baseOffset, pattern) {
34444
+ const keepFrom = pattern.kind === "substring" ? substringKeepStart(text, pattern.value) : regexKeepStart(text, REGEX_WAIT_SCAN_WINDOW_BYTES);
34445
+ if (keepFrom <= 0)
34446
+ return { text, baseOffset };
34447
+ return {
34448
+ text: text.slice(keepFrom),
34449
+ baseOffset: baseOffset + Buffer.byteLength(text.slice(0, keepFrom), "utf8")
34450
+ };
34451
+ }
34452
+ function substringKeepStart(text, pattern) {
34453
+ const keepChars = Math.max(0, pattern.length - 1);
34454
+ return text.length > keepChars ? text.length - keepChars : 0;
34455
+ }
34456
+ function regexKeepStart(text, maxBytes) {
34457
+ if (Buffer.byteLength(text, "utf8") <= maxBytes)
34458
+ return 0;
34459
+ let low = 0;
34460
+ let high = text.length;
34461
+ while (low < high) {
34462
+ const mid = Math.floor((low + high) / 2);
34463
+ if (Buffer.byteLength(text.slice(mid), "utf8") > maxBytes) {
34464
+ low = mid + 1;
34465
+ } else {
34466
+ high = mid;
34467
+ }
34468
+ }
34469
+ return low;
34208
34470
  }
34209
34471
  function withWaited(data, waited) {
34210
34472
  return { ...data, waited };
@@ -34280,9 +34542,6 @@ function ptyCacheKey(extCtx, taskId) {
34280
34542
  function watchPtyCacheKey(extCtx, taskId) {
34281
34543
  return `${ptyCacheKey(extCtx, taskId)}::watch`;
34282
34544
  }
34283
- function isTerminalStatus(status) {
34284
- return status === "completed" || status === "failed" || status === "killed" || status === "timed_out";
34285
- }
34286
34545
  function renderBashCall(command, description, theme, context) {
34287
34546
  const text = reuseText3(context.lastComponent);
34288
34547
  const display = description ?? (command ? shortenCommand(command) : "...");
@@ -34386,12 +34645,12 @@ function registerConflictsTool(pi, ctx) {
34386
34645
  async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
34387
34646
  const bridge = bridgeFor(ctx, extCtx.cwd);
34388
34647
  const reqParams = {};
34389
- const path2 = params?.path;
34390
- if (typeof path2 === "string" && path2.trim() !== "") {
34391
- await assertExternalDirectoryPermission(extCtx, path2, "inspect", {
34648
+ const path3 = params?.path;
34649
+ if (typeof path3 === "string" && path3.trim() !== "") {
34650
+ await assertExternalDirectoryPermission(extCtx, path3, "inspect", {
34392
34651
  restrictToProjectRoot: ctx.config.restrict_to_project_root ?? false
34393
34652
  });
34394
- reqParams.path = await resolvePathArg(extCtx.cwd, path2);
34653
+ reqParams.path = await resolvePathArg(extCtx.cwd, path3);
34395
34654
  }
34396
34655
  const response = await callBridge(bridge, "git_conflicts", reqParams, extCtx);
34397
34656
  return textResult(response.text ?? JSON.stringify(response, null, 2));
@@ -34790,8 +35049,8 @@ function tier2SummaryPart(summary, key, label) {
34790
35049
  return `${label} ${status ?? "unavailable"}`;
34791
35050
  }
34792
35051
  function shortDupOccurrence(entry) {
34793
- const [path2] = entry.split(":");
34794
- return path2?.split("/").pop() ?? entry;
35052
+ const [path3] = entry.split(":");
35053
+ return path3?.split("/").pop() ?? entry;
34795
35054
  }
34796
35055
  function tier2TopPreview(summary, theme) {
34797
35056
  const lines = [];
@@ -35000,9 +35259,9 @@ function depthWarning(response, theme, depthField = "depth_limited", truncatedFi
35000
35259
  const detail = truncated > 0 ? `, ${truncated} truncated` : "";
35001
35260
  return theme.fg("warning", `(depth limited${detail})`);
35002
35261
  }
35003
- function renderTracePath(path2, index, lines) {
35262
+ function renderTracePath(path3, index, lines) {
35004
35263
  lines.push(`Path ${index + 1}`);
35005
- asRecords(path2.hops).forEach((hop, hopIndex) => {
35264
+ asRecords(path3.hops).forEach((hop, hopIndex) => {
35006
35265
  const symbol2 = asString(hop.symbol) ?? "(unknown)";
35007
35266
  const file2 = shortenPath2(asString(hop.file) ?? "(unknown file)");
35008
35267
  const line = asNumber(hop.line);
@@ -35040,15 +35299,15 @@ function buildNavigateSections(args, payload, theme) {
35040
35299
  return sections2;
35041
35300
  }
35042
35301
  if (args.op === "trace_to_symbol") {
35043
- const path2 = asRecords(response.path);
35302
+ const path3 = asRecords(response.path);
35044
35303
  const complete = asBoolean(response.complete);
35045
35304
  const reason = asString(response.reason);
35046
- if (path2.length === 0) {
35305
+ if (path3.length === 0) {
35047
35306
  const prefix = complete === false ? theme.fg("warning", "No complete path") : theme.fg("muted", "No path");
35048
35307
  return [`${prefix}${reason ? ` (${reason})` : ""}`];
35049
35308
  }
35050
- const lines = [theme.fg("success", `${path2.length} hop${path2.length === 1 ? "" : "s"}`)];
35051
- path2.forEach((hop, index) => {
35309
+ const lines = [theme.fg("success", `${path3.length} hop${path3.length === 1 ? "" : "s"}`)];
35310
+ path3.forEach((hop, index) => {
35052
35311
  const symbol2 = asString(hop.symbol) ?? "(unknown)";
35053
35312
  const file2 = shortenPath2(asString(hop.file) ?? "(unknown file)");
35054
35313
  const line = asNumber(hop.line);
@@ -35064,9 +35323,9 @@ function buildNavigateSections(args, payload, theme) {
35064
35323
  ];
35065
35324
  if (paths.length === 0)
35066
35325
  sections2.push(theme.fg("muted", "No entry paths found."));
35067
- paths.forEach((path2, index) => {
35326
+ paths.forEach((path3, index) => {
35068
35327
  const lines = [];
35069
- renderTracePath(path2, index, lines);
35328
+ renderTracePath(path3, index, lines);
35070
35329
  sections2.push(lines.join(`
35071
35330
  `));
35072
35331
  });
@@ -35524,6 +35783,11 @@ Pass a single \`target\`:
35524
35783
  }));
35525
35784
  if (symbolsArray.length === 1) {
35526
35785
  const response2 = results[0] ?? { success: false, message: "missing zoom response" };
35786
+ const rustBatch = unwrapRustZoomBatchEnvelope(response2);
35787
+ if (rustBatch) {
35788
+ const batch2 = formatZoomBatchResult(targetLabel, rustBatch.names, rustBatch.responses);
35789
+ return textResult(batch2.text, batch2);
35790
+ }
35527
35791
  if (response2.success === false) {
35528
35792
  throw new Error(response2.message || "zoom failed");
35529
35793
  }
@@ -35759,7 +36023,7 @@ function registerRefactorTool(pi, ctx) {
35759
36023
  import { StringEnum as StringEnum5 } from "@earendil-works/pi-ai";
35760
36024
  import { Type as Type12 } from "typebox";
35761
36025
  function responsePaths(response) {
35762
- return Array.isArray(response.paths) ? response.paths.filter((path2) => typeof path2 === "string" && path2.length > 0) : [];
36026
+ return Array.isArray(response.paths) ? response.paths.filter((path3) => typeof path3 === "string" && path3.length > 0) : [];
35763
36027
  }
35764
36028
  var SafetyParams = Type12.Object({
35765
36029
  op: StringEnum5(["undo", "history", "checkpoint", "restore", "list"], {
@@ -36225,18 +36489,18 @@ function createVersionMismatchHandler(getPool, ensureCompatibleBinary = ensureBi
36225
36489
  const upgradePromise = (async () => {
36226
36490
  warn2(`WARNING: aft binary v${binaryVersion} is older than plugin v${minVersion}. ` + "Some features may not work. Attempting to download a compatible binary...");
36227
36491
  try {
36228
- const path2 = await ensureCompatibleBinary(`v${minVersion}`);
36229
- if (!path2) {
36492
+ const path3 = await ensureCompatibleBinary(`v${minVersion}`);
36493
+ if (!path3) {
36230
36494
  warn2(`Could not find or download v${minVersion}. Continuing with v${binaryVersion}.`);
36231
36495
  return null;
36232
36496
  }
36233
36497
  const pool = getPool();
36234
36498
  if (!pool) {
36235
- warn2(`Found/downloaded compatible binary at ${path2}, but bridge pool is not ready.`);
36499
+ warn2(`Found/downloaded compatible binary at ${path3}, but bridge pool is not ready.`);
36236
36500
  return null;
36237
36501
  }
36238
- log2(`Found/downloaded compatible binary at ${path2}. Replacing running bridges...`);
36239
- const replaced = await pool.replaceBinary(path2);
36502
+ log2(`Found/downloaded compatible binary at ${path3}. Replacing running bridges...`);
36503
+ const replaced = await pool.replaceBinary(path3);
36240
36504
  log2("Binary replaced successfully. New bridges will use the updated binary.");
36241
36505
  return replaced;
36242
36506
  } catch (err) {
@@ -36487,6 +36751,7 @@ ${lines}
36487
36751
  }
36488
36752
  let pool;
36489
36753
  const poolOptions = {
36754
+ ...resolveBridgePoolTransportOptions(config2),
36490
36755
  errorPrefix: "[aft-pi]",
36491
36756
  minVersion: PLUGIN_VERSION,
36492
36757
  onVersionMismatch: createVersionMismatchHandler(() => pool),
@@ -36561,7 +36826,7 @@ ${lines}
36561
36826
  if (onnxRuntimePromise) {
36562
36827
  await Promise.race([
36563
36828
  onnxRuntimePromise,
36564
- new Promise((resolve4) => setTimeout(() => resolve4(null), 60000))
36829
+ new Promise((resolve5) => setTimeout(() => resolve5(null), 60000))
36565
36830
  ]);
36566
36831
  }
36567
36832
  const bridge = pool.getBridge(cwd);