@cortexkit/aft-pi 0.25.1 → 0.26.0

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.d.ts CHANGED
@@ -31,6 +31,10 @@
31
31
  */
32
32
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
33
33
  import { type AftConfig, loadAftConfig } from "./config.js";
34
+ type VersionMismatchPool = {
35
+ replaceBinary(path: string): Promise<string>;
36
+ };
37
+ declare function createVersionMismatchHandler(getPool: () => VersionMismatchPool | undefined, ensureCompatibleBinary?: (version?: string) => Promise<string | null>): (binaryVersion: string, minVersion: string) => Promise<string | null>;
34
38
  declare function shouldPrepareOnnxRuntime(config: Pick<AftConfig, "semantic_search" | "semantic">): boolean;
35
39
  declare function handleConfigureWarningsForSession(context: {
36
40
  projectRoot: string;
@@ -80,6 +84,7 @@ export declare const __test__: {
80
84
  resolveToolSurface: typeof resolveToolSurface;
81
85
  handleConfigureWarningsForSession: typeof handleConfigureWarningsForSession;
82
86
  shouldPrepareOnnxRuntime: typeof shouldPrepareOnnxRuntime;
87
+ createVersionMismatchHandler: typeof createVersionMismatchHandler;
83
88
  };
84
89
  export {};
85
90
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAaH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAQpE,OAAO,EACL,KAAK,SAAS,EACd,aAAa,EAGd,MAAM,aAAa,CAAC;AAgGrB,iBAAS,wBAAwB,CAC/B,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE,iBAAiB,GAAG,UAAU,CAAC,GACtD,OAAO,CAGT;AASD,iBAAe,iCAAiC,CAAC,OAAO,EAAE;IACxD,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgChB;AAQD;;;;;;;;GAQG;AACH,iBAAS,kBAAkB,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,GAAG;IACrE,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAiEA;AAED;;;;GAIG;AACH,yBAA+B,EAAE,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA6Z9D;AAED,eAAO,MAAM,QAAQ;;;;CAIpB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAcH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAQpE,OAAO,EACL,KAAK,SAAS,EACd,aAAa,EAGd,MAAM,aAAa,CAAC;AAgDrB,KAAK,mBAAmB,GAAG;IACzB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9C,CAAC;AAEF,iBAAS,4BAA4B,CACnC,OAAO,EAAE,MAAM,mBAAmB,GAAG,SAAS,EAC9C,sBAAsB,GAAE,CAAC,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAgB,IAOrE,eAAe,MAAM,EAAE,YAAY,MAAM,KAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAkCjF;AAkDD,iBAAS,wBAAwB,CAC/B,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE,iBAAiB,GAAG,UAAU,CAAC,GACtD,OAAO,CAGT;AASD,iBAAe,iCAAiC,CAAC,OAAO,EAAE;IACxD,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgChB;AAQD;;;;;;;;GAQG;AACH,iBAAS,kBAAkB,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,GAAG;IACrE,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAiEA;AAED;;;;GAIG;AACH,yBAA+B,EAAE,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA+Z9D;AAED,eAAO,MAAM,QAAQ;;;;;CAKpB,CAAC"}
package/dist/index.js CHANGED
@@ -30601,6 +30601,15 @@ function clampSemanticTimeout(configOverrides, bridgeTimeoutMs) {
30601
30601
  };
30602
30602
  }
30603
30603
 
30604
+ class BridgeReplacedDuringVersionCheck extends Error {
30605
+ newBinaryPath;
30606
+ constructor(newBinaryPath) {
30607
+ super(`Bridge binary replaced during version check: ${newBinaryPath}`);
30608
+ this.newBinaryPath = newBinaryPath;
30609
+ this.name = "BridgeReplacedDuringVersionCheck";
30610
+ }
30611
+ }
30612
+
30604
30613
  class BinaryBridge {
30605
30614
  static RESTART_RESET_MS = 5 * 60 * 1000;
30606
30615
  static STDERR_TAIL_MAX = 20;
@@ -30689,97 +30698,108 @@ class BinaryBridge {
30689
30698
  this.cachedStatus = snapshot;
30690
30699
  }
30691
30700
  async send(command, params = {}, options) {
30692
- if (this._shuttingDown) {
30693
- throw new Error(`${this.errorPrefix} Bridge is shutting down, cannot send "${command}"`);
30694
- }
30695
- if (Object.hasOwn(params, "id")) {
30696
- throw new Error("params cannot contain reserved key 'id'");
30697
- }
30698
- const requestSessionId = typeof params.session_id === "string" && params.session_id.length > 0 ? params.session_id : undefined;
30699
- this.ensureSpawned(requestSessionId);
30700
- if (requestSessionId && options?.configureWarningClient !== undefined) {
30701
- this.configureWarningClients.set(requestSessionId, options.configureWarningClient);
30702
- }
30703
- if (!this.configured) {
30704
- if (command !== "configure" && command !== "version") {
30705
- if (!this._configurePromise) {
30706
- const sessionIdForConfigure = typeof params.session_id === "string" ? params.session_id : undefined;
30707
- this._configurePromise = (async () => {
30708
- try {
30709
- const configResult = await this.send("configure", {
30710
- project_root: this.cwd,
30711
- ...this.configOverrides,
30712
- ...sessionIdForConfigure ? { session_id: sessionIdForConfigure } : {}
30713
- });
30714
- if (configResult.success === false) {
30715
- throw new Error(`${this.errorPrefix} Configure failed: ${configResult.message ?? "unknown error"}`);
30716
- }
30717
- await this.deliverConfigureWarnings(configResult, params, options);
30718
- await this.checkVersion();
30719
- if (!this.isAlive()) {
30720
- throw new Error(`${this.errorPrefix} Bridge died during version check. Check logs: ${getLogFilePath()}`);
30701
+ return this.sendWithVersionMismatchRetry(command, params, options, true);
30702
+ }
30703
+ async sendWithVersionMismatchRetry(command, params, options, canRetryAfterVersionSwap) {
30704
+ try {
30705
+ if (this._shuttingDown) {
30706
+ throw new Error(`${this.errorPrefix} Bridge is shutting down, cannot send "${command}"`);
30707
+ }
30708
+ if (Object.hasOwn(params, "id")) {
30709
+ throw new Error("params cannot contain reserved key 'id'");
30710
+ }
30711
+ const requestSessionId = typeof params.session_id === "string" && params.session_id.length > 0 ? params.session_id : undefined;
30712
+ this.ensureSpawned(requestSessionId);
30713
+ if (requestSessionId && options?.configureWarningClient !== undefined) {
30714
+ this.configureWarningClients.set(requestSessionId, options.configureWarningClient);
30715
+ }
30716
+ if (!this.configured) {
30717
+ if (command !== "configure" && command !== "version") {
30718
+ if (!this._configurePromise) {
30719
+ const sessionIdForConfigure = typeof params.session_id === "string" ? params.session_id : undefined;
30720
+ this._configurePromise = (async () => {
30721
+ try {
30722
+ const configResult = await this.send("configure", {
30723
+ project_root: this.cwd,
30724
+ ...this.configOverrides,
30725
+ ...sessionIdForConfigure ? { session_id: sessionIdForConfigure } : {}
30726
+ });
30727
+ if (configResult.success === false) {
30728
+ throw new Error(`${this.errorPrefix} Configure failed: ${configResult.message ?? "unknown error"}`);
30729
+ }
30730
+ await this.deliverConfigureWarnings(configResult, params, options);
30731
+ await this.checkVersion();
30732
+ if (!this.isAlive()) {
30733
+ throw new Error(`${this.errorPrefix} Bridge died during version check. Check logs: ${getLogFilePath()}`);
30734
+ }
30735
+ this.configured = true;
30736
+ } finally {
30737
+ this._configurePromise = null;
30721
30738
  }
30722
- this.configured = true;
30723
- } finally {
30724
- this._configurePromise = null;
30725
- }
30726
- })();
30739
+ })();
30740
+ }
30741
+ await this._configurePromise;
30727
30742
  }
30728
- await this._configurePromise;
30729
30743
  }
30730
- }
30731
- const id = String(this.nextId++);
30732
- let request;
30733
- if (Object.hasOwn(params, "command") || Object.hasOwn(params, "method")) {
30734
- const nested = { ...params };
30735
- const reserved = {};
30736
- for (const key of ["session_id", "lsp_hints"]) {
30737
- if (Object.hasOwn(nested, key)) {
30738
- reserved[key] = nested[key];
30739
- delete nested[key];
30744
+ const id = String(this.nextId++);
30745
+ let request;
30746
+ if (Object.hasOwn(params, "command") || Object.hasOwn(params, "method")) {
30747
+ const nested = { ...params };
30748
+ const reserved = {};
30749
+ for (const key of ["session_id", "lsp_hints"]) {
30750
+ if (Object.hasOwn(nested, key)) {
30751
+ reserved[key] = nested[key];
30752
+ delete nested[key];
30753
+ }
30740
30754
  }
30755
+ request = { id, command, ...reserved, params: nested };
30756
+ } else {
30757
+ request = { id, command, ...params };
30741
30758
  }
30742
- request = { id, command, ...reserved, params: nested };
30743
- } else {
30744
- request = { id, command, ...params };
30745
- }
30746
- const line = `${JSON.stringify(request)}
30759
+ const line = `${JSON.stringify(request)}
30747
30760
  `;
30748
- const effectiveTimeoutMs = options?.transportTimeoutMs ?? options?.timeoutMs ?? this.timeoutMs;
30749
- const keepBridgeOnTimeout = options?.keepBridgeOnTimeout === true;
30750
- return new Promise((resolve, reject) => {
30751
- const timer = setTimeout(() => {
30752
- this.pending.delete(id);
30753
- const restartSuffix = keepBridgeOnTimeout ? "" : " — restarting bridge";
30754
- const timeoutMsg = `Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms${restartSuffix}`;
30755
- if (requestSessionId) {
30756
- sessionWarn(requestSessionId, timeoutMsg);
30757
- } else {
30758
- warn(timeoutMsg);
30759
- }
30760
- reject(new Error(`${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`));
30761
- if (!keepBridgeOnTimeout) {
30762
- this.handleTimeout(requestSessionId);
30763
- }
30764
- }, effectiveTimeoutMs);
30765
- this.pending.set(id, { resolve, reject, timer, onProgress: options?.onProgress });
30766
- if (!this.process?.stdin?.writable) {
30767
- this.pending.delete(id);
30768
- clearTimeout(timer);
30769
- reject(new Error(`${this.errorPrefix} stdin not writable for command "${command}"`));
30770
- return;
30771
- }
30772
- this.process.stdin.write(line, (err) => {
30773
- if (err) {
30774
- const entry = this.pending.get(id);
30775
- if (entry) {
30776
- this.pending.delete(id);
30777
- clearTimeout(entry.timer);
30778
- entry.reject(new Error(`${this.errorPrefix} Failed to write to stdin: ${err.message}`));
30761
+ const effectiveTimeoutMs = options?.transportTimeoutMs ?? options?.timeoutMs ?? this.timeoutMs;
30762
+ const keepBridgeOnTimeout = options?.keepBridgeOnTimeout === true;
30763
+ return new Promise((resolve, reject) => {
30764
+ const timer = setTimeout(() => {
30765
+ this.pending.delete(id);
30766
+ const restartSuffix = keepBridgeOnTimeout ? "" : " — restarting bridge";
30767
+ const timeoutMsg = `Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms${restartSuffix}`;
30768
+ if (requestSessionId) {
30769
+ sessionWarn(requestSessionId, timeoutMsg);
30770
+ } else {
30771
+ warn(timeoutMsg);
30779
30772
  }
30773
+ reject(new Error(`${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`));
30774
+ if (!keepBridgeOnTimeout) {
30775
+ this.handleTimeout(requestSessionId);
30776
+ }
30777
+ }, effectiveTimeoutMs);
30778
+ this.pending.set(id, { resolve, reject, timer, onProgress: options?.onProgress });
30779
+ if (!this.process?.stdin?.writable) {
30780
+ this.pending.delete(id);
30781
+ clearTimeout(timer);
30782
+ reject(new Error(`${this.errorPrefix} stdin not writable for command "${command}"`));
30783
+ return;
30780
30784
  }
30785
+ this.process.stdin.write(line, (err) => {
30786
+ if (err) {
30787
+ const entry = this.pending.get(id);
30788
+ if (entry) {
30789
+ this.pending.delete(id);
30790
+ clearTimeout(entry.timer);
30791
+ entry.reject(new Error(`${this.errorPrefix} Failed to write to stdin: ${err.message}`));
30792
+ }
30793
+ }
30794
+ });
30781
30795
  });
30782
- });
30796
+ } catch (err) {
30797
+ if (err instanceof BridgeReplacedDuringVersionCheck && canRetryAfterVersionSwap && command !== "configure" && command !== "version") {
30798
+ log(`Retrying request "${command}" once after coordinated binary replacement: ${err.newBinaryPath}`);
30799
+ return this.sendWithVersionMismatchRetry(command, params, options, false);
30800
+ }
30801
+ throw err;
30802
+ }
30783
30803
  }
30784
30804
  async deliverConfigureWarnings(configResult, params, options) {
30785
30805
  if (!this.onConfigureWarnings || !Array.isArray(configResult.warnings))
@@ -30878,13 +30898,43 @@ class BinaryBridge {
30878
30898
  log(`Binary version: ${binaryVersion}`);
30879
30899
  if (compareSemver(binaryVersion, this.minVersion) < 0) {
30880
30900
  warn(`Binary version ${binaryVersion} is older than required ${this.minVersion}`);
30881
- this.onVersionMismatch?.(binaryVersion, this.minVersion);
30901
+ const replacementPath = await this.onVersionMismatch?.(binaryVersion, this.minVersion);
30902
+ if (replacementPath === undefined) {
30903
+ return;
30904
+ }
30905
+ if (replacementPath === null || replacementPath.length === 0) {
30906
+ throw new Error(`Binary version ${binaryVersion} is older than required ${this.minVersion}; no compatible replacement binary was provided`);
30907
+ }
30908
+ await this.replaceCurrentBinary(replacementPath);
30909
+ throw new BridgeReplacedDuringVersionCheck(replacementPath);
30882
30910
  }
30883
30911
  } catch (err) {
30884
30912
  warn(`Version check failed: ${err.message}`);
30885
30913
  throw err;
30886
30914
  }
30887
30915
  }
30916
+ async replaceCurrentBinary(newBinaryPath) {
30917
+ this.binaryPath = newBinaryPath;
30918
+ this.configured = false;
30919
+ this.clearRestartResetTimer();
30920
+ this.rejectAllPending(new Error(`${this.errorPrefix} Bridge restarting with updated binary: ${newBinaryPath}`));
30921
+ if (!this.process)
30922
+ return;
30923
+ const proc = this.process;
30924
+ this.process = null;
30925
+ await new Promise((resolve) => {
30926
+ const forceKillTimer = setTimeout(() => {
30927
+ proc.kill("SIGKILL");
30928
+ resolve();
30929
+ }, 5000);
30930
+ proc.once("exit", () => {
30931
+ clearTimeout(forceKillTimer);
30932
+ log("Process exited during coordinated binary replacement");
30933
+ resolve();
30934
+ });
30935
+ proc.kill("SIGTERM");
30936
+ });
30937
+ }
30888
30938
  ensureSpawned(triggeringSessionId) {
30889
30939
  if (this.isAlive())
30890
30940
  return;
@@ -31189,11 +31239,12 @@ async function downloadBinary(version) {
31189
31239
  error(`Unsupported platform: ${process.platform}-${process.arch}`);
31190
31240
  return null;
31191
31241
  }
31192
- const tag = version ?? await fetchLatestTag();
31193
- if (!tag) {
31242
+ const rawTag = version ?? await fetchLatestTag();
31243
+ if (!rawTag) {
31194
31244
  error("Could not determine latest release version.");
31195
31245
  return null;
31196
31246
  }
31247
+ const tag = rawTag.startsWith("v") ? rawTag : `v${rawTag}`;
31197
31248
  const versionedCacheDir = join2(getCacheDir(), tag);
31198
31249
  const binaryName = getBinaryName();
31199
31250
  const binaryPath = join2(versionedCacheDir, binaryName);
@@ -31255,13 +31306,14 @@ async function downloadBinary(version) {
31255
31306
  }
31256
31307
  async function ensureBinary(version) {
31257
31308
  if (version) {
31258
- const versionCached = getCachedBinaryPath(version);
31309
+ const tag = version.startsWith("v") ? version : `v${version}`;
31310
+ const versionCached = getCachedBinaryPath(tag);
31259
31311
  if (versionCached) {
31260
- log(`Found cached binary for ${version}: ${versionCached}`);
31312
+ log(`Found cached binary for ${tag}: ${versionCached}`);
31261
31313
  return versionCached;
31262
31314
  }
31263
- log(`No cached binary for ${version}, downloading...`);
31264
- return downloadBinary(version);
31315
+ log(`No cached binary for ${tag}, downloading...`);
31316
+ return downloadBinary(tag);
31265
31317
  }
31266
31318
  log("No cached binary found, downloading latest...");
31267
31319
  return downloadBinary();
@@ -31967,6 +32019,7 @@ class BridgePool {
31967
32019
  this.bridges.clear();
31968
32020
  await Promise.allSettled(shutdowns);
31969
32021
  this.log(`Binary path updated to ${newPath}. All bridges cleared — next calls will use the new binary.`);
32022
+ return newPath;
31970
32023
  }
31971
32024
  log(message, meta) {
31972
32025
  const logger = this.logger ?? getActiveLogger();
@@ -32017,7 +32070,9 @@ function readBinaryVersion(binaryPath) {
32017
32070
  stdio: ["pipe", "pipe", "pipe"],
32018
32071
  timeout: 5000
32019
32072
  });
32020
- const rawVersion = result.stdout?.trim();
32073
+ const stdoutVersion = result.stdout?.trim();
32074
+ const stderrVersion = result.stderr?.trim();
32075
+ const rawVersion = stdoutVersion || stderrVersion;
32021
32076
  if (!rawVersion)
32022
32077
  return null;
32023
32078
  return rawVersion.replace(/^aft\s+/, "");
@@ -32496,6 +32551,7 @@ async function fetchUrlToTempFile(url, storageDir, options = {}) {
32496
32551
  throw new Error(`Only http:// and https:// URLs are supported, got: ${parsed.protocol}`);
32497
32552
  }
32498
32553
  const allowPrivate = options.allowPrivate === true;
32554
+ await assertPublicUrl(parsed, allowPrivate, options.lookup);
32499
32555
  const dir = cacheDir(storageDir);
32500
32556
  mkdirSync4(dir, { recursive: true });
32501
32557
  const hash = hashUrl(url);
@@ -32999,7 +33055,7 @@ import {
32999
33055
  // package.json
33000
33056
  var package_default = {
33001
33057
  name: "@cortexkit/aft-pi",
33002
- version: "0.25.1",
33058
+ version: "0.26.0",
33003
33059
  type: "module",
33004
33060
  description: "Pi coding agent extension for Agent File Tools (AFT) — tree-sitter and LSP-powered code analysis",
33005
33061
  main: "dist/index.js",
@@ -33021,18 +33077,18 @@ var package_default = {
33021
33077
  prepublishOnly: "bun run build"
33022
33078
  },
33023
33079
  dependencies: {
33024
- "@cortexkit/aft-bridge": "0.25.1",
33080
+ "@cortexkit/aft-bridge": "0.26.0",
33025
33081
  typebox: "^1.1.24",
33026
33082
  "comment-json": "^5.0.0",
33027
33083
  diff: "^8.0.4",
33028
33084
  zod: "^4.1.8"
33029
33085
  },
33030
33086
  optionalDependencies: {
33031
- "@cortexkit/aft-darwin-arm64": "0.25.1",
33032
- "@cortexkit/aft-darwin-x64": "0.25.1",
33033
- "@cortexkit/aft-linux-arm64": "0.25.1",
33034
- "@cortexkit/aft-linux-x64": "0.25.1",
33035
- "@cortexkit/aft-win32-x64": "0.25.1"
33087
+ "@cortexkit/aft-darwin-arm64": "0.26.0",
33088
+ "@cortexkit/aft-darwin-x64": "0.26.0",
33089
+ "@cortexkit/aft-linux-arm64": "0.26.0",
33090
+ "@cortexkit/aft-linux-x64": "0.26.0",
33091
+ "@cortexkit/aft-win32-x64": "0.26.0"
33036
33092
  },
33037
33093
  devDependencies: {
33038
33094
  "@earendil-works/pi-coding-agent": "*",
@@ -48048,8 +48104,9 @@ function runInstall(spec, version2, cwd, signal) {
48048
48104
  resolve2(false);
48049
48105
  return;
48050
48106
  }
48051
- const child = spawn2("bun", ["add", target, "--cwd", cwd, "--ignore-scripts", "--silent"], {
48052
- stdio: ["ignore", "pipe", "pipe"]
48107
+ const child = spawn2("npm", ["install", "--no-save", "--ignore-scripts", "--silent", target], {
48108
+ stdio: ["ignore", "pipe", "pipe"],
48109
+ cwd
48053
48110
  });
48054
48111
  child.unref();
48055
48112
  let stderrBuf = "";
@@ -50097,12 +50154,10 @@ function registerFsTools(pi, ctx, surface) {
50097
50154
  parameters: DeleteParams,
50098
50155
  async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
50099
50156
  const bridge = bridgeFor(ctx, extCtx.cwd);
50100
- const sessionId = resolveSessionId(extCtx);
50101
- const response = await bridge.send("delete_file", {
50157
+ const response = await callBridge(bridge, "delete_file", {
50102
50158
  files: params.files,
50103
- recursive: params.recursive === true,
50104
- ...sessionId ? { session_id: sessionId } : {}
50105
- });
50159
+ recursive: params.recursive === true
50160
+ }, extCtx);
50106
50161
  const deletedEntries = response.deleted ?? [];
50107
50162
  const skipped = response.skipped_files ?? [];
50108
50163
  const deleted = deletedEntries.map((entry) => entry.file);
@@ -51734,7 +51789,7 @@ function buildWorkflowHints(opts) {
51734
51789
  const hasNavigate = opts.toolSurface === "all" && !opts.absentTools.has("aft_navigate");
51735
51790
  const hasBgBash = opts.bashBackgroundEnabled && !opts.absentTools.has(bashName) && !opts.absentTools.has("bash_status");
51736
51791
  if (hasOutline && hasZoom) {
51737
- sections.push(`**Web/URL access**: \`aft_outline({ url })\` first for structure, then \`aft_zoom({ url, symbol: "<heading>" })\` for the specific section.`);
51792
+ sections.push(`**Web/URL access**: \`aft_outline({ target: "<url>" })\` first for structure, then \`aft_zoom({ target: "<url>", symbol: "<heading>" })\` for the specific section.`);
51738
51793
  }
51739
51794
  if (hasOutline && hasZoom && (hasGrep || hasSearch)) {
51740
51795
  const locator = hasGrep ? `\`${grepName}\`` : "`aft_search`";
@@ -51751,7 +51806,7 @@ function buildWorkflowHints(opts) {
51751
51806
  `));
51752
51807
  }
51753
51808
  if (hasBgBash) {
51754
- sections.push(`**Long-running commands** (builds, installs, full test suites): \`${bashName}({ background: true })\` returns immediately with a \`taskId\`. A completion reminder is delivered automatically — do not poll \`bash_status({ taskId })\`. Use \`bash_status\` only after the reminder arrives, or to inspect a task you already know is complete.`);
51809
+ sections.push(`**Long-running commands** (builds, installs, full test suites): \`${bashName}({ background: true })\` returns immediately with a \`task_id\`. A completion reminder is delivered automatically — do not poll \`bash_status({ task_id })\`. Use \`bash_status\` only after the reminder arrives, or to inspect a task you already know is complete.`);
51755
51810
  }
51756
51811
  if (sections.length === 0) {
51757
51812
  return null;
@@ -51800,6 +51855,36 @@ ${hintsBlock}` };
51800
51855
 
51801
51856
  // src/index.ts
51802
51857
  setActiveLogger(bridgeLogger);
51858
+ function createVersionMismatchHandler(getPool, ensureCompatibleBinary = ensureBinary) {
51859
+ let versionUpgradeAttempted = null;
51860
+ return async (binaryVersion, minVersion) => {
51861
+ if (versionUpgradeAttempted === binaryVersion) {
51862
+ log2(`Version ${binaryVersion} < ${minVersion} but upgrade already attempted — continuing`);
51863
+ return null;
51864
+ }
51865
+ versionUpgradeAttempted = binaryVersion;
51866
+ warn2(`WARNING: aft binary v${binaryVersion} is older than plugin v${minVersion}. ` + "Some features may not work. Attempting to download a compatible binary...");
51867
+ try {
51868
+ const path2 = await ensureCompatibleBinary(`v${minVersion}`);
51869
+ if (!path2) {
51870
+ warn2(`Could not find or download v${minVersion}. Continuing with v${binaryVersion}.`);
51871
+ return null;
51872
+ }
51873
+ const pool = getPool();
51874
+ if (!pool) {
51875
+ warn2(`Found/downloaded compatible binary at ${path2}, but bridge pool is not ready.`);
51876
+ return null;
51877
+ }
51878
+ log2(`Found/downloaded compatible binary at ${path2}. Replacing running bridges...`);
51879
+ const replaced = await pool.replaceBinary(path2);
51880
+ log2("Binary replaced successfully. New bridges will use the updated binary.");
51881
+ return replaced;
51882
+ } catch (err) {
51883
+ error2(`Auto-download failed: ${err.message}. Install manually: cargo install agent-file-tools@${minVersion}`);
51884
+ return null;
51885
+ }
51886
+ };
51887
+ }
51803
51888
  var PLUGIN_VERSION = (() => {
51804
51889
  try {
51805
51890
  const req = createRequire3(import.meta.url);
@@ -52041,9 +52126,11 @@ ${lines}
52041
52126
  } catch (err) {
52042
52127
  warn2(`[lsp] auto-install setup failed: ${err instanceof Error ? err.message : String(err)}`);
52043
52128
  }
52129
+ let pool;
52044
52130
  const poolOptions = {
52045
52131
  errorPrefix: "[aft-pi]",
52046
52132
  minVersion: PLUGIN_VERSION,
52133
+ onVersionMismatch: createVersionMismatchHandler(() => pool),
52047
52134
  onConfigureWarnings: async ({ projectRoot, sessionId, client, warnings }) => {
52048
52135
  const pendingWarnings = sessionId ? drainPendingEagerWarnings(projectRoot) : [];
52049
52136
  await handleConfigureWarningsForSession({
@@ -52072,7 +52159,7 @@ ${lines}
52072
52159
  }, reminder);
52073
52160
  }
52074
52161
  };
52075
- const pool = new BridgePool(binaryPath, poolOptions, configOverrides);
52162
+ pool = new BridgePool(binaryPath, poolOptions, configOverrides);
52076
52163
  const ctx = { pool, config: config2, storageDir };
52077
52164
  if (onnxRuntimePromise) {
52078
52165
  onnxRuntimePromise.then((ortDylibDir) => {
@@ -52188,7 +52275,8 @@ ${lines}
52188
52275
  var __test__2 = {
52189
52276
  resolveToolSurface,
52190
52277
  handleConfigureWarningsForSession,
52191
- shouldPrepareOnnxRuntime
52278
+ shouldPrepareOnnxRuntime,
52279
+ createVersionMismatchHandler
52192
52280
  };
52193
52281
  export {
52194
52282
  src_default as default,
@@ -19,7 +19,7 @@
19
19
  * installed, log a warning and keep the existing version.
20
20
  * Otherwise skip + warn.
21
21
  *
22
- * 3. Spawn `bun add <pkg>@<version> --cwd <cache_dir> --ignore-scripts`
22
+ * 3. Spawn `npm install --no-save <pkg>@<version> --ignore-scripts`
23
23
  * in the background. Drop a lockfile while running. Log progress.
24
24
  *
25
25
  * 4. The newly-installed binary will be picked up on the user's NEXT
@@ -1 +1 @@
1
- {"version":3,"file":"lsp-auto-install.d.ts","sourceRoot":"","sources":["../src/lsp-auto-install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAwBH,+DAA+D;AAC/D,MAAM,WAAW,iBAAiB;IAChC,oCAAoC;IACpC,WAAW,EAAE,OAAO,CAAC;IACrB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3C,kGAAkG;IAClG,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC/B;AAED,qCAAqC;AACrC,MAAM,WAAW,iBAAiB;IAChC,mFAAmF;IACnF,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gDAAgD;IAChD,eAAe,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B;;;;;;;OAOG;IACH,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C;;;;;;;;;OASG;IACH,gBAAgB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC;AAkDD,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CAM/D;AAwVD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,iBAAiB,EACzB,SAAS,GAAE,OAAO,KAAa,GAC9B,iBAAiB,CAwEnB"}
1
+ {"version":3,"file":"lsp-auto-install.d.ts","sourceRoot":"","sources":["../src/lsp-auto-install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAwBH,+DAA+D;AAC/D,MAAM,WAAW,iBAAiB;IAChC,oCAAoC;IACpC,WAAW,EAAE,OAAO,CAAC;IACrB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3C,kGAAkG;IAClG,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC/B;AAED,qCAAqC;AACrC,MAAM,WAAW,iBAAiB;IAChC,mFAAmF;IACnF,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gDAAgD;IAChD,eAAe,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B;;;;;;;OAOG;IACH,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C;;;;;;;;;OASG;IACH,gBAAgB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC;AAkDD,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CAM/D;AAyVD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,iBAAiB,EACzB,SAAS,GAAE,OAAO,KAAa,GAC9B,iBAAiB,CAwEnB"}
@@ -1 +1 @@
1
- {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/tools/fs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,iCAAiC,CAAC;AAC5F,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAEL,KAAK,iBAAiB,EAKvB,MAAM,qBAAqB,CAAC;AAE7B,QAAA,MAAM,YAAY;;;EAWhB,CAAC;AAEH,QAAA,MAAM,UAAU;;;EAGd,CAAC;AAEH,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,wCAAwC;AACxC,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,YAAY,GAAG,UAAU,EACnC,IAAI,EAAE,MAAM,CAAC,OAAO,YAAY,CAAC,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,EAC7D,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,iBAAiB,yCAkB3B;AAED,wCAAwC;AACxC,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,YAAY,GAAG,UAAU,EACnC,IAAI,EAAE,MAAM,CAAC,OAAO,YAAY,CAAC,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,EAC7D,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,EAChC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,iBAAiB,sFAsC3B;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,SAAS,GAAG,IAAI,CA4F9F"}
1
+ {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/tools/fs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,iCAAiC,CAAC;AAC5F,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAEL,KAAK,iBAAiB,EAKvB,MAAM,qBAAqB,CAAC;AAE7B,QAAA,MAAM,YAAY;;;EAWhB,CAAC;AAEH,QAAA,MAAM,UAAU;;;EAGd,CAAC;AAEH,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,wCAAwC;AACxC,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,YAAY,GAAG,UAAU,EACnC,IAAI,EAAE,MAAM,CAAC,OAAO,YAAY,CAAC,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,EAC7D,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,iBAAiB,yCAkB3B;AAED,wCAAwC;AACxC,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,YAAY,GAAG,UAAU,EACnC,IAAI,EAAE,MAAM,CAAC,OAAO,YAAY,CAAC,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,EAC7D,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,EAChC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,iBAAiB,sFAsC3B;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,SAAS,GAAG,IAAI,CA+F9F"}
@@ -7,7 +7,7 @@ import { type Static, Type } from "typebox";
7
7
  import type { PluginContext } from "../types.js";
8
8
  import { type RenderContextLike } from "./render-helpers.js";
9
9
  declare const ImportParams: Type.TObject<{
10
- op: Type.TUnsafe<"add" | "remove" | "organize">;
10
+ op: Type.TUnsafe<"remove" | "add" | "organize">;
11
11
  filePath: Type.TString;
12
12
  module: Type.TOptional<Type.TString>;
13
13
  names: Type.TOptional<Type.TArray<Type.TString>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/aft-pi",
3
- "version": "0.25.1",
3
+ "version": "0.26.0",
4
4
  "type": "module",
5
5
  "description": "Pi coding agent extension for Agent File Tools (AFT) — tree-sitter and LSP-powered code analysis",
6
6
  "main": "dist/index.js",
@@ -22,18 +22,18 @@
22
22
  "prepublishOnly": "bun run build"
23
23
  },
24
24
  "dependencies": {
25
- "@cortexkit/aft-bridge": "0.25.1",
25
+ "@cortexkit/aft-bridge": "0.26.0",
26
26
  "typebox": "^1.1.24",
27
27
  "comment-json": "^5.0.0",
28
28
  "diff": "^8.0.4",
29
29
  "zod": "^4.1.8"
30
30
  },
31
31
  "optionalDependencies": {
32
- "@cortexkit/aft-darwin-arm64": "0.25.1",
33
- "@cortexkit/aft-darwin-x64": "0.25.1",
34
- "@cortexkit/aft-linux-arm64": "0.25.1",
35
- "@cortexkit/aft-linux-x64": "0.25.1",
36
- "@cortexkit/aft-win32-x64": "0.25.1"
32
+ "@cortexkit/aft-darwin-arm64": "0.26.0",
33
+ "@cortexkit/aft-darwin-x64": "0.26.0",
34
+ "@cortexkit/aft-linux-arm64": "0.26.0",
35
+ "@cortexkit/aft-linux-x64": "0.26.0",
36
+ "@cortexkit/aft-win32-x64": "0.26.0"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@earendil-works/pi-coding-agent": "*",