@cortexkit/aft-opencode 0.19.0 → 0.19.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"bg-notifications.d.ts","sourceRoot":"","sources":["../src/bg-notifications.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,KAAK,cAAc,GAAG;IACpB,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAChC,kBAAkB,EAAE,YAAY,EAAE,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;IACrC,iBAAiB,EAAE,OAAO,CAAC;IAC3B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,wBAAwB,EAAE,MAAM,CAAC;IACjC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,kBAAkB,EAAE,KAAK,CAAC;QAAE,UAAU,EAAE,YAAY,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5E,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAa,CAAC;AAGtE,eAAO,MAAM,4BAA4B,QAAiB,CAAC;AAQ3D,UAAU,YAAY;IACpB,GAAG,EAAE,aAAa,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC;CAC1B;AASD,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAgB/E;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,WAAW,EAAE,OAAO,GACnB,YAAY,EAAE,CAoBhB;AAED,wBAAsB,wBAAwB,CAC5C,YAAY,EAAE,YAAY,GAAG;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,EAChD,UAAU,EAAE,OAAO,GAClB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,yBAAyB,CAC7C,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,GACtC,OAAO,CAAC,IAAI,CAAC,CAaf;AAED,wBAAsB,uBAAuB,CAC3C,YAAY,EAAE,YAAY,GAAG;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,GAC/C,OAAO,CAAC,IAAI,CAAC,CAEf;AAyDD,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAE/D;AAED,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CASjF;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAcnE;AAED,wBAAgB,kCAAkC,IAAI,IAAI,CAKzD"}
1
+ {"version":3,"file":"bg-notifications.d.ts","sourceRoot":"","sources":["../src/bg-notifications.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,KAAK,cAAc,GAAG;IACpB,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAChC,kBAAkB,EAAE,YAAY,EAAE,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;IACrC,iBAAiB,EAAE,OAAO,CAAC;IAC3B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,wBAAwB,EAAE,MAAM,CAAC;IACjC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,kBAAkB,EAAE,KAAK,CAAC;QAAE,UAAU,EAAE,YAAY,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5E,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAa,CAAC;AAGtE,eAAO,MAAM,4BAA4B,QAAiB,CAAC;AAQ3D,UAAU,YAAY;IACpB,GAAG,EAAE,aAAa,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC;CAC1B;AASD,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAgB/E;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,WAAW,EAAE,OAAO,GACnB,YAAY,EAAE,CAoBhB;AAED,wBAAsB,wBAAwB,CAC5C,YAAY,EAAE,YAAY,GAAG;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,EAChD,UAAU,EAAE,OAAO,GAClB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,yBAAyB,CAC7C,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,GACtC,OAAO,CAAC,IAAI,CAAC,CAaf;AAED,wBAAsB,uBAAuB,CAC3C,YAAY,EAAE,YAAY,GAAG;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,GAC/C,OAAO,CAAC,IAAI,CAAC,CAEf;AA2ED,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAE/D;AAED,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CASjF;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAcnE;AAED,wBAAgB,kCAAkC,IAAI,IAAI,CAKzD"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AA+JlD;;;;;;;;;;;;;;;;;;GAkBG;AACH,QAAA,MAAM,MAAM,EAAE,MA2oBb,CAAC;AAEF,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AA+JlD;;;;;;;;;;;;;;;;;;GAkBG;AACH,QAAA,MAAM,MAAM,EAAE,MA4sBb,CAAC;AAEF,eAAe,MAAM,CAAC"}
package/dist/index.js CHANGED
@@ -7847,6 +7847,9 @@ import { join } from "path";
7847
7847
  var DEFAULT_BRIDGE_TIMEOUT_MS = 30000;
7848
7848
  var SEMANTIC_TIMEOUT_SAFETY_MARGIN_MS = 5000;
7849
7849
  var MAX_STDOUT_BUFFER = 64 * 1024 * 1024;
7850
+ function tagStderrLine(line) {
7851
+ return /^\[aft(-\w+)?\] /.test(line) ? line : `[aft] ${line}`;
7852
+ }
7850
7853
  function compareSemver(a, b) {
7851
7854
  const [aMain, aPre] = a.split("-", 2);
7852
7855
  const [bMain, bPre] = b.split("-", 2);
@@ -8167,9 +8170,9 @@ class BinaryBridge {
8167
8170
  for (const line of lines) {
8168
8171
  if (!line)
8169
8172
  continue;
8170
- const stripped = line.replace(/^\[aft\]\s*/, "");
8171
- log(`[aft] ${stripped}`);
8172
- this.pushStderrLine(stripped);
8173
+ const tagged = tagStderrLine(line);
8174
+ log(tagged);
8175
+ this.pushStderrLine(tagged);
8173
8176
  }
8174
8177
  });
8175
8178
  child.on("error", (err) => {
@@ -8354,7 +8357,7 @@ import { join as join2 } from "path";
8354
8357
  var PLATFORM_ARCH_MAP = {
8355
8358
  darwin: { arm64: "darwin-arm64", x64: "darwin-x64" },
8356
8359
  linux: { arm64: "linux-arm64", x64: "linux-x64" },
8357
- win32: { x64: "win32-x64" }
8360
+ win32: { arm64: "win32-x64", x64: "win32-x64" }
8358
8361
  };
8359
8362
  var PLATFORM_ASSET_MAP = {
8360
8363
  "darwin-arm64": "aft-darwin-arm64",
@@ -8385,10 +8388,11 @@ function getCachedBinaryPath(version) {
8385
8388
  return existsSync(binaryPath) ? binaryPath : null;
8386
8389
  }
8387
8390
  async function downloadBinary(version) {
8388
- const platformKey = `${process.platform}-${process.arch}`;
8389
- const assetName = PLATFORM_ASSET_MAP[platformKey];
8390
- if (!assetName) {
8391
- error(`Unsupported platform: ${platformKey}`);
8391
+ const archMap = PLATFORM_ARCH_MAP[process.platform] ?? {};
8392
+ const platformKey = archMap[process.arch];
8393
+ const assetName = platformKey ? PLATFORM_ASSET_MAP[platformKey] : undefined;
8394
+ if (!platformKey || !assetName) {
8395
+ error(`Unsupported platform: ${process.platform}-${process.arch}`);
8392
8396
  return null;
8393
8397
  }
8394
8398
  const tag = version ?? await fetchLatestTag();
@@ -8507,7 +8511,7 @@ var MAX_DOWNLOAD_BYTES = 256 * 1024 * 1024;
8507
8511
  var MAX_EXTRACT_BYTES = 1 * 1024 * 1024 * 1024;
8508
8512
  var ONNX_LOCK_FILE = ".aft-onnx-installing";
8509
8513
  var ONNX_INSTALLED_META_FILE = ".aft-onnx-installed";
8510
- var STALE_LOCK_MS = 30 * 60 * 1000;
8514
+ var STALE_LOCK_MS = 5 * 60 * 1000;
8511
8515
  var ORT_PLATFORM_MAP = {
8512
8516
  darwin: {
8513
8517
  arm64: {
@@ -8545,7 +8549,10 @@ function getPlatformInfo() {
8545
8549
  const platformMap = ORT_PLATFORM_MAP[process.platform];
8546
8550
  if (!platformMap)
8547
8551
  return null;
8548
- return platformMap[process.arch] || null;
8552
+ const archMap = PLATFORM_ARCH_MAP[process.platform] ?? {};
8553
+ const platformKey = archMap[process.arch];
8554
+ const ortArch = platformKey ? platformKey.split("-")[1] : process.arch;
8555
+ return platformMap[ortArch] || null;
8549
8556
  }
8550
8557
  function isOrtAutoDownloadSupported() {
8551
8558
  return getPlatformInfo() !== null;
@@ -8595,6 +8602,7 @@ async function ensureOnnxRuntime(storageDir) {
8595
8602
  const onnxBaseDir = join3(storageDir, "onnxruntime");
8596
8603
  mkdirSync2(onnxBaseDir, { recursive: true });
8597
8604
  const lockPath = join3(onnxBaseDir, ONNX_LOCK_FILE);
8605
+ cleanupAbandonedOnnxAttempts(onnxBaseDir, ortDir);
8598
8606
  if (!acquireLock(lockPath)) {
8599
8607
  warn(`ONNX Runtime install already in progress in another process (lock: ${lockPath}). Skipping.`);
8600
8608
  return null;
@@ -8605,6 +8613,51 @@ async function ensureOnnxRuntime(storageDir) {
8605
8613
  releaseLock(lockPath);
8606
8614
  }
8607
8615
  }
8616
+ function cleanupAbandonedOnnxAttempts(onnxBaseDir, ortDir) {
8617
+ try {
8618
+ const entries = readdirSync(onnxBaseDir);
8619
+ const ortDirBaseName = ortDir.slice(onnxBaseDir.length + 1);
8620
+ for (const entry of entries) {
8621
+ if (!entry.startsWith(`${ortDirBaseName}.tmp.`))
8622
+ continue;
8623
+ const stagingDir = join3(onnxBaseDir, entry);
8624
+ const parts = entry.split(".");
8625
+ const pidStr = parts[parts.length - 2];
8626
+ const pid = pidStr ? Number.parseInt(pidStr, 10) : NaN;
8627
+ let abandoned = false;
8628
+ if (Number.isFinite(pid) && pid > 0) {
8629
+ if (process.platform === "win32") {
8630
+ try {
8631
+ const ageMs = Date.now() - statSync(stagingDir).mtimeMs;
8632
+ abandoned = ageMs > STALE_LOCK_MS;
8633
+ } catch {
8634
+ abandoned = true;
8635
+ }
8636
+ } else {
8637
+ abandoned = !isProcessAlive(pid);
8638
+ }
8639
+ } else {
8640
+ abandoned = true;
8641
+ }
8642
+ if (abandoned) {
8643
+ log(`[onnx] removing abandoned staging dir ${stagingDir}`);
8644
+ try {
8645
+ rmSync(stagingDir, { recursive: true, force: true });
8646
+ } catch (err) {
8647
+ warn(`[onnx] failed to remove ${stagingDir}: ${err}`);
8648
+ }
8649
+ }
8650
+ }
8651
+ } catch {}
8652
+ try {
8653
+ if (existsSync2(ortDir) && !existsSync2(join3(ortDir, ONNX_INSTALLED_META_FILE))) {
8654
+ log(`[onnx] removing half-populated install dir ${ortDir} (no meta file)`);
8655
+ rmSync(ortDir, { recursive: true, force: true });
8656
+ }
8657
+ } catch (err) {
8658
+ warn(`[onnx] failed to sweep ${ortDir}: ${err}`);
8659
+ }
8660
+ }
8608
8661
  function findSystemOnnxRuntime(libName) {
8609
8662
  if (!libName)
8610
8663
  return null;
@@ -9016,9 +9069,19 @@ class BridgePool {
9016
9069
  await Promise.allSettled(shutdowns);
9017
9070
  log(`Binary path updated to ${newPath}. All bridges cleared \u2014 next calls will use the new binary.`);
9018
9071
  }
9072
+ setConfigureOverride(key, value) {
9073
+ if (value === undefined) {
9074
+ delete this.configOverrides[key];
9075
+ } else {
9076
+ this.configOverrides[key] = value;
9077
+ }
9078
+ }
9019
9079
  get size() {
9020
9080
  return this.bridges.size;
9021
9081
  }
9082
+ _testGetConfigOverrides() {
9083
+ return { ...this.configOverrides };
9084
+ }
9022
9085
  }
9023
9086
  function normalizeKey(projectRoot) {
9024
9087
  const stripped = projectRoot.replace(/[/\\]+$/, "");
@@ -9266,15 +9329,24 @@ async function assertPublicUrl(url, allowPrivate, dnsLookup = lookup) {
9266
9329
  if (addresses.length === 0) {
9267
9330
  throw new Error(`Failed to resolve URL host ${url.hostname}`);
9268
9331
  }
9269
- return addresses[0].address;
9332
+ const ipv4 = addresses.find((entry) => entry.family === 4 || entry.family === "IPv4" || typeof entry.address === "string" && isIP(entry.address) === 4);
9333
+ const chosen = ipv4 ?? addresses[0];
9334
+ if (!chosen || typeof chosen.address !== "string" || chosen.address.length === 0) {
9335
+ throw new Error(`DNS lookup for ${url.hostname} returned no usable address (got: ${JSON.stringify(addresses)})`);
9336
+ }
9337
+ return chosen.address;
9270
9338
  }
9271
9339
  function createPinnedDispatcher(validatedIp) {
9272
- return new Agent({
9273
- connect: {
9274
- lookup: (_hostname, _opts, callback) => {
9275
- callback(null, validatedIp, validatedIp.includes(":") ? 6 : 4);
9276
- }
9340
+ const family = validatedIp.includes(":") ? 6 : 4;
9341
+ const pinnedLookup = (_hostname, opts, callback) => {
9342
+ if (opts?.all) {
9343
+ callback(null, [{ address: validatedIp, family }]);
9344
+ } else {
9345
+ callback(null, validatedIp, family);
9277
9346
  }
9347
+ };
9348
+ return new Agent({
9349
+ connect: { lookup: pinnedLookup }
9278
9350
  });
9279
9351
  }
9280
9352
  function resolveRedirectUrl(currentUrl, location) {
@@ -9304,7 +9376,19 @@ async function fetchWithRedirects(startUrl, allowPrivate, deps = {}) {
9304
9376
  }
9305
9377
  });
9306
9378
  } catch (err) {
9307
- throw new Error(`Failed to fetch ${currentUrl.href}: ${err.message}`);
9379
+ const error2 = err;
9380
+ const cause = error2.cause;
9381
+ const causeCode = cause?.code ?? error2.code;
9382
+ const causeMsg = cause?.message ?? "";
9383
+ const detail = causeCode ? causeMsg ? `${causeCode}: ${causeMsg}` : causeCode : error2.message ?? "unknown error";
9384
+ warn(`URL fetch failed: ${currentUrl.href} \u2014 ${detail}`, {
9385
+ outerMessage: error2.message,
9386
+ causeName: cause?.name,
9387
+ causeCode,
9388
+ causeErrno: cause?.errno,
9389
+ causeSyscall: cause?.syscall
9390
+ });
9391
+ throw new Error(`Failed to fetch ${currentUrl.href}: ${detail}`);
9308
9392
  } finally {
9309
9393
  clearTimeout(timer);
9310
9394
  }
@@ -9447,6 +9531,56 @@ function cleanupUrlCache(storageDir) {
9447
9531
  log(`URL cache cleanup: removed ${removed} stale entries`);
9448
9532
  }
9449
9533
  }
9534
+ // ../aft-bridge/dist/zoom-format.js
9535
+ function formatZoomText(targetLabel, response) {
9536
+ const range = response.range;
9537
+ const startLine = range?.start_line ?? 1;
9538
+ const endLine = range?.end_line ?? startLine;
9539
+ const kind = response.kind ?? "symbol";
9540
+ const name = response.name ?? "";
9541
+ const contentText = typeof response.content === "string" ? response.content : "";
9542
+ const ctxBefore = Array.isArray(response.context_before) ? response.context_before : [];
9543
+ const ctxAfter = Array.isArray(response.context_after) ? response.context_after : [];
9544
+ const header = kind === "lines" ? `${targetLabel}:${startLine}-${endLine}` : `${targetLabel}:${startLine}-${endLine} [${kind} ${name}]`.trimEnd();
9545
+ const contentLines = contentText.split(`
9546
+ `);
9547
+ if (contentLines.length > 0 && contentLines[contentLines.length - 1] === "") {
9548
+ contentLines.pop();
9549
+ }
9550
+ const lastDisplayedLine = endLine + ctxAfter.length;
9551
+ const gutterWidth = String(Math.max(lastDisplayedLine, 1)).length;
9552
+ const fmt = (lineNo2, text) => `${String(lineNo2).padStart(gutterWidth)}: ${text}`;
9553
+ const out = [header, ""];
9554
+ let lineNo = startLine - ctxBefore.length;
9555
+ for (const text of ctxBefore) {
9556
+ out.push(fmt(lineNo, text));
9557
+ lineNo += 1;
9558
+ }
9559
+ for (const text of contentLines) {
9560
+ out.push(fmt(lineNo, text));
9561
+ lineNo += 1;
9562
+ }
9563
+ for (const text of ctxAfter) {
9564
+ out.push(fmt(lineNo, text));
9565
+ lineNo += 1;
9566
+ }
9567
+ const callsOut = response.annotations?.calls_out ?? [];
9568
+ const calledBy = response.annotations?.called_by ?? [];
9569
+ if (callsOut.length > 0) {
9570
+ out.push("", "\u2500\u2500\u2500\u2500 calls_out");
9571
+ for (const ref of callsOut) {
9572
+ out.push(` ${ref.name} (line ${ref.line})`);
9573
+ }
9574
+ }
9575
+ if (calledBy.length > 0) {
9576
+ out.push("", "\u2500\u2500\u2500\u2500 called_by");
9577
+ for (const ref of calledBy) {
9578
+ out.push(` ${ref.name} (line ${ref.line})`);
9579
+ }
9580
+ }
9581
+ return out.join(`
9582
+ `);
9583
+ }
9450
9584
  // src/logger.ts
9451
9585
  import * as fs from "fs";
9452
9586
  import * as os from "os";
@@ -9696,8 +9830,6 @@ async function handleIdleBgCompletions(drainContext) {
9696
9830
  }
9697
9831
  async function triggerWakeIfPending(drainContext, skipDrain) {
9698
9832
  const state = stateFor(drainContext.sessionID);
9699
- if (state.wakeFiredThisIdle)
9700
- return;
9701
9833
  if (drainContext.isActive?.())
9702
9834
  return;
9703
9835
  if (!skipDrain && state.outstandingTaskIds.size > 0) {
@@ -27409,7 +27541,7 @@ function createBashTool(ctx) {
27409
27541
  const callID2 = getCallID(context);
27410
27542
  const taskId = data.task_id;
27411
27543
  trackBgTask(context.sessionID, taskId);
27412
- const startedLine = `Background task started: ${taskId}`;
27544
+ const startedLine = `Background task started: ${taskId}. A completion reminder will be delivered automatically; don't poll bash_status.`;
27413
27545
  const metadataPayload2 = { description, output: startedLine, status: "running", taskId };
27414
27546
  metadata?.(metadataPayload2);
27415
27547
  if (callID2) {
@@ -27479,6 +27611,10 @@ function createBashStatusTool(ctx) {
27479
27611
  if (preview && status !== "running") {
27480
27612
  text += `
27481
27613
  ${preview.slice(0, 2000)}`;
27614
+ }
27615
+ if (status === "running") {
27616
+ text += `
27617
+ A completion reminder will be delivered automatically; don't poll.`;
27482
27618
  }
27483
27619
  return text;
27484
27620
  }
@@ -28553,10 +28689,7 @@ function createMoveTool(ctx) {
28553
28689
  };
28554
28690
  }
28555
28691
  function hoistedTools(ctx) {
28556
- return {
28557
- bash: createBashTool(ctx),
28558
- bash_status: createBashStatusTool(ctx),
28559
- bash_kill: createBashKillTool(ctx),
28692
+ const tools = {
28560
28693
  read: createReadTool(ctx),
28561
28694
  write: createWriteTool(ctx, "edit"),
28562
28695
  edit: createEditTool(ctx, "write"),
@@ -28564,6 +28697,18 @@ function hoistedTools(ctx) {
28564
28697
  aft_delete: createDeleteTool(ctx),
28565
28698
  aft_move: createMoveTool(ctx)
28566
28699
  };
28700
+ const bashRewrite = ctx.config.experimental?.bash?.rewrite === true;
28701
+ const bashCompress = ctx.config.experimental?.bash?.compress === true;
28702
+ const bashBackground = ctx.config.experimental?.bash?.background === true;
28703
+ const anyBashExperimental = bashRewrite || bashCompress || bashBackground;
28704
+ if (anyBashExperimental) {
28705
+ tools.bash = createBashTool(ctx);
28706
+ }
28707
+ if (bashBackground) {
28708
+ tools.bash_status = createBashStatusTool(ctx);
28709
+ tools.bash_kill = createBashKillTool(ctx);
28710
+ }
28711
+ return tools;
28567
28712
  }
28568
28713
  function formatError2(error50) {
28569
28714
  return error50 instanceof Error ? error50.message : String(error50);
@@ -28871,6 +29016,7 @@ Provide exactly ONE of 'filePath' or 'url'. Pass either 'symbol' for a single lo
28871
29016
  const file2 = hasUrl ? await fetchUrlToTempFile(args.url, ctx.storageDir, {
28872
29017
  allowPrivate: ctx.config.url_fetch_allow_private === true
28873
29018
  }) : args.filePath;
29019
+ const targetLabel = (hasUrl ? args.url : args.filePath) ?? file2;
28874
29020
  if (Array.isArray(args.symbols) && args.symbols.length > 0) {
28875
29021
  const results = await Promise.all(args.symbols.map((sym) => {
28876
29022
  const params2 = { file: file2, symbol: sym };
@@ -28881,7 +29027,7 @@ Provide exactly ONE of 'filePath' or 'url'. Pass either 'symbol' for a single lo
28881
29027
  message: err instanceof Error ? err.message : String(err)
28882
29028
  }));
28883
29029
  }));
28884
- return JSON.stringify(formatZoomBatchResult(args.symbols, results), null, 2);
29030
+ return formatZoomBatchResult(targetLabel, args.symbols, results).text;
28885
29031
  }
28886
29032
  const params = { file: file2 };
28887
29033
  if (typeof args.symbol === "string")
@@ -28892,45 +29038,36 @@ Provide exactly ONE of 'filePath' or 'url'. Pass either 'symbol' for a single lo
28892
29038
  if (data.success === false) {
28893
29039
  throw new Error(data.message || "zoom failed");
28894
29040
  }
28895
- return JSON.stringify(data);
29041
+ return formatZoomText(targetLabel, data);
28896
29042
  }
28897
29043
  }
28898
29044
  };
28899
29045
  }
28900
- function formatZoomBatchResult(symbols, responses) {
29046
+ function formatZoomBatchResult(targetLabel, symbols, responses) {
28901
29047
  const entries = symbols.map((name, index) => {
28902
29048
  const response = responses[index] ?? { success: false, message: "missing zoom response" };
28903
29049
  if (response.success === false) {
28904
29050
  const message = typeof response.message === "string" && response.message.length > 0 ? response.message : "zoom failed";
28905
29051
  return { name, success: false, error: message };
28906
29052
  }
28907
- return { name, success: true, content: zoomResponseContent(response) };
29053
+ return { name, success: true, content: formatZoomText(targetLabel, response) };
28908
29054
  });
28909
29055
  const complete = entries.every((entry) => entry.success);
28910
- const lines = [];
29056
+ const sections = [];
28911
29057
  if (!complete) {
28912
- lines.push("Incomplete zoom results: one or more symbols failed.");
29058
+ sections.push("Incomplete zoom results: one or more symbols failed.");
28913
29059
  }
28914
29060
  for (const entry of entries) {
28915
29061
  if (entry.success) {
28916
- lines.push(`Symbol "${entry.name}":
28917
- ${entry.content ?? ""}`.trimEnd());
29062
+ sections.push(entry.content ?? "");
28918
29063
  } else {
28919
- lines.push(`Symbol "${entry.name}" not found: ${entry.error ?? "zoom failed"}`);
29064
+ sections.push(`Symbol "${entry.name}" not found: ${entry.error ?? "zoom failed"}`);
28920
29065
  }
28921
29066
  }
28922
- return { complete, symbols: entries, text: lines.join(`
29067
+ return { complete, symbols: entries, text: sections.join(`
28923
29068
 
28924
29069
  `) };
28925
29070
  }
28926
- function zoomResponseContent(response) {
28927
- if (typeof response.content === "string")
28928
- return response.content;
28929
- if (typeof response.text === "string")
28930
- return response.text;
28931
- const { success: _success2, ...rest } = response;
28932
- return JSON.stringify(rest, null, 2);
28933
- }
28934
29071
  function formatOutlineText(response) {
28935
29072
  const text = response.text ?? "";
28936
29073
  const skipped = response.skipped_files;
@@ -29478,7 +29615,7 @@ function buildWorkflowHints(opts) {
29478
29615
  }
29479
29616
  if (hasBash) {
29480
29617
  if (hasBgBash) {
29481
- sections.push(`**Long-running commands** (builds, installs, full test suites): \`${bashName}({ background: true })\` returns immediately with a \`taskId\`. Check progress with \`${bashStatusName}({ taskId })\`.`);
29618
+ sections.push(`**Long-running commands** (builds, installs, full test suites): \`${bashName}({ background: true })\` returns immediately with a \`taskId\`. A completion reminder is delivered automatically \u2014 do not poll \`${bashStatusName}({ taskId })\`. Use \`${bashStatusName}\` only after the reminder arrives, or to inspect a task you already know is complete.`);
29482
29619
  } else {
29483
29620
  sections.push(`**Long-running bash commands**: foreground \`${bashName}\` times out after 30 seconds. Pass \`timeout\` in milliseconds to extend it for commands you know will take longer.`);
29484
29621
  }
@@ -29610,17 +29747,13 @@ var plugin = async (input) => {
29610
29747
  const isFastembedSemanticBackend = (aftConfig.semantic?.backend ?? "fastembed") === "fastembed";
29611
29748
  const dataHome = process.env.XDG_DATA_HOME || join18(homedir10(), ".local", "share");
29612
29749
  configOverrides.storage_dir = join18(dataHome, "opencode", "storage", "plugin", "aft");
29750
+ let onnxRuntimePromise = null;
29613
29751
  if (aftConfig.semantic_search && isFastembedSemanticBackend) {
29614
29752
  const storageDir2 = configOverrides.storage_dir;
29615
- const ortDylibDir = await ensureOnnxRuntime(storageDir2).catch((err) => {
29753
+ onnxRuntimePromise = ensureOnnxRuntime(storageDir2).catch((err) => {
29616
29754
  warn2(`ONNX Runtime setup failed: ${err instanceof Error ? err.message : String(err)}. Semantic search will be unavailable.`);
29617
29755
  return null;
29618
29756
  });
29619
- if (ortDylibDir) {
29620
- configOverrides._ort_dylib_dir = ortDylibDir;
29621
- } else if (!isOrtAutoDownloadSupported()) {
29622
- warn2(`Semantic search requires ONNX Runtime. Install: ${getManualInstallHint()}`);
29623
- }
29624
29757
  }
29625
29758
  try {
29626
29759
  const lspAutoInstall = aftConfig.lsp?.auto_install ?? true;
@@ -29742,8 +29875,26 @@ ${lines}
29742
29875
  storageDir: configOverrides.storage_dir
29743
29876
  };
29744
29877
  setSharedBridgePool(pool);
29878
+ if (onnxRuntimePromise) {
29879
+ onnxRuntimePromise.then((ortDylibDir) => {
29880
+ if (ortDylibDir) {
29881
+ pool.setConfigureOverride("_ort_dylib_dir", ortDylibDir);
29882
+ log2(`ONNX Runtime ready at ${ortDylibDir}; new bridges will load semantic backend.`);
29883
+ } else if (!isOrtAutoDownloadSupported()) {
29884
+ log2(`ONNX Runtime auto-download not supported on ${process.platform}/${process.arch}.`);
29885
+ }
29886
+ }, (err) => {
29887
+ warn2(`ONNX Runtime resolution rejected unexpectedly: ${err}`);
29888
+ });
29889
+ }
29745
29890
  (async () => {
29746
29891
  try {
29892
+ if (onnxRuntimePromise) {
29893
+ await Promise.race([
29894
+ onnxRuntimePromise,
29895
+ new Promise((resolve9) => setTimeout(() => resolve9(null), 60000))
29896
+ ]);
29897
+ }
29747
29898
  const bridge = pool.getBridge(input.directory);
29748
29899
  await bridge.send("status", {}, { configureWarningClient: input.client });
29749
29900
  } catch (err) {
@@ -29833,13 +29984,13 @@ Install: ${getManualInstallHint()}`);
29833
29984
  sendFeatureAnnouncement(notifyOpts, ANNOUNCEMENT_VERSION, ANNOUNCEMENT_FEATURES, storageDir).catch(() => {});
29834
29985
  }, 8000);
29835
29986
  }
29836
- if (aftConfig.semantic_search && isFastembedSemanticBackend && !configOverrides._ort_dylib_dir) {
29837
- setTimeout(() => {
29838
- if (!configOverrides._ort_dylib_dir && !isOrtAutoDownloadSupported()) {
29987
+ if (onnxRuntimePromise) {
29988
+ onnxRuntimePromise.then((ortDylibDir) => {
29989
+ if (!ortDylibDir && !isOrtAutoDownloadSupported()) {
29839
29990
  sendWarning(notifyOpts, `Semantic search requires ONNX Runtime.
29840
29991
  Install: ${getManualInstallHint()}`).catch(() => {});
29841
29992
  }
29842
- }, 5000);
29993
+ }, () => {});
29843
29994
  } else {
29844
29995
  cleanupWarnings(notifyOpts).catch(() => {});
29845
29996
  }
@@ -1 +1 @@
1
- {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../src/tools/bash.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAsDjD,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAoJjE;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CA4BvE;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAmBrE"}
1
+ {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../src/tools/bash.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAsDjD,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CA6JjE;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAqCvE;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAmBrE"}
@@ -18,7 +18,15 @@ export declare const _buildUnifiedDiffForTest: (fp: string, before: string, afte
18
18
  export declare function createReadTool(ctx: PluginContext): ToolDefinition;
19
19
  /**
20
20
  * Returns hoisted tools keyed by opencode's built-in names.
21
- * Overrides: read, write, edit, apply_patch.
21
+ * Overrides: read, write, edit, apply_patch (always when hoisting is on).
22
+ *
23
+ * Bash hoisting is opt-in: `bash`, `bash_status`, and `bash_kill` are only
24
+ * registered when at least one `experimental.bash.*` flag is enabled
25
+ * (rewrite, compress, or background). When all flags are off, opencode's
26
+ * native bash stays in place — users without bash experimentals get zero
27
+ * AFT code in their bash path. `bash_status` and `bash_kill` register
28
+ * specifically when `experimental.bash.background` is true, since those
29
+ * tools only have meaning for background tasks.
22
30
  */
23
31
  export declare function hoistedTools(ctx: PluginContext): Record<string, ToolDefinition>;
24
32
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"hoisted.d.ts","sourceRoot":"","sources":["../../src/tools/hoisted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAI1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAkEjD,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,GAAI,IAAI,MAAM,EAAE,QAAQ,MAAM,EAAE,OAAO,MAAM,KAAG,MAChD,CAAC;AAqRtC;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAgJjE;AAqgCD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAY/E;AAMD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAmEnF"}
1
+ {"version":3,"file":"hoisted.d.ts","sourceRoot":"","sources":["../../src/tools/hoisted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAI1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAkEjD,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,GAAI,IAAI,MAAM,EAAE,QAAQ,MAAM,EAAE,OAAO,MAAM,KAAG,MAChD,CAAC;AAqRtC;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAgJjE;AAqgCD;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA0B/E;AAMD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAmEnF"}
@@ -15,7 +15,13 @@ interface ZoomBatchResult {
15
15
  * Tool definitions for code reading commands: outline + zoom.
16
16
  */
17
17
  export declare function readingTools(ctx: PluginContext): Record<string, ToolDefinition>;
18
- /** Exported for regression tests. */
19
- export declare function formatZoomBatchResult(symbols: string[], responses: Record<string, unknown>[]): ZoomBatchResult;
18
+ /**
19
+ * Format multi-symbol zoom results as plain text. Successful entries use
20
+ * `formatZoomText` (line-numbered, no JSON escapes); failures render as
21
+ * `Symbol "name" not found: <reason>`. Sections are blank-line separated.
22
+ *
23
+ * Exported for regression tests.
24
+ */
25
+ export declare function formatZoomBatchResult(targetLabel: string, symbols: string[], responses: Record<string, unknown>[]): ZoomBatchResult;
20
26
  export {};
21
27
  //# sourceMappingURL=reading.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reading.d.ts","sourceRoot":"","sources":["../../src/tools/reading.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAKjD,UAAU,qBAAqB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,eAAe;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAwJ/E;AAED,qCAAqC;AACrC,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GACnC,eAAe,CA0BjB"}
1
+ {"version":3,"file":"reading.d.ts","sourceRoot":"","sources":["../../src/tools/reading.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAKjD,UAAU,qBAAqB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,eAAe;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA2J/E;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GACnC,eAAe,CAyBjB"}
package/dist/tui.js CHANGED
@@ -2,7 +2,7 @@
2
2
  // package.json
3
3
  var package_default = {
4
4
  name: "@cortexkit/aft-opencode",
5
- version: "0.19.0",
5
+ version: "0.19.2",
6
6
  type: "module",
7
7
  description: "OpenCode plugin for Agent File Tools (AFT) \u2014 tree-sitter and lsp powered code analysis",
8
8
  main: "dist/index.js",
@@ -30,7 +30,7 @@ var package_default = {
30
30
  },
31
31
  dependencies: {
32
32
  "@clack/prompts": "^1.2.0",
33
- "@cortexkit/aft-bridge": "0.19.0",
33
+ "@cortexkit/aft-bridge": "0.19.2",
34
34
  "@opencode-ai/plugin": "^1.2.26",
35
35
  "@opencode-ai/sdk": "^1.2.26",
36
36
  "comment-json": "^4.6.2",
@@ -38,11 +38,11 @@ var package_default = {
38
38
  zod: "^4.1.8"
39
39
  },
40
40
  optionalDependencies: {
41
- "@cortexkit/aft-darwin-arm64": "0.19.0",
42
- "@cortexkit/aft-darwin-x64": "0.19.0",
43
- "@cortexkit/aft-linux-arm64": "0.19.0",
44
- "@cortexkit/aft-linux-x64": "0.19.0",
45
- "@cortexkit/aft-win32-x64": "0.19.0"
41
+ "@cortexkit/aft-darwin-arm64": "0.19.2",
42
+ "@cortexkit/aft-darwin-x64": "0.19.2",
43
+ "@cortexkit/aft-linux-arm64": "0.19.2",
44
+ "@cortexkit/aft-linux-x64": "0.19.2",
45
+ "@cortexkit/aft-win32-x64": "0.19.2"
46
46
  },
47
47
  devDependencies: {
48
48
  "@types/node": "^22.0.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/aft-opencode",
3
- "version": "0.19.0",
3
+ "version": "0.19.2",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for Agent File Tools (AFT) — tree-sitter and lsp powered code analysis",
6
6
  "main": "dist/index.js",
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "@clack/prompts": "^1.2.0",
31
- "@cortexkit/aft-bridge": "0.19.0",
31
+ "@cortexkit/aft-bridge": "0.19.2",
32
32
  "@opencode-ai/plugin": "^1.2.26",
33
33
  "@opencode-ai/sdk": "^1.2.26",
34
34
  "comment-json": "^4.6.2",
@@ -36,11 +36,11 @@
36
36
  "zod": "^4.1.8"
37
37
  },
38
38
  "optionalDependencies": {
39
- "@cortexkit/aft-darwin-arm64": "0.19.0",
40
- "@cortexkit/aft-darwin-x64": "0.19.0",
41
- "@cortexkit/aft-linux-arm64": "0.19.0",
42
- "@cortexkit/aft-linux-x64": "0.19.0",
43
- "@cortexkit/aft-win32-x64": "0.19.0"
39
+ "@cortexkit/aft-darwin-arm64": "0.19.2",
40
+ "@cortexkit/aft-darwin-x64": "0.19.2",
41
+ "@cortexkit/aft-linux-arm64": "0.19.2",
42
+ "@cortexkit/aft-linux-x64": "0.19.2",
43
+ "@cortexkit/aft-win32-x64": "0.19.2"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@types/node": "^22.0.0",