@cortexkit/aft 0.39.1 → 0.39.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAI3D,OAAO,EAEL,KAAK,gBAAgB,EAKtB,MAAM,uBAAuB,CAAC;AAe/B,OAAO,EAAE,KAAK,WAAW,EAAkB,MAAM,qBAAqB,CAAC;AAOvE,MAAM,MAAM,iBAAiB,GAAG,cAAc,GAAG,WAAW,GAAG,cAAc,CAAC;AAE9E,eAAO,MAAM,2BAA2B,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,iBAAiB,CAAA;CAAE,EAapF,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,iBAAiB,EAAqB,CAAC;AAEhF,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE;QACZ,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,QAAQ,CAAC,EAAE;QACT,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,WAAW,CAAC,EAAE;QACZ,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAChC,cAAc,CAAC,EAAE,MAAM,WAAW,CAAC;IACnC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,wBAAsB,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAkHvE;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAOnE;AA4BD,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,cAAc,EAAE,EAC1B,OAAO,EAAE,SAAS,iBAAiB,EAAE,EACrC,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,iBAAiB,CAAC,CAgD5B;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC1C,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,wBAAgB,gBAAgB,IAAI,sBAAsB,CAsDzD;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,QAAQ,GAAG,eAAe,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC5E,OAAO,EAAE,MAAM,CAAC;CACjB;AA0ID,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,cAAc,EAAE,EAC1B,MAAM,EAAE,gBAAgB,GACvB,iBAAiB,EAAE,CAsErB;AAED,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAIvE;AAED,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAK9F;AAwKD,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,GAAG,MAAM,CAK1F;AAsGD,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAIhF;AA4DD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7D"}
package/dist/index.js CHANGED
@@ -107,7 +107,10 @@ var init_active_logger = __esm(() => {
107
107
  // ../aft-bridge/dist/bash-hints.js
108
108
  var init_bash_hints = () => {};
109
109
  // ../aft-bridge/dist/command-timeouts.js
110
- var LONG_RUNNING_COMMAND_TIMEOUT_MS;
110
+ function isPassiveCommand(command) {
111
+ return PASSIVE_COMMANDS.has(command);
112
+ }
113
+ var LONG_RUNNING_COMMAND_TIMEOUT_MS, PASSIVE_COMMANDS, PASSIVE_COMMAND_TIMEOUT_MS = 5000;
111
114
  var init_command_timeouts = __esm(() => {
112
115
  LONG_RUNNING_COMMAND_TIMEOUT_MS = {
113
116
  callers: 60000,
@@ -119,6 +122,7 @@ var init_command_timeouts = __esm(() => {
119
122
  glob: 60000,
120
123
  semantic_search: 60000
121
124
  };
125
+ PASSIVE_COMMANDS = new Set(["status"]);
122
126
  });
123
127
 
124
128
  // ../aft-bridge/dist/status-bar.js
@@ -161,6 +165,10 @@ function bashTaskIdFrom(response) {
161
165
  function tagStderrLine(line) {
162
166
  return /^\[aft(-\w+)?\] /.test(line) ? line : `[aft] ${line}`;
163
167
  }
168
+ function shouldSurfaceStderrLine(line) {
169
+ const normalized = line.trim();
170
+ return !(normalized === `Error in cpuinfo: ${BENIGN_CPUINFO_PROC_CPUINFO_PARSE_FAILURE}` || normalized === BENIGN_CPUINFO_PROC_CPUINFO_PARSE_FAILURE);
171
+ }
164
172
  function compareSemver(a, b) {
165
173
  const [aMain, aPre] = a.split("-", 2);
166
174
  const [bMain, bPre] = b.split("-", 2);
@@ -226,7 +234,7 @@ function clampSemanticTimeout(configOverrides, bridgeTimeoutMs) {
226
234
  }
227
235
  };
228
236
  }
229
- var DEFAULT_BRIDGE_TIMEOUT_MS = 30000, BRIDGE_HANG_TIMEOUT_THRESHOLD = 2, SEMANTIC_TIMEOUT_SAFETY_MARGIN_MS = 5000, MAX_STDOUT_BUFFER, STDOUT_BUFFER_COMPACT_THRESHOLD, TERMINAL_BASH_STATUSES, BridgeReplacedDuringVersionCheck, BinaryBridge;
237
+ var DEFAULT_BRIDGE_TIMEOUT_MS = 30000, BRIDGE_HANG_TIMEOUT_THRESHOLD = 2, SEMANTIC_TIMEOUT_SAFETY_MARGIN_MS = 5000, MAX_STDOUT_BUFFER, STDOUT_BUFFER_COMPACT_THRESHOLD, TERMINAL_BASH_STATUSES, BENIGN_CPUINFO_PROC_CPUINFO_PARSE_FAILURE = "failed to parse processor information from /proc/cpuinfo", BridgeReplacedDuringVersionCheck, BinaryBridge;
230
238
  var init_bridge = __esm(() => {
231
239
  init_active_logger();
232
240
  init_command_timeouts();
@@ -264,6 +272,7 @@ var init_bridge = __esm(() => {
264
272
  _restartCount = 0;
265
273
  _shuttingDown = false;
266
274
  timeoutMs;
275
+ hangThreshold;
267
276
  maxRestarts;
268
277
  configured = false;
269
278
  _configurePromise = null;
@@ -288,6 +297,7 @@ var init_bridge = __esm(() => {
288
297
  this.binaryPath = binaryPath;
289
298
  this.cwd = cwd;
290
299
  this.timeoutMs = options?.timeoutMs ?? DEFAULT_BRIDGE_TIMEOUT_MS;
300
+ this.hangThreshold = options?.hangThreshold ?? BRIDGE_HANG_TIMEOUT_THRESHOLD;
291
301
  this.maxRestarts = options?.maxRestarts ?? 3;
292
302
  this.configOverrides = clampSemanticTimeout(configOverrides ?? {}, this.timeoutMs);
293
303
  this.minVersion = options?.minVersion;
@@ -405,7 +415,9 @@ var init_bridge = __esm(() => {
405
415
  if (requestSessionId && options?.configureWarningClient !== undefined) {
406
416
  this.configureWarningClients.set(requestSessionId, options.configureWarningClient);
407
417
  }
408
- const effectiveTimeoutMs = options?.transportTimeoutMs ?? options?.timeoutMs ?? this.timeoutMs;
418
+ const passive = isPassiveCommand(command);
419
+ const resolvedTimeoutMs = options?.transportTimeoutMs ?? options?.timeoutMs ?? this.timeoutMs;
420
+ const effectiveTimeoutMs = passive ? Math.min(resolvedTimeoutMs, PASSIVE_COMMAND_TIMEOUT_MS) : resolvedTimeoutMs;
409
421
  const implicitTransportOptions = {
410
422
  ...options?.transportTimeoutMs !== undefined || options?.timeoutMs !== undefined ? { transportTimeoutMs: effectiveTimeoutMs } : {},
411
423
  markConfiguredOnSuccess: false
@@ -455,7 +467,7 @@ var init_bridge = __esm(() => {
455
467
  }
456
468
  const line = `${JSON.stringify(request)}
457
469
  `;
458
- const keepBridgeOnTimeout = options?.keepBridgeOnTimeout === true;
470
+ const keepBridgeOnTimeout = passive || options?.keepBridgeOnTimeout === true;
459
471
  let requestSentAt = Date.now();
460
472
  const response = await new Promise((resolve, reject) => {
461
473
  const timer = setTimeout(() => {
@@ -477,7 +489,7 @@ var init_bridge = __esm(() => {
477
489
  const childActiveSinceRequest = this.lastChildActivityAt > requestSentAt;
478
490
  const consecutiveTimeouts = this.consecutiveRequestTimeouts + 1;
479
491
  this.consecutiveRequestTimeouts = consecutiveTimeouts;
480
- const keepWarm = childActiveSinceRequest || consecutiveTimeouts < BRIDGE_HANG_TIMEOUT_THRESHOLD;
492
+ const keepWarm = childActiveSinceRequest || consecutiveTimeouts < this.hangThreshold;
481
493
  const restartSuffix = keepWarm ? " — bridge kept warm" : " — restarting bridge";
482
494
  const timeoutMsg = `Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms${restartSuffix}`;
483
495
  if (requestSessionId) {
@@ -772,7 +784,7 @@ var init_bridge = __esm(() => {
772
784
  `)) !== -1) {
773
785
  const line = this.stderrBuffer.slice(0, newlineIdx).replace(/\r$/, "");
774
786
  this.stderrBuffer = this.stderrBuffer.slice(newlineIdx + 1);
775
- if (!line)
787
+ if (!line || !shouldSurfaceStderrLine(line))
776
788
  continue;
777
789
  const tagged = tagStderrLine(line);
778
790
  this.logVia(tagged);
@@ -782,7 +794,7 @@ var init_bridge = __esm(() => {
782
794
  flushStderrBuffer() {
783
795
  const line = this.stderrBuffer.replace(/\r$/, "");
784
796
  this.stderrBuffer = "";
785
- if (!line)
797
+ if (!line || !shouldSurfaceStderrLine(line))
786
798
  return;
787
799
  const tagged = tagStderrLine(line);
788
800
  this.logVia(tagged);
@@ -1304,6 +1316,7 @@ class BridgePool {
1304
1316
  this.projectConfigLoader = options.projectConfigLoader;
1305
1317
  this.bridgeOptions = {
1306
1318
  timeoutMs: options.timeoutMs,
1319
+ hangThreshold: options.hangThreshold,
1307
1320
  maxRestarts: options.maxRestarts,
1308
1321
  minVersion: options.minVersion,
1309
1322
  onVersionMismatch: options.onVersionMismatch,
@@ -12375,11 +12388,232 @@ var init_binary_cache = __esm(() => {
12375
12388
  init_paths2();
12376
12389
  });
12377
12390
 
12378
- // src/lib/lsp-cache.ts
12379
- import { existsSync as existsSync10, readdirSync as readdirSync5, rmSync as rmSync2, statSync as statSync6 } from "node:fs";
12391
+ // src/lib/sanitize.ts
12392
+ import { realpathSync as realpathSync2 } from "node:fs";
12393
+ import { homedir as homedir8, userInfo } from "node:os";
12394
+ function escapeRegex(value) {
12395
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
12396
+ }
12397
+ function safeRealpath(p2) {
12398
+ try {
12399
+ return realpathSync2(p2);
12400
+ } catch {
12401
+ return null;
12402
+ }
12403
+ }
12404
+ function isSensitiveKeyName(keyName) {
12405
+ return SENSITIVE_KEY_WORD.test(keyName) || SEGMENTED_KEY_WORD.test(keyName) || CAMEL_CASE_KEY_WORD.test(keyName);
12406
+ }
12407
+ function redactSecrets(content) {
12408
+ let sanitized = content;
12409
+ sanitized = sanitized.replace(/\b((?:Proxy-)?Authorization[^\S\r\n]*:[^\S\r\n]*(?:Bearer|Basic)[^\S\r\n]+)[A-Za-z0-9._~+/-]+=*/gi, `$1${SECRET_PLACEHOLDER}`);
12410
+ sanitized = sanitized.replace(/\bgithub_pat_[A-Za-z0-9_]+\b/g, SECRET_PLACEHOLDER);
12411
+ sanitized = sanitized.replace(/\bgh(?:p|o|s)_[A-Za-z0-9_]{16,}\b/g, SECRET_PLACEHOLDER);
12412
+ sanitized = sanitized.replace(/\bsk-(?:live-)?[A-Za-z0-9][A-Za-z0-9_-]{7,}\b/g, SECRET_PLACEHOLDER);
12413
+ sanitized = sanitized.replace(JWT_PATTERN, SECRET_PLACEHOLDER);
12414
+ sanitized = sanitized.replace(AWS_ACCESS_KEY_ID_PATTERN, SECRET_PLACEHOLDER);
12415
+ sanitized = sanitized.replace(quotedSensitiveKeyValuePattern, (match, prefix, _keyQuote, keyName, valueQuote) => isSensitiveKeyName(keyName) ? `${prefix}${valueQuote}${SECRET_PLACEHOLDER}${valueQuote}` : match);
12416
+ sanitized = sanitized.replace(unquotedSensitiveKeyValuePattern, (match, prefix, keyName, valueQuote) => isSensitiveKeyName(keyName) ? `${prefix}${valueQuote}${SECRET_PLACEHOLDER}${valueQuote}` : match);
12417
+ sanitized = sanitized.replace(bareSensitiveKeyValuePattern, (match, prefix, keyName) => isSensitiveKeyName(keyName) ? `${prefix}${SECRET_PLACEHOLDER}` : match);
12418
+ sanitized = sanitized.replace(/\b([a-z][a-z0-9+.-]*:\/\/)[^@\s/?#]+@/gi, `$1${URL_CREDENTIAL_PLACEHOLDER}@`);
12419
+ sanitized = sanitized.replace(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi, "<EMAIL>");
12420
+ return sanitized;
12421
+ }
12422
+ function sanitizeContent(content) {
12423
+ const username = userInfo().username;
12424
+ const home = homedir8();
12425
+ let sanitized = redactSecrets(content);
12426
+ const cwd = process.cwd();
12427
+ for (const candidate of new Set([cwd, safeRealpath(cwd)])) {
12428
+ if (candidate && candidate !== "/" && candidate !== home) {
12429
+ sanitized = sanitized.replace(new RegExp(escapeRegex(candidate), "g"), "<PROJECT>");
12430
+ }
12431
+ }
12432
+ if (home) {
12433
+ sanitized = sanitized.replace(new RegExp(escapeRegex(home), "g"), "~");
12434
+ }
12435
+ sanitized = sanitized.replace(/\/Users\/[^/\s"']+/g, "/Users/<USER>");
12436
+ sanitized = sanitized.replace(/\/home\/[^/\s"']+/g, "/home/<USER>");
12437
+ sanitized = sanitized.replace(/([A-Za-z]:\\\\Users\\\\)[^\\\\"'\s]+/g, "$1<USER>");
12438
+ sanitized = sanitized.replace(/([A-Za-z]:\\Users\\)[^\\"'\s]+/g, "$1<USER>");
12439
+ sanitized = sanitized.replace(/([A-Za-z]:\/Users\/)[^/\s"']+/g, "$1<USER>");
12440
+ if (username) {
12441
+ sanitized = sanitized.replace(new RegExp(escapeRegex(username), "g"), "<USER>");
12442
+ }
12443
+ return sanitized;
12444
+ }
12445
+ function sanitizeValue(value) {
12446
+ if (typeof value === "string") {
12447
+ return sanitizeContent(value);
12448
+ }
12449
+ if (Array.isArray(value)) {
12450
+ return value.map((entry) => sanitizeValue(entry));
12451
+ }
12452
+ if (value && typeof value === "object") {
12453
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, sanitizeValue(entry)]));
12454
+ }
12455
+ return value;
12456
+ }
12457
+ var SECRET_PLACEHOLDER = "<REDACTED_SECRET>", URL_CREDENTIAL_PLACEHOLDER = "***", KEY_NAME = "[A-Za-z_][A-Za-z0-9_.-]*", SENSITIVE_KEY_WORD, SEGMENTED_KEY_WORD, CAMEL_CASE_KEY_WORD, JWT_PATTERN, AWS_ACCESS_KEY_ID_PATTERN, quotedSensitiveKeyValuePattern, unquotedSensitiveKeyValuePattern, bareSensitiveKeyValuePattern;
12458
+ var init_sanitize = __esm(() => {
12459
+ SENSITIVE_KEY_WORD = /(?:token|password|secret|api[_-]?key|passwd|pwd|credential)/i;
12460
+ SEGMENTED_KEY_WORD = /(?:^|[_.-])key(?:$|[_.-])/i;
12461
+ CAMEL_CASE_KEY_WORD = /[a-z0-9]Key(?:$|[A-Z_.-])/;
12462
+ JWT_PATTERN = /\beyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g;
12463
+ AWS_ACCESS_KEY_ID_PATTERN = /\b(?:AKIA|ASIA|AGPA|AIDA|AROA)[A-Z0-9]{16}\b/g;
12464
+ quotedSensitiveKeyValuePattern = new RegExp(String.raw`((['"])(${KEY_NAME})\2[^\S\r\n]*:[^\S\r\n]*)(['"])([^'"\r\n]+)\4`, "gi");
12465
+ unquotedSensitiveKeyValuePattern = new RegExp(String.raw`\b((${KEY_NAME})[^\S\r\n]*[=:][^\S\r\n]*)(['"])([^'"\r\n]+)\3`, "gi");
12466
+ bareSensitiveKeyValuePattern = new RegExp(String.raw`\b((${KEY_NAME})[^\S\r\n]*[=:][^\S\r\n]*)([^\s,;&'"]+)`, "gi");
12467
+ });
12468
+
12469
+ // src/lib/bridge-tool-failures.ts
12470
+ import { closeSync as closeSync2, existsSync as existsSync10, openSync as openSync2, readSync as readSync2, statSync as statSync6 } from "node:fs";
12471
+ import { tmpdir as tmpdir2 } from "node:os";
12380
12472
  import { join as join10 } from "node:path";
12473
+ function resolveBridgePluginLogPath() {
12474
+ const isTestEnv = process.env.BUN_TEST === "1" || false;
12475
+ return join10(tmpdir2(), isTestEnv ? "aft-plugin-test.log" : "aft-plugin.log");
12476
+ }
12477
+ function tailLogFileBytes(path, maxBytes) {
12478
+ if (!existsSync10(path) || maxBytes <= 0)
12479
+ return "";
12480
+ let fd = null;
12481
+ try {
12482
+ const size = statSync6(path).size;
12483
+ if (size === 0)
12484
+ return "";
12485
+ const readLength = Math.min(size, maxBytes);
12486
+ const position = size - readLength;
12487
+ fd = openSync2(path, "r");
12488
+ const buffer = Buffer.allocUnsafe(readLength);
12489
+ const bytesRead = readSync2(fd, buffer, 0, readLength, position);
12490
+ return buffer.subarray(0, bytesRead).toString("utf-8").trim();
12491
+ } catch {
12492
+ return "";
12493
+ } finally {
12494
+ if (fd !== null) {
12495
+ try {
12496
+ closeSync2(fd);
12497
+ } catch {}
12498
+ }
12499
+ }
12500
+ }
12501
+ function stripSessionTags(line) {
12502
+ return line.replace(SESSION_TAG_PATTERN, "").replace(/\s+/g, " ").trim();
12503
+ }
12504
+ function stripPathLikeTokens(label) {
12505
+ let out = label;
12506
+ out = out.replace(/\/(?:Users|home|var|tmp|private|Volumes)\/[^\s"'`,;)]+/gi, "<path>");
12507
+ out = out.replace(/[A-Za-z]:\\(?:Users|Program Files)[^\\s"'`,;)]+/gi, "<path>");
12508
+ out = out.replace(/file:\/\/[^\s"'`,;)]+/gi, "<path>");
12509
+ out = out.replace(/\(id=[^)]+\)/gi, "");
12510
+ return out.replace(/\s+/g, " ").trim();
12511
+ }
12512
+ function classifyBridgeLogLine(line) {
12513
+ const timeoutMatch = line.match(/Request "([^"]+)"[\s\S]*?timed out after (\d+)ms/i);
12514
+ if (timeoutMatch) {
12515
+ return `${timeoutMatch[1]}: timed out after ${timeoutMatch[2]}ms`;
12516
+ }
12517
+ const lowerTimeout = line.match(/request "([^"]+)" timed out after (\d+)ms/i);
12518
+ if (lowerTimeout) {
12519
+ return `${lowerTimeout[1]}: timed out after ${lowerTimeout[2]}ms`;
12520
+ }
12521
+ if (/Bridge killed after timeout/i.test(line)) {
12522
+ return "bridge killed after timeout";
12523
+ }
12524
+ if (/bridge killed during sibling timeout/i.test(line)) {
12525
+ return "bridge killed during sibling timeout";
12526
+ }
12527
+ if (/restarting bridge/i.test(line)) {
12528
+ return "restarting bridge";
12529
+ }
12530
+ const rpcMatch = line.match(/RPC error:\s*([^\s=]+)/i);
12531
+ if (rpcMatch) {
12532
+ return `rpc: RPC error (${rpcMatch[1]})`;
12533
+ }
12534
+ if (/spawn error/i.test(line)) {
12535
+ return "spawn: spawn error";
12536
+ }
12537
+ if (/failed to spawn/i.test(line)) {
12538
+ return "spawn: failed to spawn";
12539
+ }
12540
+ if (/\bonnx/i.test(line) && /\b(?:error|failed|missing|incompatible)\b/i.test(line)) {
12541
+ return "onnx: onnx runtime error";
12542
+ }
12543
+ if (/\bORT_/i.test(line) && /\b(?:error|failed)\b/i.test(line)) {
12544
+ return "onnx: ORT error";
12545
+ }
12546
+ const codeMatch = line.match(STRUCTURED_CODE_PATTERN);
12547
+ if (codeMatch && /\bERROR\b/.test(line)) {
12548
+ return `code: ${codeMatch[1]}`;
12549
+ }
12550
+ if (/\bERROR\b/.test(line) && /\[aft-plugin\]|\[aft-bridge\]|\[aft-lsp\]|\[aft\]/i.test(line)) {
12551
+ return "error: ERROR log line";
12552
+ }
12553
+ return null;
12554
+ }
12555
+ function aggregateBridgeToolFailures(logText) {
12556
+ const counts = new Map;
12557
+ if (!logText.trim())
12558
+ return counts;
12559
+ for (const rawLine of logText.split(/\r?\n/)) {
12560
+ if (!stripSessionTags(rawLine))
12561
+ continue;
12562
+ const key = classifyBridgeLogLine(rawLine);
12563
+ if (!key)
12564
+ continue;
12565
+ const sanitizedKey = stripPathLikeTokens(sanitizeContent(key));
12566
+ if (!sanitizedKey)
12567
+ continue;
12568
+ counts.set(sanitizedKey, (counts.get(sanitizedKey) ?? 0) + 1);
12569
+ }
12570
+ return counts;
12571
+ }
12572
+ function sortFailureKeys(a, b, counts) {
12573
+ const countDiff = (counts.get(b) ?? 0) - (counts.get(a) ?? 0);
12574
+ if (countDiff !== 0)
12575
+ return countDiff;
12576
+ return a.localeCompare(b);
12577
+ }
12578
+ function formatRecentAftToolFailuresSection(counts, options) {
12579
+ const maxClasses = options?.maxClasses ?? MAX_TOOL_FAILURE_CLASSES;
12580
+ const heading = "### Recent AFT tool failures";
12581
+ if (counts.size === 0) {
12582
+ return `${heading}
12583
+ No recent AFT tool failures recorded.`;
12584
+ }
12585
+ const sorted = [...counts.keys()].sort((a, b) => sortFailureKeys(a, b, counts));
12586
+ const shown = sorted.slice(0, maxClasses);
12587
+ const hidden = sorted.length - shown.length;
12588
+ const bullets = shown.map((key) => {
12589
+ const count = counts.get(key) ?? 0;
12590
+ return `- ${key} ×${count}`;
12591
+ });
12592
+ if (hidden > 0) {
12593
+ bullets.push(`- +${hidden} more failure class(es) omitted`);
12594
+ }
12595
+ return [heading, ...bullets].join(`
12596
+ `);
12597
+ }
12598
+ function buildRecentAftToolFailuresSectionFromLog(logPath = resolveBridgePluginLogPath(), options) {
12599
+ const tailBytes = options?.tailBytes ?? BRIDGE_LOG_TAIL_BYTES;
12600
+ const tail = tailLogFileBytes(logPath, tailBytes);
12601
+ const counts = aggregateBridgeToolFailures(tail);
12602
+ return formatRecentAftToolFailuresSection(counts, options);
12603
+ }
12604
+ var BRIDGE_LOG_TAIL_BYTES, MAX_TOOL_FAILURE_CLASSES = 30, SESSION_TAG_PATTERN, STRUCTURED_CODE_PATTERN;
12605
+ var init_bridge_tool_failures = __esm(() => {
12606
+ init_sanitize();
12607
+ BRIDGE_LOG_TAIL_BYTES = 2 * 1024 * 1024;
12608
+ SESSION_TAG_PATTERN = /\[ses_[^\]\s]+\]|\[[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\]/g;
12609
+ STRUCTURED_CODE_PATTERN = /"code"\s*:\s*"([^"]+)"/;
12610
+ });
12611
+
12612
+ // src/lib/lsp-cache.ts
12613
+ import { existsSync as existsSync11, readdirSync as readdirSync5, rmSync as rmSync2, statSync as statSync7 } from "node:fs";
12614
+ import { join as join11 } from "node:path";
12381
12615
  function inspectDir(path) {
12382
- if (!existsSync10(path)) {
12616
+ if (!existsSync11(path)) {
12383
12617
  return { entries: [], totalSize: 0 };
12384
12618
  }
12385
12619
  const entries = [];
@@ -12391,9 +12625,9 @@ function inspectDir(path) {
12391
12625
  return { entries: [], totalSize: 0 };
12392
12626
  }
12393
12627
  for (const name of names) {
12394
- const full = join10(path, name);
12628
+ const full = join11(path, name);
12395
12629
  try {
12396
- if (!statSync6(full).isDirectory())
12630
+ if (!statSync7(full).isDirectory())
12397
12631
  continue;
12398
12632
  const size = dirSize(full);
12399
12633
  entries.push({
@@ -12449,8 +12683,8 @@ var init_lsp_cache = __esm(() => {
12449
12683
  });
12450
12684
 
12451
12685
  // src/lib/onnx.ts
12452
- import { existsSync as existsSync11, readdirSync as readdirSync6, readlinkSync, realpathSync as realpathSync2, statSync as statSync7 } from "node:fs";
12453
- import { basename, isAbsolute as isAbsolute2, join as join11, resolve as resolve4, win32 } from "node:path";
12686
+ import { existsSync as existsSync12, readdirSync as readdirSync6, readlinkSync, realpathSync as realpathSync3, statSync as statSync8 } from "node:fs";
12687
+ import { basename, isAbsolute as isAbsolute2, join as join12, resolve as resolve4, win32 } from "node:path";
12454
12688
  function getOnnxLibraryName() {
12455
12689
  if (process.platform === "darwin")
12456
12690
  return "libonnxruntime.dylib";
@@ -12513,13 +12747,13 @@ function findSystemOnnxRuntime() {
12513
12747
  searchPaths.push(...pathEntriesForPlatform());
12514
12748
  const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
12515
12749
  const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
12516
- searchPaths.push(join11(programFiles, "onnxruntime", "lib"), join11(programFiles, "Microsoft ONNX Runtime", "lib"), join11(programFiles, "Microsoft Machine Learning", "lib"), join11(programFilesX86, "onnxruntime", "lib"), ...(() => {
12750
+ searchPaths.push(join12(programFiles, "onnxruntime", "lib"), join12(programFiles, "Microsoft ONNX Runtime", "lib"), join12(programFiles, "Microsoft Machine Learning", "lib"), join12(programFilesX86, "onnxruntime", "lib"), ...(() => {
12517
12751
  const nugetPaths = [];
12518
12752
  const userProfile = process.env.USERPROFILE ?? "";
12519
12753
  if (!userProfile)
12520
12754
  return nugetPaths;
12521
- const nugetPackageDir = join11(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
12522
- if (!existsSync11(nugetPackageDir))
12755
+ const nugetPackageDir = join12(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
12756
+ if (!existsSync12(nugetPackageDir))
12523
12757
  return nugetPaths;
12524
12758
  try {
12525
12759
  for (const entry of readdirSync6(nugetPackageDir, { withFileTypes: true })) {
@@ -12527,7 +12761,7 @@ function findSystemOnnxRuntime() {
12527
12761
  continue;
12528
12762
  if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
12529
12763
  continue;
12530
- nugetPaths.push(join11(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join11(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
12764
+ nugetPaths.push(join12(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join12(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
12531
12765
  }
12532
12766
  } catch {}
12533
12767
  return nugetPaths;
@@ -12557,12 +12791,12 @@ function findSystemOnnxRuntime() {
12557
12791
  return unknownVersionPaths[0] ?? null;
12558
12792
  }
12559
12793
  function findCachedOnnxRuntime(storageDir) {
12560
- const ortDir = join11(storageDir, "onnxruntime", ONNX_RUNTIME_VERSION);
12794
+ const ortDir = join12(storageDir, "onnxruntime", ONNX_RUNTIME_VERSION);
12561
12795
  const libName = getOnnxLibraryName();
12562
- if (existsSync11(join11(ortDir, libName)))
12796
+ if (existsSync12(join12(ortDir, libName)))
12563
12797
  return ortDir;
12564
- const libSubdir = join11(ortDir, "lib");
12565
- if (existsSync11(join11(libSubdir, libName)))
12798
+ const libSubdir = join12(ortDir, "lib");
12799
+ if (existsSync12(join12(libSubdir, libName)))
12566
12800
  return libSubdir;
12567
12801
  return null;
12568
12802
  }
@@ -12583,7 +12817,7 @@ function parseOrtVersionFromDirectoryPath(value) {
12583
12817
  return null;
12584
12818
  }
12585
12819
  function detectOrtVersion(libDir) {
12586
- if (!existsSync11(libDir))
12820
+ if (!existsSync12(libDir))
12587
12821
  return null;
12588
12822
  const libName = getOnnxLibraryName();
12589
12823
  try {
@@ -12598,10 +12832,10 @@ function detectOrtVersion(libDir) {
12598
12832
  if (version)
12599
12833
  return version;
12600
12834
  }
12601
- const base = join11(libDir, libName);
12602
- if (existsSync11(base)) {
12835
+ const base = join12(libDir, libName);
12836
+ if (existsSync12(base)) {
12603
12837
  try {
12604
- const real = realpathSync2(base);
12838
+ const real = realpathSync3(base);
12605
12839
  const version = parseOrtVersionFromPath(real) ?? parseOrtVersionFromDirectoryPath(real);
12606
12840
  if (version)
12607
12841
  return version;
@@ -12629,93 +12863,15 @@ function isOrtVersionCompatible(version) {
12629
12863
  var ONNX_RUNTIME_VERSION = "1.24.4", INVALID_ORT_VERSION = "<invalid>", REQUIRED_ORT_MAJOR = 1, REQUIRED_ORT_MIN_MINOR = 20;
12630
12864
  var init_onnx = () => {};
12631
12865
 
12632
- // src/lib/sanitize.ts
12633
- import { realpathSync as realpathSync3 } from "node:fs";
12634
- import { homedir as homedir8, userInfo } from "node:os";
12635
- function escapeRegex(value) {
12636
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
12637
- }
12638
- function safeRealpath(p2) {
12639
- try {
12640
- return realpathSync3(p2);
12641
- } catch {
12642
- return null;
12643
- }
12644
- }
12645
- function isSensitiveKeyName(keyName) {
12646
- return SENSITIVE_KEY_WORD.test(keyName) || SEGMENTED_KEY_WORD.test(keyName) || CAMEL_CASE_KEY_WORD.test(keyName);
12647
- }
12648
- function redactSecrets(content) {
12649
- let sanitized = content;
12650
- sanitized = sanitized.replace(/\b((?:Proxy-)?Authorization[^\S\r\n]*:[^\S\r\n]*(?:Bearer|Basic)[^\S\r\n]+)[A-Za-z0-9._~+/-]+=*/gi, `$1${SECRET_PLACEHOLDER}`);
12651
- sanitized = sanitized.replace(/\bgithub_pat_[A-Za-z0-9_]+\b/g, SECRET_PLACEHOLDER);
12652
- sanitized = sanitized.replace(/\bgh(?:p|o|s)_[A-Za-z0-9_]{16,}\b/g, SECRET_PLACEHOLDER);
12653
- sanitized = sanitized.replace(/\bsk-(?:live-)?[A-Za-z0-9][A-Za-z0-9_-]{7,}\b/g, SECRET_PLACEHOLDER);
12654
- sanitized = sanitized.replace(JWT_PATTERN, SECRET_PLACEHOLDER);
12655
- sanitized = sanitized.replace(AWS_ACCESS_KEY_ID_PATTERN, SECRET_PLACEHOLDER);
12656
- sanitized = sanitized.replace(quotedSensitiveKeyValuePattern, (match, prefix, _keyQuote, keyName, valueQuote) => isSensitiveKeyName(keyName) ? `${prefix}${valueQuote}${SECRET_PLACEHOLDER}${valueQuote}` : match);
12657
- sanitized = sanitized.replace(unquotedSensitiveKeyValuePattern, (match, prefix, keyName, valueQuote) => isSensitiveKeyName(keyName) ? `${prefix}${valueQuote}${SECRET_PLACEHOLDER}${valueQuote}` : match);
12658
- sanitized = sanitized.replace(bareSensitiveKeyValuePattern, (match, prefix, keyName) => isSensitiveKeyName(keyName) ? `${prefix}${SECRET_PLACEHOLDER}` : match);
12659
- sanitized = sanitized.replace(/\b([a-z][a-z0-9+.-]*:\/\/)[^@\s/?#]+@/gi, `$1${URL_CREDENTIAL_PLACEHOLDER}@`);
12660
- sanitized = sanitized.replace(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi, "<EMAIL>");
12661
- return sanitized;
12662
- }
12663
- function sanitizeContent(content) {
12664
- const username = userInfo().username;
12665
- const home = homedir8();
12666
- let sanitized = redactSecrets(content);
12667
- const cwd = process.cwd();
12668
- for (const candidate of new Set([cwd, safeRealpath(cwd)])) {
12669
- if (candidate && candidate !== "/" && candidate !== home) {
12670
- sanitized = sanitized.replace(new RegExp(escapeRegex(candidate), "g"), "<PROJECT>");
12671
- }
12672
- }
12673
- if (home) {
12674
- sanitized = sanitized.replace(new RegExp(escapeRegex(home), "g"), "~");
12675
- }
12676
- sanitized = sanitized.replace(/\/Users\/[^/\s"']+/g, "/Users/<USER>");
12677
- sanitized = sanitized.replace(/\/home\/[^/\s"']+/g, "/home/<USER>");
12678
- sanitized = sanitized.replace(/([A-Za-z]:\\\\Users\\\\)[^\\\\"'\s]+/g, "$1<USER>");
12679
- sanitized = sanitized.replace(/([A-Za-z]:\\Users\\)[^\\"'\s]+/g, "$1<USER>");
12680
- sanitized = sanitized.replace(/([A-Za-z]:\/Users\/)[^/\s"']+/g, "$1<USER>");
12681
- if (username) {
12682
- sanitized = sanitized.replace(new RegExp(escapeRegex(username), "g"), "<USER>");
12683
- }
12684
- return sanitized;
12685
- }
12686
- function sanitizeValue(value) {
12687
- if (typeof value === "string") {
12688
- return sanitizeContent(value);
12689
- }
12690
- if (Array.isArray(value)) {
12691
- return value.map((entry) => sanitizeValue(entry));
12692
- }
12693
- if (value && typeof value === "object") {
12694
- return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, sanitizeValue(entry)]));
12695
- }
12696
- return value;
12697
- }
12698
- var SECRET_PLACEHOLDER = "<REDACTED_SECRET>", URL_CREDENTIAL_PLACEHOLDER = "***", KEY_NAME = "[A-Za-z_][A-Za-z0-9_.-]*", SENSITIVE_KEY_WORD, SEGMENTED_KEY_WORD, CAMEL_CASE_KEY_WORD, JWT_PATTERN, AWS_ACCESS_KEY_ID_PATTERN, quotedSensitiveKeyValuePattern, unquotedSensitiveKeyValuePattern, bareSensitiveKeyValuePattern;
12699
- var init_sanitize = __esm(() => {
12700
- SENSITIVE_KEY_WORD = /(?:token|password|secret|api[_-]?key|passwd|pwd|credential)/i;
12701
- SEGMENTED_KEY_WORD = /(?:^|[_.-])key(?:$|[_.-])/i;
12702
- CAMEL_CASE_KEY_WORD = /[a-z0-9]Key(?:$|[A-Z_.-])/;
12703
- JWT_PATTERN = /\beyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g;
12704
- AWS_ACCESS_KEY_ID_PATTERN = /\b(?:AKIA|ASIA|AGPA|AIDA|AROA)[A-Z0-9]{16}\b/g;
12705
- quotedSensitiveKeyValuePattern = new RegExp(String.raw`((['"])(${KEY_NAME})\2[^\S\r\n]*:[^\S\r\n]*)(['"])([^'"\r\n]+)\4`, "gi");
12706
- unquotedSensitiveKeyValuePattern = new RegExp(String.raw`\b((${KEY_NAME})[^\S\r\n]*[=:][^\S\r\n]*)(['"])([^'"\r\n]+)\3`, "gi");
12707
- bareSensitiveKeyValuePattern = new RegExp(String.raw`\b((${KEY_NAME})[^\S\r\n]*[=:][^\S\r\n]*)([^\s,;&'"]+)`, "gi");
12708
- });
12709
-
12710
12866
  // src/lib/diagnostics.ts
12711
12867
  import {
12712
12868
  accessSync,
12713
- closeSync as closeSync2,
12869
+ closeSync as closeSync3,
12714
12870
  constants,
12715
- existsSync as existsSync12,
12716
- openSync as openSync2,
12717
- readSync as readSync2,
12718
- statSync as statSync8
12871
+ existsSync as existsSync13,
12872
+ openSync as openSync3,
12873
+ readSync as readSync3,
12874
+ statSync as statSync9
12719
12875
  } from "node:fs";
12720
12876
  async function collectDiagnostics(adapters) {
12721
12877
  const cliVersion = getSelfVersion();
@@ -12744,7 +12900,7 @@ async function diagnoseHarness(adapter) {
12744
12900
  const logPath = adapter.getLogFile();
12745
12901
  const pluginCache = adapter.getPluginCacheInfo();
12746
12902
  const storageAccessible = (() => {
12747
- if (!existsSync12(storage))
12903
+ if (!existsSync13(storage))
12748
12904
  return false;
12749
12905
  try {
12750
12906
  accessSync(storage, constants.R_OK | constants.W_OK);
@@ -12767,14 +12923,14 @@ async function diagnoseHarness(adapter) {
12767
12923
  pluginRegistered: adapter.hasPluginEntry(),
12768
12924
  configPaths,
12769
12925
  aftConfig: {
12770
- exists: existsSync12(configPaths.aftConfig),
12926
+ exists: existsSync13(configPaths.aftConfig),
12771
12927
  ...aftConfigRead.error ? { parseError: aftConfigRead.error } : {},
12772
12928
  flags: aftFlags
12773
12929
  },
12774
12930
  pluginCache,
12775
12931
  storageDir: {
12776
12932
  path: storage,
12777
- exists: existsSync12(storage),
12933
+ exists: existsSync13(storage),
12778
12934
  accessible: storageAccessible,
12779
12935
  sizesByKey: describeStorage
12780
12936
  },
@@ -12792,8 +12948,8 @@ async function diagnoseHarness(adapter) {
12792
12948
  },
12793
12949
  logFile: {
12794
12950
  path: logPath,
12795
- exists: existsSync12(logPath),
12796
- sizeKb: existsSync12(logPath) ? Math.round(statSync8(logPath).size / 1024) : 0
12951
+ exists: existsSync13(logPath),
12952
+ sizeKb: existsSync13(logPath) ? Math.round(statSync9(logPath).size / 1024) : 0
12797
12953
  }
12798
12954
  };
12799
12955
  }
@@ -12987,15 +13143,15 @@ function formatDiagnosticIssuesSection(report) {
12987
13143
  return lines;
12988
13144
  }
12989
13145
  function tailLogFile(path, lines) {
12990
- if (!existsSync12(path))
13146
+ if (!existsSync13(path))
12991
13147
  return "";
12992
13148
  if (lines <= 0)
12993
13149
  return "";
12994
13150
  const chunkSize = 64 * 1024;
12995
13151
  let fd = null;
12996
13152
  try {
12997
- const size = statSync8(path).size;
12998
- fd = openSync2(path, "r");
13153
+ const size = statSync9(path).size;
13154
+ fd = openSync3(path, "r");
12999
13155
  const chunks = [];
13000
13156
  let position = size;
13001
13157
  let newlineCount = 0;
@@ -13003,7 +13159,7 @@ function tailLogFile(path, lines) {
13003
13159
  const readLength = Math.min(chunkSize, position);
13004
13160
  position -= readLength;
13005
13161
  const buffer = Buffer.allocUnsafe(readLength);
13006
- const bytesRead = readSync2(fd, buffer, 0, readLength, position);
13162
+ const bytesRead = readSync3(fd, buffer, 0, readLength, position);
13007
13163
  const chunk = bytesRead === readLength ? buffer : buffer.subarray(0, bytesRead);
13008
13164
  chunks.unshift(chunk);
13009
13165
  for (let i = chunk.length - 1;i >= 0; i -= 1) {
@@ -13018,7 +13174,7 @@ function tailLogFile(path, lines) {
13018
13174
  } finally {
13019
13175
  if (fd !== null) {
13020
13176
  try {
13021
- closeSync2(fd);
13177
+ closeSync3(fd);
13022
13178
  } catch {}
13023
13179
  }
13024
13180
  }
@@ -13077,7 +13233,7 @@ var init_github = () => {};
13077
13233
  function filterLogToSession(logText, sessionId) {
13078
13234
  const bareId = sessionId.replace(/^ses_/, "");
13079
13235
  const keepTokens = [`[ses_${bareId}]`, `[${bareId}]`];
13080
- return logText.split(/\r?\n/).filter((line) => !SESSION_TAG_PATTERN.test(line) || keepTokens.some((token) => line.includes(token))).join(`
13236
+ return logText.split(/\r?\n/).filter((line) => !SESSION_TAG_PATTERN2.test(line) || keepTokens.some((token) => line.includes(token))).join(`
13081
13237
  `);
13082
13238
  }
13083
13239
  function isErrorLogLine(line) {
@@ -13157,9 +13313,9 @@ function truncateToByteBudget(input, maxBytes) {
13157
13313
  }
13158
13314
  return buf.subarray(0, end).toString("utf8");
13159
13315
  }
13160
- var MAX_GITHUB_BODY_BYTES = 60000, SESSION_TAG_PATTERN, ERROR_LOG_PATTERNS;
13316
+ var MAX_GITHUB_BODY_BYTES = 60000, SESSION_TAG_PATTERN2, ERROR_LOG_PATTERNS;
13161
13317
  var init_issue_body = __esm(() => {
13162
- SESSION_TAG_PATTERN = /\[ses_[^\]\s]+\]|\[[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\]/;
13318
+ SESSION_TAG_PATTERN2 = /\[ses_[^\]\s]+\]|\[[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\]/;
13163
13319
  ERROR_LOG_PATTERNS = [
13164
13320
  /\bcrashed:/i,
13165
13321
  /\bfailed:/i,
@@ -13173,8 +13329,8 @@ var init_issue_body = __esm(() => {
13173
13329
  });
13174
13330
 
13175
13331
  // src/lib/onnx-fix.ts
13176
- import { existsSync as existsSync13, rmSync as rmSync3 } from "node:fs";
13177
- import { join as join12 } from "node:path";
13332
+ import { existsSync as existsSync14, rmSync as rmSync3 } from "node:fs";
13333
+ import { join as join13 } from "node:path";
13178
13334
  function findOnnxFixCandidates(report) {
13179
13335
  const candidates = [];
13180
13336
  for (const harness of report.harnesses) {
@@ -13182,7 +13338,7 @@ function findOnnxFixCandidates(report) {
13182
13338
  continue;
13183
13339
  if (!harness.storageDir.exists)
13184
13340
  continue;
13185
- const storageOnnxDir = join12(harness.storageDir.path, "onnxruntime");
13341
+ const storageOnnxDir = join13(harness.storageDir.path, "onnxruntime");
13186
13342
  const systemTooOld = harness.onnxRuntime.systemPath !== null && harness.onnxRuntime.systemCompatible === false;
13187
13343
  const cachedTooOld = harness.onnxRuntime.cachedPath !== null && harness.onnxRuntime.cachedCompatible === false;
13188
13344
  const hasCompatibleCached = harness.onnxRuntime.cachedCompatible === true;
@@ -13191,7 +13347,7 @@ function findOnnxFixCandidates(report) {
13191
13347
  harness,
13192
13348
  reason: `cached ONNX Runtime at ${harness.onnxRuntime.cachedPath} is v${harness.onnxRuntime.cachedVersion}, but AFT requires ${harness.onnxRuntime.requirement}. Clearing forces a fresh download on next start.`,
13193
13349
  storageOnnxDir,
13194
- storageOnnxBytes: existsSync13(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
13350
+ storageOnnxBytes: existsSync14(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
13195
13351
  });
13196
13352
  continue;
13197
13353
  }
@@ -13200,7 +13356,7 @@ function findOnnxFixCandidates(report) {
13200
13356
  harness,
13201
13357
  reason: `system ONNX Runtime at ${harness.onnxRuntime.systemPath} is v${harness.onnxRuntime.systemVersion}, but AFT requires ${harness.onnxRuntime.requirement}, and no AFT-managed install is present. AFT v0.19.5+ skips incompatible system installs and auto-downloads v1.24 on next start; clearing any stale state here ensures a clean slate.`,
13202
13358
  storageOnnxDir,
13203
- storageOnnxBytes: existsSync13(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
13359
+ storageOnnxBytes: existsSync14(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
13204
13360
  });
13205
13361
  }
13206
13362
  }
@@ -13230,7 +13386,7 @@ async function runOnnxFix(adapters, report, options = {}) {
13230
13386
  const result = { cleared: 0, bytesReclaimed: 0, errors: [] };
13231
13387
  const rmFn = options.rmFn ?? rmSync3;
13232
13388
  for (const c2 of candidates) {
13233
- if (!existsSync13(c2.storageOnnxDir)) {
13389
+ if (!existsSync14(c2.storageOnnxDir)) {
13234
13390
  O2.success(`${c2.harness.displayName}: no cached state to clear; restart your harness to trigger a fresh ONNX download`);
13235
13391
  continue;
13236
13392
  }
@@ -13256,10 +13412,10 @@ var init_onnx_fix = __esm(() => {
13256
13412
  });
13257
13413
 
13258
13414
  // src/lib/sessions.ts
13259
- import { existsSync as existsSync14, readdirSync as readdirSync7, readFileSync as readFileSync4, statSync as statSync9 } from "node:fs";
13415
+ import { existsSync as existsSync15, readdirSync as readdirSync7, readFileSync as readFileSync4, statSync as statSync10 } from "node:fs";
13260
13416
  import { createRequire as createRequire3 } from "node:module";
13261
13417
  import { homedir as homedir9 } from "node:os";
13262
- import { basename as basename2, join as join13 } from "node:path";
13418
+ import { basename as basename2, join as join14 } from "node:path";
13263
13419
  function listRecentSessions(adapter) {
13264
13420
  try {
13265
13421
  if (adapter.kind === "opencode")
@@ -13288,8 +13444,8 @@ function mapOpenCodeSessionRows(rows) {
13288
13444
  }).filter((session) => session !== null).sort((a, b) => b.lastActivity - a.lastActivity).slice(0, MAX_RECENT_SESSIONS);
13289
13445
  }
13290
13446
  function listRecentOpenCodeSessions() {
13291
- const dbPath = join13(getXdgDataHome(), "opencode", "opencode.db");
13292
- if (!existsSync14(dbPath))
13447
+ const dbPath = join14(getXdgDataHome(), "opencode", "opencode.db");
13448
+ if (!existsSync15(dbPath))
13293
13449
  return [];
13294
13450
  let db = null;
13295
13451
  try {
@@ -13308,10 +13464,10 @@ function listRecentOpenCodeSessions() {
13308
13464
  }
13309
13465
  function getXdgDataHome() {
13310
13466
  const xdgDataHome = process.env.XDG_DATA_HOME;
13311
- return xdgDataHome && xdgDataHome.length > 0 ? xdgDataHome : join13(homedir9(), ".local", "share");
13467
+ return xdgDataHome && xdgDataHome.length > 0 ? xdgDataHome : join14(homedir9(), ".local", "share");
13312
13468
  }
13313
13469
  function listRecentPiSessions() {
13314
- return listPiSessionsFromDir(join13(getHomeDir(), ".pi", "agent", "sessions"));
13470
+ return listPiSessionsFromDir(join14(getHomeDir(), ".pi", "agent", "sessions"));
13315
13471
  }
13316
13472
  function getHomeDir() {
13317
13473
  const envHome = process.platform === "win32" ? process.env.USERPROFILE : process.env.HOME;
@@ -13319,11 +13475,11 @@ function getHomeDir() {
13319
13475
  }
13320
13476
  function listPiSessionsFromDir(sessionsDir) {
13321
13477
  try {
13322
- if (!existsSync14(sessionsDir))
13478
+ if (!existsSync15(sessionsDir))
13323
13479
  return [];
13324
13480
  const files = collectJsonlFiles(sessionsDir).map((filePath) => {
13325
13481
  try {
13326
- const stats = statSync9(filePath);
13482
+ const stats = statSync10(filePath);
13327
13483
  return { filePath, mtimeMs: stats.mtimeMs };
13328
13484
  } catch {
13329
13485
  return null;
@@ -13357,7 +13513,7 @@ function collectJsonlFiles(root) {
13357
13513
  continue;
13358
13514
  }
13359
13515
  for (const entry of entries) {
13360
- const path = join13(dir, entry.name);
13516
+ const path = join14(dir, entry.name);
13361
13517
  if (entry.isDirectory()) {
13362
13518
  stack.push(path);
13363
13519
  } else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
@@ -13457,17 +13613,17 @@ __export(exports_doctor, {
13457
13613
  import { execFileSync } from "node:child_process";
13458
13614
  import {
13459
13615
  chmodSync as chmodSync2,
13460
- existsSync as existsSync15,
13616
+ existsSync as existsSync16,
13461
13617
  mkdirSync as mkdirSync3,
13462
13618
  mkdtempSync,
13463
13619
  readFileSync as readFileSync5,
13464
13620
  realpathSync as realpathSync4,
13465
13621
  rmSync as rmSync4,
13466
- statSync as statSync10,
13622
+ statSync as statSync11,
13467
13623
  writeFileSync as writeFileSync2
13468
13624
  } from "node:fs";
13469
- import { tmpdir as tmpdir2 } from "node:os";
13470
- import { join as join14 } from "node:path";
13625
+ import { tmpdir as tmpdir3 } from "node:os";
13626
+ import { join as join15 } from "node:path";
13471
13627
  async function runDoctor(options) {
13472
13628
  if (options.issue) {
13473
13629
  return runIssueFlow(options.argv);
@@ -13621,7 +13777,7 @@ function clearOldBinaries() {
13621
13777
  errors: [],
13622
13778
  keptVersion: keepTag
13623
13779
  };
13624
- if (!existsSync15(info.path)) {
13780
+ if (!existsSync16(info.path)) {
13625
13781
  O2.info(`Binary cache: nothing to clear at ${info.path}`);
13626
13782
  return result;
13627
13783
  }
@@ -13631,10 +13787,10 @@ function clearOldBinaries() {
13631
13787
  return result;
13632
13788
  }
13633
13789
  for (const version of stale) {
13634
- const dir = join14(info.path, version);
13790
+ const dir = join15(info.path, version);
13635
13791
  let bytes = 0;
13636
13792
  try {
13637
- bytes = statSync10(dir).isDirectory() ? dirSize(dir) : 0;
13793
+ bytes = statSync11(dir).isDirectory() ? dirSize(dir) : 0;
13638
13794
  } catch {
13639
13795
  bytes = 0;
13640
13796
  }
@@ -13956,7 +14112,7 @@ function ensureStorageDirsForRegisteredPlugins(adapters) {
13956
14112
  if (!adapter.isInstalled() || !adapter.hasPluginEntry())
13957
14113
  continue;
13958
14114
  const storageDir = adapter.getStorageDir();
13959
- if (existsSync15(storageDir))
14115
+ if (existsSync16(storageDir))
13960
14116
  continue;
13961
14117
  mkdirSync3(storageDir, { recursive: true });
13962
14118
  summary.created += 1;
@@ -14059,11 +14215,11 @@ function deriveIssueTitleFromBody(body) {
14059
14215
  function writeIssueReviewFile(body) {
14060
14216
  let reviewDir = null;
14061
14217
  try {
14062
- reviewDir = mkdtempSync(join14(tmpdir2(), "aft-issue-"));
14218
+ reviewDir = mkdtempSync(join15(tmpdir3(), "aft-issue-"));
14063
14219
  if (process.platform !== "win32") {
14064
14220
  chmodSync2(reviewDir, 448);
14065
14221
  }
14066
- const outPath = join14(reviewDir, "issue.md");
14222
+ const outPath = join15(reviewDir, "issue.md");
14067
14223
  writeFileSync2(outPath, `${body}
14068
14224
  `, { encoding: "utf8", mode: 384, flag: "wx" });
14069
14225
  return { path: outPath, realPath: realpathSync4(outPath) };
@@ -14152,6 +14308,7 @@ ${scopedTail || "<no log output>"}
14152
14308
  const recentErrorsSection = recentErrorLines.length === 0 ? "_No error-shaped log lines found in recent history._" : ["```", recentErrorLines.join(`
14153
14309
  `), "```"].join(`
14154
14310
  `);
14311
+ const toolFailuresSection = buildRecentAftToolFailuresSectionFromLog();
14155
14312
  const rawBody = [
14156
14313
  "## Description",
14157
14314
  description,
@@ -14169,6 +14326,8 @@ ${scopedTail || "<no log output>"}
14169
14326
  "## Recent errors (last 20, sanitized)",
14170
14327
  recentErrorsSection,
14171
14328
  "",
14329
+ toolFailuresSection,
14330
+ "",
14172
14331
  "## Logs (last 200 lines per harness)",
14173
14332
  logSections,
14174
14333
  "_Usernames and home paths have been stripped from this report._"
@@ -14223,6 +14382,7 @@ var DOCTOR_CLEAR_TARGET_OPTIONS, DOCTOR_FORCE_CLEAR_TARGETS;
14223
14382
  var init_doctor = __esm(async () => {
14224
14383
  init_dist();
14225
14384
  init_binary_cache();
14385
+ init_bridge_tool_failures();
14226
14386
  init_fs_util();
14227
14387
  init_github();
14228
14388
  init_harness_select();
@@ -0,0 +1,26 @@
1
+ /** Newest window: tail of the bridge log by bytes (not full file). */
2
+ export declare const BRIDGE_LOG_TAIL_BYTES: number;
3
+ export declare const MAX_TOOL_FAILURE_CLASSES = 30;
4
+ export declare function resolveBridgePluginLogPath(): string;
5
+ /** Read up to `maxBytes` from the end of a log file (UTF-8). */
6
+ export declare function tailLogFileBytes(path: string, maxBytes: number): string;
7
+ export type ToolFailureKey = string;
8
+ /**
9
+ * Aggregate failure-shaped lines from bridge plugin log text into counts.
10
+ * Input should be a recent tail only; keys are tool/command + error class.
11
+ */
12
+ export declare function aggregateBridgeToolFailures(logText: string): Map<ToolFailureKey, number>;
13
+ /**
14
+ * Render the `### Recent AFT tool failures` markdown section from aggregated counts.
15
+ */
16
+ export declare function formatRecentAftToolFailuresSection(counts: Map<ToolFailureKey, number>, options?: {
17
+ maxClasses?: number;
18
+ }): string;
19
+ /**
20
+ * Build the tool-failures section from the bridge log path (newest tail window).
21
+ */
22
+ export declare function buildRecentAftToolFailuresSectionFromLog(logPath?: string, options?: {
23
+ tailBytes?: number;
24
+ maxClasses?: number;
25
+ }): string;
26
+ //# sourceMappingURL=bridge-tool-failures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge-tool-failures.d.ts","sourceRoot":"","sources":["../../src/lib/bridge-tool-failures.ts"],"names":[],"mappings":"AAKA,sEAAsE;AACtE,eAAO,MAAM,qBAAqB,QAAkB,CAAC;AAErD,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAO3C,wBAAgB,0BAA0B,IAAI,MAAM,CAGnD;AAED,gEAAgE;AAChE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAuBvE;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AAmEpC;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,CAcxF;AAQD;;GAEG;AACH,wBAAgB,kCAAkC,CAChD,MAAM,EAAE,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,EACnC,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAChC,MAAM,CAqBR;AAED;;GAEG;AACH,wBAAgB,wCAAwC,CACtD,OAAO,GAAE,MAAqC,EAC9C,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GACpD,MAAM,CAKR"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/aft",
3
- "version": "0.39.1",
3
+ "version": "0.39.2",
4
4
  "type": "module",
5
5
  "description": "Unified CLI for Agent File Tools (AFT) — setup, doctor, and diagnostics across supported agent harnesses (OpenCode, Pi)",
6
6
  "license": "MIT",
@@ -24,7 +24,7 @@
24
24
  },
25
25
  "dependencies": {
26
26
  "@clack/prompts": "^1.2.0",
27
- "@cortexkit/aft-bridge": "0.39.1",
27
+ "@cortexkit/aft-bridge": "0.39.2",
28
28
  "comment-json": "^4.6.2"
29
29
  },
30
30
  "devDependencies": {