@cortexkit/aft 0.50.3 → 0.51.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +201 -105
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -515,6 +515,122 @@ var CONFLICT_HINT = `
515
515
  [Hint] Use aft_conflicts to see all conflict regions across files in a single call.`, GREP_SEARCH_AFT_SEARCH_HINT = "DO NOT search code by running grep/rg in bash — it is unindexed, unranked, and serial. Use the `aft_search` tool instead (it auto-routes concepts, identifiers, regex, and literals).", GREP_SEARCH_GREP_HINT = "DO NOT search code by running grep/rg in bash — it is unindexed, unranked, and serial. Use the `grep` tool instead (indexed and ranked).", GREP_SEARCH_HINT_PREFIX = "DO NOT search code by running grep/rg in bash —", GREP_SEARCH_FRESHNESS_WINDOW_MS = 60000;
516
516
  var init_bash_hints = () => {};
517
517
 
518
+ // ../aft-bridge/dist/bash-host-fallback.js
519
+ import { spawn } from "node:child_process";
520
+ function bashHostFallbackAskPattern(command, cwd) {
521
+ return `AFT UNAVAILABLE - host fallback execution:
522
+
523
+ Exact command:
524
+ ${command}
525
+
526
+ Working directory:
527
+ ${cwd}`;
528
+ }
529
+ function appendTail(chunks, chunk) {
530
+ const combined = Buffer.concat([...chunks, chunk]);
531
+ if (combined.byteLength <= BASH_HOST_FALLBACK_MAX_OUTPUT_BYTES) {
532
+ return { chunks: [combined], truncated: false };
533
+ }
534
+ return {
535
+ chunks: [combined.subarray(combined.byteLength - BASH_HOST_FALLBACK_MAX_OUTPUT_BYTES)],
536
+ truncated: true
537
+ };
538
+ }
539
+ function renderOutput(output, exitCode) {
540
+ const body = output.toString("utf8");
541
+ const separator = body.length === 0 || body.endsWith(`
542
+ `) ? "" : `
543
+ `;
544
+ return `${BASH_HOST_FALLBACK_BANNER}
545
+ ${body}${separator}[exit code: ${exitCode}]`;
546
+ }
547
+ async function runBashHostFallback(options) {
548
+ const timeoutMs = Math.min(Math.max(1, options.timeoutMs ?? BASH_HOST_FALLBACK_MAX_TIMEOUT_MS), BASH_HOST_FALLBACK_MAX_TIMEOUT_MS);
549
+ if (options.signal?.aborted) {
550
+ throw new DOMException("The host fallback command was aborted", "AbortError");
551
+ }
552
+ return await new Promise((resolve2, reject) => {
553
+ const child = spawn(options.command, {
554
+ cwd: options.projectRoot,
555
+ shell: true,
556
+ env: { ...process.env, ...options.env },
557
+ stdio: ["ignore", "pipe", "pipe"],
558
+ detached: process.platform !== "win32",
559
+ windowsHide: true
560
+ });
561
+ let chunks = [];
562
+ let truncated = false;
563
+ let timedOut = false;
564
+ let aborted = false;
565
+ let settled = false;
566
+ let abortForceTimer;
567
+ const capture = (chunk) => {
568
+ const next = appendTail(chunks, Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
569
+ chunks = next.chunks;
570
+ truncated ||= next.truncated;
571
+ };
572
+ child.stdout?.on("data", capture);
573
+ child.stderr?.on("data", capture);
574
+ const kill = (signal) => {
575
+ if (child.exitCode !== null || child.signalCode !== null)
576
+ return;
577
+ if (process.platform !== "win32" && child.pid !== undefined) {
578
+ try {
579
+ process.kill(-child.pid, signal);
580
+ return;
581
+ } catch {}
582
+ }
583
+ child.kill(signal);
584
+ };
585
+ const onAbort = () => {
586
+ aborted = true;
587
+ kill("SIGTERM");
588
+ abortForceTimer = setTimeout(() => kill("SIGKILL"), 250);
589
+ abortForceTimer.unref?.();
590
+ };
591
+ options.signal?.addEventListener("abort", onAbort, { once: true });
592
+ const timer = setTimeout(() => {
593
+ timedOut = true;
594
+ kill("SIGKILL");
595
+ }, timeoutMs);
596
+ const cleanup = () => {
597
+ clearTimeout(timer);
598
+ if (abortForceTimer !== undefined)
599
+ clearTimeout(abortForceTimer);
600
+ options.signal?.removeEventListener("abort", onAbort);
601
+ };
602
+ child.once("error", (error2) => {
603
+ if (settled)
604
+ return;
605
+ settled = true;
606
+ cleanup();
607
+ reject(error2);
608
+ });
609
+ child.once("close", (code) => {
610
+ if (settled)
611
+ return;
612
+ settled = true;
613
+ cleanup();
614
+ if (aborted) {
615
+ reject(new DOMException("The host fallback command was aborted", "AbortError"));
616
+ return;
617
+ }
618
+ const exitCode = timedOut ? 124 : code ?? 1;
619
+ resolve2({
620
+ success: true,
621
+ output: renderOutput(Buffer.concat(chunks), exitCode),
622
+ exit_code: exitCode,
623
+ truncated
624
+ });
625
+ });
626
+ });
627
+ }
628
+ var BASH_HOST_FALLBACK_BANNER = "[AFT host fallback - module transport down; no rewrites/compression/background]", BASH_HOST_FALLBACK_MAX_OUTPUT_BYTES, BASH_HOST_FALLBACK_MAX_TIMEOUT_MS, BASH_HOST_FALLBACK_REFUSAL = "AFT transport is down; only foreground execution is available in host fallback";
629
+ var init_bash_host_fallback = __esm(() => {
630
+ BASH_HOST_FALLBACK_MAX_OUTPUT_BYTES = 100 * 1024;
631
+ BASH_HOST_FALLBACK_MAX_TIMEOUT_MS = 10 * 60 * 1000;
632
+ });
633
+
518
634
  // ../aft-bridge/dist/bash-timeout.js
519
635
  function resolveBashKillTimeout(modelTimeout, foregroundWaitMs) {
520
636
  if (modelTimeout !== undefined && modelTimeout >= foregroundWaitMs) {
@@ -548,58 +664,8 @@ var init_command_timeouts = __esm(() => {
548
664
  PASSIVE_COMMANDS = new Set(["status"]);
549
665
  });
550
666
 
551
- // ../aft-bridge/dist/status-bar.js
552
- function createStatusBarEmitState() {
553
- return { callsSinceEmit: 0 };
554
- }
555
- function parseStatusBarCounts(value) {
556
- if (!value || typeof value !== "object")
557
- return;
558
- const record = value;
559
- const num = (key) => {
560
- const raw = record[key];
561
- return typeof raw === "number" && Number.isFinite(raw) ? raw : 0;
562
- };
563
- return {
564
- errors: num("errors"),
565
- warnings: num("warnings"),
566
- dead_code: num("dead_code"),
567
- unused_exports: num("unused_exports"),
568
- duplicates: num("duplicates"),
569
- todos: num("todos"),
570
- tier2_stale: record.tier2_stale === true,
571
- ...typeof record.line === "string" ? { line: record.line } : {}
572
- };
573
- }
574
- function countsEqual(a, b) {
575
- return a.errors === b.errors && a.warnings === b.warnings && a.dead_code === b.dead_code && a.unused_exports === b.unused_exports && a.duplicates === b.duplicates && a.todos === b.todos && a.tier2_stale === b.tier2_stale && a.line === b.line;
576
- }
577
- function shouldEmitStatusBar(state, next) {
578
- const changed = state.last === undefined || !countsEqual(state.last, next);
579
- state.callsSinceEmit += 1;
580
- const heartbeat = state.callsSinceEmit >= STATUS_BAR_HEARTBEAT_CALLS;
581
- if (changed || heartbeat) {
582
- state.last = next;
583
- state.callsSinceEmit = 0;
584
- return true;
585
- }
586
- return false;
587
- }
588
- function formatStatusBar(counts) {
589
- if (counts.line !== undefined)
590
- return counts.line;
591
- const staleMark = counts.tier2_stale ? "~" : "";
592
- return `[AFT E${counts.errors} W${counts.warnings} | ` + `${staleMark}D${counts.dead_code} U${counts.unused_exports} C${counts.duplicates} | ` + `T${counts.todos}]`;
593
- }
594
- function statusBarLine(counts) {
595
- return `
596
-
597
- ${formatStatusBar(counts)}`;
598
- }
599
- var STATUS_BAR_HEARTBEAT_CALLS = 15;
600
-
601
667
  // ../aft-bridge/dist/bridge.js
602
- import { spawn } from "node:child_process";
668
+ import { spawn as spawn2 } from "node:child_process";
603
669
  import { createHash } from "node:crypto";
604
670
  import { readFileSync } from "node:fs";
605
671
  import { homedir as homedir2 } from "node:os";
@@ -698,7 +764,7 @@ function coerceConfigureDroppedKeys(value) {
698
764
  function isBridgeTransportTimeout(err) {
699
765
  return err instanceof Error && err.code === "transport_timeout";
700
766
  }
701
- var DEFAULT_BRIDGE_TIMEOUT_MS = 30000, BRIDGE_HANG_TIMEOUT_THRESHOLD = 2, MAX_STDOUT_BUFFER, STDOUT_BUFFER_COMPACT_THRESHOLD, HASHLINE_REGISTRATION_LOG_INTERVAL_MS = 60000, HASHLINE_REGISTRATION_LOG_STATE_LIMIT = 256, TERMINAL_BASH_STATUSES, binaryFingerprintReader, BENIGN_CPUINFO_PROC_CPUINFO_PARSE_FAILURE = "failed to parse processor information from /proc/cpuinfo", BridgeReplacedDuringVersionCheck, BridgeTransportTimeoutError, BinaryBridge;
767
+ var DEFAULT_BRIDGE_TIMEOUT_MS = 30000, BRIDGE_HANG_TIMEOUT_THRESHOLD = 2, MAX_STDOUT_BUFFER, STDOUT_BUFFER_COMPACT_THRESHOLD, HASHLINE_REGISTRATION_LOG_INTERVAL_MS = 60000, HASHLINE_REGISTRATION_LOG_STATE_LIMIT = 256, TERMINAL_BASH_STATUSES, binaryFingerprintReader, BENIGN_CPUINFO_PROC_CPUINFO_PARSE_FAILURE = "failed to parse processor information from /proc/cpuinfo", BridgeReplacedDuringVersionCheck, BridgeTransportTimeoutError, BridgeTransportUnavailableError, BinaryBridge;
702
768
  var init_bridge = __esm(() => {
703
769
  init_active_logger();
704
770
  init_command_timeouts();
@@ -732,6 +798,13 @@ var init_bridge = __esm(() => {
732
798
  this.name = "BridgeTransportTimeoutError";
733
799
  }
734
800
  };
801
+ BridgeTransportUnavailableError = class BridgeTransportUnavailableError extends Error {
802
+ code = "bridge_transport_unavailable";
803
+ constructor(message, options) {
804
+ super(message, options);
805
+ this.name = "BridgeTransportUnavailableError";
806
+ }
807
+ };
735
808
  BinaryBridge = class BinaryBridge {
736
809
  static RESTART_RESET_MS = 5 * 60 * 1000;
737
810
  static STDERR_TAIL_MAX = 20;
@@ -770,7 +843,6 @@ var init_bridge = __esm(() => {
770
843
  configureWarningClients = new Map;
771
844
  restartResetTimer = null;
772
845
  lastChildActivityAt = 0;
773
- lastStatusBar;
774
846
  consecutiveRequestTimeouts = 0;
775
847
  errorPrefix;
776
848
  logger;
@@ -870,6 +942,20 @@ var init_bridge = __esm(() => {
870
942
  isAlive() {
871
943
  return this.process !== null && this.process.exitCode === null && !this.process.killed;
872
944
  }
945
+ invalidateTransportProcess(error2) {
946
+ const proc = this.process;
947
+ if (!proc)
948
+ return;
949
+ this.process = null;
950
+ this.spawnedBinaryFingerprint = null;
951
+ if (proc.exitCode === null && !proc.killed) {
952
+ proc.kill("SIGKILL");
953
+ }
954
+ this.clearRestartResetTimer();
955
+ this.configured = false;
956
+ this.outstandingBackgroundTaskIds.clear();
957
+ this.rejectAllPending(error2);
958
+ }
873
959
  hasPendingRequests() {
874
960
  return this.pending.size > 0;
875
961
  }
@@ -971,7 +1057,7 @@ var init_bridge = __esm(() => {
971
1057
  throw new Error(`${this.errorPrefix} Bridge is retiring after the on-disk binary changed; retry to respawn on the updated binary`);
972
1058
  }
973
1059
  if (this._shuttingDown) {
974
- throw new Error(`${this.errorPrefix} Bridge is shutting down, cannot send "${command}"`);
1060
+ throw new BridgeTransportUnavailableError(`${this.errorPrefix} Bridge is shutting down, cannot send "${command}"`);
975
1061
  }
976
1062
  if (Object.hasOwn(params, "id")) {
977
1063
  throw new Error("params cannot contain reserved key 'id'");
@@ -1005,7 +1091,7 @@ var init_bridge = __esm(() => {
1005
1091
  await this.deliverConfigureWarnings(configResult, params, options);
1006
1092
  await this.checkVersion(implicitTransportOptions);
1007
1093
  if (!this.isAlive()) {
1008
- throw new Error(`${this.errorPrefix} Bridge died during version check. Check logs: ${this.getLogFilePathVia()}`);
1094
+ throw new BridgeTransportUnavailableError(`${this.errorPrefix} Bridge died during version check. Check logs: ${this.getLogFilePathVia()}`);
1009
1095
  }
1010
1096
  this.configured = true;
1011
1097
  } finally {
@@ -1035,6 +1121,7 @@ var init_bridge = __esm(() => {
1035
1121
  `;
1036
1122
  const keepBridgeOnTimeout = passive || options?.keepBridgeOnTimeout === true;
1037
1123
  let requestSentAt = Date.now();
1124
+ const child = this.process;
1038
1125
  const response = await new Promise((resolve2, reject) => {
1039
1126
  const timer = setTimeout(() => {
1040
1127
  const entry = this.pending.get(id);
@@ -1071,21 +1158,27 @@ var init_bridge = __esm(() => {
1071
1158
  this.handleTimeout(requestSessionId);
1072
1159
  }, effectiveTimeoutMs);
1073
1160
  this.pending.set(id, { resolve: resolve2, reject, timer, onProgress: options?.onProgress, command });
1074
- if (!this.process?.stdin?.writable) {
1161
+ if (!child?.stdin?.writable) {
1075
1162
  this.pending.delete(id);
1076
1163
  clearTimeout(timer);
1077
- reject(new Error(`${this.errorPrefix} stdin not writable for command "${command}"`));
1164
+ const error2 = new BridgeTransportUnavailableError(`${this.errorPrefix} stdin not writable for command "${command}"`);
1165
+ reject(error2);
1166
+ if (this.process === child)
1167
+ this.invalidateTransportProcess(error2);
1078
1168
  return;
1079
1169
  }
1080
1170
  requestSentAt = Date.now();
1081
- this.process.stdin.write(line, (err) => {
1171
+ child.stdin.write(line, (err) => {
1082
1172
  if (err) {
1173
+ const error2 = new BridgeTransportUnavailableError(`${this.errorPrefix} Failed to write to stdin: ${err.message}`, { cause: err });
1083
1174
  const entry = this.pending.get(id);
1084
1175
  if (entry) {
1085
1176
  this.pending.delete(id);
1086
1177
  clearTimeout(entry.timer);
1087
- entry.reject(new Error(`${this.errorPrefix} Failed to write to stdin: ${err.message}`));
1178
+ entry.reject(error2);
1088
1179
  }
1180
+ if (this.process === child)
1181
+ this.invalidateTransportProcess(error2);
1089
1182
  }
1090
1183
  });
1091
1184
  });
@@ -1245,13 +1338,15 @@ var init_bridge = __esm(() => {
1245
1338
  });
1246
1339
  }
1247
1340
  ensureSpawned(triggeringSessionId) {
1248
- if (this.isAlive())
1341
+ if (this.isAlive() && this.process?.stdin?.writable)
1249
1342
  return;
1343
+ if (this.process !== null) {
1344
+ this.invalidateTransportProcess(new BridgeTransportUnavailableError(`${this.errorPrefix} Child stdin is not writable`));
1345
+ }
1250
1346
  this.spawnProcess(triggeringSessionId);
1251
1347
  }
1252
1348
  spawnProcess(triggeringSessionId) {
1253
1349
  this._retiringDueToBinaryChange = false;
1254
- this.lastStatusBar = undefined;
1255
1350
  if (triggeringSessionId) {
1256
1351
  this.sessionLogVia(triggeringSessionId, `Spawning binary: ${this.binaryPath} (cwd: ${this.cwd})`);
1257
1352
  } else {
@@ -1292,7 +1387,7 @@ var init_bridge = __esm(() => {
1292
1387
  }
1293
1388
  }
1294
1389
  }
1295
- const child = spawn(this.binaryPath, [], {
1390
+ const child = spawn2(this.binaryPath, [], {
1296
1391
  cwd: this.cwd,
1297
1392
  stdio: ["pipe", "pipe", "pipe"],
1298
1393
  env
@@ -1322,7 +1417,7 @@ var init_bridge = __esm(() => {
1322
1417
  if (this.process !== currentChild)
1323
1418
  return;
1324
1419
  this.errorVia(`Process error: ${err.message}${this.formatStderrTail()}`);
1325
- this.handleCrash();
1420
+ this.handleCrash(err);
1326
1421
  });
1327
1422
  child.on("exit", (code, signal) => {
1328
1423
  if (this.process !== currentChild)
@@ -1335,7 +1430,7 @@ var init_bridge = __esm(() => {
1335
1430
  this.process = null;
1336
1431
  this.configured = false;
1337
1432
  this.clearRestartResetTimer();
1338
- this.rejectAllPending(new Error(`${this.errorPrefix} Binary killed by ${signal}`));
1433
+ this.rejectAllPending(new BridgeTransportUnavailableError(`${this.errorPrefix} Binary killed by ${signal}`));
1339
1434
  return;
1340
1435
  }
1341
1436
  this.handleCrash();
@@ -1490,7 +1585,6 @@ var init_bridge = __esm(() => {
1490
1585
  this.consecutiveRequestTimeouts = 0;
1491
1586
  this.scheduleRestartCountReset();
1492
1587
  this.accountForBashTaskResponse(entry.command, response);
1493
- this.captureStatusBar(response);
1494
1588
  entry.resolve(response);
1495
1589
  } else if (typeof response.type === "string") {
1496
1590
  this.logVia(`Ignoring unknown stdout push frame type: ${response.type}`);
@@ -1511,14 +1605,6 @@ var init_bridge = __esm(() => {
1511
1605
  this.outstandingBackgroundTaskIds.add(taskId);
1512
1606
  }
1513
1607
  }
1514
- captureStatusBar(response) {
1515
- const parsed = parseStatusBarCounts(response.status_bar);
1516
- if (parsed)
1517
- this.lastStatusBar = parsed;
1518
- }
1519
- getStatusBar() {
1520
- return this.lastStatusBar;
1521
- }
1522
1608
  handleTimeout(triggeringSessionId) {
1523
1609
  this.consecutiveRequestTimeouts = 0;
1524
1610
  this.spawnedBinaryFingerprint = null;
@@ -1559,7 +1645,7 @@ var init_bridge = __esm(() => {
1559
1645
  if (tail) {
1560
1646
  this.errorVia(`Binary crashed (restarts: ${this._restartCount})${cause ? `: ${cause.message}` : ""}.${tail}`);
1561
1647
  }
1562
- this.rejectAllPending(new Error(`${this.errorPrefix} Binary crashed (restarts: ${this._restartCount})${cause ? `: ${cause.message}` : ""} (see ${this.getLogFilePathVia()})`));
1648
+ this.rejectAllPending(new BridgeTransportUnavailableError(`${this.errorPrefix} Binary crashed (restarts: ${this._restartCount})${cause ? `: ${cause.message}` : ""} (see ${this.getLogFilePathVia()})`, { cause }));
1563
1649
  if (this._retiringDueToBinaryChange) {
1564
1650
  this.logVia("Binary exited while retiring after an on-disk update; skipping auto-restart");
1565
1651
  return;
@@ -5542,7 +5628,6 @@ class SubcTransport {
5542
5628
  pool;
5543
5629
  projectRoot;
5544
5630
  generation;
5545
- lastStatusBar;
5546
5631
  cachedStatus = null;
5547
5632
  constructor(pool, projectRoot, generation) {
5548
5633
  this.pool = pool;
@@ -5558,20 +5643,12 @@ class SubcTransport {
5558
5643
  getConcretePoolId() {
5559
5644
  return this.pool.getConcretePoolId();
5560
5645
  }
5561
- getStatusBar() {
5562
- return this.lastStatusBar;
5563
- }
5564
5646
  getCachedStatus() {
5565
5647
  return this.cachedStatus;
5566
5648
  }
5567
5649
  cacheStatusSnapshot(snapshot) {
5568
5650
  this.cachedStatus = snapshot;
5569
5651
  }
5570
- captureStatusBar(response) {
5571
- const parsed = parseStatusBarCounts(response.status_bar);
5572
- if (parsed)
5573
- this.lastStatusBar = parsed;
5574
- }
5575
5652
  identityFor(session) {
5576
5653
  return {
5577
5654
  project_root: this.projectRoot,
@@ -5592,9 +5669,7 @@ class SubcTransport {
5592
5669
  if (preview === true)
5593
5670
  body.preview = true;
5594
5671
  const reply = await this.pool.routeRequest(this.identityFor(sessionId), body, timeoutMs, onProgress, this.generation);
5595
- const result = reliftReply(reply);
5596
- this.captureStatusBar(result);
5597
- return result;
5672
+ return reliftReply(reply);
5598
5673
  }
5599
5674
  async send(command, params = {}, options) {
5600
5675
  this.assertCurrent();
@@ -5608,9 +5683,7 @@ class SubcTransport {
5608
5683
  if (editSlotSurvives !== undefined)
5609
5684
  body.edit_slot_survives = editSlotSurvives;
5610
5685
  const reply = await this.pool.routeRequest(this.identityFor(session), body, timeoutMs, onProgress, this.generation);
5611
- const response = reliftReply(reply);
5612
- this.captureStatusBar(response);
5613
- return response;
5686
+ return reliftReply(reply);
5614
5687
  }
5615
5688
  splitOptions(options) {
5616
5689
  if (!options)
@@ -5881,7 +5954,7 @@ class SubcTransportPool {
5881
5954
  getBridge(projectRoot) {
5882
5955
  const root = this.canonicalRoot(projectRoot);
5883
5956
  if (this.shuttingDown && this.lifecycleEnabled()) {
5884
- throw new SubcCallError("terminal", "subc transport is shutting down");
5957
+ throw new SubcTransportShuttingDownError;
5885
5958
  }
5886
5959
  if (!this.lifecycleEnabled())
5887
5960
  return this.makeFacade(root);
@@ -6181,7 +6254,7 @@ class SubcTransportPool {
6181
6254
  }
6182
6255
  async ensureClient() {
6183
6256
  if (this.shuttingDown)
6184
- throw new SubcCallError("terminal", "subc transport is shutting down");
6257
+ throw new SubcTransportShuttingDownError;
6185
6258
  if (this.client)
6186
6259
  return this.client;
6187
6260
  if (this.connecting)
@@ -6195,7 +6268,7 @@ class SubcTransportPool {
6195
6268
  try {
6196
6269
  client.close();
6197
6270
  } catch {}
6198
- throw new SubcCallError("terminal", "subc transport is shutting down");
6271
+ throw new SubcTransportShuttingDownError;
6199
6272
  }
6200
6273
  this.client = client;
6201
6274
  this.transportFailures = 0;
@@ -6432,12 +6505,18 @@ function resolveBridgeForNudge(pool, ref) {
6432
6505
  currentConcretePoolId: candidate.getConcretePoolId?.()
6433
6506
  });
6434
6507
  }
6435
- var AFT_MODULE_ID = "aft", MAX_CONSECUTIVE_TRANSPORT_FAILURES = 3, BG_STABLE_MS = 5000, BG_LIFECYCLE_LOG_INTERVAL_MS = 60000, BG_DISPATCH_PROBE_INTERVAL_MS = 60000, DEFAULT_SESSION_ID = "__default__", LOCALLY_SATISFIED_COMMANDS, SubcRootReapedError, SubcRootGenerationExpiredError, SubcRootDemandRequiredError, RouteTornDownError;
6508
+ var SubcTransportShuttingDownError, AFT_MODULE_ID = "aft", MAX_CONSECUTIVE_TRANSPORT_FAILURES = 3, BG_STABLE_MS = 5000, BG_LIFECYCLE_LOG_INTERVAL_MS = 60000, BG_DISPATCH_PROBE_INTERVAL_MS = 60000, DEFAULT_SESSION_ID = "__default__", LOCALLY_SATISFIED_COMMANDS, SubcRootReapedError, SubcRootGenerationExpiredError, SubcRootDemandRequiredError, RouteTornDownError;
6436
6509
  var init_subc_transport = __esm(() => {
6437
6510
  init_dist();
6438
6511
  init_active_logger();
6439
6512
  init_lifecycle_registry();
6440
6513
  init_project_identity();
6514
+ SubcTransportShuttingDownError = class SubcTransportShuttingDownError extends SubcCallError {
6515
+ constructor() {
6516
+ super("terminal", "subc transport is shutting down", "transport_shutting_down");
6517
+ this.name = "SubcTransportShuttingDownError";
6518
+ }
6519
+ };
6441
6520
  LOCALLY_SATISFIED_COMMANDS = new Set(["configure"]);
6442
6521
  SubcRootReapedError = class SubcRootReapedError extends Error {
6443
6522
  code = "root_reaped";
@@ -6500,8 +6579,24 @@ function isRouteGoodbyeError(error2) {
6500
6579
  }
6501
6580
  return error2.code === "route_closed" && error2.message.includes("route closed by subc");
6502
6581
  }
6582
+ function hasEngineResponse(error2) {
6583
+ const response = error2.response;
6584
+ if (response !== null && typeof response === "object")
6585
+ return true;
6586
+ const cause = error2.cause;
6587
+ if (cause === null || typeof cause !== "object")
6588
+ return false;
6589
+ const causeResponse = cause.response;
6590
+ return causeResponse !== null && typeof causeResponse === "object";
6591
+ }
6592
+ function isBashTransportDeadError(error2) {
6593
+ if (!(error2 instanceof Error) || hasEngineResponse(error2) || isRouteGoodbyeError(error2)) {
6594
+ return false;
6595
+ }
6596
+ return error2 instanceof BridgeTransportUnavailableError || error2 instanceof SubcTransportShuttingDownError || isConsumerReconnectTransient(error2) || error2 instanceof StaleRouteHandleError || error2 instanceof SubcRootGenerationExpiredError || error2 instanceof SubcRootReapedError;
6597
+ }
6503
6598
  function isTransportClassError(error2) {
6504
- return isBridgeTransportTimeout(error2) || isConsumerReconnectTransient(error2) || error2 instanceof StaleRouteHandleError || error2 instanceof SubcRootGenerationExpiredError || error2 instanceof SubcRootReapedError;
6599
+ return isBridgeTransportTimeout(error2) || isBashTransportDeadError(error2);
6505
6600
  }
6506
6601
  function adaptToolError(command, error2) {
6507
6602
  if (!(error2 instanceof Error))
@@ -9212,9 +9307,6 @@ class RevivableProjectTransport {
9212
9307
  getCwd() {
9213
9308
  return this.projectRoot;
9214
9309
  }
9215
- getStatusBar() {
9216
- return this.owner.currentBridge(this.projectRoot)?.getStatusBar();
9217
- }
9218
9310
  getCachedStatus() {
9219
9311
  return this.owner.currentBridge(this.projectRoot)?.getCachedStatus() ?? null;
9220
9312
  }
@@ -9560,11 +9652,10 @@ __export(exports_dist, {
9560
9652
  tagStderrLine: () => tagStderrLine,
9561
9653
  stripJsoncSymbols: () => stripJsoncSymbols,
9562
9654
  stripHarnessSpecificConfigKeys: () => stripHarnessSpecificConfigKeys,
9563
- statusBarLine: () => statusBarLine,
9564
9655
  sleep: () => sleep,
9565
9656
  shouldShowAnnouncement: () => shouldShowAnnouncement,
9566
- shouldEmitStatusBar: () => shouldEmitStatusBar,
9567
9657
  setActiveLogger: () => setActiveLogger,
9658
+ runBashHostFallback: () => runBashHostFallback,
9568
9659
  resolveNpm: () => resolveNpm,
9569
9660
  resolveLegacyStorageRoot: () => resolveLegacyStorageRoot,
9570
9661
  resolveLegacyAftConfigSources: () => resolveLegacyAftConfigSources,
@@ -9584,7 +9675,6 @@ __export(exports_dist, {
9584
9675
  prepareCanonicalPathArguments: () => prepareCanonicalPathArguments,
9585
9676
  prepareCanonicalEditArguments: () => prepareCanonicalEditArguments,
9586
9677
  platformKey: () => platformKey,
9587
- parseStatusBarCounts: () => parseStatusBarCounts,
9588
9678
  npmSpawnEnv: () => npmSpawnEnv,
9589
9679
  migrateAftConfigFile: () => migrateAftConfigFile,
9590
9680
  maybeAppendGrepSearchHint: () => maybeAppendGrepSearchHint,
@@ -9599,6 +9689,7 @@ __export(exports_dist, {
9599
9689
  isHomeDirectoryRoot: () => isHomeDirectoryRoot,
9600
9690
  isEmptyParam: () => isEmptyParam,
9601
9691
  isBridgeTransportTimeout: () => isBridgeTransportTimeout,
9692
+ isBashTransportDeadError: () => isBashTransportDeadError,
9602
9693
  inlineUserConfigTier: () => inlineUserConfigTier,
9603
9694
  getMigrationStatus: () => getMigrationStatus,
9604
9695
  getManualInstallHint: () => getManualInstallHint,
@@ -9612,7 +9703,6 @@ __export(exports_dist, {
9612
9703
  formatZoomText: () => formatZoomText,
9613
9704
  formatZoomMultiTargetResult: () => formatZoomMultiTargetResult,
9614
9705
  formatTokenCount: () => formatTokenCount,
9615
- formatStatusBar: () => formatStatusBar,
9616
9706
  formatSeconds: () => formatSeconds,
9617
9707
  formatReadFooter: () => formatReadFooter,
9618
9708
  formatForegroundResult: () => formatForegroundResult,
@@ -9627,7 +9717,6 @@ __export(exports_dist, {
9627
9717
  ensureBinary: () => ensureBinary,
9628
9718
  downloadBinary: () => downloadBinary,
9629
9719
  decodeFileUrl: () => decodeFileUrl,
9630
- createStatusBarEmitState: () => createStatusBarEmitState,
9631
9720
  createAftTransportPool: () => createAftTransportPool,
9632
9721
  compressionSavingsPercent: () => compressionSavingsPercent,
9633
9722
  compareSemver: () => compareSemver,
@@ -9639,10 +9728,11 @@ __export(exports_dist, {
9639
9728
  coerceAliasedStringParam: () => coerceAliasedStringParam,
9640
9729
  cleanupOnnxRuntime: () => cleanupOnnxRuntime,
9641
9730
  canonicalizeProjectRoot: () => canonicalizeProjectRoot,
9731
+ bashHostFallbackAskPattern: () => bashHostFallbackAskPattern,
9642
9732
  adaptToolError: () => adaptToolError,
9643
9733
  __onnxTest__: () => __test__,
9734
+ SubcTransportShuttingDownError: () => SubcTransportShuttingDownError,
9644
9735
  SubcTransportPool: () => SubcTransportPool,
9645
- STATUS_BAR_HEARTBEAT_CALLS: () => STATUS_BAR_HEARTBEAT_CALLS,
9646
9736
  RotatingLogSink: () => RotatingLogSink,
9647
9737
  RevivableTransportPool: () => RevivableTransportPool,
9648
9738
  PLATFORM_ASSET_MAP: () => PLATFORM_ASSET_MAP,
@@ -9655,15 +9745,21 @@ __export(exports_dist, {
9655
9745
  HomeProjectRootError: () => HomeProjectRootError,
9656
9746
  DEFAULT_LOG_GENERATIONS: () => DEFAULT_LOG_GENERATIONS,
9657
9747
  DEFAULT_LOG_BYTES: () => DEFAULT_LOG_BYTES,
9748
+ BridgeTransportUnavailableError: () => BridgeTransportUnavailableError,
9658
9749
  BridgeTransportTimeoutError: () => BridgeTransportTimeoutError,
9659
9750
  BridgePool: () => BridgePool,
9660
9751
  BinaryBridge: () => BinaryBridge,
9661
9752
  BASH_TRANSPORT_DISPOSITION: () => BASH_TRANSPORT_DISPOSITION,
9753
+ BASH_HOST_FALLBACK_REFUSAL: () => BASH_HOST_FALLBACK_REFUSAL,
9754
+ BASH_HOST_FALLBACK_MAX_TIMEOUT_MS: () => BASH_HOST_FALLBACK_MAX_TIMEOUT_MS,
9755
+ BASH_HOST_FALLBACK_MAX_OUTPUT_BYTES: () => BASH_HOST_FALLBACK_MAX_OUTPUT_BYTES,
9756
+ BASH_HOST_FALLBACK_BANNER: () => BASH_HOST_FALLBACK_BANNER,
9662
9757
  AftToolError: () => AftToolError
9663
9758
  });
9664
9759
  var init_dist2 = __esm(() => {
9665
9760
  init_active_logger();
9666
9761
  init_bash_hints();
9762
+ init_bash_host_fallback();
9667
9763
  init_bridge();
9668
9764
  init_cache_paths();
9669
9765
  init_callgraph_format();
@@ -20197,7 +20293,7 @@ var init_setup = __esm(() => {
20197
20293
  });
20198
20294
 
20199
20295
  // src/lib/aft-bridge.ts
20200
- import { spawn as spawn2 } from "node:child_process";
20296
+ import { spawn as spawn3 } from "node:child_process";
20201
20297
  function isResponseForRequest(parsed, expectedIds) {
20202
20298
  if (!parsed || typeof parsed !== "object")
20203
20299
  return false;
@@ -20209,7 +20305,7 @@ function isResponseForRequest(parsed, expectedIds) {
20209
20305
  }
20210
20306
  async function sendAftRequests(binaryPath, requests) {
20211
20307
  return new Promise((resolve8, reject) => {
20212
- const child = spawn2(binaryPath, [], {
20308
+ const child = spawn3(binaryPath, [], {
20213
20309
  stdio: ["pipe", "pipe", "pipe"]
20214
20310
  });
20215
20311
  const responses = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/aft",
3
- "version": "0.50.3",
3
+ "version": "0.51.1",
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.6.0",
27
- "@cortexkit/aft-bridge": "0.50.3",
27
+ "@cortexkit/aft-bridge": "0.51.1",
28
28
  "comment-json": "^4.6.2"
29
29
  },
30
30
  "devDependencies": {