@cortexkit/aft-pi 0.39.0 → 0.39.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config.d.ts +17 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +710 -445
- package/dist/tools/_shared.d.ts +1 -17
- package/dist/tools/_shared.d.ts.map +1 -1
- package/dist/tools/ast.d.ts +3 -3
- package/dist/tools/bash.d.ts +12 -0
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/hoisted.d.ts +5 -5
- package/dist/tools/hoisted.d.ts.map +1 -1
- package/dist/tools/reading.d.ts.map +1 -1
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -7728,10 +7728,10 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
7728
7728
|
replacer = null;
|
|
7729
7729
|
indent = EMPTY;
|
|
7730
7730
|
};
|
|
7731
|
-
var
|
|
7731
|
+
var join10 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(one)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two)), gap) : EMPTY;
|
|
7732
7732
|
var join_content = (inside, value, gap) => {
|
|
7733
7733
|
const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
|
|
7734
|
-
return
|
|
7734
|
+
return join10(comment, inside, gap);
|
|
7735
7735
|
};
|
|
7736
7736
|
var stringify_string = (holder, key, value) => {
|
|
7737
7737
|
const raw = get_raw_string_literal(holder, key);
|
|
@@ -7753,13 +7753,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
7753
7753
|
if (i !== 0) {
|
|
7754
7754
|
inside += COMMA;
|
|
7755
7755
|
}
|
|
7756
|
-
const before =
|
|
7756
|
+
const before = join10(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
|
|
7757
7757
|
inside += before || LF + deeper_gap;
|
|
7758
7758
|
inside += stringify(i, value, deeper_gap) || STR_NULL;
|
|
7759
7759
|
inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
|
|
7760
7760
|
after_comma = process_comments(value, AFTER(i), deeper_gap);
|
|
7761
7761
|
}
|
|
7762
|
-
inside +=
|
|
7762
|
+
inside += join10(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
7763
7763
|
return BRACKET_OPEN + join_content(inside, value, gap) + BRACKET_CLOSE;
|
|
7764
7764
|
};
|
|
7765
7765
|
var object_stringify = (value, gap) => {
|
|
@@ -7780,13 +7780,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
7780
7780
|
inside += COMMA;
|
|
7781
7781
|
}
|
|
7782
7782
|
first = false;
|
|
7783
|
-
const before =
|
|
7783
|
+
const before = join10(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
|
|
7784
7784
|
inside += before || LF + deeper_gap;
|
|
7785
7785
|
inside += quote(key) + process_comments(value, AFTER_PROP(key), deeper_gap) + COLON + process_comments(value, AFTER_COLON(key), deeper_gap) + SPACE + sv + process_comments(value, AFTER_VALUE(key), deeper_gap);
|
|
7786
7786
|
after_comma = process_comments(value, AFTER(key), deeper_gap);
|
|
7787
7787
|
};
|
|
7788
7788
|
keys.forEach(iteratee);
|
|
7789
|
-
inside +=
|
|
7789
|
+
inside += join10(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
7790
7790
|
return CURLY_BRACKET_OPEN + join_content(inside, value, gap) + CURLY_BRACKET_CLOSE;
|
|
7791
7791
|
};
|
|
7792
7792
|
function stringify(key, holder, gap) {
|
|
@@ -11674,7 +11674,45 @@ function error(message, meta) {
|
|
|
11674
11674
|
console.error(`[aft-bridge] ERROR: ${message}`);
|
|
11675
11675
|
}
|
|
11676
11676
|
}
|
|
11677
|
+
// ../aft-bridge/dist/bash-format.js
|
|
11678
|
+
function appendPipeStripNote(output, note) {
|
|
11679
|
+
return note ? `${output}
|
|
11680
|
+
|
|
11681
|
+
${note}` : output;
|
|
11682
|
+
}
|
|
11683
|
+
function formatSeconds(ms) {
|
|
11684
|
+
return `${Number((ms / 1000).toFixed(1))}s`;
|
|
11685
|
+
}
|
|
11686
|
+
function formatForegroundResult(data) {
|
|
11687
|
+
const output = data.output_preview ?? "";
|
|
11688
|
+
const outputPath = data.output_path;
|
|
11689
|
+
const truncated = data.output_truncated === true;
|
|
11690
|
+
const status = data.status;
|
|
11691
|
+
const exit = data.exit_code;
|
|
11692
|
+
let rendered = output;
|
|
11693
|
+
if (truncated && outputPath) {
|
|
11694
|
+
rendered += `
|
|
11695
|
+
[output truncated; full output at ${outputPath}]`;
|
|
11696
|
+
}
|
|
11697
|
+
if (status === "timed_out") {
|
|
11698
|
+
rendered += `
|
|
11699
|
+
[command timed out]`;
|
|
11700
|
+
}
|
|
11701
|
+
if (typeof exit === "number" && exit !== 0) {
|
|
11702
|
+
rendered += `
|
|
11703
|
+
[exit code: ${exit}]`;
|
|
11704
|
+
}
|
|
11705
|
+
return rendered;
|
|
11706
|
+
}
|
|
11707
|
+
function isTerminalStatus(status) {
|
|
11708
|
+
return status === "completed" || status === "failed" || status === "killed" || status === "timed_out";
|
|
11709
|
+
}
|
|
11710
|
+
function sleep(ms) {
|
|
11711
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
11712
|
+
}
|
|
11677
11713
|
// ../aft-bridge/dist/bash-hints.js
|
|
11714
|
+
import * as os from "node:os";
|
|
11715
|
+
import * as path from "node:path";
|
|
11678
11716
|
var CONFLICT_HINT = `
|
|
11679
11717
|
|
|
11680
11718
|
[Hint] Use aft_conflicts to see all conflict regions across files in a single call.`;
|
|
@@ -11704,18 +11742,87 @@ function commandInvokesCodeSearch(command) {
|
|
|
11704
11742
|
}
|
|
11705
11743
|
return false;
|
|
11706
11744
|
}
|
|
11707
|
-
function maybeAppendGrepSearchHint(output, command, aftSearchRegistered) {
|
|
11745
|
+
function maybeAppendGrepSearchHint(output, command, aftSearchRegistered, projectRoot) {
|
|
11708
11746
|
if (output === "")
|
|
11709
11747
|
return output;
|
|
11710
11748
|
if (!commandInvokesCodeSearch(command))
|
|
11711
11749
|
return output;
|
|
11712
11750
|
if (output.includes(GREP_SEARCH_HINT_PREFIX))
|
|
11713
11751
|
return output;
|
|
11752
|
+
if (shouldSuppressGrepSearchHint(command, projectRoot))
|
|
11753
|
+
return output;
|
|
11714
11754
|
const hint = aftSearchRegistered ? GREP_SEARCH_AFT_SEARCH_HINT : GREP_SEARCH_GREP_HINT;
|
|
11715
11755
|
return `${output}
|
|
11716
11756
|
|
|
11717
11757
|
${hint}`;
|
|
11718
11758
|
}
|
|
11759
|
+
function shouldSuppressGrepSearchHint(command, projectRoot) {
|
|
11760
|
+
const root = projectRoot?.trim();
|
|
11761
|
+
if (!root)
|
|
11762
|
+
return false;
|
|
11763
|
+
const statements = splitTopLevelStatements(command);
|
|
11764
|
+
if (statements === null)
|
|
11765
|
+
return false;
|
|
11766
|
+
let sawCodeSearchStatement = false;
|
|
11767
|
+
for (const statement of statements) {
|
|
11768
|
+
const firstStage = firstPipelineStage(statement);
|
|
11769
|
+
if (firstStage === null)
|
|
11770
|
+
continue;
|
|
11771
|
+
const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0));
|
|
11772
|
+
if (firstToken === null)
|
|
11773
|
+
continue;
|
|
11774
|
+
if (firstToken.token !== "grep" && firstToken.token !== "rg")
|
|
11775
|
+
continue;
|
|
11776
|
+
sawCodeSearchStatement = true;
|
|
11777
|
+
const operands = collectPathOperands(firstStage, firstToken.end);
|
|
11778
|
+
if (operands.length === 0)
|
|
11779
|
+
return false;
|
|
11780
|
+
for (const operand of operands) {
|
|
11781
|
+
if (isPathInsideProject(root, operand))
|
|
11782
|
+
return false;
|
|
11783
|
+
}
|
|
11784
|
+
}
|
|
11785
|
+
return sawCodeSearchStatement;
|
|
11786
|
+
}
|
|
11787
|
+
function collectPathOperands(firstStage, startAfterCommand) {
|
|
11788
|
+
const operands = [];
|
|
11789
|
+
let index = skipSpaces(firstStage, startAfterCommand);
|
|
11790
|
+
while (index < firstStage.length) {
|
|
11791
|
+
const tokenResult = readShellToken(firstStage, index);
|
|
11792
|
+
if (tokenResult === null)
|
|
11793
|
+
break;
|
|
11794
|
+
const { token, end } = tokenResult;
|
|
11795
|
+
if (end <= index)
|
|
11796
|
+
break;
|
|
11797
|
+
index = skipSpaces(firstStage, end);
|
|
11798
|
+
if (token.startsWith("-"))
|
|
11799
|
+
continue;
|
|
11800
|
+
if (looksLikePathOperand(token))
|
|
11801
|
+
operands.push(token);
|
|
11802
|
+
}
|
|
11803
|
+
return operands;
|
|
11804
|
+
}
|
|
11805
|
+
function looksLikePathOperand(token) {
|
|
11806
|
+
return token.includes("/") || token.startsWith("~") || token.startsWith("./") || token.startsWith("../");
|
|
11807
|
+
}
|
|
11808
|
+
function expandTilde(target) {
|
|
11809
|
+
if (!target.startsWith("~"))
|
|
11810
|
+
return target;
|
|
11811
|
+
if (target === "~" || target.startsWith("~/")) {
|
|
11812
|
+
return path.join(os.homedir(), target.slice(1));
|
|
11813
|
+
}
|
|
11814
|
+
return target;
|
|
11815
|
+
}
|
|
11816
|
+
function resolvePathOperand(projectRoot, operand) {
|
|
11817
|
+
const expanded = expandTilde(operand);
|
|
11818
|
+
return path.isAbsolute(expanded) ? path.resolve(expanded) : path.resolve(projectRoot, expanded);
|
|
11819
|
+
}
|
|
11820
|
+
function isPathInsideProject(projectRoot, operand) {
|
|
11821
|
+
const root = path.resolve(projectRoot);
|
|
11822
|
+
const resolved = resolvePathOperand(root, operand);
|
|
11823
|
+
const rel = path.relative(root, resolved);
|
|
11824
|
+
return rel === "" || !rel.startsWith("..") && !path.isAbsolute(rel);
|
|
11825
|
+
}
|
|
11719
11826
|
function splitTopLevelStatements(command) {
|
|
11720
11827
|
const statements = [];
|
|
11721
11828
|
let start = 0;
|
|
@@ -11895,8 +12002,8 @@ function resolveBashKillTimeout(modelTimeout, foregroundWaitMs) {
|
|
|
11895
12002
|
}
|
|
11896
12003
|
// ../aft-bridge/dist/bridge.js
|
|
11897
12004
|
import { spawn } from "node:child_process";
|
|
11898
|
-
import { homedir } from "node:os";
|
|
11899
|
-
import { join } from "node:path";
|
|
12005
|
+
import { homedir as homedir2 } from "node:os";
|
|
12006
|
+
import { join as join2 } from "node:path";
|
|
11900
12007
|
import { StringDecoder } from "node:string_decoder";
|
|
11901
12008
|
|
|
11902
12009
|
// ../aft-bridge/dist/command-timeouts.js
|
|
@@ -11913,6 +12020,11 @@ var LONG_RUNNING_COMMAND_TIMEOUT_MS = {
|
|
|
11913
12020
|
function timeoutForCommand(command) {
|
|
11914
12021
|
return LONG_RUNNING_COMMAND_TIMEOUT_MS[command];
|
|
11915
12022
|
}
|
|
12023
|
+
var PASSIVE_COMMANDS = new Set(["status"]);
|
|
12024
|
+
var PASSIVE_COMMAND_TIMEOUT_MS = 5000;
|
|
12025
|
+
function isPassiveCommand(command) {
|
|
12026
|
+
return PASSIVE_COMMANDS.has(command);
|
|
12027
|
+
}
|
|
11916
12028
|
|
|
11917
12029
|
// ../aft-bridge/dist/status-bar.js
|
|
11918
12030
|
var STATUS_BAR_HEARTBEAT_CALLS = 15;
|
|
@@ -11985,6 +12097,11 @@ function bashTaskIdFrom(response) {
|
|
|
11985
12097
|
function tagStderrLine(line) {
|
|
11986
12098
|
return /^\[aft(-\w+)?\] /.test(line) ? line : `[aft] ${line}`;
|
|
11987
12099
|
}
|
|
12100
|
+
var BENIGN_CPUINFO_PROC_CPUINFO_PARSE_FAILURE = "failed to parse processor information from /proc/cpuinfo";
|
|
12101
|
+
function shouldSurfaceStderrLine(line) {
|
|
12102
|
+
const normalized = line.trim();
|
|
12103
|
+
return !(normalized === `Error in cpuinfo: ${BENIGN_CPUINFO_PROC_CPUINFO_PARSE_FAILURE}` || normalized === BENIGN_CPUINFO_PROC_CPUINFO_PARSE_FAILURE);
|
|
12104
|
+
}
|
|
11988
12105
|
function compareSemver(a, b) {
|
|
11989
12106
|
const [aMain, aPre] = a.split("-", 2);
|
|
11990
12107
|
const [bMain, bPre] = b.split("-", 2);
|
|
@@ -12076,6 +12193,7 @@ class BinaryBridge {
|
|
|
12076
12193
|
_restartCount = 0;
|
|
12077
12194
|
_shuttingDown = false;
|
|
12078
12195
|
timeoutMs;
|
|
12196
|
+
hangThreshold;
|
|
12079
12197
|
maxRestarts;
|
|
12080
12198
|
configured = false;
|
|
12081
12199
|
_configurePromise = null;
|
|
@@ -12100,6 +12218,7 @@ class BinaryBridge {
|
|
|
12100
12218
|
this.binaryPath = binaryPath;
|
|
12101
12219
|
this.cwd = cwd;
|
|
12102
12220
|
this.timeoutMs = options?.timeoutMs ?? DEFAULT_BRIDGE_TIMEOUT_MS;
|
|
12221
|
+
this.hangThreshold = options?.hangThreshold ?? BRIDGE_HANG_TIMEOUT_THRESHOLD;
|
|
12103
12222
|
this.maxRestarts = options?.maxRestarts ?? 3;
|
|
12104
12223
|
this.configOverrides = clampSemanticTimeout(configOverrides ?? {}, this.timeoutMs);
|
|
12105
12224
|
this.minVersion = options?.minVersion;
|
|
@@ -12217,7 +12336,9 @@ class BinaryBridge {
|
|
|
12217
12336
|
if (requestSessionId && options?.configureWarningClient !== undefined) {
|
|
12218
12337
|
this.configureWarningClients.set(requestSessionId, options.configureWarningClient);
|
|
12219
12338
|
}
|
|
12220
|
-
const
|
|
12339
|
+
const passive = isPassiveCommand(command);
|
|
12340
|
+
const resolvedTimeoutMs = options?.transportTimeoutMs ?? options?.timeoutMs ?? this.timeoutMs;
|
|
12341
|
+
const effectiveTimeoutMs = passive ? Math.min(resolvedTimeoutMs, PASSIVE_COMMAND_TIMEOUT_MS) : resolvedTimeoutMs;
|
|
12221
12342
|
const implicitTransportOptions = {
|
|
12222
12343
|
...options?.transportTimeoutMs !== undefined || options?.timeoutMs !== undefined ? { transportTimeoutMs: effectiveTimeoutMs } : {},
|
|
12223
12344
|
markConfiguredOnSuccess: false
|
|
@@ -12267,9 +12388,9 @@ class BinaryBridge {
|
|
|
12267
12388
|
}
|
|
12268
12389
|
const line = `${JSON.stringify(request)}
|
|
12269
12390
|
`;
|
|
12270
|
-
const keepBridgeOnTimeout = options?.keepBridgeOnTimeout === true;
|
|
12391
|
+
const keepBridgeOnTimeout = passive || options?.keepBridgeOnTimeout === true;
|
|
12271
12392
|
let requestSentAt = Date.now();
|
|
12272
|
-
const response = await new Promise((
|
|
12393
|
+
const response = await new Promise((resolve2, reject) => {
|
|
12273
12394
|
const timer = setTimeout(() => {
|
|
12274
12395
|
const entry = this.pending.get(id);
|
|
12275
12396
|
if (!entry)
|
|
@@ -12289,7 +12410,7 @@ class BinaryBridge {
|
|
|
12289
12410
|
const childActiveSinceRequest = this.lastChildActivityAt > requestSentAt;
|
|
12290
12411
|
const consecutiveTimeouts = this.consecutiveRequestTimeouts + 1;
|
|
12291
12412
|
this.consecutiveRequestTimeouts = consecutiveTimeouts;
|
|
12292
|
-
const keepWarm = childActiveSinceRequest || consecutiveTimeouts <
|
|
12413
|
+
const keepWarm = childActiveSinceRequest || consecutiveTimeouts < this.hangThreshold;
|
|
12293
12414
|
const restartSuffix = keepWarm ? " — bridge kept warm" : " — restarting bridge";
|
|
12294
12415
|
const timeoutMsg = `Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms${restartSuffix}`;
|
|
12295
12416
|
if (requestSessionId) {
|
|
@@ -12304,7 +12425,7 @@ class BinaryBridge {
|
|
|
12304
12425
|
entry.reject(new Error(`${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`));
|
|
12305
12426
|
this.handleTimeout(requestSessionId);
|
|
12306
12427
|
}, effectiveTimeoutMs);
|
|
12307
|
-
this.pending.set(id, { resolve, reject, timer, onProgress: options?.onProgress, command });
|
|
12428
|
+
this.pending.set(id, { resolve: resolve2, reject, timer, onProgress: options?.onProgress, command });
|
|
12308
12429
|
if (!this.process?.stdin?.writable) {
|
|
12309
12430
|
this.pending.delete(id);
|
|
12310
12431
|
clearTimeout(timer);
|
|
@@ -12402,15 +12523,15 @@ class BinaryBridge {
|
|
|
12402
12523
|
if (this.process) {
|
|
12403
12524
|
const proc = this.process;
|
|
12404
12525
|
this.process = null;
|
|
12405
|
-
return new Promise((
|
|
12526
|
+
return new Promise((resolve2) => {
|
|
12406
12527
|
const forceKillTimer = setTimeout(() => {
|
|
12407
12528
|
proc.kill("SIGKILL");
|
|
12408
|
-
|
|
12529
|
+
resolve2();
|
|
12409
12530
|
}, 5000);
|
|
12410
12531
|
proc.once("exit", () => {
|
|
12411
12532
|
clearTimeout(forceKillTimer);
|
|
12412
12533
|
this.logVia("Process exited during shutdown");
|
|
12413
|
-
|
|
12534
|
+
resolve2();
|
|
12414
12535
|
});
|
|
12415
12536
|
proc.kill("SIGTERM");
|
|
12416
12537
|
});
|
|
@@ -12455,15 +12576,15 @@ class BinaryBridge {
|
|
|
12455
12576
|
return;
|
|
12456
12577
|
const proc = this.process;
|
|
12457
12578
|
this.process = null;
|
|
12458
|
-
await new Promise((
|
|
12579
|
+
await new Promise((resolve2) => {
|
|
12459
12580
|
const forceKillTimer = setTimeout(() => {
|
|
12460
12581
|
proc.kill("SIGKILL");
|
|
12461
|
-
|
|
12582
|
+
resolve2();
|
|
12462
12583
|
}, 5000);
|
|
12463
12584
|
proc.once("exit", () => {
|
|
12464
12585
|
clearTimeout(forceKillTimer);
|
|
12465
12586
|
this.logVia("Process exited during coordinated binary replacement");
|
|
12466
|
-
|
|
12587
|
+
resolve2();
|
|
12467
12588
|
});
|
|
12468
12589
|
proc.kill("SIGTERM");
|
|
12469
12590
|
});
|
|
@@ -12490,7 +12611,7 @@ class BinaryBridge {
|
|
|
12490
12611
|
})();
|
|
12491
12612
|
const useFastembedBackend = semanticBackend === undefined || semanticBackend === "fastembed" || semanticBackend === "";
|
|
12492
12613
|
const ortDir = typeof this.configOverrides._ort_dylib_dir === "string" && useFastembedBackend ? this.configOverrides._ort_dylib_dir : null;
|
|
12493
|
-
const ortLibraryPath = ortDir == null ? null :
|
|
12614
|
+
const ortLibraryPath = ortDir == null ? null : join2(ortDir, process.platform === "win32" ? "onnxruntime.dll" : process.platform === "darwin" ? "libonnxruntime.dylib" : "libonnxruntime.so");
|
|
12494
12615
|
const envPath = process.platform === "win32" && ortDir ? `${ortDir};${process.env.PATH ?? ""}` : process.env.PATH;
|
|
12495
12616
|
const env = {
|
|
12496
12617
|
...process.env,
|
|
@@ -12498,7 +12619,7 @@ class BinaryBridge {
|
|
|
12498
12619
|
};
|
|
12499
12620
|
this.logVia(`bridge.spawnProcess: useFastembedBackend=${useFastembedBackend}, ` + `parentORT=${process.env.ORT_DYLIB_PATH ?? "(unset)"}, ` + `ortLibraryPath=${ortLibraryPath ?? "(none)"}`);
|
|
12500
12621
|
if (useFastembedBackend) {
|
|
12501
|
-
env.FASTEMBED_CACHE_DIR = process.env.FASTEMBED_CACHE_DIR || (typeof this.configOverrides.storage_dir === "string" ?
|
|
12622
|
+
env.FASTEMBED_CACHE_DIR = process.env.FASTEMBED_CACHE_DIR || (typeof this.configOverrides.storage_dir === "string" ? join2(this.configOverrides.storage_dir, "semantic", "models") : join2(homedir2() || "", ".cache", "fastembed"));
|
|
12502
12623
|
if (process.env.ORT_DYLIB_PATH) {
|
|
12503
12624
|
this.logVia(`ORT_DYLIB_PATH inherited from parent env: ${process.env.ORT_DYLIB_PATH}`);
|
|
12504
12625
|
} else if (ortLibraryPath) {
|
|
@@ -12584,7 +12705,7 @@ class BinaryBridge {
|
|
|
12584
12705
|
`)) !== -1) {
|
|
12585
12706
|
const line = this.stderrBuffer.slice(0, newlineIdx).replace(/\r$/, "");
|
|
12586
12707
|
this.stderrBuffer = this.stderrBuffer.slice(newlineIdx + 1);
|
|
12587
|
-
if (!line)
|
|
12708
|
+
if (!line || !shouldSurfaceStderrLine(line))
|
|
12588
12709
|
continue;
|
|
12589
12710
|
const tagged = tagStderrLine(line);
|
|
12590
12711
|
this.logVia(tagged);
|
|
@@ -12594,7 +12715,7 @@ class BinaryBridge {
|
|
|
12594
12715
|
flushStderrBuffer() {
|
|
12595
12716
|
const line = this.stderrBuffer.replace(/\r$/, "");
|
|
12596
12717
|
this.stderrBuffer = "";
|
|
12597
|
-
if (!line)
|
|
12718
|
+
if (!line || !shouldSurfaceStderrLine(line))
|
|
12598
12719
|
return;
|
|
12599
12720
|
const tagged = tagStderrLine(line);
|
|
12600
12721
|
this.logVia(tagged);
|
|
@@ -12840,12 +12961,37 @@ function coerceStringArray(value) {
|
|
|
12840
12961
|
}
|
|
12841
12962
|
return [];
|
|
12842
12963
|
}
|
|
12964
|
+
function coerceOptionalInt(v, paramName, min, max) {
|
|
12965
|
+
if (v === undefined || v === null || v === "")
|
|
12966
|
+
return;
|
|
12967
|
+
if (typeof v === "number" && (!Number.isFinite(v) || v === 0 && min > 0))
|
|
12968
|
+
return;
|
|
12969
|
+
const n = typeof v === "string" ? Number(v) : v;
|
|
12970
|
+
if (typeof n !== "number" || !Number.isInteger(n)) {
|
|
12971
|
+
throw new Error(`${paramName} must be an integer between ${min} and ${max}`);
|
|
12972
|
+
}
|
|
12973
|
+
if (n < min || n > max) {
|
|
12974
|
+
throw new Error(`${paramName} must be between ${min} and ${max}`);
|
|
12975
|
+
}
|
|
12976
|
+
return n;
|
|
12977
|
+
}
|
|
12978
|
+
function isEmptyParam(value) {
|
|
12979
|
+
if (value === undefined || value === null)
|
|
12980
|
+
return true;
|
|
12981
|
+
if (typeof value === "string")
|
|
12982
|
+
return value.length === 0;
|
|
12983
|
+
if (Array.isArray(value))
|
|
12984
|
+
return value.length === 0;
|
|
12985
|
+
if (typeof value === "object")
|
|
12986
|
+
return Object.keys(value).length === 0;
|
|
12987
|
+
return false;
|
|
12988
|
+
}
|
|
12843
12989
|
// ../aft-bridge/dist/downloader.js
|
|
12844
12990
|
import { spawnSync } from "node:child_process";
|
|
12845
12991
|
import { createHash, randomUUID } from "node:crypto";
|
|
12846
12992
|
import { chmodSync, closeSync, copyFileSync, createWriteStream, existsSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, unlinkSync, writeSync } from "node:fs";
|
|
12847
|
-
import { homedir as
|
|
12848
|
-
import { join as
|
|
12993
|
+
import { homedir as homedir3 } from "node:os";
|
|
12994
|
+
import { join as join3 } from "node:path";
|
|
12849
12995
|
import { Readable } from "node:stream";
|
|
12850
12996
|
import { pipeline } from "node:stream/promises";
|
|
12851
12997
|
|
|
@@ -12902,11 +13048,11 @@ function isExpectedCachedBinary(binaryPath, tag) {
|
|
|
12902
13048
|
function getCacheDir() {
|
|
12903
13049
|
if (process.platform === "win32") {
|
|
12904
13050
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
12905
|
-
const base2 = localAppData ||
|
|
12906
|
-
return
|
|
13051
|
+
const base2 = localAppData || join3(homedir3(), "AppData", "Local");
|
|
13052
|
+
return join3(base2, "aft", "bin");
|
|
12907
13053
|
}
|
|
12908
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
12909
|
-
return
|
|
13054
|
+
const base = process.env.XDG_CACHE_HOME || join3(homedir3(), ".cache");
|
|
13055
|
+
return join3(base, "aft", "bin");
|
|
12910
13056
|
}
|
|
12911
13057
|
function getBinaryName() {
|
|
12912
13058
|
return process.platform === "win32" ? "aft.exe" : "aft";
|
|
@@ -12914,7 +13060,7 @@ function getBinaryName() {
|
|
|
12914
13060
|
function getCachedBinaryPath(version) {
|
|
12915
13061
|
if (!version)
|
|
12916
13062
|
return null;
|
|
12917
|
-
const binaryPath =
|
|
13063
|
+
const binaryPath = join3(getCacheDir(), version, getBinaryName());
|
|
12918
13064
|
return existsSync(binaryPath) ? binaryPath : null;
|
|
12919
13065
|
}
|
|
12920
13066
|
async function downloadBinary(version) {
|
|
@@ -12931,16 +13077,16 @@ async function downloadBinary(version) {
|
|
|
12931
13077
|
return null;
|
|
12932
13078
|
}
|
|
12933
13079
|
const tag = rawTag.startsWith("v") ? rawTag : `v${rawTag}`;
|
|
12934
|
-
const versionedCacheDir =
|
|
13080
|
+
const versionedCacheDir = join3(getCacheDir(), tag);
|
|
12935
13081
|
const binaryName = getBinaryName();
|
|
12936
|
-
const binaryPath =
|
|
13082
|
+
const binaryPath = join3(versionedCacheDir, binaryName);
|
|
12937
13083
|
if (existsSync(binaryPath) && isExpectedCachedBinary(binaryPath, tag)) {
|
|
12938
13084
|
return binaryPath;
|
|
12939
13085
|
}
|
|
12940
13086
|
const downloadUrl = `https://github.com/${REPO}/releases/download/${tag}/${assetName}`;
|
|
12941
13087
|
const checksumUrl = `https://github.com/${REPO}/releases/download/${tag}/checksums.sha256`;
|
|
12942
13088
|
log(`Downloading AFT binary (${tag}) for ${platformKey}...`);
|
|
12943
|
-
const lockPath =
|
|
13089
|
+
const lockPath = join3(versionedCacheDir, ".download.lock");
|
|
12944
13090
|
let releaseLock = null;
|
|
12945
13091
|
let binaryController = null;
|
|
12946
13092
|
let checksumController = null;
|
|
@@ -13092,7 +13238,7 @@ async function acquireDownloadLock(lockPath) {
|
|
|
13092
13238
|
if (Date.now() - startedAt > DOWNLOAD_LOCK_TIMEOUT_MS) {
|
|
13093
13239
|
throw new Error(`Timed out waiting for download lock: ${lockPath}`);
|
|
13094
13240
|
}
|
|
13095
|
-
await new Promise((
|
|
13241
|
+
await new Promise((resolve2) => setTimeout(resolve2, 100));
|
|
13096
13242
|
}
|
|
13097
13243
|
}
|
|
13098
13244
|
}
|
|
@@ -13185,18 +13331,18 @@ function stripJsoncSymbols(value) {
|
|
|
13185
13331
|
// ../aft-bridge/dist/migration.js
|
|
13186
13332
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
13187
13333
|
import { existsSync as existsSync4, mkdirSync as mkdirSync4 } from "node:fs";
|
|
13188
|
-
import { homedir as
|
|
13189
|
-
import { dirname as dirname2, join as
|
|
13334
|
+
import { homedir as homedir5, tmpdir } from "node:os";
|
|
13335
|
+
import { dirname as dirname2, join as join6 } from "node:path";
|
|
13190
13336
|
|
|
13191
13337
|
// ../aft-bridge/dist/paths.js
|
|
13192
13338
|
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync as renameSync2, writeFileSync } from "node:fs";
|
|
13193
|
-
import { dirname, join as
|
|
13339
|
+
import { dirname, join as join4 } from "node:path";
|
|
13194
13340
|
function resolveHarnessStoragePath(storageRoot, harness, ...segments) {
|
|
13195
|
-
return
|
|
13341
|
+
return join4(storageRoot, harness, ...segments);
|
|
13196
13342
|
}
|
|
13197
13343
|
function repairRootScopedStorageFile(storageRoot, harness, fileName) {
|
|
13198
13344
|
const harnessPath = resolveHarnessStoragePath(storageRoot, harness, fileName);
|
|
13199
|
-
const rootPath =
|
|
13345
|
+
const rootPath = join4(storageRoot, fileName);
|
|
13200
13346
|
if (existsSync2(harnessPath) || !existsSync2(rootPath))
|
|
13201
13347
|
return harnessPath;
|
|
13202
13348
|
try {
|
|
@@ -13242,8 +13388,8 @@ function markAnnouncementSeen(storageRoot, harness, currentVersion) {
|
|
|
13242
13388
|
import { execSync } from "node:child_process";
|
|
13243
13389
|
import { chmodSync as chmodSync2, closeSync as closeSync2, copyFileSync as copyFileSync2, existsSync as existsSync3, mkdirSync as mkdirSync3, openSync as openSync2, readSync, renameSync as renameSync3, unlinkSync as unlinkSync2 } from "node:fs";
|
|
13244
13390
|
import { createRequire as createRequire2 } from "node:module";
|
|
13245
|
-
import { homedir as
|
|
13246
|
-
import { join as
|
|
13391
|
+
import { homedir as homedir4 } from "node:os";
|
|
13392
|
+
import { join as join5 } from "node:path";
|
|
13247
13393
|
var ensureBinaryForResolver = ensureBinary;
|
|
13248
13394
|
function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
13249
13395
|
try {
|
|
@@ -13252,9 +13398,9 @@ function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
|
13252
13398
|
return null;
|
|
13253
13399
|
const tag = version.startsWith("v") ? version : `v${version}`;
|
|
13254
13400
|
const cacheDir = getCacheDir();
|
|
13255
|
-
const versionedDir =
|
|
13401
|
+
const versionedDir = join5(cacheDir, tag);
|
|
13256
13402
|
const ext = process.platform === "win32" ? ".exe" : "";
|
|
13257
|
-
const cachedPath =
|
|
13403
|
+
const cachedPath = join5(versionedDir, `aft${ext}`);
|
|
13258
13404
|
if (existsSync3(cachedPath)) {
|
|
13259
13405
|
const cachedVersion = readBinaryVersion(cachedPath);
|
|
13260
13406
|
if (cachedVersion === version)
|
|
@@ -13284,18 +13430,18 @@ function normalizeBareVersion(version) {
|
|
|
13284
13430
|
return version.startsWith("v") ? version.slice(1) : version;
|
|
13285
13431
|
}
|
|
13286
13432
|
function homeDirFromEnv(env) {
|
|
13287
|
-
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) ||
|
|
13433
|
+
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir4();
|
|
13288
13434
|
}
|
|
13289
13435
|
function cacheDirFromEnv(env) {
|
|
13290
13436
|
if (process.platform === "win32") {
|
|
13291
|
-
const base2 = env.LOCALAPPDATA || env.APPDATA ||
|
|
13292
|
-
return
|
|
13437
|
+
const base2 = env.LOCALAPPDATA || env.APPDATA || join5(homeDirFromEnv(env), "AppData", "Local");
|
|
13438
|
+
return join5(base2, "aft", "bin");
|
|
13293
13439
|
}
|
|
13294
|
-
const base = env.XDG_CACHE_HOME ||
|
|
13295
|
-
return
|
|
13440
|
+
const base = env.XDG_CACHE_HOME || join5(homeDirFromEnv(env), ".cache");
|
|
13441
|
+
return join5(base, "aft", "bin");
|
|
13296
13442
|
}
|
|
13297
13443
|
function cachedBinaryPathFromEnv(version, env, ext) {
|
|
13298
|
-
const binaryPath =
|
|
13444
|
+
const binaryPath = join5(cacheDirFromEnv(env), version, `aft${ext}`);
|
|
13299
13445
|
return existsSync3(binaryPath) ? binaryPath : null;
|
|
13300
13446
|
}
|
|
13301
13447
|
function isExpectedCachedBinary2(binaryPath, expectedVersion) {
|
|
@@ -13414,7 +13560,7 @@ function findBinarySync(expectedVersion) {
|
|
|
13414
13560
|
return usable;
|
|
13415
13561
|
}
|
|
13416
13562
|
} catch {}
|
|
13417
|
-
const cargoPath =
|
|
13563
|
+
const cargoPath = join5(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
|
|
13418
13564
|
if (existsSync3(cargoPath)) {
|
|
13419
13565
|
const usable = probeBinaryCandidate(cargoPath, "cargo", expectedVersion);
|
|
13420
13566
|
if (usable)
|
|
@@ -13460,22 +13606,22 @@ function dataHome() {
|
|
|
13460
13606
|
if (process.env.XDG_DATA_HOME)
|
|
13461
13607
|
return process.env.XDG_DATA_HOME;
|
|
13462
13608
|
if (process.platform === "win32") {
|
|
13463
|
-
return process.env.LOCALAPPDATA || process.env.APPDATA ||
|
|
13609
|
+
return process.env.LOCALAPPDATA || process.env.APPDATA || join6(homeDir(), "AppData", "Local");
|
|
13464
13610
|
}
|
|
13465
|
-
return
|
|
13611
|
+
return join6(homeDir(), ".local", "share");
|
|
13466
13612
|
}
|
|
13467
13613
|
function homeDir() {
|
|
13468
13614
|
if (process.platform === "win32")
|
|
13469
|
-
return process.env.USERPROFILE || process.env.HOME ||
|
|
13470
|
-
return process.env.HOME ||
|
|
13615
|
+
return process.env.USERPROFILE || process.env.HOME || homedir5();
|
|
13616
|
+
return process.env.HOME || homedir5();
|
|
13471
13617
|
}
|
|
13472
13618
|
function resolveLegacyStorageRoot(harness) {
|
|
13473
13619
|
if (harness === "pi")
|
|
13474
|
-
return
|
|
13475
|
-
return
|
|
13620
|
+
return join6(homeDir(), ".pi", "agent", "aft");
|
|
13621
|
+
return join6(dataHome(), "opencode", "storage", "plugin", "aft");
|
|
13476
13622
|
}
|
|
13477
13623
|
function resolveCortexKitStorageRoot() {
|
|
13478
|
-
return
|
|
13624
|
+
return join6(dataHome(), "cortexkit", "aft");
|
|
13479
13625
|
}
|
|
13480
13626
|
function tail(value) {
|
|
13481
13627
|
if (!value)
|
|
@@ -13489,12 +13635,12 @@ function spawnErrorLabel(error2) {
|
|
|
13489
13635
|
return [code, error2.message].filter(Boolean).join(": ");
|
|
13490
13636
|
}
|
|
13491
13637
|
function migrationLogPath(newRoot, harness, logger) {
|
|
13492
|
-
const desired =
|
|
13638
|
+
const desired = join6(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
|
|
13493
13639
|
try {
|
|
13494
13640
|
mkdirSync4(dirname2(desired), { recursive: true });
|
|
13495
13641
|
return desired;
|
|
13496
13642
|
} catch (err) {
|
|
13497
|
-
const fallback =
|
|
13643
|
+
const fallback = join6(tmpdir(), `aft-migration-${harness}-${Date.now()}.jsonl`);
|
|
13498
13644
|
logger?.warn?.(`Failed to create AFT migration log directory ${dirname2(desired)}: ${err instanceof Error ? err.message : String(err)}. ` + `Using fallback log path ${fallback}.`);
|
|
13499
13645
|
return fallback;
|
|
13500
13646
|
}
|
|
@@ -13557,13 +13703,13 @@ async function ensureStorageMigrated(opts) {
|
|
|
13557
13703
|
}
|
|
13558
13704
|
// ../aft-bridge/dist/npm-resolver.js
|
|
13559
13705
|
import { readdirSync, statSync as statSync2 } from "node:fs";
|
|
13560
|
-
import { homedir as
|
|
13561
|
-
import { delimiter, dirname as dirname3, isAbsolute, join as
|
|
13706
|
+
import { homedir as homedir6 } from "node:os";
|
|
13707
|
+
import { delimiter, dirname as dirname3, isAbsolute as isAbsolute2, join as join7 } from "node:path";
|
|
13562
13708
|
function defaultDeps() {
|
|
13563
13709
|
return {
|
|
13564
13710
|
platform: process.platform,
|
|
13565
13711
|
env: process.env,
|
|
13566
|
-
home:
|
|
13712
|
+
home: homedir6(),
|
|
13567
13713
|
execPath: process.execPath
|
|
13568
13714
|
};
|
|
13569
13715
|
}
|
|
@@ -13582,16 +13728,16 @@ function npmFromPath(deps) {
|
|
|
13582
13728
|
const raw = deps.env.PATH ?? deps.env.Path ?? "";
|
|
13583
13729
|
for (const entry of raw.split(delimiter)) {
|
|
13584
13730
|
const dir = entry.trim().replace(/^"|"$/g, "");
|
|
13585
|
-
if (!dir || !
|
|
13731
|
+
if (!dir || !isAbsolute2(dir))
|
|
13586
13732
|
continue;
|
|
13587
|
-
if (isFile(
|
|
13733
|
+
if (isFile(join7(dir, name)))
|
|
13588
13734
|
return dir;
|
|
13589
13735
|
}
|
|
13590
13736
|
return null;
|
|
13591
13737
|
}
|
|
13592
13738
|
function npmAdjacentToNode(deps) {
|
|
13593
13739
|
const dir = dirname3(deps.execPath);
|
|
13594
|
-
return isFile(
|
|
13740
|
+
return isFile(join7(dir, npmBinaryName(deps.platform))) ? dir : null;
|
|
13595
13741
|
}
|
|
13596
13742
|
function highestVersionedNodeBin(installsDir, name) {
|
|
13597
13743
|
let entries;
|
|
@@ -13600,8 +13746,8 @@ function highestVersionedNodeBin(installsDir, name) {
|
|
|
13600
13746
|
} catch {
|
|
13601
13747
|
return null;
|
|
13602
13748
|
}
|
|
13603
|
-
const candidates = entries.filter((v) => isFile(
|
|
13604
|
-
return candidates.length > 0 ?
|
|
13749
|
+
const candidates = entries.filter((v) => isFile(join7(installsDir, v, "bin", name))).sort((a, b) => compareVersionsDesc(a, b));
|
|
13750
|
+
return candidates.length > 0 ? join7(installsDir, candidates[0], "bin") : null;
|
|
13605
13751
|
}
|
|
13606
13752
|
function compareVersionsDesc(a, b) {
|
|
13607
13753
|
const pa = a.replace(/^v/, "").split(".").map((n) => Number.parseInt(n, 10));
|
|
@@ -13626,22 +13772,22 @@ function wellKnownNpmDirs(deps) {
|
|
|
13626
13772
|
const programFiles = env.ProgramFiles || "C:\\Program Files";
|
|
13627
13773
|
const appData = env.APPDATA;
|
|
13628
13774
|
const localAppData = env.LOCALAPPDATA;
|
|
13629
|
-
push(
|
|
13775
|
+
push(join7(programFiles, "nodejs"));
|
|
13630
13776
|
if (appData)
|
|
13631
|
-
push(
|
|
13777
|
+
push(join7(appData, "npm"));
|
|
13632
13778
|
if (localAppData)
|
|
13633
|
-
push(
|
|
13779
|
+
push(join7(localAppData, "Volta", "bin"));
|
|
13634
13780
|
if (env.NVM_SYMLINK)
|
|
13635
13781
|
push(env.NVM_SYMLINK);
|
|
13636
13782
|
} else {
|
|
13637
13783
|
if (env.NVM_BIN)
|
|
13638
13784
|
push(env.NVM_BIN);
|
|
13639
|
-
push(highestVersionedNodeBin(
|
|
13640
|
-
push(highestVersionedNodeBin(
|
|
13641
|
-
push(highestVersionedNodeBin(
|
|
13642
|
-
push(
|
|
13643
|
-
push(
|
|
13644
|
-
const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin",
|
|
13785
|
+
push(highestVersionedNodeBin(join7(home, ".nvm", "versions", "node"), name));
|
|
13786
|
+
push(highestVersionedNodeBin(join7(home, ".local", "share", "mise", "installs", "node"), name));
|
|
13787
|
+
push(highestVersionedNodeBin(join7(home, ".asdf", "installs", "nodejs"), name));
|
|
13788
|
+
push(join7(home, ".volta", "bin"));
|
|
13789
|
+
push(join7(home, ".asdf", "shims"));
|
|
13790
|
+
const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin", join7(home, ".local", "bin")]);
|
|
13645
13791
|
for (const dir of systemDirs)
|
|
13646
13792
|
push(dir);
|
|
13647
13793
|
}
|
|
@@ -13651,12 +13797,12 @@ function resolveNpm(deps = defaultDeps()) {
|
|
|
13651
13797
|
const name = npmBinaryName(deps.platform);
|
|
13652
13798
|
const onPath = npmFromPath(deps);
|
|
13653
13799
|
if (onPath)
|
|
13654
|
-
return { command:
|
|
13800
|
+
return { command: join7(onPath, name), binDir: onPath };
|
|
13655
13801
|
const adjacent = npmAdjacentToNode(deps);
|
|
13656
13802
|
if (adjacent)
|
|
13657
|
-
return { command:
|
|
13803
|
+
return { command: join7(adjacent, name), binDir: adjacent };
|
|
13658
13804
|
for (const dir of wellKnownNpmDirs(deps)) {
|
|
13659
|
-
const candidate =
|
|
13805
|
+
const candidate = join7(dir, name);
|
|
13660
13806
|
if (isFile(candidate))
|
|
13661
13807
|
return { command: candidate, binDir: dir };
|
|
13662
13808
|
}
|
|
@@ -13673,7 +13819,7 @@ function npmSpawnEnv(resolved, baseEnv = process.env) {
|
|
|
13673
13819
|
import { execFileSync } from "node:child_process";
|
|
13674
13820
|
import { createHash as createHash2 } from "node:crypto";
|
|
13675
13821
|
import { chmodSync as chmodSync3, closeSync as closeSync3, copyFileSync as copyFileSync3, createWriteStream as createWriteStream2, existsSync as existsSync5, lstatSync, mkdirSync as mkdirSync5, openSync as openSync3, readdirSync as readdirSync2, readFileSync as readFileSync3, readlinkSync, realpathSync, rmSync as rmSync2, statSync as statSync3, symlinkSync, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "node:fs";
|
|
13676
|
-
import { basename, dirname as dirname4, isAbsolute as
|
|
13822
|
+
import { basename, dirname as dirname4, isAbsolute as isAbsolute3, join as join8, relative as relative2, resolve as resolve2, win32 } from "node:path";
|
|
13677
13823
|
import { Readable as Readable2 } from "node:stream";
|
|
13678
13824
|
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
13679
13825
|
var ORT_VERSION = "1.24.4";
|
|
@@ -13736,10 +13882,10 @@ function getManualInstallHint() {
|
|
|
13736
13882
|
}
|
|
13737
13883
|
async function ensureOnnxRuntime(storageDir) {
|
|
13738
13884
|
const info = getPlatformInfo();
|
|
13739
|
-
const ortVersionDir =
|
|
13885
|
+
const ortVersionDir = join8(storageDir, "onnxruntime", ORT_VERSION);
|
|
13740
13886
|
const libName = info?.libName ?? "libonnxruntime.dylib";
|
|
13741
13887
|
const resolvedOrtDir = resolveCachedOnnxRuntimeDir(ortVersionDir, libName);
|
|
13742
|
-
const libPath =
|
|
13888
|
+
const libPath = join8(resolvedOrtDir, libName);
|
|
13743
13889
|
if (existsSync5(libPath)) {
|
|
13744
13890
|
const meta = readOnnxInstalledMeta(ortVersionDir);
|
|
13745
13891
|
if (meta?.sha256) {
|
|
@@ -13769,9 +13915,9 @@ async function ensureOnnxRuntime(storageDir) {
|
|
|
13769
13915
|
warn(`ONNX Runtime auto-download not available for ${process.platform}/${process.arch}. Install manually: ${getManualInstallHint()}`);
|
|
13770
13916
|
return null;
|
|
13771
13917
|
}
|
|
13772
|
-
const onnxBaseDir =
|
|
13918
|
+
const onnxBaseDir = join8(storageDir, "onnxruntime");
|
|
13773
13919
|
mkdirSync5(onnxBaseDir, { recursive: true });
|
|
13774
|
-
const lockPath =
|
|
13920
|
+
const lockPath = join8(onnxBaseDir, ONNX_LOCK_FILE);
|
|
13775
13921
|
cleanupAbandonedStagingDirs(onnxBaseDir);
|
|
13776
13922
|
if (!acquireLock(lockPath)) {
|
|
13777
13923
|
warn(`ONNX Runtime install already in progress in another process (lock: ${lockPath}). Skipping.`);
|
|
@@ -13790,7 +13936,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
13790
13936
|
for (const entry of entries) {
|
|
13791
13937
|
if (!entry.startsWith(`${ORT_VERSION}.tmp.`))
|
|
13792
13938
|
continue;
|
|
13793
|
-
const stagingDir =
|
|
13939
|
+
const stagingDir = join8(onnxBaseDir, entry);
|
|
13794
13940
|
const parts = entry.split(".");
|
|
13795
13941
|
const pidStr = parts[parts.length - 2];
|
|
13796
13942
|
const pid = pidStr ? Number.parseInt(pidStr, 10) : NaN;
|
|
@@ -13827,7 +13973,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
13827
13973
|
}
|
|
13828
13974
|
function cleanupIncompleteTargetIfUnowned(ortDir) {
|
|
13829
13975
|
try {
|
|
13830
|
-
if (existsSync5(ortDir) && !existsSync5(
|
|
13976
|
+
if (existsSync5(ortDir) && !existsSync5(join8(ortDir, ONNX_INSTALLED_META_FILE))) {
|
|
13831
13977
|
log(`[onnx] removing half-populated install dir ${ortDir} (no meta file)`);
|
|
13832
13978
|
rmSync2(ortDir, { recursive: true, force: true });
|
|
13833
13979
|
}
|
|
@@ -13855,8 +14001,8 @@ function parseOnnxVersionFromDirectoryPath(value) {
|
|
|
13855
14001
|
return null;
|
|
13856
14002
|
}
|
|
13857
14003
|
function isPathInsideRoot(root, candidate) {
|
|
13858
|
-
const rel =
|
|
13859
|
-
return rel === "" || !rel.startsWith("../") && !rel.startsWith("..\\") && rel !== ".." && !
|
|
14004
|
+
const rel = relative2(root, candidate);
|
|
14005
|
+
return rel === "" || !rel.startsWith("../") && !rel.startsWith("..\\") && rel !== ".." && !isAbsolute3(rel) && !win32.isAbsolute(rel);
|
|
13860
14006
|
}
|
|
13861
14007
|
function detectOnnxVersion(libDir, libName) {
|
|
13862
14008
|
try {
|
|
@@ -13871,7 +14017,7 @@ function detectOnnxVersion(libDir, libName) {
|
|
|
13871
14017
|
if (version)
|
|
13872
14018
|
return version;
|
|
13873
14019
|
}
|
|
13874
|
-
const base =
|
|
14020
|
+
const base = join8(libDir, libName);
|
|
13875
14021
|
if (existsSync5(base)) {
|
|
13876
14022
|
try {
|
|
13877
14023
|
const real = realpathSync(base);
|
|
@@ -13907,7 +14053,7 @@ function pathEntriesForPlatform() {
|
|
|
13907
14053
|
return pathEnvValue().split(delimiter2).map((entry) => entry.trim().replace(/^"|"$/g, "")).filter((entry) => {
|
|
13908
14054
|
if (!entry || entry === "." || entry.includes("\x00"))
|
|
13909
14055
|
return false;
|
|
13910
|
-
return
|
|
14056
|
+
return isAbsolute3(entry) || win32.isAbsolute(entry);
|
|
13911
14057
|
});
|
|
13912
14058
|
}
|
|
13913
14059
|
function directoryContainsLibrary(dir, libName) {
|
|
@@ -13923,10 +14069,10 @@ function directoryContainsLibrary(dir, libName) {
|
|
|
13923
14069
|
}
|
|
13924
14070
|
}
|
|
13925
14071
|
function resolveCachedOnnxRuntimeDir(ortVersionDir, libName) {
|
|
13926
|
-
if (existsSync5(
|
|
14072
|
+
if (existsSync5(join8(ortVersionDir, libName)))
|
|
13927
14073
|
return ortVersionDir;
|
|
13928
|
-
const libSubdir =
|
|
13929
|
-
if (existsSync5(
|
|
14074
|
+
const libSubdir = join8(ortVersionDir, "lib");
|
|
14075
|
+
if (existsSync5(join8(libSubdir, libName)))
|
|
13930
14076
|
return libSubdir;
|
|
13931
14077
|
return ortVersionDir;
|
|
13932
14078
|
}
|
|
@@ -13941,12 +14087,12 @@ function findSystemOnnxRuntime(libName) {
|
|
|
13941
14087
|
} else if (process.platform === "win32") {
|
|
13942
14088
|
const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
|
|
13943
14089
|
const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
|
|
13944
|
-
searchPaths.push(
|
|
14090
|
+
searchPaths.push(join8(programFiles, "onnxruntime", "lib"), join8(programFiles, "Microsoft ONNX Runtime", "lib"), join8(programFiles, "Microsoft Machine Learning", "lib"), join8(programFilesX86, "onnxruntime", "lib"), ...(() => {
|
|
13945
14091
|
const nugetPaths = [];
|
|
13946
14092
|
const userProfile = process.env.USERPROFILE ?? "";
|
|
13947
14093
|
if (!userProfile)
|
|
13948
14094
|
return nugetPaths;
|
|
13949
|
-
const nugetPackageDir =
|
|
14095
|
+
const nugetPackageDir = join8(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
|
|
13950
14096
|
if (!existsSync5(nugetPackageDir))
|
|
13951
14097
|
return nugetPaths;
|
|
13952
14098
|
try {
|
|
@@ -13955,7 +14101,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
13955
14101
|
continue;
|
|
13956
14102
|
if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
|
|
13957
14103
|
continue;
|
|
13958
|
-
nugetPaths.push(
|
|
14104
|
+
nugetPaths.push(join8(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join8(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
|
|
13959
14105
|
}
|
|
13960
14106
|
} catch (err) {
|
|
13961
14107
|
warn(`Failed to scan NuGet ONNX Runtime cache ${nugetPackageDir}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -13967,7 +14113,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
13967
14113
|
const normalizeCase = process.platform === "win32" || process.platform === "darwin";
|
|
13968
14114
|
const seen = new Set;
|
|
13969
14115
|
const uniquePaths = searchPaths.filter((p) => {
|
|
13970
|
-
let key =
|
|
14116
|
+
let key = resolve2(p).replace(/[/\\]+$/, "");
|
|
13971
14117
|
if (normalizeCase)
|
|
13972
14118
|
key = key.toLowerCase();
|
|
13973
14119
|
if (seen.has(key))
|
|
@@ -13977,7 +14123,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
13977
14123
|
});
|
|
13978
14124
|
const unknownVersionPaths = [];
|
|
13979
14125
|
for (const dir of uniquePaths) {
|
|
13980
|
-
const libPath =
|
|
14126
|
+
const libPath = join8(dir, libName);
|
|
13981
14127
|
if (process.platform === "win32") {
|
|
13982
14128
|
if (!directoryContainsLibrary(dir, libName))
|
|
13983
14129
|
continue;
|
|
@@ -14043,19 +14189,19 @@ function validateExtractedTree(stagingRoot) {
|
|
|
14043
14189
|
const walk = (dir) => {
|
|
14044
14190
|
const entries = readdirSync2(dir);
|
|
14045
14191
|
for (const entry of entries) {
|
|
14046
|
-
const fullPath =
|
|
14192
|
+
const fullPath = join8(dir, entry);
|
|
14047
14193
|
const lst = lstatSync(fullPath);
|
|
14048
14194
|
if (lst.isSymbolicLink()) {
|
|
14049
14195
|
const linkTarget = readlinkSync(fullPath);
|
|
14050
|
-
const resolvedTarget =
|
|
14051
|
-
const rel2 =
|
|
14052
|
-
if (rel2.startsWith("..") ||
|
|
14196
|
+
const resolvedTarget = resolve2(dirname4(fullPath), linkTarget);
|
|
14197
|
+
const rel2 = relative2(realRoot, resolvedTarget);
|
|
14198
|
+
if (rel2.startsWith("..") || isAbsolute3(rel2) || win32.isAbsolute(rel2)) {
|
|
14053
14199
|
throw new Error(`extracted symlink ${fullPath} points outside staging root: ${linkTarget}`);
|
|
14054
14200
|
}
|
|
14055
14201
|
continue;
|
|
14056
14202
|
}
|
|
14057
|
-
const rel =
|
|
14058
|
-
if (rel.startsWith("..") ||
|
|
14203
|
+
const rel = relative2(realRoot, fullPath);
|
|
14204
|
+
if (rel.startsWith("..") || isAbsolute3(rel) || win32.isAbsolute(rel)) {
|
|
14059
14205
|
throw new Error(`extracted entry ${fullPath} escapes staging root`);
|
|
14060
14206
|
}
|
|
14061
14207
|
if (lst.isDirectory()) {
|
|
@@ -14078,7 +14224,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
14078
14224
|
const tmpDir = `${targetDir}.tmp.${process.pid}.${Date.now().toString(36)}`;
|
|
14079
14225
|
try {
|
|
14080
14226
|
mkdirSync5(tmpDir, { recursive: true });
|
|
14081
|
-
const archivePath =
|
|
14227
|
+
const archivePath = join8(tmpDir, `onnxruntime.${info.archiveType}`);
|
|
14082
14228
|
await downloadFileWithCap(url, archivePath);
|
|
14083
14229
|
const archiveSha256 = sha256File(archivePath);
|
|
14084
14230
|
log(`ONNX Runtime archive sha256=${archiveSha256}`);
|
|
@@ -14094,7 +14240,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
14094
14240
|
unlinkSync3(archivePath);
|
|
14095
14241
|
} catch {}
|
|
14096
14242
|
validateExtractedTree(tmpDir);
|
|
14097
|
-
const extractedDir =
|
|
14243
|
+
const extractedDir = join8(tmpDir, info.assetName, "lib");
|
|
14098
14244
|
if (!existsSync5(extractedDir)) {
|
|
14099
14245
|
throw new Error(`Expected directory not found: ${extractedDir}`);
|
|
14100
14246
|
}
|
|
@@ -14103,7 +14249,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
14103
14249
|
const realFiles = [];
|
|
14104
14250
|
const symlinks = [];
|
|
14105
14251
|
for (const libFile of libFiles) {
|
|
14106
|
-
const src =
|
|
14252
|
+
const src = join8(extractedDir, libFile);
|
|
14107
14253
|
try {
|
|
14108
14254
|
const stat = lstatSync(src);
|
|
14109
14255
|
log(`ORT extract: ${libFile} — isSymlink=${stat.isSymbolicLink()}, isFile=${stat.isFile()}, size=${stat.size}`);
|
|
@@ -14118,7 +14264,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
14118
14264
|
}
|
|
14119
14265
|
}
|
|
14120
14266
|
copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks);
|
|
14121
|
-
const libPath =
|
|
14267
|
+
const libPath = join8(targetDir, info.libName);
|
|
14122
14268
|
let libHash = null;
|
|
14123
14269
|
try {
|
|
14124
14270
|
libHash = sha256File(libPath);
|
|
@@ -14143,8 +14289,8 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
14143
14289
|
function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, copyFile = copyFileSync3) {
|
|
14144
14290
|
const requiredLibs = new Set([info.libName]);
|
|
14145
14291
|
for (const libFile of realFiles) {
|
|
14146
|
-
const src =
|
|
14147
|
-
const dst =
|
|
14292
|
+
const src = join8(extractedDir, libFile);
|
|
14293
|
+
const dst = join8(targetDir, libFile);
|
|
14148
14294
|
try {
|
|
14149
14295
|
copyFile(src, dst);
|
|
14150
14296
|
if (process.platform !== "win32") {
|
|
@@ -14160,12 +14306,12 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
14160
14306
|
}
|
|
14161
14307
|
const targetRoot = realpathSync(targetDir);
|
|
14162
14308
|
for (const link of symlinks) {
|
|
14163
|
-
const dst =
|
|
14309
|
+
const dst = join8(targetDir, link.name);
|
|
14164
14310
|
try {
|
|
14165
14311
|
unlinkSync3(dst);
|
|
14166
14312
|
} catch {}
|
|
14167
|
-
const dstForContainment =
|
|
14168
|
-
const resolvedTarget =
|
|
14313
|
+
const dstForContainment = join8(targetRoot, link.name);
|
|
14314
|
+
const resolvedTarget = resolve2(dirname4(dstForContainment), link.target);
|
|
14169
14315
|
if (!isPathInsideRoot(targetRoot, resolvedTarget)) {
|
|
14170
14316
|
const message = `ONNX Runtime symlink ${link.name} points outside install dir: ${link.target}`;
|
|
14171
14317
|
if (requiredLibs.has(link.name)) {
|
|
@@ -14185,7 +14331,7 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
14185
14331
|
log(`ORT extract: failed to symlink optional ${link.name}: ${symlinkErr}`);
|
|
14186
14332
|
}
|
|
14187
14333
|
}
|
|
14188
|
-
const requiredPath =
|
|
14334
|
+
const requiredPath = join8(targetDir, info.libName);
|
|
14189
14335
|
if (!existsSync5(requiredPath)) {
|
|
14190
14336
|
rmSync2(targetDir, { recursive: true, force: true });
|
|
14191
14337
|
throw new Error(`Required ONNX Runtime library missing after install: ${requiredPath}`);
|
|
@@ -14212,17 +14358,17 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
|
|
|
14212
14358
|
...sha256 ? { sha256 } : {},
|
|
14213
14359
|
archiveSha256
|
|
14214
14360
|
};
|
|
14215
|
-
writeFileSync2(
|
|
14361
|
+
writeFileSync2(join8(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
|
|
14216
14362
|
} catch (err) {
|
|
14217
14363
|
log(`[onnx] failed to write installed-meta in ${installDir}: ${err}`);
|
|
14218
14364
|
}
|
|
14219
14365
|
}
|
|
14220
14366
|
function readOnnxInstalledMeta(installDir) {
|
|
14221
|
-
const
|
|
14367
|
+
const path2 = join8(installDir, ONNX_INSTALLED_META_FILE);
|
|
14222
14368
|
try {
|
|
14223
|
-
if (!statSync3(
|
|
14369
|
+
if (!statSync3(path2).isFile())
|
|
14224
14370
|
return null;
|
|
14225
|
-
const raw = readFileSync3(
|
|
14371
|
+
const raw = readFileSync3(path2, "utf8");
|
|
14226
14372
|
const parsed = JSON.parse(raw);
|
|
14227
14373
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
14228
14374
|
return null;
|
|
@@ -14236,9 +14382,9 @@ function readOnnxInstalledMeta(installDir) {
|
|
|
14236
14382
|
return null;
|
|
14237
14383
|
}
|
|
14238
14384
|
}
|
|
14239
|
-
function sha256File(
|
|
14385
|
+
function sha256File(path2) {
|
|
14240
14386
|
const hash = createHash2("sha256");
|
|
14241
|
-
hash.update(readFileSync3(
|
|
14387
|
+
hash.update(readFileSync3(path2));
|
|
14242
14388
|
return hash.digest("hex");
|
|
14243
14389
|
}
|
|
14244
14390
|
function acquireLock(lockPath) {
|
|
@@ -14898,13 +15044,13 @@ function tokenizeStage(stage) {
|
|
|
14898
15044
|
}
|
|
14899
15045
|
// ../aft-bridge/dist/pool.js
|
|
14900
15046
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
14901
|
-
import { homedir as
|
|
15047
|
+
import { homedir as homedir7 } from "node:os";
|
|
14902
15048
|
var DEFAULT_IDLE_TIMEOUT_MS = 30 * 60 * 1000;
|
|
14903
15049
|
var DEFAULT_MAX_POOL_SIZE = 8;
|
|
14904
15050
|
var CLEANUP_INTERVAL_MS = 60 * 1000;
|
|
14905
15051
|
function canonicalHomeDir() {
|
|
14906
15052
|
try {
|
|
14907
|
-
const home =
|
|
15053
|
+
const home = homedir7();
|
|
14908
15054
|
if (!home)
|
|
14909
15055
|
return null;
|
|
14910
15056
|
try {
|
|
@@ -14942,6 +15088,7 @@ class BridgePool {
|
|
|
14942
15088
|
this.projectConfigLoader = options.projectConfigLoader;
|
|
14943
15089
|
this.bridgeOptions = {
|
|
14944
15090
|
timeoutMs: options.timeoutMs,
|
|
15091
|
+
hangThreshold: options.hangThreshold,
|
|
14945
15092
|
maxRestarts: options.maxRestarts,
|
|
14946
15093
|
minVersion: options.minVersion,
|
|
14947
15094
|
onVersionMismatch: options.onVersionMismatch,
|
|
@@ -15096,6 +15243,91 @@ function normalizeKey(projectRoot) {
|
|
|
15096
15243
|
return stripped;
|
|
15097
15244
|
}
|
|
15098
15245
|
}
|
|
15246
|
+
// ../aft-bridge/dist/tool-format.js
|
|
15247
|
+
function asPlainObject(value) {
|
|
15248
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
15249
|
+
return;
|
|
15250
|
+
return value;
|
|
15251
|
+
}
|
|
15252
|
+
function candidateLocation(candidate) {
|
|
15253
|
+
const file = typeof candidate.file === "string" && candidate.file.length > 0 ? candidate.file : undefined;
|
|
15254
|
+
if (!file)
|
|
15255
|
+
return;
|
|
15256
|
+
const line = typeof candidate.line === "number" && Number.isFinite(candidate.line) ? candidate.line : undefined;
|
|
15257
|
+
return line === undefined ? file : `${file}:${line}`;
|
|
15258
|
+
}
|
|
15259
|
+
function stringifyData(data) {
|
|
15260
|
+
if (data === undefined)
|
|
15261
|
+
return;
|
|
15262
|
+
try {
|
|
15263
|
+
return JSON.stringify(data, null, 2);
|
|
15264
|
+
} catch {
|
|
15265
|
+
return String(data);
|
|
15266
|
+
}
|
|
15267
|
+
}
|
|
15268
|
+
function formatBridgeErrorMessage(command, response, params = {}) {
|
|
15269
|
+
const code = typeof response.code === "string" && response.code.length > 0 ? response.code : undefined;
|
|
15270
|
+
const message = typeof response.message === "string" && response.message.length > 0 ? response.message : `${command} failed`;
|
|
15271
|
+
const data = asPlainObject(response.data);
|
|
15272
|
+
const rawCandidates = Array.isArray(response.candidates) ? response.candidates : Array.isArray(data?.candidates) ? data.candidates : undefined;
|
|
15273
|
+
const rawSymbol = typeof response.symbol === "string" && response.symbol.length > 0 ? response.symbol : typeof data?.symbol === "string" && data.symbol.length > 0 ? data.symbol : undefined;
|
|
15274
|
+
if (code === "ambiguous_target" || code === "target_symbol_not_in_file") {
|
|
15275
|
+
const candidates = (rawCandidates ?? []).map(asPlainObject).filter((candidate) => candidate !== undefined).map(candidateLocation).filter((candidate) => candidate !== undefined);
|
|
15276
|
+
if (candidates.length > 0) {
|
|
15277
|
+
const symbol = typeof params.toSymbol === "string" && params.toSymbol.length > 0 ? params.toSymbol : rawSymbol;
|
|
15278
|
+
const target = symbol ? `multiple symbols named "${symbol}"` : message.replace(/[.!?]+$/, "");
|
|
15279
|
+
const action = code === "ambiguous_target" ? "Pass toFile to disambiguate" : "Try one of these files for toFile";
|
|
15280
|
+
return `${command}: ${code} — ${target}. ${action}:
|
|
15281
|
+
${candidates.map((candidate) => ` - ${candidate}`).join(`
|
|
15282
|
+
`)}`;
|
|
15283
|
+
}
|
|
15284
|
+
}
|
|
15285
|
+
if (!code)
|
|
15286
|
+
return message;
|
|
15287
|
+
const lines = [`${command}: ${code} — ${message}`];
|
|
15288
|
+
const extras = collectStructuredExtras(response);
|
|
15289
|
+
if (extras)
|
|
15290
|
+
lines.push(`data: ${extras}`);
|
|
15291
|
+
return lines.join(`
|
|
15292
|
+
`);
|
|
15293
|
+
}
|
|
15294
|
+
function collectStructuredExtras(response) {
|
|
15295
|
+
const reserved = new Set([
|
|
15296
|
+
"id",
|
|
15297
|
+
"success",
|
|
15298
|
+
"code",
|
|
15299
|
+
"message",
|
|
15300
|
+
"data",
|
|
15301
|
+
"status_bar",
|
|
15302
|
+
"bg_completions"
|
|
15303
|
+
]);
|
|
15304
|
+
const extras = {};
|
|
15305
|
+
for (const [key, value] of Object.entries(response)) {
|
|
15306
|
+
if (reserved.has(key))
|
|
15307
|
+
continue;
|
|
15308
|
+
extras[key] = value;
|
|
15309
|
+
}
|
|
15310
|
+
if (Object.keys(extras).length === 0) {
|
|
15311
|
+
return stringifyData(response.data);
|
|
15312
|
+
}
|
|
15313
|
+
if (response.data !== undefined)
|
|
15314
|
+
extras.data = response.data;
|
|
15315
|
+
return stringifyData(extras);
|
|
15316
|
+
}
|
|
15317
|
+
function formatReadFooter(agentSpecifiedRange, data, options) {
|
|
15318
|
+
if (agentSpecifiedRange)
|
|
15319
|
+
return "";
|
|
15320
|
+
if (!data.truncated)
|
|
15321
|
+
return "";
|
|
15322
|
+
const startLine = data.start_line;
|
|
15323
|
+
const endLine = data.end_line;
|
|
15324
|
+
const totalLines = data.total_lines;
|
|
15325
|
+
if (startLine === undefined || endLine === undefined || totalLines === undefined) {
|
|
15326
|
+
return "";
|
|
15327
|
+
}
|
|
15328
|
+
return `
|
|
15329
|
+
(Showing lines ${startLine}-${endLine} of ${totalLines}. Use ${options.rangeHint} to read other sections.)`;
|
|
15330
|
+
}
|
|
15099
15331
|
// ../aft-bridge/dist/zoom-format.js
|
|
15100
15332
|
function formatZoomText(targetLabel, response) {
|
|
15101
15333
|
const range = response.range;
|
|
@@ -15176,13 +15408,36 @@ function formatZoomMultiTargetResult(entries) {
|
|
|
15176
15408
|
|
|
15177
15409
|
`) };
|
|
15178
15410
|
}
|
|
15411
|
+
function isRustZoomBatchEnvelope(response) {
|
|
15412
|
+
if (!Array.isArray(response.symbols) || response.symbols.length === 0) {
|
|
15413
|
+
return false;
|
|
15414
|
+
}
|
|
15415
|
+
return response.symbols.every((entry) => {
|
|
15416
|
+
if (!entry || typeof entry !== "object")
|
|
15417
|
+
return false;
|
|
15418
|
+
const row = entry;
|
|
15419
|
+
return typeof row.name === "string" && row.response !== undefined && row.response !== null;
|
|
15420
|
+
});
|
|
15421
|
+
}
|
|
15422
|
+
function unwrapRustZoomBatchEnvelope(response) {
|
|
15423
|
+
if (!isRustZoomBatchEnvelope(response)) {
|
|
15424
|
+
return null;
|
|
15425
|
+
}
|
|
15426
|
+
const names = [];
|
|
15427
|
+
const responses = [];
|
|
15428
|
+
for (const entry of response.symbols) {
|
|
15429
|
+
names.push(entry.name);
|
|
15430
|
+
responses.push(entry.response);
|
|
15431
|
+
}
|
|
15432
|
+
return { names, responses };
|
|
15433
|
+
}
|
|
15179
15434
|
// src/logger.ts
|
|
15180
15435
|
import * as fs from "node:fs";
|
|
15181
|
-
import * as
|
|
15182
|
-
import * as
|
|
15436
|
+
import * as os2 from "node:os";
|
|
15437
|
+
import * as path2 from "node:path";
|
|
15183
15438
|
var TAG = "[aft-pi]";
|
|
15184
15439
|
var isTestEnv = process.env.BUN_TEST === "1" || false;
|
|
15185
|
-
var logFile =
|
|
15440
|
+
var logFile = path2.join(os2.tmpdir(), isTestEnv ? "aft-pi-test.log" : "aft-pi.log");
|
|
15186
15441
|
var useStderr = process.env.AFT_LOG_STDERR === "1";
|
|
15187
15442
|
var buffer = [];
|
|
15188
15443
|
var flushTimer = null;
|
|
@@ -15818,7 +16073,7 @@ import {
|
|
|
15818
16073
|
// package.json
|
|
15819
16074
|
var package_default = {
|
|
15820
16075
|
name: "@cortexkit/aft-pi",
|
|
15821
|
-
version: "0.39.
|
|
16076
|
+
version: "0.39.2",
|
|
15822
16077
|
type: "module",
|
|
15823
16078
|
description: "Pi coding agent extension for Agent File Tools (AFT) — tree-sitter and LSP-powered code analysis",
|
|
15824
16079
|
main: "dist/index.js",
|
|
@@ -15841,7 +16096,7 @@ var package_default = {
|
|
|
15841
16096
|
"test:unit": "bun test src/__tests__ --path-ignore-patterns 'src/__tests__/e2e/**'"
|
|
15842
16097
|
},
|
|
15843
16098
|
dependencies: {
|
|
15844
|
-
"@cortexkit/aft-bridge": "0.39.
|
|
16099
|
+
"@cortexkit/aft-bridge": "0.39.2",
|
|
15845
16100
|
"@xterm/headless": "^5.5.0",
|
|
15846
16101
|
"comment-json": "^5.0.0",
|
|
15847
16102
|
diff: "^8.0.4",
|
|
@@ -15849,12 +16104,12 @@ var package_default = {
|
|
|
15849
16104
|
zod: "^4.1.8"
|
|
15850
16105
|
},
|
|
15851
16106
|
optionalDependencies: {
|
|
15852
|
-
"@cortexkit/aft-darwin-arm64": "0.39.
|
|
15853
|
-
"@cortexkit/aft-darwin-x64": "0.39.
|
|
15854
|
-
"@cortexkit/aft-linux-arm64": "0.39.
|
|
15855
|
-
"@cortexkit/aft-linux-x64": "0.39.
|
|
15856
|
-
"@cortexkit/aft-win32-arm64": "0.39.
|
|
15857
|
-
"@cortexkit/aft-win32-x64": "0.39.
|
|
16107
|
+
"@cortexkit/aft-darwin-arm64": "0.39.2",
|
|
16108
|
+
"@cortexkit/aft-darwin-x64": "0.39.2",
|
|
16109
|
+
"@cortexkit/aft-linux-arm64": "0.39.2",
|
|
16110
|
+
"@cortexkit/aft-linux-x64": "0.39.2",
|
|
16111
|
+
"@cortexkit/aft-win32-arm64": "0.39.2",
|
|
16112
|
+
"@cortexkit/aft-win32-x64": "0.39.2"
|
|
15858
16113
|
},
|
|
15859
16114
|
devDependencies: {
|
|
15860
16115
|
"@earendil-works/pi-coding-agent": "*",
|
|
@@ -16087,101 +16342,6 @@ function formatStatusDialogMessage(status) {
|
|
|
16087
16342
|
// src/tools/_shared.ts
|
|
16088
16343
|
import { Type } from "typebox";
|
|
16089
16344
|
var optionalInt = (_min, _max) => Type.Optional(Type.Any({ description: "(integer)" }));
|
|
16090
|
-
function coerceOptionalInt(v, paramName, min, max) {
|
|
16091
|
-
if (v === undefined || v === null || v === "")
|
|
16092
|
-
return;
|
|
16093
|
-
if (typeof v === "number" && (!Number.isFinite(v) || v === 0 && min > 0))
|
|
16094
|
-
return;
|
|
16095
|
-
const n = typeof v === "string" ? Number(v) : v;
|
|
16096
|
-
if (typeof n !== "number" || !Number.isInteger(n)) {
|
|
16097
|
-
throw new Error(`${paramName} must be an integer between ${min} and ${max}`);
|
|
16098
|
-
}
|
|
16099
|
-
if (n < min || n > max) {
|
|
16100
|
-
throw new Error(`${paramName} must be between ${min} and ${max}`);
|
|
16101
|
-
}
|
|
16102
|
-
return n;
|
|
16103
|
-
}
|
|
16104
|
-
function isEmptyParam(value) {
|
|
16105
|
-
if (value === undefined || value === null)
|
|
16106
|
-
return true;
|
|
16107
|
-
if (typeof value === "string")
|
|
16108
|
-
return value.length === 0;
|
|
16109
|
-
if (Array.isArray(value))
|
|
16110
|
-
return value.length === 0;
|
|
16111
|
-
if (typeof value === "object")
|
|
16112
|
-
return Object.keys(value).length === 0;
|
|
16113
|
-
return false;
|
|
16114
|
-
}
|
|
16115
|
-
function asPlainObject(value) {
|
|
16116
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
16117
|
-
return;
|
|
16118
|
-
return value;
|
|
16119
|
-
}
|
|
16120
|
-
function candidateLocation(candidate) {
|
|
16121
|
-
const file = typeof candidate.file === "string" && candidate.file.length > 0 ? candidate.file : undefined;
|
|
16122
|
-
if (!file)
|
|
16123
|
-
return;
|
|
16124
|
-
const line = typeof candidate.line === "number" && Number.isFinite(candidate.line) ? candidate.line : undefined;
|
|
16125
|
-
return line === undefined ? file : `${file}:${line}`;
|
|
16126
|
-
}
|
|
16127
|
-
function stringifyData(data) {
|
|
16128
|
-
if (data === undefined)
|
|
16129
|
-
return;
|
|
16130
|
-
try {
|
|
16131
|
-
return JSON.stringify(data, null, 2);
|
|
16132
|
-
} catch {
|
|
16133
|
-
return String(data);
|
|
16134
|
-
}
|
|
16135
|
-
}
|
|
16136
|
-
function formatBridgeErrorMessage(command, response, params = {}) {
|
|
16137
|
-
const code = typeof response.code === "string" && response.code.length > 0 ? response.code : undefined;
|
|
16138
|
-
const message = typeof response.message === "string" && response.message.length > 0 ? response.message : `${command} failed`;
|
|
16139
|
-
const data = asPlainObject(response.data);
|
|
16140
|
-
const rawCandidates = Array.isArray(response.candidates) ? response.candidates : Array.isArray(data?.candidates) ? data.candidates : undefined;
|
|
16141
|
-
const rawSymbol = typeof response.symbol === "string" && response.symbol.length > 0 ? response.symbol : typeof data?.symbol === "string" && data.symbol.length > 0 ? data.symbol : undefined;
|
|
16142
|
-
if (code === "ambiguous_target" || code === "target_symbol_not_in_file") {
|
|
16143
|
-
const candidates = (rawCandidates ?? []).map(asPlainObject).filter((candidate) => candidate !== undefined).map(candidateLocation).filter((candidate) => candidate !== undefined);
|
|
16144
|
-
if (candidates.length > 0) {
|
|
16145
|
-
const symbol = typeof params.toSymbol === "string" && params.toSymbol.length > 0 ? params.toSymbol : rawSymbol;
|
|
16146
|
-
const target = symbol ? `multiple symbols named "${symbol}"` : message.replace(/[.!?]+$/, "");
|
|
16147
|
-
const action = code === "ambiguous_target" ? "Pass toFile to disambiguate" : "Try one of these files for toFile";
|
|
16148
|
-
return `${command}: ${code} — ${target}. ${action}:
|
|
16149
|
-
${candidates.map((candidate) => ` - ${candidate}`).join(`
|
|
16150
|
-
`)}`;
|
|
16151
|
-
}
|
|
16152
|
-
}
|
|
16153
|
-
if (!code)
|
|
16154
|
-
return message;
|
|
16155
|
-
const lines = [`${command}: ${code} — ${message}`];
|
|
16156
|
-
const extras = collectStructuredExtras(response);
|
|
16157
|
-
if (extras)
|
|
16158
|
-
lines.push(`data: ${extras}`);
|
|
16159
|
-
return lines.join(`
|
|
16160
|
-
`);
|
|
16161
|
-
}
|
|
16162
|
-
function collectStructuredExtras(response) {
|
|
16163
|
-
const reserved = new Set([
|
|
16164
|
-
"id",
|
|
16165
|
-
"success",
|
|
16166
|
-
"code",
|
|
16167
|
-
"message",
|
|
16168
|
-
"data",
|
|
16169
|
-
"status_bar",
|
|
16170
|
-
"bg_completions"
|
|
16171
|
-
]);
|
|
16172
|
-
const extras = {};
|
|
16173
|
-
for (const [key, value] of Object.entries(response)) {
|
|
16174
|
-
if (reserved.has(key))
|
|
16175
|
-
continue;
|
|
16176
|
-
extras[key] = value;
|
|
16177
|
-
}
|
|
16178
|
-
if (Object.keys(extras).length === 0) {
|
|
16179
|
-
return stringifyData(response.data);
|
|
16180
|
-
}
|
|
16181
|
-
if (response.data !== undefined)
|
|
16182
|
-
extras.data = response.data;
|
|
16183
|
-
return stringifyData(extras);
|
|
16184
|
-
}
|
|
16185
16345
|
function bridgeFor(ctx, cwd) {
|
|
16186
16346
|
return ctx.pool.getBridge(cwd);
|
|
16187
16347
|
}
|
|
@@ -16524,8 +16684,8 @@ function registerStatusCommand(pi, ctx) {
|
|
|
16524
16684
|
|
|
16525
16685
|
// src/config.ts
|
|
16526
16686
|
import { existsSync as existsSync6, readFileSync as readFileSync4, renameSync as renameSync4, unlinkSync as unlinkSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
16527
|
-
import { homedir as
|
|
16528
|
-
import { join as
|
|
16687
|
+
import { homedir as homedir8 } from "node:os";
|
|
16688
|
+
import { join as join10 } from "node:path";
|
|
16529
16689
|
var import_comment_json = __toESM(require_src2(), 1);
|
|
16530
16690
|
|
|
16531
16691
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
|
|
@@ -17293,10 +17453,10 @@ function mergeDefs(...defs) {
|
|
|
17293
17453
|
function cloneDef(schema) {
|
|
17294
17454
|
return mergeDefs(schema._zod.def);
|
|
17295
17455
|
}
|
|
17296
|
-
function getElementAtPath(obj,
|
|
17297
|
-
if (!
|
|
17456
|
+
function getElementAtPath(obj, path3) {
|
|
17457
|
+
if (!path3)
|
|
17298
17458
|
return obj;
|
|
17299
|
-
return
|
|
17459
|
+
return path3.reduce((acc, key) => acc?.[key], obj);
|
|
17300
17460
|
}
|
|
17301
17461
|
function promiseAllObject(promisesObj) {
|
|
17302
17462
|
const keys = Object.keys(promisesObj);
|
|
@@ -17677,11 +17837,11 @@ function aborted(x, startIndex = 0) {
|
|
|
17677
17837
|
}
|
|
17678
17838
|
return false;
|
|
17679
17839
|
}
|
|
17680
|
-
function prefixIssues(
|
|
17840
|
+
function prefixIssues(path3, issues) {
|
|
17681
17841
|
return issues.map((iss) => {
|
|
17682
17842
|
var _a;
|
|
17683
17843
|
(_a = iss).path ?? (_a.path = []);
|
|
17684
|
-
iss.path.unshift(
|
|
17844
|
+
iss.path.unshift(path3);
|
|
17685
17845
|
return iss;
|
|
17686
17846
|
});
|
|
17687
17847
|
}
|
|
@@ -17864,7 +18024,7 @@ function formatError(error3, mapper = (issue2) => issue2.message) {
|
|
|
17864
18024
|
}
|
|
17865
18025
|
function treeifyError(error3, mapper = (issue2) => issue2.message) {
|
|
17866
18026
|
const result = { errors: [] };
|
|
17867
|
-
const processError = (error4,
|
|
18027
|
+
const processError = (error4, path3 = []) => {
|
|
17868
18028
|
var _a, _b;
|
|
17869
18029
|
for (const issue2 of error4.issues) {
|
|
17870
18030
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -17874,7 +18034,7 @@ function treeifyError(error3, mapper = (issue2) => issue2.message) {
|
|
|
17874
18034
|
} else if (issue2.code === "invalid_element") {
|
|
17875
18035
|
processError({ issues: issue2.issues }, issue2.path);
|
|
17876
18036
|
} else {
|
|
17877
|
-
const fullpath = [...
|
|
18037
|
+
const fullpath = [...path3, ...issue2.path];
|
|
17878
18038
|
if (fullpath.length === 0) {
|
|
17879
18039
|
result.errors.push(mapper(issue2));
|
|
17880
18040
|
continue;
|
|
@@ -17906,8 +18066,8 @@ function treeifyError(error3, mapper = (issue2) => issue2.message) {
|
|
|
17906
18066
|
}
|
|
17907
18067
|
function toDotPath(_path) {
|
|
17908
18068
|
const segs = [];
|
|
17909
|
-
const
|
|
17910
|
-
for (const seg of
|
|
18069
|
+
const path3 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
18070
|
+
for (const seg of path3) {
|
|
17911
18071
|
if (typeof seg === "number")
|
|
17912
18072
|
segs.push(`[${seg}]`);
|
|
17913
18073
|
else if (typeof seg === "symbol")
|
|
@@ -29654,13 +29814,13 @@ function resolveRef(ref, ctx) {
|
|
|
29654
29814
|
if (!ref.startsWith("#")) {
|
|
29655
29815
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
29656
29816
|
}
|
|
29657
|
-
const
|
|
29658
|
-
if (
|
|
29817
|
+
const path3 = ref.slice(1).split("/").filter(Boolean);
|
|
29818
|
+
if (path3.length === 0) {
|
|
29659
29819
|
return ctx.rootSchema;
|
|
29660
29820
|
}
|
|
29661
29821
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
29662
|
-
if (
|
|
29663
|
-
const key =
|
|
29822
|
+
if (path3[0] === defsKey) {
|
|
29823
|
+
const key = path3[1];
|
|
29664
29824
|
if (!key || !ctx.defs[key]) {
|
|
29665
29825
|
throw new Error(`Reference not found: ${ref}`);
|
|
29666
29826
|
}
|
|
@@ -30186,6 +30346,10 @@ var BashFeaturesSchema = exports_external.object({
|
|
|
30186
30346
|
foreground_wait_window_ms: exports_external.number().int().positive().optional()
|
|
30187
30347
|
});
|
|
30188
30348
|
var BashConfigSchema = exports_external.union([exports_external.boolean(), BashFeaturesSchema]);
|
|
30349
|
+
var BridgeConfigSchema = exports_external.object({
|
|
30350
|
+
request_timeout_ms: exports_external.number().int().min(1000, { message: "bridge.request_timeout_ms must be at least 1000" }).optional(),
|
|
30351
|
+
hang_threshold: exports_external.number().int().min(1, { message: "bridge.hang_threshold must be at least 1" }).optional()
|
|
30352
|
+
});
|
|
30189
30353
|
var InspectConfigSchema = exports_external.object({
|
|
30190
30354
|
enabled: exports_external.boolean().optional(),
|
|
30191
30355
|
tier2_idle_minutes: exports_external.number().min(0).optional(),
|
|
@@ -30223,7 +30387,8 @@ var AftConfigSchema = exports_external.object({
|
|
|
30223
30387
|
lsp: LspConfigSchema.optional(),
|
|
30224
30388
|
url_fetch_allow_private: exports_external.boolean().optional(),
|
|
30225
30389
|
semantic: SemanticConfigSchema.optional(),
|
|
30226
|
-
max_callgraph_files: exports_external.number().int().positive().optional()
|
|
30390
|
+
max_callgraph_files: exports_external.number().int().positive().optional(),
|
|
30391
|
+
bridge: BridgeConfigSchema.optional()
|
|
30227
30392
|
}).strict();
|
|
30228
30393
|
function normalizeLspExtension(extension) {
|
|
30229
30394
|
return extension.trim().replace(/^\.+/, "");
|
|
@@ -30317,9 +30482,9 @@ function extractCommentsForPreservation(content) {
|
|
|
30317
30482
|
}
|
|
30318
30483
|
return comments;
|
|
30319
30484
|
}
|
|
30320
|
-
function ensureRecordAtPath(root,
|
|
30485
|
+
function ensureRecordAtPath(root, path3) {
|
|
30321
30486
|
let current = root;
|
|
30322
|
-
for (const segment of
|
|
30487
|
+
for (const segment of path3) {
|
|
30323
30488
|
const existing = current[segment];
|
|
30324
30489
|
if (!existing || typeof existing !== "object" || Array.isArray(existing)) {
|
|
30325
30490
|
current[segment] = {};
|
|
@@ -30328,9 +30493,9 @@ function ensureRecordAtPath(root, path2) {
|
|
|
30328
30493
|
}
|
|
30329
30494
|
return current;
|
|
30330
30495
|
}
|
|
30331
|
-
function hasPath(root,
|
|
30496
|
+
function hasPath(root, path3) {
|
|
30332
30497
|
let current = root;
|
|
30333
|
-
for (const segment of
|
|
30498
|
+
for (const segment of path3) {
|
|
30334
30499
|
if (!current || typeof current !== "object" || Array.isArray(current))
|
|
30335
30500
|
return false;
|
|
30336
30501
|
const record2 = current;
|
|
@@ -30340,9 +30505,9 @@ function hasPath(root, path2) {
|
|
|
30340
30505
|
}
|
|
30341
30506
|
return true;
|
|
30342
30507
|
}
|
|
30343
|
-
function setPath(root,
|
|
30344
|
-
const parent = ensureRecordAtPath(root,
|
|
30345
|
-
parent[
|
|
30508
|
+
function setPath(root, path3, value) {
|
|
30509
|
+
const parent = ensureRecordAtPath(root, path3.slice(0, -1));
|
|
30510
|
+
parent[path3[path3.length - 1]] = value;
|
|
30346
30511
|
}
|
|
30347
30512
|
function migrateRawConfig(rawConfig, configPath, logger) {
|
|
30348
30513
|
const oldKeys = [];
|
|
@@ -30631,6 +30796,8 @@ function getStrippedTopLevelKeys(override) {
|
|
|
30631
30796
|
stripped.push("url_fetch_allow_private");
|
|
30632
30797
|
if (override.max_callgraph_files !== undefined)
|
|
30633
30798
|
stripped.push("max_callgraph_files");
|
|
30799
|
+
if (override.bridge !== undefined)
|
|
30800
|
+
stripped.push("bridge");
|
|
30634
30801
|
return stripped;
|
|
30635
30802
|
}
|
|
30636
30803
|
function mergeConfigs(base, override) {
|
|
@@ -30642,6 +30809,7 @@ function mergeConfigs(base, override) {
|
|
|
30642
30809
|
const experimental = mergeExperimentalConfig(base.experimental, override.experimental);
|
|
30643
30810
|
const bash = mergeBashConfig(base.bash, override.bash);
|
|
30644
30811
|
const inspect = mergeInspectConfig(base.inspect, override.inspect);
|
|
30812
|
+
const bridge = base.bridge;
|
|
30645
30813
|
const safeOverride = pickProjectSafeFields(override);
|
|
30646
30814
|
delete safeOverride.bash;
|
|
30647
30815
|
delete safeOverride.inspect;
|
|
@@ -30655,19 +30823,28 @@ function mergeConfigs(base, override) {
|
|
|
30655
30823
|
...inspect !== undefined ? { inspect } : {},
|
|
30656
30824
|
experimental,
|
|
30657
30825
|
semantic,
|
|
30826
|
+
...bridge !== undefined ? { bridge } : {},
|
|
30658
30827
|
...disabledTools.length > 0 ? { disabled_tools: [...new Set(disabledTools)] } : {}
|
|
30659
30828
|
};
|
|
30660
30829
|
}
|
|
30830
|
+
var DEFAULT_BRIDGE_REQUEST_TIMEOUT_MS = 30000;
|
|
30831
|
+
var DEFAULT_BRIDGE_HANG_THRESHOLD = 2;
|
|
30832
|
+
function resolveBridgePoolTransportOptions(config2) {
|
|
30833
|
+
return {
|
|
30834
|
+
timeoutMs: config2.bridge?.request_timeout_ms ?? DEFAULT_BRIDGE_REQUEST_TIMEOUT_MS,
|
|
30835
|
+
hangThreshold: config2.bridge?.hang_threshold ?? DEFAULT_BRIDGE_HANG_THRESHOLD
|
|
30836
|
+
};
|
|
30837
|
+
}
|
|
30661
30838
|
function getGlobalPiDir() {
|
|
30662
|
-
return
|
|
30839
|
+
return join10(homedir8(), ".pi", "agent");
|
|
30663
30840
|
}
|
|
30664
30841
|
function loadAftConfig(projectDirectory) {
|
|
30665
|
-
const userBasePath =
|
|
30842
|
+
const userBasePath = join10(getGlobalPiDir(), "aft");
|
|
30666
30843
|
migrateAftConfigFile(`${userBasePath}.jsonc`);
|
|
30667
30844
|
migrateAftConfigFile(`${userBasePath}.json`);
|
|
30668
30845
|
const userDetected = detectConfigFile(userBasePath);
|
|
30669
30846
|
const userConfigPath = userDetected.format !== "none" ? userDetected.path : `${userBasePath}.json`;
|
|
30670
|
-
const projectBasePath =
|
|
30847
|
+
const projectBasePath = join10(projectDirectory, ".pi", "aft");
|
|
30671
30848
|
migrateAftConfigFile(`${projectBasePath}.jsonc`);
|
|
30672
30849
|
migrateAftConfigFile(`${projectBasePath}.json`);
|
|
30673
30850
|
const projectDetected = detectConfigFile(projectBasePath);
|
|
@@ -30704,7 +30881,7 @@ import {
|
|
|
30704
30881
|
statSync as statSync5,
|
|
30705
30882
|
writeFileSync as writeFileSync5
|
|
30706
30883
|
} from "node:fs";
|
|
30707
|
-
import { join as
|
|
30884
|
+
import { join as join13 } from "node:path";
|
|
30708
30885
|
|
|
30709
30886
|
// src/lsp-cache.ts
|
|
30710
30887
|
import {
|
|
@@ -30716,36 +30893,36 @@ import {
|
|
|
30716
30893
|
unlinkSync as unlinkSync5,
|
|
30717
30894
|
writeFileSync as writeFileSync4
|
|
30718
30895
|
} from "node:fs";
|
|
30719
|
-
import { homedir as
|
|
30720
|
-
import { join as
|
|
30896
|
+
import { homedir as homedir9 } from "node:os";
|
|
30897
|
+
import { join as join11 } from "node:path";
|
|
30721
30898
|
function aftCacheBase() {
|
|
30722
30899
|
const override = process.env.AFT_CACHE_DIR;
|
|
30723
30900
|
if (override && override.length > 0)
|
|
30724
30901
|
return override;
|
|
30725
30902
|
if (process.platform === "win32") {
|
|
30726
30903
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
30727
|
-
const base2 = localAppData ||
|
|
30728
|
-
return
|
|
30904
|
+
const base2 = localAppData || join11(homedir9(), "AppData", "Local");
|
|
30905
|
+
return join11(base2, "aft");
|
|
30729
30906
|
}
|
|
30730
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
30731
|
-
return
|
|
30907
|
+
const base = process.env.XDG_CACHE_HOME || join11(homedir9(), ".cache");
|
|
30908
|
+
return join11(base, "aft");
|
|
30732
30909
|
}
|
|
30733
30910
|
function lspCacheRoot() {
|
|
30734
|
-
return
|
|
30911
|
+
return join11(aftCacheBase(), "lsp-packages");
|
|
30735
30912
|
}
|
|
30736
30913
|
function lspPackageDir(npmPackage) {
|
|
30737
|
-
return
|
|
30914
|
+
return join11(lspCacheRoot(), encodeURIComponent(npmPackage));
|
|
30738
30915
|
}
|
|
30739
30916
|
function lspBinaryPath(npmPackage, binary) {
|
|
30740
|
-
return
|
|
30917
|
+
return join11(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
|
|
30741
30918
|
}
|
|
30742
30919
|
function lspBinDir(npmPackage) {
|
|
30743
|
-
return
|
|
30920
|
+
return join11(lspPackageDir(npmPackage), "node_modules", ".bin");
|
|
30744
30921
|
}
|
|
30745
30922
|
function isInstalled(npmPackage, binary) {
|
|
30746
30923
|
for (const candidate of lspBinaryCandidates(binary)) {
|
|
30747
30924
|
try {
|
|
30748
|
-
if (statSync4(
|
|
30925
|
+
if (statSync4(join11(lspBinDir(npmPackage), candidate)).isFile())
|
|
30749
30926
|
return true;
|
|
30750
30927
|
} catch {}
|
|
30751
30928
|
}
|
|
@@ -30765,17 +30942,17 @@ function writeInstalledMetaIn(installDir, version2, sha256) {
|
|
|
30765
30942
|
installedAt: new Date().toISOString(),
|
|
30766
30943
|
...sha256 ? { sha256 } : {}
|
|
30767
30944
|
};
|
|
30768
|
-
writeFileSync4(
|
|
30945
|
+
writeFileSync4(join11(installDir, INSTALLED_META_FILE), JSON.stringify(meta3), "utf8");
|
|
30769
30946
|
} catch (err) {
|
|
30770
30947
|
log2(`[lsp-cache] failed to write installed-meta in ${installDir}: ${err}`);
|
|
30771
30948
|
}
|
|
30772
30949
|
}
|
|
30773
30950
|
function readInstalledMetaIn(installDir) {
|
|
30774
|
-
const
|
|
30951
|
+
const path3 = join11(installDir, INSTALLED_META_FILE);
|
|
30775
30952
|
try {
|
|
30776
|
-
if (!statSync4(
|
|
30953
|
+
if (!statSync4(path3).isFile())
|
|
30777
30954
|
return null;
|
|
30778
|
-
const raw = readFileSync5(
|
|
30955
|
+
const raw = readFileSync5(path3, "utf8");
|
|
30779
30956
|
const parsed = JSON.parse(raw);
|
|
30780
30957
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
30781
30958
|
return null;
|
|
@@ -30795,7 +30972,7 @@ function readInstalledMeta(packageKey) {
|
|
|
30795
30972
|
return readInstalledMetaIn(lspPackageDir(packageKey));
|
|
30796
30973
|
}
|
|
30797
30974
|
function lockPath(npmPackage) {
|
|
30798
|
-
return
|
|
30975
|
+
return join11(lspPackageDir(npmPackage), ".aft-installing");
|
|
30799
30976
|
}
|
|
30800
30977
|
var STALE_LOCK_MS2 = 30 * 60 * 1000;
|
|
30801
30978
|
function acquireInstallLock(lockKey) {
|
|
@@ -30902,7 +31079,7 @@ async function withInstallLock(lockKey, task) {
|
|
|
30902
31079
|
}
|
|
30903
31080
|
var VERSION_CHECK_FILE = ".aft-version-check";
|
|
30904
31081
|
function readVersionCheck(npmPackage) {
|
|
30905
|
-
const file2 =
|
|
31082
|
+
const file2 = join11(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
|
|
30906
31083
|
try {
|
|
30907
31084
|
const raw = readFileSync5(file2, "utf8");
|
|
30908
31085
|
const parsed = JSON.parse(raw);
|
|
@@ -30919,7 +31096,7 @@ function readVersionCheck(npmPackage) {
|
|
|
30919
31096
|
}
|
|
30920
31097
|
function writeVersionCheck(npmPackage, latest) {
|
|
30921
31098
|
mkdirSync6(lspPackageDir(npmPackage), { recursive: true });
|
|
30922
|
-
const file2 =
|
|
31099
|
+
const file2 = join11(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
|
|
30923
31100
|
const record2 = {
|
|
30924
31101
|
last_checked: new Date().toISOString(),
|
|
30925
31102
|
latest_eligible: latest
|
|
@@ -31082,7 +31259,7 @@ var NPM_LSP_TABLE = [
|
|
|
31082
31259
|
|
|
31083
31260
|
// src/lsp-project-relevance.ts
|
|
31084
31261
|
import { existsSync as existsSync7, readdirSync as readdirSync3, readFileSync as readFileSync6 } from "node:fs";
|
|
31085
|
-
import { join as
|
|
31262
|
+
import { join as join12 } from "node:path";
|
|
31086
31263
|
var MAX_WALK_DIRS = 200;
|
|
31087
31264
|
var MAX_WALK_DEPTH = 4;
|
|
31088
31265
|
var NOISE_DIRS = new Set([
|
|
@@ -31099,7 +31276,7 @@ function hasRootMarker(projectRoot, rootMarkers) {
|
|
|
31099
31276
|
if (!rootMarkers)
|
|
31100
31277
|
return false;
|
|
31101
31278
|
for (const marker of rootMarkers) {
|
|
31102
|
-
if (existsSync7(
|
|
31279
|
+
if (existsSync7(join12(projectRoot, marker)))
|
|
31103
31280
|
return true;
|
|
31104
31281
|
}
|
|
31105
31282
|
return false;
|
|
@@ -31123,7 +31300,7 @@ function hasPackageJsonDep(projectRoot, depNames) {
|
|
|
31123
31300
|
}
|
|
31124
31301
|
function readPackageJson(projectRoot) {
|
|
31125
31302
|
try {
|
|
31126
|
-
const raw = readFileSync6(
|
|
31303
|
+
const raw = readFileSync6(join12(projectRoot, "package.json"), "utf8");
|
|
31127
31304
|
const parsed = JSON.parse(raw);
|
|
31128
31305
|
if (typeof parsed !== "object" || parsed === null)
|
|
31129
31306
|
return null;
|
|
@@ -31153,7 +31330,7 @@ function relevantExtensionsInProject(projectRoot, extToServer) {
|
|
|
31153
31330
|
for (const entry of entries) {
|
|
31154
31331
|
if (entry.isDirectory()) {
|
|
31155
31332
|
if (current.depth < MAX_WALK_DEPTH && !NOISE_DIRS.has(entry.name.toLowerCase())) {
|
|
31156
|
-
queue.push({ dir:
|
|
31333
|
+
queue.push({ dir: join12(current.dir, entry.name), depth: current.depth + 1 });
|
|
31157
31334
|
}
|
|
31158
31335
|
continue;
|
|
31159
31336
|
}
|
|
@@ -31280,7 +31457,7 @@ async function resolveTargetVersion(spec, config2, fetchImpl = fetch) {
|
|
|
31280
31457
|
}
|
|
31281
31458
|
function ensureInstallAnchor(cwd) {
|
|
31282
31459
|
try {
|
|
31283
|
-
const stub =
|
|
31460
|
+
const stub = join13(cwd, "package.json");
|
|
31284
31461
|
if (!existsSync8(stub)) {
|
|
31285
31462
|
writeFileSync5(stub, `${JSON.stringify({ name: "aft-lsp-cache", version: "0.0.0", private: true })}
|
|
31286
31463
|
`);
|
|
@@ -31290,18 +31467,18 @@ function ensureInstallAnchor(cwd) {
|
|
|
31290
31467
|
}
|
|
31291
31468
|
}
|
|
31292
31469
|
function runInstall(spec, version2, cwd, signal) {
|
|
31293
|
-
return new Promise((
|
|
31470
|
+
return new Promise((resolve3) => {
|
|
31294
31471
|
const target = `${spec.npm}@${version2}`;
|
|
31295
31472
|
log2(`[lsp] installing ${target} to ${cwd}`);
|
|
31296
31473
|
if (signal?.aborted) {
|
|
31297
31474
|
warn2(`[lsp] install ${target} aborted before spawn`);
|
|
31298
|
-
|
|
31475
|
+
resolve3(false);
|
|
31299
31476
|
return;
|
|
31300
31477
|
}
|
|
31301
31478
|
const npm = resolveNpm();
|
|
31302
31479
|
if (!npm) {
|
|
31303
31480
|
warn2(`[lsp] npm not found on PATH or known locations; cannot install ${target}`);
|
|
31304
|
-
|
|
31481
|
+
resolve3(false);
|
|
31305
31482
|
return;
|
|
31306
31483
|
}
|
|
31307
31484
|
ensureInstallAnchor(cwd);
|
|
@@ -31324,7 +31501,7 @@ function runInstall(spec, version2, cwd, signal) {
|
|
|
31324
31501
|
return;
|
|
31325
31502
|
settled = true;
|
|
31326
31503
|
cleanup();
|
|
31327
|
-
|
|
31504
|
+
resolve3(ok);
|
|
31328
31505
|
};
|
|
31329
31506
|
const onAbort = () => {
|
|
31330
31507
|
warn2(`[lsp] install ${target} aborted during shutdown`);
|
|
@@ -31425,7 +31602,7 @@ function cachedPackageDir(npmPackage) {
|
|
|
31425
31602
|
return lspBinDir(npmPackage).replace(/[\\/]node_modules[\\/]\.bin[\\/]?$/, "");
|
|
31426
31603
|
}
|
|
31427
31604
|
function hashInstalledBinary(spec) {
|
|
31428
|
-
return new Promise((
|
|
31605
|
+
return new Promise((resolve3, reject) => {
|
|
31429
31606
|
const candidates = process.platform === "win32" ? [
|
|
31430
31607
|
lspBinaryPath(spec.npm, spec.binary),
|
|
31431
31608
|
lspBinaryPath(spec.npm, `${spec.binary}.cmd`),
|
|
@@ -31449,7 +31626,7 @@ function hashInstalledBinary(spec) {
|
|
|
31449
31626
|
const stream = createReadStream(pathToHash);
|
|
31450
31627
|
stream.on("error", reject);
|
|
31451
31628
|
stream.on("data", (chunk) => hash2.update(chunk));
|
|
31452
|
-
stream.on("end", () =>
|
|
31629
|
+
stream.on("end", () => resolve3(hash2.digest("hex")));
|
|
31453
31630
|
});
|
|
31454
31631
|
}
|
|
31455
31632
|
function installedBinaryPath(spec) {
|
|
@@ -31467,15 +31644,15 @@ function installedBinaryPath(spec) {
|
|
|
31467
31644
|
}
|
|
31468
31645
|
return null;
|
|
31469
31646
|
}
|
|
31470
|
-
function sha256OfFileSync(
|
|
31471
|
-
return createHash3("sha256").update(readFileSync7(
|
|
31647
|
+
function sha256OfFileSync(path3) {
|
|
31648
|
+
return createHash3("sha256").update(readFileSync7(path3)).digest("hex");
|
|
31472
31649
|
}
|
|
31473
31650
|
function quarantineCachedNpmInstall(spec, reason) {
|
|
31474
31651
|
const packageDir = lspPackageDir(spec.npm);
|
|
31475
|
-
const dest =
|
|
31652
|
+
const dest = join13(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
|
|
31476
31653
|
warn2(`[lsp] tofu_mismatch ${spec.npm}: ${reason}; quarantining ${packageDir} -> ${dest}`);
|
|
31477
31654
|
try {
|
|
31478
|
-
mkdirSync7(
|
|
31655
|
+
mkdirSync7(join13(dest, ".."), { recursive: true });
|
|
31479
31656
|
rmSync3(dest, { recursive: true, force: true });
|
|
31480
31657
|
renameSync5(packageDir, dest);
|
|
31481
31658
|
} catch (err) {
|
|
@@ -31570,7 +31747,7 @@ import {
|
|
|
31570
31747
|
unlinkSync as unlinkSync6,
|
|
31571
31748
|
writeFileSync as writeFileSync6
|
|
31572
31749
|
} from "node:fs";
|
|
31573
|
-
import { dirname as dirname5, join as
|
|
31750
|
+
import { dirname as dirname5, join as join14, relative as relative3, resolve as resolve3 } from "node:path";
|
|
31574
31751
|
import { Readable as Readable3 } from "node:stream";
|
|
31575
31752
|
import { pipeline as pipeline3 } from "node:stream/promises";
|
|
31576
31753
|
|
|
@@ -31660,26 +31837,26 @@ function detectHostPlatform() {
|
|
|
31660
31837
|
|
|
31661
31838
|
// src/lsp-github-install.ts
|
|
31662
31839
|
function ghCacheRoot() {
|
|
31663
|
-
return
|
|
31840
|
+
return join14(aftCacheBase(), "lsp-binaries");
|
|
31664
31841
|
}
|
|
31665
31842
|
function ghPackageDir(spec) {
|
|
31666
|
-
return
|
|
31843
|
+
return join14(ghCacheRoot(), spec.id);
|
|
31667
31844
|
}
|
|
31668
31845
|
function ghBinDir(spec) {
|
|
31669
|
-
return
|
|
31846
|
+
return join14(ghPackageDir(spec), "bin");
|
|
31670
31847
|
}
|
|
31671
31848
|
function ghExtractDir(spec) {
|
|
31672
|
-
return
|
|
31849
|
+
return join14(ghPackageDir(spec), "extracted");
|
|
31673
31850
|
}
|
|
31674
31851
|
var INSTALLED_META_FILE2 = ".aft-installed";
|
|
31675
31852
|
function ghBinaryPath(spec, platform) {
|
|
31676
31853
|
const ext = platform === "win32" ? ".exe" : "";
|
|
31677
|
-
return
|
|
31854
|
+
return join14(ghBinDir(spec), `${spec.binary}${ext}`);
|
|
31678
31855
|
}
|
|
31679
31856
|
function isGithubInstalled(spec, platform) {
|
|
31680
31857
|
for (const candidate of ghBinaryCandidates(spec, platform)) {
|
|
31681
31858
|
try {
|
|
31682
|
-
if (statSync6(
|
|
31859
|
+
if (statSync6(join14(ghBinDir(spec), candidate)).isFile())
|
|
31683
31860
|
return true;
|
|
31684
31861
|
} catch {}
|
|
31685
31862
|
}
|
|
@@ -31692,10 +31869,10 @@ function ghBinaryCandidates(spec, platform) {
|
|
|
31692
31869
|
}
|
|
31693
31870
|
function readGithubInstalledMetaIn(installDir) {
|
|
31694
31871
|
try {
|
|
31695
|
-
const
|
|
31696
|
-
if (!statSync6(
|
|
31872
|
+
const path3 = join14(installDir, INSTALLED_META_FILE2);
|
|
31873
|
+
if (!statSync6(path3).isFile())
|
|
31697
31874
|
return null;
|
|
31698
|
-
const parsed = JSON.parse(readFileSync8(
|
|
31875
|
+
const parsed = JSON.parse(readFileSync8(path3, "utf8"));
|
|
31699
31876
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
31700
31877
|
return null;
|
|
31701
31878
|
return {
|
|
@@ -31719,24 +31896,24 @@ function writeGithubInstalledMetaIn(installDir, version2, binarySha256, archiveS
|
|
|
31719
31896
|
binarySha256,
|
|
31720
31897
|
...archiveSha256 ? { archiveSha256 } : {}
|
|
31721
31898
|
};
|
|
31722
|
-
writeFileSync6(
|
|
31899
|
+
writeFileSync6(join14(installDir, INSTALLED_META_FILE2), JSON.stringify(meta3), "utf8");
|
|
31723
31900
|
} catch (err) {
|
|
31724
31901
|
warn2(`[lsp] failed to write github installed metadata in ${installDir}: ${err}`);
|
|
31725
31902
|
}
|
|
31726
31903
|
}
|
|
31727
31904
|
var MAX_DOWNLOAD_BYTES3 = 256 * 1024 * 1024;
|
|
31728
31905
|
var MAX_EXTRACT_BYTES2 = 1024 * 1024 * 1024;
|
|
31729
|
-
function sha256OfFile(
|
|
31730
|
-
return new Promise((
|
|
31906
|
+
function sha256OfFile(path3) {
|
|
31907
|
+
return new Promise((resolve4, reject) => {
|
|
31731
31908
|
const hash2 = createHash4("sha256");
|
|
31732
|
-
const stream = createReadStream2(
|
|
31909
|
+
const stream = createReadStream2(path3);
|
|
31733
31910
|
stream.on("error", reject);
|
|
31734
31911
|
stream.on("data", (chunk) => hash2.update(chunk));
|
|
31735
|
-
stream.on("end", () =>
|
|
31912
|
+
stream.on("end", () => resolve4(hash2.digest("hex")));
|
|
31736
31913
|
});
|
|
31737
31914
|
}
|
|
31738
|
-
function sha256OfFileSync2(
|
|
31739
|
-
return createHash4("sha256").update(readFileSync8(
|
|
31915
|
+
function sha256OfFileSync2(path3) {
|
|
31916
|
+
return createHash4("sha256").update(readFileSync8(path3)).digest("hex");
|
|
31740
31917
|
}
|
|
31741
31918
|
async function fetchReleaseByTag(githubRepo, tag, fetchImpl, signal) {
|
|
31742
31919
|
const candidates = [];
|
|
@@ -31968,7 +32145,7 @@ function validateExtraction(stagingRoot) {
|
|
|
31968
32145
|
throw new Error(`failed to read staging dir ${dir}: ${err}`);
|
|
31969
32146
|
}
|
|
31970
32147
|
for (const entry of entries) {
|
|
31971
|
-
const full =
|
|
32148
|
+
const full = join14(dir, entry);
|
|
31972
32149
|
let lst;
|
|
31973
32150
|
try {
|
|
31974
32151
|
lst = lstatSync2(full);
|
|
@@ -31980,7 +32157,7 @@ function validateExtraction(stagingRoot) {
|
|
|
31980
32157
|
try {
|
|
31981
32158
|
target = readlinkSync2(full);
|
|
31982
32159
|
} catch {}
|
|
31983
|
-
throw new Error(`archive contains symlink ${
|
|
32160
|
+
throw new Error(`archive contains symlink ${relative3(realStagingRoot, full)} → ${target}; rejecting (zip-slip defense)`);
|
|
31984
32161
|
}
|
|
31985
32162
|
let realFull;
|
|
31986
32163
|
try {
|
|
@@ -31988,8 +32165,8 @@ function validateExtraction(stagingRoot) {
|
|
|
31988
32165
|
} catch (err) {
|
|
31989
32166
|
throw new Error(`failed to realpath ${full}: ${err}`);
|
|
31990
32167
|
}
|
|
31991
|
-
const rel =
|
|
31992
|
-
if (rel.startsWith("..") ||
|
|
32168
|
+
const rel = relative3(realStagingRoot, realFull);
|
|
32169
|
+
if (rel.startsWith("..") || resolve3(realStagingRoot, rel) !== realFull) {
|
|
31993
32170
|
throw new Error(`archive entry escapes staging root: ${full} → ${realFull} (zip-slip defense)`);
|
|
31994
32171
|
}
|
|
31995
32172
|
if (lst.isDirectory()) {
|
|
@@ -32056,7 +32233,7 @@ function extractArchiveSafely(archivePath, destDir, archiveType) {
|
|
|
32056
32233
|
}
|
|
32057
32234
|
function quarantineCachedGithubInstall(spec, reason) {
|
|
32058
32235
|
const packageDir = ghPackageDir(spec);
|
|
32059
|
-
const dest =
|
|
32236
|
+
const dest = join14(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
|
|
32060
32237
|
warn2(`[lsp] tofu_mismatch ${spec.id}: ${reason}; quarantining ${packageDir} -> ${dest}`);
|
|
32061
32238
|
try {
|
|
32062
32239
|
mkdirSync8(dirname5(dest), { recursive: true });
|
|
@@ -32069,7 +32246,7 @@ function quarantineCachedGithubInstall(spec, reason) {
|
|
|
32069
32246
|
function validateCachedGithubInstall(spec, platform) {
|
|
32070
32247
|
const packageDir = ghPackageDir(spec);
|
|
32071
32248
|
const meta3 = readGithubInstalledMetaIn(packageDir);
|
|
32072
|
-
const binaryPath = ghBinaryCandidates(spec, platform).map((candidate) =>
|
|
32249
|
+
const binaryPath = ghBinaryCandidates(spec, platform).map((candidate) => join14(ghBinDir(spec), candidate)).find((candidate) => {
|
|
32073
32250
|
try {
|
|
32074
32251
|
return statSync6(candidate).isFile();
|
|
32075
32252
|
} catch {
|
|
@@ -32147,7 +32324,7 @@ async function downloadAndInstall(spec, tag, assets, platform, arch, fetchImpl,
|
|
|
32147
32324
|
}
|
|
32148
32325
|
const pkgDir = ghPackageDir(spec);
|
|
32149
32326
|
const extractDir = ghExtractDir(spec);
|
|
32150
|
-
const archivePath =
|
|
32327
|
+
const archivePath = join14(pkgDir, expected.name);
|
|
32151
32328
|
log2(`[lsp] downloading ${spec.id} ${tag} → ${matchingAsset.url}`);
|
|
32152
32329
|
try {
|
|
32153
32330
|
await downloadFile(matchingAsset.url, archivePath, fetchImpl, matchingAsset.size, signal);
|
|
@@ -32187,7 +32364,7 @@ async function downloadAndInstall(spec, tag, assets, platform, arch, fetchImpl,
|
|
|
32187
32364
|
unlinkSync6(archivePath);
|
|
32188
32365
|
} catch {}
|
|
32189
32366
|
}
|
|
32190
|
-
const innerBinaryPath =
|
|
32367
|
+
const innerBinaryPath = join14(extractDir, spec.binaryPathInArchive(platform, arch, version2));
|
|
32191
32368
|
if (!existsSync9(innerBinaryPath)) {
|
|
32192
32369
|
error2(`[lsp] ${spec.id}: extracted binary not found at ${innerBinaryPath}`);
|
|
32193
32370
|
return null;
|
|
@@ -32585,7 +32762,7 @@ function renderScreen(state, rows = state.rows, cols = state.cols) {
|
|
|
32585
32762
|
`);
|
|
32586
32763
|
}
|
|
32587
32764
|
function writeTerminal(terminal, data) {
|
|
32588
|
-
return new Promise((
|
|
32765
|
+
return new Promise((resolve4) => terminal.write(data, resolve4));
|
|
32589
32766
|
}
|
|
32590
32767
|
|
|
32591
32768
|
// src/shutdown-hooks.ts
|
|
@@ -32642,8 +32819,8 @@ function installProcessHandlers() {
|
|
|
32642
32819
|
}
|
|
32643
32820
|
signalShutdownStarted = true;
|
|
32644
32821
|
process.exitCode = SIGNAL_EXIT_CODES[sig];
|
|
32645
|
-
const timeout = new Promise((
|
|
32646
|
-
setTimeout(
|
|
32822
|
+
const timeout = new Promise((resolve4) => {
|
|
32823
|
+
setTimeout(resolve4, SIGNAL_CLEANUP_TIMEOUT_MS);
|
|
32647
32824
|
});
|
|
32648
32825
|
Promise.race([runCleanups(sig), timeout]).finally(() => {
|
|
32649
32826
|
process.exit(SIGNAL_EXIT_CODES[sig]);
|
|
@@ -32685,8 +32862,8 @@ import { Type as Type3 } from "typebox";
|
|
|
32685
32862
|
|
|
32686
32863
|
// src/tools/hoisted.ts
|
|
32687
32864
|
import { stat } from "node:fs/promises";
|
|
32688
|
-
import { homedir as
|
|
32689
|
-
import { isAbsolute as
|
|
32865
|
+
import { homedir as homedir10 } from "node:os";
|
|
32866
|
+
import { isAbsolute as isAbsolute4, relative as relative4, resolve as resolve4, sep } from "node:path";
|
|
32690
32867
|
import {
|
|
32691
32868
|
renderDiff
|
|
32692
32869
|
} from "@earendil-works/pi-coding-agent";
|
|
@@ -32800,18 +32977,72 @@ function diagnosticsOnEditDefault(ctx) {
|
|
|
32800
32977
|
return ctx.config.lsp?.diagnostics_on_edit ?? false;
|
|
32801
32978
|
}
|
|
32802
32979
|
function containsPath(parent, child) {
|
|
32803
|
-
const rel =
|
|
32804
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
32980
|
+
const rel = relative4(parent, child);
|
|
32981
|
+
return rel === "" || !rel.startsWith("..") && !isAbsolute4(rel);
|
|
32982
|
+
}
|
|
32983
|
+
function expandTilde2(path3) {
|
|
32984
|
+
if (!path3 || !path3.startsWith("~"))
|
|
32985
|
+
return path3;
|
|
32986
|
+
if (path3 === "~")
|
|
32987
|
+
return homedir10();
|
|
32988
|
+
if (path3.startsWith(`~${sep}`) || path3.startsWith("~/")) {
|
|
32989
|
+
return resolve4(homedir10(), path3.slice(2));
|
|
32990
|
+
}
|
|
32991
|
+
return path3;
|
|
32992
|
+
}
|
|
32993
|
+
function absoluteSearchPath(cwd, target) {
|
|
32994
|
+
const expanded = expandTilde2(target);
|
|
32995
|
+
return isAbsolute4(expanded) ? expanded : resolve4(cwd, expanded);
|
|
32996
|
+
}
|
|
32997
|
+
async function searchPathExists(cwd, target) {
|
|
32998
|
+
try {
|
|
32999
|
+
await stat(absoluteSearchPath(cwd, target));
|
|
33000
|
+
return true;
|
|
33001
|
+
} catch {
|
|
33002
|
+
return false;
|
|
33003
|
+
}
|
|
33004
|
+
}
|
|
33005
|
+
async function splitSearchPathArg(cwd, raw) {
|
|
33006
|
+
if (await searchPathExists(cwd, raw) || !/\s/.test(raw)) {
|
|
33007
|
+
return { paths: [raw], missing: [] };
|
|
33008
|
+
}
|
|
33009
|
+
const fragments = raw.trim().split(/\s+/).filter(Boolean);
|
|
33010
|
+
if (fragments.length < 2) {
|
|
33011
|
+
return { paths: [raw], missing: [] };
|
|
33012
|
+
}
|
|
33013
|
+
const existing = [];
|
|
33014
|
+
const missing = [];
|
|
33015
|
+
for (const fragment of fragments) {
|
|
33016
|
+
if (await searchPathExists(cwd, fragment)) {
|
|
33017
|
+
existing.push(fragment);
|
|
33018
|
+
} else {
|
|
33019
|
+
missing.push(fragment);
|
|
33020
|
+
}
|
|
33021
|
+
}
|
|
33022
|
+
if (existing.length === 0) {
|
|
33023
|
+
return { paths: [raw], missing: [] };
|
|
33024
|
+
}
|
|
33025
|
+
return { paths: existing, missing };
|
|
32805
33026
|
}
|
|
32806
|
-
function
|
|
32807
|
-
if (
|
|
32808
|
-
return
|
|
32809
|
-
if (path2 === "~")
|
|
32810
|
-
return homedir9();
|
|
32811
|
-
if (path2.startsWith(`~${sep}`) || path2.startsWith("~/")) {
|
|
32812
|
-
return resolve3(homedir9(), path2.slice(2));
|
|
33027
|
+
async function bridgeSearchPathArg(cwd, split) {
|
|
33028
|
+
if (split.paths.length === 1 && split.missing.length === 0) {
|
|
33029
|
+
return await resolvePathArg(cwd, split.paths[0]);
|
|
32813
33030
|
}
|
|
32814
|
-
return
|
|
33031
|
+
return split.paths.map((target) => absoluteSearchPath(cwd, target)).join(" ");
|
|
33032
|
+
}
|
|
33033
|
+
function formatSkippedSearchPaths(missing) {
|
|
33034
|
+
if (missing.length === 0)
|
|
33035
|
+
return;
|
|
33036
|
+
const noun = missing.length === 1 ? "path" : "paths";
|
|
33037
|
+
return `Skipped ${missing.length} ${noun} not found: ${missing.join(", ")}`;
|
|
33038
|
+
}
|
|
33039
|
+
function appendSkippedSearchPaths(text, missing) {
|
|
33040
|
+
const note = formatSkippedSearchPaths(missing);
|
|
33041
|
+
if (!note)
|
|
33042
|
+
return text;
|
|
33043
|
+
return text.length > 0 ? `${text}
|
|
33044
|
+
|
|
33045
|
+
${note}` : note;
|
|
32815
33046
|
}
|
|
32816
33047
|
function externalDirectoryPromptTimeoutMs() {
|
|
32817
33048
|
const raw = process.env.AFT_PI_EXTERNAL_PROMPT_TIMEOUT_MS;
|
|
@@ -32823,8 +33054,8 @@ function externalDirectoryPromptTimeoutMs() {
|
|
|
32823
33054
|
async function assertExternalDirectoryPermission(extCtx, target, action = "modify", options = {}) {
|
|
32824
33055
|
if (!target)
|
|
32825
33056
|
return;
|
|
32826
|
-
const expanded =
|
|
32827
|
-
const absoluteTarget =
|
|
33057
|
+
const expanded = expandTilde2(target);
|
|
33058
|
+
const absoluteTarget = isAbsolute4(expanded) ? expanded : resolve4(extCtx.cwd, expanded);
|
|
32828
33059
|
if (containsPath(extCtx.cwd, absoluteTarget))
|
|
32829
33060
|
return;
|
|
32830
33061
|
if (options.restrictToProjectRoot === false)
|
|
@@ -32835,8 +33066,8 @@ async function assertExternalDirectoryPermission(extCtx, target, action = "modif
|
|
|
32835
33066
|
}
|
|
32836
33067
|
const timeoutMs = externalDirectoryPromptTimeoutMs();
|
|
32837
33068
|
let timer;
|
|
32838
|
-
const timeoutPromise = new Promise((
|
|
32839
|
-
timer = setTimeout(() =>
|
|
33069
|
+
const timeoutPromise = new Promise((resolve5) => {
|
|
33070
|
+
timer = setTimeout(() => resolve5("timeout"), timeoutMs);
|
|
32840
33071
|
});
|
|
32841
33072
|
try {
|
|
32842
33073
|
const result = await Promise.race([
|
|
@@ -32900,8 +33131,12 @@ function registerHoistedTools(pi, ctx, surface) {
|
|
|
32900
33131
|
const bridge = bridgeFor(ctx, extCtx.cwd);
|
|
32901
33132
|
const offset = coerceOptionalInt(params.offset, "offset", 1, Number.MAX_SAFE_INTEGER);
|
|
32902
33133
|
const limit = coerceOptionalInt(params.limit, "limit", 1, Number.MAX_SAFE_INTEGER);
|
|
33134
|
+
const filePath = await resolvePathArg(extCtx.cwd, params.path);
|
|
33135
|
+
await assertExternalDirectoryPermission(extCtx, filePath, "read", {
|
|
33136
|
+
restrictToProjectRoot: surface.restrictToProjectRoot
|
|
33137
|
+
});
|
|
32903
33138
|
const req = {
|
|
32904
|
-
file:
|
|
33139
|
+
file: filePath
|
|
32905
33140
|
};
|
|
32906
33141
|
if (offset !== undefined) {
|
|
32907
33142
|
req.start_line = offset;
|
|
@@ -32918,7 +33153,7 @@ function registerHoistedTools(pi, ctx, surface) {
|
|
|
32918
33153
|
}
|
|
32919
33154
|
let text = response.content ?? "";
|
|
32920
33155
|
const agentSpecifiedRange = offset !== undefined || limit !== undefined;
|
|
32921
|
-
const footer =
|
|
33156
|
+
const footer = formatReadFooter2(agentSpecifiedRange, response);
|
|
32922
33157
|
if (footer)
|
|
32923
33158
|
text += footer;
|
|
32924
33159
|
return textResult(text);
|
|
@@ -33018,19 +33253,26 @@ function registerHoistedTools(pi, ctx, surface) {
|
|
|
33018
33253
|
async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
|
|
33019
33254
|
const bridge = bridgeFor(ctx, extCtx.cwd);
|
|
33020
33255
|
const req = { pattern: params.pattern };
|
|
33256
|
+
let pathSplit;
|
|
33021
33257
|
if (params.path) {
|
|
33022
|
-
await
|
|
33023
|
-
|
|
33024
|
-
|
|
33025
|
-
|
|
33258
|
+
pathSplit = await splitSearchPathArg(extCtx.cwd, params.path);
|
|
33259
|
+
for (const target of pathSplit.paths) {
|
|
33260
|
+
await assertExternalDirectoryPermission(extCtx, absoluteSearchPath(extCtx.cwd, target), "search", {
|
|
33261
|
+
restrictToProjectRoot: surface.restrictToProjectRoot
|
|
33262
|
+
});
|
|
33263
|
+
}
|
|
33264
|
+
req.path = await bridgeSearchPathArg(extCtx.cwd, pathSplit);
|
|
33026
33265
|
}
|
|
33027
33266
|
if (params.include)
|
|
33028
33267
|
req.include = splitIncludeGlobs(params.include);
|
|
33029
33268
|
if (params.caseSensitive !== undefined)
|
|
33030
33269
|
req.case_sensitive = params.caseSensitive;
|
|
33031
33270
|
const response = await callBridge(bridge, "grep", req, extCtx);
|
|
33032
|
-
|
|
33033
|
-
|
|
33271
|
+
if (pathSplit && pathSplit.missing.length > 0) {
|
|
33272
|
+
response.complete = false;
|
|
33273
|
+
}
|
|
33274
|
+
const text = appendSkippedSearchPaths(response.text ?? "", pathSplit?.missing ?? []);
|
|
33275
|
+
return textResult(text, response);
|
|
33034
33276
|
}
|
|
33035
33277
|
});
|
|
33036
33278
|
}
|
|
@@ -33174,15 +33416,15 @@ ${summary}${suffix}`);
|
|
|
33174
33416
|
container.addChild(new Text(renderDiff(diff), 1, 0));
|
|
33175
33417
|
return container;
|
|
33176
33418
|
}
|
|
33177
|
-
function shortenPath(
|
|
33178
|
-
const home =
|
|
33179
|
-
if (
|
|
33180
|
-
return `~${
|
|
33181
|
-
return
|
|
33419
|
+
function shortenPath(path3) {
|
|
33420
|
+
const home = homedir10();
|
|
33421
|
+
if (path3.startsWith(home))
|
|
33422
|
+
return `~${path3.slice(home.length)}`;
|
|
33423
|
+
return path3;
|
|
33182
33424
|
}
|
|
33183
|
-
async function resolvePathArg(cwd,
|
|
33184
|
-
const expanded =
|
|
33185
|
-
const abs =
|
|
33425
|
+
async function resolvePathArg(cwd, path3) {
|
|
33426
|
+
const expanded = expandTilde2(path3);
|
|
33427
|
+
const abs = absoluteSearchPath(cwd, path3);
|
|
33186
33428
|
try {
|
|
33187
33429
|
await stat(abs);
|
|
33188
33430
|
return abs;
|
|
@@ -33220,23 +33462,12 @@ function splitIncludeGlobs(include) {
|
|
|
33220
33462
|
out.push(tail2);
|
|
33221
33463
|
return out;
|
|
33222
33464
|
}
|
|
33223
|
-
function
|
|
33224
|
-
|
|
33225
|
-
return "";
|
|
33226
|
-
if (!data.truncated)
|
|
33227
|
-
return "";
|
|
33228
|
-
const startLine = data.start_line;
|
|
33229
|
-
const endLine = data.end_line;
|
|
33230
|
-
const totalLines = data.total_lines;
|
|
33231
|
-
if (startLine === undefined || endLine === undefined || totalLines === undefined) {
|
|
33232
|
-
return "";
|
|
33233
|
-
}
|
|
33234
|
-
return `
|
|
33235
|
-
(Showing lines ${startLine}-${endLine} of ${totalLines}. Use offset/limit to read other sections.)`;
|
|
33465
|
+
function formatReadFooter2(agentSpecifiedRange, data) {
|
|
33466
|
+
return formatReadFooter(agentSpecifiedRange, data, { rangeHint: "offset/limit" });
|
|
33236
33467
|
}
|
|
33237
33468
|
|
|
33238
33469
|
// src/tools/render-helpers.ts
|
|
33239
|
-
import { homedir as
|
|
33470
|
+
import { homedir as homedir11 } from "node:os";
|
|
33240
33471
|
import { renderDiff as renderDiff2 } from "@earendil-works/pi-coding-agent";
|
|
33241
33472
|
import { Container as Container2, Spacer as Spacer2, Text as Text2 } from "@earendil-works/pi-tui";
|
|
33242
33473
|
function reuseText2(last) {
|
|
@@ -33245,11 +33476,11 @@ function reuseText2(last) {
|
|
|
33245
33476
|
function reuseContainer2(last) {
|
|
33246
33477
|
return last instanceof Container2 ? last : new Container2;
|
|
33247
33478
|
}
|
|
33248
|
-
function shortenPath2(
|
|
33249
|
-
const home =
|
|
33250
|
-
if (
|
|
33251
|
-
return `~${
|
|
33252
|
-
return
|
|
33479
|
+
function shortenPath2(path3) {
|
|
33480
|
+
const home = homedir11();
|
|
33481
|
+
if (path3.startsWith(home))
|
|
33482
|
+
return `~${path3.slice(home.length)}`;
|
|
33483
|
+
return path3;
|
|
33253
33484
|
}
|
|
33254
33485
|
function renderToolCall(toolName, summary, theme, context) {
|
|
33255
33486
|
const text = reuseText2(context.lastComponent);
|
|
@@ -33257,10 +33488,10 @@ function renderToolCall(toolName, summary, theme, context) {
|
|
|
33257
33488
|
text.setText(`${theme.fg("toolTitle", theme.bold(toolName))}${suffix}`);
|
|
33258
33489
|
return text;
|
|
33259
33490
|
}
|
|
33260
|
-
function accentPath(theme,
|
|
33261
|
-
if (!
|
|
33491
|
+
function accentPath(theme, path3) {
|
|
33492
|
+
if (!path3)
|
|
33262
33493
|
return theme.fg("toolOutput", "...");
|
|
33263
|
-
return theme.fg("accent", shortenPath2(
|
|
33494
|
+
return theme.fg("accent", shortenPath2(path3));
|
|
33264
33495
|
}
|
|
33265
33496
|
function collectTextContent(result) {
|
|
33266
33497
|
return result.content.filter((part) => part.type === "text").map((part) => part.text ?? "").join(`
|
|
@@ -33407,7 +33638,7 @@ function renderUnifiedDiff(unifiedDiff) {
|
|
|
33407
33638
|
}
|
|
33408
33639
|
|
|
33409
33640
|
// src/tools/ast.ts
|
|
33410
|
-
var AstLang = StringEnum(["typescript", "tsx", "javascript", "python", "rust", "go", "pascal"], {
|
|
33641
|
+
var AstLang = StringEnum(["typescript", "tsx", "javascript", "python", "rust", "go", "pascal", "r"], {
|
|
33411
33642
|
description: "Target language"
|
|
33412
33643
|
});
|
|
33413
33644
|
var SearchParams = Type3.Object({
|
|
@@ -33448,17 +33679,17 @@ ${warningStrings.map((w) => ` ${w}`).join(`
|
|
|
33448
33679
|
async function resolveAstPaths(extCtx, paths) {
|
|
33449
33680
|
if (isEmptyParam(paths) || !Array.isArray(paths))
|
|
33450
33681
|
return;
|
|
33451
|
-
return Promise.all(paths.filter((
|
|
33682
|
+
return Promise.all(paths.filter((path3) => typeof path3 === "string").map((path3) => resolvePathArg(extCtx.cwd, path3)));
|
|
33452
33683
|
}
|
|
33453
33684
|
async function assertAstPathsPermission(extCtx, paths, action, restrictToProjectRoot) {
|
|
33454
33685
|
if (paths === undefined || paths.length === 0)
|
|
33455
33686
|
return;
|
|
33456
33687
|
const checked = new Set;
|
|
33457
|
-
for (const
|
|
33458
|
-
if (checked.has(
|
|
33688
|
+
for (const path3 of paths) {
|
|
33689
|
+
if (checked.has(path3))
|
|
33459
33690
|
continue;
|
|
33460
|
-
checked.add(
|
|
33461
|
-
await assertExternalDirectoryPermission(extCtx,
|
|
33691
|
+
checked.add(path3);
|
|
33692
|
+
await assertExternalDirectoryPermission(extCtx, path3, action, { restrictToProjectRoot });
|
|
33462
33693
|
}
|
|
33463
33694
|
}
|
|
33464
33695
|
function buildAstSearchSections(payload, theme) {
|
|
@@ -33641,6 +33872,7 @@ var FOREGROUND_POLL_INTERVAL_MS = 100;
|
|
|
33641
33872
|
var BASH_WAIT_POLL_INTERVAL_MS = 100;
|
|
33642
33873
|
var DEFAULT_BASH_STATUS_WAIT_TIMEOUT_MS = 30000;
|
|
33643
33874
|
var MAX_BASH_STATUS_WAIT_TIMEOUT_MS = 300000;
|
|
33875
|
+
var REGEX_WAIT_SCAN_WINDOW_BYTES = 64 * 1024;
|
|
33644
33876
|
function resolveForegroundWaitMs(configured) {
|
|
33645
33877
|
const override = process.env.AFT_TEST_FOREGROUND_WAIT_MS;
|
|
33646
33878
|
if (override !== undefined) {
|
|
@@ -33825,7 +34057,7 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
33825
34057
|
throw new Error(status.message ?? "bash_status failed");
|
|
33826
34058
|
}
|
|
33827
34059
|
if (isTerminalStatus(status.status)) {
|
|
33828
|
-
return bashResult(appendPipeStripNote(withBashHints(formatForegroundResult(status), bridgeCommand, aftSearchRegistered), pipeStrip.note), {
|
|
34060
|
+
return bashResult(appendPipeStripNote(withBashHints(formatForegroundResult(status), bridgeCommand, aftSearchRegistered, extCtx.cwd), pipeStrip.note), {
|
|
33829
34061
|
exit_code: status.exit_code,
|
|
33830
34062
|
duration_ms: status.duration_ms,
|
|
33831
34063
|
truncated: status.output_truncated,
|
|
@@ -33852,7 +34084,7 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
33852
34084
|
task_id: taskId
|
|
33853
34085
|
};
|
|
33854
34086
|
const output = response.output ?? "";
|
|
33855
|
-
return bashResult(appendPipeStripNote(withBashHints(output, bridgeCommand, aftSearchRegistered), pipeStrip.note), details);
|
|
34087
|
+
return bashResult(appendPipeStripNote(withBashHints(output, bridgeCommand, aftSearchRegistered, extCtx.cwd), pipeStrip.note), details);
|
|
33856
34088
|
},
|
|
33857
34089
|
renderCall(args, theme, context) {
|
|
33858
34090
|
return renderBashCall(args?.command, args?.description, theme, context);
|
|
@@ -33866,11 +34098,6 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
33866
34098
|
pi.registerTool(createBashWriteTool(ctx));
|
|
33867
34099
|
pi.registerTool(createBashKillTool(ctx));
|
|
33868
34100
|
}
|
|
33869
|
-
function appendPipeStripNote(output, note) {
|
|
33870
|
-
return note ? `${output}
|
|
33871
|
-
|
|
33872
|
-
${note}` : output;
|
|
33873
|
-
}
|
|
33874
34101
|
function formatBackgroundLaunch(taskId, isPty) {
|
|
33875
34102
|
if (isPty) {
|
|
33876
34103
|
return `PTY task started: ${taskId}. Use bash_status({ task_id: "${taskId}", output_mode: "screen" }) to see the visible terminal, bash_write({ task_id: "${taskId}", input: ... }) to send keystrokes. A completion reminder fires automatically when the task exits.`;
|
|
@@ -33881,35 +34108,8 @@ function formatPromotionMessage(taskId, timeout, waitWindowMs) {
|
|
|
33881
34108
|
const waited = timeout !== undefined ? Math.min(timeout, waitWindowMs) : waitWindowMs;
|
|
33882
34109
|
return `Foreground bash didn't finish within ${formatSeconds(waited)} and was promoted to background: ${taskId}. A completion reminder will be delivered automatically; use bash_status({ task_id: "${taskId}" }) to inspect output or bash_kill({ task_id: "${taskId}" }) to terminate.`;
|
|
33883
34110
|
}
|
|
33884
|
-
function
|
|
33885
|
-
return
|
|
33886
|
-
}
|
|
33887
|
-
function withBashHints(output, command, aftSearchRegistered) {
|
|
33888
|
-
return maybeAppendGrepSearchHint(maybeAppendConflictsHint(output), command, aftSearchRegistered);
|
|
33889
|
-
}
|
|
33890
|
-
function formatForegroundResult(data) {
|
|
33891
|
-
const output = data.output_preview ?? "";
|
|
33892
|
-
const outputPath = data.output_path;
|
|
33893
|
-
const truncated = data.output_truncated === true;
|
|
33894
|
-
const status = data.status;
|
|
33895
|
-
const exit = data.exit_code;
|
|
33896
|
-
let rendered = output;
|
|
33897
|
-
if (truncated && outputPath) {
|
|
33898
|
-
rendered += `
|
|
33899
|
-
[output truncated; full output at ${outputPath}]`;
|
|
33900
|
-
}
|
|
33901
|
-
if (status === "timed_out") {
|
|
33902
|
-
rendered += `
|
|
33903
|
-
[command timed out]`;
|
|
33904
|
-
}
|
|
33905
|
-
if (typeof exit === "number" && exit !== 0) {
|
|
33906
|
-
rendered += `
|
|
33907
|
-
[exit code: ${exit}]`;
|
|
33908
|
-
}
|
|
33909
|
-
return rendered;
|
|
33910
|
-
}
|
|
33911
|
-
function sleep(ms) {
|
|
33912
|
-
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
34111
|
+
function withBashHints(output, command, aftSearchRegistered, projectRoot) {
|
|
34112
|
+
return maybeAppendGrepSearchHint(maybeAppendConflictsHint(output), command, aftSearchRegistered, projectRoot);
|
|
33913
34113
|
}
|
|
33914
34114
|
function createBashStatusTool(ctx) {
|
|
33915
34115
|
return {
|
|
@@ -34076,6 +34276,9 @@ async function waitForBashStatus(ctx, bridge, extCtx, taskId, outputMode, waitFo
|
|
|
34076
34276
|
keepBridgeOnTimeout: true,
|
|
34077
34277
|
transportTimeoutMs: BASH_TRANSPORT_TIMEOUT_MS
|
|
34078
34278
|
};
|
|
34279
|
+
if (waitFor?.kind === "regex") {
|
|
34280
|
+
await validateWaitRegex(bridge, extCtx, waitFor);
|
|
34281
|
+
}
|
|
34079
34282
|
const sessionId = resolveSessionId(extCtx);
|
|
34080
34283
|
clearSyncWatchAbort(sessionId);
|
|
34081
34284
|
if (waitForExit)
|
|
@@ -34092,7 +34295,12 @@ async function waitForBashStatus(ctx, bridge, extCtx, taskId, outputMode, waitFo
|
|
|
34092
34295
|
if (scanText.length === 0)
|
|
34093
34296
|
scanBaseOffset = scan.baseOffset;
|
|
34094
34297
|
scanText += scan.text;
|
|
34095
|
-
|
|
34298
|
+
if (waitFor.kind === "regex") {
|
|
34299
|
+
const trimmed = trimWaitScanBuffer(scanText, scanBaseOffset, waitFor);
|
|
34300
|
+
scanText = trimmed.text;
|
|
34301
|
+
scanBaseOffset = trimmed.baseOffset;
|
|
34302
|
+
}
|
|
34303
|
+
const match = await findWaitMatch(bridge, extCtx, scanText, waitFor);
|
|
34096
34304
|
if (match) {
|
|
34097
34305
|
if (waitForExit && terminal) {
|
|
34098
34306
|
sawTerminal = true;
|
|
@@ -34103,9 +34311,14 @@ async function waitForBashStatus(ctx, bridge, extCtx, taskId, outputMode, waitFo
|
|
|
34103
34311
|
reason: "matched",
|
|
34104
34312
|
elapsed_ms: Date.now() - startedAt,
|
|
34105
34313
|
match: match.text,
|
|
34106
|
-
match_offset: scanBaseOffset +
|
|
34314
|
+
match_offset: scanBaseOffset + match.byteOffset
|
|
34107
34315
|
});
|
|
34108
34316
|
}
|
|
34317
|
+
if (waitFor.kind === "substring") {
|
|
34318
|
+
const trimmed = trimWaitScanBuffer(scanText, scanBaseOffset, waitFor);
|
|
34319
|
+
scanText = trimmed.text;
|
|
34320
|
+
scanBaseOffset = trimmed.baseOffset;
|
|
34321
|
+
}
|
|
34109
34322
|
}
|
|
34110
34323
|
}
|
|
34111
34324
|
if (terminal) {
|
|
@@ -34191,20 +34404,69 @@ function parseWaitPattern(value) {
|
|
|
34191
34404
|
if (typeof value === "string")
|
|
34192
34405
|
return { kind: "substring", value };
|
|
34193
34406
|
if (isRegexWaitObject(value))
|
|
34194
|
-
return { kind: "regex",
|
|
34407
|
+
return { kind: "regex", source: value.regex };
|
|
34195
34408
|
return;
|
|
34196
34409
|
}
|
|
34197
34410
|
function isRegexWaitObject(value) {
|
|
34198
34411
|
return typeof value === "object" && value !== null && "regex" in value && typeof value.regex === "string";
|
|
34199
34412
|
}
|
|
34200
|
-
function
|
|
34413
|
+
async function validateWaitRegex(bridge, extCtx, pattern) {
|
|
34414
|
+
await matchRegexWithBridge(bridge, extCtx, pattern.source, "");
|
|
34415
|
+
}
|
|
34416
|
+
async function findWaitMatch(bridge, extCtx, text, pattern) {
|
|
34201
34417
|
if (pattern.kind === "substring") {
|
|
34202
34418
|
const index = text.indexOf(pattern.value);
|
|
34203
|
-
return index >= 0 ? { text: pattern.value, index } : undefined;
|
|
34419
|
+
return index >= 0 ? { text: pattern.value, byteOffset: Buffer.byteLength(text.slice(0, index), "utf8") } : undefined;
|
|
34204
34420
|
}
|
|
34205
|
-
pattern.
|
|
34206
|
-
|
|
34207
|
-
|
|
34421
|
+
return await matchRegexWithBridge(bridge, extCtx, pattern.source, text);
|
|
34422
|
+
}
|
|
34423
|
+
async function matchRegexWithBridge(bridge, extCtx, pattern, text) {
|
|
34424
|
+
try {
|
|
34425
|
+
const result = await callBashBridge(bridge, "bash_regex_match", { pattern, text }, extCtx);
|
|
34426
|
+
if (result.matched !== true)
|
|
34427
|
+
return;
|
|
34428
|
+
return {
|
|
34429
|
+
text: typeof result.match_text === "string" ? result.match_text : "",
|
|
34430
|
+
byteOffset: coerceMatchOffset(result.match_offset)
|
|
34431
|
+
};
|
|
34432
|
+
} catch (err) {
|
|
34433
|
+
if (err instanceof BridgeError && err.code === "invalid_regex") {
|
|
34434
|
+
throw new Error(`invalid_request: invalid_regex: ${err.message}`);
|
|
34435
|
+
}
|
|
34436
|
+
throw err;
|
|
34437
|
+
}
|
|
34438
|
+
}
|
|
34439
|
+
function coerceMatchOffset(value) {
|
|
34440
|
+
const offset = typeof value === "number" ? value : Number(value ?? 0);
|
|
34441
|
+
return Number.isFinite(offset) && offset >= 0 ? offset : 0;
|
|
34442
|
+
}
|
|
34443
|
+
function trimWaitScanBuffer(text, baseOffset, pattern) {
|
|
34444
|
+
const keepFrom = pattern.kind === "substring" ? substringKeepStart(text, pattern.value) : regexKeepStart(text, REGEX_WAIT_SCAN_WINDOW_BYTES);
|
|
34445
|
+
if (keepFrom <= 0)
|
|
34446
|
+
return { text, baseOffset };
|
|
34447
|
+
return {
|
|
34448
|
+
text: text.slice(keepFrom),
|
|
34449
|
+
baseOffset: baseOffset + Buffer.byteLength(text.slice(0, keepFrom), "utf8")
|
|
34450
|
+
};
|
|
34451
|
+
}
|
|
34452
|
+
function substringKeepStart(text, pattern) {
|
|
34453
|
+
const keepChars = Math.max(0, pattern.length - 1);
|
|
34454
|
+
return text.length > keepChars ? text.length - keepChars : 0;
|
|
34455
|
+
}
|
|
34456
|
+
function regexKeepStart(text, maxBytes) {
|
|
34457
|
+
if (Buffer.byteLength(text, "utf8") <= maxBytes)
|
|
34458
|
+
return 0;
|
|
34459
|
+
let low = 0;
|
|
34460
|
+
let high = text.length;
|
|
34461
|
+
while (low < high) {
|
|
34462
|
+
const mid = Math.floor((low + high) / 2);
|
|
34463
|
+
if (Buffer.byteLength(text.slice(mid), "utf8") > maxBytes) {
|
|
34464
|
+
low = mid + 1;
|
|
34465
|
+
} else {
|
|
34466
|
+
high = mid;
|
|
34467
|
+
}
|
|
34468
|
+
}
|
|
34469
|
+
return low;
|
|
34208
34470
|
}
|
|
34209
34471
|
function withWaited(data, waited) {
|
|
34210
34472
|
return { ...data, waited };
|
|
@@ -34280,9 +34542,6 @@ function ptyCacheKey(extCtx, taskId) {
|
|
|
34280
34542
|
function watchPtyCacheKey(extCtx, taskId) {
|
|
34281
34543
|
return `${ptyCacheKey(extCtx, taskId)}::watch`;
|
|
34282
34544
|
}
|
|
34283
|
-
function isTerminalStatus(status) {
|
|
34284
|
-
return status === "completed" || status === "failed" || status === "killed" || status === "timed_out";
|
|
34285
|
-
}
|
|
34286
34545
|
function renderBashCall(command, description, theme, context) {
|
|
34287
34546
|
const text = reuseText3(context.lastComponent);
|
|
34288
34547
|
const display = description ?? (command ? shortenCommand(command) : "...");
|
|
@@ -34386,12 +34645,12 @@ function registerConflictsTool(pi, ctx) {
|
|
|
34386
34645
|
async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
|
|
34387
34646
|
const bridge = bridgeFor(ctx, extCtx.cwd);
|
|
34388
34647
|
const reqParams = {};
|
|
34389
|
-
const
|
|
34390
|
-
if (typeof
|
|
34391
|
-
await assertExternalDirectoryPermission(extCtx,
|
|
34648
|
+
const path3 = params?.path;
|
|
34649
|
+
if (typeof path3 === "string" && path3.trim() !== "") {
|
|
34650
|
+
await assertExternalDirectoryPermission(extCtx, path3, "inspect", {
|
|
34392
34651
|
restrictToProjectRoot: ctx.config.restrict_to_project_root ?? false
|
|
34393
34652
|
});
|
|
34394
|
-
reqParams.path = await resolvePathArg(extCtx.cwd,
|
|
34653
|
+
reqParams.path = await resolvePathArg(extCtx.cwd, path3);
|
|
34395
34654
|
}
|
|
34396
34655
|
const response = await callBridge(bridge, "git_conflicts", reqParams, extCtx);
|
|
34397
34656
|
return textResult(response.text ?? JSON.stringify(response, null, 2));
|
|
@@ -34790,8 +35049,8 @@ function tier2SummaryPart(summary, key, label) {
|
|
|
34790
35049
|
return `${label} ${status ?? "unavailable"}`;
|
|
34791
35050
|
}
|
|
34792
35051
|
function shortDupOccurrence(entry) {
|
|
34793
|
-
const [
|
|
34794
|
-
return
|
|
35052
|
+
const [path3] = entry.split(":");
|
|
35053
|
+
return path3?.split("/").pop() ?? entry;
|
|
34795
35054
|
}
|
|
34796
35055
|
function tier2TopPreview(summary, theme) {
|
|
34797
35056
|
const lines = [];
|
|
@@ -35000,9 +35259,9 @@ function depthWarning(response, theme, depthField = "depth_limited", truncatedFi
|
|
|
35000
35259
|
const detail = truncated > 0 ? `, ${truncated} truncated` : "";
|
|
35001
35260
|
return theme.fg("warning", `(depth limited${detail})`);
|
|
35002
35261
|
}
|
|
35003
|
-
function renderTracePath(
|
|
35262
|
+
function renderTracePath(path3, index, lines) {
|
|
35004
35263
|
lines.push(`Path ${index + 1}`);
|
|
35005
|
-
asRecords(
|
|
35264
|
+
asRecords(path3.hops).forEach((hop, hopIndex) => {
|
|
35006
35265
|
const symbol2 = asString(hop.symbol) ?? "(unknown)";
|
|
35007
35266
|
const file2 = shortenPath2(asString(hop.file) ?? "(unknown file)");
|
|
35008
35267
|
const line = asNumber(hop.line);
|
|
@@ -35040,15 +35299,15 @@ function buildNavigateSections(args, payload, theme) {
|
|
|
35040
35299
|
return sections2;
|
|
35041
35300
|
}
|
|
35042
35301
|
if (args.op === "trace_to_symbol") {
|
|
35043
|
-
const
|
|
35302
|
+
const path3 = asRecords(response.path);
|
|
35044
35303
|
const complete = asBoolean(response.complete);
|
|
35045
35304
|
const reason = asString(response.reason);
|
|
35046
|
-
if (
|
|
35305
|
+
if (path3.length === 0) {
|
|
35047
35306
|
const prefix = complete === false ? theme.fg("warning", "No complete path") : theme.fg("muted", "No path");
|
|
35048
35307
|
return [`${prefix}${reason ? ` (${reason})` : ""}`];
|
|
35049
35308
|
}
|
|
35050
|
-
const lines = [theme.fg("success", `${
|
|
35051
|
-
|
|
35309
|
+
const lines = [theme.fg("success", `${path3.length} hop${path3.length === 1 ? "" : "s"}`)];
|
|
35310
|
+
path3.forEach((hop, index) => {
|
|
35052
35311
|
const symbol2 = asString(hop.symbol) ?? "(unknown)";
|
|
35053
35312
|
const file2 = shortenPath2(asString(hop.file) ?? "(unknown file)");
|
|
35054
35313
|
const line = asNumber(hop.line);
|
|
@@ -35064,9 +35323,9 @@ function buildNavigateSections(args, payload, theme) {
|
|
|
35064
35323
|
];
|
|
35065
35324
|
if (paths.length === 0)
|
|
35066
35325
|
sections2.push(theme.fg("muted", "No entry paths found."));
|
|
35067
|
-
paths.forEach((
|
|
35326
|
+
paths.forEach((path3, index) => {
|
|
35068
35327
|
const lines = [];
|
|
35069
|
-
renderTracePath(
|
|
35328
|
+
renderTracePath(path3, index, lines);
|
|
35070
35329
|
sections2.push(lines.join(`
|
|
35071
35330
|
`));
|
|
35072
35331
|
});
|
|
@@ -35524,6 +35783,11 @@ Pass a single \`target\`:
|
|
|
35524
35783
|
}));
|
|
35525
35784
|
if (symbolsArray.length === 1) {
|
|
35526
35785
|
const response2 = results[0] ?? { success: false, message: "missing zoom response" };
|
|
35786
|
+
const rustBatch = unwrapRustZoomBatchEnvelope(response2);
|
|
35787
|
+
if (rustBatch) {
|
|
35788
|
+
const batch2 = formatZoomBatchResult(targetLabel, rustBatch.names, rustBatch.responses);
|
|
35789
|
+
return textResult(batch2.text, batch2);
|
|
35790
|
+
}
|
|
35527
35791
|
if (response2.success === false) {
|
|
35528
35792
|
throw new Error(response2.message || "zoom failed");
|
|
35529
35793
|
}
|
|
@@ -35759,7 +36023,7 @@ function registerRefactorTool(pi, ctx) {
|
|
|
35759
36023
|
import { StringEnum as StringEnum5 } from "@earendil-works/pi-ai";
|
|
35760
36024
|
import { Type as Type12 } from "typebox";
|
|
35761
36025
|
function responsePaths(response) {
|
|
35762
|
-
return Array.isArray(response.paths) ? response.paths.filter((
|
|
36026
|
+
return Array.isArray(response.paths) ? response.paths.filter((path3) => typeof path3 === "string" && path3.length > 0) : [];
|
|
35763
36027
|
}
|
|
35764
36028
|
var SafetyParams = Type12.Object({
|
|
35765
36029
|
op: StringEnum5(["undo", "history", "checkpoint", "restore", "list"], {
|
|
@@ -36225,18 +36489,18 @@ function createVersionMismatchHandler(getPool, ensureCompatibleBinary = ensureBi
|
|
|
36225
36489
|
const upgradePromise = (async () => {
|
|
36226
36490
|
warn2(`WARNING: aft binary v${binaryVersion} is older than plugin v${minVersion}. ` + "Some features may not work. Attempting to download a compatible binary...");
|
|
36227
36491
|
try {
|
|
36228
|
-
const
|
|
36229
|
-
if (!
|
|
36492
|
+
const path3 = await ensureCompatibleBinary(`v${minVersion}`);
|
|
36493
|
+
if (!path3) {
|
|
36230
36494
|
warn2(`Could not find or download v${minVersion}. Continuing with v${binaryVersion}.`);
|
|
36231
36495
|
return null;
|
|
36232
36496
|
}
|
|
36233
36497
|
const pool = getPool();
|
|
36234
36498
|
if (!pool) {
|
|
36235
|
-
warn2(`Found/downloaded compatible binary at ${
|
|
36499
|
+
warn2(`Found/downloaded compatible binary at ${path3}, but bridge pool is not ready.`);
|
|
36236
36500
|
return null;
|
|
36237
36501
|
}
|
|
36238
|
-
log2(`Found/downloaded compatible binary at ${
|
|
36239
|
-
const replaced = await pool.replaceBinary(
|
|
36502
|
+
log2(`Found/downloaded compatible binary at ${path3}. Replacing running bridges...`);
|
|
36503
|
+
const replaced = await pool.replaceBinary(path3);
|
|
36240
36504
|
log2("Binary replaced successfully. New bridges will use the updated binary.");
|
|
36241
36505
|
return replaced;
|
|
36242
36506
|
} catch (err) {
|
|
@@ -36487,6 +36751,7 @@ ${lines}
|
|
|
36487
36751
|
}
|
|
36488
36752
|
let pool;
|
|
36489
36753
|
const poolOptions = {
|
|
36754
|
+
...resolveBridgePoolTransportOptions(config2),
|
|
36490
36755
|
errorPrefix: "[aft-pi]",
|
|
36491
36756
|
minVersion: PLUGIN_VERSION,
|
|
36492
36757
|
onVersionMismatch: createVersionMismatchHandler(() => pool),
|
|
@@ -36561,7 +36826,7 @@ ${lines}
|
|
|
36561
36826
|
if (onnxRuntimePromise) {
|
|
36562
36827
|
await Promise.race([
|
|
36563
36828
|
onnxRuntimePromise,
|
|
36564
|
-
new Promise((
|
|
36829
|
+
new Promise((resolve5) => setTimeout(() => resolve5(null), 60000))
|
|
36565
36830
|
]);
|
|
36566
36831
|
}
|
|
36567
36832
|
const bridge = pool.getBridge(cwd);
|