@cortexkit/aft-opencode 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/bg-notifications.d.ts.map +1 -1
- package/dist/config.d.ts +12 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +801 -531
- package/dist/tools/_shared.d.ts +1 -32
- package/dist/tools/_shared.d.ts.map +1 -1
- package/dist/tools/ast.d.ts.map +1 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash_watch.d.ts +0 -1
- package/dist/tools/bash_watch.d.ts.map +1 -1
- package/dist/tools/hoisted.d.ts.map +1 -1
- package/dist/tools/reading.d.ts.map +1 -1
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tui/preferences.d.ts +33 -0
- package/dist/tui/preferences.d.ts.map +1 -0
- package/dist/tui.js +8102 -84
- package/package.json +8 -8
- package/src/tui/index.tsx +1 -1
- package/src/tui/preferences.ts +243 -0
- package/src/tui/sidebar.tsx +142 -91
package/dist/index.js
CHANGED
|
@@ -7652,10 +7652,10 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
7652
7652
|
replacer = null;
|
|
7653
7653
|
indent = EMPTY;
|
|
7654
7654
|
};
|
|
7655
|
-
var
|
|
7655
|
+
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)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two, gap)), gap) : EMPTY;
|
|
7656
7656
|
var join_content = (inside, value, gap) => {
|
|
7657
7657
|
const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
|
|
7658
|
-
return
|
|
7658
|
+
return join10(comment, inside, gap);
|
|
7659
7659
|
};
|
|
7660
7660
|
var stringify_string = (holder, key, value) => {
|
|
7661
7661
|
const raw = get_raw_string_literal(holder, key);
|
|
@@ -7677,13 +7677,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
7677
7677
|
if (i !== 0) {
|
|
7678
7678
|
inside += COMMA;
|
|
7679
7679
|
}
|
|
7680
|
-
const before =
|
|
7680
|
+
const before = join10(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
|
|
7681
7681
|
inside += before || LF + deeper_gap;
|
|
7682
7682
|
inside += stringify(i, value, deeper_gap) || STR_NULL;
|
|
7683
7683
|
inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
|
|
7684
7684
|
after_comma = process_comments(value, AFTER(i), deeper_gap);
|
|
7685
7685
|
}
|
|
7686
|
-
inside +=
|
|
7686
|
+
inside += join10(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
7687
7687
|
return BRACKET_OPEN + join_content(inside, value, gap) + BRACKET_CLOSE;
|
|
7688
7688
|
};
|
|
7689
7689
|
var object_stringify = (value, gap) => {
|
|
@@ -7704,13 +7704,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
7704
7704
|
inside += COMMA;
|
|
7705
7705
|
}
|
|
7706
7706
|
first = false;
|
|
7707
|
-
const before =
|
|
7707
|
+
const before = join10(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
|
|
7708
7708
|
inside += before || LF + deeper_gap;
|
|
7709
7709
|
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);
|
|
7710
7710
|
after_comma = process_comments(value, AFTER(key), deeper_gap);
|
|
7711
7711
|
};
|
|
7712
7712
|
keys.forEach(iteratee);
|
|
7713
|
-
inside +=
|
|
7713
|
+
inside += join10(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
7714
7714
|
return CURLY_BRACKET_OPEN + join_content(inside, value, gap) + CURLY_BRACKET_CLOSE;
|
|
7715
7715
|
};
|
|
7716
7716
|
function stringify(key, holder, gap) {
|
|
@@ -11593,7 +11593,45 @@ function error(message, meta) {
|
|
|
11593
11593
|
console.error(`[aft-bridge] ERROR: ${message}`);
|
|
11594
11594
|
}
|
|
11595
11595
|
}
|
|
11596
|
+
// ../aft-bridge/dist/bash-format.js
|
|
11597
|
+
function appendPipeStripNote(output, note) {
|
|
11598
|
+
return note ? `${output}
|
|
11599
|
+
|
|
11600
|
+
${note}` : output;
|
|
11601
|
+
}
|
|
11602
|
+
function formatSeconds(ms) {
|
|
11603
|
+
return `${Number((ms / 1000).toFixed(1))}s`;
|
|
11604
|
+
}
|
|
11605
|
+
function formatForegroundResult(data) {
|
|
11606
|
+
const output = data.output_preview ?? "";
|
|
11607
|
+
const outputPath = data.output_path;
|
|
11608
|
+
const truncated = data.output_truncated === true;
|
|
11609
|
+
const status = data.status;
|
|
11610
|
+
const exit = data.exit_code;
|
|
11611
|
+
let rendered = output;
|
|
11612
|
+
if (truncated && outputPath) {
|
|
11613
|
+
rendered += `
|
|
11614
|
+
[output truncated; full output at ${outputPath}]`;
|
|
11615
|
+
}
|
|
11616
|
+
if (status === "timed_out") {
|
|
11617
|
+
rendered += `
|
|
11618
|
+
[command timed out]`;
|
|
11619
|
+
}
|
|
11620
|
+
if (typeof exit === "number" && exit !== 0) {
|
|
11621
|
+
rendered += `
|
|
11622
|
+
[exit code: ${exit}]`;
|
|
11623
|
+
}
|
|
11624
|
+
return rendered;
|
|
11625
|
+
}
|
|
11626
|
+
function isTerminalStatus(status) {
|
|
11627
|
+
return status === "completed" || status === "failed" || status === "killed" || status === "timed_out";
|
|
11628
|
+
}
|
|
11629
|
+
function sleep(ms) {
|
|
11630
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
11631
|
+
}
|
|
11596
11632
|
// ../aft-bridge/dist/bash-hints.js
|
|
11633
|
+
import * as os from "node:os";
|
|
11634
|
+
import * as path from "node:path";
|
|
11597
11635
|
var CONFLICT_HINT = `
|
|
11598
11636
|
|
|
11599
11637
|
[Hint] Use aft_conflicts to see all conflict regions across files in a single call.`;
|
|
@@ -11623,18 +11661,87 @@ function commandInvokesCodeSearch(command) {
|
|
|
11623
11661
|
}
|
|
11624
11662
|
return false;
|
|
11625
11663
|
}
|
|
11626
|
-
function maybeAppendGrepSearchHint(output, command, aftSearchRegistered) {
|
|
11664
|
+
function maybeAppendGrepSearchHint(output, command, aftSearchRegistered, projectRoot) {
|
|
11627
11665
|
if (output === "")
|
|
11628
11666
|
return output;
|
|
11629
11667
|
if (!commandInvokesCodeSearch(command))
|
|
11630
11668
|
return output;
|
|
11631
11669
|
if (output.includes(GREP_SEARCH_HINT_PREFIX))
|
|
11632
11670
|
return output;
|
|
11671
|
+
if (shouldSuppressGrepSearchHint(command, projectRoot))
|
|
11672
|
+
return output;
|
|
11633
11673
|
const hint = aftSearchRegistered ? GREP_SEARCH_AFT_SEARCH_HINT : GREP_SEARCH_GREP_HINT;
|
|
11634
11674
|
return `${output}
|
|
11635
11675
|
|
|
11636
11676
|
${hint}`;
|
|
11637
11677
|
}
|
|
11678
|
+
function shouldSuppressGrepSearchHint(command, projectRoot) {
|
|
11679
|
+
const root = projectRoot?.trim();
|
|
11680
|
+
if (!root)
|
|
11681
|
+
return false;
|
|
11682
|
+
const statements = splitTopLevelStatements(command);
|
|
11683
|
+
if (statements === null)
|
|
11684
|
+
return false;
|
|
11685
|
+
let sawCodeSearchStatement = false;
|
|
11686
|
+
for (const statement of statements) {
|
|
11687
|
+
const firstStage = firstPipelineStage(statement);
|
|
11688
|
+
if (firstStage === null)
|
|
11689
|
+
continue;
|
|
11690
|
+
const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0));
|
|
11691
|
+
if (firstToken === null)
|
|
11692
|
+
continue;
|
|
11693
|
+
if (firstToken.token !== "grep" && firstToken.token !== "rg")
|
|
11694
|
+
continue;
|
|
11695
|
+
sawCodeSearchStatement = true;
|
|
11696
|
+
const operands = collectPathOperands(firstStage, firstToken.end);
|
|
11697
|
+
if (operands.length === 0)
|
|
11698
|
+
return false;
|
|
11699
|
+
for (const operand of operands) {
|
|
11700
|
+
if (isPathInsideProject(root, operand))
|
|
11701
|
+
return false;
|
|
11702
|
+
}
|
|
11703
|
+
}
|
|
11704
|
+
return sawCodeSearchStatement;
|
|
11705
|
+
}
|
|
11706
|
+
function collectPathOperands(firstStage, startAfterCommand) {
|
|
11707
|
+
const operands = [];
|
|
11708
|
+
let index = skipSpaces(firstStage, startAfterCommand);
|
|
11709
|
+
while (index < firstStage.length) {
|
|
11710
|
+
const tokenResult = readShellToken(firstStage, index);
|
|
11711
|
+
if (tokenResult === null)
|
|
11712
|
+
break;
|
|
11713
|
+
const { token, end } = tokenResult;
|
|
11714
|
+
if (end <= index)
|
|
11715
|
+
break;
|
|
11716
|
+
index = skipSpaces(firstStage, end);
|
|
11717
|
+
if (token.startsWith("-"))
|
|
11718
|
+
continue;
|
|
11719
|
+
if (looksLikePathOperand(token))
|
|
11720
|
+
operands.push(token);
|
|
11721
|
+
}
|
|
11722
|
+
return operands;
|
|
11723
|
+
}
|
|
11724
|
+
function looksLikePathOperand(token) {
|
|
11725
|
+
return token.includes("/") || token.startsWith("~") || token.startsWith("./") || token.startsWith("../");
|
|
11726
|
+
}
|
|
11727
|
+
function expandTilde(target) {
|
|
11728
|
+
if (!target.startsWith("~"))
|
|
11729
|
+
return target;
|
|
11730
|
+
if (target === "~" || target.startsWith("~/")) {
|
|
11731
|
+
return path.join(os.homedir(), target.slice(1));
|
|
11732
|
+
}
|
|
11733
|
+
return target;
|
|
11734
|
+
}
|
|
11735
|
+
function resolvePathOperand(projectRoot, operand) {
|
|
11736
|
+
const expanded = expandTilde(operand);
|
|
11737
|
+
return path.isAbsolute(expanded) ? path.resolve(expanded) : path.resolve(projectRoot, expanded);
|
|
11738
|
+
}
|
|
11739
|
+
function isPathInsideProject(projectRoot, operand) {
|
|
11740
|
+
const root = path.resolve(projectRoot);
|
|
11741
|
+
const resolved = resolvePathOperand(root, operand);
|
|
11742
|
+
const rel = path.relative(root, resolved);
|
|
11743
|
+
return rel === "" || !rel.startsWith("..") && !path.isAbsolute(rel);
|
|
11744
|
+
}
|
|
11638
11745
|
function splitTopLevelStatements(command) {
|
|
11639
11746
|
const statements = [];
|
|
11640
11747
|
let start = 0;
|
|
@@ -11814,8 +11921,8 @@ function resolveBashKillTimeout(modelTimeout, foregroundWaitMs) {
|
|
|
11814
11921
|
}
|
|
11815
11922
|
// ../aft-bridge/dist/bridge.js
|
|
11816
11923
|
import { spawn } from "node:child_process";
|
|
11817
|
-
import { homedir } from "node:os";
|
|
11818
|
-
import { join } from "node:path";
|
|
11924
|
+
import { homedir as homedir2 } from "node:os";
|
|
11925
|
+
import { join as join2 } from "node:path";
|
|
11819
11926
|
import { StringDecoder } from "node:string_decoder";
|
|
11820
11927
|
|
|
11821
11928
|
// ../aft-bridge/dist/command-timeouts.js
|
|
@@ -11832,6 +11939,11 @@ var LONG_RUNNING_COMMAND_TIMEOUT_MS = {
|
|
|
11832
11939
|
function timeoutForCommand(command) {
|
|
11833
11940
|
return LONG_RUNNING_COMMAND_TIMEOUT_MS[command];
|
|
11834
11941
|
}
|
|
11942
|
+
var PASSIVE_COMMANDS = new Set(["status"]);
|
|
11943
|
+
var PASSIVE_COMMAND_TIMEOUT_MS = 5000;
|
|
11944
|
+
function isPassiveCommand(command) {
|
|
11945
|
+
return PASSIVE_COMMANDS.has(command);
|
|
11946
|
+
}
|
|
11835
11947
|
|
|
11836
11948
|
// ../aft-bridge/dist/status-bar.js
|
|
11837
11949
|
var STATUS_BAR_HEARTBEAT_CALLS = 15;
|
|
@@ -11909,6 +12021,11 @@ function bashTaskIdFrom(response) {
|
|
|
11909
12021
|
function tagStderrLine(line) {
|
|
11910
12022
|
return /^\[aft(-\w+)?\] /.test(line) ? line : `[aft] ${line}`;
|
|
11911
12023
|
}
|
|
12024
|
+
var BENIGN_CPUINFO_PROC_CPUINFO_PARSE_FAILURE = "failed to parse processor information from /proc/cpuinfo";
|
|
12025
|
+
function shouldSurfaceStderrLine(line) {
|
|
12026
|
+
const normalized = line.trim();
|
|
12027
|
+
return !(normalized === `Error in cpuinfo: ${BENIGN_CPUINFO_PROC_CPUINFO_PARSE_FAILURE}` || normalized === BENIGN_CPUINFO_PROC_CPUINFO_PARSE_FAILURE);
|
|
12028
|
+
}
|
|
11912
12029
|
function compareSemver(a, b) {
|
|
11913
12030
|
const [aMain, aPre] = a.split("-", 2);
|
|
11914
12031
|
const [bMain, bPre] = b.split("-", 2);
|
|
@@ -12000,6 +12117,7 @@ class BinaryBridge {
|
|
|
12000
12117
|
_restartCount = 0;
|
|
12001
12118
|
_shuttingDown = false;
|
|
12002
12119
|
timeoutMs;
|
|
12120
|
+
hangThreshold;
|
|
12003
12121
|
maxRestarts;
|
|
12004
12122
|
configured = false;
|
|
12005
12123
|
_configurePromise = null;
|
|
@@ -12024,6 +12142,7 @@ class BinaryBridge {
|
|
|
12024
12142
|
this.binaryPath = binaryPath;
|
|
12025
12143
|
this.cwd = cwd;
|
|
12026
12144
|
this.timeoutMs = options?.timeoutMs ?? DEFAULT_BRIDGE_TIMEOUT_MS;
|
|
12145
|
+
this.hangThreshold = options?.hangThreshold ?? BRIDGE_HANG_TIMEOUT_THRESHOLD;
|
|
12027
12146
|
this.maxRestarts = options?.maxRestarts ?? 3;
|
|
12028
12147
|
this.configOverrides = clampSemanticTimeout(configOverrides ?? {}, this.timeoutMs);
|
|
12029
12148
|
this.minVersion = options?.minVersion;
|
|
@@ -12141,7 +12260,9 @@ class BinaryBridge {
|
|
|
12141
12260
|
if (requestSessionId && options?.configureWarningClient !== undefined) {
|
|
12142
12261
|
this.configureWarningClients.set(requestSessionId, options.configureWarningClient);
|
|
12143
12262
|
}
|
|
12144
|
-
const
|
|
12263
|
+
const passive = isPassiveCommand(command);
|
|
12264
|
+
const resolvedTimeoutMs = options?.transportTimeoutMs ?? options?.timeoutMs ?? this.timeoutMs;
|
|
12265
|
+
const effectiveTimeoutMs = passive ? Math.min(resolvedTimeoutMs, PASSIVE_COMMAND_TIMEOUT_MS) : resolvedTimeoutMs;
|
|
12145
12266
|
const implicitTransportOptions = {
|
|
12146
12267
|
...options?.transportTimeoutMs !== undefined || options?.timeoutMs !== undefined ? { transportTimeoutMs: effectiveTimeoutMs } : {},
|
|
12147
12268
|
markConfiguredOnSuccess: false
|
|
@@ -12191,9 +12312,9 @@ class BinaryBridge {
|
|
|
12191
12312
|
}
|
|
12192
12313
|
const line = `${JSON.stringify(request)}
|
|
12193
12314
|
`;
|
|
12194
|
-
const keepBridgeOnTimeout = options?.keepBridgeOnTimeout === true;
|
|
12315
|
+
const keepBridgeOnTimeout = passive || options?.keepBridgeOnTimeout === true;
|
|
12195
12316
|
let requestSentAt = Date.now();
|
|
12196
|
-
const response = await new Promise((
|
|
12317
|
+
const response = await new Promise((resolve2, reject) => {
|
|
12197
12318
|
const timer = setTimeout(() => {
|
|
12198
12319
|
const entry = this.pending.get(id);
|
|
12199
12320
|
if (!entry)
|
|
@@ -12213,7 +12334,7 @@ class BinaryBridge {
|
|
|
12213
12334
|
const childActiveSinceRequest = this.lastChildActivityAt > requestSentAt;
|
|
12214
12335
|
const consecutiveTimeouts = this.consecutiveRequestTimeouts + 1;
|
|
12215
12336
|
this.consecutiveRequestTimeouts = consecutiveTimeouts;
|
|
12216
|
-
const keepWarm = childActiveSinceRequest || consecutiveTimeouts <
|
|
12337
|
+
const keepWarm = childActiveSinceRequest || consecutiveTimeouts < this.hangThreshold;
|
|
12217
12338
|
const restartSuffix = keepWarm ? " — bridge kept warm" : " — restarting bridge";
|
|
12218
12339
|
const timeoutMsg = `Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms${restartSuffix}`;
|
|
12219
12340
|
if (requestSessionId) {
|
|
@@ -12228,7 +12349,7 @@ class BinaryBridge {
|
|
|
12228
12349
|
entry.reject(new Error(`${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`));
|
|
12229
12350
|
this.handleTimeout(requestSessionId);
|
|
12230
12351
|
}, effectiveTimeoutMs);
|
|
12231
|
-
this.pending.set(id, { resolve, reject, timer, onProgress: options?.onProgress, command });
|
|
12352
|
+
this.pending.set(id, { resolve: resolve2, reject, timer, onProgress: options?.onProgress, command });
|
|
12232
12353
|
if (!this.process?.stdin?.writable) {
|
|
12233
12354
|
this.pending.delete(id);
|
|
12234
12355
|
clearTimeout(timer);
|
|
@@ -12326,15 +12447,15 @@ class BinaryBridge {
|
|
|
12326
12447
|
if (this.process) {
|
|
12327
12448
|
const proc = this.process;
|
|
12328
12449
|
this.process = null;
|
|
12329
|
-
return new Promise((
|
|
12450
|
+
return new Promise((resolve2) => {
|
|
12330
12451
|
const forceKillTimer = setTimeout(() => {
|
|
12331
12452
|
proc.kill("SIGKILL");
|
|
12332
|
-
|
|
12453
|
+
resolve2();
|
|
12333
12454
|
}, 5000);
|
|
12334
12455
|
proc.once("exit", () => {
|
|
12335
12456
|
clearTimeout(forceKillTimer);
|
|
12336
12457
|
this.logVia("Process exited during shutdown");
|
|
12337
|
-
|
|
12458
|
+
resolve2();
|
|
12338
12459
|
});
|
|
12339
12460
|
proc.kill("SIGTERM");
|
|
12340
12461
|
});
|
|
@@ -12379,15 +12500,15 @@ class BinaryBridge {
|
|
|
12379
12500
|
return;
|
|
12380
12501
|
const proc = this.process;
|
|
12381
12502
|
this.process = null;
|
|
12382
|
-
await new Promise((
|
|
12503
|
+
await new Promise((resolve2) => {
|
|
12383
12504
|
const forceKillTimer = setTimeout(() => {
|
|
12384
12505
|
proc.kill("SIGKILL");
|
|
12385
|
-
|
|
12506
|
+
resolve2();
|
|
12386
12507
|
}, 5000);
|
|
12387
12508
|
proc.once("exit", () => {
|
|
12388
12509
|
clearTimeout(forceKillTimer);
|
|
12389
12510
|
this.logVia("Process exited during coordinated binary replacement");
|
|
12390
|
-
|
|
12511
|
+
resolve2();
|
|
12391
12512
|
});
|
|
12392
12513
|
proc.kill("SIGTERM");
|
|
12393
12514
|
});
|
|
@@ -12414,7 +12535,7 @@ class BinaryBridge {
|
|
|
12414
12535
|
})();
|
|
12415
12536
|
const useFastembedBackend = semanticBackend === undefined || semanticBackend === "fastembed" || semanticBackend === "";
|
|
12416
12537
|
const ortDir = typeof this.configOverrides._ort_dylib_dir === "string" && useFastembedBackend ? this.configOverrides._ort_dylib_dir : null;
|
|
12417
|
-
const ortLibraryPath = ortDir == null ? null :
|
|
12538
|
+
const ortLibraryPath = ortDir == null ? null : join2(ortDir, process.platform === "win32" ? "onnxruntime.dll" : process.platform === "darwin" ? "libonnxruntime.dylib" : "libonnxruntime.so");
|
|
12418
12539
|
const envPath = process.platform === "win32" && ortDir ? `${ortDir};${process.env.PATH ?? ""}` : process.env.PATH;
|
|
12419
12540
|
const env = {
|
|
12420
12541
|
...process.env,
|
|
@@ -12422,7 +12543,7 @@ class BinaryBridge {
|
|
|
12422
12543
|
};
|
|
12423
12544
|
this.logVia(`bridge.spawnProcess: useFastembedBackend=${useFastembedBackend}, ` + `parentORT=${process.env.ORT_DYLIB_PATH ?? "(unset)"}, ` + `ortLibraryPath=${ortLibraryPath ?? "(none)"}`);
|
|
12424
12545
|
if (useFastembedBackend) {
|
|
12425
|
-
env.FASTEMBED_CACHE_DIR = process.env.FASTEMBED_CACHE_DIR || (typeof this.configOverrides.storage_dir === "string" ?
|
|
12546
|
+
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"));
|
|
12426
12547
|
if (process.env.ORT_DYLIB_PATH) {
|
|
12427
12548
|
this.logVia(`ORT_DYLIB_PATH inherited from parent env: ${process.env.ORT_DYLIB_PATH}`);
|
|
12428
12549
|
} else if (ortLibraryPath) {
|
|
@@ -12508,7 +12629,7 @@ class BinaryBridge {
|
|
|
12508
12629
|
`)) !== -1) {
|
|
12509
12630
|
const line = this.stderrBuffer.slice(0, newlineIdx).replace(/\r$/, "");
|
|
12510
12631
|
this.stderrBuffer = this.stderrBuffer.slice(newlineIdx + 1);
|
|
12511
|
-
if (!line)
|
|
12632
|
+
if (!line || !shouldSurfaceStderrLine(line))
|
|
12512
12633
|
continue;
|
|
12513
12634
|
const tagged = tagStderrLine(line);
|
|
12514
12635
|
this.logVia(tagged);
|
|
@@ -12518,7 +12639,7 @@ class BinaryBridge {
|
|
|
12518
12639
|
flushStderrBuffer() {
|
|
12519
12640
|
const line = this.stderrBuffer.replace(/\r$/, "");
|
|
12520
12641
|
this.stderrBuffer = "";
|
|
12521
|
-
if (!line)
|
|
12642
|
+
if (!line || !shouldSurfaceStderrLine(line))
|
|
12522
12643
|
return;
|
|
12523
12644
|
const tagged = tagStderrLine(line);
|
|
12524
12645
|
this.logVia(tagged);
|
|
@@ -12764,12 +12885,23 @@ function coerceStringArray(value) {
|
|
|
12764
12885
|
}
|
|
12765
12886
|
return [];
|
|
12766
12887
|
}
|
|
12888
|
+
function isEmptyParam(value) {
|
|
12889
|
+
if (value === undefined || value === null)
|
|
12890
|
+
return true;
|
|
12891
|
+
if (typeof value === "string")
|
|
12892
|
+
return value.length === 0;
|
|
12893
|
+
if (Array.isArray(value))
|
|
12894
|
+
return value.length === 0;
|
|
12895
|
+
if (typeof value === "object")
|
|
12896
|
+
return Object.keys(value).length === 0;
|
|
12897
|
+
return false;
|
|
12898
|
+
}
|
|
12767
12899
|
// ../aft-bridge/dist/downloader.js
|
|
12768
12900
|
import { spawnSync } from "node:child_process";
|
|
12769
12901
|
import { createHash, randomUUID } from "node:crypto";
|
|
12770
12902
|
import { chmodSync, closeSync, copyFileSync, createWriteStream, existsSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, unlinkSync, writeSync } from "node:fs";
|
|
12771
|
-
import { homedir as
|
|
12772
|
-
import { join as
|
|
12903
|
+
import { homedir as homedir3 } from "node:os";
|
|
12904
|
+
import { join as join3 } from "node:path";
|
|
12773
12905
|
import { Readable } from "node:stream";
|
|
12774
12906
|
import { pipeline } from "node:stream/promises";
|
|
12775
12907
|
|
|
@@ -12826,11 +12958,11 @@ function isExpectedCachedBinary(binaryPath, tag) {
|
|
|
12826
12958
|
function getCacheDir() {
|
|
12827
12959
|
if (process.platform === "win32") {
|
|
12828
12960
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
12829
|
-
const base2 = localAppData ||
|
|
12830
|
-
return
|
|
12961
|
+
const base2 = localAppData || join3(homedir3(), "AppData", "Local");
|
|
12962
|
+
return join3(base2, "aft", "bin");
|
|
12831
12963
|
}
|
|
12832
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
12833
|
-
return
|
|
12964
|
+
const base = process.env.XDG_CACHE_HOME || join3(homedir3(), ".cache");
|
|
12965
|
+
return join3(base, "aft", "bin");
|
|
12834
12966
|
}
|
|
12835
12967
|
function getBinaryName() {
|
|
12836
12968
|
return process.platform === "win32" ? "aft.exe" : "aft";
|
|
@@ -12838,7 +12970,7 @@ function getBinaryName() {
|
|
|
12838
12970
|
function getCachedBinaryPath(version) {
|
|
12839
12971
|
if (!version)
|
|
12840
12972
|
return null;
|
|
12841
|
-
const binaryPath =
|
|
12973
|
+
const binaryPath = join3(getCacheDir(), version, getBinaryName());
|
|
12842
12974
|
return existsSync(binaryPath) ? binaryPath : null;
|
|
12843
12975
|
}
|
|
12844
12976
|
async function downloadBinary(version) {
|
|
@@ -12855,16 +12987,16 @@ async function downloadBinary(version) {
|
|
|
12855
12987
|
return null;
|
|
12856
12988
|
}
|
|
12857
12989
|
const tag = rawTag.startsWith("v") ? rawTag : `v${rawTag}`;
|
|
12858
|
-
const versionedCacheDir =
|
|
12990
|
+
const versionedCacheDir = join3(getCacheDir(), tag);
|
|
12859
12991
|
const binaryName = getBinaryName();
|
|
12860
|
-
const binaryPath =
|
|
12992
|
+
const binaryPath = join3(versionedCacheDir, binaryName);
|
|
12861
12993
|
if (existsSync(binaryPath) && isExpectedCachedBinary(binaryPath, tag)) {
|
|
12862
12994
|
return binaryPath;
|
|
12863
12995
|
}
|
|
12864
12996
|
const downloadUrl = `https://github.com/${REPO}/releases/download/${tag}/${assetName}`;
|
|
12865
12997
|
const checksumUrl = `https://github.com/${REPO}/releases/download/${tag}/checksums.sha256`;
|
|
12866
12998
|
log(`Downloading AFT binary (${tag}) for ${platformKey}...`);
|
|
12867
|
-
const lockPath =
|
|
12999
|
+
const lockPath = join3(versionedCacheDir, ".download.lock");
|
|
12868
13000
|
let releaseLock = null;
|
|
12869
13001
|
let binaryController = null;
|
|
12870
13002
|
let checksumController = null;
|
|
@@ -13016,7 +13148,7 @@ async function acquireDownloadLock(lockPath) {
|
|
|
13016
13148
|
if (Date.now() - startedAt > DOWNLOAD_LOCK_TIMEOUT_MS) {
|
|
13017
13149
|
throw new Error(`Timed out waiting for download lock: ${lockPath}`);
|
|
13018
13150
|
}
|
|
13019
|
-
await new Promise((
|
|
13151
|
+
await new Promise((resolve2) => setTimeout(resolve2, 100));
|
|
13020
13152
|
}
|
|
13021
13153
|
}
|
|
13022
13154
|
}
|
|
@@ -13102,18 +13234,18 @@ function stripJsoncSymbols(value) {
|
|
|
13102
13234
|
// ../aft-bridge/dist/migration.js
|
|
13103
13235
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
13104
13236
|
import { existsSync as existsSync4, mkdirSync as mkdirSync4 } from "node:fs";
|
|
13105
|
-
import { homedir as
|
|
13106
|
-
import { dirname as dirname2, join as
|
|
13237
|
+
import { homedir as homedir5, tmpdir } from "node:os";
|
|
13238
|
+
import { dirname as dirname2, join as join6 } from "node:path";
|
|
13107
13239
|
|
|
13108
13240
|
// ../aft-bridge/dist/paths.js
|
|
13109
13241
|
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync as renameSync2, writeFileSync } from "node:fs";
|
|
13110
|
-
import { dirname, join as
|
|
13242
|
+
import { dirname, join as join4 } from "node:path";
|
|
13111
13243
|
function resolveHarnessStoragePath(storageRoot, harness, ...segments) {
|
|
13112
|
-
return
|
|
13244
|
+
return join4(storageRoot, harness, ...segments);
|
|
13113
13245
|
}
|
|
13114
13246
|
function repairRootScopedStorageFile(storageRoot, harness, fileName) {
|
|
13115
13247
|
const harnessPath = resolveHarnessStoragePath(storageRoot, harness, fileName);
|
|
13116
|
-
const rootPath =
|
|
13248
|
+
const rootPath = join4(storageRoot, fileName);
|
|
13117
13249
|
if (existsSync2(harnessPath) || !existsSync2(rootPath))
|
|
13118
13250
|
return harnessPath;
|
|
13119
13251
|
try {
|
|
@@ -13159,8 +13291,8 @@ function markAnnouncementSeen(storageRoot, harness, currentVersion) {
|
|
|
13159
13291
|
import { execSync } from "node:child_process";
|
|
13160
13292
|
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";
|
|
13161
13293
|
import { createRequire as createRequire2 } from "node:module";
|
|
13162
|
-
import { homedir as
|
|
13163
|
-
import { join as
|
|
13294
|
+
import { homedir as homedir4 } from "node:os";
|
|
13295
|
+
import { join as join5 } from "node:path";
|
|
13164
13296
|
var ensureBinaryForResolver = ensureBinary;
|
|
13165
13297
|
function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
13166
13298
|
try {
|
|
@@ -13169,9 +13301,9 @@ function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
|
13169
13301
|
return null;
|
|
13170
13302
|
const tag = version.startsWith("v") ? version : `v${version}`;
|
|
13171
13303
|
const cacheDir = getCacheDir();
|
|
13172
|
-
const versionedDir =
|
|
13304
|
+
const versionedDir = join5(cacheDir, tag);
|
|
13173
13305
|
const ext = process.platform === "win32" ? ".exe" : "";
|
|
13174
|
-
const cachedPath =
|
|
13306
|
+
const cachedPath = join5(versionedDir, `aft${ext}`);
|
|
13175
13307
|
if (existsSync3(cachedPath)) {
|
|
13176
13308
|
const cachedVersion = readBinaryVersion(cachedPath);
|
|
13177
13309
|
if (cachedVersion === version)
|
|
@@ -13201,18 +13333,18 @@ function normalizeBareVersion(version) {
|
|
|
13201
13333
|
return version.startsWith("v") ? version.slice(1) : version;
|
|
13202
13334
|
}
|
|
13203
13335
|
function homeDirFromEnv(env) {
|
|
13204
|
-
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) ||
|
|
13336
|
+
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir4();
|
|
13205
13337
|
}
|
|
13206
13338
|
function cacheDirFromEnv(env) {
|
|
13207
13339
|
if (process.platform === "win32") {
|
|
13208
|
-
const base2 = env.LOCALAPPDATA || env.APPDATA ||
|
|
13209
|
-
return
|
|
13340
|
+
const base2 = env.LOCALAPPDATA || env.APPDATA || join5(homeDirFromEnv(env), "AppData", "Local");
|
|
13341
|
+
return join5(base2, "aft", "bin");
|
|
13210
13342
|
}
|
|
13211
|
-
const base = env.XDG_CACHE_HOME ||
|
|
13212
|
-
return
|
|
13343
|
+
const base = env.XDG_CACHE_HOME || join5(homeDirFromEnv(env), ".cache");
|
|
13344
|
+
return join5(base, "aft", "bin");
|
|
13213
13345
|
}
|
|
13214
13346
|
function cachedBinaryPathFromEnv(version, env, ext) {
|
|
13215
|
-
const binaryPath =
|
|
13347
|
+
const binaryPath = join5(cacheDirFromEnv(env), version, `aft${ext}`);
|
|
13216
13348
|
return existsSync3(binaryPath) ? binaryPath : null;
|
|
13217
13349
|
}
|
|
13218
13350
|
function isExpectedCachedBinary2(binaryPath, expectedVersion) {
|
|
@@ -13331,7 +13463,7 @@ function findBinarySync(expectedVersion) {
|
|
|
13331
13463
|
return usable;
|
|
13332
13464
|
}
|
|
13333
13465
|
} catch {}
|
|
13334
|
-
const cargoPath =
|
|
13466
|
+
const cargoPath = join5(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
|
|
13335
13467
|
if (existsSync3(cargoPath)) {
|
|
13336
13468
|
const usable = probeBinaryCandidate(cargoPath, "cargo", expectedVersion);
|
|
13337
13469
|
if (usable)
|
|
@@ -13377,22 +13509,22 @@ function dataHome() {
|
|
|
13377
13509
|
if (process.env.XDG_DATA_HOME)
|
|
13378
13510
|
return process.env.XDG_DATA_HOME;
|
|
13379
13511
|
if (process.platform === "win32") {
|
|
13380
|
-
return process.env.LOCALAPPDATA || process.env.APPDATA ||
|
|
13512
|
+
return process.env.LOCALAPPDATA || process.env.APPDATA || join6(homeDir(), "AppData", "Local");
|
|
13381
13513
|
}
|
|
13382
|
-
return
|
|
13514
|
+
return join6(homeDir(), ".local", "share");
|
|
13383
13515
|
}
|
|
13384
13516
|
function homeDir() {
|
|
13385
13517
|
if (process.platform === "win32")
|
|
13386
|
-
return process.env.USERPROFILE || process.env.HOME ||
|
|
13387
|
-
return process.env.HOME ||
|
|
13518
|
+
return process.env.USERPROFILE || process.env.HOME || homedir5();
|
|
13519
|
+
return process.env.HOME || homedir5();
|
|
13388
13520
|
}
|
|
13389
13521
|
function resolveLegacyStorageRoot(harness) {
|
|
13390
13522
|
if (harness === "pi")
|
|
13391
|
-
return
|
|
13392
|
-
return
|
|
13523
|
+
return join6(homeDir(), ".pi", "agent", "aft");
|
|
13524
|
+
return join6(dataHome(), "opencode", "storage", "plugin", "aft");
|
|
13393
13525
|
}
|
|
13394
13526
|
function resolveCortexKitStorageRoot() {
|
|
13395
|
-
return
|
|
13527
|
+
return join6(dataHome(), "cortexkit", "aft");
|
|
13396
13528
|
}
|
|
13397
13529
|
function tail(value) {
|
|
13398
13530
|
if (!value)
|
|
@@ -13406,12 +13538,12 @@ function spawnErrorLabel(error2) {
|
|
|
13406
13538
|
return [code, error2.message].filter(Boolean).join(": ");
|
|
13407
13539
|
}
|
|
13408
13540
|
function migrationLogPath(newRoot, harness, logger) {
|
|
13409
|
-
const desired =
|
|
13541
|
+
const desired = join6(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
|
|
13410
13542
|
try {
|
|
13411
13543
|
mkdirSync4(dirname2(desired), { recursive: true });
|
|
13412
13544
|
return desired;
|
|
13413
13545
|
} catch (err) {
|
|
13414
|
-
const fallback =
|
|
13546
|
+
const fallback = join6(tmpdir(), `aft-migration-${harness}-${Date.now()}.jsonl`);
|
|
13415
13547
|
logger?.warn?.(`Failed to create AFT migration log directory ${dirname2(desired)}: ${err instanceof Error ? err.message : String(err)}. ` + `Using fallback log path ${fallback}.`);
|
|
13416
13548
|
return fallback;
|
|
13417
13549
|
}
|
|
@@ -13474,13 +13606,13 @@ async function ensureStorageMigrated(opts) {
|
|
|
13474
13606
|
}
|
|
13475
13607
|
// ../aft-bridge/dist/npm-resolver.js
|
|
13476
13608
|
import { readdirSync, statSync as statSync2 } from "node:fs";
|
|
13477
|
-
import { homedir as
|
|
13478
|
-
import { delimiter, dirname as dirname3, isAbsolute, join as
|
|
13609
|
+
import { homedir as homedir6 } from "node:os";
|
|
13610
|
+
import { delimiter, dirname as dirname3, isAbsolute as isAbsolute2, join as join7 } from "node:path";
|
|
13479
13611
|
function defaultDeps() {
|
|
13480
13612
|
return {
|
|
13481
13613
|
platform: process.platform,
|
|
13482
13614
|
env: process.env,
|
|
13483
|
-
home:
|
|
13615
|
+
home: homedir6(),
|
|
13484
13616
|
execPath: process.execPath
|
|
13485
13617
|
};
|
|
13486
13618
|
}
|
|
@@ -13499,16 +13631,16 @@ function npmFromPath(deps) {
|
|
|
13499
13631
|
const raw = deps.env.PATH ?? deps.env.Path ?? "";
|
|
13500
13632
|
for (const entry of raw.split(delimiter)) {
|
|
13501
13633
|
const dir = entry.trim().replace(/^"|"$/g, "");
|
|
13502
|
-
if (!dir || !
|
|
13634
|
+
if (!dir || !isAbsolute2(dir))
|
|
13503
13635
|
continue;
|
|
13504
|
-
if (isFile(
|
|
13636
|
+
if (isFile(join7(dir, name)))
|
|
13505
13637
|
return dir;
|
|
13506
13638
|
}
|
|
13507
13639
|
return null;
|
|
13508
13640
|
}
|
|
13509
13641
|
function npmAdjacentToNode(deps) {
|
|
13510
13642
|
const dir = dirname3(deps.execPath);
|
|
13511
|
-
return isFile(
|
|
13643
|
+
return isFile(join7(dir, npmBinaryName(deps.platform))) ? dir : null;
|
|
13512
13644
|
}
|
|
13513
13645
|
function highestVersionedNodeBin(installsDir, name) {
|
|
13514
13646
|
let entries;
|
|
@@ -13517,8 +13649,8 @@ function highestVersionedNodeBin(installsDir, name) {
|
|
|
13517
13649
|
} catch {
|
|
13518
13650
|
return null;
|
|
13519
13651
|
}
|
|
13520
|
-
const candidates = entries.filter((v) => isFile(
|
|
13521
|
-
return candidates.length > 0 ?
|
|
13652
|
+
const candidates = entries.filter((v) => isFile(join7(installsDir, v, "bin", name))).sort((a, b) => compareVersionsDesc(a, b));
|
|
13653
|
+
return candidates.length > 0 ? join7(installsDir, candidates[0], "bin") : null;
|
|
13522
13654
|
}
|
|
13523
13655
|
function compareVersionsDesc(a, b) {
|
|
13524
13656
|
const pa = a.replace(/^v/, "").split(".").map((n) => Number.parseInt(n, 10));
|
|
@@ -13543,22 +13675,22 @@ function wellKnownNpmDirs(deps) {
|
|
|
13543
13675
|
const programFiles = env.ProgramFiles || "C:\\Program Files";
|
|
13544
13676
|
const appData = env.APPDATA;
|
|
13545
13677
|
const localAppData = env.LOCALAPPDATA;
|
|
13546
|
-
push(
|
|
13678
|
+
push(join7(programFiles, "nodejs"));
|
|
13547
13679
|
if (appData)
|
|
13548
|
-
push(
|
|
13680
|
+
push(join7(appData, "npm"));
|
|
13549
13681
|
if (localAppData)
|
|
13550
|
-
push(
|
|
13682
|
+
push(join7(localAppData, "Volta", "bin"));
|
|
13551
13683
|
if (env.NVM_SYMLINK)
|
|
13552
13684
|
push(env.NVM_SYMLINK);
|
|
13553
13685
|
} else {
|
|
13554
13686
|
if (env.NVM_BIN)
|
|
13555
13687
|
push(env.NVM_BIN);
|
|
13556
|
-
push(highestVersionedNodeBin(
|
|
13557
|
-
push(highestVersionedNodeBin(
|
|
13558
|
-
push(highestVersionedNodeBin(
|
|
13559
|
-
push(
|
|
13560
|
-
push(
|
|
13561
|
-
const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin",
|
|
13688
|
+
push(highestVersionedNodeBin(join7(home, ".nvm", "versions", "node"), name));
|
|
13689
|
+
push(highestVersionedNodeBin(join7(home, ".local", "share", "mise", "installs", "node"), name));
|
|
13690
|
+
push(highestVersionedNodeBin(join7(home, ".asdf", "installs", "nodejs"), name));
|
|
13691
|
+
push(join7(home, ".volta", "bin"));
|
|
13692
|
+
push(join7(home, ".asdf", "shims"));
|
|
13693
|
+
const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin", join7(home, ".local", "bin")]);
|
|
13562
13694
|
for (const dir of systemDirs)
|
|
13563
13695
|
push(dir);
|
|
13564
13696
|
}
|
|
@@ -13568,12 +13700,12 @@ function resolveNpm(deps = defaultDeps()) {
|
|
|
13568
13700
|
const name = npmBinaryName(deps.platform);
|
|
13569
13701
|
const onPath = npmFromPath(deps);
|
|
13570
13702
|
if (onPath)
|
|
13571
|
-
return { command:
|
|
13703
|
+
return { command: join7(onPath, name), binDir: onPath };
|
|
13572
13704
|
const adjacent = npmAdjacentToNode(deps);
|
|
13573
13705
|
if (adjacent)
|
|
13574
|
-
return { command:
|
|
13706
|
+
return { command: join7(adjacent, name), binDir: adjacent };
|
|
13575
13707
|
for (const dir of wellKnownNpmDirs(deps)) {
|
|
13576
|
-
const candidate =
|
|
13708
|
+
const candidate = join7(dir, name);
|
|
13577
13709
|
if (isFile(candidate))
|
|
13578
13710
|
return { command: candidate, binDir: dir };
|
|
13579
13711
|
}
|
|
@@ -13593,7 +13725,7 @@ function isNpmAvailable(deps = defaultDeps()) {
|
|
|
13593
13725
|
import { execFileSync } from "node:child_process";
|
|
13594
13726
|
import { createHash as createHash2 } from "node:crypto";
|
|
13595
13727
|
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";
|
|
13596
|
-
import { basename, dirname as dirname4, isAbsolute as
|
|
13728
|
+
import { basename, dirname as dirname4, isAbsolute as isAbsolute3, join as join8, relative as relative2, resolve as resolve2, win32 } from "node:path";
|
|
13597
13729
|
import { Readable as Readable2 } from "node:stream";
|
|
13598
13730
|
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
13599
13731
|
var ORT_VERSION = "1.24.4";
|
|
@@ -13659,10 +13791,10 @@ function getManualInstallHint() {
|
|
|
13659
13791
|
}
|
|
13660
13792
|
async function ensureOnnxRuntime(storageDir) {
|
|
13661
13793
|
const info = getPlatformInfo();
|
|
13662
|
-
const ortVersionDir =
|
|
13794
|
+
const ortVersionDir = join8(storageDir, "onnxruntime", ORT_VERSION);
|
|
13663
13795
|
const libName = info?.libName ?? "libonnxruntime.dylib";
|
|
13664
13796
|
const resolvedOrtDir = resolveCachedOnnxRuntimeDir(ortVersionDir, libName);
|
|
13665
|
-
const libPath =
|
|
13797
|
+
const libPath = join8(resolvedOrtDir, libName);
|
|
13666
13798
|
if (existsSync5(libPath)) {
|
|
13667
13799
|
const meta = readOnnxInstalledMeta(ortVersionDir);
|
|
13668
13800
|
if (meta?.sha256) {
|
|
@@ -13692,9 +13824,9 @@ async function ensureOnnxRuntime(storageDir) {
|
|
|
13692
13824
|
warn(`ONNX Runtime auto-download not available for ${process.platform}/${process.arch}. Install manually: ${getManualInstallHint()}`);
|
|
13693
13825
|
return null;
|
|
13694
13826
|
}
|
|
13695
|
-
const onnxBaseDir =
|
|
13827
|
+
const onnxBaseDir = join8(storageDir, "onnxruntime");
|
|
13696
13828
|
mkdirSync5(onnxBaseDir, { recursive: true });
|
|
13697
|
-
const lockPath =
|
|
13829
|
+
const lockPath = join8(onnxBaseDir, ONNX_LOCK_FILE);
|
|
13698
13830
|
cleanupAbandonedStagingDirs(onnxBaseDir);
|
|
13699
13831
|
if (!acquireLock(lockPath)) {
|
|
13700
13832
|
warn(`ONNX Runtime install already in progress in another process (lock: ${lockPath}). Skipping.`);
|
|
@@ -13713,7 +13845,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
13713
13845
|
for (const entry of entries) {
|
|
13714
13846
|
if (!entry.startsWith(`${ORT_VERSION}.tmp.`))
|
|
13715
13847
|
continue;
|
|
13716
|
-
const stagingDir =
|
|
13848
|
+
const stagingDir = join8(onnxBaseDir, entry);
|
|
13717
13849
|
const parts = entry.split(".");
|
|
13718
13850
|
const pidStr = parts[parts.length - 2];
|
|
13719
13851
|
const pid = pidStr ? Number.parseInt(pidStr, 10) : NaN;
|
|
@@ -13750,7 +13882,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
13750
13882
|
}
|
|
13751
13883
|
function cleanupIncompleteTargetIfUnowned(ortDir) {
|
|
13752
13884
|
try {
|
|
13753
|
-
if (existsSync5(ortDir) && !existsSync5(
|
|
13885
|
+
if (existsSync5(ortDir) && !existsSync5(join8(ortDir, ONNX_INSTALLED_META_FILE))) {
|
|
13754
13886
|
log(`[onnx] removing half-populated install dir ${ortDir} (no meta file)`);
|
|
13755
13887
|
rmSync2(ortDir, { recursive: true, force: true });
|
|
13756
13888
|
}
|
|
@@ -13778,8 +13910,8 @@ function parseOnnxVersionFromDirectoryPath(value) {
|
|
|
13778
13910
|
return null;
|
|
13779
13911
|
}
|
|
13780
13912
|
function isPathInsideRoot(root, candidate) {
|
|
13781
|
-
const rel =
|
|
13782
|
-
return rel === "" || !rel.startsWith("../") && !rel.startsWith("..\\") && rel !== ".." && !
|
|
13913
|
+
const rel = relative2(root, candidate);
|
|
13914
|
+
return rel === "" || !rel.startsWith("../") && !rel.startsWith("..\\") && rel !== ".." && !isAbsolute3(rel) && !win32.isAbsolute(rel);
|
|
13783
13915
|
}
|
|
13784
13916
|
function detectOnnxVersion(libDir, libName) {
|
|
13785
13917
|
try {
|
|
@@ -13794,7 +13926,7 @@ function detectOnnxVersion(libDir, libName) {
|
|
|
13794
13926
|
if (version)
|
|
13795
13927
|
return version;
|
|
13796
13928
|
}
|
|
13797
|
-
const base =
|
|
13929
|
+
const base = join8(libDir, libName);
|
|
13798
13930
|
if (existsSync5(base)) {
|
|
13799
13931
|
try {
|
|
13800
13932
|
const real = realpathSync(base);
|
|
@@ -13830,7 +13962,7 @@ function pathEntriesForPlatform() {
|
|
|
13830
13962
|
return pathEnvValue().split(delimiter2).map((entry) => entry.trim().replace(/^"|"$/g, "")).filter((entry) => {
|
|
13831
13963
|
if (!entry || entry === "." || entry.includes("\x00"))
|
|
13832
13964
|
return false;
|
|
13833
|
-
return
|
|
13965
|
+
return isAbsolute3(entry) || win32.isAbsolute(entry);
|
|
13834
13966
|
});
|
|
13835
13967
|
}
|
|
13836
13968
|
function directoryContainsLibrary(dir, libName) {
|
|
@@ -13846,10 +13978,10 @@ function directoryContainsLibrary(dir, libName) {
|
|
|
13846
13978
|
}
|
|
13847
13979
|
}
|
|
13848
13980
|
function resolveCachedOnnxRuntimeDir(ortVersionDir, libName) {
|
|
13849
|
-
if (existsSync5(
|
|
13981
|
+
if (existsSync5(join8(ortVersionDir, libName)))
|
|
13850
13982
|
return ortVersionDir;
|
|
13851
|
-
const libSubdir =
|
|
13852
|
-
if (existsSync5(
|
|
13983
|
+
const libSubdir = join8(ortVersionDir, "lib");
|
|
13984
|
+
if (existsSync5(join8(libSubdir, libName)))
|
|
13853
13985
|
return libSubdir;
|
|
13854
13986
|
return ortVersionDir;
|
|
13855
13987
|
}
|
|
@@ -13864,12 +13996,12 @@ function findSystemOnnxRuntime(libName) {
|
|
|
13864
13996
|
} else if (process.platform === "win32") {
|
|
13865
13997
|
const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
|
|
13866
13998
|
const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
|
|
13867
|
-
searchPaths.push(
|
|
13999
|
+
searchPaths.push(join8(programFiles, "onnxruntime", "lib"), join8(programFiles, "Microsoft ONNX Runtime", "lib"), join8(programFiles, "Microsoft Machine Learning", "lib"), join8(programFilesX86, "onnxruntime", "lib"), ...(() => {
|
|
13868
14000
|
const nugetPaths = [];
|
|
13869
14001
|
const userProfile = process.env.USERPROFILE ?? "";
|
|
13870
14002
|
if (!userProfile)
|
|
13871
14003
|
return nugetPaths;
|
|
13872
|
-
const nugetPackageDir =
|
|
14004
|
+
const nugetPackageDir = join8(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
|
|
13873
14005
|
if (!existsSync5(nugetPackageDir))
|
|
13874
14006
|
return nugetPaths;
|
|
13875
14007
|
try {
|
|
@@ -13878,7 +14010,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
13878
14010
|
continue;
|
|
13879
14011
|
if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
|
|
13880
14012
|
continue;
|
|
13881
|
-
nugetPaths.push(
|
|
14013
|
+
nugetPaths.push(join8(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join8(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
|
|
13882
14014
|
}
|
|
13883
14015
|
} catch (err) {
|
|
13884
14016
|
warn(`Failed to scan NuGet ONNX Runtime cache ${nugetPackageDir}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -13890,7 +14022,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
13890
14022
|
const normalizeCase = process.platform === "win32" || process.platform === "darwin";
|
|
13891
14023
|
const seen = new Set;
|
|
13892
14024
|
const uniquePaths = searchPaths.filter((p) => {
|
|
13893
|
-
let key =
|
|
14025
|
+
let key = resolve2(p).replace(/[/\\]+$/, "");
|
|
13894
14026
|
if (normalizeCase)
|
|
13895
14027
|
key = key.toLowerCase();
|
|
13896
14028
|
if (seen.has(key))
|
|
@@ -13900,7 +14032,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
13900
14032
|
});
|
|
13901
14033
|
const unknownVersionPaths = [];
|
|
13902
14034
|
for (const dir of uniquePaths) {
|
|
13903
|
-
const libPath =
|
|
14035
|
+
const libPath = join8(dir, libName);
|
|
13904
14036
|
if (process.platform === "win32") {
|
|
13905
14037
|
if (!directoryContainsLibrary(dir, libName))
|
|
13906
14038
|
continue;
|
|
@@ -13966,19 +14098,19 @@ function validateExtractedTree(stagingRoot) {
|
|
|
13966
14098
|
const walk = (dir) => {
|
|
13967
14099
|
const entries = readdirSync2(dir);
|
|
13968
14100
|
for (const entry of entries) {
|
|
13969
|
-
const fullPath =
|
|
14101
|
+
const fullPath = join8(dir, entry);
|
|
13970
14102
|
const lst = lstatSync(fullPath);
|
|
13971
14103
|
if (lst.isSymbolicLink()) {
|
|
13972
14104
|
const linkTarget = readlinkSync(fullPath);
|
|
13973
|
-
const resolvedTarget =
|
|
13974
|
-
const rel2 =
|
|
13975
|
-
if (rel2.startsWith("..") ||
|
|
14105
|
+
const resolvedTarget = resolve2(dirname4(fullPath), linkTarget);
|
|
14106
|
+
const rel2 = relative2(realRoot, resolvedTarget);
|
|
14107
|
+
if (rel2.startsWith("..") || isAbsolute3(rel2) || win32.isAbsolute(rel2)) {
|
|
13976
14108
|
throw new Error(`extracted symlink ${fullPath} points outside staging root: ${linkTarget}`);
|
|
13977
14109
|
}
|
|
13978
14110
|
continue;
|
|
13979
14111
|
}
|
|
13980
|
-
const rel =
|
|
13981
|
-
if (rel.startsWith("..") ||
|
|
14112
|
+
const rel = relative2(realRoot, fullPath);
|
|
14113
|
+
if (rel.startsWith("..") || isAbsolute3(rel) || win32.isAbsolute(rel)) {
|
|
13982
14114
|
throw new Error(`extracted entry ${fullPath} escapes staging root`);
|
|
13983
14115
|
}
|
|
13984
14116
|
if (lst.isDirectory()) {
|
|
@@ -14001,7 +14133,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
14001
14133
|
const tmpDir = `${targetDir}.tmp.${process.pid}.${Date.now().toString(36)}`;
|
|
14002
14134
|
try {
|
|
14003
14135
|
mkdirSync5(tmpDir, { recursive: true });
|
|
14004
|
-
const archivePath =
|
|
14136
|
+
const archivePath = join8(tmpDir, `onnxruntime.${info.archiveType}`);
|
|
14005
14137
|
await downloadFileWithCap(url, archivePath);
|
|
14006
14138
|
const archiveSha256 = sha256File(archivePath);
|
|
14007
14139
|
log(`ONNX Runtime archive sha256=${archiveSha256}`);
|
|
@@ -14017,7 +14149,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
14017
14149
|
unlinkSync3(archivePath);
|
|
14018
14150
|
} catch {}
|
|
14019
14151
|
validateExtractedTree(tmpDir);
|
|
14020
|
-
const extractedDir =
|
|
14152
|
+
const extractedDir = join8(tmpDir, info.assetName, "lib");
|
|
14021
14153
|
if (!existsSync5(extractedDir)) {
|
|
14022
14154
|
throw new Error(`Expected directory not found: ${extractedDir}`);
|
|
14023
14155
|
}
|
|
@@ -14026,7 +14158,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
14026
14158
|
const realFiles = [];
|
|
14027
14159
|
const symlinks = [];
|
|
14028
14160
|
for (const libFile of libFiles) {
|
|
14029
|
-
const src =
|
|
14161
|
+
const src = join8(extractedDir, libFile);
|
|
14030
14162
|
try {
|
|
14031
14163
|
const stat = lstatSync(src);
|
|
14032
14164
|
log(`ORT extract: ${libFile} — isSymlink=${stat.isSymbolicLink()}, isFile=${stat.isFile()}, size=${stat.size}`);
|
|
@@ -14041,7 +14173,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
14041
14173
|
}
|
|
14042
14174
|
}
|
|
14043
14175
|
copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks);
|
|
14044
|
-
const libPath =
|
|
14176
|
+
const libPath = join8(targetDir, info.libName);
|
|
14045
14177
|
let libHash = null;
|
|
14046
14178
|
try {
|
|
14047
14179
|
libHash = sha256File(libPath);
|
|
@@ -14066,8 +14198,8 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
14066
14198
|
function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, copyFile = copyFileSync3) {
|
|
14067
14199
|
const requiredLibs = new Set([info.libName]);
|
|
14068
14200
|
for (const libFile of realFiles) {
|
|
14069
|
-
const src =
|
|
14070
|
-
const dst =
|
|
14201
|
+
const src = join8(extractedDir, libFile);
|
|
14202
|
+
const dst = join8(targetDir, libFile);
|
|
14071
14203
|
try {
|
|
14072
14204
|
copyFile(src, dst);
|
|
14073
14205
|
if (process.platform !== "win32") {
|
|
@@ -14083,12 +14215,12 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
14083
14215
|
}
|
|
14084
14216
|
const targetRoot = realpathSync(targetDir);
|
|
14085
14217
|
for (const link of symlinks) {
|
|
14086
|
-
const dst =
|
|
14218
|
+
const dst = join8(targetDir, link.name);
|
|
14087
14219
|
try {
|
|
14088
14220
|
unlinkSync3(dst);
|
|
14089
14221
|
} catch {}
|
|
14090
|
-
const dstForContainment =
|
|
14091
|
-
const resolvedTarget =
|
|
14222
|
+
const dstForContainment = join8(targetRoot, link.name);
|
|
14223
|
+
const resolvedTarget = resolve2(dirname4(dstForContainment), link.target);
|
|
14092
14224
|
if (!isPathInsideRoot(targetRoot, resolvedTarget)) {
|
|
14093
14225
|
const message = `ONNX Runtime symlink ${link.name} points outside install dir: ${link.target}`;
|
|
14094
14226
|
if (requiredLibs.has(link.name)) {
|
|
@@ -14108,7 +14240,7 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
14108
14240
|
log(`ORT extract: failed to symlink optional ${link.name}: ${symlinkErr}`);
|
|
14109
14241
|
}
|
|
14110
14242
|
}
|
|
14111
|
-
const requiredPath =
|
|
14243
|
+
const requiredPath = join8(targetDir, info.libName);
|
|
14112
14244
|
if (!existsSync5(requiredPath)) {
|
|
14113
14245
|
rmSync2(targetDir, { recursive: true, force: true });
|
|
14114
14246
|
throw new Error(`Required ONNX Runtime library missing after install: ${requiredPath}`);
|
|
@@ -14135,17 +14267,17 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
|
|
|
14135
14267
|
...sha256 ? { sha256 } : {},
|
|
14136
14268
|
archiveSha256
|
|
14137
14269
|
};
|
|
14138
|
-
writeFileSync2(
|
|
14270
|
+
writeFileSync2(join8(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
|
|
14139
14271
|
} catch (err) {
|
|
14140
14272
|
log(`[onnx] failed to write installed-meta in ${installDir}: ${err}`);
|
|
14141
14273
|
}
|
|
14142
14274
|
}
|
|
14143
14275
|
function readOnnxInstalledMeta(installDir) {
|
|
14144
|
-
const
|
|
14276
|
+
const path2 = join8(installDir, ONNX_INSTALLED_META_FILE);
|
|
14145
14277
|
try {
|
|
14146
|
-
if (!statSync3(
|
|
14278
|
+
if (!statSync3(path2).isFile())
|
|
14147
14279
|
return null;
|
|
14148
|
-
const raw = readFileSync3(
|
|
14280
|
+
const raw = readFileSync3(path2, "utf8");
|
|
14149
14281
|
const parsed = JSON.parse(raw);
|
|
14150
14282
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
14151
14283
|
return null;
|
|
@@ -14159,9 +14291,9 @@ function readOnnxInstalledMeta(installDir) {
|
|
|
14159
14291
|
return null;
|
|
14160
14292
|
}
|
|
14161
14293
|
}
|
|
14162
|
-
function sha256File(
|
|
14294
|
+
function sha256File(path2) {
|
|
14163
14295
|
const hash = createHash2("sha256");
|
|
14164
|
-
hash.update(readFileSync3(
|
|
14296
|
+
hash.update(readFileSync3(path2));
|
|
14165
14297
|
return hash.digest("hex");
|
|
14166
14298
|
}
|
|
14167
14299
|
function acquireLock(lockPath) {
|
|
@@ -14843,6 +14975,7 @@ class BridgePool {
|
|
|
14843
14975
|
this.projectConfigLoader = options.projectConfigLoader;
|
|
14844
14976
|
this.bridgeOptions = {
|
|
14845
14977
|
timeoutMs: options.timeoutMs,
|
|
14978
|
+
hangThreshold: options.hangThreshold,
|
|
14846
14979
|
maxRestarts: options.maxRestarts,
|
|
14847
14980
|
minVersion: options.minVersion,
|
|
14848
14981
|
onVersionMismatch: options.onVersionMismatch,
|
|
@@ -14997,6 +15130,91 @@ function normalizeKey(projectRoot) {
|
|
|
14997
15130
|
return stripped;
|
|
14998
15131
|
}
|
|
14999
15132
|
}
|
|
15133
|
+
// ../aft-bridge/dist/tool-format.js
|
|
15134
|
+
function asPlainObject(value) {
|
|
15135
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
15136
|
+
return;
|
|
15137
|
+
return value;
|
|
15138
|
+
}
|
|
15139
|
+
function candidateLocation(candidate) {
|
|
15140
|
+
const file = typeof candidate.file === "string" && candidate.file.length > 0 ? candidate.file : undefined;
|
|
15141
|
+
if (!file)
|
|
15142
|
+
return;
|
|
15143
|
+
const line = typeof candidate.line === "number" && Number.isFinite(candidate.line) ? candidate.line : undefined;
|
|
15144
|
+
return line === undefined ? file : `${file}:${line}`;
|
|
15145
|
+
}
|
|
15146
|
+
function stringifyData(data) {
|
|
15147
|
+
if (data === undefined)
|
|
15148
|
+
return;
|
|
15149
|
+
try {
|
|
15150
|
+
return JSON.stringify(data, null, 2);
|
|
15151
|
+
} catch {
|
|
15152
|
+
return String(data);
|
|
15153
|
+
}
|
|
15154
|
+
}
|
|
15155
|
+
function formatBridgeErrorMessage(command, response, params = {}) {
|
|
15156
|
+
const code = typeof response.code === "string" && response.code.length > 0 ? response.code : undefined;
|
|
15157
|
+
const message = typeof response.message === "string" && response.message.length > 0 ? response.message : `${command} failed`;
|
|
15158
|
+
const data = asPlainObject(response.data);
|
|
15159
|
+
const rawCandidates = Array.isArray(response.candidates) ? response.candidates : Array.isArray(data?.candidates) ? data.candidates : undefined;
|
|
15160
|
+
const rawSymbol = typeof response.symbol === "string" && response.symbol.length > 0 ? response.symbol : typeof data?.symbol === "string" && data.symbol.length > 0 ? data.symbol : undefined;
|
|
15161
|
+
if (code === "ambiguous_target" || code === "target_symbol_not_in_file") {
|
|
15162
|
+
const candidates = (rawCandidates ?? []).map(asPlainObject).filter((candidate) => candidate !== undefined).map(candidateLocation).filter((candidate) => candidate !== undefined);
|
|
15163
|
+
if (candidates.length > 0) {
|
|
15164
|
+
const symbol = typeof params.toSymbol === "string" && params.toSymbol.length > 0 ? params.toSymbol : rawSymbol;
|
|
15165
|
+
const target = symbol ? `multiple symbols named "${symbol}"` : message.replace(/[.!?]+$/, "");
|
|
15166
|
+
const action = code === "ambiguous_target" ? "Pass toFile to disambiguate" : "Try one of these files for toFile";
|
|
15167
|
+
return `${command}: ${code} — ${target}. ${action}:
|
|
15168
|
+
${candidates.map((candidate) => ` - ${candidate}`).join(`
|
|
15169
|
+
`)}`;
|
|
15170
|
+
}
|
|
15171
|
+
}
|
|
15172
|
+
if (!code)
|
|
15173
|
+
return message;
|
|
15174
|
+
const lines = [`${command}: ${code} — ${message}`];
|
|
15175
|
+
const extras = collectStructuredExtras(response);
|
|
15176
|
+
if (extras)
|
|
15177
|
+
lines.push(`data: ${extras}`);
|
|
15178
|
+
return lines.join(`
|
|
15179
|
+
`);
|
|
15180
|
+
}
|
|
15181
|
+
function collectStructuredExtras(response) {
|
|
15182
|
+
const reserved = new Set([
|
|
15183
|
+
"id",
|
|
15184
|
+
"success",
|
|
15185
|
+
"code",
|
|
15186
|
+
"message",
|
|
15187
|
+
"data",
|
|
15188
|
+
"status_bar",
|
|
15189
|
+
"bg_completions"
|
|
15190
|
+
]);
|
|
15191
|
+
const extras = {};
|
|
15192
|
+
for (const [key, value] of Object.entries(response)) {
|
|
15193
|
+
if (reserved.has(key))
|
|
15194
|
+
continue;
|
|
15195
|
+
extras[key] = value;
|
|
15196
|
+
}
|
|
15197
|
+
if (Object.keys(extras).length === 0) {
|
|
15198
|
+
return stringifyData(response.data);
|
|
15199
|
+
}
|
|
15200
|
+
if (response.data !== undefined)
|
|
15201
|
+
extras.data = response.data;
|
|
15202
|
+
return stringifyData(extras);
|
|
15203
|
+
}
|
|
15204
|
+
function formatReadFooter(agentSpecifiedRange, data, options) {
|
|
15205
|
+
if (agentSpecifiedRange)
|
|
15206
|
+
return "";
|
|
15207
|
+
if (!data.truncated)
|
|
15208
|
+
return "";
|
|
15209
|
+
const startLine = data.start_line;
|
|
15210
|
+
const endLine = data.end_line;
|
|
15211
|
+
const totalLines = data.total_lines;
|
|
15212
|
+
if (startLine === undefined || endLine === undefined || totalLines === undefined) {
|
|
15213
|
+
return "";
|
|
15214
|
+
}
|
|
15215
|
+
return `
|
|
15216
|
+
(Showing lines ${startLine}-${endLine} of ${totalLines}. Use ${options.rangeHint} to read other sections.)`;
|
|
15217
|
+
}
|
|
15000
15218
|
// ../aft-bridge/dist/zoom-format.js
|
|
15001
15219
|
function formatZoomText(targetLabel, response) {
|
|
15002
15220
|
const range = response.range;
|
|
@@ -15077,16 +15295,39 @@ function formatZoomMultiTargetResult(entries) {
|
|
|
15077
15295
|
|
|
15078
15296
|
`) };
|
|
15079
15297
|
}
|
|
15298
|
+
function isRustZoomBatchEnvelope(response) {
|
|
15299
|
+
if (!Array.isArray(response.symbols) || response.symbols.length === 0) {
|
|
15300
|
+
return false;
|
|
15301
|
+
}
|
|
15302
|
+
return response.symbols.every((entry) => {
|
|
15303
|
+
if (!entry || typeof entry !== "object")
|
|
15304
|
+
return false;
|
|
15305
|
+
const row = entry;
|
|
15306
|
+
return typeof row.name === "string" && row.response !== undefined && row.response !== null;
|
|
15307
|
+
});
|
|
15308
|
+
}
|
|
15309
|
+
function unwrapRustZoomBatchEnvelope(response) {
|
|
15310
|
+
if (!isRustZoomBatchEnvelope(response)) {
|
|
15311
|
+
return null;
|
|
15312
|
+
}
|
|
15313
|
+
const names = [];
|
|
15314
|
+
const responses = [];
|
|
15315
|
+
for (const entry of response.symbols) {
|
|
15316
|
+
names.push(entry.name);
|
|
15317
|
+
responses.push(entry.response);
|
|
15318
|
+
}
|
|
15319
|
+
return { names, responses };
|
|
15320
|
+
}
|
|
15080
15321
|
// src/bg-notifications.ts
|
|
15081
15322
|
import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypto";
|
|
15082
15323
|
|
|
15083
15324
|
// src/logger.ts
|
|
15084
15325
|
import * as fs from "node:fs";
|
|
15085
|
-
import * as
|
|
15086
|
-
import * as
|
|
15326
|
+
import * as os2 from "node:os";
|
|
15327
|
+
import * as path2 from "node:path";
|
|
15087
15328
|
var TAG = "[aft-plugin]";
|
|
15088
15329
|
var isTestEnv = process.env.BUN_TEST === "1" || false;
|
|
15089
|
-
var logFile =
|
|
15330
|
+
var logFile = path2.join(os2.tmpdir(), isTestEnv ? "aft-plugin-test.log" : "aft-plugin.log");
|
|
15090
15331
|
var useStderr = process.env.AFT_LOG_STDERR === "1";
|
|
15091
15332
|
var buffer = [];
|
|
15092
15333
|
var flushTimer = null;
|
|
@@ -15561,7 +15802,7 @@ async function triggerWakeIfPending(drainContext, skipDrain, includeDeferredComp
|
|
|
15561
15802
|
const promptContext = await resolvePromptContext(client, drainContext.sessionID);
|
|
15562
15803
|
const body = {
|
|
15563
15804
|
noReply: false,
|
|
15564
|
-
parts: [{ type: "text", text: reminder }]
|
|
15805
|
+
parts: [{ type: "text", text: reminder, synthetic: true }]
|
|
15565
15806
|
};
|
|
15566
15807
|
if (promptContext?.agent)
|
|
15567
15808
|
body.agent = promptContext.agent;
|
|
@@ -16030,8 +16271,8 @@ function formatDuration(completion) {
|
|
|
16030
16271
|
|
|
16031
16272
|
// src/config.ts
|
|
16032
16273
|
import { existsSync as existsSync6, readFileSync as readFileSync4, renameSync as renameSync4, unlinkSync as unlinkSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
16033
|
-
import { homedir as
|
|
16034
|
-
import { join as
|
|
16274
|
+
import { homedir as homedir7 } from "node:os";
|
|
16275
|
+
import { join as join10 } from "node:path";
|
|
16035
16276
|
var import_comment_json = __toESM(require_src2(), 1);
|
|
16036
16277
|
|
|
16037
16278
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
|
|
@@ -16799,10 +17040,10 @@ function mergeDefs(...defs) {
|
|
|
16799
17040
|
function cloneDef(schema) {
|
|
16800
17041
|
return mergeDefs(schema._zod.def);
|
|
16801
17042
|
}
|
|
16802
|
-
function getElementAtPath(obj,
|
|
16803
|
-
if (!
|
|
17043
|
+
function getElementAtPath(obj, path3) {
|
|
17044
|
+
if (!path3)
|
|
16804
17045
|
return obj;
|
|
16805
|
-
return
|
|
17046
|
+
return path3.reduce((acc, key) => acc?.[key], obj);
|
|
16806
17047
|
}
|
|
16807
17048
|
function promiseAllObject(promisesObj) {
|
|
16808
17049
|
const keys = Object.keys(promisesObj);
|
|
@@ -17183,11 +17424,11 @@ function aborted(x, startIndex = 0) {
|
|
|
17183
17424
|
}
|
|
17184
17425
|
return false;
|
|
17185
17426
|
}
|
|
17186
|
-
function prefixIssues(
|
|
17427
|
+
function prefixIssues(path3, issues) {
|
|
17187
17428
|
return issues.map((iss) => {
|
|
17188
17429
|
var _a;
|
|
17189
17430
|
(_a = iss).path ?? (_a.path = []);
|
|
17190
|
-
iss.path.unshift(
|
|
17431
|
+
iss.path.unshift(path3);
|
|
17191
17432
|
return iss;
|
|
17192
17433
|
});
|
|
17193
17434
|
}
|
|
@@ -17370,7 +17611,7 @@ function formatError(error3, mapper = (issue2) => issue2.message) {
|
|
|
17370
17611
|
}
|
|
17371
17612
|
function treeifyError(error3, mapper = (issue2) => issue2.message) {
|
|
17372
17613
|
const result = { errors: [] };
|
|
17373
|
-
const processError = (error4,
|
|
17614
|
+
const processError = (error4, path3 = []) => {
|
|
17374
17615
|
var _a, _b;
|
|
17375
17616
|
for (const issue2 of error4.issues) {
|
|
17376
17617
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -17380,7 +17621,7 @@ function treeifyError(error3, mapper = (issue2) => issue2.message) {
|
|
|
17380
17621
|
} else if (issue2.code === "invalid_element") {
|
|
17381
17622
|
processError({ issues: issue2.issues }, issue2.path);
|
|
17382
17623
|
} else {
|
|
17383
|
-
const fullpath = [...
|
|
17624
|
+
const fullpath = [...path3, ...issue2.path];
|
|
17384
17625
|
if (fullpath.length === 0) {
|
|
17385
17626
|
result.errors.push(mapper(issue2));
|
|
17386
17627
|
continue;
|
|
@@ -17412,8 +17653,8 @@ function treeifyError(error3, mapper = (issue2) => issue2.message) {
|
|
|
17412
17653
|
}
|
|
17413
17654
|
function toDotPath(_path) {
|
|
17414
17655
|
const segs = [];
|
|
17415
|
-
const
|
|
17416
|
-
for (const seg of
|
|
17656
|
+
const path3 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
17657
|
+
for (const seg of path3) {
|
|
17417
17658
|
if (typeof seg === "number")
|
|
17418
17659
|
segs.push(`[${seg}]`);
|
|
17419
17660
|
else if (typeof seg === "symbol")
|
|
@@ -29160,13 +29401,13 @@ function resolveRef(ref, ctx) {
|
|
|
29160
29401
|
if (!ref.startsWith("#")) {
|
|
29161
29402
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
29162
29403
|
}
|
|
29163
|
-
const
|
|
29164
|
-
if (
|
|
29404
|
+
const path3 = ref.slice(1).split("/").filter(Boolean);
|
|
29405
|
+
if (path3.length === 0) {
|
|
29165
29406
|
return ctx.rootSchema;
|
|
29166
29407
|
}
|
|
29167
29408
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
29168
|
-
if (
|
|
29169
|
-
const key =
|
|
29409
|
+
if (path3[0] === defsKey) {
|
|
29410
|
+
const key = path3[1];
|
|
29170
29411
|
if (!key || !ctx.defs[key]) {
|
|
29171
29412
|
throw new Error(`Reference not found: ${ref}`);
|
|
29172
29413
|
}
|
|
@@ -29645,6 +29886,10 @@ var BashFeaturesSchema = exports_external.object({
|
|
|
29645
29886
|
foreground_wait_window_ms: exports_external.number().int().positive().optional()
|
|
29646
29887
|
});
|
|
29647
29888
|
var BashConfigSchema = exports_external.union([exports_external.boolean(), BashFeaturesSchema]);
|
|
29889
|
+
var BridgeConfigSchema = exports_external.object({
|
|
29890
|
+
request_timeout_ms: exports_external.number().int().min(1000, { message: "bridge.request_timeout_ms must be at least 1000" }).optional(),
|
|
29891
|
+
hang_threshold: exports_external.number().int().min(1, { message: "bridge.hang_threshold must be at least 1" }).optional()
|
|
29892
|
+
});
|
|
29648
29893
|
var InspectConfigSchema = exports_external.object({
|
|
29649
29894
|
enabled: exports_external.boolean().optional(),
|
|
29650
29895
|
tier2_idle_minutes: exports_external.number().min(0).optional(),
|
|
@@ -29684,7 +29929,8 @@ var AftConfigSchema = exports_external.object({
|
|
|
29684
29929
|
url_fetch_allow_private: exports_external.boolean().optional(),
|
|
29685
29930
|
semantic: SemanticConfigSchema.optional(),
|
|
29686
29931
|
max_callgraph_files: exports_external.number().int().positive().optional(),
|
|
29687
|
-
auto_update: exports_external.boolean().optional()
|
|
29932
|
+
auto_update: exports_external.boolean().optional(),
|
|
29933
|
+
bridge: BridgeConfigSchema.optional()
|
|
29688
29934
|
}).strict();
|
|
29689
29935
|
function normalizeLspExtension(extension) {
|
|
29690
29936
|
return extension.trim().replace(/^\.+/, "");
|
|
@@ -29864,9 +30110,9 @@ function extractCommentsForPreservation(content) {
|
|
|
29864
30110
|
}
|
|
29865
30111
|
return comments;
|
|
29866
30112
|
}
|
|
29867
|
-
function ensureRecordAtPath(root,
|
|
30113
|
+
function ensureRecordAtPath(root, path3) {
|
|
29868
30114
|
let current = root;
|
|
29869
|
-
for (const segment of
|
|
30115
|
+
for (const segment of path3) {
|
|
29870
30116
|
const existing = current[segment];
|
|
29871
30117
|
if (!existing || typeof existing !== "object" || Array.isArray(existing)) {
|
|
29872
30118
|
current[segment] = {};
|
|
@@ -29875,9 +30121,9 @@ function ensureRecordAtPath(root, path2) {
|
|
|
29875
30121
|
}
|
|
29876
30122
|
return current;
|
|
29877
30123
|
}
|
|
29878
|
-
function hasPath(root,
|
|
30124
|
+
function hasPath(root, path3) {
|
|
29879
30125
|
let current = root;
|
|
29880
|
-
for (const segment of
|
|
30126
|
+
for (const segment of path3) {
|
|
29881
30127
|
if (!current || typeof current !== "object" || Array.isArray(current))
|
|
29882
30128
|
return false;
|
|
29883
30129
|
const record2 = current;
|
|
@@ -29887,9 +30133,9 @@ function hasPath(root, path2) {
|
|
|
29887
30133
|
}
|
|
29888
30134
|
return true;
|
|
29889
30135
|
}
|
|
29890
|
-
function setPath(root,
|
|
29891
|
-
const parent = ensureRecordAtPath(root,
|
|
29892
|
-
parent[
|
|
30136
|
+
function setPath(root, path3, value) {
|
|
30137
|
+
const parent = ensureRecordAtPath(root, path3.slice(0, -1));
|
|
30138
|
+
parent[path3[path3.length - 1]] = value;
|
|
29893
30139
|
}
|
|
29894
30140
|
function migrateRawConfig(rawConfig, configPath, logger) {
|
|
29895
30141
|
const oldKeys = [];
|
|
@@ -30194,6 +30440,8 @@ function getStrippedTopLevelKeys(override) {
|
|
|
30194
30440
|
stripped.push("max_callgraph_files");
|
|
30195
30441
|
if (override.auto_update !== undefined)
|
|
30196
30442
|
stripped.push("auto_update");
|
|
30443
|
+
if (override.bridge !== undefined)
|
|
30444
|
+
stripped.push("bridge");
|
|
30197
30445
|
return stripped;
|
|
30198
30446
|
}
|
|
30199
30447
|
function mergeConfigs(base, override) {
|
|
@@ -30205,6 +30453,7 @@ function mergeConfigs(base, override) {
|
|
|
30205
30453
|
const experimental = mergeExperimentalConfig(base.experimental, override.experimental);
|
|
30206
30454
|
const bash = mergeBashConfig(base.bash, override.bash);
|
|
30207
30455
|
const inspect = mergeInspectConfig(base.inspect, override.inspect);
|
|
30456
|
+
const bridge = base.bridge;
|
|
30208
30457
|
const safeOverride = pickProjectSafeFields(override);
|
|
30209
30458
|
delete safeOverride.bash;
|
|
30210
30459
|
delete safeOverride.inspect;
|
|
@@ -30218,25 +30467,34 @@ function mergeConfigs(base, override) {
|
|
|
30218
30467
|
...inspect !== undefined ? { inspect } : {},
|
|
30219
30468
|
experimental,
|
|
30220
30469
|
semantic,
|
|
30470
|
+
...bridge !== undefined ? { bridge } : {},
|
|
30221
30471
|
...disabledTools.length > 0 ? { disabled_tools: [...new Set(disabledTools)] } : {}
|
|
30222
30472
|
};
|
|
30223
30473
|
}
|
|
30474
|
+
var DEFAULT_BRIDGE_REQUEST_TIMEOUT_MS = 30000;
|
|
30475
|
+
var DEFAULT_BRIDGE_HANG_THRESHOLD = 2;
|
|
30476
|
+
function resolveBridgePoolTransportOptions(config2) {
|
|
30477
|
+
return {
|
|
30478
|
+
timeoutMs: config2.bridge?.request_timeout_ms ?? DEFAULT_BRIDGE_REQUEST_TIMEOUT_MS,
|
|
30479
|
+
hangThreshold: config2.bridge?.hang_threshold ?? DEFAULT_BRIDGE_HANG_THRESHOLD
|
|
30480
|
+
};
|
|
30481
|
+
}
|
|
30224
30482
|
function getOpenCodeConfigDir() {
|
|
30225
30483
|
const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
30226
30484
|
if (envDir) {
|
|
30227
30485
|
return envDir;
|
|
30228
30486
|
}
|
|
30229
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME ||
|
|
30230
|
-
return
|
|
30487
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME || join10(homedir7(), ".config");
|
|
30488
|
+
return join10(xdgConfig, "opencode");
|
|
30231
30489
|
}
|
|
30232
30490
|
function loadAftConfig(projectDirectory) {
|
|
30233
30491
|
const configDir = getOpenCodeConfigDir();
|
|
30234
|
-
const userBasePath =
|
|
30492
|
+
const userBasePath = join10(configDir, "aft");
|
|
30235
30493
|
migrateAftConfigFile(`${userBasePath}.jsonc`);
|
|
30236
30494
|
migrateAftConfigFile(`${userBasePath}.json`);
|
|
30237
30495
|
const userDetected = detectConfigFile(userBasePath);
|
|
30238
30496
|
const userConfigPath = userDetected.format !== "none" ? userDetected.path : `${userBasePath}.json`;
|
|
30239
|
-
const projectBasePath =
|
|
30497
|
+
const projectBasePath = join10(projectDirectory, ".opencode", "aft");
|
|
30240
30498
|
migrateAftConfigFile(`${projectBasePath}.jsonc`);
|
|
30241
30499
|
migrateAftConfigFile(`${projectBasePath}.json`);
|
|
30242
30500
|
const projectDetected = detectConfigFile(projectBasePath);
|
|
@@ -30262,8 +30520,8 @@ function loadAftConfig(projectDirectory) {
|
|
|
30262
30520
|
|
|
30263
30521
|
// src/notifications.ts
|
|
30264
30522
|
import { existsSync as existsSync7, readFileSync as readFileSync5 } from "node:fs";
|
|
30265
|
-
import { homedir as
|
|
30266
|
-
import { join as
|
|
30523
|
+
import { homedir as homedir8, platform } from "node:os";
|
|
30524
|
+
import { join as join11 } from "node:path";
|
|
30267
30525
|
function isTuiMode() {
|
|
30268
30526
|
return process.env.OPENCODE_CLIENT === "cli";
|
|
30269
30527
|
}
|
|
@@ -30283,18 +30541,18 @@ var FEATURE_MARKER = `${AFT_MARKER} New in`;
|
|
|
30283
30541
|
var WARNING_MARKER = `${AFT_MARKER} ⚠️`;
|
|
30284
30542
|
var STATUS_MARKER = `${AFT_MARKER} ✅`;
|
|
30285
30543
|
function getDesktopStatePath() {
|
|
30286
|
-
const
|
|
30287
|
-
const home =
|
|
30288
|
-
if (
|
|
30289
|
-
return
|
|
30544
|
+
const os3 = platform();
|
|
30545
|
+
const home = homedir8();
|
|
30546
|
+
if (os3 === "darwin") {
|
|
30547
|
+
return join11(home, "Library", "Application Support", "ai.opencode.desktop", "opencode.global.dat");
|
|
30290
30548
|
}
|
|
30291
|
-
if (
|
|
30292
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME ||
|
|
30293
|
-
return
|
|
30549
|
+
if (os3 === "linux") {
|
|
30550
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME || join11(home, ".config");
|
|
30551
|
+
return join11(xdgConfig, "ai.opencode.desktop", "opencode.global.dat");
|
|
30294
30552
|
}
|
|
30295
|
-
if (
|
|
30296
|
-
const appData = process.env.APPDATA ||
|
|
30297
|
-
return
|
|
30553
|
+
if (os3 === "win32") {
|
|
30554
|
+
const appData = process.env.APPDATA || join11(home, "AppData", "Roaming");
|
|
30555
|
+
return join11(appData, "ai.opencode.desktop", "opencode.global.dat");
|
|
30298
30556
|
}
|
|
30299
30557
|
return null;
|
|
30300
30558
|
}
|
|
@@ -30764,37 +31022,37 @@ import { dirname as dirname7 } from "node:path";
|
|
|
30764
31022
|
import { spawn as spawn2 } from "node:child_process";
|
|
30765
31023
|
import { cpSync, existsSync as existsSync9, mkdtempSync, readFileSync as readFileSync7, rmSync as rmSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
30766
31024
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
30767
|
-
import { basename as basename2, dirname as dirname6, join as
|
|
31025
|
+
import { basename as basename2, dirname as dirname6, join as join14 } from "node:path";
|
|
30768
31026
|
var import_comment_json3 = __toESM(require_src2(), 1);
|
|
30769
31027
|
|
|
30770
31028
|
// src/hooks/auto-update-checker/checker.ts
|
|
30771
31029
|
var import_comment_json2 = __toESM(require_src2(), 1);
|
|
30772
31030
|
import { existsSync as existsSync8, readFileSync as readFileSync6, statSync as statSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
30773
|
-
import { homedir as
|
|
30774
|
-
import { dirname as dirname5, isAbsolute as
|
|
31031
|
+
import { homedir as homedir10 } from "node:os";
|
|
31032
|
+
import { dirname as dirname5, isAbsolute as isAbsolute4, join as join13, resolve as resolve3 } from "node:path";
|
|
30775
31033
|
import { fileURLToPath } from "node:url";
|
|
30776
31034
|
|
|
30777
31035
|
// src/hooks/auto-update-checker/constants.ts
|
|
30778
|
-
import { homedir as
|
|
30779
|
-
import { join as
|
|
31036
|
+
import { homedir as homedir9, platform as platform2 } from "node:os";
|
|
31037
|
+
import { join as join12 } from "node:path";
|
|
30780
31038
|
var PACKAGE_NAME = "@cortexkit/aft-opencode";
|
|
30781
31039
|
var NPM_REGISTRY_URL = "https://registry.npmjs.org";
|
|
30782
31040
|
var NPM_FETCH_TIMEOUT = 1e4;
|
|
30783
31041
|
function getOpenCodeCacheRoot() {
|
|
30784
31042
|
if (platform2() === "win32") {
|
|
30785
|
-
return
|
|
31043
|
+
return join12(process.env.LOCALAPPDATA ?? homedir9(), "opencode");
|
|
30786
31044
|
}
|
|
30787
|
-
return
|
|
31045
|
+
return join12(homedir9(), ".cache", "opencode");
|
|
30788
31046
|
}
|
|
30789
31047
|
function getOpenCodeConfigRoot() {
|
|
30790
31048
|
if (platform2() === "win32") {
|
|
30791
|
-
return
|
|
31049
|
+
return join12(process.env.APPDATA ?? join12(homedir9(), "AppData", "Roaming"), "opencode");
|
|
30792
31050
|
}
|
|
30793
|
-
return
|
|
31051
|
+
return join12(process.env.XDG_CONFIG_HOME ?? join12(homedir9(), ".config"), "opencode");
|
|
30794
31052
|
}
|
|
30795
|
-
var CACHE_DIR =
|
|
30796
|
-
var USER_OPENCODE_CONFIG =
|
|
30797
|
-
var USER_OPENCODE_CONFIG_JSONC =
|
|
31053
|
+
var CACHE_DIR = join12(getOpenCodeCacheRoot(), "packages");
|
|
31054
|
+
var USER_OPENCODE_CONFIG = join12(getOpenCodeConfigRoot(), "opencode.json");
|
|
31055
|
+
var USER_OPENCODE_CONFIG_JSONC = join12(getOpenCodeConfigRoot(), "opencode.jsonc");
|
|
30798
31056
|
|
|
30799
31057
|
// src/hooks/auto-update-checker/types.ts
|
|
30800
31058
|
var NpmPackageEnvelopeSchema = exports_external.object({
|
|
@@ -30852,8 +31110,8 @@ function extractChannel(version2) {
|
|
|
30852
31110
|
}
|
|
30853
31111
|
function getConfigPaths(directory) {
|
|
30854
31112
|
return [
|
|
30855
|
-
|
|
30856
|
-
|
|
31113
|
+
join13(directory, ".opencode", "opencode.json"),
|
|
31114
|
+
join13(directory, ".opencode", "opencode.jsonc"),
|
|
30857
31115
|
USER_OPENCODE_CONFIG,
|
|
30858
31116
|
USER_OPENCODE_CONFIG_JSONC
|
|
30859
31117
|
];
|
|
@@ -30866,9 +31124,9 @@ function resolvePathPluginSpec(spec, configPath) {
|
|
|
30866
31124
|
return spec.replace(/^file:\/\//, "");
|
|
30867
31125
|
}
|
|
30868
31126
|
}
|
|
30869
|
-
if (
|
|
31127
|
+
if (isAbsolute4(spec) || /^[A-Za-z]:[\\/]/.test(spec))
|
|
30870
31128
|
return spec;
|
|
30871
|
-
return
|
|
31129
|
+
return resolve3(dirname5(configPath), spec);
|
|
30872
31130
|
}
|
|
30873
31131
|
function getLocalDevPath(directory) {
|
|
30874
31132
|
for (const configPath of getConfigPaths(directory)) {
|
|
@@ -30880,7 +31138,7 @@ function getLocalDevPath(directory) {
|
|
|
30880
31138
|
for (const entry of plugins) {
|
|
30881
31139
|
if (entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`))
|
|
30882
31140
|
continue;
|
|
30883
|
-
if (entry.startsWith("file://") || entry.startsWith(".") ||
|
|
31141
|
+
if (entry.startsWith("file://") || entry.startsWith(".") || isAbsolute4(entry)) {
|
|
30884
31142
|
const localPath = resolvePathPluginSpec(entry, configPath);
|
|
30885
31143
|
const pkgPath = findPackageJsonUp(localPath);
|
|
30886
31144
|
if (!pkgPath)
|
|
@@ -30899,7 +31157,7 @@ function findPackageJsonUp(startPath) {
|
|
|
30899
31157
|
const stat = statSync4(startPath);
|
|
30900
31158
|
let dir = stat.isDirectory() ? startPath : dirname5(startPath);
|
|
30901
31159
|
for (let i = 0;i < 10; i++) {
|
|
30902
|
-
const pkgPath =
|
|
31160
|
+
const pkgPath = join13(dir, "package.json");
|
|
30903
31161
|
if (existsSync8(pkgPath)) {
|
|
30904
31162
|
try {
|
|
30905
31163
|
const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync6(pkgPath, "utf-8")));
|
|
@@ -30960,7 +31218,7 @@ function findPluginEntry(directory) {
|
|
|
30960
31218
|
}
|
|
30961
31219
|
var cachedPackageVersion = null;
|
|
30962
31220
|
function getSpecCachePackageJsonPath(spec) {
|
|
30963
|
-
return
|
|
31221
|
+
return join13(CACHE_DIR, spec, "node_modules", PACKAGE_NAME, "package.json");
|
|
30964
31222
|
}
|
|
30965
31223
|
function getCachedVersion(spec) {
|
|
30966
31224
|
if (!spec && cachedPackageVersion)
|
|
@@ -30969,7 +31227,7 @@ function getCachedVersion(spec) {
|
|
|
30969
31227
|
getCurrentRuntimePackageJsonPath(),
|
|
30970
31228
|
spec ? getSpecCachePackageJsonPath(spec) : null,
|
|
30971
31229
|
getSpecCachePackageJsonPath(`${PACKAGE_NAME}@latest`),
|
|
30972
|
-
|
|
31230
|
+
join13(homedir10(), ".cache", "opencode", "node_modules", PACKAGE_NAME, "package.json")
|
|
30973
31231
|
].filter(isString);
|
|
30974
31232
|
for (const packageJsonPath of candidates) {
|
|
30975
31233
|
try {
|
|
@@ -31017,10 +31275,10 @@ async function getLatestVersion(channel = "latest", options = {}) {
|
|
|
31017
31275
|
// src/hooks/auto-update-checker/cache.ts
|
|
31018
31276
|
var pendingSnapshots = new Map;
|
|
31019
31277
|
function createAutoUpdateSnapshot(installDir, packageJsonPath, packageName) {
|
|
31020
|
-
const packageDir =
|
|
31021
|
-
const lockfilePath =
|
|
31022
|
-
const tempDir = mkdtempSync(
|
|
31023
|
-
const stagedPackageDir = existsSync9(packageDir) ?
|
|
31278
|
+
const packageDir = join14(installDir, "node_modules", packageName);
|
|
31279
|
+
const lockfilePath = join14(installDir, "package-lock.json");
|
|
31280
|
+
const tempDir = mkdtempSync(join14(tmpdir3(), "aft-auto-update-"));
|
|
31281
|
+
const stagedPackageDir = existsSync9(packageDir) ? join14(tempDir, "package") : null;
|
|
31024
31282
|
if (stagedPackageDir)
|
|
31025
31283
|
cpSync(packageDir, stagedPackageDir, { recursive: true });
|
|
31026
31284
|
return {
|
|
@@ -31061,7 +31319,7 @@ function stripPackageNameFromPath(pathValue, packageName) {
|
|
|
31061
31319
|
return current;
|
|
31062
31320
|
}
|
|
31063
31321
|
function removeFromPackageLock(installDir, packageName) {
|
|
31064
|
-
const lockPath =
|
|
31322
|
+
const lockPath = join14(installDir, "package-lock.json");
|
|
31065
31323
|
if (!existsSync9(lockPath))
|
|
31066
31324
|
return false;
|
|
31067
31325
|
try {
|
|
@@ -31110,7 +31368,7 @@ function ensureDependencyVersion(packageJsonPath, packageName, version2) {
|
|
|
31110
31368
|
}
|
|
31111
31369
|
}
|
|
31112
31370
|
function removeInstalledPackage(installDir, packageName) {
|
|
31113
|
-
const packageDir =
|
|
31371
|
+
const packageDir = join14(installDir, "node_modules", packageName);
|
|
31114
31372
|
if (!existsSync9(packageDir))
|
|
31115
31373
|
return false;
|
|
31116
31374
|
rmSync3(packageDir, { recursive: true, force: true });
|
|
@@ -31123,13 +31381,13 @@ function resolveInstallContext(runtimePackageJsonPath = getCurrentRuntimePackage
|
|
|
31123
31381
|
const nodeModulesDir = stripPackageNameFromPath(packageDir, PACKAGE_NAME);
|
|
31124
31382
|
if (nodeModulesDir && basename2(nodeModulesDir) === "node_modules") {
|
|
31125
31383
|
const installDir = dirname6(nodeModulesDir);
|
|
31126
|
-
const packageJsonPath =
|
|
31384
|
+
const packageJsonPath = join14(installDir, "package.json");
|
|
31127
31385
|
if (existsSync9(packageJsonPath))
|
|
31128
31386
|
return { installDir, packageJsonPath };
|
|
31129
31387
|
}
|
|
31130
31388
|
return null;
|
|
31131
31389
|
}
|
|
31132
|
-
const legacyPackageJsonPath =
|
|
31390
|
+
const legacyPackageJsonPath = join14(dirname6(CACHE_DIR), "package.json");
|
|
31133
31391
|
if (existsSync9(legacyPackageJsonPath)) {
|
|
31134
31392
|
return { installDir: dirname6(CACHE_DIR), packageJsonPath: legacyPackageJsonPath };
|
|
31135
31393
|
}
|
|
@@ -31460,7 +31718,7 @@ import {
|
|
|
31460
31718
|
statSync as statSync6,
|
|
31461
31719
|
writeFileSync as writeFileSync8
|
|
31462
31720
|
} from "node:fs";
|
|
31463
|
-
import { join as
|
|
31721
|
+
import { join as join17 } from "node:path";
|
|
31464
31722
|
|
|
31465
31723
|
// src/lsp-cache.ts
|
|
31466
31724
|
import {
|
|
@@ -31472,36 +31730,36 @@ import {
|
|
|
31472
31730
|
unlinkSync as unlinkSync5,
|
|
31473
31731
|
writeFileSync as writeFileSync7
|
|
31474
31732
|
} from "node:fs";
|
|
31475
|
-
import { homedir as
|
|
31476
|
-
import { join as
|
|
31733
|
+
import { homedir as homedir11 } from "node:os";
|
|
31734
|
+
import { join as join15 } from "node:path";
|
|
31477
31735
|
function aftCacheBase() {
|
|
31478
31736
|
const override = process.env.AFT_CACHE_DIR;
|
|
31479
31737
|
if (override && override.length > 0)
|
|
31480
31738
|
return override;
|
|
31481
31739
|
if (process.platform === "win32") {
|
|
31482
31740
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
31483
|
-
const base2 = localAppData ||
|
|
31484
|
-
return
|
|
31741
|
+
const base2 = localAppData || join15(homedir11(), "AppData", "Local");
|
|
31742
|
+
return join15(base2, "aft");
|
|
31485
31743
|
}
|
|
31486
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
31487
|
-
return
|
|
31744
|
+
const base = process.env.XDG_CACHE_HOME || join15(homedir11(), ".cache");
|
|
31745
|
+
return join15(base, "aft");
|
|
31488
31746
|
}
|
|
31489
31747
|
function lspCacheRoot() {
|
|
31490
|
-
return
|
|
31748
|
+
return join15(aftCacheBase(), "lsp-packages");
|
|
31491
31749
|
}
|
|
31492
31750
|
function lspPackageDir(npmPackage) {
|
|
31493
|
-
return
|
|
31751
|
+
return join15(lspCacheRoot(), encodeURIComponent(npmPackage));
|
|
31494
31752
|
}
|
|
31495
31753
|
function lspBinaryPath(npmPackage, binary) {
|
|
31496
|
-
return
|
|
31754
|
+
return join15(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
|
|
31497
31755
|
}
|
|
31498
31756
|
function lspBinDir(npmPackage) {
|
|
31499
|
-
return
|
|
31757
|
+
return join15(lspPackageDir(npmPackage), "node_modules", ".bin");
|
|
31500
31758
|
}
|
|
31501
31759
|
function isInstalled(npmPackage, binary) {
|
|
31502
31760
|
for (const candidate of lspBinaryCandidates(binary)) {
|
|
31503
31761
|
try {
|
|
31504
|
-
if (statSync5(
|
|
31762
|
+
if (statSync5(join15(lspBinDir(npmPackage), candidate)).isFile())
|
|
31505
31763
|
return true;
|
|
31506
31764
|
} catch {}
|
|
31507
31765
|
}
|
|
@@ -31521,17 +31779,17 @@ function writeInstalledMetaIn(installDir, version2, sha256) {
|
|
|
31521
31779
|
installedAt: new Date().toISOString(),
|
|
31522
31780
|
...sha256 ? { sha256 } : {}
|
|
31523
31781
|
};
|
|
31524
|
-
writeFileSync7(
|
|
31782
|
+
writeFileSync7(join15(installDir, INSTALLED_META_FILE), JSON.stringify(meta3), "utf8");
|
|
31525
31783
|
} catch (err) {
|
|
31526
31784
|
log2(`[lsp-cache] failed to write installed-meta in ${installDir}: ${err}`);
|
|
31527
31785
|
}
|
|
31528
31786
|
}
|
|
31529
31787
|
function readInstalledMetaIn(installDir) {
|
|
31530
|
-
const
|
|
31788
|
+
const path3 = join15(installDir, INSTALLED_META_FILE);
|
|
31531
31789
|
try {
|
|
31532
|
-
if (!statSync5(
|
|
31790
|
+
if (!statSync5(path3).isFile())
|
|
31533
31791
|
return null;
|
|
31534
|
-
const raw = readFileSync9(
|
|
31792
|
+
const raw = readFileSync9(path3, "utf8");
|
|
31535
31793
|
const parsed = JSON.parse(raw);
|
|
31536
31794
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
31537
31795
|
return null;
|
|
@@ -31551,7 +31809,7 @@ function readInstalledMeta(packageKey) {
|
|
|
31551
31809
|
return readInstalledMetaIn(lspPackageDir(packageKey));
|
|
31552
31810
|
}
|
|
31553
31811
|
function lockPath(npmPackage) {
|
|
31554
|
-
return
|
|
31812
|
+
return join15(lspPackageDir(npmPackage), ".aft-installing");
|
|
31555
31813
|
}
|
|
31556
31814
|
var STALE_LOCK_MS2 = 30 * 60 * 1000;
|
|
31557
31815
|
function acquireInstallLock(lockKey) {
|
|
@@ -31658,7 +31916,7 @@ async function withInstallLock(lockKey, task) {
|
|
|
31658
31916
|
}
|
|
31659
31917
|
var VERSION_CHECK_FILE = ".aft-version-check";
|
|
31660
31918
|
function readVersionCheck(npmPackage) {
|
|
31661
|
-
const file2 =
|
|
31919
|
+
const file2 = join15(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
|
|
31662
31920
|
try {
|
|
31663
31921
|
const raw = readFileSync9(file2, "utf8");
|
|
31664
31922
|
const parsed = JSON.parse(raw);
|
|
@@ -31675,7 +31933,7 @@ function readVersionCheck(npmPackage) {
|
|
|
31675
31933
|
}
|
|
31676
31934
|
function writeVersionCheck(npmPackage, latest) {
|
|
31677
31935
|
mkdirSync7(lspPackageDir(npmPackage), { recursive: true });
|
|
31678
|
-
const file2 =
|
|
31936
|
+
const file2 = join15(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
|
|
31679
31937
|
const record2 = {
|
|
31680
31938
|
last_checked: new Date().toISOString(),
|
|
31681
31939
|
latest_eligible: latest
|
|
@@ -31838,7 +32096,7 @@ var NPM_LSP_TABLE = [
|
|
|
31838
32096
|
|
|
31839
32097
|
// src/lsp-project-relevance.ts
|
|
31840
32098
|
import { existsSync as existsSync11, readdirSync as readdirSync3, readFileSync as readFileSync10 } from "node:fs";
|
|
31841
|
-
import { join as
|
|
32099
|
+
import { join as join16 } from "node:path";
|
|
31842
32100
|
var MAX_WALK_DIRS = 200;
|
|
31843
32101
|
var MAX_WALK_DEPTH = 4;
|
|
31844
32102
|
var NOISE_DIRS = new Set([
|
|
@@ -31855,7 +32113,7 @@ function hasRootMarker(projectRoot, rootMarkers) {
|
|
|
31855
32113
|
if (!rootMarkers)
|
|
31856
32114
|
return false;
|
|
31857
32115
|
for (const marker of rootMarkers) {
|
|
31858
|
-
if (existsSync11(
|
|
32116
|
+
if (existsSync11(join16(projectRoot, marker)))
|
|
31859
32117
|
return true;
|
|
31860
32118
|
}
|
|
31861
32119
|
return false;
|
|
@@ -31879,7 +32137,7 @@ function hasPackageJsonDep(projectRoot, depNames) {
|
|
|
31879
32137
|
}
|
|
31880
32138
|
function readPackageJson(projectRoot) {
|
|
31881
32139
|
try {
|
|
31882
|
-
const raw = readFileSync10(
|
|
32140
|
+
const raw = readFileSync10(join16(projectRoot, "package.json"), "utf8");
|
|
31883
32141
|
const parsed = JSON.parse(raw);
|
|
31884
32142
|
if (typeof parsed !== "object" || parsed === null)
|
|
31885
32143
|
return null;
|
|
@@ -31909,7 +32167,7 @@ function relevantExtensionsInProject(projectRoot, extToServer) {
|
|
|
31909
32167
|
for (const entry of entries) {
|
|
31910
32168
|
if (entry.isDirectory()) {
|
|
31911
32169
|
if (current.depth < MAX_WALK_DEPTH && !NOISE_DIRS.has(entry.name.toLowerCase())) {
|
|
31912
|
-
queue.push({ dir:
|
|
32170
|
+
queue.push({ dir: join16(current.dir, entry.name), depth: current.depth + 1 });
|
|
31913
32171
|
}
|
|
31914
32172
|
continue;
|
|
31915
32173
|
}
|
|
@@ -32036,7 +32294,7 @@ async function resolveTargetVersion(spec, config2, fetchImpl = fetch) {
|
|
|
32036
32294
|
}
|
|
32037
32295
|
function ensureInstallAnchor(cwd) {
|
|
32038
32296
|
try {
|
|
32039
|
-
const stub =
|
|
32297
|
+
const stub = join17(cwd, "package.json");
|
|
32040
32298
|
if (!existsSync12(stub)) {
|
|
32041
32299
|
writeFileSync8(stub, `${JSON.stringify({ name: "aft-lsp-cache", version: "0.0.0", private: true })}
|
|
32042
32300
|
`);
|
|
@@ -32046,18 +32304,18 @@ function ensureInstallAnchor(cwd) {
|
|
|
32046
32304
|
}
|
|
32047
32305
|
}
|
|
32048
32306
|
function runInstall(spec, version2, cwd, signal) {
|
|
32049
|
-
return new Promise((
|
|
32307
|
+
return new Promise((resolve4) => {
|
|
32050
32308
|
const target = `${spec.npm}@${version2}`;
|
|
32051
32309
|
log2(`[lsp] installing ${target} to ${cwd}`);
|
|
32052
32310
|
if (signal?.aborted) {
|
|
32053
32311
|
warn2(`[lsp] install ${target} aborted before spawn`);
|
|
32054
|
-
|
|
32312
|
+
resolve4(false);
|
|
32055
32313
|
return;
|
|
32056
32314
|
}
|
|
32057
32315
|
const npm = resolveNpm();
|
|
32058
32316
|
if (!npm) {
|
|
32059
32317
|
warn2(`[lsp] npm not found on PATH or known locations; cannot install ${target}`);
|
|
32060
|
-
|
|
32318
|
+
resolve4(false);
|
|
32061
32319
|
return;
|
|
32062
32320
|
}
|
|
32063
32321
|
ensureInstallAnchor(cwd);
|
|
@@ -32080,7 +32338,7 @@ function runInstall(spec, version2, cwd, signal) {
|
|
|
32080
32338
|
return;
|
|
32081
32339
|
settled = true;
|
|
32082
32340
|
cleanup();
|
|
32083
|
-
|
|
32341
|
+
resolve4(ok);
|
|
32084
32342
|
};
|
|
32085
32343
|
const onAbort = () => {
|
|
32086
32344
|
warn2(`[lsp] install ${target} aborted during shutdown`);
|
|
@@ -32181,7 +32439,7 @@ function cachedPackageDir(npmPackage) {
|
|
|
32181
32439
|
return lspBinDir(npmPackage).replace(/[\\/]node_modules[\\/]\.bin[\\/]?$/, "");
|
|
32182
32440
|
}
|
|
32183
32441
|
function hashInstalledBinary(spec) {
|
|
32184
|
-
return new Promise((
|
|
32442
|
+
return new Promise((resolve4, reject) => {
|
|
32185
32443
|
const candidates = process.platform === "win32" ? [
|
|
32186
32444
|
lspBinaryPath(spec.npm, spec.binary),
|
|
32187
32445
|
lspBinaryPath(spec.npm, `${spec.binary}.cmd`),
|
|
@@ -32205,7 +32463,7 @@ function hashInstalledBinary(spec) {
|
|
|
32205
32463
|
const stream = createReadStream(pathToHash);
|
|
32206
32464
|
stream.on("error", reject);
|
|
32207
32465
|
stream.on("data", (chunk) => hash2.update(chunk));
|
|
32208
|
-
stream.on("end", () =>
|
|
32466
|
+
stream.on("end", () => resolve4(hash2.digest("hex")));
|
|
32209
32467
|
});
|
|
32210
32468
|
}
|
|
32211
32469
|
function installedBinaryPath(spec) {
|
|
@@ -32223,15 +32481,15 @@ function installedBinaryPath(spec) {
|
|
|
32223
32481
|
}
|
|
32224
32482
|
return null;
|
|
32225
32483
|
}
|
|
32226
|
-
function sha256OfFileSync(
|
|
32227
|
-
return createHash4("sha256").update(readFileSync11(
|
|
32484
|
+
function sha256OfFileSync(path3) {
|
|
32485
|
+
return createHash4("sha256").update(readFileSync11(path3)).digest("hex");
|
|
32228
32486
|
}
|
|
32229
32487
|
function quarantineCachedNpmInstall(spec, reason) {
|
|
32230
32488
|
const packageDir = lspPackageDir(spec.npm);
|
|
32231
|
-
const dest =
|
|
32489
|
+
const dest = join17(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
|
|
32232
32490
|
warn2(`[lsp] tofu_mismatch ${spec.npm}: ${reason}; quarantining ${packageDir} -> ${dest}`);
|
|
32233
32491
|
try {
|
|
32234
|
-
mkdirSync8(
|
|
32492
|
+
mkdirSync8(join17(dest, ".."), { recursive: true });
|
|
32235
32493
|
rmSync5(dest, { recursive: true, force: true });
|
|
32236
32494
|
renameSync6(packageDir, dest);
|
|
32237
32495
|
} catch (err) {
|
|
@@ -32327,7 +32585,7 @@ import {
|
|
|
32327
32585
|
unlinkSync as unlinkSync6,
|
|
32328
32586
|
writeFileSync as writeFileSync9
|
|
32329
32587
|
} from "node:fs";
|
|
32330
|
-
import { dirname as dirname8, join as
|
|
32588
|
+
import { dirname as dirname8, join as join18, relative as relative3, resolve as resolve4 } from "node:path";
|
|
32331
32589
|
import { Readable as Readable3 } from "node:stream";
|
|
32332
32590
|
import { pipeline as pipeline3 } from "node:stream/promises";
|
|
32333
32591
|
|
|
@@ -32417,26 +32675,26 @@ function detectHostPlatform() {
|
|
|
32417
32675
|
|
|
32418
32676
|
// src/lsp-github-install.ts
|
|
32419
32677
|
function ghCacheRoot() {
|
|
32420
|
-
return
|
|
32678
|
+
return join18(aftCacheBase(), "lsp-binaries");
|
|
32421
32679
|
}
|
|
32422
32680
|
function ghPackageDir(spec) {
|
|
32423
|
-
return
|
|
32681
|
+
return join18(ghCacheRoot(), spec.id);
|
|
32424
32682
|
}
|
|
32425
32683
|
function ghBinDir(spec) {
|
|
32426
|
-
return
|
|
32684
|
+
return join18(ghPackageDir(spec), "bin");
|
|
32427
32685
|
}
|
|
32428
32686
|
function ghExtractDir(spec) {
|
|
32429
|
-
return
|
|
32687
|
+
return join18(ghPackageDir(spec), "extracted");
|
|
32430
32688
|
}
|
|
32431
32689
|
var INSTALLED_META_FILE2 = ".aft-installed";
|
|
32432
32690
|
function ghBinaryPath(spec, platform3) {
|
|
32433
32691
|
const ext = platform3 === "win32" ? ".exe" : "";
|
|
32434
|
-
return
|
|
32692
|
+
return join18(ghBinDir(spec), `${spec.binary}${ext}`);
|
|
32435
32693
|
}
|
|
32436
32694
|
function isGithubInstalled(spec, platform3) {
|
|
32437
32695
|
for (const candidate of ghBinaryCandidates(spec, platform3)) {
|
|
32438
32696
|
try {
|
|
32439
|
-
if (statSync7(
|
|
32697
|
+
if (statSync7(join18(ghBinDir(spec), candidate)).isFile())
|
|
32440
32698
|
return true;
|
|
32441
32699
|
} catch {}
|
|
32442
32700
|
}
|
|
@@ -32449,10 +32707,10 @@ function ghBinaryCandidates(spec, platform3) {
|
|
|
32449
32707
|
}
|
|
32450
32708
|
function readGithubInstalledMetaIn(installDir) {
|
|
32451
32709
|
try {
|
|
32452
|
-
const
|
|
32453
|
-
if (!statSync7(
|
|
32710
|
+
const path3 = join18(installDir, INSTALLED_META_FILE2);
|
|
32711
|
+
if (!statSync7(path3).isFile())
|
|
32454
32712
|
return null;
|
|
32455
|
-
const parsed = JSON.parse(readFileSync12(
|
|
32713
|
+
const parsed = JSON.parse(readFileSync12(path3, "utf8"));
|
|
32456
32714
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
32457
32715
|
return null;
|
|
32458
32716
|
return {
|
|
@@ -32476,24 +32734,24 @@ function writeGithubInstalledMetaIn(installDir, version2, binarySha256, archiveS
|
|
|
32476
32734
|
binarySha256,
|
|
32477
32735
|
...archiveSha256 ? { archiveSha256 } : {}
|
|
32478
32736
|
};
|
|
32479
|
-
writeFileSync9(
|
|
32737
|
+
writeFileSync9(join18(installDir, INSTALLED_META_FILE2), JSON.stringify(meta3), "utf8");
|
|
32480
32738
|
} catch (err) {
|
|
32481
32739
|
warn2(`[lsp] failed to write github installed metadata in ${installDir}: ${err}`);
|
|
32482
32740
|
}
|
|
32483
32741
|
}
|
|
32484
32742
|
var MAX_DOWNLOAD_BYTES3 = 256 * 1024 * 1024;
|
|
32485
32743
|
var MAX_EXTRACT_BYTES2 = 1024 * 1024 * 1024;
|
|
32486
|
-
function sha256OfFile(
|
|
32487
|
-
return new Promise((
|
|
32744
|
+
function sha256OfFile(path3) {
|
|
32745
|
+
return new Promise((resolve5, reject) => {
|
|
32488
32746
|
const hash2 = createHash5("sha256");
|
|
32489
|
-
const stream = createReadStream2(
|
|
32747
|
+
const stream = createReadStream2(path3);
|
|
32490
32748
|
stream.on("error", reject);
|
|
32491
32749
|
stream.on("data", (chunk) => hash2.update(chunk));
|
|
32492
|
-
stream.on("end", () =>
|
|
32750
|
+
stream.on("end", () => resolve5(hash2.digest("hex")));
|
|
32493
32751
|
});
|
|
32494
32752
|
}
|
|
32495
|
-
function sha256OfFileSync2(
|
|
32496
|
-
return createHash5("sha256").update(readFileSync12(
|
|
32753
|
+
function sha256OfFileSync2(path3) {
|
|
32754
|
+
return createHash5("sha256").update(readFileSync12(path3)).digest("hex");
|
|
32497
32755
|
}
|
|
32498
32756
|
async function fetchReleaseByTag(githubRepo, tag, fetchImpl, signal) {
|
|
32499
32757
|
const candidates = [];
|
|
@@ -32725,7 +32983,7 @@ function validateExtraction(stagingRoot) {
|
|
|
32725
32983
|
throw new Error(`failed to read staging dir ${dir}: ${err}`);
|
|
32726
32984
|
}
|
|
32727
32985
|
for (const entry of entries) {
|
|
32728
|
-
const full =
|
|
32986
|
+
const full = join18(dir, entry);
|
|
32729
32987
|
let lst;
|
|
32730
32988
|
try {
|
|
32731
32989
|
lst = lstatSync2(full);
|
|
@@ -32737,7 +32995,7 @@ function validateExtraction(stagingRoot) {
|
|
|
32737
32995
|
try {
|
|
32738
32996
|
target = readlinkSync2(full);
|
|
32739
32997
|
} catch {}
|
|
32740
|
-
throw new Error(`archive contains symlink ${
|
|
32998
|
+
throw new Error(`archive contains symlink ${relative3(realStagingRoot, full)} → ${target}; rejecting (zip-slip defense)`);
|
|
32741
32999
|
}
|
|
32742
33000
|
let realFull;
|
|
32743
33001
|
try {
|
|
@@ -32745,8 +33003,8 @@ function validateExtraction(stagingRoot) {
|
|
|
32745
33003
|
} catch (err) {
|
|
32746
33004
|
throw new Error(`failed to realpath ${full}: ${err}`);
|
|
32747
33005
|
}
|
|
32748
|
-
const rel =
|
|
32749
|
-
if (rel.startsWith("..") ||
|
|
33006
|
+
const rel = relative3(realStagingRoot, realFull);
|
|
33007
|
+
if (rel.startsWith("..") || resolve4(realStagingRoot, rel) !== realFull) {
|
|
32750
33008
|
throw new Error(`archive entry escapes staging root: ${full} → ${realFull} (zip-slip defense)`);
|
|
32751
33009
|
}
|
|
32752
33010
|
if (lst.isDirectory()) {
|
|
@@ -32813,7 +33071,7 @@ function extractArchiveSafely(archivePath, destDir, archiveType) {
|
|
|
32813
33071
|
}
|
|
32814
33072
|
function quarantineCachedGithubInstall(spec, reason) {
|
|
32815
33073
|
const packageDir = ghPackageDir(spec);
|
|
32816
|
-
const dest =
|
|
33074
|
+
const dest = join18(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
|
|
32817
33075
|
warn2(`[lsp] tofu_mismatch ${spec.id}: ${reason}; quarantining ${packageDir} -> ${dest}`);
|
|
32818
33076
|
try {
|
|
32819
33077
|
mkdirSync9(dirname8(dest), { recursive: true });
|
|
@@ -32826,7 +33084,7 @@ function quarantineCachedGithubInstall(spec, reason) {
|
|
|
32826
33084
|
function validateCachedGithubInstall(spec, platform3) {
|
|
32827
33085
|
const packageDir = ghPackageDir(spec);
|
|
32828
33086
|
const meta3 = readGithubInstalledMetaIn(packageDir);
|
|
32829
|
-
const binaryPath = ghBinaryCandidates(spec, platform3).map((candidate) =>
|
|
33087
|
+
const binaryPath = ghBinaryCandidates(spec, platform3).map((candidate) => join18(ghBinDir(spec), candidate)).find((candidate) => {
|
|
32830
33088
|
try {
|
|
32831
33089
|
return statSync7(candidate).isFile();
|
|
32832
33090
|
} catch {
|
|
@@ -32904,7 +33162,7 @@ async function downloadAndInstall(spec, tag, assets, platform3, arch, fetchImpl,
|
|
|
32904
33162
|
}
|
|
32905
33163
|
const pkgDir = ghPackageDir(spec);
|
|
32906
33164
|
const extractDir = ghExtractDir(spec);
|
|
32907
|
-
const archivePath =
|
|
33165
|
+
const archivePath = join18(pkgDir, expected.name);
|
|
32908
33166
|
log2(`[lsp] downloading ${spec.id} ${tag} → ${matchingAsset.url}`);
|
|
32909
33167
|
try {
|
|
32910
33168
|
await downloadFile(matchingAsset.url, archivePath, fetchImpl, matchingAsset.size, signal);
|
|
@@ -32944,7 +33202,7 @@ async function downloadAndInstall(spec, tag, assets, platform3, arch, fetchImpl,
|
|
|
32944
33202
|
unlinkSync6(archivePath);
|
|
32945
33203
|
} catch {}
|
|
32946
33204
|
}
|
|
32947
|
-
const innerBinaryPath =
|
|
33205
|
+
const innerBinaryPath = join18(extractDir, spec.binaryPathInArchive(platform3, arch, version2));
|
|
32948
33206
|
if (!existsSync13(innerBinaryPath)) {
|
|
32949
33207
|
error2(`[lsp] ${spec.id}: extracted binary not found at ${innerBinaryPath}`);
|
|
32950
33208
|
return null;
|
|
@@ -33239,7 +33497,7 @@ function renderScreen(state, rows = state.rows, cols = state.cols) {
|
|
|
33239
33497
|
`);
|
|
33240
33498
|
}
|
|
33241
33499
|
function writeTerminal(terminal, data) {
|
|
33242
|
-
return new Promise((
|
|
33500
|
+
return new Promise((resolve5) => terminal.write(data, resolve5));
|
|
33243
33501
|
}
|
|
33244
33502
|
|
|
33245
33503
|
// src/shared/rpc-server.ts
|
|
@@ -33254,18 +33512,18 @@ import {
|
|
|
33254
33512
|
writeFileSync as writeFileSync10
|
|
33255
33513
|
} from "node:fs";
|
|
33256
33514
|
import { createServer } from "node:http";
|
|
33257
|
-
import { dirname as dirname9, join as
|
|
33515
|
+
import { dirname as dirname9, join as join20 } from "node:path";
|
|
33258
33516
|
|
|
33259
33517
|
// src/shared/rpc-utils.ts
|
|
33260
33518
|
import { createHash as createHash6 } from "node:crypto";
|
|
33261
|
-
import { join as
|
|
33519
|
+
import { join as join19 } from "node:path";
|
|
33262
33520
|
function projectHash(directory) {
|
|
33263
33521
|
const normalized = directory.replace(/\/+$/, "");
|
|
33264
33522
|
return createHash6("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
33265
33523
|
}
|
|
33266
33524
|
function rpcPortFileDir(storageDir, directory) {
|
|
33267
33525
|
const hash2 = projectHash(directory);
|
|
33268
|
-
return
|
|
33526
|
+
return join19(storageDir, "rpc", hash2, "ports");
|
|
33269
33527
|
}
|
|
33270
33528
|
function isPidAlive(pid) {
|
|
33271
33529
|
if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0)
|
|
@@ -33318,13 +33576,13 @@ class AftRpcServer {
|
|
|
33318
33576
|
constructor(storageDir, directory) {
|
|
33319
33577
|
this.portsDir = rpcPortFileDir(storageDir, directory);
|
|
33320
33578
|
this.instanceId = randomBytes2(8).toString("hex");
|
|
33321
|
-
this.portFilePath =
|
|
33579
|
+
this.portFilePath = join20(this.portsDir, `${this.instanceId}.json`);
|
|
33322
33580
|
}
|
|
33323
33581
|
handle(method, handler) {
|
|
33324
33582
|
this.handlers.set(method, handler);
|
|
33325
33583
|
}
|
|
33326
33584
|
async start() {
|
|
33327
|
-
return new Promise((
|
|
33585
|
+
return new Promise((resolve5, reject) => {
|
|
33328
33586
|
const server = createServer((req, res) => this.dispatch(req, res));
|
|
33329
33587
|
server.on("error", (err) => {
|
|
33330
33588
|
warn2(`RPC server error: ${err.message}`);
|
|
@@ -33357,7 +33615,7 @@ class AftRpcServer {
|
|
|
33357
33615
|
} catch (err) {
|
|
33358
33616
|
warn2(`Failed to write RPC port file: ${err}`);
|
|
33359
33617
|
}
|
|
33360
|
-
|
|
33618
|
+
resolve5(this.port);
|
|
33361
33619
|
});
|
|
33362
33620
|
server.unref();
|
|
33363
33621
|
});
|
|
@@ -33372,7 +33630,7 @@ class AftRpcServer {
|
|
|
33372
33630
|
for (const entry of entries) {
|
|
33373
33631
|
if (!entry.endsWith(".json"))
|
|
33374
33632
|
continue;
|
|
33375
|
-
const filePath =
|
|
33633
|
+
const filePath = join20(this.portsDir, entry);
|
|
33376
33634
|
if (filePath === this.portFilePath)
|
|
33377
33635
|
continue;
|
|
33378
33636
|
try {
|
|
@@ -33777,20 +34035,20 @@ function formatStatusMarkdown(status) {
|
|
|
33777
34035
|
// src/shared/tui-config.ts
|
|
33778
34036
|
var import_comment_json4 = __toESM(require_src2(), 1);
|
|
33779
34037
|
import { existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "node:fs";
|
|
33780
|
-
import { dirname as dirname10, join as
|
|
34038
|
+
import { dirname as dirname10, join as join22 } from "node:path";
|
|
33781
34039
|
|
|
33782
34040
|
// src/shared/opencode-config-dir.ts
|
|
33783
|
-
import { homedir as
|
|
33784
|
-
import { join as
|
|
34041
|
+
import { homedir as homedir12 } from "node:os";
|
|
34042
|
+
import { join as join21, resolve as resolve5 } from "node:path";
|
|
33785
34043
|
function getCliConfigDir() {
|
|
33786
34044
|
const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
33787
34045
|
if (envConfigDir) {
|
|
33788
|
-
return
|
|
34046
|
+
return resolve5(envConfigDir);
|
|
33789
34047
|
}
|
|
33790
34048
|
if (process.platform === "win32") {
|
|
33791
|
-
return
|
|
34049
|
+
return join21(homedir12(), ".config", "opencode");
|
|
33792
34050
|
}
|
|
33793
|
-
return
|
|
34051
|
+
return join21(process.env.XDG_CONFIG_HOME || join21(homedir12(), ".config"), "opencode");
|
|
33794
34052
|
}
|
|
33795
34053
|
function getOpenCodeConfigDir2(_options) {
|
|
33796
34054
|
return getCliConfigDir();
|
|
@@ -33799,10 +34057,10 @@ function getOpenCodeConfigPaths(options) {
|
|
|
33799
34057
|
const configDir = getOpenCodeConfigDir2(options);
|
|
33800
34058
|
return {
|
|
33801
34059
|
configDir,
|
|
33802
|
-
configJson:
|
|
33803
|
-
configJsonc:
|
|
33804
|
-
packageJson:
|
|
33805
|
-
omoConfig:
|
|
34060
|
+
configJson: join21(configDir, "opencode.json"),
|
|
34061
|
+
configJsonc: join21(configDir, "opencode.jsonc"),
|
|
34062
|
+
packageJson: join21(configDir, "package.json"),
|
|
34063
|
+
omoConfig: join21(configDir, "magic-context.jsonc")
|
|
33806
34064
|
};
|
|
33807
34065
|
}
|
|
33808
34066
|
|
|
@@ -33811,8 +34069,8 @@ var PLUGIN_NAME = "@cortexkit/aft-opencode";
|
|
|
33811
34069
|
var PLUGIN_ENTRY = `${PLUGIN_NAME}@latest`;
|
|
33812
34070
|
function resolveTuiConfigPath() {
|
|
33813
34071
|
const configDir = getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
|
|
33814
|
-
const jsoncPath =
|
|
33815
|
-
const jsonPath =
|
|
34072
|
+
const jsoncPath = join22(configDir, "tui.jsonc");
|
|
34073
|
+
const jsonPath = join22(configDir, "tui.json");
|
|
33816
34074
|
if (existsSync15(jsoncPath))
|
|
33817
34075
|
return jsoncPath;
|
|
33818
34076
|
if (existsSync15(jsonPath))
|
|
@@ -33901,8 +34159,8 @@ function installProcessHandlers() {
|
|
|
33901
34159
|
}
|
|
33902
34160
|
signalShutdownStarted = true;
|
|
33903
34161
|
process.exitCode = SIGNAL_EXIT_CODES[sig];
|
|
33904
|
-
const timeout = new Promise((
|
|
33905
|
-
setTimeout(
|
|
34162
|
+
const timeout = new Promise((resolve6) => {
|
|
34163
|
+
setTimeout(resolve6, SIGNAL_CLEANUP_TIMEOUT_MS);
|
|
33906
34164
|
});
|
|
33907
34165
|
Promise.race([runCleanups(sig), timeout]).finally(() => {
|
|
33908
34166
|
process.exit(SIGNAL_EXIT_CODES[sig]);
|
|
@@ -34014,99 +34272,18 @@ import { tool as tool3 } from "@opencode-ai/plugin";
|
|
|
34014
34272
|
|
|
34015
34273
|
// src/tools/_shared.ts
|
|
34016
34274
|
import * as fs3 from "node:fs";
|
|
34017
|
-
import * as
|
|
34018
|
-
import * as
|
|
34275
|
+
import * as os3 from "node:os";
|
|
34276
|
+
import * as path3 from "node:path";
|
|
34019
34277
|
import { tool as tool2 } from "@opencode-ai/plugin";
|
|
34020
34278
|
var z2 = tool2.schema;
|
|
34021
34279
|
var optionalInt = (min, max) => z2.number().int().min(min).max(max).optional();
|
|
34022
|
-
function isEmptyParam(value) {
|
|
34023
|
-
if (value === undefined || value === null)
|
|
34024
|
-
return true;
|
|
34025
|
-
if (typeof value === "string")
|
|
34026
|
-
return value.length === 0;
|
|
34027
|
-
if (Array.isArray(value))
|
|
34028
|
-
return value.length === 0;
|
|
34029
|
-
if (typeof value === "object")
|
|
34030
|
-
return Object.keys(value).length === 0;
|
|
34031
|
-
return false;
|
|
34032
|
-
}
|
|
34033
34280
|
var BASH_TRANSPORT_TIMEOUT_MS = 30000;
|
|
34034
|
-
function asPlainObject(value) {
|
|
34035
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
34036
|
-
return;
|
|
34037
|
-
return value;
|
|
34038
|
-
}
|
|
34039
|
-
function candidateLocation(candidate) {
|
|
34040
|
-
const file2 = typeof candidate.file === "string" && candidate.file.length > 0 ? candidate.file : undefined;
|
|
34041
|
-
if (!file2)
|
|
34042
|
-
return;
|
|
34043
|
-
const line = typeof candidate.line === "number" && Number.isFinite(candidate.line) ? candidate.line : undefined;
|
|
34044
|
-
return line === undefined ? file2 : `${file2}:${line}`;
|
|
34045
|
-
}
|
|
34046
|
-
function stringifyData(data) {
|
|
34047
|
-
if (data === undefined)
|
|
34048
|
-
return;
|
|
34049
|
-
try {
|
|
34050
|
-
return JSON.stringify(data, null, 2);
|
|
34051
|
-
} catch {
|
|
34052
|
-
return String(data);
|
|
34053
|
-
}
|
|
34054
|
-
}
|
|
34055
|
-
function formatBridgeErrorMessage(command, response, params = {}) {
|
|
34056
|
-
const code = typeof response.code === "string" && response.code.length > 0 ? response.code : undefined;
|
|
34057
|
-
const message = typeof response.message === "string" && response.message.length > 0 ? response.message : `${command} failed`;
|
|
34058
|
-
const data = asPlainObject(response.data);
|
|
34059
|
-
const rawCandidates = Array.isArray(response.candidates) ? response.candidates : Array.isArray(data?.candidates) ? data.candidates : undefined;
|
|
34060
|
-
const rawSymbol = typeof response.symbol === "string" && response.symbol.length > 0 ? response.symbol : typeof data?.symbol === "string" && data.symbol.length > 0 ? data.symbol : undefined;
|
|
34061
|
-
if (code === "ambiguous_target" || code === "target_symbol_not_in_file") {
|
|
34062
|
-
const candidates = (rawCandidates ?? []).map(asPlainObject).filter((candidate) => candidate !== undefined).map(candidateLocation).filter((candidate) => candidate !== undefined);
|
|
34063
|
-
if (candidates.length > 0) {
|
|
34064
|
-
const symbol2 = typeof params.toSymbol === "string" && params.toSymbol.length > 0 ? params.toSymbol : rawSymbol;
|
|
34065
|
-
const target = symbol2 ? `multiple symbols named "${symbol2}"` : message.replace(/[.!?]+$/, "");
|
|
34066
|
-
const action = code === "ambiguous_target" ? "Pass toFile to disambiguate" : "Try one of these files for toFile";
|
|
34067
|
-
return `${command}: ${code} — ${target}. ${action}:
|
|
34068
|
-
${candidates.map((candidate) => ` - ${candidate}`).join(`
|
|
34069
|
-
`)}`;
|
|
34070
|
-
}
|
|
34071
|
-
}
|
|
34072
|
-
if (!code)
|
|
34073
|
-
return message;
|
|
34074
|
-
const lines = [`${command}: ${code} — ${message}`];
|
|
34075
|
-
const extras = collectStructuredExtras(response);
|
|
34076
|
-
if (extras)
|
|
34077
|
-
lines.push(`data: ${extras}`);
|
|
34078
|
-
return lines.join(`
|
|
34079
|
-
`);
|
|
34080
|
-
}
|
|
34081
|
-
function collectStructuredExtras(response) {
|
|
34082
|
-
const reserved = new Set([
|
|
34083
|
-
"id",
|
|
34084
|
-
"success",
|
|
34085
|
-
"code",
|
|
34086
|
-
"message",
|
|
34087
|
-
"data",
|
|
34088
|
-
"status_bar",
|
|
34089
|
-
"bg_completions"
|
|
34090
|
-
]);
|
|
34091
|
-
const extras = {};
|
|
34092
|
-
for (const [key, value] of Object.entries(response)) {
|
|
34093
|
-
if (reserved.has(key))
|
|
34094
|
-
continue;
|
|
34095
|
-
extras[key] = value;
|
|
34096
|
-
}
|
|
34097
|
-
if (Object.keys(extras).length === 0) {
|
|
34098
|
-
return stringifyData(response.data);
|
|
34099
|
-
}
|
|
34100
|
-
if (response.data !== undefined)
|
|
34101
|
-
extras.data = response.data;
|
|
34102
|
-
return stringifyData(extras);
|
|
34103
|
-
}
|
|
34104
34281
|
function canonicalizeDirectory(dir) {
|
|
34105
34282
|
const trimmed = dir.replace(/[/\\]+$/, "");
|
|
34106
34283
|
try {
|
|
34107
34284
|
return fs3.realpathSync(trimmed);
|
|
34108
34285
|
} catch {
|
|
34109
|
-
return
|
|
34286
|
+
return path3.resolve(trimmed);
|
|
34110
34287
|
}
|
|
34111
34288
|
}
|
|
34112
34289
|
function projectRootFor(runtime) {
|
|
@@ -34123,19 +34300,19 @@ async function resolveProjectRoot(ctx, runtime) {
|
|
|
34123
34300
|
}
|
|
34124
34301
|
return projectRootFor(runtime);
|
|
34125
34302
|
}
|
|
34126
|
-
function
|
|
34303
|
+
function expandTilde2(input) {
|
|
34127
34304
|
if (!input || !input.startsWith("~"))
|
|
34128
34305
|
return input;
|
|
34129
34306
|
if (input === "~")
|
|
34130
|
-
return
|
|
34131
|
-
if (input.startsWith("~/") || input.startsWith(`~${
|
|
34132
|
-
return
|
|
34307
|
+
return os3.homedir();
|
|
34308
|
+
if (input.startsWith("~/") || input.startsWith(`~${path3.sep}`)) {
|
|
34309
|
+
return path3.resolve(os3.homedir(), input.slice(2));
|
|
34133
34310
|
}
|
|
34134
34311
|
return input;
|
|
34135
34312
|
}
|
|
34136
34313
|
function resolvePathFromProjectRoot(projectRoot, target) {
|
|
34137
|
-
const expanded =
|
|
34138
|
-
return
|
|
34314
|
+
const expanded = expandTilde2(target);
|
|
34315
|
+
return path3.isAbsolute(expanded) ? expanded : path3.resolve(projectRoot, expanded);
|
|
34139
34316
|
}
|
|
34140
34317
|
async function resolvePathArg(ctx, runtime, target) {
|
|
34141
34318
|
return resolvePathFromProjectRoot(await resolveProjectRoot(ctx, runtime), target);
|
|
@@ -34177,19 +34354,19 @@ async function callBashBridge(ctx, runtime, command, params = {}, options) {
|
|
|
34177
34354
|
|
|
34178
34355
|
// src/tools/permissions.ts
|
|
34179
34356
|
import * as fs4 from "node:fs";
|
|
34180
|
-
import * as
|
|
34357
|
+
import * as path4 from "node:path";
|
|
34181
34358
|
var UNSUPPORTED_ASK_HOST = "AFT requires OpenCode 1.15.5 or newer for permission asks; please upgrade OpenCode";
|
|
34182
34359
|
async function runAsk(maybe) {
|
|
34183
34360
|
await maybe;
|
|
34184
34361
|
}
|
|
34185
34362
|
function resolveAbsolutePath(context, target) {
|
|
34186
|
-
return
|
|
34363
|
+
return path4.isAbsolute(target) ? target : path4.resolve(projectRootFor(context), target);
|
|
34187
34364
|
}
|
|
34188
34365
|
function resolveRelativePattern(context, target) {
|
|
34189
|
-
return
|
|
34366
|
+
return path4.relative(projectRootFor(context), resolveAbsolutePath(context, target)) || ".";
|
|
34190
34367
|
}
|
|
34191
34368
|
function resolveRelativePatternFromAbsolute(context, absolutePath) {
|
|
34192
|
-
return
|
|
34369
|
+
return path4.relative(projectRootFor(context), absolutePath) || ".";
|
|
34193
34370
|
}
|
|
34194
34371
|
function resolveRelativePatterns(context, targets) {
|
|
34195
34372
|
const seen = new Set;
|
|
@@ -34229,8 +34406,8 @@ async function askEditPermission(context, patterns, metadata = {}) {
|
|
|
34229
34406
|
function containsPath(parent, child) {
|
|
34230
34407
|
if (!parent)
|
|
34231
34408
|
return false;
|
|
34232
|
-
const rel =
|
|
34233
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
34409
|
+
const rel = path4.relative(parent, child);
|
|
34410
|
+
return rel === "" || !rel.startsWith("..") && !path4.isAbsolute(rel);
|
|
34234
34411
|
}
|
|
34235
34412
|
function windowsPath(p) {
|
|
34236
34413
|
if (process.platform !== "win32")
|
|
@@ -34240,7 +34417,7 @@ function windowsPath(p) {
|
|
|
34240
34417
|
function normalizePath(p) {
|
|
34241
34418
|
if (process.platform !== "win32")
|
|
34242
34419
|
return p;
|
|
34243
|
-
const resolved =
|
|
34420
|
+
const resolved = path4.resolve(windowsPath(p));
|
|
34244
34421
|
try {
|
|
34245
34422
|
return fs4.realpathSync.native(resolved);
|
|
34246
34423
|
} catch {
|
|
@@ -34256,7 +34433,7 @@ function normalizePathPattern(p) {
|
|
|
34256
34433
|
if (!match)
|
|
34257
34434
|
return normalizePath(p);
|
|
34258
34435
|
const dir = /^[A-Za-z]:$/.test(match[1]) ? `${match[1]}\\` : match[1];
|
|
34259
|
-
return
|
|
34436
|
+
return path4.join(normalizePath(dir), match[2]);
|
|
34260
34437
|
}
|
|
34261
34438
|
async function assertExternalDirectoryPermission(context, target, options) {
|
|
34262
34439
|
if (!target)
|
|
@@ -34275,8 +34452,8 @@ async function assertExternalDirectoryPermission(context, target, options) {
|
|
|
34275
34452
|
return;
|
|
34276
34453
|
}
|
|
34277
34454
|
const kind = options?.kind ?? "file";
|
|
34278
|
-
const parentDir = kind === "directory" ? absoluteTarget :
|
|
34279
|
-
const rawGlob = process.platform === "win32" ? normalizePathPattern(
|
|
34455
|
+
const parentDir = kind === "directory" ? absoluteTarget : path4.dirname(absoluteTarget);
|
|
34456
|
+
const rawGlob = process.platform === "win32" ? normalizePathPattern(path4.join(parentDir, "*")) : path4.join(parentDir, "*").replaceAll("\\", "/");
|
|
34280
34457
|
try {
|
|
34281
34458
|
await runAsk(context.ask({
|
|
34282
34459
|
permission: "external_directory",
|
|
@@ -34350,6 +34527,20 @@ function extractHint(response) {
|
|
|
34350
34527
|
const hint = response.hint;
|
|
34351
34528
|
return typeof hint === "string" && hint.length > 0 ? hint : null;
|
|
34352
34529
|
}
|
|
34530
|
+
function appendSkippedFiles(output, skippedFiles) {
|
|
34531
|
+
if (!skippedFiles || skippedFiles.length === 0)
|
|
34532
|
+
return output;
|
|
34533
|
+
const lines = skippedFiles.map((skipped) => {
|
|
34534
|
+
const file2 = skipped.file ?? "unknown";
|
|
34535
|
+
const reason = skipped.reason ?? "unknown reason";
|
|
34536
|
+
return ` ${file2}: ${reason}`;
|
|
34537
|
+
});
|
|
34538
|
+
return `${output}
|
|
34539
|
+
|
|
34540
|
+
Incomplete: skipped ${skippedFiles.length} file(s)
|
|
34541
|
+
${lines.join(`
|
|
34542
|
+
`)}`;
|
|
34543
|
+
}
|
|
34353
34544
|
async function resolveAstPaths(ctx, context, paths) {
|
|
34354
34545
|
if (isEmptyParam(paths) || !Array.isArray(paths))
|
|
34355
34546
|
return;
|
|
@@ -34374,17 +34565,18 @@ var SUPPORTED_LANGS = [
|
|
|
34374
34565
|
"python",
|
|
34375
34566
|
"rust",
|
|
34376
34567
|
"go",
|
|
34377
|
-
"pascal"
|
|
34568
|
+
"pascal",
|
|
34569
|
+
"r"
|
|
34378
34570
|
];
|
|
34379
34571
|
function astTools(ctx) {
|
|
34380
34572
|
const searchTool = {
|
|
34381
|
-
description: `Search code patterns across filesystem using AST-aware matching. Supports
|
|
34573
|
+
description: `Search code patterns across filesystem using AST-aware matching. Supports 8 languages.
|
|
34382
34574
|
|
|
34383
34575
|
` + `Use meta-variables: $VAR matches a single AST node, $$$ matches multiple nodes (variadic).
|
|
34384
34576
|
` + `IMPORTANT: Patterns must be complete AST nodes (valid code fragments).
|
|
34385
34577
|
` + `For functions, include params and body: 'export async function $NAME($$$) { $$$ }' not just 'export async function $NAME'.
|
|
34386
34578
|
|
|
34387
|
-
` + "Examples: pattern='console.log($MSG)' lang='typescript', pattern='async function $NAME($$$) { $$$ }' lang='javascript', pattern='def $FUNC($$$): $$$' lang='python', pattern='Writeln($MSG);' lang='pascal'",
|
|
34579
|
+
` + "Examples: pattern='console.log($MSG)' lang='typescript', pattern='async function $NAME($$$) { $$$ }' lang='javascript', pattern='def $FUNC($$$): $$$' lang='python', pattern='Writeln($MSG);' lang='pascal', pattern='$X <- $Y' lang='r'",
|
|
34388
34580
|
args: {
|
|
34389
34581
|
pattern: z3.string().describe("AST pattern with meta-variables ($VAR, $$$). Must be complete AST node."),
|
|
34390
34582
|
lang: z3.enum(SUPPORTED_LANGS).describe("Target language"),
|
|
@@ -34465,6 +34657,9 @@ ${hint}`;
|
|
|
34465
34657
|
}
|
|
34466
34658
|
}
|
|
34467
34659
|
}
|
|
34660
|
+
if (data.complete === false || (data.skipped_files?.length ?? 0) > 0) {
|
|
34661
|
+
output = appendSkippedFiles(output, data.skipped_files);
|
|
34662
|
+
}
|
|
34468
34663
|
showOutputToUser(context, output);
|
|
34469
34664
|
return output;
|
|
34470
34665
|
}
|
|
@@ -34808,7 +35003,7 @@ function createBashTool(ctx, aftSearchRegisteredOverride) {
|
|
|
34808
35003
|
throw new Error(status.message ?? "bash_status failed");
|
|
34809
35004
|
}
|
|
34810
35005
|
if (isTerminalStatus(status.status)) {
|
|
34811
|
-
const rendered2 = maybeAppendGrepSearchHint(appendPipeStripNote(formatForegroundResult(status), pipeStrip.note), command, aftSearchRegistered);
|
|
35006
|
+
const rendered2 = maybeAppendGrepSearchHint(appendPipeStripNote(formatForegroundResult(status), pipeStrip.note), command, aftSearchRegistered, projectRootFor(context));
|
|
34812
35007
|
const metadataPayload2 = foregroundMetadata(description, status, rendered2);
|
|
34813
35008
|
metadata?.(metadataPayload2);
|
|
34814
35009
|
return { output: rendered2, title: uiTitle, metadata: metadataPayload2 };
|
|
@@ -34872,11 +35067,6 @@ function createBashTool(ctx, aftSearchRegisteredOverride) {
|
|
|
34872
35067
|
}
|
|
34873
35068
|
};
|
|
34874
35069
|
}
|
|
34875
|
-
function appendPipeStripNote(output, note) {
|
|
34876
|
-
return note ? `${output}
|
|
34877
|
-
|
|
34878
|
-
${note}` : output;
|
|
34879
|
-
}
|
|
34880
35070
|
function createBashStatusTool(ctx) {
|
|
34881
35071
|
return {
|
|
34882
35072
|
description: "Read-only snapshot of a background or PTY bash task's current state and output. Returns immediately. Never waits. Use bash_watch to block on or register for pattern matches and exit events.",
|
|
@@ -34981,9 +35171,6 @@ function ptyCacheKey(runtime, taskId) {
|
|
|
34981
35171
|
function preview(output) {
|
|
34982
35172
|
return output.length <= METADATA_PREVIEW_LIMIT ? output : output.slice(-METADATA_PREVIEW_LIMIT);
|
|
34983
35173
|
}
|
|
34984
|
-
function isTerminalStatus(status) {
|
|
34985
|
-
return status === "completed" || status === "failed" || status === "killed" || status === "timed_out";
|
|
34986
|
-
}
|
|
34987
35174
|
function subagentGuidance(taskId) {
|
|
34988
35175
|
return `
|
|
34989
35176
|
|
|
@@ -34999,30 +35186,6 @@ function formatPromotionMessage(taskId, timeout, waitWindowMs) {
|
|
|
34999
35186
|
const waited = timeout !== undefined ? Math.min(timeout, waitWindowMs) : waitWindowMs;
|
|
35000
35187
|
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({ taskId: "${taskId}" }) to inspect output or bash_kill({ taskId: "${taskId}" }) to terminate.`;
|
|
35001
35188
|
}
|
|
35002
|
-
function formatSeconds(ms) {
|
|
35003
|
-
return `${Number((ms / 1000).toFixed(1))}s`;
|
|
35004
|
-
}
|
|
35005
|
-
function formatForegroundResult(data) {
|
|
35006
|
-
const output = data.output_preview ?? "";
|
|
35007
|
-
const outputPath = data.output_path;
|
|
35008
|
-
const truncated = data.output_truncated === true;
|
|
35009
|
-
const status = data.status;
|
|
35010
|
-
const exit = data.exit_code;
|
|
35011
|
-
let rendered = output;
|
|
35012
|
-
if (truncated && outputPath) {
|
|
35013
|
-
rendered += `
|
|
35014
|
-
[output truncated; full output at ${outputPath}]`;
|
|
35015
|
-
}
|
|
35016
|
-
if (status === "timed_out") {
|
|
35017
|
-
rendered += `
|
|
35018
|
-
[command timed out]`;
|
|
35019
|
-
}
|
|
35020
|
-
if (typeof exit === "number" && exit !== 0) {
|
|
35021
|
-
rendered += `
|
|
35022
|
-
[exit code: ${exit}]`;
|
|
35023
|
-
}
|
|
35024
|
-
return rendered;
|
|
35025
|
-
}
|
|
35026
35189
|
function foregroundMetadata(description, data, rendered) {
|
|
35027
35190
|
const outputPath = data.output_path;
|
|
35028
35191
|
return {
|
|
@@ -35033,9 +35196,6 @@ function foregroundMetadata(description, data, rendered) {
|
|
|
35033
35196
|
...outputPath ? { outputPath } : {}
|
|
35034
35197
|
};
|
|
35035
35198
|
}
|
|
35036
|
-
function sleep(ms) {
|
|
35037
|
-
return new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
35038
|
-
}
|
|
35039
35199
|
function getCallID(ctx) {
|
|
35040
35200
|
const c = ctx;
|
|
35041
35201
|
return c.callID ?? c.callId ?? c.call_id;
|
|
@@ -35058,7 +35218,7 @@ function conflictTools(ctx) {
|
|
|
35058
35218
|
execute: async (args, context) => {
|
|
35059
35219
|
const params = {};
|
|
35060
35220
|
if (!isEmptyParam(args?.path)) {
|
|
35061
|
-
const expanded =
|
|
35221
|
+
const expanded = expandTilde2(String(args.path));
|
|
35062
35222
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
35063
35223
|
const resolved = resolvePathFromProjectRoot(projectRoot, expanded);
|
|
35064
35224
|
const denied = await assertExternalDirectoryPermission(context, resolved, {
|
|
@@ -35080,7 +35240,7 @@ function conflictTools(ctx) {
|
|
|
35080
35240
|
|
|
35081
35241
|
// src/tools/hoisted.ts
|
|
35082
35242
|
import * as fs6 from "node:fs";
|
|
35083
|
-
import * as
|
|
35243
|
+
import * as path5 from "node:path";
|
|
35084
35244
|
import { tool as tool8 } from "@opencode-ai/plugin";
|
|
35085
35245
|
|
|
35086
35246
|
// src/patch-parser.ts
|
|
@@ -35520,13 +35680,16 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
|
|
|
35520
35680
|
let scanText = "";
|
|
35521
35681
|
let scanBaseOffset = 0;
|
|
35522
35682
|
const bridgeOptions = {};
|
|
35683
|
+
if (waitFor?.kind === "regex") {
|
|
35684
|
+
await validateWaitRegex(ctx, runtime, waitFor);
|
|
35685
|
+
}
|
|
35523
35686
|
clearSyncWatchAbort(runtime.sessionID);
|
|
35524
35687
|
markTaskWaiting(runtime.sessionID, taskId);
|
|
35525
35688
|
let sawTerminal = false;
|
|
35526
35689
|
try {
|
|
35527
35690
|
while (true) {
|
|
35528
35691
|
const data = await bashStatusSnapshot2(ctx, runtime, taskId, outputMode, bridgeOptions);
|
|
35529
|
-
const terminal =
|
|
35692
|
+
const terminal = isTerminalStatus(data.status);
|
|
35530
35693
|
if (waitFor) {
|
|
35531
35694
|
const scan = await readNewTaskOutput(runtime, taskId, data, spillCursor);
|
|
35532
35695
|
if (scan) {
|
|
@@ -35534,7 +35697,12 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
|
|
|
35534
35697
|
if (scanText.length === 0)
|
|
35535
35698
|
scanBaseOffset = scan.baseOffset;
|
|
35536
35699
|
scanText += scan.text;
|
|
35537
|
-
|
|
35700
|
+
if (waitFor.kind === "regex") {
|
|
35701
|
+
const trimmed = trimWaitScanBuffer(scanText, scanBaseOffset, waitFor);
|
|
35702
|
+
scanText = trimmed.text;
|
|
35703
|
+
scanBaseOffset = trimmed.baseOffset;
|
|
35704
|
+
}
|
|
35705
|
+
const match = await findWaitMatch(ctx, runtime, scanText, waitFor);
|
|
35538
35706
|
if (match) {
|
|
35539
35707
|
if (terminal) {
|
|
35540
35708
|
sawTerminal = true;
|
|
@@ -35545,12 +35713,14 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
|
|
|
35545
35713
|
reason: "matched",
|
|
35546
35714
|
elapsed_ms: Date.now() - startedAt,
|
|
35547
35715
|
match: match.text,
|
|
35548
|
-
match_offset: scanBaseOffset +
|
|
35716
|
+
match_offset: scanBaseOffset + match.byteOffset
|
|
35549
35717
|
});
|
|
35550
35718
|
}
|
|
35551
|
-
|
|
35552
|
-
|
|
35553
|
-
|
|
35719
|
+
if (waitFor.kind === "substring") {
|
|
35720
|
+
const trimmed = trimWaitScanBuffer(scanText, scanBaseOffset, waitFor);
|
|
35721
|
+
scanText = trimmed.text;
|
|
35722
|
+
scanBaseOffset = trimmed.baseOffset;
|
|
35723
|
+
}
|
|
35554
35724
|
}
|
|
35555
35725
|
}
|
|
35556
35726
|
if (terminal) {
|
|
@@ -35565,7 +35735,7 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
|
|
|
35565
35735
|
if (Date.now() >= deadline) {
|
|
35566
35736
|
return withWaited(data, { reason: "timeout", elapsed_ms: Date.now() - startedAt });
|
|
35567
35737
|
}
|
|
35568
|
-
await
|
|
35738
|
+
await sleep(Math.min(BASH_WAIT_POLL_INTERVAL_MS, Math.max(0, deadline - Date.now())));
|
|
35569
35739
|
}
|
|
35570
35740
|
} finally {
|
|
35571
35741
|
if (!sawTerminal)
|
|
@@ -35631,20 +35801,41 @@ function parseWaitPattern(value) {
|
|
|
35631
35801
|
if (typeof value === "string")
|
|
35632
35802
|
return { kind: "substring", value };
|
|
35633
35803
|
if (isRegexWaitObject(value))
|
|
35634
|
-
return { kind: "regex",
|
|
35804
|
+
return { kind: "regex", source: value.regex };
|
|
35635
35805
|
return;
|
|
35636
35806
|
}
|
|
35637
35807
|
function isRegexWaitObject(value) {
|
|
35638
35808
|
return typeof value === "object" && value !== null && "regex" in value && typeof value.regex === "string";
|
|
35639
35809
|
}
|
|
35640
|
-
function
|
|
35810
|
+
async function validateWaitRegex(ctx, runtime, pattern) {
|
|
35811
|
+
await matchRegexWithBridge(ctx, runtime, pattern.source, "");
|
|
35812
|
+
}
|
|
35813
|
+
async function findWaitMatch(ctx, runtime, text, pattern) {
|
|
35641
35814
|
if (pattern.kind === "substring") {
|
|
35642
35815
|
const index = text.indexOf(pattern.value);
|
|
35643
|
-
return index >= 0 ? { text: pattern.value, index } : undefined;
|
|
35816
|
+
return index >= 0 ? { text: pattern.value, byteOffset: Buffer.byteLength(text.slice(0, index), "utf8") } : undefined;
|
|
35817
|
+
}
|
|
35818
|
+
return await matchRegexWithBridge(ctx, runtime, pattern.source, text);
|
|
35819
|
+
}
|
|
35820
|
+
async function matchRegexWithBridge(ctx, runtime, pattern, text) {
|
|
35821
|
+
const result = await callBashBridge(ctx, runtime, "bash_regex_match", { pattern, text });
|
|
35822
|
+
if (result.success === false) {
|
|
35823
|
+
const code = String(result.code ?? "invalid_request");
|
|
35824
|
+
const message = String(result.message ?? "bash_regex_match failed");
|
|
35825
|
+
if (code === "invalid_regex")
|
|
35826
|
+
throw new Error(`invalid_request: invalid_regex: ${message}`);
|
|
35827
|
+
throw new Error(`${code}: ${message}`);
|
|
35644
35828
|
}
|
|
35645
|
-
|
|
35646
|
-
|
|
35647
|
-
return
|
|
35829
|
+
if (result.matched !== true)
|
|
35830
|
+
return;
|
|
35831
|
+
return {
|
|
35832
|
+
text: typeof result.match_text === "string" ? result.match_text : "",
|
|
35833
|
+
byteOffset: coerceMatchOffset(result.match_offset)
|
|
35834
|
+
};
|
|
35835
|
+
}
|
|
35836
|
+
function coerceMatchOffset(value) {
|
|
35837
|
+
const offset = typeof value === "number" ? value : Number(value ?? 0);
|
|
35838
|
+
return Number.isFinite(offset) && offset >= 0 ? offset : 0;
|
|
35648
35839
|
}
|
|
35649
35840
|
function trimWaitScanBuffer(text, baseOffset, pattern) {
|
|
35650
35841
|
const keepFrom = pattern.kind === "substring" ? substringKeepStart(text, pattern.value) : regexKeepStart(text, REGEX_WAIT_SCAN_WINDOW_BYTES);
|
|
@@ -35677,18 +35868,12 @@ function regexKeepStart(text, maxBytes) {
|
|
|
35677
35868
|
function withWaited(data, waited) {
|
|
35678
35869
|
return { ...data, waited };
|
|
35679
35870
|
}
|
|
35680
|
-
function isTerminalStatus2(status) {
|
|
35681
|
-
return status === "completed" || status === "failed" || status === "killed" || status === "timed_out";
|
|
35682
|
-
}
|
|
35683
35871
|
function ptyCacheKey2(runtime, taskId) {
|
|
35684
35872
|
return `${projectRootFor(runtime)}::${runtime.sessionID ?? "__default__"}::${taskId}`;
|
|
35685
35873
|
}
|
|
35686
35874
|
function watchPtyCacheKey(runtime, taskId) {
|
|
35687
35875
|
return `${ptyCacheKey2(runtime, taskId)}::watch`;
|
|
35688
35876
|
}
|
|
35689
|
-
function sleep2(ms) {
|
|
35690
|
-
return new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
35691
|
-
}
|
|
35692
35877
|
|
|
35693
35878
|
// src/tools/bash_write.ts
|
|
35694
35879
|
import { tool as tool7 } from "@opencode-ai/plugin";
|
|
@@ -35723,21 +35908,10 @@ function createBashWriteTool(ctx) {
|
|
|
35723
35908
|
|
|
35724
35909
|
// src/tools/hoisted.ts
|
|
35725
35910
|
function relativeToWorktree(fp, worktree) {
|
|
35726
|
-
return
|
|
35911
|
+
return path5.relative(worktree, fp);
|
|
35727
35912
|
}
|
|
35728
|
-
function
|
|
35729
|
-
|
|
35730
|
-
return "";
|
|
35731
|
-
if (!data.truncated)
|
|
35732
|
-
return "";
|
|
35733
|
-
const startLine = data.start_line;
|
|
35734
|
-
const endLine = data.end_line;
|
|
35735
|
-
const totalLines = data.total_lines;
|
|
35736
|
-
if (startLine === undefined || endLine === undefined || totalLines === undefined) {
|
|
35737
|
-
return "";
|
|
35738
|
-
}
|
|
35739
|
-
return `
|
|
35740
|
-
(Showing lines ${startLine}-${endLine} of ${totalLines}. Use startLine/endLine to read other sections.)`;
|
|
35913
|
+
function formatReadFooter2(agentSpecifiedRange, data) {
|
|
35914
|
+
return formatReadFooter(agentSpecifiedRange, data, { rangeHint: "startLine/endLine" });
|
|
35741
35915
|
}
|
|
35742
35916
|
function buildUnifiedDiff(fp, before, after) {
|
|
35743
35917
|
const beforeLines = before.split(`
|
|
@@ -36064,7 +36238,7 @@ function createReadTool(ctx) {
|
|
|
36064
36238
|
return permissionDeniedResponse(error50.message);
|
|
36065
36239
|
return permissionDeniedResponse("Permission denied.");
|
|
36066
36240
|
}
|
|
36067
|
-
const ext =
|
|
36241
|
+
const ext = path5.extname(filePath).toLowerCase();
|
|
36068
36242
|
const mimeMap = {
|
|
36069
36243
|
".png": "image/png",
|
|
36070
36244
|
".jpg": "image/jpeg",
|
|
@@ -36093,7 +36267,7 @@ function createReadTool(ctx) {
|
|
|
36093
36267
|
const msg = `${label} read successfully`;
|
|
36094
36268
|
return {
|
|
36095
36269
|
output: `${msg} (${ext.slice(1).toUpperCase()}, ${sizeStr}). File: ${filePath}`,
|
|
36096
|
-
title:
|
|
36270
|
+
title: path5.relative(projectRoot, filePath),
|
|
36097
36271
|
metadata: {
|
|
36098
36272
|
preview: msg,
|
|
36099
36273
|
filepath: filePath,
|
|
@@ -36135,7 +36309,7 @@ function createReadTool(ctx) {
|
|
|
36135
36309
|
}
|
|
36136
36310
|
let output = data.content;
|
|
36137
36311
|
const agentSpecifiedRange = args.startLine !== undefined || args.endLine !== undefined || args.offset !== undefined || args.limit !== undefined;
|
|
36138
|
-
const footer =
|
|
36312
|
+
const footer = formatReadFooter2(agentSpecifiedRange, data);
|
|
36139
36313
|
if (footer)
|
|
36140
36314
|
output += footer;
|
|
36141
36315
|
return { output, title: dp, metadata: { title: dp } };
|
|
@@ -36157,7 +36331,7 @@ function createWriteTool(ctx, editToolName = "edit") {
|
|
|
36157
36331
|
const content = args.content;
|
|
36158
36332
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
36159
36333
|
const filePath = resolvePathFromProjectRoot(projectRoot, file2);
|
|
36160
|
-
const relPath =
|
|
36334
|
+
const relPath = path5.relative(projectRoot, filePath);
|
|
36161
36335
|
{
|
|
36162
36336
|
const denial2 = await assertExternalDirectoryPermission(context, filePath);
|
|
36163
36337
|
if (denial2)
|
|
@@ -36308,7 +36482,7 @@ function createEditTool(ctx, writeToolName = "write") {
|
|
|
36308
36482
|
throw new Error("'filePath' parameter is required");
|
|
36309
36483
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
36310
36484
|
const filePath = resolvePathFromProjectRoot(projectRoot, file2);
|
|
36311
|
-
const relPath =
|
|
36485
|
+
const relPath = path5.relative(projectRoot, filePath);
|
|
36312
36486
|
{
|
|
36313
36487
|
const denial2 = await assertExternalDirectoryPermission(context, filePath);
|
|
36314
36488
|
if (denial2)
|
|
@@ -36511,22 +36685,34 @@ function createApplyPatchTool(ctx) {
|
|
|
36511
36685
|
}
|
|
36512
36686
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
36513
36687
|
const affectedAbs = new Set;
|
|
36688
|
+
const initiallyExistsAbs = new Map;
|
|
36689
|
+
const rememberAffectedPath = (abs) => {
|
|
36690
|
+
affectedAbs.add(abs);
|
|
36691
|
+
if (!initiallyExistsAbs.has(abs)) {
|
|
36692
|
+
initiallyExistsAbs.set(abs, fs6.existsSync(abs));
|
|
36693
|
+
}
|
|
36694
|
+
};
|
|
36695
|
+
for (const h of hunks) {
|
|
36696
|
+
const srcAbs = resolvePathFromProjectRoot(projectRoot, h.path);
|
|
36697
|
+
rememberAffectedPath(srcAbs);
|
|
36698
|
+
if (h.type === "update" && h.move_path) {
|
|
36699
|
+
rememberAffectedPath(resolvePathFromProjectRoot(projectRoot, h.move_path));
|
|
36700
|
+
}
|
|
36701
|
+
}
|
|
36514
36702
|
const newlyCreatedAbs = new Set;
|
|
36515
36703
|
for (const h of hunks) {
|
|
36516
36704
|
const srcAbs = resolvePathFromProjectRoot(projectRoot, h.path);
|
|
36517
|
-
|
|
36518
|
-
if (h.type === "add") {
|
|
36705
|
+
if (h.type === "add" && initiallyExistsAbs.get(srcAbs) === false) {
|
|
36519
36706
|
newlyCreatedAbs.add(srcAbs);
|
|
36520
36707
|
}
|
|
36521
36708
|
if (h.type === "update" && h.move_path) {
|
|
36522
36709
|
const dstAbs = resolvePathFromProjectRoot(projectRoot, h.move_path);
|
|
36523
|
-
|
|
36524
|
-
if (!fs6.existsSync(dstAbs)) {
|
|
36710
|
+
if (initiallyExistsAbs.get(dstAbs) === false) {
|
|
36525
36711
|
newlyCreatedAbs.add(dstAbs);
|
|
36526
36712
|
}
|
|
36527
36713
|
}
|
|
36528
36714
|
}
|
|
36529
|
-
const relPaths = Array.from(affectedAbs).map((abs) =>
|
|
36715
|
+
const relPaths = Array.from(affectedAbs).map((abs) => path5.relative(projectRoot, abs));
|
|
36530
36716
|
const multiFileWritePaths = Array.from(affectedAbs);
|
|
36531
36717
|
{
|
|
36532
36718
|
const asked = new Set;
|
|
@@ -36560,15 +36746,15 @@ function createApplyPatchTool(ctx) {
|
|
|
36560
36746
|
}
|
|
36561
36747
|
const results = [];
|
|
36562
36748
|
const failures = [];
|
|
36563
|
-
const
|
|
36564
|
-
for (const hunk of hunks) {
|
|
36749
|
+
const appliedHunkResults = [];
|
|
36750
|
+
for (const [hunkIndex, hunk] of hunks.entries()) {
|
|
36565
36751
|
const filePath = resolvePathFromProjectRoot(projectRoot, hunk.path);
|
|
36566
36752
|
switch (hunk.type) {
|
|
36567
36753
|
case "add": {
|
|
36568
36754
|
if (fs6.existsSync(filePath)) {
|
|
36569
36755
|
const msg = `Failed to create ${hunk.path}: file already exists. Use *** Update File: to modify, or *** Delete File: first if you want to replace it entirely.`;
|
|
36570
36756
|
results.push(msg);
|
|
36571
|
-
failures.push(hunk.path);
|
|
36757
|
+
failures.push({ index: hunkIndex, path: hunk.path });
|
|
36572
36758
|
break;
|
|
36573
36759
|
}
|
|
36574
36760
|
try {
|
|
@@ -36590,10 +36776,13 @@ function createApplyPatchTool(ctx) {
|
|
|
36590
36776
|
throw new Error("produced invalid syntax (rolled back)");
|
|
36591
36777
|
}
|
|
36592
36778
|
const wrDiff = writeResult.diff;
|
|
36593
|
-
|
|
36779
|
+
appliedHunkResults.push({
|
|
36780
|
+
index: hunkIndex,
|
|
36781
|
+
hunk,
|
|
36594
36782
|
filePath,
|
|
36783
|
+
displayPath: filePath,
|
|
36595
36784
|
before: "",
|
|
36596
|
-
after:
|
|
36785
|
+
after: content,
|
|
36597
36786
|
additions: wrDiff?.additions ?? lineCount(content),
|
|
36598
36787
|
deletions: wrDiff?.deletions ?? 0
|
|
36599
36788
|
});
|
|
@@ -36601,7 +36790,7 @@ function createApplyPatchTool(ctx) {
|
|
|
36601
36790
|
} catch (e) {
|
|
36602
36791
|
const msg = `Failed to create ${hunk.path}: ${e instanceof Error ? e.message : e}`;
|
|
36603
36792
|
results.push(msg);
|
|
36604
|
-
failures.push(hunk.path);
|
|
36793
|
+
failures.push({ index: hunkIndex, path: hunk.path });
|
|
36605
36794
|
const filePath2 = resolvePathFromProjectRoot(projectRoot, hunk.path);
|
|
36606
36795
|
if (fs6.existsSync(filePath2)) {
|
|
36607
36796
|
try {
|
|
@@ -36620,8 +36809,11 @@ function createApplyPatchTool(ctx) {
|
|
|
36620
36809
|
if (deleteResult.success === false) {
|
|
36621
36810
|
throw new Error(deleteResult.message ?? "delete failed");
|
|
36622
36811
|
}
|
|
36623
|
-
|
|
36812
|
+
appliedHunkResults.push({
|
|
36813
|
+
index: hunkIndex,
|
|
36814
|
+
hunk,
|
|
36624
36815
|
filePath,
|
|
36816
|
+
displayPath: filePath,
|
|
36625
36817
|
before,
|
|
36626
36818
|
after: "",
|
|
36627
36819
|
additions: 0,
|
|
@@ -36630,7 +36822,7 @@ function createApplyPatchTool(ctx) {
|
|
|
36630
36822
|
results.push(`Deleted ${hunk.path}`);
|
|
36631
36823
|
} catch (e) {
|
|
36632
36824
|
results.push(`Failed to delete ${hunk.path}: ${e instanceof Error ? e.message : e}`);
|
|
36633
|
-
failures.push(hunk.path);
|
|
36825
|
+
failures.push({ index: hunkIndex, path: hunk.path });
|
|
36634
36826
|
}
|
|
36635
36827
|
break;
|
|
36636
36828
|
}
|
|
@@ -36657,7 +36849,7 @@ function createApplyPatchTool(ctx) {
|
|
|
36657
36849
|
if (diags && diags.length > 0) {
|
|
36658
36850
|
const errors3 = diags.filter((d) => d.severity === "error");
|
|
36659
36851
|
if (errors3.length > 0) {
|
|
36660
|
-
const relPath =
|
|
36852
|
+
const relPath = path5.relative(projectRoot, targetPath);
|
|
36661
36853
|
const diagLines = errors3.map((d) => ` Line ${d.line}: ${d.message}`).join(`
|
|
36662
36854
|
`);
|
|
36663
36855
|
results.push(`
|
|
@@ -36671,13 +36863,17 @@ ${diagLines}`);
|
|
|
36671
36863
|
additions: wrDiff.additions,
|
|
36672
36864
|
deletions: wrDiff.deletions
|
|
36673
36865
|
};
|
|
36674
|
-
|
|
36866
|
+
const appliedHunkResult = {
|
|
36867
|
+
index: hunkIndex,
|
|
36868
|
+
hunk,
|
|
36675
36869
|
filePath,
|
|
36870
|
+
displayPath: targetPath,
|
|
36871
|
+
...hunk.move_path ? { movePath: targetPath } : {},
|
|
36676
36872
|
before: original,
|
|
36677
36873
|
after: newContent,
|
|
36678
36874
|
additions,
|
|
36679
36875
|
deletions
|
|
36680
|
-
}
|
|
36876
|
+
};
|
|
36681
36877
|
if (hunk.move_path) {
|
|
36682
36878
|
try {
|
|
36683
36879
|
const deleteResult = await callBridge(ctx, context, "delete_file", {
|
|
@@ -36710,13 +36906,15 @@ ${diagLines}`);
|
|
|
36710
36906
|
}
|
|
36711
36907
|
throw new Error(`source delete failed after writing move destination; restored pre-patch checkpoint ${checkpointName}: ${formatError2(deleteError)}`);
|
|
36712
36908
|
}
|
|
36909
|
+
appliedHunkResults.push(appliedHunkResult);
|
|
36713
36910
|
results.push(`Updated and moved ${hunk.path} → ${hunk.move_path}`);
|
|
36714
36911
|
} else {
|
|
36912
|
+
appliedHunkResults.push(appliedHunkResult);
|
|
36715
36913
|
results.push(`Updated ${hunk.path}`);
|
|
36716
36914
|
}
|
|
36717
36915
|
} catch (e) {
|
|
36718
36916
|
results.push(`Failed to update ${hunk.path}: ${e instanceof Error ? e.message : e}`);
|
|
36719
|
-
failures.push(hunk.path);
|
|
36917
|
+
failures.push({ index: hunkIndex, path: hunk.path });
|
|
36720
36918
|
break;
|
|
36721
36919
|
}
|
|
36722
36920
|
break;
|
|
@@ -36725,7 +36923,8 @@ ${diagLines}`);
|
|
|
36725
36923
|
}
|
|
36726
36924
|
if (failures.length > 0) {
|
|
36727
36925
|
const partial2 = failures.length < hunks.length;
|
|
36728
|
-
const
|
|
36926
|
+
const failedList = failures.map((failure) => failure.path).join(", ");
|
|
36927
|
+
const summary = partial2 ? `Patch partially applied — ${hunks.length - failures.length} of ${hunks.length} hunk(s) succeeded. Failed: ${failedList}. Successful changes are kept; use \`aft_safety\` to revert if you want to abort.` : `Patch failed — none of the ${hunks.length} hunk(s) applied: ${failedList}.`;
|
|
36729
36928
|
results.push(summary);
|
|
36730
36929
|
if (!partial2) {
|
|
36731
36930
|
throw new Error(results.join(`
|
|
@@ -36733,28 +36932,56 @@ ${diagLines}`);
|
|
|
36733
36932
|
}
|
|
36734
36933
|
}
|
|
36735
36934
|
{
|
|
36736
|
-
const
|
|
36737
|
-
const
|
|
36738
|
-
|
|
36739
|
-
|
|
36740
|
-
|
|
36741
|
-
|
|
36742
|
-
|
|
36743
|
-
|
|
36744
|
-
|
|
36745
|
-
|
|
36746
|
-
|
|
36747
|
-
|
|
36748
|
-
|
|
36749
|
-
|
|
36935
|
+
const diffByReportKey = new Map;
|
|
36936
|
+
for (const applied of appliedHunkResults) {
|
|
36937
|
+
const reportKey = applied.movePath ? `${applied.filePath}\x00${applied.displayPath}` : applied.filePath;
|
|
36938
|
+
const existing = diffByReportKey.get(reportKey);
|
|
36939
|
+
if (!existing) {
|
|
36940
|
+
diffByReportKey.set(reportKey, {
|
|
36941
|
+
filePath: applied.filePath,
|
|
36942
|
+
displayPath: applied.displayPath,
|
|
36943
|
+
...applied.movePath ? { movePath: applied.movePath } : {},
|
|
36944
|
+
lastHunk: applied.hunk,
|
|
36945
|
+
before: applied.before,
|
|
36946
|
+
after: applied.after,
|
|
36947
|
+
additions: applied.additions,
|
|
36948
|
+
deletions: applied.deletions,
|
|
36949
|
+
hunkCount: 1
|
|
36950
|
+
});
|
|
36951
|
+
continue;
|
|
36952
|
+
}
|
|
36953
|
+
existing.displayPath = applied.displayPath;
|
|
36954
|
+
existing.movePath = applied.movePath ?? existing.movePath;
|
|
36955
|
+
existing.lastHunk = applied.hunk;
|
|
36956
|
+
existing.after = applied.after;
|
|
36957
|
+
existing.hunkCount += 1;
|
|
36958
|
+
const netCounts = countDiffLines(existing.before, existing.after);
|
|
36959
|
+
existing.additions = netCounts.additions;
|
|
36960
|
+
existing.deletions = netCounts.deletions;
|
|
36961
|
+
}
|
|
36962
|
+
const files = Array.from(diffByReportKey.values()).map((entry) => {
|
|
36963
|
+
const relPath = path5.relative(projectRoot, entry.displayPath);
|
|
36964
|
+
const patch = buildUnifiedDiff(entry.displayPath, entry.before, entry.after);
|
|
36965
|
+
let uiType;
|
|
36966
|
+
if (entry.movePath) {
|
|
36967
|
+
uiType = "move";
|
|
36968
|
+
} else if (entry.hunkCount === 1) {
|
|
36969
|
+
uiType = entry.lastHunk.type;
|
|
36970
|
+
} else if (entry.before.length === 0 && entry.after.length > 0) {
|
|
36971
|
+
uiType = "add";
|
|
36972
|
+
} else if (entry.before.length > 0 && entry.after.length === 0) {
|
|
36973
|
+
uiType = "delete";
|
|
36974
|
+
} else {
|
|
36975
|
+
uiType = "update";
|
|
36976
|
+
}
|
|
36750
36977
|
return {
|
|
36751
|
-
filePath,
|
|
36978
|
+
filePath: entry.filePath,
|
|
36752
36979
|
relativePath: relPath,
|
|
36753
36980
|
type: uiType,
|
|
36754
36981
|
patch,
|
|
36755
|
-
additions,
|
|
36756
|
-
deletions,
|
|
36757
|
-
...movePath ? { movePath } : {}
|
|
36982
|
+
additions: entry.additions,
|
|
36983
|
+
deletions: entry.deletions,
|
|
36984
|
+
...entry.movePath ? { movePath: entry.movePath } : {}
|
|
36758
36985
|
};
|
|
36759
36986
|
});
|
|
36760
36987
|
const fileList = files.map((f) => {
|
|
@@ -36762,7 +36989,7 @@ ${diagLines}`);
|
|
|
36762
36989
|
return `${prefix} ${f.relativePath}`;
|
|
36763
36990
|
}).join(`
|
|
36764
36991
|
`);
|
|
36765
|
-
const title = failures.length > 0 ? `Partially applied (${
|
|
36992
|
+
const title = failures.length > 0 ? `Partially applied (${hunks.length - failures.length} of ${hunks.length}). Updated:
|
|
36766
36993
|
${fileList}` : `Success. Updated the following files:
|
|
36767
36994
|
${fileList}`;
|
|
36768
36995
|
const diffText = files.map((f) => f.patch).filter(Boolean).join(`
|
|
@@ -36915,7 +37142,7 @@ function aftPrefixedTools(ctx) {
|
|
|
36915
37142
|
const file2 = normalizedArgs.filePath;
|
|
36916
37143
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
36917
37144
|
const filePath = resolvePathFromProjectRoot(projectRoot, file2);
|
|
36918
|
-
const relPath =
|
|
37145
|
+
const relPath = path5.relative(projectRoot, filePath);
|
|
36919
37146
|
{
|
|
36920
37147
|
const denial2 = await assertExternalDirectoryPermission(context, filePath);
|
|
36921
37148
|
if (denial2)
|
|
@@ -37312,15 +37539,15 @@ function buildZoomTitle(args) {
|
|
|
37312
37539
|
}
|
|
37313
37540
|
return `${args.targets.filePath}#${args.targets.symbol}`;
|
|
37314
37541
|
}
|
|
37315
|
-
const
|
|
37542
|
+
const path6 = args.filePath ?? args.url ?? "";
|
|
37316
37543
|
if (typeof args.symbols === "string")
|
|
37317
|
-
return
|
|
37544
|
+
return path6 ? `${path6}#${args.symbols}` : args.symbols;
|
|
37318
37545
|
if (Array.isArray(args.symbols) && args.symbols.length > 0) {
|
|
37319
37546
|
if (args.symbols.length === 1)
|
|
37320
|
-
return
|
|
37321
|
-
return
|
|
37547
|
+
return path6 ? `${path6}#${args.symbols[0]}` : args.symbols[0];
|
|
37548
|
+
return path6 ? `${path6} (${args.symbols.length} symbols)` : `${args.symbols.length} symbols`;
|
|
37322
37549
|
}
|
|
37323
|
-
return
|
|
37550
|
+
return path6 || "(no target)";
|
|
37324
37551
|
}
|
|
37325
37552
|
function readingTools(ctx) {
|
|
37326
37553
|
return {
|
|
@@ -37553,6 +37780,11 @@ function readingTools(ctx) {
|
|
|
37553
37780
|
}));
|
|
37554
37781
|
if (symbolsArray.length === 1) {
|
|
37555
37782
|
const response = results[0] ?? { success: false, message: "missing zoom response" };
|
|
37783
|
+
const rustBatch = unwrapRustZoomBatchEnvelope(response);
|
|
37784
|
+
if (rustBatch) {
|
|
37785
|
+
const batch = formatZoomBatchResult(targetLabel, rustBatch.names, rustBatch.responses);
|
|
37786
|
+
return withMeta(batch.text);
|
|
37787
|
+
}
|
|
37556
37788
|
if (response.success === false) {
|
|
37557
37789
|
throw new Error(response.message || "zoom failed");
|
|
37558
37790
|
}
|
|
@@ -37821,11 +38053,11 @@ function refactoringTools(ctx) {
|
|
|
37821
38053
|
}
|
|
37822
38054
|
|
|
37823
38055
|
// src/tools/safety.ts
|
|
37824
|
-
import * as
|
|
38056
|
+
import * as path6 from "node:path";
|
|
37825
38057
|
import { tool as tool14 } from "@opencode-ai/plugin";
|
|
37826
38058
|
var z14 = tool14.schema;
|
|
37827
38059
|
function responsePaths(response) {
|
|
37828
|
-
return Array.isArray(response.paths) ? response.paths.filter((
|
|
38060
|
+
return Array.isArray(response.paths) ? response.paths.filter((path7) => typeof path7 === "string" && path7.length > 0) : [];
|
|
37829
38061
|
}
|
|
37830
38062
|
function bridgeErrorMessage(response, fallback) {
|
|
37831
38063
|
return typeof response.message === "string" && response.message.length > 0 ? response.message : fallback;
|
|
@@ -37902,9 +38134,9 @@ function safetyTools(ctx) {
|
|
|
37902
38134
|
for (const rawFile of checkpointFiles) {
|
|
37903
38135
|
if (typeof rawFile !== "string")
|
|
37904
38136
|
continue;
|
|
37905
|
-
const file2 =
|
|
37906
|
-
const abs =
|
|
37907
|
-
const parent =
|
|
38137
|
+
const file2 = expandTilde2(rawFile);
|
|
38138
|
+
const abs = path6.isAbsolute(file2) ? file2 : path6.resolve(projectRoot, file2);
|
|
38139
|
+
const parent = path6.dirname(abs);
|
|
37908
38140
|
if (uniqueParents.has(parent))
|
|
37909
38141
|
continue;
|
|
37910
38142
|
uniqueParents.add(parent);
|
|
@@ -37942,8 +38174,8 @@ function safetyTools(ctx) {
|
|
|
37942
38174
|
const params = {};
|
|
37943
38175
|
if (args.name !== undefined)
|
|
37944
38176
|
params.name = args.name;
|
|
37945
|
-
const payloadFiles = coerceStringArray(args.files).map(
|
|
37946
|
-
const filePathArg = typeof args.filePath === "string" ?
|
|
38177
|
+
const payloadFiles = coerceStringArray(args.files).map(expandTilde2);
|
|
38178
|
+
const filePathArg = typeof args.filePath === "string" ? expandTilde2(args.filePath) : undefined;
|
|
37947
38179
|
if (op === "checkpoint") {
|
|
37948
38180
|
if (payloadFiles.length > 0) {
|
|
37949
38181
|
params.files = payloadFiles;
|
|
@@ -37968,7 +38200,7 @@ function safetyTools(ctx) {
|
|
|
37968
38200
|
|
|
37969
38201
|
// src/tools/search.ts
|
|
37970
38202
|
import * as fs7 from "node:fs";
|
|
37971
|
-
import * as
|
|
38203
|
+
import * as path7 from "node:path";
|
|
37972
38204
|
function arg2(schema) {
|
|
37973
38205
|
return schema;
|
|
37974
38206
|
}
|
|
@@ -38000,20 +38232,49 @@ function normalizeGlob(pattern) {
|
|
|
38000
38232
|
return pattern;
|
|
38001
38233
|
}
|
|
38002
38234
|
function absoluteSearchPath(projectRoot, target) {
|
|
38003
|
-
return resolvePathFromProjectRoot(projectRoot,
|
|
38235
|
+
return resolvePathFromProjectRoot(projectRoot, expandTilde2(target));
|
|
38004
38236
|
}
|
|
38005
38237
|
function searchPathExists(projectRoot, target) {
|
|
38006
38238
|
return fs7.existsSync(absoluteSearchPath(projectRoot, target));
|
|
38007
38239
|
}
|
|
38008
38240
|
function splitSearchPathArg(projectRoot, raw) {
|
|
38009
38241
|
if (searchPathExists(projectRoot, raw) || !/\s/.test(raw)) {
|
|
38010
|
-
return [raw];
|
|
38242
|
+
return { paths: [raw], missing: [] };
|
|
38011
38243
|
}
|
|
38012
38244
|
const fragments = raw.trim().split(/\s+/).filter(Boolean);
|
|
38013
|
-
if (fragments.length < 2
|
|
38014
|
-
return [raw];
|
|
38245
|
+
if (fragments.length < 2) {
|
|
38246
|
+
return { paths: [raw], missing: [] };
|
|
38247
|
+
}
|
|
38248
|
+
const existing = [];
|
|
38249
|
+
const missing = [];
|
|
38250
|
+
for (const fragment of fragments) {
|
|
38251
|
+
if (searchPathExists(projectRoot, fragment)) {
|
|
38252
|
+
existing.push(fragment);
|
|
38253
|
+
} else {
|
|
38254
|
+
missing.push(fragment);
|
|
38255
|
+
}
|
|
38015
38256
|
}
|
|
38016
|
-
|
|
38257
|
+
if (existing.length === 0) {
|
|
38258
|
+
return { paths: [raw], missing: [] };
|
|
38259
|
+
}
|
|
38260
|
+
return { paths: existing, missing };
|
|
38261
|
+
}
|
|
38262
|
+
function bridgeSearchPathArg(projectRoot, split) {
|
|
38263
|
+
return split.paths.map((target) => absoluteSearchPath(projectRoot, target)).join(" ");
|
|
38264
|
+
}
|
|
38265
|
+
function formatSkippedSearchPaths(missing) {
|
|
38266
|
+
if (missing.length === 0)
|
|
38267
|
+
return;
|
|
38268
|
+
const noun = missing.length === 1 ? "path" : "paths";
|
|
38269
|
+
return `Skipped ${missing.length} ${noun} not found: ${missing.join(", ")}`;
|
|
38270
|
+
}
|
|
38271
|
+
function appendSkippedSearchPaths(text, missing) {
|
|
38272
|
+
const note = formatSkippedSearchPaths(missing);
|
|
38273
|
+
if (!note)
|
|
38274
|
+
return text;
|
|
38275
|
+
return text.length > 0 ? `${text}
|
|
38276
|
+
|
|
38277
|
+
${note}` : note;
|
|
38017
38278
|
}
|
|
38018
38279
|
function searchPathKind(projectRoot, target, defaultKind) {
|
|
38019
38280
|
try {
|
|
@@ -38026,8 +38287,8 @@ function searchPathKind(projectRoot, target, defaultKind) {
|
|
|
38026
38287
|
return defaultKind;
|
|
38027
38288
|
}
|
|
38028
38289
|
}
|
|
38029
|
-
function searchPathTargets(projectRoot,
|
|
38030
|
-
return
|
|
38290
|
+
function searchPathTargets(projectRoot, split, defaultKind) {
|
|
38291
|
+
return split.paths.map((target) => {
|
|
38031
38292
|
const absoluteTarget = absoluteSearchPath(projectRoot, target);
|
|
38032
38293
|
return {
|
|
38033
38294
|
target: absoluteTarget,
|
|
@@ -38077,16 +38338,17 @@ function searchTools(ctx) {
|
|
|
38077
38338
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
38078
38339
|
const pattern = String(args.pattern);
|
|
38079
38340
|
const includeArg = args.include ? String(args.include) : undefined;
|
|
38080
|
-
const pathArg = args.path ?
|
|
38081
|
-
const
|
|
38341
|
+
const pathArg = args.path ? String(args.path) : undefined;
|
|
38342
|
+
const pathSplit = pathArg ? splitSearchPathArg(projectRoot, pathArg) : undefined;
|
|
38343
|
+
const bridgePath = pathSplit ? bridgeSearchPathArg(projectRoot, pathSplit) : undefined;
|
|
38082
38344
|
const grepDenied = await askGrepPermission(context, pattern, {
|
|
38083
38345
|
path: bridgePath,
|
|
38084
38346
|
include: includeArg
|
|
38085
38347
|
});
|
|
38086
38348
|
if (grepDenied)
|
|
38087
38349
|
return permissionDeniedResponse(grepDenied);
|
|
38088
|
-
if (
|
|
38089
|
-
for (const target of searchPathTargets(projectRoot,
|
|
38350
|
+
if (pathSplit) {
|
|
38351
|
+
for (const target of searchPathTargets(projectRoot, pathSplit, "file")) {
|
|
38090
38352
|
const externalDenied = await assertExternalDirectoryPermission(context, target.target, {
|
|
38091
38353
|
kind: target.kind
|
|
38092
38354
|
});
|
|
@@ -38104,7 +38366,10 @@ function searchTools(ctx) {
|
|
|
38104
38366
|
if (response.success === false) {
|
|
38105
38367
|
throw new Error(response.message || "grep failed");
|
|
38106
38368
|
}
|
|
38107
|
-
|
|
38369
|
+
if (pathSplit && pathSplit.missing.length > 0) {
|
|
38370
|
+
response.complete = false;
|
|
38371
|
+
}
|
|
38372
|
+
return appendSkippedSearchPaths(formatGrepOutput(response), pathSplit?.missing ?? []);
|
|
38108
38373
|
}
|
|
38109
38374
|
};
|
|
38110
38375
|
const globTool = {
|
|
@@ -38115,8 +38380,8 @@ function searchTools(ctx) {
|
|
|
38115
38380
|
},
|
|
38116
38381
|
execute: async (args, context) => {
|
|
38117
38382
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
38118
|
-
let globPattern =
|
|
38119
|
-
let globPath = args.path ?
|
|
38383
|
+
let globPattern = expandTilde2(String(args.pattern));
|
|
38384
|
+
let globPath = args.path ? String(args.path) : undefined;
|
|
38120
38385
|
if (!globPath && globPattern.startsWith("/")) {
|
|
38121
38386
|
const metaIdx = globPattern.search(/[*?{}[\]]/);
|
|
38122
38387
|
if (metaIdx > 0) {
|
|
@@ -38126,16 +38391,17 @@ function searchTools(ctx) {
|
|
|
38126
38391
|
globPattern = `**/${globPattern.slice(lastSlash + 1)}`;
|
|
38127
38392
|
}
|
|
38128
38393
|
} else if (metaIdx === -1) {
|
|
38129
|
-
globPath =
|
|
38130
|
-
globPattern =
|
|
38394
|
+
globPath = path7.dirname(globPattern);
|
|
38395
|
+
globPattern = path7.basename(globPattern);
|
|
38131
38396
|
}
|
|
38132
38397
|
}
|
|
38133
|
-
const
|
|
38398
|
+
const pathSplit = globPath ? splitSearchPathArg(projectRoot, globPath) : undefined;
|
|
38399
|
+
const bridgePath = pathSplit ? bridgeSearchPathArg(projectRoot, pathSplit) : undefined;
|
|
38400
|
+
const globDenied = await askGlobPermission(context, globPattern, { path: bridgePath });
|
|
38134
38401
|
if (globDenied)
|
|
38135
38402
|
return permissionDeniedResponse(globDenied);
|
|
38136
|
-
|
|
38137
|
-
|
|
38138
|
-
for (const target of searchPathTargets(projectRoot, globPath, "directory")) {
|
|
38403
|
+
if (pathSplit) {
|
|
38404
|
+
for (const target of searchPathTargets(projectRoot, pathSplit, "directory")) {
|
|
38139
38405
|
const externalDenied = await assertExternalDirectoryPermission(context, target.target, {
|
|
38140
38406
|
kind: target.kind
|
|
38141
38407
|
});
|
|
@@ -38150,14 +38416,17 @@ function searchTools(ctx) {
|
|
|
38150
38416
|
if (response.success === false) {
|
|
38151
38417
|
throw new Error(response.message || "glob failed");
|
|
38152
38418
|
}
|
|
38419
|
+
if (pathSplit && pathSplit.missing.length > 0) {
|
|
38420
|
+
response.complete = false;
|
|
38421
|
+
}
|
|
38153
38422
|
if (typeof response.text === "string") {
|
|
38154
|
-
return response.text;
|
|
38423
|
+
return appendSkippedSearchPaths(response.text, pathSplit?.missing ?? []);
|
|
38155
38424
|
}
|
|
38156
38425
|
if (Array.isArray(response.files)) {
|
|
38157
|
-
return response.files.join(`
|
|
38158
|
-
`);
|
|
38426
|
+
return appendSkippedSearchPaths(response.files.join(`
|
|
38427
|
+
`), pathSplit?.missing ?? []);
|
|
38159
38428
|
}
|
|
38160
|
-
return response.text || JSON.stringify(response);
|
|
38429
|
+
return appendSkippedSearchPaths(response.text || JSON.stringify(response), pathSplit?.missing ?? []);
|
|
38161
38430
|
}
|
|
38162
38431
|
};
|
|
38163
38432
|
const hoisting = ctx.config.hoist_builtin_tools !== false;
|
|
@@ -38472,6 +38741,7 @@ ${lines}
|
|
|
38472
38741
|
}
|
|
38473
38742
|
const versionUpgradePromises = new Map;
|
|
38474
38743
|
const poolOptions = {
|
|
38744
|
+
...resolveBridgePoolTransportOptions(aftConfig),
|
|
38475
38745
|
errorPrefix: "[aft-plugin]",
|
|
38476
38746
|
minVersion: PLUGIN_VERSION,
|
|
38477
38747
|
projectConfigLoader: (projectRoot) => {
|
|
@@ -38492,13 +38762,13 @@ ${lines}
|
|
|
38492
38762
|
const upgradePromise = (async () => {
|
|
38493
38763
|
warn2(`WARNING: aft binary v${binaryVersion} is older than plugin v${minVersion}. ` + "Some features may not work. Attempting to download a compatible binary...");
|
|
38494
38764
|
try {
|
|
38495
|
-
const
|
|
38496
|
-
if (!
|
|
38765
|
+
const path8 = await ensureBinary(`v${minVersion}`);
|
|
38766
|
+
if (!path8) {
|
|
38497
38767
|
warn2(`Could not find or download v${minVersion}. Continuing with v${binaryVersion}.`);
|
|
38498
38768
|
return null;
|
|
38499
38769
|
}
|
|
38500
|
-
log2(`Found/downloaded compatible binary at ${
|
|
38501
|
-
const replaced = await pool.replaceBinary(
|
|
38770
|
+
log2(`Found/downloaded compatible binary at ${path8}. Replacing running bridges...`);
|
|
38771
|
+
const replaced = await pool.replaceBinary(path8);
|
|
38502
38772
|
log2("Binary replaced successfully. New bridges will use the updated binary.");
|
|
38503
38773
|
return replaced;
|
|
38504
38774
|
} catch (err) {
|