@cortexkit/aft 0.36.1 → 0.37.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.
package/dist/index.js CHANGED
@@ -104,6 +104,21 @@ 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/command-timeouts.js
108
+ var LONG_RUNNING_COMMAND_TIMEOUT_MS;
109
+ var init_command_timeouts = __esm(() => {
110
+ LONG_RUNNING_COMMAND_TIMEOUT_MS = {
111
+ callers: 60000,
112
+ trace_to: 60000,
113
+ trace_to_symbol: 60000,
114
+ trace_data: 60000,
115
+ impact: 60000,
116
+ grep: 60000,
117
+ glob: 60000,
118
+ semantic_search: 60000
119
+ };
120
+ });
121
+
107
122
  // ../aft-bridge/dist/status-bar.js
108
123
  function parseStatusBarCounts(value) {
109
124
  if (!value || typeof value !== "object")
@@ -129,6 +144,18 @@ import { spawn } from "node:child_process";
129
144
  import { homedir } from "node:os";
130
145
  import { join } from "node:path";
131
146
  import { StringDecoder } from "node:string_decoder";
147
+ function isTerminalBashStatus(status) {
148
+ return typeof status === "string" && TERMINAL_BASH_STATUSES.has(status);
149
+ }
150
+ function bashTaskIdFrom(response) {
151
+ const snakeCase = response.task_id;
152
+ if (typeof snakeCase === "string" && snakeCase.length > 0)
153
+ return snakeCase;
154
+ const camelCase = response.taskId;
155
+ if (typeof camelCase === "string" && camelCase.length > 0)
156
+ return camelCase;
157
+ return;
158
+ }
132
159
  function tagStderrLine(line) {
133
160
  return /^\[aft(-\w+)?\] /.test(line) ? line : `[aft] ${line}`;
134
161
  }
@@ -183,11 +210,12 @@ function clampSemanticTimeout(configOverrides, bridgeTimeoutMs) {
183
210
  if (typeof timeoutMs !== "number" || !Number.isFinite(timeoutMs)) {
184
211
  return configOverrides;
185
212
  }
186
- const maxSemanticTimeoutMs = bridgeTimeoutMs > SEMANTIC_TIMEOUT_SAFETY_MARGIN_MS ? bridgeTimeoutMs - SEMANTIC_TIMEOUT_SAFETY_MARGIN_MS : Math.max(1, bridgeTimeoutMs - 1);
213
+ const semanticTransportBudgetMs = Math.max(bridgeTimeoutMs, LONG_RUNNING_COMMAND_TIMEOUT_MS.semantic_search ?? 0);
214
+ const maxSemanticTimeoutMs = semanticTransportBudgetMs > SEMANTIC_TIMEOUT_SAFETY_MARGIN_MS ? semanticTransportBudgetMs - SEMANTIC_TIMEOUT_SAFETY_MARGIN_MS : Math.max(1, semanticTransportBudgetMs - 1);
187
215
  if (timeoutMs <= maxSemanticTimeoutMs) {
188
216
  return configOverrides;
189
217
  }
190
- warn(`semantic.timeout_ms=${timeoutMs} exceeds bridge timeout budget; clamping to ${maxSemanticTimeoutMs}ms (bridge timeout: ${bridgeTimeoutMs}ms)`);
218
+ warn(`semantic.timeout_ms=${timeoutMs} exceeds the semantic transport budget; clamping to ${maxSemanticTimeoutMs}ms (budget: ${semanticTransportBudgetMs}ms)`);
191
219
  return {
192
220
  ...configOverrides,
193
221
  semantic: {
@@ -196,10 +224,20 @@ function clampSemanticTimeout(configOverrides, bridgeTimeoutMs) {
196
224
  }
197
225
  };
198
226
  }
199
- var DEFAULT_BRIDGE_TIMEOUT_MS = 30000, BRIDGE_HANG_TIMEOUT_THRESHOLD = 2, SEMANTIC_TIMEOUT_SAFETY_MARGIN_MS = 5000, MAX_STDOUT_BUFFER, BridgeReplacedDuringVersionCheck, BinaryBridge;
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;
200
228
  var init_bridge = __esm(() => {
201
229
  init_active_logger();
230
+ init_command_timeouts();
202
231
  MAX_STDOUT_BUFFER = 64 * 1024 * 1024;
232
+ STDOUT_BUFFER_COMPACT_THRESHOLD = 64 * 1024;
233
+ TERMINAL_BASH_STATUSES = new Set([
234
+ "completed",
235
+ "failed",
236
+ "killed",
237
+ "timed_out",
238
+ "cancelled",
239
+ "timeout"
240
+ ]);
203
241
  BridgeReplacedDuringVersionCheck = class BridgeReplacedDuringVersionCheck extends Error {
204
242
  newBinaryPath;
205
243
  constructor(newBinaryPath) {
@@ -215,8 +253,10 @@ var init_bridge = __esm(() => {
215
253
  cwd;
216
254
  process = null;
217
255
  pending = new Map;
256
+ outstandingBackgroundTaskIds = new Set;
218
257
  nextId = 1;
219
258
  stdoutBuffer = "";
259
+ stdoutReadOffset = 0;
220
260
  stderrBuffer = "";
221
261
  stderrTail = [];
222
262
  _restartCount = 0;
@@ -326,6 +366,9 @@ var init_bridge = __esm(() => {
326
366
  hasPendingRequests() {
327
367
  return this.pending.size > 0;
328
368
  }
369
+ hasOutstandingBackgroundTasks() {
370
+ return this.outstandingBackgroundTaskIds.size > 0;
371
+ }
329
372
  getCwd() {
330
373
  return this.cwd;
331
374
  }
@@ -447,7 +490,7 @@ var init_bridge = __esm(() => {
447
490
  entry.reject(new Error(`${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`));
448
491
  this.handleTimeout(requestSessionId);
449
492
  }, effectiveTimeoutMs);
450
- this.pending.set(id, { resolve, reject, timer, onProgress: options?.onProgress });
493
+ this.pending.set(id, { resolve, reject, timer, onProgress: options?.onProgress, command });
451
494
  if (!this.process?.stdin?.writable) {
452
495
  this.pending.delete(id);
453
496
  clearTimeout(timer);
@@ -708,6 +751,7 @@ var init_bridge = __esm(() => {
708
751
  });
709
752
  this.process = child;
710
753
  this.stdoutBuffer = "";
754
+ this.stdoutReadOffset = 0;
711
755
  this.stderrBuffer = "";
712
756
  this.lastChildActivityAt = 0;
713
757
  this.consecutiveRequestTimeouts = 0;
@@ -752,24 +796,41 @@ var init_bridge = __esm(() => {
752
796
  ${tail}`;
753
797
  }
754
798
  onStdoutData(data) {
799
+ if (this.stdoutReadOffset > STDOUT_BUFFER_COMPACT_THRESHOLD) {
800
+ this.compactStdoutBuffer();
801
+ }
755
802
  this.stdoutBuffer += data;
756
- if (this.stdoutBuffer.length > MAX_STDOUT_BUFFER) {
803
+ if (this.stdoutBuffer.length - this.stdoutReadOffset > MAX_STDOUT_BUFFER) {
757
804
  this.handleCrash(new Error(`aft bridge stdout buffer exceeded ${MAX_STDOUT_BUFFER} bytes — killing bridge`));
758
805
  return;
759
806
  }
760
807
  let newlineIdx;
761
808
  while ((newlineIdx = this.stdoutBuffer.indexOf(`
762
- `)) !== -1) {
763
- const line = this.stdoutBuffer.slice(0, newlineIdx).trim();
764
- this.stdoutBuffer = this.stdoutBuffer.slice(newlineIdx + 1);
765
- if (!line)
766
- continue;
767
- this.processStdoutLine(line);
809
+ `, this.stdoutReadOffset)) !== -1) {
810
+ const line = this.stdoutBuffer.slice(this.stdoutReadOffset, newlineIdx).trim();
811
+ this.stdoutReadOffset = newlineIdx + 1;
812
+ if (line) {
813
+ this.processStdoutLine(line);
814
+ }
815
+ if (this.stdoutReadOffset > STDOUT_BUFFER_COMPACT_THRESHOLD && this.stdoutReadOffset > this.stdoutBuffer.length / 2) {
816
+ this.compactStdoutBuffer();
817
+ }
818
+ }
819
+ if (this.stdoutReadOffset === this.stdoutBuffer.length) {
820
+ this.stdoutBuffer = "";
821
+ this.stdoutReadOffset = 0;
768
822
  }
769
823
  }
824
+ compactStdoutBuffer() {
825
+ if (this.stdoutReadOffset === 0)
826
+ return;
827
+ this.stdoutBuffer = this.stdoutBuffer.slice(this.stdoutReadOffset);
828
+ this.stdoutReadOffset = 0;
829
+ }
770
830
  flushStdoutBuffer() {
771
- const line = this.stdoutBuffer.trim();
831
+ const line = this.stdoutBuffer.slice(this.stdoutReadOffset).trim();
772
832
  this.stdoutBuffer = "";
833
+ this.stdoutReadOffset = 0;
773
834
  if (!line)
774
835
  return;
775
836
  this.processStdoutLine(line);
@@ -802,6 +863,9 @@ var init_bridge = __esm(() => {
802
863
  return;
803
864
  }
804
865
  if (response.type === "bash_completed") {
866
+ const taskId = bashTaskIdFrom(response);
867
+ if (taskId)
868
+ this.outstandingBackgroundTaskIds.delete(taskId);
805
869
  this.onBashCompletion?.(response, this);
806
870
  return;
807
871
  }
@@ -832,6 +896,7 @@ var init_bridge = __esm(() => {
832
896
  clearTimeout(entry.timer);
833
897
  this.consecutiveRequestTimeouts = 0;
834
898
  this.scheduleRestartCountReset();
899
+ this.accountForBashTaskResponse(entry.command, response);
835
900
  this.captureStatusBar(response);
836
901
  entry.resolve(response);
837
902
  } else if (typeof response.type === "string") {
@@ -841,6 +906,18 @@ var init_bridge = __esm(() => {
841
906
  this.warnVia(`Failed to parse stdout line: ${line}`);
842
907
  }
843
908
  }
909
+ accountForBashTaskResponse(command, response) {
910
+ const taskId = bashTaskIdFrom(response);
911
+ if (!taskId)
912
+ return;
913
+ if (isTerminalBashStatus(response.status)) {
914
+ this.outstandingBackgroundTaskIds.delete(taskId);
915
+ return;
916
+ }
917
+ if (command === "bash" && response.success !== false) {
918
+ this.outstandingBackgroundTaskIds.add(taskId);
919
+ }
920
+ }
844
921
  captureStatusBar(response) {
845
922
  const parsed = parseStatusBarCounts(response.status_bar);
846
923
  if (parsed)
@@ -852,6 +929,7 @@ var init_bridge = __esm(() => {
852
929
  handleTimeout(triggeringSessionId) {
853
930
  this.consecutiveRequestTimeouts = 0;
854
931
  this.rejectAllPending(new Error(`${this.errorPrefix} bridge killed during sibling timeout — request aborted`));
932
+ this.outstandingBackgroundTaskIds.clear();
855
933
  if (this.process) {
856
934
  this.process.kill("SIGKILL");
857
935
  this.process = null;
@@ -881,6 +959,7 @@ var init_bridge = __esm(() => {
881
959
  }
882
960
  this.clearRestartResetTimer();
883
961
  this.configured = false;
962
+ this.outstandingBackgroundTaskIds.clear();
884
963
  const tail = this.formatStderrTail();
885
964
  if (tail) {
886
965
  this.errorVia(`Binary crashed (restarts: ${this._restartCount})${cause ? `: ${cause.message}` : ""}.${tail}`);
@@ -1275,7 +1354,7 @@ class BridgePool {
1275
1354
  cleanup() {
1276
1355
  const now = Date.now();
1277
1356
  for (const [dir, entry] of this.bridges) {
1278
- if (entry.bridge.hasPendingRequests())
1357
+ if (entry.bridge.hasPendingRequests() || entry.bridge.hasOutstandingBackgroundTasks())
1279
1358
  continue;
1280
1359
  if (now - entry.lastUsed > this.idleTimeoutMs) {
1281
1360
  entry.bridge.shutdown().catch((err) => this.error("cleanup shutdown failed:", err));
@@ -1283,7 +1362,7 @@ class BridgePool {
1283
1362
  }
1284
1363
  }
1285
1364
  for (const bridge of this.staleBridges) {
1286
- if (bridge.hasPendingRequests())
1365
+ if (bridge.hasPendingRequests() || bridge.hasOutstandingBackgroundTasks())
1287
1366
  continue;
1288
1367
  bridge.shutdown().catch((err) => this.error("stale cleanup shutdown failed:", err));
1289
1368
  this.staleBridges.delete(bridge);
@@ -1293,7 +1372,7 @@ class BridgePool {
1293
1372
  let oldestDir = null;
1294
1373
  let oldestTime = Infinity;
1295
1374
  for (const [dir, entry] of this.bridges) {
1296
- if (entry.bridge.hasPendingRequests())
1375
+ if (entry.bridge.hasPendingRequests() || entry.bridge.hasOutstandingBackgroundTasks())
1297
1376
  continue;
1298
1377
  if (entry.lastUsed < oldestTime) {
1299
1378
  oldestTime = entry.lastUsed;
@@ -1377,16 +1456,18 @@ function normalizeKey(projectRoot) {
1377
1456
  return stripped;
1378
1457
  }
1379
1458
  }
1380
- var DEFAULT_IDLE_TIMEOUT_MS = Infinity, DEFAULT_MAX_POOL_SIZE = 8, CLEANUP_INTERVAL_MS;
1459
+ var DEFAULT_IDLE_TIMEOUT_MS, DEFAULT_MAX_POOL_SIZE = 8, CLEANUP_INTERVAL_MS;
1381
1460
  var init_pool = __esm(() => {
1382
1461
  init_active_logger();
1383
1462
  init_bridge();
1463
+ DEFAULT_IDLE_TIMEOUT_MS = 30 * 60 * 1000;
1384
1464
  CLEANUP_INTERVAL_MS = 60 * 1000;
1385
1465
  });
1386
1466
  // ../aft-bridge/dist/index.js
1387
1467
  var init_dist = __esm(() => {
1388
1468
  init_active_logger();
1389
1469
  init_bridge();
1470
+ init_command_timeouts();
1390
1471
  init_downloader();
1391
1472
  init_migration();
1392
1473
  init_npm_resolver();
@@ -9481,7 +9562,7 @@ function ensureAftSchemaUrl(path, format) {
9481
9562
  message: `updated $schema URL in ${path}`
9482
9563
  };
9483
9564
  }
9484
- var import_comment_json, AFT_SCHEMA_URL = "https://raw.githubusercontent.com/cortexkit/aft/master/assets/aft.schema.json";
9565
+ var import_comment_json, AFT_SCHEMA_URL = "https://raw.githubusercontent.com/cortexkit/aft/main/assets/aft.schema.json";
9485
9566
  var init_jsonc = __esm(() => {
9486
9567
  import_comment_json = __toESM(require_src2(), 1);
9487
9568
  });
@@ -12591,8 +12672,9 @@ function sanitizeContent(content) {
12591
12672
  }
12592
12673
  sanitized = sanitized.replace(/\/Users\/[^/\s"']+/g, "/Users/<USER>");
12593
12674
  sanitized = sanitized.replace(/\/home\/[^/\s"']+/g, "/home/<USER>");
12594
- sanitized = sanitized.replace(/C:\\\\Users\\\\[^\\\\"'\s]+/g, "C:\\\\Users\\\\<USER>");
12595
- sanitized = sanitized.replace(/C:\\Users\\[^\\"'\s]+/g, "C:\\Users\\<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>");
12596
12678
  if (username) {
12597
12679
  sanitized = sanitized.replace(new RegExp(escapeRegex(username), "g"), "<USER>");
12598
12680
  }
@@ -17,7 +17,7 @@ export declare function readJsoncFile(path: string): {
17
17
  */
18
18
  export declare function writeJsoncFile(path: string, value: Record<string, unknown>, format?: JsoncFormat): void;
19
19
  /** Canonical URL of the published AFT config schema. */
20
- export declare const AFT_SCHEMA_URL = "https://raw.githubusercontent.com/cortexkit/aft/master/assets/aft.schema.json";
20
+ export declare const AFT_SCHEMA_URL = "https://raw.githubusercontent.com/cortexkit/aft/main/assets/aft.schema.json";
21
21
  export type AftSchemaAction = "added" | "updated" | "unchanged";
22
22
  /**
23
23
  * Ensure `aft.jsonc` (or `aft.json`) contains a top-level `$schema` field
@@ -1 +1 @@
1
- {"version":3,"file":"jsonc.d.ts","sourceRoot":"","sources":["../../src/lib/jsonc.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAEpD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,CAW9E;AAED,8EAA8E;AAC9E,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG;IAC3C,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAcA;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,MAAM,GAAE,WAAoB,GAC3B,IAAI,CAKN;AAED,wDAAwD;AACxD,eAAO,MAAM,cAAc,kFACsD,CAAC;AAElF,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW,CAAC;AAEhE;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,WAAW,GAClB;IAAE,MAAM,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAoC9C"}
1
+ {"version":3,"file":"jsonc.d.ts","sourceRoot":"","sources":["../../src/lib/jsonc.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAEpD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,CAW9E;AAED,8EAA8E;AAC9E,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG;IAC3C,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAcA;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,MAAM,GAAE,WAAoB,GAC3B,IAAI,CAKN;AAED,wDAAwD;AACxD,eAAO,MAAM,cAAc,gFACoD,CAAC;AAEhF,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW,CAAC;AAEhE;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,WAAW,GAClB;IAAE,MAAM,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAoC9C"}
@@ -1 +1 @@
1
- {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/lib/sanitize.ts"],"names":[],"mappings":"AAGA,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAmFD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA4BvD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAarD"}
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/lib/sanitize.ts"],"names":[],"mappings":"AAGA,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAmFD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAkCvD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAarD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/aft",
3
- "version": "0.36.1",
3
+ "version": "0.37.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.2.0",
27
- "@cortexkit/aft-bridge": "0.36.1",
27
+ "@cortexkit/aft-bridge": "0.37.1",
28
28
  "comment-json": "^4.6.2"
29
29
  },
30
30
  "devDependencies": {