@cortexkit/aft-pi 0.26.4 → 0.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -8301,11 +8301,11 @@ var require_fixed_queue = __commonJS((exports, module) => {
8301
8301
  this.head.push(data);
8302
8302
  }
8303
8303
  shift() {
8304
- const tail = this.tail;
8305
- const next = tail.shift();
8306
- if (tail.isEmpty() && tail.next !== null) {
8307
- this.tail = tail.next;
8308
- tail.next = null;
8304
+ const tail2 = this.tail;
8305
+ const next = tail2.shift();
8306
+ if (tail2.isEmpty() && tail2.next !== null) {
8307
+ this.tail = tail2.next;
8308
+ tail2.next = null;
8309
8309
  }
8310
8310
  return next;
8311
8311
  }
@@ -12716,7 +12716,7 @@ var require_snapshot_utils = __commonJS((exports, module) => {
12716
12716
  // ../../node_modules/.bun/undici@8.2.0/node_modules/undici/lib/mock/snapshot-recorder.js
12717
12717
  var require_snapshot_recorder = __commonJS((exports, module) => {
12718
12718
  var { writeFile, readFile, mkdir } = __require("node:fs/promises");
12719
- var { dirname: dirname2, resolve: resolve2 } = __require("node:path");
12719
+ var { dirname: dirname3, resolve: resolve2 } = __require("node:path");
12720
12720
  var { setTimeout: setTimeout2, clearTimeout: clearTimeout2 } = __require("node:timers");
12721
12721
  var { InvalidArgumentError, UndiciError } = require_errors();
12722
12722
  var { hashId, isUrlExcludedFactory, normalizeHeaders, createHeaderFilters } = require_snapshot_utils();
@@ -12911,7 +12911,7 @@ var require_snapshot_recorder = __commonJS((exports, module) => {
12911
12911
  throw new InvalidArgumentError("Snapshot path is required");
12912
12912
  }
12913
12913
  const resolvedPath = resolve2(path);
12914
- await mkdir(dirname2(resolvedPath), { recursive: true });
12914
+ await mkdir(dirname3(resolvedPath), { recursive: true });
12915
12915
  const data = Array.from(this.#snapshots.entries()).map(([hash, snapshot]) => ({
12916
12916
  hash,
12917
12917
  snapshot
@@ -20784,7 +20784,7 @@ var require_permessage_deflate = __commonJS((exports, module) => {
20784
20784
  var { createInflateRaw, Z_DEFAULT_WINDOWBITS } = __require("node:zlib");
20785
20785
  var { isValidClientWindowBits } = require_util5();
20786
20786
  var { MessageSizeExceededError } = require_errors();
20787
- var tail = Buffer.from([0, 0, 255, 255]);
20787
+ var tail2 = Buffer.from([0, 0, 255, 255]);
20788
20788
  var kBuffer = Symbol("kBuffer");
20789
20789
  var kLength = Symbol("kLength");
20790
20790
 
@@ -20832,7 +20832,7 @@ var require_permessage_deflate = __commonJS((exports, module) => {
20832
20832
  }
20833
20833
  this.#inflate.write(chunk);
20834
20834
  if (fin) {
20835
- this.#inflate.write(tail);
20835
+ this.#inflate.write(tail2);
20836
20836
  }
20837
20837
  this.#inflate.flush(() => {
20838
20838
  if (!this.#inflate) {
@@ -24197,10 +24197,10 @@ var require_esprima = __commonJS((exports, module) => {
24197
24197
  }();
24198
24198
  exports2.TaggedTemplateExpression = TaggedTemplateExpression;
24199
24199
  var TemplateElement = function() {
24200
- function TemplateElement2(value, tail) {
24200
+ function TemplateElement2(value, tail2) {
24201
24201
  this.type = syntax_1.Syntax.TemplateElement;
24202
24202
  this.value = value;
24203
- this.tail = tail;
24203
+ this.tail = tail2;
24204
24204
  }
24205
24205
  return TemplateElement2;
24206
24206
  }();
@@ -28040,14 +28040,14 @@ var require_esprima = __commonJS((exports, module) => {
28040
28040
  var terminated = false;
28041
28041
  var start = this.index;
28042
28042
  var head = this.source[start] === "`";
28043
- var tail = false;
28043
+ var tail2 = false;
28044
28044
  var rawOffset = 2;
28045
28045
  ++this.index;
28046
28046
  while (!this.eof()) {
28047
28047
  var ch = this.source[this.index++];
28048
28048
  if (ch === "`") {
28049
28049
  rawOffset = 1;
28050
- tail = true;
28050
+ tail2 = true;
28051
28051
  terminated = true;
28052
28052
  break;
28053
28053
  } else if (ch === "$") {
@@ -28148,7 +28148,7 @@ var require_esprima = __commonJS((exports, module) => {
28148
28148
  value: this.source.slice(start + 1, this.index - rawOffset),
28149
28149
  cooked,
28150
28150
  head,
28151
- tail,
28151
+ tail: tail2,
28152
28152
  lineNumber: this.lineNumber,
28153
28153
  lineStart: this.lineStart,
28154
28154
  start,
@@ -30318,10 +30318,10 @@ var require_stringify = __commonJS((exports, module) => {
30318
30318
  replacer = null;
30319
30319
  indent = EMPTY;
30320
30320
  };
30321
- var join7 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(one)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two)), gap) : EMPTY;
30321
+ var join8 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(one)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two)), gap) : EMPTY;
30322
30322
  var join_content = (inside, value, gap) => {
30323
30323
  const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
30324
- return join7(comment, inside, gap);
30324
+ return join8(comment, inside, gap);
30325
30325
  };
30326
30326
  var stringify_string = (holder, key, value) => {
30327
30327
  const raw = get_raw_string_literal(holder, key);
@@ -30343,13 +30343,13 @@ var require_stringify = __commonJS((exports, module) => {
30343
30343
  if (i !== 0) {
30344
30344
  inside += COMMA;
30345
30345
  }
30346
- const before = join7(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
30346
+ const before = join8(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
30347
30347
  inside += before || LF + deeper_gap;
30348
30348
  inside += stringify(i, value, deeper_gap) || STR_NULL;
30349
30349
  inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
30350
30350
  after_comma = process_comments(value, AFTER(i), deeper_gap);
30351
30351
  }
30352
- inside += join7(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
30352
+ inside += join8(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
30353
30353
  return BRACKET_OPEN + join_content(inside, value, gap) + BRACKET_CLOSE;
30354
30354
  };
30355
30355
  var object_stringify = (value, gap) => {
@@ -30370,13 +30370,13 @@ var require_stringify = __commonJS((exports, module) => {
30370
30370
  inside += COMMA;
30371
30371
  }
30372
30372
  first = false;
30373
- const before = join7(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
30373
+ const before = join8(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
30374
30374
  inside += before || LF + deeper_gap;
30375
30375
  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);
30376
30376
  after_comma = process_comments(value, AFTER(key), deeper_gap);
30377
30377
  };
30378
30378
  keys.forEach(iteratee);
30379
- inside += join7(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
30379
+ inside += join8(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
30380
30380
  return CURLY_BRACKET_OPEN + join_content(inside, value, gap) + CURLY_BRACKET_CLOSE;
30381
30381
  };
30382
30382
  function stringify(key, holder, gap) {
@@ -30475,8 +30475,6 @@ var require_src2 = __commonJS((exports, module) => {
30475
30475
 
30476
30476
  // src/index.ts
30477
30477
  import { createRequire as createRequire3 } from "node:module";
30478
- import { homedir as homedir9 } from "node:os";
30479
- import { join as join13 } from "node:path";
30480
30478
 
30481
30479
  // ../aft-bridge/dist/active-logger.js
30482
30480
  var ACTIVE_LOGGER_SYMBOL = Symbol.for("aft-bridge-active-logger");
@@ -31501,11 +31499,295 @@ async function fetchLatestTag() {
31501
31499
  clearTimeout(timeout);
31502
31500
  }
31503
31501
  }
31502
+ // ../aft-bridge/dist/format.js
31503
+ function compressionSavingsPercent(original, compressed) {
31504
+ if (original <= 0)
31505
+ return null;
31506
+ const saved = Math.max(0, original - compressed);
31507
+ return Math.round(saved / original * 100);
31508
+ }
31509
+ // ../aft-bridge/dist/migration.js
31510
+ import { spawnSync as spawnSync2 } from "node:child_process";
31511
+ import { existsSync as existsSync3, mkdirSync as mkdirSync3 } from "node:fs";
31512
+ import { homedir as homedir4, tmpdir } from "node:os";
31513
+ import { dirname, join as join4 } from "node:path";
31514
+
31515
+ // ../aft-bridge/dist/resolver.js
31516
+ import { execSync, spawnSync } from "node:child_process";
31517
+ import { chmodSync as chmodSync2, copyFileSync, existsSync as existsSync2, mkdirSync as mkdirSync2, renameSync as renameSync2 } from "node:fs";
31518
+ import { createRequire as createRequire2 } from "node:module";
31519
+ import { homedir as homedir3 } from "node:os";
31520
+ import { join as join3 } from "node:path";
31521
+ function readBinaryVersion(binaryPath) {
31522
+ try {
31523
+ const result = spawnSync(binaryPath, ["--version"], {
31524
+ encoding: "utf-8",
31525
+ stdio: ["pipe", "pipe", "pipe"],
31526
+ timeout: 5000
31527
+ });
31528
+ const stdoutVersion = result.stdout?.trim();
31529
+ const stderrVersion = result.stderr?.trim();
31530
+ const rawVersion = stdoutVersion || stderrVersion;
31531
+ if (!rawVersion)
31532
+ return null;
31533
+ return rawVersion.replace(/^aft\s+/, "");
31534
+ } catch {
31535
+ return null;
31536
+ }
31537
+ }
31538
+ function copyToVersionedCache(npmBinaryPath, knownVersion) {
31539
+ try {
31540
+ const version = knownVersion ?? readBinaryVersion(npmBinaryPath);
31541
+ if (!version)
31542
+ return null;
31543
+ const tag = version.startsWith("v") ? version : `v${version}`;
31544
+ const cacheDir = getCacheDir();
31545
+ const versionedDir = join3(cacheDir, tag);
31546
+ const ext = process.platform === "win32" ? ".exe" : "";
31547
+ const cachedPath = join3(versionedDir, `aft${ext}`);
31548
+ if (existsSync2(cachedPath)) {
31549
+ const cachedVersion = readBinaryVersion(cachedPath);
31550
+ if (cachedVersion === version)
31551
+ return cachedPath;
31552
+ warn(`Cached binary at ${cachedPath} reports ${cachedVersion ?? "no version"}, expected ${version}; refreshing from npm package`);
31553
+ }
31554
+ mkdirSync2(versionedDir, { recursive: true });
31555
+ const tmpPath = `${cachedPath}.${process.pid}.${Date.now()}.tmp`;
31556
+ copyFileSync(npmBinaryPath, tmpPath);
31557
+ if (process.platform !== "win32") {
31558
+ chmodSync2(tmpPath, 493);
31559
+ }
31560
+ renameSync2(tmpPath, cachedPath);
31561
+ log(`Copied npm binary to versioned cache: ${cachedPath}`);
31562
+ return cachedPath;
31563
+ } catch (err) {
31564
+ warn(`Failed to copy binary to cache: ${err instanceof Error ? err.message : String(err)}`);
31565
+ return null;
31566
+ }
31567
+ }
31568
+ function normalizeBareVersion(version) {
31569
+ return version.startsWith("v") ? version.slice(1) : version;
31570
+ }
31571
+ function homeDirFromEnv(env) {
31572
+ return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir3();
31573
+ }
31574
+ function cacheDirFromEnv(env) {
31575
+ if (process.platform === "win32") {
31576
+ const base2 = env.LOCALAPPDATA || env.APPDATA || join3(homeDirFromEnv(env), "AppData", "Local");
31577
+ return join3(base2, "aft", "bin");
31578
+ }
31579
+ const base = env.XDG_CACHE_HOME || join3(homeDirFromEnv(env), ".cache");
31580
+ return join3(base, "aft", "bin");
31581
+ }
31582
+ function cachedBinaryPathFromEnv(version, env, ext) {
31583
+ const binaryPath = join3(cacheDirFromEnv(env), version, `aft${ext}`);
31584
+ return existsSync2(binaryPath) ? binaryPath : null;
31585
+ }
31586
+ function isExpectedCachedBinary(binaryPath, expectedVersion) {
31587
+ const expected = normalizeBareVersion(expectedVersion);
31588
+ const actual = readBinaryVersion(binaryPath);
31589
+ if (actual === expected)
31590
+ return true;
31591
+ warn(`Cached binary at ${binaryPath} reports ${actual ?? "no version"}, expected ${expected}; skipping cache candidate`);
31592
+ return false;
31593
+ }
31594
+ function platformKey(platform = process.platform, arch = process.arch) {
31595
+ const archMap = PLATFORM_ARCH_MAP[platform];
31596
+ if (!archMap) {
31597
+ throw new Error(`Unsupported platform: ${platform} (arch: ${arch}). ` + `Supported platforms: ${Object.keys(PLATFORM_ARCH_MAP).join(", ")}`);
31598
+ }
31599
+ const key = archMap[arch];
31600
+ if (!key) {
31601
+ throw new Error(`Unsupported architecture: ${arch} on platform ${platform}. ` + `Supported architectures for ${platform}: ${Object.keys(archMap).join(", ")}`);
31602
+ }
31603
+ return key;
31604
+ }
31605
+ function findBinarySync(expectedVersion) {
31606
+ const ext = process.platform === "win32" ? ".exe" : "";
31607
+ const env = { ...process.env };
31608
+ const pluginVersion = expectedVersion ?? (() => {
31609
+ try {
31610
+ const req = createRequire2(import.meta.url);
31611
+ return req("../package.json").version;
31612
+ } catch {
31613
+ return null;
31614
+ }
31615
+ })();
31616
+ if (pluginVersion) {
31617
+ const tag = pluginVersion.startsWith("v") ? pluginVersion : `v${pluginVersion}`;
31618
+ const versionCached = cachedBinaryPathFromEnv(tag, env, ext);
31619
+ if (versionCached && isExpectedCachedBinary(versionCached, pluginVersion))
31620
+ return versionCached;
31621
+ }
31622
+ try {
31623
+ const key = platformKey();
31624
+ const packageBin = `@cortexkit/aft-${key}/bin/aft${ext}`;
31625
+ const req = createRequire2(import.meta.url);
31626
+ const resolved = req.resolve(packageBin);
31627
+ if (existsSync2(resolved)) {
31628
+ const npmVersion = readBinaryVersion(resolved);
31629
+ if (npmVersion === null) {
31630
+ warn(`npm platform package binary at ${resolved} did not report a version; skipping (continuing to PATH lookup)`);
31631
+ } else if (pluginVersion && npmVersion !== normalizeBareVersion(pluginVersion)) {
31632
+ warn(`npm platform package binary v${npmVersion} does not match plugin v${pluginVersion}; skipping (continuing to PATH lookup)`);
31633
+ } else {
31634
+ const copied = copyToVersionedCache(resolved, npmVersion);
31635
+ return copied ?? resolved;
31636
+ }
31637
+ }
31638
+ } catch {}
31639
+ try {
31640
+ const whichCmd = process.platform === "win32" ? "where aft" : "which aft";
31641
+ const result = execSync(whichCmd, {
31642
+ encoding: "utf-8",
31643
+ env,
31644
+ stdio: ["pipe", "pipe", "pipe"]
31645
+ }).trim();
31646
+ if (result)
31647
+ return result;
31648
+ } catch {}
31649
+ const cargoPath = join3(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
31650
+ if (existsSync2(cargoPath))
31651
+ return cargoPath;
31652
+ return null;
31653
+ }
31654
+ async function findBinary(expectedVersion) {
31655
+ const syncResult = findBinarySync(expectedVersion);
31656
+ if (syncResult) {
31657
+ log(`Resolved binary: ${syncResult}`);
31658
+ return syncResult;
31659
+ }
31660
+ log("Binary not found locally, attempting auto-download...");
31661
+ const downloaded = await ensureBinary(expectedVersion);
31662
+ if (downloaded)
31663
+ return downloaded;
31664
+ throw new Error([
31665
+ "Could not find the `aft` binary.",
31666
+ "",
31667
+ "Attempted sources:",
31668
+ " - Cache directory (~/.cache/aft/bin/)",
31669
+ " - npm platform package (@cortexkit/aft-<platform>)",
31670
+ " - PATH lookup (which aft)",
31671
+ " - ~/.cargo/bin/aft",
31672
+ " - Auto-download from GitHub releases (failed)",
31673
+ "",
31674
+ "Install it using one of these methods:",
31675
+ " npm install @cortexkit/aft-opencode # installs platform-specific binary via npm",
31676
+ " cargo install agent-file-tools # from crates.io",
31677
+ " cargo build --release # from source (binary at target/release/aft)",
31678
+ "",
31679
+ "Or add the aft directory to your PATH."
31680
+ ].join(`
31681
+ `));
31682
+ }
31683
+
31684
+ // ../aft-bridge/dist/migration.js
31685
+ var TARGET_MARKER = ".migrated_from_legacy";
31686
+ var DEFAULT_TIMEOUT_MS = 30 * 60 * 1000;
31687
+ function dataHome() {
31688
+ if (process.env.XDG_DATA_HOME)
31689
+ return process.env.XDG_DATA_HOME;
31690
+ if (process.platform === "win32") {
31691
+ return process.env.LOCALAPPDATA || process.env.APPDATA || join4(homeDir(), "AppData", "Local");
31692
+ }
31693
+ return join4(homeDir(), ".local", "share");
31694
+ }
31695
+ function homeDir() {
31696
+ if (process.platform === "win32")
31697
+ return process.env.USERPROFILE || process.env.HOME || homedir4();
31698
+ return process.env.HOME || homedir4();
31699
+ }
31700
+ function resolveLegacyStorageRoot(harness) {
31701
+ if (harness === "pi")
31702
+ return join4(homeDir(), ".pi", "agent", "aft");
31703
+ return join4(dataHome(), "opencode", "storage", "plugin", "aft");
31704
+ }
31705
+ function resolveCortexKitStorageRoot() {
31706
+ return join4(dataHome(), "cortexkit", "aft");
31707
+ }
31708
+ function tail(value) {
31709
+ if (!value)
31710
+ return "";
31711
+ return value.split(`
31712
+ `).slice(-20).join(`
31713
+ `).trim();
31714
+ }
31715
+ function spawnErrorLabel(error2) {
31716
+ const code = "code" in error2 ? String(error2.code ?? "") : "";
31717
+ return [code, error2.message].filter(Boolean).join(": ");
31718
+ }
31719
+ function migrationLogPath(newRoot, harness, logger) {
31720
+ const desired = join4(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
31721
+ try {
31722
+ mkdirSync3(dirname(desired), { recursive: true });
31723
+ return desired;
31724
+ } catch (err) {
31725
+ const fallback = join4(tmpdir(), `aft-migration-${harness}-${Date.now()}.jsonl`);
31726
+ logger?.warn?.(`Failed to create AFT migration log directory ${dirname(desired)}: ${err instanceof Error ? err.message : String(err)}. ` + `Using fallback log path ${fallback}.`);
31727
+ return fallback;
31728
+ }
31729
+ }
31730
+ async function ensureStorageMigrated(opts) {
31731
+ const legacyRoot = resolveLegacyStorageRoot(opts.harness);
31732
+ const newRoot = resolveCortexKitStorageRoot();
31733
+ const targetMarker = join4(newRoot, opts.harness, TARGET_MARKER);
31734
+ const info = opts.logger?.info ?? opts.logger?.log;
31735
+ if (existsSync3(targetMarker)) {
31736
+ info?.(`AFT storage already migrated for ${opts.harness}; using ${newRoot}`);
31737
+ return;
31738
+ }
31739
+ if (!existsSync3(legacyRoot)) {
31740
+ info?.(`AFT storage migration skipped for ${opts.harness}: no legacy data at ${legacyRoot}; ` + `using ${newRoot} for fresh install`);
31741
+ return;
31742
+ }
31743
+ const logPath = migrationLogPath(newRoot, opts.harness, opts.logger);
31744
+ const binaryPath = opts.binaryPath ?? await findBinary();
31745
+ const startMs = Date.now();
31746
+ info?.(`AFT storage migration starting for ${opts.harness}: ${legacyRoot} -> ${newRoot} ` + `(binary=${binaryPath}, log=${logPath})`);
31747
+ try {
31748
+ process.stderr.write(`
31749
+ [AFT] Migrating ${opts.harness} storage to ${newRoot}.
31750
+ ` + `[AFT] This may take several minutes for large indexes — please do not close ${opts.harness === "pi" ? "Pi" : "OpenCode"}.
31751
+ ` + `[AFT] Source: ${legacyRoot}
31752
+ ` + `[AFT] Log: ${logPath}
31753
+
31754
+ `);
31755
+ } catch {}
31756
+ const result = spawnSync2(binaryPath, [
31757
+ "migrate-storage",
31758
+ "--from",
31759
+ legacyRoot,
31760
+ "--to",
31761
+ newRoot,
31762
+ "--harness",
31763
+ opts.harness,
31764
+ "--log",
31765
+ logPath
31766
+ ], {
31767
+ encoding: "utf8",
31768
+ stdio: ["ignore", "pipe", "pipe"],
31769
+ timeout: opts.timeoutMs ?? DEFAULT_TIMEOUT_MS
31770
+ });
31771
+ if (!result.error && result.status === 0) {
31772
+ const elapsedMs = Date.now() - startMs;
31773
+ info?.(`AFT storage migration completed for ${opts.harness} in ${elapsedMs}ms (log=${logPath})`);
31774
+ try {
31775
+ process.stderr.write(`[AFT] Migration complete (${(elapsedMs / 1000).toFixed(1)}s).
31776
+
31777
+ `);
31778
+ } catch {}
31779
+ return;
31780
+ }
31781
+ const detail = result.error ? `spawn error ${spawnErrorLabel(result.error)}` : result.status === null ? `terminated by signal ${result.signal ?? "unknown"}` : `exit ${result.status}`;
31782
+ const stderrTail = tail(result.stderr);
31783
+ const stdoutTail = tail(result.stdout);
31784
+ throw new Error(`AFT storage migration failed (${detail}). ` + `Harness: ${opts.harness}. Legacy: ${legacyRoot}. Target: ${newRoot}. ` + `See log: ${logPath}. ` + `Plugin load aborted to prevent legacy/new state divergence.` + (stderrTail ? ` Stderr tail: ${stderrTail}` : "") + (stdoutTail ? ` Stdout tail: ${stdoutTail}` : ""));
31785
+ }
31504
31786
  // ../aft-bridge/dist/onnx-runtime.js
31505
31787
  import { execFileSync } from "node:child_process";
31506
31788
  import { createHash as createHash2 } from "node:crypto";
31507
- import { chmodSync as chmodSync2, closeSync as closeSync2, copyFileSync, createWriteStream as createWriteStream2, existsSync as existsSync2, lstatSync, mkdirSync as mkdirSync2, openSync as openSync2, readdirSync, readFileSync, readlinkSync, realpathSync, rmSync as rmSync2, statSync as statSync2, symlinkSync, unlinkSync as unlinkSync2, writeFileSync } from "node:fs";
31508
- import { dirname, join as join3, relative, resolve } from "node:path";
31789
+ import { chmodSync as chmodSync3, closeSync as closeSync2, copyFileSync as copyFileSync2, createWriteStream as createWriteStream2, existsSync as existsSync4, lstatSync, mkdirSync as mkdirSync4, openSync as openSync2, readdirSync, readFileSync, readlinkSync, realpathSync, rmSync as rmSync2, statSync as statSync2, symlinkSync, unlinkSync as unlinkSync2, writeFileSync } from "node:fs";
31790
+ import { dirname as dirname2, join as join5, relative, resolve } from "node:path";
31509
31791
  import { Readable as Readable2 } from "node:stream";
31510
31792
  import { pipeline as pipeline2 } from "node:stream/promises";
31511
31793
  var ORT_VERSION = "1.24.4";
@@ -31553,8 +31835,8 @@ function getPlatformInfo() {
31553
31835
  if (!platformMap)
31554
31836
  return null;
31555
31837
  const archMap = PLATFORM_ARCH_MAP[process.platform] ?? {};
31556
- const platformKey = archMap[process.arch];
31557
- const ortArch = platformKey ? platformKey.split("-")[1] : process.arch;
31838
+ const platformKey2 = archMap[process.arch];
31839
+ const ortArch = platformKey2 ? platformKey2.split("-")[1] : process.arch;
31558
31840
  return platformMap[ortArch] || null;
31559
31841
  }
31560
31842
  function getManualInstallHint() {
@@ -31568,9 +31850,9 @@ function getManualInstallHint() {
31568
31850
  }
31569
31851
  async function ensureOnnxRuntime(storageDir) {
31570
31852
  const info = getPlatformInfo();
31571
- const ortDir = join3(storageDir, "onnxruntime", ORT_VERSION);
31572
- const libPath = join3(ortDir, info?.libName ?? "libonnxruntime.dylib");
31573
- if (existsSync2(libPath)) {
31853
+ const ortDir = join5(storageDir, "onnxruntime", ORT_VERSION);
31854
+ const libPath = join5(ortDir, info?.libName ?? "libonnxruntime.dylib");
31855
+ if (existsSync4(libPath)) {
31574
31856
  const meta = readOnnxInstalledMeta(ortDir);
31575
31857
  if (meta?.sha256) {
31576
31858
  try {
@@ -31599,9 +31881,9 @@ async function ensureOnnxRuntime(storageDir) {
31599
31881
  warn(`ONNX Runtime auto-download not available for ${process.platform}/${process.arch}. Install manually: ${getManualInstallHint()}`);
31600
31882
  return null;
31601
31883
  }
31602
- const onnxBaseDir = join3(storageDir, "onnxruntime");
31603
- mkdirSync2(onnxBaseDir, { recursive: true });
31604
- const lockPath = join3(onnxBaseDir, ONNX_LOCK_FILE);
31884
+ const onnxBaseDir = join5(storageDir, "onnxruntime");
31885
+ mkdirSync4(onnxBaseDir, { recursive: true });
31886
+ const lockPath = join5(onnxBaseDir, ONNX_LOCK_FILE);
31605
31887
  cleanupAbandonedStagingDirs(onnxBaseDir);
31606
31888
  if (!acquireLock(lockPath)) {
31607
31889
  warn(`ONNX Runtime install already in progress in another process (lock: ${lockPath}). Skipping.`);
@@ -31620,7 +31902,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
31620
31902
  for (const entry of entries) {
31621
31903
  if (!entry.startsWith(`${ORT_VERSION}.tmp.`))
31622
31904
  continue;
31623
- const stagingDir = join3(onnxBaseDir, entry);
31905
+ const stagingDir = join5(onnxBaseDir, entry);
31624
31906
  const parts = entry.split(".");
31625
31907
  const pidStr = parts[parts.length - 2];
31626
31908
  const pid = pidStr ? Number.parseInt(pidStr, 10) : NaN;
@@ -31652,7 +31934,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
31652
31934
  }
31653
31935
  function cleanupIncompleteTargetIfUnowned(ortDir) {
31654
31936
  try {
31655
- if (existsSync2(ortDir) && !existsSync2(join3(ortDir, ONNX_INSTALLED_META_FILE))) {
31937
+ if (existsSync4(ortDir) && !existsSync4(join5(ortDir, ONNX_INSTALLED_META_FILE))) {
31656
31938
  log(`[onnx] removing half-populated install dir ${ortDir} (no meta file)`);
31657
31939
  rmSync2(ortDir, { recursive: true, force: true });
31658
31940
  }
@@ -31673,8 +31955,8 @@ function detectOnnxVersion(libDir, libName) {
31673
31955
  if (match)
31674
31956
  return match[1];
31675
31957
  }
31676
- const base = join3(libDir, libName);
31677
- if (existsSync2(base)) {
31958
+ const base = join5(libDir, libName);
31959
+ if (existsSync4(base)) {
31678
31960
  try {
31679
31961
  const real = realpathSync(base);
31680
31962
  const m = real.match(/\.(\d+\.\d+\.\d+)(?:\.dylib)?$/);
@@ -31710,7 +31992,7 @@ function findSystemOnnxRuntime(libName) {
31710
31992
  searchPaths.push("/usr/lib", "/usr/lib/x86_64-linux-gnu", "/usr/lib/aarch64-linux-gnu", "/usr/local/lib");
31711
31993
  }
31712
31994
  for (const dir of searchPaths) {
31713
- if (!existsSync2(join3(dir, libName)))
31995
+ if (!existsSync4(join5(dir, libName)))
31714
31996
  continue;
31715
31997
  const version = detectOnnxVersion(dir, libName);
31716
31998
  if (version && !isOnnxVersionCompatible(version)) {
@@ -31737,7 +32019,7 @@ async function downloadFileWithCap(url, destPath) {
31737
32019
  if (Number.isFinite(advertised) && advertised > MAX_DOWNLOAD_BYTES2) {
31738
32020
  throw new Error(`Content-Length ${advertised} exceeds max ${MAX_DOWNLOAD_BYTES2}`);
31739
32021
  }
31740
- mkdirSync2(dirname(destPath), { recursive: true });
32022
+ mkdirSync4(dirname2(destPath), { recursive: true });
31741
32023
  let bytesWritten = 0;
31742
32024
  const guard = new TransformStream({
31743
32025
  transform(chunk, transformController) {
@@ -31767,11 +32049,11 @@ function validateExtractedTree(stagingRoot) {
31767
32049
  const walk = (dir) => {
31768
32050
  const entries = readdirSync(dir);
31769
32051
  for (const entry of entries) {
31770
- const fullPath = join3(dir, entry);
32052
+ const fullPath = join5(dir, entry);
31771
32053
  const lst = lstatSync(fullPath);
31772
32054
  if (lst.isSymbolicLink()) {
31773
32055
  const linkTarget = readlinkSync(fullPath);
31774
- const resolvedTarget = resolve(dirname(fullPath), linkTarget);
32056
+ const resolvedTarget = resolve(dirname2(fullPath), linkTarget);
31775
32057
  const rel2 = relative(realRoot, resolvedTarget);
31776
32058
  if (rel2.startsWith("..") || process.platform !== "win32" && rel2.startsWith("/")) {
31777
32059
  throw new Error(`extracted symlink ${fullPath} points outside staging root: ${linkTarget}`);
@@ -31801,8 +32083,8 @@ async function downloadOnnxRuntime(info, targetDir) {
31801
32083
  log(`Downloading ONNX Runtime v${ORT_VERSION} for ${process.platform}/${process.arch}...`);
31802
32084
  const tmpDir = `${targetDir}.tmp.${process.pid}.${Date.now().toString(36)}`;
31803
32085
  try {
31804
- mkdirSync2(tmpDir, { recursive: true });
31805
- const archivePath = join3(tmpDir, `onnxruntime.${info.archiveType}`);
32086
+ mkdirSync4(tmpDir, { recursive: true });
32087
+ const archivePath = join5(tmpDir, `onnxruntime.${info.archiveType}`);
31806
32088
  await downloadFileWithCap(url, archivePath);
31807
32089
  const archiveSha256 = sha256File(archivePath);
31808
32090
  log(`ONNX Runtime archive sha256=${archiveSha256}`);
@@ -31818,16 +32100,16 @@ async function downloadOnnxRuntime(info, targetDir) {
31818
32100
  unlinkSync2(archivePath);
31819
32101
  } catch {}
31820
32102
  validateExtractedTree(tmpDir);
31821
- const extractedDir = join3(tmpDir, info.assetName, "lib");
31822
- if (!existsSync2(extractedDir)) {
32103
+ const extractedDir = join5(tmpDir, info.assetName, "lib");
32104
+ if (!existsSync4(extractedDir)) {
31823
32105
  throw new Error(`Expected directory not found: ${extractedDir}`);
31824
32106
  }
31825
- mkdirSync2(targetDir, { recursive: true });
32107
+ mkdirSync4(targetDir, { recursive: true });
31826
32108
  const libFiles = readdirSync(extractedDir).filter((f) => f.startsWith("libonnxruntime") || f.startsWith("onnxruntime"));
31827
32109
  const realFiles = [];
31828
32110
  const symlinks = [];
31829
32111
  for (const libFile of libFiles) {
31830
- const src = join3(extractedDir, libFile);
32112
+ const src = join5(extractedDir, libFile);
31831
32113
  try {
31832
32114
  const stat = lstatSync(src);
31833
32115
  log(`ORT extract: ${libFile} — isSymlink=${stat.isSymbolicLink()}, isFile=${stat.isFile()}, size=${stat.size}`);
@@ -31842,7 +32124,7 @@ async function downloadOnnxRuntime(info, targetDir) {
31842
32124
  }
31843
32125
  }
31844
32126
  copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks);
31845
- const libPath = join3(targetDir, info.libName);
32127
+ const libPath = join5(targetDir, info.libName);
31846
32128
  let libHash = null;
31847
32129
  try {
31848
32130
  libHash = sha256File(libPath);
@@ -31864,15 +32146,15 @@ async function downloadOnnxRuntime(info, targetDir) {
31864
32146
  return null;
31865
32147
  }
31866
32148
  }
31867
- function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, copyFile = copyFileSync) {
32149
+ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, copyFile = copyFileSync2) {
31868
32150
  const requiredLibs = new Set([info.libName]);
31869
32151
  for (const libFile of realFiles) {
31870
- const src = join3(extractedDir, libFile);
31871
- const dst = join3(targetDir, libFile);
32152
+ const src = join5(extractedDir, libFile);
32153
+ const dst = join5(targetDir, libFile);
31872
32154
  try {
31873
32155
  copyFile(src, dst);
31874
32156
  if (process.platform !== "win32") {
31875
- chmodSync2(dst, 493);
32157
+ chmodSync3(dst, 493);
31876
32158
  }
31877
32159
  } catch (copyErr) {
31878
32160
  if (requiredLibs.has(libFile)) {
@@ -31883,7 +32165,7 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
31883
32165
  }
31884
32166
  }
31885
32167
  for (const link of symlinks) {
31886
- const dst = join3(targetDir, link.name);
32168
+ const dst = join5(targetDir, link.name);
31887
32169
  try {
31888
32170
  unlinkSync2(dst);
31889
32171
  } catch {}
@@ -31897,8 +32179,8 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
31897
32179
  log(`ORT extract: failed to symlink optional ${link.name}: ${symlinkErr}`);
31898
32180
  }
31899
32181
  }
31900
- const requiredPath = join3(targetDir, info.libName);
31901
- if (!existsSync2(requiredPath)) {
32182
+ const requiredPath = join5(targetDir, info.libName);
32183
+ if (!existsSync4(requiredPath)) {
31902
32184
  rmSync2(targetDir, { recursive: true, force: true });
31903
32185
  throw new Error(`Required ONNX Runtime library missing after install: ${requiredPath}`);
31904
32186
  }
@@ -31924,13 +32206,13 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
31924
32206
  ...sha256 ? { sha256 } : {},
31925
32207
  archiveSha256
31926
32208
  };
31927
- writeFileSync(join3(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
32209
+ writeFileSync(join5(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
31928
32210
  } catch (err) {
31929
32211
  log(`[onnx] failed to write installed-meta in ${installDir}: ${err}`);
31930
32212
  }
31931
32213
  }
31932
32214
  function readOnnxInstalledMeta(installDir) {
31933
- const path = join3(installDir, ONNX_INSTALLED_META_FILE);
32215
+ const path = join5(installDir, ONNX_INSTALLED_META_FILE);
31934
32216
  try {
31935
32217
  if (!statSync2(path).isFile())
31936
32218
  return null;
@@ -32045,13 +32327,13 @@ function isProcessAlive(pid) {
32045
32327
  }
32046
32328
  // ../aft-bridge/dist/pool.js
32047
32329
  import { realpathSync as realpathSync2 } from "node:fs";
32048
- import { homedir as homedir3 } from "node:os";
32330
+ import { homedir as homedir5 } from "node:os";
32049
32331
  var DEFAULT_IDLE_TIMEOUT_MS = Infinity;
32050
32332
  var DEFAULT_MAX_POOL_SIZE = 8;
32051
32333
  var CLEANUP_INTERVAL_MS = 60 * 1000;
32052
32334
  function canonicalHomeDir() {
32053
32335
  try {
32054
- const home = homedir3();
32336
+ const home = homedir5();
32055
32337
  if (!home)
32056
32338
  return null;
32057
32339
  try {
@@ -32077,6 +32359,7 @@ class BridgePool {
32077
32359
  idleTimeoutMs;
32078
32360
  bridgeOptions;
32079
32361
  configOverrides;
32362
+ projectConfigLoader;
32080
32363
  logger;
32081
32364
  cleanupTimer = null;
32082
32365
  constructor(binaryPath, options = {}, configOverrides = {}) {
@@ -32084,6 +32367,7 @@ class BridgePool {
32084
32367
  this.maxPoolSize = options.maxPoolSize ?? DEFAULT_MAX_POOL_SIZE;
32085
32368
  this.idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
32086
32369
  this.logger = options.logger;
32370
+ this.projectConfigLoader = options.projectConfigLoader;
32087
32371
  this.bridgeOptions = {
32088
32372
  timeoutMs: options.timeoutMs,
32089
32373
  maxRestarts: options.maxRestarts,
@@ -32119,7 +32403,17 @@ class BridgePool {
32119
32403
  if (this.bridges.size >= this.maxPoolSize) {
32120
32404
  this.evictLRU();
32121
32405
  }
32122
- const bridge = new BinaryBridge(this.binaryPath, key, this.bridgeOptions, this.configOverrides);
32406
+ let projectOverrides = {};
32407
+ if (this.projectConfigLoader) {
32408
+ try {
32409
+ projectOverrides = this.projectConfigLoader(key) ?? {};
32410
+ } catch (err) {
32411
+ const message = err instanceof Error ? err.message : String(err);
32412
+ this.error(`projectConfigLoader failed; using global overrides only: ${message}`);
32413
+ }
32414
+ }
32415
+ const mergedOverrides = { ...this.configOverrides, ...projectOverrides };
32416
+ const bridge = new BinaryBridge(this.binaryPath, key, this.bridgeOptions, mergedOverrides);
32123
32417
  this.bridges.set(key, { bridge, lastUsed: Date.now() });
32124
32418
  return bridge;
32125
32419
  }
@@ -32212,180 +32506,12 @@ function normalizeKey(projectRoot) {
32212
32506
  return stripped;
32213
32507
  }
32214
32508
  }
32215
- // ../aft-bridge/dist/resolver.js
32216
- import { execSync, spawnSync } from "node:child_process";
32217
- import { chmodSync as chmodSync3, copyFileSync as copyFileSync2, existsSync as existsSync3, mkdirSync as mkdirSync3, renameSync as renameSync2 } from "node:fs";
32218
- import { createRequire as createRequire2 } from "node:module";
32219
- import { homedir as homedir4 } from "node:os";
32220
- import { join as join4 } from "node:path";
32221
- function readBinaryVersion(binaryPath) {
32222
- try {
32223
- const result = spawnSync(binaryPath, ["--version"], {
32224
- encoding: "utf-8",
32225
- stdio: ["pipe", "pipe", "pipe"],
32226
- timeout: 5000
32227
- });
32228
- const stdoutVersion = result.stdout?.trim();
32229
- const stderrVersion = result.stderr?.trim();
32230
- const rawVersion = stdoutVersion || stderrVersion;
32231
- if (!rawVersion)
32232
- return null;
32233
- return rawVersion.replace(/^aft\s+/, "");
32234
- } catch {
32235
- return null;
32236
- }
32237
- }
32238
- function copyToVersionedCache(npmBinaryPath, knownVersion) {
32239
- try {
32240
- const version = knownVersion ?? readBinaryVersion(npmBinaryPath);
32241
- if (!version)
32242
- return null;
32243
- const tag = version.startsWith("v") ? version : `v${version}`;
32244
- const cacheDir = getCacheDir();
32245
- const versionedDir = join4(cacheDir, tag);
32246
- const ext = process.platform === "win32" ? ".exe" : "";
32247
- const cachedPath = join4(versionedDir, `aft${ext}`);
32248
- if (existsSync3(cachedPath)) {
32249
- const cachedVersion = readBinaryVersion(cachedPath);
32250
- if (cachedVersion === version)
32251
- return cachedPath;
32252
- warn(`Cached binary at ${cachedPath} reports ${cachedVersion ?? "no version"}, expected ${version}; refreshing from npm package`);
32253
- }
32254
- mkdirSync3(versionedDir, { recursive: true });
32255
- const tmpPath = `${cachedPath}.${process.pid}.${Date.now()}.tmp`;
32256
- copyFileSync2(npmBinaryPath, tmpPath);
32257
- if (process.platform !== "win32") {
32258
- chmodSync3(tmpPath, 493);
32259
- }
32260
- renameSync2(tmpPath, cachedPath);
32261
- log(`Copied npm binary to versioned cache: ${cachedPath}`);
32262
- return cachedPath;
32263
- } catch (err) {
32264
- warn(`Failed to copy binary to cache: ${err instanceof Error ? err.message : String(err)}`);
32265
- return null;
32266
- }
32267
- }
32268
- function normalizeBareVersion(version) {
32269
- return version.startsWith("v") ? version.slice(1) : version;
32270
- }
32271
- function homeDirFromEnv(env) {
32272
- return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir4();
32273
- }
32274
- function cacheDirFromEnv(env) {
32275
- if (process.platform === "win32") {
32276
- const base2 = env.LOCALAPPDATA || env.APPDATA || join4(homeDirFromEnv(env), "AppData", "Local");
32277
- return join4(base2, "aft", "bin");
32278
- }
32279
- const base = env.XDG_CACHE_HOME || join4(homeDirFromEnv(env), ".cache");
32280
- return join4(base, "aft", "bin");
32281
- }
32282
- function cachedBinaryPathFromEnv(version, env, ext) {
32283
- const binaryPath = join4(cacheDirFromEnv(env), version, `aft${ext}`);
32284
- return existsSync3(binaryPath) ? binaryPath : null;
32285
- }
32286
- function isExpectedCachedBinary(binaryPath, expectedVersion) {
32287
- const expected = normalizeBareVersion(expectedVersion);
32288
- const actual = readBinaryVersion(binaryPath);
32289
- if (actual === expected)
32290
- return true;
32291
- warn(`Cached binary at ${binaryPath} reports ${actual ?? "no version"}, expected ${expected}; skipping cache candidate`);
32292
- return false;
32293
- }
32294
- function platformKey(platform = process.platform, arch = process.arch) {
32295
- const archMap = PLATFORM_ARCH_MAP[platform];
32296
- if (!archMap) {
32297
- throw new Error(`Unsupported platform: ${platform} (arch: ${arch}). ` + `Supported platforms: ${Object.keys(PLATFORM_ARCH_MAP).join(", ")}`);
32298
- }
32299
- const key = archMap[arch];
32300
- if (!key) {
32301
- throw new Error(`Unsupported architecture: ${arch} on platform ${platform}. ` + `Supported architectures for ${platform}: ${Object.keys(archMap).join(", ")}`);
32302
- }
32303
- return key;
32304
- }
32305
- function findBinarySync(expectedVersion) {
32306
- const ext = process.platform === "win32" ? ".exe" : "";
32307
- const env = { ...process.env };
32308
- const pluginVersion = expectedVersion ?? (() => {
32309
- try {
32310
- const req = createRequire2(import.meta.url);
32311
- return req("../package.json").version;
32312
- } catch {
32313
- return null;
32314
- }
32315
- })();
32316
- if (pluginVersion) {
32317
- const tag = pluginVersion.startsWith("v") ? pluginVersion : `v${pluginVersion}`;
32318
- const versionCached = cachedBinaryPathFromEnv(tag, env, ext);
32319
- if (versionCached && isExpectedCachedBinary(versionCached, pluginVersion))
32320
- return versionCached;
32321
- }
32322
- try {
32323
- const key = platformKey();
32324
- const packageBin = `@cortexkit/aft-${key}/bin/aft${ext}`;
32325
- const req = createRequire2(import.meta.url);
32326
- const resolved = req.resolve(packageBin);
32327
- if (existsSync3(resolved)) {
32328
- const npmVersion = readBinaryVersion(resolved);
32329
- if (npmVersion === null) {
32330
- warn(`npm platform package binary at ${resolved} did not report a version; skipping (continuing to PATH lookup)`);
32331
- } else if (pluginVersion && npmVersion !== normalizeBareVersion(pluginVersion)) {
32332
- warn(`npm platform package binary v${npmVersion} does not match plugin v${pluginVersion}; skipping (continuing to PATH lookup)`);
32333
- } else {
32334
- const copied = copyToVersionedCache(resolved, npmVersion);
32335
- return copied ?? resolved;
32336
- }
32337
- }
32338
- } catch {}
32339
- try {
32340
- const whichCmd = process.platform === "win32" ? "where aft" : "which aft";
32341
- const result = execSync(whichCmd, {
32342
- encoding: "utf-8",
32343
- env,
32344
- stdio: ["pipe", "pipe", "pipe"]
32345
- }).trim();
32346
- if (result)
32347
- return result;
32348
- } catch {}
32349
- const cargoPath = join4(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
32350
- if (existsSync3(cargoPath))
32351
- return cargoPath;
32352
- return null;
32353
- }
32354
- async function findBinary(expectedVersion) {
32355
- const syncResult = findBinarySync(expectedVersion);
32356
- if (syncResult) {
32357
- log(`Resolved binary: ${syncResult}`);
32358
- return syncResult;
32359
- }
32360
- log("Binary not found locally, attempting auto-download...");
32361
- const downloaded = await ensureBinary(expectedVersion);
32362
- if (downloaded)
32363
- return downloaded;
32364
- throw new Error([
32365
- "Could not find the `aft` binary.",
32366
- "",
32367
- "Attempted sources:",
32368
- " - Cache directory (~/.cache/aft/bin/)",
32369
- " - npm platform package (@cortexkit/aft-<platform>)",
32370
- " - PATH lookup (which aft)",
32371
- " - ~/.cargo/bin/aft",
32372
- " - Auto-download from GitHub releases (failed)",
32373
- "",
32374
- "Install it using one of these methods:",
32375
- " npm install @cortexkit/aft-opencode # installs platform-specific binary via npm",
32376
- " cargo install agent-file-tools # from crates.io",
32377
- " cargo build --release # from source (binary at target/release/aft)",
32378
- "",
32379
- "Or add the aft directory to your PATH."
32380
- ].join(`
32381
- `));
32382
- }
32383
32509
  // ../aft-bridge/dist/url-fetch.js
32384
32510
  import { createHash as createHash3 } from "node:crypto";
32385
32511
  import { lookup } from "node:dns/promises";
32386
- import { existsSync as existsSync4, mkdirSync as mkdirSync4, readdirSync as readdirSync2, readFileSync as readFileSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "node:fs";
32512
+ import { existsSync as existsSync5, mkdirSync as mkdirSync5, readdirSync as readdirSync2, readFileSync as readFileSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "node:fs";
32387
32513
  import { isIP } from "node:net";
32388
- import { join as join5 } from "node:path";
32514
+ import { join as join6 } from "node:path";
32389
32515
 
32390
32516
  // ../../node_modules/.bun/undici@8.2.0/node_modules/undici/index.js
32391
32517
  var __filename = "/home/runner/work/aft/aft/node_modules/.bun/undici@8.2.0/node_modules/undici/index.js";
@@ -32535,16 +32661,16 @@ var CACHE_TTL_MS = 24 * 60 * 60 * 1000;
32535
32661
  var FETCH_TIMEOUT_MS = 30000;
32536
32662
  var MAX_REDIRECTS = 5;
32537
32663
  function cacheDir(storageDir) {
32538
- return join5(storageDir, "url_cache");
32664
+ return join6(storageDir, "url_cache");
32539
32665
  }
32540
32666
  function hashUrl(url) {
32541
32667
  return createHash3("sha256").update(url).digest("hex").slice(0, 16);
32542
32668
  }
32543
32669
  function metaPath(storageDir, hash) {
32544
- return join5(cacheDir(storageDir), `${hash}.meta.json`);
32670
+ return join6(cacheDir(storageDir), `${hash}.meta.json`);
32545
32671
  }
32546
32672
  function contentPath(storageDir, hash, extension) {
32547
- return join5(cacheDir(storageDir), `${hash}${extension}`);
32673
+ return join6(cacheDir(storageDir), `${hash}${extension}`);
32548
32674
  }
32549
32675
  function _isPrivateIpv4(address) {
32550
32676
  const parts = address.split(".").map((part) => Number.parseInt(part, 10));
@@ -32562,9 +32688,9 @@ function expandIpv6(addr) {
32562
32688
  let normalized = addr;
32563
32689
  const lastColon = normalized.lastIndexOf(":");
32564
32690
  if (lastColon !== -1) {
32565
- const tail = normalized.slice(lastColon + 1);
32566
- if (tail.includes(".")) {
32567
- const octets = tail.split(".").map((p) => Number.parseInt(p, 10));
32691
+ const tail2 = normalized.slice(lastColon + 1);
32692
+ if (tail2.includes(".")) {
32693
+ const octets = tail2.split(".").map((p) => Number.parseInt(p, 10));
32568
32694
  if (octets.length !== 4 || octets.some((o) => Number.isNaN(o) || o < 0 || o > 255)) {
32569
32695
  return null;
32570
32696
  }
@@ -32742,15 +32868,15 @@ async function fetchUrlToTempFile(url, storageDir, options = {}) {
32742
32868
  const allowPrivate = options.allowPrivate === true;
32743
32869
  await assertPublicUrl(parsed, allowPrivate, options.lookup);
32744
32870
  const dir = cacheDir(storageDir);
32745
- mkdirSync4(dir, { recursive: true });
32871
+ mkdirSync5(dir, { recursive: true });
32746
32872
  const hash = hashUrl(url);
32747
32873
  const metaFile = metaPath(storageDir, hash);
32748
- if (existsSync4(metaFile)) {
32874
+ if (existsSync5(metaFile)) {
32749
32875
  try {
32750
32876
  const meta2 = JSON.parse(readFileSync2(metaFile, "utf8"));
32751
32877
  const age = Date.now() - meta2.fetchedAt;
32752
32878
  const cached = contentPath(storageDir, hash, meta2.extension);
32753
- if (age < CACHE_TTL_MS && existsSync4(cached)) {
32879
+ if (age < CACHE_TTL_MS && existsSync5(cached)) {
32754
32880
  log(`URL cache hit: ${url} (${Math.round(age / 1000)}s old)`);
32755
32881
  return cached;
32756
32882
  }
@@ -33056,12 +33182,12 @@ function formatSystemReminder(completions) {
33056
33182
  const bullets = completions.map((completion) => formatCompletion(completion)).join(`
33057
33183
  `);
33058
33184
  const anyTruncated = completions.some((c) => c.output_truncated === true);
33059
- const tail = anyTruncated ? `
33185
+ const tail2 = anyTruncated ? `
33060
33186
 
33061
33187
  For truncated tasks, use bash_status({ task_id: "..." }) to retrieve full output.` : "";
33062
33188
  return `<system-reminder>
33063
33189
  [BACKGROUND BASH COMPLETED]
33064
- ${bullets}${tail}
33190
+ ${bullets}${tail2}
33065
33191
  </system-reminder>`;
33066
33192
  }
33067
33193
  function formatLongRunningReminder(reminders) {
@@ -33299,7 +33425,7 @@ import {
33299
33425
  // package.json
33300
33426
  var package_default = {
33301
33427
  name: "@cortexkit/aft-pi",
33302
- version: "0.26.4",
33428
+ version: "0.27.1",
33303
33429
  type: "module",
33304
33430
  description: "Pi coding agent extension for Agent File Tools (AFT) — tree-sitter and LSP-powered code analysis",
33305
33431
  main: "dist/index.js",
@@ -33321,18 +33447,18 @@ var package_default = {
33321
33447
  prepublishOnly: "bun run build"
33322
33448
  },
33323
33449
  dependencies: {
33324
- "@cortexkit/aft-bridge": "0.26.4",
33450
+ "@cortexkit/aft-bridge": "0.27.1",
33325
33451
  typebox: "^1.1.24",
33326
33452
  "comment-json": "^5.0.0",
33327
33453
  diff: "^8.0.4",
33328
33454
  zod: "^4.1.8"
33329
33455
  },
33330
33456
  optionalDependencies: {
33331
- "@cortexkit/aft-darwin-arm64": "0.26.4",
33332
- "@cortexkit/aft-darwin-x64": "0.26.4",
33333
- "@cortexkit/aft-linux-arm64": "0.26.4",
33334
- "@cortexkit/aft-linux-x64": "0.26.4",
33335
- "@cortexkit/aft-win32-x64": "0.26.4"
33457
+ "@cortexkit/aft-darwin-arm64": "0.27.1",
33458
+ "@cortexkit/aft-darwin-x64": "0.27.1",
33459
+ "@cortexkit/aft-linux-arm64": "0.27.1",
33460
+ "@cortexkit/aft-linux-x64": "0.27.1",
33461
+ "@cortexkit/aft-win32-x64": "0.27.1"
33336
33462
  },
33337
33463
  devDependencies: {
33338
33464
  "@earendil-works/pi-coding-agent": "*",
@@ -33377,6 +33503,24 @@ function readNumber(value, fallback = 0) {
33377
33503
  function readOptionalNumber(value) {
33378
33504
  return typeof value === "number" && Number.isFinite(value) ? value : null;
33379
33505
  }
33506
+ function readCompressionAggregate(value) {
33507
+ const aggregate = asRecord(value);
33508
+ return {
33509
+ events: readNumber(aggregate.events),
33510
+ original_tokens: readNumber(aggregate.original_tokens),
33511
+ compressed_tokens: readNumber(aggregate.compressed_tokens),
33512
+ savings_tokens: readNumber(aggregate.savings_tokens)
33513
+ };
33514
+ }
33515
+ function readCompression(value) {
33516
+ if (typeof value !== "object" || value === null)
33517
+ return;
33518
+ const compression = asRecord(value);
33519
+ return {
33520
+ project: readCompressionAggregate(compression.project),
33521
+ session: readCompressionAggregate(compression.session)
33522
+ };
33523
+ }
33380
33524
  function formatFlag(enabled) {
33381
33525
  return enabled ? "enabled" : "disabled";
33382
33526
  }
@@ -33452,7 +33596,8 @@ function coerceAftStatus(response) {
33452
33596
  id: readString(session.id, "__default__"),
33453
33597
  tracked_files: readNumber(session.tracked_files),
33454
33598
  checkpoints: readNumber(session.checkpoints)
33455
- }
33599
+ },
33600
+ compression: readCompression(response.compression)
33456
33601
  };
33457
33602
  }
33458
33603
  function formatStatusDialogMessage(status) {
@@ -33688,6 +33833,13 @@ function renderInner(s, error3, theme, innerWidth) {
33688
33833
  lines.push("");
33689
33834
  lines.push(theme.fg("muted", "Features"));
33690
33835
  lines.push(` ${featureBadge("format_on_edit", s.features.format_on_edit, theme)} ${featureBadge("search_index", s.features.search_index, theme)} ${featureBadge("semantic_search", s.features.semantic_search, theme)}`);
33836
+ const compressionRows = formatCompressionStatusRows(s.compression);
33837
+ if (compressionRows.length > 0) {
33838
+ lines.push("");
33839
+ lines.push(theme.fg("muted", "Compression"));
33840
+ for (const row of compressionRows)
33841
+ lines.push(row);
33842
+ }
33691
33843
  if (s.semantic_index.stage) {
33692
33844
  lines.push("");
33693
33845
  lines.push(theme.fg("muted", "Semantic build progress"));
@@ -33711,6 +33863,23 @@ function renderInner(s, error3, theme, innerWidth) {
33711
33863
  lines.push(theme.fg("muted", "Press Escape to close"));
33712
33864
  return lines;
33713
33865
  }
33866
+ function appendCompressionScope(rows, label, aggregate) {
33867
+ const pct = compressionSavingsPercent(aggregate.original_tokens, aggregate.compressed_tokens);
33868
+ const savings = aggregate.savings_tokens;
33869
+ rows.push(label);
33870
+ rows.push(` Tokens Saved ${savings.toLocaleString("en-US")}`);
33871
+ rows.push(` Compression Ratio ${pct ?? 0}%`);
33872
+ }
33873
+ function formatCompressionStatusRows(compression) {
33874
+ if (!compression || compression.project.events <= 0)
33875
+ return [];
33876
+ const rows = [];
33877
+ if (compression.session.events > 0) {
33878
+ appendCompressionScope(rows, "Session", compression.session);
33879
+ }
33880
+ appendCompressionScope(rows, "Project", compression.project);
33881
+ return rows;
33882
+ }
33714
33883
  function colorStatus(status, theme) {
33715
33884
  switch (status) {
33716
33885
  case "ready":
@@ -33817,9 +33986,9 @@ function registerStatusCommand(pi, ctx) {
33817
33986
 
33818
33987
  // src/config.ts
33819
33988
  var import_comment_json = __toESM(require_src2(), 1);
33820
- import { existsSync as existsSync5, readFileSync as readFileSync3, renameSync as renameSync3, unlinkSync as unlinkSync4, writeFileSync as writeFileSync3 } from "node:fs";
33821
- import { homedir as homedir5 } from "node:os";
33822
- import { join as join7 } from "node:path";
33989
+ import { existsSync as existsSync6, readFileSync as readFileSync3, renameSync as renameSync3, unlinkSync as unlinkSync4, writeFileSync as writeFileSync3 } from "node:fs";
33990
+ import { homedir as homedir6 } from "node:os";
33991
+ import { join as join8 } from "node:path";
33823
33992
 
33824
33993
  // ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
33825
33994
  var exports_external = {};
@@ -47417,6 +47586,7 @@ var ExperimentalConfigSchema = exports_external.object({
47417
47586
  lsp_ty: exports_external.boolean().optional()
47418
47587
  });
47419
47588
  var AftConfigSchema = exports_external.object({
47589
+ $schema: exports_external.string().optional(),
47420
47590
  format_on_edit: exports_external.boolean().optional(),
47421
47591
  formatter_timeout_secs: exports_external.number().int().min(1).max(600).optional(),
47422
47592
  validate_on_edit: exports_external.enum(["syntax", "full"]).optional(),
@@ -47569,7 +47739,7 @@ function migrateRawConfig(rawConfig, configPath, logger) {
47569
47739
  return oldKeys;
47570
47740
  }
47571
47741
  function migrateAftConfigFile(configPath, logger = { log: log2, warn: warn2 }) {
47572
- if (!existsSync5(configPath)) {
47742
+ if (!existsSync6(configPath)) {
47573
47743
  return { migrated: false, oldKeys: [] };
47574
47744
  }
47575
47745
  let tmpPath = null;
@@ -47612,15 +47782,15 @@ ${serialized}` : serialized;
47612
47782
  function detectConfigFile(basePath) {
47613
47783
  const jsoncPath = `${basePath}.jsonc`;
47614
47784
  const jsonPath = `${basePath}.json`;
47615
- if (existsSync5(jsoncPath))
47785
+ if (existsSync6(jsoncPath))
47616
47786
  return { format: "jsonc", path: jsoncPath };
47617
- if (existsSync5(jsonPath))
47787
+ if (existsSync6(jsonPath))
47618
47788
  return { format: "json", path: jsonPath };
47619
47789
  return { format: "none", path: jsonPath };
47620
47790
  }
47621
47791
  function loadConfigFromPath(configPath) {
47622
47792
  try {
47623
- if (!existsSync5(configPath))
47793
+ if (!existsSync6(configPath))
47624
47794
  return null;
47625
47795
  const content = readFileSync3(configPath, "utf-8");
47626
47796
  const rawConfig = import_comment_json.parse(content);
@@ -47773,15 +47943,15 @@ function mergeConfigs(base, override) {
47773
47943
  };
47774
47944
  }
47775
47945
  function getGlobalPiDir() {
47776
- return join7(homedir5(), ".pi", "agent");
47946
+ return join8(homedir6(), ".pi", "agent");
47777
47947
  }
47778
47948
  function loadAftConfig(projectDirectory) {
47779
- const userBasePath = join7(getGlobalPiDir(), "aft");
47949
+ const userBasePath = join8(getGlobalPiDir(), "aft");
47780
47950
  migrateAftConfigFile(`${userBasePath}.jsonc`);
47781
47951
  migrateAftConfigFile(`${userBasePath}.json`);
47782
47952
  const userDetected = detectConfigFile(userBasePath);
47783
47953
  const userConfigPath = userDetected.format !== "none" ? userDetected.path : `${userBasePath}.json`;
47784
- const projectBasePath = join7(projectDirectory, ".pi", "aft");
47954
+ const projectBasePath = join8(projectDirectory, ".pi", "aft");
47785
47955
  migrateAftConfigFile(`${projectBasePath}.jsonc`);
47786
47956
  migrateAftConfigFile(`${projectBasePath}.json`);
47787
47957
  const projectDetected = detectConfigFile(projectBasePath);
@@ -47808,49 +47978,49 @@ function loadAftConfig(projectDirectory) {
47808
47978
  // src/lsp-auto-install.ts
47809
47979
  import { spawn as spawn2 } from "node:child_process";
47810
47980
  import { createHash as createHash4 } from "node:crypto";
47811
- import { createReadStream, mkdirSync as mkdirSync6, readFileSync as readFileSync5, renameSync as renameSync4, rmSync as rmSync3, statSync as statSync4 } from "node:fs";
47812
- import { join as join10 } from "node:path";
47981
+ import { createReadStream, mkdirSync as mkdirSync7, readFileSync as readFileSync5, renameSync as renameSync4, rmSync as rmSync3, statSync as statSync4 } from "node:fs";
47982
+ import { join as join11 } from "node:path";
47813
47983
 
47814
47984
  // src/lsp-cache.ts
47815
47985
  import {
47816
47986
  closeSync as closeSync3,
47817
- mkdirSync as mkdirSync5,
47987
+ mkdirSync as mkdirSync6,
47818
47988
  openSync as openSync3,
47819
47989
  readFileSync as readFileSync4,
47820
47990
  statSync as statSync3,
47821
47991
  unlinkSync as unlinkSync5,
47822
47992
  writeFileSync as writeFileSync4
47823
47993
  } from "node:fs";
47824
- import { homedir as homedir6 } from "node:os";
47825
- import { join as join8 } from "node:path";
47994
+ import { homedir as homedir7 } from "node:os";
47995
+ import { join as join9 } from "node:path";
47826
47996
  function aftCacheBase() {
47827
47997
  const override = process.env.AFT_CACHE_DIR;
47828
47998
  if (override && override.length > 0)
47829
47999
  return override;
47830
48000
  if (process.platform === "win32") {
47831
48001
  const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
47832
- const base2 = localAppData || join8(homedir6(), "AppData", "Local");
47833
- return join8(base2, "aft");
48002
+ const base2 = localAppData || join9(homedir7(), "AppData", "Local");
48003
+ return join9(base2, "aft");
47834
48004
  }
47835
- const base = process.env.XDG_CACHE_HOME || join8(homedir6(), ".cache");
47836
- return join8(base, "aft");
48005
+ const base = process.env.XDG_CACHE_HOME || join9(homedir7(), ".cache");
48006
+ return join9(base, "aft");
47837
48007
  }
47838
48008
  function lspCacheRoot() {
47839
- return join8(aftCacheBase(), "lsp-packages");
48009
+ return join9(aftCacheBase(), "lsp-packages");
47840
48010
  }
47841
48011
  function lspPackageDir(npmPackage) {
47842
- return join8(lspCacheRoot(), encodeURIComponent(npmPackage));
48012
+ return join9(lspCacheRoot(), encodeURIComponent(npmPackage));
47843
48013
  }
47844
48014
  function lspBinaryPath(npmPackage, binary) {
47845
- return join8(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
48015
+ return join9(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
47846
48016
  }
47847
48017
  function lspBinDir(npmPackage) {
47848
- return join8(lspPackageDir(npmPackage), "node_modules", ".bin");
48018
+ return join9(lspPackageDir(npmPackage), "node_modules", ".bin");
47849
48019
  }
47850
48020
  function isInstalled(npmPackage, binary) {
47851
48021
  for (const candidate of lspBinaryCandidates(binary)) {
47852
48022
  try {
47853
- if (statSync3(join8(lspBinDir(npmPackage), candidate)).isFile())
48023
+ if (statSync3(join9(lspBinDir(npmPackage), candidate)).isFile())
47854
48024
  return true;
47855
48025
  } catch {}
47856
48026
  }
@@ -47864,19 +48034,19 @@ function lspBinaryCandidates(binary) {
47864
48034
  var INSTALLED_META_FILE = ".aft-installed";
47865
48035
  function writeInstalledMetaIn(installDir, version2, sha256) {
47866
48036
  try {
47867
- mkdirSync5(installDir, { recursive: true });
48037
+ mkdirSync6(installDir, { recursive: true });
47868
48038
  const meta3 = {
47869
48039
  version: version2,
47870
48040
  installedAt: new Date().toISOString(),
47871
48041
  ...sha256 ? { sha256 } : {}
47872
48042
  };
47873
- writeFileSync4(join8(installDir, INSTALLED_META_FILE), JSON.stringify(meta3), "utf8");
48043
+ writeFileSync4(join9(installDir, INSTALLED_META_FILE), JSON.stringify(meta3), "utf8");
47874
48044
  } catch (err) {
47875
48045
  log2(`[lsp-cache] failed to write installed-meta in ${installDir}: ${err}`);
47876
48046
  }
47877
48047
  }
47878
48048
  function readInstalledMetaIn(installDir) {
47879
- const path2 = join8(installDir, INSTALLED_META_FILE);
48049
+ const path2 = join9(installDir, INSTALLED_META_FILE);
47880
48050
  try {
47881
48051
  if (!statSync3(path2).isFile())
47882
48052
  return null;
@@ -47900,11 +48070,11 @@ function readInstalledMeta(packageKey) {
47900
48070
  return readInstalledMetaIn(lspPackageDir(packageKey));
47901
48071
  }
47902
48072
  function lockPath(npmPackage) {
47903
- return join8(lspPackageDir(npmPackage), ".aft-installing");
48073
+ return join9(lspPackageDir(npmPackage), ".aft-installing");
47904
48074
  }
47905
48075
  var STALE_LOCK_MS2 = 30 * 60 * 1000;
47906
48076
  function acquireInstallLock(lockKey) {
47907
- mkdirSync5(lspPackageDir(lockKey), { recursive: true });
48077
+ mkdirSync6(lspPackageDir(lockKey), { recursive: true });
47908
48078
  const lock = lockPath(lockKey);
47909
48079
  const tryClaim = () => {
47910
48080
  try {
@@ -48007,7 +48177,7 @@ async function withInstallLock(lockKey, task) {
48007
48177
  }
48008
48178
  var VERSION_CHECK_FILE = ".aft-version-check";
48009
48179
  function readVersionCheck(npmPackage) {
48010
- const file2 = join8(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
48180
+ const file2 = join9(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
48011
48181
  try {
48012
48182
  const raw = readFileSync4(file2, "utf8");
48013
48183
  const parsed = JSON.parse(raw);
@@ -48023,8 +48193,8 @@ function readVersionCheck(npmPackage) {
48023
48193
  }
48024
48194
  }
48025
48195
  function writeVersionCheck(npmPackage, latest) {
48026
- mkdirSync5(lspPackageDir(npmPackage), { recursive: true });
48027
- const file2 = join8(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
48196
+ mkdirSync6(lspPackageDir(npmPackage), { recursive: true });
48197
+ const file2 = join9(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
48028
48198
  const record2 = {
48029
48199
  last_checked: new Date().toISOString(),
48030
48200
  latest_eligible: latest
@@ -48172,8 +48342,8 @@ var NPM_LSP_TABLE = [
48172
48342
  ];
48173
48343
 
48174
48344
  // src/lsp-project-relevance.ts
48175
- import { existsSync as existsSync6, readdirSync as readdirSync3 } from "node:fs";
48176
- import { join as join9 } from "node:path";
48345
+ import { existsSync as existsSync7, readdirSync as readdirSync3 } from "node:fs";
48346
+ import { join as join10 } from "node:path";
48177
48347
  var MAX_WALK_DIRS = 200;
48178
48348
  var MAX_WALK_DEPTH = 4;
48179
48349
  var NOISE_DIRS = new Set([
@@ -48190,7 +48360,7 @@ function hasRootMarker(projectRoot, rootMarkers) {
48190
48360
  if (!rootMarkers)
48191
48361
  return false;
48192
48362
  for (const marker of rootMarkers) {
48193
- if (existsSync6(join9(projectRoot, marker)))
48363
+ if (existsSync7(join10(projectRoot, marker)))
48194
48364
  return true;
48195
48365
  }
48196
48366
  return false;
@@ -48216,7 +48386,7 @@ function relevantExtensionsInProject(projectRoot, extToServer) {
48216
48386
  for (const entry of entries) {
48217
48387
  if (entry.isDirectory()) {
48218
48388
  if (current.depth < MAX_WALK_DEPTH && !NOISE_DIRS.has(entry.name.toLowerCase())) {
48219
- queue.push({ dir: join9(current.dir, entry.name), depth: current.depth + 1 });
48389
+ queue.push({ dir: join10(current.dir, entry.name), depth: current.depth + 1 });
48220
48390
  }
48221
48391
  continue;
48222
48392
  }
@@ -48514,10 +48684,10 @@ function sha256OfFileSync(path2) {
48514
48684
  }
48515
48685
  function quarantineCachedNpmInstall(spec, reason) {
48516
48686
  const packageDir = lspPackageDir(spec.npm);
48517
- const dest = join10(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
48687
+ const dest = join11(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
48518
48688
  warn2(`[lsp] tofu_mismatch ${spec.npm}: ${reason}; quarantining ${packageDir} -> ${dest}`);
48519
48689
  try {
48520
- mkdirSync6(join10(dest, ".."), { recursive: true });
48690
+ mkdirSync7(join11(dest, ".."), { recursive: true });
48521
48691
  rmSync3(dest, { recursive: true, force: true });
48522
48692
  renameSync4(packageDir, dest);
48523
48693
  } catch (err) {
@@ -48600,9 +48770,9 @@ import {
48600
48770
  copyFileSync as copyFileSync3,
48601
48771
  createReadStream as createReadStream2,
48602
48772
  createWriteStream as createWriteStream3,
48603
- existsSync as existsSync7,
48773
+ existsSync as existsSync8,
48604
48774
  lstatSync as lstatSync2,
48605
- mkdirSync as mkdirSync7,
48775
+ mkdirSync as mkdirSync8,
48606
48776
  readdirSync as readdirSync4,
48607
48777
  readFileSync as readFileSync6,
48608
48778
  readlinkSync as readlinkSync2,
@@ -48613,7 +48783,7 @@ import {
48613
48783
  unlinkSync as unlinkSync6,
48614
48784
  writeFileSync as writeFileSync5
48615
48785
  } from "node:fs";
48616
- import { dirname as dirname2, join as join11, relative as relative2, resolve as resolve2 } from "node:path";
48786
+ import { dirname as dirname3, join as join12, relative as relative2, resolve as resolve2 } from "node:path";
48617
48787
  import { Readable as Readable3 } from "node:stream";
48618
48788
  import { pipeline as pipeline3 } from "node:stream/promises";
48619
48789
 
@@ -48703,26 +48873,26 @@ function detectHostPlatform() {
48703
48873
 
48704
48874
  // src/lsp-github-install.ts
48705
48875
  function ghCacheRoot() {
48706
- return join11(aftCacheBase(), "lsp-binaries");
48876
+ return join12(aftCacheBase(), "lsp-binaries");
48707
48877
  }
48708
48878
  function ghPackageDir(spec) {
48709
- return join11(ghCacheRoot(), spec.id);
48879
+ return join12(ghCacheRoot(), spec.id);
48710
48880
  }
48711
48881
  function ghBinDir(spec) {
48712
- return join11(ghPackageDir(spec), "bin");
48882
+ return join12(ghPackageDir(spec), "bin");
48713
48883
  }
48714
48884
  function ghExtractDir(spec) {
48715
- return join11(ghPackageDir(spec), "extracted");
48885
+ return join12(ghPackageDir(spec), "extracted");
48716
48886
  }
48717
48887
  var INSTALLED_META_FILE2 = ".aft-installed";
48718
48888
  function ghBinaryPath(spec, platform) {
48719
48889
  const ext = platform === "win32" ? ".exe" : "";
48720
- return join11(ghBinDir(spec), `${spec.binary}${ext}`);
48890
+ return join12(ghBinDir(spec), `${spec.binary}${ext}`);
48721
48891
  }
48722
48892
  function isGithubInstalled(spec, platform) {
48723
48893
  for (const candidate of ghBinaryCandidates(spec, platform)) {
48724
48894
  try {
48725
- if (statSync5(join11(ghBinDir(spec), candidate)).isFile())
48895
+ if (statSync5(join12(ghBinDir(spec), candidate)).isFile())
48726
48896
  return true;
48727
48897
  } catch {}
48728
48898
  }
@@ -48735,7 +48905,7 @@ function ghBinaryCandidates(spec, platform) {
48735
48905
  }
48736
48906
  function readGithubInstalledMetaIn(installDir) {
48737
48907
  try {
48738
- const path2 = join11(installDir, INSTALLED_META_FILE2);
48908
+ const path2 = join12(installDir, INSTALLED_META_FILE2);
48739
48909
  if (!statSync5(path2).isFile())
48740
48910
  return null;
48741
48911
  const parsed = JSON.parse(readFileSync6(path2, "utf8"));
@@ -48754,7 +48924,7 @@ function readGithubInstalledMetaIn(installDir) {
48754
48924
  }
48755
48925
  function writeGithubInstalledMetaIn(installDir, version2, binarySha256, archiveSha256) {
48756
48926
  try {
48757
- mkdirSync7(installDir, { recursive: true });
48927
+ mkdirSync8(installDir, { recursive: true });
48758
48928
  const meta3 = {
48759
48929
  version: version2,
48760
48930
  installedAt: new Date().toISOString(),
@@ -48762,7 +48932,7 @@ function writeGithubInstalledMetaIn(installDir, version2, binarySha256, archiveS
48762
48932
  binarySha256,
48763
48933
  ...archiveSha256 ? { archiveSha256 } : {}
48764
48934
  };
48765
- writeFileSync5(join11(installDir, INSTALLED_META_FILE2), JSON.stringify(meta3), "utf8");
48935
+ writeFileSync5(join12(installDir, INSTALLED_META_FILE2), JSON.stringify(meta3), "utf8");
48766
48936
  } catch (err) {
48767
48937
  warn2(`[lsp] failed to write github installed metadata in ${installDir}: ${err}`);
48768
48938
  }
@@ -48955,7 +49125,7 @@ async function downloadFile(url2, destPath, fetchImpl2, assetSize, signal) {
48955
49125
  if (Number.isFinite(advertised) && advertised > MAX_DOWNLOAD_BYTES3) {
48956
49126
  throw new Error(`Content-Length ${advertised} exceeds max ${MAX_DOWNLOAD_BYTES3}`);
48957
49127
  }
48958
- mkdirSync7(dirname2(destPath), { recursive: true });
49128
+ mkdirSync8(dirname3(destPath), { recursive: true });
48959
49129
  let bytesWritten = 0;
48960
49130
  const guard = new TransformStream({
48961
49131
  transform(chunk, controller) {
@@ -49011,7 +49181,7 @@ function validateExtraction(stagingRoot) {
49011
49181
  throw new Error(`failed to read staging dir ${dir}: ${err}`);
49012
49182
  }
49013
49183
  for (const entry of entries) {
49014
- const full = join11(dir, entry);
49184
+ const full = join12(dir, entry);
49015
49185
  let lst;
49016
49186
  try {
49017
49187
  lst = lstatSync2(full);
@@ -49081,7 +49251,7 @@ function extractArchiveSafely(archivePath, destDir, archiveType) {
49081
49251
  try {
49082
49252
  rmSync4(stagingDir, { recursive: true, force: true });
49083
49253
  } catch {}
49084
- mkdirSync7(stagingDir, { recursive: true });
49254
+ mkdirSync8(stagingDir, { recursive: true });
49085
49255
  try {
49086
49256
  precheckArchiveContents(archivePath, archiveType);
49087
49257
  runPlatformExtractor(archivePath, stagingDir, archiveType);
@@ -49099,10 +49269,10 @@ function extractArchiveSafely(archivePath, destDir, archiveType) {
49099
49269
  }
49100
49270
  function quarantineCachedGithubInstall(spec, reason) {
49101
49271
  const packageDir = ghPackageDir(spec);
49102
- const dest = join11(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
49272
+ const dest = join12(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
49103
49273
  warn2(`[lsp] tofu_mismatch ${spec.id}: ${reason}; quarantining ${packageDir} -> ${dest}`);
49104
49274
  try {
49105
- mkdirSync7(dirname2(dest), { recursive: true });
49275
+ mkdirSync8(dirname3(dest), { recursive: true });
49106
49276
  rmSync4(dest, { recursive: true, force: true });
49107
49277
  renameSync5(packageDir, dest);
49108
49278
  } catch (err) {
@@ -49112,7 +49282,7 @@ function quarantineCachedGithubInstall(spec, reason) {
49112
49282
  function validateCachedGithubInstall(spec, platform) {
49113
49283
  const packageDir = ghPackageDir(spec);
49114
49284
  const meta3 = readGithubInstalledMetaIn(packageDir);
49115
- const binaryPath = ghBinaryCandidates(spec, platform).map((candidate) => join11(ghBinDir(spec), candidate)).find((candidate) => {
49285
+ const binaryPath = ghBinaryCandidates(spec, platform).map((candidate) => join12(ghBinDir(spec), candidate)).find((candidate) => {
49116
49286
  try {
49117
49287
  return statSync5(candidate).isFile();
49118
49288
  } catch {
@@ -49190,7 +49360,7 @@ async function downloadAndInstall(spec, tag, assets, platform, arch, fetchImpl2,
49190
49360
  }
49191
49361
  const pkgDir = ghPackageDir(spec);
49192
49362
  const extractDir = ghExtractDir(spec);
49193
- const archivePath = join11(pkgDir, expected.name);
49363
+ const archivePath = join12(pkgDir, expected.name);
49194
49364
  log2(`[lsp] downloading ${spec.id} ${tag} → ${matchingAsset.url}`);
49195
49365
  try {
49196
49366
  await downloadFile(matchingAsset.url, archivePath, fetchImpl2, matchingAsset.size, signal);
@@ -49230,13 +49400,13 @@ async function downloadAndInstall(spec, tag, assets, platform, arch, fetchImpl2,
49230
49400
  unlinkSync6(archivePath);
49231
49401
  } catch {}
49232
49402
  }
49233
- const innerBinaryPath = join11(extractDir, spec.binaryPathInArchive(platform, arch, version2));
49234
- if (!existsSync7(innerBinaryPath)) {
49403
+ const innerBinaryPath = join12(extractDir, spec.binaryPathInArchive(platform, arch, version2));
49404
+ if (!existsSync8(innerBinaryPath)) {
49235
49405
  error2(`[lsp] ${spec.id}: extracted binary not found at ${innerBinaryPath}`);
49236
49406
  return null;
49237
49407
  }
49238
49408
  const targetBinary = ghBinaryPath(spec, platform);
49239
- mkdirSync7(dirname2(targetBinary), { recursive: true });
49409
+ mkdirSync8(dirname3(targetBinary), { recursive: true });
49240
49410
  try {
49241
49411
  copyFileSync3(innerBinaryPath, targetBinary);
49242
49412
  if (platform !== "win32") {
@@ -49315,7 +49485,7 @@ function runGithubAutoInstall(relevantServers, config2, fetchImpl2 = fetch) {
49315
49485
  if (!host) {
49316
49486
  for (const spec of GITHUB_LSP_TABLE) {
49317
49487
  try {
49318
- if (existsSync7(ghBinDir(spec))) {
49488
+ if (existsSync8(ghBinDir(spec))) {
49319
49489
  cachedBinDirs.push(ghBinDir(spec));
49320
49490
  }
49321
49491
  } catch {}
@@ -49413,11 +49583,10 @@ function discoverRelevantGithubServers(projectRoot) {
49413
49583
  }
49414
49584
 
49415
49585
  // src/notifications.ts
49416
- import { existsSync as existsSync8, mkdirSync as mkdirSync8, readFileSync as readFileSync7, renameSync as renameSync6, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "node:fs";
49417
- import { join as join12 } from "node:path";
49586
+ import { existsSync as existsSync9, mkdirSync as mkdirSync9, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "node:fs";
49587
+ import { join as join13 } from "node:path";
49418
49588
  var WARNING_MARKER = "\uD83D\uDD27 AFT: ⚠️";
49419
49589
  var FEATURE_MARKER = "\uD83D\uDD27 AFT: ✨";
49420
- var WARNED_TOOLS_FILE = "warned_tools.json";
49421
49590
  function sendIgnoredMessage(client, sessionId, text) {
49422
49591
  const typedClient = client;
49423
49592
  if (typeof typedClient.ui?.notify !== "function")
@@ -49430,55 +49599,36 @@ function sendIgnoredMessage(client, sessionId, text) {
49430
49599
  return false;
49431
49600
  }
49432
49601
  }
49433
- function readWarnedTools(storageDir) {
49602
+ async function readWarnedTools(bridge) {
49434
49603
  try {
49435
- const warnedToolsPath = join12(storageDir, WARNED_TOOLS_FILE);
49436
- if (!existsSync8(warnedToolsPath))
49604
+ const resp = await bridge.send("db_get_state", { key: "warned_tools" });
49605
+ if (resp.success === false)
49606
+ return {};
49607
+ const value = resp.data?.value;
49608
+ if (typeof value !== "string")
49437
49609
  return {};
49438
- const parsed = JSON.parse(readFileSync7(warnedToolsPath, "utf-8"));
49610
+ const parsed = JSON.parse(value);
49439
49611
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
49440
49612
  return {};
49441
- const warned = {};
49442
- for (const [key, version2] of Object.entries(parsed)) {
49443
- if (typeof version2 === "string") {
49444
- warned[key] = version2;
49445
- }
49446
- }
49447
- return warned;
49613
+ return parsed;
49448
49614
  } catch {
49449
49615
  return {};
49450
49616
  }
49451
49617
  }
49452
- function writeWarnedTools(storageDir, warned) {
49618
+ async function hasWarnedFor(bridge, key) {
49619
+ const warned = await readWarnedTools(bridge);
49620
+ return warned[key] === true || typeof warned[key] === "string";
49621
+ }
49622
+ async function recordWarning(bridge, key) {
49623
+ const warned = await readWarnedTools(bridge);
49624
+ warned[key] = true;
49453
49625
  try {
49454
- mkdirSync8(storageDir, { recursive: true });
49455
- const warnedToolsPath = join12(storageDir, WARNED_TOOLS_FILE);
49456
- const tmpPath = join12(storageDir, `${WARNED_TOOLS_FILE}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
49457
- writeFileSync6(tmpPath, `${JSON.stringify(warned, null, 2)}
49458
- `);
49459
- renameSync6(tmpPath, warnedToolsPath);
49626
+ await bridge.send("db_set_state", {
49627
+ key: "warned_tools",
49628
+ value: JSON.stringify(warned)
49629
+ });
49460
49630
  } catch {}
49461
49631
  }
49462
- async function withWarnedToolsLock(storageDir, fn) {
49463
- const lockDir = join12(storageDir, "warned_tools.lock");
49464
- for (let attempt = 0;attempt < 5; attempt++) {
49465
- try {
49466
- mkdirSync8(storageDir, { recursive: true });
49467
- mkdirSync8(lockDir, { mode: 448 });
49468
- try {
49469
- return await fn();
49470
- } finally {
49471
- rmSync5(lockDir, { recursive: true, force: true });
49472
- }
49473
- } catch (err) {
49474
- const code = err.code;
49475
- if (code !== "EEXIST")
49476
- return null;
49477
- await new Promise((resolve3) => setTimeout(resolve3, 10 * (attempt + 1)));
49478
- }
49479
- }
49480
- return null;
49481
- }
49482
49632
  function warningKey(warning, projectRoot) {
49483
49633
  const scope = warning.kind === "lsp_binary_missing" ? "_" : projectRoot ?? "_";
49484
49634
  return [
@@ -49517,35 +49667,19 @@ ${warning.hint}`;
49517
49667
  async function deliverConfigureWarnings(opts, warnings) {
49518
49668
  if (warnings.length === 0)
49519
49669
  return;
49520
- const deliveredWithLock = await withWarnedToolsLock(opts.storageDir, async () => {
49521
- const warned = readWarnedTools(opts.storageDir);
49522
- let changed = false;
49523
- for (const warning of warnings) {
49524
- const key = warningKey(warning, opts.projectRoot);
49525
- if (Object.hasOwn(warned, key))
49526
- continue;
49527
- if (!sendIgnoredMessage(opts.client, opts.sessionId, formatConfigureWarning(warning))) {
49528
- continue;
49529
- }
49530
- warned[key] = opts.pluginVersion;
49531
- changed = true;
49532
- }
49533
- if (changed) {
49534
- const merged = { ...readWarnedTools(opts.storageDir), ...warned };
49535
- writeWarnedTools(opts.storageDir, merged);
49536
- }
49537
- return true;
49538
- });
49539
- if (deliveredWithLock)
49540
- return;
49541
49670
  for (const warning of warnings) {
49542
- sendIgnoredMessage(opts.client, opts.sessionId, formatConfigureWarning(warning));
49671
+ const key = warningKey(warning, opts.projectRoot);
49672
+ if (await hasWarnedFor(opts.bridge, key))
49673
+ continue;
49674
+ if (!sendIgnoredMessage(opts.client, opts.sessionId, formatConfigureWarning(warning)))
49675
+ continue;
49676
+ await recordWarning(opts.bridge, key);
49543
49677
  }
49544
49678
  }
49545
49679
  function sendFeatureAnnouncement(version2, features, storageDir) {
49546
- const versionFile = join12(storageDir, "last_announced_version");
49680
+ const versionFile = join13(storageDir, "last_announced_version");
49547
49681
  try {
49548
- if (existsSync8(versionFile)) {
49682
+ if (existsSync9(versionFile)) {
49549
49683
  const lastVersion = readFileSync7(versionFile, "utf-8").trim();
49550
49684
  if (lastVersion === version2)
49551
49685
  return;
@@ -49554,7 +49688,7 @@ function sendFeatureAnnouncement(version2, features, storageDir) {
49554
49688
  log2([`${FEATURE_MARKER} v${version2}:`, ...features.map((feature) => ` • ${feature}`)].join(`
49555
49689
  `));
49556
49690
  try {
49557
- mkdirSync8(storageDir, { recursive: true });
49691
+ mkdirSync9(storageDir, { recursive: true });
49558
49692
  writeFileSync6(versionFile, version2);
49559
49693
  } catch {}
49560
49694
  }
@@ -49616,7 +49750,7 @@ import { StringEnum } from "@earendil-works/pi-ai";
49616
49750
  import { Type } from "typebox";
49617
49751
 
49618
49752
  // src/tools/render-helpers.ts
49619
- import { homedir as homedir7 } from "node:os";
49753
+ import { homedir as homedir8 } from "node:os";
49620
49754
  import { renderDiff } from "@earendil-works/pi-coding-agent";
49621
49755
  import { Container, Spacer, Text } from "@earendil-works/pi-tui";
49622
49756
  function reuseText(last) {
@@ -49626,7 +49760,7 @@ function reuseContainer(last) {
49626
49760
  return last instanceof Container ? last : new Container;
49627
49761
  }
49628
49762
  function shortenPath(path2) {
49629
- const home = homedir7();
49763
+ const home = homedir8();
49630
49764
  if (path2.startsWith(home))
49631
49765
  return `~${path2.slice(home.length)}`;
49632
49766
  return path2;
@@ -50510,7 +50644,7 @@ function registerFsTools(pi, ctx, surface) {
50510
50644
 
50511
50645
  // src/tools/hoisted.ts
50512
50646
  import { stat } from "node:fs/promises";
50513
- import { homedir as homedir8 } from "node:os";
50647
+ import { homedir as homedir9 } from "node:os";
50514
50648
  import { isAbsolute, relative as relative3, resolve as resolve3 } from "node:path";
50515
50649
  import {
50516
50650
  renderDiff as renderDiff2
@@ -50707,7 +50841,7 @@ function registerHoistedTools(pi, ctx, surface) {
50707
50841
  promptGuidelines: ["Use write only for new files or complete rewrites."],
50708
50842
  parameters: WriteParams,
50709
50843
  async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
50710
- await assertExternalDirectoryPermission(extCtx, params.filePath);
50844
+ await assertExternalDirectoryPermission(extCtx, params.filePath, "modify");
50711
50845
  const bridge = bridgeFor(ctx, extCtx.cwd);
50712
50846
  const response = await callBridge(bridge, "write", {
50713
50847
  file: params.filePath,
@@ -50738,7 +50872,7 @@ function registerHoistedTools(pi, ctx, surface) {
50738
50872
  ],
50739
50873
  parameters: EditParams,
50740
50874
  async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
50741
- await assertExternalDirectoryPermission(extCtx, params.filePath);
50875
+ await assertExternalDirectoryPermission(extCtx, params.filePath, "modify");
50742
50876
  const bridge = bridgeFor(ctx, extCtx.cwd);
50743
50877
  if (typeof params.appendContent === "string") {
50744
50878
  const req2 = {
@@ -50808,6 +50942,7 @@ function buildMutationResult(filePath, response) {
50808
50942
  const replacements = response.replacements;
50809
50943
  const diagnostics = response.lsp_diagnostics;
50810
50944
  const truncated = diffObj?.truncated === true;
50945
+ const noOp = response.no_op === true;
50811
50946
  const formatted = response.formatted;
50812
50947
  const formatSkippedReason = response.format_skipped_reason;
50813
50948
  const globFormatSkipReasons = response.format_skip_reasons;
@@ -50828,6 +50963,11 @@ ${diffText}`;
50828
50963
  text += `
50829
50964
 
50830
50965
  (diff truncated — file too large to include before/after content)`;
50966
+ }
50967
+ if (noOp) {
50968
+ text += `
50969
+
50970
+ Note: no net file change — the match was found and applied, but the file content is byte-identical to before. Likely causes: oldString and newString are identical, or a formatter normalized the change away.`;
50831
50971
  }
50832
50972
  const skipNote = formatSkipReasonNote(formatSkippedReason);
50833
50973
  if (skipNote)
@@ -50856,7 +50996,8 @@ ${formatDiagnosticsText(diagnostics)}`;
50856
50996
  diagnostics,
50857
50997
  truncated: truncated || undefined,
50858
50998
  formatted,
50859
- formatSkippedReason
50999
+ formatSkippedReason,
51000
+ noOp: noOp || undefined
50860
51001
  }
50861
51002
  };
50862
51003
  }
@@ -50927,7 +51068,12 @@ ${theme.fg("error", errorText || "edit failed")}`);
50927
51068
  const deletions = details?.deletions ?? 0;
50928
51069
  const text = reuseText3(context.lastComponent);
50929
51070
  const summary = theme.fg("success", `+${additions}/-${deletions}`);
50930
- const suffix = details?.truncated ? ` ${theme.fg("muted", "(diff truncated)")}` : "";
51071
+ let suffix = "";
51072
+ if (details?.truncated) {
51073
+ suffix = ` ${theme.fg("muted", "(diff truncated)")}`;
51074
+ } else if (details?.noOp) {
51075
+ suffix = ` ${theme.fg("muted", "(no net change)")}`;
51076
+ }
50931
51077
  text.setText(`
50932
51078
  ${summary}${suffix}`);
50933
51079
  return text;
@@ -50939,7 +51085,7 @@ ${summary}${suffix}`);
50939
51085
  return container;
50940
51086
  }
50941
51087
  function shortenPath2(path2) {
50942
- const home = homedir8();
51088
+ const home = homedir9();
50943
51089
  if (path2.startsWith(home))
50944
51090
  return `~${path2.slice(home.length)}`;
50945
51091
  return path2;
@@ -50978,9 +51124,9 @@ function splitIncludeGlobs(include) {
50978
51124
  }
50979
51125
  buf += ch;
50980
51126
  }
50981
- const tail = buf.trim();
50982
- if (tail.length > 0)
50983
- out.push(tail);
51127
+ const tail2 = buf.trim();
51128
+ if (tail2.length > 0)
51129
+ out.push(tail2);
50984
51130
  return out;
50985
51131
  }
50986
51132
  function formatReadFooter(agentSpecifiedRange, data) {
@@ -52201,15 +52347,12 @@ var PLUGIN_VERSION = (() => {
52201
52347
  return "0.0.0";
52202
52348
  }
52203
52349
  })();
52204
- var ANNOUNCEMENT_VERSION = "0.18.0";
52350
+ var ANNOUNCEMENT_VERSION = "0.27.0";
52205
52351
  var ANNOUNCEMENT_FEATURES = [
52206
- `New experimental features AFT now optionally hoists bash:
52207
- - Run bash scripts in the background.
52208
- - Initial output compression for git, cargo, npm, bun, pnpm, pytest, tsc (more in 0.19).
52209
- - Rewrite cat/grep/find/sed/ls into AFT counterparts for faster, formatted output.
52210
- Check GitHub for how to enable.`,
52211
- "Trigram grep/glob and semantic search (aft_search) graduated out of experimental.",
52212
- "Lots of bugfixes and new end-to-end test coverage."
52352
+ "Storage moved to ~/.local/share/cortexkit/aft (~/Library/Application Support/cortexkit/aft on macOS, %APPDATA%/cortexkit/aft on Windows). Your existing data migrated automatically on first launch.",
52353
+ "Bash output compression now reports token savings — visible in /aft-status (Session + Project totals).",
52354
+ "Seven new languages supported by aft_outline / aft_zoom / aft_search / ast_grep: Java, Ruby, Kotlin, Swift, PHP, Lua, Perl.",
52355
+ "Join us on Discord: https://discord.gg/F2uWxjGnU"
52213
52356
  ];
52214
52357
  var ALL_ONLY_TOOLS = new Set([
52215
52358
  "aft_navigate",
@@ -52259,14 +52402,12 @@ async function handleConfigureWarningsForSession(context) {
52259
52402
  await deliverConfigureWarnings({
52260
52403
  client: context.client,
52261
52404
  sessionId: context.sessionId,
52405
+ bridge: context.bridge,
52262
52406
  storageDir: context.storageDir,
52263
52407
  pluginVersion: context.pluginVersion,
52264
52408
  projectRoot: context.projectRoot
52265
52409
  }, combinedWarnings);
52266
52410
  }
52267
- function resolveStorageDir() {
52268
- return join13(homedir9(), ".pi", "agent", "aft");
52269
- }
52270
52411
  function resolveToolSurface(config2) {
52271
52412
  const surface = config2.tool_surface ?? "recommended";
52272
52413
  const disabled = new Set(config2.disabled_tools ?? []);
@@ -52337,8 +52478,9 @@ async function src_default(pi) {
52337
52478
  warn2(`Failed to resolve AFT binary: ${err instanceof Error ? err.message : String(err)}. ` + "Tools will not be registered.");
52338
52479
  return;
52339
52480
  }
52481
+ await ensureStorageMigrated({ harness: "pi", binaryPath, logger: bridgeLogger });
52340
52482
  const config2 = loadAftConfig(process.cwd());
52341
- const storageDir = resolveStorageDir();
52483
+ const storageDir = resolveCortexKitStorageRoot();
52342
52484
  let onnxRuntimePromise = null;
52343
52485
  if (shouldPrepareOnnxRuntime(config2)) {
52344
52486
  onnxRuntimePromise = ensureOnnxRuntime(storageDir).catch((err) => {
@@ -52439,16 +52581,22 @@ ${lines}
52439
52581
  errorPrefix: "[aft-pi]",
52440
52582
  minVersion: PLUGIN_VERSION,
52441
52583
  onVersionMismatch: createVersionMismatchHandler(() => pool),
52442
- onConfigureWarnings: async ({ projectRoot, sessionId, client, warnings }) => {
52584
+ onConfigureWarnings: ({ projectRoot, sessionId, client, warnings }) => {
52585
+ const bridge = pool.getActiveBridgeForRoot(projectRoot);
52586
+ if (!bridge)
52587
+ return;
52443
52588
  const pendingWarnings = sessionId ? drainPendingEagerWarnings(projectRoot) : [];
52444
- await handleConfigureWarningsForSession({
52445
- projectRoot,
52446
- sessionId,
52447
- client,
52448
- warnings: [...pendingWarnings, ...warnings],
52449
- storageDir,
52450
- pluginVersion: PLUGIN_VERSION
52451
- });
52589
+ setTimeout(() => {
52590
+ handleConfigureWarningsForSession({
52591
+ projectRoot,
52592
+ sessionId,
52593
+ client,
52594
+ bridge,
52595
+ warnings: [...pendingWarnings, ...warnings],
52596
+ storageDir,
52597
+ pluginVersion: PLUGIN_VERSION
52598
+ });
52599
+ }, 0);
52452
52600
  },
52453
52601
  onBashCompletion: (completion) => {
52454
52602
  handlePushedBgCompletion({
@@ -52468,6 +52616,7 @@ ${lines}
52468
52616
  }
52469
52617
  };
52470
52618
  pool = new BridgePool(binaryPath, poolOptions, configOverrides);
52619
+ pool.setConfigureOverride("harness", "pi");
52471
52620
  const ctx = { pool, config: config2, storageDir };
52472
52621
  if (onnxRuntimePromise) {
52473
52622
  onnxRuntimePromise.then((ortDylibDir) => {