@cortexkit/aft 0.39.0 → 0.39.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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":"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"}
package/dist/index.js CHANGED
@@ -104,8 +104,13 @@ var ACTIVE_LOGGER_SYMBOL;
104
104
  var init_active_logger = __esm(() => {
105
105
  ACTIVE_LOGGER_SYMBOL = Symbol.for("aft-bridge-active-logger");
106
106
  });
107
+ // ../aft-bridge/dist/bash-hints.js
108
+ var init_bash_hints = () => {};
107
109
  // ../aft-bridge/dist/command-timeouts.js
108
- 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;
109
114
  var init_command_timeouts = __esm(() => {
110
115
  LONG_RUNNING_COMMAND_TIMEOUT_MS = {
111
116
  callers: 60000,
@@ -117,6 +122,7 @@ var init_command_timeouts = __esm(() => {
117
122
  glob: 60000,
118
123
  semantic_search: 60000
119
124
  };
125
+ PASSIVE_COMMANDS = new Set(["status"]);
120
126
  });
121
127
 
122
128
  // ../aft-bridge/dist/status-bar.js
@@ -159,6 +165,10 @@ function bashTaskIdFrom(response) {
159
165
  function tagStderrLine(line) {
160
166
  return /^\[aft(-\w+)?\] /.test(line) ? line : `[aft] ${line}`;
161
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
+ }
162
172
  function compareSemver(a, b) {
163
173
  const [aMain, aPre] = a.split("-", 2);
164
174
  const [bMain, bPre] = b.split("-", 2);
@@ -224,7 +234,7 @@ function clampSemanticTimeout(configOverrides, bridgeTimeoutMs) {
224
234
  }
225
235
  };
226
236
  }
227
- 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;
228
238
  var init_bridge = __esm(() => {
229
239
  init_active_logger();
230
240
  init_command_timeouts();
@@ -262,6 +272,7 @@ var init_bridge = __esm(() => {
262
272
  _restartCount = 0;
263
273
  _shuttingDown = false;
264
274
  timeoutMs;
275
+ hangThreshold;
265
276
  maxRestarts;
266
277
  configured = false;
267
278
  _configurePromise = null;
@@ -286,6 +297,7 @@ var init_bridge = __esm(() => {
286
297
  this.binaryPath = binaryPath;
287
298
  this.cwd = cwd;
288
299
  this.timeoutMs = options?.timeoutMs ?? DEFAULT_BRIDGE_TIMEOUT_MS;
300
+ this.hangThreshold = options?.hangThreshold ?? BRIDGE_HANG_TIMEOUT_THRESHOLD;
289
301
  this.maxRestarts = options?.maxRestarts ?? 3;
290
302
  this.configOverrides = clampSemanticTimeout(configOverrides ?? {}, this.timeoutMs);
291
303
  this.minVersion = options?.minVersion;
@@ -403,7 +415,9 @@ var init_bridge = __esm(() => {
403
415
  if (requestSessionId && options?.configureWarningClient !== undefined) {
404
416
  this.configureWarningClients.set(requestSessionId, options.configureWarningClient);
405
417
  }
406
- 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;
407
421
  const implicitTransportOptions = {
408
422
  ...options?.transportTimeoutMs !== undefined || options?.timeoutMs !== undefined ? { transportTimeoutMs: effectiveTimeoutMs } : {},
409
423
  markConfiguredOnSuccess: false
@@ -453,7 +467,7 @@ var init_bridge = __esm(() => {
453
467
  }
454
468
  const line = `${JSON.stringify(request)}
455
469
  `;
456
- const keepBridgeOnTimeout = options?.keepBridgeOnTimeout === true;
470
+ const keepBridgeOnTimeout = passive || options?.keepBridgeOnTimeout === true;
457
471
  let requestSentAt = Date.now();
458
472
  const response = await new Promise((resolve, reject) => {
459
473
  const timer = setTimeout(() => {
@@ -475,7 +489,7 @@ var init_bridge = __esm(() => {
475
489
  const childActiveSinceRequest = this.lastChildActivityAt > requestSentAt;
476
490
  const consecutiveTimeouts = this.consecutiveRequestTimeouts + 1;
477
491
  this.consecutiveRequestTimeouts = consecutiveTimeouts;
478
- const keepWarm = childActiveSinceRequest || consecutiveTimeouts < BRIDGE_HANG_TIMEOUT_THRESHOLD;
492
+ const keepWarm = childActiveSinceRequest || consecutiveTimeouts < this.hangThreshold;
479
493
  const restartSuffix = keepWarm ? " — bridge kept warm" : " — restarting bridge";
480
494
  const timeoutMsg = `Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms${restartSuffix}`;
481
495
  if (requestSessionId) {
@@ -770,7 +784,7 @@ var init_bridge = __esm(() => {
770
784
  `)) !== -1) {
771
785
  const line = this.stderrBuffer.slice(0, newlineIdx).replace(/\r$/, "");
772
786
  this.stderrBuffer = this.stderrBuffer.slice(newlineIdx + 1);
773
- if (!line)
787
+ if (!line || !shouldSurfaceStderrLine(line))
774
788
  continue;
775
789
  const tagged = tagStderrLine(line);
776
790
  this.logVia(tagged);
@@ -780,7 +794,7 @@ var init_bridge = __esm(() => {
780
794
  flushStderrBuffer() {
781
795
  const line = this.stderrBuffer.replace(/\r$/, "");
782
796
  this.stderrBuffer = "";
783
- if (!line)
797
+ if (!line || !shouldSurfaceStderrLine(line))
784
798
  return;
785
799
  const tagged = tagStderrLine(line);
786
800
  this.logVia(tagged);
@@ -1302,6 +1316,7 @@ class BridgePool {
1302
1316
  this.projectConfigLoader = options.projectConfigLoader;
1303
1317
  this.bridgeOptions = {
1304
1318
  timeoutMs: options.timeoutMs,
1319
+ hangThreshold: options.hangThreshold,
1305
1320
  maxRestarts: options.maxRestarts,
1306
1321
  minVersion: options.minVersion,
1307
1322
  onVersionMismatch: options.onVersionMismatch,
@@ -1466,6 +1481,7 @@ var init_pool = __esm(() => {
1466
1481
  // ../aft-bridge/dist/index.js
1467
1482
  var init_dist = __esm(() => {
1468
1483
  init_active_logger();
1484
+ init_bash_hints();
1469
1485
  init_bridge();
1470
1486
  init_command_timeouts();
1471
1487
  init_downloader();
@@ -12372,11 +12388,232 @@ var init_binary_cache = __esm(() => {
12372
12388
  init_paths2();
12373
12389
  });
12374
12390
 
12375
- // src/lib/lsp-cache.ts
12376
- 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";
12377
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";
12378
12615
  function inspectDir(path) {
12379
- if (!existsSync10(path)) {
12616
+ if (!existsSync11(path)) {
12380
12617
  return { entries: [], totalSize: 0 };
12381
12618
  }
12382
12619
  const entries = [];
@@ -12388,9 +12625,9 @@ function inspectDir(path) {
12388
12625
  return { entries: [], totalSize: 0 };
12389
12626
  }
12390
12627
  for (const name of names) {
12391
- const full = join10(path, name);
12628
+ const full = join11(path, name);
12392
12629
  try {
12393
- if (!statSync6(full).isDirectory())
12630
+ if (!statSync7(full).isDirectory())
12394
12631
  continue;
12395
12632
  const size = dirSize(full);
12396
12633
  entries.push({
@@ -12446,8 +12683,8 @@ var init_lsp_cache = __esm(() => {
12446
12683
  });
12447
12684
 
12448
12685
  // src/lib/onnx.ts
12449
- import { existsSync as existsSync11, readdirSync as readdirSync6, readlinkSync, realpathSync as realpathSync2, statSync as statSync7 } from "node:fs";
12450
- 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";
12451
12688
  function getOnnxLibraryName() {
12452
12689
  if (process.platform === "darwin")
12453
12690
  return "libonnxruntime.dylib";
@@ -12510,13 +12747,13 @@ function findSystemOnnxRuntime() {
12510
12747
  searchPaths.push(...pathEntriesForPlatform());
12511
12748
  const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
12512
12749
  const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
12513
- 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"), ...(() => {
12514
12751
  const nugetPaths = [];
12515
12752
  const userProfile = process.env.USERPROFILE ?? "";
12516
12753
  if (!userProfile)
12517
12754
  return nugetPaths;
12518
- const nugetPackageDir = join11(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
12519
- if (!existsSync11(nugetPackageDir))
12755
+ const nugetPackageDir = join12(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
12756
+ if (!existsSync12(nugetPackageDir))
12520
12757
  return nugetPaths;
12521
12758
  try {
12522
12759
  for (const entry of readdirSync6(nugetPackageDir, { withFileTypes: true })) {
@@ -12524,7 +12761,7 @@ function findSystemOnnxRuntime() {
12524
12761
  continue;
12525
12762
  if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
12526
12763
  continue;
12527
- 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"));
12528
12765
  }
12529
12766
  } catch {}
12530
12767
  return nugetPaths;
@@ -12554,12 +12791,12 @@ function findSystemOnnxRuntime() {
12554
12791
  return unknownVersionPaths[0] ?? null;
12555
12792
  }
12556
12793
  function findCachedOnnxRuntime(storageDir) {
12557
- const ortDir = join11(storageDir, "onnxruntime", ONNX_RUNTIME_VERSION);
12794
+ const ortDir = join12(storageDir, "onnxruntime", ONNX_RUNTIME_VERSION);
12558
12795
  const libName = getOnnxLibraryName();
12559
- if (existsSync11(join11(ortDir, libName)))
12796
+ if (existsSync12(join12(ortDir, libName)))
12560
12797
  return ortDir;
12561
- const libSubdir = join11(ortDir, "lib");
12562
- if (existsSync11(join11(libSubdir, libName)))
12798
+ const libSubdir = join12(ortDir, "lib");
12799
+ if (existsSync12(join12(libSubdir, libName)))
12563
12800
  return libSubdir;
12564
12801
  return null;
12565
12802
  }
@@ -12580,7 +12817,7 @@ function parseOrtVersionFromDirectoryPath(value) {
12580
12817
  return null;
12581
12818
  }
12582
12819
  function detectOrtVersion(libDir) {
12583
- if (!existsSync11(libDir))
12820
+ if (!existsSync12(libDir))
12584
12821
  return null;
12585
12822
  const libName = getOnnxLibraryName();
12586
12823
  try {
@@ -12595,10 +12832,10 @@ function detectOrtVersion(libDir) {
12595
12832
  if (version)
12596
12833
  return version;
12597
12834
  }
12598
- const base = join11(libDir, libName);
12599
- if (existsSync11(base)) {
12835
+ const base = join12(libDir, libName);
12836
+ if (existsSync12(base)) {
12600
12837
  try {
12601
- const real = realpathSync2(base);
12838
+ const real = realpathSync3(base);
12602
12839
  const version = parseOrtVersionFromPath(real) ?? parseOrtVersionFromDirectoryPath(real);
12603
12840
  if (version)
12604
12841
  return version;
@@ -12626,93 +12863,15 @@ function isOrtVersionCompatible(version) {
12626
12863
  var ONNX_RUNTIME_VERSION = "1.24.4", INVALID_ORT_VERSION = "<invalid>", REQUIRED_ORT_MAJOR = 1, REQUIRED_ORT_MIN_MINOR = 20;
12627
12864
  var init_onnx = () => {};
12628
12865
 
12629
- // src/lib/sanitize.ts
12630
- import { realpathSync as realpathSync3 } from "node:fs";
12631
- import { homedir as homedir8, userInfo } from "node:os";
12632
- function escapeRegex(value) {
12633
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
12634
- }
12635
- function safeRealpath(p2) {
12636
- try {
12637
- return realpathSync3(p2);
12638
- } catch {
12639
- return null;
12640
- }
12641
- }
12642
- function isSensitiveKeyName(keyName) {
12643
- return SENSITIVE_KEY_WORD.test(keyName) || SEGMENTED_KEY_WORD.test(keyName) || CAMEL_CASE_KEY_WORD.test(keyName);
12644
- }
12645
- function redactSecrets(content) {
12646
- let sanitized = content;
12647
- 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}`);
12648
- sanitized = sanitized.replace(/\bgithub_pat_[A-Za-z0-9_]+\b/g, SECRET_PLACEHOLDER);
12649
- sanitized = sanitized.replace(/\bgh(?:p|o|s)_[A-Za-z0-9_]{16,}\b/g, SECRET_PLACEHOLDER);
12650
- sanitized = sanitized.replace(/\bsk-(?:live-)?[A-Za-z0-9][A-Za-z0-9_-]{7,}\b/g, SECRET_PLACEHOLDER);
12651
- sanitized = sanitized.replace(JWT_PATTERN, SECRET_PLACEHOLDER);
12652
- sanitized = sanitized.replace(AWS_ACCESS_KEY_ID_PATTERN, SECRET_PLACEHOLDER);
12653
- sanitized = sanitized.replace(quotedSensitiveKeyValuePattern, (match, prefix, _keyQuote, keyName, valueQuote) => isSensitiveKeyName(keyName) ? `${prefix}${valueQuote}${SECRET_PLACEHOLDER}${valueQuote}` : match);
12654
- sanitized = sanitized.replace(unquotedSensitiveKeyValuePattern, (match, prefix, keyName, valueQuote) => isSensitiveKeyName(keyName) ? `${prefix}${valueQuote}${SECRET_PLACEHOLDER}${valueQuote}` : match);
12655
- sanitized = sanitized.replace(bareSensitiveKeyValuePattern, (match, prefix, keyName) => isSensitiveKeyName(keyName) ? `${prefix}${SECRET_PLACEHOLDER}` : match);
12656
- sanitized = sanitized.replace(/\b([a-z][a-z0-9+.-]*:\/\/)[^@\s/?#]+@/gi, `$1${URL_CREDENTIAL_PLACEHOLDER}@`);
12657
- sanitized = sanitized.replace(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi, "<EMAIL>");
12658
- return sanitized;
12659
- }
12660
- function sanitizeContent(content) {
12661
- const username = userInfo().username;
12662
- const home = homedir8();
12663
- let sanitized = redactSecrets(content);
12664
- const cwd = process.cwd();
12665
- for (const candidate of new Set([cwd, safeRealpath(cwd)])) {
12666
- if (candidate && candidate !== "/" && candidate !== home) {
12667
- sanitized = sanitized.replace(new RegExp(escapeRegex(candidate), "g"), "<PROJECT>");
12668
- }
12669
- }
12670
- if (home) {
12671
- sanitized = sanitized.replace(new RegExp(escapeRegex(home), "g"), "~");
12672
- }
12673
- sanitized = sanitized.replace(/\/Users\/[^/\s"']+/g, "/Users/<USER>");
12674
- sanitized = sanitized.replace(/\/home\/[^/\s"']+/g, "/home/<USER>");
12675
- sanitized = sanitized.replace(/([A-Za-z]:\\\\Users\\\\)[^\\\\"'\s]+/g, "$1<USER>");
12676
- sanitized = sanitized.replace(/([A-Za-z]:\\Users\\)[^\\"'\s]+/g, "$1<USER>");
12677
- sanitized = sanitized.replace(/([A-Za-z]:\/Users\/)[^/\s"']+/g, "$1<USER>");
12678
- if (username) {
12679
- sanitized = sanitized.replace(new RegExp(escapeRegex(username), "g"), "<USER>");
12680
- }
12681
- return sanitized;
12682
- }
12683
- function sanitizeValue(value) {
12684
- if (typeof value === "string") {
12685
- return sanitizeContent(value);
12686
- }
12687
- if (Array.isArray(value)) {
12688
- return value.map((entry) => sanitizeValue(entry));
12689
- }
12690
- if (value && typeof value === "object") {
12691
- return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, sanitizeValue(entry)]));
12692
- }
12693
- return value;
12694
- }
12695
- 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;
12696
- var init_sanitize = __esm(() => {
12697
- SENSITIVE_KEY_WORD = /(?:token|password|secret|api[_-]?key|passwd|pwd|credential)/i;
12698
- SEGMENTED_KEY_WORD = /(?:^|[_.-])key(?:$|[_.-])/i;
12699
- CAMEL_CASE_KEY_WORD = /[a-z0-9]Key(?:$|[A-Z_.-])/;
12700
- JWT_PATTERN = /\beyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g;
12701
- AWS_ACCESS_KEY_ID_PATTERN = /\b(?:AKIA|ASIA|AGPA|AIDA|AROA)[A-Z0-9]{16}\b/g;
12702
- quotedSensitiveKeyValuePattern = new RegExp(String.raw`((['"])(${KEY_NAME})\2[^\S\r\n]*:[^\S\r\n]*)(['"])([^'"\r\n]+)\4`, "gi");
12703
- unquotedSensitiveKeyValuePattern = new RegExp(String.raw`\b((${KEY_NAME})[^\S\r\n]*[=:][^\S\r\n]*)(['"])([^'"\r\n]+)\3`, "gi");
12704
- bareSensitiveKeyValuePattern = new RegExp(String.raw`\b((${KEY_NAME})[^\S\r\n]*[=:][^\S\r\n]*)([^\s,;&'"]+)`, "gi");
12705
- });
12706
-
12707
12866
  // src/lib/diagnostics.ts
12708
12867
  import {
12709
12868
  accessSync,
12710
- closeSync as closeSync2,
12869
+ closeSync as closeSync3,
12711
12870
  constants,
12712
- existsSync as existsSync12,
12713
- openSync as openSync2,
12714
- readSync as readSync2,
12715
- statSync as statSync8
12871
+ existsSync as existsSync13,
12872
+ openSync as openSync3,
12873
+ readSync as readSync3,
12874
+ statSync as statSync9
12716
12875
  } from "node:fs";
12717
12876
  async function collectDiagnostics(adapters) {
12718
12877
  const cliVersion = getSelfVersion();
@@ -12741,7 +12900,7 @@ async function diagnoseHarness(adapter) {
12741
12900
  const logPath = adapter.getLogFile();
12742
12901
  const pluginCache = adapter.getPluginCacheInfo();
12743
12902
  const storageAccessible = (() => {
12744
- if (!existsSync12(storage))
12903
+ if (!existsSync13(storage))
12745
12904
  return false;
12746
12905
  try {
12747
12906
  accessSync(storage, constants.R_OK | constants.W_OK);
@@ -12764,14 +12923,14 @@ async function diagnoseHarness(adapter) {
12764
12923
  pluginRegistered: adapter.hasPluginEntry(),
12765
12924
  configPaths,
12766
12925
  aftConfig: {
12767
- exists: existsSync12(configPaths.aftConfig),
12926
+ exists: existsSync13(configPaths.aftConfig),
12768
12927
  ...aftConfigRead.error ? { parseError: aftConfigRead.error } : {},
12769
12928
  flags: aftFlags
12770
12929
  },
12771
12930
  pluginCache,
12772
12931
  storageDir: {
12773
12932
  path: storage,
12774
- exists: existsSync12(storage),
12933
+ exists: existsSync13(storage),
12775
12934
  accessible: storageAccessible,
12776
12935
  sizesByKey: describeStorage
12777
12936
  },
@@ -12789,8 +12948,8 @@ async function diagnoseHarness(adapter) {
12789
12948
  },
12790
12949
  logFile: {
12791
12950
  path: logPath,
12792
- exists: existsSync12(logPath),
12793
- 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
12794
12953
  }
12795
12954
  };
12796
12955
  }
@@ -12984,15 +13143,15 @@ function formatDiagnosticIssuesSection(report) {
12984
13143
  return lines;
12985
13144
  }
12986
13145
  function tailLogFile(path, lines) {
12987
- if (!existsSync12(path))
13146
+ if (!existsSync13(path))
12988
13147
  return "";
12989
13148
  if (lines <= 0)
12990
13149
  return "";
12991
13150
  const chunkSize = 64 * 1024;
12992
13151
  let fd = null;
12993
13152
  try {
12994
- const size = statSync8(path).size;
12995
- fd = openSync2(path, "r");
13153
+ const size = statSync9(path).size;
13154
+ fd = openSync3(path, "r");
12996
13155
  const chunks = [];
12997
13156
  let position = size;
12998
13157
  let newlineCount = 0;
@@ -13000,7 +13159,7 @@ function tailLogFile(path, lines) {
13000
13159
  const readLength = Math.min(chunkSize, position);
13001
13160
  position -= readLength;
13002
13161
  const buffer = Buffer.allocUnsafe(readLength);
13003
- const bytesRead = readSync2(fd, buffer, 0, readLength, position);
13162
+ const bytesRead = readSync3(fd, buffer, 0, readLength, position);
13004
13163
  const chunk = bytesRead === readLength ? buffer : buffer.subarray(0, bytesRead);
13005
13164
  chunks.unshift(chunk);
13006
13165
  for (let i = chunk.length - 1;i >= 0; i -= 1) {
@@ -13015,7 +13174,7 @@ function tailLogFile(path, lines) {
13015
13174
  } finally {
13016
13175
  if (fd !== null) {
13017
13176
  try {
13018
- closeSync2(fd);
13177
+ closeSync3(fd);
13019
13178
  } catch {}
13020
13179
  }
13021
13180
  }
@@ -13074,7 +13233,7 @@ var init_github = () => {};
13074
13233
  function filterLogToSession(logText, sessionId) {
13075
13234
  const bareId = sessionId.replace(/^ses_/, "");
13076
13235
  const keepTokens = [`[ses_${bareId}]`, `[${bareId}]`];
13077
- 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(`
13078
13237
  `);
13079
13238
  }
13080
13239
  function isErrorLogLine(line) {
@@ -13154,9 +13313,9 @@ function truncateToByteBudget(input, maxBytes) {
13154
13313
  }
13155
13314
  return buf.subarray(0, end).toString("utf8");
13156
13315
  }
13157
- 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;
13158
13317
  var init_issue_body = __esm(() => {
13159
- 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}\]/;
13160
13319
  ERROR_LOG_PATTERNS = [
13161
13320
  /\bcrashed:/i,
13162
13321
  /\bfailed:/i,
@@ -13170,8 +13329,8 @@ var init_issue_body = __esm(() => {
13170
13329
  });
13171
13330
 
13172
13331
  // src/lib/onnx-fix.ts
13173
- import { existsSync as existsSync13, rmSync as rmSync3 } from "node:fs";
13174
- 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";
13175
13334
  function findOnnxFixCandidates(report) {
13176
13335
  const candidates = [];
13177
13336
  for (const harness of report.harnesses) {
@@ -13179,7 +13338,7 @@ function findOnnxFixCandidates(report) {
13179
13338
  continue;
13180
13339
  if (!harness.storageDir.exists)
13181
13340
  continue;
13182
- const storageOnnxDir = join12(harness.storageDir.path, "onnxruntime");
13341
+ const storageOnnxDir = join13(harness.storageDir.path, "onnxruntime");
13183
13342
  const systemTooOld = harness.onnxRuntime.systemPath !== null && harness.onnxRuntime.systemCompatible === false;
13184
13343
  const cachedTooOld = harness.onnxRuntime.cachedPath !== null && harness.onnxRuntime.cachedCompatible === false;
13185
13344
  const hasCompatibleCached = harness.onnxRuntime.cachedCompatible === true;
@@ -13188,7 +13347,7 @@ function findOnnxFixCandidates(report) {
13188
13347
  harness,
13189
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.`,
13190
13349
  storageOnnxDir,
13191
- storageOnnxBytes: existsSync13(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
13350
+ storageOnnxBytes: existsSync14(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
13192
13351
  });
13193
13352
  continue;
13194
13353
  }
@@ -13197,7 +13356,7 @@ function findOnnxFixCandidates(report) {
13197
13356
  harness,
13198
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.`,
13199
13358
  storageOnnxDir,
13200
- storageOnnxBytes: existsSync13(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
13359
+ storageOnnxBytes: existsSync14(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
13201
13360
  });
13202
13361
  }
13203
13362
  }
@@ -13227,7 +13386,7 @@ async function runOnnxFix(adapters, report, options = {}) {
13227
13386
  const result = { cleared: 0, bytesReclaimed: 0, errors: [] };
13228
13387
  const rmFn = options.rmFn ?? rmSync3;
13229
13388
  for (const c2 of candidates) {
13230
- if (!existsSync13(c2.storageOnnxDir)) {
13389
+ if (!existsSync14(c2.storageOnnxDir)) {
13231
13390
  O2.success(`${c2.harness.displayName}: no cached state to clear; restart your harness to trigger a fresh ONNX download`);
13232
13391
  continue;
13233
13392
  }
@@ -13253,10 +13412,10 @@ var init_onnx_fix = __esm(() => {
13253
13412
  });
13254
13413
 
13255
13414
  // src/lib/sessions.ts
13256
- 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";
13257
13416
  import { createRequire as createRequire3 } from "node:module";
13258
13417
  import { homedir as homedir9 } from "node:os";
13259
- import { basename as basename2, join as join13 } from "node:path";
13418
+ import { basename as basename2, join as join14 } from "node:path";
13260
13419
  function listRecentSessions(adapter) {
13261
13420
  try {
13262
13421
  if (adapter.kind === "opencode")
@@ -13285,8 +13444,8 @@ function mapOpenCodeSessionRows(rows) {
13285
13444
  }).filter((session) => session !== null).sort((a, b) => b.lastActivity - a.lastActivity).slice(0, MAX_RECENT_SESSIONS);
13286
13445
  }
13287
13446
  function listRecentOpenCodeSessions() {
13288
- const dbPath = join13(getXdgDataHome(), "opencode", "opencode.db");
13289
- if (!existsSync14(dbPath))
13447
+ const dbPath = join14(getXdgDataHome(), "opencode", "opencode.db");
13448
+ if (!existsSync15(dbPath))
13290
13449
  return [];
13291
13450
  let db = null;
13292
13451
  try {
@@ -13305,10 +13464,10 @@ function listRecentOpenCodeSessions() {
13305
13464
  }
13306
13465
  function getXdgDataHome() {
13307
13466
  const xdgDataHome = process.env.XDG_DATA_HOME;
13308
- return xdgDataHome && xdgDataHome.length > 0 ? xdgDataHome : join13(homedir9(), ".local", "share");
13467
+ return xdgDataHome && xdgDataHome.length > 0 ? xdgDataHome : join14(homedir9(), ".local", "share");
13309
13468
  }
13310
13469
  function listRecentPiSessions() {
13311
- return listPiSessionsFromDir(join13(getHomeDir(), ".pi", "agent", "sessions"));
13470
+ return listPiSessionsFromDir(join14(getHomeDir(), ".pi", "agent", "sessions"));
13312
13471
  }
13313
13472
  function getHomeDir() {
13314
13473
  const envHome = process.platform === "win32" ? process.env.USERPROFILE : process.env.HOME;
@@ -13316,11 +13475,11 @@ function getHomeDir() {
13316
13475
  }
13317
13476
  function listPiSessionsFromDir(sessionsDir) {
13318
13477
  try {
13319
- if (!existsSync14(sessionsDir))
13478
+ if (!existsSync15(sessionsDir))
13320
13479
  return [];
13321
13480
  const files = collectJsonlFiles(sessionsDir).map((filePath) => {
13322
13481
  try {
13323
- const stats = statSync9(filePath);
13482
+ const stats = statSync10(filePath);
13324
13483
  return { filePath, mtimeMs: stats.mtimeMs };
13325
13484
  } catch {
13326
13485
  return null;
@@ -13354,7 +13513,7 @@ function collectJsonlFiles(root) {
13354
13513
  continue;
13355
13514
  }
13356
13515
  for (const entry of entries) {
13357
- const path = join13(dir, entry.name);
13516
+ const path = join14(dir, entry.name);
13358
13517
  if (entry.isDirectory()) {
13359
13518
  stack.push(path);
13360
13519
  } else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
@@ -13454,17 +13613,17 @@ __export(exports_doctor, {
13454
13613
  import { execFileSync } from "node:child_process";
13455
13614
  import {
13456
13615
  chmodSync as chmodSync2,
13457
- existsSync as existsSync15,
13616
+ existsSync as existsSync16,
13458
13617
  mkdirSync as mkdirSync3,
13459
13618
  mkdtempSync,
13460
13619
  readFileSync as readFileSync5,
13461
13620
  realpathSync as realpathSync4,
13462
13621
  rmSync as rmSync4,
13463
- statSync as statSync10,
13622
+ statSync as statSync11,
13464
13623
  writeFileSync as writeFileSync2
13465
13624
  } from "node:fs";
13466
- import { tmpdir as tmpdir2 } from "node:os";
13467
- import { join as join14 } from "node:path";
13625
+ import { tmpdir as tmpdir3 } from "node:os";
13626
+ import { join as join15 } from "node:path";
13468
13627
  async function runDoctor(options) {
13469
13628
  if (options.issue) {
13470
13629
  return runIssueFlow(options.argv);
@@ -13618,7 +13777,7 @@ function clearOldBinaries() {
13618
13777
  errors: [],
13619
13778
  keptVersion: keepTag
13620
13779
  };
13621
- if (!existsSync15(info.path)) {
13780
+ if (!existsSync16(info.path)) {
13622
13781
  O2.info(`Binary cache: nothing to clear at ${info.path}`);
13623
13782
  return result;
13624
13783
  }
@@ -13628,10 +13787,10 @@ function clearOldBinaries() {
13628
13787
  return result;
13629
13788
  }
13630
13789
  for (const version of stale) {
13631
- const dir = join14(info.path, version);
13790
+ const dir = join15(info.path, version);
13632
13791
  let bytes = 0;
13633
13792
  try {
13634
- bytes = statSync10(dir).isDirectory() ? dirSize(dir) : 0;
13793
+ bytes = statSync11(dir).isDirectory() ? dirSize(dir) : 0;
13635
13794
  } catch {
13636
13795
  bytes = 0;
13637
13796
  }
@@ -13953,7 +14112,7 @@ function ensureStorageDirsForRegisteredPlugins(adapters) {
13953
14112
  if (!adapter.isInstalled() || !adapter.hasPluginEntry())
13954
14113
  continue;
13955
14114
  const storageDir = adapter.getStorageDir();
13956
- if (existsSync15(storageDir))
14115
+ if (existsSync16(storageDir))
13957
14116
  continue;
13958
14117
  mkdirSync3(storageDir, { recursive: true });
13959
14118
  summary.created += 1;
@@ -14056,11 +14215,11 @@ function deriveIssueTitleFromBody(body) {
14056
14215
  function writeIssueReviewFile(body) {
14057
14216
  let reviewDir = null;
14058
14217
  try {
14059
- reviewDir = mkdtempSync(join14(tmpdir2(), "aft-issue-"));
14218
+ reviewDir = mkdtempSync(join15(tmpdir3(), "aft-issue-"));
14060
14219
  if (process.platform !== "win32") {
14061
14220
  chmodSync2(reviewDir, 448);
14062
14221
  }
14063
- const outPath = join14(reviewDir, "issue.md");
14222
+ const outPath = join15(reviewDir, "issue.md");
14064
14223
  writeFileSync2(outPath, `${body}
14065
14224
  `, { encoding: "utf8", mode: 384, flag: "wx" });
14066
14225
  return { path: outPath, realPath: realpathSync4(outPath) };
@@ -14149,6 +14308,7 @@ ${scopedTail || "<no log output>"}
14149
14308
  const recentErrorsSection = recentErrorLines.length === 0 ? "_No error-shaped log lines found in recent history._" : ["```", recentErrorLines.join(`
14150
14309
  `), "```"].join(`
14151
14310
  `);
14311
+ const toolFailuresSection = buildRecentAftToolFailuresSectionFromLog();
14152
14312
  const rawBody = [
14153
14313
  "## Description",
14154
14314
  description,
@@ -14166,6 +14326,8 @@ ${scopedTail || "<no log output>"}
14166
14326
  "## Recent errors (last 20, sanitized)",
14167
14327
  recentErrorsSection,
14168
14328
  "",
14329
+ toolFailuresSection,
14330
+ "",
14169
14331
  "## Logs (last 200 lines per harness)",
14170
14332
  logSections,
14171
14333
  "_Usernames and home paths have been stripped from this report._"
@@ -14220,6 +14382,7 @@ var DOCTOR_CLEAR_TARGET_OPTIONS, DOCTOR_FORCE_CLEAR_TARGETS;
14220
14382
  var init_doctor = __esm(async () => {
14221
14383
  init_dist();
14222
14384
  init_binary_cache();
14385
+ init_bridge_tool_failures();
14223
14386
  init_fs_util();
14224
14387
  init_github();
14225
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.0",
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.0",
27
+ "@cortexkit/aft-bridge": "0.39.2",
28
28
  "comment-json": "^4.6.2"
29
29
  },
30
30
  "devDependencies": {