@cortexkit/aft-opencode 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
@@ -7652,10 +7652,10 @@ var require_stringify = __commonJS((exports, module) => {
7652
7652
  replacer = null;
7653
7653
  indent = EMPTY;
7654
7654
  };
7655
- 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)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two, gap)), gap) : EMPTY;
7655
+ 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)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two, gap)), gap) : EMPTY;
7656
7656
  var join_content = (inside, value, gap) => {
7657
7657
  const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
7658
- return join9(comment, inside, gap);
7658
+ return join10(comment, inside, gap);
7659
7659
  };
7660
7660
  var stringify_string = (holder, key, value) => {
7661
7661
  const raw = get_raw_string_literal(holder, key);
@@ -7677,13 +7677,13 @@ var require_stringify = __commonJS((exports, module) => {
7677
7677
  if (i !== 0) {
7678
7678
  inside += COMMA;
7679
7679
  }
7680
- const before = join9(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
7680
+ const before = join10(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
7681
7681
  inside += before || LF + deeper_gap;
7682
7682
  inside += stringify(i, value, deeper_gap) || STR_NULL;
7683
7683
  inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
7684
7684
  after_comma = process_comments(value, AFTER(i), deeper_gap);
7685
7685
  }
7686
- inside += join9(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
7686
+ inside += join10(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
7687
7687
  return BRACKET_OPEN + join_content(inside, value, gap) + BRACKET_CLOSE;
7688
7688
  };
7689
7689
  var object_stringify = (value, gap) => {
@@ -7704,13 +7704,13 @@ var require_stringify = __commonJS((exports, module) => {
7704
7704
  inside += COMMA;
7705
7705
  }
7706
7706
  first = false;
7707
- const before = join9(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
7707
+ const before = join10(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
7708
7708
  inside += before || LF + deeper_gap;
7709
7709
  inside += quote(key) + process_comments(value, AFTER_PROP(key), deeper_gap) + COLON + process_comments(value, AFTER_COLON(key), deeper_gap) + SPACE + sv + process_comments(value, AFTER_VALUE(key), deeper_gap);
7710
7710
  after_comma = process_comments(value, AFTER(key), deeper_gap);
7711
7711
  };
7712
7712
  keys.forEach(iteratee);
7713
- inside += join9(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
7713
+ inside += join10(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
7714
7714
  return CURLY_BRACKET_OPEN + join_content(inside, value, gap) + CURLY_BRACKET_CLOSE;
7715
7715
  };
7716
7716
  function stringify(key, holder, gap) {
@@ -11593,7 +11593,45 @@ function error(message, meta) {
11593
11593
  console.error(`[aft-bridge] ERROR: ${message}`);
11594
11594
  }
11595
11595
  }
11596
+ // ../aft-bridge/dist/bash-format.js
11597
+ function appendPipeStripNote(output, note) {
11598
+ return note ? `${output}
11599
+
11600
+ ${note}` : output;
11601
+ }
11602
+ function formatSeconds(ms) {
11603
+ return `${Number((ms / 1000).toFixed(1))}s`;
11604
+ }
11605
+ function formatForegroundResult(data) {
11606
+ const output = data.output_preview ?? "";
11607
+ const outputPath = data.output_path;
11608
+ const truncated = data.output_truncated === true;
11609
+ const status = data.status;
11610
+ const exit = data.exit_code;
11611
+ let rendered = output;
11612
+ if (truncated && outputPath) {
11613
+ rendered += `
11614
+ [output truncated; full output at ${outputPath}]`;
11615
+ }
11616
+ if (status === "timed_out") {
11617
+ rendered += `
11618
+ [command timed out]`;
11619
+ }
11620
+ if (typeof exit === "number" && exit !== 0) {
11621
+ rendered += `
11622
+ [exit code: ${exit}]`;
11623
+ }
11624
+ return rendered;
11625
+ }
11626
+ function isTerminalStatus(status) {
11627
+ return status === "completed" || status === "failed" || status === "killed" || status === "timed_out";
11628
+ }
11629
+ function sleep(ms) {
11630
+ return new Promise((resolve) => setTimeout(resolve, ms));
11631
+ }
11596
11632
  // ../aft-bridge/dist/bash-hints.js
11633
+ import * as os from "node:os";
11634
+ import * as path from "node:path";
11597
11635
  var CONFLICT_HINT = `
11598
11636
 
11599
11637
  [Hint] Use aft_conflicts to see all conflict regions across files in a single call.`;
@@ -11623,18 +11661,87 @@ function commandInvokesCodeSearch(command) {
11623
11661
  }
11624
11662
  return false;
11625
11663
  }
11626
- function maybeAppendGrepSearchHint(output, command, aftSearchRegistered) {
11664
+ function maybeAppendGrepSearchHint(output, command, aftSearchRegistered, projectRoot) {
11627
11665
  if (output === "")
11628
11666
  return output;
11629
11667
  if (!commandInvokesCodeSearch(command))
11630
11668
  return output;
11631
11669
  if (output.includes(GREP_SEARCH_HINT_PREFIX))
11632
11670
  return output;
11671
+ if (shouldSuppressGrepSearchHint(command, projectRoot))
11672
+ return output;
11633
11673
  const hint = aftSearchRegistered ? GREP_SEARCH_AFT_SEARCH_HINT : GREP_SEARCH_GREP_HINT;
11634
11674
  return `${output}
11635
11675
 
11636
11676
  ${hint}`;
11637
11677
  }
11678
+ function shouldSuppressGrepSearchHint(command, projectRoot) {
11679
+ const root = projectRoot?.trim();
11680
+ if (!root)
11681
+ return false;
11682
+ const statements = splitTopLevelStatements(command);
11683
+ if (statements === null)
11684
+ return false;
11685
+ let sawCodeSearchStatement = false;
11686
+ for (const statement of statements) {
11687
+ const firstStage = firstPipelineStage(statement);
11688
+ if (firstStage === null)
11689
+ continue;
11690
+ const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0));
11691
+ if (firstToken === null)
11692
+ continue;
11693
+ if (firstToken.token !== "grep" && firstToken.token !== "rg")
11694
+ continue;
11695
+ sawCodeSearchStatement = true;
11696
+ const operands = collectPathOperands(firstStage, firstToken.end);
11697
+ if (operands.length === 0)
11698
+ return false;
11699
+ for (const operand of operands) {
11700
+ if (isPathInsideProject(root, operand))
11701
+ return false;
11702
+ }
11703
+ }
11704
+ return sawCodeSearchStatement;
11705
+ }
11706
+ function collectPathOperands(firstStage, startAfterCommand) {
11707
+ const operands = [];
11708
+ let index = skipSpaces(firstStage, startAfterCommand);
11709
+ while (index < firstStage.length) {
11710
+ const tokenResult = readShellToken(firstStage, index);
11711
+ if (tokenResult === null)
11712
+ break;
11713
+ const { token, end } = tokenResult;
11714
+ if (end <= index)
11715
+ break;
11716
+ index = skipSpaces(firstStage, end);
11717
+ if (token.startsWith("-"))
11718
+ continue;
11719
+ if (looksLikePathOperand(token))
11720
+ operands.push(token);
11721
+ }
11722
+ return operands;
11723
+ }
11724
+ function looksLikePathOperand(token) {
11725
+ return token.includes("/") || token.startsWith("~") || token.startsWith("./") || token.startsWith("../");
11726
+ }
11727
+ function expandTilde(target) {
11728
+ if (!target.startsWith("~"))
11729
+ return target;
11730
+ if (target === "~" || target.startsWith("~/")) {
11731
+ return path.join(os.homedir(), target.slice(1));
11732
+ }
11733
+ return target;
11734
+ }
11735
+ function resolvePathOperand(projectRoot, operand) {
11736
+ const expanded = expandTilde(operand);
11737
+ return path.isAbsolute(expanded) ? path.resolve(expanded) : path.resolve(projectRoot, expanded);
11738
+ }
11739
+ function isPathInsideProject(projectRoot, operand) {
11740
+ const root = path.resolve(projectRoot);
11741
+ const resolved = resolvePathOperand(root, operand);
11742
+ const rel = path.relative(root, resolved);
11743
+ return rel === "" || !rel.startsWith("..") && !path.isAbsolute(rel);
11744
+ }
11638
11745
  function splitTopLevelStatements(command) {
11639
11746
  const statements = [];
11640
11747
  let start = 0;
@@ -11814,8 +11921,8 @@ function resolveBashKillTimeout(modelTimeout, foregroundWaitMs) {
11814
11921
  }
11815
11922
  // ../aft-bridge/dist/bridge.js
11816
11923
  import { spawn } from "node:child_process";
11817
- import { homedir } from "node:os";
11818
- import { join } from "node:path";
11924
+ import { homedir as homedir2 } from "node:os";
11925
+ import { join as join2 } from "node:path";
11819
11926
  import { StringDecoder } from "node:string_decoder";
11820
11927
 
11821
11928
  // ../aft-bridge/dist/command-timeouts.js
@@ -11832,6 +11939,11 @@ var LONG_RUNNING_COMMAND_TIMEOUT_MS = {
11832
11939
  function timeoutForCommand(command) {
11833
11940
  return LONG_RUNNING_COMMAND_TIMEOUT_MS[command];
11834
11941
  }
11942
+ var PASSIVE_COMMANDS = new Set(["status"]);
11943
+ var PASSIVE_COMMAND_TIMEOUT_MS = 5000;
11944
+ function isPassiveCommand(command) {
11945
+ return PASSIVE_COMMANDS.has(command);
11946
+ }
11835
11947
 
11836
11948
  // ../aft-bridge/dist/status-bar.js
11837
11949
  var STATUS_BAR_HEARTBEAT_CALLS = 15;
@@ -11909,6 +12021,11 @@ function bashTaskIdFrom(response) {
11909
12021
  function tagStderrLine(line) {
11910
12022
  return /^\[aft(-\w+)?\] /.test(line) ? line : `[aft] ${line}`;
11911
12023
  }
12024
+ var BENIGN_CPUINFO_PROC_CPUINFO_PARSE_FAILURE = "failed to parse processor information from /proc/cpuinfo";
12025
+ function shouldSurfaceStderrLine(line) {
12026
+ const normalized = line.trim();
12027
+ return !(normalized === `Error in cpuinfo: ${BENIGN_CPUINFO_PROC_CPUINFO_PARSE_FAILURE}` || normalized === BENIGN_CPUINFO_PROC_CPUINFO_PARSE_FAILURE);
12028
+ }
11912
12029
  function compareSemver(a, b) {
11913
12030
  const [aMain, aPre] = a.split("-", 2);
11914
12031
  const [bMain, bPre] = b.split("-", 2);
@@ -12000,6 +12117,7 @@ class BinaryBridge {
12000
12117
  _restartCount = 0;
12001
12118
  _shuttingDown = false;
12002
12119
  timeoutMs;
12120
+ hangThreshold;
12003
12121
  maxRestarts;
12004
12122
  configured = false;
12005
12123
  _configurePromise = null;
@@ -12024,6 +12142,7 @@ class BinaryBridge {
12024
12142
  this.binaryPath = binaryPath;
12025
12143
  this.cwd = cwd;
12026
12144
  this.timeoutMs = options?.timeoutMs ?? DEFAULT_BRIDGE_TIMEOUT_MS;
12145
+ this.hangThreshold = options?.hangThreshold ?? BRIDGE_HANG_TIMEOUT_THRESHOLD;
12027
12146
  this.maxRestarts = options?.maxRestarts ?? 3;
12028
12147
  this.configOverrides = clampSemanticTimeout(configOverrides ?? {}, this.timeoutMs);
12029
12148
  this.minVersion = options?.minVersion;
@@ -12141,7 +12260,9 @@ class BinaryBridge {
12141
12260
  if (requestSessionId && options?.configureWarningClient !== undefined) {
12142
12261
  this.configureWarningClients.set(requestSessionId, options.configureWarningClient);
12143
12262
  }
12144
- const effectiveTimeoutMs = options?.transportTimeoutMs ?? options?.timeoutMs ?? this.timeoutMs;
12263
+ const passive = isPassiveCommand(command);
12264
+ const resolvedTimeoutMs = options?.transportTimeoutMs ?? options?.timeoutMs ?? this.timeoutMs;
12265
+ const effectiveTimeoutMs = passive ? Math.min(resolvedTimeoutMs, PASSIVE_COMMAND_TIMEOUT_MS) : resolvedTimeoutMs;
12145
12266
  const implicitTransportOptions = {
12146
12267
  ...options?.transportTimeoutMs !== undefined || options?.timeoutMs !== undefined ? { transportTimeoutMs: effectiveTimeoutMs } : {},
12147
12268
  markConfiguredOnSuccess: false
@@ -12191,9 +12312,9 @@ class BinaryBridge {
12191
12312
  }
12192
12313
  const line = `${JSON.stringify(request)}
12193
12314
  `;
12194
- const keepBridgeOnTimeout = options?.keepBridgeOnTimeout === true;
12315
+ const keepBridgeOnTimeout = passive || options?.keepBridgeOnTimeout === true;
12195
12316
  let requestSentAt = Date.now();
12196
- const response = await new Promise((resolve, reject) => {
12317
+ const response = await new Promise((resolve2, reject) => {
12197
12318
  const timer = setTimeout(() => {
12198
12319
  const entry = this.pending.get(id);
12199
12320
  if (!entry)
@@ -12213,7 +12334,7 @@ class BinaryBridge {
12213
12334
  const childActiveSinceRequest = this.lastChildActivityAt > requestSentAt;
12214
12335
  const consecutiveTimeouts = this.consecutiveRequestTimeouts + 1;
12215
12336
  this.consecutiveRequestTimeouts = consecutiveTimeouts;
12216
- const keepWarm = childActiveSinceRequest || consecutiveTimeouts < BRIDGE_HANG_TIMEOUT_THRESHOLD;
12337
+ const keepWarm = childActiveSinceRequest || consecutiveTimeouts < this.hangThreshold;
12217
12338
  const restartSuffix = keepWarm ? " — bridge kept warm" : " — restarting bridge";
12218
12339
  const timeoutMsg = `Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms${restartSuffix}`;
12219
12340
  if (requestSessionId) {
@@ -12228,7 +12349,7 @@ class BinaryBridge {
12228
12349
  entry.reject(new Error(`${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`));
12229
12350
  this.handleTimeout(requestSessionId);
12230
12351
  }, effectiveTimeoutMs);
12231
- this.pending.set(id, { resolve, reject, timer, onProgress: options?.onProgress, command });
12352
+ this.pending.set(id, { resolve: resolve2, reject, timer, onProgress: options?.onProgress, command });
12232
12353
  if (!this.process?.stdin?.writable) {
12233
12354
  this.pending.delete(id);
12234
12355
  clearTimeout(timer);
@@ -12326,15 +12447,15 @@ class BinaryBridge {
12326
12447
  if (this.process) {
12327
12448
  const proc = this.process;
12328
12449
  this.process = null;
12329
- return new Promise((resolve) => {
12450
+ return new Promise((resolve2) => {
12330
12451
  const forceKillTimer = setTimeout(() => {
12331
12452
  proc.kill("SIGKILL");
12332
- resolve();
12453
+ resolve2();
12333
12454
  }, 5000);
12334
12455
  proc.once("exit", () => {
12335
12456
  clearTimeout(forceKillTimer);
12336
12457
  this.logVia("Process exited during shutdown");
12337
- resolve();
12458
+ resolve2();
12338
12459
  });
12339
12460
  proc.kill("SIGTERM");
12340
12461
  });
@@ -12379,15 +12500,15 @@ class BinaryBridge {
12379
12500
  return;
12380
12501
  const proc = this.process;
12381
12502
  this.process = null;
12382
- await new Promise((resolve) => {
12503
+ await new Promise((resolve2) => {
12383
12504
  const forceKillTimer = setTimeout(() => {
12384
12505
  proc.kill("SIGKILL");
12385
- resolve();
12506
+ resolve2();
12386
12507
  }, 5000);
12387
12508
  proc.once("exit", () => {
12388
12509
  clearTimeout(forceKillTimer);
12389
12510
  this.logVia("Process exited during coordinated binary replacement");
12390
- resolve();
12511
+ resolve2();
12391
12512
  });
12392
12513
  proc.kill("SIGTERM");
12393
12514
  });
@@ -12414,7 +12535,7 @@ class BinaryBridge {
12414
12535
  })();
12415
12536
  const useFastembedBackend = semanticBackend === undefined || semanticBackend === "fastembed" || semanticBackend === "";
12416
12537
  const ortDir = typeof this.configOverrides._ort_dylib_dir === "string" && useFastembedBackend ? this.configOverrides._ort_dylib_dir : null;
12417
- const ortLibraryPath = ortDir == null ? null : join(ortDir, process.platform === "win32" ? "onnxruntime.dll" : process.platform === "darwin" ? "libonnxruntime.dylib" : "libonnxruntime.so");
12538
+ const ortLibraryPath = ortDir == null ? null : join2(ortDir, process.platform === "win32" ? "onnxruntime.dll" : process.platform === "darwin" ? "libonnxruntime.dylib" : "libonnxruntime.so");
12418
12539
  const envPath = process.platform === "win32" && ortDir ? `${ortDir};${process.env.PATH ?? ""}` : process.env.PATH;
12419
12540
  const env = {
12420
12541
  ...process.env,
@@ -12422,7 +12543,7 @@ class BinaryBridge {
12422
12543
  };
12423
12544
  this.logVia(`bridge.spawnProcess: useFastembedBackend=${useFastembedBackend}, ` + `parentORT=${process.env.ORT_DYLIB_PATH ?? "(unset)"}, ` + `ortLibraryPath=${ortLibraryPath ?? "(none)"}`);
12424
12545
  if (useFastembedBackend) {
12425
- 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"));
12546
+ 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"));
12426
12547
  if (process.env.ORT_DYLIB_PATH) {
12427
12548
  this.logVia(`ORT_DYLIB_PATH inherited from parent env: ${process.env.ORT_DYLIB_PATH}`);
12428
12549
  } else if (ortLibraryPath) {
@@ -12508,7 +12629,7 @@ class BinaryBridge {
12508
12629
  `)) !== -1) {
12509
12630
  const line = this.stderrBuffer.slice(0, newlineIdx).replace(/\r$/, "");
12510
12631
  this.stderrBuffer = this.stderrBuffer.slice(newlineIdx + 1);
12511
- if (!line)
12632
+ if (!line || !shouldSurfaceStderrLine(line))
12512
12633
  continue;
12513
12634
  const tagged = tagStderrLine(line);
12514
12635
  this.logVia(tagged);
@@ -12518,7 +12639,7 @@ class BinaryBridge {
12518
12639
  flushStderrBuffer() {
12519
12640
  const line = this.stderrBuffer.replace(/\r$/, "");
12520
12641
  this.stderrBuffer = "";
12521
- if (!line)
12642
+ if (!line || !shouldSurfaceStderrLine(line))
12522
12643
  return;
12523
12644
  const tagged = tagStderrLine(line);
12524
12645
  this.logVia(tagged);
@@ -12764,12 +12885,23 @@ function coerceStringArray(value) {
12764
12885
  }
12765
12886
  return [];
12766
12887
  }
12888
+ function isEmptyParam(value) {
12889
+ if (value === undefined || value === null)
12890
+ return true;
12891
+ if (typeof value === "string")
12892
+ return value.length === 0;
12893
+ if (Array.isArray(value))
12894
+ return value.length === 0;
12895
+ if (typeof value === "object")
12896
+ return Object.keys(value).length === 0;
12897
+ return false;
12898
+ }
12767
12899
  // ../aft-bridge/dist/downloader.js
12768
12900
  import { spawnSync } from "node:child_process";
12769
12901
  import { createHash, randomUUID } from "node:crypto";
12770
12902
  import { chmodSync, closeSync, copyFileSync, createWriteStream, existsSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, unlinkSync, writeSync } from "node:fs";
12771
- import { homedir as homedir2 } from "node:os";
12772
- import { join as join2 } from "node:path";
12903
+ import { homedir as homedir3 } from "node:os";
12904
+ import { join as join3 } from "node:path";
12773
12905
  import { Readable } from "node:stream";
12774
12906
  import { pipeline } from "node:stream/promises";
12775
12907
 
@@ -12826,11 +12958,11 @@ function isExpectedCachedBinary(binaryPath, tag) {
12826
12958
  function getCacheDir() {
12827
12959
  if (process.platform === "win32") {
12828
12960
  const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
12829
- const base2 = localAppData || join2(homedir2(), "AppData", "Local");
12830
- return join2(base2, "aft", "bin");
12961
+ const base2 = localAppData || join3(homedir3(), "AppData", "Local");
12962
+ return join3(base2, "aft", "bin");
12831
12963
  }
12832
- const base = process.env.XDG_CACHE_HOME || join2(homedir2(), ".cache");
12833
- return join2(base, "aft", "bin");
12964
+ const base = process.env.XDG_CACHE_HOME || join3(homedir3(), ".cache");
12965
+ return join3(base, "aft", "bin");
12834
12966
  }
12835
12967
  function getBinaryName() {
12836
12968
  return process.platform === "win32" ? "aft.exe" : "aft";
@@ -12838,7 +12970,7 @@ function getBinaryName() {
12838
12970
  function getCachedBinaryPath(version) {
12839
12971
  if (!version)
12840
12972
  return null;
12841
- const binaryPath = join2(getCacheDir(), version, getBinaryName());
12973
+ const binaryPath = join3(getCacheDir(), version, getBinaryName());
12842
12974
  return existsSync(binaryPath) ? binaryPath : null;
12843
12975
  }
12844
12976
  async function downloadBinary(version) {
@@ -12855,16 +12987,16 @@ async function downloadBinary(version) {
12855
12987
  return null;
12856
12988
  }
12857
12989
  const tag = rawTag.startsWith("v") ? rawTag : `v${rawTag}`;
12858
- const versionedCacheDir = join2(getCacheDir(), tag);
12990
+ const versionedCacheDir = join3(getCacheDir(), tag);
12859
12991
  const binaryName = getBinaryName();
12860
- const binaryPath = join2(versionedCacheDir, binaryName);
12992
+ const binaryPath = join3(versionedCacheDir, binaryName);
12861
12993
  if (existsSync(binaryPath) && isExpectedCachedBinary(binaryPath, tag)) {
12862
12994
  return binaryPath;
12863
12995
  }
12864
12996
  const downloadUrl = `https://github.com/${REPO}/releases/download/${tag}/${assetName}`;
12865
12997
  const checksumUrl = `https://github.com/${REPO}/releases/download/${tag}/checksums.sha256`;
12866
12998
  log(`Downloading AFT binary (${tag}) for ${platformKey}...`);
12867
- const lockPath = join2(versionedCacheDir, ".download.lock");
12999
+ const lockPath = join3(versionedCacheDir, ".download.lock");
12868
13000
  let releaseLock = null;
12869
13001
  let binaryController = null;
12870
13002
  let checksumController = null;
@@ -13016,7 +13148,7 @@ async function acquireDownloadLock(lockPath) {
13016
13148
  if (Date.now() - startedAt > DOWNLOAD_LOCK_TIMEOUT_MS) {
13017
13149
  throw new Error(`Timed out waiting for download lock: ${lockPath}`);
13018
13150
  }
13019
- await new Promise((resolve) => setTimeout(resolve, 100));
13151
+ await new Promise((resolve2) => setTimeout(resolve2, 100));
13020
13152
  }
13021
13153
  }
13022
13154
  }
@@ -13102,18 +13234,18 @@ function stripJsoncSymbols(value) {
13102
13234
  // ../aft-bridge/dist/migration.js
13103
13235
  import { spawnSync as spawnSync2 } from "node:child_process";
13104
13236
  import { existsSync as existsSync4, mkdirSync as mkdirSync4 } from "node:fs";
13105
- import { homedir as homedir4, tmpdir } from "node:os";
13106
- import { dirname as dirname2, join as join5 } from "node:path";
13237
+ import { homedir as homedir5, tmpdir } from "node:os";
13238
+ import { dirname as dirname2, join as join6 } from "node:path";
13107
13239
 
13108
13240
  // ../aft-bridge/dist/paths.js
13109
13241
  import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync as renameSync2, writeFileSync } from "node:fs";
13110
- import { dirname, join as join3 } from "node:path";
13242
+ import { dirname, join as join4 } from "node:path";
13111
13243
  function resolveHarnessStoragePath(storageRoot, harness, ...segments) {
13112
- return join3(storageRoot, harness, ...segments);
13244
+ return join4(storageRoot, harness, ...segments);
13113
13245
  }
13114
13246
  function repairRootScopedStorageFile(storageRoot, harness, fileName) {
13115
13247
  const harnessPath = resolveHarnessStoragePath(storageRoot, harness, fileName);
13116
- const rootPath = join3(storageRoot, fileName);
13248
+ const rootPath = join4(storageRoot, fileName);
13117
13249
  if (existsSync2(harnessPath) || !existsSync2(rootPath))
13118
13250
  return harnessPath;
13119
13251
  try {
@@ -13159,8 +13291,8 @@ function markAnnouncementSeen(storageRoot, harness, currentVersion) {
13159
13291
  import { execSync } from "node:child_process";
13160
13292
  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";
13161
13293
  import { createRequire as createRequire2 } from "node:module";
13162
- import { homedir as homedir3 } from "node:os";
13163
- import { join as join4 } from "node:path";
13294
+ import { homedir as homedir4 } from "node:os";
13295
+ import { join as join5 } from "node:path";
13164
13296
  var ensureBinaryForResolver = ensureBinary;
13165
13297
  function copyToVersionedCache(npmBinaryPath, knownVersion) {
13166
13298
  try {
@@ -13169,9 +13301,9 @@ function copyToVersionedCache(npmBinaryPath, knownVersion) {
13169
13301
  return null;
13170
13302
  const tag = version.startsWith("v") ? version : `v${version}`;
13171
13303
  const cacheDir = getCacheDir();
13172
- const versionedDir = join4(cacheDir, tag);
13304
+ const versionedDir = join5(cacheDir, tag);
13173
13305
  const ext = process.platform === "win32" ? ".exe" : "";
13174
- const cachedPath = join4(versionedDir, `aft${ext}`);
13306
+ const cachedPath = join5(versionedDir, `aft${ext}`);
13175
13307
  if (existsSync3(cachedPath)) {
13176
13308
  const cachedVersion = readBinaryVersion(cachedPath);
13177
13309
  if (cachedVersion === version)
@@ -13201,18 +13333,18 @@ function normalizeBareVersion(version) {
13201
13333
  return version.startsWith("v") ? version.slice(1) : version;
13202
13334
  }
13203
13335
  function homeDirFromEnv(env) {
13204
- return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir3();
13336
+ return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir4();
13205
13337
  }
13206
13338
  function cacheDirFromEnv(env) {
13207
13339
  if (process.platform === "win32") {
13208
- const base2 = env.LOCALAPPDATA || env.APPDATA || join4(homeDirFromEnv(env), "AppData", "Local");
13209
- return join4(base2, "aft", "bin");
13340
+ const base2 = env.LOCALAPPDATA || env.APPDATA || join5(homeDirFromEnv(env), "AppData", "Local");
13341
+ return join5(base2, "aft", "bin");
13210
13342
  }
13211
- const base = env.XDG_CACHE_HOME || join4(homeDirFromEnv(env), ".cache");
13212
- return join4(base, "aft", "bin");
13343
+ const base = env.XDG_CACHE_HOME || join5(homeDirFromEnv(env), ".cache");
13344
+ return join5(base, "aft", "bin");
13213
13345
  }
13214
13346
  function cachedBinaryPathFromEnv(version, env, ext) {
13215
- const binaryPath = join4(cacheDirFromEnv(env), version, `aft${ext}`);
13347
+ const binaryPath = join5(cacheDirFromEnv(env), version, `aft${ext}`);
13216
13348
  return existsSync3(binaryPath) ? binaryPath : null;
13217
13349
  }
13218
13350
  function isExpectedCachedBinary2(binaryPath, expectedVersion) {
@@ -13331,7 +13463,7 @@ function findBinarySync(expectedVersion) {
13331
13463
  return usable;
13332
13464
  }
13333
13465
  } catch {}
13334
- const cargoPath = join4(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
13466
+ const cargoPath = join5(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
13335
13467
  if (existsSync3(cargoPath)) {
13336
13468
  const usable = probeBinaryCandidate(cargoPath, "cargo", expectedVersion);
13337
13469
  if (usable)
@@ -13377,22 +13509,22 @@ function dataHome() {
13377
13509
  if (process.env.XDG_DATA_HOME)
13378
13510
  return process.env.XDG_DATA_HOME;
13379
13511
  if (process.platform === "win32") {
13380
- return process.env.LOCALAPPDATA || process.env.APPDATA || join5(homeDir(), "AppData", "Local");
13512
+ return process.env.LOCALAPPDATA || process.env.APPDATA || join6(homeDir(), "AppData", "Local");
13381
13513
  }
13382
- return join5(homeDir(), ".local", "share");
13514
+ return join6(homeDir(), ".local", "share");
13383
13515
  }
13384
13516
  function homeDir() {
13385
13517
  if (process.platform === "win32")
13386
- return process.env.USERPROFILE || process.env.HOME || homedir4();
13387
- return process.env.HOME || homedir4();
13518
+ return process.env.USERPROFILE || process.env.HOME || homedir5();
13519
+ return process.env.HOME || homedir5();
13388
13520
  }
13389
13521
  function resolveLegacyStorageRoot(harness) {
13390
13522
  if (harness === "pi")
13391
- return join5(homeDir(), ".pi", "agent", "aft");
13392
- return join5(dataHome(), "opencode", "storage", "plugin", "aft");
13523
+ return join6(homeDir(), ".pi", "agent", "aft");
13524
+ return join6(dataHome(), "opencode", "storage", "plugin", "aft");
13393
13525
  }
13394
13526
  function resolveCortexKitStorageRoot() {
13395
- return join5(dataHome(), "cortexkit", "aft");
13527
+ return join6(dataHome(), "cortexkit", "aft");
13396
13528
  }
13397
13529
  function tail(value) {
13398
13530
  if (!value)
@@ -13406,12 +13538,12 @@ function spawnErrorLabel(error2) {
13406
13538
  return [code, error2.message].filter(Boolean).join(": ");
13407
13539
  }
13408
13540
  function migrationLogPath(newRoot, harness, logger) {
13409
- const desired = join5(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
13541
+ const desired = join6(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
13410
13542
  try {
13411
13543
  mkdirSync4(dirname2(desired), { recursive: true });
13412
13544
  return desired;
13413
13545
  } catch (err) {
13414
- const fallback = join5(tmpdir(), `aft-migration-${harness}-${Date.now()}.jsonl`);
13546
+ const fallback = join6(tmpdir(), `aft-migration-${harness}-${Date.now()}.jsonl`);
13415
13547
  logger?.warn?.(`Failed to create AFT migration log directory ${dirname2(desired)}: ${err instanceof Error ? err.message : String(err)}. ` + `Using fallback log path ${fallback}.`);
13416
13548
  return fallback;
13417
13549
  }
@@ -13474,13 +13606,13 @@ async function ensureStorageMigrated(opts) {
13474
13606
  }
13475
13607
  // ../aft-bridge/dist/npm-resolver.js
13476
13608
  import { readdirSync, statSync as statSync2 } from "node:fs";
13477
- import { homedir as homedir5 } from "node:os";
13478
- import { delimiter, dirname as dirname3, isAbsolute, join as join6 } from "node:path";
13609
+ import { homedir as homedir6 } from "node:os";
13610
+ import { delimiter, dirname as dirname3, isAbsolute as isAbsolute2, join as join7 } from "node:path";
13479
13611
  function defaultDeps() {
13480
13612
  return {
13481
13613
  platform: process.platform,
13482
13614
  env: process.env,
13483
- home: homedir5(),
13615
+ home: homedir6(),
13484
13616
  execPath: process.execPath
13485
13617
  };
13486
13618
  }
@@ -13499,16 +13631,16 @@ function npmFromPath(deps) {
13499
13631
  const raw = deps.env.PATH ?? deps.env.Path ?? "";
13500
13632
  for (const entry of raw.split(delimiter)) {
13501
13633
  const dir = entry.trim().replace(/^"|"$/g, "");
13502
- if (!dir || !isAbsolute(dir))
13634
+ if (!dir || !isAbsolute2(dir))
13503
13635
  continue;
13504
- if (isFile(join6(dir, name)))
13636
+ if (isFile(join7(dir, name)))
13505
13637
  return dir;
13506
13638
  }
13507
13639
  return null;
13508
13640
  }
13509
13641
  function npmAdjacentToNode(deps) {
13510
13642
  const dir = dirname3(deps.execPath);
13511
- return isFile(join6(dir, npmBinaryName(deps.platform))) ? dir : null;
13643
+ return isFile(join7(dir, npmBinaryName(deps.platform))) ? dir : null;
13512
13644
  }
13513
13645
  function highestVersionedNodeBin(installsDir, name) {
13514
13646
  let entries;
@@ -13517,8 +13649,8 @@ function highestVersionedNodeBin(installsDir, name) {
13517
13649
  } catch {
13518
13650
  return null;
13519
13651
  }
13520
- const candidates = entries.filter((v) => isFile(join6(installsDir, v, "bin", name))).sort((a, b) => compareVersionsDesc(a, b));
13521
- return candidates.length > 0 ? join6(installsDir, candidates[0], "bin") : null;
13652
+ const candidates = entries.filter((v) => isFile(join7(installsDir, v, "bin", name))).sort((a, b) => compareVersionsDesc(a, b));
13653
+ return candidates.length > 0 ? join7(installsDir, candidates[0], "bin") : null;
13522
13654
  }
13523
13655
  function compareVersionsDesc(a, b) {
13524
13656
  const pa = a.replace(/^v/, "").split(".").map((n) => Number.parseInt(n, 10));
@@ -13543,22 +13675,22 @@ function wellKnownNpmDirs(deps) {
13543
13675
  const programFiles = env.ProgramFiles || "C:\\Program Files";
13544
13676
  const appData = env.APPDATA;
13545
13677
  const localAppData = env.LOCALAPPDATA;
13546
- push(join6(programFiles, "nodejs"));
13678
+ push(join7(programFiles, "nodejs"));
13547
13679
  if (appData)
13548
- push(join6(appData, "npm"));
13680
+ push(join7(appData, "npm"));
13549
13681
  if (localAppData)
13550
- push(join6(localAppData, "Volta", "bin"));
13682
+ push(join7(localAppData, "Volta", "bin"));
13551
13683
  if (env.NVM_SYMLINK)
13552
13684
  push(env.NVM_SYMLINK);
13553
13685
  } else {
13554
13686
  if (env.NVM_BIN)
13555
13687
  push(env.NVM_BIN);
13556
- push(highestVersionedNodeBin(join6(home, ".nvm", "versions", "node"), name));
13557
- push(highestVersionedNodeBin(join6(home, ".local", "share", "mise", "installs", "node"), name));
13558
- push(highestVersionedNodeBin(join6(home, ".asdf", "installs", "nodejs"), name));
13559
- push(join6(home, ".volta", "bin"));
13560
- push(join6(home, ".asdf", "shims"));
13561
- const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin", join6(home, ".local", "bin")]);
13688
+ push(highestVersionedNodeBin(join7(home, ".nvm", "versions", "node"), name));
13689
+ push(highestVersionedNodeBin(join7(home, ".local", "share", "mise", "installs", "node"), name));
13690
+ push(highestVersionedNodeBin(join7(home, ".asdf", "installs", "nodejs"), name));
13691
+ push(join7(home, ".volta", "bin"));
13692
+ push(join7(home, ".asdf", "shims"));
13693
+ const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin", join7(home, ".local", "bin")]);
13562
13694
  for (const dir of systemDirs)
13563
13695
  push(dir);
13564
13696
  }
@@ -13568,12 +13700,12 @@ function resolveNpm(deps = defaultDeps()) {
13568
13700
  const name = npmBinaryName(deps.platform);
13569
13701
  const onPath = npmFromPath(deps);
13570
13702
  if (onPath)
13571
- return { command: join6(onPath, name), binDir: onPath };
13703
+ return { command: join7(onPath, name), binDir: onPath };
13572
13704
  const adjacent = npmAdjacentToNode(deps);
13573
13705
  if (adjacent)
13574
- return { command: join6(adjacent, name), binDir: adjacent };
13706
+ return { command: join7(adjacent, name), binDir: adjacent };
13575
13707
  for (const dir of wellKnownNpmDirs(deps)) {
13576
- const candidate = join6(dir, name);
13708
+ const candidate = join7(dir, name);
13577
13709
  if (isFile(candidate))
13578
13710
  return { command: candidate, binDir: dir };
13579
13711
  }
@@ -13593,7 +13725,7 @@ function isNpmAvailable(deps = defaultDeps()) {
13593
13725
  import { execFileSync } from "node:child_process";
13594
13726
  import { createHash as createHash2 } from "node:crypto";
13595
13727
  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";
13596
- import { basename, dirname as dirname4, isAbsolute as isAbsolute2, join as join7, relative, resolve, win32 } from "node:path";
13728
+ import { basename, dirname as dirname4, isAbsolute as isAbsolute3, join as join8, relative as relative2, resolve as resolve2, win32 } from "node:path";
13597
13729
  import { Readable as Readable2 } from "node:stream";
13598
13730
  import { pipeline as pipeline2 } from "node:stream/promises";
13599
13731
  var ORT_VERSION = "1.24.4";
@@ -13659,10 +13791,10 @@ function getManualInstallHint() {
13659
13791
  }
13660
13792
  async function ensureOnnxRuntime(storageDir) {
13661
13793
  const info = getPlatformInfo();
13662
- const ortVersionDir = join7(storageDir, "onnxruntime", ORT_VERSION);
13794
+ const ortVersionDir = join8(storageDir, "onnxruntime", ORT_VERSION);
13663
13795
  const libName = info?.libName ?? "libonnxruntime.dylib";
13664
13796
  const resolvedOrtDir = resolveCachedOnnxRuntimeDir(ortVersionDir, libName);
13665
- const libPath = join7(resolvedOrtDir, libName);
13797
+ const libPath = join8(resolvedOrtDir, libName);
13666
13798
  if (existsSync5(libPath)) {
13667
13799
  const meta = readOnnxInstalledMeta(ortVersionDir);
13668
13800
  if (meta?.sha256) {
@@ -13692,9 +13824,9 @@ async function ensureOnnxRuntime(storageDir) {
13692
13824
  warn(`ONNX Runtime auto-download not available for ${process.platform}/${process.arch}. Install manually: ${getManualInstallHint()}`);
13693
13825
  return null;
13694
13826
  }
13695
- const onnxBaseDir = join7(storageDir, "onnxruntime");
13827
+ const onnxBaseDir = join8(storageDir, "onnxruntime");
13696
13828
  mkdirSync5(onnxBaseDir, { recursive: true });
13697
- const lockPath = join7(onnxBaseDir, ONNX_LOCK_FILE);
13829
+ const lockPath = join8(onnxBaseDir, ONNX_LOCK_FILE);
13698
13830
  cleanupAbandonedStagingDirs(onnxBaseDir);
13699
13831
  if (!acquireLock(lockPath)) {
13700
13832
  warn(`ONNX Runtime install already in progress in another process (lock: ${lockPath}). Skipping.`);
@@ -13713,7 +13845,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
13713
13845
  for (const entry of entries) {
13714
13846
  if (!entry.startsWith(`${ORT_VERSION}.tmp.`))
13715
13847
  continue;
13716
- const stagingDir = join7(onnxBaseDir, entry);
13848
+ const stagingDir = join8(onnxBaseDir, entry);
13717
13849
  const parts = entry.split(".");
13718
13850
  const pidStr = parts[parts.length - 2];
13719
13851
  const pid = pidStr ? Number.parseInt(pidStr, 10) : NaN;
@@ -13750,7 +13882,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
13750
13882
  }
13751
13883
  function cleanupIncompleteTargetIfUnowned(ortDir) {
13752
13884
  try {
13753
- if (existsSync5(ortDir) && !existsSync5(join7(ortDir, ONNX_INSTALLED_META_FILE))) {
13885
+ if (existsSync5(ortDir) && !existsSync5(join8(ortDir, ONNX_INSTALLED_META_FILE))) {
13754
13886
  log(`[onnx] removing half-populated install dir ${ortDir} (no meta file)`);
13755
13887
  rmSync2(ortDir, { recursive: true, force: true });
13756
13888
  }
@@ -13778,8 +13910,8 @@ function parseOnnxVersionFromDirectoryPath(value) {
13778
13910
  return null;
13779
13911
  }
13780
13912
  function isPathInsideRoot(root, candidate) {
13781
- const rel = relative(root, candidate);
13782
- return rel === "" || !rel.startsWith("../") && !rel.startsWith("..\\") && rel !== ".." && !isAbsolute2(rel) && !win32.isAbsolute(rel);
13913
+ const rel = relative2(root, candidate);
13914
+ return rel === "" || !rel.startsWith("../") && !rel.startsWith("..\\") && rel !== ".." && !isAbsolute3(rel) && !win32.isAbsolute(rel);
13783
13915
  }
13784
13916
  function detectOnnxVersion(libDir, libName) {
13785
13917
  try {
@@ -13794,7 +13926,7 @@ function detectOnnxVersion(libDir, libName) {
13794
13926
  if (version)
13795
13927
  return version;
13796
13928
  }
13797
- const base = join7(libDir, libName);
13929
+ const base = join8(libDir, libName);
13798
13930
  if (existsSync5(base)) {
13799
13931
  try {
13800
13932
  const real = realpathSync(base);
@@ -13830,7 +13962,7 @@ function pathEntriesForPlatform() {
13830
13962
  return pathEnvValue().split(delimiter2).map((entry) => entry.trim().replace(/^"|"$/g, "")).filter((entry) => {
13831
13963
  if (!entry || entry === "." || entry.includes("\x00"))
13832
13964
  return false;
13833
- return isAbsolute2(entry) || win32.isAbsolute(entry);
13965
+ return isAbsolute3(entry) || win32.isAbsolute(entry);
13834
13966
  });
13835
13967
  }
13836
13968
  function directoryContainsLibrary(dir, libName) {
@@ -13846,10 +13978,10 @@ function directoryContainsLibrary(dir, libName) {
13846
13978
  }
13847
13979
  }
13848
13980
  function resolveCachedOnnxRuntimeDir(ortVersionDir, libName) {
13849
- if (existsSync5(join7(ortVersionDir, libName)))
13981
+ if (existsSync5(join8(ortVersionDir, libName)))
13850
13982
  return ortVersionDir;
13851
- const libSubdir = join7(ortVersionDir, "lib");
13852
- if (existsSync5(join7(libSubdir, libName)))
13983
+ const libSubdir = join8(ortVersionDir, "lib");
13984
+ if (existsSync5(join8(libSubdir, libName)))
13853
13985
  return libSubdir;
13854
13986
  return ortVersionDir;
13855
13987
  }
@@ -13864,12 +13996,12 @@ function findSystemOnnxRuntime(libName) {
13864
13996
  } else if (process.platform === "win32") {
13865
13997
  const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
13866
13998
  const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
13867
- searchPaths.push(join7(programFiles, "onnxruntime", "lib"), join7(programFiles, "Microsoft ONNX Runtime", "lib"), join7(programFiles, "Microsoft Machine Learning", "lib"), join7(programFilesX86, "onnxruntime", "lib"), ...(() => {
13999
+ searchPaths.push(join8(programFiles, "onnxruntime", "lib"), join8(programFiles, "Microsoft ONNX Runtime", "lib"), join8(programFiles, "Microsoft Machine Learning", "lib"), join8(programFilesX86, "onnxruntime", "lib"), ...(() => {
13868
14000
  const nugetPaths = [];
13869
14001
  const userProfile = process.env.USERPROFILE ?? "";
13870
14002
  if (!userProfile)
13871
14003
  return nugetPaths;
13872
- const nugetPackageDir = join7(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
14004
+ const nugetPackageDir = join8(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
13873
14005
  if (!existsSync5(nugetPackageDir))
13874
14006
  return nugetPaths;
13875
14007
  try {
@@ -13878,7 +14010,7 @@ function findSystemOnnxRuntime(libName) {
13878
14010
  continue;
13879
14011
  if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
13880
14012
  continue;
13881
- nugetPaths.push(join7(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join7(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
14013
+ nugetPaths.push(join8(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join8(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
13882
14014
  }
13883
14015
  } catch (err) {
13884
14016
  warn(`Failed to scan NuGet ONNX Runtime cache ${nugetPackageDir}: ${err instanceof Error ? err.message : String(err)}`);
@@ -13890,7 +14022,7 @@ function findSystemOnnxRuntime(libName) {
13890
14022
  const normalizeCase = process.platform === "win32" || process.platform === "darwin";
13891
14023
  const seen = new Set;
13892
14024
  const uniquePaths = searchPaths.filter((p) => {
13893
- let key = resolve(p).replace(/[/\\]+$/, "");
14025
+ let key = resolve2(p).replace(/[/\\]+$/, "");
13894
14026
  if (normalizeCase)
13895
14027
  key = key.toLowerCase();
13896
14028
  if (seen.has(key))
@@ -13900,7 +14032,7 @@ function findSystemOnnxRuntime(libName) {
13900
14032
  });
13901
14033
  const unknownVersionPaths = [];
13902
14034
  for (const dir of uniquePaths) {
13903
- const libPath = join7(dir, libName);
14035
+ const libPath = join8(dir, libName);
13904
14036
  if (process.platform === "win32") {
13905
14037
  if (!directoryContainsLibrary(dir, libName))
13906
14038
  continue;
@@ -13966,19 +14098,19 @@ function validateExtractedTree(stagingRoot) {
13966
14098
  const walk = (dir) => {
13967
14099
  const entries = readdirSync2(dir);
13968
14100
  for (const entry of entries) {
13969
- const fullPath = join7(dir, entry);
14101
+ const fullPath = join8(dir, entry);
13970
14102
  const lst = lstatSync(fullPath);
13971
14103
  if (lst.isSymbolicLink()) {
13972
14104
  const linkTarget = readlinkSync(fullPath);
13973
- const resolvedTarget = resolve(dirname4(fullPath), linkTarget);
13974
- const rel2 = relative(realRoot, resolvedTarget);
13975
- if (rel2.startsWith("..") || isAbsolute2(rel2) || win32.isAbsolute(rel2)) {
14105
+ const resolvedTarget = resolve2(dirname4(fullPath), linkTarget);
14106
+ const rel2 = relative2(realRoot, resolvedTarget);
14107
+ if (rel2.startsWith("..") || isAbsolute3(rel2) || win32.isAbsolute(rel2)) {
13976
14108
  throw new Error(`extracted symlink ${fullPath} points outside staging root: ${linkTarget}`);
13977
14109
  }
13978
14110
  continue;
13979
14111
  }
13980
- const rel = relative(realRoot, fullPath);
13981
- if (rel.startsWith("..") || isAbsolute2(rel) || win32.isAbsolute(rel)) {
14112
+ const rel = relative2(realRoot, fullPath);
14113
+ if (rel.startsWith("..") || isAbsolute3(rel) || win32.isAbsolute(rel)) {
13982
14114
  throw new Error(`extracted entry ${fullPath} escapes staging root`);
13983
14115
  }
13984
14116
  if (lst.isDirectory()) {
@@ -14001,7 +14133,7 @@ async function downloadOnnxRuntime(info, targetDir) {
14001
14133
  const tmpDir = `${targetDir}.tmp.${process.pid}.${Date.now().toString(36)}`;
14002
14134
  try {
14003
14135
  mkdirSync5(tmpDir, { recursive: true });
14004
- const archivePath = join7(tmpDir, `onnxruntime.${info.archiveType}`);
14136
+ const archivePath = join8(tmpDir, `onnxruntime.${info.archiveType}`);
14005
14137
  await downloadFileWithCap(url, archivePath);
14006
14138
  const archiveSha256 = sha256File(archivePath);
14007
14139
  log(`ONNX Runtime archive sha256=${archiveSha256}`);
@@ -14017,7 +14149,7 @@ async function downloadOnnxRuntime(info, targetDir) {
14017
14149
  unlinkSync3(archivePath);
14018
14150
  } catch {}
14019
14151
  validateExtractedTree(tmpDir);
14020
- const extractedDir = join7(tmpDir, info.assetName, "lib");
14152
+ const extractedDir = join8(tmpDir, info.assetName, "lib");
14021
14153
  if (!existsSync5(extractedDir)) {
14022
14154
  throw new Error(`Expected directory not found: ${extractedDir}`);
14023
14155
  }
@@ -14026,7 +14158,7 @@ async function downloadOnnxRuntime(info, targetDir) {
14026
14158
  const realFiles = [];
14027
14159
  const symlinks = [];
14028
14160
  for (const libFile of libFiles) {
14029
- const src = join7(extractedDir, libFile);
14161
+ const src = join8(extractedDir, libFile);
14030
14162
  try {
14031
14163
  const stat = lstatSync(src);
14032
14164
  log(`ORT extract: ${libFile} — isSymlink=${stat.isSymbolicLink()}, isFile=${stat.isFile()}, size=${stat.size}`);
@@ -14041,7 +14173,7 @@ async function downloadOnnxRuntime(info, targetDir) {
14041
14173
  }
14042
14174
  }
14043
14175
  copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks);
14044
- const libPath = join7(targetDir, info.libName);
14176
+ const libPath = join8(targetDir, info.libName);
14045
14177
  let libHash = null;
14046
14178
  try {
14047
14179
  libHash = sha256File(libPath);
@@ -14066,8 +14198,8 @@ async function downloadOnnxRuntime(info, targetDir) {
14066
14198
  function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, copyFile = copyFileSync3) {
14067
14199
  const requiredLibs = new Set([info.libName]);
14068
14200
  for (const libFile of realFiles) {
14069
- const src = join7(extractedDir, libFile);
14070
- const dst = join7(targetDir, libFile);
14201
+ const src = join8(extractedDir, libFile);
14202
+ const dst = join8(targetDir, libFile);
14071
14203
  try {
14072
14204
  copyFile(src, dst);
14073
14205
  if (process.platform !== "win32") {
@@ -14083,12 +14215,12 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
14083
14215
  }
14084
14216
  const targetRoot = realpathSync(targetDir);
14085
14217
  for (const link of symlinks) {
14086
- const dst = join7(targetDir, link.name);
14218
+ const dst = join8(targetDir, link.name);
14087
14219
  try {
14088
14220
  unlinkSync3(dst);
14089
14221
  } catch {}
14090
- const dstForContainment = join7(targetRoot, link.name);
14091
- const resolvedTarget = resolve(dirname4(dstForContainment), link.target);
14222
+ const dstForContainment = join8(targetRoot, link.name);
14223
+ const resolvedTarget = resolve2(dirname4(dstForContainment), link.target);
14092
14224
  if (!isPathInsideRoot(targetRoot, resolvedTarget)) {
14093
14225
  const message = `ONNX Runtime symlink ${link.name} points outside install dir: ${link.target}`;
14094
14226
  if (requiredLibs.has(link.name)) {
@@ -14108,7 +14240,7 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
14108
14240
  log(`ORT extract: failed to symlink optional ${link.name}: ${symlinkErr}`);
14109
14241
  }
14110
14242
  }
14111
- const requiredPath = join7(targetDir, info.libName);
14243
+ const requiredPath = join8(targetDir, info.libName);
14112
14244
  if (!existsSync5(requiredPath)) {
14113
14245
  rmSync2(targetDir, { recursive: true, force: true });
14114
14246
  throw new Error(`Required ONNX Runtime library missing after install: ${requiredPath}`);
@@ -14135,17 +14267,17 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
14135
14267
  ...sha256 ? { sha256 } : {},
14136
14268
  archiveSha256
14137
14269
  };
14138
- writeFileSync2(join7(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
14270
+ writeFileSync2(join8(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
14139
14271
  } catch (err) {
14140
14272
  log(`[onnx] failed to write installed-meta in ${installDir}: ${err}`);
14141
14273
  }
14142
14274
  }
14143
14275
  function readOnnxInstalledMeta(installDir) {
14144
- const path = join7(installDir, ONNX_INSTALLED_META_FILE);
14276
+ const path2 = join8(installDir, ONNX_INSTALLED_META_FILE);
14145
14277
  try {
14146
- if (!statSync3(path).isFile())
14278
+ if (!statSync3(path2).isFile())
14147
14279
  return null;
14148
- const raw = readFileSync3(path, "utf8");
14280
+ const raw = readFileSync3(path2, "utf8");
14149
14281
  const parsed = JSON.parse(raw);
14150
14282
  if (typeof parsed.version !== "string" || parsed.version.length === 0)
14151
14283
  return null;
@@ -14159,9 +14291,9 @@ function readOnnxInstalledMeta(installDir) {
14159
14291
  return null;
14160
14292
  }
14161
14293
  }
14162
- function sha256File(path) {
14294
+ function sha256File(path2) {
14163
14295
  const hash = createHash2("sha256");
14164
- hash.update(readFileSync3(path));
14296
+ hash.update(readFileSync3(path2));
14165
14297
  return hash.digest("hex");
14166
14298
  }
14167
14299
  function acquireLock(lockPath) {
@@ -14843,6 +14975,7 @@ class BridgePool {
14843
14975
  this.projectConfigLoader = options.projectConfigLoader;
14844
14976
  this.bridgeOptions = {
14845
14977
  timeoutMs: options.timeoutMs,
14978
+ hangThreshold: options.hangThreshold,
14846
14979
  maxRestarts: options.maxRestarts,
14847
14980
  minVersion: options.minVersion,
14848
14981
  onVersionMismatch: options.onVersionMismatch,
@@ -14997,6 +15130,91 @@ function normalizeKey(projectRoot) {
14997
15130
  return stripped;
14998
15131
  }
14999
15132
  }
15133
+ // ../aft-bridge/dist/tool-format.js
15134
+ function asPlainObject(value) {
15135
+ if (!value || typeof value !== "object" || Array.isArray(value))
15136
+ return;
15137
+ return value;
15138
+ }
15139
+ function candidateLocation(candidate) {
15140
+ const file = typeof candidate.file === "string" && candidate.file.length > 0 ? candidate.file : undefined;
15141
+ if (!file)
15142
+ return;
15143
+ const line = typeof candidate.line === "number" && Number.isFinite(candidate.line) ? candidate.line : undefined;
15144
+ return line === undefined ? file : `${file}:${line}`;
15145
+ }
15146
+ function stringifyData(data) {
15147
+ if (data === undefined)
15148
+ return;
15149
+ try {
15150
+ return JSON.stringify(data, null, 2);
15151
+ } catch {
15152
+ return String(data);
15153
+ }
15154
+ }
15155
+ function formatBridgeErrorMessage(command, response, params = {}) {
15156
+ const code = typeof response.code === "string" && response.code.length > 0 ? response.code : undefined;
15157
+ const message = typeof response.message === "string" && response.message.length > 0 ? response.message : `${command} failed`;
15158
+ const data = asPlainObject(response.data);
15159
+ const rawCandidates = Array.isArray(response.candidates) ? response.candidates : Array.isArray(data?.candidates) ? data.candidates : undefined;
15160
+ const rawSymbol = typeof response.symbol === "string" && response.symbol.length > 0 ? response.symbol : typeof data?.symbol === "string" && data.symbol.length > 0 ? data.symbol : undefined;
15161
+ if (code === "ambiguous_target" || code === "target_symbol_not_in_file") {
15162
+ const candidates = (rawCandidates ?? []).map(asPlainObject).filter((candidate) => candidate !== undefined).map(candidateLocation).filter((candidate) => candidate !== undefined);
15163
+ if (candidates.length > 0) {
15164
+ const symbol = typeof params.toSymbol === "string" && params.toSymbol.length > 0 ? params.toSymbol : rawSymbol;
15165
+ const target = symbol ? `multiple symbols named "${symbol}"` : message.replace(/[.!?]+$/, "");
15166
+ const action = code === "ambiguous_target" ? "Pass toFile to disambiguate" : "Try one of these files for toFile";
15167
+ return `${command}: ${code} — ${target}. ${action}:
15168
+ ${candidates.map((candidate) => ` - ${candidate}`).join(`
15169
+ `)}`;
15170
+ }
15171
+ }
15172
+ if (!code)
15173
+ return message;
15174
+ const lines = [`${command}: ${code} — ${message}`];
15175
+ const extras = collectStructuredExtras(response);
15176
+ if (extras)
15177
+ lines.push(`data: ${extras}`);
15178
+ return lines.join(`
15179
+ `);
15180
+ }
15181
+ function collectStructuredExtras(response) {
15182
+ const reserved = new Set([
15183
+ "id",
15184
+ "success",
15185
+ "code",
15186
+ "message",
15187
+ "data",
15188
+ "status_bar",
15189
+ "bg_completions"
15190
+ ]);
15191
+ const extras = {};
15192
+ for (const [key, value] of Object.entries(response)) {
15193
+ if (reserved.has(key))
15194
+ continue;
15195
+ extras[key] = value;
15196
+ }
15197
+ if (Object.keys(extras).length === 0) {
15198
+ return stringifyData(response.data);
15199
+ }
15200
+ if (response.data !== undefined)
15201
+ extras.data = response.data;
15202
+ return stringifyData(extras);
15203
+ }
15204
+ function formatReadFooter(agentSpecifiedRange, data, options) {
15205
+ if (agentSpecifiedRange)
15206
+ return "";
15207
+ if (!data.truncated)
15208
+ return "";
15209
+ const startLine = data.start_line;
15210
+ const endLine = data.end_line;
15211
+ const totalLines = data.total_lines;
15212
+ if (startLine === undefined || endLine === undefined || totalLines === undefined) {
15213
+ return "";
15214
+ }
15215
+ return `
15216
+ (Showing lines ${startLine}-${endLine} of ${totalLines}. Use ${options.rangeHint} to read other sections.)`;
15217
+ }
15000
15218
  // ../aft-bridge/dist/zoom-format.js
15001
15219
  function formatZoomText(targetLabel, response) {
15002
15220
  const range = response.range;
@@ -15077,16 +15295,39 @@ function formatZoomMultiTargetResult(entries) {
15077
15295
 
15078
15296
  `) };
15079
15297
  }
15298
+ function isRustZoomBatchEnvelope(response) {
15299
+ if (!Array.isArray(response.symbols) || response.symbols.length === 0) {
15300
+ return false;
15301
+ }
15302
+ return response.symbols.every((entry) => {
15303
+ if (!entry || typeof entry !== "object")
15304
+ return false;
15305
+ const row = entry;
15306
+ return typeof row.name === "string" && row.response !== undefined && row.response !== null;
15307
+ });
15308
+ }
15309
+ function unwrapRustZoomBatchEnvelope(response) {
15310
+ if (!isRustZoomBatchEnvelope(response)) {
15311
+ return null;
15312
+ }
15313
+ const names = [];
15314
+ const responses = [];
15315
+ for (const entry of response.symbols) {
15316
+ names.push(entry.name);
15317
+ responses.push(entry.response);
15318
+ }
15319
+ return { names, responses };
15320
+ }
15080
15321
  // src/bg-notifications.ts
15081
15322
  import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypto";
15082
15323
 
15083
15324
  // src/logger.ts
15084
15325
  import * as fs from "node:fs";
15085
- import * as os from "node:os";
15086
- import * as path from "node:path";
15326
+ import * as os2 from "node:os";
15327
+ import * as path2 from "node:path";
15087
15328
  var TAG = "[aft-plugin]";
15088
15329
  var isTestEnv = process.env.BUN_TEST === "1" || false;
15089
- var logFile = path.join(os.tmpdir(), isTestEnv ? "aft-plugin-test.log" : "aft-plugin.log");
15330
+ var logFile = path2.join(os2.tmpdir(), isTestEnv ? "aft-plugin-test.log" : "aft-plugin.log");
15090
15331
  var useStderr = process.env.AFT_LOG_STDERR === "1";
15091
15332
  var buffer = [];
15092
15333
  var flushTimer = null;
@@ -15561,7 +15802,7 @@ async function triggerWakeIfPending(drainContext, skipDrain, includeDeferredComp
15561
15802
  const promptContext = await resolvePromptContext(client, drainContext.sessionID);
15562
15803
  const body = {
15563
15804
  noReply: false,
15564
- parts: [{ type: "text", text: reminder }]
15805
+ parts: [{ type: "text", text: reminder, synthetic: true }]
15565
15806
  };
15566
15807
  if (promptContext?.agent)
15567
15808
  body.agent = promptContext.agent;
@@ -16030,8 +16271,8 @@ function formatDuration(completion) {
16030
16271
 
16031
16272
  // src/config.ts
16032
16273
  import { existsSync as existsSync6, readFileSync as readFileSync4, renameSync as renameSync4, unlinkSync as unlinkSync4, writeFileSync as writeFileSync3 } from "node:fs";
16033
- import { homedir as homedir6 } from "node:os";
16034
- import { join as join9 } from "node:path";
16274
+ import { homedir as homedir7 } from "node:os";
16275
+ import { join as join10 } from "node:path";
16035
16276
  var import_comment_json = __toESM(require_src2(), 1);
16036
16277
 
16037
16278
  // ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
@@ -16799,10 +17040,10 @@ function mergeDefs(...defs) {
16799
17040
  function cloneDef(schema) {
16800
17041
  return mergeDefs(schema._zod.def);
16801
17042
  }
16802
- function getElementAtPath(obj, path2) {
16803
- if (!path2)
17043
+ function getElementAtPath(obj, path3) {
17044
+ if (!path3)
16804
17045
  return obj;
16805
- return path2.reduce((acc, key) => acc?.[key], obj);
17046
+ return path3.reduce((acc, key) => acc?.[key], obj);
16806
17047
  }
16807
17048
  function promiseAllObject(promisesObj) {
16808
17049
  const keys = Object.keys(promisesObj);
@@ -17183,11 +17424,11 @@ function aborted(x, startIndex = 0) {
17183
17424
  }
17184
17425
  return false;
17185
17426
  }
17186
- function prefixIssues(path2, issues) {
17427
+ function prefixIssues(path3, issues) {
17187
17428
  return issues.map((iss) => {
17188
17429
  var _a;
17189
17430
  (_a = iss).path ?? (_a.path = []);
17190
- iss.path.unshift(path2);
17431
+ iss.path.unshift(path3);
17191
17432
  return iss;
17192
17433
  });
17193
17434
  }
@@ -17370,7 +17611,7 @@ function formatError(error3, mapper = (issue2) => issue2.message) {
17370
17611
  }
17371
17612
  function treeifyError(error3, mapper = (issue2) => issue2.message) {
17372
17613
  const result = { errors: [] };
17373
- const processError = (error4, path2 = []) => {
17614
+ const processError = (error4, path3 = []) => {
17374
17615
  var _a, _b;
17375
17616
  for (const issue2 of error4.issues) {
17376
17617
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -17380,7 +17621,7 @@ function treeifyError(error3, mapper = (issue2) => issue2.message) {
17380
17621
  } else if (issue2.code === "invalid_element") {
17381
17622
  processError({ issues: issue2.issues }, issue2.path);
17382
17623
  } else {
17383
- const fullpath = [...path2, ...issue2.path];
17624
+ const fullpath = [...path3, ...issue2.path];
17384
17625
  if (fullpath.length === 0) {
17385
17626
  result.errors.push(mapper(issue2));
17386
17627
  continue;
@@ -17412,8 +17653,8 @@ function treeifyError(error3, mapper = (issue2) => issue2.message) {
17412
17653
  }
17413
17654
  function toDotPath(_path) {
17414
17655
  const segs = [];
17415
- const path2 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
17416
- for (const seg of path2) {
17656
+ const path3 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
17657
+ for (const seg of path3) {
17417
17658
  if (typeof seg === "number")
17418
17659
  segs.push(`[${seg}]`);
17419
17660
  else if (typeof seg === "symbol")
@@ -29160,13 +29401,13 @@ function resolveRef(ref, ctx) {
29160
29401
  if (!ref.startsWith("#")) {
29161
29402
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
29162
29403
  }
29163
- const path2 = ref.slice(1).split("/").filter(Boolean);
29164
- if (path2.length === 0) {
29404
+ const path3 = ref.slice(1).split("/").filter(Boolean);
29405
+ if (path3.length === 0) {
29165
29406
  return ctx.rootSchema;
29166
29407
  }
29167
29408
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
29168
- if (path2[0] === defsKey) {
29169
- const key = path2[1];
29409
+ if (path3[0] === defsKey) {
29410
+ const key = path3[1];
29170
29411
  if (!key || !ctx.defs[key]) {
29171
29412
  throw new Error(`Reference not found: ${ref}`);
29172
29413
  }
@@ -29645,6 +29886,10 @@ var BashFeaturesSchema = exports_external.object({
29645
29886
  foreground_wait_window_ms: exports_external.number().int().positive().optional()
29646
29887
  });
29647
29888
  var BashConfigSchema = exports_external.union([exports_external.boolean(), BashFeaturesSchema]);
29889
+ var BridgeConfigSchema = exports_external.object({
29890
+ request_timeout_ms: exports_external.number().int().min(1000, { message: "bridge.request_timeout_ms must be at least 1000" }).optional(),
29891
+ hang_threshold: exports_external.number().int().min(1, { message: "bridge.hang_threshold must be at least 1" }).optional()
29892
+ });
29648
29893
  var InspectConfigSchema = exports_external.object({
29649
29894
  enabled: exports_external.boolean().optional(),
29650
29895
  tier2_idle_minutes: exports_external.number().min(0).optional(),
@@ -29684,7 +29929,8 @@ var AftConfigSchema = exports_external.object({
29684
29929
  url_fetch_allow_private: exports_external.boolean().optional(),
29685
29930
  semantic: SemanticConfigSchema.optional(),
29686
29931
  max_callgraph_files: exports_external.number().int().positive().optional(),
29687
- auto_update: exports_external.boolean().optional()
29932
+ auto_update: exports_external.boolean().optional(),
29933
+ bridge: BridgeConfigSchema.optional()
29688
29934
  }).strict();
29689
29935
  function normalizeLspExtension(extension) {
29690
29936
  return extension.trim().replace(/^\.+/, "");
@@ -29864,9 +30110,9 @@ function extractCommentsForPreservation(content) {
29864
30110
  }
29865
30111
  return comments;
29866
30112
  }
29867
- function ensureRecordAtPath(root, path2) {
30113
+ function ensureRecordAtPath(root, path3) {
29868
30114
  let current = root;
29869
- for (const segment of path2) {
30115
+ for (const segment of path3) {
29870
30116
  const existing = current[segment];
29871
30117
  if (!existing || typeof existing !== "object" || Array.isArray(existing)) {
29872
30118
  current[segment] = {};
@@ -29875,9 +30121,9 @@ function ensureRecordAtPath(root, path2) {
29875
30121
  }
29876
30122
  return current;
29877
30123
  }
29878
- function hasPath(root, path2) {
30124
+ function hasPath(root, path3) {
29879
30125
  let current = root;
29880
- for (const segment of path2) {
30126
+ for (const segment of path3) {
29881
30127
  if (!current || typeof current !== "object" || Array.isArray(current))
29882
30128
  return false;
29883
30129
  const record2 = current;
@@ -29887,9 +30133,9 @@ function hasPath(root, path2) {
29887
30133
  }
29888
30134
  return true;
29889
30135
  }
29890
- function setPath(root, path2, value) {
29891
- const parent = ensureRecordAtPath(root, path2.slice(0, -1));
29892
- parent[path2[path2.length - 1]] = value;
30136
+ function setPath(root, path3, value) {
30137
+ const parent = ensureRecordAtPath(root, path3.slice(0, -1));
30138
+ parent[path3[path3.length - 1]] = value;
29893
30139
  }
29894
30140
  function migrateRawConfig(rawConfig, configPath, logger) {
29895
30141
  const oldKeys = [];
@@ -30194,6 +30440,8 @@ function getStrippedTopLevelKeys(override) {
30194
30440
  stripped.push("max_callgraph_files");
30195
30441
  if (override.auto_update !== undefined)
30196
30442
  stripped.push("auto_update");
30443
+ if (override.bridge !== undefined)
30444
+ stripped.push("bridge");
30197
30445
  return stripped;
30198
30446
  }
30199
30447
  function mergeConfigs(base, override) {
@@ -30205,6 +30453,7 @@ function mergeConfigs(base, override) {
30205
30453
  const experimental = mergeExperimentalConfig(base.experimental, override.experimental);
30206
30454
  const bash = mergeBashConfig(base.bash, override.bash);
30207
30455
  const inspect = mergeInspectConfig(base.inspect, override.inspect);
30456
+ const bridge = base.bridge;
30208
30457
  const safeOverride = pickProjectSafeFields(override);
30209
30458
  delete safeOverride.bash;
30210
30459
  delete safeOverride.inspect;
@@ -30218,25 +30467,34 @@ function mergeConfigs(base, override) {
30218
30467
  ...inspect !== undefined ? { inspect } : {},
30219
30468
  experimental,
30220
30469
  semantic,
30470
+ ...bridge !== undefined ? { bridge } : {},
30221
30471
  ...disabledTools.length > 0 ? { disabled_tools: [...new Set(disabledTools)] } : {}
30222
30472
  };
30223
30473
  }
30474
+ var DEFAULT_BRIDGE_REQUEST_TIMEOUT_MS = 30000;
30475
+ var DEFAULT_BRIDGE_HANG_THRESHOLD = 2;
30476
+ function resolveBridgePoolTransportOptions(config2) {
30477
+ return {
30478
+ timeoutMs: config2.bridge?.request_timeout_ms ?? DEFAULT_BRIDGE_REQUEST_TIMEOUT_MS,
30479
+ hangThreshold: config2.bridge?.hang_threshold ?? DEFAULT_BRIDGE_HANG_THRESHOLD
30480
+ };
30481
+ }
30224
30482
  function getOpenCodeConfigDir() {
30225
30483
  const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
30226
30484
  if (envDir) {
30227
30485
  return envDir;
30228
30486
  }
30229
- const xdgConfig = process.env.XDG_CONFIG_HOME || join9(homedir6(), ".config");
30230
- return join9(xdgConfig, "opencode");
30487
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join10(homedir7(), ".config");
30488
+ return join10(xdgConfig, "opencode");
30231
30489
  }
30232
30490
  function loadAftConfig(projectDirectory) {
30233
30491
  const configDir = getOpenCodeConfigDir();
30234
- const userBasePath = join9(configDir, "aft");
30492
+ const userBasePath = join10(configDir, "aft");
30235
30493
  migrateAftConfigFile(`${userBasePath}.jsonc`);
30236
30494
  migrateAftConfigFile(`${userBasePath}.json`);
30237
30495
  const userDetected = detectConfigFile(userBasePath);
30238
30496
  const userConfigPath = userDetected.format !== "none" ? userDetected.path : `${userBasePath}.json`;
30239
- const projectBasePath = join9(projectDirectory, ".opencode", "aft");
30497
+ const projectBasePath = join10(projectDirectory, ".opencode", "aft");
30240
30498
  migrateAftConfigFile(`${projectBasePath}.jsonc`);
30241
30499
  migrateAftConfigFile(`${projectBasePath}.json`);
30242
30500
  const projectDetected = detectConfigFile(projectBasePath);
@@ -30262,8 +30520,8 @@ function loadAftConfig(projectDirectory) {
30262
30520
 
30263
30521
  // src/notifications.ts
30264
30522
  import { existsSync as existsSync7, readFileSync as readFileSync5 } from "node:fs";
30265
- import { homedir as homedir7, platform } from "node:os";
30266
- import { join as join10 } from "node:path";
30523
+ import { homedir as homedir8, platform } from "node:os";
30524
+ import { join as join11 } from "node:path";
30267
30525
  function isTuiMode() {
30268
30526
  return process.env.OPENCODE_CLIENT === "cli";
30269
30527
  }
@@ -30283,18 +30541,18 @@ var FEATURE_MARKER = `${AFT_MARKER} New in`;
30283
30541
  var WARNING_MARKER = `${AFT_MARKER} ⚠️`;
30284
30542
  var STATUS_MARKER = `${AFT_MARKER} ✅`;
30285
30543
  function getDesktopStatePath() {
30286
- const os2 = platform();
30287
- const home = homedir7();
30288
- if (os2 === "darwin") {
30289
- return join10(home, "Library", "Application Support", "ai.opencode.desktop", "opencode.global.dat");
30544
+ const os3 = platform();
30545
+ const home = homedir8();
30546
+ if (os3 === "darwin") {
30547
+ return join11(home, "Library", "Application Support", "ai.opencode.desktop", "opencode.global.dat");
30290
30548
  }
30291
- if (os2 === "linux") {
30292
- const xdgConfig = process.env.XDG_CONFIG_HOME || join10(home, ".config");
30293
- return join10(xdgConfig, "ai.opencode.desktop", "opencode.global.dat");
30549
+ if (os3 === "linux") {
30550
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join11(home, ".config");
30551
+ return join11(xdgConfig, "ai.opencode.desktop", "opencode.global.dat");
30294
30552
  }
30295
- if (os2 === "win32") {
30296
- const appData = process.env.APPDATA || join10(home, "AppData", "Roaming");
30297
- return join10(appData, "ai.opencode.desktop", "opencode.global.dat");
30553
+ if (os3 === "win32") {
30554
+ const appData = process.env.APPDATA || join11(home, "AppData", "Roaming");
30555
+ return join11(appData, "ai.opencode.desktop", "opencode.global.dat");
30298
30556
  }
30299
30557
  return null;
30300
30558
  }
@@ -30764,37 +31022,37 @@ import { dirname as dirname7 } from "node:path";
30764
31022
  import { spawn as spawn2 } from "node:child_process";
30765
31023
  import { cpSync, existsSync as existsSync9, mkdtempSync, readFileSync as readFileSync7, rmSync as rmSync3, writeFileSync as writeFileSync5 } from "node:fs";
30766
31024
  import { tmpdir as tmpdir3 } from "node:os";
30767
- import { basename as basename2, dirname as dirname6, join as join13 } from "node:path";
31025
+ import { basename as basename2, dirname as dirname6, join as join14 } from "node:path";
30768
31026
  var import_comment_json3 = __toESM(require_src2(), 1);
30769
31027
 
30770
31028
  // src/hooks/auto-update-checker/checker.ts
30771
31029
  var import_comment_json2 = __toESM(require_src2(), 1);
30772
31030
  import { existsSync as existsSync8, readFileSync as readFileSync6, statSync as statSync4, writeFileSync as writeFileSync4 } from "node:fs";
30773
- import { homedir as homedir9 } from "node:os";
30774
- import { dirname as dirname5, isAbsolute as isAbsolute3, join as join12, resolve as resolve2 } from "node:path";
31031
+ import { homedir as homedir10 } from "node:os";
31032
+ import { dirname as dirname5, isAbsolute as isAbsolute4, join as join13, resolve as resolve3 } from "node:path";
30775
31033
  import { fileURLToPath } from "node:url";
30776
31034
 
30777
31035
  // src/hooks/auto-update-checker/constants.ts
30778
- import { homedir as homedir8, platform as platform2 } from "node:os";
30779
- import { join as join11 } from "node:path";
31036
+ import { homedir as homedir9, platform as platform2 } from "node:os";
31037
+ import { join as join12 } from "node:path";
30780
31038
  var PACKAGE_NAME = "@cortexkit/aft-opencode";
30781
31039
  var NPM_REGISTRY_URL = "https://registry.npmjs.org";
30782
31040
  var NPM_FETCH_TIMEOUT = 1e4;
30783
31041
  function getOpenCodeCacheRoot() {
30784
31042
  if (platform2() === "win32") {
30785
- return join11(process.env.LOCALAPPDATA ?? homedir8(), "opencode");
31043
+ return join12(process.env.LOCALAPPDATA ?? homedir9(), "opencode");
30786
31044
  }
30787
- return join11(homedir8(), ".cache", "opencode");
31045
+ return join12(homedir9(), ".cache", "opencode");
30788
31046
  }
30789
31047
  function getOpenCodeConfigRoot() {
30790
31048
  if (platform2() === "win32") {
30791
- return join11(process.env.APPDATA ?? join11(homedir8(), "AppData", "Roaming"), "opencode");
31049
+ return join12(process.env.APPDATA ?? join12(homedir9(), "AppData", "Roaming"), "opencode");
30792
31050
  }
30793
- return join11(process.env.XDG_CONFIG_HOME ?? join11(homedir8(), ".config"), "opencode");
31051
+ return join12(process.env.XDG_CONFIG_HOME ?? join12(homedir9(), ".config"), "opencode");
30794
31052
  }
30795
- var CACHE_DIR = join11(getOpenCodeCacheRoot(), "packages");
30796
- var USER_OPENCODE_CONFIG = join11(getOpenCodeConfigRoot(), "opencode.json");
30797
- var USER_OPENCODE_CONFIG_JSONC = join11(getOpenCodeConfigRoot(), "opencode.jsonc");
31053
+ var CACHE_DIR = join12(getOpenCodeCacheRoot(), "packages");
31054
+ var USER_OPENCODE_CONFIG = join12(getOpenCodeConfigRoot(), "opencode.json");
31055
+ var USER_OPENCODE_CONFIG_JSONC = join12(getOpenCodeConfigRoot(), "opencode.jsonc");
30798
31056
 
30799
31057
  // src/hooks/auto-update-checker/types.ts
30800
31058
  var NpmPackageEnvelopeSchema = exports_external.object({
@@ -30852,8 +31110,8 @@ function extractChannel(version2) {
30852
31110
  }
30853
31111
  function getConfigPaths(directory) {
30854
31112
  return [
30855
- join12(directory, ".opencode", "opencode.json"),
30856
- join12(directory, ".opencode", "opencode.jsonc"),
31113
+ join13(directory, ".opencode", "opencode.json"),
31114
+ join13(directory, ".opencode", "opencode.jsonc"),
30857
31115
  USER_OPENCODE_CONFIG,
30858
31116
  USER_OPENCODE_CONFIG_JSONC
30859
31117
  ];
@@ -30866,9 +31124,9 @@ function resolvePathPluginSpec(spec, configPath) {
30866
31124
  return spec.replace(/^file:\/\//, "");
30867
31125
  }
30868
31126
  }
30869
- if (isAbsolute3(spec) || /^[A-Za-z]:[\\/]/.test(spec))
31127
+ if (isAbsolute4(spec) || /^[A-Za-z]:[\\/]/.test(spec))
30870
31128
  return spec;
30871
- return resolve2(dirname5(configPath), spec);
31129
+ return resolve3(dirname5(configPath), spec);
30872
31130
  }
30873
31131
  function getLocalDevPath(directory) {
30874
31132
  for (const configPath of getConfigPaths(directory)) {
@@ -30880,7 +31138,7 @@ function getLocalDevPath(directory) {
30880
31138
  for (const entry of plugins) {
30881
31139
  if (entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`))
30882
31140
  continue;
30883
- if (entry.startsWith("file://") || entry.startsWith(".") || isAbsolute3(entry)) {
31141
+ if (entry.startsWith("file://") || entry.startsWith(".") || isAbsolute4(entry)) {
30884
31142
  const localPath = resolvePathPluginSpec(entry, configPath);
30885
31143
  const pkgPath = findPackageJsonUp(localPath);
30886
31144
  if (!pkgPath)
@@ -30899,7 +31157,7 @@ function findPackageJsonUp(startPath) {
30899
31157
  const stat = statSync4(startPath);
30900
31158
  let dir = stat.isDirectory() ? startPath : dirname5(startPath);
30901
31159
  for (let i = 0;i < 10; i++) {
30902
- const pkgPath = join12(dir, "package.json");
31160
+ const pkgPath = join13(dir, "package.json");
30903
31161
  if (existsSync8(pkgPath)) {
30904
31162
  try {
30905
31163
  const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync6(pkgPath, "utf-8")));
@@ -30960,7 +31218,7 @@ function findPluginEntry(directory) {
30960
31218
  }
30961
31219
  var cachedPackageVersion = null;
30962
31220
  function getSpecCachePackageJsonPath(spec) {
30963
- return join12(CACHE_DIR, spec, "node_modules", PACKAGE_NAME, "package.json");
31221
+ return join13(CACHE_DIR, spec, "node_modules", PACKAGE_NAME, "package.json");
30964
31222
  }
30965
31223
  function getCachedVersion(spec) {
30966
31224
  if (!spec && cachedPackageVersion)
@@ -30969,7 +31227,7 @@ function getCachedVersion(spec) {
30969
31227
  getCurrentRuntimePackageJsonPath(),
30970
31228
  spec ? getSpecCachePackageJsonPath(spec) : null,
30971
31229
  getSpecCachePackageJsonPath(`${PACKAGE_NAME}@latest`),
30972
- join12(homedir9(), ".cache", "opencode", "node_modules", PACKAGE_NAME, "package.json")
31230
+ join13(homedir10(), ".cache", "opencode", "node_modules", PACKAGE_NAME, "package.json")
30973
31231
  ].filter(isString);
30974
31232
  for (const packageJsonPath of candidates) {
30975
31233
  try {
@@ -31017,10 +31275,10 @@ async function getLatestVersion(channel = "latest", options = {}) {
31017
31275
  // src/hooks/auto-update-checker/cache.ts
31018
31276
  var pendingSnapshots = new Map;
31019
31277
  function createAutoUpdateSnapshot(installDir, packageJsonPath, packageName) {
31020
- const packageDir = join13(installDir, "node_modules", packageName);
31021
- const lockfilePath = join13(installDir, "package-lock.json");
31022
- const tempDir = mkdtempSync(join13(tmpdir3(), "aft-auto-update-"));
31023
- const stagedPackageDir = existsSync9(packageDir) ? join13(tempDir, "package") : null;
31278
+ const packageDir = join14(installDir, "node_modules", packageName);
31279
+ const lockfilePath = join14(installDir, "package-lock.json");
31280
+ const tempDir = mkdtempSync(join14(tmpdir3(), "aft-auto-update-"));
31281
+ const stagedPackageDir = existsSync9(packageDir) ? join14(tempDir, "package") : null;
31024
31282
  if (stagedPackageDir)
31025
31283
  cpSync(packageDir, stagedPackageDir, { recursive: true });
31026
31284
  return {
@@ -31061,7 +31319,7 @@ function stripPackageNameFromPath(pathValue, packageName) {
31061
31319
  return current;
31062
31320
  }
31063
31321
  function removeFromPackageLock(installDir, packageName) {
31064
- const lockPath = join13(installDir, "package-lock.json");
31322
+ const lockPath = join14(installDir, "package-lock.json");
31065
31323
  if (!existsSync9(lockPath))
31066
31324
  return false;
31067
31325
  try {
@@ -31110,7 +31368,7 @@ function ensureDependencyVersion(packageJsonPath, packageName, version2) {
31110
31368
  }
31111
31369
  }
31112
31370
  function removeInstalledPackage(installDir, packageName) {
31113
- const packageDir = join13(installDir, "node_modules", packageName);
31371
+ const packageDir = join14(installDir, "node_modules", packageName);
31114
31372
  if (!existsSync9(packageDir))
31115
31373
  return false;
31116
31374
  rmSync3(packageDir, { recursive: true, force: true });
@@ -31123,13 +31381,13 @@ function resolveInstallContext(runtimePackageJsonPath = getCurrentRuntimePackage
31123
31381
  const nodeModulesDir = stripPackageNameFromPath(packageDir, PACKAGE_NAME);
31124
31382
  if (nodeModulesDir && basename2(nodeModulesDir) === "node_modules") {
31125
31383
  const installDir = dirname6(nodeModulesDir);
31126
- const packageJsonPath = join13(installDir, "package.json");
31384
+ const packageJsonPath = join14(installDir, "package.json");
31127
31385
  if (existsSync9(packageJsonPath))
31128
31386
  return { installDir, packageJsonPath };
31129
31387
  }
31130
31388
  return null;
31131
31389
  }
31132
- const legacyPackageJsonPath = join13(dirname6(CACHE_DIR), "package.json");
31390
+ const legacyPackageJsonPath = join14(dirname6(CACHE_DIR), "package.json");
31133
31391
  if (existsSync9(legacyPackageJsonPath)) {
31134
31392
  return { installDir: dirname6(CACHE_DIR), packageJsonPath: legacyPackageJsonPath };
31135
31393
  }
@@ -31460,7 +31718,7 @@ import {
31460
31718
  statSync as statSync6,
31461
31719
  writeFileSync as writeFileSync8
31462
31720
  } from "node:fs";
31463
- import { join as join16 } from "node:path";
31721
+ import { join as join17 } from "node:path";
31464
31722
 
31465
31723
  // src/lsp-cache.ts
31466
31724
  import {
@@ -31472,36 +31730,36 @@ import {
31472
31730
  unlinkSync as unlinkSync5,
31473
31731
  writeFileSync as writeFileSync7
31474
31732
  } from "node:fs";
31475
- import { homedir as homedir10 } from "node:os";
31476
- import { join as join14 } from "node:path";
31733
+ import { homedir as homedir11 } from "node:os";
31734
+ import { join as join15 } from "node:path";
31477
31735
  function aftCacheBase() {
31478
31736
  const override = process.env.AFT_CACHE_DIR;
31479
31737
  if (override && override.length > 0)
31480
31738
  return override;
31481
31739
  if (process.platform === "win32") {
31482
31740
  const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
31483
- const base2 = localAppData || join14(homedir10(), "AppData", "Local");
31484
- return join14(base2, "aft");
31741
+ const base2 = localAppData || join15(homedir11(), "AppData", "Local");
31742
+ return join15(base2, "aft");
31485
31743
  }
31486
- const base = process.env.XDG_CACHE_HOME || join14(homedir10(), ".cache");
31487
- return join14(base, "aft");
31744
+ const base = process.env.XDG_CACHE_HOME || join15(homedir11(), ".cache");
31745
+ return join15(base, "aft");
31488
31746
  }
31489
31747
  function lspCacheRoot() {
31490
- return join14(aftCacheBase(), "lsp-packages");
31748
+ return join15(aftCacheBase(), "lsp-packages");
31491
31749
  }
31492
31750
  function lspPackageDir(npmPackage) {
31493
- return join14(lspCacheRoot(), encodeURIComponent(npmPackage));
31751
+ return join15(lspCacheRoot(), encodeURIComponent(npmPackage));
31494
31752
  }
31495
31753
  function lspBinaryPath(npmPackage, binary) {
31496
- return join14(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
31754
+ return join15(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
31497
31755
  }
31498
31756
  function lspBinDir(npmPackage) {
31499
- return join14(lspPackageDir(npmPackage), "node_modules", ".bin");
31757
+ return join15(lspPackageDir(npmPackage), "node_modules", ".bin");
31500
31758
  }
31501
31759
  function isInstalled(npmPackage, binary) {
31502
31760
  for (const candidate of lspBinaryCandidates(binary)) {
31503
31761
  try {
31504
- if (statSync5(join14(lspBinDir(npmPackage), candidate)).isFile())
31762
+ if (statSync5(join15(lspBinDir(npmPackage), candidate)).isFile())
31505
31763
  return true;
31506
31764
  } catch {}
31507
31765
  }
@@ -31521,17 +31779,17 @@ function writeInstalledMetaIn(installDir, version2, sha256) {
31521
31779
  installedAt: new Date().toISOString(),
31522
31780
  ...sha256 ? { sha256 } : {}
31523
31781
  };
31524
- writeFileSync7(join14(installDir, INSTALLED_META_FILE), JSON.stringify(meta3), "utf8");
31782
+ writeFileSync7(join15(installDir, INSTALLED_META_FILE), JSON.stringify(meta3), "utf8");
31525
31783
  } catch (err) {
31526
31784
  log2(`[lsp-cache] failed to write installed-meta in ${installDir}: ${err}`);
31527
31785
  }
31528
31786
  }
31529
31787
  function readInstalledMetaIn(installDir) {
31530
- const path2 = join14(installDir, INSTALLED_META_FILE);
31788
+ const path3 = join15(installDir, INSTALLED_META_FILE);
31531
31789
  try {
31532
- if (!statSync5(path2).isFile())
31790
+ if (!statSync5(path3).isFile())
31533
31791
  return null;
31534
- const raw = readFileSync9(path2, "utf8");
31792
+ const raw = readFileSync9(path3, "utf8");
31535
31793
  const parsed = JSON.parse(raw);
31536
31794
  if (typeof parsed.version !== "string" || parsed.version.length === 0)
31537
31795
  return null;
@@ -31551,7 +31809,7 @@ function readInstalledMeta(packageKey) {
31551
31809
  return readInstalledMetaIn(lspPackageDir(packageKey));
31552
31810
  }
31553
31811
  function lockPath(npmPackage) {
31554
- return join14(lspPackageDir(npmPackage), ".aft-installing");
31812
+ return join15(lspPackageDir(npmPackage), ".aft-installing");
31555
31813
  }
31556
31814
  var STALE_LOCK_MS2 = 30 * 60 * 1000;
31557
31815
  function acquireInstallLock(lockKey) {
@@ -31658,7 +31916,7 @@ async function withInstallLock(lockKey, task) {
31658
31916
  }
31659
31917
  var VERSION_CHECK_FILE = ".aft-version-check";
31660
31918
  function readVersionCheck(npmPackage) {
31661
- const file2 = join14(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
31919
+ const file2 = join15(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
31662
31920
  try {
31663
31921
  const raw = readFileSync9(file2, "utf8");
31664
31922
  const parsed = JSON.parse(raw);
@@ -31675,7 +31933,7 @@ function readVersionCheck(npmPackage) {
31675
31933
  }
31676
31934
  function writeVersionCheck(npmPackage, latest) {
31677
31935
  mkdirSync7(lspPackageDir(npmPackage), { recursive: true });
31678
- const file2 = join14(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
31936
+ const file2 = join15(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
31679
31937
  const record2 = {
31680
31938
  last_checked: new Date().toISOString(),
31681
31939
  latest_eligible: latest
@@ -31838,7 +32096,7 @@ var NPM_LSP_TABLE = [
31838
32096
 
31839
32097
  // src/lsp-project-relevance.ts
31840
32098
  import { existsSync as existsSync11, readdirSync as readdirSync3, readFileSync as readFileSync10 } from "node:fs";
31841
- import { join as join15 } from "node:path";
32099
+ import { join as join16 } from "node:path";
31842
32100
  var MAX_WALK_DIRS = 200;
31843
32101
  var MAX_WALK_DEPTH = 4;
31844
32102
  var NOISE_DIRS = new Set([
@@ -31855,7 +32113,7 @@ function hasRootMarker(projectRoot, rootMarkers) {
31855
32113
  if (!rootMarkers)
31856
32114
  return false;
31857
32115
  for (const marker of rootMarkers) {
31858
- if (existsSync11(join15(projectRoot, marker)))
32116
+ if (existsSync11(join16(projectRoot, marker)))
31859
32117
  return true;
31860
32118
  }
31861
32119
  return false;
@@ -31879,7 +32137,7 @@ function hasPackageJsonDep(projectRoot, depNames) {
31879
32137
  }
31880
32138
  function readPackageJson(projectRoot) {
31881
32139
  try {
31882
- const raw = readFileSync10(join15(projectRoot, "package.json"), "utf8");
32140
+ const raw = readFileSync10(join16(projectRoot, "package.json"), "utf8");
31883
32141
  const parsed = JSON.parse(raw);
31884
32142
  if (typeof parsed !== "object" || parsed === null)
31885
32143
  return null;
@@ -31909,7 +32167,7 @@ function relevantExtensionsInProject(projectRoot, extToServer) {
31909
32167
  for (const entry of entries) {
31910
32168
  if (entry.isDirectory()) {
31911
32169
  if (current.depth < MAX_WALK_DEPTH && !NOISE_DIRS.has(entry.name.toLowerCase())) {
31912
- queue.push({ dir: join15(current.dir, entry.name), depth: current.depth + 1 });
32170
+ queue.push({ dir: join16(current.dir, entry.name), depth: current.depth + 1 });
31913
32171
  }
31914
32172
  continue;
31915
32173
  }
@@ -32036,7 +32294,7 @@ async function resolveTargetVersion(spec, config2, fetchImpl = fetch) {
32036
32294
  }
32037
32295
  function ensureInstallAnchor(cwd) {
32038
32296
  try {
32039
- const stub = join16(cwd, "package.json");
32297
+ const stub = join17(cwd, "package.json");
32040
32298
  if (!existsSync12(stub)) {
32041
32299
  writeFileSync8(stub, `${JSON.stringify({ name: "aft-lsp-cache", version: "0.0.0", private: true })}
32042
32300
  `);
@@ -32046,18 +32304,18 @@ function ensureInstallAnchor(cwd) {
32046
32304
  }
32047
32305
  }
32048
32306
  function runInstall(spec, version2, cwd, signal) {
32049
- return new Promise((resolve3) => {
32307
+ return new Promise((resolve4) => {
32050
32308
  const target = `${spec.npm}@${version2}`;
32051
32309
  log2(`[lsp] installing ${target} to ${cwd}`);
32052
32310
  if (signal?.aborted) {
32053
32311
  warn2(`[lsp] install ${target} aborted before spawn`);
32054
- resolve3(false);
32312
+ resolve4(false);
32055
32313
  return;
32056
32314
  }
32057
32315
  const npm = resolveNpm();
32058
32316
  if (!npm) {
32059
32317
  warn2(`[lsp] npm not found on PATH or known locations; cannot install ${target}`);
32060
- resolve3(false);
32318
+ resolve4(false);
32061
32319
  return;
32062
32320
  }
32063
32321
  ensureInstallAnchor(cwd);
@@ -32080,7 +32338,7 @@ function runInstall(spec, version2, cwd, signal) {
32080
32338
  return;
32081
32339
  settled = true;
32082
32340
  cleanup();
32083
- resolve3(ok);
32341
+ resolve4(ok);
32084
32342
  };
32085
32343
  const onAbort = () => {
32086
32344
  warn2(`[lsp] install ${target} aborted during shutdown`);
@@ -32181,7 +32439,7 @@ function cachedPackageDir(npmPackage) {
32181
32439
  return lspBinDir(npmPackage).replace(/[\\/]node_modules[\\/]\.bin[\\/]?$/, "");
32182
32440
  }
32183
32441
  function hashInstalledBinary(spec) {
32184
- return new Promise((resolve3, reject) => {
32442
+ return new Promise((resolve4, reject) => {
32185
32443
  const candidates = process.platform === "win32" ? [
32186
32444
  lspBinaryPath(spec.npm, spec.binary),
32187
32445
  lspBinaryPath(spec.npm, `${spec.binary}.cmd`),
@@ -32205,7 +32463,7 @@ function hashInstalledBinary(spec) {
32205
32463
  const stream = createReadStream(pathToHash);
32206
32464
  stream.on("error", reject);
32207
32465
  stream.on("data", (chunk) => hash2.update(chunk));
32208
- stream.on("end", () => resolve3(hash2.digest("hex")));
32466
+ stream.on("end", () => resolve4(hash2.digest("hex")));
32209
32467
  });
32210
32468
  }
32211
32469
  function installedBinaryPath(spec) {
@@ -32223,15 +32481,15 @@ function installedBinaryPath(spec) {
32223
32481
  }
32224
32482
  return null;
32225
32483
  }
32226
- function sha256OfFileSync(path2) {
32227
- return createHash4("sha256").update(readFileSync11(path2)).digest("hex");
32484
+ function sha256OfFileSync(path3) {
32485
+ return createHash4("sha256").update(readFileSync11(path3)).digest("hex");
32228
32486
  }
32229
32487
  function quarantineCachedNpmInstall(spec, reason) {
32230
32488
  const packageDir = lspPackageDir(spec.npm);
32231
- const dest = join16(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
32489
+ const dest = join17(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
32232
32490
  warn2(`[lsp] tofu_mismatch ${spec.npm}: ${reason}; quarantining ${packageDir} -> ${dest}`);
32233
32491
  try {
32234
- mkdirSync8(join16(dest, ".."), { recursive: true });
32492
+ mkdirSync8(join17(dest, ".."), { recursive: true });
32235
32493
  rmSync5(dest, { recursive: true, force: true });
32236
32494
  renameSync6(packageDir, dest);
32237
32495
  } catch (err) {
@@ -32327,7 +32585,7 @@ import {
32327
32585
  unlinkSync as unlinkSync6,
32328
32586
  writeFileSync as writeFileSync9
32329
32587
  } from "node:fs";
32330
- import { dirname as dirname8, join as join17, relative as relative2, resolve as resolve3 } from "node:path";
32588
+ import { dirname as dirname8, join as join18, relative as relative3, resolve as resolve4 } from "node:path";
32331
32589
  import { Readable as Readable3 } from "node:stream";
32332
32590
  import { pipeline as pipeline3 } from "node:stream/promises";
32333
32591
 
@@ -32417,26 +32675,26 @@ function detectHostPlatform() {
32417
32675
 
32418
32676
  // src/lsp-github-install.ts
32419
32677
  function ghCacheRoot() {
32420
- return join17(aftCacheBase(), "lsp-binaries");
32678
+ return join18(aftCacheBase(), "lsp-binaries");
32421
32679
  }
32422
32680
  function ghPackageDir(spec) {
32423
- return join17(ghCacheRoot(), spec.id);
32681
+ return join18(ghCacheRoot(), spec.id);
32424
32682
  }
32425
32683
  function ghBinDir(spec) {
32426
- return join17(ghPackageDir(spec), "bin");
32684
+ return join18(ghPackageDir(spec), "bin");
32427
32685
  }
32428
32686
  function ghExtractDir(spec) {
32429
- return join17(ghPackageDir(spec), "extracted");
32687
+ return join18(ghPackageDir(spec), "extracted");
32430
32688
  }
32431
32689
  var INSTALLED_META_FILE2 = ".aft-installed";
32432
32690
  function ghBinaryPath(spec, platform3) {
32433
32691
  const ext = platform3 === "win32" ? ".exe" : "";
32434
- return join17(ghBinDir(spec), `${spec.binary}${ext}`);
32692
+ return join18(ghBinDir(spec), `${spec.binary}${ext}`);
32435
32693
  }
32436
32694
  function isGithubInstalled(spec, platform3) {
32437
32695
  for (const candidate of ghBinaryCandidates(spec, platform3)) {
32438
32696
  try {
32439
- if (statSync7(join17(ghBinDir(spec), candidate)).isFile())
32697
+ if (statSync7(join18(ghBinDir(spec), candidate)).isFile())
32440
32698
  return true;
32441
32699
  } catch {}
32442
32700
  }
@@ -32449,10 +32707,10 @@ function ghBinaryCandidates(spec, platform3) {
32449
32707
  }
32450
32708
  function readGithubInstalledMetaIn(installDir) {
32451
32709
  try {
32452
- const path2 = join17(installDir, INSTALLED_META_FILE2);
32453
- if (!statSync7(path2).isFile())
32710
+ const path3 = join18(installDir, INSTALLED_META_FILE2);
32711
+ if (!statSync7(path3).isFile())
32454
32712
  return null;
32455
- const parsed = JSON.parse(readFileSync12(path2, "utf8"));
32713
+ const parsed = JSON.parse(readFileSync12(path3, "utf8"));
32456
32714
  if (typeof parsed.version !== "string" || parsed.version.length === 0)
32457
32715
  return null;
32458
32716
  return {
@@ -32476,24 +32734,24 @@ function writeGithubInstalledMetaIn(installDir, version2, binarySha256, archiveS
32476
32734
  binarySha256,
32477
32735
  ...archiveSha256 ? { archiveSha256 } : {}
32478
32736
  };
32479
- writeFileSync9(join17(installDir, INSTALLED_META_FILE2), JSON.stringify(meta3), "utf8");
32737
+ writeFileSync9(join18(installDir, INSTALLED_META_FILE2), JSON.stringify(meta3), "utf8");
32480
32738
  } catch (err) {
32481
32739
  warn2(`[lsp] failed to write github installed metadata in ${installDir}: ${err}`);
32482
32740
  }
32483
32741
  }
32484
32742
  var MAX_DOWNLOAD_BYTES3 = 256 * 1024 * 1024;
32485
32743
  var MAX_EXTRACT_BYTES2 = 1024 * 1024 * 1024;
32486
- function sha256OfFile(path2) {
32487
- return new Promise((resolve4, reject) => {
32744
+ function sha256OfFile(path3) {
32745
+ return new Promise((resolve5, reject) => {
32488
32746
  const hash2 = createHash5("sha256");
32489
- const stream = createReadStream2(path2);
32747
+ const stream = createReadStream2(path3);
32490
32748
  stream.on("error", reject);
32491
32749
  stream.on("data", (chunk) => hash2.update(chunk));
32492
- stream.on("end", () => resolve4(hash2.digest("hex")));
32750
+ stream.on("end", () => resolve5(hash2.digest("hex")));
32493
32751
  });
32494
32752
  }
32495
- function sha256OfFileSync2(path2) {
32496
- return createHash5("sha256").update(readFileSync12(path2)).digest("hex");
32753
+ function sha256OfFileSync2(path3) {
32754
+ return createHash5("sha256").update(readFileSync12(path3)).digest("hex");
32497
32755
  }
32498
32756
  async function fetchReleaseByTag(githubRepo, tag, fetchImpl, signal) {
32499
32757
  const candidates = [];
@@ -32725,7 +32983,7 @@ function validateExtraction(stagingRoot) {
32725
32983
  throw new Error(`failed to read staging dir ${dir}: ${err}`);
32726
32984
  }
32727
32985
  for (const entry of entries) {
32728
- const full = join17(dir, entry);
32986
+ const full = join18(dir, entry);
32729
32987
  let lst;
32730
32988
  try {
32731
32989
  lst = lstatSync2(full);
@@ -32737,7 +32995,7 @@ function validateExtraction(stagingRoot) {
32737
32995
  try {
32738
32996
  target = readlinkSync2(full);
32739
32997
  } catch {}
32740
- throw new Error(`archive contains symlink ${relative2(realStagingRoot, full)} → ${target}; rejecting (zip-slip defense)`);
32998
+ throw new Error(`archive contains symlink ${relative3(realStagingRoot, full)} → ${target}; rejecting (zip-slip defense)`);
32741
32999
  }
32742
33000
  let realFull;
32743
33001
  try {
@@ -32745,8 +33003,8 @@ function validateExtraction(stagingRoot) {
32745
33003
  } catch (err) {
32746
33004
  throw new Error(`failed to realpath ${full}: ${err}`);
32747
33005
  }
32748
- const rel = relative2(realStagingRoot, realFull);
32749
- if (rel.startsWith("..") || resolve3(realStagingRoot, rel) !== realFull) {
33006
+ const rel = relative3(realStagingRoot, realFull);
33007
+ if (rel.startsWith("..") || resolve4(realStagingRoot, rel) !== realFull) {
32750
33008
  throw new Error(`archive entry escapes staging root: ${full} → ${realFull} (zip-slip defense)`);
32751
33009
  }
32752
33010
  if (lst.isDirectory()) {
@@ -32813,7 +33071,7 @@ function extractArchiveSafely(archivePath, destDir, archiveType) {
32813
33071
  }
32814
33072
  function quarantineCachedGithubInstall(spec, reason) {
32815
33073
  const packageDir = ghPackageDir(spec);
32816
- const dest = join17(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
33074
+ const dest = join18(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
32817
33075
  warn2(`[lsp] tofu_mismatch ${spec.id}: ${reason}; quarantining ${packageDir} -> ${dest}`);
32818
33076
  try {
32819
33077
  mkdirSync9(dirname8(dest), { recursive: true });
@@ -32826,7 +33084,7 @@ function quarantineCachedGithubInstall(spec, reason) {
32826
33084
  function validateCachedGithubInstall(spec, platform3) {
32827
33085
  const packageDir = ghPackageDir(spec);
32828
33086
  const meta3 = readGithubInstalledMetaIn(packageDir);
32829
- const binaryPath = ghBinaryCandidates(spec, platform3).map((candidate) => join17(ghBinDir(spec), candidate)).find((candidate) => {
33087
+ const binaryPath = ghBinaryCandidates(spec, platform3).map((candidate) => join18(ghBinDir(spec), candidate)).find((candidate) => {
32830
33088
  try {
32831
33089
  return statSync7(candidate).isFile();
32832
33090
  } catch {
@@ -32904,7 +33162,7 @@ async function downloadAndInstall(spec, tag, assets, platform3, arch, fetchImpl,
32904
33162
  }
32905
33163
  const pkgDir = ghPackageDir(spec);
32906
33164
  const extractDir = ghExtractDir(spec);
32907
- const archivePath = join17(pkgDir, expected.name);
33165
+ const archivePath = join18(pkgDir, expected.name);
32908
33166
  log2(`[lsp] downloading ${spec.id} ${tag} → ${matchingAsset.url}`);
32909
33167
  try {
32910
33168
  await downloadFile(matchingAsset.url, archivePath, fetchImpl, matchingAsset.size, signal);
@@ -32944,7 +33202,7 @@ async function downloadAndInstall(spec, tag, assets, platform3, arch, fetchImpl,
32944
33202
  unlinkSync6(archivePath);
32945
33203
  } catch {}
32946
33204
  }
32947
- const innerBinaryPath = join17(extractDir, spec.binaryPathInArchive(platform3, arch, version2));
33205
+ const innerBinaryPath = join18(extractDir, spec.binaryPathInArchive(platform3, arch, version2));
32948
33206
  if (!existsSync13(innerBinaryPath)) {
32949
33207
  error2(`[lsp] ${spec.id}: extracted binary not found at ${innerBinaryPath}`);
32950
33208
  return null;
@@ -33239,7 +33497,7 @@ function renderScreen(state, rows = state.rows, cols = state.cols) {
33239
33497
  `);
33240
33498
  }
33241
33499
  function writeTerminal(terminal, data) {
33242
- return new Promise((resolve4) => terminal.write(data, resolve4));
33500
+ return new Promise((resolve5) => terminal.write(data, resolve5));
33243
33501
  }
33244
33502
 
33245
33503
  // src/shared/rpc-server.ts
@@ -33254,18 +33512,18 @@ import {
33254
33512
  writeFileSync as writeFileSync10
33255
33513
  } from "node:fs";
33256
33514
  import { createServer } from "node:http";
33257
- import { dirname as dirname9, join as join19 } from "node:path";
33515
+ import { dirname as dirname9, join as join20 } from "node:path";
33258
33516
 
33259
33517
  // src/shared/rpc-utils.ts
33260
33518
  import { createHash as createHash6 } from "node:crypto";
33261
- import { join as join18 } from "node:path";
33519
+ import { join as join19 } from "node:path";
33262
33520
  function projectHash(directory) {
33263
33521
  const normalized = directory.replace(/\/+$/, "");
33264
33522
  return createHash6("sha256").update(normalized).digest("hex").slice(0, 16);
33265
33523
  }
33266
33524
  function rpcPortFileDir(storageDir, directory) {
33267
33525
  const hash2 = projectHash(directory);
33268
- return join18(storageDir, "rpc", hash2, "ports");
33526
+ return join19(storageDir, "rpc", hash2, "ports");
33269
33527
  }
33270
33528
  function isPidAlive(pid) {
33271
33529
  if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0)
@@ -33318,13 +33576,13 @@ class AftRpcServer {
33318
33576
  constructor(storageDir, directory) {
33319
33577
  this.portsDir = rpcPortFileDir(storageDir, directory);
33320
33578
  this.instanceId = randomBytes2(8).toString("hex");
33321
- this.portFilePath = join19(this.portsDir, `${this.instanceId}.json`);
33579
+ this.portFilePath = join20(this.portsDir, `${this.instanceId}.json`);
33322
33580
  }
33323
33581
  handle(method, handler) {
33324
33582
  this.handlers.set(method, handler);
33325
33583
  }
33326
33584
  async start() {
33327
- return new Promise((resolve4, reject) => {
33585
+ return new Promise((resolve5, reject) => {
33328
33586
  const server = createServer((req, res) => this.dispatch(req, res));
33329
33587
  server.on("error", (err) => {
33330
33588
  warn2(`RPC server error: ${err.message}`);
@@ -33357,7 +33615,7 @@ class AftRpcServer {
33357
33615
  } catch (err) {
33358
33616
  warn2(`Failed to write RPC port file: ${err}`);
33359
33617
  }
33360
- resolve4(this.port);
33618
+ resolve5(this.port);
33361
33619
  });
33362
33620
  server.unref();
33363
33621
  });
@@ -33372,7 +33630,7 @@ class AftRpcServer {
33372
33630
  for (const entry of entries) {
33373
33631
  if (!entry.endsWith(".json"))
33374
33632
  continue;
33375
- const filePath = join19(this.portsDir, entry);
33633
+ const filePath = join20(this.portsDir, entry);
33376
33634
  if (filePath === this.portFilePath)
33377
33635
  continue;
33378
33636
  try {
@@ -33777,20 +34035,20 @@ function formatStatusMarkdown(status) {
33777
34035
  // src/shared/tui-config.ts
33778
34036
  var import_comment_json4 = __toESM(require_src2(), 1);
33779
34037
  import { existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "node:fs";
33780
- import { dirname as dirname10, join as join21 } from "node:path";
34038
+ import { dirname as dirname10, join as join22 } from "node:path";
33781
34039
 
33782
34040
  // src/shared/opencode-config-dir.ts
33783
- import { homedir as homedir11 } from "node:os";
33784
- import { join as join20, resolve as resolve4 } from "node:path";
34041
+ import { homedir as homedir12 } from "node:os";
34042
+ import { join as join21, resolve as resolve5 } from "node:path";
33785
34043
  function getCliConfigDir() {
33786
34044
  const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
33787
34045
  if (envConfigDir) {
33788
- return resolve4(envConfigDir);
34046
+ return resolve5(envConfigDir);
33789
34047
  }
33790
34048
  if (process.platform === "win32") {
33791
- return join20(homedir11(), ".config", "opencode");
34049
+ return join21(homedir12(), ".config", "opencode");
33792
34050
  }
33793
- return join20(process.env.XDG_CONFIG_HOME || join20(homedir11(), ".config"), "opencode");
34051
+ return join21(process.env.XDG_CONFIG_HOME || join21(homedir12(), ".config"), "opencode");
33794
34052
  }
33795
34053
  function getOpenCodeConfigDir2(_options) {
33796
34054
  return getCliConfigDir();
@@ -33799,10 +34057,10 @@ function getOpenCodeConfigPaths(options) {
33799
34057
  const configDir = getOpenCodeConfigDir2(options);
33800
34058
  return {
33801
34059
  configDir,
33802
- configJson: join20(configDir, "opencode.json"),
33803
- configJsonc: join20(configDir, "opencode.jsonc"),
33804
- packageJson: join20(configDir, "package.json"),
33805
- omoConfig: join20(configDir, "magic-context.jsonc")
34060
+ configJson: join21(configDir, "opencode.json"),
34061
+ configJsonc: join21(configDir, "opencode.jsonc"),
34062
+ packageJson: join21(configDir, "package.json"),
34063
+ omoConfig: join21(configDir, "magic-context.jsonc")
33806
34064
  };
33807
34065
  }
33808
34066
 
@@ -33811,8 +34069,8 @@ var PLUGIN_NAME = "@cortexkit/aft-opencode";
33811
34069
  var PLUGIN_ENTRY = `${PLUGIN_NAME}@latest`;
33812
34070
  function resolveTuiConfigPath() {
33813
34071
  const configDir = getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
33814
- const jsoncPath = join21(configDir, "tui.jsonc");
33815
- const jsonPath = join21(configDir, "tui.json");
34072
+ const jsoncPath = join22(configDir, "tui.jsonc");
34073
+ const jsonPath = join22(configDir, "tui.json");
33816
34074
  if (existsSync15(jsoncPath))
33817
34075
  return jsoncPath;
33818
34076
  if (existsSync15(jsonPath))
@@ -33901,8 +34159,8 @@ function installProcessHandlers() {
33901
34159
  }
33902
34160
  signalShutdownStarted = true;
33903
34161
  process.exitCode = SIGNAL_EXIT_CODES[sig];
33904
- const timeout = new Promise((resolve5) => {
33905
- setTimeout(resolve5, SIGNAL_CLEANUP_TIMEOUT_MS);
34162
+ const timeout = new Promise((resolve6) => {
34163
+ setTimeout(resolve6, SIGNAL_CLEANUP_TIMEOUT_MS);
33906
34164
  });
33907
34165
  Promise.race([runCleanups(sig), timeout]).finally(() => {
33908
34166
  process.exit(SIGNAL_EXIT_CODES[sig]);
@@ -34014,99 +34272,18 @@ import { tool as tool3 } from "@opencode-ai/plugin";
34014
34272
 
34015
34273
  // src/tools/_shared.ts
34016
34274
  import * as fs3 from "node:fs";
34017
- import * as os2 from "node:os";
34018
- import * as path2 from "node:path";
34275
+ import * as os3 from "node:os";
34276
+ import * as path3 from "node:path";
34019
34277
  import { tool as tool2 } from "@opencode-ai/plugin";
34020
34278
  var z2 = tool2.schema;
34021
34279
  var optionalInt = (min, max) => z2.number().int().min(min).max(max).optional();
34022
- function isEmptyParam(value) {
34023
- if (value === undefined || value === null)
34024
- return true;
34025
- if (typeof value === "string")
34026
- return value.length === 0;
34027
- if (Array.isArray(value))
34028
- return value.length === 0;
34029
- if (typeof value === "object")
34030
- return Object.keys(value).length === 0;
34031
- return false;
34032
- }
34033
34280
  var BASH_TRANSPORT_TIMEOUT_MS = 30000;
34034
- function asPlainObject(value) {
34035
- if (!value || typeof value !== "object" || Array.isArray(value))
34036
- return;
34037
- return value;
34038
- }
34039
- function candidateLocation(candidate) {
34040
- const file2 = typeof candidate.file === "string" && candidate.file.length > 0 ? candidate.file : undefined;
34041
- if (!file2)
34042
- return;
34043
- const line = typeof candidate.line === "number" && Number.isFinite(candidate.line) ? candidate.line : undefined;
34044
- return line === undefined ? file2 : `${file2}:${line}`;
34045
- }
34046
- function stringifyData(data) {
34047
- if (data === undefined)
34048
- return;
34049
- try {
34050
- return JSON.stringify(data, null, 2);
34051
- } catch {
34052
- return String(data);
34053
- }
34054
- }
34055
- function formatBridgeErrorMessage(command, response, params = {}) {
34056
- const code = typeof response.code === "string" && response.code.length > 0 ? response.code : undefined;
34057
- const message = typeof response.message === "string" && response.message.length > 0 ? response.message : `${command} failed`;
34058
- const data = asPlainObject(response.data);
34059
- const rawCandidates = Array.isArray(response.candidates) ? response.candidates : Array.isArray(data?.candidates) ? data.candidates : undefined;
34060
- const rawSymbol = typeof response.symbol === "string" && response.symbol.length > 0 ? response.symbol : typeof data?.symbol === "string" && data.symbol.length > 0 ? data.symbol : undefined;
34061
- if (code === "ambiguous_target" || code === "target_symbol_not_in_file") {
34062
- const candidates = (rawCandidates ?? []).map(asPlainObject).filter((candidate) => candidate !== undefined).map(candidateLocation).filter((candidate) => candidate !== undefined);
34063
- if (candidates.length > 0) {
34064
- const symbol2 = typeof params.toSymbol === "string" && params.toSymbol.length > 0 ? params.toSymbol : rawSymbol;
34065
- const target = symbol2 ? `multiple symbols named "${symbol2}"` : message.replace(/[.!?]+$/, "");
34066
- const action = code === "ambiguous_target" ? "Pass toFile to disambiguate" : "Try one of these files for toFile";
34067
- return `${command}: ${code} — ${target}. ${action}:
34068
- ${candidates.map((candidate) => ` - ${candidate}`).join(`
34069
- `)}`;
34070
- }
34071
- }
34072
- if (!code)
34073
- return message;
34074
- const lines = [`${command}: ${code} — ${message}`];
34075
- const extras = collectStructuredExtras(response);
34076
- if (extras)
34077
- lines.push(`data: ${extras}`);
34078
- return lines.join(`
34079
- `);
34080
- }
34081
- function collectStructuredExtras(response) {
34082
- const reserved = new Set([
34083
- "id",
34084
- "success",
34085
- "code",
34086
- "message",
34087
- "data",
34088
- "status_bar",
34089
- "bg_completions"
34090
- ]);
34091
- const extras = {};
34092
- for (const [key, value] of Object.entries(response)) {
34093
- if (reserved.has(key))
34094
- continue;
34095
- extras[key] = value;
34096
- }
34097
- if (Object.keys(extras).length === 0) {
34098
- return stringifyData(response.data);
34099
- }
34100
- if (response.data !== undefined)
34101
- extras.data = response.data;
34102
- return stringifyData(extras);
34103
- }
34104
34281
  function canonicalizeDirectory(dir) {
34105
34282
  const trimmed = dir.replace(/[/\\]+$/, "");
34106
34283
  try {
34107
34284
  return fs3.realpathSync(trimmed);
34108
34285
  } catch {
34109
- return path2.resolve(trimmed);
34286
+ return path3.resolve(trimmed);
34110
34287
  }
34111
34288
  }
34112
34289
  function projectRootFor(runtime) {
@@ -34123,19 +34300,19 @@ async function resolveProjectRoot(ctx, runtime) {
34123
34300
  }
34124
34301
  return projectRootFor(runtime);
34125
34302
  }
34126
- function expandTilde(input) {
34303
+ function expandTilde2(input) {
34127
34304
  if (!input || !input.startsWith("~"))
34128
34305
  return input;
34129
34306
  if (input === "~")
34130
- return os2.homedir();
34131
- if (input.startsWith("~/") || input.startsWith(`~${path2.sep}`)) {
34132
- return path2.resolve(os2.homedir(), input.slice(2));
34307
+ return os3.homedir();
34308
+ if (input.startsWith("~/") || input.startsWith(`~${path3.sep}`)) {
34309
+ return path3.resolve(os3.homedir(), input.slice(2));
34133
34310
  }
34134
34311
  return input;
34135
34312
  }
34136
34313
  function resolvePathFromProjectRoot(projectRoot, target) {
34137
- const expanded = expandTilde(target);
34138
- return path2.isAbsolute(expanded) ? expanded : path2.resolve(projectRoot, expanded);
34314
+ const expanded = expandTilde2(target);
34315
+ return path3.isAbsolute(expanded) ? expanded : path3.resolve(projectRoot, expanded);
34139
34316
  }
34140
34317
  async function resolvePathArg(ctx, runtime, target) {
34141
34318
  return resolvePathFromProjectRoot(await resolveProjectRoot(ctx, runtime), target);
@@ -34177,19 +34354,19 @@ async function callBashBridge(ctx, runtime, command, params = {}, options) {
34177
34354
 
34178
34355
  // src/tools/permissions.ts
34179
34356
  import * as fs4 from "node:fs";
34180
- import * as path3 from "node:path";
34357
+ import * as path4 from "node:path";
34181
34358
  var UNSUPPORTED_ASK_HOST = "AFT requires OpenCode 1.15.5 or newer for permission asks; please upgrade OpenCode";
34182
34359
  async function runAsk(maybe) {
34183
34360
  await maybe;
34184
34361
  }
34185
34362
  function resolveAbsolutePath(context, target) {
34186
- return path3.isAbsolute(target) ? target : path3.resolve(projectRootFor(context), target);
34363
+ return path4.isAbsolute(target) ? target : path4.resolve(projectRootFor(context), target);
34187
34364
  }
34188
34365
  function resolveRelativePattern(context, target) {
34189
- return path3.relative(projectRootFor(context), resolveAbsolutePath(context, target)) || ".";
34366
+ return path4.relative(projectRootFor(context), resolveAbsolutePath(context, target)) || ".";
34190
34367
  }
34191
34368
  function resolveRelativePatternFromAbsolute(context, absolutePath) {
34192
- return path3.relative(projectRootFor(context), absolutePath) || ".";
34369
+ return path4.relative(projectRootFor(context), absolutePath) || ".";
34193
34370
  }
34194
34371
  function resolveRelativePatterns(context, targets) {
34195
34372
  const seen = new Set;
@@ -34229,8 +34406,8 @@ async function askEditPermission(context, patterns, metadata = {}) {
34229
34406
  function containsPath(parent, child) {
34230
34407
  if (!parent)
34231
34408
  return false;
34232
- const rel = path3.relative(parent, child);
34233
- return rel === "" || !rel.startsWith("..") && !path3.isAbsolute(rel);
34409
+ const rel = path4.relative(parent, child);
34410
+ return rel === "" || !rel.startsWith("..") && !path4.isAbsolute(rel);
34234
34411
  }
34235
34412
  function windowsPath(p) {
34236
34413
  if (process.platform !== "win32")
@@ -34240,7 +34417,7 @@ function windowsPath(p) {
34240
34417
  function normalizePath(p) {
34241
34418
  if (process.platform !== "win32")
34242
34419
  return p;
34243
- const resolved = path3.resolve(windowsPath(p));
34420
+ const resolved = path4.resolve(windowsPath(p));
34244
34421
  try {
34245
34422
  return fs4.realpathSync.native(resolved);
34246
34423
  } catch {
@@ -34256,7 +34433,7 @@ function normalizePathPattern(p) {
34256
34433
  if (!match)
34257
34434
  return normalizePath(p);
34258
34435
  const dir = /^[A-Za-z]:$/.test(match[1]) ? `${match[1]}\\` : match[1];
34259
- return path3.join(normalizePath(dir), match[2]);
34436
+ return path4.join(normalizePath(dir), match[2]);
34260
34437
  }
34261
34438
  async function assertExternalDirectoryPermission(context, target, options) {
34262
34439
  if (!target)
@@ -34275,8 +34452,8 @@ async function assertExternalDirectoryPermission(context, target, options) {
34275
34452
  return;
34276
34453
  }
34277
34454
  const kind = options?.kind ?? "file";
34278
- const parentDir = kind === "directory" ? absoluteTarget : path3.dirname(absoluteTarget);
34279
- const rawGlob = process.platform === "win32" ? normalizePathPattern(path3.join(parentDir, "*")) : path3.join(parentDir, "*").replaceAll("\\", "/");
34455
+ const parentDir = kind === "directory" ? absoluteTarget : path4.dirname(absoluteTarget);
34456
+ const rawGlob = process.platform === "win32" ? normalizePathPattern(path4.join(parentDir, "*")) : path4.join(parentDir, "*").replaceAll("\\", "/");
34280
34457
  try {
34281
34458
  await runAsk(context.ask({
34282
34459
  permission: "external_directory",
@@ -34350,6 +34527,20 @@ function extractHint(response) {
34350
34527
  const hint = response.hint;
34351
34528
  return typeof hint === "string" && hint.length > 0 ? hint : null;
34352
34529
  }
34530
+ function appendSkippedFiles(output, skippedFiles) {
34531
+ if (!skippedFiles || skippedFiles.length === 0)
34532
+ return output;
34533
+ const lines = skippedFiles.map((skipped) => {
34534
+ const file2 = skipped.file ?? "unknown";
34535
+ const reason = skipped.reason ?? "unknown reason";
34536
+ return ` ${file2}: ${reason}`;
34537
+ });
34538
+ return `${output}
34539
+
34540
+ Incomplete: skipped ${skippedFiles.length} file(s)
34541
+ ${lines.join(`
34542
+ `)}`;
34543
+ }
34353
34544
  async function resolveAstPaths(ctx, context, paths) {
34354
34545
  if (isEmptyParam(paths) || !Array.isArray(paths))
34355
34546
  return;
@@ -34374,17 +34565,18 @@ var SUPPORTED_LANGS = [
34374
34565
  "python",
34375
34566
  "rust",
34376
34567
  "go",
34377
- "pascal"
34568
+ "pascal",
34569
+ "r"
34378
34570
  ];
34379
34571
  function astTools(ctx) {
34380
34572
  const searchTool = {
34381
- description: `Search code patterns across filesystem using AST-aware matching. Supports 7 languages.
34573
+ description: `Search code patterns across filesystem using AST-aware matching. Supports 8 languages.
34382
34574
 
34383
34575
  ` + `Use meta-variables: $VAR matches a single AST node, $$$ matches multiple nodes (variadic).
34384
34576
  ` + `IMPORTANT: Patterns must be complete AST nodes (valid code fragments).
34385
34577
  ` + `For functions, include params and body: 'export async function $NAME($$$) { $$$ }' not just 'export async function $NAME'.
34386
34578
 
34387
- ` + "Examples: pattern='console.log($MSG)' lang='typescript', pattern='async function $NAME($$$) { $$$ }' lang='javascript', pattern='def $FUNC($$$): $$$' lang='python', pattern='Writeln($MSG);' lang='pascal'",
34579
+ ` + "Examples: pattern='console.log($MSG)' lang='typescript', pattern='async function $NAME($$$) { $$$ }' lang='javascript', pattern='def $FUNC($$$): $$$' lang='python', pattern='Writeln($MSG);' lang='pascal', pattern='$X <- $Y' lang='r'",
34388
34580
  args: {
34389
34581
  pattern: z3.string().describe("AST pattern with meta-variables ($VAR, $$$). Must be complete AST node."),
34390
34582
  lang: z3.enum(SUPPORTED_LANGS).describe("Target language"),
@@ -34465,6 +34657,9 @@ ${hint}`;
34465
34657
  }
34466
34658
  }
34467
34659
  }
34660
+ if (data.complete === false || (data.skipped_files?.length ?? 0) > 0) {
34661
+ output = appendSkippedFiles(output, data.skipped_files);
34662
+ }
34468
34663
  showOutputToUser(context, output);
34469
34664
  return output;
34470
34665
  }
@@ -34808,7 +35003,7 @@ function createBashTool(ctx, aftSearchRegisteredOverride) {
34808
35003
  throw new Error(status.message ?? "bash_status failed");
34809
35004
  }
34810
35005
  if (isTerminalStatus(status.status)) {
34811
- const rendered2 = maybeAppendGrepSearchHint(appendPipeStripNote(formatForegroundResult(status), pipeStrip.note), command, aftSearchRegistered);
35006
+ const rendered2 = maybeAppendGrepSearchHint(appendPipeStripNote(formatForegroundResult(status), pipeStrip.note), command, aftSearchRegistered, projectRootFor(context));
34812
35007
  const metadataPayload2 = foregroundMetadata(description, status, rendered2);
34813
35008
  metadata?.(metadataPayload2);
34814
35009
  return { output: rendered2, title: uiTitle, metadata: metadataPayload2 };
@@ -34872,11 +35067,6 @@ function createBashTool(ctx, aftSearchRegisteredOverride) {
34872
35067
  }
34873
35068
  };
34874
35069
  }
34875
- function appendPipeStripNote(output, note) {
34876
- return note ? `${output}
34877
-
34878
- ${note}` : output;
34879
- }
34880
35070
  function createBashStatusTool(ctx) {
34881
35071
  return {
34882
35072
  description: "Read-only snapshot of a background or PTY bash task's current state and output. Returns immediately. Never waits. Use bash_watch to block on or register for pattern matches and exit events.",
@@ -34981,9 +35171,6 @@ function ptyCacheKey(runtime, taskId) {
34981
35171
  function preview(output) {
34982
35172
  return output.length <= METADATA_PREVIEW_LIMIT ? output : output.slice(-METADATA_PREVIEW_LIMIT);
34983
35173
  }
34984
- function isTerminalStatus(status) {
34985
- return status === "completed" || status === "failed" || status === "killed" || status === "timed_out";
34986
- }
34987
35174
  function subagentGuidance(taskId) {
34988
35175
  return `
34989
35176
 
@@ -34999,30 +35186,6 @@ function formatPromotionMessage(taskId, timeout, waitWindowMs) {
34999
35186
  const waited = timeout !== undefined ? Math.min(timeout, waitWindowMs) : waitWindowMs;
35000
35187
  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({ taskId: "${taskId}" }) to inspect output or bash_kill({ taskId: "${taskId}" }) to terminate.`;
35001
35188
  }
35002
- function formatSeconds(ms) {
35003
- return `${Number((ms / 1000).toFixed(1))}s`;
35004
- }
35005
- function formatForegroundResult(data) {
35006
- const output = data.output_preview ?? "";
35007
- const outputPath = data.output_path;
35008
- const truncated = data.output_truncated === true;
35009
- const status = data.status;
35010
- const exit = data.exit_code;
35011
- let rendered = output;
35012
- if (truncated && outputPath) {
35013
- rendered += `
35014
- [output truncated; full output at ${outputPath}]`;
35015
- }
35016
- if (status === "timed_out") {
35017
- rendered += `
35018
- [command timed out]`;
35019
- }
35020
- if (typeof exit === "number" && exit !== 0) {
35021
- rendered += `
35022
- [exit code: ${exit}]`;
35023
- }
35024
- return rendered;
35025
- }
35026
35189
  function foregroundMetadata(description, data, rendered) {
35027
35190
  const outputPath = data.output_path;
35028
35191
  return {
@@ -35033,9 +35196,6 @@ function foregroundMetadata(description, data, rendered) {
35033
35196
  ...outputPath ? { outputPath } : {}
35034
35197
  };
35035
35198
  }
35036
- function sleep(ms) {
35037
- return new Promise((resolve7) => setTimeout(resolve7, ms));
35038
- }
35039
35199
  function getCallID(ctx) {
35040
35200
  const c = ctx;
35041
35201
  return c.callID ?? c.callId ?? c.call_id;
@@ -35058,7 +35218,7 @@ function conflictTools(ctx) {
35058
35218
  execute: async (args, context) => {
35059
35219
  const params = {};
35060
35220
  if (!isEmptyParam(args?.path)) {
35061
- const expanded = expandTilde(String(args.path));
35221
+ const expanded = expandTilde2(String(args.path));
35062
35222
  const projectRoot = await resolveProjectRoot(ctx, context);
35063
35223
  const resolved = resolvePathFromProjectRoot(projectRoot, expanded);
35064
35224
  const denied = await assertExternalDirectoryPermission(context, resolved, {
@@ -35080,7 +35240,7 @@ function conflictTools(ctx) {
35080
35240
 
35081
35241
  // src/tools/hoisted.ts
35082
35242
  import * as fs6 from "node:fs";
35083
- import * as path4 from "node:path";
35243
+ import * as path5 from "node:path";
35084
35244
  import { tool as tool8 } from "@opencode-ai/plugin";
35085
35245
 
35086
35246
  // src/patch-parser.ts
@@ -35520,13 +35680,16 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
35520
35680
  let scanText = "";
35521
35681
  let scanBaseOffset = 0;
35522
35682
  const bridgeOptions = {};
35683
+ if (waitFor?.kind === "regex") {
35684
+ await validateWaitRegex(ctx, runtime, waitFor);
35685
+ }
35523
35686
  clearSyncWatchAbort(runtime.sessionID);
35524
35687
  markTaskWaiting(runtime.sessionID, taskId);
35525
35688
  let sawTerminal = false;
35526
35689
  try {
35527
35690
  while (true) {
35528
35691
  const data = await bashStatusSnapshot2(ctx, runtime, taskId, outputMode, bridgeOptions);
35529
- const terminal = isTerminalStatus2(data.status);
35692
+ const terminal = isTerminalStatus(data.status);
35530
35693
  if (waitFor) {
35531
35694
  const scan = await readNewTaskOutput(runtime, taskId, data, spillCursor);
35532
35695
  if (scan) {
@@ -35534,7 +35697,12 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
35534
35697
  if (scanText.length === 0)
35535
35698
  scanBaseOffset = scan.baseOffset;
35536
35699
  scanText += scan.text;
35537
- const match = findWaitMatch(scanText, waitFor);
35700
+ if (waitFor.kind === "regex") {
35701
+ const trimmed = trimWaitScanBuffer(scanText, scanBaseOffset, waitFor);
35702
+ scanText = trimmed.text;
35703
+ scanBaseOffset = trimmed.baseOffset;
35704
+ }
35705
+ const match = await findWaitMatch(ctx, runtime, scanText, waitFor);
35538
35706
  if (match) {
35539
35707
  if (terminal) {
35540
35708
  sawTerminal = true;
@@ -35545,12 +35713,14 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
35545
35713
  reason: "matched",
35546
35714
  elapsed_ms: Date.now() - startedAt,
35547
35715
  match: match.text,
35548
- match_offset: scanBaseOffset + Buffer.byteLength(scanText.slice(0, match.index), "utf8")
35716
+ match_offset: scanBaseOffset + match.byteOffset
35549
35717
  });
35550
35718
  }
35551
- const trimmed = trimWaitScanBuffer(scanText, scanBaseOffset, waitFor);
35552
- scanText = trimmed.text;
35553
- scanBaseOffset = trimmed.baseOffset;
35719
+ if (waitFor.kind === "substring") {
35720
+ const trimmed = trimWaitScanBuffer(scanText, scanBaseOffset, waitFor);
35721
+ scanText = trimmed.text;
35722
+ scanBaseOffset = trimmed.baseOffset;
35723
+ }
35554
35724
  }
35555
35725
  }
35556
35726
  if (terminal) {
@@ -35565,7 +35735,7 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
35565
35735
  if (Date.now() >= deadline) {
35566
35736
  return withWaited(data, { reason: "timeout", elapsed_ms: Date.now() - startedAt });
35567
35737
  }
35568
- await sleep2(Math.min(BASH_WAIT_POLL_INTERVAL_MS, Math.max(0, deadline - Date.now())));
35738
+ await sleep(Math.min(BASH_WAIT_POLL_INTERVAL_MS, Math.max(0, deadline - Date.now())));
35569
35739
  }
35570
35740
  } finally {
35571
35741
  if (!sawTerminal)
@@ -35631,20 +35801,41 @@ function parseWaitPattern(value) {
35631
35801
  if (typeof value === "string")
35632
35802
  return { kind: "substring", value };
35633
35803
  if (isRegexWaitObject(value))
35634
- return { kind: "regex", value: new RegExp(value.regex), source: value.regex };
35804
+ return { kind: "regex", source: value.regex };
35635
35805
  return;
35636
35806
  }
35637
35807
  function isRegexWaitObject(value) {
35638
35808
  return typeof value === "object" && value !== null && "regex" in value && typeof value.regex === "string";
35639
35809
  }
35640
- function findWaitMatch(text, pattern) {
35810
+ async function validateWaitRegex(ctx, runtime, pattern) {
35811
+ await matchRegexWithBridge(ctx, runtime, pattern.source, "");
35812
+ }
35813
+ async function findWaitMatch(ctx, runtime, text, pattern) {
35641
35814
  if (pattern.kind === "substring") {
35642
35815
  const index = text.indexOf(pattern.value);
35643
- return index >= 0 ? { text: pattern.value, index } : undefined;
35816
+ return index >= 0 ? { text: pattern.value, byteOffset: Buffer.byteLength(text.slice(0, index), "utf8") } : undefined;
35817
+ }
35818
+ return await matchRegexWithBridge(ctx, runtime, pattern.source, text);
35819
+ }
35820
+ async function matchRegexWithBridge(ctx, runtime, pattern, text) {
35821
+ const result = await callBashBridge(ctx, runtime, "bash_regex_match", { pattern, text });
35822
+ if (result.success === false) {
35823
+ const code = String(result.code ?? "invalid_request");
35824
+ const message = String(result.message ?? "bash_regex_match failed");
35825
+ if (code === "invalid_regex")
35826
+ throw new Error(`invalid_request: invalid_regex: ${message}`);
35827
+ throw new Error(`${code}: ${message}`);
35644
35828
  }
35645
- pattern.value.lastIndex = 0;
35646
- const match = pattern.value.exec(text);
35647
- return match ? { text: match[0], index: match.index } : undefined;
35829
+ if (result.matched !== true)
35830
+ return;
35831
+ return {
35832
+ text: typeof result.match_text === "string" ? result.match_text : "",
35833
+ byteOffset: coerceMatchOffset(result.match_offset)
35834
+ };
35835
+ }
35836
+ function coerceMatchOffset(value) {
35837
+ const offset = typeof value === "number" ? value : Number(value ?? 0);
35838
+ return Number.isFinite(offset) && offset >= 0 ? offset : 0;
35648
35839
  }
35649
35840
  function trimWaitScanBuffer(text, baseOffset, pattern) {
35650
35841
  const keepFrom = pattern.kind === "substring" ? substringKeepStart(text, pattern.value) : regexKeepStart(text, REGEX_WAIT_SCAN_WINDOW_BYTES);
@@ -35677,18 +35868,12 @@ function regexKeepStart(text, maxBytes) {
35677
35868
  function withWaited(data, waited) {
35678
35869
  return { ...data, waited };
35679
35870
  }
35680
- function isTerminalStatus2(status) {
35681
- return status === "completed" || status === "failed" || status === "killed" || status === "timed_out";
35682
- }
35683
35871
  function ptyCacheKey2(runtime, taskId) {
35684
35872
  return `${projectRootFor(runtime)}::${runtime.sessionID ?? "__default__"}::${taskId}`;
35685
35873
  }
35686
35874
  function watchPtyCacheKey(runtime, taskId) {
35687
35875
  return `${ptyCacheKey2(runtime, taskId)}::watch`;
35688
35876
  }
35689
- function sleep2(ms) {
35690
- return new Promise((resolve7) => setTimeout(resolve7, ms));
35691
- }
35692
35877
 
35693
35878
  // src/tools/bash_write.ts
35694
35879
  import { tool as tool7 } from "@opencode-ai/plugin";
@@ -35723,21 +35908,10 @@ function createBashWriteTool(ctx) {
35723
35908
 
35724
35909
  // src/tools/hoisted.ts
35725
35910
  function relativeToWorktree(fp, worktree) {
35726
- return path4.relative(worktree, fp);
35911
+ return path5.relative(worktree, fp);
35727
35912
  }
35728
- function formatReadFooter(agentSpecifiedRange, data) {
35729
- if (agentSpecifiedRange)
35730
- return "";
35731
- if (!data.truncated)
35732
- return "";
35733
- const startLine = data.start_line;
35734
- const endLine = data.end_line;
35735
- const totalLines = data.total_lines;
35736
- if (startLine === undefined || endLine === undefined || totalLines === undefined) {
35737
- return "";
35738
- }
35739
- return `
35740
- (Showing lines ${startLine}-${endLine} of ${totalLines}. Use startLine/endLine to read other sections.)`;
35913
+ function formatReadFooter2(agentSpecifiedRange, data) {
35914
+ return formatReadFooter(agentSpecifiedRange, data, { rangeHint: "startLine/endLine" });
35741
35915
  }
35742
35916
  function buildUnifiedDiff(fp, before, after) {
35743
35917
  const beforeLines = before.split(`
@@ -36064,7 +36238,7 @@ function createReadTool(ctx) {
36064
36238
  return permissionDeniedResponse(error50.message);
36065
36239
  return permissionDeniedResponse("Permission denied.");
36066
36240
  }
36067
- const ext = path4.extname(filePath).toLowerCase();
36241
+ const ext = path5.extname(filePath).toLowerCase();
36068
36242
  const mimeMap = {
36069
36243
  ".png": "image/png",
36070
36244
  ".jpg": "image/jpeg",
@@ -36093,7 +36267,7 @@ function createReadTool(ctx) {
36093
36267
  const msg = `${label} read successfully`;
36094
36268
  return {
36095
36269
  output: `${msg} (${ext.slice(1).toUpperCase()}, ${sizeStr}). File: ${filePath}`,
36096
- title: path4.relative(projectRoot, filePath),
36270
+ title: path5.relative(projectRoot, filePath),
36097
36271
  metadata: {
36098
36272
  preview: msg,
36099
36273
  filepath: filePath,
@@ -36135,7 +36309,7 @@ function createReadTool(ctx) {
36135
36309
  }
36136
36310
  let output = data.content;
36137
36311
  const agentSpecifiedRange = args.startLine !== undefined || args.endLine !== undefined || args.offset !== undefined || args.limit !== undefined;
36138
- const footer = formatReadFooter(agentSpecifiedRange, data);
36312
+ const footer = formatReadFooter2(agentSpecifiedRange, data);
36139
36313
  if (footer)
36140
36314
  output += footer;
36141
36315
  return { output, title: dp, metadata: { title: dp } };
@@ -36157,7 +36331,7 @@ function createWriteTool(ctx, editToolName = "edit") {
36157
36331
  const content = args.content;
36158
36332
  const projectRoot = await resolveProjectRoot(ctx, context);
36159
36333
  const filePath = resolvePathFromProjectRoot(projectRoot, file2);
36160
- const relPath = path4.relative(projectRoot, filePath);
36334
+ const relPath = path5.relative(projectRoot, filePath);
36161
36335
  {
36162
36336
  const denial2 = await assertExternalDirectoryPermission(context, filePath);
36163
36337
  if (denial2)
@@ -36308,7 +36482,7 @@ function createEditTool(ctx, writeToolName = "write") {
36308
36482
  throw new Error("'filePath' parameter is required");
36309
36483
  const projectRoot = await resolveProjectRoot(ctx, context);
36310
36484
  const filePath = resolvePathFromProjectRoot(projectRoot, file2);
36311
- const relPath = path4.relative(projectRoot, filePath);
36485
+ const relPath = path5.relative(projectRoot, filePath);
36312
36486
  {
36313
36487
  const denial2 = await assertExternalDirectoryPermission(context, filePath);
36314
36488
  if (denial2)
@@ -36511,22 +36685,34 @@ function createApplyPatchTool(ctx) {
36511
36685
  }
36512
36686
  const projectRoot = await resolveProjectRoot(ctx, context);
36513
36687
  const affectedAbs = new Set;
36688
+ const initiallyExistsAbs = new Map;
36689
+ const rememberAffectedPath = (abs) => {
36690
+ affectedAbs.add(abs);
36691
+ if (!initiallyExistsAbs.has(abs)) {
36692
+ initiallyExistsAbs.set(abs, fs6.existsSync(abs));
36693
+ }
36694
+ };
36695
+ for (const h of hunks) {
36696
+ const srcAbs = resolvePathFromProjectRoot(projectRoot, h.path);
36697
+ rememberAffectedPath(srcAbs);
36698
+ if (h.type === "update" && h.move_path) {
36699
+ rememberAffectedPath(resolvePathFromProjectRoot(projectRoot, h.move_path));
36700
+ }
36701
+ }
36514
36702
  const newlyCreatedAbs = new Set;
36515
36703
  for (const h of hunks) {
36516
36704
  const srcAbs = resolvePathFromProjectRoot(projectRoot, h.path);
36517
- affectedAbs.add(srcAbs);
36518
- if (h.type === "add") {
36705
+ if (h.type === "add" && initiallyExistsAbs.get(srcAbs) === false) {
36519
36706
  newlyCreatedAbs.add(srcAbs);
36520
36707
  }
36521
36708
  if (h.type === "update" && h.move_path) {
36522
36709
  const dstAbs = resolvePathFromProjectRoot(projectRoot, h.move_path);
36523
- affectedAbs.add(dstAbs);
36524
- if (!fs6.existsSync(dstAbs)) {
36710
+ if (initiallyExistsAbs.get(dstAbs) === false) {
36525
36711
  newlyCreatedAbs.add(dstAbs);
36526
36712
  }
36527
36713
  }
36528
36714
  }
36529
- const relPaths = Array.from(affectedAbs).map((abs) => path4.relative(projectRoot, abs));
36715
+ const relPaths = Array.from(affectedAbs).map((abs) => path5.relative(projectRoot, abs));
36530
36716
  const multiFileWritePaths = Array.from(affectedAbs);
36531
36717
  {
36532
36718
  const asked = new Set;
@@ -36560,15 +36746,15 @@ function createApplyPatchTool(ctx) {
36560
36746
  }
36561
36747
  const results = [];
36562
36748
  const failures = [];
36563
- const perFileDiffs = [];
36564
- for (const hunk of hunks) {
36749
+ const appliedHunkResults = [];
36750
+ for (const [hunkIndex, hunk] of hunks.entries()) {
36565
36751
  const filePath = resolvePathFromProjectRoot(projectRoot, hunk.path);
36566
36752
  switch (hunk.type) {
36567
36753
  case "add": {
36568
36754
  if (fs6.existsSync(filePath)) {
36569
36755
  const msg = `Failed to create ${hunk.path}: file already exists. Use *** Update File: to modify, or *** Delete File: first if you want to replace it entirely.`;
36570
36756
  results.push(msg);
36571
- failures.push(hunk.path);
36757
+ failures.push({ index: hunkIndex, path: hunk.path });
36572
36758
  break;
36573
36759
  }
36574
36760
  try {
@@ -36590,10 +36776,13 @@ function createApplyPatchTool(ctx) {
36590
36776
  throw new Error("produced invalid syntax (rolled back)");
36591
36777
  }
36592
36778
  const wrDiff = writeResult.diff;
36593
- perFileDiffs.push({
36779
+ appliedHunkResults.push({
36780
+ index: hunkIndex,
36781
+ hunk,
36594
36782
  filePath,
36783
+ displayPath: filePath,
36595
36784
  before: "",
36596
- after: hunk.contents,
36785
+ after: content,
36597
36786
  additions: wrDiff?.additions ?? lineCount(content),
36598
36787
  deletions: wrDiff?.deletions ?? 0
36599
36788
  });
@@ -36601,7 +36790,7 @@ function createApplyPatchTool(ctx) {
36601
36790
  } catch (e) {
36602
36791
  const msg = `Failed to create ${hunk.path}: ${e instanceof Error ? e.message : e}`;
36603
36792
  results.push(msg);
36604
- failures.push(hunk.path);
36793
+ failures.push({ index: hunkIndex, path: hunk.path });
36605
36794
  const filePath2 = resolvePathFromProjectRoot(projectRoot, hunk.path);
36606
36795
  if (fs6.existsSync(filePath2)) {
36607
36796
  try {
@@ -36620,8 +36809,11 @@ function createApplyPatchTool(ctx) {
36620
36809
  if (deleteResult.success === false) {
36621
36810
  throw new Error(deleteResult.message ?? "delete failed");
36622
36811
  }
36623
- perFileDiffs.push({
36812
+ appliedHunkResults.push({
36813
+ index: hunkIndex,
36814
+ hunk,
36624
36815
  filePath,
36816
+ displayPath: filePath,
36625
36817
  before,
36626
36818
  after: "",
36627
36819
  additions: 0,
@@ -36630,7 +36822,7 @@ function createApplyPatchTool(ctx) {
36630
36822
  results.push(`Deleted ${hunk.path}`);
36631
36823
  } catch (e) {
36632
36824
  results.push(`Failed to delete ${hunk.path}: ${e instanceof Error ? e.message : e}`);
36633
- failures.push(hunk.path);
36825
+ failures.push({ index: hunkIndex, path: hunk.path });
36634
36826
  }
36635
36827
  break;
36636
36828
  }
@@ -36657,7 +36849,7 @@ function createApplyPatchTool(ctx) {
36657
36849
  if (diags && diags.length > 0) {
36658
36850
  const errors3 = diags.filter((d) => d.severity === "error");
36659
36851
  if (errors3.length > 0) {
36660
- const relPath = path4.relative(projectRoot, targetPath);
36852
+ const relPath = path5.relative(projectRoot, targetPath);
36661
36853
  const diagLines = errors3.map((d) => ` Line ${d.line}: ${d.message}`).join(`
36662
36854
  `);
36663
36855
  results.push(`
@@ -36671,13 +36863,17 @@ ${diagLines}`);
36671
36863
  additions: wrDiff.additions,
36672
36864
  deletions: wrDiff.deletions
36673
36865
  };
36674
- perFileDiffs.push({
36866
+ const appliedHunkResult = {
36867
+ index: hunkIndex,
36868
+ hunk,
36675
36869
  filePath,
36870
+ displayPath: targetPath,
36871
+ ...hunk.move_path ? { movePath: targetPath } : {},
36676
36872
  before: original,
36677
36873
  after: newContent,
36678
36874
  additions,
36679
36875
  deletions
36680
- });
36876
+ };
36681
36877
  if (hunk.move_path) {
36682
36878
  try {
36683
36879
  const deleteResult = await callBridge(ctx, context, "delete_file", {
@@ -36710,13 +36906,15 @@ ${diagLines}`);
36710
36906
  }
36711
36907
  throw new Error(`source delete failed after writing move destination; restored pre-patch checkpoint ${checkpointName}: ${formatError2(deleteError)}`);
36712
36908
  }
36909
+ appliedHunkResults.push(appliedHunkResult);
36713
36910
  results.push(`Updated and moved ${hunk.path} → ${hunk.move_path}`);
36714
36911
  } else {
36912
+ appliedHunkResults.push(appliedHunkResult);
36715
36913
  results.push(`Updated ${hunk.path}`);
36716
36914
  }
36717
36915
  } catch (e) {
36718
36916
  results.push(`Failed to update ${hunk.path}: ${e instanceof Error ? e.message : e}`);
36719
- failures.push(hunk.path);
36917
+ failures.push({ index: hunkIndex, path: hunk.path });
36720
36918
  break;
36721
36919
  }
36722
36920
  break;
@@ -36725,7 +36923,8 @@ ${diagLines}`);
36725
36923
  }
36726
36924
  if (failures.length > 0) {
36727
36925
  const partial2 = failures.length < hunks.length;
36728
- const summary = partial2 ? `Patch partially applied — ${hunks.length - failures.length} of ${hunks.length} hunk(s) succeeded. Failed: ${failures.join(", ")}. Successful changes are kept; use \`aft_safety\` to revert if you want to abort.` : `Patch failed — none of the ${hunks.length} hunk(s) applied: ${failures.join(", ")}.`;
36926
+ const failedList = failures.map((failure) => failure.path).join(", ");
36927
+ const summary = partial2 ? `Patch partially applied — ${hunks.length - failures.length} of ${hunks.length} hunk(s) succeeded. Failed: ${failedList}. Successful changes are kept; use \`aft_safety\` to revert if you want to abort.` : `Patch failed — none of the ${hunks.length} hunk(s) applied: ${failedList}.`;
36729
36928
  results.push(summary);
36730
36929
  if (!partial2) {
36731
36930
  throw new Error(results.join(`
@@ -36733,28 +36932,56 @@ ${diagLines}`);
36733
36932
  }
36734
36933
  }
36735
36934
  {
36736
- const diffByPath = new Map(perFileDiffs.map((d) => [d.filePath, d]));
36737
- const failedPaths = new Set(failures);
36738
- const appliedHunks = hunks.filter((h) => !failedPaths.has(h.path));
36739
- const files = appliedHunks.map((h) => {
36740
- const filePath = resolvePathFromProjectRoot(projectRoot, h.path);
36741
- const rawMovePath = h.type === "update" ? h.move_path : undefined;
36742
- const movePath = rawMovePath ? resolvePathFromProjectRoot(projectRoot, rawMovePath) : undefined;
36743
- const displayPath = movePath ?? filePath;
36744
- const relPath = path4.relative(projectRoot, displayPath);
36745
- const diffEntry = diffByPath.get(filePath);
36746
- const patch = diffEntry ? buildUnifiedDiff(displayPath, diffEntry.before, diffEntry.after) : "";
36747
- const additions = diffEntry?.additions ?? 0;
36748
- const deletions = diffEntry?.deletions ?? 0;
36749
- const uiType = h.type === "update" && rawMovePath ? "move" : h.type;
36935
+ const diffByReportKey = new Map;
36936
+ for (const applied of appliedHunkResults) {
36937
+ const reportKey = applied.movePath ? `${applied.filePath}\x00${applied.displayPath}` : applied.filePath;
36938
+ const existing = diffByReportKey.get(reportKey);
36939
+ if (!existing) {
36940
+ diffByReportKey.set(reportKey, {
36941
+ filePath: applied.filePath,
36942
+ displayPath: applied.displayPath,
36943
+ ...applied.movePath ? { movePath: applied.movePath } : {},
36944
+ lastHunk: applied.hunk,
36945
+ before: applied.before,
36946
+ after: applied.after,
36947
+ additions: applied.additions,
36948
+ deletions: applied.deletions,
36949
+ hunkCount: 1
36950
+ });
36951
+ continue;
36952
+ }
36953
+ existing.displayPath = applied.displayPath;
36954
+ existing.movePath = applied.movePath ?? existing.movePath;
36955
+ existing.lastHunk = applied.hunk;
36956
+ existing.after = applied.after;
36957
+ existing.hunkCount += 1;
36958
+ const netCounts = countDiffLines(existing.before, existing.after);
36959
+ existing.additions = netCounts.additions;
36960
+ existing.deletions = netCounts.deletions;
36961
+ }
36962
+ const files = Array.from(diffByReportKey.values()).map((entry) => {
36963
+ const relPath = path5.relative(projectRoot, entry.displayPath);
36964
+ const patch = buildUnifiedDiff(entry.displayPath, entry.before, entry.after);
36965
+ let uiType;
36966
+ if (entry.movePath) {
36967
+ uiType = "move";
36968
+ } else if (entry.hunkCount === 1) {
36969
+ uiType = entry.lastHunk.type;
36970
+ } else if (entry.before.length === 0 && entry.after.length > 0) {
36971
+ uiType = "add";
36972
+ } else if (entry.before.length > 0 && entry.after.length === 0) {
36973
+ uiType = "delete";
36974
+ } else {
36975
+ uiType = "update";
36976
+ }
36750
36977
  return {
36751
- filePath,
36978
+ filePath: entry.filePath,
36752
36979
  relativePath: relPath,
36753
36980
  type: uiType,
36754
36981
  patch,
36755
- additions,
36756
- deletions,
36757
- ...movePath ? { movePath } : {}
36982
+ additions: entry.additions,
36983
+ deletions: entry.deletions,
36984
+ ...entry.movePath ? { movePath: entry.movePath } : {}
36758
36985
  };
36759
36986
  });
36760
36987
  const fileList = files.map((f) => {
@@ -36762,7 +36989,7 @@ ${diagLines}`);
36762
36989
  return `${prefix} ${f.relativePath}`;
36763
36990
  }).join(`
36764
36991
  `);
36765
- const title = failures.length > 0 ? `Partially applied (${files.length} of ${hunks.length}). Updated:
36992
+ const title = failures.length > 0 ? `Partially applied (${hunks.length - failures.length} of ${hunks.length}). Updated:
36766
36993
  ${fileList}` : `Success. Updated the following files:
36767
36994
  ${fileList}`;
36768
36995
  const diffText = files.map((f) => f.patch).filter(Boolean).join(`
@@ -36915,7 +37142,7 @@ function aftPrefixedTools(ctx) {
36915
37142
  const file2 = normalizedArgs.filePath;
36916
37143
  const projectRoot = await resolveProjectRoot(ctx, context);
36917
37144
  const filePath = resolvePathFromProjectRoot(projectRoot, file2);
36918
- const relPath = path4.relative(projectRoot, filePath);
37145
+ const relPath = path5.relative(projectRoot, filePath);
36919
37146
  {
36920
37147
  const denial2 = await assertExternalDirectoryPermission(context, filePath);
36921
37148
  if (denial2)
@@ -37312,15 +37539,15 @@ function buildZoomTitle(args) {
37312
37539
  }
37313
37540
  return `${args.targets.filePath}#${args.targets.symbol}`;
37314
37541
  }
37315
- const path5 = args.filePath ?? args.url ?? "";
37542
+ const path6 = args.filePath ?? args.url ?? "";
37316
37543
  if (typeof args.symbols === "string")
37317
- return path5 ? `${path5}#${args.symbols}` : args.symbols;
37544
+ return path6 ? `${path6}#${args.symbols}` : args.symbols;
37318
37545
  if (Array.isArray(args.symbols) && args.symbols.length > 0) {
37319
37546
  if (args.symbols.length === 1)
37320
- return path5 ? `${path5}#${args.symbols[0]}` : args.symbols[0];
37321
- return path5 ? `${path5} (${args.symbols.length} symbols)` : `${args.symbols.length} symbols`;
37547
+ return path6 ? `${path6}#${args.symbols[0]}` : args.symbols[0];
37548
+ return path6 ? `${path6} (${args.symbols.length} symbols)` : `${args.symbols.length} symbols`;
37322
37549
  }
37323
- return path5 || "(no target)";
37550
+ return path6 || "(no target)";
37324
37551
  }
37325
37552
  function readingTools(ctx) {
37326
37553
  return {
@@ -37553,6 +37780,11 @@ function readingTools(ctx) {
37553
37780
  }));
37554
37781
  if (symbolsArray.length === 1) {
37555
37782
  const response = results[0] ?? { success: false, message: "missing zoom response" };
37783
+ const rustBatch = unwrapRustZoomBatchEnvelope(response);
37784
+ if (rustBatch) {
37785
+ const batch = formatZoomBatchResult(targetLabel, rustBatch.names, rustBatch.responses);
37786
+ return withMeta(batch.text);
37787
+ }
37556
37788
  if (response.success === false) {
37557
37789
  throw new Error(response.message || "zoom failed");
37558
37790
  }
@@ -37821,11 +38053,11 @@ function refactoringTools(ctx) {
37821
38053
  }
37822
38054
 
37823
38055
  // src/tools/safety.ts
37824
- import * as path5 from "node:path";
38056
+ import * as path6 from "node:path";
37825
38057
  import { tool as tool14 } from "@opencode-ai/plugin";
37826
38058
  var z14 = tool14.schema;
37827
38059
  function responsePaths(response) {
37828
- return Array.isArray(response.paths) ? response.paths.filter((path6) => typeof path6 === "string" && path6.length > 0) : [];
38060
+ return Array.isArray(response.paths) ? response.paths.filter((path7) => typeof path7 === "string" && path7.length > 0) : [];
37829
38061
  }
37830
38062
  function bridgeErrorMessage(response, fallback) {
37831
38063
  return typeof response.message === "string" && response.message.length > 0 ? response.message : fallback;
@@ -37902,9 +38134,9 @@ function safetyTools(ctx) {
37902
38134
  for (const rawFile of checkpointFiles) {
37903
38135
  if (typeof rawFile !== "string")
37904
38136
  continue;
37905
- const file2 = expandTilde(rawFile);
37906
- const abs = path5.isAbsolute(file2) ? file2 : path5.resolve(projectRoot, file2);
37907
- const parent = path5.dirname(abs);
38137
+ const file2 = expandTilde2(rawFile);
38138
+ const abs = path6.isAbsolute(file2) ? file2 : path6.resolve(projectRoot, file2);
38139
+ const parent = path6.dirname(abs);
37908
38140
  if (uniqueParents.has(parent))
37909
38141
  continue;
37910
38142
  uniqueParents.add(parent);
@@ -37942,8 +38174,8 @@ function safetyTools(ctx) {
37942
38174
  const params = {};
37943
38175
  if (args.name !== undefined)
37944
38176
  params.name = args.name;
37945
- const payloadFiles = coerceStringArray(args.files).map(expandTilde);
37946
- const filePathArg = typeof args.filePath === "string" ? expandTilde(args.filePath) : undefined;
38177
+ const payloadFiles = coerceStringArray(args.files).map(expandTilde2);
38178
+ const filePathArg = typeof args.filePath === "string" ? expandTilde2(args.filePath) : undefined;
37947
38179
  if (op === "checkpoint") {
37948
38180
  if (payloadFiles.length > 0) {
37949
38181
  params.files = payloadFiles;
@@ -37968,7 +38200,7 @@ function safetyTools(ctx) {
37968
38200
 
37969
38201
  // src/tools/search.ts
37970
38202
  import * as fs7 from "node:fs";
37971
- import * as path6 from "node:path";
38203
+ import * as path7 from "node:path";
37972
38204
  function arg2(schema) {
37973
38205
  return schema;
37974
38206
  }
@@ -38000,20 +38232,49 @@ function normalizeGlob(pattern) {
38000
38232
  return pattern;
38001
38233
  }
38002
38234
  function absoluteSearchPath(projectRoot, target) {
38003
- return resolvePathFromProjectRoot(projectRoot, expandTilde(target));
38235
+ return resolvePathFromProjectRoot(projectRoot, expandTilde2(target));
38004
38236
  }
38005
38237
  function searchPathExists(projectRoot, target) {
38006
38238
  return fs7.existsSync(absoluteSearchPath(projectRoot, target));
38007
38239
  }
38008
38240
  function splitSearchPathArg(projectRoot, raw) {
38009
38241
  if (searchPathExists(projectRoot, raw) || !/\s/.test(raw)) {
38010
- return [raw];
38242
+ return { paths: [raw], missing: [] };
38011
38243
  }
38012
38244
  const fragments = raw.trim().split(/\s+/).filter(Boolean);
38013
- if (fragments.length < 2 || !fragments.every((fragment) => searchPathExists(projectRoot, fragment))) {
38014
- return [raw];
38245
+ if (fragments.length < 2) {
38246
+ return { paths: [raw], missing: [] };
38247
+ }
38248
+ const existing = [];
38249
+ const missing = [];
38250
+ for (const fragment of fragments) {
38251
+ if (searchPathExists(projectRoot, fragment)) {
38252
+ existing.push(fragment);
38253
+ } else {
38254
+ missing.push(fragment);
38255
+ }
38015
38256
  }
38016
- return fragments;
38257
+ if (existing.length === 0) {
38258
+ return { paths: [raw], missing: [] };
38259
+ }
38260
+ return { paths: existing, missing };
38261
+ }
38262
+ function bridgeSearchPathArg(projectRoot, split) {
38263
+ return split.paths.map((target) => absoluteSearchPath(projectRoot, target)).join(" ");
38264
+ }
38265
+ function formatSkippedSearchPaths(missing) {
38266
+ if (missing.length === 0)
38267
+ return;
38268
+ const noun = missing.length === 1 ? "path" : "paths";
38269
+ return `Skipped ${missing.length} ${noun} not found: ${missing.join(", ")}`;
38270
+ }
38271
+ function appendSkippedSearchPaths(text, missing) {
38272
+ const note = formatSkippedSearchPaths(missing);
38273
+ if (!note)
38274
+ return text;
38275
+ return text.length > 0 ? `${text}
38276
+
38277
+ ${note}` : note;
38017
38278
  }
38018
38279
  function searchPathKind(projectRoot, target, defaultKind) {
38019
38280
  try {
@@ -38026,8 +38287,8 @@ function searchPathKind(projectRoot, target, defaultKind) {
38026
38287
  return defaultKind;
38027
38288
  }
38028
38289
  }
38029
- function searchPathTargets(projectRoot, raw, defaultKind) {
38030
- return splitSearchPathArg(projectRoot, raw).map((target) => {
38290
+ function searchPathTargets(projectRoot, split, defaultKind) {
38291
+ return split.paths.map((target) => {
38031
38292
  const absoluteTarget = absoluteSearchPath(projectRoot, target);
38032
38293
  return {
38033
38294
  target: absoluteTarget,
@@ -38077,16 +38338,17 @@ function searchTools(ctx) {
38077
38338
  const projectRoot = await resolveProjectRoot(ctx, context);
38078
38339
  const pattern = String(args.pattern);
38079
38340
  const includeArg = args.include ? String(args.include) : undefined;
38080
- const pathArg = args.path ? expandTilde(String(args.path)) : undefined;
38081
- const bridgePath = pathArg ? absoluteSearchPath(projectRoot, pathArg) : undefined;
38341
+ const pathArg = args.path ? String(args.path) : undefined;
38342
+ const pathSplit = pathArg ? splitSearchPathArg(projectRoot, pathArg) : undefined;
38343
+ const bridgePath = pathSplit ? bridgeSearchPathArg(projectRoot, pathSplit) : undefined;
38082
38344
  const grepDenied = await askGrepPermission(context, pattern, {
38083
38345
  path: bridgePath,
38084
38346
  include: includeArg
38085
38347
  });
38086
38348
  if (grepDenied)
38087
38349
  return permissionDeniedResponse(grepDenied);
38088
- if (pathArg) {
38089
- for (const target of searchPathTargets(projectRoot, pathArg, "file")) {
38350
+ if (pathSplit) {
38351
+ for (const target of searchPathTargets(projectRoot, pathSplit, "file")) {
38090
38352
  const externalDenied = await assertExternalDirectoryPermission(context, target.target, {
38091
38353
  kind: target.kind
38092
38354
  });
@@ -38104,7 +38366,10 @@ function searchTools(ctx) {
38104
38366
  if (response.success === false) {
38105
38367
  throw new Error(response.message || "grep failed");
38106
38368
  }
38107
- return formatGrepOutput(response);
38369
+ if (pathSplit && pathSplit.missing.length > 0) {
38370
+ response.complete = false;
38371
+ }
38372
+ return appendSkippedSearchPaths(formatGrepOutput(response), pathSplit?.missing ?? []);
38108
38373
  }
38109
38374
  };
38110
38375
  const globTool = {
@@ -38115,8 +38380,8 @@ function searchTools(ctx) {
38115
38380
  },
38116
38381
  execute: async (args, context) => {
38117
38382
  const projectRoot = await resolveProjectRoot(ctx, context);
38118
- let globPattern = expandTilde(String(args.pattern));
38119
- let globPath = args.path ? expandTilde(String(args.path)) : undefined;
38383
+ let globPattern = expandTilde2(String(args.pattern));
38384
+ let globPath = args.path ? String(args.path) : undefined;
38120
38385
  if (!globPath && globPattern.startsWith("/")) {
38121
38386
  const metaIdx = globPattern.search(/[*?{}[\]]/);
38122
38387
  if (metaIdx > 0) {
@@ -38126,16 +38391,17 @@ function searchTools(ctx) {
38126
38391
  globPattern = `**/${globPattern.slice(lastSlash + 1)}`;
38127
38392
  }
38128
38393
  } else if (metaIdx === -1) {
38129
- globPath = path6.dirname(globPattern);
38130
- globPattern = path6.basename(globPattern);
38394
+ globPath = path7.dirname(globPattern);
38395
+ globPattern = path7.basename(globPattern);
38131
38396
  }
38132
38397
  }
38133
- const globDenied = await askGlobPermission(context, globPattern, { path: globPath });
38398
+ const pathSplit = globPath ? splitSearchPathArg(projectRoot, globPath) : undefined;
38399
+ const bridgePath = pathSplit ? bridgeSearchPathArg(projectRoot, pathSplit) : undefined;
38400
+ const globDenied = await askGlobPermission(context, globPattern, { path: bridgePath });
38134
38401
  if (globDenied)
38135
38402
  return permissionDeniedResponse(globDenied);
38136
- const bridgePath = globPath ? absoluteSearchPath(projectRoot, globPath) : undefined;
38137
- if (globPath) {
38138
- for (const target of searchPathTargets(projectRoot, globPath, "directory")) {
38403
+ if (pathSplit) {
38404
+ for (const target of searchPathTargets(projectRoot, pathSplit, "directory")) {
38139
38405
  const externalDenied = await assertExternalDirectoryPermission(context, target.target, {
38140
38406
  kind: target.kind
38141
38407
  });
@@ -38150,14 +38416,17 @@ function searchTools(ctx) {
38150
38416
  if (response.success === false) {
38151
38417
  throw new Error(response.message || "glob failed");
38152
38418
  }
38419
+ if (pathSplit && pathSplit.missing.length > 0) {
38420
+ response.complete = false;
38421
+ }
38153
38422
  if (typeof response.text === "string") {
38154
- return response.text;
38423
+ return appendSkippedSearchPaths(response.text, pathSplit?.missing ?? []);
38155
38424
  }
38156
38425
  if (Array.isArray(response.files)) {
38157
- return response.files.join(`
38158
- `);
38426
+ return appendSkippedSearchPaths(response.files.join(`
38427
+ `), pathSplit?.missing ?? []);
38159
38428
  }
38160
- return response.text || JSON.stringify(response);
38429
+ return appendSkippedSearchPaths(response.text || JSON.stringify(response), pathSplit?.missing ?? []);
38161
38430
  }
38162
38431
  };
38163
38432
  const hoisting = ctx.config.hoist_builtin_tools !== false;
@@ -38472,6 +38741,7 @@ ${lines}
38472
38741
  }
38473
38742
  const versionUpgradePromises = new Map;
38474
38743
  const poolOptions = {
38744
+ ...resolveBridgePoolTransportOptions(aftConfig),
38475
38745
  errorPrefix: "[aft-plugin]",
38476
38746
  minVersion: PLUGIN_VERSION,
38477
38747
  projectConfigLoader: (projectRoot) => {
@@ -38492,13 +38762,13 @@ ${lines}
38492
38762
  const upgradePromise = (async () => {
38493
38763
  warn2(`WARNING: aft binary v${binaryVersion} is older than plugin v${minVersion}. ` + "Some features may not work. Attempting to download a compatible binary...");
38494
38764
  try {
38495
- const path7 = await ensureBinary(`v${minVersion}`);
38496
- if (!path7) {
38765
+ const path8 = await ensureBinary(`v${minVersion}`);
38766
+ if (!path8) {
38497
38767
  warn2(`Could not find or download v${minVersion}. Continuing with v${binaryVersion}.`);
38498
38768
  return null;
38499
38769
  }
38500
- log2(`Found/downloaded compatible binary at ${path7}. Replacing running bridges...`);
38501
- const replaced = await pool.replaceBinary(path7);
38770
+ log2(`Found/downloaded compatible binary at ${path8}. Replacing running bridges...`);
38771
+ const replaced = await pool.replaceBinary(path8);
38502
38772
  log2("Binary replaced successfully. New bridges will use the updated binary.");
38503
38773
  return replaced;
38504
38774
  } catch (err) {