@cortexkit/aft-opencode 0.64.0 → 0.65.0

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 (37) hide show
  1. package/dist/bg-notifications.d.ts.map +1 -1
  2. package/dist/config-live-reload.d.ts +2 -14
  3. package/dist/config-live-reload.d.ts.map +1 -1
  4. package/dist/config.d.ts +4 -16
  5. package/dist/config.d.ts.map +1 -1
  6. package/dist/entry/server.js +1271 -583
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +1271 -583
  9. package/dist/shared/session-directory.d.ts +7 -2
  10. package/dist/shared/session-directory.d.ts.map +1 -1
  11. package/dist/shared/status.d.ts +2 -2
  12. package/dist/shared/status.d.ts.map +1 -1
  13. package/dist/tool-registration.d.ts +1 -1
  14. package/dist/tool-registration.d.ts.map +1 -1
  15. package/dist/tools/bash.d.ts.map +1 -1
  16. package/dist/tools/bash_watch.d.ts.map +1 -1
  17. package/dist/tools/definitions/v2.d.ts +1 -1
  18. package/dist/tools/definitions/v2.d.ts.map +1 -1
  19. package/dist/tui/shared-sidebar.d.ts +4 -0
  20. package/dist/tui/shared-sidebar.d.ts.map +1 -0
  21. package/dist/v2-session-lifecycle.d.ts.map +1 -1
  22. package/dist/workflow-hints.d.ts +1 -5
  23. package/dist/workflow-hints.d.ts.map +1 -1
  24. package/package.json +14 -12
  25. package/src/shared/session-directory.ts +80 -12
  26. package/src/shared/status.ts +4 -4
  27. package/src/tui/index.tsx +7 -3
  28. package/src/tui/shared-sidebar.ts +14 -0
  29. package/src/tui/sidebar-view.tsx +256 -245
  30. package/src/tui-compiled/index.tsx +4 -3
  31. package/src/tui-compiled/shared-sidebar-host.tsx +816 -0
  32. package/src/tui-compiled/shared-sidebar-local.tsx +816 -0
  33. package/src/tui-compiled/shared-sidebar.LICENSE +21 -0
  34. package/src/tui-compiled/shared-sidebar.ts +14 -0
  35. package/src/tui-compiled/sidebar-view.tsx +183 -221
  36. package/src/tui-compiled/sidebar.tsx +1 -0
  37. package/src/tui-compiled/v2.tsx +1 -0
package/dist/index.js CHANGED
@@ -8709,7 +8709,14 @@ var TERMINAL_BASH_STATUSES = new Set(TERMINAL_BG_TASK_STATUSES);
8709
8709
  function isTerminalBashStatus(status, compatibilityAliases = false) {
8710
8710
  return typeof status === "string" && (TERMINAL_BASH_STATUSES.has(status) || compatibilityAliases && (status === "cancelled" || status === "timeout"));
8711
8711
  }
8712
+
8712
8713
  // ../aft-bridge/dist/bash-format.js
8714
+ function formatUnknownPtyExit(taskId, data) {
8715
+ if (data.status !== "fate_unknown" || data.status_reason !== "AFT could not read how it ended") {
8716
+ return;
8717
+ }
8718
+ return `Task ${taskId}: exit status unknown (AFT could not read how it ended)`;
8719
+ }
8713
8720
  function isTerminalStatus(status) {
8714
8721
  return isTerminalBashStatus(status);
8715
8722
  }
@@ -8733,6 +8740,79 @@ function relativePathEscapesRoot(rel, platform = process.platform) {
8733
8740
  return rel === ".." || rel.startsWith("../") || platform === "win32" && rel.startsWith("..\\") || (platform === "win32" ? win32.isAbsolute(rel) : posix.isAbsolute(rel));
8734
8741
  }
8735
8742
 
8743
+ // ../aft-bridge/dist/wait-clock.js
8744
+ var SUSPEND_SKEW_MS = 1000;
8745
+ var RESUME_ALLOWANCE_MS = 1e4;
8746
+ var DEADLINE_POLL_MS = 250;
8747
+
8748
+ class WaitClock {
8749
+ wallNow;
8750
+ awakeNow;
8751
+ wall;
8752
+ awake;
8753
+ skew = 0;
8754
+ elapsed;
8755
+ suspendCount = 0;
8756
+ lastSuspendEnd = Number.NEGATIVE_INFINITY;
8757
+ constructor(wallNow = Date.now, awakeNow = () => performance.now()) {
8758
+ this.wallNow = wallNow;
8759
+ this.awakeNow = awakeNow;
8760
+ this.wall = wallNow();
8761
+ this.awake = awakeNow();
8762
+ this.elapsed = this.awake;
8763
+ }
8764
+ now() {
8765
+ const wall = this.wallNow();
8766
+ const awake = this.awakeNow();
8767
+ const active = Math.max(0, awake - this.awake);
8768
+ this.skew = Math.max(0, this.skew + wall - this.wall - active);
8769
+ this.elapsed += active;
8770
+ if (this.skew >= SUSPEND_SKEW_MS) {
8771
+ this.elapsed += this.skew;
8772
+ this.lastSuspendEnd = this.elapsed;
8773
+ this.skew = 0;
8774
+ this.suspendCount++;
8775
+ }
8776
+ this.wall = wall;
8777
+ this.awake = awake;
8778
+ return this.elapsed;
8779
+ }
8780
+ }
8781
+
8782
+ class RequestDeadline {
8783
+ clock;
8784
+ allowResume;
8785
+ deadline;
8786
+ suspendCount;
8787
+ resumed = false;
8788
+ constructor(clock, timeoutMs, allowResume = true) {
8789
+ this.clock = clock;
8790
+ this.allowResume = allowResume;
8791
+ this.deadline = clock.now() + timeoutMs;
8792
+ this.suspendCount = clock.suspendCount;
8793
+ }
8794
+ remaining() {
8795
+ const now = this.clock.now();
8796
+ if (now >= this.deadline && this.allowResume && !this.resumed && this.clock.suspendCount > this.suspendCount && this.clock.lastSuspendEnd >= this.deadline) {
8797
+ this.resumed = true;
8798
+ this.deadline = now + RESUME_ALLOWANCE_MS;
8799
+ }
8800
+ return Math.max(0, this.deadline - now);
8801
+ }
8802
+ }
8803
+ function deadlineTimer(scheduler, remaining, expired) {
8804
+ let timer;
8805
+ const check = () => {
8806
+ const left = remaining();
8807
+ if (left <= 0)
8808
+ expired();
8809
+ else
8810
+ timer = scheduler.setTimeout(check, Math.min(left, DEADLINE_POLL_MS));
8811
+ };
8812
+ check();
8813
+ return () => scheduler.clearTimeout(timer);
8814
+ }
8815
+
8736
8816
  // ../aft-bridge/dist/bash-hints.js
8737
8817
  var DEFAULT_PRIMARY_WATCH_TIMEOUT_MS = 30000;
8738
8818
  var MAX_WATCH_TIMEOUT_MS = 1800000;
@@ -8760,7 +8840,8 @@ function watchPollDelayMs(elapsedMs) {
8760
8840
  return 1000;
8761
8841
  }
8762
8842
  var watchClock = {
8763
- now: () => performance.now(),
8843
+ source: new WaitClock,
8844
+ now: () => watchClock.source.now(),
8764
8845
  sleep: abortableSleep
8765
8846
  };
8766
8847
  function abortableSleep(ms, signal) {
@@ -8906,6 +8987,7 @@ var GREP_SEARCH_AFT_SEARCH_HINT = "DO NOT search code by running grep/rg in bash
8906
8987
  var 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).";
8907
8988
  var GREP_SEARCH_HINT_PREFIX = "DO NOT search code by running grep/rg in bash —";
8908
8989
  var GREP_SEARCH_FRESHNESS_WINDOW_MS = 60000;
8990
+ var MTIME_CLOCK_SLACK_MS = 1;
8909
8991
  function maybeAppendConflictsHint(output) {
8910
8992
  if (!output.includes("Automatic merge failed; fix conflicts"))
8911
8993
  return output;
@@ -8913,15 +8995,15 @@ function maybeAppendConflictsHint(output) {
8913
8995
  return output;
8914
8996
  return output + CONFLICT_HINT;
8915
8997
  }
8916
- function commandInvokesCodeSearch(command) {
8917
- const statements = splitTopLevelStatements(command);
8998
+ function commandInvokesCodeSearch(command, platform = process.platform) {
8999
+ const statements = splitTopLevelStatements(command, platform);
8918
9000
  if (statements === null)
8919
9001
  return false;
8920
9002
  for (const statement of statements) {
8921
- const firstStage = firstPipelineStage(statement);
9003
+ const firstStage = firstPipelineStage(statement, platform);
8922
9004
  if (firstStage === null)
8923
9005
  continue;
8924
- const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0));
9006
+ const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0), platform);
8925
9007
  if (firstToken === null)
8926
9008
  continue;
8927
9009
  if (firstToken.token === "grep" || firstToken.token === "rg")
@@ -8929,42 +9011,43 @@ function commandInvokesCodeSearch(command) {
8929
9011
  }
8930
9012
  return false;
8931
9013
  }
8932
- function maybeAppendGrepSearchHint(output, command, aftSearchRegistered, projectRoot) {
9014
+ function maybeAppendGrepSearchHint(output, command, aftSearchRegistered, projectRoot, platform = process.platform, workdir) {
8933
9015
  if (output === "")
8934
9016
  return output;
8935
- if (!commandInvokesCodeSearch(command))
9017
+ if (!commandInvokesCodeSearch(command, platform))
8936
9018
  return output;
8937
9019
  if (output.includes(GREP_SEARCH_HINT_PREFIX))
8938
9020
  return output;
8939
- if (shouldSuppressGrepSearchHint(command, projectRoot))
9021
+ if (shouldSuppressGrepSearchHint(command, projectRoot, platform, workdir))
8940
9022
  return output;
8941
9023
  const hint = aftSearchRegistered ? GREP_SEARCH_AFT_SEARCH_HINT : GREP_SEARCH_GREP_HINT;
8942
9024
  return `${output}
8943
9025
 
8944
9026
  ${hint}`;
8945
9027
  }
8946
- function shouldSuppressGrepSearchHint(command, projectRoot) {
8947
- const statements = splitTopLevelStatements(command);
9028
+ function shouldSuppressGrepSearchHint(command, projectRoot, platform, workdir) {
9029
+ const statements = splitTopLevelStatements(command, platform);
8948
9030
  if (statements === null)
8949
9031
  return false;
8950
- if (allSearchPathOperandsAreDynamic(statements))
9032
+ if (allSearchPathOperandsAreDynamic(statements, platform))
8951
9033
  return true;
8952
9034
  const root = projectRoot?.trim();
8953
9035
  if (!root)
8954
9036
  return false;
8955
- const resolvedRoot = path.resolve(root);
8956
- let effectiveCwd = resolvedRoot;
9037
+ const paths = platform === "win32" ? path.win32 : path.posix;
9038
+ const resolvedRoot = paths.resolve(root);
9039
+ let effectiveCwd = paths.resolve(resolvedRoot, workdir ?? ".");
8957
9040
  let sawCodeSearchStatement = false;
8958
9041
  for (const statement of statements) {
8959
- const firstStage = firstPipelineStage(statement);
9042
+ const firstStage = firstPipelineStage(statement, platform);
8960
9043
  if (firstStage === null)
8961
9044
  continue;
8962
- const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0));
9045
+ const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0), platform);
8963
9046
  if (firstToken === null)
8964
9047
  continue;
8965
9048
  const head = firstToken.token;
8966
9049
  if (head === "cd") {
8967
- effectiveCwd = nextCwdAfterCd(effectiveCwd, firstStage, firstToken.end);
9050
+ effectiveCwd = nextCwdAfterCd(effectiveCwd, firstStage, firstToken.end, platform);
8968
9051
  continue;
8969
9052
  }
8970
9053
  if (head !== "grep" && head !== "rg")
@@ -8972,20 +9055,23 @@ function shouldSuppressGrepSearchHint(command, projectRoot) {
8972
9055
  sawCodeSearchStatement = true;
8973
9056
  if (effectiveCwd === null)
8974
9057
  continue;
8975
- if (!isDirInsideProject(resolvedRoot, effectiveCwd))
9058
+ if (!isDirInsideProject(resolvedRoot, effectiveCwd, platform))
8976
9059
  continue;
8977
- const operands = collectPathOperands(firstStage, firstToken.end);
9060
+ const operands = collectPathOperands(firstStage, firstToken.end, platform);
8978
9061
  if (operands.length === 0)
8979
9062
  return false;
8980
9063
  let sawInProjectOperand = false;
8981
9064
  for (const operand of operands) {
8982
9065
  if (isDynamicPathOperand(operand))
8983
9066
  continue;
8984
- const resolvedOperand = resolvePathOperand(effectiveCwd, operand);
8985
- if (!isPathInsideProject(resolvedRoot, effectiveCwd, operand))
9067
+ const resolvedOperand = resolvePathOperand(effectiveCwd, operand, platform);
9068
+ if (!isPathInsideProject(resolvedRoot, effectiveCwd, operand, platform))
9069
+ continue;
9070
+ const suppress = shouldSuppressResolvedPath(resolvedOperand);
9071
+ if (suppress === undefined)
8986
9072
  continue;
8987
9073
  sawInProjectOperand = true;
8988
- if (shouldSuppressResolvedPath(resolvedOperand))
9074
+ if (suppress)
8989
9075
  return true;
8990
9076
  }
8991
9077
  if (sawInProjectOperand)
@@ -8993,19 +9079,19 @@ function shouldSuppressGrepSearchHint(command, projectRoot) {
8993
9079
  }
8994
9080
  return sawCodeSearchStatement;
8995
9081
  }
8996
- function allSearchPathOperandsAreDynamic(statements) {
9082
+ function allSearchPathOperandsAreDynamic(statements, platform) {
8997
9083
  let sawDynamicOnlySearch = false;
8998
9084
  for (const statement of statements) {
8999
- const firstStage = firstPipelineStage(statement);
9085
+ const firstStage = firstPipelineStage(statement, platform);
9000
9086
  if (firstStage === null)
9001
9087
  continue;
9002
- const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0));
9088
+ const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0), platform);
9003
9089
  if (firstToken === null)
9004
9090
  continue;
9005
9091
  const head = firstToken.token;
9006
9092
  if (head !== "grep" && head !== "rg")
9007
9093
  continue;
9008
- const operands = collectPathOperands(firstStage, firstToken.end);
9094
+ const operands = collectPathOperands(firstStage, firstToken.end, platform);
9009
9095
  if (operands.length === 0)
9010
9096
  return false;
9011
9097
  if (operands.some((operand) => !isDynamicPathOperand(operand)))
@@ -9014,11 +9100,12 @@ function allSearchPathOperandsAreDynamic(statements) {
9014
9100
  }
9015
9101
  return sawDynamicOnlySearch;
9016
9102
  }
9017
- function nextCwdAfterCd(currentCwd, firstStage, afterCd) {
9103
+ function nextCwdAfterCd(currentCwd, firstStage, afterCd, platform) {
9104
+ const paths = platform === "win32" ? path.win32 : path.posix;
9018
9105
  let index = skipSpaces(firstStage, afterCd);
9019
9106
  let target = null;
9020
9107
  while (index < firstStage.length) {
9021
- const tokenResult = readShellToken(firstStage, index);
9108
+ const tokenResult = readShellToken(firstStage, index, platform);
9022
9109
  if (tokenResult === null)
9023
9110
  break;
9024
9111
  const { token, end } = tokenResult;
@@ -9033,28 +9120,29 @@ function nextCwdAfterCd(currentCwd, firstStage, afterCd) {
9033
9120
  break;
9034
9121
  }
9035
9122
  if (target === null)
9036
- return path.resolve(os.homedir());
9123
+ return paths.resolve(os.homedir());
9037
9124
  if (target.includes("$") || target.includes("`"))
9038
9125
  return null;
9039
- const expanded = expandTilde(target);
9040
- if (path.isAbsolute(expanded))
9041
- return path.resolve(expanded);
9126
+ const expanded = expandTilde(target, platform);
9127
+ if (paths.isAbsolute(expanded))
9128
+ return paths.resolve(expanded);
9042
9129
  if (currentCwd === null)
9043
9130
  return null;
9044
- return path.resolve(currentCwd, expanded);
9131
+ return paths.resolve(currentCwd, expanded);
9045
9132
  }
9046
- function isDirInsideProject(resolvedRoot, dir) {
9047
- const rel = path.relative(resolvedRoot, path.resolve(dir));
9048
- return !relativePathEscapesRoot(rel);
9133
+ function isDirInsideProject(resolvedRoot, dir, platform) {
9134
+ const paths = platform === "win32" ? path.win32 : path.posix;
9135
+ const rel = paths.relative(resolvedRoot, paths.resolve(dir));
9136
+ return !relativePathEscapesRoot(rel, platform);
9049
9137
  }
9050
- function collectPathOperands(firstStage, startAfterCommand) {
9138
+ function collectPathOperands(firstStage, startAfterCommand, platform) {
9051
9139
  const operands = [];
9052
9140
  let index = skipSpaces(firstStage, startAfterCommand);
9053
9141
  let sawPattern = false;
9054
9142
  let optionsEnded = false;
9055
9143
  let optionValue;
9056
9144
  while (index < firstStage.length) {
9057
- const tokenResult = readShellToken(firstStage, index);
9145
+ const tokenResult = readShellToken(firstStage, index, platform);
9058
9146
  if (tokenResult === null)
9059
9147
  break;
9060
9148
  const { token, end } = tokenResult;
@@ -9113,22 +9201,25 @@ function collectPathOperands(firstStage, startAfterCommand) {
9113
9201
  function isDynamicPathOperand(token) {
9114
9202
  return token.startsWith("~") || token.includes("$") || token.includes("`");
9115
9203
  }
9116
- function expandTilde(target) {
9204
+ function expandTilde(target, platform) {
9117
9205
  if (!target.startsWith("~"))
9118
9206
  return target;
9119
9207
  if (target === "~" || target.startsWith("~/")) {
9120
- return path.join(os.homedir(), target.slice(1));
9208
+ const paths = platform === "win32" ? path.win32 : path.posix;
9209
+ return paths.join(os.homedir(), target.slice(1));
9121
9210
  }
9122
9211
  return target;
9123
9212
  }
9124
- function resolvePathOperand(projectRoot, operand) {
9125
- const expanded = expandTilde(operand);
9126
- return path.isAbsolute(expanded) ? path.resolve(expanded) : path.resolve(projectRoot, expanded);
9213
+ function resolvePathOperand(projectRoot, operand, platform) {
9214
+ const paths = platform === "win32" ? path.win32 : path.posix;
9215
+ const expanded = expandTilde(operand, platform);
9216
+ return paths.isAbsolute(expanded) ? paths.resolve(expanded) : paths.resolve(projectRoot, expanded);
9127
9217
  }
9128
- function isPathInsideProject(resolvedRoot, baseCwd, operand) {
9129
- const resolved = resolvePathOperand(baseCwd, operand);
9130
- const rel = path.relative(resolvedRoot, resolved);
9131
- return !relativePathEscapesRoot(rel);
9218
+ function isPathInsideProject(resolvedRoot, baseCwd, operand, platform) {
9219
+ const paths = platform === "win32" ? path.win32 : path.posix;
9220
+ const resolved = resolvePathOperand(baseCwd, operand, platform);
9221
+ const rel = paths.relative(resolvedRoot, resolved);
9222
+ return !relativePathEscapesRoot(rel, platform);
9132
9223
  }
9133
9224
  function shouldSuppressResolvedPath(resolved) {
9134
9225
  try {
@@ -9136,12 +9227,12 @@ function shouldSuppressResolvedPath(resolved) {
9136
9227
  if (stats.isFile())
9137
9228
  return true;
9138
9229
  const ageMs = Date.now() - stats.mtimeMs;
9139
- return ageMs >= 0 && ageMs < GREP_SEARCH_FRESHNESS_WINDOW_MS;
9230
+ return ageMs > -MTIME_CLOCK_SLACK_MS && ageMs < GREP_SEARCH_FRESHNESS_WINDOW_MS;
9140
9231
  } catch {
9141
- return false;
9232
+ return;
9142
9233
  }
9143
9234
  }
9144
- function splitTopLevelStatements(command) {
9235
+ function splitTopLevelStatements(command, platform = process.platform) {
9145
9236
  const statements = [];
9146
9237
  let start = 0;
9147
9238
  let quote = "none";
@@ -9160,7 +9251,7 @@ function splitTopLevelStatements(command) {
9160
9251
  continue;
9161
9252
  }
9162
9253
  if (quote === "double") {
9163
- if (ch === "\\")
9254
+ if (ch === "\\" && backslashEscapesNext(command[index + 1], quote, platform))
9164
9255
  escaped = true;
9165
9256
  else if (ch === '"')
9166
9257
  quote = "none";
@@ -9171,7 +9262,7 @@ function splitTopLevelStatements(command) {
9171
9262
  inBacktick = false;
9172
9263
  continue;
9173
9264
  }
9174
- if (ch === "\\") {
9265
+ if (ch === "\\" && backslashEscapesNext(command[index + 1], quote, platform)) {
9175
9266
  escaped = true;
9176
9267
  continue;
9177
9268
  }
@@ -9214,7 +9305,7 @@ function splitTopLevelStatements(command) {
9214
9305
  statements.push(command.slice(start));
9215
9306
  return statements;
9216
9307
  }
9217
- function firstPipelineStage(command) {
9308
+ function firstPipelineStage(command, platform = process.platform) {
9218
9309
  let quote = "none";
9219
9310
  let firstPipeIndex;
9220
9311
  for (let index = 0;index < command.length; index++) {
@@ -9227,7 +9318,7 @@ function firstPipelineStage(command) {
9227
9318
  if (quote === "double") {
9228
9319
  if (ch === '"') {
9229
9320
  quote = "none";
9230
- } else if (ch === "\\") {
9321
+ } else if (ch === "\\" && backslashEscapesNext(command[index + 1], quote, platform)) {
9231
9322
  index++;
9232
9323
  } else if (ch === "`") {
9233
9324
  return null;
@@ -9238,7 +9329,7 @@ function firstPipelineStage(command) {
9238
9329
  quote = "single";
9239
9330
  } else if (ch === '"') {
9240
9331
  quote = "double";
9241
- } else if (ch === "\\") {
9332
+ } else if (ch === "\\" && backslashEscapesNext(command[index + 1], quote, platform)) {
9242
9333
  index++;
9243
9334
  } else if (ch === "`") {
9244
9335
  return null;
@@ -9254,7 +9345,7 @@ function firstPipelineStage(command) {
9254
9345
  return null;
9255
9346
  return command.slice(0, firstPipeIndex ?? command.length).trim();
9256
9347
  }
9257
- function readShellToken(command, start) {
9348
+ function readShellToken(command, start, platform = process.platform) {
9258
9349
  let quote = "none";
9259
9350
  let token = "";
9260
9351
  let index = start;
@@ -9271,9 +9362,11 @@ function readShellToken(command, start) {
9271
9362
  if (quote === "double") {
9272
9363
  if (ch === '"') {
9273
9364
  quote = "none";
9274
- } else if (ch === "\\") {
9365
+ } else if (ch === "\\" && backslashEscapesNext(command[index + 1], quote, platform)) {
9275
9366
  index++;
9276
- token += command[index] ?? "\\";
9367
+ if (command[index] !== `
9368
+ `)
9369
+ token += command[index];
9277
9370
  } else if (ch === "`") {
9278
9371
  return null;
9279
9372
  } else {
@@ -9289,7 +9382,7 @@ function readShellToken(command, start) {
9289
9382
  quote = "single";
9290
9383
  } else if (ch === '"') {
9291
9384
  quote = "double";
9292
- } else if (ch === "\\") {
9385
+ } else if (ch === "\\" && backslashEscapesNext(command[index + 1], quote, platform)) {
9293
9386
  index++;
9294
9387
  token += command[index] ?? "\\";
9295
9388
  } else if (ch === "`") {
@@ -9302,6 +9395,11 @@ function readShellToken(command, start) {
9302
9395
  return null;
9303
9396
  return { token, end: index };
9304
9397
  }
9398
+ function backslashEscapesNext(next, quote, platform) {
9399
+ if (quote === "double")
9400
+ return next !== undefined && '$`"\\\n'.includes(next);
9401
+ return platform !== "win32";
9402
+ }
9305
9403
  function isTokenBoundary(ch) {
9306
9404
  return ch === "|" || ch === ";" || ch === "&" || ch === "<" || ch === ">";
9307
9405
  }
@@ -9313,7 +9411,7 @@ function skipSpaces(input, start) {
9313
9411
  }
9314
9412
  // ../aft-bridge/dist/bash-host-fallback.js
9315
9413
  import { existsSync } from "node:fs";
9316
- import { join as join4 } from "node:path";
9414
+ import { join as join3 } from "node:path";
9317
9415
 
9318
9416
  // ../aft-bridge/dist/child-process.js
9319
9417
  import { execFile as nodeExecFile, execFileSync as nodeExecFileSync, execSync as nodeExecSync, spawn as nodeSpawn, spawnSync as nodeSpawnSync } from "node:child_process";
@@ -9321,7 +9419,7 @@ import { execFile as nodeExecFile, execFileSync as nodeExecFileSync, execSync as
9321
9419
  // ../aft-bridge/dist/test-child-environment.js
9322
9420
  import { mkdirSync, realpathSync } from "node:fs";
9323
9421
  import { homedir as homedir2, tmpdir } from "node:os";
9324
- import { dirname, isAbsolute as isAbsolute2, join as join2, relative as relative2, resolve as resolve2 } from "node:path";
9422
+ import { dirname, isAbsolute, join, relative, resolve } from "node:path";
9325
9423
  var DIRECTORIES = [
9326
9424
  "HOME",
9327
9425
  "USERPROFILE",
@@ -9341,8 +9439,8 @@ function toolchainHomes(inherited) {
9341
9439
  if (!global[TOOLCHAINS]) {
9342
9440
  const home = process.platform === "win32" ? inherited.USERPROFILE || inherited.HOME || homedir2() : inherited.HOME || homedir2();
9343
9441
  global[TOOLCHAINS] = {
9344
- RUSTUP_HOME: inherited.RUSTUP_HOME || join2(home, ".rustup"),
9345
- CARGO_HOME: inherited.CARGO_HOME || join2(home, ".cargo")
9442
+ RUSTUP_HOME: inherited.RUSTUP_HOME || join(home, ".rustup"),
9443
+ CARGO_HOME: inherited.CARGO_HOME || join(home, ".cargo")
9346
9444
  };
9347
9445
  }
9348
9446
  return global[TOOLCHAINS];
@@ -9369,31 +9467,31 @@ function isolatedAftEnvironment(root, inherited = process.env) {
9369
9467
  "aft-cache"
9370
9468
  ];
9371
9469
  for (const [index, key] of DIRECTORIES.entries()) {
9372
- env[key] = join2(root, names[index]);
9470
+ env[key] = join(root, names[index]);
9373
9471
  mkdirSync(env[key], { recursive: true });
9374
9472
  }
9375
9473
  delete env.AFT_ALLOW_PRODUCTION_MIGRATION;
9376
- createdRoots().add(resolve2(root));
9474
+ createdRoots().add(resolve(root));
9377
9475
  return env;
9378
9476
  }
9379
9477
  function canonical(path) {
9380
- let ancestor = resolve2(path);
9478
+ let ancestor = resolve(path);
9381
9479
  const tail = [];
9382
9480
  while (true) {
9383
9481
  try {
9384
- return join2(realpathSync(ancestor), ...tail);
9482
+ return join(realpathSync(ancestor), ...tail);
9385
9483
  } catch {
9386
9484
  const parent = dirname(ancestor);
9387
9485
  if (parent === ancestor)
9388
- return resolve2(path);
9389
- tail.unshift(relative2(parent, ancestor));
9486
+ return resolve(path);
9487
+ tail.unshift(relative(parent, ancestor));
9390
9488
  ancestor = parent;
9391
9489
  }
9392
9490
  }
9393
9491
  }
9394
9492
  function within(path, root) {
9395
- const tail = relative2(canonical(root), canonical(path));
9396
- return tail === "" || !tail.startsWith("..") && !isAbsolute2(tail);
9493
+ const tail = relative(canonical(root), canonical(path));
9494
+ return tail === "" || !tail.startsWith("..") && !isAbsolute(tail);
9397
9495
  }
9398
9496
  function testChildEnvironment(env) {
9399
9497
  const root = process.env.AFT_TEST_ISOLATION_ROOT;
@@ -9469,7 +9567,7 @@ function withPathPrepended(env, dir, platform = process.platform) {
9469
9567
 
9470
9568
  // ../aft-bridge/dist/storage-paths.js
9471
9569
  import { homedir as homedir3, tmpdir as tmpdir2 } from "node:os";
9472
- import { join as join3, resolve as resolve3 } from "node:path";
9570
+ import { join as join2, resolve as resolve2 } from "node:path";
9473
9571
  function environmentValue(context, name) {
9474
9572
  const value = (context.lookup ?? ((key) => process.env[key]))(name);
9475
9573
  return value !== undefined && value.length > 0 ? value : undefined;
@@ -9491,21 +9589,21 @@ function resolveDataHome(context = {}) {
9491
9589
  return localAppData;
9492
9590
  const userProfile = environmentValue(context, "USERPROFILE");
9493
9591
  if (userProfile)
9494
- return join3(userProfile, "AppData", "Local");
9592
+ return join2(userProfile, "AppData", "Local");
9495
9593
  }
9496
9594
  const home = environmentValue(context, "HOME");
9497
9595
  if (home)
9498
- return join3(home, ".local", "share");
9499
- return join3(".local", "share");
9596
+ return join2(home, ".local", "share");
9597
+ return join2(".local", "share");
9500
9598
  }
9501
9599
  function resolveStoragePath(raw, context = {}) {
9502
9600
  let expanded = raw;
9503
9601
  if (raw === "~") {
9504
9602
  expanded = homeDir(context);
9505
9603
  } else if (raw.startsWith("~/") || raw.startsWith("~\\")) {
9506
- expanded = join3(homeDir(context), raw.slice(2));
9604
+ expanded = join2(homeDir(context), raw.slice(2));
9507
9605
  }
9508
- return resolve3(context.currentDirectory ?? process.cwd(), expanded);
9606
+ return resolve2(context.currentDirectory ?? process.cwd(), expanded);
9509
9607
  }
9510
9608
  function resolveCortexKitStorageRoot(context = {}) {
9511
9609
  const override = environmentValue(context, "AFT_STORAGE_DIR");
@@ -9513,8 +9611,8 @@ function resolveCortexKitStorageRoot(context = {}) {
9513
9611
  return resolveStoragePath(override, context);
9514
9612
  const legacyCache = environmentValue(context, "AFT_CACHE_DIR");
9515
9613
  if (legacyCache)
9516
- return join3(resolveStoragePath(legacyCache, context), "aft");
9517
- return resolveStoragePath(join3(resolveDataHome(context), "cortexkit", "aft"), context);
9614
+ return join2(resolveStoragePath(legacyCache, context), "aft");
9615
+ return resolveStoragePath(join2(resolveDataHome(context), "cortexkit", "aft"), context);
9518
9616
  }
9519
9617
  function resolveAftStorageRoot(configuredRoot, context = {}) {
9520
9618
  if (environmentValue(context, "AFT_STORAGE_DIR")) {
@@ -9525,14 +9623,14 @@ function resolveAftStorageRoot(configuredRoot, context = {}) {
9525
9623
  return resolveCortexKitStorageRoot(context);
9526
9624
  }
9527
9625
  function resolveAftLogPath(filename, configuredRoot, context = {}) {
9528
- return join3(resolveAftStorageRoot(configuredRoot, context), "logs", filename);
9626
+ return join2(resolveAftStorageRoot(configuredRoot, context), "logs", filename);
9529
9627
  }
9530
9628
  function isTestEnvironment(context = {}) {
9531
9629
  return environmentValue(context, "BUN_TEST") === "1" || environmentValue(context, "NODE_ENV") === "test";
9532
9630
  }
9533
9631
  function resolvePluginLogPath(context = {}) {
9534
9632
  if (isTestEnvironment(context)) {
9535
- return join3(environmentValue(context, "TMPDIR") ?? tmpdir2(), `aft-plugin-tests-${process.pid}`, "logs", "aft-plugin-test.log");
9633
+ return join2(environmentValue(context, "TMPDIR") ?? tmpdir2(), `aft-plugin-tests-${process.pid}`, "logs", "aft-plugin-test.log");
9536
9634
  }
9537
9635
  return resolveAftLogPath("aft-plugin.log", undefined, context);
9538
9636
  }
@@ -9567,8 +9665,8 @@ function hostFallbackEnvWithShims(env, platform) {
9567
9665
  const pathKey = pathKeyForPlatform(normalized, platform);
9568
9666
  const inherited = pathKey === undefined ? undefined : normalized[pathKey];
9569
9667
  const storageRoot = normalized.AFT_STORAGE_DIR ? resolveStoragePath(normalized.AFT_STORAGE_DIR) : resolveCortexKitStorageRoot();
9570
- const shimsDir = join4(storageRoot, "shims");
9571
- if (!existsSync(join4(shimsDir, platform === "win32" ? "gh.cmd" : "gh")))
9668
+ const shimsDir = join3(storageRoot, "shims");
9669
+ if (!existsSync(join3(shimsDir, platform === "win32" ? "gh.cmd" : "gh")))
9572
9670
  return normalized;
9573
9671
  const separator = platform === "win32" ? ";" : ":";
9574
9672
  const entries = (inherited ?? "").split(separator).filter((entry) => entry.length > 0);
@@ -10344,7 +10442,7 @@ async function cachedFileSha256(path) {
10344
10442
  }
10345
10443
  // ../aft-bridge/dist/bridge.js
10346
10444
  import { homedir as homedir4 } from "node:os";
10347
- import { join as join5 } from "node:path";
10445
+ import { join as join4 } from "node:path";
10348
10446
  import { StringDecoder } from "node:string_decoder";
10349
10447
 
10350
10448
  // ../aft-bridge/dist/command-timeouts.js
@@ -10482,6 +10580,7 @@ function compareSemver(a, b) {
10482
10580
  }
10483
10581
  var SYSTEM_CLOCK = {
10484
10582
  now: () => Date.now(),
10583
+ awakeNow: () => performance.now(),
10485
10584
  setTimeout: (callback, ms) => setTimeout(callback, ms),
10486
10585
  clearTimeout: (timer) => clearTimeout(timer)
10487
10586
  };
@@ -10598,6 +10697,7 @@ class BinaryBridge {
10598
10697
  hangWindowMinMs;
10599
10698
  hangProbeTimeoutMs;
10600
10699
  clock;
10700
+ waitClock;
10601
10701
  lateShellReplyGraceMs;
10602
10702
  maxRestarts;
10603
10703
  configured = false;
@@ -10634,6 +10734,7 @@ class BinaryBridge {
10634
10734
  this.hangWindowMinMs = options?.hangWindowMinMs ?? DEFAULT_MIN_HANG_WINDOW_MS;
10635
10735
  this.hangProbeTimeoutMs = options?.hangProbeTimeoutMs ?? DEFAULT_HANG_PROBE_TIMEOUT_MS;
10636
10736
  this.clock = options?.clock ?? SYSTEM_CLOCK;
10737
+ this.waitClock = new WaitClock(() => this.clock.now(), () => this.clock.awakeNow?.() ?? this.clock.now());
10637
10738
  this.lateShellReplyGraceMs = options?.lateShellReplyGraceMs ?? DEFAULT_LATE_SHELL_REPLY_GRACE_MS;
10638
10739
  this.maxRestarts = options?.maxRestarts ?? 3;
10639
10740
  this.errorPrefix = options?.errorPrefix ?? "[aft-bridge]";
@@ -11000,11 +11101,17 @@ class BinaryBridge {
11000
11101
  const keepBridgeOnTimeout = passive || command === "bash_drain_completions" || options?.keepBridgeOnTimeout === true;
11001
11102
  const child = this.process;
11002
11103
  const response = await new Promise((resolve, reject) => {
11003
- const timer = this.clock.setTimeout(() => {
11104
+ const deadline = new RequestDeadline(this.waitClock, effectiveTimeoutMs);
11105
+ const expire = () => {
11004
11106
  const entry = this.pending.get(id);
11005
11107
  if (!entry)
11006
11108
  return;
11007
- if (keepBridgeOnTimeout && this.holdForLateShellReply(id, entry, effectiveTimeoutMs, requestSessionId)) {
11109
+ const remaining = deadline.remaining();
11110
+ if (remaining > 0) {
11111
+ entry.timer = this.clock.setTimeout(expire, Math.min(remaining, DEADLINE_POLL_MS));
11112
+ return;
11113
+ }
11114
+ if (keepBridgeOnTimeout && !deadline.resumed && this.holdForLateShellReply(id, entry, effectiveTimeoutMs, requestSessionId)) {
11008
11115
  return;
11009
11116
  }
11010
11117
  this.pending.delete(id);
@@ -11017,11 +11124,12 @@ class BinaryBridge {
11017
11124
  this.warnVia(timeoutMsg);
11018
11125
  }
11019
11126
  if (keepBridgeOnTimeout) {
11020
- entry.reject(new BridgeTransportTimeoutError(command, effectiveTimeoutMs, `${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`));
11127
+ entry.reject(new BridgeTransportTimeoutError(command, effectiveTimeoutMs, `${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`, deadline.resumed && SHELL_TASK_COMMANDS.has(command) ? { kind: "unknown" } : undefined));
11021
11128
  return;
11022
11129
  }
11023
11130
  entry.reject(new Error(`${this.errorPrefix} request "${command}" timed out after ${effectiveTimeoutMs}ms (bridge busy/under load); bridge kept warm — retry. A timed-out mutation may still complete; inspect before repeating it.`));
11024
- }, effectiveTimeoutMs);
11131
+ };
11132
+ const timer = this.clock.setTimeout(expire, Math.min(effectiveTimeoutMs, DEADLINE_POLL_MS));
11025
11133
  const entry = {
11026
11134
  resolve,
11027
11135
  reject,
@@ -11252,11 +11360,11 @@ class BinaryBridge {
11252
11360
  })();
11253
11361
  const useFastembedBackend = semanticBackend === undefined || semanticBackend === "fastembed" || semanticBackend === "";
11254
11362
  const ortDir = typeof this.configOverrides._ort_dylib_dir === "string" && useFastembedBackend ? this.configOverrides._ort_dylib_dir : null;
11255
- const ortLibraryPath = ortDir == null ? null : join5(ortDir, this.platform === "win32" ? "onnxruntime.dll" : this.platform === "darwin" ? "libonnxruntime.dylib" : "libonnxruntime.so");
11363
+ const ortLibraryPath = ortDir == null ? null : join4(ortDir, this.platform === "win32" ? "onnxruntime.dll" : this.platform === "darwin" ? "libonnxruntime.dylib" : "libonnxruntime.so");
11256
11364
  const env = { ...process.env };
11257
11365
  this.logVia(`bridge.spawnProcess: useFastembedBackend=${useFastembedBackend}, ` + `parentORT=${process.env.ORT_DYLIB_PATH ?? "(unset)"}, ` + `ortLibraryPath=${ortLibraryPath ?? "(none)"}`);
11258
11366
  if (useFastembedBackend) {
11259
- env.FASTEMBED_CACHE_DIR = process.env.FASTEMBED_CACHE_DIR || (typeof this.configOverrides.storage_dir === "string" ? join5(this.configOverrides.storage_dir, "semantic", "models") : join5(homedir4() || "", ".cache", "fastembed"));
11367
+ env.FASTEMBED_CACHE_DIR = process.env.FASTEMBED_CACHE_DIR || (typeof this.configOverrides.storage_dir === "string" ? join4(this.configOverrides.storage_dir, "semantic", "models") : join4(homedir4() || "", ".cache", "fastembed"));
11260
11368
  if (process.env.ORT_DYLIB_PATH) {
11261
11369
  this.logVia(`ORT_DYLIB_PATH inherited from parent env: ${process.env.ORT_DYLIB_PATH}`);
11262
11370
  } else if (ortLibraryPath) {
@@ -11577,14 +11685,21 @@ class BinaryBridge {
11577
11685
  };
11578
11686
  entry.resolve = (response) => settle(shellOutcomeFromLateReply(response));
11579
11687
  this.clock.clearTimeout(entry.timer);
11580
- entry.timer = this.clock.setTimeout(() => {
11688
+ const deadline = new RequestDeadline(this.waitClock, graceMs, false);
11689
+ const expire = () => {
11581
11690
  if (this.pending.get(id) !== entry)
11582
11691
  return;
11692
+ const remaining = deadline.remaining();
11693
+ if (remaining > 0) {
11694
+ entry.timer = this.clock.setTimeout(expire, Math.min(remaining, DEADLINE_POLL_MS));
11695
+ return;
11696
+ }
11583
11697
  this.pending.delete(id);
11584
11698
  entry.onSettled?.();
11585
11699
  this.warnVia(`Request "${entry.command}" (id=${id}) got no reply within ${graceMs}ms after its deadline`);
11586
11700
  settle({ kind: "unknown" });
11587
- }, graceMs);
11701
+ };
11702
+ entry.timer = this.clock.setTimeout(expire, Math.min(graceMs, DEADLINE_POLL_MS));
11588
11703
  return true;
11589
11704
  }
11590
11705
  accountForBashTaskResponse(command, response) {
@@ -11832,34 +11947,34 @@ class BinaryBridge {
11832
11947
  }
11833
11948
  // ../aft-bridge/dist/cache-paths.js
11834
11949
  import { homedir as homedir5 } from "node:os";
11835
- import { join as join6 } from "node:path";
11950
+ import { join as join5 } from "node:path";
11836
11951
  function homeDir2(env) {
11837
11952
  return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir5();
11838
11953
  }
11839
11954
  function getOpenCodeCacheRoot(env = process.env, home = homedir5()) {
11840
- return join6(env.XDG_CACHE_HOME || join6(home, ".cache"), "opencode");
11955
+ return join5(env.XDG_CACHE_HOME || join5(home, ".cache"), "opencode");
11841
11956
  }
11842
11957
  function getOpenCodeConfigRoot(env = process.env, home = homedir5()) {
11843
- return join6(env.XDG_CONFIG_HOME || join6(home, ".config"), "opencode");
11958
+ return join5(env.XDG_CONFIG_HOME || join5(home, ".config"), "opencode");
11844
11959
  }
11845
11960
  function getAftCacheRoot(env = process.env) {
11846
11961
  if (env.AFT_CACHE_DIR)
11847
11962
  return env.AFT_CACHE_DIR;
11848
11963
  if (process.platform === "win32") {
11849
- const base = env.LOCALAPPDATA || env.APPDATA || join6(homeDir2(env), "AppData", "Local");
11850
- return join6(base, "aft");
11964
+ const base = env.LOCALAPPDATA || env.APPDATA || join5(homeDir2(env), "AppData", "Local");
11965
+ return join5(base, "aft");
11851
11966
  }
11852
- const base = env.XDG_CACHE_HOME || join6(homeDir2(env), ".cache");
11853
- return join6(base, "aft");
11967
+ const base = env.XDG_CACHE_HOME || join5(homeDir2(env), ".cache");
11968
+ return join5(base, "aft");
11854
11969
  }
11855
11970
  function getAftBinaryCacheDir(env = process.env) {
11856
- return join6(getAftCacheRoot(env), "bin");
11971
+ return join5(getAftCacheRoot(env), "bin");
11857
11972
  }
11858
11973
  function getAftLspPackagesDir(env = process.env) {
11859
- return join6(getAftCacheRoot(env), "lsp-packages");
11974
+ return join5(getAftCacheRoot(env), "lsp-packages");
11860
11975
  }
11861
11976
  function getAftLspBinariesDir(env = process.env) {
11862
- return join6(getAftCacheRoot(env), "lsp-binaries");
11977
+ return join5(getAftCacheRoot(env), "lsp-binaries");
11863
11978
  }
11864
11979
  // ../aft-bridge/dist/coerce.js
11865
11980
  function coerceStringArray(value) {
@@ -12004,7 +12119,7 @@ function isFindReplaceOnlyEdit(args) {
12004
12119
  }
12005
12120
  // ../aft-bridge/dist/config-error.js
12006
12121
  import { homedir as homedir6 } from "node:os";
12007
- import { isAbsolute as isAbsolute3, join as join7 } from "node:path";
12122
+ import { isAbsolute as isAbsolute2, join as join6 } from "node:path";
12008
12123
  var CONFIG_ERROR_RESTART_NOTE = "AFT reads its config only at startup, so restart the host after fixing it.";
12009
12124
  function formatConfigErrorMessage(detail) {
12010
12125
  const trimmed = detail.trim();
@@ -12014,10 +12129,10 @@ function formatConfigErrorMessage(detail) {
12014
12129
  function resolveSubcConnectionFilePath(raw, home = homedir6()) {
12015
12130
  const trimmed = raw.trim();
12016
12131
  if (trimmed.startsWith("~"))
12017
- return join7(home, trimmed.slice(1).replace(/^[/\\]/, ""));
12018
- if (isAbsolute3(trimmed))
12132
+ return join6(home, trimmed.slice(1).replace(/^[/\\]/, ""));
12133
+ if (isAbsolute2(trimmed))
12019
12134
  return trimmed;
12020
- return join7(home, trimmed);
12135
+ return join6(home, trimmed);
12021
12136
  }
12022
12137
  function formatSubcConnectionMissingMessage(raw, resolved) {
12023
12138
  return `subc.connection_file is set to "${raw.trim()}" (resolved: ${resolved}) but no subc ` + `connection file exists there. Start the Subconscious daemon, correct the path, ` + `or remove subc.connection_file from your user config to use the standalone bridge.`;
@@ -12087,7 +12202,7 @@ function stripHarnessSpecificConfigKeys(value, keys) {
12087
12202
  }
12088
12203
  // ../aft-bridge/dist/config-tiers.js
12089
12204
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
12090
- import { resolve as resolve4 } from "node:path";
12205
+ import { resolve as resolve3 } from "node:path";
12091
12206
  function readConfigTiers(opts) {
12092
12207
  const tiers = [];
12093
12208
  try {
@@ -12095,7 +12210,7 @@ function readConfigTiers(opts) {
12095
12210
  const doc = readFileSync2(opts.userConfigPath, "utf-8");
12096
12211
  tiers.push({
12097
12212
  tier: "user",
12098
- source: resolve4(opts.userConfigPath),
12213
+ source: resolve3(opts.userConfigPath),
12099
12214
  doc
12100
12215
  });
12101
12216
  }
@@ -12105,7 +12220,7 @@ function readConfigTiers(opts) {
12105
12220
  const doc = readFileSync2(opts.projectConfigPath, "utf-8");
12106
12221
  tiers.push({
12107
12222
  tier: "project",
12108
- source: resolve4(opts.projectConfigPath),
12223
+ source: resolve3(opts.projectConfigPath),
12109
12224
  doc
12110
12225
  });
12111
12226
  }
@@ -12121,7 +12236,7 @@ function formatDroppedKeyWarnings(dropped) {
12121
12236
  // ../aft-bridge/dist/config-watch.js
12122
12237
  import { createHash as createHash2 } from "node:crypto";
12123
12238
  import { closeSync as closeSync2, fstatSync, openSync as openSync2, readFileSync as readFileSync3, readSync as readSync2, realpathSync as realpathSync2, statSync as statSync3, watch } from "node:fs";
12124
- import { basename, dirname as dirname2, resolve as resolve5 } from "node:path";
12239
+ import { basename, dirname as dirname2, resolve as resolve4 } from "node:path";
12125
12240
  var CONFIG_WATCH_DEBOUNCE_MS = 150;
12126
12241
  var CONFIG_LIVE_KEEP_NOTE = "AFT keeps using the last valid configuration until the file is fixed.";
12127
12242
  function pathKey(name) {
@@ -12176,6 +12291,7 @@ function aftLiveConfigKeys(resolveBash) {
12176
12291
  pathKey("revision_reads"),
12177
12292
  pathKey("inspect.diagnostics_timeout_ms"),
12178
12293
  pathKey("lsp.idle_minutes"),
12294
+ pathKey("lsp.max_servers"),
12179
12295
  ...[
12180
12296
  "diagnostics",
12181
12297
  "todos",
@@ -12288,7 +12404,7 @@ function canonicalDirectory(dir) {
12288
12404
  try {
12289
12405
  return realpathSync2(dir);
12290
12406
  } catch {
12291
- return resolve5(dir);
12407
+ return resolve4(dir);
12292
12408
  }
12293
12409
  }
12294
12410
  function watchAftConfigFiles(options) {
@@ -12308,6 +12424,7 @@ function watchAftConfigFiles(options) {
12308
12424
  const fallbackSeen = new Map;
12309
12425
  const watchImpl = options.watchImpl ?? watch;
12310
12426
  let rejectedRetries = 0;
12427
+ let recheckAfterArming = false;
12311
12428
  const check = () => {
12312
12429
  if (retryTimer)
12313
12430
  clearTimeout(retryTimer);
@@ -12316,7 +12433,8 @@ function watchAftConfigFiles(options) {
12316
12433
  firstPendingAt = null;
12317
12434
  if (stopped)
12318
12435
  return;
12319
- revalidate();
12436
+ if (revalidate())
12437
+ recheckAfterArming = true;
12320
12438
  const seen = new Map;
12321
12439
  for (const path of options.paths) {
12322
12440
  const text = readTextOrNull(path);
@@ -12374,7 +12492,7 @@ function watchAftConfigFiles(options) {
12374
12492
  for (const path of options.paths) {
12375
12493
  try {
12376
12494
  const resolved = realpathSync2(path);
12377
- const target = resolved === resolve5(path) ? undefined : resolved;
12495
+ const target = resolved === resolve4(path) ? undefined : resolved;
12378
12496
  if (targets.get(path) !== target) {
12379
12497
  if (target)
12380
12498
  targets.set(path, target);
@@ -12438,12 +12556,16 @@ function watchAftConfigFiles(options) {
12438
12556
  }
12439
12557
  return moved;
12440
12558
  }
12441
- revalidate();
12559
+ recheckAfterArming = revalidate();
12442
12560
  if (options.checkAtStart)
12443
12561
  check();
12444
12562
  const revalidateTimer = setInterval(() => {
12445
- if (!stopped && revalidate())
12563
+ if (stopped)
12564
+ return;
12565
+ const moved = revalidate();
12566
+ if (moved || recheckAfterArming)
12446
12567
  schedule();
12568
+ recheckAfterArming = moved;
12447
12569
  }, CONFIG_WATCH_REVALIDATE_MS);
12448
12570
  revalidateTimer.unref?.();
12449
12571
  return () => {
@@ -12486,6 +12608,10 @@ function aftLiveSecurityKeys(keys) {
12486
12608
  return minutes(next) > minutes(current);
12487
12609
  }
12488
12610
  },
12611
+ {
12612
+ key: pick("lsp.max_servers"),
12613
+ loosens: (current, next) => (typeof next === "number" ? next : 8) > (typeof current === "number" ? current : 8)
12614
+ },
12489
12615
  ...[
12490
12616
  "diagnostics",
12491
12617
  "todos",
@@ -12595,7 +12721,7 @@ function startLiveConfigReload(options) {
12595
12721
  import { createHash as createHash3, randomUUID } from "node:crypto";
12596
12722
  import { chmodSync, closeSync as closeSync3, copyFileSync, createWriteStream, existsSync as existsSync3, mkdirSync as mkdirSync2, openSync as openSync3, readdirSync, readFileSync as readFileSync4, renameSync as renameSync2, rmSync, statSync as statSync4, unlinkSync as unlinkSync2, writeSync } from "node:fs";
12597
12723
  import { hostname } from "node:os";
12598
- import { join as join8 } from "node:path";
12724
+ import { join as join7 } from "node:path";
12599
12725
  import { Readable } from "node:stream";
12600
12726
  import { pipeline } from "node:stream/promises";
12601
12727
 
@@ -12711,7 +12837,7 @@ function getBinaryName() {
12711
12837
  function getCachedBinaryPath(version) {
12712
12838
  if (!version)
12713
12839
  return null;
12714
- const binaryPath = join8(getAftBinaryCacheDir(), version, getBinaryName());
12840
+ const binaryPath = join7(getAftBinaryCacheDir(), version, getBinaryName());
12715
12841
  return existsSync3(binaryPath) ? binaryPath : null;
12716
12842
  }
12717
12843
  async function downloadBinary(version) {
@@ -12728,16 +12854,16 @@ async function downloadBinary(version) {
12728
12854
  return null;
12729
12855
  }
12730
12856
  const tag = rawTag.startsWith("v") ? rawTag : `v${rawTag}`;
12731
- const versionedCacheDir = join8(getAftBinaryCacheDir(), tag);
12857
+ const versionedCacheDir = join7(getAftBinaryCacheDir(), tag);
12732
12858
  const binaryName = getBinaryName();
12733
- const binaryPath = join8(versionedCacheDir, binaryName);
12859
+ const binaryPath = join7(versionedCacheDir, binaryName);
12734
12860
  if (existsSync3(binaryPath) && await isExpectedCachedBinary(binaryPath, tag)) {
12735
12861
  return binaryPath;
12736
12862
  }
12737
12863
  const downloadUrl = `https://github.com/${REPO}/releases/download/${tag}/${assetName}`;
12738
12864
  const checksumUrl = `https://github.com/${REPO}/releases/download/${tag}/checksums.sha256`;
12739
12865
  log(`Downloading AFT binary (${tag}) for ${platformKey}...`);
12740
- const lockPath = join8(versionedCacheDir, ".download.lock");
12866
+ const lockPath = join7(versionedCacheDir, ".download.lock");
12741
12867
  let releaseLock = null;
12742
12868
  let binaryController = null;
12743
12869
  let checksumController = null;
@@ -12963,7 +13089,7 @@ function sweepStaleDownloadTemps(versionedCacheDir, binaryName) {
12963
13089
  if (!entry.isFile() || !entry.name.startsWith(tempPrefix) || !entry.name.endsWith(".tmp")) {
12964
13090
  continue;
12965
13091
  }
12966
- const tempPath = join8(versionedCacheDir, entry.name);
13092
+ const tempPath = join7(versionedCacheDir, entry.name);
12967
13093
  const ageMs = Date.now() - statSync4(tempPath).mtimeMs;
12968
13094
  if (Math.abs(ageMs) > DOWNLOAD_LOCK_STALE_MS)
12969
13095
  unlinkSync2(tempPath);
@@ -13054,7 +13180,7 @@ import { dirname as dirname3 } from "node:path";
13054
13180
 
13055
13181
  // ../aft-bridge/dist/private-storage.js
13056
13182
  import { closeSync as closeSync4, constants, copyFileSync as copyFileSync2, fchmodSync, fstatSync as fstatSync2, lstatSync, mkdirSync as mkdirSync3, openSync as openSync4, readSync as readSync3, writeSync as writeSync2 } from "node:fs";
13057
- import { isAbsolute as isAbsolute4, join as join9, parse, relative as relative3, resolve as resolve6, sep } from "node:path";
13183
+ import { isAbsolute as isAbsolute3, join as join8, parse, relative as relative2, resolve as resolve5, sep } from "node:path";
13058
13184
  var PRIVATE_FILE_MODE = 384;
13059
13185
  var PRIVATE_DIRECTORY_MODE = 448;
13060
13186
  function privateMkdirSync(path, recursive = true) {
@@ -13089,19 +13215,19 @@ function privateCopyFileSync(source, destination) {
13089
13215
  }
13090
13216
  var warned = new Set;
13091
13217
  function openPrivateStorageDir(root, path = root) {
13092
- const base = resolve6(root);
13218
+ const base = resolve5(root);
13093
13219
  if (!root || base === parse(base).root) {
13094
13220
  throw new Error(`refusing filesystem root as private storage: ${base}`);
13095
13221
  }
13096
- const rel = relative3(base, resolve6(path));
13097
- if (rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute4(rel))
13222
+ const rel = relative2(base, resolve5(path));
13223
+ if (rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute3(rel))
13098
13224
  return;
13099
13225
  privateMkdirSync(path);
13100
13226
  if (process.platform === "win32")
13101
13227
  return;
13102
13228
  let current = base;
13103
13229
  for (const component of ["", ...rel.split(sep).filter(Boolean)]) {
13104
- current = join9(current, component);
13230
+ current = join8(current, component);
13105
13231
  let fd;
13106
13232
  try {
13107
13233
  if (lstatSync(current).isSymbolicLink())
@@ -13295,21 +13421,23 @@ async function renameIfPresent(from, to) {
13295
13421
  throw error;
13296
13422
  }
13297
13423
  }
13298
- // ../../node_modules/.bun/@cortexkit+subc-client@0.21.2/node_modules/@cortexkit/subc-client/dist/client.js
13424
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/client.js
13299
13425
  import { promises as fs3 } from "node:fs";
13426
+ import { createHash as createHash4 } from "node:crypto";
13300
13427
  import { debuglog } from "node:util";
13301
13428
 
13302
- // ../../node_modules/.bun/@cortexkit+subc-client@0.21.2/node_modules/@cortexkit/subc-client/dist/auth.js
13429
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/auth.js
13303
13430
  import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
13304
13431
 
13305
- // ../../node_modules/.bun/@cortexkit+subc-client@0.21.2/node_modules/@cortexkit/subc-client/dist/socket.js
13432
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/socket.js
13306
13433
  import net from "node:net";
13307
13434
 
13308
- // ../../node_modules/.bun/@cortexkit+subc-client@0.21.2/node_modules/@cortexkit/subc-client/dist/envelope.js
13435
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/envelope.js
13309
13436
  var PROTOCOL_VERSION = 2;
13310
13437
  var HEADER_LEN = 21;
13311
13438
  var FROZEN_PREFIX_LEN = 5;
13312
13439
  var MAX_FRAME_BODY_LEN = 64 * 1024 * 1024;
13440
+ var MAX_DELIVERED_FRAME_LEN = 4 * 1024 * 1024;
13313
13441
  var FrameType;
13314
13442
  (function(FrameType) {
13315
13443
  FrameType[FrameType["Request"] = 0] = "Request";
@@ -13347,6 +13475,8 @@ var FLAG_PRIORITY_SHIFT = 1;
13347
13475
  var FLAG_LAST = 8;
13348
13476
  var FLAG_ADMISSION_MASK = 48;
13349
13477
  var FLAG_ADMISSION_SHIFT = 4;
13478
+ var DAEMON_ORIGIN_FLAG = 64;
13479
+ var SUBSCRIPTION_FLAG = 128;
13350
13480
  var FLAG_RESERVED_MASK = 0;
13351
13481
  function buildFlags(binary, priority, last, admissionClass = AdmissionClass.Normal) {
13352
13482
  let flags = 0;
@@ -13481,7 +13611,7 @@ function encodeFrame(frame) {
13481
13611
  return output;
13482
13612
  }
13483
13613
 
13484
- // ../../node_modules/.bun/@cortexkit+subc-client@0.21.2/node_modules/@cortexkit/subc-client/dist/socket.js
13614
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/socket.js
13485
13615
  class SocketClosedError extends Error {
13486
13616
  }
13487
13617
 
@@ -13531,14 +13661,12 @@ class SubcSocket {
13531
13661
  sock.on("data", (chunk) => {
13532
13662
  this.chunks.push(chunk);
13533
13663
  this.buffered += chunk.length;
13534
- if (this.waiter) {
13664
+ if (this.waiter && this.waiter.extendOnProgress && this.buffered < this.waiter.need) {
13535
13665
  if (this.waiter.immediate) {
13536
13666
  clearImmediate(this.waiter.immediate);
13537
13667
  this.waiter.immediate = null;
13538
13668
  }
13539
- if (this.waiter.extendOnProgress && this.buffered < this.waiter.need) {
13540
- this.armWaiterTimer(this.waiter);
13541
- }
13669
+ this.armWaiterTimer(this.waiter);
13542
13670
  }
13543
13671
  this.tryServe();
13544
13672
  });
@@ -13555,12 +13683,18 @@ class SubcSocket {
13555
13683
  return this.sock.localPort ?? null;
13556
13684
  }
13557
13685
  static connect(host, port, deadlineMs) {
13686
+ return SubcSocket.connectTo({ host, port }, `${host}:${port}`, deadlineMs);
13687
+ }
13688
+ static connectLocal(path, deadlineMs) {
13689
+ return SubcSocket.connectTo({ path }, path, deadlineMs);
13690
+ }
13691
+ static connectTo(options, endpoint, deadlineMs) {
13558
13692
  return new Promise((resolve, reject) => {
13559
- const sock = net.connect({ host, port });
13693
+ const sock = net.connect(options);
13560
13694
  sock.setNoDelay(true);
13561
13695
  const timer = setTimeout(() => {
13562
13696
  sock.destroy();
13563
- reject(new SocketTimeoutError(`timed out connecting to ${host}:${port}`));
13697
+ reject(new SocketTimeoutError(`timed out connecting to ${endpoint}`));
13564
13698
  }, Math.max(0, deadlineMs - Date.now()));
13565
13699
  sock.once("connect", () => {
13566
13700
  clearTimeout(timer);
@@ -13777,7 +13911,7 @@ class SubcSocket {
13777
13911
  }
13778
13912
  }
13779
13913
 
13780
- // ../../node_modules/.bun/@cortexkit+subc-client@0.21.2/node_modules/@cortexkit/subc-client/dist/auth.js
13914
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/auth.js
13781
13915
  var NONCE_LEN = 32;
13782
13916
  var MAX_AUTH_MESSAGE_LEN = 4096;
13783
13917
  var SERVER_PROOF_DOMAIN = "subc-server-v1";
@@ -13851,7 +13985,7 @@ async function authenticateClient(sock, conn, deadlineMs) {
13851
13985
  await writeMessage(sock, { client_auth: Array.from(clientAuth) }, deadlineMs);
13852
13986
  }
13853
13987
 
13854
- // ../../node_modules/.bun/@cortexkit+subc-client@0.21.2/node_modules/@cortexkit/subc-client/dist/connection-file.js
13988
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/connection-file.js
13855
13989
  import { promises as fs2 } from "node:fs";
13856
13990
  var SCHEMA_VERSION = 1;
13857
13991
  var MIN_KEY_LEN = 32;
@@ -13898,7 +14032,10 @@ function verifyOwnerOnly(path, stat, expectedUid) {
13898
14032
  async function readConnectionFile(path) {
13899
14033
  return readConnectionFileForUid(path, process.geteuid?.());
13900
14034
  }
13901
- async function readConnectionFileForUid(path, expectedUid) {
14035
+ async function readConnectionFileWithLocalEndpoint(path) {
14036
+ return readConnectionFileForUid(path, process.geteuid?.(), true);
14037
+ }
14038
+ async function readConnectionFileForUid(path, expectedUid, includeLocalEndpoint = false) {
13902
14039
  const handle = await fs2.open(path, "r");
13903
14040
  let raw;
13904
14041
  try {
@@ -13937,13 +14074,26 @@ async function readConnectionFileForUid(path, expectedUid) {
13937
14074
  daemonVer: parsed.daemon_ver ?? ""
13938
14075
  };
13939
14076
  validate(info);
14077
+ if (includeLocalEndpoint && parsed.local_endpoint != null) {
14078
+ const endpoint = parsed.local_endpoint;
14079
+ if (endpoint.kind === "unix" && typeof endpoint.path === "string" && endpoint.path.length > 0) {
14080
+ info.localEndpoint = { kind: "unix", path: endpoint.path };
14081
+ } else if (endpoint.kind === "pipe" && typeof endpoint.name === "string" && endpoint.name.length > 0) {
14082
+ info.localEndpoint = { kind: "pipe", name: endpoint.name };
14083
+ } else {
14084
+ throw new ConnectionFileError("connection file local_endpoint must name a unix path or pipe name");
14085
+ }
14086
+ }
13940
14087
  return info;
13941
14088
  }
13942
14089
 
13943
- // ../../node_modules/.bun/@cortexkit+subc-client@0.21.2/node_modules/@cortexkit/subc-client/dist/launch-nonce.js
14090
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/launch-nonce.js
13944
14091
  import { closeSync as closeSync5, fstatSync as fstatSync3, readSync as readSync4 } from "node:fs";
14092
+ import { connect } from "node:net";
13945
14093
  var SUBC_LAUNCH_NONCE_ENV = "SUBC_LAUNCH_NONCE";
13946
14094
  var SUBC_LAUNCH_NONCE_FD_ENV = "SUBC_LAUNCH_NONCE_FD";
14095
+ var SUBC_LAUNCH_NONCE_PIPE_ENV = "SUBC_LAUNCH_NONCE_PIPE";
14096
+ var SUBC_LAUNCH_NONCE_PIPE_FALLBACK_ENV = "SUBC_LAUNCH_NONCE_PIPE_FALLBACK";
13947
14097
  class LaunchNonceError extends Error {
13948
14098
  name = "LaunchNonceError";
13949
14099
  kind;
@@ -13962,9 +14112,21 @@ class LaunchNonceError extends Error {
13962
14112
  this.foundInode = details.foundInode;
13963
14113
  }
13964
14114
  }
13965
- function launchNonceOrUndefined() {
13966
- const result = processCell().result();
13967
- return result.ok ? result.nonce ?? undefined : undefined;
14115
+ function isLaunchNonceError(error) {
14116
+ return error instanceof Error && error.name === "LaunchNonceError" && typeof error.kind === "string";
14117
+ }
14118
+ async function launchNonceAsync() {
14119
+ const cell = processCell();
14120
+ return unwrap(await (cell.resultAsync?.() ?? cell.result()));
14121
+ }
14122
+ async function launchNonceOrUndefinedAsync() {
14123
+ try {
14124
+ return await launchNonceAsync();
14125
+ } catch (error) {
14126
+ if (isLaunchNonceError(error))
14127
+ return;
14128
+ throw error;
14129
+ }
13968
14130
  }
13969
14131
  var PROCESS_CELL_KEY = Symbol.for("@cortexkit/subc-client/launch-nonce/v1");
13970
14132
  function processCell() {
@@ -13984,20 +14146,60 @@ function unwrap(result) {
13984
14146
 
13985
14147
  class LaunchNonceCell {
13986
14148
  cached;
14149
+ pending;
13987
14150
  descriptorReads = 0;
13988
14151
  lookup;
13989
14152
  platform;
13990
14153
  stat;
13991
- constructor(lookup, platform = process.platform, stat = (fd) => fstatSync3(fd, { bigint: true })) {
14154
+ pipeReader;
14155
+ constructor(lookup, platform = process.platform, stat = (fd) => fstatSync3(fd, { bigint: true }), pipeReader = readLaunchNoncePipe) {
13992
14156
  this.lookup = lookup;
13993
14157
  this.platform = platform;
13994
14158
  this.stat = stat;
14159
+ this.pipeReader = pipeReader;
13995
14160
  }
13996
14161
  result() {
14162
+ if (this.cached === undefined && this.platform === "win32" && this.lookup(SUBC_LAUNCH_NONCE_PIPE_ENV) !== undefined) {
14163
+ const fallback = this.permittedPipeFallback();
14164
+ if (fallback === undefined) {
14165
+ throw new LaunchNonceError("PipeNeedsAsync", "call launchNonceAsync() before the synchronous reader when SUBC_LAUNCH_NONCE_PIPE is set");
14166
+ }
14167
+ this.cached = { ok: true, nonce: fallback };
14168
+ }
13997
14169
  if (this.cached === undefined)
13998
14170
  this.cached = this.read();
13999
14171
  return this.cached;
14000
14172
  }
14173
+ async resultAsync() {
14174
+ if (this.cached !== undefined)
14175
+ return this.cached;
14176
+ if (this.pending !== undefined)
14177
+ return this.pending;
14178
+ const named = this.platform === "win32" ? this.lookup(SUBC_LAUNCH_NONCE_PIPE_ENV) : undefined;
14179
+ if (named === undefined)
14180
+ return this.result();
14181
+ const fallback = this.permittedPipeFallback();
14182
+ this.pending = this.pipeReader(named).then((nonce) => ({ ok: true, nonce: fallback !== undefined && nonce.value !== fallback.value ? fallback : nonce }), (error) => {
14183
+ if (fallback !== undefined)
14184
+ return { ok: true, nonce: fallback };
14185
+ if (!isLaunchNonceError(error))
14186
+ throw error;
14187
+ return { ok: false, error };
14188
+ }).then((result) => {
14189
+ this.cached ??= result;
14190
+ return this.cached;
14191
+ });
14192
+ return this.pending;
14193
+ }
14194
+ permittedPipeFallback() {
14195
+ if (this.lookup(SUBC_LAUNCH_NONCE_PIPE_FALLBACK_ENV) !== "env")
14196
+ return;
14197
+ const value = this.lookup(SUBC_LAUNCH_NONCE_ENV);
14198
+ return value ? makeLaunchNonce(value, "env") : undefined;
14199
+ }
14200
+ async getAsync() {
14201
+ return unwrap(await this.resultAsync());
14202
+ }
14001
14203
  get() {
14002
14204
  return unwrap(this.result());
14003
14205
  }
@@ -14128,8 +14330,198 @@ function closeQuietly(fd) {
14128
14330
  closeSync5(fd);
14129
14331
  } catch {}
14130
14332
  }
14333
+ async function readLaunchNoncePipe(name, connector = (path) => connect(path), openWindowMs = 500, readWindowMs = 2000) {
14334
+ const deadline = Date.now() + openWindowMs;
14335
+ for (;; ) {
14336
+ try {
14337
+ const bytes = await pipeAttempt(name, connector, Math.max(1, deadline - Date.now()), readWindowMs);
14338
+ if (bytes.length === 0)
14339
+ throw new LaunchNonceError("PipeEmpty", "the launch nonce named pipe is empty");
14340
+ let value;
14341
+ try {
14342
+ value = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
14343
+ } catch {
14344
+ throw new LaunchNonceError("PipeNotUtf8", "the launch nonce named pipe held bytes that are not UTF-8");
14345
+ }
14346
+ return makeLaunchNonce(value, "pipe");
14347
+ } catch (error) {
14348
+ if (isLaunchNonceError(error))
14349
+ throw error;
14350
+ const busy = error?.code === "EBUSY" || errnoOf(error) === 231;
14351
+ if (!busy || Date.now() >= deadline) {
14352
+ throw new LaunchNonceError("PipeNotOpen", "SUBC_LAUNCH_NONCE_PIPE names a pipe that could not be opened", { errno: errnoOf(error) });
14353
+ }
14354
+ await new Promise((resolve) => setTimeout(resolve, Math.min(10, Math.max(1, deadline - Date.now()))));
14355
+ }
14356
+ }
14357
+ }
14358
+ function pipeAttempt(name, connector, openWindowMs, readWindowMs) {
14359
+ return new Promise((resolve, reject) => {
14360
+ let socket;
14361
+ try {
14362
+ socket = connector(name);
14363
+ } catch (error) {
14364
+ reject(error);
14365
+ return;
14366
+ }
14367
+ let connected = false;
14368
+ let settled = false;
14369
+ let size = 0;
14370
+ const chunks = [];
14371
+ let timer = setTimeout(() => finish(new LaunchNonceError("PipeNotOpen", "launch nonce pipe open timed out")), openWindowMs);
14372
+ function finish(error) {
14373
+ if (settled)
14374
+ return;
14375
+ settled = true;
14376
+ clearTimeout(timer);
14377
+ socket.destroy();
14378
+ if (error !== undefined)
14379
+ reject(error);
14380
+ else
14381
+ resolve(Buffer.concat(chunks));
14382
+ }
14383
+ socket.once("connect", () => {
14384
+ connected = true;
14385
+ clearTimeout(timer);
14386
+ timer = setTimeout(() => finish(new LaunchNonceError("PipeUnreadable", "launch nonce pipe read timed out")), readWindowMs);
14387
+ });
14388
+ socket.on("data", (chunk) => {
14389
+ size += chunk.length;
14390
+ if (size > 4096) {
14391
+ finish(new LaunchNonceError("PipeUnreadable", "launch nonce pipe exceeded its byte limit"));
14392
+ return;
14393
+ }
14394
+ chunks.push(Buffer.from(chunk));
14395
+ });
14396
+ socket.once("end", () => finish());
14397
+ socket.once("error", (error) => finish(connected ? new LaunchNonceError("PipeUnreadable", "could not read the launch nonce from the named pipe", { errno: errnoOf(error) }) : error));
14398
+ socket.once("close", () => {
14399
+ if (!settled)
14400
+ finish(new LaunchNonceError("PipeUnreadable", "launch nonce pipe closed before EOF"));
14401
+ });
14402
+ });
14403
+ }
14131
14404
 
14132
- // ../../node_modules/.bun/@cortexkit+subc-client@0.21.2/node_modules/@cortexkit/subc-client/dist/route-handle.js
14405
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/request-gate.js
14406
+ class Lane {
14407
+ limit;
14408
+ used = 0;
14409
+ waiters = [];
14410
+ failure;
14411
+ constructor(limit) {
14412
+ this.limit = limit;
14413
+ }
14414
+ acquire(timeoutMs, signal) {
14415
+ if (this.failure)
14416
+ return Promise.reject(this.failure);
14417
+ if (signal?.aborted)
14418
+ return Promise.reject(new Error("request cancelled before write"));
14419
+ if (timeoutMs !== undefined && timeoutMs <= 0)
14420
+ return Promise.reject(new Error("request deadline elapsed waiting for a slot"));
14421
+ if (this.used < this.limit && this.waiters.length === 0) {
14422
+ this.used++;
14423
+ return Promise.resolve(this.releaser());
14424
+ }
14425
+ return new Promise((resolve, reject) => {
14426
+ let timer;
14427
+ const clean = () => {
14428
+ if (timer !== undefined)
14429
+ clearTimeout(timer);
14430
+ signal?.removeEventListener("abort", abort);
14431
+ };
14432
+ const waiter = {
14433
+ grant: () => {
14434
+ clean();
14435
+ resolve(this.releaser());
14436
+ },
14437
+ fail: (error) => {
14438
+ clean();
14439
+ reject(error);
14440
+ }
14441
+ };
14442
+ const abort = () => {
14443
+ const index = this.waiters.indexOf(waiter);
14444
+ if (index < 0)
14445
+ return;
14446
+ this.waiters.splice(index, 1);
14447
+ waiter.fail(new Error("request cancelled before write"));
14448
+ };
14449
+ this.waiters.push(waiter);
14450
+ signal?.addEventListener("abort", abort, { once: true });
14451
+ if (timeoutMs !== undefined)
14452
+ timer = setTimeout(() => {
14453
+ const index = this.waiters.indexOf(waiter);
14454
+ if (index < 0)
14455
+ return;
14456
+ this.waiters.splice(index, 1);
14457
+ waiter.fail(new Error("request deadline elapsed waiting for a slot"));
14458
+ }, timeoutMs);
14459
+ });
14460
+ }
14461
+ close(error) {
14462
+ this.failure = error;
14463
+ for (const waiter of this.waiters.splice(0))
14464
+ waiter.fail(error);
14465
+ }
14466
+ releaser() {
14467
+ let released = false;
14468
+ return () => {
14469
+ if (released)
14470
+ return;
14471
+ released = true;
14472
+ const waiter = this.waiters.shift();
14473
+ if (waiter)
14474
+ waiter.grant();
14475
+ else
14476
+ this.used--;
14477
+ };
14478
+ }
14479
+ }
14480
+
14481
+ class RequestGate {
14482
+ total;
14483
+ watches;
14484
+ slots = new Set;
14485
+ closed = new AbortController;
14486
+ get signal() {
14487
+ return this.closed.signal;
14488
+ }
14489
+ constructor(requestWindow, watchWindow) {
14490
+ this.total = new Lane(requestWindow);
14491
+ if (watchWindow !== undefined)
14492
+ this.watches = new Lane(watchWindow);
14493
+ }
14494
+ async acquire(watch, timeoutMs, signal) {
14495
+ const deadline = timeoutMs === undefined ? undefined : Date.now() + timeoutMs;
14496
+ const watchRelease = watch && this.watches ? await this.watches.acquire(timeoutMs, signal) : undefined;
14497
+ try {
14498
+ const totalRelease = await this.total.acquire(deadline === undefined ? undefined : deadline - Date.now(), signal);
14499
+ const slot = {
14500
+ inFlight: false,
14501
+ release: () => {
14502
+ if (!this.slots.delete(slot))
14503
+ return;
14504
+ totalRelease();
14505
+ watchRelease?.();
14506
+ }
14507
+ };
14508
+ this.slots.add(slot);
14509
+ return slot;
14510
+ } catch (error) {
14511
+ watchRelease?.();
14512
+ throw error;
14513
+ }
14514
+ }
14515
+ close(error) {
14516
+ this.total.close(error);
14517
+ this.watches?.close(error);
14518
+ this.closed.abort(error);
14519
+ for (const slot of this.slots)
14520
+ slot.release();
14521
+ }
14522
+ }
14523
+
14524
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/route-handle.js
14133
14525
  var connectionToken = new WeakMap;
14134
14526
  var reverseRequests = new WeakMap;
14135
14527
 
@@ -14222,10 +14614,13 @@ function sameRouteHandle(left, right) {
14222
14614
  return left === right;
14223
14615
  }
14224
14616
 
14225
- // ../../node_modules/.bun/@cortexkit+subc-client@0.21.2/node_modules/@cortexkit/subc-client/dist/client.js
14617
+ // ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/client.js
14226
14618
  var debug = debuglog("subc-client");
14227
14619
  var DEFAULT_HANDSHAKE_TIMEOUT_MS = 1e4;
14228
14620
  var DEFAULT_REQUEST_TIMEOUT_MS = 30000;
14621
+ var DEFAULT_SLEEP_GRACE_MS = 15000;
14622
+ var SLEEP_DETECTION_THRESHOLD_MS = 2000;
14623
+ var MIN_REQUEST_BUDGET_MS = 1;
14229
14624
  var TIMEOUT_ARBITRATION_GRACE_MS = 50;
14230
14625
  var LIVENESS_PROBE_WINDOW_MS = 2000;
14231
14626
  var REQUEST_DEADLINE_MARKER = "request_deadline";
@@ -14261,6 +14656,14 @@ class SubcCallError extends Error {
14261
14656
  }
14262
14657
  }
14263
14658
 
14659
+ class DaemonUnavailableError extends SubcCallError {
14660
+ recovery = "user_action_required";
14661
+ constructor(cause) {
14662
+ super("not_sent", "CortexKit's daemon is not running or can't be reached on this computer, so this tool call was not sent. Retrying won't start it. Stop calling CortexKit tools and ask the user to start the daemon (run `ck setup`, or restart the CortexKit service), then try again after they confirm it is running.", errorCode(cause), cause);
14663
+ this.name = "DaemonUnavailableError";
14664
+ }
14665
+ }
14666
+
14264
14667
  class SubcError extends Error {
14265
14668
  code;
14266
14669
  detail;
@@ -14385,6 +14788,14 @@ class SubcClient {
14385
14788
  reconnecting = null;
14386
14789
  generation = 1;
14387
14790
  routeOpenGateInstance;
14791
+ requestGates;
14792
+ wireSlots;
14793
+ get gates() {
14794
+ return this.requestGates ??= new Map;
14795
+ }
14796
+ get slots() {
14797
+ return this.wireSlots ??= new Map;
14798
+ }
14388
14799
  readerActive = false;
14389
14800
  constructor(sock, currentConn, opts) {
14390
14801
  this.sock = sock;
@@ -14400,8 +14811,15 @@ class SubcClient {
14400
14811
  }
14401
14812
  static async connect(opts) {
14402
14813
  const normalized = normalizeConnectOptions(opts);
14403
- const opened = await SubcClient.openConnection(normalized);
14404
- return new SubcClient(opened.sock, opened.conn, normalized);
14814
+ try {
14815
+ const opened = await SubcClient.openConnection(normalized);
14816
+ return new SubcClient(opened.sock, opened.conn, normalized);
14817
+ } catch (err) {
14818
+ if (errorCode(err) === "ENOENT" || errorCode(err) === "ECONNREFUSED") {
14819
+ throw new DaemonUnavailableError(err);
14820
+ }
14821
+ throw err;
14822
+ }
14405
14823
  }
14406
14824
  async catalogList(moduleId) {
14407
14825
  const body = this.encode(moduleId === undefined ? { op: "catalog.list" } : { op: "catalog.list", module_id: moduleId });
@@ -14437,17 +14855,23 @@ class SubcClient {
14437
14855
  }
14438
14856
  async sendRouteOpen(target, identity, opts = {}) {
14439
14857
  const scope = validatedRouteScope(opts.scope);
14440
- const consumerIdentity = routeOpenConsumerIdentity(opts);
14858
+ const consumerIdentity = await routeOpenConsumerIdentity(opts);
14441
14859
  const reverseRequests = opts.reverseRequests ?? new ReverseRequestRegistry;
14442
14860
  reverseRequests.seal();
14443
14861
  const consumerCapabilities = reverseRequests.capabilities();
14444
14862
  const body = this.encode({
14445
14863
  op: "route.open",
14864
+ busy_refusals: true,
14446
14865
  target,
14447
14866
  identity,
14448
14867
  ...consumerIdentity ? { consumer_identity: consumerIdentity } : {},
14449
14868
  ...consumerCapabilities.length > 0 ? { consumer_capabilities: consumerCapabilities } : {},
14450
- ...scope ? { scope: { owner: scope.owner, ref: scope.ref, scope_epoch: scope.scopeEpoch } } : {}
14869
+ ...scope ? { scope: {
14870
+ owner: scope.owner,
14871
+ ref: scope.ref,
14872
+ scope_epoch: scope.scopeEpoch,
14873
+ ...scope.bindProof !== undefined ? { bind_proof: scope.bindProof } : {}
14874
+ } } : {}
14451
14875
  });
14452
14876
  let installed = null;
14453
14877
  const install = (frame) => {
@@ -14458,6 +14882,8 @@ class SubcClient {
14458
14882
  throw new SubcError(`route.open returned no route handle: ${JSON.stringify(parsed)}`);
14459
14883
  }
14460
14884
  installed = this.installRoute(parsed.route_channel, parsed.route_epoch, reverseRequests);
14885
+ if (parsed.request_window !== undefined)
14886
+ this.gates.set(installed, new RequestGate(parsed.request_window, parsed.watch_window));
14461
14887
  this.routeModules.set(parsed.route_channel, target.module_id);
14462
14888
  return true;
14463
14889
  };
@@ -14487,7 +14913,7 @@ class SubcClient {
14487
14913
  const bytes = binary ? requireBinaryBody(body) : body instanceof Uint8Array ? body : this.encode(body);
14488
14914
  const priority = opts.priority ?? Priority.Interactive;
14489
14915
  const admission = opts.admissionClass ?? AdmissionClass.Normal;
14490
- const reply = await this.send(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress, undefined, undefined, binary, opts.signal);
14916
+ const reply = await this.send(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress, undefined, undefined, binary, opts.signal, validatedSleepGraceMs(opts.sleepGraceMs ?? this.opts.sleepGraceMs ?? DEFAULT_SLEEP_GRACE_MS));
14491
14917
  return this.decodeReply(reply);
14492
14918
  }
14493
14919
  async call(moduleId, method, params, opts = {}) {
@@ -14503,10 +14929,12 @@ class SubcClient {
14503
14929
  }
14504
14930
  async managedCall(moduleId, body, opts) {
14505
14931
  let retriedUnknownChannel = false;
14932
+ const startedAt = opts.timeoutMs === undefined ? undefined : this.opts.now();
14933
+ let attemptOpts = opts;
14506
14934
  for (;; ) {
14507
- const routeHandle = await this.cachedRouteHandle(moduleId, opts);
14935
+ const routeHandle = await this.cachedRouteHandle(moduleId, attemptOpts);
14508
14936
  try {
14509
- return await this.managedRequest(routeHandle, body, opts);
14937
+ return await this.managedRequest(routeHandle, body, attemptOpts);
14510
14938
  } catch (err) {
14511
14939
  if (!(err instanceof SubcCallError))
14512
14940
  throw this.terminalCallError("managed call failed", err);
@@ -14516,6 +14944,15 @@ class SubcClient {
14516
14944
  this.evictRouteHandle(routeHandle);
14517
14945
  continue;
14518
14946
  }
14947
+ if (isDataPlaneDrainRefusal(err.code) && !retriedUnknownChannel && !this.closeStarted && !opts.signal?.aborted) {
14948
+ const remainingMs = opts.timeoutMs === undefined || startedAt === undefined ? undefined : opts.timeoutMs - (this.opts.now() - startedAt);
14949
+ if (remainingMs === undefined || remainingMs > 0) {
14950
+ retriedUnknownChannel = true;
14951
+ this.evictRouteHandle(routeHandle);
14952
+ attemptOpts = remainingMs === undefined ? opts : { ...opts, timeoutMs: remainingMs };
14953
+ continue;
14954
+ }
14955
+ }
14519
14956
  if (deadBindCode && retriedUnknownChannel) {
14520
14957
  this.evictRouteHandle(routeHandle);
14521
14958
  }
@@ -14545,6 +14982,8 @@ class SubcClient {
14545
14982
  }
14546
14983
  subscribe(handle, body, onEvent, opts = {}) {
14547
14984
  this.assertLiveHandle(handle);
14985
+ if (this.gates.has(handle))
14986
+ return this.subscribeGated(handle, body, onEvent, opts);
14548
14987
  const bytes = body instanceof Uint8Array ? body : this.encode(body);
14549
14988
  const priority = opts.priority ?? Priority.Interactive;
14550
14989
  const admission = opts.admissionClass ?? AdmissionClass.Normal;
@@ -14552,22 +14991,43 @@ class SubcClient {
14552
14991
  const key = pendingKey(handle, corr);
14553
14992
  let subscriptionPending = null;
14554
14993
  let resolveClosed = null;
14994
+ let resolveEnded;
14995
+ const ended = new Promise((resolve) => {
14996
+ resolveEnded = resolve;
14997
+ });
14998
+ const endFailure = (err, frame) => {
14999
+ if (frame?.header.ty === FrameType.Error) {
15000
+ const error = err;
15001
+ resolveEnded({ kind: "error", code: error.code, message: error.message, detail: error.detail });
15002
+ } else if (err instanceof SubcError && err.closeReason && err.closeReason !== "connection_lost") {
15003
+ resolveEnded({ kind: "route_closed", reason: err.closeReason });
15004
+ } else {
15005
+ resolveEnded({ kind: "connection_lost" });
15006
+ }
15007
+ };
14555
15008
  const closed = new Promise((resolve, reject) => {
14556
15009
  if (this.closedErr) {
15010
+ endFailure(this.closedErr);
14557
15011
  reject(this.closedErr);
14558
15012
  return;
14559
15013
  }
14560
15014
  resolveClosed = resolve;
14561
15015
  subscriptionPending = {
14562
15016
  handle,
14563
- resolve: () => resolve(),
14564
- reject,
15017
+ resolve: (frame) => {
15018
+ resolveEnded(frame.header.ty === FrameType.Response ? { kind: "response", body: frame.body } : { kind: "stream_end" });
15019
+ resolve();
15020
+ },
15021
+ reject: (err, frame) => {
15022
+ endFailure(err, frame);
15023
+ reject(err);
15024
+ },
14565
15025
  onProgress: onEvent,
14566
15026
  timer: null,
14567
15027
  subscription: true
14568
15028
  };
14569
15029
  this.pending.set(key, subscriptionPending);
14570
- const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), handle.channel, handle.epoch, corr, bytes);
15030
+ const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission) | SUBSCRIPTION_FLAG, handle.channel, handle.epoch, corr, bytes);
14571
15031
  writeBorrowed(this.sock, encodeFrame(frame), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS).catch((err) => {
14572
15032
  const pending = this.pending.get(key);
14573
15033
  if (pending)
@@ -14580,11 +15040,14 @@ class SubcClient {
14580
15040
  return;
14581
15041
  cancelled = true;
14582
15042
  if (subscriptionPending && resolveClosed)
14583
- this.settle(key, subscriptionPending, resolveClosed);
15043
+ this.settle(key, subscriptionPending, () => {
15044
+ resolveEnded({ kind: "cancelled" });
15045
+ resolveClosed?.();
15046
+ });
14584
15047
  if (this.isLiveHandle(handle))
14585
15048
  this.cancel(handle, corr, priority);
14586
15049
  };
14587
- return { unsubscribe, closed };
15050
+ return { unsubscribe, closed, ended };
14588
15051
  }
14589
15052
  attachCancelSignal(signal, key, handle, corr, priority) {
14590
15053
  if (!handle)
@@ -14650,7 +15113,7 @@ class SubcClient {
14650
15113
  this.sendRouteGoodbye(handle);
14651
15114
  }
14652
15115
  async closeManagedRoute(target, identity, opts = {}) {
14653
- const key = routeCacheKey(target, identity, routeOpenConsumerIdentity(opts), (opts.reverseRequests ?? new ReverseRequestRegistry).capabilities(), validatedRouteScope(opts.scope));
15116
+ const key = routeCacheKey(target, identity, await routeOpenConsumerIdentity(opts), (opts.reverseRequests ?? new ReverseRequestRegistry).capabilities(), validatedRouteScope(opts.scope));
14654
15117
  const cached = this.routes.get(key);
14655
15118
  if (!cached)
14656
15119
  return;
@@ -14703,10 +15166,21 @@ class SubcClient {
14703
15166
  });
14704
15167
  }
14705
15168
  static async openConnection(opts) {
14706
- const conn = await readConnectionFile(opts.connectionFile);
15169
+ const conn = opts.transport === "local" ? await readConnectionFileWithLocalEndpoint(opts.connectionFile) : await readConnectionFile(opts.connectionFile);
14707
15170
  const deadline = Date.now() + (opts.handshakeTimeoutMs ?? DEFAULT_HANDSHAKE_TIMEOUT_MS);
14708
15171
  const endpoint = conn.endpoints[0];
14709
- const sock = await SubcSocket.connect(endpoint.host, endpoint.port, deadline);
15172
+ let sock;
15173
+ if (opts.transport === "local") {
15174
+ const local = conn.localEndpoint;
15175
+ if (!local)
15176
+ throw new SubcError("connection file has no local_endpoint", "local_endpoint_absent");
15177
+ if (local.kind === "unix" !== (process.platform !== "win32")) {
15178
+ throw new SubcError("unsupported local endpoint kind on this platform", "local_endpoint_unsupported");
15179
+ }
15180
+ sock = await SubcSocket.connectLocal(local.kind === "unix" ? local.path : local.name, deadline);
15181
+ } else {
15182
+ sock = await SubcSocket.connect(endpoint.host, endpoint.port, deadline);
15183
+ }
14710
15184
  try {
14711
15185
  await authenticateClient(sock, conn, deadline);
14712
15186
  } catch (err) {
@@ -14718,7 +15192,125 @@ class SubcClient {
14718
15192
  async controlRpc(body, acceptFrame, onLateResponse) {
14719
15193
  return this.send(null, body, Priority.Interactive, AdmissionClass.Normal, undefined, undefined, acceptFrame, onLateResponse);
14720
15194
  }
14721
- send(handle, body, priority, admission, timeoutMs, onProgress, acceptFrame, onLateResponse, binary = false, signal) {
15195
+ send(...args) {
15196
+ const [handle, body, priority, admission, timeoutMs, onProgress, acceptFrame, onLateResponse, binary, signal, sleepGraceMs] = args;
15197
+ if (!handle || !this.gates.has(handle))
15198
+ return this.sendAttempt(...args);
15199
+ return this.gatedRequest(handle, false, timeoutMs, signal, (slot, remaining) => this.sendAttempt(handle, body, priority, admission, remaining, onProgress, acceptFrame, onLateResponse, binary, signal, sleepGraceMs, slot));
15200
+ }
15201
+ async gatedRequest(handle, watch, timeoutMs, signal, attempt) {
15202
+ const gate = this.gates.get(handle);
15203
+ const deadline = this.opts.now() + (timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS);
15204
+ let slot;
15205
+ try {
15206
+ slot = await gate.acquire(watch, deadline - this.opts.now(), signal);
15207
+ } catch (error) {
15208
+ throw this.notSentCallError("request was not sent while waiting for a route slot", error);
15209
+ }
15210
+ let delay = 25;
15211
+ let busyDeadlineError;
15212
+ try {
15213
+ for (;; ) {
15214
+ if (gate.signal.aborted)
15215
+ throw gate.signal.reason;
15216
+ if (signal?.aborted)
15217
+ throw this.notSentCallError("request cancelled before write", signal.reason);
15218
+ this.assertLiveHandle(handle);
15219
+ const budget = deadline - this.opts.now();
15220
+ if (budget < MIN_REQUEST_BUDGET_MS)
15221
+ throw busyDeadlineError ?? this.notSentCallError("request deadline elapsed before write", new Error("less than 1ms remains before the request deadline"));
15222
+ try {
15223
+ return await attempt(slot, budget);
15224
+ } catch (error) {
15225
+ const refusal = error instanceof SubcError ? error : error instanceof SubcCallError && error.cause instanceof SubcError ? error.cause : undefined;
15226
+ if (!refusal || !isRouteBusyRetryable(errorFrameFlags.get(refusal) ?? 0, refusal.code, this.gates.get(handle) === gate))
15227
+ throw error;
15228
+ const exhausted = () => new SubcCallError("not_sent", `daemon refused before forwarding: ${refusal.message}`, "route_busy", refusal);
15229
+ busyDeadlineError = exhausted();
15230
+ const remaining = deadline - this.opts.now();
15231
+ if (remaining <= 0 || signal?.aborted)
15232
+ throw exhausted();
15233
+ const ms = Math.min(remaining, delay * (0.5 + this.opts.random() * 0.5));
15234
+ delay = Math.min(1000, delay * 2);
15235
+ const proceed = await this.busySleep(ms, gate.signal, signal);
15236
+ if (gate.signal.aborted)
15237
+ throw gate.signal.reason;
15238
+ if (!proceed || this.opts.now() >= deadline)
15239
+ throw exhausted();
15240
+ }
15241
+ }
15242
+ } finally {
15243
+ if (!slot.inFlight)
15244
+ slot.release();
15245
+ }
15246
+ }
15247
+ async busySleep(ms, closed, signal) {
15248
+ if (closed.aborted || signal?.aborted)
15249
+ return false;
15250
+ let abort;
15251
+ const cancelled = new Promise((resolve) => {
15252
+ abort = () => resolve(false);
15253
+ });
15254
+ closed.addEventListener("abort", abort, { once: true });
15255
+ signal?.addEventListener("abort", abort, { once: true });
15256
+ try {
15257
+ return await Promise.race([this.opts.sleep(ms).then(() => true), cancelled]);
15258
+ } finally {
15259
+ closed.removeEventListener("abort", abort);
15260
+ signal?.removeEventListener("abort", abort);
15261
+ }
15262
+ }
15263
+ subscribeGated(handle, body, onEvent, opts) {
15264
+ const bytes = body instanceof Uint8Array ? body : this.encode(body);
15265
+ const priority = opts.priority ?? Priority.Interactive;
15266
+ const admission = opts.admissionClass ?? AdmissionClass.Normal;
15267
+ const abort = new AbortController;
15268
+ let current;
15269
+ let cancelled = false;
15270
+ let resolveClosed;
15271
+ let rejectClosed;
15272
+ let resolveEnded;
15273
+ const closed = new Promise((resolve, reject) => {
15274
+ resolveClosed = resolve;
15275
+ rejectClosed = reject;
15276
+ });
15277
+ const ended = new Promise((resolve) => {
15278
+ resolveEnded = resolve;
15279
+ });
15280
+ this.gatedRequest(handle, true, undefined, abort.signal, (slot, remaining) => this.sendAttempt(handle, bytes, priority, admission, remaining, onEvent, undefined, undefined, false, undefined, undefined, slot, true, (key, pending, corr) => {
15281
+ current = { key, pending, corr };
15282
+ })).then((frame) => {
15283
+ if (cancelled)
15284
+ return;
15285
+ resolveEnded(frame.header.ty === FrameType.Response ? { kind: "response", body: frame.body } : { kind: "stream_end" });
15286
+ resolveClosed();
15287
+ }, (error) => {
15288
+ if (cancelled)
15289
+ return;
15290
+ if (error instanceof SubcError && error.closeReason)
15291
+ resolveEnded(error.closeReason === "connection_lost" ? { kind: "connection_lost" } : { kind: "route_closed", reason: error.closeReason });
15292
+ else if (error instanceof SubcError || error instanceof SubcCallError)
15293
+ resolveEnded({ kind: "error", code: error.code, message: error.message, detail: error.detail });
15294
+ else
15295
+ resolveEnded({ kind: "connection_lost" });
15296
+ rejectClosed(error);
15297
+ });
15298
+ return { closed, ended, unsubscribe: () => {
15299
+ if (cancelled)
15300
+ return;
15301
+ cancelled = true;
15302
+ abort.abort();
15303
+ if (current && this.pending.get(current.key) === current.pending) {
15304
+ const { key, pending, corr } = current;
15305
+ this.settle(key, pending, () => pending.reject(new SubcError("subscription cancelled")));
15306
+ if (this.isLiveHandle(handle))
15307
+ this.cancel(handle, corr, priority);
15308
+ }
15309
+ resolveEnded({ kind: "cancelled" });
15310
+ resolveClosed();
15311
+ } };
15312
+ }
15313
+ sendAttempt(handle, body, priority, admission, timeoutMs, onProgress, acceptFrame, onLateResponse, binary = false, signal, sleepGraceMs = this.opts.sleepGraceMs ?? DEFAULT_SLEEP_GRACE_MS, slot, subscription = false, registered) {
14722
15314
  if (handle)
14723
15315
  this.assertLiveHandle(handle);
14724
15316
  if (this.closedErr)
@@ -14732,7 +15324,7 @@ class SubcClient {
14732
15324
  const key = pendingKey(handle, corr);
14733
15325
  const channel = handle?.channel ?? 0;
14734
15326
  const epoch = handle?.epoch ?? 0;
14735
- const frame = buildFrame(FrameType.Request, buildFlags(binary, priority, false, admission), channel, epoch, corr, body);
15327
+ const frame = buildFrame(FrameType.Request, buildFlags(binary, priority, false, admission) | (subscription ? SUBSCRIPTION_FLAG : 0), channel, epoch, corr, body);
14736
15328
  return new Promise((resolve, reject) => {
14737
15329
  const ms = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
14738
15330
  const pending = {
@@ -14742,11 +15334,27 @@ class SubcClient {
14742
15334
  onProgress,
14743
15335
  timer: null,
14744
15336
  acceptFrame,
14745
- onLateResponse
15337
+ onLateResponse,
15338
+ slot,
15339
+ subscription
14746
15340
  };
14747
- pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, channel, corr, ms), ms);
15341
+ if (!subscription)
15342
+ this.armRequestTimeout(key, pending, channel, corr, ms, sleepGraceMs);
14748
15343
  this.pending.set(key, pending);
14749
- writeBorrowed(this.sock, encodeFrame(frame), Date.now() + ms).catch((error) => {
15344
+ registered?.(key, pending, corr);
15345
+ if (slot && handle) {
15346
+ slot.inFlight = true;
15347
+ this.slots.set(key, { handle, slot });
15348
+ }
15349
+ const write = writeTrackedBorrowed(this.sock, encodeFrame(frame), Date.now() + ms);
15350
+ if (slot && !write.queued) {
15351
+ this.slots.delete(key);
15352
+ slot.inFlight = false;
15353
+ slot.release();
15354
+ }
15355
+ write.completed.catch((error) => {
15356
+ if (error instanceof SocketWriteNotQueuedError || error instanceof SocketWriteQueuedError)
15357
+ error = error.cause ?? error;
14750
15358
  const current = this.pending.get(key);
14751
15359
  if (current)
14752
15360
  this.rejectPending(key, current, error instanceof Error ? error : new SubcError(String(error)));
@@ -14755,10 +15363,16 @@ class SubcClient {
14755
15363
  this.attachCancelSignal(signal, key, handle, corr, priority);
14756
15364
  });
14757
15365
  }
15366
+ armRequestTimeout(key, pending, channel, corr, ms, sleepGraceMs) {
15367
+ pending.sleepGrace = { wallStartMs: Date.now(), awakeStartMs: performance.now(), ms: sleepGraceMs, used: false };
15368
+ pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, channel, corr, ms), ms);
15369
+ }
14758
15370
  arbitrateTimeout(key, pending, channel, corr, ms) {
14759
15371
  const settleAsTimeout = () => {
14760
15372
  if (pending.onLateResponse)
14761
15373
  this.lateResponses.set(key, pending.onLateResponse);
15374
+ if (pending.slot?.inFlight && pending.handle && this.isLiveHandle(pending.handle))
15375
+ this.cancel(pending.handle, corr);
14762
15376
  this.rejectPending(key, pending, new SubcError(this.timeoutMessage(channel, corr, ms), REQUEST_DEADLINE_MARKER));
14763
15377
  };
14764
15378
  const graceDeadline = Date.now() + this.opts.timeoutArbitrationGraceMs;
@@ -14770,6 +15384,17 @@ class SubcClient {
14770
15384
  setImmediate(arbitrate);
14771
15385
  return;
14772
15386
  }
15387
+ const sleep = pending.sleepGrace;
15388
+ if (sleep && !sleep.used && sleep.ms > 0) {
15389
+ const wallElapsed = Date.now() - sleep.wallStartMs;
15390
+ const awakeElapsed = performance.now() - sleep.awakeStartMs;
15391
+ const sleptMs = wallElapsed - awakeElapsed;
15392
+ if (sleptMs > SLEEP_DETECTION_THRESHOLD_MS) {
15393
+ sleep.used = true;
15394
+ pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, channel, corr, ms), sleep.ms);
15395
+ return;
15396
+ }
15397
+ }
14773
15398
  settleAsTimeout();
14774
15399
  };
14775
15400
  setImmediate(arbitrate);
@@ -14780,7 +15405,7 @@ class SubcClient {
14780
15405
  const priority = opts.priority ?? Priority.Interactive;
14781
15406
  const admission = opts.admissionClass ?? AdmissionClass.Normal;
14782
15407
  try {
14783
- const reply = await this.sendManaged(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress, binary, opts.signal);
15408
+ const reply = await this.sendManaged(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress, binary, opts.signal, validatedSleepGraceMs(opts.sleepGraceMs ?? this.opts.sleepGraceMs ?? DEFAULT_SLEEP_GRACE_MS));
14784
15409
  return this.decodeReply(reply);
14785
15410
  } catch (error) {
14786
15411
  if (error instanceof SubcCallError)
@@ -14788,7 +15413,13 @@ class SubcClient {
14788
15413
  throw this.terminalCallError("managed call failed", error);
14789
15414
  }
14790
15415
  }
14791
- sendManaged(handle, body, priority, admission, timeoutMs, onProgress, binary = false, signal) {
15416
+ sendManaged(...args) {
15417
+ const [handle, body, priority, admission, timeoutMs, onProgress, binary, signal, sleepGraceMs] = args;
15418
+ if (!this.gates.has(handle))
15419
+ return this.sendManagedAttempt(...args);
15420
+ return this.gatedRequest(handle, false, timeoutMs, signal, (slot, remaining) => this.sendManagedAttempt(handle, body, priority, admission, remaining, onProgress, binary, signal, sleepGraceMs, slot));
15421
+ }
15422
+ sendManagedAttempt(handle, body, priority, admission, timeoutMs, onProgress, binary = false, signal, sleepGraceMs = this.opts.sleepGraceMs ?? DEFAULT_SLEEP_GRACE_MS, slot) {
14792
15423
  try {
14793
15424
  this.assertLiveHandle(handle);
14794
15425
  } catch (error) {
@@ -14822,12 +15453,22 @@ class SubcClient {
14822
15453
  reject,
14823
15454
  onProgress,
14824
15455
  timer: null,
14825
- classifyFailure
15456
+ classifyFailure,
15457
+ slot
14826
15458
  };
14827
- pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, handle.channel, corr, ms), ms);
15459
+ this.armRequestTimeout(key, pending, handle.channel, corr, ms, sleepGraceMs);
14828
15460
  this.pending.set(key, pending);
15461
+ if (slot) {
15462
+ slot.inFlight = true;
15463
+ this.slots.set(key, { handle, slot });
15464
+ }
14829
15465
  const write = writeTrackedBorrowed(this.sock, encodeFrame(frame), Date.now() + ms);
14830
15466
  handedToSocket = write.queued;
15467
+ if (slot && !write.queued) {
15468
+ this.slots.delete(key);
15469
+ slot.inFlight = false;
15470
+ slot.release();
15471
+ }
14831
15472
  write.completed.catch((error) => {
14832
15473
  const current = this.pending.get(key);
14833
15474
  if (current)
@@ -14844,7 +15485,7 @@ class SubcClient {
14844
15485
  throw new SubcCallError("terminal", "managed call requires a BindIdentity in SubcClient.connect({ identity }) or call(..., { identity })", "missing_identity");
14845
15486
  }
14846
15487
  const target = { kind: opts.targetKind ?? this.opts.targetKind, module_id: moduleId };
14847
- const consumerIdentity = routeOpenConsumerIdentity(opts);
15488
+ const consumerIdentity = await routeOpenConsumerIdentity(opts);
14848
15489
  const reverseRequests = opts.reverseRequests ?? new ReverseRequestRegistry;
14849
15490
  reverseRequests.seal();
14850
15491
  const key = routeCacheKey(target, identity, consumerIdentity, reverseRequests.capabilities(), scope);
@@ -14929,6 +15570,7 @@ class SubcClient {
14929
15570
  if ("handle" in outcome) {
14930
15571
  const { handle } = outcome;
14931
15572
  if (cached.closed) {
15573
+ this.failHandle(handle, new SubcError("route closed during route.open", "route_closed", undefined, "closed_by_caller"));
14932
15574
  this.liveRoutes.delete(handle.channel);
14933
15575
  this.sendRouteGoodbye(handle);
14934
15576
  throw this.routeClosedDuringOpen();
@@ -15052,6 +15694,9 @@ class SubcClient {
15052
15694
  return;
15053
15695
  } catch (err) {
15054
15696
  if (!isConsumerReconnectTransient(err) || attempt >= this.opts.reconnectBackoff.maxAttempts) {
15697
+ if (isConsumerReconnectTransient(err) && !(err instanceof AuthError)) {
15698
+ throw new DaemonUnavailableError(err);
15699
+ }
15055
15700
  if (err instanceof AuthError && attempt > 1) {
15056
15701
  throw new AuthError(`reconnect gave up after ${attempt} attempts: ${err.message} — the connection file and the daemon's key disagree persistently ` + `(daemon restarting in a loop, split connection-file paths, or a genuinely foreign daemon on this port); ` + `check the daemon, then restart this host app`);
15057
15702
  }
@@ -15174,6 +15819,16 @@ class SubcClient {
15174
15819
  }
15175
15820
  const key = pendingKey(handle, frame.header.corr);
15176
15821
  const pending = this.pending.get(key);
15822
+ if (frame.header.ty === FrameType.Response || frame.header.ty === FrameType.Error || frame.header.ty === FrameType.StreamEnd) {
15823
+ const record = this.slots.get(key);
15824
+ if (record) {
15825
+ this.slots.delete(key);
15826
+ record.slot.inFlight = false;
15827
+ const busy = frame.header.ty === FrameType.Error && pending?.slot === record.slot && isRouteBusyRetryable(frame.header.flags, this.errorFromFrame(frame).code, !!handle && this.gates.has(handle));
15828
+ if (!busy)
15829
+ record.slot.release();
15830
+ }
15831
+ }
15177
15832
  if (pending) {
15178
15833
  if (pending.acceptFrame && !pending.acceptFrame(frame))
15179
15834
  return;
@@ -15189,7 +15844,7 @@ class SubcClient {
15189
15844
  this.settle(key, pending, () => pending.resolve(frame));
15190
15845
  return;
15191
15846
  case FrameType.Error:
15192
- this.settle(key, pending, () => pending.reject(this.errorFromFrame(frame)));
15847
+ this.settle(key, pending, () => pending.reject(this.errorFromFrame(frame), frame));
15193
15848
  return;
15194
15849
  default:
15195
15850
  return;
@@ -15326,6 +15981,14 @@ class SubcClient {
15326
15981
  return this.legacyChannelReasons.get(channel) ?? "unknown";
15327
15982
  }
15328
15983
  failHandle(handle, error) {
15984
+ this.gates.get(handle)?.close(error);
15985
+ this.gates.delete(handle);
15986
+ for (const [key, record] of this.slots) {
15987
+ if (sameRouteHandle(record.handle, handle)) {
15988
+ record.slot.release();
15989
+ this.slots.delete(key);
15990
+ }
15991
+ }
15329
15992
  for (const [key, pending] of this.pending) {
15330
15993
  if (pending.handle && sameRouteHandle(pending.handle, handle))
15331
15994
  this.rejectPending(key, pending, error);
@@ -15335,6 +15998,10 @@ class SubcClient {
15335
15998
  const routeError = err instanceof SubcError && err.closeReason ? err : new SubcError(err.message, errorCode(err), undefined, this.closeStarted ? "closed_by_caller" : "connection_lost");
15336
15999
  if (!this.closedErr)
15337
16000
  this.closedErr = err;
16001
+ for (const gate of this.gates.values())
16002
+ gate.close(routeError);
16003
+ this.gates.clear();
16004
+ this.slots.clear();
15338
16005
  this.routeEndReasons.clear();
15339
16006
  this.legacyChannelReasons.clear();
15340
16007
  this.routeModules.clear();
@@ -15368,6 +16035,9 @@ class SubcClient {
15368
16035
  return this.ingressEpochDropCount;
15369
16036
  }
15370
16037
  installRoute(channel, epoch, reverseRequests = new ReverseRequestRegistry) {
16038
+ const previous = this.liveRoutes.get(channel);
16039
+ if (previous && this.gates.has(previous))
16040
+ this.failHandle(previous, new SubcError("route replaced", "route_closed", undefined, "closed_by_caller"));
15371
16041
  const handle = createRouteHandle(channel, epoch, this.connectionToken, reverseRequests);
15372
16042
  this.routeEndReasons.delete(channel);
15373
16043
  this.legacyChannelReasons.delete(channel);
@@ -15438,9 +16108,15 @@ function isRetryableRouteOpenCode(code) {
15438
16108
  return false;
15439
16109
  if (code === "target_flow_unsupported")
15440
16110
  return false;
16111
+ if (code === "target_federated_unsupported")
16112
+ return false;
15441
16113
  if (code === "target_agent_run_unsupported")
15442
16114
  return false;
15443
- return code === "module_reloading" || code === "module_warming" || code === "target_unavailable" || code === "module_timeout" || code === "scope_not_synced" || code === "scope_changed";
16115
+ if (code === "scope_bind_proof_required" || code === "scope_bind_proof_mismatch")
16116
+ return false;
16117
+ if (code === "scope_epoch_in_use")
16118
+ return false;
16119
+ return code === "module_reloading" || code === "module_warming" || code === "target_unavailable" || code === "module_timeout" || code === "scope_not_synced" || code === "scope_changed" || code === "session_address_unavailable" || code === "bind_busy";
15444
16120
  }
15445
16121
  function equalJitter(delayMs, random) {
15446
16122
  const half = delayMs / 2;
@@ -15477,6 +16153,12 @@ var STALE_ROUTE_EPOCH = "stale_route_epoch";
15477
16153
  function isEstablishedRouteDead(_flags, code) {
15478
16154
  return code === UNKNOWN_CHANNEL || code === STALE_ROUTE_EPOCH;
15479
16155
  }
16156
+ function isRouteBusyRetryable(flags, code, routeOptedIn) {
16157
+ return routeOptedIn && (flags & DAEMON_ORIGIN_FLAG) !== 0 && code === "route_busy";
16158
+ }
16159
+ function isDataPlaneDrainRefusal(code) {
16160
+ return code === "module_reloading";
16161
+ }
15480
16162
  async function connectionFileExists(path) {
15481
16163
  try {
15482
16164
  await fs3.access(path);
@@ -15488,6 +16170,7 @@ async function connectionFileExists(path) {
15488
16170
  function normalizeConnectOptions(opts) {
15489
16171
  return {
15490
16172
  connectionFile: opts.connectionFile,
16173
+ transport: opts.transport ?? "tcp",
15491
16174
  handshakeTimeoutMs: opts.handshakeTimeoutMs,
15492
16175
  identity: opts.identity,
15493
16176
  targetKind: opts.targetKind ?? DEFAULT_MANAGED_TARGET_KIND,
@@ -15497,11 +16180,18 @@ function normalizeConnectOptions(opts) {
15497
16180
  random: opts.random ?? Math.random,
15498
16181
  routeOpenRetryDeadlineMs: opts.routeOpenRetryDeadlineMs ?? ROUTE_OPEN_RETRY_DEADLINE_MS,
15499
16182
  timeoutArbitrationGraceMs: opts.timeoutArbitrationGraceMs ?? TIMEOUT_ARBITRATION_GRACE_MS,
16183
+ sleepGraceMs: validatedSleepGraceMs(opts.sleepGraceMs ?? DEFAULT_SLEEP_GRACE_MS),
15500
16184
  bodyReadTimeoutMs: opts.bodyReadTimeoutMs,
15501
16185
  livenessProbeWindowMs: opts.livenessProbeWindowMs ?? LIVENESS_PROBE_WINDOW_MS,
15502
16186
  onControlPush: opts.onControlPush
15503
16187
  };
15504
16188
  }
16189
+ function validatedSleepGraceMs(ms) {
16190
+ if (!Number.isFinite(ms) || ms < 0 || ms > 2147483647) {
16191
+ throw new RangeError("sleepGraceMs must be finite and in 0..2147483647 milliseconds");
16192
+ }
16193
+ return ms;
16194
+ }
15505
16195
  function isValidCapabilityIdentifier(identifier) {
15506
16196
  if (/\s/u.test(identifier))
15507
16197
  return false;
@@ -15524,7 +16214,13 @@ function isValidCapabilityIdentifier(identifier) {
15524
16214
  function routeCacheKey(target, identity, consumerIdentity, consumerCapabilities, scope) {
15525
16215
  const consumerPart = consumerIdentity ? `${consumerIdentity.module_id}\x00${consumerIdentity.launch_nonce}` : "";
15526
16216
  const capabilitiesPart = [...consumerCapabilities].sort().join("\x00");
15527
- const scopePart = scope ? JSON.stringify([scope.owner.kind, scope.owner.kind === "reserved" ? scope.owner.module_id : null, scope.ref, scope.scopeEpoch]) : "";
16217
+ const scopePart = scope ? JSON.stringify([
16218
+ scope.owner.kind,
16219
+ scope.owner.kind === "reserved" ? scope.owner.module_id : null,
16220
+ scope.ref,
16221
+ scope.scopeEpoch,
16222
+ scope.bindProof === undefined ? null : createHash4("sha256").update(scope.bindProof).digest("hex")
16223
+ ]) : "";
15528
16224
  return `${target.kind}\x00${target.module_id}\x00${identity.project_root}\x00${identity.harness}\x00${identity.session}\x00${consumerPart}\x00${capabilitiesPart}\x00${scopePart}`;
15529
16225
  }
15530
16226
  function validatedRouteScope(scope) {
@@ -15542,13 +16238,18 @@ function validatedRouteScope(scope) {
15542
16238
  if (!Number.isSafeInteger(scope.scopeEpoch) || scope.scopeEpoch < 0) {
15543
16239
  throw new SubcError("scope.scopeEpoch must be a safe non-negative integer", "invalid_scope");
15544
16240
  }
15545
- return { owner: { ...scope.owner }, ref: scope.ref, scopeEpoch: scope.scopeEpoch };
16241
+ return {
16242
+ owner: { ...scope.owner },
16243
+ ref: scope.ref,
16244
+ scopeEpoch: scope.scopeEpoch,
16245
+ ...scope.bindProof !== undefined ? { bindProof: scope.bindProof } : {}
16246
+ };
15546
16247
  }
15547
- function routeOpenConsumerIdentity(opts = {}) {
16248
+ async function routeOpenConsumerIdentity(opts = {}) {
15548
16249
  if (opts.consumerIdentity !== undefined)
15549
16250
  return opts.consumerIdentity ?? undefined;
15550
16251
  const moduleId = process.env[SUBC_MODULE_ID_ENV];
15551
- const launchNonce = launchNonceOrUndefined()?.value;
16252
+ const launchNonce = (await launchNonceOrUndefinedAsync())?.value;
15552
16253
  if (!moduleId || !launchNonce)
15553
16254
  return;
15554
16255
  return { module_id: moduleId, launch_nonce: launchNonce };
@@ -16000,21 +16701,21 @@ function getLifecycleRegistry() {
16000
16701
  }
16001
16702
 
16002
16703
  // ../aft-bridge/dist/project-identity.js
16003
- import { createHash as createHash4 } from "node:crypto";
16704
+ import { createHash as createHash5 } from "node:crypto";
16004
16705
  import { realpathSync as realpathSync3 } from "node:fs";
16005
- import { posix as posix2, resolve as resolve7, win32 as win322 } from "node:path";
16706
+ import { posix as posix3, resolve as resolve6, win32 as win323 } from "node:path";
16006
16707
  function canonicalizeProjectRoot(dir) {
16007
16708
  const trimmed = trimProjectRootSeparators(dir);
16008
16709
  let canonical;
16009
16710
  try {
16010
16711
  canonical = realpathSync3(trimmed);
16011
16712
  } catch {
16012
- canonical = resolve7(trimmed);
16713
+ canonical = resolve6(trimmed);
16013
16714
  }
16014
16715
  return normalizeWindowsRoot(canonical);
16015
16716
  }
16016
16717
  function trimProjectRootSeparators(dir, platform = process.platform) {
16017
- const root = (platform === "win32" ? win322 : posix2).parse(dir).root;
16718
+ const root = (platform === "win32" ? win323 : posix3).parse(dir).root;
16018
16719
  const trimmed = dir.replace(/[/\\]+$/, "");
16019
16720
  return trimmed.length < root.length ? root : trimmed;
16020
16721
  }
@@ -16049,7 +16750,7 @@ function hasDotComponent(path) {
16049
16750
  return path.split(/[\\/]/).some((component) => component === "." || component === "..");
16050
16751
  }
16051
16752
  function projectRootKeyHash(dir) {
16052
- return createHash4("sha256").update(canonicalizeProjectRoot(dir)).digest("hex").slice(0, 16);
16753
+ return createHash5("sha256").update(canonicalizeProjectRoot(dir)).digest("hex").slice(0, 16);
16053
16754
  }
16054
16755
 
16055
16756
  // ../aft-bridge/dist/subc-transport.js
@@ -16816,6 +17517,8 @@ class SubcTransportPool {
16816
17517
  harness;
16817
17518
  connectionFile;
16818
17519
  handshakeTimeoutMs;
17520
+ clock;
17521
+ waitClock;
16819
17522
  consumerIdentity;
16820
17523
  hostScopes;
16821
17524
  hostScopeCache = new Map;
@@ -16858,6 +17561,13 @@ class SubcTransportPool {
16858
17561
  editSlotSurvives;
16859
17562
  editSlotSurvivesCaptured = false;
16860
17563
  constructor(options) {
17564
+ this.clock = options.clock ?? {
17565
+ now: () => Date.now(),
17566
+ awakeNow: () => performance.now(),
17567
+ setTimeout: (callback, ms) => setTimeout(callback, ms),
17568
+ clearTimeout: (timer) => clearTimeout(timer)
17569
+ };
17570
+ this.waitClock = new WaitClock(() => this.clock.now(), () => this.clock.awakeNow?.() ?? this.clock.now());
16861
17571
  this.connectionFile = options.connectionFile;
16862
17572
  this.harness = options.harness;
16863
17573
  this.handshakeTimeoutMs = options.handshakeTimeoutMs;
@@ -17484,11 +18194,12 @@ class SubcTransportPool {
17484
18194
  this.stopUnusedHostScopeRetry(record.identity.session);
17485
18195
  }
17486
18196
  async routeRequest(identity, body, timeoutMs, onProgress, expectedGeneration, abortSignal) {
17487
- const callStartedAt = performance.now();
18197
+ const callStartedAt = this.waitClock.now();
17488
18198
  const callDeadlineMs = timeoutMs ?? SUBC_DEFAULT_REQUEST_TIMEOUT_MS;
18199
+ const deadline = new RequestDeadline(this.waitClock, callDeadlineMs);
17489
18200
  let scheduledDelayMs = 0;
17490
- const spentMs = () => Math.max(performance.now() - callStartedAt, scheduledDelayMs);
17491
- const remainingMs = () => callDeadlineMs - spentMs();
18201
+ const spentMs = () => Math.max(this.waitClock.now() - callStartedAt, scheduledDelayMs);
18202
+ const remainingMs = () => deadline.remaining() - Math.max(0, scheduledDelayMs - (this.waitClock.now() - callStartedAt));
17492
18203
  const root = asCanonicalRootPath(identity.project_root);
17493
18204
  let generation = expectedGeneration;
17494
18205
  if (this.lifecycleEnabled()) {
@@ -17509,12 +18220,12 @@ class SubcTransportPool {
17509
18220
  const remaining = remainingMs();
17510
18221
  if (remaining <= 0)
17511
18222
  throw keyChanged ?? callDeadlinePassedError(undefined, callDeadlineMs);
17512
- let timer;
18223
+ let cancelTimer;
17513
18224
  try {
17514
18225
  const acquired = await Promise.race([
17515
18226
  this.ensureClient(),
17516
18227
  new Promise((resolve) => {
17517
- timer = setTimeout(() => resolve(CALL_DEADLINE_EXPIRED), remaining);
18228
+ cancelTimer = deadlineTimer(this.clock, remainingMs, () => resolve(CALL_DEADLINE_EXPIRED));
17518
18229
  })
17519
18230
  ]);
17520
18231
  if (acquired === CALL_DEADLINE_EXPIRED) {
@@ -17529,22 +18240,22 @@ class SubcTransportPool {
17529
18240
  if (spentMs() + this.nextRouteReopenDelayMs() >= callDeadlineMs)
17530
18241
  throw error;
17531
18242
  } finally {
17532
- clearTimeout(timer);
18243
+ cancelTimer?.();
17533
18244
  }
17534
18245
  const { delayMs, wait } = this.waitForRouteReopenBackoff();
17535
18246
  scheduledDelayMs = spentMs() + delayMs;
17536
- let retryTimer;
18247
+ let cancelRetryTimer;
17537
18248
  try {
17538
18249
  const waited = await Promise.race([
17539
18250
  wait,
17540
18251
  new Promise((resolve) => {
17541
- retryTimer = setTimeout(() => resolve(CALL_DEADLINE_EXPIRED), callDeadlineMs - (performance.now() - callStartedAt));
18252
+ cancelRetryTimer = deadlineTimer(this.clock, remainingMs, () => resolve(CALL_DEADLINE_EXPIRED));
17542
18253
  })
17543
18254
  ]);
17544
18255
  if (waited === CALL_DEADLINE_EXPIRED)
17545
18256
  throw keyChanged;
17546
18257
  } finally {
17547
- clearTimeout(retryTimer);
18258
+ cancelRetryTimer?.();
17548
18259
  }
17549
18260
  }
17550
18261
  this.assertRecordLive(record);
@@ -17587,9 +18298,9 @@ class SubcTransportPool {
17587
18298
  const remaining = remainingMs();
17588
18299
  if (remaining <= 0)
17589
18300
  throw callDeadlinePassedError(lastRefusal, callDeadlineMs);
17590
- let timer;
18301
+ let cancelTimer;
17591
18302
  const expired = new Promise((resolve) => {
17592
- timer = setTimeout(() => resolve(CALL_DEADLINE_EXPIRED), remaining);
18303
+ cancelTimer = deadlineTimer(this.clock, remainingMs, () => resolve(CALL_DEADLINE_EXPIRED));
17593
18304
  });
17594
18305
  try {
17595
18306
  const opened = await Promise.race([openRoute(), expired]);
@@ -17598,7 +18309,7 @@ class SubcTransportPool {
17598
18309
  }
17599
18310
  return opened;
17600
18311
  } finally {
17601
- clearTimeout(timer);
18312
+ cancelTimer?.();
17602
18313
  }
17603
18314
  };
17604
18315
  const openRouteAfterReloadWindow = async () => {
@@ -17677,6 +18388,7 @@ class SubcTransportPool {
17677
18388
  try {
17678
18389
  request = client.request(route, body, {
17679
18390
  timeoutMs: Math.ceil(requestTimeoutMs),
18391
+ ...deadline.resumed ? { sleepGraceMs: 0 } : {},
17680
18392
  onProgress
17681
18393
  });
17682
18394
  } catch (error) {
@@ -17804,6 +18516,7 @@ class SubcTransportPool {
17804
18516
  this.connecting = this.connectFn({
17805
18517
  connectionFile: this.connectionFile,
17806
18518
  handshakeTimeoutMs: this.handshakeTimeoutMs,
18519
+ sleepGraceMs: RESUME_ALLOWANCE_MS,
17807
18520
  onControlPush: (push) => {
17808
18521
  if (owner && this.client === owner)
17809
18522
  this.onScopeRouteClose(push);
@@ -18805,7 +19518,7 @@ function taskIdFromError(error) {
18805
19518
  return;
18806
19519
  }
18807
19520
  // ../aft-bridge/dist/feature-config.js
18808
- import { createHash as createHash5 } from "node:crypto";
19521
+ import { createHash as createHash6 } from "node:crypto";
18809
19522
  import { createRequire } from "node:module";
18810
19523
  var CANONICAL_TOOLS = [
18811
19524
  "aft_callgraph",
@@ -18866,12 +19579,7 @@ var RETIRED_IDLE_CHECKOUT_HOURS = [
18866
19579
  "idle.checkout_hours"
18867
19580
  ];
18868
19581
  var DATA_LAYER_KEYS_REFUSED_FROM = [0, 65];
18869
- var DATA_LAYER_RETIRED_PATHS = [
18870
- "views.callgraph_copies",
18871
- "views.enabled",
18872
- "views.idle_checkout_hours",
18873
- "worktree.ram_overlay"
18874
- ];
19582
+ var DATA_LAYER_RETIRED_PATHS = ["views.idle_checkout_hours"];
18875
19583
  var IDLE_CHECKOUT_HOURS_DEFAULT = 168;
18876
19584
  var IDLE_CHECKOUT_HOURS_MIN = 1;
18877
19585
  var IDLE_CHECKOUT_HOURS_MAX = 24 * 365;
@@ -18898,7 +19606,10 @@ function readRunningRelease() {
18898
19606
  return [0, 0];
18899
19607
  }
18900
19608
  var runningRelease;
19609
+ var runningReleaseOverrideForTest;
18901
19610
  function getRunningRelease() {
19611
+ if (runningReleaseOverrideForTest)
19612
+ return runningReleaseOverrideForTest;
18902
19613
  runningRelease ??= readRunningRelease();
18903
19614
  return runningRelease;
18904
19615
  }
@@ -18927,7 +19638,7 @@ function removedBlockKeyErrors(value, release, refuseRetired) {
18927
19638
  const paths = REMOVED_OPENCODE_PATHS.filter((path) => hasPath(value, path));
18928
19639
  if (refuseRetired)
18929
19640
  paths.push(...refusedRetiredNames(value));
18930
- if (releaseAtLeast(release, DATA_LAYER_KEYS_REFUSED_FROM))
19641
+ if (refuseRetired && releaseAtLeast(release, DATA_LAYER_KEYS_REFUSED_FROM))
18931
19642
  paths.push(...DATA_LAYER_RETIRED_PATHS.filter((path) => hasPath(value, path)));
18932
19643
  return paths.map((path) => `removed_config_key:${path}; run npx @cortexkit/aft doctor --fix`);
18933
19644
  }
@@ -18951,7 +19662,10 @@ var REFUSED_RETIRED_PATHS = [
18951
19662
  "experimental.bash",
18952
19663
  "idle.lsp_ttl_minutes",
18953
19664
  "inspect.tier2_soft_deadline_ms",
18954
- "inspect.max_drill_down_items"
19665
+ "inspect.max_drill_down_items",
19666
+ "views.callgraph_copies",
19667
+ "views.enabled",
19668
+ "worktree.ram_overlay"
18955
19669
  ];
18956
19670
  function refusedRetiredNames(block) {
18957
19671
  const names = REFUSED_RETIRED_PATHS.filter((path) => hasPath(block, path));
@@ -19143,8 +19857,9 @@ function translateDataLayerPaths(map, prefix, out) {
19143
19857
  }
19144
19858
  }
19145
19859
  for (const path of REMOVED_DATA_LAYER_PATHS) {
19146
- if (hasPath(map, path))
19147
- out.removedKeys.push(`${prefix}${path}`);
19860
+ const [container, leaf] = path.split(".");
19861
+ if (container && leaf && takeNested(map, container, leaf).found)
19862
+ recordRetired(out, prefix, path);
19148
19863
  }
19149
19864
  }
19150
19865
  function translateExperimentalPaths(map, prefix, out) {
@@ -19394,7 +20109,7 @@ var NO_EFFECT_RETIRED_NOTES = [
19394
20109
  ]
19395
20110
  ];
19396
20111
  function noEffectNote(key) {
19397
- return NO_EFFECT_RETIRED_NOTES.find(([path]) => namesPath(key, path))?.[1];
20112
+ return [...NO_EFFECT_RETIRED_NOTES, ...REMOVED_DATA_LAYER_NOTES].find(([path]) => namesPath(key, path))?.[1];
19398
20113
  }
19399
20114
  function namesPath(key, path) {
19400
20115
  return key === path || key.endsWith(`.${path}`);
@@ -19415,26 +20130,7 @@ var REMOVED_DATA_LAYER_NOTES = [
19415
20130
  ];
19416
20131
  function retiredIdleCheckoutHoursNote() {
19417
20132
  const [retired, replacement] = RETIRED_IDLE_CHECKOUT_HOURS;
19418
- return `${retired} is now ${replacement}; from ${refusedFromVersion()} AFT refuses a config file that still sets ${retired}.`;
19419
- }
19420
- function removedConfigKeysNoticeMessage(configPath, translation) {
19421
- const removed = translation.removedKeys ?? [];
19422
- if (removed.length === 0)
19423
- return "";
19424
- const parts = [
19425
- `${configPath} sets removed keys (${removed.join(", ")}); AFT ignores them, and from ${refusedFromVersion()} it refuses a config file that sets them. Run \`npx @cortexkit/aft doctor --fix\` to remove them.`
19426
- ];
19427
- for (const [path, note] of REMOVED_DATA_LAYER_NOTES) {
19428
- if (removed.some((key) => namesPath(key, path)))
19429
- parts.push(note);
19430
- }
19431
- return parts.join(" ");
19432
- }
19433
- function removedConfigKeysNoticeDigest(translation) {
19434
- return noticeDigest({
19435
- notice: "removed_data_layer_keys_v1",
19436
- keys: sortedUnique(translation.removedKeys)
19437
- });
20133
+ return `${retired} is now ${replacement}; from ${refusedFromVersion()} AFT refuses a user config file that still sets ${retired}.`;
19438
20134
  }
19439
20135
  function legacyConfigNoticeMessage(configPath, translation) {
19440
20136
  const equivalents = translation.retiredKeys.filter((key) => noEffectNote(key) === undefined);
@@ -19448,13 +20144,10 @@ function legacyConfigNoticeMessage(configPath, translation) {
19448
20144
  parts.push(retiredIdleCheckoutHoursNote());
19449
20145
  }
19450
20146
  }
19451
- for (const [, note] of NO_EFFECT_RETIRED_NOTES) {
20147
+ for (const [, note] of [...NO_EFFECT_RETIRED_NOTES, ...REMOVED_DATA_LAYER_NOTES]) {
19452
20148
  if (noEffect.has(note))
19453
20149
  parts.push(note);
19454
20150
  }
19455
- const removed = removedConfigKeysNoticeMessage(configPath, translation);
19456
- if (removed)
19457
- parts.push(removed);
19458
20151
  return parts.join(" ");
19459
20152
  }
19460
20153
  function translateConfigDocument(map, tier) {
@@ -19462,7 +20155,6 @@ function translateConfigDocument(map, tier) {
19462
20155
  warnings: [],
19463
20156
  legacyInput: false,
19464
20157
  retiredKeys: [],
19465
- removedKeys: [],
19466
20158
  retiredEnabledFalse: false
19467
20159
  };
19468
20160
  translateBlock(map, tier === "user", "base", out);
@@ -19473,7 +20165,6 @@ function translateConfigDocument(map, tier) {
19473
20165
  }
19474
20166
  }
19475
20167
  out.retiredKeys = sortedUnique(out.retiredKeys);
19476
- out.removedKeys = sortedUnique(out.removedKeys);
19477
20168
  return out;
19478
20169
  }
19479
20170
  function unknownDisabledTools(disabled) {
@@ -19512,7 +20203,8 @@ function projectBlock(block) {
19512
20203
  for (const path of [
19513
20204
  ...RETIRED_PATHS.map(([retired]) => retired),
19514
20205
  ...REMOVED_NO_EFFECT_PATHS,
19515
- ...DATA_LAYER_RETIRED_PATHS
20206
+ ...DATA_LAYER_RETIRED_PATHS,
20207
+ ...REMOVED_DATA_LAYER_PATHS
19516
20208
  ]) {
19517
20209
  const dot = path.indexOf(".");
19518
20210
  if (dot < 0) {
@@ -19592,7 +20284,7 @@ function canonicalJson(value) {
19592
20284
  return JSON.stringify(value);
19593
20285
  }
19594
20286
  function noticeDigest(projection) {
19595
- return createHash5("sha256").update(canonicalJson(projection), "utf8").digest("hex");
20287
+ return createHash6("sha256").update(canonicalJson(projection), "utf8").digest("hex");
19596
20288
  }
19597
20289
  var SEMANTIC_COST_NOTICE = "AFT indexes now default on; the local semantic backend may download an ONNX runtime and model and use CPU. Run npx @cortexkit/aft setup to change indexes.semantic.";
19598
20290
  var SEMANTIC_COST_NOTICE_DIGEST = noticeDigest({ notice: "semantic_default_cost_v1" });
@@ -20630,9 +21322,9 @@ async function releaseBridge(pool) {
20630
21322
  await pool.shutdown();
20631
21323
  }
20632
21324
  // ../aft-bridge/dist/lsp-github-install.js
20633
- import { createHash as createHash6, randomBytes as randomBytes2 } from "node:crypto";
21325
+ import { createHash as createHash7, randomBytes as randomBytes2 } from "node:crypto";
20634
21326
  import { closeSync as closeSync6, copyFileSync as copyFileSync3, createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync6, lstatSync as lstatSync2, mkdirSync as mkdirSync4, openSync as openSync5, readdirSync as readdirSync2, readFileSync as readFileSync5, readlinkSync, readSync as readSync5, realpathSync as realpathSync4, renameSync as renameSync3, rmSync as rmSync2, statSync as statSync6, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "node:fs";
20635
- import { dirname as dirname4, join as join11, relative as relative4, resolve as resolve8 } from "node:path";
21327
+ import { dirname as dirname4, join as join10, relative as relative3, resolve as resolve7 } from "node:path";
20636
21328
  import { Readable as Readable2 } from "node:stream";
20637
21329
  import { pipeline as pipeline2 } from "node:stream/promises";
20638
21330
 
@@ -20851,13 +21543,13 @@ function detectHostPlatform() {
20851
21543
 
20852
21544
  // ../aft-bridge/dist/tar-executable.js
20853
21545
  import { existsSync as existsSync5 } from "node:fs";
20854
- import { join as join10 } from "node:path";
21546
+ import { join as join9 } from "node:path";
20855
21547
  function windowsTarExecutable(options = {}) {
20856
21548
  const platform = options.platform ?? process.platform;
20857
21549
  if (platform !== "win32")
20858
21550
  return "tar";
20859
21551
  const env = options.env ?? process.env;
20860
- const systemTar = join10(env.SystemRoot ?? "C:\\Windows", "System32", "tar.exe");
21552
+ const systemTar = join9(env.SystemRoot ?? "C:\\Windows", "System32", "tar.exe");
20861
21553
  return (options.exists ?? existsSync5)(systemTar) ? systemTar : "tar";
20862
21554
  }
20863
21555
  function extractionCommand(args, privateStorage) {
@@ -20901,14 +21593,14 @@ function createGithubInstaller(services) {
20901
21593
  return getAftLspBinariesDir();
20902
21594
  }
20903
21595
  function ghPackageDir(spec) {
20904
- return join11(ghCacheRoot(), spec.id);
21596
+ return join10(ghCacheRoot(), spec.id);
20905
21597
  }
20906
21598
  function ghBinDir(spec) {
20907
21599
  const platform = detectHostPlatform()?.platform ?? "linux";
20908
21600
  return dirname4(ghBinaryPath(spec, platform));
20909
21601
  }
20910
21602
  function ghExtractDir(spec) {
20911
- return join11(ghPackageDir(spec), "extracted");
21603
+ return join10(ghPackageDir(spec), "extracted");
20912
21604
  }
20913
21605
  const INSTALLED_META_FILE = ".aft-installed";
20914
21606
  const INSTALL_FAILED_FILE = ".aft-install-failed.json";
@@ -20916,8 +21608,9 @@ function createGithubInstaller(services) {
20916
21608
  const INSTALL_LOCK_WAIT_MS = 10 * 60 * 1000;
20917
21609
  const INSTALL_LOCK_POLL_INTERVAL_MS = 1000;
20918
21610
  const INSTALL_LOCK_WAIT_TIMEOUT_REASON = "install lock held by another process for 10 minutes";
21611
+ const SMOKE_TIMEOUT_MS = 2000;
20919
21612
  function installFailureMarkerPath(spec) {
20920
- return join11(ghPackageDir(spec), INSTALL_FAILED_FILE);
21613
+ return join10(ghPackageDir(spec), INSTALL_FAILED_FILE);
20921
21614
  }
20922
21615
  function readInstallFailureMarker(spec) {
20923
21616
  try {
@@ -20961,15 +21654,15 @@ function createGithubInstaller(services) {
20961
21654
  const meta = readGithubInstalledMetaIn(ghPackageDir(spec));
20962
21655
  if (spec.layout === "distribution" && meta?.layout === "distribution" && isSafeVersion(meta.version)) {
20963
21656
  const arch = detectHostPlatform()?.arch ?? "x64";
20964
- return join11(ghExtractDir(spec), spec.binaryPathInArchive(platform, arch, stripTagV(meta.version)));
21657
+ return join10(ghExtractDir(spec), spec.binaryPathInArchive(platform, arch, stripTagV(meta.version)));
20965
21658
  }
20966
21659
  const ext = platform === "win32" ? ".exe" : "";
20967
- return join11(ghPackageDir(spec), "bin", `${spec.binary}${ext}`);
21660
+ return join10(ghPackageDir(spec), "bin", `${spec.binary}${ext}`);
20968
21661
  }
20969
21662
  function isGithubInstalled(spec, platform) {
20970
21663
  for (const candidate of ghBinaryCandidates(spec, platform)) {
20971
21664
  try {
20972
- if (statSync6(join11(ghBinDir(spec), candidate)).isFile())
21665
+ if (statSync6(join10(ghBinDir(spec), candidate)).isFile())
20973
21666
  return true;
20974
21667
  } catch {}
20975
21668
  }
@@ -20982,7 +21675,7 @@ function createGithubInstaller(services) {
20982
21675
  }
20983
21676
  function readGithubInstalledMetaIn(installDir) {
20984
21677
  try {
20985
- const path = join11(installDir, INSTALLED_META_FILE);
21678
+ const path = join10(installDir, INSTALLED_META_FILE);
20986
21679
  if (!statSync6(path).isFile())
20987
21680
  return null;
20988
21681
  const parsed = JSON.parse(readFileSync5(path, "utf8"));
@@ -21013,7 +21706,7 @@ function createGithubInstaller(services) {
21013
21706
  ...layout ? { layout } : {},
21014
21707
  ...smoke ? { smoke } : {}
21015
21708
  };
21016
- const path = join11(installDir, INSTALLED_META_FILE);
21709
+ const path = join10(installDir, INSTALLED_META_FILE);
21017
21710
  const tempPath = `${path}.tmp-${process.pid}-${randomBytes2(6).toString("hex")}`;
21018
21711
  try {
21019
21712
  writeFileSync2(tempPath, JSON.stringify(meta), { encoding: "utf8", flag: "wx" });
@@ -21029,7 +21722,7 @@ function createGithubInstaller(services) {
21029
21722
  const MAX_EXTRACT_BYTES = 1024 * 1024 * 1024;
21030
21723
  function sha256OfFile(path) {
21031
21724
  return new Promise((resolve, reject) => {
21032
- const hash = createHash6("sha256");
21725
+ const hash = createHash7("sha256");
21033
21726
  const stream = createReadStream2(path);
21034
21727
  stream.on("error", reject);
21035
21728
  stream.on("data", (chunk) => hash.update(chunk));
@@ -21037,7 +21730,7 @@ function createGithubInstaller(services) {
21037
21730
  });
21038
21731
  }
21039
21732
  function sha256OfFileSync(path) {
21040
- const hash = createHash6("sha256");
21733
+ const hash = createHash7("sha256");
21041
21734
  const fd = openSync5(path, "r");
21042
21735
  try {
21043
21736
  const buffer = Buffer.allocUnsafe(1024 * 1024);
@@ -21265,7 +21958,7 @@ function createGithubInstaller(services) {
21265
21958
  throw new Error(`failed to read staging dir ${dir}: ${err}`);
21266
21959
  }
21267
21960
  for (const entry of entries) {
21268
- const full = join11(dir, entry);
21961
+ const full = join10(dir, entry);
21269
21962
  let lst;
21270
21963
  try {
21271
21964
  lst = lstatSync2(full);
@@ -21277,7 +21970,7 @@ function createGithubInstaller(services) {
21277
21970
  try {
21278
21971
  target = readlinkSync(full);
21279
21972
  } catch {}
21280
- throw new Error(`archive contains symlink ${relative4(realStagingRoot, full)} → ${target}; rejecting (zip-slip defense)`);
21973
+ throw new Error(`archive contains symlink ${relative3(realStagingRoot, full)} → ${target}; rejecting (zip-slip defense)`);
21281
21974
  }
21282
21975
  let realFull;
21283
21976
  try {
@@ -21285,8 +21978,8 @@ function createGithubInstaller(services) {
21285
21978
  } catch (err) {
21286
21979
  throw new Error(`failed to realpath ${full}: ${err}`);
21287
21980
  }
21288
- const rel = relative4(realStagingRoot, realFull);
21289
- if (relativePathEscapesRoot(rel) || resolve8(realStagingRoot, rel) !== realFull) {
21981
+ const rel = relative3(realStagingRoot, realFull);
21982
+ if (relativePathEscapesRoot(rel) || resolve7(realStagingRoot, rel) !== realFull) {
21290
21983
  throw new Error(`archive entry escapes staging root: ${full} → ${realFull} (zip-slip defense)`);
21291
21984
  }
21292
21985
  if (lst.isDirectory()) {
@@ -21426,7 +22119,7 @@ function createGithubInstaller(services) {
21426
22119
  }
21427
22120
  function quarantineCachedGithubInstall(spec, reason) {
21428
22121
  const packageDir = ghPackageDir(spec);
21429
- const dest = join11(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
22122
+ const dest = join10(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
21430
22123
  warn(`[lsp] tofu_mismatch ${spec.id}: ${reason}; quarantining ${packageDir} -> ${dest}`);
21431
22124
  try {
21432
22125
  mkdirSync4(dirname4(dest), { recursive: true });
@@ -21436,7 +22129,7 @@ function createGithubInstaller(services) {
21436
22129
  warn(`[lsp] tofu_mismatch ${spec.id}: failed to quarantine cache entry: ${err}`);
21437
22130
  }
21438
22131
  }
21439
- async function smokeGithubBinary(spec, binaryPath) {
22132
+ async function smokeGithubBinary(spec, binaryPath, timeoutMs = SMOKE_TIMEOUT_MS) {
21440
22133
  return new Promise((resolveSmoke) => {
21441
22134
  let child;
21442
22135
  let settled = false;
@@ -21456,8 +22149,8 @@ function createGithubInstaller(services) {
21456
22149
  const timer = setTimeout(() => {
21457
22150
  child?.kill("SIGKILL");
21458
22151
  child?.unref();
21459
- finish("timeout", "exceeded 2000 ms; keeping install");
21460
- }, 2000);
22152
+ finish("timeout", `exceeded ${timeoutMs} ms; keeping install`);
22153
+ }, timeoutMs);
21461
22154
  const capture = (chunk) => {
21462
22155
  const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
21463
22156
  const available = 64 * 1024 - output.length;
@@ -21481,19 +22174,19 @@ function createGithubInstaller(services) {
21481
22174
  function hasRequiredRuntime(spec, extractDir, version) {
21482
22175
  return (spec.requiredRuntimePaths?.(stripTagV(version)) ?? []).every(({ path, kind }) => {
21483
22176
  try {
21484
- const info = statSync6(join11(extractDir, path));
22177
+ const info = statSync6(join10(extractDir, path));
21485
22178
  return kind === "file" ? info.isFile() : info.isDirectory();
21486
22179
  } catch {
21487
22180
  return false;
21488
22181
  }
21489
22182
  });
21490
22183
  }
21491
- function validateCachedGithubInstall(spec, platform) {
22184
+ function validateCachedGithubInstall(spec, platform, smokeTimeoutMs = SMOKE_TIMEOUT_MS) {
21492
22185
  const lease = acquireInstallLock(spec.githubRepo);
21493
22186
  if (!lease)
21494
22187
  return null;
21495
22188
  try {
21496
- const validation = validateCachedGithubInstallUnderLock(spec, platform);
22189
+ const validation = validateCachedGithubInstallUnderLock(spec, platform, smokeTimeoutMs);
21497
22190
  if (typeof validation !== "boolean")
21498
22191
  return validation.finally(() => lease.release());
21499
22192
  lease.release();
@@ -21503,10 +22196,10 @@ function createGithubInstaller(services) {
21503
22196
  throw err;
21504
22197
  }
21505
22198
  }
21506
- function validateCachedGithubInstallUnderLock(spec, platform) {
22199
+ function validateCachedGithubInstallUnderLock(spec, platform, smokeTimeoutMs = SMOKE_TIMEOUT_MS) {
21507
22200
  const packageDir = ghPackageDir(spec);
21508
22201
  const meta = readGithubInstalledMetaIn(packageDir);
21509
- const binaryPath = ghBinaryCandidates(spec, platform).map((candidate) => join11(ghBinDir(spec), candidate)).find((candidate) => {
22202
+ const binaryPath = ghBinaryCandidates(spec, platform).map((candidate) => join10(ghBinDir(spec), candidate)).find((candidate) => {
21510
22203
  try {
21511
22204
  return statSync6(candidate).isFile();
21512
22205
  } catch {
@@ -21536,7 +22229,7 @@ function createGithubInstaller(services) {
21536
22229
  quarantineCachedGithubInstall(spec, "missing required runtime files");
21537
22230
  return false;
21538
22231
  }
21539
- const verdict = await smokeGithubBinary(spec, binaryPath);
22232
+ const verdict = await smokeGithubBinary(spec, binaryPath, smokeTimeoutMs);
21540
22233
  if (verdict === "failed") {
21541
22234
  quarantineCachedGithubInstall(spec, "cached binary failed runtime smoke check");
21542
22235
  return false;
@@ -21582,7 +22275,7 @@ function createGithubInstaller(services) {
21582
22275
  }
21583
22276
  const pkgDir = ghPackageDir(spec);
21584
22277
  const extractDir = ghExtractDir(spec);
21585
- const archivePath = join11(pkgDir, expected.name);
22278
+ const archivePath = join10(pkgDir, expected.name);
21586
22279
  log(`[lsp] downloading ${spec.id} ${tag} → ${matchingAsset.url}`);
21587
22280
  try {
21588
22281
  await downloadFile(matchingAsset.url, archivePath, fetchImpl, matchingAsset.size, signal);
@@ -21618,7 +22311,7 @@ function createGithubInstaller(services) {
21618
22311
  const binaryRelativePath = spec.binaryPathInArchive(platform, arch, version);
21619
22312
  try {
21620
22313
  await extractArchiveSafely(archivePath, extractDir, expected.archive, async (stagingDir) => {
21621
- const stagedBinary = join11(stagingDir, binaryRelativePath);
22314
+ const stagedBinary = join10(stagingDir, binaryRelativePath);
21622
22315
  if (!existsSync6(stagedBinary) || !statSync6(stagedBinary).isFile()) {
21623
22316
  throw new Error(`extracted binary not found at ${stagedBinary}`);
21624
22317
  }
@@ -21648,7 +22341,7 @@ function createGithubInstaller(services) {
21648
22341
  unlinkSync3(archivePath);
21649
22342
  } catch {}
21650
22343
  }
21651
- const innerBinaryPath = join11(extractDir, binaryRelativePath);
22344
+ const innerBinaryPath = join10(extractDir, binaryRelativePath);
21652
22345
  const targetBinary = spec.layout === "distribution" ? innerBinaryPath : ghBinaryPath(spec, platform);
21653
22346
  mkdirSync4(dirname4(targetBinary), { recursive: true });
21654
22347
  try {
@@ -21775,6 +22468,7 @@ function createGithubInstaller(services) {
21775
22468
  let installsStarted = 0;
21776
22469
  const lockWaitTimeoutMs = Math.max(0, options.__lockWaitTimeoutMsForTests ?? INSTALL_LOCK_WAIT_MS);
21777
22470
  const lockPollIntervalMs = Math.max(1, options.__lockPollIntervalMsForTests ?? INSTALL_LOCK_POLL_INTERVAL_MS);
22471
+ const smokeTimeoutMs = Math.max(1, options.__smokeTimeoutMsForTests ?? SMOKE_TIMEOUT_MS);
21778
22472
  function notifyCachedBinDirsChanged(directory) {
21779
22473
  try {
21780
22474
  options.onCachedBinDirsChanged?.(directory);
@@ -21787,7 +22481,7 @@ function createGithubInstaller(services) {
21787
22481
  while (true) {
21788
22482
  if (signal.aborted)
21789
22483
  return null;
21790
- const validation = await withInstallLock(spec.githubRepo, async () => validateCachedGithubInstallUnderLock(spec, platform));
22484
+ const validation = await withInstallLock(spec.githubRepo, async () => validateCachedGithubInstallUnderLock(spec, platform, smokeTimeoutMs));
21791
22485
  if (validation !== null)
21792
22486
  return validation;
21793
22487
  if (signal.aborted)
@@ -21816,7 +22510,7 @@ function createGithubInstaller(services) {
21816
22510
  }
21817
22511
  for (const spec of GITHUB_LSP_TABLE) {
21818
22512
  const controller = new AbortController;
21819
- const validation = isGithubInstalled(spec, host.platform) ? validateCachedGithubInstall(spec, host.platform) : false;
22513
+ const validation = isGithubInstalled(spec, host.platform) ? validateCachedGithubInstall(spec, host.platform, smokeTimeoutMs) : false;
21820
22514
  if (validation === true)
21821
22515
  cachedBinDirs.push(ghBinDir(spec));
21822
22516
  const cacheReady = (validation === null ? retryBusyCacheValidation(spec, host.platform, controller.signal) : Promise.resolve(validation)).then((healthy) => {
@@ -21871,7 +22565,7 @@ function createGithubInstaller(services) {
21871
22565
  const currentHost = detectHostPlatform();
21872
22566
  if (!currentHost)
21873
22567
  return [];
21874
- const directories = await Promise.all(GITHUB_LSP_TABLE.map(async (spec) => isGithubInstalled(spec, currentHost.platform) && await validateCachedGithubInstall(spec, currentHost.platform) ? ghBinDir(spec) : null));
22568
+ const directories = await Promise.all(GITHUB_LSP_TABLE.map(async (spec) => isGithubInstalled(spec, currentHost.platform) && await validateCachedGithubInstall(spec, currentHost.platform, smokeTimeoutMs) ? ghBinDir(spec) : null));
21875
22569
  return directories.filter((directory) => directory !== null);
21876
22570
  }
21877
22571
  };
@@ -21942,7 +22636,7 @@ import { stat as stat2 } from "node:fs/promises";
21942
22636
  // ../aft-bridge/dist/npm-resolver.js
21943
22637
  import { readdirSync as readdirSync3, statSync as statSync7 } from "node:fs";
21944
22638
  import { homedir as homedir7 } from "node:os";
21945
- import { dirname as dirname5, isAbsolute as isAbsolute5, join as join12 } from "node:path";
22639
+ import { dirname as dirname5, isAbsolute as isAbsolute4, join as join11 } from "node:path";
21946
22640
  function defaultDeps() {
21947
22641
  return {
21948
22642
  platform: process.platform,
@@ -21969,16 +22663,16 @@ function npmFromPath(deps) {
21969
22663
  const separator = deps.platform === "win32" ? ";" : ":";
21970
22664
  for (const entry of raw.split(separator)) {
21971
22665
  const dir = entry.trim().replace(/^"|"$/g, "");
21972
- if (!dir || !isAbsolute5(dir))
22666
+ if (!dir || !isAbsolute4(dir))
21973
22667
  continue;
21974
- if (isFile(join12(dir, name)))
22668
+ if (isFile(join11(dir, name)))
21975
22669
  return dir;
21976
22670
  }
21977
22671
  return null;
21978
22672
  }
21979
22673
  function npmAdjacentToNode(deps) {
21980
22674
  const dir = dirname5(deps.execPath);
21981
- return isFile(join12(dir, npmBinaryName(deps.platform))) ? dir : null;
22675
+ return isFile(join11(dir, npmBinaryName(deps.platform))) ? dir : null;
21982
22676
  }
21983
22677
  function highestVersionedNodeBin(installsDir, name) {
21984
22678
  let entries;
@@ -21987,8 +22681,8 @@ function highestVersionedNodeBin(installsDir, name) {
21987
22681
  } catch {
21988
22682
  return null;
21989
22683
  }
21990
- const candidates = entries.filter((v) => isFile(join12(installsDir, v, "bin", name))).sort((a, b) => compareVersionsDesc(a, b));
21991
- return candidates.length > 0 ? join12(installsDir, candidates[0], "bin") : null;
22684
+ const candidates = entries.filter((v) => isFile(join11(installsDir, v, "bin", name))).sort((a, b) => compareVersionsDesc(a, b));
22685
+ return candidates.length > 0 ? join11(installsDir, candidates[0], "bin") : null;
21992
22686
  }
21993
22687
  function compareVersionsDesc(a, b) {
21994
22688
  const pa = a.replace(/^v/, "").split(".").map((n) => Number.parseInt(n, 10));
@@ -22013,22 +22707,22 @@ function wellKnownNpmDirs(deps) {
22013
22707
  const programFiles = env.ProgramFiles || "C:\\Program Files";
22014
22708
  const appData = env.APPDATA;
22015
22709
  const localAppData = env.LOCALAPPDATA;
22016
- push(join12(programFiles, "nodejs"));
22710
+ push(join11(programFiles, "nodejs"));
22017
22711
  if (appData)
22018
- push(join12(appData, "npm"));
22712
+ push(join11(appData, "npm"));
22019
22713
  if (localAppData)
22020
- push(join12(localAppData, "Volta", "bin"));
22714
+ push(join11(localAppData, "Volta", "bin"));
22021
22715
  if (env.NVM_SYMLINK)
22022
22716
  push(env.NVM_SYMLINK);
22023
22717
  } else {
22024
22718
  if (env.NVM_BIN)
22025
22719
  push(env.NVM_BIN);
22026
- push(highestVersionedNodeBin(join12(home, ".nvm", "versions", "node"), name));
22027
- push(highestVersionedNodeBin(join12(home, ".local", "share", "mise", "installs", "node"), name));
22028
- push(highestVersionedNodeBin(join12(home, ".asdf", "installs", "nodejs"), name));
22029
- push(join12(home, ".volta", "bin"));
22030
- push(join12(home, ".asdf", "shims"));
22031
- const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin", join12(home, ".local", "bin")]);
22720
+ push(highestVersionedNodeBin(join11(home, ".nvm", "versions", "node"), name));
22721
+ push(highestVersionedNodeBin(join11(home, ".local", "share", "mise", "installs", "node"), name));
22722
+ push(highestVersionedNodeBin(join11(home, ".asdf", "installs", "nodejs"), name));
22723
+ push(join11(home, ".volta", "bin"));
22724
+ push(join11(home, ".asdf", "shims"));
22725
+ const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin", join11(home, ".local", "bin")]);
22032
22726
  for (const dir of systemDirs)
22033
22727
  push(dir);
22034
22728
  }
@@ -22038,12 +22732,12 @@ function resolveNpm(deps = defaultDeps()) {
22038
22732
  const name = npmBinaryName(deps.platform);
22039
22733
  const onPath = npmFromPath(deps);
22040
22734
  if (onPath)
22041
- return { command: join12(onPath, name), binDir: onPath };
22735
+ return { command: join11(onPath, name), binDir: onPath };
22042
22736
  const adjacent = npmAdjacentToNode(deps);
22043
22737
  if (adjacent)
22044
- return { command: join12(adjacent, name), binDir: adjacent };
22738
+ return { command: join11(adjacent, name), binDir: adjacent };
22045
22739
  for (const dir of wellKnownNpmDirs(deps)) {
22046
- const candidate = join12(dir, name);
22740
+ const candidate = join11(dir, name);
22047
22741
  if (isFile(candidate))
22048
22742
  return { command: candidate, binDir: dir };
22049
22743
  }
@@ -22052,15 +22746,15 @@ function resolveNpm(deps = defaultDeps()) {
22052
22746
  function npmCandidates(deps = defaultDeps()) {
22053
22747
  const name = npmBinaryName(deps.platform);
22054
22748
  const dirs = [
22055
- ...(deps.env.PATH ?? "").split(deps.platform === "win32" ? ";" : ":").filter(isAbsolute5),
22749
+ ...(deps.env.PATH ?? "").split(deps.platform === "win32" ? ";" : ":").filter(isAbsolute4),
22056
22750
  dirname5(deps.execPath),
22057
22751
  ...wellKnownNpmDirs(deps)
22058
22752
  ];
22059
22753
  return [...new Set(dirs)].flatMap((binDir) => {
22060
22754
  return [
22061
- join12(binDir, name),
22062
- join12(binDir, "node_modules", "npm", "bin", "npm-cli.js"),
22063
- join12(binDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
22755
+ join11(binDir, name),
22756
+ join11(binDir, "node_modules", "npm", "bin", "npm-cli.js"),
22757
+ join11(binDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
22064
22758
  ].filter(isFile).map((command) => ({ command, binDir }));
22065
22759
  });
22066
22760
  }
@@ -22229,7 +22923,7 @@ function terminateNpmProcessTree(child, invocation, env = process.env, gracePeri
22229
22923
  };
22230
22924
  child.once("exit", onChildExit);
22231
22925
  const systemRoot = env.SystemRoot ?? env.SYSTEMROOT;
22232
- const taskkill = systemRoot ? join12(systemRoot, "System32", "taskkill.exe") : "taskkill.exe";
22926
+ const taskkill = systemRoot ? join11(systemRoot, "System32", "taskkill.exe") : "taskkill.exe";
22233
22927
  try {
22234
22928
  killer = spawn(taskkill, ["/pid", String(child.pid), "/t", "/f"], {
22235
22929
  stdio: "ignore",
@@ -22363,7 +23057,7 @@ async function lspNpmInstallInvocation(npm, target, before, clock = SYSTEM_CLOCK
22363
23057
  }
22364
23058
  // ../aft-bridge/dist/lsp-npm-selection.js
22365
23059
  import { readFile, realpath, stat as stat3 } from "node:fs/promises";
22366
- import { dirname as dirname6, join as join13, resolve as resolve9 } from "node:path";
23060
+ import { dirname as dirname6, join as join12, resolve as resolve8 } from "node:path";
22367
23061
  var LSP_NPM_REFUSAL = "AFT can't install language servers with the npm at <path> (<reason>). Put a real npm 7 or newer first on PATH; pinning a server version won't help.";
22368
23062
  function lspNpmRefusal(path, reason) {
22369
23063
  return LSP_NPM_REFUSAL.replace("<path>", path).replace("<reason>", reason);
@@ -22378,13 +23072,13 @@ async function genuineNpm(candidate) {
22378
23072
  const windowsShim = /\.(?:cmd|bat)$/i.test(executable);
22379
23073
  let current = dirname6(executable);
22380
23074
  if (windowsShim)
22381
- current = join13(current, "node_modules", "npm");
23075
+ current = join12(current, "node_modules", "npm");
22382
23076
  for (;; ) {
22383
23077
  try {
22384
- const pkg = JSON.parse(await readFile(join13(current, "package.json"), "utf8"));
23078
+ const pkg = JSON.parse(await readFile(join12(current, "package.json"), "utf8"));
22385
23079
  const bin = typeof pkg.bin === "string" ? pkg.bin : pkg.bin?.npm;
22386
23080
  if (pkg.name === "npm" && typeof bin === "string") {
22387
- const cli = await realpath(resolve9(current, bin));
23081
+ const cli = await realpath(resolve8(current, bin));
22388
23082
  if (!windowsShim && cli !== executable)
22389
23083
  return { reason: "not npm: command is not npm's declared CLI" };
22390
23084
  const major = /^(\d+)\.\d+\.\d+$/.exec(pkg.version)?.[1];
@@ -22393,7 +23087,7 @@ async function genuineNpm(candidate) {
22393
23087
  if (Number(major) < 7)
22394
23088
  return { reason: `old npm: ${pkg.version} (requires npm 7 or newer)` };
22395
23089
  if (windowsShim || process.platform === "win32" && /\.[cm]?js$/i.test(cli)) {
22396
- const node = join13(candidate.binDir ?? dirname6(executable), "node.exe");
23090
+ const node = join12(candidate.binDir ?? dirname6(executable), "node.exe");
22397
23091
  if (!(await stat3(node)).isFile())
22398
23092
  return { reason: "probe failed: adjacent Node is missing" };
22399
23093
  return { npm: { command: node, binDir: dirname6(node), cliPath: cli }, reason: "" };
@@ -22485,12 +23179,12 @@ function shouldInterruptWaitsForMessage(detachOnUserMessage, operatorText) {
22485
23179
  // ../aft-bridge/dist/migration.js
22486
23180
  import { closeSync as closeSync8, existsSync as existsSync9, mkdirSync as mkdirSync5, openSync as openSync7, readFileSync as readFileSync8, renameSync as renameSync5, rmSync as rmSync3, statSync as statSync8, unlinkSync as unlinkSync4, writeFileSync as writeFileSync4 } from "node:fs";
22487
23181
  import { homedir as homedir10, tmpdir as tmpdir3 } from "node:os";
22488
- import { basename as basename2, dirname as dirname9, join as join16, resolve as resolve11 } from "node:path";
23182
+ import { basename as basename2, dirname as dirname9, join as join15, resolve as resolve10 } from "node:path";
22489
23183
 
22490
23184
  // ../aft-bridge/dist/paths.js
22491
23185
  import { existsSync as existsSync7, readFileSync as readFileSync6, realpathSync as realpathSync5, renameSync as renameSync4, writeFileSync as writeFileSync3 } from "node:fs";
22492
23186
  import { homedir as homedir8 } from "node:os";
22493
- import { dirname as dirname7, isAbsolute as isAbsolute6, join as join14, resolve as resolve10 } from "node:path";
23187
+ import { dirname as dirname7, isAbsolute as isAbsolute5, join as join13, resolve as resolve9 } from "node:path";
22494
23188
  function homeDir3() {
22495
23189
  if (process.platform === "win32")
22496
23190
  return process.env.USERPROFILE || process.env.HOME || homedir8();
@@ -22498,18 +23192,18 @@ function homeDir3() {
22498
23192
  }
22499
23193
  function configHome() {
22500
23194
  const xdg = process.env.XDG_CONFIG_HOME;
22501
- if (xdg && isAbsolute6(xdg))
23195
+ if (xdg && isAbsolute5(xdg))
22502
23196
  return xdg;
22503
- return join14(homeDir3(), ".config");
23197
+ return join13(homeDir3(), ".config");
22504
23198
  }
22505
23199
  function legacyOpenCodeConfigDir() {
22506
23200
  const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
22507
23201
  if (envDir)
22508
- return resolve10(envDir);
22509
- return join14(configHome(), "opencode");
23202
+ return resolve9(envDir);
23203
+ return join13(configHome(), "opencode");
22510
23204
  }
22511
23205
  function legacyPiAgentDir() {
22512
- return join14(homeDir3(), ".pi", "agent");
23206
+ return join13(homeDir3(), ".pi", "agent");
22513
23207
  }
22514
23208
  function legacySources(basePath, label, harness) {
22515
23209
  return [
@@ -22518,10 +23212,10 @@ function legacySources(basePath, label, harness) {
22518
23212
  ];
22519
23213
  }
22520
23214
  function resolveCortexKitUserConfigPath() {
22521
- return join14(configHome(), "cortexkit", "aft.jsonc");
23215
+ return join13(configHome(), "cortexkit", "aft.jsonc");
22522
23216
  }
22523
23217
  function resolveCortexKitProjectConfigPath(projectDirectory) {
22524
- return join14(projectDirectory, ".cortexkit", "aft.jsonc");
23218
+ return join13(projectDirectory, ".cortexkit", "aft.jsonc");
22525
23219
  }
22526
23220
  function resolveProjectConfigReadPath(projectDirectory, operatingHarness) {
22527
23221
  const canonical = resolveCortexKitProjectConfigPath(projectDirectory);
@@ -22548,14 +23242,14 @@ function resolveCortexKitConfigPaths(projectDirectory) {
22548
23242
  }
22549
23243
  function resolveLegacyAftConfigSources(projectDirectory) {
22550
23244
  const project = [
22551
- ...legacySources(join14(projectDirectory, ".opencode", "aft"), "OpenCode project", "opencode"),
22552
- ...legacySources(join14(projectDirectory, ".pi", "aft"), "Pi project", "pi")
23245
+ ...legacySources(join13(projectDirectory, ".opencode", "aft"), "OpenCode project", "opencode"),
23246
+ ...legacySources(join13(projectDirectory, ".pi", "aft"), "Pi project", "pi")
22553
23247
  ];
22554
23248
  const identity = (path) => {
22555
23249
  try {
22556
23250
  return realpathSync5(path);
22557
23251
  } catch {
22558
- return resolve10(path);
23252
+ return resolve9(path);
22559
23253
  }
22560
23254
  };
22561
23255
  const protectedPaths = new Set([
@@ -22564,18 +23258,18 @@ function resolveLegacyAftConfigSources(projectDirectory) {
22564
23258
  ].map(identity));
22565
23259
  return {
22566
23260
  user: [
22567
- ...legacySources(join14(legacyOpenCodeConfigDir(), "aft"), "OpenCode user", "opencode"),
22568
- ...legacySources(join14(legacyPiAgentDir(), "aft"), "Pi user", "pi")
23261
+ ...legacySources(join13(legacyOpenCodeConfigDir(), "aft"), "OpenCode user", "opencode"),
23262
+ ...legacySources(join13(legacyPiAgentDir(), "aft"), "Pi user", "pi")
22569
23263
  ].filter((source) => !protectedPaths.has(identity(source.path))),
22570
23264
  project
22571
23265
  };
22572
23266
  }
22573
23267
  function resolveHarnessStoragePath(storageRoot, harness, ...segments) {
22574
- return join14(storageRoot, harness, ...segments);
23268
+ return join13(storageRoot, harness, ...segments);
22575
23269
  }
22576
23270
  function repairRootScopedStorageFile(storageRoot, harness, fileName) {
22577
23271
  const harnessPath = resolveHarnessStoragePath(storageRoot, harness, fileName);
22578
- const rootPath = join14(storageRoot, fileName);
23272
+ const rootPath = join13(storageRoot, fileName);
22579
23273
  if (existsSync7(harnessPath) || !existsSync7(rootPath))
22580
23274
  return harnessPath;
22581
23275
  try {
@@ -22664,15 +23358,15 @@ function decodeFileUrl(target) {
22664
23358
  import { closeSync as closeSync7, existsSync as existsSync8, promises as fsPromises, openSync as openSync6, readFileSync as readFileSync7, readSync as readSync6 } from "node:fs";
22665
23359
  import { createRequire as createRequire2 } from "node:module";
22666
23360
  import { homedir as homedir9 } from "node:os";
22667
- import { delimiter, dirname as dirname8, isAbsolute as isAbsolute7, join as join15 } from "node:path";
23361
+ import { delimiter, dirname as dirname8, isAbsolute as isAbsolute6, join as join14 } from "node:path";
22668
23362
  var ensureBinaryForResolver = ensureBinary;
22669
23363
  var npmPlatformPackageReader = null;
22670
23364
  var cacheCopiesInFlight = new Map;
22671
23365
  function copyToVersionedCache(npmBinaryPath, version) {
22672
23366
  const tag = version.startsWith("v") ? version : `v${version}`;
22673
23367
  const ext = process.platform === "win32" ? ".exe" : "";
22674
- const versionedDir = join15(getAftBinaryCacheDir(), tag);
22675
- const cachedPath = join15(versionedDir, `aft${ext}`);
23368
+ const versionedDir = join14(getAftBinaryCacheDir(), tag);
23369
+ const cachedPath = join14(versionedDir, `aft${ext}`);
22676
23370
  if (existsSync8(cachedPath) && isTrustedCachedBinary(cachedPath, version))
22677
23371
  return { cachedPath };
22678
23372
  const existing = cacheCopiesInFlight.get(cachedPath);
@@ -22718,7 +23412,7 @@ function homeDirFromEnv(env) {
22718
23412
  return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir9();
22719
23413
  }
22720
23414
  function cachedBinaryPathFromEnv(version, env, ext) {
22721
- const binaryPath = join15(getAftBinaryCacheDir(env), version, `aft${ext}`);
23415
+ const binaryPath = join14(getAftBinaryCacheDir(env), version, `aft${ext}`);
22722
23416
  return existsSync8(binaryPath) ? binaryPath : null;
22723
23417
  }
22724
23418
  async function probeBinaryCandidateOffThread(binaryPath, source, expectedVersion) {
@@ -22738,9 +23432,9 @@ function pathCandidates(env, ext) {
22738
23432
  const seen = new Set;
22739
23433
  const candidates = [];
22740
23434
  for (const dir of rawPath.split(delimiter)) {
22741
- if (!dir || !isAbsolute7(dir))
23435
+ if (!dir || !isAbsolute6(dir))
22742
23436
  continue;
22743
- const candidate = join15(dir, `aft${ext}`);
23437
+ const candidate = join14(dir, `aft${ext}`);
22744
23438
  if (seen.has(candidate))
22745
23439
  continue;
22746
23440
  seen.add(candidate);
@@ -22818,7 +23512,7 @@ function npmPlatformPackage(ext) {
22818
23512
  const req = createRequire2(import.meta.url);
22819
23513
  const manifestPath = req.resolve(`@cortexkit/aft-${platformKey()}/package.json`);
22820
23514
  const manifest = JSON.parse(readFileSync7(manifestPath, "utf8"));
22821
- const binaryPath = join15(dirname8(manifestPath), "bin", `aft${ext}`);
23515
+ const binaryPath = join14(dirname8(manifestPath), "bin", `aft${ext}`);
22822
23516
  if (typeof manifest.version !== "string" || !existsSync8(binaryPath))
22823
23517
  return null;
22824
23518
  return { binaryPath, version: normalizeBareVersion(manifest.version) };
@@ -22885,7 +23579,7 @@ async function findProbedBinary(expectedVersion, env) {
22885
23579
  if (usable)
22886
23580
  return { path: usable, source: "PATH" };
22887
23581
  }
22888
- const cargoPath = join15(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
23582
+ const cargoPath = join14(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
22889
23583
  if (existsSync8(cargoPath)) {
22890
23584
  const usable = await probeBinaryCandidateOffThread(cargoPath, "cargo", pluginVersion);
22891
23585
  if (usable)
@@ -22984,9 +23678,9 @@ function dataHome() {
22984
23678
  if (process.env.XDG_DATA_HOME)
22985
23679
  return process.env.XDG_DATA_HOME;
22986
23680
  if (process.platform === "win32") {
22987
- return process.env.LOCALAPPDATA || process.env.APPDATA || join16(homeDir4(), "AppData", "Local");
23681
+ return process.env.LOCALAPPDATA || process.env.APPDATA || join15(homeDir4(), "AppData", "Local");
22988
23682
  }
22989
- return join16(homeDir4(), ".local", "share");
23683
+ return join15(homeDir4(), ".local", "share");
22990
23684
  }
22991
23685
  function homeDir4() {
22992
23686
  if (process.platform === "win32")
@@ -22995,8 +23689,8 @@ function homeDir4() {
22995
23689
  }
22996
23690
  function resolveLegacyStorageRoot(harness) {
22997
23691
  if (harness === "pi")
22998
- return join16(homeDir4(), ".pi", "agent", "aft");
22999
- return join16(dataHome(), "opencode", "storage", "plugin", "aft");
23692
+ return join15(homeDir4(), ".pi", "agent", "aft");
23693
+ return join15(dataHome(), "opencode", "storage", "plugin", "aft");
23000
23694
  }
23001
23695
  function stripJsoncForParse(input) {
23002
23696
  let out = "";
@@ -23126,7 +23820,7 @@ function acquireConfigMigrationLock(lockDir) {
23126
23820
  }
23127
23821
  function atomicCopyConfigFile(sourcePath, targetPath) {
23128
23822
  mkdirSync5(dirname9(targetPath), { recursive: true });
23129
- const tmpPath = join16(dirname9(targetPath), `.${basename2(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
23823
+ const tmpPath = join15(dirname9(targetPath), `.${basename2(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
23130
23824
  let fd = null;
23131
23825
  try {
23132
23826
  fd = openSync7(tmpPath, "wx", 384);
@@ -23148,7 +23842,7 @@ function atomicCopyConfigFile(sourcePath, targetPath) {
23148
23842
  }
23149
23843
  function atomicWriteConfigFile(targetPath, content) {
23150
23844
  mkdirSync5(dirname9(targetPath), { recursive: true });
23151
- const tmpPath = join16(dirname9(targetPath), `.${basename2(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
23845
+ const tmpPath = join15(dirname9(targetPath), `.${basename2(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
23152
23846
  let fd = null;
23153
23847
  try {
23154
23848
  fd = openSync7(tmpPath, "wx", 384);
@@ -23267,8 +23961,8 @@ function visibleConfigMigrationWarning(scope, targetPath, paths, reason) {
23267
23961
  }
23268
23962
  function migrateAftConfigFile(opts) {
23269
23963
  const warnings = [];
23270
- const resolvedTarget = resolve11(opts.targetPath);
23271
- const existingSources = opts.legacySources.filter((source) => existsSync9(source.path) && resolve11(source.path) !== resolvedTarget);
23964
+ const resolvedTarget = resolve10(opts.targetPath);
23965
+ const existingSources = opts.legacySources.filter((source) => existsSync9(source.path) && resolve10(source.path) !== resolvedTarget);
23272
23966
  const info = opts.logger?.info ?? opts.logger?.log;
23273
23967
  if (existingSources.length === 0) {
23274
23968
  return { migrated: false, conflict: false, targetPath: opts.targetPath, warnings };
@@ -23330,12 +24024,12 @@ function spawnErrorLabel(error) {
23330
24024
  return [code, error.message].filter(Boolean).join(": ");
23331
24025
  }
23332
24026
  function migrationLogPath(newRoot, harness, logger) {
23333
- const desired = join16(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
24027
+ const desired = join15(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
23334
24028
  try {
23335
24029
  mkdirSync5(dirname9(desired), { recursive: true });
23336
24030
  return desired;
23337
24031
  } catch (err) {
23338
- const fallback = join16(tmpdir3(), `aft-migration-${harness}-${Date.now()}.jsonl`);
24032
+ const fallback = join15(tmpdir3(), `aft-migration-${harness}-${Date.now()}.jsonl`);
23339
24033
  logger?.warn?.(`Failed to create AFT migration log directory ${dirname9(desired)}: ${err instanceof Error ? err.message : String(err)}. ` + `Using fallback log path ${fallback}.`);
23340
24034
  return fallback;
23341
24035
  }
@@ -23395,13 +24089,13 @@ async function ensureStorageMigrated(opts) {
23395
24089
  // ../aft-bridge/dist/migration-notices.js
23396
24090
  import { readFileSync as readFileSync9, renameSync as renameSync6, rmdirSync, statSync as statSync9, writeFileSync as writeFileSync5 } from "node:fs";
23397
24091
  import { homedir as homedir11 } from "node:os";
23398
- import { dirname as dirname10, join as join17, resolve as resolve12 } from "node:path";
24092
+ import { dirname as dirname10, join as join16, resolve as resolve11 } from "node:path";
23399
24093
  function migrationNoticeStorePath(env = process.env) {
23400
- const stateHome = env.XDG_STATE_HOME && env.XDG_STATE_HOME.length > 0 ? env.XDG_STATE_HOME : join17(homedir11(), ".local", "state");
23401
- return join17(stateHome, "cortexkit", "aft", "migration-notices.json");
24094
+ const stateHome = env.XDG_STATE_HOME && env.XDG_STATE_HOME.length > 0 ? env.XDG_STATE_HOME : join16(homedir11(), ".local", "state");
24095
+ return join16(stateHome, "cortexkit", "aft", "migration-notices.json");
23402
24096
  }
23403
24097
  function noticeKey(configPath, digest) {
23404
- return `${resolve12(configPath)}|${MIGRATION_POLICY_ID}|${digest}`;
24098
+ return `${resolve11(configPath)}|${MIGRATION_POLICY_ID}|${digest}`;
23405
24099
  }
23406
24100
  function readRecords(storePath) {
23407
24101
  try {
@@ -23595,7 +24289,7 @@ function probeOnnxRuntimeLoadable(libPath, arch = process.arch) {
23595
24289
  // ../aft-bridge/dist/onnx-runtime.js
23596
24290
  import { randomBytes as randomBytes3 } from "node:crypto";
23597
24291
  import { chmodSync as chmodSync2, closeSync as closeSync10, copyFileSync as copyFileSync4, createWriteStream as createWriteStream3, existsSync as existsSync11, lstatSync as lstatSync3, openSync as openSync9, readdirSync as readdirSync4, readFileSync as readFileSync10, readlinkSync as readlinkSync2, realpathSync as realpathSync7, renameSync as renameSync7, rmSync as rmSync4, statSync as statSync10, symlinkSync, unlinkSync as unlinkSync5, writeFileSync as writeFileSync6 } from "node:fs";
23598
- import { basename as basename3, dirname as dirname11, isAbsolute as isAbsolute8, join as join18, relative as relative5, resolve as resolve13, win32 as win323 } from "node:path";
24292
+ import { basename as basename3, dirname as dirname11, isAbsolute as isAbsolute7, join as join17, relative as relative4, resolve as resolve12, win32 as win324 } from "node:path";
23599
24293
  import { Readable as Readable3 } from "node:stream";
23600
24294
  import { pipeline as pipeline3 } from "node:stream/promises";
23601
24295
  var ORT_VERSION = "1.24.4";
@@ -23686,7 +24380,7 @@ function resolveOnnxRuntime(storageDir, seams) {
23686
24380
  }
23687
24381
  async function findCachedOnnxRuntime(ortVersionDir, libName) {
23688
24382
  const resolvedOrtDir = resolveCachedOnnxRuntimeDir(ortVersionDir, libName);
23689
- const libPath = join18(resolvedOrtDir, libName);
24383
+ const libPath = join17(resolvedOrtDir, libName);
23690
24384
  if (existsSync11(libPath)) {
23691
24385
  const meta = readOnnxInstalledMeta(ortVersionDir);
23692
24386
  if (meta?.sha256) {
@@ -23711,7 +24405,7 @@ async function findCachedOnnxRuntime(ortVersionDir, libName) {
23711
24405
  }
23712
24406
  async function resolveOnnxRuntimeUncoalesced(storageDir, seams) {
23713
24407
  const info = seams.platformInfo !== undefined ? seams.platformInfo : getPlatformInfo();
23714
- const ortVersionDir = join18(storageDir, "onnxruntime", ORT_VERSION);
24408
+ const ortVersionDir = join17(storageDir, "onnxruntime", ORT_VERSION);
23715
24409
  const libName = info?.libName ?? "libonnxruntime.dylib";
23716
24410
  const cached = await findCachedOnnxRuntime(ortVersionDir, libName);
23717
24411
  if (cached)
@@ -23725,9 +24419,9 @@ async function resolveOnnxRuntimeUncoalesced(storageDir, seams) {
23725
24419
  warn(`ONNX Runtime auto-download not available for ${process.platform}/${process.arch}. Install manually: ${getManualInstallHint()}`);
23726
24420
  return null;
23727
24421
  }
23728
- const onnxBaseDir = join18(storageDir, "onnxruntime");
24422
+ const onnxBaseDir = join17(storageDir, "onnxruntime");
23729
24423
  openPrivateStorageDir(storageDir, onnxBaseDir);
23730
- const lockPath = join18(onnxBaseDir, ONNX_LOCK_FILE);
24424
+ const lockPath = join17(onnxBaseDir, ONNX_LOCK_FILE);
23731
24425
  const pollMs = seams.lockPollMs ?? LOCK_POLL_MS;
23732
24426
  const deadline = Date.now() + LOCK_WAIT_MS;
23733
24427
  let announcedWait = false;
@@ -23772,7 +24466,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
23772
24466
  for (const entry of entries) {
23773
24467
  if (!entry.startsWith(`${ORT_VERSION}.tmp.`))
23774
24468
  continue;
23775
- const stagingDir = join18(onnxBaseDir, entry);
24469
+ const stagingDir = join17(onnxBaseDir, entry);
23776
24470
  const parts = entry.split(".");
23777
24471
  const pidStr = parts[parts.length - 2];
23778
24472
  const pid = pidStr ? Number.parseInt(pidStr, 10) : NaN;
@@ -23809,7 +24503,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
23809
24503
  }
23810
24504
  function cleanupIncompleteTargetIfUnowned(ortDir) {
23811
24505
  try {
23812
- if (existsSync11(ortDir) && !existsSync11(join18(ortDir, ONNX_INSTALLED_META_FILE))) {
24506
+ if (existsSync11(ortDir) && !existsSync11(join17(ortDir, ONNX_INSTALLED_META_FILE))) {
23813
24507
  log(`[onnx] removing half-populated install dir ${ortDir} (no meta file)`);
23814
24508
  rmSync4(ortDir, { recursive: true, force: true });
23815
24509
  }
@@ -23837,14 +24531,14 @@ function parseOnnxVersionFromDirectoryPath(value) {
23837
24531
  return null;
23838
24532
  }
23839
24533
  function isPathInsideRoot(root, candidate) {
23840
- const rel = relative5(root, candidate);
23841
- return rel === "" || !rel.startsWith("../") && !rel.startsWith("..\\") && rel !== ".." && !isAbsolute8(rel) && !win323.isAbsolute(rel);
24534
+ const rel = relative4(root, candidate);
24535
+ return rel === "" || !rel.startsWith("../") && !rel.startsWith("..\\") && rel !== ".." && !isAbsolute7(rel) && !win324.isAbsolute(rel);
23842
24536
  }
23843
24537
  function detectOnnxVersion(libDir, libName) {
23844
24538
  try {
23845
24539
  const entries = readdirSync4(libDir);
23846
24540
  try {
23847
- const resolved = parseOnnxVersionFromPath(realpathSync7(join18(libDir, libName)));
24541
+ const resolved = parseOnnxVersionFromPath(realpathSync7(join17(libDir, libName)));
23848
24542
  if (resolved && resolved !== INVALID_ORT_VERSION)
23849
24543
  return resolved;
23850
24544
  } catch {}
@@ -23858,7 +24552,7 @@ function detectOnnxVersion(libDir, libName) {
23858
24552
  if (version)
23859
24553
  return version;
23860
24554
  }
23861
- const base = join18(libDir, libName);
24555
+ const base = join17(libDir, libName);
23862
24556
  if (existsSync11(base)) {
23863
24557
  try {
23864
24558
  const real = realpathSync7(base);
@@ -23898,18 +24592,18 @@ function pathEntriesForPlatform() {
23898
24592
  return pathEnvValue().split(delimiter).map((entry) => entry.trim().replace(/^"|"$/g, "")).filter((entry) => {
23899
24593
  if (!entry || entry === "." || entry.includes("\x00"))
23900
24594
  return false;
23901
- return isAbsolute8(entry) || win323.isAbsolute(entry);
24595
+ return isAbsolute7(entry) || win324.isAbsolute(entry);
23902
24596
  });
23903
24597
  }
23904
24598
  function isWindowsSystem32Directory(dir) {
23905
24599
  if (process.platform !== "win32")
23906
24600
  return false;
23907
- const normalizedDir = win323.resolve(dir).replace(/[\\/]+$/, "").toLowerCase();
24601
+ const normalizedDir = win324.resolve(dir).replace(/[\\/]+$/, "").toLowerCase();
23908
24602
  const windowsRoots = [process.env.SystemRoot, process.env.windir, "C:\\Windows"];
23909
24603
  return windowsRoots.some((root) => {
23910
24604
  if (!root)
23911
24605
  return false;
23912
- return normalizedDir === win323.resolve(root, "System32").replace(/[\\/]+$/, "").toLowerCase();
24606
+ return normalizedDir === win324.resolve(root, "System32").replace(/[\\/]+$/, "").toLowerCase();
23913
24607
  });
23914
24608
  }
23915
24609
  function directoryContainsLibrary(dir, libName) {
@@ -23925,10 +24619,10 @@ function directoryContainsLibrary(dir, libName) {
23925
24619
  }
23926
24620
  }
23927
24621
  function resolveCachedOnnxRuntimeDir(ortVersionDir, libName) {
23928
- if (existsSync11(join18(ortVersionDir, libName)))
24622
+ if (existsSync11(join17(ortVersionDir, libName)))
23929
24623
  return ortVersionDir;
23930
- const libSubdir = join18(ortVersionDir, "lib");
23931
- if (existsSync11(join18(libSubdir, libName)))
24624
+ const libSubdir = join17(ortVersionDir, "lib");
24625
+ if (existsSync11(join17(libSubdir, libName)))
23932
24626
  return libSubdir;
23933
24627
  return ortVersionDir;
23934
24628
  }
@@ -23943,12 +24637,12 @@ function findSystemOnnxRuntime(libName, searchPathsOverride) {
23943
24637
  } else if (process.platform === "win32") {
23944
24638
  const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
23945
24639
  const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
23946
- searchPaths.push(join18(programFiles, "onnxruntime", "lib"), join18(programFiles, "Microsoft ONNX Runtime", "lib"), join18(programFiles, "Microsoft Machine Learning", "lib"), join18(programFilesX86, "onnxruntime", "lib"), ...(() => {
24640
+ searchPaths.push(join17(programFiles, "onnxruntime", "lib"), join17(programFiles, "Microsoft ONNX Runtime", "lib"), join17(programFiles, "Microsoft Machine Learning", "lib"), join17(programFilesX86, "onnxruntime", "lib"), ...(() => {
23947
24641
  const nugetPaths = [];
23948
24642
  const userProfile = process.env.USERPROFILE ?? "";
23949
24643
  if (!userProfile)
23950
24644
  return nugetPaths;
23951
- const nugetPackageDir = join18(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
24645
+ const nugetPackageDir = join17(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
23952
24646
  if (!existsSync11(nugetPackageDir))
23953
24647
  return nugetPaths;
23954
24648
  try {
@@ -23957,7 +24651,7 @@ function findSystemOnnxRuntime(libName, searchPathsOverride) {
23957
24651
  continue;
23958
24652
  if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
23959
24653
  continue;
23960
- nugetPaths.push(join18(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join18(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
24654
+ nugetPaths.push(join17(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join17(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
23961
24655
  }
23962
24656
  } catch (err) {
23963
24657
  warn(`Failed to scan NuGet ONNX Runtime cache ${nugetPackageDir}: ${err instanceof Error ? err.message : String(err)}`);
@@ -23969,7 +24663,7 @@ function findSystemOnnxRuntime(libName, searchPathsOverride) {
23969
24663
  const normalizeCase = process.platform === "win32" || process.platform === "darwin";
23970
24664
  const seen = new Set;
23971
24665
  const uniquePaths = searchPaths.filter((p) => {
23972
- let key = resolve13(p).replace(/[/\\]+$/, "");
24666
+ let key = resolve12(p).replace(/[/\\]+$/, "");
23973
24667
  if (normalizeCase)
23974
24668
  key = key.toLowerCase();
23975
24669
  if (seen.has(key))
@@ -23979,7 +24673,7 @@ function findSystemOnnxRuntime(libName, searchPathsOverride) {
23979
24673
  });
23980
24674
  const unknownVersionPaths = [];
23981
24675
  for (const dir of uniquePaths) {
23982
- const libPath = join18(dir, libName);
24676
+ const libPath = join17(dir, libName);
23983
24677
  if (process.platform === "win32") {
23984
24678
  if (!directoryContainsLibrary(dir, libName))
23985
24679
  continue;
@@ -24058,19 +24752,19 @@ function validateExtractedTree(stagingRoot) {
24058
24752
  const walk = (dir) => {
24059
24753
  const entries = readdirSync4(dir);
24060
24754
  for (const entry of entries) {
24061
- const fullPath = join18(dir, entry);
24755
+ const fullPath = join17(dir, entry);
24062
24756
  const lst = lstatSync3(fullPath);
24063
24757
  if (lst.isSymbolicLink()) {
24064
24758
  const linkTarget = readlinkSync2(fullPath);
24065
- const resolvedTarget = resolve13(dirname11(fullPath), linkTarget);
24066
- const rel = relative5(realRoot, resolvedTarget);
24067
- if (relativePathEscapesRoot(rel) || win323.isAbsolute(rel)) {
24759
+ const resolvedTarget = resolve12(dirname11(fullPath), linkTarget);
24760
+ const rel = relative4(realRoot, resolvedTarget);
24761
+ if (relativePathEscapesRoot(rel) || win324.isAbsolute(rel)) {
24068
24762
  throw new Error(`extracted symlink ${fullPath} points outside staging root: ${linkTarget}`);
24069
24763
  }
24070
24764
  continue;
24071
24765
  }
24072
- const rel = relative5(realRoot, fullPath);
24073
- if (relativePathEscapesRoot(rel) || win323.isAbsolute(rel)) {
24766
+ const rel = relative4(realRoot, fullPath);
24767
+ if (relativePathEscapesRoot(rel) || win324.isAbsolute(rel)) {
24074
24768
  throw new Error(`extracted entry ${fullPath} escapes staging root`);
24075
24769
  }
24076
24770
  if (lst.isDirectory()) {
@@ -24095,11 +24789,11 @@ async function downloadOnnxRuntime(info, targetDir) {
24095
24789
  const url = `https://github.com/${ORT_REPO}/releases/download/v${ORT_VERSION}/${info.assetName}.${info.archiveType === "tgz" ? "tgz" : "zip"}`;
24096
24790
  log(`Downloading ONNX Runtime v${ORT_VERSION} for ${process.platform}/${process.arch}...`);
24097
24791
  const tmpDir = `${targetDir}.tmp.${process.pid}.${Date.now().toString(36)}${randomBytes3(4).toString("hex")}`;
24098
- const extractionRoot = join18(tmpDir, "extract");
24099
- const stagedInstallDir = join18(tmpDir, "install");
24792
+ const extractionRoot = join17(tmpDir, "extract");
24793
+ const stagedInstallDir = join17(tmpDir, "install");
24100
24794
  try {
24101
24795
  privateMkdirSync(extractionRoot);
24102
- const archivePath = join18(tmpDir, `onnxruntime.${info.archiveType}`);
24796
+ const archivePath = join17(tmpDir, `onnxruntime.${info.archiveType}`);
24103
24797
  await downloadFileWithCap(url, archivePath);
24104
24798
  const archiveSha256 = await sha256File(archivePath);
24105
24799
  log(`ONNX Runtime archive sha256=${archiveSha256}`);
@@ -24112,7 +24806,7 @@ async function downloadOnnxRuntime(info, targetDir) {
24112
24806
  unlinkSync5(archivePath);
24113
24807
  } catch {}
24114
24808
  validateExtractedTree(extractionRoot);
24115
- const extractedDir = join18(extractionRoot, info.assetName, "lib");
24809
+ const extractedDir = join17(extractionRoot, info.assetName, "lib");
24116
24810
  if (!existsSync11(extractedDir)) {
24117
24811
  throw new Error(`Expected directory not found: ${extractedDir}`);
24118
24812
  }
@@ -24120,7 +24814,7 @@ async function downloadOnnxRuntime(info, targetDir) {
24120
24814
  const realFiles = [];
24121
24815
  const symlinks = [];
24122
24816
  for (const libFile of libFiles) {
24123
- const src = join18(extractedDir, libFile);
24817
+ const src = join17(extractedDir, libFile);
24124
24818
  try {
24125
24819
  const stat = lstatSync3(src);
24126
24820
  log(`ORT extract: ${libFile} — isSymlink=${stat.isSymbolicLink()}, isFile=${stat.isFile()}, size=${stat.size}`);
@@ -24135,14 +24829,14 @@ async function downloadOnnxRuntime(info, targetDir) {
24135
24829
  }
24136
24830
  }
24137
24831
  copyOnnxLibraries(info, extractedDir, stagedInstallDir, realFiles, symlinks);
24138
- const libPath = join18(stagedInstallDir, info.libName);
24832
+ const libPath = join17(stagedInstallDir, info.libName);
24139
24833
  const libHash = await sha256File(libPath);
24140
24834
  if (libHash !== info.librarySha256) {
24141
24835
  throw new Error(`onnx runtime library hash mismatch at ${libPath}: sha256 ${libHash}, ` + `expected the pinned ${info.librarySha256} for ${info.assetName}`);
24142
24836
  }
24143
24837
  writeOnnxInstalledMeta(stagedInstallDir, ORT_VERSION, libHash, archiveSha256);
24144
24838
  publishOnnxRuntime(stagedInstallDir, targetDir);
24145
- writeStampedFileDigest(join18(targetDir, info.libName), libHash);
24839
+ writeStampedFileDigest(join17(targetDir, info.libName), libHash);
24146
24840
  rmSync4(tmpDir, { recursive: true, force: true });
24147
24841
  log(`ONNX Runtime v${ORT_VERSION} installed to ${targetDir}`);
24148
24842
  return targetDir;
@@ -24184,8 +24878,8 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
24184
24878
  const requiredLibs = new Set([info.libName]);
24185
24879
  privateMkdirSync(targetDir);
24186
24880
  for (const libFile of realFiles) {
24187
- const src = join18(extractedDir, libFile);
24188
- const dst = join18(targetDir, libFile);
24881
+ const src = join17(extractedDir, libFile);
24882
+ const dst = join17(targetDir, libFile);
24189
24883
  try {
24190
24884
  if (copyFile === copyFileSync4)
24191
24885
  privateCopyFileSync(src, dst);
@@ -24204,12 +24898,12 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
24204
24898
  }
24205
24899
  const targetRoot = realpathSync7(targetDir);
24206
24900
  for (const link of symlinks) {
24207
- const dst = join18(targetDir, link.name);
24901
+ const dst = join17(targetDir, link.name);
24208
24902
  try {
24209
24903
  unlinkSync5(dst);
24210
24904
  } catch {}
24211
- const dstForContainment = join18(targetRoot, link.name);
24212
- const resolvedTarget = resolve13(dirname11(dstForContainment), link.target);
24905
+ const dstForContainment = join17(targetRoot, link.name);
24906
+ const resolvedTarget = resolve12(dirname11(dstForContainment), link.target);
24213
24907
  if (!isPathInsideRoot(targetRoot, resolvedTarget)) {
24214
24908
  const message = `ONNX Runtime symlink ${link.name} points outside install dir: ${link.target}`;
24215
24909
  if (requiredLibs.has(link.name)) {
@@ -24229,7 +24923,7 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
24229
24923
  log(`ORT extract: failed to symlink optional ${link.name}: ${symlinkErr}`);
24230
24924
  }
24231
24925
  }
24232
- const requiredPath = join18(targetDir, info.libName);
24926
+ const requiredPath = join17(targetDir, info.libName);
24233
24927
  if (!existsSync11(requiredPath)) {
24234
24928
  rmSync4(targetDir, { recursive: true, force: true });
24235
24929
  throw new Error(`Required ONNX Runtime library missing after install: ${requiredPath}`);
@@ -24257,7 +24951,7 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
24257
24951
  ...sha256 ? { sha256 } : {},
24258
24952
  archiveSha256
24259
24953
  };
24260
- writeFileSync6(join18(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), {
24954
+ writeFileSync6(join17(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), {
24261
24955
  encoding: "utf8",
24262
24956
  mode: PRIVATE_FILE_MODE
24263
24957
  });
@@ -24266,7 +24960,7 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
24266
24960
  }
24267
24961
  }
24268
24962
  function readOnnxInstalledMeta(installDir) {
24269
- const path = join18(installDir, ONNX_INSTALLED_META_FILE);
24963
+ const path = join17(installDir, ONNX_INSTALLED_META_FILE);
24270
24964
  try {
24271
24965
  if (!statSync10(path).isFile())
24272
24966
  return null;
@@ -25071,7 +25765,7 @@ function formatSemanticIndexStatus(status, stage, error, backend) {
25071
25765
  // src/config.ts
25072
25766
  import { existsSync as existsSync12, readFileSync as readFileSync11, statSync as statSync11 } from "node:fs";
25073
25767
  import { homedir as homedir12 } from "node:os";
25074
- import { isAbsolute as isAbsolute9, parse as parsePath, resolve as resolvePath } from "node:path";
25768
+ import { isAbsolute as isAbsolute8, parse as parsePath, resolve as resolvePath } from "node:path";
25075
25769
  var import_comment_json = __toESM(require_src2(), 1);
25076
25770
 
25077
25771
  // ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/core/core.js
@@ -29957,9 +30651,9 @@ var SemanticBackendEnum = _enum(["fastembed", "openai_compatible", "ollama", "sy
29957
30651
  var IndexKindSchema = _enum(["search", "semantic", "callgraph"]);
29958
30652
  function isSupportedAbsoluteIndexPath(path) {
29959
30653
  if (path === "~" || path.startsWith("~/") || path.startsWith("~\\")) {
29960
- return isAbsolute9(homedir12());
30654
+ return isAbsolute8(homedir12());
29961
30655
  }
29962
- return isAbsolute9(path);
30656
+ return isAbsolute8(path);
29963
30657
  }
29964
30658
  var IndexRootSchema = object({
29965
30659
  path: string2().refine(isSupportedAbsoluteIndexPath, {
@@ -30016,6 +30710,7 @@ var LspServerEntrySchema = object({
30016
30710
  initialization_options: unknown().optional()
30017
30711
  });
30018
30712
  var LspConfigSchema = object({
30713
+ max_servers: number2().int().nonnegative().optional(),
30019
30714
  idle_minutes: union([
30020
30715
  number2().int().transform((value) => Math.min(1440, Math.max(5, value))),
30021
30716
  literal("never")
@@ -30099,7 +30794,7 @@ var SubcConfigSchema = object({
30099
30794
  client_reaper: boolean2().optional()
30100
30795
  });
30101
30796
  var GhShimConfigSchema = object({
30102
- binary_path: string2().trim().refine(isAbsolute9, "gh_shim.binary_path must be absolute").optional()
30797
+ binary_path: string2().trim().refine(isAbsolute8, "gh_shim.binary_path must be absolute").optional()
30103
30798
  });
30104
30799
  var RemoteExecConfigSchema = object({
30105
30800
  enabled: boolean2().optional(),
@@ -30152,13 +30847,6 @@ var IdleConfigSchema = object({
30152
30847
  root_ttl_minutes: number2().int().optional().transform((value) => value === undefined ? undefined : clampIdleRootTtlMinutes(value)),
30153
30848
  checkout_hours: number2().int().optional().transform((value) => value === undefined ? undefined : clampIdleCheckoutHours(value))
30154
30849
  });
30155
- var ViewsConfigSchema = object({
30156
- enabled: boolean2().optional(),
30157
- callgraph_copies: number2().int().optional()
30158
- });
30159
- var WorktreeConfigSchema = object({
30160
- ram_overlay: boolean2().optional()
30161
- });
30162
30850
  var BackupConfigSchema = object({
30163
30851
  enabled: boolean2().optional(),
30164
30852
  max_depth: number2().int().positive().optional(),
@@ -30184,12 +30872,10 @@ var AftConfigFieldsSchema = object({
30184
30872
  indexes: IndexesConfigSchema.optional(),
30185
30873
  index: IndexConfigSchema.optional(),
30186
30874
  storage: object({ cache_dir: string2().nullable().optional() }).optional(),
30187
- views: ViewsConfigSchema.optional(),
30188
30875
  callgraph_chunk_size: number2().optional(),
30189
30876
  inspect: InspectConfigSchema.optional(),
30190
30877
  idle: IdleConfigSchema.optional(),
30191
30878
  backup: BackupConfigSchema.optional(),
30192
- worktree: WorktreeConfigSchema.optional(),
30193
30879
  sandbox: SandboxConfigSchema.optional(),
30194
30880
  bash: BashConfigSchema.optional(),
30195
30881
  experimental: ExperimentalConfigSchema.optional(),
@@ -30472,6 +31158,9 @@ function loadConfigFromPath(configPath, tier) {
30472
31158
  throw new ConfigRejectedError(["invalid_config_document"], configPath);
30473
31159
  }
30474
31160
  const removed = removedConfigKeyErrors(cleanConfig, undefined, false);
31161
+ if (tier === "user") {
31162
+ removed.push(...removedConfigKeyErrors(cleanConfig).filter((error) => [...REMOVED_DATA_LAYER_PATHS, ...DATA_LAYER_RETIRED_PATHS].some((path) => error.endsWith(`${path}; run npx @cortexkit/aft doctor --fix`))));
31163
+ }
30475
31164
  if (removed.length) {
30476
31165
  throw new ConfigRejectedError(removed);
30477
31166
  }
@@ -30498,14 +31187,7 @@ function loadConfigFromPath(configPath, tier) {
30498
31187
  if (translation.legacyInput) {
30499
31188
  log2(`Config ${configPath} uses retired keys (${translation.retiredKeys.join(", ")}); applied their current equivalents in memory`);
30500
31189
  }
30501
- if (translation.removedKeys.length > 0) {
30502
- configLoadNotices.push({
30503
- configPath,
30504
- digest: removedConfigKeysNoticeDigest(translation),
30505
- message: removedConfigKeysNoticeMessage(configPath, translation)
30506
- });
30507
- }
30508
- } else if (translation.legacyInput || translation.removedKeys.length > 0) {
31190
+ } else if (translation.legacyInput) {
30509
31191
  configLoadNotices.push({
30510
31192
  configPath,
30511
31193
  digest: noticeDigest(projection),
@@ -30560,6 +31242,9 @@ function mergeSemanticConfig(baseSemantic, overrideSemantic) {
30560
31242
  }
30561
31243
  function mergeLspConfig(baseLsp, overrideLsp) {
30562
31244
  const projectLsp = {};
31245
+ if (overrideLsp?.max_servers !== undefined && overrideLsp.max_servers <= (baseLsp?.max_servers ?? 8)) {
31246
+ projectLsp.max_servers = overrideLsp.max_servers;
31247
+ }
30563
31248
  if (overrideLsp?.python !== undefined)
30564
31249
  projectLsp.python = overrideLsp.python;
30565
31250
  if (overrideLsp?.diagnostics_on_edit !== undefined) {
@@ -30581,15 +31266,6 @@ function mergeLspConfig(baseLsp, overrideLsp) {
30581
31266
  }
30582
31267
  return Object.fromEntries(Object.entries(lsp).filter(([, value]) => value !== undefined));
30583
31268
  }
30584
- function mergeWorktreeConfig(baseWorktree, overrideWorktree) {
30585
- if (baseWorktree === undefined && overrideWorktree === undefined)
30586
- return;
30587
- if (overrideWorktree === undefined)
30588
- return baseWorktree;
30589
- if (baseWorktree === undefined)
30590
- return overrideWorktree;
30591
- return { ...baseWorktree, ...overrideWorktree };
30592
- }
30593
31269
  function mergeIdleConfig(baseIdle, overrideIdle) {
30594
31270
  const merged = {
30595
31271
  root_ttl_minutes: overrideIdle?.root_ttl_minutes ?? baseIdle?.root_ttl_minutes,
@@ -30726,11 +31402,9 @@ var PROJECT_SAFE_TOP_LEVEL_FIELDS = new Set([
30726
31402
  "revision_reads",
30727
31403
  "validate_on_edit",
30728
31404
  "configure_warnings_delivery",
30729
- "views",
30730
31405
  "callgraph_chunk_size",
30731
31406
  "inspect",
30732
31407
  "idle",
30733
- "worktree",
30734
31408
  "git",
30735
31409
  "pi",
30736
31410
  "experimental",
@@ -30847,22 +31521,18 @@ function mergeConfigs(base, override) {
30847
31521
  bash.project_env = projectEnv;
30848
31522
  }
30849
31523
  const inspect = mergeInspectConfig(base.inspect, override.inspect);
30850
- const worktree = mergeWorktreeConfig(base.worktree, override.worktree);
30851
31524
  const idle = mergeIdleConfig(base.idle, override.idle);
30852
31525
  const sandbox = mergeSandboxConfig(base.sandbox, override.sandbox);
30853
31526
  const remoteExec = mergeRemoteExecConfig(base.remote_exec, override.remote_exec);
30854
31527
  const backup = mergeProjectBackupConfig(base.backup, override.backup);
30855
31528
  const pi = mergePiConfig(base.pi, override.pi);
30856
- const views = base.views !== undefined || override.views !== undefined ? { ...base.views, ...override.views } : undefined;
30857
31529
  const bridge = base.bridge;
30858
31530
  const safeOverride = pickProjectSafeFields(override);
30859
31531
  delete safeOverride.indexes;
30860
31532
  delete safeOverride.bash;
30861
31533
  delete safeOverride.inspect;
30862
- delete safeOverride.worktree;
30863
31534
  delete safeOverride.idle;
30864
31535
  delete safeOverride.pi;
30865
- delete safeOverride.views;
30866
31536
  return {
30867
31537
  ...base,
30868
31538
  ...safeOverride,
@@ -30871,13 +31541,11 @@ function mergeConfigs(base, override) {
30871
31541
  ...lsp ? { lsp } : {},
30872
31542
  ...bash !== undefined ? { bash } : {},
30873
31543
  ...inspect !== undefined ? { inspect } : {},
30874
- ...worktree !== undefined ? { worktree } : {},
30875
31544
  ...idle !== undefined ? { idle } : {},
30876
31545
  ...sandbox !== undefined ? { sandbox } : {},
30877
31546
  ...remoteExec !== undefined ? { remote_exec: remoteExec } : {},
30878
31547
  ...backup !== undefined ? { backup } : {},
30879
31548
  ...pi !== undefined ? { pi } : {},
30880
- ...views !== undefined ? { views } : {},
30881
31549
  experimental,
30882
31550
  semantic,
30883
31551
  search,
@@ -31281,7 +31949,7 @@ async function signalActiveBridges(pool, projectRoot, sessionID, request) {
31281
31949
  }
31282
31950
 
31283
31951
  // src/bg-notifications.ts
31284
- import { createHash as createHash7, randomBytes as randomBytes4, randomUUID as randomUUID2 } from "node:crypto";
31952
+ import { createHash as createHash8, randomBytes as randomBytes4, randomUUID as randomUUID2 } from "node:crypto";
31285
31953
 
31286
31954
  // src/shared/last-assistant-model.ts
31287
31955
  function isRecord3(value) {
@@ -31605,7 +32273,7 @@ async function awaitWakeAdmission(options) {
31605
32273
 
31606
32274
  // src/bg-notifications.ts
31607
32275
  function hashReminder(text) {
31608
- return createHash7("sha256").update(text).digest("hex").slice(0, 16);
32276
+ return createHash8("sha256").update(text).digest("hex").slice(0, 16);
31609
32277
  }
31610
32278
  var CONSUMED_TASKIDS_CAP = 256;
31611
32279
  var DELIVERED_AWAITING_ACK_CAP = 4096;
@@ -33105,7 +33773,7 @@ function shorten(value, limit) {
33105
33773
  function formatCompletion(completion) {
33106
33774
  const status = formatStatus(completion);
33107
33775
  const duration = formatDuration(completion);
33108
- const header = `- task ${completion.task_id} (${status}${duration ? `, ${duration}` : ""})`;
33776
+ const header = formatUnknownPtyExit(completion.task_id, completion) ?? `- task ${completion.task_id} (${status}${duration ? `, ${duration}` : ""})`;
33109
33777
  const previewBlock = formatOutputPreview(completion);
33110
33778
  const descendantWarning = completion.live_descendants_summary ? ` ${completion.live_descendants_summary}` : "";
33111
33779
  const captureWarning = completion.output_incomplete || completion.status === "failed" && completion.status_reason ? ` [${completion.status_reason || "PTY output may be incomplete"}]` : "";
@@ -33161,7 +33829,7 @@ async function runDetachedBgHandler(work, onError) {
33161
33829
 
33162
33830
  // src/lsp-auto-install.ts
33163
33831
  import { existsSync as existsSync14, mkdirSync as mkdirSync7, renameSync as renameSync9, rmSync as rmSync6, statSync as statSync13, writeFileSync as writeFileSync8 } from "node:fs";
33164
- import { join as join21 } from "node:path";
33832
+ import { join as join20 } from "node:path";
33165
33833
 
33166
33834
  // src/lsp-cache.ts
33167
33835
  import { randomUUID as randomUUID3 } from "node:crypto";
@@ -33176,7 +33844,7 @@ import {
33176
33844
  unlinkSync as unlinkSync6,
33177
33845
  writeFileSync as writeFileSync7
33178
33846
  } from "node:fs";
33179
- import { join as join19 } from "node:path";
33847
+ import { join as join18 } from "node:path";
33180
33848
  function aftCacheBase() {
33181
33849
  return getAftCacheRoot();
33182
33850
  }
@@ -33184,18 +33852,18 @@ function lspCacheRoot() {
33184
33852
  return getAftLspPackagesDir();
33185
33853
  }
33186
33854
  function lspPackageDir(npmPackage) {
33187
- return join19(lspCacheRoot(), encodeURIComponent(npmPackage));
33855
+ return join18(lspCacheRoot(), encodeURIComponent(npmPackage));
33188
33856
  }
33189
33857
  function lspBinaryPath(npmPackage, binary) {
33190
- return join19(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
33858
+ return join18(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
33191
33859
  }
33192
33860
  function lspBinDir(npmPackage) {
33193
- return join19(lspPackageDir(npmPackage), "node_modules", ".bin");
33861
+ return join18(lspPackageDir(npmPackage), "node_modules", ".bin");
33194
33862
  }
33195
33863
  function isInstalled(npmPackage, binary) {
33196
33864
  for (const candidate of lspBinaryCandidates(binary)) {
33197
33865
  try {
33198
- if (statSync12(join19(lspBinDir(npmPackage), candidate)).isFile())
33866
+ if (statSync12(join18(lspBinDir(npmPackage), candidate)).isFile())
33199
33867
  return true;
33200
33868
  } catch {}
33201
33869
  }
@@ -33215,13 +33883,13 @@ function writeInstalledMetaIn(installDir, version, sha256) {
33215
33883
  installedAt: new Date().toISOString(),
33216
33884
  ...sha256 ? { sha256 } : {}
33217
33885
  };
33218
- writeFileSync7(join19(installDir, INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
33886
+ writeFileSync7(join18(installDir, INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
33219
33887
  } catch (err) {
33220
33888
  log2(`[lsp-cache] failed to write installed-meta in ${installDir}: ${err}`);
33221
33889
  }
33222
33890
  }
33223
33891
  function readInstalledMetaIn(installDir) {
33224
- const path = join19(installDir, INSTALLED_META_FILE);
33892
+ const path = join18(installDir, INSTALLED_META_FILE);
33225
33893
  try {
33226
33894
  if (!statSync12(path).isFile())
33227
33895
  return null;
@@ -33245,7 +33913,7 @@ function readInstalledMeta(packageKey) {
33245
33913
  return readInstalledMetaIn(lspPackageDir(packageKey));
33246
33914
  }
33247
33915
  function lockPath(npmPackage) {
33248
- return join19(lspPackageDir(npmPackage), ".aft-installing");
33916
+ return join18(lspPackageDir(npmPackage), ".aft-installing");
33249
33917
  }
33250
33918
  var STALE_LOCK_MS2 = 30 * 60 * 1000;
33251
33919
  function acquireInstallLock(lockKey) {
@@ -33376,7 +34044,7 @@ var AUTO_INSTALL_STAMP_FILE = "last-lsp-autoinstall.json";
33376
34044
  var AUTO_INSTALL_WINDOW_MS = 60 * 1000;
33377
34045
  var AUTO_INSTALL_LOCK_STALE_MS = 30 * 60 * 1000;
33378
34046
  function autoInstallStampPath() {
33379
- return join19(aftCacheBase(), AUTO_INSTALL_STAMP_FILE);
34047
+ return join18(aftCacheBase(), AUTO_INSTALL_STAMP_FILE);
33380
34048
  }
33381
34049
  function hasRecentAutoInstallStamp(path) {
33382
34050
  try {
@@ -33477,7 +34145,7 @@ function claimLspAutoInstallPass() {
33477
34145
  }
33478
34146
  var VERSION_CHECK_FILE = ".aft-version-check";
33479
34147
  function readVersionCheck(npmPackage) {
33480
- const file = join19(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
34148
+ const file = join18(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
33481
34149
  try {
33482
34150
  const raw = readFileSync12(file, "utf8");
33483
34151
  const parsed = JSON.parse(raw);
@@ -33494,7 +34162,7 @@ function readVersionCheck(npmPackage) {
33494
34162
  }
33495
34163
  function writeVersionCheck(npmPackage, latest) {
33496
34164
  mkdirSync6(lspPackageDir(npmPackage), { recursive: true });
33497
- const file = join19(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
34165
+ const file = join18(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
33498
34166
  const record = {
33499
34167
  last_checked: new Date().toISOString(),
33500
34168
  latest_eligible: latest
@@ -33611,7 +34279,7 @@ function isVersionSupported(spec, version) {
33611
34279
 
33612
34280
  // src/lsp-project-relevance.ts
33613
34281
  import { existsSync as existsSync13, readdirSync as readdirSync5, readFileSync as readFileSync13 } from "node:fs";
33614
- import { join as join20 } from "node:path";
34282
+ import { join as join19 } from "node:path";
33615
34283
  var MAX_WALK_DIRS = 200;
33616
34284
  var MAX_WALK_DEPTH = 4;
33617
34285
  var NOISE_DIRS = new Set([
@@ -33628,7 +34296,7 @@ function hasRootMarker(projectRoot, rootMarkers) {
33628
34296
  if (!rootMarkers)
33629
34297
  return false;
33630
34298
  for (const marker of rootMarkers) {
33631
- if (existsSync13(join20(projectRoot, marker)))
34299
+ if (existsSync13(join19(projectRoot, marker)))
33632
34300
  return true;
33633
34301
  }
33634
34302
  return false;
@@ -33652,7 +34320,7 @@ function hasPackageJsonDep(projectRoot, depNames) {
33652
34320
  }
33653
34321
  function readPackageJson(projectRoot) {
33654
34322
  try {
33655
- const raw = readFileSync13(join20(projectRoot, "package.json"), "utf8");
34323
+ const raw = readFileSync13(join19(projectRoot, "package.json"), "utf8");
33656
34324
  const parsed = JSON.parse(raw);
33657
34325
  if (typeof parsed !== "object" || parsed === null)
33658
34326
  return null;
@@ -33682,7 +34350,7 @@ function relevantExtensionsInProject(projectRoot, extToServer) {
33682
34350
  for (const entry of entries) {
33683
34351
  if (entry.isDirectory()) {
33684
34352
  if (current.depth < MAX_WALK_DEPTH && !NOISE_DIRS.has(entry.name.toLowerCase())) {
33685
- queue.push({ dir: join20(current.dir, entry.name), depth: current.depth + 1 });
34353
+ queue.push({ dir: join19(current.dir, entry.name), depth: current.depth + 1 });
33686
34354
  }
33687
34355
  continue;
33688
34356
  }
@@ -33815,7 +34483,7 @@ async function resolveTargetVersion(spec, config, fetchImpl = fetch) {
33815
34483
  }
33816
34484
  function ensureInstallAnchor(cwd) {
33817
34485
  try {
33818
- const stub = join21(cwd, "package.json");
34486
+ const stub = join20(cwd, "package.json");
33819
34487
  if (!existsSync14(stub)) {
33820
34488
  writeFileSync8(stub, `${JSON.stringify({ name: "aft-lsp-cache", version: "0.0.0", private: true })}
33821
34489
  `);
@@ -34036,10 +34704,10 @@ function sha256OfFileSync(path) {
34036
34704
  }
34037
34705
  function quarantineCachedNpmInstall(spec, reason) {
34038
34706
  const packageDir = lspPackageDir(spec.npm);
34039
- const dest = join21(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
34707
+ const dest = join20(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
34040
34708
  warn2(`[lsp] tofu_mismatch ${spec.npm}: ${reason}; quarantining ${packageDir} -> ${dest}`);
34041
34709
  try {
34042
- mkdirSync7(join21(dest, ".."), { recursive: true });
34710
+ mkdirSync7(join20(dest, ".."), { recursive: true });
34043
34711
  rmSync6(dest, { recursive: true, force: true });
34044
34712
  renameSync9(packageDir, dest);
34045
34713
  } catch (err) {
@@ -45786,7 +46454,7 @@ function date6(params) {
45786
46454
 
45787
46455
  // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/classic/external.js
45788
46456
  config2(en_default());
45789
- // ../../node_modules/.bun/@opencode-ai+plugin@1.17.11+f7c91cc509d955ee/node_modules/@opencode-ai/plugin/dist/tool.js
46457
+ // ../../node_modules/.bun/@opencode-ai+plugin@1.17.11+a24dd7ca87f30650/node_modules/@opencode-ai/plugin/dist/tool.js
45790
46458
  function tool(input) {
45791
46459
  return input;
45792
46460
  }
@@ -45900,6 +46568,31 @@ async function getSessionDirectory(client, sessionId, fallbackDirectory) {
45900
46568
  inflight.set(sessionId, lookup);
45901
46569
  return lookup;
45902
46570
  }
46571
+ async function getSessionDirectoryForEvent(client, sessionId, instanceDirectory) {
46572
+ const directory = await getSessionDirectory(client, sessionId, instanceDirectory);
46573
+ if (isV2PluginContext(client) && (directory !== client.location.directory || cache.get(sessionId)?.location?.workspaceID !== client.location.workspaceID))
46574
+ return null;
46575
+ return directory;
46576
+ }
46577
+ function getSessionDirectoryForDeletedEvent(client, sessionId, eventLocation) {
46578
+ if (!sessionId || !isV2PluginContext(client))
46579
+ return null;
46580
+ let location;
46581
+ if (eventLocation === undefined) {
46582
+ location = cache.get(sessionId)?.location;
46583
+ } else {
46584
+ if (!eventLocation || typeof eventLocation !== "object")
46585
+ return null;
46586
+ const ref = eventLocation;
46587
+ if (typeof ref.directory !== "string" || !ref.directory || ref.workspaceID !== undefined && typeof ref.workspaceID !== "string")
46588
+ return null;
46589
+ location = { directory: ref.directory, workspaceID: ref.workspaceID };
46590
+ setCache(sessionId, location.directory, location);
46591
+ }
46592
+ if (!location || location.directory !== client.location.directory || location.workspaceID !== client.location.workspaceID)
46593
+ return null;
46594
+ return location.directory;
46595
+ }
45903
46596
  async function boundedLookup(client, sessionId, fallbackDirectory) {
45904
46597
  const generation = {};
45905
46598
  lookupGenerations.set(sessionId, generation);
@@ -45909,6 +46602,7 @@ async function boundedLookup(client, sessionId, fallbackDirectory) {
45909
46602
  lookupGenerations.delete(oldest);
45910
46603
  }
45911
46604
  let timer;
46605
+ let location;
45912
46606
  try {
45913
46607
  const timeout = new Promise((resolve) => {
45914
46608
  timer = setTimeout(() => {
@@ -45917,9 +46611,11 @@ async function boundedLookup(client, sessionId, fallbackDirectory) {
45917
46611
  }, LOOKUP_TIMEOUT_MS);
45918
46612
  });
45919
46613
  const directory = await Promise.race([
45920
- lookupSessionDirectory(client, sessionId, fallbackDirectory).then((directory) => {
46614
+ lookupSessionDirectory(client, sessionId, fallbackDirectory, (ref) => {
46615
+ location = ref;
46616
+ }).then((directory) => {
45921
46617
  if (lookupGenerations.get(sessionId) === generation && directory !== null) {
45922
- setCache(sessionId, directory);
46618
+ setCache(sessionId, directory, location);
45923
46619
  }
45924
46620
  return directory;
45925
46621
  }).finally(() => {
@@ -45928,15 +46624,15 @@ async function boundedLookup(client, sessionId, fallbackDirectory) {
45928
46624
  }),
45929
46625
  timeout
45930
46626
  ]);
45931
- setCache(sessionId, directory);
46627
+ setCache(sessionId, directory, location);
45932
46628
  return directory;
45933
46629
  } finally {
45934
46630
  clearTimeout(timer);
45935
46631
  }
45936
46632
  }
45937
- async function lookupSessionDirectory(client, sessionId, fallbackDirectory) {
46633
+ async function lookupSessionDirectory(client, sessionId, fallbackDirectory, onLocation) {
45938
46634
  if (isV2PluginContext(client))
45939
- return lookupV2SessionDirectory(client, sessionId);
46635
+ return lookupV2SessionDirectory(client, sessionId, onLocation);
45940
46636
  const c = client;
45941
46637
  const sessionApi = c?.session;
45942
46638
  if (!sessionApi || typeof sessionApi.get !== "function") {
@@ -45955,15 +46651,16 @@ async function lookupSessionDirectory(client, sessionId, fallbackDirectory) {
45955
46651
  }
45956
46652
  return dir;
45957
46653
  }
45958
- async function lookupV2SessionDirectory(context, sessionId) {
46654
+ async function lookupV2SessionDirectory(context, sessionId, onLocation) {
45959
46655
  let dir = null;
45960
46656
  let failure;
45961
46657
  try {
45962
46658
  const session = await Effect.runPromise(Effect.timeout(context.session.get({ sessionID: sessionId }), V2_SESSION_LOOKUP_TIMEOUT_MS));
45963
46659
  const directory = session?.location?.directory;
45964
- if (typeof directory === "string" && directory.length > 0)
46660
+ if (typeof directory === "string" && directory.length > 0) {
45965
46661
  dir = directory;
45966
- else
46662
+ onLocation({ directory, workspaceID: session?.location?.workspaceID });
46663
+ } else
45967
46664
  failure = "the session record has no location.directory";
45968
46665
  } catch (err) {
45969
46666
  failure = err instanceof Error ? err.message || err.name : String(err);
@@ -45973,10 +46670,10 @@ async function lookupV2SessionDirectory(context, sessionId) {
45973
46670
  }
45974
46671
  return dir;
45975
46672
  }
45976
- function setCache(sessionId, directory) {
46673
+ function setCache(sessionId, directory, location) {
45977
46674
  if (cache.has(sessionId))
45978
46675
  cache.delete(sessionId);
45979
- cache.set(sessionId, { directory, recordedAt: Date.now() });
46676
+ cache.set(sessionId, { directory, location, recordedAt: Date.now() });
45980
46677
  if (cache.size > CACHE_MAX_ENTRIES) {
45981
46678
  const oldest = cache.keys().next().value;
45982
46679
  if (oldest !== undefined)
@@ -47243,7 +47940,7 @@ async function trackV2BackgroundTask(ctx, runtime, taskId, startedEpoch) {
47243
47940
  }
47244
47941
  state.tasks.set(taskId, kill);
47245
47942
  }
47246
- async function killStoppedBackgroundTasks(client, sessionID, ctx, startedBeforeMs) {
47943
+ async function killStoppedBackgroundTasks(client, sessionID, ctx, startedBeforeMs, deletedEvent) {
47247
47944
  const kills = [];
47248
47945
  const visited = new Set;
47249
47946
  const dispatch = (taskId, kill) => {
@@ -47263,10 +47960,11 @@ async function killStoppedBackgroundTasks(client, sessionID, ctx, startedBeforeM
47263
47960
  dispatch(taskId, kill);
47264
47961
  }
47265
47962
  }
47266
- if (ctx) {
47963
+ const directory = ctx ? deletedEvent ? getSessionDirectoryForDeletedEvent(client, sessionID, deletedEvent.location) : await getSessionDirectoryForEvent(client, sessionID, client.location.directory) : null;
47964
+ if (ctx && directory) {
47267
47965
  const runtime = {
47268
47966
  sessionID,
47269
- directory: client.location.directory,
47967
+ directory,
47270
47968
  directoryIsSessionRoot: true
47271
47969
  };
47272
47970
  try {
@@ -47340,7 +48038,7 @@ function registerV2SessionLifecycle(context, ctx) {
47340
48038
  }
47341
48039
  if (event.type === "session.deleted") {
47342
48040
  const state = sessions.get(sessionID);
47343
- const kills = killStoppedBackgroundTasks(context, sessionID, ctx);
48041
+ const kills = killStoppedBackgroundTasks(context, sessionID, ctx, undefined, event);
47344
48042
  rememberDeleted(context, sessionID);
47345
48043
  sessions.delete(sessionID);
47346
48044
  releaseSessionState(sessionID);
@@ -47688,7 +48386,8 @@ ${BASH_RUNON_GUIDANCE}`, "");
47688
48386
  const metadata = metadataUpdater(context);
47689
48387
  const rawCommand = args.command;
47690
48388
  const command = rawCommand;
47691
- const cwd = args.workdir ?? context.directory;
48389
+ const workdir = args.workdir;
48390
+ const cwd = workdir ?? context.directory;
47692
48391
  const subagentStatus = await resolveSubagentStatus(ctx.client, context.sessionID, context.directory);
47693
48392
  const isSubagent = subagentStatus === true;
47694
48393
  const backgroundDisabled = !bashCfg.background;
@@ -47732,7 +48431,7 @@ ${BASH_RUNON_GUIDANCE}`, "");
47732
48431
  data = await withPermissionLoop(ctx, context, {
47733
48432
  command,
47734
48433
  timeout: rawTimeout,
47735
- workdir: args.workdir,
48434
+ workdir,
47736
48435
  env: shellEnv?.env ?? {},
47737
48436
  description,
47738
48437
  background: effectiveBackground,
@@ -47818,7 +48517,7 @@ ${BASH_RUNON_GUIDANCE}`, "");
47818
48517
  return { output: rendered, title: uiTitle, metadata: metadataPayload };
47819
48518
  }
47820
48519
  const output = data.output ?? "";
47821
- const rendered = usedHostFallback ? output : maybeAppendGrepSearchHint(output, command, aftSearchRegistered, projectRootFor(context));
48520
+ const rendered = usedHostFallback ? output : maybeAppendGrepSearchHint(output, command, aftSearchRegistered, projectRootFor(context), undefined, workdir);
47822
48521
  const metadataPayload = foregroundMetadata(description, data, rendered);
47823
48522
  await metadata(metadataPayload);
47824
48523
  return {
@@ -47894,7 +48593,7 @@ async function formatBashStatusText(runtime, taskId, data, requestedOutputMode,
47894
48593
  const status = data.status;
47895
48594
  const exit = typeof data.exit_code === "number" ? ` (exit ${data.exit_code})` : "";
47896
48595
  const dur = typeof data.duration_ms === "number" ? ` ${Math.round(data.duration_ms / 1000)}s` : "";
47897
- let text = `Task ${taskId}: ${status}${exit}${dur}`;
48596
+ let text = formatUnknownPtyExit(taskId, data) ?? `Task ${taskId}: ${status}${exit}${dur}`;
47898
48597
  if (typeof data.live_descendants_summary === "string") {
47899
48598
  text += ` · ${data.live_descendants_summary}`;
47900
48599
  }
@@ -49845,7 +50544,7 @@ function createDeleteTool(ctx) {
49845
50544
  recursive
49846
50545
  });
49847
50546
  if (response.success === false) {
49848
- throw new Error(response.message ?? "delete failed");
50547
+ throw toolErrorFromResponse("delete", response);
49849
50548
  }
49850
50549
  const deletedEntries = response.deleted ?? [];
49851
50550
  const skipped = response.skipped_files ?? [];
@@ -51151,6 +51850,15 @@ function semanticTools(ctx) {
51151
51850
 
51152
51851
  // src/tool-registration.ts
51153
51852
  var V2_BUILTIN_REPLACEMENTS = new Set(["read", "edit", "write", "apply_patch"]);
51853
+ var V2_CODEMODE_NAMES = {
51854
+ read: "read",
51855
+ grep: "grep",
51856
+ glob: "glob",
51857
+ aft_search: "search",
51858
+ aft_outline: "outline",
51859
+ aft_zoom: "zoom",
51860
+ aft_callgraph: "callgraph"
51861
+ };
51154
51862
  function openCodeEditSlotSurvives(config) {
51155
51863
  return !resolvedDisabledTools(config).includes("edit");
51156
51864
  }
@@ -51217,6 +51925,25 @@ function registerAftTools(context, location, definitions, consumers = {}) {
51217
51925
  if (V2_BUILTIN_REPLACEMENTS.has(name))
51218
51926
  editor.remove(projected.name);
51219
51927
  editor.add(projected);
51928
+ const codeModeName = V2_CODEMODE_NAMES[name];
51929
+ if (codeModeName) {
51930
+ editor.add({
51931
+ name: codeModeName,
51932
+ get description() {
51933
+ return projected.description;
51934
+ },
51935
+ get input() {
51936
+ return projected.input;
51937
+ },
51938
+ options: {
51939
+ ...projected.options,
51940
+ namespace: "aft.code",
51941
+ permission: projected.name,
51942
+ codemode: true
51943
+ },
51944
+ execute: projected.execute
51945
+ });
51946
+ }
51220
51947
  }
51221
51948
  });
51222
51949
  }
@@ -51672,7 +52399,7 @@ function startOpenCodeLiveConfigReload(options) {
51672
52399
  // src/notifications.ts
51673
52400
  import { existsSync as existsSync17, readFileSync as readFileSync14 } from "node:fs";
51674
52401
  import { homedir as homedir14, platform } from "node:os";
51675
- import { join as join24 } from "node:path";
52402
+ import { join as join23 } from "node:path";
51676
52403
  function isTuiMode() {
51677
52404
  return process.env.OPENCODE_CLIENT === "cli";
51678
52405
  }
@@ -51694,15 +52421,15 @@ function getDesktopStatePath() {
51694
52421
  const os = platform();
51695
52422
  const home = homedir14();
51696
52423
  if (os === "darwin") {
51697
- return join24(home, "Library", "Application Support", "ai.opencode.desktop", "opencode.global.dat");
52424
+ return join23(home, "Library", "Application Support", "ai.opencode.desktop", "opencode.global.dat");
51698
52425
  }
51699
52426
  if (os === "linux") {
51700
- const xdgConfig = process.env.XDG_CONFIG_HOME || join24(home, ".config");
51701
- return join24(xdgConfig, "ai.opencode.desktop", "opencode.global.dat");
52427
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join23(home, ".config");
52428
+ return join23(xdgConfig, "ai.opencode.desktop", "opencode.global.dat");
51702
52429
  }
51703
52430
  if (os === "win32") {
51704
- const appData = process.env.APPDATA || join24(home, "AppData", "Roaming");
51705
- return join24(appData, "ai.opencode.desktop", "opencode.global.dat");
52431
+ const appData = process.env.APPDATA || join23(home, "AppData", "Roaming");
52432
+ return join23(appData, "ai.opencode.desktop", "opencode.global.dat");
51706
52433
  }
51707
52434
  return null;
51708
52435
  }
@@ -52231,30 +52958,30 @@ import { dirname as dirname16 } from "node:path";
52231
52958
  // src/hooks/auto-update-checker/cache.ts
52232
52959
  import { cpSync, existsSync as existsSync19, mkdtempSync, readFileSync as readFileSync16, rmSync as rmSync7, writeFileSync as writeFileSync10 } from "node:fs";
52233
52960
  import { tmpdir as tmpdir4 } from "node:os";
52234
- import { basename as basename5, dirname as dirname15, join as join27 } from "node:path";
52961
+ import { basename as basename5, dirname as dirname15, join as join26 } from "node:path";
52235
52962
  var import_comment_json3 = __toESM(require_src2(), 1);
52236
52963
 
52237
52964
  // src/hooks/auto-update-checker/checker.ts
52238
52965
  import { existsSync as existsSync18, readFileSync as readFileSync15, statSync as statSync16, writeFileSync as writeFileSync9 } from "node:fs";
52239
52966
  import { readFile as readFile2 } from "node:fs/promises";
52240
52967
  import { homedir as homedir15 } from "node:os";
52241
- import { dirname as dirname14, isAbsolute as isAbsolute14, join as join26, resolve as resolve17 } from "node:path";
52968
+ import { dirname as dirname14, isAbsolute as isAbsolute13, join as join25, resolve as resolve16 } from "node:path";
52242
52969
  import { fileURLToPath } from "node:url";
52243
52970
  var import_comment_json2 = __toESM(require_src2(), 1);
52244
52971
 
52245
52972
  // src/hooks/auto-update-checker/constants.ts
52246
- import { join as join25 } from "node:path";
52973
+ import { join as join24 } from "node:path";
52247
52974
  var PACKAGE_NAME = "@cortexkit/aft-opencode";
52248
52975
  var NPM_REGISTRY_URL = "https://registry.npmjs.org";
52249
52976
  var NPM_FETCH_TIMEOUT = 1e4;
52250
52977
  function cacheDir() {
52251
- return join25(getOpenCodeCacheRoot(), "packages");
52978
+ return join24(getOpenCodeCacheRoot(), "packages");
52252
52979
  }
52253
52980
  function userOpenCodeConfig() {
52254
- return join25(getOpenCodeConfigRoot(), "opencode.json");
52981
+ return join24(getOpenCodeConfigRoot(), "opencode.json");
52255
52982
  }
52256
52983
  function userOpenCodeConfigJsonc() {
52257
- return join25(getOpenCodeConfigRoot(), "opencode.jsonc");
52984
+ return join24(getOpenCodeConfigRoot(), "opencode.jsonc");
52258
52985
  }
52259
52986
 
52260
52987
  // src/hooks/auto-update-checker/types.ts
@@ -52313,8 +53040,8 @@ function extractChannel(version) {
52313
53040
  }
52314
53041
  function getConfigPaths(directory) {
52315
53042
  return [
52316
- join26(directory, ".opencode", "opencode.json"),
52317
- join26(directory, ".opencode", "opencode.jsonc"),
53043
+ join25(directory, ".opencode", "opencode.json"),
53044
+ join25(directory, ".opencode", "opencode.jsonc"),
52318
53045
  userOpenCodeConfig(),
52319
53046
  userOpenCodeConfigJsonc()
52320
53047
  ];
@@ -52327,9 +53054,9 @@ function resolvePathPluginSpec(spec, configPath) {
52327
53054
  return spec.replace(/^file:\/\//, "");
52328
53055
  }
52329
53056
  }
52330
- if (isAbsolute14(spec) || /^[A-Za-z]:[\\/]/.test(spec))
53057
+ if (isAbsolute13(spec) || /^[A-Za-z]:[\\/]/.test(spec))
52331
53058
  return spec;
52332
- return resolve17(dirname14(configPath), spec);
53059
+ return resolve16(dirname14(configPath), spec);
52333
53060
  }
52334
53061
  function getLocalDevPath(directory) {
52335
53062
  for (const configPath of getConfigPaths(directory)) {
@@ -52341,7 +53068,7 @@ function getLocalDevPath(directory) {
52341
53068
  for (const entry of plugins) {
52342
53069
  if (entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`))
52343
53070
  continue;
52344
- if (entry.startsWith("file://") || entry.startsWith(".") || isAbsolute14(entry)) {
53071
+ if (entry.startsWith("file://") || entry.startsWith(".") || isAbsolute13(entry)) {
52345
53072
  const localPath = resolvePathPluginSpec(entry, configPath);
52346
53073
  const pkgPath = findPackageJsonUp(localPath);
52347
53074
  if (!pkgPath)
@@ -52360,7 +53087,7 @@ function findPackageJsonUp(startPath) {
52360
53087
  const stat = statSync16(startPath);
52361
53088
  let dir = stat.isDirectory() ? startPath : dirname14(startPath);
52362
53089
  for (let i = 0;i < 10; i++) {
52363
- const pkgPath = join26(dir, "package.json");
53090
+ const pkgPath = join25(dir, "package.json");
52364
53091
  if (existsSync18(pkgPath)) {
52365
53092
  try {
52366
53093
  const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync15(pkgPath, "utf-8")));
@@ -52426,7 +53153,7 @@ function findPluginEntry(directory) {
52426
53153
  }
52427
53154
  var cachedPackageVersion = null;
52428
53155
  function getSpecCachePackageJsonPath(spec) {
52429
- return join26(cacheDir(), spec, "node_modules", PACKAGE_NAME, "package.json");
53156
+ return join25(cacheDir(), spec, "node_modules", PACKAGE_NAME, "package.json");
52430
53157
  }
52431
53158
  function getCachedVersion(spec) {
52432
53159
  if (!spec && cachedPackageVersion)
@@ -52435,7 +53162,7 @@ function getCachedVersion(spec) {
52435
53162
  getCurrentRuntimePackageJsonPath(),
52436
53163
  spec ? getSpecCachePackageJsonPath(spec) : null,
52437
53164
  getSpecCachePackageJsonPath(`${PACKAGE_NAME}@latest`),
52438
- join26(getOpenCodeCacheRoot(), "node_modules", PACKAGE_NAME, "package.json")
53165
+ join25(getOpenCodeCacheRoot(), "node_modules", PACKAGE_NAME, "package.json")
52439
53166
  ].filter(isString);
52440
53167
  for (const packageJsonPath of candidates) {
52441
53168
  try {
@@ -52506,7 +53233,7 @@ async function registryWithoutNpm(directory) {
52506
53233
  for (let current = directory;; current = dirname14(current)) {
52507
53234
  if (scoped)
52508
53235
  break;
52509
- const path = join26(current, ".npmrc");
53236
+ const path = join25(current, ".npmrc");
52510
53237
  visited.add(path);
52511
53238
  const settings = await readRegistrySettings(path);
52512
53239
  scoped ??= settings["@cortexkit:registry"];
@@ -52516,7 +53243,7 @@ async function registryWithoutNpm(directory) {
52516
53243
  }
52517
53244
  const explicitUserConfig = process.env.npm_config_userconfig ?? process.env.NPM_CONFIG_USERCONFIG;
52518
53245
  const home = (process.platform === "win32" ? process.env.USERPROFILE : process.env.HOME) ?? homedir15();
52519
- const userConfig = explicitUserConfig ?? join26(home, ".npmrc");
53246
+ const userConfig = explicitUserConfig ?? join25(home, ".npmrc");
52520
53247
  if (!scoped && !visited.has(userConfig)) {
52521
53248
  const settings = await readRegistrySettings(userConfig, explicitUserConfig !== undefined);
52522
53249
  scoped = settings["@cortexkit:registry"];
@@ -52538,14 +53265,14 @@ function validateRegistry(registry) {
52538
53265
  }
52539
53266
  var reportedRegistryFailures = new Set;
52540
53267
  function reportRegistryFailure(directory) {
52541
- const key = resolve17(directory);
53268
+ const key = resolve16(directory);
52542
53269
  if (reportedRegistryFailures.has(key))
52543
53270
  return;
52544
53271
  reportedRegistryFailures.add(key);
52545
53272
  debug2("[auto-update-checker] Configured npm registry could not be resolved or used; skipping update check.");
52546
53273
  }
52547
53274
  function resolveRegistry(directory) {
52548
- const key = resolve17(directory);
53275
+ const key = resolve16(directory);
52549
53276
  let pending = registryCache.get(key);
52550
53277
  if (!pending) {
52551
53278
  pending = (async () => {
@@ -52602,10 +53329,10 @@ async function getLatestVersion(channel = "latest", options = {}) {
52602
53329
  var pendingSnapshots = new Map;
52603
53330
  var quarantinedInstallDirs = new Set;
52604
53331
  function createAutoUpdateSnapshot(installDir, packageJsonPath, packageName) {
52605
- const packageDir = join27(installDir, "node_modules", packageName);
52606
- const lockfilePath = join27(installDir, "package-lock.json");
52607
- const tempDir = mkdtempSync(join27(tmpdir4(), "aft-auto-update-"));
52608
- const stagedPackageDir = existsSync19(packageDir) ? join27(tempDir, "package") : null;
53332
+ const packageDir = join26(installDir, "node_modules", packageName);
53333
+ const lockfilePath = join26(installDir, "package-lock.json");
53334
+ const tempDir = mkdtempSync(join26(tmpdir4(), "aft-auto-update-"));
53335
+ const stagedPackageDir = existsSync19(packageDir) ? join26(tempDir, "package") : null;
52609
53336
  if (stagedPackageDir)
52610
53337
  cpSync(packageDir, stagedPackageDir, { recursive: true });
52611
53338
  return {
@@ -52646,7 +53373,7 @@ function stripPackageNameFromPath(pathValue, packageName) {
52646
53373
  return current;
52647
53374
  }
52648
53375
  function removeFromPackageLock(installDir, packageName) {
52649
- const lockPath = join27(installDir, "package-lock.json");
53376
+ const lockPath = join26(installDir, "package-lock.json");
52650
53377
  if (!existsSync19(lockPath))
52651
53378
  return false;
52652
53379
  try {
@@ -52702,7 +53429,7 @@ function restorePendingSnapshot(installDir) {
52702
53429
  restoreAutoUpdateSnapshot(snapshot);
52703
53430
  }
52704
53431
  function removeInstalledPackage(installDir, packageName) {
52705
- const packageDir = join27(installDir, "node_modules", packageName);
53432
+ const packageDir = join26(installDir, "node_modules", packageName);
52706
53433
  if (!existsSync19(packageDir))
52707
53434
  return false;
52708
53435
  rmSync7(packageDir, { recursive: true, force: true });
@@ -52715,14 +53442,14 @@ function resolveInstallContext(runtimePackageJsonPath = getCurrentRuntimePackage
52715
53442
  const nodeModulesDir = stripPackageNameFromPath(packageDir, PACKAGE_NAME);
52716
53443
  if (nodeModulesDir && basename5(nodeModulesDir) === "node_modules") {
52717
53444
  const installDir = dirname15(nodeModulesDir);
52718
- const packageJsonPath = join27(installDir, "package.json");
53445
+ const packageJsonPath = join26(installDir, "package.json");
52719
53446
  if (existsSync19(packageJsonPath))
52720
53447
  return { installDir, packageJsonPath };
52721
53448
  }
52722
53449
  return null;
52723
53450
  }
52724
53451
  const cacheRoot = dirname15(cacheDir());
52725
- const legacyPackageJsonPath = join27(cacheRoot, "package.json");
53452
+ const legacyPackageJsonPath = join26(cacheRoot, "package.json");
52726
53453
  if (existsSync19(legacyPackageJsonPath)) {
52727
53454
  return { installDir: cacheRoot, packageJsonPath: legacyPackageJsonPath };
52728
53455
  }
@@ -53348,16 +54075,16 @@ import {
53348
54075
  writeFileSync as writeFileSync12
53349
54076
  } from "node:fs";
53350
54077
  import { createServer } from "node:http";
53351
- import { dirname as dirname17, join as join29 } from "node:path";
54078
+ import { dirname as dirname17, join as join28 } from "node:path";
53352
54079
 
53353
54080
  // src/shared/rpc-utils.ts
53354
- import { join as join28 } from "node:path";
54081
+ import { join as join27 } from "node:path";
53355
54082
  function projectHash(directory) {
53356
54083
  return projectRootKeyHash(directory);
53357
54084
  }
53358
54085
  function rpcPortFileDir(storageDir, directory) {
53359
54086
  const hash = projectHash(directory);
53360
- return join28(storageDir, "rpc", hash, "ports");
54087
+ return join27(storageDir, "rpc", hash, "ports");
53361
54088
  }
53362
54089
  function isPidAlive(pid) {
53363
54090
  if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0)
@@ -53434,7 +54161,7 @@ class AftRpcServer {
53434
54161
  constructor(storageDir, directory) {
53435
54162
  this.portsDir = rpcPortFileDir(storageDir, directory);
53436
54163
  this.instanceId = randomBytes5(8).toString("hex");
53437
- this.portFilePath = join29(this.portsDir, `${this.instanceId}.json`);
54164
+ this.portFilePath = join28(this.portsDir, `${this.instanceId}.json`);
53438
54165
  }
53439
54166
  handle(method, handler) {
53440
54167
  this.handlers.set(method, handler);
@@ -53533,13 +54260,13 @@ class AftRpcServer {
53533
54260
  const temporary = entry.endsWith(".json.tmp");
53534
54261
  if (!temporary && !entry.endsWith(".json"))
53535
54262
  continue;
53536
- const filePath = join29(this.portsDir, entry);
54263
+ const filePath = join28(this.portsDir, entry);
53537
54264
  if (filePath === this.portFilePath)
53538
54265
  continue;
53539
54266
  try {
53540
54267
  const record = parseRpcPortRecord(readFileSync18(filePath, "utf-8"));
53541
54268
  if (record === null) {
53542
- if (!temporary || Date.now() - statSync18(join29(this.portsDir, entry)).mtimeMs >= UNREADABLE_TMP_MAX_AGE_MS) {
54269
+ if (!temporary || Date.now() - statSync18(join28(this.portsDir, entry)).mtimeMs >= UNREADABLE_TMP_MAX_AGE_MS) {
53543
54270
  unlinkSync7(filePath);
53544
54271
  }
53545
54272
  continue;
@@ -53978,11 +54705,11 @@ function coerceAftStatus(response) {
53978
54705
  warm_entries: readNumber(symbolCache.warm_entries)
53979
54706
  },
53980
54707
  storage_dir: readNullableString(response.storage_dir),
53981
- checkpoints_total: readNumber(response.checkpoints_total),
54708
+ checkpoints_total: readOptionalNumber(response.checkpoints_total),
53982
54709
  session: {
53983
54710
  id: readString(session.id, "__default__"),
53984
54711
  tracked_files: readNumber(session.tracked_files),
53985
- checkpoints: readNumber(session.checkpoints)
54712
+ checkpoints: readOptionalNumber(session.checkpoints)
53986
54713
  },
53987
54714
  compression: readCompression(response.compression),
53988
54715
  status_bar: readStatusBar(response.status_bar),
@@ -54180,95 +54907,52 @@ function registerShutdownCleanup(fn) {
54180
54907
  }
54181
54908
 
54182
54909
  // src/workflow-hints.ts
54183
- var HEADING = "## IMPORTANT NOTICE about your tools";
54910
+ var HEADING = "# Agent Foundational Toolkit";
54184
54911
  function hashlineTagSourceHint(bashRewritesMintTags, isRegistered = () => true) {
54185
54912
  return `**Hashline edit tags**: ${hashlineTagSourceSentence(bashRewritesMintTags, isRegistered)}`;
54186
54913
  }
54187
54914
  var HASHLINE_TAG_SOURCE_HINT = hashlineTagSourceHint(true);
54188
54915
  function buildWorkflowHints(opts) {
54189
- const sections = [];
54190
- const grepName = "grep";
54191
- const bashName = "bash";
54192
- const bashStatusName = "bash_status";
54193
- const bashWriteName = "bash_write";
54194
- const hasOutline = !opts.disabledTools.has("aft_outline");
54195
- const hasZoom = !opts.disabledTools.has("aft_zoom");
54196
- const readName = "read";
54197
- const hasRead = !opts.disabledTools.has(readName);
54198
- const hasGrep = !opts.disabledTools.has(grepName);
54199
- const hasSearch = !opts.disabledTools.has("aft_search");
54200
- const hasNavigate = !opts.disabledTools.has("aft_callgraph");
54201
- const hasInspect = !opts.disabledTools.has("aft_inspect");
54202
- const hasBash = !opts.disabledTools.has(bashName);
54203
- const hasBgBash = hasBash && opts.bashBackgroundEnabled && !opts.disabledTools.has(bashStatusName);
54204
- const hasWatch = !opts.disabledTools.has("bash_watch");
54205
- const hasWrite = !opts.disabledTools.has(bashWriteName);
54206
- if (hasBash && opts.bashCompressionEnabled) {
54207
- sections.push([
54208
- "**Test/build output**: bash output is auto-compressed for non-piped commands. Piped commands run verbatim and show the pipeline's output. For AFT's test/build summary, run the runner without filters:",
54209
- "- `bun test | grep fail` → run `bun test`",
54210
- "- `cargo test 2>&1 | tail -20` → run `cargo test`",
54211
- "- `npm run build | head -50` → run `npm run build`"
54212
- ].join(`
54213
- `));
54916
+ const has = (name) => !opts.disabledTools.has(name);
54917
+ const hasBash = has("bash");
54918
+ const hasBackground = hasBash && opts.bashBackgroundEnabled && has("bash_watch") && has("bash_status");
54919
+ const finding = [];
54920
+ if (has("aft_search")) {
54921
+ finding.push("start with aft_search; it takes concepts, identifiers, regex and literals.");
54214
54922
  }
54215
- if (hasOutline && hasZoom) {
54216
- sections.push(`**Web/URL access**: \`aft_outline({ target: url })\` first for structure, then \`aft_zoom({ batch: [{ target: url, symbols: "<heading>" }] })\` for the specific section.`);
54217
- }
54218
- if (hasOutline && (hasGrep || hasSearch) && (hasZoom || hasRead)) {
54219
- const searchName = hasSearch ? "aft_search" : grepName;
54220
- const locate = hasSearch ? "`aft_search` is the primary code-search tool: one call auto-routes concepts, identifiers, regex, error strings, and literals." : `\`${grepName}\` (the tool — indexed and ranked) locates code.`;
54221
- const zoomSteer = hasZoom ? ", or aft_zoom" : "";
54222
- const searchSteer = hasSearch ? `use aft_search (concepts, identifiers, regex, literals), ${readName}, aft_outline${zoomSteer} instead` : `use the ${grepName} tool, ${readName}, aft_outline${zoomSteer} instead`;
54223
- const bashSteer = hasBash ? ` If you are about to run grep, rg, sed, awk, find, or cat through ${bashName} to locate or read code: STOP — ${searchSteer}.` : "";
54224
- sections.push([
54225
- `**Code exploration**: ${locate} Then \`aft_outline\` for structure → \`${hasZoom ? "aft_zoom" : readName}\` for symbol(s). DO NOT run \`grep\`/\`rg\`/\`find\`/\`sed\`/\`cat\` through \`bash\` to locate or read code — the bash path is unindexed, unranked, serial, and routinely surfaces the wrong hit. Keep \`bash\` for shell facts (git state, file metadata, processes).${bashSteer} Reflex translations:`,
54226
- `- \`grep -rn "handleAuth" src/\` in bash → \`${searchName}({ query: "handleAuth" })\``,
54227
- `- \`find . -name "*.ts" | xargs grep watcher\` in bash → \`${searchName}({ query: "watcher invalidation" })\` (concepts work too)`,
54228
- `- \`sed -n '100,160p' app.ts\` / \`cat app.ts\` in bash → \`${readName}({ path: "app.ts", startLine: 100, endLine: 160 })\``
54229
- ].join(`
54230
- `));
54231
- }
54232
- if (hasInspect) {
54233
- sections.push("**Codebase health & diagnostics**: AFT does not surface compile/type errors automatically after edits — pull them with `aft_inspect`. Run it after a batch of edits and before you run tests or commit, when starting in unfamiliar code, or before a refactor/review. One call summarizes diagnostics (compile/type errors), TODOs, metrics, dead code, unused exports, and duplicates; pass `sections` for focused drill-down and `scope` to actively pull diagnostics for a specific file or directory. Its diagnostics are a fast checkpoint, not the authority — a clean `tsc` / `cargo check` / `pyright` run is the real gate. Dead code, unused exports, duplicates, cycles and complexity are computed only when you call aft_inspect, and the call waits until they are current; nothing refreshes them in the background, so run it again after further edits instead of polling.");
54234
- sections.push("**AFT status bar**: tool results may end with a one-line health bar `[AFT E<errors> W<warnings> | T<todos>]` — an IDE-style glance that appears when a count changes. `E`/`W` are live LSP diagnostics for files touched this session (your universal compile-error signal across every language with an LSP). Dead code, unused exports and duplicates are not on the bar; run `aft_inspect` for them. A `?` in place of a number means that count has no value yet (not zero). When `E>0`, you likely just introduced errors; investigate before moving on.");
54235
- }
54236
- if (hasNavigate) {
54237
- sections.push([
54238
- "Use `aft_callgraph` for code-relationship questions instead of grep + read chains:",
54239
- "- `callers` — find all call sites before changing a function signature",
54240
- "- `impact` — blast radius (which functions/files will need updates)",
54241
- "- `trace_to` — how execution reaches this code; each path runs back to a root labelled main, test, attribute, public API, or no caller found",
54242
- "- `trace_to_symbol` — shortest call path from one symbol to another",
54243
- "- `trace_data` — follow a value through assignments and parameters across files"
54244
- ].join(`
54245
- `));
54923
+ if (has("aft_outline") && has("aft_zoom") && has("read")) {
54924
+ finding.push(`${finding.length ? "Then " : ""}aft_outline for structure, aft_zoom for named symbols, read for line ranges.`);
54246
54925
  }
54247
- if (hasBgBash && hasWatch) {
54248
- sections.push([
54249
- `**Long-running commands** (builds, installs, full test suites): run them in the FOREGROUND — use \`${bashName}({ command, wait: true })\` when you know it is long and need the result before anything else; if you send a new message, the wait detaches to background; otherwise omit \`wait\` so auto-promote can hand you a reminder while you work.`,
54250
- "- `background: true` is ONLY for when you have OTHER useful work to do while it runs: start it, do the other work, and the completion reminder delivers the result (or spawn a subagent for the side work). Do NOT background a command and then immediately `bash_watch` it — that spends a whole extra turn waiting for something foreground returns in one.",
54251
- "- `bash_watch` is for blocking on an ALREADY-backgrounded task once you've run out of parallel work (sync — the user can interrupt), or reacting to a specific early output line (async: background:true + pattern). Never loop `bash_status` to wait — it's a one-shot inspector."
54252
- ].join(`
54253
- `));
54926
+ if (hasBash) {
54927
+ finding.push("Don't find or read code with grep, find, sed or cat in bash.");
54254
54928
  }
54255
- if (hasBgBash && hasWrite) {
54256
- sections.push(`**PTY / interactive commands**: PTY mode is for interactive REPLs and terminal apps (python, node, bash itself, vim). Start with \`${bashName}({ command: "python", pty: true, background: true })\`, read the screen with \`${bashStatusName}({ taskId, outputMode: "screen" })\`, and send input with \`${bashWriteName}({ taskId, input: "..." })\`.`);
54929
+ const commands = [];
54930
+ if (hasBash && opts.bashCompressionEnabled) {
54931
+ commands.push("don't pipe test or build output into tail, grep or head; AFT already shortens it.");
54257
54932
  }
54258
- if (opts.hashlineEffective === true) {
54259
- sections.push(hashlineTagSourceHint(hasBash && opts.bashRewriteEnabled !== false, (name) => !opts.disabledTools.has(name)));
54933
+ if (hasBackground) {
54934
+ commands.push("Pass wait: true when you need a long command's result before anything else; a new message from the user detaches the wait.", "Otherwise a long command moves to the background and a reminder brings its result.", "Block on it with bash_watch only when nothing else is left; bash_watch with background: true and a pattern tells you when a line appears.", "Never loop bash_status.");
54260
54935
  }
54261
- if (sections.length === 0) {
54936
+ const sections = [
54937
+ finding.length ? `**Finding code**: ${finding.join(" ")}` : "",
54938
+ has("aft_callgraph") ? "**Relationships**: aft_callgraph for callers, impact, and execution or data-flow traces." : "",
54939
+ has("aft_outline") && has("aft_zoom") ? "**Web pages**: aft_outline with a URL as target, then aft_zoom on a heading." : "",
54940
+ "",
54941
+ has("aft_inspect") ? "**After edits**: run aft_inspect for diagnostics; the project's typecheck and tests are the final check." : "",
54942
+ has("aft_inspect") ? "**Status bar**: `[AFT E.. W.. | T..]` appears when a count changes. E above 0 usually means your last edit broke something; `?` means unknown, not zero." : "",
54943
+ commands.length ? `**Commands**: ${commands.join(" ")}` : ""
54944
+ ];
54945
+ const hashline = opts.hashlineEffective === true ? hashlineTagSourceHint(hasBash && opts.bashRewriteEnabled !== false, has) : "";
54946
+ if (!sections.some(Boolean) && !hashline)
54262
54947
  return null;
54263
- }
54264
- sections.unshift(`You are equipped with a non-standard tool set: indexed code search, symbol-level reading, structural editing, and code analysis that are faster, more precise, and far cheaper in tokens than stitching together command-line utilities in bash. Always reach for these tools first.
54265
-
54266
- **Parallel tool calls**: when several read-only operations are independent, emit them in ONE response instead of serializing — file reads, structure and symbol lookups, code search, diagnostics, and git status/diff/log. Sequence only when a call depends on a prior result or when a command mutates state.`);
54267
- return `${HEADING}
54268
-
54269
- ${sections.join(`
54948
+ sections[3] = "**Parallel calls**: send independent read-only calls in one response.";
54949
+ const text = `${HEADING}
54270
54950
 
54951
+ ${sections.filter(Boolean).join(`
54271
54952
  `)}`;
54953
+ return hashline ? `${text}
54954
+
54955
+ ${hashline}` : text;
54272
54956
  }
54273
54957
  function buildHintsFromConfig(config, disabledTools, hashlineEffective = false) {
54274
54958
  const bashCfg = resolveBashConfig(config);
@@ -54330,12 +55014,12 @@ function throwSentinel(command) {
54330
55014
  throw sentinel;
54331
55015
  }
54332
55016
  var PLUGIN_VERSION = resolvePluginVersion(import.meta.url);
54333
- var ANNOUNCEMENT_VERSION = "0.64.0";
55017
+ var ANNOUNCEMENT_VERSION = "0.65.0";
54334
55018
  var ANNOUNCEMENT_FEATURES = [
54335
- "A new index store makes AFT much faster: call graphs build 26x faster, edits reach the call graph about 9x faster, dead-code checks run 4x faster, and the index takes 4x less disk and 3x less memory.",
54336
- "All worktrees of a repository share one index, so a new worktree is ready in under a second. `npx @cortexkit/aft cache prune-legacy` lists the old index folders and can remove them.",
54337
- "`trace_to` labels each root it reaches: main, test, attribute, public API, or no caller found.",
54338
- "Dead code, unused exports, duplicates, cycles and complexity run only when `aft_inspect` is called; the status bar shows errors, warnings and TODOs."
55019
+ "OpenCode 2: AFT's read-only tools also work inside Code Mode as `tools.aft.code.*`.",
55020
+ "TypeScript monorepos run one language server per TypeScript version instead of one per package; `lsp.max_servers` caps the total.",
55021
+ "Search and grep stay light on large growing files, and shell waits survive the computer going to sleep.",
55022
+ "`views.enabled`, `views.callgraph_copies` and `worktree.ram_overlay` are now refused in user config; `npx @cortexkit/aft doctor --fix` removes them."
54339
55023
  ];
54340
55024
  var ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/DSa65w8wuf";
54341
55025
  var plugin = async (input) => initializePluginForDirectory(input);
@@ -54705,14 +55389,19 @@ Install: ${getManualInstallHint()}`);
54705
55389
  event: async (eventInput) => {
54706
55390
  await autoUpdateEventHook(eventInput);
54707
55391
  const eventType = eventInput.event.type;
54708
- observeOpenCodeBgNotificationEvent(eventInput.event);
54709
55392
  const sessionID = extractSessionID(eventInput.event.properties);
55393
+ let sessionDir = null;
55394
+ if (sessionID && (eventType === "session.created" || eventType === "session.idle" || eventType === "session.status")) {
55395
+ sessionDir = await getSessionDirectoryForEvent(input.client, sessionID, input.directory);
55396
+ if (!sessionDir)
55397
+ return;
55398
+ }
55399
+ observeOpenCodeBgNotificationEvent(eventInput.event);
54710
55400
  if (eventType === "session.moved" && sessionID) {
54711
55401
  clearSessionDirectory(sessionID);
54712
55402
  return;
54713
55403
  }
54714
- if (eventType === "session.created" && sessionID) {
54715
- const sessionDir = await getSessionDirectory(input.client, sessionID, input.directory) ?? input.directory;
55404
+ if (eventType === "session.created" && sessionID && sessionDir) {
54716
55405
  observeFreshSessionStart(pool, sessionDir, sessionID, "new");
54717
55406
  }
54718
55407
  if (eventType === "session.deleted" && sessionID) {
@@ -54722,9 +55411,8 @@ Install: ${getManualInstallHint()}`);
54722
55411
  }
54723
55412
  if (eventType !== "session.idle")
54724
55413
  return;
54725
- if (!sessionID)
55414
+ if (!sessionID || !sessionDir)
54726
55415
  return;
54727
- const sessionDir = await getSessionDirectory(input.client, sessionID, input.directory) ?? input.directory;
54728
55416
  if (!isProjectEnabled(sessionDir))
54729
55417
  return;
54730
55418
  await handleIdleBgCompletions({