@cortexkit/aft-pi 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.
- package/README.md +1 -1
- package/dist/bg-notifications.d.ts.map +1 -1
- package/dist/config.d.ts +4 -30
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1172 -544
- package/dist/shared/status.d.ts +2 -2
- package/dist/shared/status.d.ts.map +1 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/workflow-hints.d.ts +1 -0
- package/dist/workflow-hints.d.ts.map +1 -1
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -8082,7 +8082,14 @@ var TERMINAL_BASH_STATUSES = new Set(TERMINAL_BG_TASK_STATUSES);
|
|
|
8082
8082
|
function isTerminalBashStatus(status, compatibilityAliases = false) {
|
|
8083
8083
|
return typeof status === "string" && (TERMINAL_BASH_STATUSES.has(status) || compatibilityAliases && (status === "cancelled" || status === "timeout"));
|
|
8084
8084
|
}
|
|
8085
|
+
|
|
8085
8086
|
// ../aft-bridge/dist/bash-format.js
|
|
8087
|
+
function formatUnknownPtyExit(taskId, data) {
|
|
8088
|
+
if (data.status !== "fate_unknown" || data.status_reason !== "AFT could not read how it ended") {
|
|
8089
|
+
return;
|
|
8090
|
+
}
|
|
8091
|
+
return `Task ${taskId}: exit status unknown (AFT could not read how it ended)`;
|
|
8092
|
+
}
|
|
8086
8093
|
function isTerminalStatus(status) {
|
|
8087
8094
|
return isTerminalBashStatus(status);
|
|
8088
8095
|
}
|
|
@@ -8114,6 +8121,79 @@ function relativePathEscapesRoot(rel, platform = process.platform) {
|
|
|
8114
8121
|
return rel === ".." || rel.startsWith("../") || platform === "win32" && rel.startsWith("..\\") || (platform === "win32" ? win32.isAbsolute(rel) : posix.isAbsolute(rel));
|
|
8115
8122
|
}
|
|
8116
8123
|
|
|
8124
|
+
// ../aft-bridge/dist/wait-clock.js
|
|
8125
|
+
var SUSPEND_SKEW_MS = 1000;
|
|
8126
|
+
var RESUME_ALLOWANCE_MS = 1e4;
|
|
8127
|
+
var DEADLINE_POLL_MS = 250;
|
|
8128
|
+
|
|
8129
|
+
class WaitClock {
|
|
8130
|
+
wallNow;
|
|
8131
|
+
awakeNow;
|
|
8132
|
+
wall;
|
|
8133
|
+
awake;
|
|
8134
|
+
skew = 0;
|
|
8135
|
+
elapsed;
|
|
8136
|
+
suspendCount = 0;
|
|
8137
|
+
lastSuspendEnd = Number.NEGATIVE_INFINITY;
|
|
8138
|
+
constructor(wallNow = Date.now, awakeNow = () => performance.now()) {
|
|
8139
|
+
this.wallNow = wallNow;
|
|
8140
|
+
this.awakeNow = awakeNow;
|
|
8141
|
+
this.wall = wallNow();
|
|
8142
|
+
this.awake = awakeNow();
|
|
8143
|
+
this.elapsed = this.awake;
|
|
8144
|
+
}
|
|
8145
|
+
now() {
|
|
8146
|
+
const wall = this.wallNow();
|
|
8147
|
+
const awake = this.awakeNow();
|
|
8148
|
+
const active = Math.max(0, awake - this.awake);
|
|
8149
|
+
this.skew = Math.max(0, this.skew + wall - this.wall - active);
|
|
8150
|
+
this.elapsed += active;
|
|
8151
|
+
if (this.skew >= SUSPEND_SKEW_MS) {
|
|
8152
|
+
this.elapsed += this.skew;
|
|
8153
|
+
this.lastSuspendEnd = this.elapsed;
|
|
8154
|
+
this.skew = 0;
|
|
8155
|
+
this.suspendCount++;
|
|
8156
|
+
}
|
|
8157
|
+
this.wall = wall;
|
|
8158
|
+
this.awake = awake;
|
|
8159
|
+
return this.elapsed;
|
|
8160
|
+
}
|
|
8161
|
+
}
|
|
8162
|
+
|
|
8163
|
+
class RequestDeadline {
|
|
8164
|
+
clock;
|
|
8165
|
+
allowResume;
|
|
8166
|
+
deadline;
|
|
8167
|
+
suspendCount;
|
|
8168
|
+
resumed = false;
|
|
8169
|
+
constructor(clock, timeoutMs, allowResume = true) {
|
|
8170
|
+
this.clock = clock;
|
|
8171
|
+
this.allowResume = allowResume;
|
|
8172
|
+
this.deadline = clock.now() + timeoutMs;
|
|
8173
|
+
this.suspendCount = clock.suspendCount;
|
|
8174
|
+
}
|
|
8175
|
+
remaining() {
|
|
8176
|
+
const now = this.clock.now();
|
|
8177
|
+
if (now >= this.deadline && this.allowResume && !this.resumed && this.clock.suspendCount > this.suspendCount && this.clock.lastSuspendEnd >= this.deadline) {
|
|
8178
|
+
this.resumed = true;
|
|
8179
|
+
this.deadline = now + RESUME_ALLOWANCE_MS;
|
|
8180
|
+
}
|
|
8181
|
+
return Math.max(0, this.deadline - now);
|
|
8182
|
+
}
|
|
8183
|
+
}
|
|
8184
|
+
function deadlineTimer(scheduler, remaining, expired) {
|
|
8185
|
+
let timer;
|
|
8186
|
+
const check = () => {
|
|
8187
|
+
const left = remaining();
|
|
8188
|
+
if (left <= 0)
|
|
8189
|
+
expired();
|
|
8190
|
+
else
|
|
8191
|
+
timer = scheduler.setTimeout(check, Math.min(left, DEADLINE_POLL_MS));
|
|
8192
|
+
};
|
|
8193
|
+
check();
|
|
8194
|
+
return () => scheduler.clearTimeout(timer);
|
|
8195
|
+
}
|
|
8196
|
+
|
|
8117
8197
|
// ../aft-bridge/dist/bash-hints.js
|
|
8118
8198
|
var DEFAULT_PRIMARY_WATCH_TIMEOUT_MS = 30000;
|
|
8119
8199
|
var MAX_WATCH_TIMEOUT_MS = 1800000;
|
|
@@ -8141,7 +8221,8 @@ function watchPollDelayMs(elapsedMs) {
|
|
|
8141
8221
|
return 1000;
|
|
8142
8222
|
}
|
|
8143
8223
|
var watchClock = {
|
|
8144
|
-
|
|
8224
|
+
source: new WaitClock,
|
|
8225
|
+
now: () => watchClock.source.now(),
|
|
8145
8226
|
sleep: abortableSleep
|
|
8146
8227
|
};
|
|
8147
8228
|
function abortableSleep(ms, signal) {
|
|
@@ -8287,6 +8368,7 @@ var GREP_SEARCH_AFT_SEARCH_HINT = "DO NOT search code by running grep/rg in bash
|
|
|
8287
8368
|
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).";
|
|
8288
8369
|
var GREP_SEARCH_HINT_PREFIX = "DO NOT search code by running grep/rg in bash —";
|
|
8289
8370
|
var GREP_SEARCH_FRESHNESS_WINDOW_MS = 60000;
|
|
8371
|
+
var MTIME_CLOCK_SLACK_MS = 1;
|
|
8290
8372
|
function maybeAppendConflictsHint(output) {
|
|
8291
8373
|
if (!output.includes("Automatic merge failed; fix conflicts"))
|
|
8292
8374
|
return output;
|
|
@@ -8294,15 +8376,15 @@ function maybeAppendConflictsHint(output) {
|
|
|
8294
8376
|
return output;
|
|
8295
8377
|
return output + CONFLICT_HINT;
|
|
8296
8378
|
}
|
|
8297
|
-
function commandInvokesCodeSearch(command) {
|
|
8298
|
-
const statements = splitTopLevelStatements(command);
|
|
8379
|
+
function commandInvokesCodeSearch(command, platform = process.platform) {
|
|
8380
|
+
const statements = splitTopLevelStatements(command, platform);
|
|
8299
8381
|
if (statements === null)
|
|
8300
8382
|
return false;
|
|
8301
8383
|
for (const statement of statements) {
|
|
8302
|
-
const firstStage = firstPipelineStage(statement);
|
|
8384
|
+
const firstStage = firstPipelineStage(statement, platform);
|
|
8303
8385
|
if (firstStage === null)
|
|
8304
8386
|
continue;
|
|
8305
|
-
const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0));
|
|
8387
|
+
const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0), platform);
|
|
8306
8388
|
if (firstToken === null)
|
|
8307
8389
|
continue;
|
|
8308
8390
|
if (firstToken.token === "grep" || firstToken.token === "rg")
|
|
@@ -8310,42 +8392,43 @@ function commandInvokesCodeSearch(command) {
|
|
|
8310
8392
|
}
|
|
8311
8393
|
return false;
|
|
8312
8394
|
}
|
|
8313
|
-
function maybeAppendGrepSearchHint(output, command, aftSearchRegistered, projectRoot) {
|
|
8395
|
+
function maybeAppendGrepSearchHint(output, command, aftSearchRegistered, projectRoot, platform = process.platform, workdir) {
|
|
8314
8396
|
if (output === "")
|
|
8315
8397
|
return output;
|
|
8316
|
-
if (!commandInvokesCodeSearch(command))
|
|
8398
|
+
if (!commandInvokesCodeSearch(command, platform))
|
|
8317
8399
|
return output;
|
|
8318
8400
|
if (output.includes(GREP_SEARCH_HINT_PREFIX))
|
|
8319
8401
|
return output;
|
|
8320
|
-
if (shouldSuppressGrepSearchHint(command, projectRoot))
|
|
8402
|
+
if (shouldSuppressGrepSearchHint(command, projectRoot, platform, workdir))
|
|
8321
8403
|
return output;
|
|
8322
8404
|
const hint = aftSearchRegistered ? GREP_SEARCH_AFT_SEARCH_HINT : GREP_SEARCH_GREP_HINT;
|
|
8323
8405
|
return `${output}
|
|
8324
8406
|
|
|
8325
8407
|
${hint}`;
|
|
8326
8408
|
}
|
|
8327
|
-
function shouldSuppressGrepSearchHint(command, projectRoot) {
|
|
8328
|
-
const statements = splitTopLevelStatements(command);
|
|
8409
|
+
function shouldSuppressGrepSearchHint(command, projectRoot, platform, workdir) {
|
|
8410
|
+
const statements = splitTopLevelStatements(command, platform);
|
|
8329
8411
|
if (statements === null)
|
|
8330
8412
|
return false;
|
|
8331
|
-
if (allSearchPathOperandsAreDynamic(statements))
|
|
8413
|
+
if (allSearchPathOperandsAreDynamic(statements, platform))
|
|
8332
8414
|
return true;
|
|
8333
8415
|
const root = projectRoot?.trim();
|
|
8334
8416
|
if (!root)
|
|
8335
8417
|
return false;
|
|
8336
|
-
const
|
|
8337
|
-
|
|
8418
|
+
const paths = platform === "win32" ? path.win32 : path.posix;
|
|
8419
|
+
const resolvedRoot = paths.resolve(root);
|
|
8420
|
+
let effectiveCwd = paths.resolve(resolvedRoot, workdir ?? ".");
|
|
8338
8421
|
let sawCodeSearchStatement = false;
|
|
8339
8422
|
for (const statement of statements) {
|
|
8340
|
-
const firstStage = firstPipelineStage(statement);
|
|
8423
|
+
const firstStage = firstPipelineStage(statement, platform);
|
|
8341
8424
|
if (firstStage === null)
|
|
8342
8425
|
continue;
|
|
8343
|
-
const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0));
|
|
8426
|
+
const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0), platform);
|
|
8344
8427
|
if (firstToken === null)
|
|
8345
8428
|
continue;
|
|
8346
8429
|
const head = firstToken.token;
|
|
8347
8430
|
if (head === "cd") {
|
|
8348
|
-
effectiveCwd = nextCwdAfterCd(effectiveCwd, firstStage, firstToken.end);
|
|
8431
|
+
effectiveCwd = nextCwdAfterCd(effectiveCwd, firstStage, firstToken.end, platform);
|
|
8349
8432
|
continue;
|
|
8350
8433
|
}
|
|
8351
8434
|
if (head !== "grep" && head !== "rg")
|
|
@@ -8353,20 +8436,23 @@ function shouldSuppressGrepSearchHint(command, projectRoot) {
|
|
|
8353
8436
|
sawCodeSearchStatement = true;
|
|
8354
8437
|
if (effectiveCwd === null)
|
|
8355
8438
|
continue;
|
|
8356
|
-
if (!isDirInsideProject(resolvedRoot, effectiveCwd))
|
|
8439
|
+
if (!isDirInsideProject(resolvedRoot, effectiveCwd, platform))
|
|
8357
8440
|
continue;
|
|
8358
|
-
const operands = collectPathOperands(firstStage, firstToken.end);
|
|
8441
|
+
const operands = collectPathOperands(firstStage, firstToken.end, platform);
|
|
8359
8442
|
if (operands.length === 0)
|
|
8360
8443
|
return false;
|
|
8361
8444
|
let sawInProjectOperand = false;
|
|
8362
8445
|
for (const operand of operands) {
|
|
8363
8446
|
if (isDynamicPathOperand(operand))
|
|
8364
8447
|
continue;
|
|
8365
|
-
const resolvedOperand = resolvePathOperand(effectiveCwd, operand);
|
|
8366
|
-
if (!isPathInsideProject(resolvedRoot, effectiveCwd, operand))
|
|
8448
|
+
const resolvedOperand = resolvePathOperand(effectiveCwd, operand, platform);
|
|
8449
|
+
if (!isPathInsideProject(resolvedRoot, effectiveCwd, operand, platform))
|
|
8450
|
+
continue;
|
|
8451
|
+
const suppress = shouldSuppressResolvedPath(resolvedOperand);
|
|
8452
|
+
if (suppress === undefined)
|
|
8367
8453
|
continue;
|
|
8368
8454
|
sawInProjectOperand = true;
|
|
8369
|
-
if (
|
|
8455
|
+
if (suppress)
|
|
8370
8456
|
return true;
|
|
8371
8457
|
}
|
|
8372
8458
|
if (sawInProjectOperand)
|
|
@@ -8374,19 +8460,19 @@ function shouldSuppressGrepSearchHint(command, projectRoot) {
|
|
|
8374
8460
|
}
|
|
8375
8461
|
return sawCodeSearchStatement;
|
|
8376
8462
|
}
|
|
8377
|
-
function allSearchPathOperandsAreDynamic(statements) {
|
|
8463
|
+
function allSearchPathOperandsAreDynamic(statements, platform) {
|
|
8378
8464
|
let sawDynamicOnlySearch = false;
|
|
8379
8465
|
for (const statement of statements) {
|
|
8380
|
-
const firstStage = firstPipelineStage(statement);
|
|
8466
|
+
const firstStage = firstPipelineStage(statement, platform);
|
|
8381
8467
|
if (firstStage === null)
|
|
8382
8468
|
continue;
|
|
8383
|
-
const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0));
|
|
8469
|
+
const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0), platform);
|
|
8384
8470
|
if (firstToken === null)
|
|
8385
8471
|
continue;
|
|
8386
8472
|
const head = firstToken.token;
|
|
8387
8473
|
if (head !== "grep" && head !== "rg")
|
|
8388
8474
|
continue;
|
|
8389
|
-
const operands = collectPathOperands(firstStage, firstToken.end);
|
|
8475
|
+
const operands = collectPathOperands(firstStage, firstToken.end, platform);
|
|
8390
8476
|
if (operands.length === 0)
|
|
8391
8477
|
return false;
|
|
8392
8478
|
if (operands.some((operand) => !isDynamicPathOperand(operand)))
|
|
@@ -8395,11 +8481,12 @@ function allSearchPathOperandsAreDynamic(statements) {
|
|
|
8395
8481
|
}
|
|
8396
8482
|
return sawDynamicOnlySearch;
|
|
8397
8483
|
}
|
|
8398
|
-
function nextCwdAfterCd(currentCwd, firstStage, afterCd) {
|
|
8484
|
+
function nextCwdAfterCd(currentCwd, firstStage, afterCd, platform) {
|
|
8485
|
+
const paths = platform === "win32" ? path.win32 : path.posix;
|
|
8399
8486
|
let index = skipSpaces(firstStage, afterCd);
|
|
8400
8487
|
let target = null;
|
|
8401
8488
|
while (index < firstStage.length) {
|
|
8402
|
-
const tokenResult = readShellToken(firstStage, index);
|
|
8489
|
+
const tokenResult = readShellToken(firstStage, index, platform);
|
|
8403
8490
|
if (tokenResult === null)
|
|
8404
8491
|
break;
|
|
8405
8492
|
const { token, end } = tokenResult;
|
|
@@ -8414,28 +8501,29 @@ function nextCwdAfterCd(currentCwd, firstStage, afterCd) {
|
|
|
8414
8501
|
break;
|
|
8415
8502
|
}
|
|
8416
8503
|
if (target === null)
|
|
8417
|
-
return
|
|
8504
|
+
return paths.resolve(os.homedir());
|
|
8418
8505
|
if (target.includes("$") || target.includes("`"))
|
|
8419
8506
|
return null;
|
|
8420
|
-
const expanded = expandTilde(target);
|
|
8421
|
-
if (
|
|
8422
|
-
return
|
|
8507
|
+
const expanded = expandTilde(target, platform);
|
|
8508
|
+
if (paths.isAbsolute(expanded))
|
|
8509
|
+
return paths.resolve(expanded);
|
|
8423
8510
|
if (currentCwd === null)
|
|
8424
8511
|
return null;
|
|
8425
|
-
return
|
|
8512
|
+
return paths.resolve(currentCwd, expanded);
|
|
8426
8513
|
}
|
|
8427
|
-
function isDirInsideProject(resolvedRoot, dir) {
|
|
8428
|
-
const
|
|
8429
|
-
|
|
8514
|
+
function isDirInsideProject(resolvedRoot, dir, platform) {
|
|
8515
|
+
const paths = platform === "win32" ? path.win32 : path.posix;
|
|
8516
|
+
const rel = paths.relative(resolvedRoot, paths.resolve(dir));
|
|
8517
|
+
return !relativePathEscapesRoot(rel, platform);
|
|
8430
8518
|
}
|
|
8431
|
-
function collectPathOperands(firstStage, startAfterCommand) {
|
|
8519
|
+
function collectPathOperands(firstStage, startAfterCommand, platform) {
|
|
8432
8520
|
const operands = [];
|
|
8433
8521
|
let index = skipSpaces(firstStage, startAfterCommand);
|
|
8434
8522
|
let sawPattern = false;
|
|
8435
8523
|
let optionsEnded = false;
|
|
8436
8524
|
let optionValue;
|
|
8437
8525
|
while (index < firstStage.length) {
|
|
8438
|
-
const tokenResult = readShellToken(firstStage, index);
|
|
8526
|
+
const tokenResult = readShellToken(firstStage, index, platform);
|
|
8439
8527
|
if (tokenResult === null)
|
|
8440
8528
|
break;
|
|
8441
8529
|
const { token, end } = tokenResult;
|
|
@@ -8494,22 +8582,25 @@ function collectPathOperands(firstStage, startAfterCommand) {
|
|
|
8494
8582
|
function isDynamicPathOperand(token) {
|
|
8495
8583
|
return token.startsWith("~") || token.includes("$") || token.includes("`");
|
|
8496
8584
|
}
|
|
8497
|
-
function expandTilde(target) {
|
|
8585
|
+
function expandTilde(target, platform) {
|
|
8498
8586
|
if (!target.startsWith("~"))
|
|
8499
8587
|
return target;
|
|
8500
8588
|
if (target === "~" || target.startsWith("~/")) {
|
|
8501
|
-
|
|
8589
|
+
const paths = platform === "win32" ? path.win32 : path.posix;
|
|
8590
|
+
return paths.join(os.homedir(), target.slice(1));
|
|
8502
8591
|
}
|
|
8503
8592
|
return target;
|
|
8504
8593
|
}
|
|
8505
|
-
function resolvePathOperand(projectRoot, operand) {
|
|
8506
|
-
const
|
|
8507
|
-
|
|
8594
|
+
function resolvePathOperand(projectRoot, operand, platform) {
|
|
8595
|
+
const paths = platform === "win32" ? path.win32 : path.posix;
|
|
8596
|
+
const expanded = expandTilde(operand, platform);
|
|
8597
|
+
return paths.isAbsolute(expanded) ? paths.resolve(expanded) : paths.resolve(projectRoot, expanded);
|
|
8508
8598
|
}
|
|
8509
|
-
function isPathInsideProject(resolvedRoot, baseCwd, operand) {
|
|
8510
|
-
const
|
|
8511
|
-
const
|
|
8512
|
-
|
|
8599
|
+
function isPathInsideProject(resolvedRoot, baseCwd, operand, platform) {
|
|
8600
|
+
const paths = platform === "win32" ? path.win32 : path.posix;
|
|
8601
|
+
const resolved = resolvePathOperand(baseCwd, operand, platform);
|
|
8602
|
+
const rel = paths.relative(resolvedRoot, resolved);
|
|
8603
|
+
return !relativePathEscapesRoot(rel, platform);
|
|
8513
8604
|
}
|
|
8514
8605
|
function shouldSuppressResolvedPath(resolved) {
|
|
8515
8606
|
try {
|
|
@@ -8517,12 +8608,12 @@ function shouldSuppressResolvedPath(resolved) {
|
|
|
8517
8608
|
if (stats.isFile())
|
|
8518
8609
|
return true;
|
|
8519
8610
|
const ageMs = Date.now() - stats.mtimeMs;
|
|
8520
|
-
return ageMs
|
|
8611
|
+
return ageMs > -MTIME_CLOCK_SLACK_MS && ageMs < GREP_SEARCH_FRESHNESS_WINDOW_MS;
|
|
8521
8612
|
} catch {
|
|
8522
|
-
return
|
|
8613
|
+
return;
|
|
8523
8614
|
}
|
|
8524
8615
|
}
|
|
8525
|
-
function splitTopLevelStatements(command) {
|
|
8616
|
+
function splitTopLevelStatements(command, platform = process.platform) {
|
|
8526
8617
|
const statements = [];
|
|
8527
8618
|
let start = 0;
|
|
8528
8619
|
let quote = "none";
|
|
@@ -8541,7 +8632,7 @@ function splitTopLevelStatements(command) {
|
|
|
8541
8632
|
continue;
|
|
8542
8633
|
}
|
|
8543
8634
|
if (quote === "double") {
|
|
8544
|
-
if (ch === "\\")
|
|
8635
|
+
if (ch === "\\" && backslashEscapesNext(command[index + 1], quote, platform))
|
|
8545
8636
|
escaped = true;
|
|
8546
8637
|
else if (ch === '"')
|
|
8547
8638
|
quote = "none";
|
|
@@ -8552,7 +8643,7 @@ function splitTopLevelStatements(command) {
|
|
|
8552
8643
|
inBacktick = false;
|
|
8553
8644
|
continue;
|
|
8554
8645
|
}
|
|
8555
|
-
if (ch === "\\") {
|
|
8646
|
+
if (ch === "\\" && backslashEscapesNext(command[index + 1], quote, platform)) {
|
|
8556
8647
|
escaped = true;
|
|
8557
8648
|
continue;
|
|
8558
8649
|
}
|
|
@@ -8595,7 +8686,7 @@ function splitTopLevelStatements(command) {
|
|
|
8595
8686
|
statements.push(command.slice(start));
|
|
8596
8687
|
return statements;
|
|
8597
8688
|
}
|
|
8598
|
-
function firstPipelineStage(command) {
|
|
8689
|
+
function firstPipelineStage(command, platform = process.platform) {
|
|
8599
8690
|
let quote = "none";
|
|
8600
8691
|
let firstPipeIndex;
|
|
8601
8692
|
for (let index = 0;index < command.length; index++) {
|
|
@@ -8608,7 +8699,7 @@ function firstPipelineStage(command) {
|
|
|
8608
8699
|
if (quote === "double") {
|
|
8609
8700
|
if (ch === '"') {
|
|
8610
8701
|
quote = "none";
|
|
8611
|
-
} else if (ch === "\\") {
|
|
8702
|
+
} else if (ch === "\\" && backslashEscapesNext(command[index + 1], quote, platform)) {
|
|
8612
8703
|
index++;
|
|
8613
8704
|
} else if (ch === "`") {
|
|
8614
8705
|
return null;
|
|
@@ -8619,7 +8710,7 @@ function firstPipelineStage(command) {
|
|
|
8619
8710
|
quote = "single";
|
|
8620
8711
|
} else if (ch === '"') {
|
|
8621
8712
|
quote = "double";
|
|
8622
|
-
} else if (ch === "\\") {
|
|
8713
|
+
} else if (ch === "\\" && backslashEscapesNext(command[index + 1], quote, platform)) {
|
|
8623
8714
|
index++;
|
|
8624
8715
|
} else if (ch === "`") {
|
|
8625
8716
|
return null;
|
|
@@ -8635,7 +8726,7 @@ function firstPipelineStage(command) {
|
|
|
8635
8726
|
return null;
|
|
8636
8727
|
return command.slice(0, firstPipeIndex ?? command.length).trim();
|
|
8637
8728
|
}
|
|
8638
|
-
function readShellToken(command, start) {
|
|
8729
|
+
function readShellToken(command, start, platform = process.platform) {
|
|
8639
8730
|
let quote = "none";
|
|
8640
8731
|
let token = "";
|
|
8641
8732
|
let index = start;
|
|
@@ -8652,9 +8743,11 @@ function readShellToken(command, start) {
|
|
|
8652
8743
|
if (quote === "double") {
|
|
8653
8744
|
if (ch === '"') {
|
|
8654
8745
|
quote = "none";
|
|
8655
|
-
} else if (ch === "\\") {
|
|
8746
|
+
} else if (ch === "\\" && backslashEscapesNext(command[index + 1], quote, platform)) {
|
|
8656
8747
|
index++;
|
|
8657
|
-
|
|
8748
|
+
if (command[index] !== `
|
|
8749
|
+
`)
|
|
8750
|
+
token += command[index];
|
|
8658
8751
|
} else if (ch === "`") {
|
|
8659
8752
|
return null;
|
|
8660
8753
|
} else {
|
|
@@ -8670,7 +8763,7 @@ function readShellToken(command, start) {
|
|
|
8670
8763
|
quote = "single";
|
|
8671
8764
|
} else if (ch === '"') {
|
|
8672
8765
|
quote = "double";
|
|
8673
|
-
} else if (ch === "\\") {
|
|
8766
|
+
} else if (ch === "\\" && backslashEscapesNext(command[index + 1], quote, platform)) {
|
|
8674
8767
|
index++;
|
|
8675
8768
|
token += command[index] ?? "\\";
|
|
8676
8769
|
} else if (ch === "`") {
|
|
@@ -8683,6 +8776,11 @@ function readShellToken(command, start) {
|
|
|
8683
8776
|
return null;
|
|
8684
8777
|
return { token, end: index };
|
|
8685
8778
|
}
|
|
8779
|
+
function backslashEscapesNext(next, quote, platform) {
|
|
8780
|
+
if (quote === "double")
|
|
8781
|
+
return next !== undefined && '$`"\\\n'.includes(next);
|
|
8782
|
+
return platform !== "win32";
|
|
8783
|
+
}
|
|
8686
8784
|
function isTokenBoundary(ch) {
|
|
8687
8785
|
return ch === "|" || ch === ";" || ch === "&" || ch === "<" || ch === ">";
|
|
8688
8786
|
}
|
|
@@ -8694,7 +8792,7 @@ function skipSpaces(input, start) {
|
|
|
8694
8792
|
}
|
|
8695
8793
|
// ../aft-bridge/dist/bash-host-fallback.js
|
|
8696
8794
|
import { existsSync } from "node:fs";
|
|
8697
|
-
import { join as
|
|
8795
|
+
import { join as join3 } from "node:path";
|
|
8698
8796
|
|
|
8699
8797
|
// ../aft-bridge/dist/child-process.js
|
|
8700
8798
|
import { execFile as nodeExecFile, execFileSync as nodeExecFileSync, execSync as nodeExecSync, spawn as nodeSpawn, spawnSync as nodeSpawnSync } from "node:child_process";
|
|
@@ -8702,7 +8800,7 @@ import { execFile as nodeExecFile, execFileSync as nodeExecFileSync, execSync as
|
|
|
8702
8800
|
// ../aft-bridge/dist/test-child-environment.js
|
|
8703
8801
|
import { mkdirSync, realpathSync } from "node:fs";
|
|
8704
8802
|
import { homedir as homedir3, tmpdir } from "node:os";
|
|
8705
|
-
import { dirname, isAbsolute
|
|
8803
|
+
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
8706
8804
|
var DIRECTORIES = [
|
|
8707
8805
|
"HOME",
|
|
8708
8806
|
"USERPROFILE",
|
|
@@ -8722,8 +8820,8 @@ function toolchainHomes(inherited) {
|
|
|
8722
8820
|
if (!global[TOOLCHAINS]) {
|
|
8723
8821
|
const home = process.platform === "win32" ? inherited.USERPROFILE || inherited.HOME || homedir3() : inherited.HOME || homedir3();
|
|
8724
8822
|
global[TOOLCHAINS] = {
|
|
8725
|
-
RUSTUP_HOME: inherited.RUSTUP_HOME ||
|
|
8726
|
-
CARGO_HOME: inherited.CARGO_HOME ||
|
|
8823
|
+
RUSTUP_HOME: inherited.RUSTUP_HOME || join(home, ".rustup"),
|
|
8824
|
+
CARGO_HOME: inherited.CARGO_HOME || join(home, ".cargo")
|
|
8727
8825
|
};
|
|
8728
8826
|
}
|
|
8729
8827
|
return global[TOOLCHAINS];
|
|
@@ -8750,31 +8848,31 @@ function isolatedAftEnvironment(root, inherited = process.env) {
|
|
|
8750
8848
|
"aft-cache"
|
|
8751
8849
|
];
|
|
8752
8850
|
for (const [index, key] of DIRECTORIES.entries()) {
|
|
8753
|
-
env[key] =
|
|
8851
|
+
env[key] = join(root, names[index]);
|
|
8754
8852
|
mkdirSync(env[key], { recursive: true });
|
|
8755
8853
|
}
|
|
8756
8854
|
delete env.AFT_ALLOW_PRODUCTION_MIGRATION;
|
|
8757
|
-
createdRoots().add(
|
|
8855
|
+
createdRoots().add(resolve(root));
|
|
8758
8856
|
return env;
|
|
8759
8857
|
}
|
|
8760
8858
|
function canonical(path) {
|
|
8761
|
-
let ancestor =
|
|
8859
|
+
let ancestor = resolve(path);
|
|
8762
8860
|
const tail = [];
|
|
8763
8861
|
while (true) {
|
|
8764
8862
|
try {
|
|
8765
|
-
return
|
|
8863
|
+
return join(realpathSync(ancestor), ...tail);
|
|
8766
8864
|
} catch {
|
|
8767
8865
|
const parent = dirname(ancestor);
|
|
8768
8866
|
if (parent === ancestor)
|
|
8769
|
-
return
|
|
8770
|
-
tail.unshift(
|
|
8867
|
+
return resolve(path);
|
|
8868
|
+
tail.unshift(relative(parent, ancestor));
|
|
8771
8869
|
ancestor = parent;
|
|
8772
8870
|
}
|
|
8773
8871
|
}
|
|
8774
8872
|
}
|
|
8775
8873
|
function within(path, root) {
|
|
8776
|
-
const tail =
|
|
8777
|
-
return tail === "" || !tail.startsWith("..") && !
|
|
8874
|
+
const tail = relative(canonical(root), canonical(path));
|
|
8875
|
+
return tail === "" || !tail.startsWith("..") && !isAbsolute(tail);
|
|
8778
8876
|
}
|
|
8779
8877
|
function testChildEnvironment(env) {
|
|
8780
8878
|
const root = process.env.AFT_TEST_ISOLATION_ROOT;
|
|
@@ -8850,7 +8948,7 @@ function withPathPrepended(env, dir, platform = process.platform) {
|
|
|
8850
8948
|
|
|
8851
8949
|
// ../aft-bridge/dist/storage-paths.js
|
|
8852
8950
|
import { homedir as homedir4, tmpdir as tmpdir2 } from "node:os";
|
|
8853
|
-
import { join as
|
|
8951
|
+
import { join as join2, resolve as resolve2 } from "node:path";
|
|
8854
8952
|
function environmentValue(context, name) {
|
|
8855
8953
|
const value = (context.lookup ?? ((key) => process.env[key]))(name);
|
|
8856
8954
|
return value !== undefined && value.length > 0 ? value : undefined;
|
|
@@ -8872,21 +8970,21 @@ function resolveDataHome(context = {}) {
|
|
|
8872
8970
|
return localAppData;
|
|
8873
8971
|
const userProfile = environmentValue(context, "USERPROFILE");
|
|
8874
8972
|
if (userProfile)
|
|
8875
|
-
return
|
|
8973
|
+
return join2(userProfile, "AppData", "Local");
|
|
8876
8974
|
}
|
|
8877
8975
|
const home = environmentValue(context, "HOME");
|
|
8878
8976
|
if (home)
|
|
8879
|
-
return
|
|
8880
|
-
return
|
|
8977
|
+
return join2(home, ".local", "share");
|
|
8978
|
+
return join2(".local", "share");
|
|
8881
8979
|
}
|
|
8882
8980
|
function resolveStoragePath(raw, context = {}) {
|
|
8883
8981
|
let expanded = raw;
|
|
8884
8982
|
if (raw === "~") {
|
|
8885
8983
|
expanded = homeDir(context);
|
|
8886
8984
|
} else if (raw.startsWith("~/") || raw.startsWith("~\\")) {
|
|
8887
|
-
expanded =
|
|
8985
|
+
expanded = join2(homeDir(context), raw.slice(2));
|
|
8888
8986
|
}
|
|
8889
|
-
return
|
|
8987
|
+
return resolve2(context.currentDirectory ?? process.cwd(), expanded);
|
|
8890
8988
|
}
|
|
8891
8989
|
function resolveCortexKitStorageRoot(context = {}) {
|
|
8892
8990
|
const override = environmentValue(context, "AFT_STORAGE_DIR");
|
|
@@ -8894,8 +8992,8 @@ function resolveCortexKitStorageRoot(context = {}) {
|
|
|
8894
8992
|
return resolveStoragePath(override, context);
|
|
8895
8993
|
const legacyCache = environmentValue(context, "AFT_CACHE_DIR");
|
|
8896
8994
|
if (legacyCache)
|
|
8897
|
-
return
|
|
8898
|
-
return resolveStoragePath(
|
|
8995
|
+
return join2(resolveStoragePath(legacyCache, context), "aft");
|
|
8996
|
+
return resolveStoragePath(join2(resolveDataHome(context), "cortexkit", "aft"), context);
|
|
8899
8997
|
}
|
|
8900
8998
|
function resolveAftStorageRoot(configuredRoot, context = {}) {
|
|
8901
8999
|
if (environmentValue(context, "AFT_STORAGE_DIR")) {
|
|
@@ -8906,14 +9004,14 @@ function resolveAftStorageRoot(configuredRoot, context = {}) {
|
|
|
8906
9004
|
return resolveCortexKitStorageRoot(context);
|
|
8907
9005
|
}
|
|
8908
9006
|
function resolveAftLogPath(filename, configuredRoot, context = {}) {
|
|
8909
|
-
return
|
|
9007
|
+
return join2(resolveAftStorageRoot(configuredRoot, context), "logs", filename);
|
|
8910
9008
|
}
|
|
8911
9009
|
function isTestEnvironment(context = {}) {
|
|
8912
9010
|
return environmentValue(context, "BUN_TEST") === "1" || environmentValue(context, "NODE_ENV") === "test";
|
|
8913
9011
|
}
|
|
8914
9012
|
function resolvePluginLogPath(context = {}) {
|
|
8915
9013
|
if (isTestEnvironment(context)) {
|
|
8916
|
-
return
|
|
9014
|
+
return join2(environmentValue(context, "TMPDIR") ?? tmpdir2(), `aft-plugin-tests-${process.pid}`, "logs", "aft-plugin-test.log");
|
|
8917
9015
|
}
|
|
8918
9016
|
return resolveAftLogPath("aft-plugin.log", undefined, context);
|
|
8919
9017
|
}
|
|
@@ -8948,8 +9046,8 @@ function hostFallbackEnvWithShims(env, platform) {
|
|
|
8948
9046
|
const pathKey = pathKeyForPlatform(normalized, platform);
|
|
8949
9047
|
const inherited = pathKey === undefined ? undefined : normalized[pathKey];
|
|
8950
9048
|
const storageRoot = normalized.AFT_STORAGE_DIR ? resolveStoragePath(normalized.AFT_STORAGE_DIR) : resolveCortexKitStorageRoot();
|
|
8951
|
-
const shimsDir =
|
|
8952
|
-
if (!existsSync(
|
|
9049
|
+
const shimsDir = join3(storageRoot, "shims");
|
|
9050
|
+
if (!existsSync(join3(shimsDir, platform === "win32" ? "gh.cmd" : "gh")))
|
|
8953
9051
|
return normalized;
|
|
8954
9052
|
const separator = platform === "win32" ? ";" : ":";
|
|
8955
9053
|
const entries = (inherited ?? "").split(separator).filter((entry) => entry.length > 0);
|
|
@@ -9708,7 +9806,7 @@ async function cachedFileSha256(path) {
|
|
|
9708
9806
|
}
|
|
9709
9807
|
// ../aft-bridge/dist/bridge.js
|
|
9710
9808
|
import { homedir as homedir5 } from "node:os";
|
|
9711
|
-
import { join as
|
|
9809
|
+
import { join as join4 } from "node:path";
|
|
9712
9810
|
import { StringDecoder } from "node:string_decoder";
|
|
9713
9811
|
|
|
9714
9812
|
// ../aft-bridge/dist/command-timeouts.js
|
|
@@ -9846,6 +9944,7 @@ function compareSemver(a, b) {
|
|
|
9846
9944
|
}
|
|
9847
9945
|
var SYSTEM_CLOCK = {
|
|
9848
9946
|
now: () => Date.now(),
|
|
9947
|
+
awakeNow: () => performance.now(),
|
|
9849
9948
|
setTimeout: (callback, ms) => setTimeout(callback, ms),
|
|
9850
9949
|
clearTimeout: (timer) => clearTimeout(timer)
|
|
9851
9950
|
};
|
|
@@ -9962,6 +10061,7 @@ class BinaryBridge {
|
|
|
9962
10061
|
hangWindowMinMs;
|
|
9963
10062
|
hangProbeTimeoutMs;
|
|
9964
10063
|
clock;
|
|
10064
|
+
waitClock;
|
|
9965
10065
|
lateShellReplyGraceMs;
|
|
9966
10066
|
maxRestarts;
|
|
9967
10067
|
configured = false;
|
|
@@ -9998,6 +10098,7 @@ class BinaryBridge {
|
|
|
9998
10098
|
this.hangWindowMinMs = options?.hangWindowMinMs ?? DEFAULT_MIN_HANG_WINDOW_MS;
|
|
9999
10099
|
this.hangProbeTimeoutMs = options?.hangProbeTimeoutMs ?? DEFAULT_HANG_PROBE_TIMEOUT_MS;
|
|
10000
10100
|
this.clock = options?.clock ?? SYSTEM_CLOCK;
|
|
10101
|
+
this.waitClock = new WaitClock(() => this.clock.now(), () => this.clock.awakeNow?.() ?? this.clock.now());
|
|
10001
10102
|
this.lateShellReplyGraceMs = options?.lateShellReplyGraceMs ?? DEFAULT_LATE_SHELL_REPLY_GRACE_MS;
|
|
10002
10103
|
this.maxRestarts = options?.maxRestarts ?? 3;
|
|
10003
10104
|
this.errorPrefix = options?.errorPrefix ?? "[aft-bridge]";
|
|
@@ -10364,11 +10465,17 @@ class BinaryBridge {
|
|
|
10364
10465
|
const keepBridgeOnTimeout = passive || command === "bash_drain_completions" || options?.keepBridgeOnTimeout === true;
|
|
10365
10466
|
const child = this.process;
|
|
10366
10467
|
const response = await new Promise((resolve, reject) => {
|
|
10367
|
-
const
|
|
10468
|
+
const deadline = new RequestDeadline(this.waitClock, effectiveTimeoutMs);
|
|
10469
|
+
const expire = () => {
|
|
10368
10470
|
const entry = this.pending.get(id);
|
|
10369
10471
|
if (!entry)
|
|
10370
10472
|
return;
|
|
10371
|
-
|
|
10473
|
+
const remaining = deadline.remaining();
|
|
10474
|
+
if (remaining > 0) {
|
|
10475
|
+
entry.timer = this.clock.setTimeout(expire, Math.min(remaining, DEADLINE_POLL_MS));
|
|
10476
|
+
return;
|
|
10477
|
+
}
|
|
10478
|
+
if (keepBridgeOnTimeout && !deadline.resumed && this.holdForLateShellReply(id, entry, effectiveTimeoutMs, requestSessionId)) {
|
|
10372
10479
|
return;
|
|
10373
10480
|
}
|
|
10374
10481
|
this.pending.delete(id);
|
|
@@ -10381,11 +10488,12 @@ class BinaryBridge {
|
|
|
10381
10488
|
this.warnVia(timeoutMsg);
|
|
10382
10489
|
}
|
|
10383
10490
|
if (keepBridgeOnTimeout) {
|
|
10384
|
-
entry.reject(new BridgeTransportTimeoutError(command, effectiveTimeoutMs, `${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms
|
|
10491
|
+
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));
|
|
10385
10492
|
return;
|
|
10386
10493
|
}
|
|
10387
10494
|
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.`));
|
|
10388
|
-
}
|
|
10495
|
+
};
|
|
10496
|
+
const timer = this.clock.setTimeout(expire, Math.min(effectiveTimeoutMs, DEADLINE_POLL_MS));
|
|
10389
10497
|
const entry = {
|
|
10390
10498
|
resolve,
|
|
10391
10499
|
reject,
|
|
@@ -10616,11 +10724,11 @@ class BinaryBridge {
|
|
|
10616
10724
|
})();
|
|
10617
10725
|
const useFastembedBackend = semanticBackend === undefined || semanticBackend === "fastembed" || semanticBackend === "";
|
|
10618
10726
|
const ortDir = typeof this.configOverrides._ort_dylib_dir === "string" && useFastembedBackend ? this.configOverrides._ort_dylib_dir : null;
|
|
10619
|
-
const ortLibraryPath = ortDir == null ? null :
|
|
10727
|
+
const ortLibraryPath = ortDir == null ? null : join4(ortDir, this.platform === "win32" ? "onnxruntime.dll" : this.platform === "darwin" ? "libonnxruntime.dylib" : "libonnxruntime.so");
|
|
10620
10728
|
const env = { ...process.env };
|
|
10621
10729
|
this.logVia(`bridge.spawnProcess: useFastembedBackend=${useFastembedBackend}, ` + `parentORT=${process.env.ORT_DYLIB_PATH ?? "(unset)"}, ` + `ortLibraryPath=${ortLibraryPath ?? "(none)"}`);
|
|
10622
10730
|
if (useFastembedBackend) {
|
|
10623
|
-
env.FASTEMBED_CACHE_DIR = process.env.FASTEMBED_CACHE_DIR || (typeof this.configOverrides.storage_dir === "string" ?
|
|
10731
|
+
env.FASTEMBED_CACHE_DIR = process.env.FASTEMBED_CACHE_DIR || (typeof this.configOverrides.storage_dir === "string" ? join4(this.configOverrides.storage_dir, "semantic", "models") : join4(homedir5() || "", ".cache", "fastembed"));
|
|
10624
10732
|
if (process.env.ORT_DYLIB_PATH) {
|
|
10625
10733
|
this.logVia(`ORT_DYLIB_PATH inherited from parent env: ${process.env.ORT_DYLIB_PATH}`);
|
|
10626
10734
|
} else if (ortLibraryPath) {
|
|
@@ -10941,14 +11049,21 @@ class BinaryBridge {
|
|
|
10941
11049
|
};
|
|
10942
11050
|
entry.resolve = (response) => settle(shellOutcomeFromLateReply(response));
|
|
10943
11051
|
this.clock.clearTimeout(entry.timer);
|
|
10944
|
-
|
|
11052
|
+
const deadline = new RequestDeadline(this.waitClock, graceMs, false);
|
|
11053
|
+
const expire = () => {
|
|
10945
11054
|
if (this.pending.get(id) !== entry)
|
|
10946
11055
|
return;
|
|
11056
|
+
const remaining = deadline.remaining();
|
|
11057
|
+
if (remaining > 0) {
|
|
11058
|
+
entry.timer = this.clock.setTimeout(expire, Math.min(remaining, DEADLINE_POLL_MS));
|
|
11059
|
+
return;
|
|
11060
|
+
}
|
|
10947
11061
|
this.pending.delete(id);
|
|
10948
11062
|
entry.onSettled?.();
|
|
10949
11063
|
this.warnVia(`Request "${entry.command}" (id=${id}) got no reply within ${graceMs}ms after its deadline`);
|
|
10950
11064
|
settle({ kind: "unknown" });
|
|
10951
|
-
}
|
|
11065
|
+
};
|
|
11066
|
+
entry.timer = this.clock.setTimeout(expire, Math.min(graceMs, DEADLINE_POLL_MS));
|
|
10952
11067
|
return true;
|
|
10953
11068
|
}
|
|
10954
11069
|
accountForBashTaskResponse(command, response) {
|
|
@@ -11196,7 +11311,7 @@ class BinaryBridge {
|
|
|
11196
11311
|
}
|
|
11197
11312
|
// ../aft-bridge/dist/cache-paths.js
|
|
11198
11313
|
import { homedir as homedir6 } from "node:os";
|
|
11199
|
-
import { join as
|
|
11314
|
+
import { join as join5 } from "node:path";
|
|
11200
11315
|
function homeDir2(env) {
|
|
11201
11316
|
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir6();
|
|
11202
11317
|
}
|
|
@@ -11204,20 +11319,20 @@ function getAftCacheRoot(env = process.env) {
|
|
|
11204
11319
|
if (env.AFT_CACHE_DIR)
|
|
11205
11320
|
return env.AFT_CACHE_DIR;
|
|
11206
11321
|
if (process.platform === "win32") {
|
|
11207
|
-
const base = env.LOCALAPPDATA || env.APPDATA ||
|
|
11208
|
-
return
|
|
11322
|
+
const base = env.LOCALAPPDATA || env.APPDATA || join5(homeDir2(env), "AppData", "Local");
|
|
11323
|
+
return join5(base, "aft");
|
|
11209
11324
|
}
|
|
11210
|
-
const base = env.XDG_CACHE_HOME ||
|
|
11211
|
-
return
|
|
11325
|
+
const base = env.XDG_CACHE_HOME || join5(homeDir2(env), ".cache");
|
|
11326
|
+
return join5(base, "aft");
|
|
11212
11327
|
}
|
|
11213
11328
|
function getAftBinaryCacheDir(env = process.env) {
|
|
11214
|
-
return
|
|
11329
|
+
return join5(getAftCacheRoot(env), "bin");
|
|
11215
11330
|
}
|
|
11216
11331
|
function getAftLspPackagesDir(env = process.env) {
|
|
11217
|
-
return
|
|
11332
|
+
return join5(getAftCacheRoot(env), "lsp-packages");
|
|
11218
11333
|
}
|
|
11219
11334
|
function getAftLspBinariesDir(env = process.env) {
|
|
11220
|
-
return
|
|
11335
|
+
return join5(getAftCacheRoot(env), "lsp-binaries");
|
|
11221
11336
|
}
|
|
11222
11337
|
// ../aft-bridge/dist/callgraph-format.js
|
|
11223
11338
|
var UNRESOLVED_SUMMARY_NAME_LIMIT = 10;
|
|
@@ -11706,7 +11821,7 @@ function isFindReplaceOnlyEdit(args) {
|
|
|
11706
11821
|
}
|
|
11707
11822
|
// ../aft-bridge/dist/config-error.js
|
|
11708
11823
|
import { homedir as homedir7 } from "node:os";
|
|
11709
|
-
import { isAbsolute as
|
|
11824
|
+
import { isAbsolute as isAbsolute2, join as join6 } from "node:path";
|
|
11710
11825
|
var CONFIG_ERROR_RESTART_NOTE = "AFT reads its config only at startup, so restart the host after fixing it.";
|
|
11711
11826
|
function formatConfigErrorMessage(detail) {
|
|
11712
11827
|
const trimmed = detail.trim();
|
|
@@ -11716,10 +11831,10 @@ function formatConfigErrorMessage(detail) {
|
|
|
11716
11831
|
function resolveSubcConnectionFilePath(raw, home = homedir7()) {
|
|
11717
11832
|
const trimmed = raw.trim();
|
|
11718
11833
|
if (trimmed.startsWith("~"))
|
|
11719
|
-
return
|
|
11720
|
-
if (
|
|
11834
|
+
return join6(home, trimmed.slice(1).replace(/^[/\\]/, ""));
|
|
11835
|
+
if (isAbsolute2(trimmed))
|
|
11721
11836
|
return trimmed;
|
|
11722
|
-
return
|
|
11837
|
+
return join6(home, trimmed);
|
|
11723
11838
|
}
|
|
11724
11839
|
function formatSubcConnectionMissingMessage(raw, resolved) {
|
|
11725
11840
|
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.`;
|
|
@@ -11780,7 +11895,7 @@ function stripHarnessSpecificConfigKeys(value, keys) {
|
|
|
11780
11895
|
}
|
|
11781
11896
|
// ../aft-bridge/dist/config-tiers.js
|
|
11782
11897
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
11783
|
-
import { resolve as
|
|
11898
|
+
import { resolve as resolve3 } from "node:path";
|
|
11784
11899
|
function readConfigTiers(opts) {
|
|
11785
11900
|
const tiers = [];
|
|
11786
11901
|
try {
|
|
@@ -11788,7 +11903,7 @@ function readConfigTiers(opts) {
|
|
|
11788
11903
|
const doc = readFileSync2(opts.userConfigPath, "utf-8");
|
|
11789
11904
|
tiers.push({
|
|
11790
11905
|
tier: "user",
|
|
11791
|
-
source:
|
|
11906
|
+
source: resolve3(opts.userConfigPath),
|
|
11792
11907
|
doc
|
|
11793
11908
|
});
|
|
11794
11909
|
}
|
|
@@ -11798,7 +11913,7 @@ function readConfigTiers(opts) {
|
|
|
11798
11913
|
const doc = readFileSync2(opts.projectConfigPath, "utf-8");
|
|
11799
11914
|
tiers.push({
|
|
11800
11915
|
tier: "project",
|
|
11801
|
-
source:
|
|
11916
|
+
source: resolve3(opts.projectConfigPath),
|
|
11802
11917
|
doc
|
|
11803
11918
|
});
|
|
11804
11919
|
}
|
|
@@ -11814,7 +11929,7 @@ function formatDroppedKeyWarnings(dropped) {
|
|
|
11814
11929
|
// ../aft-bridge/dist/config-watch.js
|
|
11815
11930
|
import { createHash as createHash2 } from "node:crypto";
|
|
11816
11931
|
import { closeSync as closeSync2, fstatSync, openSync as openSync2, readFileSync as readFileSync3, readSync as readSync2, realpathSync as realpathSync2, statSync as statSync3, watch } from "node:fs";
|
|
11817
|
-
import { basename, dirname as dirname2, resolve as
|
|
11932
|
+
import { basename, dirname as dirname2, resolve as resolve4 } from "node:path";
|
|
11818
11933
|
var CONFIG_WATCH_DEBOUNCE_MS = 150;
|
|
11819
11934
|
var CONFIG_LIVE_KEEP_NOTE = "AFT keeps using the last valid configuration until the file is fixed.";
|
|
11820
11935
|
function pathKey(name) {
|
|
@@ -11869,6 +11984,7 @@ function aftLiveConfigKeys(resolveBash) {
|
|
|
11869
11984
|
pathKey("revision_reads"),
|
|
11870
11985
|
pathKey("inspect.diagnostics_timeout_ms"),
|
|
11871
11986
|
pathKey("lsp.idle_minutes"),
|
|
11987
|
+
pathKey("lsp.max_servers"),
|
|
11872
11988
|
...[
|
|
11873
11989
|
"diagnostics",
|
|
11874
11990
|
"todos",
|
|
@@ -11981,7 +12097,7 @@ function canonicalDirectory(dir) {
|
|
|
11981
12097
|
try {
|
|
11982
12098
|
return realpathSync2(dir);
|
|
11983
12099
|
} catch {
|
|
11984
|
-
return
|
|
12100
|
+
return resolve4(dir);
|
|
11985
12101
|
}
|
|
11986
12102
|
}
|
|
11987
12103
|
function watchAftConfigFiles(options) {
|
|
@@ -12001,6 +12117,7 @@ function watchAftConfigFiles(options) {
|
|
|
12001
12117
|
const fallbackSeen = new Map;
|
|
12002
12118
|
const watchImpl = options.watchImpl ?? watch;
|
|
12003
12119
|
let rejectedRetries = 0;
|
|
12120
|
+
let recheckAfterArming = false;
|
|
12004
12121
|
const check = () => {
|
|
12005
12122
|
if (retryTimer)
|
|
12006
12123
|
clearTimeout(retryTimer);
|
|
@@ -12009,7 +12126,8 @@ function watchAftConfigFiles(options) {
|
|
|
12009
12126
|
firstPendingAt = null;
|
|
12010
12127
|
if (stopped)
|
|
12011
12128
|
return;
|
|
12012
|
-
revalidate()
|
|
12129
|
+
if (revalidate())
|
|
12130
|
+
recheckAfterArming = true;
|
|
12013
12131
|
const seen = new Map;
|
|
12014
12132
|
for (const path of options.paths) {
|
|
12015
12133
|
const text = readTextOrNull(path);
|
|
@@ -12067,7 +12185,7 @@ function watchAftConfigFiles(options) {
|
|
|
12067
12185
|
for (const path of options.paths) {
|
|
12068
12186
|
try {
|
|
12069
12187
|
const resolved = realpathSync2(path);
|
|
12070
|
-
const target = resolved ===
|
|
12188
|
+
const target = resolved === resolve4(path) ? undefined : resolved;
|
|
12071
12189
|
if (targets.get(path) !== target) {
|
|
12072
12190
|
if (target)
|
|
12073
12191
|
targets.set(path, target);
|
|
@@ -12131,12 +12249,16 @@ function watchAftConfigFiles(options) {
|
|
|
12131
12249
|
}
|
|
12132
12250
|
return moved;
|
|
12133
12251
|
}
|
|
12134
|
-
revalidate();
|
|
12252
|
+
recheckAfterArming = revalidate();
|
|
12135
12253
|
if (options.checkAtStart)
|
|
12136
12254
|
check();
|
|
12137
12255
|
const revalidateTimer = setInterval(() => {
|
|
12138
|
-
if (
|
|
12256
|
+
if (stopped)
|
|
12257
|
+
return;
|
|
12258
|
+
const moved = revalidate();
|
|
12259
|
+
if (moved || recheckAfterArming)
|
|
12139
12260
|
schedule();
|
|
12261
|
+
recheckAfterArming = moved;
|
|
12140
12262
|
}, CONFIG_WATCH_REVALIDATE_MS);
|
|
12141
12263
|
revalidateTimer.unref?.();
|
|
12142
12264
|
return () => {
|
|
@@ -12179,6 +12301,10 @@ function aftLiveSecurityKeys(keys) {
|
|
|
12179
12301
|
return minutes(next) > minutes(current);
|
|
12180
12302
|
}
|
|
12181
12303
|
},
|
|
12304
|
+
{
|
|
12305
|
+
key: pick("lsp.max_servers"),
|
|
12306
|
+
loosens: (current, next) => (typeof next === "number" ? next : 8) > (typeof current === "number" ? current : 8)
|
|
12307
|
+
},
|
|
12182
12308
|
...[
|
|
12183
12309
|
"diagnostics",
|
|
12184
12310
|
"todos",
|
|
@@ -12288,7 +12414,7 @@ function startLiveConfigReload(options) {
|
|
|
12288
12414
|
import { createHash as createHash3, randomUUID } from "node:crypto";
|
|
12289
12415
|
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";
|
|
12290
12416
|
import { hostname } from "node:os";
|
|
12291
|
-
import { join as
|
|
12417
|
+
import { join as join7 } from "node:path";
|
|
12292
12418
|
import { Readable } from "node:stream";
|
|
12293
12419
|
import { pipeline } from "node:stream/promises";
|
|
12294
12420
|
|
|
@@ -12404,7 +12530,7 @@ function getBinaryName() {
|
|
|
12404
12530
|
function getCachedBinaryPath(version) {
|
|
12405
12531
|
if (!version)
|
|
12406
12532
|
return null;
|
|
12407
|
-
const binaryPath =
|
|
12533
|
+
const binaryPath = join7(getAftBinaryCacheDir(), version, getBinaryName());
|
|
12408
12534
|
return existsSync3(binaryPath) ? binaryPath : null;
|
|
12409
12535
|
}
|
|
12410
12536
|
async function downloadBinary(version) {
|
|
@@ -12421,16 +12547,16 @@ async function downloadBinary(version) {
|
|
|
12421
12547
|
return null;
|
|
12422
12548
|
}
|
|
12423
12549
|
const tag = rawTag.startsWith("v") ? rawTag : `v${rawTag}`;
|
|
12424
|
-
const versionedCacheDir =
|
|
12550
|
+
const versionedCacheDir = join7(getAftBinaryCacheDir(), tag);
|
|
12425
12551
|
const binaryName = getBinaryName();
|
|
12426
|
-
const binaryPath =
|
|
12552
|
+
const binaryPath = join7(versionedCacheDir, binaryName);
|
|
12427
12553
|
if (existsSync3(binaryPath) && await isExpectedCachedBinary(binaryPath, tag)) {
|
|
12428
12554
|
return binaryPath;
|
|
12429
12555
|
}
|
|
12430
12556
|
const downloadUrl = `https://github.com/${REPO}/releases/download/${tag}/${assetName}`;
|
|
12431
12557
|
const checksumUrl = `https://github.com/${REPO}/releases/download/${tag}/checksums.sha256`;
|
|
12432
12558
|
log(`Downloading AFT binary (${tag}) for ${platformKey}...`);
|
|
12433
|
-
const lockPath =
|
|
12559
|
+
const lockPath = join7(versionedCacheDir, ".download.lock");
|
|
12434
12560
|
let releaseLock = null;
|
|
12435
12561
|
let binaryController = null;
|
|
12436
12562
|
let checksumController = null;
|
|
@@ -12656,7 +12782,7 @@ function sweepStaleDownloadTemps(versionedCacheDir, binaryName) {
|
|
|
12656
12782
|
if (!entry.isFile() || !entry.name.startsWith(tempPrefix) || !entry.name.endsWith(".tmp")) {
|
|
12657
12783
|
continue;
|
|
12658
12784
|
}
|
|
12659
|
-
const tempPath =
|
|
12785
|
+
const tempPath = join7(versionedCacheDir, entry.name);
|
|
12660
12786
|
const ageMs = Date.now() - statSync4(tempPath).mtimeMs;
|
|
12661
12787
|
if (Math.abs(ageMs) > DOWNLOAD_LOCK_STALE_MS)
|
|
12662
12788
|
unlinkSync2(tempPath);
|
|
@@ -12747,7 +12873,7 @@ import { dirname as dirname3 } from "node:path";
|
|
|
12747
12873
|
|
|
12748
12874
|
// ../aft-bridge/dist/private-storage.js
|
|
12749
12875
|
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";
|
|
12750
|
-
import { isAbsolute as
|
|
12876
|
+
import { isAbsolute as isAbsolute3, join as join8, parse, relative as relative2, resolve as resolve5, sep } from "node:path";
|
|
12751
12877
|
var PRIVATE_FILE_MODE = 384;
|
|
12752
12878
|
var PRIVATE_DIRECTORY_MODE = 448;
|
|
12753
12879
|
function privateMkdirSync(path, recursive = true) {
|
|
@@ -12782,19 +12908,19 @@ function privateCopyFileSync(source, destination) {
|
|
|
12782
12908
|
}
|
|
12783
12909
|
var warned = new Set;
|
|
12784
12910
|
function openPrivateStorageDir(root, path = root) {
|
|
12785
|
-
const base =
|
|
12911
|
+
const base = resolve5(root);
|
|
12786
12912
|
if (!root || base === parse(base).root) {
|
|
12787
12913
|
throw new Error(`refusing filesystem root as private storage: ${base}`);
|
|
12788
12914
|
}
|
|
12789
|
-
const rel =
|
|
12790
|
-
if (rel === ".." || rel.startsWith(`..${sep}`) ||
|
|
12915
|
+
const rel = relative2(base, resolve5(path));
|
|
12916
|
+
if (rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute3(rel))
|
|
12791
12917
|
return;
|
|
12792
12918
|
privateMkdirSync(path);
|
|
12793
12919
|
if (process.platform === "win32")
|
|
12794
12920
|
return;
|
|
12795
12921
|
let current = base;
|
|
12796
12922
|
for (const component of ["", ...rel.split(sep).filter(Boolean)]) {
|
|
12797
|
-
current =
|
|
12923
|
+
current = join8(current, component);
|
|
12798
12924
|
let fd;
|
|
12799
12925
|
try {
|
|
12800
12926
|
if (lstatSync(current).isSymbolicLink())
|
|
@@ -13047,21 +13173,23 @@ ${reflowText}`;
|
|
|
13047
13173
|
}
|
|
13048
13174
|
return " Auto-formatted.";
|
|
13049
13175
|
}
|
|
13050
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
13176
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/client.js
|
|
13051
13177
|
import { promises as fs3 } from "node:fs";
|
|
13178
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
13052
13179
|
import { debuglog } from "node:util";
|
|
13053
13180
|
|
|
13054
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
13181
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/auth.js
|
|
13055
13182
|
import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
|
|
13056
13183
|
|
|
13057
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
13184
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/socket.js
|
|
13058
13185
|
import net from "node:net";
|
|
13059
13186
|
|
|
13060
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
13187
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/envelope.js
|
|
13061
13188
|
var PROTOCOL_VERSION = 2;
|
|
13062
13189
|
var HEADER_LEN = 21;
|
|
13063
13190
|
var FROZEN_PREFIX_LEN = 5;
|
|
13064
13191
|
var MAX_FRAME_BODY_LEN = 64 * 1024 * 1024;
|
|
13192
|
+
var MAX_DELIVERED_FRAME_LEN = 4 * 1024 * 1024;
|
|
13065
13193
|
var FrameType;
|
|
13066
13194
|
(function(FrameType) {
|
|
13067
13195
|
FrameType[FrameType["Request"] = 0] = "Request";
|
|
@@ -13099,6 +13227,8 @@ var FLAG_PRIORITY_SHIFT = 1;
|
|
|
13099
13227
|
var FLAG_LAST = 8;
|
|
13100
13228
|
var FLAG_ADMISSION_MASK = 48;
|
|
13101
13229
|
var FLAG_ADMISSION_SHIFT = 4;
|
|
13230
|
+
var DAEMON_ORIGIN_FLAG = 64;
|
|
13231
|
+
var SUBSCRIPTION_FLAG = 128;
|
|
13102
13232
|
var FLAG_RESERVED_MASK = 0;
|
|
13103
13233
|
function buildFlags(binary, priority, last, admissionClass = AdmissionClass.Normal) {
|
|
13104
13234
|
let flags = 0;
|
|
@@ -13233,7 +13363,7 @@ function encodeFrame(frame) {
|
|
|
13233
13363
|
return output;
|
|
13234
13364
|
}
|
|
13235
13365
|
|
|
13236
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
13366
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/socket.js
|
|
13237
13367
|
class SocketClosedError extends Error {
|
|
13238
13368
|
}
|
|
13239
13369
|
|
|
@@ -13283,14 +13413,12 @@ class SubcSocket {
|
|
|
13283
13413
|
sock.on("data", (chunk) => {
|
|
13284
13414
|
this.chunks.push(chunk);
|
|
13285
13415
|
this.buffered += chunk.length;
|
|
13286
|
-
if (this.waiter) {
|
|
13416
|
+
if (this.waiter && this.waiter.extendOnProgress && this.buffered < this.waiter.need) {
|
|
13287
13417
|
if (this.waiter.immediate) {
|
|
13288
13418
|
clearImmediate(this.waiter.immediate);
|
|
13289
13419
|
this.waiter.immediate = null;
|
|
13290
13420
|
}
|
|
13291
|
-
|
|
13292
|
-
this.armWaiterTimer(this.waiter);
|
|
13293
|
-
}
|
|
13421
|
+
this.armWaiterTimer(this.waiter);
|
|
13294
13422
|
}
|
|
13295
13423
|
this.tryServe();
|
|
13296
13424
|
});
|
|
@@ -13307,12 +13435,18 @@ class SubcSocket {
|
|
|
13307
13435
|
return this.sock.localPort ?? null;
|
|
13308
13436
|
}
|
|
13309
13437
|
static connect(host, port, deadlineMs) {
|
|
13438
|
+
return SubcSocket.connectTo({ host, port }, `${host}:${port}`, deadlineMs);
|
|
13439
|
+
}
|
|
13440
|
+
static connectLocal(path, deadlineMs) {
|
|
13441
|
+
return SubcSocket.connectTo({ path }, path, deadlineMs);
|
|
13442
|
+
}
|
|
13443
|
+
static connectTo(options, endpoint, deadlineMs) {
|
|
13310
13444
|
return new Promise((resolve, reject) => {
|
|
13311
|
-
const sock = net.connect(
|
|
13445
|
+
const sock = net.connect(options);
|
|
13312
13446
|
sock.setNoDelay(true);
|
|
13313
13447
|
const timer = setTimeout(() => {
|
|
13314
13448
|
sock.destroy();
|
|
13315
|
-
reject(new SocketTimeoutError(`timed out connecting to ${
|
|
13449
|
+
reject(new SocketTimeoutError(`timed out connecting to ${endpoint}`));
|
|
13316
13450
|
}, Math.max(0, deadlineMs - Date.now()));
|
|
13317
13451
|
sock.once("connect", () => {
|
|
13318
13452
|
clearTimeout(timer);
|
|
@@ -13529,7 +13663,7 @@ class SubcSocket {
|
|
|
13529
13663
|
}
|
|
13530
13664
|
}
|
|
13531
13665
|
|
|
13532
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
13666
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/auth.js
|
|
13533
13667
|
var NONCE_LEN = 32;
|
|
13534
13668
|
var MAX_AUTH_MESSAGE_LEN = 4096;
|
|
13535
13669
|
var SERVER_PROOF_DOMAIN = "subc-server-v1";
|
|
@@ -13603,7 +13737,7 @@ async function authenticateClient(sock, conn, deadlineMs) {
|
|
|
13603
13737
|
await writeMessage(sock, { client_auth: Array.from(clientAuth) }, deadlineMs);
|
|
13604
13738
|
}
|
|
13605
13739
|
|
|
13606
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
13740
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/connection-file.js
|
|
13607
13741
|
import { promises as fs2 } from "node:fs";
|
|
13608
13742
|
var SCHEMA_VERSION = 1;
|
|
13609
13743
|
var MIN_KEY_LEN = 32;
|
|
@@ -13650,7 +13784,10 @@ function verifyOwnerOnly(path, stat, expectedUid) {
|
|
|
13650
13784
|
async function readConnectionFile(path) {
|
|
13651
13785
|
return readConnectionFileForUid(path, process.geteuid?.());
|
|
13652
13786
|
}
|
|
13653
|
-
async function
|
|
13787
|
+
async function readConnectionFileWithLocalEndpoint(path) {
|
|
13788
|
+
return readConnectionFileForUid(path, process.geteuid?.(), true);
|
|
13789
|
+
}
|
|
13790
|
+
async function readConnectionFileForUid(path, expectedUid, includeLocalEndpoint = false) {
|
|
13654
13791
|
const handle = await fs2.open(path, "r");
|
|
13655
13792
|
let raw;
|
|
13656
13793
|
try {
|
|
@@ -13689,13 +13826,26 @@ async function readConnectionFileForUid(path, expectedUid) {
|
|
|
13689
13826
|
daemonVer: parsed.daemon_ver ?? ""
|
|
13690
13827
|
};
|
|
13691
13828
|
validate(info);
|
|
13829
|
+
if (includeLocalEndpoint && parsed.local_endpoint != null) {
|
|
13830
|
+
const endpoint = parsed.local_endpoint;
|
|
13831
|
+
if (endpoint.kind === "unix" && typeof endpoint.path === "string" && endpoint.path.length > 0) {
|
|
13832
|
+
info.localEndpoint = { kind: "unix", path: endpoint.path };
|
|
13833
|
+
} else if (endpoint.kind === "pipe" && typeof endpoint.name === "string" && endpoint.name.length > 0) {
|
|
13834
|
+
info.localEndpoint = { kind: "pipe", name: endpoint.name };
|
|
13835
|
+
} else {
|
|
13836
|
+
throw new ConnectionFileError("connection file local_endpoint must name a unix path or pipe name");
|
|
13837
|
+
}
|
|
13838
|
+
}
|
|
13692
13839
|
return info;
|
|
13693
13840
|
}
|
|
13694
13841
|
|
|
13695
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
13842
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/launch-nonce.js
|
|
13696
13843
|
import { closeSync as closeSync5, fstatSync as fstatSync3, readSync as readSync4 } from "node:fs";
|
|
13844
|
+
import { connect } from "node:net";
|
|
13697
13845
|
var SUBC_LAUNCH_NONCE_ENV = "SUBC_LAUNCH_NONCE";
|
|
13698
13846
|
var SUBC_LAUNCH_NONCE_FD_ENV = "SUBC_LAUNCH_NONCE_FD";
|
|
13847
|
+
var SUBC_LAUNCH_NONCE_PIPE_ENV = "SUBC_LAUNCH_NONCE_PIPE";
|
|
13848
|
+
var SUBC_LAUNCH_NONCE_PIPE_FALLBACK_ENV = "SUBC_LAUNCH_NONCE_PIPE_FALLBACK";
|
|
13699
13849
|
class LaunchNonceError extends Error {
|
|
13700
13850
|
name = "LaunchNonceError";
|
|
13701
13851
|
kind;
|
|
@@ -13714,9 +13864,21 @@ class LaunchNonceError extends Error {
|
|
|
13714
13864
|
this.foundInode = details.foundInode;
|
|
13715
13865
|
}
|
|
13716
13866
|
}
|
|
13717
|
-
function
|
|
13718
|
-
|
|
13719
|
-
|
|
13867
|
+
function isLaunchNonceError(error) {
|
|
13868
|
+
return error instanceof Error && error.name === "LaunchNonceError" && typeof error.kind === "string";
|
|
13869
|
+
}
|
|
13870
|
+
async function launchNonceAsync() {
|
|
13871
|
+
const cell = processCell();
|
|
13872
|
+
return unwrap(await (cell.resultAsync?.() ?? cell.result()));
|
|
13873
|
+
}
|
|
13874
|
+
async function launchNonceOrUndefinedAsync() {
|
|
13875
|
+
try {
|
|
13876
|
+
return await launchNonceAsync();
|
|
13877
|
+
} catch (error) {
|
|
13878
|
+
if (isLaunchNonceError(error))
|
|
13879
|
+
return;
|
|
13880
|
+
throw error;
|
|
13881
|
+
}
|
|
13720
13882
|
}
|
|
13721
13883
|
var PROCESS_CELL_KEY = Symbol.for("@cortexkit/subc-client/launch-nonce/v1");
|
|
13722
13884
|
function processCell() {
|
|
@@ -13736,20 +13898,60 @@ function unwrap(result) {
|
|
|
13736
13898
|
|
|
13737
13899
|
class LaunchNonceCell {
|
|
13738
13900
|
cached;
|
|
13901
|
+
pending;
|
|
13739
13902
|
descriptorReads = 0;
|
|
13740
13903
|
lookup;
|
|
13741
13904
|
platform;
|
|
13742
13905
|
stat;
|
|
13743
|
-
|
|
13906
|
+
pipeReader;
|
|
13907
|
+
constructor(lookup, platform = process.platform, stat = (fd) => fstatSync3(fd, { bigint: true }), pipeReader = readLaunchNoncePipe) {
|
|
13744
13908
|
this.lookup = lookup;
|
|
13745
13909
|
this.platform = platform;
|
|
13746
13910
|
this.stat = stat;
|
|
13911
|
+
this.pipeReader = pipeReader;
|
|
13747
13912
|
}
|
|
13748
13913
|
result() {
|
|
13914
|
+
if (this.cached === undefined && this.platform === "win32" && this.lookup(SUBC_LAUNCH_NONCE_PIPE_ENV) !== undefined) {
|
|
13915
|
+
const fallback = this.permittedPipeFallback();
|
|
13916
|
+
if (fallback === undefined) {
|
|
13917
|
+
throw new LaunchNonceError("PipeNeedsAsync", "call launchNonceAsync() before the synchronous reader when SUBC_LAUNCH_NONCE_PIPE is set");
|
|
13918
|
+
}
|
|
13919
|
+
this.cached = { ok: true, nonce: fallback };
|
|
13920
|
+
}
|
|
13749
13921
|
if (this.cached === undefined)
|
|
13750
13922
|
this.cached = this.read();
|
|
13751
13923
|
return this.cached;
|
|
13752
13924
|
}
|
|
13925
|
+
async resultAsync() {
|
|
13926
|
+
if (this.cached !== undefined)
|
|
13927
|
+
return this.cached;
|
|
13928
|
+
if (this.pending !== undefined)
|
|
13929
|
+
return this.pending;
|
|
13930
|
+
const named = this.platform === "win32" ? this.lookup(SUBC_LAUNCH_NONCE_PIPE_ENV) : undefined;
|
|
13931
|
+
if (named === undefined)
|
|
13932
|
+
return this.result();
|
|
13933
|
+
const fallback = this.permittedPipeFallback();
|
|
13934
|
+
this.pending = this.pipeReader(named).then((nonce) => ({ ok: true, nonce: fallback !== undefined && nonce.value !== fallback.value ? fallback : nonce }), (error) => {
|
|
13935
|
+
if (fallback !== undefined)
|
|
13936
|
+
return { ok: true, nonce: fallback };
|
|
13937
|
+
if (!isLaunchNonceError(error))
|
|
13938
|
+
throw error;
|
|
13939
|
+
return { ok: false, error };
|
|
13940
|
+
}).then((result) => {
|
|
13941
|
+
this.cached ??= result;
|
|
13942
|
+
return this.cached;
|
|
13943
|
+
});
|
|
13944
|
+
return this.pending;
|
|
13945
|
+
}
|
|
13946
|
+
permittedPipeFallback() {
|
|
13947
|
+
if (this.lookup(SUBC_LAUNCH_NONCE_PIPE_FALLBACK_ENV) !== "env")
|
|
13948
|
+
return;
|
|
13949
|
+
const value = this.lookup(SUBC_LAUNCH_NONCE_ENV);
|
|
13950
|
+
return value ? makeLaunchNonce(value, "env") : undefined;
|
|
13951
|
+
}
|
|
13952
|
+
async getAsync() {
|
|
13953
|
+
return unwrap(await this.resultAsync());
|
|
13954
|
+
}
|
|
13753
13955
|
get() {
|
|
13754
13956
|
return unwrap(this.result());
|
|
13755
13957
|
}
|
|
@@ -13880,8 +14082,198 @@ function closeQuietly(fd) {
|
|
|
13880
14082
|
closeSync5(fd);
|
|
13881
14083
|
} catch {}
|
|
13882
14084
|
}
|
|
14085
|
+
async function readLaunchNoncePipe(name, connector = (path) => connect(path), openWindowMs = 500, readWindowMs = 2000) {
|
|
14086
|
+
const deadline = Date.now() + openWindowMs;
|
|
14087
|
+
for (;; ) {
|
|
14088
|
+
try {
|
|
14089
|
+
const bytes = await pipeAttempt(name, connector, Math.max(1, deadline - Date.now()), readWindowMs);
|
|
14090
|
+
if (bytes.length === 0)
|
|
14091
|
+
throw new LaunchNonceError("PipeEmpty", "the launch nonce named pipe is empty");
|
|
14092
|
+
let value;
|
|
14093
|
+
try {
|
|
14094
|
+
value = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
14095
|
+
} catch {
|
|
14096
|
+
throw new LaunchNonceError("PipeNotUtf8", "the launch nonce named pipe held bytes that are not UTF-8");
|
|
14097
|
+
}
|
|
14098
|
+
return makeLaunchNonce(value, "pipe");
|
|
14099
|
+
} catch (error) {
|
|
14100
|
+
if (isLaunchNonceError(error))
|
|
14101
|
+
throw error;
|
|
14102
|
+
const busy = error?.code === "EBUSY" || errnoOf(error) === 231;
|
|
14103
|
+
if (!busy || Date.now() >= deadline) {
|
|
14104
|
+
throw new LaunchNonceError("PipeNotOpen", "SUBC_LAUNCH_NONCE_PIPE names a pipe that could not be opened", { errno: errnoOf(error) });
|
|
14105
|
+
}
|
|
14106
|
+
await new Promise((resolve) => setTimeout(resolve, Math.min(10, Math.max(1, deadline - Date.now()))));
|
|
14107
|
+
}
|
|
14108
|
+
}
|
|
14109
|
+
}
|
|
14110
|
+
function pipeAttempt(name, connector, openWindowMs, readWindowMs) {
|
|
14111
|
+
return new Promise((resolve, reject) => {
|
|
14112
|
+
let socket;
|
|
14113
|
+
try {
|
|
14114
|
+
socket = connector(name);
|
|
14115
|
+
} catch (error) {
|
|
14116
|
+
reject(error);
|
|
14117
|
+
return;
|
|
14118
|
+
}
|
|
14119
|
+
let connected = false;
|
|
14120
|
+
let settled = false;
|
|
14121
|
+
let size = 0;
|
|
14122
|
+
const chunks = [];
|
|
14123
|
+
let timer = setTimeout(() => finish(new LaunchNonceError("PipeNotOpen", "launch nonce pipe open timed out")), openWindowMs);
|
|
14124
|
+
function finish(error) {
|
|
14125
|
+
if (settled)
|
|
14126
|
+
return;
|
|
14127
|
+
settled = true;
|
|
14128
|
+
clearTimeout(timer);
|
|
14129
|
+
socket.destroy();
|
|
14130
|
+
if (error !== undefined)
|
|
14131
|
+
reject(error);
|
|
14132
|
+
else
|
|
14133
|
+
resolve(Buffer.concat(chunks));
|
|
14134
|
+
}
|
|
14135
|
+
socket.once("connect", () => {
|
|
14136
|
+
connected = true;
|
|
14137
|
+
clearTimeout(timer);
|
|
14138
|
+
timer = setTimeout(() => finish(new LaunchNonceError("PipeUnreadable", "launch nonce pipe read timed out")), readWindowMs);
|
|
14139
|
+
});
|
|
14140
|
+
socket.on("data", (chunk) => {
|
|
14141
|
+
size += chunk.length;
|
|
14142
|
+
if (size > 4096) {
|
|
14143
|
+
finish(new LaunchNonceError("PipeUnreadable", "launch nonce pipe exceeded its byte limit"));
|
|
14144
|
+
return;
|
|
14145
|
+
}
|
|
14146
|
+
chunks.push(Buffer.from(chunk));
|
|
14147
|
+
});
|
|
14148
|
+
socket.once("end", () => finish());
|
|
14149
|
+
socket.once("error", (error) => finish(connected ? new LaunchNonceError("PipeUnreadable", "could not read the launch nonce from the named pipe", { errno: errnoOf(error) }) : error));
|
|
14150
|
+
socket.once("close", () => {
|
|
14151
|
+
if (!settled)
|
|
14152
|
+
finish(new LaunchNonceError("PipeUnreadable", "launch nonce pipe closed before EOF"));
|
|
14153
|
+
});
|
|
14154
|
+
});
|
|
14155
|
+
}
|
|
14156
|
+
|
|
14157
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/request-gate.js
|
|
14158
|
+
class Lane {
|
|
14159
|
+
limit;
|
|
14160
|
+
used = 0;
|
|
14161
|
+
waiters = [];
|
|
14162
|
+
failure;
|
|
14163
|
+
constructor(limit) {
|
|
14164
|
+
this.limit = limit;
|
|
14165
|
+
}
|
|
14166
|
+
acquire(timeoutMs, signal) {
|
|
14167
|
+
if (this.failure)
|
|
14168
|
+
return Promise.reject(this.failure);
|
|
14169
|
+
if (signal?.aborted)
|
|
14170
|
+
return Promise.reject(new Error("request cancelled before write"));
|
|
14171
|
+
if (timeoutMs !== undefined && timeoutMs <= 0)
|
|
14172
|
+
return Promise.reject(new Error("request deadline elapsed waiting for a slot"));
|
|
14173
|
+
if (this.used < this.limit && this.waiters.length === 0) {
|
|
14174
|
+
this.used++;
|
|
14175
|
+
return Promise.resolve(this.releaser());
|
|
14176
|
+
}
|
|
14177
|
+
return new Promise((resolve, reject) => {
|
|
14178
|
+
let timer;
|
|
14179
|
+
const clean = () => {
|
|
14180
|
+
if (timer !== undefined)
|
|
14181
|
+
clearTimeout(timer);
|
|
14182
|
+
signal?.removeEventListener("abort", abort);
|
|
14183
|
+
};
|
|
14184
|
+
const waiter = {
|
|
14185
|
+
grant: () => {
|
|
14186
|
+
clean();
|
|
14187
|
+
resolve(this.releaser());
|
|
14188
|
+
},
|
|
14189
|
+
fail: (error) => {
|
|
14190
|
+
clean();
|
|
14191
|
+
reject(error);
|
|
14192
|
+
}
|
|
14193
|
+
};
|
|
14194
|
+
const abort = () => {
|
|
14195
|
+
const index = this.waiters.indexOf(waiter);
|
|
14196
|
+
if (index < 0)
|
|
14197
|
+
return;
|
|
14198
|
+
this.waiters.splice(index, 1);
|
|
14199
|
+
waiter.fail(new Error("request cancelled before write"));
|
|
14200
|
+
};
|
|
14201
|
+
this.waiters.push(waiter);
|
|
14202
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
14203
|
+
if (timeoutMs !== undefined)
|
|
14204
|
+
timer = setTimeout(() => {
|
|
14205
|
+
const index = this.waiters.indexOf(waiter);
|
|
14206
|
+
if (index < 0)
|
|
14207
|
+
return;
|
|
14208
|
+
this.waiters.splice(index, 1);
|
|
14209
|
+
waiter.fail(new Error("request deadline elapsed waiting for a slot"));
|
|
14210
|
+
}, timeoutMs);
|
|
14211
|
+
});
|
|
14212
|
+
}
|
|
14213
|
+
close(error) {
|
|
14214
|
+
this.failure = error;
|
|
14215
|
+
for (const waiter of this.waiters.splice(0))
|
|
14216
|
+
waiter.fail(error);
|
|
14217
|
+
}
|
|
14218
|
+
releaser() {
|
|
14219
|
+
let released = false;
|
|
14220
|
+
return () => {
|
|
14221
|
+
if (released)
|
|
14222
|
+
return;
|
|
14223
|
+
released = true;
|
|
14224
|
+
const waiter = this.waiters.shift();
|
|
14225
|
+
if (waiter)
|
|
14226
|
+
waiter.grant();
|
|
14227
|
+
else
|
|
14228
|
+
this.used--;
|
|
14229
|
+
};
|
|
14230
|
+
}
|
|
14231
|
+
}
|
|
13883
14232
|
|
|
13884
|
-
|
|
14233
|
+
class RequestGate {
|
|
14234
|
+
total;
|
|
14235
|
+
watches;
|
|
14236
|
+
slots = new Set;
|
|
14237
|
+
closed = new AbortController;
|
|
14238
|
+
get signal() {
|
|
14239
|
+
return this.closed.signal;
|
|
14240
|
+
}
|
|
14241
|
+
constructor(requestWindow, watchWindow) {
|
|
14242
|
+
this.total = new Lane(requestWindow);
|
|
14243
|
+
if (watchWindow !== undefined)
|
|
14244
|
+
this.watches = new Lane(watchWindow);
|
|
14245
|
+
}
|
|
14246
|
+
async acquire(watch, timeoutMs, signal) {
|
|
14247
|
+
const deadline = timeoutMs === undefined ? undefined : Date.now() + timeoutMs;
|
|
14248
|
+
const watchRelease = watch && this.watches ? await this.watches.acquire(timeoutMs, signal) : undefined;
|
|
14249
|
+
try {
|
|
14250
|
+
const totalRelease = await this.total.acquire(deadline === undefined ? undefined : deadline - Date.now(), signal);
|
|
14251
|
+
const slot = {
|
|
14252
|
+
inFlight: false,
|
|
14253
|
+
release: () => {
|
|
14254
|
+
if (!this.slots.delete(slot))
|
|
14255
|
+
return;
|
|
14256
|
+
totalRelease();
|
|
14257
|
+
watchRelease?.();
|
|
14258
|
+
}
|
|
14259
|
+
};
|
|
14260
|
+
this.slots.add(slot);
|
|
14261
|
+
return slot;
|
|
14262
|
+
} catch (error) {
|
|
14263
|
+
watchRelease?.();
|
|
14264
|
+
throw error;
|
|
14265
|
+
}
|
|
14266
|
+
}
|
|
14267
|
+
close(error) {
|
|
14268
|
+
this.total.close(error);
|
|
14269
|
+
this.watches?.close(error);
|
|
14270
|
+
this.closed.abort(error);
|
|
14271
|
+
for (const slot of this.slots)
|
|
14272
|
+
slot.release();
|
|
14273
|
+
}
|
|
14274
|
+
}
|
|
14275
|
+
|
|
14276
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/route-handle.js
|
|
13885
14277
|
var connectionToken = new WeakMap;
|
|
13886
14278
|
var reverseRequests = new WeakMap;
|
|
13887
14279
|
|
|
@@ -13974,10 +14366,13 @@ function sameRouteHandle(left, right) {
|
|
|
13974
14366
|
return left === right;
|
|
13975
14367
|
}
|
|
13976
14368
|
|
|
13977
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
14369
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/client.js
|
|
13978
14370
|
var debug = debuglog("subc-client");
|
|
13979
14371
|
var DEFAULT_HANDSHAKE_TIMEOUT_MS = 1e4;
|
|
13980
14372
|
var DEFAULT_REQUEST_TIMEOUT_MS = 30000;
|
|
14373
|
+
var DEFAULT_SLEEP_GRACE_MS = 15000;
|
|
14374
|
+
var SLEEP_DETECTION_THRESHOLD_MS = 2000;
|
|
14375
|
+
var MIN_REQUEST_BUDGET_MS = 1;
|
|
13981
14376
|
var TIMEOUT_ARBITRATION_GRACE_MS = 50;
|
|
13982
14377
|
var LIVENESS_PROBE_WINDOW_MS = 2000;
|
|
13983
14378
|
var REQUEST_DEADLINE_MARKER = "request_deadline";
|
|
@@ -14013,6 +14408,14 @@ class SubcCallError extends Error {
|
|
|
14013
14408
|
}
|
|
14014
14409
|
}
|
|
14015
14410
|
|
|
14411
|
+
class DaemonUnavailableError extends SubcCallError {
|
|
14412
|
+
recovery = "user_action_required";
|
|
14413
|
+
constructor(cause) {
|
|
14414
|
+
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);
|
|
14415
|
+
this.name = "DaemonUnavailableError";
|
|
14416
|
+
}
|
|
14417
|
+
}
|
|
14418
|
+
|
|
14016
14419
|
class SubcError extends Error {
|
|
14017
14420
|
code;
|
|
14018
14421
|
detail;
|
|
@@ -14137,6 +14540,14 @@ class SubcClient {
|
|
|
14137
14540
|
reconnecting = null;
|
|
14138
14541
|
generation = 1;
|
|
14139
14542
|
routeOpenGateInstance;
|
|
14543
|
+
requestGates;
|
|
14544
|
+
wireSlots;
|
|
14545
|
+
get gates() {
|
|
14546
|
+
return this.requestGates ??= new Map;
|
|
14547
|
+
}
|
|
14548
|
+
get slots() {
|
|
14549
|
+
return this.wireSlots ??= new Map;
|
|
14550
|
+
}
|
|
14140
14551
|
readerActive = false;
|
|
14141
14552
|
constructor(sock, currentConn, opts) {
|
|
14142
14553
|
this.sock = sock;
|
|
@@ -14152,8 +14563,15 @@ class SubcClient {
|
|
|
14152
14563
|
}
|
|
14153
14564
|
static async connect(opts) {
|
|
14154
14565
|
const normalized = normalizeConnectOptions(opts);
|
|
14155
|
-
|
|
14156
|
-
|
|
14566
|
+
try {
|
|
14567
|
+
const opened = await SubcClient.openConnection(normalized);
|
|
14568
|
+
return new SubcClient(opened.sock, opened.conn, normalized);
|
|
14569
|
+
} catch (err) {
|
|
14570
|
+
if (errorCode(err) === "ENOENT" || errorCode(err) === "ECONNREFUSED") {
|
|
14571
|
+
throw new DaemonUnavailableError(err);
|
|
14572
|
+
}
|
|
14573
|
+
throw err;
|
|
14574
|
+
}
|
|
14157
14575
|
}
|
|
14158
14576
|
async catalogList(moduleId) {
|
|
14159
14577
|
const body = this.encode(moduleId === undefined ? { op: "catalog.list" } : { op: "catalog.list", module_id: moduleId });
|
|
@@ -14189,17 +14607,23 @@ class SubcClient {
|
|
|
14189
14607
|
}
|
|
14190
14608
|
async sendRouteOpen(target, identity, opts = {}) {
|
|
14191
14609
|
const scope = validatedRouteScope(opts.scope);
|
|
14192
|
-
const consumerIdentity = routeOpenConsumerIdentity(opts);
|
|
14610
|
+
const consumerIdentity = await routeOpenConsumerIdentity(opts);
|
|
14193
14611
|
const reverseRequests = opts.reverseRequests ?? new ReverseRequestRegistry;
|
|
14194
14612
|
reverseRequests.seal();
|
|
14195
14613
|
const consumerCapabilities = reverseRequests.capabilities();
|
|
14196
14614
|
const body = this.encode({
|
|
14197
14615
|
op: "route.open",
|
|
14616
|
+
busy_refusals: true,
|
|
14198
14617
|
target,
|
|
14199
14618
|
identity,
|
|
14200
14619
|
...consumerIdentity ? { consumer_identity: consumerIdentity } : {},
|
|
14201
14620
|
...consumerCapabilities.length > 0 ? { consumer_capabilities: consumerCapabilities } : {},
|
|
14202
|
-
...scope ? { scope: {
|
|
14621
|
+
...scope ? { scope: {
|
|
14622
|
+
owner: scope.owner,
|
|
14623
|
+
ref: scope.ref,
|
|
14624
|
+
scope_epoch: scope.scopeEpoch,
|
|
14625
|
+
...scope.bindProof !== undefined ? { bind_proof: scope.bindProof } : {}
|
|
14626
|
+
} } : {}
|
|
14203
14627
|
});
|
|
14204
14628
|
let installed = null;
|
|
14205
14629
|
const install = (frame) => {
|
|
@@ -14210,6 +14634,8 @@ class SubcClient {
|
|
|
14210
14634
|
throw new SubcError(`route.open returned no route handle: ${JSON.stringify(parsed)}`);
|
|
14211
14635
|
}
|
|
14212
14636
|
installed = this.installRoute(parsed.route_channel, parsed.route_epoch, reverseRequests);
|
|
14637
|
+
if (parsed.request_window !== undefined)
|
|
14638
|
+
this.gates.set(installed, new RequestGate(parsed.request_window, parsed.watch_window));
|
|
14213
14639
|
this.routeModules.set(parsed.route_channel, target.module_id);
|
|
14214
14640
|
return true;
|
|
14215
14641
|
};
|
|
@@ -14239,7 +14665,7 @@ class SubcClient {
|
|
|
14239
14665
|
const bytes = binary ? requireBinaryBody(body) : body instanceof Uint8Array ? body : this.encode(body);
|
|
14240
14666
|
const priority = opts.priority ?? Priority.Interactive;
|
|
14241
14667
|
const admission = opts.admissionClass ?? AdmissionClass.Normal;
|
|
14242
|
-
const reply = await this.send(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress, undefined, undefined, binary, opts.signal);
|
|
14668
|
+
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));
|
|
14243
14669
|
return this.decodeReply(reply);
|
|
14244
14670
|
}
|
|
14245
14671
|
async call(moduleId, method, params, opts = {}) {
|
|
@@ -14255,10 +14681,12 @@ class SubcClient {
|
|
|
14255
14681
|
}
|
|
14256
14682
|
async managedCall(moduleId, body, opts) {
|
|
14257
14683
|
let retriedUnknownChannel = false;
|
|
14684
|
+
const startedAt = opts.timeoutMs === undefined ? undefined : this.opts.now();
|
|
14685
|
+
let attemptOpts = opts;
|
|
14258
14686
|
for (;; ) {
|
|
14259
|
-
const routeHandle = await this.cachedRouteHandle(moduleId,
|
|
14687
|
+
const routeHandle = await this.cachedRouteHandle(moduleId, attemptOpts);
|
|
14260
14688
|
try {
|
|
14261
|
-
return await this.managedRequest(routeHandle, body,
|
|
14689
|
+
return await this.managedRequest(routeHandle, body, attemptOpts);
|
|
14262
14690
|
} catch (err) {
|
|
14263
14691
|
if (!(err instanceof SubcCallError))
|
|
14264
14692
|
throw this.terminalCallError("managed call failed", err);
|
|
@@ -14268,6 +14696,15 @@ class SubcClient {
|
|
|
14268
14696
|
this.evictRouteHandle(routeHandle);
|
|
14269
14697
|
continue;
|
|
14270
14698
|
}
|
|
14699
|
+
if (isDataPlaneDrainRefusal(err.code) && !retriedUnknownChannel && !this.closeStarted && !opts.signal?.aborted) {
|
|
14700
|
+
const remainingMs = opts.timeoutMs === undefined || startedAt === undefined ? undefined : opts.timeoutMs - (this.opts.now() - startedAt);
|
|
14701
|
+
if (remainingMs === undefined || remainingMs > 0) {
|
|
14702
|
+
retriedUnknownChannel = true;
|
|
14703
|
+
this.evictRouteHandle(routeHandle);
|
|
14704
|
+
attemptOpts = remainingMs === undefined ? opts : { ...opts, timeoutMs: remainingMs };
|
|
14705
|
+
continue;
|
|
14706
|
+
}
|
|
14707
|
+
}
|
|
14271
14708
|
if (deadBindCode && retriedUnknownChannel) {
|
|
14272
14709
|
this.evictRouteHandle(routeHandle);
|
|
14273
14710
|
}
|
|
@@ -14297,6 +14734,8 @@ class SubcClient {
|
|
|
14297
14734
|
}
|
|
14298
14735
|
subscribe(handle, body, onEvent, opts = {}) {
|
|
14299
14736
|
this.assertLiveHandle(handle);
|
|
14737
|
+
if (this.gates.has(handle))
|
|
14738
|
+
return this.subscribeGated(handle, body, onEvent, opts);
|
|
14300
14739
|
const bytes = body instanceof Uint8Array ? body : this.encode(body);
|
|
14301
14740
|
const priority = opts.priority ?? Priority.Interactive;
|
|
14302
14741
|
const admission = opts.admissionClass ?? AdmissionClass.Normal;
|
|
@@ -14304,22 +14743,43 @@ class SubcClient {
|
|
|
14304
14743
|
const key = pendingKey(handle, corr);
|
|
14305
14744
|
let subscriptionPending = null;
|
|
14306
14745
|
let resolveClosed = null;
|
|
14746
|
+
let resolveEnded;
|
|
14747
|
+
const ended = new Promise((resolve) => {
|
|
14748
|
+
resolveEnded = resolve;
|
|
14749
|
+
});
|
|
14750
|
+
const endFailure = (err, frame) => {
|
|
14751
|
+
if (frame?.header.ty === FrameType.Error) {
|
|
14752
|
+
const error = err;
|
|
14753
|
+
resolveEnded({ kind: "error", code: error.code, message: error.message, detail: error.detail });
|
|
14754
|
+
} else if (err instanceof SubcError && err.closeReason && err.closeReason !== "connection_lost") {
|
|
14755
|
+
resolveEnded({ kind: "route_closed", reason: err.closeReason });
|
|
14756
|
+
} else {
|
|
14757
|
+
resolveEnded({ kind: "connection_lost" });
|
|
14758
|
+
}
|
|
14759
|
+
};
|
|
14307
14760
|
const closed = new Promise((resolve, reject) => {
|
|
14308
14761
|
if (this.closedErr) {
|
|
14762
|
+
endFailure(this.closedErr);
|
|
14309
14763
|
reject(this.closedErr);
|
|
14310
14764
|
return;
|
|
14311
14765
|
}
|
|
14312
14766
|
resolveClosed = resolve;
|
|
14313
14767
|
subscriptionPending = {
|
|
14314
14768
|
handle,
|
|
14315
|
-
resolve: () =>
|
|
14316
|
-
|
|
14769
|
+
resolve: (frame) => {
|
|
14770
|
+
resolveEnded(frame.header.ty === FrameType.Response ? { kind: "response", body: frame.body } : { kind: "stream_end" });
|
|
14771
|
+
resolve();
|
|
14772
|
+
},
|
|
14773
|
+
reject: (err, frame) => {
|
|
14774
|
+
endFailure(err, frame);
|
|
14775
|
+
reject(err);
|
|
14776
|
+
},
|
|
14317
14777
|
onProgress: onEvent,
|
|
14318
14778
|
timer: null,
|
|
14319
14779
|
subscription: true
|
|
14320
14780
|
};
|
|
14321
14781
|
this.pending.set(key, subscriptionPending);
|
|
14322
|
-
const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), handle.channel, handle.epoch, corr, bytes);
|
|
14782
|
+
const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission) | SUBSCRIPTION_FLAG, handle.channel, handle.epoch, corr, bytes);
|
|
14323
14783
|
writeBorrowed(this.sock, encodeFrame(frame), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS).catch((err) => {
|
|
14324
14784
|
const pending = this.pending.get(key);
|
|
14325
14785
|
if (pending)
|
|
@@ -14332,11 +14792,14 @@ class SubcClient {
|
|
|
14332
14792
|
return;
|
|
14333
14793
|
cancelled = true;
|
|
14334
14794
|
if (subscriptionPending && resolveClosed)
|
|
14335
|
-
this.settle(key, subscriptionPending,
|
|
14795
|
+
this.settle(key, subscriptionPending, () => {
|
|
14796
|
+
resolveEnded({ kind: "cancelled" });
|
|
14797
|
+
resolveClosed?.();
|
|
14798
|
+
});
|
|
14336
14799
|
if (this.isLiveHandle(handle))
|
|
14337
14800
|
this.cancel(handle, corr, priority);
|
|
14338
14801
|
};
|
|
14339
|
-
return { unsubscribe, closed };
|
|
14802
|
+
return { unsubscribe, closed, ended };
|
|
14340
14803
|
}
|
|
14341
14804
|
attachCancelSignal(signal, key, handle, corr, priority) {
|
|
14342
14805
|
if (!handle)
|
|
@@ -14402,7 +14865,7 @@ class SubcClient {
|
|
|
14402
14865
|
this.sendRouteGoodbye(handle);
|
|
14403
14866
|
}
|
|
14404
14867
|
async closeManagedRoute(target, identity, opts = {}) {
|
|
14405
|
-
const key = routeCacheKey(target, identity, routeOpenConsumerIdentity(opts), (opts.reverseRequests ?? new ReverseRequestRegistry).capabilities(), validatedRouteScope(opts.scope));
|
|
14868
|
+
const key = routeCacheKey(target, identity, await routeOpenConsumerIdentity(opts), (opts.reverseRequests ?? new ReverseRequestRegistry).capabilities(), validatedRouteScope(opts.scope));
|
|
14406
14869
|
const cached = this.routes.get(key);
|
|
14407
14870
|
if (!cached)
|
|
14408
14871
|
return;
|
|
@@ -14455,10 +14918,21 @@ class SubcClient {
|
|
|
14455
14918
|
});
|
|
14456
14919
|
}
|
|
14457
14920
|
static async openConnection(opts) {
|
|
14458
|
-
const conn = await readConnectionFile(opts.connectionFile);
|
|
14921
|
+
const conn = opts.transport === "local" ? await readConnectionFileWithLocalEndpoint(opts.connectionFile) : await readConnectionFile(opts.connectionFile);
|
|
14459
14922
|
const deadline = Date.now() + (opts.handshakeTimeoutMs ?? DEFAULT_HANDSHAKE_TIMEOUT_MS);
|
|
14460
14923
|
const endpoint = conn.endpoints[0];
|
|
14461
|
-
|
|
14924
|
+
let sock;
|
|
14925
|
+
if (opts.transport === "local") {
|
|
14926
|
+
const local = conn.localEndpoint;
|
|
14927
|
+
if (!local)
|
|
14928
|
+
throw new SubcError("connection file has no local_endpoint", "local_endpoint_absent");
|
|
14929
|
+
if (local.kind === "unix" !== (process.platform !== "win32")) {
|
|
14930
|
+
throw new SubcError("unsupported local endpoint kind on this platform", "local_endpoint_unsupported");
|
|
14931
|
+
}
|
|
14932
|
+
sock = await SubcSocket.connectLocal(local.kind === "unix" ? local.path : local.name, deadline);
|
|
14933
|
+
} else {
|
|
14934
|
+
sock = await SubcSocket.connect(endpoint.host, endpoint.port, deadline);
|
|
14935
|
+
}
|
|
14462
14936
|
try {
|
|
14463
14937
|
await authenticateClient(sock, conn, deadline);
|
|
14464
14938
|
} catch (err) {
|
|
@@ -14470,7 +14944,125 @@ class SubcClient {
|
|
|
14470
14944
|
async controlRpc(body, acceptFrame, onLateResponse) {
|
|
14471
14945
|
return this.send(null, body, Priority.Interactive, AdmissionClass.Normal, undefined, undefined, acceptFrame, onLateResponse);
|
|
14472
14946
|
}
|
|
14473
|
-
send(
|
|
14947
|
+
send(...args) {
|
|
14948
|
+
const [handle, body, priority, admission, timeoutMs, onProgress, acceptFrame, onLateResponse, binary, signal, sleepGraceMs] = args;
|
|
14949
|
+
if (!handle || !this.gates.has(handle))
|
|
14950
|
+
return this.sendAttempt(...args);
|
|
14951
|
+
return this.gatedRequest(handle, false, timeoutMs, signal, (slot, remaining) => this.sendAttempt(handle, body, priority, admission, remaining, onProgress, acceptFrame, onLateResponse, binary, signal, sleepGraceMs, slot));
|
|
14952
|
+
}
|
|
14953
|
+
async gatedRequest(handle, watch, timeoutMs, signal, attempt) {
|
|
14954
|
+
const gate = this.gates.get(handle);
|
|
14955
|
+
const deadline = this.opts.now() + (timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS);
|
|
14956
|
+
let slot;
|
|
14957
|
+
try {
|
|
14958
|
+
slot = await gate.acquire(watch, deadline - this.opts.now(), signal);
|
|
14959
|
+
} catch (error) {
|
|
14960
|
+
throw this.notSentCallError("request was not sent while waiting for a route slot", error);
|
|
14961
|
+
}
|
|
14962
|
+
let delay = 25;
|
|
14963
|
+
let busyDeadlineError;
|
|
14964
|
+
try {
|
|
14965
|
+
for (;; ) {
|
|
14966
|
+
if (gate.signal.aborted)
|
|
14967
|
+
throw gate.signal.reason;
|
|
14968
|
+
if (signal?.aborted)
|
|
14969
|
+
throw this.notSentCallError("request cancelled before write", signal.reason);
|
|
14970
|
+
this.assertLiveHandle(handle);
|
|
14971
|
+
const budget = deadline - this.opts.now();
|
|
14972
|
+
if (budget < MIN_REQUEST_BUDGET_MS)
|
|
14973
|
+
throw busyDeadlineError ?? this.notSentCallError("request deadline elapsed before write", new Error("less than 1ms remains before the request deadline"));
|
|
14974
|
+
try {
|
|
14975
|
+
return await attempt(slot, budget);
|
|
14976
|
+
} catch (error) {
|
|
14977
|
+
const refusal = error instanceof SubcError ? error : error instanceof SubcCallError && error.cause instanceof SubcError ? error.cause : undefined;
|
|
14978
|
+
if (!refusal || !isRouteBusyRetryable(errorFrameFlags.get(refusal) ?? 0, refusal.code, this.gates.get(handle) === gate))
|
|
14979
|
+
throw error;
|
|
14980
|
+
const exhausted = () => new SubcCallError("not_sent", `daemon refused before forwarding: ${refusal.message}`, "route_busy", refusal);
|
|
14981
|
+
busyDeadlineError = exhausted();
|
|
14982
|
+
const remaining = deadline - this.opts.now();
|
|
14983
|
+
if (remaining <= 0 || signal?.aborted)
|
|
14984
|
+
throw exhausted();
|
|
14985
|
+
const ms = Math.min(remaining, delay * (0.5 + this.opts.random() * 0.5));
|
|
14986
|
+
delay = Math.min(1000, delay * 2);
|
|
14987
|
+
const proceed = await this.busySleep(ms, gate.signal, signal);
|
|
14988
|
+
if (gate.signal.aborted)
|
|
14989
|
+
throw gate.signal.reason;
|
|
14990
|
+
if (!proceed || this.opts.now() >= deadline)
|
|
14991
|
+
throw exhausted();
|
|
14992
|
+
}
|
|
14993
|
+
}
|
|
14994
|
+
} finally {
|
|
14995
|
+
if (!slot.inFlight)
|
|
14996
|
+
slot.release();
|
|
14997
|
+
}
|
|
14998
|
+
}
|
|
14999
|
+
async busySleep(ms, closed, signal) {
|
|
15000
|
+
if (closed.aborted || signal?.aborted)
|
|
15001
|
+
return false;
|
|
15002
|
+
let abort;
|
|
15003
|
+
const cancelled = new Promise((resolve) => {
|
|
15004
|
+
abort = () => resolve(false);
|
|
15005
|
+
});
|
|
15006
|
+
closed.addEventListener("abort", abort, { once: true });
|
|
15007
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
15008
|
+
try {
|
|
15009
|
+
return await Promise.race([this.opts.sleep(ms).then(() => true), cancelled]);
|
|
15010
|
+
} finally {
|
|
15011
|
+
closed.removeEventListener("abort", abort);
|
|
15012
|
+
signal?.removeEventListener("abort", abort);
|
|
15013
|
+
}
|
|
15014
|
+
}
|
|
15015
|
+
subscribeGated(handle, body, onEvent, opts) {
|
|
15016
|
+
const bytes = body instanceof Uint8Array ? body : this.encode(body);
|
|
15017
|
+
const priority = opts.priority ?? Priority.Interactive;
|
|
15018
|
+
const admission = opts.admissionClass ?? AdmissionClass.Normal;
|
|
15019
|
+
const abort = new AbortController;
|
|
15020
|
+
let current;
|
|
15021
|
+
let cancelled = false;
|
|
15022
|
+
let resolveClosed;
|
|
15023
|
+
let rejectClosed;
|
|
15024
|
+
let resolveEnded;
|
|
15025
|
+
const closed = new Promise((resolve, reject) => {
|
|
15026
|
+
resolveClosed = resolve;
|
|
15027
|
+
rejectClosed = reject;
|
|
15028
|
+
});
|
|
15029
|
+
const ended = new Promise((resolve) => {
|
|
15030
|
+
resolveEnded = resolve;
|
|
15031
|
+
});
|
|
15032
|
+
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) => {
|
|
15033
|
+
current = { key, pending, corr };
|
|
15034
|
+
})).then((frame) => {
|
|
15035
|
+
if (cancelled)
|
|
15036
|
+
return;
|
|
15037
|
+
resolveEnded(frame.header.ty === FrameType.Response ? { kind: "response", body: frame.body } : { kind: "stream_end" });
|
|
15038
|
+
resolveClosed();
|
|
15039
|
+
}, (error) => {
|
|
15040
|
+
if (cancelled)
|
|
15041
|
+
return;
|
|
15042
|
+
if (error instanceof SubcError && error.closeReason)
|
|
15043
|
+
resolveEnded(error.closeReason === "connection_lost" ? { kind: "connection_lost" } : { kind: "route_closed", reason: error.closeReason });
|
|
15044
|
+
else if (error instanceof SubcError || error instanceof SubcCallError)
|
|
15045
|
+
resolveEnded({ kind: "error", code: error.code, message: error.message, detail: error.detail });
|
|
15046
|
+
else
|
|
15047
|
+
resolveEnded({ kind: "connection_lost" });
|
|
15048
|
+
rejectClosed(error);
|
|
15049
|
+
});
|
|
15050
|
+
return { closed, ended, unsubscribe: () => {
|
|
15051
|
+
if (cancelled)
|
|
15052
|
+
return;
|
|
15053
|
+
cancelled = true;
|
|
15054
|
+
abort.abort();
|
|
15055
|
+
if (current && this.pending.get(current.key) === current.pending) {
|
|
15056
|
+
const { key, pending, corr } = current;
|
|
15057
|
+
this.settle(key, pending, () => pending.reject(new SubcError("subscription cancelled")));
|
|
15058
|
+
if (this.isLiveHandle(handle))
|
|
15059
|
+
this.cancel(handle, corr, priority);
|
|
15060
|
+
}
|
|
15061
|
+
resolveEnded({ kind: "cancelled" });
|
|
15062
|
+
resolveClosed();
|
|
15063
|
+
} };
|
|
15064
|
+
}
|
|
15065
|
+
sendAttempt(handle, body, priority, admission, timeoutMs, onProgress, acceptFrame, onLateResponse, binary = false, signal, sleepGraceMs = this.opts.sleepGraceMs ?? DEFAULT_SLEEP_GRACE_MS, slot, subscription = false, registered) {
|
|
14474
15066
|
if (handle)
|
|
14475
15067
|
this.assertLiveHandle(handle);
|
|
14476
15068
|
if (this.closedErr)
|
|
@@ -14484,7 +15076,7 @@ class SubcClient {
|
|
|
14484
15076
|
const key = pendingKey(handle, corr);
|
|
14485
15077
|
const channel = handle?.channel ?? 0;
|
|
14486
15078
|
const epoch = handle?.epoch ?? 0;
|
|
14487
|
-
const frame = buildFrame(FrameType.Request, buildFlags(binary, priority, false, admission), channel, epoch, corr, body);
|
|
15079
|
+
const frame = buildFrame(FrameType.Request, buildFlags(binary, priority, false, admission) | (subscription ? SUBSCRIPTION_FLAG : 0), channel, epoch, corr, body);
|
|
14488
15080
|
return new Promise((resolve, reject) => {
|
|
14489
15081
|
const ms = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
14490
15082
|
const pending = {
|
|
@@ -14494,11 +15086,27 @@ class SubcClient {
|
|
|
14494
15086
|
onProgress,
|
|
14495
15087
|
timer: null,
|
|
14496
15088
|
acceptFrame,
|
|
14497
|
-
onLateResponse
|
|
15089
|
+
onLateResponse,
|
|
15090
|
+
slot,
|
|
15091
|
+
subscription
|
|
14498
15092
|
};
|
|
14499
|
-
|
|
15093
|
+
if (!subscription)
|
|
15094
|
+
this.armRequestTimeout(key, pending, channel, corr, ms, sleepGraceMs);
|
|
14500
15095
|
this.pending.set(key, pending);
|
|
14501
|
-
|
|
15096
|
+
registered?.(key, pending, corr);
|
|
15097
|
+
if (slot && handle) {
|
|
15098
|
+
slot.inFlight = true;
|
|
15099
|
+
this.slots.set(key, { handle, slot });
|
|
15100
|
+
}
|
|
15101
|
+
const write = writeTrackedBorrowed(this.sock, encodeFrame(frame), Date.now() + ms);
|
|
15102
|
+
if (slot && !write.queued) {
|
|
15103
|
+
this.slots.delete(key);
|
|
15104
|
+
slot.inFlight = false;
|
|
15105
|
+
slot.release();
|
|
15106
|
+
}
|
|
15107
|
+
write.completed.catch((error) => {
|
|
15108
|
+
if (error instanceof SocketWriteNotQueuedError || error instanceof SocketWriteQueuedError)
|
|
15109
|
+
error = error.cause ?? error;
|
|
14502
15110
|
const current = this.pending.get(key);
|
|
14503
15111
|
if (current)
|
|
14504
15112
|
this.rejectPending(key, current, error instanceof Error ? error : new SubcError(String(error)));
|
|
@@ -14507,10 +15115,16 @@ class SubcClient {
|
|
|
14507
15115
|
this.attachCancelSignal(signal, key, handle, corr, priority);
|
|
14508
15116
|
});
|
|
14509
15117
|
}
|
|
15118
|
+
armRequestTimeout(key, pending, channel, corr, ms, sleepGraceMs) {
|
|
15119
|
+
pending.sleepGrace = { wallStartMs: Date.now(), awakeStartMs: performance.now(), ms: sleepGraceMs, used: false };
|
|
15120
|
+
pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, channel, corr, ms), ms);
|
|
15121
|
+
}
|
|
14510
15122
|
arbitrateTimeout(key, pending, channel, corr, ms) {
|
|
14511
15123
|
const settleAsTimeout = () => {
|
|
14512
15124
|
if (pending.onLateResponse)
|
|
14513
15125
|
this.lateResponses.set(key, pending.onLateResponse);
|
|
15126
|
+
if (pending.slot?.inFlight && pending.handle && this.isLiveHandle(pending.handle))
|
|
15127
|
+
this.cancel(pending.handle, corr);
|
|
14514
15128
|
this.rejectPending(key, pending, new SubcError(this.timeoutMessage(channel, corr, ms), REQUEST_DEADLINE_MARKER));
|
|
14515
15129
|
};
|
|
14516
15130
|
const graceDeadline = Date.now() + this.opts.timeoutArbitrationGraceMs;
|
|
@@ -14522,6 +15136,17 @@ class SubcClient {
|
|
|
14522
15136
|
setImmediate(arbitrate);
|
|
14523
15137
|
return;
|
|
14524
15138
|
}
|
|
15139
|
+
const sleep = pending.sleepGrace;
|
|
15140
|
+
if (sleep && !sleep.used && sleep.ms > 0) {
|
|
15141
|
+
const wallElapsed = Date.now() - sleep.wallStartMs;
|
|
15142
|
+
const awakeElapsed = performance.now() - sleep.awakeStartMs;
|
|
15143
|
+
const sleptMs = wallElapsed - awakeElapsed;
|
|
15144
|
+
if (sleptMs > SLEEP_DETECTION_THRESHOLD_MS) {
|
|
15145
|
+
sleep.used = true;
|
|
15146
|
+
pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, channel, corr, ms), sleep.ms);
|
|
15147
|
+
return;
|
|
15148
|
+
}
|
|
15149
|
+
}
|
|
14525
15150
|
settleAsTimeout();
|
|
14526
15151
|
};
|
|
14527
15152
|
setImmediate(arbitrate);
|
|
@@ -14532,7 +15157,7 @@ class SubcClient {
|
|
|
14532
15157
|
const priority = opts.priority ?? Priority.Interactive;
|
|
14533
15158
|
const admission = opts.admissionClass ?? AdmissionClass.Normal;
|
|
14534
15159
|
try {
|
|
14535
|
-
const reply = await this.sendManaged(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress, binary, opts.signal);
|
|
15160
|
+
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));
|
|
14536
15161
|
return this.decodeReply(reply);
|
|
14537
15162
|
} catch (error) {
|
|
14538
15163
|
if (error instanceof SubcCallError)
|
|
@@ -14540,7 +15165,13 @@ class SubcClient {
|
|
|
14540
15165
|
throw this.terminalCallError("managed call failed", error);
|
|
14541
15166
|
}
|
|
14542
15167
|
}
|
|
14543
|
-
sendManaged(
|
|
15168
|
+
sendManaged(...args) {
|
|
15169
|
+
const [handle, body, priority, admission, timeoutMs, onProgress, binary, signal, sleepGraceMs] = args;
|
|
15170
|
+
if (!this.gates.has(handle))
|
|
15171
|
+
return this.sendManagedAttempt(...args);
|
|
15172
|
+
return this.gatedRequest(handle, false, timeoutMs, signal, (slot, remaining) => this.sendManagedAttempt(handle, body, priority, admission, remaining, onProgress, binary, signal, sleepGraceMs, slot));
|
|
15173
|
+
}
|
|
15174
|
+
sendManagedAttempt(handle, body, priority, admission, timeoutMs, onProgress, binary = false, signal, sleepGraceMs = this.opts.sleepGraceMs ?? DEFAULT_SLEEP_GRACE_MS, slot) {
|
|
14544
15175
|
try {
|
|
14545
15176
|
this.assertLiveHandle(handle);
|
|
14546
15177
|
} catch (error) {
|
|
@@ -14574,12 +15205,22 @@ class SubcClient {
|
|
|
14574
15205
|
reject,
|
|
14575
15206
|
onProgress,
|
|
14576
15207
|
timer: null,
|
|
14577
|
-
classifyFailure
|
|
15208
|
+
classifyFailure,
|
|
15209
|
+
slot
|
|
14578
15210
|
};
|
|
14579
|
-
|
|
15211
|
+
this.armRequestTimeout(key, pending, handle.channel, corr, ms, sleepGraceMs);
|
|
14580
15212
|
this.pending.set(key, pending);
|
|
15213
|
+
if (slot) {
|
|
15214
|
+
slot.inFlight = true;
|
|
15215
|
+
this.slots.set(key, { handle, slot });
|
|
15216
|
+
}
|
|
14581
15217
|
const write = writeTrackedBorrowed(this.sock, encodeFrame(frame), Date.now() + ms);
|
|
14582
15218
|
handedToSocket = write.queued;
|
|
15219
|
+
if (slot && !write.queued) {
|
|
15220
|
+
this.slots.delete(key);
|
|
15221
|
+
slot.inFlight = false;
|
|
15222
|
+
slot.release();
|
|
15223
|
+
}
|
|
14583
15224
|
write.completed.catch((error) => {
|
|
14584
15225
|
const current = this.pending.get(key);
|
|
14585
15226
|
if (current)
|
|
@@ -14596,7 +15237,7 @@ class SubcClient {
|
|
|
14596
15237
|
throw new SubcCallError("terminal", "managed call requires a BindIdentity in SubcClient.connect({ identity }) or call(..., { identity })", "missing_identity");
|
|
14597
15238
|
}
|
|
14598
15239
|
const target = { kind: opts.targetKind ?? this.opts.targetKind, module_id: moduleId };
|
|
14599
|
-
const consumerIdentity = routeOpenConsumerIdentity(opts);
|
|
15240
|
+
const consumerIdentity = await routeOpenConsumerIdentity(opts);
|
|
14600
15241
|
const reverseRequests = opts.reverseRequests ?? new ReverseRequestRegistry;
|
|
14601
15242
|
reverseRequests.seal();
|
|
14602
15243
|
const key = routeCacheKey(target, identity, consumerIdentity, reverseRequests.capabilities(), scope);
|
|
@@ -14681,6 +15322,7 @@ class SubcClient {
|
|
|
14681
15322
|
if ("handle" in outcome) {
|
|
14682
15323
|
const { handle } = outcome;
|
|
14683
15324
|
if (cached.closed) {
|
|
15325
|
+
this.failHandle(handle, new SubcError("route closed during route.open", "route_closed", undefined, "closed_by_caller"));
|
|
14684
15326
|
this.liveRoutes.delete(handle.channel);
|
|
14685
15327
|
this.sendRouteGoodbye(handle);
|
|
14686
15328
|
throw this.routeClosedDuringOpen();
|
|
@@ -14804,6 +15446,9 @@ class SubcClient {
|
|
|
14804
15446
|
return;
|
|
14805
15447
|
} catch (err) {
|
|
14806
15448
|
if (!isConsumerReconnectTransient(err) || attempt >= this.opts.reconnectBackoff.maxAttempts) {
|
|
15449
|
+
if (isConsumerReconnectTransient(err) && !(err instanceof AuthError)) {
|
|
15450
|
+
throw new DaemonUnavailableError(err);
|
|
15451
|
+
}
|
|
14807
15452
|
if (err instanceof AuthError && attempt > 1) {
|
|
14808
15453
|
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`);
|
|
14809
15454
|
}
|
|
@@ -14926,6 +15571,16 @@ class SubcClient {
|
|
|
14926
15571
|
}
|
|
14927
15572
|
const key = pendingKey(handle, frame.header.corr);
|
|
14928
15573
|
const pending = this.pending.get(key);
|
|
15574
|
+
if (frame.header.ty === FrameType.Response || frame.header.ty === FrameType.Error || frame.header.ty === FrameType.StreamEnd) {
|
|
15575
|
+
const record = this.slots.get(key);
|
|
15576
|
+
if (record) {
|
|
15577
|
+
this.slots.delete(key);
|
|
15578
|
+
record.slot.inFlight = false;
|
|
15579
|
+
const busy = frame.header.ty === FrameType.Error && pending?.slot === record.slot && isRouteBusyRetryable(frame.header.flags, this.errorFromFrame(frame).code, !!handle && this.gates.has(handle));
|
|
15580
|
+
if (!busy)
|
|
15581
|
+
record.slot.release();
|
|
15582
|
+
}
|
|
15583
|
+
}
|
|
14929
15584
|
if (pending) {
|
|
14930
15585
|
if (pending.acceptFrame && !pending.acceptFrame(frame))
|
|
14931
15586
|
return;
|
|
@@ -14941,7 +15596,7 @@ class SubcClient {
|
|
|
14941
15596
|
this.settle(key, pending, () => pending.resolve(frame));
|
|
14942
15597
|
return;
|
|
14943
15598
|
case FrameType.Error:
|
|
14944
|
-
this.settle(key, pending, () => pending.reject(this.errorFromFrame(frame)));
|
|
15599
|
+
this.settle(key, pending, () => pending.reject(this.errorFromFrame(frame), frame));
|
|
14945
15600
|
return;
|
|
14946
15601
|
default:
|
|
14947
15602
|
return;
|
|
@@ -15078,6 +15733,14 @@ class SubcClient {
|
|
|
15078
15733
|
return this.legacyChannelReasons.get(channel) ?? "unknown";
|
|
15079
15734
|
}
|
|
15080
15735
|
failHandle(handle, error) {
|
|
15736
|
+
this.gates.get(handle)?.close(error);
|
|
15737
|
+
this.gates.delete(handle);
|
|
15738
|
+
for (const [key, record] of this.slots) {
|
|
15739
|
+
if (sameRouteHandle(record.handle, handle)) {
|
|
15740
|
+
record.slot.release();
|
|
15741
|
+
this.slots.delete(key);
|
|
15742
|
+
}
|
|
15743
|
+
}
|
|
15081
15744
|
for (const [key, pending] of this.pending) {
|
|
15082
15745
|
if (pending.handle && sameRouteHandle(pending.handle, handle))
|
|
15083
15746
|
this.rejectPending(key, pending, error);
|
|
@@ -15087,6 +15750,10 @@ class SubcClient {
|
|
|
15087
15750
|
const routeError = err instanceof SubcError && err.closeReason ? err : new SubcError(err.message, errorCode(err), undefined, this.closeStarted ? "closed_by_caller" : "connection_lost");
|
|
15088
15751
|
if (!this.closedErr)
|
|
15089
15752
|
this.closedErr = err;
|
|
15753
|
+
for (const gate of this.gates.values())
|
|
15754
|
+
gate.close(routeError);
|
|
15755
|
+
this.gates.clear();
|
|
15756
|
+
this.slots.clear();
|
|
15090
15757
|
this.routeEndReasons.clear();
|
|
15091
15758
|
this.legacyChannelReasons.clear();
|
|
15092
15759
|
this.routeModules.clear();
|
|
@@ -15120,6 +15787,9 @@ class SubcClient {
|
|
|
15120
15787
|
return this.ingressEpochDropCount;
|
|
15121
15788
|
}
|
|
15122
15789
|
installRoute(channel, epoch, reverseRequests = new ReverseRequestRegistry) {
|
|
15790
|
+
const previous = this.liveRoutes.get(channel);
|
|
15791
|
+
if (previous && this.gates.has(previous))
|
|
15792
|
+
this.failHandle(previous, new SubcError("route replaced", "route_closed", undefined, "closed_by_caller"));
|
|
15123
15793
|
const handle = createRouteHandle(channel, epoch, this.connectionToken, reverseRequests);
|
|
15124
15794
|
this.routeEndReasons.delete(channel);
|
|
15125
15795
|
this.legacyChannelReasons.delete(channel);
|
|
@@ -15190,9 +15860,15 @@ function isRetryableRouteOpenCode(code) {
|
|
|
15190
15860
|
return false;
|
|
15191
15861
|
if (code === "target_flow_unsupported")
|
|
15192
15862
|
return false;
|
|
15863
|
+
if (code === "target_federated_unsupported")
|
|
15864
|
+
return false;
|
|
15193
15865
|
if (code === "target_agent_run_unsupported")
|
|
15194
15866
|
return false;
|
|
15195
|
-
|
|
15867
|
+
if (code === "scope_bind_proof_required" || code === "scope_bind_proof_mismatch")
|
|
15868
|
+
return false;
|
|
15869
|
+
if (code === "scope_epoch_in_use")
|
|
15870
|
+
return false;
|
|
15871
|
+
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";
|
|
15196
15872
|
}
|
|
15197
15873
|
function equalJitter(delayMs, random) {
|
|
15198
15874
|
const half = delayMs / 2;
|
|
@@ -15229,6 +15905,12 @@ var STALE_ROUTE_EPOCH = "stale_route_epoch";
|
|
|
15229
15905
|
function isEstablishedRouteDead(_flags, code) {
|
|
15230
15906
|
return code === UNKNOWN_CHANNEL || code === STALE_ROUTE_EPOCH;
|
|
15231
15907
|
}
|
|
15908
|
+
function isRouteBusyRetryable(flags, code, routeOptedIn) {
|
|
15909
|
+
return routeOptedIn && (flags & DAEMON_ORIGIN_FLAG) !== 0 && code === "route_busy";
|
|
15910
|
+
}
|
|
15911
|
+
function isDataPlaneDrainRefusal(code) {
|
|
15912
|
+
return code === "module_reloading";
|
|
15913
|
+
}
|
|
15232
15914
|
async function connectionFileExists(path) {
|
|
15233
15915
|
try {
|
|
15234
15916
|
await fs3.access(path);
|
|
@@ -15240,6 +15922,7 @@ async function connectionFileExists(path) {
|
|
|
15240
15922
|
function normalizeConnectOptions(opts) {
|
|
15241
15923
|
return {
|
|
15242
15924
|
connectionFile: opts.connectionFile,
|
|
15925
|
+
transport: opts.transport ?? "tcp",
|
|
15243
15926
|
handshakeTimeoutMs: opts.handshakeTimeoutMs,
|
|
15244
15927
|
identity: opts.identity,
|
|
15245
15928
|
targetKind: opts.targetKind ?? DEFAULT_MANAGED_TARGET_KIND,
|
|
@@ -15249,11 +15932,18 @@ function normalizeConnectOptions(opts) {
|
|
|
15249
15932
|
random: opts.random ?? Math.random,
|
|
15250
15933
|
routeOpenRetryDeadlineMs: opts.routeOpenRetryDeadlineMs ?? ROUTE_OPEN_RETRY_DEADLINE_MS,
|
|
15251
15934
|
timeoutArbitrationGraceMs: opts.timeoutArbitrationGraceMs ?? TIMEOUT_ARBITRATION_GRACE_MS,
|
|
15935
|
+
sleepGraceMs: validatedSleepGraceMs(opts.sleepGraceMs ?? DEFAULT_SLEEP_GRACE_MS),
|
|
15252
15936
|
bodyReadTimeoutMs: opts.bodyReadTimeoutMs,
|
|
15253
15937
|
livenessProbeWindowMs: opts.livenessProbeWindowMs ?? LIVENESS_PROBE_WINDOW_MS,
|
|
15254
15938
|
onControlPush: opts.onControlPush
|
|
15255
15939
|
};
|
|
15256
15940
|
}
|
|
15941
|
+
function validatedSleepGraceMs(ms) {
|
|
15942
|
+
if (!Number.isFinite(ms) || ms < 0 || ms > 2147483647) {
|
|
15943
|
+
throw new RangeError("sleepGraceMs must be finite and in 0..2147483647 milliseconds");
|
|
15944
|
+
}
|
|
15945
|
+
return ms;
|
|
15946
|
+
}
|
|
15257
15947
|
function isValidCapabilityIdentifier(identifier) {
|
|
15258
15948
|
if (/\s/u.test(identifier))
|
|
15259
15949
|
return false;
|
|
@@ -15276,7 +15966,13 @@ function isValidCapabilityIdentifier(identifier) {
|
|
|
15276
15966
|
function routeCacheKey(target, identity, consumerIdentity, consumerCapabilities, scope) {
|
|
15277
15967
|
const consumerPart = consumerIdentity ? `${consumerIdentity.module_id}\x00${consumerIdentity.launch_nonce}` : "";
|
|
15278
15968
|
const capabilitiesPart = [...consumerCapabilities].sort().join("\x00");
|
|
15279
|
-
const scopePart = scope ? JSON.stringify([
|
|
15969
|
+
const scopePart = scope ? JSON.stringify([
|
|
15970
|
+
scope.owner.kind,
|
|
15971
|
+
scope.owner.kind === "reserved" ? scope.owner.module_id : null,
|
|
15972
|
+
scope.ref,
|
|
15973
|
+
scope.scopeEpoch,
|
|
15974
|
+
scope.bindProof === undefined ? null : createHash4("sha256").update(scope.bindProof).digest("hex")
|
|
15975
|
+
]) : "";
|
|
15280
15976
|
return `${target.kind}\x00${target.module_id}\x00${identity.project_root}\x00${identity.harness}\x00${identity.session}\x00${consumerPart}\x00${capabilitiesPart}\x00${scopePart}`;
|
|
15281
15977
|
}
|
|
15282
15978
|
function validatedRouteScope(scope) {
|
|
@@ -15294,13 +15990,18 @@ function validatedRouteScope(scope) {
|
|
|
15294
15990
|
if (!Number.isSafeInteger(scope.scopeEpoch) || scope.scopeEpoch < 0) {
|
|
15295
15991
|
throw new SubcError("scope.scopeEpoch must be a safe non-negative integer", "invalid_scope");
|
|
15296
15992
|
}
|
|
15297
|
-
return {
|
|
15993
|
+
return {
|
|
15994
|
+
owner: { ...scope.owner },
|
|
15995
|
+
ref: scope.ref,
|
|
15996
|
+
scopeEpoch: scope.scopeEpoch,
|
|
15997
|
+
...scope.bindProof !== undefined ? { bindProof: scope.bindProof } : {}
|
|
15998
|
+
};
|
|
15298
15999
|
}
|
|
15299
|
-
function routeOpenConsumerIdentity(opts = {}) {
|
|
16000
|
+
async function routeOpenConsumerIdentity(opts = {}) {
|
|
15300
16001
|
if (opts.consumerIdentity !== undefined)
|
|
15301
16002
|
return opts.consumerIdentity ?? undefined;
|
|
15302
16003
|
const moduleId = process.env[SUBC_MODULE_ID_ENV];
|
|
15303
|
-
const launchNonce =
|
|
16004
|
+
const launchNonce = (await launchNonceOrUndefinedAsync())?.value;
|
|
15304
16005
|
if (!moduleId || !launchNonce)
|
|
15305
16006
|
return;
|
|
15306
16007
|
return { module_id: moduleId, launch_nonce: launchNonce };
|
|
@@ -15753,19 +16454,19 @@ function getLifecycleRegistry() {
|
|
|
15753
16454
|
|
|
15754
16455
|
// ../aft-bridge/dist/project-identity.js
|
|
15755
16456
|
import { realpathSync as realpathSync3 } from "node:fs";
|
|
15756
|
-
import { posix as
|
|
16457
|
+
import { posix as posix3, resolve as resolve6, win32 as win323 } from "node:path";
|
|
15757
16458
|
function canonicalizeProjectRoot(dir) {
|
|
15758
16459
|
const trimmed = trimProjectRootSeparators(dir);
|
|
15759
16460
|
let canonical;
|
|
15760
16461
|
try {
|
|
15761
16462
|
canonical = realpathSync3(trimmed);
|
|
15762
16463
|
} catch {
|
|
15763
|
-
canonical =
|
|
16464
|
+
canonical = resolve6(trimmed);
|
|
15764
16465
|
}
|
|
15765
16466
|
return normalizeWindowsRoot(canonical);
|
|
15766
16467
|
}
|
|
15767
16468
|
function trimProjectRootSeparators(dir, platform = process.platform) {
|
|
15768
|
-
const root = (platform === "win32" ?
|
|
16469
|
+
const root = (platform === "win32" ? win323 : posix3).parse(dir).root;
|
|
15769
16470
|
const trimmed = dir.replace(/[/\\]+$/, "");
|
|
15770
16471
|
return trimmed.length < root.length ? root : trimmed;
|
|
15771
16472
|
}
|
|
@@ -16564,6 +17265,8 @@ class SubcTransportPool {
|
|
|
16564
17265
|
harness;
|
|
16565
17266
|
connectionFile;
|
|
16566
17267
|
handshakeTimeoutMs;
|
|
17268
|
+
clock;
|
|
17269
|
+
waitClock;
|
|
16567
17270
|
consumerIdentity;
|
|
16568
17271
|
hostScopes;
|
|
16569
17272
|
hostScopeCache = new Map;
|
|
@@ -16606,6 +17309,13 @@ class SubcTransportPool {
|
|
|
16606
17309
|
editSlotSurvives;
|
|
16607
17310
|
editSlotSurvivesCaptured = false;
|
|
16608
17311
|
constructor(options) {
|
|
17312
|
+
this.clock = options.clock ?? {
|
|
17313
|
+
now: () => Date.now(),
|
|
17314
|
+
awakeNow: () => performance.now(),
|
|
17315
|
+
setTimeout: (callback, ms) => setTimeout(callback, ms),
|
|
17316
|
+
clearTimeout: (timer) => clearTimeout(timer)
|
|
17317
|
+
};
|
|
17318
|
+
this.waitClock = new WaitClock(() => this.clock.now(), () => this.clock.awakeNow?.() ?? this.clock.now());
|
|
16609
17319
|
this.connectionFile = options.connectionFile;
|
|
16610
17320
|
this.harness = options.harness;
|
|
16611
17321
|
this.handshakeTimeoutMs = options.handshakeTimeoutMs;
|
|
@@ -17232,11 +17942,12 @@ class SubcTransportPool {
|
|
|
17232
17942
|
this.stopUnusedHostScopeRetry(record.identity.session);
|
|
17233
17943
|
}
|
|
17234
17944
|
async routeRequest(identity, body, timeoutMs, onProgress, expectedGeneration, abortSignal) {
|
|
17235
|
-
const callStartedAt =
|
|
17945
|
+
const callStartedAt = this.waitClock.now();
|
|
17236
17946
|
const callDeadlineMs = timeoutMs ?? SUBC_DEFAULT_REQUEST_TIMEOUT_MS;
|
|
17947
|
+
const deadline = new RequestDeadline(this.waitClock, callDeadlineMs);
|
|
17237
17948
|
let scheduledDelayMs = 0;
|
|
17238
|
-
const spentMs = () => Math.max(
|
|
17239
|
-
const remainingMs = () =>
|
|
17949
|
+
const spentMs = () => Math.max(this.waitClock.now() - callStartedAt, scheduledDelayMs);
|
|
17950
|
+
const remainingMs = () => deadline.remaining() - Math.max(0, scheduledDelayMs - (this.waitClock.now() - callStartedAt));
|
|
17240
17951
|
const root = asCanonicalRootPath(identity.project_root);
|
|
17241
17952
|
let generation = expectedGeneration;
|
|
17242
17953
|
if (this.lifecycleEnabled()) {
|
|
@@ -17257,12 +17968,12 @@ class SubcTransportPool {
|
|
|
17257
17968
|
const remaining = remainingMs();
|
|
17258
17969
|
if (remaining <= 0)
|
|
17259
17970
|
throw keyChanged ?? callDeadlinePassedError(undefined, callDeadlineMs);
|
|
17260
|
-
let
|
|
17971
|
+
let cancelTimer;
|
|
17261
17972
|
try {
|
|
17262
17973
|
const acquired = await Promise.race([
|
|
17263
17974
|
this.ensureClient(),
|
|
17264
17975
|
new Promise((resolve) => {
|
|
17265
|
-
|
|
17976
|
+
cancelTimer = deadlineTimer(this.clock, remainingMs, () => resolve(CALL_DEADLINE_EXPIRED));
|
|
17266
17977
|
})
|
|
17267
17978
|
]);
|
|
17268
17979
|
if (acquired === CALL_DEADLINE_EXPIRED) {
|
|
@@ -17277,22 +17988,22 @@ class SubcTransportPool {
|
|
|
17277
17988
|
if (spentMs() + this.nextRouteReopenDelayMs() >= callDeadlineMs)
|
|
17278
17989
|
throw error;
|
|
17279
17990
|
} finally {
|
|
17280
|
-
|
|
17991
|
+
cancelTimer?.();
|
|
17281
17992
|
}
|
|
17282
17993
|
const { delayMs, wait } = this.waitForRouteReopenBackoff();
|
|
17283
17994
|
scheduledDelayMs = spentMs() + delayMs;
|
|
17284
|
-
let
|
|
17995
|
+
let cancelRetryTimer;
|
|
17285
17996
|
try {
|
|
17286
17997
|
const waited = await Promise.race([
|
|
17287
17998
|
wait,
|
|
17288
17999
|
new Promise((resolve) => {
|
|
17289
|
-
|
|
18000
|
+
cancelRetryTimer = deadlineTimer(this.clock, remainingMs, () => resolve(CALL_DEADLINE_EXPIRED));
|
|
17290
18001
|
})
|
|
17291
18002
|
]);
|
|
17292
18003
|
if (waited === CALL_DEADLINE_EXPIRED)
|
|
17293
18004
|
throw keyChanged;
|
|
17294
18005
|
} finally {
|
|
17295
|
-
|
|
18006
|
+
cancelRetryTimer?.();
|
|
17296
18007
|
}
|
|
17297
18008
|
}
|
|
17298
18009
|
this.assertRecordLive(record);
|
|
@@ -17335,9 +18046,9 @@ class SubcTransportPool {
|
|
|
17335
18046
|
const remaining = remainingMs();
|
|
17336
18047
|
if (remaining <= 0)
|
|
17337
18048
|
throw callDeadlinePassedError(lastRefusal, callDeadlineMs);
|
|
17338
|
-
let
|
|
18049
|
+
let cancelTimer;
|
|
17339
18050
|
const expired = new Promise((resolve) => {
|
|
17340
|
-
|
|
18051
|
+
cancelTimer = deadlineTimer(this.clock, remainingMs, () => resolve(CALL_DEADLINE_EXPIRED));
|
|
17341
18052
|
});
|
|
17342
18053
|
try {
|
|
17343
18054
|
const opened = await Promise.race([openRoute(), expired]);
|
|
@@ -17346,7 +18057,7 @@ class SubcTransportPool {
|
|
|
17346
18057
|
}
|
|
17347
18058
|
return opened;
|
|
17348
18059
|
} finally {
|
|
17349
|
-
|
|
18060
|
+
cancelTimer?.();
|
|
17350
18061
|
}
|
|
17351
18062
|
};
|
|
17352
18063
|
const openRouteAfterReloadWindow = async () => {
|
|
@@ -17425,6 +18136,7 @@ class SubcTransportPool {
|
|
|
17425
18136
|
try {
|
|
17426
18137
|
request = client.request(route, body, {
|
|
17427
18138
|
timeoutMs: Math.ceil(requestTimeoutMs),
|
|
18139
|
+
...deadline.resumed ? { sleepGraceMs: 0 } : {},
|
|
17428
18140
|
onProgress
|
|
17429
18141
|
});
|
|
17430
18142
|
} catch (error) {
|
|
@@ -17552,6 +18264,7 @@ class SubcTransportPool {
|
|
|
17552
18264
|
this.connecting = this.connectFn({
|
|
17553
18265
|
connectionFile: this.connectionFile,
|
|
17554
18266
|
handshakeTimeoutMs: this.handshakeTimeoutMs,
|
|
18267
|
+
sleepGraceMs: RESUME_ALLOWANCE_MS,
|
|
17555
18268
|
onControlPush: (push) => {
|
|
17556
18269
|
if (owner && this.client === owner)
|
|
17557
18270
|
this.onScopeRouteClose(push);
|
|
@@ -18553,7 +19266,7 @@ function taskIdFromError(error) {
|
|
|
18553
19266
|
return;
|
|
18554
19267
|
}
|
|
18555
19268
|
// ../aft-bridge/dist/feature-config.js
|
|
18556
|
-
import { createHash as
|
|
19269
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
18557
19270
|
import { createRequire } from "node:module";
|
|
18558
19271
|
var CANONICAL_TOOLS = [
|
|
18559
19272
|
"aft_callgraph",
|
|
@@ -18614,12 +19327,7 @@ var RETIRED_IDLE_CHECKOUT_HOURS = [
|
|
|
18614
19327
|
"idle.checkout_hours"
|
|
18615
19328
|
];
|
|
18616
19329
|
var DATA_LAYER_KEYS_REFUSED_FROM = [0, 65];
|
|
18617
|
-
var DATA_LAYER_RETIRED_PATHS = [
|
|
18618
|
-
"views.callgraph_copies",
|
|
18619
|
-
"views.enabled",
|
|
18620
|
-
"views.idle_checkout_hours",
|
|
18621
|
-
"worktree.ram_overlay"
|
|
18622
|
-
];
|
|
19330
|
+
var DATA_LAYER_RETIRED_PATHS = ["views.idle_checkout_hours"];
|
|
18623
19331
|
var IDLE_CHECKOUT_HOURS_DEFAULT = 168;
|
|
18624
19332
|
var IDLE_CHECKOUT_HOURS_MIN = 1;
|
|
18625
19333
|
var IDLE_CHECKOUT_HOURS_MAX = 24 * 365;
|
|
@@ -18646,7 +19354,10 @@ function readRunningRelease() {
|
|
|
18646
19354
|
return [0, 0];
|
|
18647
19355
|
}
|
|
18648
19356
|
var runningRelease;
|
|
19357
|
+
var runningReleaseOverrideForTest;
|
|
18649
19358
|
function getRunningRelease() {
|
|
19359
|
+
if (runningReleaseOverrideForTest)
|
|
19360
|
+
return runningReleaseOverrideForTest;
|
|
18650
19361
|
runningRelease ??= readRunningRelease();
|
|
18651
19362
|
return runningRelease;
|
|
18652
19363
|
}
|
|
@@ -18675,7 +19386,7 @@ function removedBlockKeyErrors(value, release, refuseRetired) {
|
|
|
18675
19386
|
const paths = REMOVED_OPENCODE_PATHS.filter((path) => hasPath(value, path));
|
|
18676
19387
|
if (refuseRetired)
|
|
18677
19388
|
paths.push(...refusedRetiredNames(value));
|
|
18678
|
-
if (releaseAtLeast(release, DATA_LAYER_KEYS_REFUSED_FROM))
|
|
19389
|
+
if (refuseRetired && releaseAtLeast(release, DATA_LAYER_KEYS_REFUSED_FROM))
|
|
18679
19390
|
paths.push(...DATA_LAYER_RETIRED_PATHS.filter((path) => hasPath(value, path)));
|
|
18680
19391
|
return paths.map((path) => `removed_config_key:${path}; run npx @cortexkit/aft doctor --fix`);
|
|
18681
19392
|
}
|
|
@@ -18699,7 +19410,10 @@ var REFUSED_RETIRED_PATHS = [
|
|
|
18699
19410
|
"experimental.bash",
|
|
18700
19411
|
"idle.lsp_ttl_minutes",
|
|
18701
19412
|
"inspect.tier2_soft_deadline_ms",
|
|
18702
|
-
"inspect.max_drill_down_items"
|
|
19413
|
+
"inspect.max_drill_down_items",
|
|
19414
|
+
"views.callgraph_copies",
|
|
19415
|
+
"views.enabled",
|
|
19416
|
+
"worktree.ram_overlay"
|
|
18703
19417
|
];
|
|
18704
19418
|
function refusedRetiredNames(block) {
|
|
18705
19419
|
const names = REFUSED_RETIRED_PATHS.filter((path) => hasPath(block, path));
|
|
@@ -18897,8 +19611,9 @@ function translateDataLayerPaths(map, prefix, out) {
|
|
|
18897
19611
|
}
|
|
18898
19612
|
}
|
|
18899
19613
|
for (const path of REMOVED_DATA_LAYER_PATHS) {
|
|
18900
|
-
|
|
18901
|
-
|
|
19614
|
+
const [container, leaf] = path.split(".");
|
|
19615
|
+
if (container && leaf && takeNested(map, container, leaf).found)
|
|
19616
|
+
recordRetired(out, prefix, path);
|
|
18902
19617
|
}
|
|
18903
19618
|
}
|
|
18904
19619
|
function translateExperimentalPaths(map, prefix, out) {
|
|
@@ -19148,7 +19863,7 @@ var NO_EFFECT_RETIRED_NOTES = [
|
|
|
19148
19863
|
]
|
|
19149
19864
|
];
|
|
19150
19865
|
function noEffectNote(key) {
|
|
19151
|
-
return NO_EFFECT_RETIRED_NOTES.find(([path]) => namesPath(key, path))?.[1];
|
|
19866
|
+
return [...NO_EFFECT_RETIRED_NOTES, ...REMOVED_DATA_LAYER_NOTES].find(([path]) => namesPath(key, path))?.[1];
|
|
19152
19867
|
}
|
|
19153
19868
|
function namesPath(key, path) {
|
|
19154
19869
|
return key === path || key.endsWith(`.${path}`);
|
|
@@ -19169,26 +19884,7 @@ var REMOVED_DATA_LAYER_NOTES = [
|
|
|
19169
19884
|
];
|
|
19170
19885
|
function retiredIdleCheckoutHoursNote() {
|
|
19171
19886
|
const [retired, replacement] = RETIRED_IDLE_CHECKOUT_HOURS;
|
|
19172
|
-
return `${retired} is now ${replacement}; from ${refusedFromVersion()} AFT refuses a config file that still sets ${retired}.`;
|
|
19173
|
-
}
|
|
19174
|
-
function removedConfigKeysNoticeMessage(configPath, translation) {
|
|
19175
|
-
const removed = translation.removedKeys ?? [];
|
|
19176
|
-
if (removed.length === 0)
|
|
19177
|
-
return "";
|
|
19178
|
-
const parts = [
|
|
19179
|
-
`${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.`
|
|
19180
|
-
];
|
|
19181
|
-
for (const [path, note] of REMOVED_DATA_LAYER_NOTES) {
|
|
19182
|
-
if (removed.some((key) => namesPath(key, path)))
|
|
19183
|
-
parts.push(note);
|
|
19184
|
-
}
|
|
19185
|
-
return parts.join(" ");
|
|
19186
|
-
}
|
|
19187
|
-
function removedConfigKeysNoticeDigest(translation) {
|
|
19188
|
-
return noticeDigest({
|
|
19189
|
-
notice: "removed_data_layer_keys_v1",
|
|
19190
|
-
keys: sortedUnique(translation.removedKeys)
|
|
19191
|
-
});
|
|
19887
|
+
return `${retired} is now ${replacement}; from ${refusedFromVersion()} AFT refuses a user config file that still sets ${retired}.`;
|
|
19192
19888
|
}
|
|
19193
19889
|
function legacyConfigNoticeMessage(configPath, translation) {
|
|
19194
19890
|
const equivalents = translation.retiredKeys.filter((key) => noEffectNote(key) === undefined);
|
|
@@ -19202,13 +19898,10 @@ function legacyConfigNoticeMessage(configPath, translation) {
|
|
|
19202
19898
|
parts.push(retiredIdleCheckoutHoursNote());
|
|
19203
19899
|
}
|
|
19204
19900
|
}
|
|
19205
|
-
for (const [, note] of NO_EFFECT_RETIRED_NOTES) {
|
|
19901
|
+
for (const [, note] of [...NO_EFFECT_RETIRED_NOTES, ...REMOVED_DATA_LAYER_NOTES]) {
|
|
19206
19902
|
if (noEffect.has(note))
|
|
19207
19903
|
parts.push(note);
|
|
19208
19904
|
}
|
|
19209
|
-
const removed = removedConfigKeysNoticeMessage(configPath, translation);
|
|
19210
|
-
if (removed)
|
|
19211
|
-
parts.push(removed);
|
|
19212
19905
|
return parts.join(" ");
|
|
19213
19906
|
}
|
|
19214
19907
|
function translateConfigDocument(map, tier) {
|
|
@@ -19216,7 +19909,6 @@ function translateConfigDocument(map, tier) {
|
|
|
19216
19909
|
warnings: [],
|
|
19217
19910
|
legacyInput: false,
|
|
19218
19911
|
retiredKeys: [],
|
|
19219
|
-
removedKeys: [],
|
|
19220
19912
|
retiredEnabledFalse: false
|
|
19221
19913
|
};
|
|
19222
19914
|
translateBlock(map, tier === "user", "base", out);
|
|
@@ -19227,7 +19919,6 @@ function translateConfigDocument(map, tier) {
|
|
|
19227
19919
|
}
|
|
19228
19920
|
}
|
|
19229
19921
|
out.retiredKeys = sortedUnique(out.retiredKeys);
|
|
19230
|
-
out.removedKeys = sortedUnique(out.removedKeys);
|
|
19231
19922
|
return out;
|
|
19232
19923
|
}
|
|
19233
19924
|
function unknownDisabledTools(disabled) {
|
|
@@ -19266,7 +19957,8 @@ function projectBlock(block) {
|
|
|
19266
19957
|
for (const path of [
|
|
19267
19958
|
...RETIRED_PATHS.map(([retired]) => retired),
|
|
19268
19959
|
...REMOVED_NO_EFFECT_PATHS,
|
|
19269
|
-
...DATA_LAYER_RETIRED_PATHS
|
|
19960
|
+
...DATA_LAYER_RETIRED_PATHS,
|
|
19961
|
+
...REMOVED_DATA_LAYER_PATHS
|
|
19270
19962
|
]) {
|
|
19271
19963
|
const dot = path.indexOf(".");
|
|
19272
19964
|
if (dot < 0) {
|
|
@@ -19346,7 +20038,7 @@ function canonicalJson(value) {
|
|
|
19346
20038
|
return JSON.stringify(value);
|
|
19347
20039
|
}
|
|
19348
20040
|
function noticeDigest(projection) {
|
|
19349
|
-
return
|
|
20041
|
+
return createHash5("sha256").update(canonicalJson(projection), "utf8").digest("hex");
|
|
19350
20042
|
}
|
|
19351
20043
|
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.";
|
|
19352
20044
|
var SEMANTIC_COST_NOTICE_DIGEST = noticeDigest({ notice: "semantic_default_cost_v1" });
|
|
@@ -20219,9 +20911,9 @@ async function createConcreteAftTransportPool(opts) {
|
|
|
20219
20911
|
var LIFECYCLE_STATE = Symbol.for("@cortexkit/aft-bridge/location-lifecycle/v1");
|
|
20220
20912
|
var RELEASE_LOCATION = Symbol.for("@cortexkit/aft-bridge/location-release/v1");
|
|
20221
20913
|
// ../aft-bridge/dist/lsp-github-install.js
|
|
20222
|
-
import { createHash as
|
|
20914
|
+
import { createHash as createHash6, randomBytes as randomBytes2 } from "node:crypto";
|
|
20223
20915
|
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";
|
|
20224
|
-
import { dirname as dirname4, join as
|
|
20916
|
+
import { dirname as dirname4, join as join10, relative as relative3, resolve as resolve7 } from "node:path";
|
|
20225
20917
|
import { Readable as Readable2 } from "node:stream";
|
|
20226
20918
|
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
20227
20919
|
|
|
@@ -20440,13 +21132,13 @@ function detectHostPlatform() {
|
|
|
20440
21132
|
|
|
20441
21133
|
// ../aft-bridge/dist/tar-executable.js
|
|
20442
21134
|
import { existsSync as existsSync5 } from "node:fs";
|
|
20443
|
-
import { join as
|
|
21135
|
+
import { join as join9 } from "node:path";
|
|
20444
21136
|
function windowsTarExecutable(options = {}) {
|
|
20445
21137
|
const platform = options.platform ?? process.platform;
|
|
20446
21138
|
if (platform !== "win32")
|
|
20447
21139
|
return "tar";
|
|
20448
21140
|
const env = options.env ?? process.env;
|
|
20449
|
-
const systemTar =
|
|
21141
|
+
const systemTar = join9(env.SystemRoot ?? "C:\\Windows", "System32", "tar.exe");
|
|
20450
21142
|
return (options.exists ?? existsSync5)(systemTar) ? systemTar : "tar";
|
|
20451
21143
|
}
|
|
20452
21144
|
function extractionCommand(args, privateStorage) {
|
|
@@ -20490,14 +21182,14 @@ function createGithubInstaller(services) {
|
|
|
20490
21182
|
return getAftLspBinariesDir();
|
|
20491
21183
|
}
|
|
20492
21184
|
function ghPackageDir(spec) {
|
|
20493
|
-
return
|
|
21185
|
+
return join10(ghCacheRoot(), spec.id);
|
|
20494
21186
|
}
|
|
20495
21187
|
function ghBinDir(spec) {
|
|
20496
21188
|
const platform = detectHostPlatform()?.platform ?? "linux";
|
|
20497
21189
|
return dirname4(ghBinaryPath(spec, platform));
|
|
20498
21190
|
}
|
|
20499
21191
|
function ghExtractDir(spec) {
|
|
20500
|
-
return
|
|
21192
|
+
return join10(ghPackageDir(spec), "extracted");
|
|
20501
21193
|
}
|
|
20502
21194
|
const INSTALLED_META_FILE = ".aft-installed";
|
|
20503
21195
|
const INSTALL_FAILED_FILE = ".aft-install-failed.json";
|
|
@@ -20505,8 +21197,9 @@ function createGithubInstaller(services) {
|
|
|
20505
21197
|
const INSTALL_LOCK_WAIT_MS = 10 * 60 * 1000;
|
|
20506
21198
|
const INSTALL_LOCK_POLL_INTERVAL_MS = 1000;
|
|
20507
21199
|
const INSTALL_LOCK_WAIT_TIMEOUT_REASON = "install lock held by another process for 10 minutes";
|
|
21200
|
+
const SMOKE_TIMEOUT_MS = 2000;
|
|
20508
21201
|
function installFailureMarkerPath(spec) {
|
|
20509
|
-
return
|
|
21202
|
+
return join10(ghPackageDir(spec), INSTALL_FAILED_FILE);
|
|
20510
21203
|
}
|
|
20511
21204
|
function readInstallFailureMarker(spec) {
|
|
20512
21205
|
try {
|
|
@@ -20550,15 +21243,15 @@ function createGithubInstaller(services) {
|
|
|
20550
21243
|
const meta = readGithubInstalledMetaIn(ghPackageDir(spec));
|
|
20551
21244
|
if (spec.layout === "distribution" && meta?.layout === "distribution" && isSafeVersion(meta.version)) {
|
|
20552
21245
|
const arch = detectHostPlatform()?.arch ?? "x64";
|
|
20553
|
-
return
|
|
21246
|
+
return join10(ghExtractDir(spec), spec.binaryPathInArchive(platform, arch, stripTagV(meta.version)));
|
|
20554
21247
|
}
|
|
20555
21248
|
const ext = platform === "win32" ? ".exe" : "";
|
|
20556
|
-
return
|
|
21249
|
+
return join10(ghPackageDir(spec), "bin", `${spec.binary}${ext}`);
|
|
20557
21250
|
}
|
|
20558
21251
|
function isGithubInstalled(spec, platform) {
|
|
20559
21252
|
for (const candidate of ghBinaryCandidates(spec, platform)) {
|
|
20560
21253
|
try {
|
|
20561
|
-
if (statSync6(
|
|
21254
|
+
if (statSync6(join10(ghBinDir(spec), candidate)).isFile())
|
|
20562
21255
|
return true;
|
|
20563
21256
|
} catch {}
|
|
20564
21257
|
}
|
|
@@ -20571,7 +21264,7 @@ function createGithubInstaller(services) {
|
|
|
20571
21264
|
}
|
|
20572
21265
|
function readGithubInstalledMetaIn(installDir) {
|
|
20573
21266
|
try {
|
|
20574
|
-
const path =
|
|
21267
|
+
const path = join10(installDir, INSTALLED_META_FILE);
|
|
20575
21268
|
if (!statSync6(path).isFile())
|
|
20576
21269
|
return null;
|
|
20577
21270
|
const parsed = JSON.parse(readFileSync5(path, "utf8"));
|
|
@@ -20602,7 +21295,7 @@ function createGithubInstaller(services) {
|
|
|
20602
21295
|
...layout ? { layout } : {},
|
|
20603
21296
|
...smoke ? { smoke } : {}
|
|
20604
21297
|
};
|
|
20605
|
-
const path =
|
|
21298
|
+
const path = join10(installDir, INSTALLED_META_FILE);
|
|
20606
21299
|
const tempPath = `${path}.tmp-${process.pid}-${randomBytes2(6).toString("hex")}`;
|
|
20607
21300
|
try {
|
|
20608
21301
|
writeFileSync2(tempPath, JSON.stringify(meta), { encoding: "utf8", flag: "wx" });
|
|
@@ -20618,7 +21311,7 @@ function createGithubInstaller(services) {
|
|
|
20618
21311
|
const MAX_EXTRACT_BYTES = 1024 * 1024 * 1024;
|
|
20619
21312
|
function sha256OfFile(path) {
|
|
20620
21313
|
return new Promise((resolve, reject) => {
|
|
20621
|
-
const hash =
|
|
21314
|
+
const hash = createHash6("sha256");
|
|
20622
21315
|
const stream = createReadStream2(path);
|
|
20623
21316
|
stream.on("error", reject);
|
|
20624
21317
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
@@ -20626,7 +21319,7 @@ function createGithubInstaller(services) {
|
|
|
20626
21319
|
});
|
|
20627
21320
|
}
|
|
20628
21321
|
function sha256OfFileSync(path) {
|
|
20629
|
-
const hash =
|
|
21322
|
+
const hash = createHash6("sha256");
|
|
20630
21323
|
const fd = openSync5(path, "r");
|
|
20631
21324
|
try {
|
|
20632
21325
|
const buffer = Buffer.allocUnsafe(1024 * 1024);
|
|
@@ -20854,7 +21547,7 @@ function createGithubInstaller(services) {
|
|
|
20854
21547
|
throw new Error(`failed to read staging dir ${dir}: ${err}`);
|
|
20855
21548
|
}
|
|
20856
21549
|
for (const entry of entries) {
|
|
20857
|
-
const full =
|
|
21550
|
+
const full = join10(dir, entry);
|
|
20858
21551
|
let lst;
|
|
20859
21552
|
try {
|
|
20860
21553
|
lst = lstatSync2(full);
|
|
@@ -20866,7 +21559,7 @@ function createGithubInstaller(services) {
|
|
|
20866
21559
|
try {
|
|
20867
21560
|
target = readlinkSync(full);
|
|
20868
21561
|
} catch {}
|
|
20869
|
-
throw new Error(`archive contains symlink ${
|
|
21562
|
+
throw new Error(`archive contains symlink ${relative3(realStagingRoot, full)} → ${target}; rejecting (zip-slip defense)`);
|
|
20870
21563
|
}
|
|
20871
21564
|
let realFull;
|
|
20872
21565
|
try {
|
|
@@ -20874,8 +21567,8 @@ function createGithubInstaller(services) {
|
|
|
20874
21567
|
} catch (err) {
|
|
20875
21568
|
throw new Error(`failed to realpath ${full}: ${err}`);
|
|
20876
21569
|
}
|
|
20877
|
-
const rel =
|
|
20878
|
-
if (relativePathEscapesRoot(rel) ||
|
|
21570
|
+
const rel = relative3(realStagingRoot, realFull);
|
|
21571
|
+
if (relativePathEscapesRoot(rel) || resolve7(realStagingRoot, rel) !== realFull) {
|
|
20879
21572
|
throw new Error(`archive entry escapes staging root: ${full} → ${realFull} (zip-slip defense)`);
|
|
20880
21573
|
}
|
|
20881
21574
|
if (lst.isDirectory()) {
|
|
@@ -21015,7 +21708,7 @@ function createGithubInstaller(services) {
|
|
|
21015
21708
|
}
|
|
21016
21709
|
function quarantineCachedGithubInstall(spec, reason) {
|
|
21017
21710
|
const packageDir = ghPackageDir(spec);
|
|
21018
|
-
const dest =
|
|
21711
|
+
const dest = join10(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
|
|
21019
21712
|
warn(`[lsp] tofu_mismatch ${spec.id}: ${reason}; quarantining ${packageDir} -> ${dest}`);
|
|
21020
21713
|
try {
|
|
21021
21714
|
mkdirSync4(dirname4(dest), { recursive: true });
|
|
@@ -21025,7 +21718,7 @@ function createGithubInstaller(services) {
|
|
|
21025
21718
|
warn(`[lsp] tofu_mismatch ${spec.id}: failed to quarantine cache entry: ${err}`);
|
|
21026
21719
|
}
|
|
21027
21720
|
}
|
|
21028
|
-
async function smokeGithubBinary(spec, binaryPath) {
|
|
21721
|
+
async function smokeGithubBinary(spec, binaryPath, timeoutMs = SMOKE_TIMEOUT_MS) {
|
|
21029
21722
|
return new Promise((resolveSmoke) => {
|
|
21030
21723
|
let child;
|
|
21031
21724
|
let settled = false;
|
|
@@ -21045,8 +21738,8 @@ function createGithubInstaller(services) {
|
|
|
21045
21738
|
const timer = setTimeout(() => {
|
|
21046
21739
|
child?.kill("SIGKILL");
|
|
21047
21740
|
child?.unref();
|
|
21048
|
-
finish("timeout",
|
|
21049
|
-
},
|
|
21741
|
+
finish("timeout", `exceeded ${timeoutMs} ms; keeping install`);
|
|
21742
|
+
}, timeoutMs);
|
|
21050
21743
|
const capture = (chunk) => {
|
|
21051
21744
|
const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
21052
21745
|
const available = 64 * 1024 - output.length;
|
|
@@ -21070,19 +21763,19 @@ function createGithubInstaller(services) {
|
|
|
21070
21763
|
function hasRequiredRuntime(spec, extractDir, version) {
|
|
21071
21764
|
return (spec.requiredRuntimePaths?.(stripTagV(version)) ?? []).every(({ path, kind }) => {
|
|
21072
21765
|
try {
|
|
21073
|
-
const info = statSync6(
|
|
21766
|
+
const info = statSync6(join10(extractDir, path));
|
|
21074
21767
|
return kind === "file" ? info.isFile() : info.isDirectory();
|
|
21075
21768
|
} catch {
|
|
21076
21769
|
return false;
|
|
21077
21770
|
}
|
|
21078
21771
|
});
|
|
21079
21772
|
}
|
|
21080
|
-
function validateCachedGithubInstall(spec, platform) {
|
|
21773
|
+
function validateCachedGithubInstall(spec, platform, smokeTimeoutMs = SMOKE_TIMEOUT_MS) {
|
|
21081
21774
|
const lease = acquireInstallLock(spec.githubRepo);
|
|
21082
21775
|
if (!lease)
|
|
21083
21776
|
return null;
|
|
21084
21777
|
try {
|
|
21085
|
-
const validation = validateCachedGithubInstallUnderLock(spec, platform);
|
|
21778
|
+
const validation = validateCachedGithubInstallUnderLock(spec, platform, smokeTimeoutMs);
|
|
21086
21779
|
if (typeof validation !== "boolean")
|
|
21087
21780
|
return validation.finally(() => lease.release());
|
|
21088
21781
|
lease.release();
|
|
@@ -21092,10 +21785,10 @@ function createGithubInstaller(services) {
|
|
|
21092
21785
|
throw err;
|
|
21093
21786
|
}
|
|
21094
21787
|
}
|
|
21095
|
-
function validateCachedGithubInstallUnderLock(spec, platform) {
|
|
21788
|
+
function validateCachedGithubInstallUnderLock(spec, platform, smokeTimeoutMs = SMOKE_TIMEOUT_MS) {
|
|
21096
21789
|
const packageDir = ghPackageDir(spec);
|
|
21097
21790
|
const meta = readGithubInstalledMetaIn(packageDir);
|
|
21098
|
-
const binaryPath = ghBinaryCandidates(spec, platform).map((candidate) =>
|
|
21791
|
+
const binaryPath = ghBinaryCandidates(spec, platform).map((candidate) => join10(ghBinDir(spec), candidate)).find((candidate) => {
|
|
21099
21792
|
try {
|
|
21100
21793
|
return statSync6(candidate).isFile();
|
|
21101
21794
|
} catch {
|
|
@@ -21125,7 +21818,7 @@ function createGithubInstaller(services) {
|
|
|
21125
21818
|
quarantineCachedGithubInstall(spec, "missing required runtime files");
|
|
21126
21819
|
return false;
|
|
21127
21820
|
}
|
|
21128
|
-
const verdict = await smokeGithubBinary(spec, binaryPath);
|
|
21821
|
+
const verdict = await smokeGithubBinary(spec, binaryPath, smokeTimeoutMs);
|
|
21129
21822
|
if (verdict === "failed") {
|
|
21130
21823
|
quarantineCachedGithubInstall(spec, "cached binary failed runtime smoke check");
|
|
21131
21824
|
return false;
|
|
@@ -21171,7 +21864,7 @@ function createGithubInstaller(services) {
|
|
|
21171
21864
|
}
|
|
21172
21865
|
const pkgDir = ghPackageDir(spec);
|
|
21173
21866
|
const extractDir = ghExtractDir(spec);
|
|
21174
|
-
const archivePath =
|
|
21867
|
+
const archivePath = join10(pkgDir, expected.name);
|
|
21175
21868
|
log(`[lsp] downloading ${spec.id} ${tag} → ${matchingAsset.url}`);
|
|
21176
21869
|
try {
|
|
21177
21870
|
await downloadFile(matchingAsset.url, archivePath, fetchImpl, matchingAsset.size, signal);
|
|
@@ -21207,7 +21900,7 @@ function createGithubInstaller(services) {
|
|
|
21207
21900
|
const binaryRelativePath = spec.binaryPathInArchive(platform, arch, version);
|
|
21208
21901
|
try {
|
|
21209
21902
|
await extractArchiveSafely(archivePath, extractDir, expected.archive, async (stagingDir) => {
|
|
21210
|
-
const stagedBinary =
|
|
21903
|
+
const stagedBinary = join10(stagingDir, binaryRelativePath);
|
|
21211
21904
|
if (!existsSync6(stagedBinary) || !statSync6(stagedBinary).isFile()) {
|
|
21212
21905
|
throw new Error(`extracted binary not found at ${stagedBinary}`);
|
|
21213
21906
|
}
|
|
@@ -21237,7 +21930,7 @@ function createGithubInstaller(services) {
|
|
|
21237
21930
|
unlinkSync3(archivePath);
|
|
21238
21931
|
} catch {}
|
|
21239
21932
|
}
|
|
21240
|
-
const innerBinaryPath =
|
|
21933
|
+
const innerBinaryPath = join10(extractDir, binaryRelativePath);
|
|
21241
21934
|
const targetBinary = spec.layout === "distribution" ? innerBinaryPath : ghBinaryPath(spec, platform);
|
|
21242
21935
|
mkdirSync4(dirname4(targetBinary), { recursive: true });
|
|
21243
21936
|
try {
|
|
@@ -21364,6 +22057,7 @@ function createGithubInstaller(services) {
|
|
|
21364
22057
|
let installsStarted = 0;
|
|
21365
22058
|
const lockWaitTimeoutMs = Math.max(0, options.__lockWaitTimeoutMsForTests ?? INSTALL_LOCK_WAIT_MS);
|
|
21366
22059
|
const lockPollIntervalMs = Math.max(1, options.__lockPollIntervalMsForTests ?? INSTALL_LOCK_POLL_INTERVAL_MS);
|
|
22060
|
+
const smokeTimeoutMs = Math.max(1, options.__smokeTimeoutMsForTests ?? SMOKE_TIMEOUT_MS);
|
|
21367
22061
|
function notifyCachedBinDirsChanged(directory) {
|
|
21368
22062
|
try {
|
|
21369
22063
|
options.onCachedBinDirsChanged?.(directory);
|
|
@@ -21376,7 +22070,7 @@ function createGithubInstaller(services) {
|
|
|
21376
22070
|
while (true) {
|
|
21377
22071
|
if (signal.aborted)
|
|
21378
22072
|
return null;
|
|
21379
|
-
const validation = await withInstallLock(spec.githubRepo, async () => validateCachedGithubInstallUnderLock(spec, platform));
|
|
22073
|
+
const validation = await withInstallLock(spec.githubRepo, async () => validateCachedGithubInstallUnderLock(spec, platform, smokeTimeoutMs));
|
|
21380
22074
|
if (validation !== null)
|
|
21381
22075
|
return validation;
|
|
21382
22076
|
if (signal.aborted)
|
|
@@ -21405,7 +22099,7 @@ function createGithubInstaller(services) {
|
|
|
21405
22099
|
}
|
|
21406
22100
|
for (const spec of GITHUB_LSP_TABLE) {
|
|
21407
22101
|
const controller = new AbortController;
|
|
21408
|
-
const validation = isGithubInstalled(spec, host.platform) ? validateCachedGithubInstall(spec, host.platform) : false;
|
|
22102
|
+
const validation = isGithubInstalled(spec, host.platform) ? validateCachedGithubInstall(spec, host.platform, smokeTimeoutMs) : false;
|
|
21409
22103
|
if (validation === true)
|
|
21410
22104
|
cachedBinDirs.push(ghBinDir(spec));
|
|
21411
22105
|
const cacheReady = (validation === null ? retryBusyCacheValidation(spec, host.platform, controller.signal) : Promise.resolve(validation)).then((healthy) => {
|
|
@@ -21460,7 +22154,7 @@ function createGithubInstaller(services) {
|
|
|
21460
22154
|
const currentHost = detectHostPlatform();
|
|
21461
22155
|
if (!currentHost)
|
|
21462
22156
|
return [];
|
|
21463
|
-
const directories = await Promise.all(GITHUB_LSP_TABLE.map(async (spec) => isGithubInstalled(spec, currentHost.platform) && await validateCachedGithubInstall(spec, currentHost.platform) ? ghBinDir(spec) : null));
|
|
22157
|
+
const directories = await Promise.all(GITHUB_LSP_TABLE.map(async (spec) => isGithubInstalled(spec, currentHost.platform) && await validateCachedGithubInstall(spec, currentHost.platform, smokeTimeoutMs) ? ghBinDir(spec) : null));
|
|
21464
22158
|
return directories.filter((directory) => directory !== null);
|
|
21465
22159
|
}
|
|
21466
22160
|
};
|
|
@@ -21531,7 +22225,7 @@ import { stat as stat2 } from "node:fs/promises";
|
|
|
21531
22225
|
// ../aft-bridge/dist/npm-resolver.js
|
|
21532
22226
|
import { readdirSync as readdirSync3, statSync as statSync7 } from "node:fs";
|
|
21533
22227
|
import { homedir as homedir9 } from "node:os";
|
|
21534
|
-
import { dirname as dirname5, isAbsolute as
|
|
22228
|
+
import { dirname as dirname5, isAbsolute as isAbsolute4, join as join11 } from "node:path";
|
|
21535
22229
|
function defaultDeps() {
|
|
21536
22230
|
return {
|
|
21537
22231
|
platform: process.platform,
|
|
@@ -21558,16 +22252,16 @@ function npmFromPath(deps) {
|
|
|
21558
22252
|
const separator = deps.platform === "win32" ? ";" : ":";
|
|
21559
22253
|
for (const entry of raw.split(separator)) {
|
|
21560
22254
|
const dir = entry.trim().replace(/^"|"$/g, "");
|
|
21561
|
-
if (!dir || !
|
|
22255
|
+
if (!dir || !isAbsolute4(dir))
|
|
21562
22256
|
continue;
|
|
21563
|
-
if (isFile(
|
|
22257
|
+
if (isFile(join11(dir, name)))
|
|
21564
22258
|
return dir;
|
|
21565
22259
|
}
|
|
21566
22260
|
return null;
|
|
21567
22261
|
}
|
|
21568
22262
|
function npmAdjacentToNode(deps) {
|
|
21569
22263
|
const dir = dirname5(deps.execPath);
|
|
21570
|
-
return isFile(
|
|
22264
|
+
return isFile(join11(dir, npmBinaryName(deps.platform))) ? dir : null;
|
|
21571
22265
|
}
|
|
21572
22266
|
function highestVersionedNodeBin(installsDir, name) {
|
|
21573
22267
|
let entries;
|
|
@@ -21576,8 +22270,8 @@ function highestVersionedNodeBin(installsDir, name) {
|
|
|
21576
22270
|
} catch {
|
|
21577
22271
|
return null;
|
|
21578
22272
|
}
|
|
21579
|
-
const candidates = entries.filter((v) => isFile(
|
|
21580
|
-
return candidates.length > 0 ?
|
|
22273
|
+
const candidates = entries.filter((v) => isFile(join11(installsDir, v, "bin", name))).sort((a, b) => compareVersionsDesc(a, b));
|
|
22274
|
+
return candidates.length > 0 ? join11(installsDir, candidates[0], "bin") : null;
|
|
21581
22275
|
}
|
|
21582
22276
|
function compareVersionsDesc(a, b) {
|
|
21583
22277
|
const pa = a.replace(/^v/, "").split(".").map((n) => Number.parseInt(n, 10));
|
|
@@ -21602,22 +22296,22 @@ function wellKnownNpmDirs(deps) {
|
|
|
21602
22296
|
const programFiles = env.ProgramFiles || "C:\\Program Files";
|
|
21603
22297
|
const appData = env.APPDATA;
|
|
21604
22298
|
const localAppData = env.LOCALAPPDATA;
|
|
21605
|
-
push(
|
|
22299
|
+
push(join11(programFiles, "nodejs"));
|
|
21606
22300
|
if (appData)
|
|
21607
|
-
push(
|
|
22301
|
+
push(join11(appData, "npm"));
|
|
21608
22302
|
if (localAppData)
|
|
21609
|
-
push(
|
|
22303
|
+
push(join11(localAppData, "Volta", "bin"));
|
|
21610
22304
|
if (env.NVM_SYMLINK)
|
|
21611
22305
|
push(env.NVM_SYMLINK);
|
|
21612
22306
|
} else {
|
|
21613
22307
|
if (env.NVM_BIN)
|
|
21614
22308
|
push(env.NVM_BIN);
|
|
21615
|
-
push(highestVersionedNodeBin(
|
|
21616
|
-
push(highestVersionedNodeBin(
|
|
21617
|
-
push(highestVersionedNodeBin(
|
|
21618
|
-
push(
|
|
21619
|
-
push(
|
|
21620
|
-
const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin",
|
|
22309
|
+
push(highestVersionedNodeBin(join11(home, ".nvm", "versions", "node"), name));
|
|
22310
|
+
push(highestVersionedNodeBin(join11(home, ".local", "share", "mise", "installs", "node"), name));
|
|
22311
|
+
push(highestVersionedNodeBin(join11(home, ".asdf", "installs", "nodejs"), name));
|
|
22312
|
+
push(join11(home, ".volta", "bin"));
|
|
22313
|
+
push(join11(home, ".asdf", "shims"));
|
|
22314
|
+
const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin", join11(home, ".local", "bin")]);
|
|
21621
22315
|
for (const dir of systemDirs)
|
|
21622
22316
|
push(dir);
|
|
21623
22317
|
}
|
|
@@ -21627,12 +22321,12 @@ function resolveNpm(deps = defaultDeps()) {
|
|
|
21627
22321
|
const name = npmBinaryName(deps.platform);
|
|
21628
22322
|
const onPath = npmFromPath(deps);
|
|
21629
22323
|
if (onPath)
|
|
21630
|
-
return { command:
|
|
22324
|
+
return { command: join11(onPath, name), binDir: onPath };
|
|
21631
22325
|
const adjacent = npmAdjacentToNode(deps);
|
|
21632
22326
|
if (adjacent)
|
|
21633
|
-
return { command:
|
|
22327
|
+
return { command: join11(adjacent, name), binDir: adjacent };
|
|
21634
22328
|
for (const dir of wellKnownNpmDirs(deps)) {
|
|
21635
|
-
const candidate =
|
|
22329
|
+
const candidate = join11(dir, name);
|
|
21636
22330
|
if (isFile(candidate))
|
|
21637
22331
|
return { command: candidate, binDir: dir };
|
|
21638
22332
|
}
|
|
@@ -21641,15 +22335,15 @@ function resolveNpm(deps = defaultDeps()) {
|
|
|
21641
22335
|
function npmCandidates(deps = defaultDeps()) {
|
|
21642
22336
|
const name = npmBinaryName(deps.platform);
|
|
21643
22337
|
const dirs = [
|
|
21644
|
-
...(deps.env.PATH ?? "").split(deps.platform === "win32" ? ";" : ":").filter(
|
|
22338
|
+
...(deps.env.PATH ?? "").split(deps.platform === "win32" ? ";" : ":").filter(isAbsolute4),
|
|
21645
22339
|
dirname5(deps.execPath),
|
|
21646
22340
|
...wellKnownNpmDirs(deps)
|
|
21647
22341
|
];
|
|
21648
22342
|
return [...new Set(dirs)].flatMap((binDir) => {
|
|
21649
22343
|
return [
|
|
21650
|
-
|
|
21651
|
-
|
|
21652
|
-
|
|
22344
|
+
join11(binDir, name),
|
|
22345
|
+
join11(binDir, "node_modules", "npm", "bin", "npm-cli.js"),
|
|
22346
|
+
join11(binDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
|
|
21653
22347
|
].filter(isFile).map((command) => ({ command, binDir }));
|
|
21654
22348
|
});
|
|
21655
22349
|
}
|
|
@@ -21818,7 +22512,7 @@ function terminateNpmProcessTree(child, invocation, env = process.env, gracePeri
|
|
|
21818
22512
|
};
|
|
21819
22513
|
child.once("exit", onChildExit);
|
|
21820
22514
|
const systemRoot = env.SystemRoot ?? env.SYSTEMROOT;
|
|
21821
|
-
const taskkill = systemRoot ?
|
|
22515
|
+
const taskkill = systemRoot ? join11(systemRoot, "System32", "taskkill.exe") : "taskkill.exe";
|
|
21822
22516
|
try {
|
|
21823
22517
|
killer = spawn(taskkill, ["/pid", String(child.pid), "/t", "/f"], {
|
|
21824
22518
|
stdio: "ignore",
|
|
@@ -21949,7 +22643,7 @@ async function lspNpmInstallInvocation(npm, target, before, clock = SYSTEM_CLOCK
|
|
|
21949
22643
|
}
|
|
21950
22644
|
// ../aft-bridge/dist/lsp-npm-selection.js
|
|
21951
22645
|
import { readFile, realpath, stat as stat3 } from "node:fs/promises";
|
|
21952
|
-
import { dirname as dirname6, join as
|
|
22646
|
+
import { dirname as dirname6, join as join12, resolve as resolve8 } from "node:path";
|
|
21953
22647
|
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.";
|
|
21954
22648
|
function lspNpmRefusal(path, reason) {
|
|
21955
22649
|
return LSP_NPM_REFUSAL.replace("<path>", path).replace("<reason>", reason);
|
|
@@ -21964,13 +22658,13 @@ async function genuineNpm(candidate) {
|
|
|
21964
22658
|
const windowsShim = /\.(?:cmd|bat)$/i.test(executable);
|
|
21965
22659
|
let current = dirname6(executable);
|
|
21966
22660
|
if (windowsShim)
|
|
21967
|
-
current =
|
|
22661
|
+
current = join12(current, "node_modules", "npm");
|
|
21968
22662
|
for (;; ) {
|
|
21969
22663
|
try {
|
|
21970
|
-
const pkg = JSON.parse(await readFile(
|
|
22664
|
+
const pkg = JSON.parse(await readFile(join12(current, "package.json"), "utf8"));
|
|
21971
22665
|
const bin = typeof pkg.bin === "string" ? pkg.bin : pkg.bin?.npm;
|
|
21972
22666
|
if (pkg.name === "npm" && typeof bin === "string") {
|
|
21973
|
-
const cli = await realpath(
|
|
22667
|
+
const cli = await realpath(resolve8(current, bin));
|
|
21974
22668
|
if (!windowsShim && cli !== executable)
|
|
21975
22669
|
return { reason: "not npm: command is not npm's declared CLI" };
|
|
21976
22670
|
const major = /^(\d+)\.\d+\.\d+$/.exec(pkg.version)?.[1];
|
|
@@ -21979,7 +22673,7 @@ async function genuineNpm(candidate) {
|
|
|
21979
22673
|
if (Number(major) < 7)
|
|
21980
22674
|
return { reason: `old npm: ${pkg.version} (requires npm 7 or newer)` };
|
|
21981
22675
|
if (windowsShim || process.platform === "win32" && /\.[cm]?js$/i.test(cli)) {
|
|
21982
|
-
const node =
|
|
22676
|
+
const node = join12(candidate.binDir ?? dirname6(executable), "node.exe");
|
|
21983
22677
|
if (!(await stat3(node)).isFile())
|
|
21984
22678
|
return { reason: "probe failed: adjacent Node is missing" };
|
|
21985
22679
|
return { npm: { command: node, binDir: dirname6(node), cliPath: cli }, reason: "" };
|
|
@@ -22071,12 +22765,12 @@ function shouldInterruptWaitsForMessage(detachOnUserMessage, operatorText) {
|
|
|
22071
22765
|
// ../aft-bridge/dist/migration.js
|
|
22072
22766
|
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";
|
|
22073
22767
|
import { homedir as homedir12, tmpdir as tmpdir3 } from "node:os";
|
|
22074
|
-
import { basename as basename2, dirname as dirname9, join as
|
|
22768
|
+
import { basename as basename2, dirname as dirname9, join as join15, resolve as resolve10 } from "node:path";
|
|
22075
22769
|
|
|
22076
22770
|
// ../aft-bridge/dist/paths.js
|
|
22077
22771
|
import { existsSync as existsSync7, readFileSync as readFileSync6, realpathSync as realpathSync5, renameSync as renameSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
22078
22772
|
import { homedir as homedir10 } from "node:os";
|
|
22079
|
-
import { dirname as dirname7, isAbsolute as
|
|
22773
|
+
import { dirname as dirname7, isAbsolute as isAbsolute5, join as join13, resolve as resolve9 } from "node:path";
|
|
22080
22774
|
function homeDir3() {
|
|
22081
22775
|
if (process.platform === "win32")
|
|
22082
22776
|
return process.env.USERPROFILE || process.env.HOME || homedir10();
|
|
@@ -22084,18 +22778,18 @@ function homeDir3() {
|
|
|
22084
22778
|
}
|
|
22085
22779
|
function configHome() {
|
|
22086
22780
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
22087
|
-
if (xdg &&
|
|
22781
|
+
if (xdg && isAbsolute5(xdg))
|
|
22088
22782
|
return xdg;
|
|
22089
|
-
return
|
|
22783
|
+
return join13(homeDir3(), ".config");
|
|
22090
22784
|
}
|
|
22091
22785
|
function legacyOpenCodeConfigDir() {
|
|
22092
22786
|
const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
22093
22787
|
if (envDir)
|
|
22094
|
-
return
|
|
22095
|
-
return
|
|
22788
|
+
return resolve9(envDir);
|
|
22789
|
+
return join13(configHome(), "opencode");
|
|
22096
22790
|
}
|
|
22097
22791
|
function legacyPiAgentDir() {
|
|
22098
|
-
return
|
|
22792
|
+
return join13(homeDir3(), ".pi", "agent");
|
|
22099
22793
|
}
|
|
22100
22794
|
function legacySources(basePath, label, harness) {
|
|
22101
22795
|
return [
|
|
@@ -22104,10 +22798,10 @@ function legacySources(basePath, label, harness) {
|
|
|
22104
22798
|
];
|
|
22105
22799
|
}
|
|
22106
22800
|
function resolveCortexKitUserConfigPath() {
|
|
22107
|
-
return
|
|
22801
|
+
return join13(configHome(), "cortexkit", "aft.jsonc");
|
|
22108
22802
|
}
|
|
22109
22803
|
function resolveCortexKitProjectConfigPath(projectDirectory) {
|
|
22110
|
-
return
|
|
22804
|
+
return join13(projectDirectory, ".cortexkit", "aft.jsonc");
|
|
22111
22805
|
}
|
|
22112
22806
|
function resolveProjectConfigReadPath(projectDirectory, operatingHarness) {
|
|
22113
22807
|
const canonical = resolveCortexKitProjectConfigPath(projectDirectory);
|
|
@@ -22134,14 +22828,14 @@ function resolveCortexKitConfigPaths(projectDirectory) {
|
|
|
22134
22828
|
}
|
|
22135
22829
|
function resolveLegacyAftConfigSources(projectDirectory) {
|
|
22136
22830
|
const project = [
|
|
22137
|
-
...legacySources(
|
|
22138
|
-
...legacySources(
|
|
22831
|
+
...legacySources(join13(projectDirectory, ".opencode", "aft"), "OpenCode project", "opencode"),
|
|
22832
|
+
...legacySources(join13(projectDirectory, ".pi", "aft"), "Pi project", "pi")
|
|
22139
22833
|
];
|
|
22140
22834
|
const identity = (path) => {
|
|
22141
22835
|
try {
|
|
22142
22836
|
return realpathSync5(path);
|
|
22143
22837
|
} catch {
|
|
22144
|
-
return
|
|
22838
|
+
return resolve9(path);
|
|
22145
22839
|
}
|
|
22146
22840
|
};
|
|
22147
22841
|
const protectedPaths = new Set([
|
|
@@ -22150,18 +22844,18 @@ function resolveLegacyAftConfigSources(projectDirectory) {
|
|
|
22150
22844
|
].map(identity));
|
|
22151
22845
|
return {
|
|
22152
22846
|
user: [
|
|
22153
|
-
...legacySources(
|
|
22154
|
-
...legacySources(
|
|
22847
|
+
...legacySources(join13(legacyOpenCodeConfigDir(), "aft"), "OpenCode user", "opencode"),
|
|
22848
|
+
...legacySources(join13(legacyPiAgentDir(), "aft"), "Pi user", "pi")
|
|
22155
22849
|
].filter((source) => !protectedPaths.has(identity(source.path))),
|
|
22156
22850
|
project
|
|
22157
22851
|
};
|
|
22158
22852
|
}
|
|
22159
22853
|
function resolveHarnessStoragePath(storageRoot, harness, ...segments) {
|
|
22160
|
-
return
|
|
22854
|
+
return join13(storageRoot, harness, ...segments);
|
|
22161
22855
|
}
|
|
22162
22856
|
function repairRootScopedStorageFile(storageRoot, harness, fileName) {
|
|
22163
22857
|
const harnessPath = resolveHarnessStoragePath(storageRoot, harness, fileName);
|
|
22164
|
-
const rootPath =
|
|
22858
|
+
const rootPath = join13(storageRoot, fileName);
|
|
22165
22859
|
if (existsSync7(harnessPath) || !existsSync7(rootPath))
|
|
22166
22860
|
return harnessPath;
|
|
22167
22861
|
try {
|
|
@@ -22250,15 +22944,15 @@ function decodeFileUrl(target) {
|
|
|
22250
22944
|
import { closeSync as closeSync7, existsSync as existsSync8, promises as fsPromises, openSync as openSync6, readFileSync as readFileSync7, readSync as readSync6 } from "node:fs";
|
|
22251
22945
|
import { createRequire as createRequire2 } from "node:module";
|
|
22252
22946
|
import { homedir as homedir11 } from "node:os";
|
|
22253
|
-
import { delimiter, dirname as dirname8, isAbsolute as
|
|
22947
|
+
import { delimiter, dirname as dirname8, isAbsolute as isAbsolute6, join as join14 } from "node:path";
|
|
22254
22948
|
var ensureBinaryForResolver = ensureBinary;
|
|
22255
22949
|
var npmPlatformPackageReader = null;
|
|
22256
22950
|
var cacheCopiesInFlight = new Map;
|
|
22257
22951
|
function copyToVersionedCache(npmBinaryPath, version) {
|
|
22258
22952
|
const tag = version.startsWith("v") ? version : `v${version}`;
|
|
22259
22953
|
const ext = process.platform === "win32" ? ".exe" : "";
|
|
22260
|
-
const versionedDir =
|
|
22261
|
-
const cachedPath =
|
|
22954
|
+
const versionedDir = join14(getAftBinaryCacheDir(), tag);
|
|
22955
|
+
const cachedPath = join14(versionedDir, `aft${ext}`);
|
|
22262
22956
|
if (existsSync8(cachedPath) && isTrustedCachedBinary(cachedPath, version))
|
|
22263
22957
|
return { cachedPath };
|
|
22264
22958
|
const existing = cacheCopiesInFlight.get(cachedPath);
|
|
@@ -22304,7 +22998,7 @@ function homeDirFromEnv(env) {
|
|
|
22304
22998
|
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir11();
|
|
22305
22999
|
}
|
|
22306
23000
|
function cachedBinaryPathFromEnv(version, env, ext) {
|
|
22307
|
-
const binaryPath =
|
|
23001
|
+
const binaryPath = join14(getAftBinaryCacheDir(env), version, `aft${ext}`);
|
|
22308
23002
|
return existsSync8(binaryPath) ? binaryPath : null;
|
|
22309
23003
|
}
|
|
22310
23004
|
async function probeBinaryCandidateOffThread(binaryPath, source, expectedVersion) {
|
|
@@ -22324,9 +23018,9 @@ function pathCandidates(env, ext) {
|
|
|
22324
23018
|
const seen = new Set;
|
|
22325
23019
|
const candidates = [];
|
|
22326
23020
|
for (const dir of rawPath.split(delimiter)) {
|
|
22327
|
-
if (!dir || !
|
|
23021
|
+
if (!dir || !isAbsolute6(dir))
|
|
22328
23022
|
continue;
|
|
22329
|
-
const candidate =
|
|
23023
|
+
const candidate = join14(dir, `aft${ext}`);
|
|
22330
23024
|
if (seen.has(candidate))
|
|
22331
23025
|
continue;
|
|
22332
23026
|
seen.add(candidate);
|
|
@@ -22404,7 +23098,7 @@ function npmPlatformPackage(ext) {
|
|
|
22404
23098
|
const req = createRequire2(import.meta.url);
|
|
22405
23099
|
const manifestPath = req.resolve(`@cortexkit/aft-${platformKey()}/package.json`);
|
|
22406
23100
|
const manifest = JSON.parse(readFileSync7(manifestPath, "utf8"));
|
|
22407
|
-
const binaryPath =
|
|
23101
|
+
const binaryPath = join14(dirname8(manifestPath), "bin", `aft${ext}`);
|
|
22408
23102
|
if (typeof manifest.version !== "string" || !existsSync8(binaryPath))
|
|
22409
23103
|
return null;
|
|
22410
23104
|
return { binaryPath, version: normalizeBareVersion(manifest.version) };
|
|
@@ -22471,7 +23165,7 @@ async function findProbedBinary(expectedVersion, env) {
|
|
|
22471
23165
|
if (usable)
|
|
22472
23166
|
return { path: usable, source: "PATH" };
|
|
22473
23167
|
}
|
|
22474
|
-
const cargoPath =
|
|
23168
|
+
const cargoPath = join14(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
|
|
22475
23169
|
if (existsSync8(cargoPath)) {
|
|
22476
23170
|
const usable = await probeBinaryCandidateOffThread(cargoPath, "cargo", pluginVersion);
|
|
22477
23171
|
if (usable)
|
|
@@ -22570,9 +23264,9 @@ function dataHome() {
|
|
|
22570
23264
|
if (process.env.XDG_DATA_HOME)
|
|
22571
23265
|
return process.env.XDG_DATA_HOME;
|
|
22572
23266
|
if (process.platform === "win32") {
|
|
22573
|
-
return process.env.LOCALAPPDATA || process.env.APPDATA ||
|
|
23267
|
+
return process.env.LOCALAPPDATA || process.env.APPDATA || join15(homeDir4(), "AppData", "Local");
|
|
22574
23268
|
}
|
|
22575
|
-
return
|
|
23269
|
+
return join15(homeDir4(), ".local", "share");
|
|
22576
23270
|
}
|
|
22577
23271
|
function homeDir4() {
|
|
22578
23272
|
if (process.platform === "win32")
|
|
@@ -22581,8 +23275,8 @@ function homeDir4() {
|
|
|
22581
23275
|
}
|
|
22582
23276
|
function resolveLegacyStorageRoot(harness) {
|
|
22583
23277
|
if (harness === "pi")
|
|
22584
|
-
return
|
|
22585
|
-
return
|
|
23278
|
+
return join15(homeDir4(), ".pi", "agent", "aft");
|
|
23279
|
+
return join15(dataHome(), "opencode", "storage", "plugin", "aft");
|
|
22586
23280
|
}
|
|
22587
23281
|
function stripJsoncForParse(input) {
|
|
22588
23282
|
let out = "";
|
|
@@ -22712,7 +23406,7 @@ function acquireConfigMigrationLock(lockDir) {
|
|
|
22712
23406
|
}
|
|
22713
23407
|
function atomicCopyConfigFile(sourcePath, targetPath) {
|
|
22714
23408
|
mkdirSync5(dirname9(targetPath), { recursive: true });
|
|
22715
|
-
const tmpPath =
|
|
23409
|
+
const tmpPath = join15(dirname9(targetPath), `.${basename2(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
|
|
22716
23410
|
let fd = null;
|
|
22717
23411
|
try {
|
|
22718
23412
|
fd = openSync7(tmpPath, "wx", 384);
|
|
@@ -22734,7 +23428,7 @@ function atomicCopyConfigFile(sourcePath, targetPath) {
|
|
|
22734
23428
|
}
|
|
22735
23429
|
function atomicWriteConfigFile(targetPath, content) {
|
|
22736
23430
|
mkdirSync5(dirname9(targetPath), { recursive: true });
|
|
22737
|
-
const tmpPath =
|
|
23431
|
+
const tmpPath = join15(dirname9(targetPath), `.${basename2(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
|
|
22738
23432
|
let fd = null;
|
|
22739
23433
|
try {
|
|
22740
23434
|
fd = openSync7(tmpPath, "wx", 384);
|
|
@@ -22853,8 +23547,8 @@ function visibleConfigMigrationWarning(scope, targetPath, paths, reason) {
|
|
|
22853
23547
|
}
|
|
22854
23548
|
function migrateAftConfigFile(opts) {
|
|
22855
23549
|
const warnings = [];
|
|
22856
|
-
const resolvedTarget =
|
|
22857
|
-
const existingSources = opts.legacySources.filter((source) => existsSync9(source.path) &&
|
|
23550
|
+
const resolvedTarget = resolve10(opts.targetPath);
|
|
23551
|
+
const existingSources = opts.legacySources.filter((source) => existsSync9(source.path) && resolve10(source.path) !== resolvedTarget);
|
|
22858
23552
|
const info = opts.logger?.info ?? opts.logger?.log;
|
|
22859
23553
|
if (existingSources.length === 0) {
|
|
22860
23554
|
return { migrated: false, conflict: false, targetPath: opts.targetPath, warnings };
|
|
@@ -22916,12 +23610,12 @@ function spawnErrorLabel(error) {
|
|
|
22916
23610
|
return [code, error.message].filter(Boolean).join(": ");
|
|
22917
23611
|
}
|
|
22918
23612
|
function migrationLogPath(newRoot, harness, logger) {
|
|
22919
|
-
const desired =
|
|
23613
|
+
const desired = join15(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
|
|
22920
23614
|
try {
|
|
22921
23615
|
mkdirSync5(dirname9(desired), { recursive: true });
|
|
22922
23616
|
return desired;
|
|
22923
23617
|
} catch (err) {
|
|
22924
|
-
const fallback =
|
|
23618
|
+
const fallback = join15(tmpdir3(), `aft-migration-${harness}-${Date.now()}.jsonl`);
|
|
22925
23619
|
logger?.warn?.(`Failed to create AFT migration log directory ${dirname9(desired)}: ${err instanceof Error ? err.message : String(err)}. ` + `Using fallback log path ${fallback}.`);
|
|
22926
23620
|
return fallback;
|
|
22927
23621
|
}
|
|
@@ -22981,13 +23675,13 @@ async function ensureStorageMigrated(opts) {
|
|
|
22981
23675
|
// ../aft-bridge/dist/migration-notices.js
|
|
22982
23676
|
import { readFileSync as readFileSync9, renameSync as renameSync6, rmdirSync, statSync as statSync9, writeFileSync as writeFileSync5 } from "node:fs";
|
|
22983
23677
|
import { homedir as homedir13 } from "node:os";
|
|
22984
|
-
import { dirname as dirname10, join as
|
|
23678
|
+
import { dirname as dirname10, join as join16, resolve as resolve11 } from "node:path";
|
|
22985
23679
|
function migrationNoticeStorePath(env = process.env) {
|
|
22986
|
-
const stateHome = env.XDG_STATE_HOME && env.XDG_STATE_HOME.length > 0 ? env.XDG_STATE_HOME :
|
|
22987
|
-
return
|
|
23680
|
+
const stateHome = env.XDG_STATE_HOME && env.XDG_STATE_HOME.length > 0 ? env.XDG_STATE_HOME : join16(homedir13(), ".local", "state");
|
|
23681
|
+
return join16(stateHome, "cortexkit", "aft", "migration-notices.json");
|
|
22988
23682
|
}
|
|
22989
23683
|
function noticeKey(configPath, digest) {
|
|
22990
|
-
return `${
|
|
23684
|
+
return `${resolve11(configPath)}|${MIGRATION_POLICY_ID}|${digest}`;
|
|
22991
23685
|
}
|
|
22992
23686
|
function readRecords(storePath) {
|
|
22993
23687
|
try {
|
|
@@ -23181,7 +23875,7 @@ function probeOnnxRuntimeLoadable(libPath, arch = process.arch) {
|
|
|
23181
23875
|
// ../aft-bridge/dist/onnx-runtime.js
|
|
23182
23876
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
23183
23877
|
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";
|
|
23184
|
-
import { basename as basename3, dirname as dirname11, isAbsolute as
|
|
23878
|
+
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";
|
|
23185
23879
|
import { Readable as Readable3 } from "node:stream";
|
|
23186
23880
|
import { pipeline as pipeline3 } from "node:stream/promises";
|
|
23187
23881
|
var ORT_VERSION = "1.24.4";
|
|
@@ -23269,7 +23963,7 @@ function resolveOnnxRuntime(storageDir, seams) {
|
|
|
23269
23963
|
}
|
|
23270
23964
|
async function findCachedOnnxRuntime(ortVersionDir, libName) {
|
|
23271
23965
|
const resolvedOrtDir = resolveCachedOnnxRuntimeDir(ortVersionDir, libName);
|
|
23272
|
-
const libPath =
|
|
23966
|
+
const libPath = join17(resolvedOrtDir, libName);
|
|
23273
23967
|
if (existsSync11(libPath)) {
|
|
23274
23968
|
const meta = readOnnxInstalledMeta(ortVersionDir);
|
|
23275
23969
|
if (meta?.sha256) {
|
|
@@ -23294,7 +23988,7 @@ async function findCachedOnnxRuntime(ortVersionDir, libName) {
|
|
|
23294
23988
|
}
|
|
23295
23989
|
async function resolveOnnxRuntimeUncoalesced(storageDir, seams) {
|
|
23296
23990
|
const info = seams.platformInfo !== undefined ? seams.platformInfo : getPlatformInfo();
|
|
23297
|
-
const ortVersionDir =
|
|
23991
|
+
const ortVersionDir = join17(storageDir, "onnxruntime", ORT_VERSION);
|
|
23298
23992
|
const libName = info?.libName ?? "libonnxruntime.dylib";
|
|
23299
23993
|
const cached = await findCachedOnnxRuntime(ortVersionDir, libName);
|
|
23300
23994
|
if (cached)
|
|
@@ -23308,9 +24002,9 @@ async function resolveOnnxRuntimeUncoalesced(storageDir, seams) {
|
|
|
23308
24002
|
warn(`ONNX Runtime auto-download not available for ${process.platform}/${process.arch}. Install manually: ${getManualInstallHint()}`);
|
|
23309
24003
|
return null;
|
|
23310
24004
|
}
|
|
23311
|
-
const onnxBaseDir =
|
|
24005
|
+
const onnxBaseDir = join17(storageDir, "onnxruntime");
|
|
23312
24006
|
openPrivateStorageDir(storageDir, onnxBaseDir);
|
|
23313
|
-
const lockPath =
|
|
24007
|
+
const lockPath = join17(onnxBaseDir, ONNX_LOCK_FILE);
|
|
23314
24008
|
const pollMs = seams.lockPollMs ?? LOCK_POLL_MS;
|
|
23315
24009
|
const deadline = Date.now() + LOCK_WAIT_MS;
|
|
23316
24010
|
let announcedWait = false;
|
|
@@ -23355,7 +24049,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
23355
24049
|
for (const entry of entries) {
|
|
23356
24050
|
if (!entry.startsWith(`${ORT_VERSION}.tmp.`))
|
|
23357
24051
|
continue;
|
|
23358
|
-
const stagingDir =
|
|
24052
|
+
const stagingDir = join17(onnxBaseDir, entry);
|
|
23359
24053
|
const parts = entry.split(".");
|
|
23360
24054
|
const pidStr = parts[parts.length - 2];
|
|
23361
24055
|
const pid = pidStr ? Number.parseInt(pidStr, 10) : NaN;
|
|
@@ -23392,7 +24086,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
23392
24086
|
}
|
|
23393
24087
|
function cleanupIncompleteTargetIfUnowned(ortDir) {
|
|
23394
24088
|
try {
|
|
23395
|
-
if (existsSync11(ortDir) && !existsSync11(
|
|
24089
|
+
if (existsSync11(ortDir) && !existsSync11(join17(ortDir, ONNX_INSTALLED_META_FILE))) {
|
|
23396
24090
|
log(`[onnx] removing half-populated install dir ${ortDir} (no meta file)`);
|
|
23397
24091
|
rmSync4(ortDir, { recursive: true, force: true });
|
|
23398
24092
|
}
|
|
@@ -23420,14 +24114,14 @@ function parseOnnxVersionFromDirectoryPath(value) {
|
|
|
23420
24114
|
return null;
|
|
23421
24115
|
}
|
|
23422
24116
|
function isPathInsideRoot(root, candidate) {
|
|
23423
|
-
const rel =
|
|
23424
|
-
return rel === "" || !rel.startsWith("../") && !rel.startsWith("..\\") && rel !== ".." && !
|
|
24117
|
+
const rel = relative4(root, candidate);
|
|
24118
|
+
return rel === "" || !rel.startsWith("../") && !rel.startsWith("..\\") && rel !== ".." && !isAbsolute7(rel) && !win324.isAbsolute(rel);
|
|
23425
24119
|
}
|
|
23426
24120
|
function detectOnnxVersion(libDir, libName) {
|
|
23427
24121
|
try {
|
|
23428
24122
|
const entries = readdirSync4(libDir);
|
|
23429
24123
|
try {
|
|
23430
|
-
const resolved = parseOnnxVersionFromPath(realpathSync7(
|
|
24124
|
+
const resolved = parseOnnxVersionFromPath(realpathSync7(join17(libDir, libName)));
|
|
23431
24125
|
if (resolved && resolved !== INVALID_ORT_VERSION)
|
|
23432
24126
|
return resolved;
|
|
23433
24127
|
} catch {}
|
|
@@ -23441,7 +24135,7 @@ function detectOnnxVersion(libDir, libName) {
|
|
|
23441
24135
|
if (version)
|
|
23442
24136
|
return version;
|
|
23443
24137
|
}
|
|
23444
|
-
const base =
|
|
24138
|
+
const base = join17(libDir, libName);
|
|
23445
24139
|
if (existsSync11(base)) {
|
|
23446
24140
|
try {
|
|
23447
24141
|
const real = realpathSync7(base);
|
|
@@ -23481,18 +24175,18 @@ function pathEntriesForPlatform() {
|
|
|
23481
24175
|
return pathEnvValue().split(delimiter).map((entry) => entry.trim().replace(/^"|"$/g, "")).filter((entry) => {
|
|
23482
24176
|
if (!entry || entry === "." || entry.includes("\x00"))
|
|
23483
24177
|
return false;
|
|
23484
|
-
return
|
|
24178
|
+
return isAbsolute7(entry) || win324.isAbsolute(entry);
|
|
23485
24179
|
});
|
|
23486
24180
|
}
|
|
23487
24181
|
function isWindowsSystem32Directory(dir) {
|
|
23488
24182
|
if (process.platform !== "win32")
|
|
23489
24183
|
return false;
|
|
23490
|
-
const normalizedDir =
|
|
24184
|
+
const normalizedDir = win324.resolve(dir).replace(/[\\/]+$/, "").toLowerCase();
|
|
23491
24185
|
const windowsRoots = [process.env.SystemRoot, process.env.windir, "C:\\Windows"];
|
|
23492
24186
|
return windowsRoots.some((root) => {
|
|
23493
24187
|
if (!root)
|
|
23494
24188
|
return false;
|
|
23495
|
-
return normalizedDir ===
|
|
24189
|
+
return normalizedDir === win324.resolve(root, "System32").replace(/[\\/]+$/, "").toLowerCase();
|
|
23496
24190
|
});
|
|
23497
24191
|
}
|
|
23498
24192
|
function directoryContainsLibrary(dir, libName) {
|
|
@@ -23508,10 +24202,10 @@ function directoryContainsLibrary(dir, libName) {
|
|
|
23508
24202
|
}
|
|
23509
24203
|
}
|
|
23510
24204
|
function resolveCachedOnnxRuntimeDir(ortVersionDir, libName) {
|
|
23511
|
-
if (existsSync11(
|
|
24205
|
+
if (existsSync11(join17(ortVersionDir, libName)))
|
|
23512
24206
|
return ortVersionDir;
|
|
23513
|
-
const libSubdir =
|
|
23514
|
-
if (existsSync11(
|
|
24207
|
+
const libSubdir = join17(ortVersionDir, "lib");
|
|
24208
|
+
if (existsSync11(join17(libSubdir, libName)))
|
|
23515
24209
|
return libSubdir;
|
|
23516
24210
|
return ortVersionDir;
|
|
23517
24211
|
}
|
|
@@ -23526,12 +24220,12 @@ function findSystemOnnxRuntime(libName, searchPathsOverride) {
|
|
|
23526
24220
|
} else if (process.platform === "win32") {
|
|
23527
24221
|
const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
|
|
23528
24222
|
const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
|
|
23529
|
-
searchPaths.push(
|
|
24223
|
+
searchPaths.push(join17(programFiles, "onnxruntime", "lib"), join17(programFiles, "Microsoft ONNX Runtime", "lib"), join17(programFiles, "Microsoft Machine Learning", "lib"), join17(programFilesX86, "onnxruntime", "lib"), ...(() => {
|
|
23530
24224
|
const nugetPaths = [];
|
|
23531
24225
|
const userProfile = process.env.USERPROFILE ?? "";
|
|
23532
24226
|
if (!userProfile)
|
|
23533
24227
|
return nugetPaths;
|
|
23534
|
-
const nugetPackageDir =
|
|
24228
|
+
const nugetPackageDir = join17(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
|
|
23535
24229
|
if (!existsSync11(nugetPackageDir))
|
|
23536
24230
|
return nugetPaths;
|
|
23537
24231
|
try {
|
|
@@ -23540,7 +24234,7 @@ function findSystemOnnxRuntime(libName, searchPathsOverride) {
|
|
|
23540
24234
|
continue;
|
|
23541
24235
|
if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
|
|
23542
24236
|
continue;
|
|
23543
|
-
nugetPaths.push(
|
|
24237
|
+
nugetPaths.push(join17(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join17(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
|
|
23544
24238
|
}
|
|
23545
24239
|
} catch (err) {
|
|
23546
24240
|
warn(`Failed to scan NuGet ONNX Runtime cache ${nugetPackageDir}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -23552,7 +24246,7 @@ function findSystemOnnxRuntime(libName, searchPathsOverride) {
|
|
|
23552
24246
|
const normalizeCase = process.platform === "win32" || process.platform === "darwin";
|
|
23553
24247
|
const seen = new Set;
|
|
23554
24248
|
const uniquePaths = searchPaths.filter((p) => {
|
|
23555
|
-
let key =
|
|
24249
|
+
let key = resolve12(p).replace(/[/\\]+$/, "");
|
|
23556
24250
|
if (normalizeCase)
|
|
23557
24251
|
key = key.toLowerCase();
|
|
23558
24252
|
if (seen.has(key))
|
|
@@ -23562,7 +24256,7 @@ function findSystemOnnxRuntime(libName, searchPathsOverride) {
|
|
|
23562
24256
|
});
|
|
23563
24257
|
const unknownVersionPaths = [];
|
|
23564
24258
|
for (const dir of uniquePaths) {
|
|
23565
|
-
const libPath =
|
|
24259
|
+
const libPath = join17(dir, libName);
|
|
23566
24260
|
if (process.platform === "win32") {
|
|
23567
24261
|
if (!directoryContainsLibrary(dir, libName))
|
|
23568
24262
|
continue;
|
|
@@ -23641,19 +24335,19 @@ function validateExtractedTree(stagingRoot) {
|
|
|
23641
24335
|
const walk = (dir) => {
|
|
23642
24336
|
const entries = readdirSync4(dir);
|
|
23643
24337
|
for (const entry of entries) {
|
|
23644
|
-
const fullPath =
|
|
24338
|
+
const fullPath = join17(dir, entry);
|
|
23645
24339
|
const lst = lstatSync3(fullPath);
|
|
23646
24340
|
if (lst.isSymbolicLink()) {
|
|
23647
24341
|
const linkTarget = readlinkSync2(fullPath);
|
|
23648
|
-
const resolvedTarget =
|
|
23649
|
-
const rel =
|
|
23650
|
-
if (relativePathEscapesRoot(rel) ||
|
|
24342
|
+
const resolvedTarget = resolve12(dirname11(fullPath), linkTarget);
|
|
24343
|
+
const rel = relative4(realRoot, resolvedTarget);
|
|
24344
|
+
if (relativePathEscapesRoot(rel) || win324.isAbsolute(rel)) {
|
|
23651
24345
|
throw new Error(`extracted symlink ${fullPath} points outside staging root: ${linkTarget}`);
|
|
23652
24346
|
}
|
|
23653
24347
|
continue;
|
|
23654
24348
|
}
|
|
23655
|
-
const rel =
|
|
23656
|
-
if (relativePathEscapesRoot(rel) ||
|
|
24349
|
+
const rel = relative4(realRoot, fullPath);
|
|
24350
|
+
if (relativePathEscapesRoot(rel) || win324.isAbsolute(rel)) {
|
|
23657
24351
|
throw new Error(`extracted entry ${fullPath} escapes staging root`);
|
|
23658
24352
|
}
|
|
23659
24353
|
if (lst.isDirectory()) {
|
|
@@ -23678,11 +24372,11 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
23678
24372
|
const url = `https://github.com/${ORT_REPO}/releases/download/v${ORT_VERSION}/${info.assetName}.${info.archiveType === "tgz" ? "tgz" : "zip"}`;
|
|
23679
24373
|
log(`Downloading ONNX Runtime v${ORT_VERSION} for ${process.platform}/${process.arch}...`);
|
|
23680
24374
|
const tmpDir = `${targetDir}.tmp.${process.pid}.${Date.now().toString(36)}${randomBytes3(4).toString("hex")}`;
|
|
23681
|
-
const extractionRoot =
|
|
23682
|
-
const stagedInstallDir =
|
|
24375
|
+
const extractionRoot = join17(tmpDir, "extract");
|
|
24376
|
+
const stagedInstallDir = join17(tmpDir, "install");
|
|
23683
24377
|
try {
|
|
23684
24378
|
privateMkdirSync(extractionRoot);
|
|
23685
|
-
const archivePath =
|
|
24379
|
+
const archivePath = join17(tmpDir, `onnxruntime.${info.archiveType}`);
|
|
23686
24380
|
await downloadFileWithCap(url, archivePath);
|
|
23687
24381
|
const archiveSha256 = await sha256File(archivePath);
|
|
23688
24382
|
log(`ONNX Runtime archive sha256=${archiveSha256}`);
|
|
@@ -23695,7 +24389,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
23695
24389
|
unlinkSync5(archivePath);
|
|
23696
24390
|
} catch {}
|
|
23697
24391
|
validateExtractedTree(extractionRoot);
|
|
23698
|
-
const extractedDir =
|
|
24392
|
+
const extractedDir = join17(extractionRoot, info.assetName, "lib");
|
|
23699
24393
|
if (!existsSync11(extractedDir)) {
|
|
23700
24394
|
throw new Error(`Expected directory not found: ${extractedDir}`);
|
|
23701
24395
|
}
|
|
@@ -23703,7 +24397,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
23703
24397
|
const realFiles = [];
|
|
23704
24398
|
const symlinks = [];
|
|
23705
24399
|
for (const libFile of libFiles) {
|
|
23706
|
-
const src =
|
|
24400
|
+
const src = join17(extractedDir, libFile);
|
|
23707
24401
|
try {
|
|
23708
24402
|
const stat = lstatSync3(src);
|
|
23709
24403
|
log(`ORT extract: ${libFile} — isSymlink=${stat.isSymbolicLink()}, isFile=${stat.isFile()}, size=${stat.size}`);
|
|
@@ -23718,14 +24412,14 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
23718
24412
|
}
|
|
23719
24413
|
}
|
|
23720
24414
|
copyOnnxLibraries(info, extractedDir, stagedInstallDir, realFiles, symlinks);
|
|
23721
|
-
const libPath =
|
|
24415
|
+
const libPath = join17(stagedInstallDir, info.libName);
|
|
23722
24416
|
const libHash = await sha256File(libPath);
|
|
23723
24417
|
if (libHash !== info.librarySha256) {
|
|
23724
24418
|
throw new Error(`onnx runtime library hash mismatch at ${libPath}: sha256 ${libHash}, ` + `expected the pinned ${info.librarySha256} for ${info.assetName}`);
|
|
23725
24419
|
}
|
|
23726
24420
|
writeOnnxInstalledMeta(stagedInstallDir, ORT_VERSION, libHash, archiveSha256);
|
|
23727
24421
|
publishOnnxRuntime(stagedInstallDir, targetDir);
|
|
23728
|
-
writeStampedFileDigest(
|
|
24422
|
+
writeStampedFileDigest(join17(targetDir, info.libName), libHash);
|
|
23729
24423
|
rmSync4(tmpDir, { recursive: true, force: true });
|
|
23730
24424
|
log(`ONNX Runtime v${ORT_VERSION} installed to ${targetDir}`);
|
|
23731
24425
|
return targetDir;
|
|
@@ -23767,8 +24461,8 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
23767
24461
|
const requiredLibs = new Set([info.libName]);
|
|
23768
24462
|
privateMkdirSync(targetDir);
|
|
23769
24463
|
for (const libFile of realFiles) {
|
|
23770
|
-
const src =
|
|
23771
|
-
const dst =
|
|
24464
|
+
const src = join17(extractedDir, libFile);
|
|
24465
|
+
const dst = join17(targetDir, libFile);
|
|
23772
24466
|
try {
|
|
23773
24467
|
if (copyFile === copyFileSync4)
|
|
23774
24468
|
privateCopyFileSync(src, dst);
|
|
@@ -23787,12 +24481,12 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
23787
24481
|
}
|
|
23788
24482
|
const targetRoot = realpathSync7(targetDir);
|
|
23789
24483
|
for (const link of symlinks) {
|
|
23790
|
-
const dst =
|
|
24484
|
+
const dst = join17(targetDir, link.name);
|
|
23791
24485
|
try {
|
|
23792
24486
|
unlinkSync5(dst);
|
|
23793
24487
|
} catch {}
|
|
23794
|
-
const dstForContainment =
|
|
23795
|
-
const resolvedTarget =
|
|
24488
|
+
const dstForContainment = join17(targetRoot, link.name);
|
|
24489
|
+
const resolvedTarget = resolve12(dirname11(dstForContainment), link.target);
|
|
23796
24490
|
if (!isPathInsideRoot(targetRoot, resolvedTarget)) {
|
|
23797
24491
|
const message = `ONNX Runtime symlink ${link.name} points outside install dir: ${link.target}`;
|
|
23798
24492
|
if (requiredLibs.has(link.name)) {
|
|
@@ -23812,7 +24506,7 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
23812
24506
|
log(`ORT extract: failed to symlink optional ${link.name}: ${symlinkErr}`);
|
|
23813
24507
|
}
|
|
23814
24508
|
}
|
|
23815
|
-
const requiredPath =
|
|
24509
|
+
const requiredPath = join17(targetDir, info.libName);
|
|
23816
24510
|
if (!existsSync11(requiredPath)) {
|
|
23817
24511
|
rmSync4(targetDir, { recursive: true, force: true });
|
|
23818
24512
|
throw new Error(`Required ONNX Runtime library missing after install: ${requiredPath}`);
|
|
@@ -23840,7 +24534,7 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
|
|
|
23840
24534
|
...sha256 ? { sha256 } : {},
|
|
23841
24535
|
archiveSha256
|
|
23842
24536
|
};
|
|
23843
|
-
writeFileSync6(
|
|
24537
|
+
writeFileSync6(join17(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), {
|
|
23844
24538
|
encoding: "utf8",
|
|
23845
24539
|
mode: PRIVATE_FILE_MODE
|
|
23846
24540
|
});
|
|
@@ -23849,7 +24543,7 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
|
|
|
23849
24543
|
}
|
|
23850
24544
|
}
|
|
23851
24545
|
function readOnnxInstalledMeta(installDir) {
|
|
23852
|
-
const path =
|
|
24546
|
+
const path = join17(installDir, ONNX_INSTALLED_META_FILE);
|
|
23853
24547
|
try {
|
|
23854
24548
|
if (!statSync10(path).isFile())
|
|
23855
24549
|
return null;
|
|
@@ -25705,7 +26399,7 @@ function isBgCompletion(value) {
|
|
|
25705
26399
|
function formatCompletion(completion) {
|
|
25706
26400
|
const status = formatStatus(completion);
|
|
25707
26401
|
const duration = formatDuration(completion);
|
|
25708
|
-
const header = `- task ${completion.task_id} (${status}${duration ? `, ${duration}` : ""})`;
|
|
26402
|
+
const header = formatUnknownPtyExit(completion.task_id, completion) ?? `- task ${completion.task_id} (${status}${duration ? `, ${duration}` : ""})`;
|
|
25709
26403
|
const previewBlock = formatOutputPreview(completion);
|
|
25710
26404
|
const descendantWarning = completion.live_descendants_summary ? ` ${completion.live_descendants_summary}` : "";
|
|
25711
26405
|
const captureWarning = completion.output_incomplete || completion.status === "failed" && completion.status_reason ? ` [${completion.status_reason || "PTY output may be incomplete"}]` : "";
|
|
@@ -25772,9 +26466,9 @@ import {
|
|
|
25772
26466
|
// package.json
|
|
25773
26467
|
var package_default = {
|
|
25774
26468
|
name: "@cortexkit/aft-pi",
|
|
25775
|
-
version: "0.
|
|
26469
|
+
version: "0.65.0",
|
|
25776
26470
|
type: "module",
|
|
25777
|
-
description: "Pi coding agent extension for Agent
|
|
26471
|
+
description: "Pi coding agent extension for Agent Foundational Toolkit (AFT) — tree-sitter and LSP-powered code analysis",
|
|
25778
26472
|
main: "dist/index.js",
|
|
25779
26473
|
types: "dist/index.d.ts",
|
|
25780
26474
|
license: "MIT",
|
|
@@ -25796,18 +26490,18 @@ var package_default = {
|
|
|
25796
26490
|
"test:e2e": "bun test src/__tests__/e2e/"
|
|
25797
26491
|
},
|
|
25798
26492
|
dependencies: {
|
|
25799
|
-
"@cortexkit/aft-bridge": "0.
|
|
26493
|
+
"@cortexkit/aft-bridge": "0.65.0",
|
|
25800
26494
|
"comment-json": "^5.0.0",
|
|
25801
26495
|
diff: "^8.0.4",
|
|
25802
26496
|
zod: "^4.4.3"
|
|
25803
26497
|
},
|
|
25804
26498
|
optionalDependencies: {
|
|
25805
|
-
"@cortexkit/aft-darwin-arm64": "0.
|
|
25806
|
-
"@cortexkit/aft-darwin-x64": "0.
|
|
25807
|
-
"@cortexkit/aft-linux-arm64": "0.
|
|
25808
|
-
"@cortexkit/aft-linux-x64": "0.
|
|
25809
|
-
"@cortexkit/aft-win32-arm64": "0.
|
|
25810
|
-
"@cortexkit/aft-win32-x64": "0.
|
|
26499
|
+
"@cortexkit/aft-darwin-arm64": "0.65.0",
|
|
26500
|
+
"@cortexkit/aft-darwin-x64": "0.65.0",
|
|
26501
|
+
"@cortexkit/aft-linux-arm64": "0.65.0",
|
|
26502
|
+
"@cortexkit/aft-linux-x64": "0.65.0",
|
|
26503
|
+
"@cortexkit/aft-win32-arm64": "0.65.0",
|
|
26504
|
+
"@cortexkit/aft-win32-x64": "0.65.0"
|
|
25811
26505
|
},
|
|
25812
26506
|
devDependencies: {
|
|
25813
26507
|
"@earendil-works/pi-coding-agent": "^0.80.2",
|
|
@@ -26010,11 +26704,11 @@ function coerceAftStatus(response) {
|
|
|
26010
26704
|
warm_entries: readNumber(symbolCache.warm_entries)
|
|
26011
26705
|
},
|
|
26012
26706
|
storage_dir: readNullableString(response.storage_dir),
|
|
26013
|
-
checkpoints_total:
|
|
26707
|
+
checkpoints_total: readOptionalNumber(response.checkpoints_total),
|
|
26014
26708
|
session: {
|
|
26015
26709
|
id: readString(session.id, "__default__"),
|
|
26016
26710
|
tracked_files: readNumber(session.tracked_files),
|
|
26017
|
-
checkpoints:
|
|
26711
|
+
checkpoints: readOptionalNumber(session.checkpoints)
|
|
26018
26712
|
},
|
|
26019
26713
|
compression: readCompression(response.compression),
|
|
26020
26714
|
status_bar: readStatusBar(response.status_bar ?? response.status_bar_values)
|
|
@@ -26100,7 +26794,7 @@ import { Type } from "typebox";
|
|
|
26100
26794
|
// src/config.ts
|
|
26101
26795
|
import { existsSync as existsSync12, readFileSync as readFileSync11 } from "node:fs";
|
|
26102
26796
|
import { homedir as homedir14 } from "node:os";
|
|
26103
|
-
import { isAbsolute as
|
|
26797
|
+
import { isAbsolute as isAbsolute8 } from "node:path";
|
|
26104
26798
|
var import_comment_json = __toESM(require_src2(), 1);
|
|
26105
26799
|
|
|
26106
26800
|
// ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/core/core.js
|
|
@@ -30966,9 +31660,9 @@ var ConfigureWarningsDeliveryEnum = _enum(["toast", "log", "chat"]);
|
|
|
30966
31660
|
var IndexKindSchema = _enum(["search", "semantic", "callgraph"]);
|
|
30967
31661
|
function isSupportedAbsoluteIndexPath(path) {
|
|
30968
31662
|
if (path === "~" || path.startsWith("~/") || path.startsWith("~\\")) {
|
|
30969
|
-
return
|
|
31663
|
+
return isAbsolute8(homedir14());
|
|
30970
31664
|
}
|
|
30971
|
-
return
|
|
31665
|
+
return isAbsolute8(path);
|
|
30972
31666
|
}
|
|
30973
31667
|
var IndexRootSchema = object({
|
|
30974
31668
|
path: string2().refine(isSupportedAbsoluteIndexPath, {
|
|
@@ -31025,6 +31719,7 @@ var LspServerEntrySchema = object({
|
|
|
31025
31719
|
initialization_options: unknown().optional()
|
|
31026
31720
|
});
|
|
31027
31721
|
var LspConfigSchema = object({
|
|
31722
|
+
max_servers: number2().int().nonnegative().optional(),
|
|
31028
31723
|
idle_minutes: union([
|
|
31029
31724
|
number2().int().transform((value) => Math.min(1440, Math.max(5, value))),
|
|
31030
31725
|
literal("never")
|
|
@@ -31108,7 +31803,7 @@ var SubcConfigSchema = object({
|
|
|
31108
31803
|
connection_file: string2().optional()
|
|
31109
31804
|
});
|
|
31110
31805
|
var GhShimConfigSchema = object({
|
|
31111
|
-
binary_path: string2().trim().refine(
|
|
31806
|
+
binary_path: string2().trim().refine(isAbsolute8, "gh_shim.binary_path must be absolute").optional()
|
|
31112
31807
|
});
|
|
31113
31808
|
var RemoteExecConfigSchema = object({
|
|
31114
31809
|
enabled: boolean2().optional(),
|
|
@@ -31159,13 +31854,6 @@ var IdleConfigSchema = object({
|
|
|
31159
31854
|
root_ttl_minutes: number2().int().optional().transform((value) => value === undefined ? undefined : clampIdleRootTtlMinutes(value)),
|
|
31160
31855
|
checkout_hours: number2().int().optional().transform((value) => value === undefined ? undefined : clampIdleCheckoutHours(value))
|
|
31161
31856
|
});
|
|
31162
|
-
var ViewsConfigSchema = object({
|
|
31163
|
-
enabled: boolean2().optional(),
|
|
31164
|
-
callgraph_copies: number2().int().optional()
|
|
31165
|
-
});
|
|
31166
|
-
var WorktreeConfigSchema = object({
|
|
31167
|
-
ram_overlay: boolean2().optional()
|
|
31168
|
-
});
|
|
31169
31857
|
var BackupConfigSchema = object({
|
|
31170
31858
|
enabled: boolean2().optional(),
|
|
31171
31859
|
max_depth: number2().int().positive().optional(),
|
|
@@ -31186,12 +31874,10 @@ var AftConfigFieldsSchema = object({
|
|
|
31186
31874
|
indexes: IndexesConfigSchema.optional(),
|
|
31187
31875
|
index: IndexConfigSchema.optional(),
|
|
31188
31876
|
storage: object({ cache_dir: string2().nullable().optional() }).optional(),
|
|
31189
|
-
views: ViewsConfigSchema.optional(),
|
|
31190
31877
|
callgraph_chunk_size: number2().optional(),
|
|
31191
31878
|
inspect: InspectConfigSchema.optional(),
|
|
31192
31879
|
idle: IdleConfigSchema.optional(),
|
|
31193
31880
|
backup: BackupConfigSchema.optional(),
|
|
31194
|
-
worktree: WorktreeConfigSchema.optional(),
|
|
31195
31881
|
sandbox: SandboxConfigSchema.optional(),
|
|
31196
31882
|
bash: BashConfigSchema.optional(),
|
|
31197
31883
|
experimental: ExperimentalConfigSchema.optional(),
|
|
@@ -31347,6 +32033,9 @@ function loadConfigFromPath(configPath, tier) {
|
|
|
31347
32033
|
throw new ConfigRejectedError(["invalid_config_document"], configPath);
|
|
31348
32034
|
}
|
|
31349
32035
|
const removed = removedConfigKeyErrors(cleanConfig, undefined, false);
|
|
32036
|
+
if (tier === "user") {
|
|
32037
|
+
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`))));
|
|
32038
|
+
}
|
|
31350
32039
|
if (removed.length) {
|
|
31351
32040
|
throw new ConfigRejectedError(removed);
|
|
31352
32041
|
}
|
|
@@ -31373,14 +32062,7 @@ function loadConfigFromPath(configPath, tier) {
|
|
|
31373
32062
|
if (translation.legacyInput) {
|
|
31374
32063
|
log2(`Config ${configPath} uses retired keys (${translation.retiredKeys.join(", ")}); applied their current equivalents in memory`);
|
|
31375
32064
|
}
|
|
31376
|
-
|
|
31377
|
-
configLoadNotices.push({
|
|
31378
|
-
configPath,
|
|
31379
|
-
digest: removedConfigKeysNoticeDigest(translation),
|
|
31380
|
-
message: removedConfigKeysNoticeMessage(configPath, translation)
|
|
31381
|
-
});
|
|
31382
|
-
}
|
|
31383
|
-
} else if (translation.legacyInput || translation.removedKeys.length > 0) {
|
|
32065
|
+
} else if (translation.legacyInput) {
|
|
31384
32066
|
configLoadNotices.push({
|
|
31385
32067
|
configPath,
|
|
31386
32068
|
digest: noticeDigest(projection),
|
|
@@ -31465,6 +32147,9 @@ function mergeSemanticConfig(base, override) {
|
|
|
31465
32147
|
}
|
|
31466
32148
|
function mergeLspConfig(base, override) {
|
|
31467
32149
|
const projectSafe = {};
|
|
32150
|
+
if (override?.max_servers !== undefined && override.max_servers <= (base?.max_servers ?? 8)) {
|
|
32151
|
+
projectSafe.max_servers = override.max_servers;
|
|
32152
|
+
}
|
|
31468
32153
|
if (override?.python !== undefined)
|
|
31469
32154
|
projectSafe.python = override.python;
|
|
31470
32155
|
if (override?.diagnostics_on_edit !== undefined) {
|
|
@@ -31485,15 +32170,6 @@ function mergeLspConfig(base, override) {
|
|
|
31485
32170
|
return;
|
|
31486
32171
|
return Object.fromEntries(Object.entries(lsp).filter(([, v]) => v !== undefined));
|
|
31487
32172
|
}
|
|
31488
|
-
function mergeWorktreeConfig(baseWorktree, overrideWorktree) {
|
|
31489
|
-
if (baseWorktree === undefined && overrideWorktree === undefined)
|
|
31490
|
-
return;
|
|
31491
|
-
if (overrideWorktree === undefined)
|
|
31492
|
-
return baseWorktree;
|
|
31493
|
-
if (baseWorktree === undefined)
|
|
31494
|
-
return overrideWorktree;
|
|
31495
|
-
return { ...baseWorktree, ...overrideWorktree };
|
|
31496
|
-
}
|
|
31497
32173
|
function mergeIdleConfig(baseIdle, overrideIdle) {
|
|
31498
32174
|
const merged = {
|
|
31499
32175
|
root_ttl_minutes: overrideIdle?.root_ttl_minutes ?? baseIdle?.root_ttl_minutes,
|
|
@@ -31609,11 +32285,9 @@ var PROJECT_SAFE_TOP_LEVEL_FIELDS = new Set([
|
|
|
31609
32285
|
"revision_reads",
|
|
31610
32286
|
"validate_on_edit",
|
|
31611
32287
|
"configure_warnings_delivery",
|
|
31612
|
-
"views",
|
|
31613
32288
|
"callgraph_chunk_size",
|
|
31614
32289
|
"inspect",
|
|
31615
32290
|
"idle",
|
|
31616
|
-
"worktree",
|
|
31617
32291
|
"git",
|
|
31618
32292
|
"pi",
|
|
31619
32293
|
"experimental",
|
|
@@ -31728,22 +32402,18 @@ function mergeConfigs(base, override) {
|
|
|
31728
32402
|
bash.project_env = projectEnv;
|
|
31729
32403
|
}
|
|
31730
32404
|
const inspect = mergeInspectConfig(base.inspect, override.inspect);
|
|
31731
|
-
const worktree = mergeWorktreeConfig(base.worktree, override.worktree);
|
|
31732
32405
|
const idle = mergeIdleConfig(base.idle, override.idle);
|
|
31733
32406
|
const sandbox = mergeSandboxConfig(base.sandbox, override.sandbox);
|
|
31734
32407
|
const remoteExec = mergeRemoteExecConfig(base.remote_exec, override.remote_exec);
|
|
31735
32408
|
const backup = mergeProjectBackupConfig(base.backup, override.backup);
|
|
31736
32409
|
const pi = mergePiConfig(base.pi, override.pi);
|
|
31737
|
-
const views = base.views !== undefined || override.views !== undefined ? { ...base.views, ...override.views } : undefined;
|
|
31738
32410
|
const bridge = base.bridge;
|
|
31739
32411
|
const safeOverride = pickProjectSafeFields(override);
|
|
31740
32412
|
delete safeOverride.indexes;
|
|
31741
32413
|
delete safeOverride.bash;
|
|
31742
32414
|
delete safeOverride.inspect;
|
|
31743
|
-
delete safeOverride.worktree;
|
|
31744
32415
|
delete safeOverride.idle;
|
|
31745
32416
|
delete safeOverride.pi;
|
|
31746
|
-
delete safeOverride.views;
|
|
31747
32417
|
return {
|
|
31748
32418
|
...base,
|
|
31749
32419
|
...safeOverride,
|
|
@@ -31752,13 +32422,11 @@ function mergeConfigs(base, override) {
|
|
|
31752
32422
|
...lsp ? { lsp } : {},
|
|
31753
32423
|
...bash !== undefined ? { bash } : {},
|
|
31754
32424
|
...inspect !== undefined ? { inspect } : {},
|
|
31755
|
-
...worktree !== undefined ? { worktree } : {},
|
|
31756
32425
|
...idle !== undefined ? { idle } : {},
|
|
31757
32426
|
...sandbox !== undefined ? { sandbox } : {},
|
|
31758
32427
|
...remoteExec !== undefined ? { remote_exec: remoteExec } : {},
|
|
31759
32428
|
...backup !== undefined ? { backup } : {},
|
|
31760
32429
|
...pi !== undefined ? { pi } : {},
|
|
31761
|
-
...views !== undefined ? { views } : {},
|
|
31762
32430
|
experimental,
|
|
31763
32431
|
semantic,
|
|
31764
32432
|
search,
|
|
@@ -32076,7 +32744,7 @@ function detectPiHarness(api) {
|
|
|
32076
32744
|
// src/omp-approval.ts
|
|
32077
32745
|
import { realpathSync as realpathSync8 } from "node:fs";
|
|
32078
32746
|
import { homedir as homedir15 } from "node:os";
|
|
32079
|
-
import { basename as basename4, dirname as dirname12, isAbsolute as
|
|
32747
|
+
import { basename as basename4, dirname as dirname12, isAbsolute as isAbsolute9, join as join18, relative as relative5, resolve as resolve13, sep as sep2 } from "node:path";
|
|
32080
32748
|
var OMP_TOOL_TIERS = {
|
|
32081
32749
|
read: "read",
|
|
32082
32750
|
grep: "read",
|
|
@@ -32121,7 +32789,7 @@ function expandPath(value) {
|
|
|
32121
32789
|
if (decoded === "~")
|
|
32122
32790
|
return homedir15();
|
|
32123
32791
|
if (decoded.startsWith("~/") || decoded.startsWith(`~${sep2}`))
|
|
32124
|
-
return
|
|
32792
|
+
return resolve13(homedir15(), decoded.slice(2));
|
|
32125
32793
|
return decoded;
|
|
32126
32794
|
}
|
|
32127
32795
|
function realLocation(path) {
|
|
@@ -32129,7 +32797,7 @@ function realLocation(path) {
|
|
|
32129
32797
|
let current = path;
|
|
32130
32798
|
for (;; ) {
|
|
32131
32799
|
try {
|
|
32132
|
-
return missing.length > 0 ?
|
|
32800
|
+
return missing.length > 0 ? join18(realpathSync8(current), ...missing) : realpathSync8(current);
|
|
32133
32801
|
} catch (error) {
|
|
32134
32802
|
if (error.code !== "ENOENT")
|
|
32135
32803
|
throw error;
|
|
@@ -32149,11 +32817,11 @@ function namesOutsidePath(root, value) {
|
|
|
32149
32817
|
const expanded = expandPath(value);
|
|
32150
32818
|
if (expanded.startsWith("file:"))
|
|
32151
32819
|
return false;
|
|
32152
|
-
const absolute =
|
|
32153
|
-
if (relativePathEscapesRoot(
|
|
32820
|
+
const absolute = isAbsolute9(expanded) ? expanded : resolve13(root, expanded);
|
|
32821
|
+
if (relativePathEscapesRoot(relative5(root, absolute)))
|
|
32154
32822
|
return true;
|
|
32155
32823
|
try {
|
|
32156
|
-
return relativePathEscapesRoot(
|
|
32824
|
+
return relativePathEscapesRoot(relative5(realLocation(root), realLocation(absolute)));
|
|
32157
32825
|
} catch {
|
|
32158
32826
|
return true;
|
|
32159
32827
|
}
|
|
@@ -32724,8 +33392,8 @@ function renderInner(s, error, theme, innerWidth) {
|
|
|
32724
33392
|
left2.push(kv("symbol cache", `${formatCountShort(s.symbol_cache.local_entries)} local · ${formatCountShort(s.symbol_cache.warm_entries)} warm`, theme));
|
|
32725
33393
|
right2.push(theme.fg("muted", "Current session"));
|
|
32726
33394
|
right2.push(kv("tracked files", String(s.session.tracked_files), theme));
|
|
32727
|
-
right2.push(kv("checkpoints",
|
|
32728
|
-
right2.push(kv("all-session",
|
|
33395
|
+
right2.push(kv("checkpoints", s.session.checkpoints?.toString() ?? "—", theme));
|
|
33396
|
+
right2.push(kv("all-session", s.checkpoints_total?.toString() ?? "—", theme));
|
|
32729
33397
|
for (const line of renderColumns(left2, right2, colWidth))
|
|
32730
33398
|
lines.push(line);
|
|
32731
33399
|
lines.push("");
|
|
@@ -32888,7 +33556,7 @@ function registerStatusCommand(pi, ctx) {
|
|
|
32888
33556
|
|
|
32889
33557
|
// src/lsp-auto-install.ts
|
|
32890
33558
|
import { existsSync as existsSync15, mkdirSync as mkdirSync7, renameSync as renameSync10, rmSync as rmSync7, statSync as statSync12, writeFileSync as writeFileSync9 } from "node:fs";
|
|
32891
|
-
import { join as
|
|
33559
|
+
import { join as join21 } from "node:path";
|
|
32892
33560
|
|
|
32893
33561
|
// src/lsp-cache.ts
|
|
32894
33562
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
@@ -32903,7 +33571,7 @@ import {
|
|
|
32903
33571
|
unlinkSync as unlinkSync6,
|
|
32904
33572
|
writeFileSync as writeFileSync8
|
|
32905
33573
|
} from "node:fs";
|
|
32906
|
-
import { join as
|
|
33574
|
+
import { join as join19 } from "node:path";
|
|
32907
33575
|
|
|
32908
33576
|
// src/atomic-file.ts
|
|
32909
33577
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
@@ -32926,18 +33594,18 @@ function lspCacheRoot() {
|
|
|
32926
33594
|
return getAftLspPackagesDir();
|
|
32927
33595
|
}
|
|
32928
33596
|
function lspPackageDir(npmPackage) {
|
|
32929
|
-
return
|
|
33597
|
+
return join19(lspCacheRoot(), encodeURIComponent(npmPackage));
|
|
32930
33598
|
}
|
|
32931
33599
|
function lspBinaryPath(npmPackage, binary) {
|
|
32932
|
-
return
|
|
33600
|
+
return join19(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
|
|
32933
33601
|
}
|
|
32934
33602
|
function lspBinDir(npmPackage) {
|
|
32935
|
-
return
|
|
33603
|
+
return join19(lspPackageDir(npmPackage), "node_modules", ".bin");
|
|
32936
33604
|
}
|
|
32937
33605
|
function isInstalled(npmPackage, binary) {
|
|
32938
33606
|
for (const candidate of lspBinaryCandidates(binary)) {
|
|
32939
33607
|
try {
|
|
32940
|
-
if (statSync11(
|
|
33608
|
+
if (statSync11(join19(lspBinDir(npmPackage), candidate)).isFile())
|
|
32941
33609
|
return true;
|
|
32942
33610
|
} catch {}
|
|
32943
33611
|
}
|
|
@@ -32957,13 +33625,13 @@ function writeInstalledMetaIn(installDir, version, sha256) {
|
|
|
32957
33625
|
installedAt: new Date().toISOString(),
|
|
32958
33626
|
...sha256 ? { sha256 } : {}
|
|
32959
33627
|
};
|
|
32960
|
-
writeAtomicFile(
|
|
33628
|
+
writeAtomicFile(join19(installDir, INSTALLED_META_FILE), JSON.stringify(meta));
|
|
32961
33629
|
} catch (err) {
|
|
32962
33630
|
log2(`[lsp-cache] failed to write installed-meta in ${installDir}: ${err}`);
|
|
32963
33631
|
}
|
|
32964
33632
|
}
|
|
32965
33633
|
function readInstalledMetaIn(installDir) {
|
|
32966
|
-
const path =
|
|
33634
|
+
const path = join19(installDir, INSTALLED_META_FILE);
|
|
32967
33635
|
try {
|
|
32968
33636
|
if (!statSync11(path).isFile())
|
|
32969
33637
|
return null;
|
|
@@ -32987,7 +33655,7 @@ function readInstalledMeta(packageKey) {
|
|
|
32987
33655
|
return readInstalledMetaIn(lspPackageDir(packageKey));
|
|
32988
33656
|
}
|
|
32989
33657
|
function lockPath(npmPackage) {
|
|
32990
|
-
return
|
|
33658
|
+
return join19(lspPackageDir(npmPackage), ".aft-installing");
|
|
32991
33659
|
}
|
|
32992
33660
|
var STALE_LOCK_MS2 = 30 * 60 * 1000;
|
|
32993
33661
|
function acquireInstallLock(lockKey) {
|
|
@@ -33118,7 +33786,7 @@ var AUTO_INSTALL_STAMP_FILE = "last-lsp-autoinstall.json";
|
|
|
33118
33786
|
var AUTO_INSTALL_WINDOW_MS = 60 * 1000;
|
|
33119
33787
|
var AUTO_INSTALL_LOCK_STALE_MS = 30 * 60 * 1000;
|
|
33120
33788
|
function autoInstallStampPath() {
|
|
33121
|
-
return
|
|
33789
|
+
return join19(aftCacheBase(), AUTO_INSTALL_STAMP_FILE);
|
|
33122
33790
|
}
|
|
33123
33791
|
function hasRecentAutoInstallStamp(path) {
|
|
33124
33792
|
try {
|
|
@@ -33219,7 +33887,7 @@ function claimLspAutoInstallPass() {
|
|
|
33219
33887
|
}
|
|
33220
33888
|
var VERSION_CHECK_FILE = ".aft-version-check";
|
|
33221
33889
|
function readVersionCheck(npmPackage) {
|
|
33222
|
-
const file =
|
|
33890
|
+
const file = join19(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
|
|
33223
33891
|
try {
|
|
33224
33892
|
const raw = readFileSync12(file, "utf8");
|
|
33225
33893
|
const parsed = JSON.parse(raw);
|
|
@@ -33236,7 +33904,7 @@ function readVersionCheck(npmPackage) {
|
|
|
33236
33904
|
}
|
|
33237
33905
|
function writeVersionCheck(npmPackage, latest) {
|
|
33238
33906
|
mkdirSync6(lspPackageDir(npmPackage), { recursive: true });
|
|
33239
|
-
const file =
|
|
33907
|
+
const file = join19(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
|
|
33240
33908
|
const record = {
|
|
33241
33909
|
last_checked: new Date().toISOString(),
|
|
33242
33910
|
latest_eligible: latest
|
|
@@ -33353,7 +34021,7 @@ function isVersionSupported(spec, version) {
|
|
|
33353
34021
|
|
|
33354
34022
|
// src/lsp-project-relevance.ts
|
|
33355
34023
|
import { existsSync as existsSync14, readdirSync as readdirSync5, readFileSync as readFileSync13 } from "node:fs";
|
|
33356
|
-
import { join as
|
|
34024
|
+
import { join as join20 } from "node:path";
|
|
33357
34025
|
var MAX_WALK_DIRS = 200;
|
|
33358
34026
|
var MAX_WALK_DEPTH = 4;
|
|
33359
34027
|
var NOISE_DIRS = new Set([
|
|
@@ -33370,7 +34038,7 @@ function hasRootMarker(projectRoot, rootMarkers) {
|
|
|
33370
34038
|
if (!rootMarkers)
|
|
33371
34039
|
return false;
|
|
33372
34040
|
for (const marker of rootMarkers) {
|
|
33373
|
-
if (existsSync14(
|
|
34041
|
+
if (existsSync14(join20(projectRoot, marker)))
|
|
33374
34042
|
return true;
|
|
33375
34043
|
}
|
|
33376
34044
|
return false;
|
|
@@ -33394,7 +34062,7 @@ function hasPackageJsonDep(projectRoot, depNames) {
|
|
|
33394
34062
|
}
|
|
33395
34063
|
function readPackageJson(projectRoot) {
|
|
33396
34064
|
try {
|
|
33397
|
-
const raw = readFileSync13(
|
|
34065
|
+
const raw = readFileSync13(join20(projectRoot, "package.json"), "utf8");
|
|
33398
34066
|
const parsed = JSON.parse(raw);
|
|
33399
34067
|
if (typeof parsed !== "object" || parsed === null)
|
|
33400
34068
|
return null;
|
|
@@ -33424,7 +34092,7 @@ function relevantExtensionsInProject(projectRoot, extToServer) {
|
|
|
33424
34092
|
for (const entry of entries) {
|
|
33425
34093
|
if (entry.isDirectory()) {
|
|
33426
34094
|
if (current.depth < MAX_WALK_DEPTH && !NOISE_DIRS.has(entry.name.toLowerCase())) {
|
|
33427
|
-
queue.push({ dir:
|
|
34095
|
+
queue.push({ dir: join20(current.dir, entry.name), depth: current.depth + 1 });
|
|
33428
34096
|
}
|
|
33429
34097
|
continue;
|
|
33430
34098
|
}
|
|
@@ -33557,7 +34225,7 @@ async function resolveTargetVersion(spec, config, fetchImpl = fetch) {
|
|
|
33557
34225
|
}
|
|
33558
34226
|
function ensureInstallAnchor(cwd) {
|
|
33559
34227
|
try {
|
|
33560
|
-
const stub =
|
|
34228
|
+
const stub = join21(cwd, "package.json");
|
|
33561
34229
|
if (!existsSync15(stub)) {
|
|
33562
34230
|
writeFileSync9(stub, `${JSON.stringify({ name: "aft-lsp-cache", version: "0.0.0", private: true })}
|
|
33563
34231
|
`);
|
|
@@ -33784,10 +34452,10 @@ function sha256OfFileSync(path) {
|
|
|
33784
34452
|
}
|
|
33785
34453
|
function quarantineCachedNpmInstall(spec, reason) {
|
|
33786
34454
|
const packageDir = lspPackageDir(spec.npm);
|
|
33787
|
-
const dest =
|
|
34455
|
+
const dest = join21(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
|
|
33788
34456
|
warn2(`[lsp] tofu_mismatch ${spec.npm}: ${reason}; quarantining ${packageDir} -> ${dest}`);
|
|
33789
34457
|
try {
|
|
33790
|
-
mkdirSync7(
|
|
34458
|
+
mkdirSync7(join21(dest, ".."), { recursive: true });
|
|
33791
34459
|
rmSync7(dest, { recursive: true, force: true });
|
|
33792
34460
|
renameSync10(packageDir, dest);
|
|
33793
34461
|
} catch (err) {
|
|
@@ -34522,7 +35190,7 @@ import { Type as Type4 } from "typebox";
|
|
|
34522
35190
|
// src/tools/hoisted.ts
|
|
34523
35191
|
import { stat as stat4 } from "node:fs/promises";
|
|
34524
35192
|
import { homedir as homedir16 } from "node:os";
|
|
34525
|
-
import { isAbsolute as
|
|
35193
|
+
import { isAbsolute as isAbsolute10, relative as relative6, resolve as resolve14, sep as sep3 } from "node:path";
|
|
34526
35194
|
import {
|
|
34527
35195
|
renderDiff as renderDiff2
|
|
34528
35196
|
} from "@earendil-works/pi-coding-agent";
|
|
@@ -34700,7 +35368,7 @@ function modelSupportsImages(extCtx) {
|
|
|
34700
35368
|
}
|
|
34701
35369
|
var NON_VISION_IMAGE_NOTE = "[Current model does not support images. The image will be omitted from this request.]";
|
|
34702
35370
|
function containsPath(parent, child) {
|
|
34703
|
-
const rel =
|
|
35371
|
+
const rel = relative6(parent, child);
|
|
34704
35372
|
return !relativePathEscapesRoot(rel);
|
|
34705
35373
|
}
|
|
34706
35374
|
function normalizePathInput(path) {
|
|
@@ -34710,13 +35378,13 @@ function normalizePathInput(path) {
|
|
|
34710
35378
|
if (decoded === "~")
|
|
34711
35379
|
return homedir16();
|
|
34712
35380
|
if (decoded.startsWith(`~${sep3}`) || decoded.startsWith("~/")) {
|
|
34713
|
-
return
|
|
35381
|
+
return resolve14(homedir16(), decoded.slice(2));
|
|
34714
35382
|
}
|
|
34715
35383
|
return decoded;
|
|
34716
35384
|
}
|
|
34717
35385
|
function absoluteSearchPath(cwd, target) {
|
|
34718
35386
|
const expanded = normalizePathInput(target);
|
|
34719
|
-
return
|
|
35387
|
+
return isAbsolute10(expanded) ? expanded : resolve14(cwd, expanded);
|
|
34720
35388
|
}
|
|
34721
35389
|
async function searchPathExists(cwd, target) {
|
|
34722
35390
|
try {
|
|
@@ -34772,7 +35440,7 @@ async function assertExternalDirectoryPermission(extCtx, target, options = {}) {
|
|
|
34772
35440
|
if (!target)
|
|
34773
35441
|
return;
|
|
34774
35442
|
const expanded = normalizePathInput(target);
|
|
34775
|
-
const absoluteTarget =
|
|
35443
|
+
const absoluteTarget = isAbsolute10(expanded) ? expanded : resolve14(extCtx.cwd, expanded);
|
|
34776
35444
|
if (containsPath(extCtx.cwd, absoluteTarget))
|
|
34777
35445
|
return;
|
|
34778
35446
|
if (options.restrictToProjectRoot === false)
|
|
@@ -34781,7 +35449,7 @@ async function assertExternalDirectoryPermission(extCtx, target, options = {}) {
|
|
|
34781
35449
|
}
|
|
34782
35450
|
async function assertExternalReadPermission(ctx, extCtx, target, restrictToProjectRoot = ctx.config.restrict_to_project_root ?? false) {
|
|
34783
35451
|
const expanded = normalizePathInput(target);
|
|
34784
|
-
const absoluteTarget =
|
|
35452
|
+
const absoluteTarget = isAbsolute10(expanded) ? expanded : resolve14(extCtx.cwd, expanded);
|
|
34785
35453
|
if (!restrictToProjectRoot || containsPath(extCtx.cwd, absoluteTarget))
|
|
34786
35454
|
return;
|
|
34787
35455
|
try {
|
|
@@ -36187,6 +36855,7 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
36187
36855
|
}
|
|
36188
36856
|
}
|
|
36189
36857
|
const bridgeCommand = spawnContext.command;
|
|
36858
|
+
const workdir = spawnContext.cwd ?? params.workdir;
|
|
36190
36859
|
let streamed = "";
|
|
36191
36860
|
let usedHostFallback = false;
|
|
36192
36861
|
let response;
|
|
@@ -36194,7 +36863,7 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
36194
36863
|
response = await withOutsidePermissionOperation(() => callBashWithPermissionLoop(bridge, {
|
|
36195
36864
|
command: bridgeCommand,
|
|
36196
36865
|
timeout,
|
|
36197
|
-
workdir
|
|
36866
|
+
workdir,
|
|
36198
36867
|
env: spawnContext.env,
|
|
36199
36868
|
description: params.description,
|
|
36200
36869
|
background: effectiveBackground,
|
|
@@ -36286,7 +36955,7 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
36286
36955
|
task_id: taskId
|
|
36287
36956
|
};
|
|
36288
36957
|
const output = response.output ?? "";
|
|
36289
|
-
return bashResult(usedHostFallback || isPowerShell ? output : withBashHints(output, bridgeCommand, aftSearchRegistered, extCtx.cwd), details);
|
|
36958
|
+
return bashResult(usedHostFallback || isPowerShell ? output : withBashHints(output, bridgeCommand, aftSearchRegistered, extCtx.cwd, workdir), details);
|
|
36290
36959
|
},
|
|
36291
36960
|
renderCall(args, theme, context) {
|
|
36292
36961
|
return renderBashCall(asString2(args?.command), asString2(args?.description), theme, context);
|
|
@@ -36314,8 +36983,8 @@ function registerBashCompanionTools(pi, ctx, enabled = { bashStatus: true, bashW
|
|
|
36314
36983
|
pi.registerTool(createBashKillTool(ctx));
|
|
36315
36984
|
}
|
|
36316
36985
|
}
|
|
36317
|
-
function withBashHints(output, command, aftSearchRegistered, projectRoot) {
|
|
36318
|
-
return maybeAppendGrepSearchHint(maybeAppendConflictsHint(output), command, aftSearchRegistered, projectRoot);
|
|
36986
|
+
function withBashHints(output, command, aftSearchRegistered, projectRoot, workdir) {
|
|
36987
|
+
return maybeAppendGrepSearchHint(maybeAppendConflictsHint(output), command, aftSearchRegistered, projectRoot, undefined, workdir);
|
|
36319
36988
|
}
|
|
36320
36989
|
function createBashStatusTool(ctx) {
|
|
36321
36990
|
return {
|
|
@@ -36816,7 +37485,7 @@ function formatWaitSummary(taskId, waited, details, watchRole) {
|
|
|
36816
37485
|
async function formatBashStatus(extCtx, taskId, details, requestedOutputMode, watchRole) {
|
|
36817
37486
|
const exit = typeof details.exit_code === "number" ? ` (exit ${details.exit_code})` : "";
|
|
36818
37487
|
const dur = typeof details.duration_ms === "number" ? ` ${Math.round(details.duration_ms / 1000)}s` : "";
|
|
36819
|
-
let text = `Task ${taskId}: ${details.status}${exit}${dur}`;
|
|
37488
|
+
let text = formatUnknownPtyExit(taskId, details) ?? `Task ${taskId}: ${details.status}${exit}${dur}`;
|
|
36820
37489
|
if (details.live_descendants_summary) {
|
|
36821
37490
|
text += ` · ${details.live_descendants_summary}`;
|
|
36822
37491
|
}
|
|
@@ -37122,7 +37791,7 @@ function registerFsTools(pi, ctx, surface) {
|
|
|
37122
37791
|
recursive: coerceBoolean(params.recursive)
|
|
37123
37792
|
}, extCtx);
|
|
37124
37793
|
if (response.success === false) {
|
|
37125
|
-
throw
|
|
37794
|
+
throw toolErrorFromResponse("delete", response);
|
|
37126
37795
|
}
|
|
37127
37796
|
const deletedEntries = response.deleted ?? [];
|
|
37128
37797
|
const skipped = response.skipped_files ?? [];
|
|
@@ -38398,7 +39067,7 @@ function registerSafetyTool(pi, ctx) {
|
|
|
38398
39067
|
|
|
38399
39068
|
// src/tools/semantic.ts
|
|
38400
39069
|
import { homedir as homedir17 } from "node:os";
|
|
38401
|
-
import { isAbsolute as
|
|
39070
|
+
import { isAbsolute as isAbsolute11, resolve as resolve15 } from "node:path";
|
|
38402
39071
|
import { Type as Type13 } from "typebox";
|
|
38403
39072
|
var FILESYSTEM_SCAN_STATUS = "answered by a filesystem scan";
|
|
38404
39073
|
function semanticHonestyNote(response, theme) {
|
|
@@ -38421,8 +39090,8 @@ function selectedProjectRoot(cwd, pathArg) {
|
|
|
38421
39090
|
const target = pathArg?.trim();
|
|
38422
39091
|
if (!target)
|
|
38423
39092
|
return canonicalizeProjectRoot(cwd);
|
|
38424
|
-
const expanded = target === "~" ? homedir17() : /^~[/\\]/u.test(target) ?
|
|
38425
|
-
return canonicalizeProjectRoot(
|
|
39093
|
+
const expanded = target === "~" ? homedir17() : /^~[/\\]/u.test(target) ? resolve15(homedir17(), target.slice(2)) : target;
|
|
39094
|
+
return canonicalizeProjectRoot(isAbsolute11(expanded) ? expanded : resolve15(cwd, expanded));
|
|
38426
39095
|
}
|
|
38427
39096
|
function continuityKey(projectRoot, query, includeTests, topK) {
|
|
38428
39097
|
return JSON.stringify([
|
|
@@ -39019,93 +39688,52 @@ function registerShutdownCleanup(fn) {
|
|
|
39019
39688
|
}
|
|
39020
39689
|
|
|
39021
39690
|
// src/workflow-hints.ts
|
|
39022
|
-
var HEADING = "
|
|
39691
|
+
var HEADING = "# Agent Foundational Toolkit";
|
|
39023
39692
|
function hashlineTagSourceHint(bashRewritesMintTags, isRegistered = () => true) {
|
|
39024
39693
|
return `**Hashline edit tags**: ${hashlineTagSourceSentence(bashRewritesMintTags, isRegistered)}`;
|
|
39025
39694
|
}
|
|
39026
39695
|
var HASHLINE_TAG_SOURCE_HINT = hashlineTagSourceHint(true);
|
|
39027
39696
|
function buildWorkflowHints(opts) {
|
|
39028
|
-
const
|
|
39029
|
-
const
|
|
39030
|
-
const
|
|
39031
|
-
const
|
|
39032
|
-
|
|
39033
|
-
|
|
39034
|
-
const hasRead = !opts.absentTools.has(readName);
|
|
39035
|
-
const hasGrep = !opts.absentTools.has(grepName);
|
|
39036
|
-
const hasSearch = !opts.absentTools.has("aft_search");
|
|
39037
|
-
const hasNavigate = !opts.absentTools.has("aft_callgraph");
|
|
39038
|
-
const hasInspect = !opts.absentTools.has("aft_inspect");
|
|
39039
|
-
const hasBash = !opts.absentTools.has(bashName);
|
|
39040
|
-
const hasBgBash = opts.bashBackgroundEnabled && hasBash && !opts.absentTools.has("bash_status");
|
|
39041
|
-
const hasWatch = !opts.absentTools.has("bash_watch");
|
|
39042
|
-
const hasWrite = !opts.absentTools.has("bash_write");
|
|
39043
|
-
if (hasBash && opts.bashCompressionEnabled) {
|
|
39044
|
-
sections.push([
|
|
39045
|
-
"**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:",
|
|
39046
|
-
"- `bun test | grep fail` → run `bun test`",
|
|
39047
|
-
"- `cargo test 2>&1 | tail -20` → run `cargo test`",
|
|
39048
|
-
"- `npm run build | head -50` → run `npm run build`"
|
|
39049
|
-
].join(`
|
|
39050
|
-
`));
|
|
39697
|
+
const has = (name) => !opts.absentTools.has(name);
|
|
39698
|
+
const hasBash = has("bash");
|
|
39699
|
+
const hasBackground = hasBash && opts.bashBackgroundEnabled && has("bash_watch") && has("bash_status");
|
|
39700
|
+
const finding = [];
|
|
39701
|
+
if (has("aft_search")) {
|
|
39702
|
+
finding.push("start with aft_search; it takes concepts, identifiers, regex and literals.");
|
|
39051
39703
|
}
|
|
39052
|
-
if (
|
|
39053
|
-
|
|
39054
|
-
}
|
|
39055
|
-
if (hasOutline && (hasGrep || hasSearch) && (hasZoom || hasRead)) {
|
|
39056
|
-
const searchName = hasSearch ? "aft_search" : grepName;
|
|
39057
|
-
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.`;
|
|
39058
|
-
const zoomSteer = hasZoom ? ", or `aft_zoom`" : "";
|
|
39059
|
-
const searchSteer = hasSearch ? `use \`aft_search\` (concepts, identifiers, regex, literals), \`${readName}\`, \`aft_outline\`${zoomSteer} instead` : `use the \`${grepName}\` tool, \`${readName}\`, \`aft_outline\`${zoomSteer} instead`;
|
|
39060
|
-
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}.` : "";
|
|
39061
|
-
sections.push([
|
|
39062
|
-
`**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:`,
|
|
39063
|
-
`- \`grep -rn "handleAuth" src/\` in bash → \`${searchName}({ query: "handleAuth" })\``,
|
|
39064
|
-
`- \`find . -name "*.ts" | xargs grep watcher\` in bash → \`${searchName}({ query: "watcher invalidation" })\` (concepts work too)`,
|
|
39065
|
-
`- \`sed -n '100,160p' app.ts\` / \`cat app.ts\` in bash → \`${readName}({ path: "app.ts", startLine: 100, endLine: 160 })\``
|
|
39066
|
-
].join(`
|
|
39067
|
-
`));
|
|
39704
|
+
if (has("aft_outline") && has("aft_zoom") && has("read")) {
|
|
39705
|
+
finding.push(`${finding.length ? "Then " : ""}aft_outline for structure, aft_zoom for named symbols, read for line ranges.`);
|
|
39068
39706
|
}
|
|
39069
|
-
if (
|
|
39070
|
-
|
|
39071
|
-
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.");
|
|
39072
|
-
}
|
|
39073
|
-
if (hasNavigate) {
|
|
39074
|
-
sections.push([
|
|
39075
|
-
"Use `aft_callgraph` for code-relationship questions instead of grep + read chains:",
|
|
39076
|
-
"- `callers` — find all call sites before changing a function signature",
|
|
39077
|
-
"- `impact` — blast radius (which functions/files will need updates)",
|
|
39078
|
-
"- `trace_to` — how execution reaches this code; each path runs back to a root labelled main, test, attribute, public API, or no caller found",
|
|
39079
|
-
"- `trace_to_symbol` — shortest call path from one symbol to another",
|
|
39080
|
-
"- `trace_data` — follow a value through assignments and parameters across files"
|
|
39081
|
-
].join(`
|
|
39082
|
-
`));
|
|
39083
|
-
}
|
|
39084
|
-
if (hasBgBash && hasWatch) {
|
|
39085
|
-
sections.push([
|
|
39086
|
-
`**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.`,
|
|
39087
|
-
"- `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.",
|
|
39088
|
-
"- `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."
|
|
39089
|
-
].join(`
|
|
39090
|
-
`));
|
|
39707
|
+
if (hasBash) {
|
|
39708
|
+
finding.push("Don't find or read code with grep, find, sed or cat in bash.");
|
|
39091
39709
|
}
|
|
39092
|
-
|
|
39093
|
-
|
|
39710
|
+
const commands = [];
|
|
39711
|
+
if (hasBash && opts.bashCompressionEnabled) {
|
|
39712
|
+
commands.push("don't pipe test or build output into tail, grep or head; AFT already shortens it.");
|
|
39094
39713
|
}
|
|
39095
|
-
if (
|
|
39096
|
-
|
|
39714
|
+
if (hasBackground) {
|
|
39715
|
+
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.");
|
|
39097
39716
|
}
|
|
39098
|
-
|
|
39717
|
+
const sections = [
|
|
39718
|
+
finding.length ? `**Finding code**: ${finding.join(" ")}` : "",
|
|
39719
|
+
has("aft_callgraph") ? "**Relationships**: aft_callgraph for callers, impact, and execution or data-flow traces." : "",
|
|
39720
|
+
has("aft_outline") && has("aft_zoom") ? "**Web pages**: aft_outline with a URL as target, then aft_zoom on a heading." : "",
|
|
39721
|
+
"",
|
|
39722
|
+
has("aft_inspect") ? "**After edits**: run aft_inspect for diagnostics; the project's typecheck and tests are the final check." : "",
|
|
39723
|
+
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." : "",
|
|
39724
|
+
commands.length ? `**Commands**: ${commands.join(" ")}` : ""
|
|
39725
|
+
];
|
|
39726
|
+
const hashline = opts.hashlineEffective === true ? hashlineTagSourceHint(hasBash && opts.bashRewriteEnabled !== false, has) : "";
|
|
39727
|
+
if (!sections.some(Boolean) && !hashline)
|
|
39099
39728
|
return null;
|
|
39100
|
-
|
|
39101
|
-
|
|
39102
|
-
|
|
39103
|
-
**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.`);
|
|
39104
|
-
return `${HEADING}
|
|
39105
|
-
|
|
39106
|
-
${sections.join(`
|
|
39729
|
+
sections[3] = "**Parallel calls**: send independent read-only calls in one response.";
|
|
39730
|
+
const text = `${HEADING}
|
|
39107
39731
|
|
|
39732
|
+
${sections.filter(Boolean).join(`
|
|
39108
39733
|
`)}`;
|
|
39734
|
+
return hashline ? `${text}
|
|
39735
|
+
|
|
39736
|
+
${hashline}` : text;
|
|
39109
39737
|
}
|
|
39110
39738
|
function buildHintsFromConfig(config, absentTools, hashlineEffective = false) {
|
|
39111
39739
|
const bashCfg = resolveBashConfig(config);
|
|
@@ -39216,12 +39844,12 @@ var PLUGIN_VERSION = (() => {
|
|
|
39216
39844
|
return "0.0.0";
|
|
39217
39845
|
}
|
|
39218
39846
|
})();
|
|
39219
|
-
var ANNOUNCEMENT_VERSION = "0.
|
|
39847
|
+
var ANNOUNCEMENT_VERSION = "0.65.0";
|
|
39220
39848
|
var ANNOUNCEMENT_FEATURES = [
|
|
39221
|
-
"
|
|
39222
|
-
"
|
|
39223
|
-
"
|
|
39224
|
-
"
|
|
39849
|
+
"OpenCode 2: AFT's read-only tools also work inside Code Mode as `tools.aft.code.*`.",
|
|
39850
|
+
"TypeScript monorepos run one language server per TypeScript version instead of one per package; `lsp.max_servers` caps the total.",
|
|
39851
|
+
"Search and grep stay light on large growing files, and shell waits survive the computer going to sleep.",
|
|
39852
|
+
"`views.enabled`, `views.callgraph_copies` and `worktree.ram_overlay` are now refused in user config; `npx @cortexkit/aft doctor --fix` removes them."
|
|
39225
39853
|
];
|
|
39226
39854
|
var ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/DSa65w8wuf";
|
|
39227
39855
|
var pendingEagerWarnings = new Map;
|