@cortexkit/aft 0.51.0 → 0.51.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.
Files changed (2) hide show
  1. package/dist/index.js +81 -17
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -764,7 +764,7 @@ function coerceConfigureDroppedKeys(value) {
764
764
  function isBridgeTransportTimeout(err) {
765
765
  return err instanceof Error && err.code === "transport_timeout";
766
766
  }
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;
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, BridgeTransportUnknownOutcomeError, BinaryBridge;
768
768
  var init_bridge = __esm(() => {
769
769
  init_active_logger();
770
770
  init_command_timeouts();
@@ -805,6 +805,12 @@ var init_bridge = __esm(() => {
805
805
  this.name = "BridgeTransportUnavailableError";
806
806
  }
807
807
  };
808
+ BridgeTransportUnknownOutcomeError = class BridgeTransportUnknownOutcomeError extends BridgeTransportUnavailableError {
809
+ constructor(message, options) {
810
+ super(message, options);
811
+ this.name = "BridgeTransportUnknownOutcomeError";
812
+ }
813
+ };
808
814
  BinaryBridge = class BinaryBridge {
809
815
  static RESTART_RESET_MS = 5 * 60 * 1000;
810
816
  static STDERR_TAIL_MAX = 20;
@@ -942,6 +948,20 @@ var init_bridge = __esm(() => {
942
948
  isAlive() {
943
949
  return this.process !== null && this.process.exitCode === null && !this.process.killed;
944
950
  }
951
+ invalidateTransportProcess(error2) {
952
+ const proc = this.process;
953
+ if (!proc)
954
+ return;
955
+ this.process = null;
956
+ this.spawnedBinaryFingerprint = null;
957
+ if (proc.exitCode === null && !proc.killed) {
958
+ proc.kill("SIGKILL");
959
+ }
960
+ this.clearRestartResetTimer();
961
+ this.configured = false;
962
+ this.outstandingBackgroundTaskIds.clear();
963
+ this.rejectAllPending(error2 instanceof BridgeTransportUnknownOutcomeError ? error2 : new BridgeTransportUnknownOutcomeError(error2.message, { cause: error2 }));
964
+ }
945
965
  hasPendingRequests() {
946
966
  return this.pending.size > 0;
947
967
  }
@@ -1063,6 +1083,12 @@ var init_bridge = __esm(() => {
1063
1083
  if (!this.configured) {
1064
1084
  if (command !== "configure" && command !== "version") {
1065
1085
  if (!this._configurePromise) {
1086
+ const configuringChild = this.process;
1087
+ const requireConfiguringChild = () => {
1088
+ if (this.process !== configuringChild) {
1089
+ throw new BridgeTransportUnavailableError(`${this.errorPrefix} Bridge process changed during configure; retry on replacement`);
1090
+ }
1091
+ };
1066
1092
  const sessionIdForConfigure = typeof params.session_id === "string" ? params.session_id : undefined;
1067
1093
  this._configurePromise = (async () => {
1068
1094
  try {
@@ -1071,11 +1097,14 @@ var init_bridge = __esm(() => {
1071
1097
  ...this.configOverrides,
1072
1098
  ...sessionIdForConfigure ? { session_id: sessionIdForConfigure } : {}
1073
1099
  }, implicitTransportOptions);
1100
+ requireConfiguringChild();
1074
1101
  if (configResult.success === false) {
1075
1102
  throw new Error(`${this.errorPrefix} Configure failed: ${configResult.message ?? "unknown error"}`);
1076
1103
  }
1077
1104
  await this.deliverConfigureWarnings(configResult, params, options);
1105
+ requireConfiguringChild();
1078
1106
  await this.checkVersion(implicitTransportOptions);
1107
+ requireConfiguringChild();
1079
1108
  if (!this.isAlive()) {
1080
1109
  throw new BridgeTransportUnavailableError(`${this.errorPrefix} Bridge died during version check. Check logs: ${this.getLogFilePathVia()}`);
1081
1110
  }
@@ -1107,6 +1136,7 @@ var init_bridge = __esm(() => {
1107
1136
  `;
1108
1137
  const keepBridgeOnTimeout = passive || options?.keepBridgeOnTimeout === true;
1109
1138
  let requestSentAt = Date.now();
1139
+ const child = this.process;
1110
1140
  const response = await new Promise((resolve2, reject) => {
1111
1141
  const timer = setTimeout(() => {
1112
1142
  const entry = this.pending.get(id);
@@ -1143,23 +1173,36 @@ var init_bridge = __esm(() => {
1143
1173
  this.handleTimeout(requestSessionId);
1144
1174
  }, effectiveTimeoutMs);
1145
1175
  this.pending.set(id, { resolve: resolve2, reject, timer, onProgress: options?.onProgress, command });
1146
- if (!this.process?.stdin?.writable) {
1176
+ if (!child?.stdin?.writable) {
1147
1177
  this.pending.delete(id);
1148
1178
  clearTimeout(timer);
1149
- reject(new BridgeTransportUnavailableError(`${this.errorPrefix} stdin not writable for command "${command}"`));
1179
+ const error2 = new BridgeTransportUnavailableError(`${this.errorPrefix} stdin not writable for command "${command}"`);
1180
+ reject(error2);
1181
+ if (this.process === child)
1182
+ this.invalidateTransportProcess(error2);
1150
1183
  return;
1151
1184
  }
1152
1185
  requestSentAt = Date.now();
1153
- this.process.stdin.write(line, (err) => {
1154
- if (err) {
1155
- const entry = this.pending.get(id);
1156
- if (entry) {
1157
- this.pending.delete(id);
1158
- clearTimeout(entry.timer);
1159
- entry.reject(new BridgeTransportUnavailableError(`${this.errorPrefix} Failed to write to stdin: ${err.message}`, { cause: err }));
1160
- }
1186
+ const handleWriteFailure = (cause) => {
1187
+ const writeError = cause instanceof Error ? cause : new Error(String(cause));
1188
+ const error2 = new BridgeTransportUnknownOutcomeError(`${this.errorPrefix} Failed to write to stdin: ${writeError.message}`, { cause: writeError });
1189
+ const entry = this.pending.get(id);
1190
+ if (entry) {
1191
+ this.pending.delete(id);
1192
+ clearTimeout(entry.timer);
1193
+ entry.reject(error2);
1161
1194
  }
1162
- });
1195
+ if (this.process === child)
1196
+ this.invalidateTransportProcess(error2);
1197
+ };
1198
+ try {
1199
+ child.stdin.write(line, (err) => {
1200
+ if (err)
1201
+ handleWriteFailure(err);
1202
+ });
1203
+ } catch (err) {
1204
+ handleWriteFailure(err);
1205
+ }
1163
1206
  });
1164
1207
  if (command === "configure" && response.success === true && options?.markConfiguredOnSuccess !== false) {
1165
1208
  this.configured = true;
@@ -1317,8 +1360,11 @@ var init_bridge = __esm(() => {
1317
1360
  });
1318
1361
  }
1319
1362
  ensureSpawned(triggeringSessionId) {
1320
- if (this.isAlive())
1363
+ if (this.isAlive() && this.process?.stdin?.writable)
1321
1364
  return;
1365
+ if (this.process !== null) {
1366
+ this.invalidateTransportProcess(new BridgeTransportUnavailableError(`${this.errorPrefix} Child stdin is not writable`));
1367
+ }
1322
1368
  this.spawnProcess(triggeringSessionId);
1323
1369
  }
1324
1370
  spawnProcess(triggeringSessionId) {
@@ -1371,9 +1417,13 @@ var init_bridge = __esm(() => {
1371
1417
  const currentChild = child;
1372
1418
  const stdoutDecoder = new StringDecoder("utf8");
1373
1419
  child.stdout?.on("data", (chunk) => {
1420
+ if (this.process !== currentChild)
1421
+ return;
1374
1422
  this.onStdoutData(stdoutDecoder.write(chunk));
1375
1423
  });
1376
1424
  child.stdout?.on("end", () => {
1425
+ if (this.process !== currentChild)
1426
+ return;
1377
1427
  const remaining = stdoutDecoder.end();
1378
1428
  if (remaining)
1379
1429
  this.onStdoutData(remaining);
@@ -1381,9 +1431,13 @@ var init_bridge = __esm(() => {
1381
1431
  });
1382
1432
  const stderrDecoder = new StringDecoder("utf8");
1383
1433
  child.stderr?.on("data", (chunk) => {
1434
+ if (this.process !== currentChild)
1435
+ return;
1384
1436
  this.onStderrData(stderrDecoder.write(chunk));
1385
1437
  });
1386
1438
  child.stderr?.on("end", () => {
1439
+ if (this.process !== currentChild)
1440
+ return;
1387
1441
  const remaining = stderrDecoder.end();
1388
1442
  if (remaining)
1389
1443
  this.onStderrData(remaining);
@@ -1406,7 +1460,7 @@ var init_bridge = __esm(() => {
1406
1460
  this.process = null;
1407
1461
  this.configured = false;
1408
1462
  this.clearRestartResetTimer();
1409
- this.rejectAllPending(new BridgeTransportUnavailableError(`${this.errorPrefix} Binary killed by ${signal}`));
1463
+ this.rejectAllPending(new BridgeTransportUnknownOutcomeError(`${this.errorPrefix} Binary killed by ${signal}`));
1410
1464
  return;
1411
1465
  }
1412
1466
  this.handleCrash();
@@ -1584,7 +1638,7 @@ var init_bridge = __esm(() => {
1584
1638
  handleTimeout(triggeringSessionId) {
1585
1639
  this.consecutiveRequestTimeouts = 0;
1586
1640
  this.spawnedBinaryFingerprint = null;
1587
- this.rejectAllPending(new Error(`${this.errorPrefix} bridge killed during sibling timeout — request aborted`));
1641
+ this.rejectAllPending(new BridgeTransportUnknownOutcomeError(`${this.errorPrefix} bridge killed during sibling timeout — request aborted`));
1588
1642
  this.outstandingBackgroundTaskIds.clear();
1589
1643
  if (this.process) {
1590
1644
  this.process.kill("SIGKILL");
@@ -1621,7 +1675,7 @@ var init_bridge = __esm(() => {
1621
1675
  if (tail) {
1622
1676
  this.errorVia(`Binary crashed (restarts: ${this._restartCount})${cause ? `: ${cause.message}` : ""}.${tail}`);
1623
1677
  }
1624
- this.rejectAllPending(new BridgeTransportUnavailableError(`${this.errorPrefix} Binary crashed (restarts: ${this._restartCount})${cause ? `: ${cause.message}` : ""} (see ${this.getLogFilePathVia()})`, { cause }));
1678
+ this.rejectAllPending(new BridgeTransportUnknownOutcomeError(`${this.errorPrefix} Binary crashed (restarts: ${this._restartCount})${cause ? `: ${cause.message}` : ""} (see ${this.getLogFilePathVia()})`, { cause }));
1625
1679
  if (this._retiringDueToBinaryChange) {
1626
1680
  this.logVia("Binary exited while retiring after an on-disk update; skipping auto-restart");
1627
1681
  return;
@@ -6569,6 +6623,8 @@ function isBashTransportDeadError(error2) {
6569
6623
  if (!(error2 instanceof Error) || hasEngineResponse(error2) || isRouteGoodbyeError(error2)) {
6570
6624
  return false;
6571
6625
  }
6626
+ if (error2 instanceof BridgeTransportUnknownOutcomeError)
6627
+ return false;
6572
6628
  return error2 instanceof BridgeTransportUnavailableError || error2 instanceof SubcTransportShuttingDownError || isConsumerReconnectTransient(error2) || error2 instanceof StaleRouteHandleError || error2 instanceof SubcRootGenerationExpiredError || error2 instanceof SubcRootReapedError;
6573
6629
  }
6574
6630
  function isTransportClassError(error2) {
@@ -6577,6 +6633,12 @@ function isTransportClassError(error2) {
6577
6633
  function adaptToolError(command, error2) {
6578
6634
  if (!(error2 instanceof Error))
6579
6635
  return error2;
6636
+ if (error2 instanceof BridgeTransportUnknownOutcomeError) {
6637
+ if (error2.message.includes(BRIDGE_TRANSPORT_UNKNOWN_OUTCOME_DISPOSITION))
6638
+ return error2;
6639
+ error2.message = error2.message ? `${error2.message} ${BRIDGE_TRANSPORT_UNKNOWN_OUTCOME_DISPOSITION}` : BRIDGE_TRANSPORT_UNKNOWN_OUTCOME_DISPOSITION;
6640
+ return error2;
6641
+ }
6580
6642
  if (isRouteGoodbyeError(error2)) {
6581
6643
  if (error2.message.includes(SUBC_MODULE_RESTART_DISPOSITION))
6582
6644
  return error2;
@@ -6590,7 +6652,7 @@ function adaptToolError(command, error2) {
6590
6652
  error2.message = error2.message ? `${error2.message} ${BASH_TRANSPORT_DISPOSITION}` : BASH_TRANSPORT_DISPOSITION;
6591
6653
  return error2;
6592
6654
  }
6593
- var AftToolError, BASH_TRANSPORT_DISPOSITION = "The transport to the AFT daemon was interrupted; no background task was created for this command and no task ID exists. Re-run the command. Do not poll bash_status for it.", SUBC_MODULE_RESTART_DISPOSITION = "The AFT daemon module restarted while this call was in flight, so its outcome is UNKNOWN: it may or may not have executed. Verify actual state before re-running, and never blind-retry a mutation.";
6655
+ var AftToolError, BASH_TRANSPORT_DISPOSITION = "The transport to the AFT daemon was interrupted; no background task was created for this command and no task ID exists. Re-run the command. Do not poll bash_status for it.", SUBC_MODULE_RESTART_DISPOSITION = "The AFT daemon module restarted while this call was in flight, so its outcome is UNKNOWN: it may or may not have executed. Verify actual state before re-running, and never blind-retry a mutation.", BRIDGE_TRANSPORT_UNKNOWN_OUTCOME_DISPOSITION = "The standalone AFT transport failed after this call may have been sent, so its outcome is UNKNOWN: it may or may not have executed. Verify actual state before re-running, and never blind-retry a mutation.";
6594
6656
  var init_error_contract = __esm(() => {
6595
6657
  init_dist();
6596
6658
  init_bridge();
@@ -9721,10 +9783,12 @@ __export(exports_dist, {
9721
9783
  HomeProjectRootError: () => HomeProjectRootError,
9722
9784
  DEFAULT_LOG_GENERATIONS: () => DEFAULT_LOG_GENERATIONS,
9723
9785
  DEFAULT_LOG_BYTES: () => DEFAULT_LOG_BYTES,
9786
+ BridgeTransportUnknownOutcomeError: () => BridgeTransportUnknownOutcomeError,
9724
9787
  BridgeTransportUnavailableError: () => BridgeTransportUnavailableError,
9725
9788
  BridgeTransportTimeoutError: () => BridgeTransportTimeoutError,
9726
9789
  BridgePool: () => BridgePool,
9727
9790
  BinaryBridge: () => BinaryBridge,
9791
+ BRIDGE_TRANSPORT_UNKNOWN_OUTCOME_DISPOSITION: () => BRIDGE_TRANSPORT_UNKNOWN_OUTCOME_DISPOSITION,
9728
9792
  BASH_TRANSPORT_DISPOSITION: () => BASH_TRANSPORT_DISPOSITION,
9729
9793
  BASH_HOST_FALLBACK_REFUSAL: () => BASH_HOST_FALLBACK_REFUSAL,
9730
9794
  BASH_HOST_FALLBACK_MAX_TIMEOUT_MS: () => BASH_HOST_FALLBACK_MAX_TIMEOUT_MS,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/aft",
3
- "version": "0.51.0",
3
+ "version": "0.51.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.6.0",
27
- "@cortexkit/aft-bridge": "0.51.0",
27
+ "@cortexkit/aft-bridge": "0.51.2",
28
28
  "comment-json": "^4.6.2"
29
29
  },
30
30
  "devDependencies": {