@cortexkit/aft-opencode 0.38.0 → 0.39.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +933 -576
- 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/tui/preferences.d.ts +33 -0
- package/dist/tui/preferences.d.ts.map +1 -0
- package/dist/tui.js +8089 -74
- package/package.json +8 -8
- package/src/tui/index.tsx +1 -1
- package/src/tui/preferences.ts +243 -0
- package/src/tui/sidebar.tsx +123 -77
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.`;
|
|
@@ -11607,48 +11645,175 @@ function maybeAppendConflictsHint(output) {
|
|
|
11607
11645
|
return output;
|
|
11608
11646
|
return output + CONFLICT_HINT;
|
|
11609
11647
|
}
|
|
11610
|
-
function
|
|
11611
|
-
const
|
|
11612
|
-
if (
|
|
11613
|
-
return false;
|
|
11614
|
-
const afterCd = peelLeadingCdAnd(trimmed);
|
|
11615
|
-
if (afterCd === null)
|
|
11616
|
-
return false;
|
|
11617
|
-
const firstStage = firstPipelineStage(afterCd);
|
|
11618
|
-
if (firstStage === null)
|
|
11648
|
+
function commandInvokesCodeSearch(command) {
|
|
11649
|
+
const statements = splitTopLevelStatements(command);
|
|
11650
|
+
if (statements === null)
|
|
11619
11651
|
return false;
|
|
11620
|
-
const
|
|
11621
|
-
|
|
11622
|
-
|
|
11623
|
-
|
|
11652
|
+
for (const statement of statements) {
|
|
11653
|
+
const firstStage = firstPipelineStage(statement);
|
|
11654
|
+
if (firstStage === null)
|
|
11655
|
+
continue;
|
|
11656
|
+
const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0));
|
|
11657
|
+
if (firstToken === null)
|
|
11658
|
+
continue;
|
|
11659
|
+
if (firstToken.token === "grep" || firstToken.token === "rg")
|
|
11660
|
+
return true;
|
|
11661
|
+
}
|
|
11662
|
+
return false;
|
|
11624
11663
|
}
|
|
11625
|
-
function maybeAppendGrepSearchHint(output, command, aftSearchRegistered) {
|
|
11664
|
+
function maybeAppendGrepSearchHint(output, command, aftSearchRegistered, projectRoot) {
|
|
11626
11665
|
if (output === "")
|
|
11627
11666
|
return output;
|
|
11628
|
-
if (!
|
|
11667
|
+
if (!commandInvokesCodeSearch(command))
|
|
11629
11668
|
return output;
|
|
11630
11669
|
if (output.includes(GREP_SEARCH_HINT_PREFIX))
|
|
11631
11670
|
return output;
|
|
11671
|
+
if (shouldSuppressGrepSearchHint(command, projectRoot))
|
|
11672
|
+
return output;
|
|
11632
11673
|
const hint = aftSearchRegistered ? GREP_SEARCH_AFT_SEARCH_HINT : GREP_SEARCH_GREP_HINT;
|
|
11633
11674
|
return `${output}
|
|
11634
11675
|
|
|
11635
11676
|
${hint}`;
|
|
11636
11677
|
}
|
|
11637
|
-
function
|
|
11638
|
-
const
|
|
11639
|
-
if (
|
|
11640
|
-
return
|
|
11641
|
-
|
|
11642
|
-
|
|
11643
|
-
|
|
11644
|
-
|
|
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
|
+
}
|
|
11745
|
+
function splitTopLevelStatements(command) {
|
|
11746
|
+
const statements = [];
|
|
11747
|
+
let start = 0;
|
|
11748
|
+
let quote = "none";
|
|
11749
|
+
let escaped = false;
|
|
11750
|
+
let inBacktick = false;
|
|
11751
|
+
let parenDepth = 0;
|
|
11752
|
+
for (let index = 0;index < command.length; index++) {
|
|
11753
|
+
const ch = command[index];
|
|
11754
|
+
if (escaped) {
|
|
11755
|
+
escaped = false;
|
|
11756
|
+
continue;
|
|
11757
|
+
}
|
|
11758
|
+
if (quote === "single") {
|
|
11759
|
+
if (ch === "'")
|
|
11760
|
+
quote = "none";
|
|
11761
|
+
continue;
|
|
11762
|
+
}
|
|
11763
|
+
if (quote === "double") {
|
|
11764
|
+
if (ch === "\\")
|
|
11765
|
+
escaped = true;
|
|
11766
|
+
else if (ch === '"')
|
|
11767
|
+
quote = "none";
|
|
11768
|
+
continue;
|
|
11769
|
+
}
|
|
11770
|
+
if (inBacktick) {
|
|
11771
|
+
if (ch === "`")
|
|
11772
|
+
inBacktick = false;
|
|
11773
|
+
continue;
|
|
11774
|
+
}
|
|
11775
|
+
if (ch === "\\") {
|
|
11776
|
+
escaped = true;
|
|
11777
|
+
continue;
|
|
11778
|
+
}
|
|
11779
|
+
if (ch === "'") {
|
|
11780
|
+
quote = "single";
|
|
11781
|
+
continue;
|
|
11782
|
+
}
|
|
11783
|
+
if (ch === '"') {
|
|
11784
|
+
quote = "double";
|
|
11785
|
+
continue;
|
|
11786
|
+
}
|
|
11787
|
+
if (ch === "`") {
|
|
11788
|
+
inBacktick = true;
|
|
11789
|
+
continue;
|
|
11790
|
+
}
|
|
11791
|
+
if (ch === "(") {
|
|
11792
|
+
parenDepth++;
|
|
11793
|
+
continue;
|
|
11794
|
+
}
|
|
11795
|
+
if (ch === ")") {
|
|
11796
|
+
if (parenDepth > 0)
|
|
11797
|
+
parenDepth--;
|
|
11798
|
+
continue;
|
|
11799
|
+
}
|
|
11800
|
+
if (parenDepth > 0)
|
|
11801
|
+
continue;
|
|
11802
|
+
const next = command[index + 1];
|
|
11803
|
+
if (ch === "&" && next === "&" || ch === "|" && next === "|") {
|
|
11804
|
+
statements.push(command.slice(start, index));
|
|
11805
|
+
index++;
|
|
11806
|
+
start = index + 1;
|
|
11807
|
+
} else if (ch === ";" || ch === `
|
|
11808
|
+
` || ch === "&") {
|
|
11809
|
+
statements.push(command.slice(start, index));
|
|
11810
|
+
start = index + 1;
|
|
11811
|
+
}
|
|
11812
|
+
}
|
|
11813
|
+
if (quote !== "none" || inBacktick || escaped)
|
|
11645
11814
|
return null;
|
|
11646
|
-
|
|
11647
|
-
|
|
11648
|
-
const afterDir = skipSpaces(command, dir.end);
|
|
11649
|
-
if (!command.startsWith("&&", afterDir))
|
|
11650
|
-
return command;
|
|
11651
|
-
return command.slice(afterDir + 2).trim();
|
|
11815
|
+
statements.push(command.slice(start));
|
|
11816
|
+
return statements;
|
|
11652
11817
|
}
|
|
11653
11818
|
function firstPipelineStage(command) {
|
|
11654
11819
|
let quote = "none";
|
|
@@ -11756,8 +11921,8 @@ function resolveBashKillTimeout(modelTimeout, foregroundWaitMs) {
|
|
|
11756
11921
|
}
|
|
11757
11922
|
// ../aft-bridge/dist/bridge.js
|
|
11758
11923
|
import { spawn } from "node:child_process";
|
|
11759
|
-
import { homedir } from "node:os";
|
|
11760
|
-
import { join } from "node:path";
|
|
11924
|
+
import { homedir as homedir2 } from "node:os";
|
|
11925
|
+
import { join as join2 } from "node:path";
|
|
11761
11926
|
import { StringDecoder } from "node:string_decoder";
|
|
11762
11927
|
|
|
11763
11928
|
// ../aft-bridge/dist/command-timeouts.js
|
|
@@ -12135,7 +12300,7 @@ class BinaryBridge {
|
|
|
12135
12300
|
`;
|
|
12136
12301
|
const keepBridgeOnTimeout = options?.keepBridgeOnTimeout === true;
|
|
12137
12302
|
let requestSentAt = Date.now();
|
|
12138
|
-
const response = await new Promise((
|
|
12303
|
+
const response = await new Promise((resolve2, reject) => {
|
|
12139
12304
|
const timer = setTimeout(() => {
|
|
12140
12305
|
const entry = this.pending.get(id);
|
|
12141
12306
|
if (!entry)
|
|
@@ -12170,7 +12335,7 @@ class BinaryBridge {
|
|
|
12170
12335
|
entry.reject(new Error(`${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`));
|
|
12171
12336
|
this.handleTimeout(requestSessionId);
|
|
12172
12337
|
}, effectiveTimeoutMs);
|
|
12173
|
-
this.pending.set(id, { resolve, reject, timer, onProgress: options?.onProgress, command });
|
|
12338
|
+
this.pending.set(id, { resolve: resolve2, reject, timer, onProgress: options?.onProgress, command });
|
|
12174
12339
|
if (!this.process?.stdin?.writable) {
|
|
12175
12340
|
this.pending.delete(id);
|
|
12176
12341
|
clearTimeout(timer);
|
|
@@ -12268,15 +12433,15 @@ class BinaryBridge {
|
|
|
12268
12433
|
if (this.process) {
|
|
12269
12434
|
const proc = this.process;
|
|
12270
12435
|
this.process = null;
|
|
12271
|
-
return new Promise((
|
|
12436
|
+
return new Promise((resolve2) => {
|
|
12272
12437
|
const forceKillTimer = setTimeout(() => {
|
|
12273
12438
|
proc.kill("SIGKILL");
|
|
12274
|
-
|
|
12439
|
+
resolve2();
|
|
12275
12440
|
}, 5000);
|
|
12276
12441
|
proc.once("exit", () => {
|
|
12277
12442
|
clearTimeout(forceKillTimer);
|
|
12278
12443
|
this.logVia("Process exited during shutdown");
|
|
12279
|
-
|
|
12444
|
+
resolve2();
|
|
12280
12445
|
});
|
|
12281
12446
|
proc.kill("SIGTERM");
|
|
12282
12447
|
});
|
|
@@ -12321,15 +12486,15 @@ class BinaryBridge {
|
|
|
12321
12486
|
return;
|
|
12322
12487
|
const proc = this.process;
|
|
12323
12488
|
this.process = null;
|
|
12324
|
-
await new Promise((
|
|
12489
|
+
await new Promise((resolve2) => {
|
|
12325
12490
|
const forceKillTimer = setTimeout(() => {
|
|
12326
12491
|
proc.kill("SIGKILL");
|
|
12327
|
-
|
|
12492
|
+
resolve2();
|
|
12328
12493
|
}, 5000);
|
|
12329
12494
|
proc.once("exit", () => {
|
|
12330
12495
|
clearTimeout(forceKillTimer);
|
|
12331
12496
|
this.logVia("Process exited during coordinated binary replacement");
|
|
12332
|
-
|
|
12497
|
+
resolve2();
|
|
12333
12498
|
});
|
|
12334
12499
|
proc.kill("SIGTERM");
|
|
12335
12500
|
});
|
|
@@ -12356,7 +12521,7 @@ class BinaryBridge {
|
|
|
12356
12521
|
})();
|
|
12357
12522
|
const useFastembedBackend = semanticBackend === undefined || semanticBackend === "fastembed" || semanticBackend === "";
|
|
12358
12523
|
const ortDir = typeof this.configOverrides._ort_dylib_dir === "string" && useFastembedBackend ? this.configOverrides._ort_dylib_dir : null;
|
|
12359
|
-
const ortLibraryPath = ortDir == null ? null :
|
|
12524
|
+
const ortLibraryPath = ortDir == null ? null : join2(ortDir, process.platform === "win32" ? "onnxruntime.dll" : process.platform === "darwin" ? "libonnxruntime.dylib" : "libonnxruntime.so");
|
|
12360
12525
|
const envPath = process.platform === "win32" && ortDir ? `${ortDir};${process.env.PATH ?? ""}` : process.env.PATH;
|
|
12361
12526
|
const env = {
|
|
12362
12527
|
...process.env,
|
|
@@ -12364,7 +12529,7 @@ class BinaryBridge {
|
|
|
12364
12529
|
};
|
|
12365
12530
|
this.logVia(`bridge.spawnProcess: useFastembedBackend=${useFastembedBackend}, ` + `parentORT=${process.env.ORT_DYLIB_PATH ?? "(unset)"}, ` + `ortLibraryPath=${ortLibraryPath ?? "(none)"}`);
|
|
12366
12531
|
if (useFastembedBackend) {
|
|
12367
|
-
env.FASTEMBED_CACHE_DIR = process.env.FASTEMBED_CACHE_DIR || (typeof this.configOverrides.storage_dir === "string" ?
|
|
12532
|
+
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"));
|
|
12368
12533
|
if (process.env.ORT_DYLIB_PATH) {
|
|
12369
12534
|
this.logVia(`ORT_DYLIB_PATH inherited from parent env: ${process.env.ORT_DYLIB_PATH}`);
|
|
12370
12535
|
} else if (ortLibraryPath) {
|
|
@@ -12706,12 +12871,23 @@ function coerceStringArray(value) {
|
|
|
12706
12871
|
}
|
|
12707
12872
|
return [];
|
|
12708
12873
|
}
|
|
12874
|
+
function isEmptyParam(value) {
|
|
12875
|
+
if (value === undefined || value === null)
|
|
12876
|
+
return true;
|
|
12877
|
+
if (typeof value === "string")
|
|
12878
|
+
return value.length === 0;
|
|
12879
|
+
if (Array.isArray(value))
|
|
12880
|
+
return value.length === 0;
|
|
12881
|
+
if (typeof value === "object")
|
|
12882
|
+
return Object.keys(value).length === 0;
|
|
12883
|
+
return false;
|
|
12884
|
+
}
|
|
12709
12885
|
// ../aft-bridge/dist/downloader.js
|
|
12710
12886
|
import { spawnSync } from "node:child_process";
|
|
12711
12887
|
import { createHash, randomUUID } from "node:crypto";
|
|
12712
12888
|
import { chmodSync, closeSync, copyFileSync, createWriteStream, existsSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, unlinkSync, writeSync } from "node:fs";
|
|
12713
|
-
import { homedir as
|
|
12714
|
-
import { join as
|
|
12889
|
+
import { homedir as homedir3 } from "node:os";
|
|
12890
|
+
import { join as join3 } from "node:path";
|
|
12715
12891
|
import { Readable } from "node:stream";
|
|
12716
12892
|
import { pipeline } from "node:stream/promises";
|
|
12717
12893
|
|
|
@@ -12768,11 +12944,11 @@ function isExpectedCachedBinary(binaryPath, tag) {
|
|
|
12768
12944
|
function getCacheDir() {
|
|
12769
12945
|
if (process.platform === "win32") {
|
|
12770
12946
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
12771
|
-
const base2 = localAppData ||
|
|
12772
|
-
return
|
|
12947
|
+
const base2 = localAppData || join3(homedir3(), "AppData", "Local");
|
|
12948
|
+
return join3(base2, "aft", "bin");
|
|
12773
12949
|
}
|
|
12774
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
12775
|
-
return
|
|
12950
|
+
const base = process.env.XDG_CACHE_HOME || join3(homedir3(), ".cache");
|
|
12951
|
+
return join3(base, "aft", "bin");
|
|
12776
12952
|
}
|
|
12777
12953
|
function getBinaryName() {
|
|
12778
12954
|
return process.platform === "win32" ? "aft.exe" : "aft";
|
|
@@ -12780,7 +12956,7 @@ function getBinaryName() {
|
|
|
12780
12956
|
function getCachedBinaryPath(version) {
|
|
12781
12957
|
if (!version)
|
|
12782
12958
|
return null;
|
|
12783
|
-
const binaryPath =
|
|
12959
|
+
const binaryPath = join3(getCacheDir(), version, getBinaryName());
|
|
12784
12960
|
return existsSync(binaryPath) ? binaryPath : null;
|
|
12785
12961
|
}
|
|
12786
12962
|
async function downloadBinary(version) {
|
|
@@ -12797,16 +12973,16 @@ async function downloadBinary(version) {
|
|
|
12797
12973
|
return null;
|
|
12798
12974
|
}
|
|
12799
12975
|
const tag = rawTag.startsWith("v") ? rawTag : `v${rawTag}`;
|
|
12800
|
-
const versionedCacheDir =
|
|
12976
|
+
const versionedCacheDir = join3(getCacheDir(), tag);
|
|
12801
12977
|
const binaryName = getBinaryName();
|
|
12802
|
-
const binaryPath =
|
|
12978
|
+
const binaryPath = join3(versionedCacheDir, binaryName);
|
|
12803
12979
|
if (existsSync(binaryPath) && isExpectedCachedBinary(binaryPath, tag)) {
|
|
12804
12980
|
return binaryPath;
|
|
12805
12981
|
}
|
|
12806
12982
|
const downloadUrl = `https://github.com/${REPO}/releases/download/${tag}/${assetName}`;
|
|
12807
12983
|
const checksumUrl = `https://github.com/${REPO}/releases/download/${tag}/checksums.sha256`;
|
|
12808
12984
|
log(`Downloading AFT binary (${tag}) for ${platformKey}...`);
|
|
12809
|
-
const lockPath =
|
|
12985
|
+
const lockPath = join3(versionedCacheDir, ".download.lock");
|
|
12810
12986
|
let releaseLock = null;
|
|
12811
12987
|
let binaryController = null;
|
|
12812
12988
|
let checksumController = null;
|
|
@@ -12958,7 +13134,7 @@ async function acquireDownloadLock(lockPath) {
|
|
|
12958
13134
|
if (Date.now() - startedAt > DOWNLOAD_LOCK_TIMEOUT_MS) {
|
|
12959
13135
|
throw new Error(`Timed out waiting for download lock: ${lockPath}`);
|
|
12960
13136
|
}
|
|
12961
|
-
await new Promise((
|
|
13137
|
+
await new Promise((resolve2) => setTimeout(resolve2, 100));
|
|
12962
13138
|
}
|
|
12963
13139
|
}
|
|
12964
13140
|
}
|
|
@@ -13044,18 +13220,18 @@ function stripJsoncSymbols(value) {
|
|
|
13044
13220
|
// ../aft-bridge/dist/migration.js
|
|
13045
13221
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
13046
13222
|
import { existsSync as existsSync4, mkdirSync as mkdirSync4 } from "node:fs";
|
|
13047
|
-
import { homedir as
|
|
13048
|
-
import { dirname as dirname2, join as
|
|
13223
|
+
import { homedir as homedir5, tmpdir } from "node:os";
|
|
13224
|
+
import { dirname as dirname2, join as join6 } from "node:path";
|
|
13049
13225
|
|
|
13050
13226
|
// ../aft-bridge/dist/paths.js
|
|
13051
13227
|
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync as renameSync2, writeFileSync } from "node:fs";
|
|
13052
|
-
import { dirname, join as
|
|
13228
|
+
import { dirname, join as join4 } from "node:path";
|
|
13053
13229
|
function resolveHarnessStoragePath(storageRoot, harness, ...segments) {
|
|
13054
|
-
return
|
|
13230
|
+
return join4(storageRoot, harness, ...segments);
|
|
13055
13231
|
}
|
|
13056
13232
|
function repairRootScopedStorageFile(storageRoot, harness, fileName) {
|
|
13057
13233
|
const harnessPath = resolveHarnessStoragePath(storageRoot, harness, fileName);
|
|
13058
|
-
const rootPath =
|
|
13234
|
+
const rootPath = join4(storageRoot, fileName);
|
|
13059
13235
|
if (existsSync2(harnessPath) || !existsSync2(rootPath))
|
|
13060
13236
|
return harnessPath;
|
|
13061
13237
|
try {
|
|
@@ -13101,8 +13277,8 @@ function markAnnouncementSeen(storageRoot, harness, currentVersion) {
|
|
|
13101
13277
|
import { execSync } from "node:child_process";
|
|
13102
13278
|
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";
|
|
13103
13279
|
import { createRequire as createRequire2 } from "node:module";
|
|
13104
|
-
import { homedir as
|
|
13105
|
-
import { join as
|
|
13280
|
+
import { homedir as homedir4 } from "node:os";
|
|
13281
|
+
import { join as join5 } from "node:path";
|
|
13106
13282
|
var ensureBinaryForResolver = ensureBinary;
|
|
13107
13283
|
function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
13108
13284
|
try {
|
|
@@ -13111,9 +13287,9 @@ function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
|
13111
13287
|
return null;
|
|
13112
13288
|
const tag = version.startsWith("v") ? version : `v${version}`;
|
|
13113
13289
|
const cacheDir = getCacheDir();
|
|
13114
|
-
const versionedDir =
|
|
13290
|
+
const versionedDir = join5(cacheDir, tag);
|
|
13115
13291
|
const ext = process.platform === "win32" ? ".exe" : "";
|
|
13116
|
-
const cachedPath =
|
|
13292
|
+
const cachedPath = join5(versionedDir, `aft${ext}`);
|
|
13117
13293
|
if (existsSync3(cachedPath)) {
|
|
13118
13294
|
const cachedVersion = readBinaryVersion(cachedPath);
|
|
13119
13295
|
if (cachedVersion === version)
|
|
@@ -13143,18 +13319,18 @@ function normalizeBareVersion(version) {
|
|
|
13143
13319
|
return version.startsWith("v") ? version.slice(1) : version;
|
|
13144
13320
|
}
|
|
13145
13321
|
function homeDirFromEnv(env) {
|
|
13146
|
-
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) ||
|
|
13322
|
+
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir4();
|
|
13147
13323
|
}
|
|
13148
13324
|
function cacheDirFromEnv(env) {
|
|
13149
13325
|
if (process.platform === "win32") {
|
|
13150
|
-
const base2 = env.LOCALAPPDATA || env.APPDATA ||
|
|
13151
|
-
return
|
|
13326
|
+
const base2 = env.LOCALAPPDATA || env.APPDATA || join5(homeDirFromEnv(env), "AppData", "Local");
|
|
13327
|
+
return join5(base2, "aft", "bin");
|
|
13152
13328
|
}
|
|
13153
|
-
const base = env.XDG_CACHE_HOME ||
|
|
13154
|
-
return
|
|
13329
|
+
const base = env.XDG_CACHE_HOME || join5(homeDirFromEnv(env), ".cache");
|
|
13330
|
+
return join5(base, "aft", "bin");
|
|
13155
13331
|
}
|
|
13156
13332
|
function cachedBinaryPathFromEnv(version, env, ext) {
|
|
13157
|
-
const binaryPath =
|
|
13333
|
+
const binaryPath = join5(cacheDirFromEnv(env), version, `aft${ext}`);
|
|
13158
13334
|
return existsSync3(binaryPath) ? binaryPath : null;
|
|
13159
13335
|
}
|
|
13160
13336
|
function isExpectedCachedBinary2(binaryPath, expectedVersion) {
|
|
@@ -13273,7 +13449,7 @@ function findBinarySync(expectedVersion) {
|
|
|
13273
13449
|
return usable;
|
|
13274
13450
|
}
|
|
13275
13451
|
} catch {}
|
|
13276
|
-
const cargoPath =
|
|
13452
|
+
const cargoPath = join5(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
|
|
13277
13453
|
if (existsSync3(cargoPath)) {
|
|
13278
13454
|
const usable = probeBinaryCandidate(cargoPath, "cargo", expectedVersion);
|
|
13279
13455
|
if (usable)
|
|
@@ -13319,22 +13495,22 @@ function dataHome() {
|
|
|
13319
13495
|
if (process.env.XDG_DATA_HOME)
|
|
13320
13496
|
return process.env.XDG_DATA_HOME;
|
|
13321
13497
|
if (process.platform === "win32") {
|
|
13322
|
-
return process.env.LOCALAPPDATA || process.env.APPDATA ||
|
|
13498
|
+
return process.env.LOCALAPPDATA || process.env.APPDATA || join6(homeDir(), "AppData", "Local");
|
|
13323
13499
|
}
|
|
13324
|
-
return
|
|
13500
|
+
return join6(homeDir(), ".local", "share");
|
|
13325
13501
|
}
|
|
13326
13502
|
function homeDir() {
|
|
13327
13503
|
if (process.platform === "win32")
|
|
13328
|
-
return process.env.USERPROFILE || process.env.HOME ||
|
|
13329
|
-
return process.env.HOME ||
|
|
13504
|
+
return process.env.USERPROFILE || process.env.HOME || homedir5();
|
|
13505
|
+
return process.env.HOME || homedir5();
|
|
13330
13506
|
}
|
|
13331
13507
|
function resolveLegacyStorageRoot(harness) {
|
|
13332
13508
|
if (harness === "pi")
|
|
13333
|
-
return
|
|
13334
|
-
return
|
|
13509
|
+
return join6(homeDir(), ".pi", "agent", "aft");
|
|
13510
|
+
return join6(dataHome(), "opencode", "storage", "plugin", "aft");
|
|
13335
13511
|
}
|
|
13336
13512
|
function resolveCortexKitStorageRoot() {
|
|
13337
|
-
return
|
|
13513
|
+
return join6(dataHome(), "cortexkit", "aft");
|
|
13338
13514
|
}
|
|
13339
13515
|
function tail(value) {
|
|
13340
13516
|
if (!value)
|
|
@@ -13348,12 +13524,12 @@ function spawnErrorLabel(error2) {
|
|
|
13348
13524
|
return [code, error2.message].filter(Boolean).join(": ");
|
|
13349
13525
|
}
|
|
13350
13526
|
function migrationLogPath(newRoot, harness, logger) {
|
|
13351
|
-
const desired =
|
|
13527
|
+
const desired = join6(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
|
|
13352
13528
|
try {
|
|
13353
13529
|
mkdirSync4(dirname2(desired), { recursive: true });
|
|
13354
13530
|
return desired;
|
|
13355
13531
|
} catch (err) {
|
|
13356
|
-
const fallback =
|
|
13532
|
+
const fallback = join6(tmpdir(), `aft-migration-${harness}-${Date.now()}.jsonl`);
|
|
13357
13533
|
logger?.warn?.(`Failed to create AFT migration log directory ${dirname2(desired)}: ${err instanceof Error ? err.message : String(err)}. ` + `Using fallback log path ${fallback}.`);
|
|
13358
13534
|
return fallback;
|
|
13359
13535
|
}
|
|
@@ -13416,13 +13592,13 @@ async function ensureStorageMigrated(opts) {
|
|
|
13416
13592
|
}
|
|
13417
13593
|
// ../aft-bridge/dist/npm-resolver.js
|
|
13418
13594
|
import { readdirSync, statSync as statSync2 } from "node:fs";
|
|
13419
|
-
import { homedir as
|
|
13420
|
-
import { delimiter, dirname as dirname3, isAbsolute, join as
|
|
13595
|
+
import { homedir as homedir6 } from "node:os";
|
|
13596
|
+
import { delimiter, dirname as dirname3, isAbsolute as isAbsolute2, join as join7 } from "node:path";
|
|
13421
13597
|
function defaultDeps() {
|
|
13422
13598
|
return {
|
|
13423
13599
|
platform: process.platform,
|
|
13424
13600
|
env: process.env,
|
|
13425
|
-
home:
|
|
13601
|
+
home: homedir6(),
|
|
13426
13602
|
execPath: process.execPath
|
|
13427
13603
|
};
|
|
13428
13604
|
}
|
|
@@ -13441,16 +13617,16 @@ function npmFromPath(deps) {
|
|
|
13441
13617
|
const raw = deps.env.PATH ?? deps.env.Path ?? "";
|
|
13442
13618
|
for (const entry of raw.split(delimiter)) {
|
|
13443
13619
|
const dir = entry.trim().replace(/^"|"$/g, "");
|
|
13444
|
-
if (!dir || !
|
|
13620
|
+
if (!dir || !isAbsolute2(dir))
|
|
13445
13621
|
continue;
|
|
13446
|
-
if (isFile(
|
|
13622
|
+
if (isFile(join7(dir, name)))
|
|
13447
13623
|
return dir;
|
|
13448
13624
|
}
|
|
13449
13625
|
return null;
|
|
13450
13626
|
}
|
|
13451
13627
|
function npmAdjacentToNode(deps) {
|
|
13452
13628
|
const dir = dirname3(deps.execPath);
|
|
13453
|
-
return isFile(
|
|
13629
|
+
return isFile(join7(dir, npmBinaryName(deps.platform))) ? dir : null;
|
|
13454
13630
|
}
|
|
13455
13631
|
function highestVersionedNodeBin(installsDir, name) {
|
|
13456
13632
|
let entries;
|
|
@@ -13459,8 +13635,8 @@ function highestVersionedNodeBin(installsDir, name) {
|
|
|
13459
13635
|
} catch {
|
|
13460
13636
|
return null;
|
|
13461
13637
|
}
|
|
13462
|
-
const candidates = entries.filter((v) => isFile(
|
|
13463
|
-
return candidates.length > 0 ?
|
|
13638
|
+
const candidates = entries.filter((v) => isFile(join7(installsDir, v, "bin", name))).sort((a, b) => compareVersionsDesc(a, b));
|
|
13639
|
+
return candidates.length > 0 ? join7(installsDir, candidates[0], "bin") : null;
|
|
13464
13640
|
}
|
|
13465
13641
|
function compareVersionsDesc(a, b) {
|
|
13466
13642
|
const pa = a.replace(/^v/, "").split(".").map((n) => Number.parseInt(n, 10));
|
|
@@ -13485,22 +13661,22 @@ function wellKnownNpmDirs(deps) {
|
|
|
13485
13661
|
const programFiles = env.ProgramFiles || "C:\\Program Files";
|
|
13486
13662
|
const appData = env.APPDATA;
|
|
13487
13663
|
const localAppData = env.LOCALAPPDATA;
|
|
13488
|
-
push(
|
|
13664
|
+
push(join7(programFiles, "nodejs"));
|
|
13489
13665
|
if (appData)
|
|
13490
|
-
push(
|
|
13666
|
+
push(join7(appData, "npm"));
|
|
13491
13667
|
if (localAppData)
|
|
13492
|
-
push(
|
|
13668
|
+
push(join7(localAppData, "Volta", "bin"));
|
|
13493
13669
|
if (env.NVM_SYMLINK)
|
|
13494
13670
|
push(env.NVM_SYMLINK);
|
|
13495
13671
|
} else {
|
|
13496
13672
|
if (env.NVM_BIN)
|
|
13497
13673
|
push(env.NVM_BIN);
|
|
13498
|
-
push(highestVersionedNodeBin(
|
|
13499
|
-
push(highestVersionedNodeBin(
|
|
13500
|
-
push(highestVersionedNodeBin(
|
|
13501
|
-
push(
|
|
13502
|
-
push(
|
|
13503
|
-
const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin",
|
|
13674
|
+
push(highestVersionedNodeBin(join7(home, ".nvm", "versions", "node"), name));
|
|
13675
|
+
push(highestVersionedNodeBin(join7(home, ".local", "share", "mise", "installs", "node"), name));
|
|
13676
|
+
push(highestVersionedNodeBin(join7(home, ".asdf", "installs", "nodejs"), name));
|
|
13677
|
+
push(join7(home, ".volta", "bin"));
|
|
13678
|
+
push(join7(home, ".asdf", "shims"));
|
|
13679
|
+
const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin", join7(home, ".local", "bin")]);
|
|
13504
13680
|
for (const dir of systemDirs)
|
|
13505
13681
|
push(dir);
|
|
13506
13682
|
}
|
|
@@ -13510,12 +13686,12 @@ function resolveNpm(deps = defaultDeps()) {
|
|
|
13510
13686
|
const name = npmBinaryName(deps.platform);
|
|
13511
13687
|
const onPath = npmFromPath(deps);
|
|
13512
13688
|
if (onPath)
|
|
13513
|
-
return { command:
|
|
13689
|
+
return { command: join7(onPath, name), binDir: onPath };
|
|
13514
13690
|
const adjacent = npmAdjacentToNode(deps);
|
|
13515
13691
|
if (adjacent)
|
|
13516
|
-
return { command:
|
|
13692
|
+
return { command: join7(adjacent, name), binDir: adjacent };
|
|
13517
13693
|
for (const dir of wellKnownNpmDirs(deps)) {
|
|
13518
|
-
const candidate =
|
|
13694
|
+
const candidate = join7(dir, name);
|
|
13519
13695
|
if (isFile(candidate))
|
|
13520
13696
|
return { command: candidate, binDir: dir };
|
|
13521
13697
|
}
|
|
@@ -13535,7 +13711,7 @@ function isNpmAvailable(deps = defaultDeps()) {
|
|
|
13535
13711
|
import { execFileSync } from "node:child_process";
|
|
13536
13712
|
import { createHash as createHash2 } from "node:crypto";
|
|
13537
13713
|
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";
|
|
13538
|
-
import { basename, dirname as dirname4, isAbsolute as
|
|
13714
|
+
import { basename, dirname as dirname4, isAbsolute as isAbsolute3, join as join8, relative as relative2, resolve as resolve2, win32 } from "node:path";
|
|
13539
13715
|
import { Readable as Readable2 } from "node:stream";
|
|
13540
13716
|
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
13541
13717
|
var ORT_VERSION = "1.24.4";
|
|
@@ -13601,10 +13777,10 @@ function getManualInstallHint() {
|
|
|
13601
13777
|
}
|
|
13602
13778
|
async function ensureOnnxRuntime(storageDir) {
|
|
13603
13779
|
const info = getPlatformInfo();
|
|
13604
|
-
const ortVersionDir =
|
|
13780
|
+
const ortVersionDir = join8(storageDir, "onnxruntime", ORT_VERSION);
|
|
13605
13781
|
const libName = info?.libName ?? "libonnxruntime.dylib";
|
|
13606
13782
|
const resolvedOrtDir = resolveCachedOnnxRuntimeDir(ortVersionDir, libName);
|
|
13607
|
-
const libPath =
|
|
13783
|
+
const libPath = join8(resolvedOrtDir, libName);
|
|
13608
13784
|
if (existsSync5(libPath)) {
|
|
13609
13785
|
const meta = readOnnxInstalledMeta(ortVersionDir);
|
|
13610
13786
|
if (meta?.sha256) {
|
|
@@ -13634,9 +13810,9 @@ async function ensureOnnxRuntime(storageDir) {
|
|
|
13634
13810
|
warn(`ONNX Runtime auto-download not available for ${process.platform}/${process.arch}. Install manually: ${getManualInstallHint()}`);
|
|
13635
13811
|
return null;
|
|
13636
13812
|
}
|
|
13637
|
-
const onnxBaseDir =
|
|
13813
|
+
const onnxBaseDir = join8(storageDir, "onnxruntime");
|
|
13638
13814
|
mkdirSync5(onnxBaseDir, { recursive: true });
|
|
13639
|
-
const lockPath =
|
|
13815
|
+
const lockPath = join8(onnxBaseDir, ONNX_LOCK_FILE);
|
|
13640
13816
|
cleanupAbandonedStagingDirs(onnxBaseDir);
|
|
13641
13817
|
if (!acquireLock(lockPath)) {
|
|
13642
13818
|
warn(`ONNX Runtime install already in progress in another process (lock: ${lockPath}). Skipping.`);
|
|
@@ -13655,7 +13831,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
13655
13831
|
for (const entry of entries) {
|
|
13656
13832
|
if (!entry.startsWith(`${ORT_VERSION}.tmp.`))
|
|
13657
13833
|
continue;
|
|
13658
|
-
const stagingDir =
|
|
13834
|
+
const stagingDir = join8(onnxBaseDir, entry);
|
|
13659
13835
|
const parts = entry.split(".");
|
|
13660
13836
|
const pidStr = parts[parts.length - 2];
|
|
13661
13837
|
const pid = pidStr ? Number.parseInt(pidStr, 10) : NaN;
|
|
@@ -13692,7 +13868,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
13692
13868
|
}
|
|
13693
13869
|
function cleanupIncompleteTargetIfUnowned(ortDir) {
|
|
13694
13870
|
try {
|
|
13695
|
-
if (existsSync5(ortDir) && !existsSync5(
|
|
13871
|
+
if (existsSync5(ortDir) && !existsSync5(join8(ortDir, ONNX_INSTALLED_META_FILE))) {
|
|
13696
13872
|
log(`[onnx] removing half-populated install dir ${ortDir} (no meta file)`);
|
|
13697
13873
|
rmSync2(ortDir, { recursive: true, force: true });
|
|
13698
13874
|
}
|
|
@@ -13720,8 +13896,8 @@ function parseOnnxVersionFromDirectoryPath(value) {
|
|
|
13720
13896
|
return null;
|
|
13721
13897
|
}
|
|
13722
13898
|
function isPathInsideRoot(root, candidate) {
|
|
13723
|
-
const rel =
|
|
13724
|
-
return rel === "" || !rel.startsWith("../") && !rel.startsWith("..\\") && rel !== ".." && !
|
|
13899
|
+
const rel = relative2(root, candidate);
|
|
13900
|
+
return rel === "" || !rel.startsWith("../") && !rel.startsWith("..\\") && rel !== ".." && !isAbsolute3(rel) && !win32.isAbsolute(rel);
|
|
13725
13901
|
}
|
|
13726
13902
|
function detectOnnxVersion(libDir, libName) {
|
|
13727
13903
|
try {
|
|
@@ -13736,7 +13912,7 @@ function detectOnnxVersion(libDir, libName) {
|
|
|
13736
13912
|
if (version)
|
|
13737
13913
|
return version;
|
|
13738
13914
|
}
|
|
13739
|
-
const base =
|
|
13915
|
+
const base = join8(libDir, libName);
|
|
13740
13916
|
if (existsSync5(base)) {
|
|
13741
13917
|
try {
|
|
13742
13918
|
const real = realpathSync(base);
|
|
@@ -13772,7 +13948,7 @@ function pathEntriesForPlatform() {
|
|
|
13772
13948
|
return pathEnvValue().split(delimiter2).map((entry) => entry.trim().replace(/^"|"$/g, "")).filter((entry) => {
|
|
13773
13949
|
if (!entry || entry === "." || entry.includes("\x00"))
|
|
13774
13950
|
return false;
|
|
13775
|
-
return
|
|
13951
|
+
return isAbsolute3(entry) || win32.isAbsolute(entry);
|
|
13776
13952
|
});
|
|
13777
13953
|
}
|
|
13778
13954
|
function directoryContainsLibrary(dir, libName) {
|
|
@@ -13788,10 +13964,10 @@ function directoryContainsLibrary(dir, libName) {
|
|
|
13788
13964
|
}
|
|
13789
13965
|
}
|
|
13790
13966
|
function resolveCachedOnnxRuntimeDir(ortVersionDir, libName) {
|
|
13791
|
-
if (existsSync5(
|
|
13967
|
+
if (existsSync5(join8(ortVersionDir, libName)))
|
|
13792
13968
|
return ortVersionDir;
|
|
13793
|
-
const libSubdir =
|
|
13794
|
-
if (existsSync5(
|
|
13969
|
+
const libSubdir = join8(ortVersionDir, "lib");
|
|
13970
|
+
if (existsSync5(join8(libSubdir, libName)))
|
|
13795
13971
|
return libSubdir;
|
|
13796
13972
|
return ortVersionDir;
|
|
13797
13973
|
}
|
|
@@ -13806,12 +13982,12 @@ function findSystemOnnxRuntime(libName) {
|
|
|
13806
13982
|
} else if (process.platform === "win32") {
|
|
13807
13983
|
const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
|
|
13808
13984
|
const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
|
|
13809
|
-
searchPaths.push(
|
|
13985
|
+
searchPaths.push(join8(programFiles, "onnxruntime", "lib"), join8(programFiles, "Microsoft ONNX Runtime", "lib"), join8(programFiles, "Microsoft Machine Learning", "lib"), join8(programFilesX86, "onnxruntime", "lib"), ...(() => {
|
|
13810
13986
|
const nugetPaths = [];
|
|
13811
13987
|
const userProfile = process.env.USERPROFILE ?? "";
|
|
13812
13988
|
if (!userProfile)
|
|
13813
13989
|
return nugetPaths;
|
|
13814
|
-
const nugetPackageDir =
|
|
13990
|
+
const nugetPackageDir = join8(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
|
|
13815
13991
|
if (!existsSync5(nugetPackageDir))
|
|
13816
13992
|
return nugetPaths;
|
|
13817
13993
|
try {
|
|
@@ -13820,7 +13996,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
13820
13996
|
continue;
|
|
13821
13997
|
if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
|
|
13822
13998
|
continue;
|
|
13823
|
-
nugetPaths.push(
|
|
13999
|
+
nugetPaths.push(join8(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join8(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
|
|
13824
14000
|
}
|
|
13825
14001
|
} catch (err) {
|
|
13826
14002
|
warn(`Failed to scan NuGet ONNX Runtime cache ${nugetPackageDir}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -13832,7 +14008,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
13832
14008
|
const normalizeCase = process.platform === "win32" || process.platform === "darwin";
|
|
13833
14009
|
const seen = new Set;
|
|
13834
14010
|
const uniquePaths = searchPaths.filter((p) => {
|
|
13835
|
-
let key =
|
|
14011
|
+
let key = resolve2(p).replace(/[/\\]+$/, "");
|
|
13836
14012
|
if (normalizeCase)
|
|
13837
14013
|
key = key.toLowerCase();
|
|
13838
14014
|
if (seen.has(key))
|
|
@@ -13842,7 +14018,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
13842
14018
|
});
|
|
13843
14019
|
const unknownVersionPaths = [];
|
|
13844
14020
|
for (const dir of uniquePaths) {
|
|
13845
|
-
const libPath =
|
|
14021
|
+
const libPath = join8(dir, libName);
|
|
13846
14022
|
if (process.platform === "win32") {
|
|
13847
14023
|
if (!directoryContainsLibrary(dir, libName))
|
|
13848
14024
|
continue;
|
|
@@ -13908,19 +14084,19 @@ function validateExtractedTree(stagingRoot) {
|
|
|
13908
14084
|
const walk = (dir) => {
|
|
13909
14085
|
const entries = readdirSync2(dir);
|
|
13910
14086
|
for (const entry of entries) {
|
|
13911
|
-
const fullPath =
|
|
14087
|
+
const fullPath = join8(dir, entry);
|
|
13912
14088
|
const lst = lstatSync(fullPath);
|
|
13913
14089
|
if (lst.isSymbolicLink()) {
|
|
13914
14090
|
const linkTarget = readlinkSync(fullPath);
|
|
13915
|
-
const resolvedTarget =
|
|
13916
|
-
const rel2 =
|
|
13917
|
-
if (rel2.startsWith("..") ||
|
|
14091
|
+
const resolvedTarget = resolve2(dirname4(fullPath), linkTarget);
|
|
14092
|
+
const rel2 = relative2(realRoot, resolvedTarget);
|
|
14093
|
+
if (rel2.startsWith("..") || isAbsolute3(rel2) || win32.isAbsolute(rel2)) {
|
|
13918
14094
|
throw new Error(`extracted symlink ${fullPath} points outside staging root: ${linkTarget}`);
|
|
13919
14095
|
}
|
|
13920
14096
|
continue;
|
|
13921
14097
|
}
|
|
13922
|
-
const rel =
|
|
13923
|
-
if (rel.startsWith("..") ||
|
|
14098
|
+
const rel = relative2(realRoot, fullPath);
|
|
14099
|
+
if (rel.startsWith("..") || isAbsolute3(rel) || win32.isAbsolute(rel)) {
|
|
13924
14100
|
throw new Error(`extracted entry ${fullPath} escapes staging root`);
|
|
13925
14101
|
}
|
|
13926
14102
|
if (lst.isDirectory()) {
|
|
@@ -13943,7 +14119,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
13943
14119
|
const tmpDir = `${targetDir}.tmp.${process.pid}.${Date.now().toString(36)}`;
|
|
13944
14120
|
try {
|
|
13945
14121
|
mkdirSync5(tmpDir, { recursive: true });
|
|
13946
|
-
const archivePath =
|
|
14122
|
+
const archivePath = join8(tmpDir, `onnxruntime.${info.archiveType}`);
|
|
13947
14123
|
await downloadFileWithCap(url, archivePath);
|
|
13948
14124
|
const archiveSha256 = sha256File(archivePath);
|
|
13949
14125
|
log(`ONNX Runtime archive sha256=${archiveSha256}`);
|
|
@@ -13959,7 +14135,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
13959
14135
|
unlinkSync3(archivePath);
|
|
13960
14136
|
} catch {}
|
|
13961
14137
|
validateExtractedTree(tmpDir);
|
|
13962
|
-
const extractedDir =
|
|
14138
|
+
const extractedDir = join8(tmpDir, info.assetName, "lib");
|
|
13963
14139
|
if (!existsSync5(extractedDir)) {
|
|
13964
14140
|
throw new Error(`Expected directory not found: ${extractedDir}`);
|
|
13965
14141
|
}
|
|
@@ -13968,7 +14144,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
13968
14144
|
const realFiles = [];
|
|
13969
14145
|
const symlinks = [];
|
|
13970
14146
|
for (const libFile of libFiles) {
|
|
13971
|
-
const src =
|
|
14147
|
+
const src = join8(extractedDir, libFile);
|
|
13972
14148
|
try {
|
|
13973
14149
|
const stat = lstatSync(src);
|
|
13974
14150
|
log(`ORT extract: ${libFile} — isSymlink=${stat.isSymbolicLink()}, isFile=${stat.isFile()}, size=${stat.size}`);
|
|
@@ -13983,7 +14159,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
13983
14159
|
}
|
|
13984
14160
|
}
|
|
13985
14161
|
copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks);
|
|
13986
|
-
const libPath =
|
|
14162
|
+
const libPath = join8(targetDir, info.libName);
|
|
13987
14163
|
let libHash = null;
|
|
13988
14164
|
try {
|
|
13989
14165
|
libHash = sha256File(libPath);
|
|
@@ -14008,8 +14184,8 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
14008
14184
|
function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, copyFile = copyFileSync3) {
|
|
14009
14185
|
const requiredLibs = new Set([info.libName]);
|
|
14010
14186
|
for (const libFile of realFiles) {
|
|
14011
|
-
const src =
|
|
14012
|
-
const dst =
|
|
14187
|
+
const src = join8(extractedDir, libFile);
|
|
14188
|
+
const dst = join8(targetDir, libFile);
|
|
14013
14189
|
try {
|
|
14014
14190
|
copyFile(src, dst);
|
|
14015
14191
|
if (process.platform !== "win32") {
|
|
@@ -14025,12 +14201,12 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
14025
14201
|
}
|
|
14026
14202
|
const targetRoot = realpathSync(targetDir);
|
|
14027
14203
|
for (const link of symlinks) {
|
|
14028
|
-
const dst =
|
|
14204
|
+
const dst = join8(targetDir, link.name);
|
|
14029
14205
|
try {
|
|
14030
14206
|
unlinkSync3(dst);
|
|
14031
14207
|
} catch {}
|
|
14032
|
-
const dstForContainment =
|
|
14033
|
-
const resolvedTarget =
|
|
14208
|
+
const dstForContainment = join8(targetRoot, link.name);
|
|
14209
|
+
const resolvedTarget = resolve2(dirname4(dstForContainment), link.target);
|
|
14034
14210
|
if (!isPathInsideRoot(targetRoot, resolvedTarget)) {
|
|
14035
14211
|
const message = `ONNX Runtime symlink ${link.name} points outside install dir: ${link.target}`;
|
|
14036
14212
|
if (requiredLibs.has(link.name)) {
|
|
@@ -14050,7 +14226,7 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
14050
14226
|
log(`ORT extract: failed to symlink optional ${link.name}: ${symlinkErr}`);
|
|
14051
14227
|
}
|
|
14052
14228
|
}
|
|
14053
|
-
const requiredPath =
|
|
14229
|
+
const requiredPath = join8(targetDir, info.libName);
|
|
14054
14230
|
if (!existsSync5(requiredPath)) {
|
|
14055
14231
|
rmSync2(targetDir, { recursive: true, force: true });
|
|
14056
14232
|
throw new Error(`Required ONNX Runtime library missing after install: ${requiredPath}`);
|
|
@@ -14077,17 +14253,17 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
|
|
|
14077
14253
|
...sha256 ? { sha256 } : {},
|
|
14078
14254
|
archiveSha256
|
|
14079
14255
|
};
|
|
14080
|
-
writeFileSync2(
|
|
14256
|
+
writeFileSync2(join8(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
|
|
14081
14257
|
} catch (err) {
|
|
14082
14258
|
log(`[onnx] failed to write installed-meta in ${installDir}: ${err}`);
|
|
14083
14259
|
}
|
|
14084
14260
|
}
|
|
14085
14261
|
function readOnnxInstalledMeta(installDir) {
|
|
14086
|
-
const
|
|
14262
|
+
const path2 = join8(installDir, ONNX_INSTALLED_META_FILE);
|
|
14087
14263
|
try {
|
|
14088
|
-
if (!statSync3(
|
|
14264
|
+
if (!statSync3(path2).isFile())
|
|
14089
14265
|
return null;
|
|
14090
|
-
const raw = readFileSync3(
|
|
14266
|
+
const raw = readFileSync3(path2, "utf8");
|
|
14091
14267
|
const parsed = JSON.parse(raw);
|
|
14092
14268
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
14093
14269
|
return null;
|
|
@@ -14101,9 +14277,9 @@ function readOnnxInstalledMeta(installDir) {
|
|
|
14101
14277
|
return null;
|
|
14102
14278
|
}
|
|
14103
14279
|
}
|
|
14104
|
-
function sha256File(
|
|
14280
|
+
function sha256File(path2) {
|
|
14105
14281
|
const hash = createHash2("sha256");
|
|
14106
|
-
hash.update(readFileSync3(
|
|
14282
|
+
hash.update(readFileSync3(path2));
|
|
14107
14283
|
return hash.digest("hex");
|
|
14108
14284
|
}
|
|
14109
14285
|
function acquireLock(lockPath) {
|
|
@@ -14939,6 +15115,91 @@ function normalizeKey(projectRoot) {
|
|
|
14939
15115
|
return stripped;
|
|
14940
15116
|
}
|
|
14941
15117
|
}
|
|
15118
|
+
// ../aft-bridge/dist/tool-format.js
|
|
15119
|
+
function asPlainObject(value) {
|
|
15120
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
15121
|
+
return;
|
|
15122
|
+
return value;
|
|
15123
|
+
}
|
|
15124
|
+
function candidateLocation(candidate) {
|
|
15125
|
+
const file = typeof candidate.file === "string" && candidate.file.length > 0 ? candidate.file : undefined;
|
|
15126
|
+
if (!file)
|
|
15127
|
+
return;
|
|
15128
|
+
const line = typeof candidate.line === "number" && Number.isFinite(candidate.line) ? candidate.line : undefined;
|
|
15129
|
+
return line === undefined ? file : `${file}:${line}`;
|
|
15130
|
+
}
|
|
15131
|
+
function stringifyData(data) {
|
|
15132
|
+
if (data === undefined)
|
|
15133
|
+
return;
|
|
15134
|
+
try {
|
|
15135
|
+
return JSON.stringify(data, null, 2);
|
|
15136
|
+
} catch {
|
|
15137
|
+
return String(data);
|
|
15138
|
+
}
|
|
15139
|
+
}
|
|
15140
|
+
function formatBridgeErrorMessage(command, response, params = {}) {
|
|
15141
|
+
const code = typeof response.code === "string" && response.code.length > 0 ? response.code : undefined;
|
|
15142
|
+
const message = typeof response.message === "string" && response.message.length > 0 ? response.message : `${command} failed`;
|
|
15143
|
+
const data = asPlainObject(response.data);
|
|
15144
|
+
const rawCandidates = Array.isArray(response.candidates) ? response.candidates : Array.isArray(data?.candidates) ? data.candidates : undefined;
|
|
15145
|
+
const rawSymbol = typeof response.symbol === "string" && response.symbol.length > 0 ? response.symbol : typeof data?.symbol === "string" && data.symbol.length > 0 ? data.symbol : undefined;
|
|
15146
|
+
if (code === "ambiguous_target" || code === "target_symbol_not_in_file") {
|
|
15147
|
+
const candidates = (rawCandidates ?? []).map(asPlainObject).filter((candidate) => candidate !== undefined).map(candidateLocation).filter((candidate) => candidate !== undefined);
|
|
15148
|
+
if (candidates.length > 0) {
|
|
15149
|
+
const symbol = typeof params.toSymbol === "string" && params.toSymbol.length > 0 ? params.toSymbol : rawSymbol;
|
|
15150
|
+
const target = symbol ? `multiple symbols named "${symbol}"` : message.replace(/[.!?]+$/, "");
|
|
15151
|
+
const action = code === "ambiguous_target" ? "Pass toFile to disambiguate" : "Try one of these files for toFile";
|
|
15152
|
+
return `${command}: ${code} — ${target}. ${action}:
|
|
15153
|
+
${candidates.map((candidate) => ` - ${candidate}`).join(`
|
|
15154
|
+
`)}`;
|
|
15155
|
+
}
|
|
15156
|
+
}
|
|
15157
|
+
if (!code)
|
|
15158
|
+
return message;
|
|
15159
|
+
const lines = [`${command}: ${code} — ${message}`];
|
|
15160
|
+
const extras = collectStructuredExtras(response);
|
|
15161
|
+
if (extras)
|
|
15162
|
+
lines.push(`data: ${extras}`);
|
|
15163
|
+
return lines.join(`
|
|
15164
|
+
`);
|
|
15165
|
+
}
|
|
15166
|
+
function collectStructuredExtras(response) {
|
|
15167
|
+
const reserved = new Set([
|
|
15168
|
+
"id",
|
|
15169
|
+
"success",
|
|
15170
|
+
"code",
|
|
15171
|
+
"message",
|
|
15172
|
+
"data",
|
|
15173
|
+
"status_bar",
|
|
15174
|
+
"bg_completions"
|
|
15175
|
+
]);
|
|
15176
|
+
const extras = {};
|
|
15177
|
+
for (const [key, value] of Object.entries(response)) {
|
|
15178
|
+
if (reserved.has(key))
|
|
15179
|
+
continue;
|
|
15180
|
+
extras[key] = value;
|
|
15181
|
+
}
|
|
15182
|
+
if (Object.keys(extras).length === 0) {
|
|
15183
|
+
return stringifyData(response.data);
|
|
15184
|
+
}
|
|
15185
|
+
if (response.data !== undefined)
|
|
15186
|
+
extras.data = response.data;
|
|
15187
|
+
return stringifyData(extras);
|
|
15188
|
+
}
|
|
15189
|
+
function formatReadFooter(agentSpecifiedRange, data, options) {
|
|
15190
|
+
if (agentSpecifiedRange)
|
|
15191
|
+
return "";
|
|
15192
|
+
if (!data.truncated)
|
|
15193
|
+
return "";
|
|
15194
|
+
const startLine = data.start_line;
|
|
15195
|
+
const endLine = data.end_line;
|
|
15196
|
+
const totalLines = data.total_lines;
|
|
15197
|
+
if (startLine === undefined || endLine === undefined || totalLines === undefined) {
|
|
15198
|
+
return "";
|
|
15199
|
+
}
|
|
15200
|
+
return `
|
|
15201
|
+
(Showing lines ${startLine}-${endLine} of ${totalLines}. Use ${options.rangeHint} to read other sections.)`;
|
|
15202
|
+
}
|
|
14942
15203
|
// ../aft-bridge/dist/zoom-format.js
|
|
14943
15204
|
function formatZoomText(targetLabel, response) {
|
|
14944
15205
|
const range = response.range;
|
|
@@ -15019,16 +15280,39 @@ function formatZoomMultiTargetResult(entries) {
|
|
|
15019
15280
|
|
|
15020
15281
|
`) };
|
|
15021
15282
|
}
|
|
15283
|
+
function isRustZoomBatchEnvelope(response) {
|
|
15284
|
+
if (!Array.isArray(response.symbols) || response.symbols.length === 0) {
|
|
15285
|
+
return false;
|
|
15286
|
+
}
|
|
15287
|
+
return response.symbols.every((entry) => {
|
|
15288
|
+
if (!entry || typeof entry !== "object")
|
|
15289
|
+
return false;
|
|
15290
|
+
const row = entry;
|
|
15291
|
+
return typeof row.name === "string" && row.response !== undefined && row.response !== null;
|
|
15292
|
+
});
|
|
15293
|
+
}
|
|
15294
|
+
function unwrapRustZoomBatchEnvelope(response) {
|
|
15295
|
+
if (!isRustZoomBatchEnvelope(response)) {
|
|
15296
|
+
return null;
|
|
15297
|
+
}
|
|
15298
|
+
const names = [];
|
|
15299
|
+
const responses = [];
|
|
15300
|
+
for (const entry of response.symbols) {
|
|
15301
|
+
names.push(entry.name);
|
|
15302
|
+
responses.push(entry.response);
|
|
15303
|
+
}
|
|
15304
|
+
return { names, responses };
|
|
15305
|
+
}
|
|
15022
15306
|
// src/bg-notifications.ts
|
|
15023
15307
|
import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypto";
|
|
15024
15308
|
|
|
15025
15309
|
// src/logger.ts
|
|
15026
15310
|
import * as fs from "node:fs";
|
|
15027
|
-
import * as
|
|
15028
|
-
import * as
|
|
15311
|
+
import * as os2 from "node:os";
|
|
15312
|
+
import * as path2 from "node:path";
|
|
15029
15313
|
var TAG = "[aft-plugin]";
|
|
15030
15314
|
var isTestEnv = process.env.BUN_TEST === "1" || false;
|
|
15031
|
-
var logFile =
|
|
15315
|
+
var logFile = path2.join(os2.tmpdir(), isTestEnv ? "aft-plugin-test.log" : "aft-plugin.log");
|
|
15032
15316
|
var useStderr = process.env.AFT_LOG_STDERR === "1";
|
|
15033
15317
|
var buffer = [];
|
|
15034
15318
|
var flushTimer = null;
|
|
@@ -15972,8 +16256,8 @@ function formatDuration(completion) {
|
|
|
15972
16256
|
|
|
15973
16257
|
// src/config.ts
|
|
15974
16258
|
import { existsSync as existsSync6, readFileSync as readFileSync4, renameSync as renameSync4, unlinkSync as unlinkSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
15975
|
-
import { homedir as
|
|
15976
|
-
import { join as
|
|
16259
|
+
import { homedir as homedir7 } from "node:os";
|
|
16260
|
+
import { join as join10 } from "node:path";
|
|
15977
16261
|
var import_comment_json = __toESM(require_src2(), 1);
|
|
15978
16262
|
|
|
15979
16263
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
|
|
@@ -16741,10 +17025,10 @@ function mergeDefs(...defs) {
|
|
|
16741
17025
|
function cloneDef(schema) {
|
|
16742
17026
|
return mergeDefs(schema._zod.def);
|
|
16743
17027
|
}
|
|
16744
|
-
function getElementAtPath(obj,
|
|
16745
|
-
if (!
|
|
17028
|
+
function getElementAtPath(obj, path3) {
|
|
17029
|
+
if (!path3)
|
|
16746
17030
|
return obj;
|
|
16747
|
-
return
|
|
17031
|
+
return path3.reduce((acc, key) => acc?.[key], obj);
|
|
16748
17032
|
}
|
|
16749
17033
|
function promiseAllObject(promisesObj) {
|
|
16750
17034
|
const keys = Object.keys(promisesObj);
|
|
@@ -17125,11 +17409,11 @@ function aborted(x, startIndex = 0) {
|
|
|
17125
17409
|
}
|
|
17126
17410
|
return false;
|
|
17127
17411
|
}
|
|
17128
|
-
function prefixIssues(
|
|
17412
|
+
function prefixIssues(path3, issues) {
|
|
17129
17413
|
return issues.map((iss) => {
|
|
17130
17414
|
var _a;
|
|
17131
17415
|
(_a = iss).path ?? (_a.path = []);
|
|
17132
|
-
iss.path.unshift(
|
|
17416
|
+
iss.path.unshift(path3);
|
|
17133
17417
|
return iss;
|
|
17134
17418
|
});
|
|
17135
17419
|
}
|
|
@@ -17312,7 +17596,7 @@ function formatError(error3, mapper = (issue2) => issue2.message) {
|
|
|
17312
17596
|
}
|
|
17313
17597
|
function treeifyError(error3, mapper = (issue2) => issue2.message) {
|
|
17314
17598
|
const result = { errors: [] };
|
|
17315
|
-
const processError = (error4,
|
|
17599
|
+
const processError = (error4, path3 = []) => {
|
|
17316
17600
|
var _a, _b;
|
|
17317
17601
|
for (const issue2 of error4.issues) {
|
|
17318
17602
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -17322,7 +17606,7 @@ function treeifyError(error3, mapper = (issue2) => issue2.message) {
|
|
|
17322
17606
|
} else if (issue2.code === "invalid_element") {
|
|
17323
17607
|
processError({ issues: issue2.issues }, issue2.path);
|
|
17324
17608
|
} else {
|
|
17325
|
-
const fullpath = [...
|
|
17609
|
+
const fullpath = [...path3, ...issue2.path];
|
|
17326
17610
|
if (fullpath.length === 0) {
|
|
17327
17611
|
result.errors.push(mapper(issue2));
|
|
17328
17612
|
continue;
|
|
@@ -17354,8 +17638,8 @@ function treeifyError(error3, mapper = (issue2) => issue2.message) {
|
|
|
17354
17638
|
}
|
|
17355
17639
|
function toDotPath(_path) {
|
|
17356
17640
|
const segs = [];
|
|
17357
|
-
const
|
|
17358
|
-
for (const seg of
|
|
17641
|
+
const path3 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
17642
|
+
for (const seg of path3) {
|
|
17359
17643
|
if (typeof seg === "number")
|
|
17360
17644
|
segs.push(`[${seg}]`);
|
|
17361
17645
|
else if (typeof seg === "symbol")
|
|
@@ -29102,13 +29386,13 @@ function resolveRef(ref, ctx) {
|
|
|
29102
29386
|
if (!ref.startsWith("#")) {
|
|
29103
29387
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
29104
29388
|
}
|
|
29105
|
-
const
|
|
29106
|
-
if (
|
|
29389
|
+
const path3 = ref.slice(1).split("/").filter(Boolean);
|
|
29390
|
+
if (path3.length === 0) {
|
|
29107
29391
|
return ctx.rootSchema;
|
|
29108
29392
|
}
|
|
29109
29393
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
29110
|
-
if (
|
|
29111
|
-
const key =
|
|
29394
|
+
if (path3[0] === defsKey) {
|
|
29395
|
+
const key = path3[1];
|
|
29112
29396
|
if (!key || !ctx.defs[key]) {
|
|
29113
29397
|
throw new Error(`Reference not found: ${ref}`);
|
|
29114
29398
|
}
|
|
@@ -29806,9 +30090,9 @@ function extractCommentsForPreservation(content) {
|
|
|
29806
30090
|
}
|
|
29807
30091
|
return comments;
|
|
29808
30092
|
}
|
|
29809
|
-
function ensureRecordAtPath(root,
|
|
30093
|
+
function ensureRecordAtPath(root, path3) {
|
|
29810
30094
|
let current = root;
|
|
29811
|
-
for (const segment of
|
|
30095
|
+
for (const segment of path3) {
|
|
29812
30096
|
const existing = current[segment];
|
|
29813
30097
|
if (!existing || typeof existing !== "object" || Array.isArray(existing)) {
|
|
29814
30098
|
current[segment] = {};
|
|
@@ -29817,9 +30101,9 @@ function ensureRecordAtPath(root, path2) {
|
|
|
29817
30101
|
}
|
|
29818
30102
|
return current;
|
|
29819
30103
|
}
|
|
29820
|
-
function hasPath(root,
|
|
30104
|
+
function hasPath(root, path3) {
|
|
29821
30105
|
let current = root;
|
|
29822
|
-
for (const segment of
|
|
30106
|
+
for (const segment of path3) {
|
|
29823
30107
|
if (!current || typeof current !== "object" || Array.isArray(current))
|
|
29824
30108
|
return false;
|
|
29825
30109
|
const record2 = current;
|
|
@@ -29829,9 +30113,9 @@ function hasPath(root, path2) {
|
|
|
29829
30113
|
}
|
|
29830
30114
|
return true;
|
|
29831
30115
|
}
|
|
29832
|
-
function setPath(root,
|
|
29833
|
-
const parent = ensureRecordAtPath(root,
|
|
29834
|
-
parent[
|
|
30116
|
+
function setPath(root, path3, value) {
|
|
30117
|
+
const parent = ensureRecordAtPath(root, path3.slice(0, -1));
|
|
30118
|
+
parent[path3[path3.length - 1]] = value;
|
|
29835
30119
|
}
|
|
29836
30120
|
function migrateRawConfig(rawConfig, configPath, logger) {
|
|
29837
30121
|
const oldKeys = [];
|
|
@@ -30168,17 +30452,17 @@ function getOpenCodeConfigDir() {
|
|
|
30168
30452
|
if (envDir) {
|
|
30169
30453
|
return envDir;
|
|
30170
30454
|
}
|
|
30171
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME ||
|
|
30172
|
-
return
|
|
30455
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME || join10(homedir7(), ".config");
|
|
30456
|
+
return join10(xdgConfig, "opencode");
|
|
30173
30457
|
}
|
|
30174
30458
|
function loadAftConfig(projectDirectory) {
|
|
30175
30459
|
const configDir = getOpenCodeConfigDir();
|
|
30176
|
-
const userBasePath =
|
|
30460
|
+
const userBasePath = join10(configDir, "aft");
|
|
30177
30461
|
migrateAftConfigFile(`${userBasePath}.jsonc`);
|
|
30178
30462
|
migrateAftConfigFile(`${userBasePath}.json`);
|
|
30179
30463
|
const userDetected = detectConfigFile(userBasePath);
|
|
30180
30464
|
const userConfigPath = userDetected.format !== "none" ? userDetected.path : `${userBasePath}.json`;
|
|
30181
|
-
const projectBasePath =
|
|
30465
|
+
const projectBasePath = join10(projectDirectory, ".opencode", "aft");
|
|
30182
30466
|
migrateAftConfigFile(`${projectBasePath}.jsonc`);
|
|
30183
30467
|
migrateAftConfigFile(`${projectBasePath}.json`);
|
|
30184
30468
|
const projectDetected = detectConfigFile(projectBasePath);
|
|
@@ -30204,8 +30488,8 @@ function loadAftConfig(projectDirectory) {
|
|
|
30204
30488
|
|
|
30205
30489
|
// src/notifications.ts
|
|
30206
30490
|
import { existsSync as existsSync7, readFileSync as readFileSync5 } from "node:fs";
|
|
30207
|
-
import { homedir as
|
|
30208
|
-
import { join as
|
|
30491
|
+
import { homedir as homedir8, platform } from "node:os";
|
|
30492
|
+
import { join as join11 } from "node:path";
|
|
30209
30493
|
function isTuiMode() {
|
|
30210
30494
|
return process.env.OPENCODE_CLIENT === "cli";
|
|
30211
30495
|
}
|
|
@@ -30225,18 +30509,18 @@ var FEATURE_MARKER = `${AFT_MARKER} New in`;
|
|
|
30225
30509
|
var WARNING_MARKER = `${AFT_MARKER} ⚠️`;
|
|
30226
30510
|
var STATUS_MARKER = `${AFT_MARKER} ✅`;
|
|
30227
30511
|
function getDesktopStatePath() {
|
|
30228
|
-
const
|
|
30229
|
-
const home =
|
|
30230
|
-
if (
|
|
30231
|
-
return
|
|
30512
|
+
const os3 = platform();
|
|
30513
|
+
const home = homedir8();
|
|
30514
|
+
if (os3 === "darwin") {
|
|
30515
|
+
return join11(home, "Library", "Application Support", "ai.opencode.desktop", "opencode.global.dat");
|
|
30232
30516
|
}
|
|
30233
|
-
if (
|
|
30234
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME ||
|
|
30235
|
-
return
|
|
30517
|
+
if (os3 === "linux") {
|
|
30518
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME || join11(home, ".config");
|
|
30519
|
+
return join11(xdgConfig, "ai.opencode.desktop", "opencode.global.dat");
|
|
30236
30520
|
}
|
|
30237
|
-
if (
|
|
30238
|
-
const appData = process.env.APPDATA ||
|
|
30239
|
-
return
|
|
30521
|
+
if (os3 === "win32") {
|
|
30522
|
+
const appData = process.env.APPDATA || join11(home, "AppData", "Roaming");
|
|
30523
|
+
return join11(appData, "ai.opencode.desktop", "opencode.global.dat");
|
|
30240
30524
|
}
|
|
30241
30525
|
return null;
|
|
30242
30526
|
}
|
|
@@ -30706,37 +30990,37 @@ import { dirname as dirname7 } from "node:path";
|
|
|
30706
30990
|
import { spawn as spawn2 } from "node:child_process";
|
|
30707
30991
|
import { cpSync, existsSync as existsSync9, mkdtempSync, readFileSync as readFileSync7, rmSync as rmSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
30708
30992
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
30709
|
-
import { basename as basename2, dirname as dirname6, join as
|
|
30993
|
+
import { basename as basename2, dirname as dirname6, join as join14 } from "node:path";
|
|
30710
30994
|
var import_comment_json3 = __toESM(require_src2(), 1);
|
|
30711
30995
|
|
|
30712
30996
|
// src/hooks/auto-update-checker/checker.ts
|
|
30713
30997
|
var import_comment_json2 = __toESM(require_src2(), 1);
|
|
30714
30998
|
import { existsSync as existsSync8, readFileSync as readFileSync6, statSync as statSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
30715
|
-
import { homedir as
|
|
30716
|
-
import { dirname as dirname5, isAbsolute as
|
|
30999
|
+
import { homedir as homedir10 } from "node:os";
|
|
31000
|
+
import { dirname as dirname5, isAbsolute as isAbsolute4, join as join13, resolve as resolve3 } from "node:path";
|
|
30717
31001
|
import { fileURLToPath } from "node:url";
|
|
30718
31002
|
|
|
30719
31003
|
// src/hooks/auto-update-checker/constants.ts
|
|
30720
|
-
import { homedir as
|
|
30721
|
-
import { join as
|
|
31004
|
+
import { homedir as homedir9, platform as platform2 } from "node:os";
|
|
31005
|
+
import { join as join12 } from "node:path";
|
|
30722
31006
|
var PACKAGE_NAME = "@cortexkit/aft-opencode";
|
|
30723
31007
|
var NPM_REGISTRY_URL = "https://registry.npmjs.org";
|
|
30724
31008
|
var NPM_FETCH_TIMEOUT = 1e4;
|
|
30725
31009
|
function getOpenCodeCacheRoot() {
|
|
30726
31010
|
if (platform2() === "win32") {
|
|
30727
|
-
return
|
|
31011
|
+
return join12(process.env.LOCALAPPDATA ?? homedir9(), "opencode");
|
|
30728
31012
|
}
|
|
30729
|
-
return
|
|
31013
|
+
return join12(homedir9(), ".cache", "opencode");
|
|
30730
31014
|
}
|
|
30731
31015
|
function getOpenCodeConfigRoot() {
|
|
30732
31016
|
if (platform2() === "win32") {
|
|
30733
|
-
return
|
|
31017
|
+
return join12(process.env.APPDATA ?? join12(homedir9(), "AppData", "Roaming"), "opencode");
|
|
30734
31018
|
}
|
|
30735
|
-
return
|
|
31019
|
+
return join12(process.env.XDG_CONFIG_HOME ?? join12(homedir9(), ".config"), "opencode");
|
|
30736
31020
|
}
|
|
30737
|
-
var CACHE_DIR =
|
|
30738
|
-
var USER_OPENCODE_CONFIG =
|
|
30739
|
-
var USER_OPENCODE_CONFIG_JSONC =
|
|
31021
|
+
var CACHE_DIR = join12(getOpenCodeCacheRoot(), "packages");
|
|
31022
|
+
var USER_OPENCODE_CONFIG = join12(getOpenCodeConfigRoot(), "opencode.json");
|
|
31023
|
+
var USER_OPENCODE_CONFIG_JSONC = join12(getOpenCodeConfigRoot(), "opencode.jsonc");
|
|
30740
31024
|
|
|
30741
31025
|
// src/hooks/auto-update-checker/types.ts
|
|
30742
31026
|
var NpmPackageEnvelopeSchema = exports_external.object({
|
|
@@ -30794,8 +31078,8 @@ function extractChannel(version2) {
|
|
|
30794
31078
|
}
|
|
30795
31079
|
function getConfigPaths(directory) {
|
|
30796
31080
|
return [
|
|
30797
|
-
|
|
30798
|
-
|
|
31081
|
+
join13(directory, ".opencode", "opencode.json"),
|
|
31082
|
+
join13(directory, ".opencode", "opencode.jsonc"),
|
|
30799
31083
|
USER_OPENCODE_CONFIG,
|
|
30800
31084
|
USER_OPENCODE_CONFIG_JSONC
|
|
30801
31085
|
];
|
|
@@ -30808,9 +31092,9 @@ function resolvePathPluginSpec(spec, configPath) {
|
|
|
30808
31092
|
return spec.replace(/^file:\/\//, "");
|
|
30809
31093
|
}
|
|
30810
31094
|
}
|
|
30811
|
-
if (
|
|
31095
|
+
if (isAbsolute4(spec) || /^[A-Za-z]:[\\/]/.test(spec))
|
|
30812
31096
|
return spec;
|
|
30813
|
-
return
|
|
31097
|
+
return resolve3(dirname5(configPath), spec);
|
|
30814
31098
|
}
|
|
30815
31099
|
function getLocalDevPath(directory) {
|
|
30816
31100
|
for (const configPath of getConfigPaths(directory)) {
|
|
@@ -30822,7 +31106,7 @@ function getLocalDevPath(directory) {
|
|
|
30822
31106
|
for (const entry of plugins) {
|
|
30823
31107
|
if (entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`))
|
|
30824
31108
|
continue;
|
|
30825
|
-
if (entry.startsWith("file://") || entry.startsWith(".") ||
|
|
31109
|
+
if (entry.startsWith("file://") || entry.startsWith(".") || isAbsolute4(entry)) {
|
|
30826
31110
|
const localPath = resolvePathPluginSpec(entry, configPath);
|
|
30827
31111
|
const pkgPath = findPackageJsonUp(localPath);
|
|
30828
31112
|
if (!pkgPath)
|
|
@@ -30841,7 +31125,7 @@ function findPackageJsonUp(startPath) {
|
|
|
30841
31125
|
const stat = statSync4(startPath);
|
|
30842
31126
|
let dir = stat.isDirectory() ? startPath : dirname5(startPath);
|
|
30843
31127
|
for (let i = 0;i < 10; i++) {
|
|
30844
|
-
const pkgPath =
|
|
31128
|
+
const pkgPath = join13(dir, "package.json");
|
|
30845
31129
|
if (existsSync8(pkgPath)) {
|
|
30846
31130
|
try {
|
|
30847
31131
|
const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync6(pkgPath, "utf-8")));
|
|
@@ -30902,7 +31186,7 @@ function findPluginEntry(directory) {
|
|
|
30902
31186
|
}
|
|
30903
31187
|
var cachedPackageVersion = null;
|
|
30904
31188
|
function getSpecCachePackageJsonPath(spec) {
|
|
30905
|
-
return
|
|
31189
|
+
return join13(CACHE_DIR, spec, "node_modules", PACKAGE_NAME, "package.json");
|
|
30906
31190
|
}
|
|
30907
31191
|
function getCachedVersion(spec) {
|
|
30908
31192
|
if (!spec && cachedPackageVersion)
|
|
@@ -30911,7 +31195,7 @@ function getCachedVersion(spec) {
|
|
|
30911
31195
|
getCurrentRuntimePackageJsonPath(),
|
|
30912
31196
|
spec ? getSpecCachePackageJsonPath(spec) : null,
|
|
30913
31197
|
getSpecCachePackageJsonPath(`${PACKAGE_NAME}@latest`),
|
|
30914
|
-
|
|
31198
|
+
join13(homedir10(), ".cache", "opencode", "node_modules", PACKAGE_NAME, "package.json")
|
|
30915
31199
|
].filter(isString);
|
|
30916
31200
|
for (const packageJsonPath of candidates) {
|
|
30917
31201
|
try {
|
|
@@ -30959,10 +31243,10 @@ async function getLatestVersion(channel = "latest", options = {}) {
|
|
|
30959
31243
|
// src/hooks/auto-update-checker/cache.ts
|
|
30960
31244
|
var pendingSnapshots = new Map;
|
|
30961
31245
|
function createAutoUpdateSnapshot(installDir, packageJsonPath, packageName) {
|
|
30962
|
-
const packageDir =
|
|
30963
|
-
const lockfilePath =
|
|
30964
|
-
const tempDir = mkdtempSync(
|
|
30965
|
-
const stagedPackageDir = existsSync9(packageDir) ?
|
|
31246
|
+
const packageDir = join14(installDir, "node_modules", packageName);
|
|
31247
|
+
const lockfilePath = join14(installDir, "package-lock.json");
|
|
31248
|
+
const tempDir = mkdtempSync(join14(tmpdir3(), "aft-auto-update-"));
|
|
31249
|
+
const stagedPackageDir = existsSync9(packageDir) ? join14(tempDir, "package") : null;
|
|
30966
31250
|
if (stagedPackageDir)
|
|
30967
31251
|
cpSync(packageDir, stagedPackageDir, { recursive: true });
|
|
30968
31252
|
return {
|
|
@@ -31003,7 +31287,7 @@ function stripPackageNameFromPath(pathValue, packageName) {
|
|
|
31003
31287
|
return current;
|
|
31004
31288
|
}
|
|
31005
31289
|
function removeFromPackageLock(installDir, packageName) {
|
|
31006
|
-
const lockPath =
|
|
31290
|
+
const lockPath = join14(installDir, "package-lock.json");
|
|
31007
31291
|
if (!existsSync9(lockPath))
|
|
31008
31292
|
return false;
|
|
31009
31293
|
try {
|
|
@@ -31052,7 +31336,7 @@ function ensureDependencyVersion(packageJsonPath, packageName, version2) {
|
|
|
31052
31336
|
}
|
|
31053
31337
|
}
|
|
31054
31338
|
function removeInstalledPackage(installDir, packageName) {
|
|
31055
|
-
const packageDir =
|
|
31339
|
+
const packageDir = join14(installDir, "node_modules", packageName);
|
|
31056
31340
|
if (!existsSync9(packageDir))
|
|
31057
31341
|
return false;
|
|
31058
31342
|
rmSync3(packageDir, { recursive: true, force: true });
|
|
@@ -31065,13 +31349,13 @@ function resolveInstallContext(runtimePackageJsonPath = getCurrentRuntimePackage
|
|
|
31065
31349
|
const nodeModulesDir = stripPackageNameFromPath(packageDir, PACKAGE_NAME);
|
|
31066
31350
|
if (nodeModulesDir && basename2(nodeModulesDir) === "node_modules") {
|
|
31067
31351
|
const installDir = dirname6(nodeModulesDir);
|
|
31068
|
-
const packageJsonPath =
|
|
31352
|
+
const packageJsonPath = join14(installDir, "package.json");
|
|
31069
31353
|
if (existsSync9(packageJsonPath))
|
|
31070
31354
|
return { installDir, packageJsonPath };
|
|
31071
31355
|
}
|
|
31072
31356
|
return null;
|
|
31073
31357
|
}
|
|
31074
|
-
const legacyPackageJsonPath =
|
|
31358
|
+
const legacyPackageJsonPath = join14(dirname6(CACHE_DIR), "package.json");
|
|
31075
31359
|
if (existsSync9(legacyPackageJsonPath)) {
|
|
31076
31360
|
return { installDir: dirname6(CACHE_DIR), packageJsonPath: legacyPackageJsonPath };
|
|
31077
31361
|
}
|
|
@@ -31402,7 +31686,7 @@ import {
|
|
|
31402
31686
|
statSync as statSync6,
|
|
31403
31687
|
writeFileSync as writeFileSync8
|
|
31404
31688
|
} from "node:fs";
|
|
31405
|
-
import { join as
|
|
31689
|
+
import { join as join17 } from "node:path";
|
|
31406
31690
|
|
|
31407
31691
|
// src/lsp-cache.ts
|
|
31408
31692
|
import {
|
|
@@ -31414,36 +31698,36 @@ import {
|
|
|
31414
31698
|
unlinkSync as unlinkSync5,
|
|
31415
31699
|
writeFileSync as writeFileSync7
|
|
31416
31700
|
} from "node:fs";
|
|
31417
|
-
import { homedir as
|
|
31418
|
-
import { join as
|
|
31701
|
+
import { homedir as homedir11 } from "node:os";
|
|
31702
|
+
import { join as join15 } from "node:path";
|
|
31419
31703
|
function aftCacheBase() {
|
|
31420
31704
|
const override = process.env.AFT_CACHE_DIR;
|
|
31421
31705
|
if (override && override.length > 0)
|
|
31422
31706
|
return override;
|
|
31423
31707
|
if (process.platform === "win32") {
|
|
31424
31708
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
31425
|
-
const base2 = localAppData ||
|
|
31426
|
-
return
|
|
31709
|
+
const base2 = localAppData || join15(homedir11(), "AppData", "Local");
|
|
31710
|
+
return join15(base2, "aft");
|
|
31427
31711
|
}
|
|
31428
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
31429
|
-
return
|
|
31712
|
+
const base = process.env.XDG_CACHE_HOME || join15(homedir11(), ".cache");
|
|
31713
|
+
return join15(base, "aft");
|
|
31430
31714
|
}
|
|
31431
31715
|
function lspCacheRoot() {
|
|
31432
|
-
return
|
|
31716
|
+
return join15(aftCacheBase(), "lsp-packages");
|
|
31433
31717
|
}
|
|
31434
31718
|
function lspPackageDir(npmPackage) {
|
|
31435
|
-
return
|
|
31719
|
+
return join15(lspCacheRoot(), encodeURIComponent(npmPackage));
|
|
31436
31720
|
}
|
|
31437
31721
|
function lspBinaryPath(npmPackage, binary) {
|
|
31438
|
-
return
|
|
31722
|
+
return join15(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
|
|
31439
31723
|
}
|
|
31440
31724
|
function lspBinDir(npmPackage) {
|
|
31441
|
-
return
|
|
31725
|
+
return join15(lspPackageDir(npmPackage), "node_modules", ".bin");
|
|
31442
31726
|
}
|
|
31443
31727
|
function isInstalled(npmPackage, binary) {
|
|
31444
31728
|
for (const candidate of lspBinaryCandidates(binary)) {
|
|
31445
31729
|
try {
|
|
31446
|
-
if (statSync5(
|
|
31730
|
+
if (statSync5(join15(lspBinDir(npmPackage), candidate)).isFile())
|
|
31447
31731
|
return true;
|
|
31448
31732
|
} catch {}
|
|
31449
31733
|
}
|
|
@@ -31463,17 +31747,17 @@ function writeInstalledMetaIn(installDir, version2, sha256) {
|
|
|
31463
31747
|
installedAt: new Date().toISOString(),
|
|
31464
31748
|
...sha256 ? { sha256 } : {}
|
|
31465
31749
|
};
|
|
31466
|
-
writeFileSync7(
|
|
31750
|
+
writeFileSync7(join15(installDir, INSTALLED_META_FILE), JSON.stringify(meta3), "utf8");
|
|
31467
31751
|
} catch (err) {
|
|
31468
31752
|
log2(`[lsp-cache] failed to write installed-meta in ${installDir}: ${err}`);
|
|
31469
31753
|
}
|
|
31470
31754
|
}
|
|
31471
31755
|
function readInstalledMetaIn(installDir) {
|
|
31472
|
-
const
|
|
31756
|
+
const path3 = join15(installDir, INSTALLED_META_FILE);
|
|
31473
31757
|
try {
|
|
31474
|
-
if (!statSync5(
|
|
31758
|
+
if (!statSync5(path3).isFile())
|
|
31475
31759
|
return null;
|
|
31476
|
-
const raw = readFileSync9(
|
|
31760
|
+
const raw = readFileSync9(path3, "utf8");
|
|
31477
31761
|
const parsed = JSON.parse(raw);
|
|
31478
31762
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
31479
31763
|
return null;
|
|
@@ -31493,7 +31777,7 @@ function readInstalledMeta(packageKey) {
|
|
|
31493
31777
|
return readInstalledMetaIn(lspPackageDir(packageKey));
|
|
31494
31778
|
}
|
|
31495
31779
|
function lockPath(npmPackage) {
|
|
31496
|
-
return
|
|
31780
|
+
return join15(lspPackageDir(npmPackage), ".aft-installing");
|
|
31497
31781
|
}
|
|
31498
31782
|
var STALE_LOCK_MS2 = 30 * 60 * 1000;
|
|
31499
31783
|
function acquireInstallLock(lockKey) {
|
|
@@ -31600,7 +31884,7 @@ async function withInstallLock(lockKey, task) {
|
|
|
31600
31884
|
}
|
|
31601
31885
|
var VERSION_CHECK_FILE = ".aft-version-check";
|
|
31602
31886
|
function readVersionCheck(npmPackage) {
|
|
31603
|
-
const file2 =
|
|
31887
|
+
const file2 = join15(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
|
|
31604
31888
|
try {
|
|
31605
31889
|
const raw = readFileSync9(file2, "utf8");
|
|
31606
31890
|
const parsed = JSON.parse(raw);
|
|
@@ -31617,7 +31901,7 @@ function readVersionCheck(npmPackage) {
|
|
|
31617
31901
|
}
|
|
31618
31902
|
function writeVersionCheck(npmPackage, latest) {
|
|
31619
31903
|
mkdirSync7(lspPackageDir(npmPackage), { recursive: true });
|
|
31620
|
-
const file2 =
|
|
31904
|
+
const file2 = join15(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
|
|
31621
31905
|
const record2 = {
|
|
31622
31906
|
last_checked: new Date().toISOString(),
|
|
31623
31907
|
latest_eligible: latest
|
|
@@ -31780,7 +32064,7 @@ var NPM_LSP_TABLE = [
|
|
|
31780
32064
|
|
|
31781
32065
|
// src/lsp-project-relevance.ts
|
|
31782
32066
|
import { existsSync as existsSync11, readdirSync as readdirSync3, readFileSync as readFileSync10 } from "node:fs";
|
|
31783
|
-
import { join as
|
|
32067
|
+
import { join as join16 } from "node:path";
|
|
31784
32068
|
var MAX_WALK_DIRS = 200;
|
|
31785
32069
|
var MAX_WALK_DEPTH = 4;
|
|
31786
32070
|
var NOISE_DIRS = new Set([
|
|
@@ -31797,7 +32081,7 @@ function hasRootMarker(projectRoot, rootMarkers) {
|
|
|
31797
32081
|
if (!rootMarkers)
|
|
31798
32082
|
return false;
|
|
31799
32083
|
for (const marker of rootMarkers) {
|
|
31800
|
-
if (existsSync11(
|
|
32084
|
+
if (existsSync11(join16(projectRoot, marker)))
|
|
31801
32085
|
return true;
|
|
31802
32086
|
}
|
|
31803
32087
|
return false;
|
|
@@ -31821,7 +32105,7 @@ function hasPackageJsonDep(projectRoot, depNames) {
|
|
|
31821
32105
|
}
|
|
31822
32106
|
function readPackageJson(projectRoot) {
|
|
31823
32107
|
try {
|
|
31824
|
-
const raw = readFileSync10(
|
|
32108
|
+
const raw = readFileSync10(join16(projectRoot, "package.json"), "utf8");
|
|
31825
32109
|
const parsed = JSON.parse(raw);
|
|
31826
32110
|
if (typeof parsed !== "object" || parsed === null)
|
|
31827
32111
|
return null;
|
|
@@ -31851,7 +32135,7 @@ function relevantExtensionsInProject(projectRoot, extToServer) {
|
|
|
31851
32135
|
for (const entry of entries) {
|
|
31852
32136
|
if (entry.isDirectory()) {
|
|
31853
32137
|
if (current.depth < MAX_WALK_DEPTH && !NOISE_DIRS.has(entry.name.toLowerCase())) {
|
|
31854
|
-
queue.push({ dir:
|
|
32138
|
+
queue.push({ dir: join16(current.dir, entry.name), depth: current.depth + 1 });
|
|
31855
32139
|
}
|
|
31856
32140
|
continue;
|
|
31857
32141
|
}
|
|
@@ -31978,7 +32262,7 @@ async function resolveTargetVersion(spec, config2, fetchImpl = fetch) {
|
|
|
31978
32262
|
}
|
|
31979
32263
|
function ensureInstallAnchor(cwd) {
|
|
31980
32264
|
try {
|
|
31981
|
-
const stub =
|
|
32265
|
+
const stub = join17(cwd, "package.json");
|
|
31982
32266
|
if (!existsSync12(stub)) {
|
|
31983
32267
|
writeFileSync8(stub, `${JSON.stringify({ name: "aft-lsp-cache", version: "0.0.0", private: true })}
|
|
31984
32268
|
`);
|
|
@@ -31988,18 +32272,18 @@ function ensureInstallAnchor(cwd) {
|
|
|
31988
32272
|
}
|
|
31989
32273
|
}
|
|
31990
32274
|
function runInstall(spec, version2, cwd, signal) {
|
|
31991
|
-
return new Promise((
|
|
32275
|
+
return new Promise((resolve4) => {
|
|
31992
32276
|
const target = `${spec.npm}@${version2}`;
|
|
31993
32277
|
log2(`[lsp] installing ${target} to ${cwd}`);
|
|
31994
32278
|
if (signal?.aborted) {
|
|
31995
32279
|
warn2(`[lsp] install ${target} aborted before spawn`);
|
|
31996
|
-
|
|
32280
|
+
resolve4(false);
|
|
31997
32281
|
return;
|
|
31998
32282
|
}
|
|
31999
32283
|
const npm = resolveNpm();
|
|
32000
32284
|
if (!npm) {
|
|
32001
32285
|
warn2(`[lsp] npm not found on PATH or known locations; cannot install ${target}`);
|
|
32002
|
-
|
|
32286
|
+
resolve4(false);
|
|
32003
32287
|
return;
|
|
32004
32288
|
}
|
|
32005
32289
|
ensureInstallAnchor(cwd);
|
|
@@ -32022,7 +32306,7 @@ function runInstall(spec, version2, cwd, signal) {
|
|
|
32022
32306
|
return;
|
|
32023
32307
|
settled = true;
|
|
32024
32308
|
cleanup();
|
|
32025
|
-
|
|
32309
|
+
resolve4(ok);
|
|
32026
32310
|
};
|
|
32027
32311
|
const onAbort = () => {
|
|
32028
32312
|
warn2(`[lsp] install ${target} aborted during shutdown`);
|
|
@@ -32123,7 +32407,7 @@ function cachedPackageDir(npmPackage) {
|
|
|
32123
32407
|
return lspBinDir(npmPackage).replace(/[\\/]node_modules[\\/]\.bin[\\/]?$/, "");
|
|
32124
32408
|
}
|
|
32125
32409
|
function hashInstalledBinary(spec) {
|
|
32126
|
-
return new Promise((
|
|
32410
|
+
return new Promise((resolve4, reject) => {
|
|
32127
32411
|
const candidates = process.platform === "win32" ? [
|
|
32128
32412
|
lspBinaryPath(spec.npm, spec.binary),
|
|
32129
32413
|
lspBinaryPath(spec.npm, `${spec.binary}.cmd`),
|
|
@@ -32147,7 +32431,7 @@ function hashInstalledBinary(spec) {
|
|
|
32147
32431
|
const stream = createReadStream(pathToHash);
|
|
32148
32432
|
stream.on("error", reject);
|
|
32149
32433
|
stream.on("data", (chunk) => hash2.update(chunk));
|
|
32150
|
-
stream.on("end", () =>
|
|
32434
|
+
stream.on("end", () => resolve4(hash2.digest("hex")));
|
|
32151
32435
|
});
|
|
32152
32436
|
}
|
|
32153
32437
|
function installedBinaryPath(spec) {
|
|
@@ -32165,15 +32449,15 @@ function installedBinaryPath(spec) {
|
|
|
32165
32449
|
}
|
|
32166
32450
|
return null;
|
|
32167
32451
|
}
|
|
32168
|
-
function sha256OfFileSync(
|
|
32169
|
-
return createHash4("sha256").update(readFileSync11(
|
|
32452
|
+
function sha256OfFileSync(path3) {
|
|
32453
|
+
return createHash4("sha256").update(readFileSync11(path3)).digest("hex");
|
|
32170
32454
|
}
|
|
32171
32455
|
function quarantineCachedNpmInstall(spec, reason) {
|
|
32172
32456
|
const packageDir = lspPackageDir(spec.npm);
|
|
32173
|
-
const dest =
|
|
32457
|
+
const dest = join17(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
|
|
32174
32458
|
warn2(`[lsp] tofu_mismatch ${spec.npm}: ${reason}; quarantining ${packageDir} -> ${dest}`);
|
|
32175
32459
|
try {
|
|
32176
|
-
mkdirSync8(
|
|
32460
|
+
mkdirSync8(join17(dest, ".."), { recursive: true });
|
|
32177
32461
|
rmSync5(dest, { recursive: true, force: true });
|
|
32178
32462
|
renameSync6(packageDir, dest);
|
|
32179
32463
|
} catch (err) {
|
|
@@ -32269,7 +32553,7 @@ import {
|
|
|
32269
32553
|
unlinkSync as unlinkSync6,
|
|
32270
32554
|
writeFileSync as writeFileSync9
|
|
32271
32555
|
} from "node:fs";
|
|
32272
|
-
import { dirname as dirname8, join as
|
|
32556
|
+
import { dirname as dirname8, join as join18, relative as relative3, resolve as resolve4 } from "node:path";
|
|
32273
32557
|
import { Readable as Readable3 } from "node:stream";
|
|
32274
32558
|
import { pipeline as pipeline3 } from "node:stream/promises";
|
|
32275
32559
|
|
|
@@ -32359,26 +32643,26 @@ function detectHostPlatform() {
|
|
|
32359
32643
|
|
|
32360
32644
|
// src/lsp-github-install.ts
|
|
32361
32645
|
function ghCacheRoot() {
|
|
32362
|
-
return
|
|
32646
|
+
return join18(aftCacheBase(), "lsp-binaries");
|
|
32363
32647
|
}
|
|
32364
32648
|
function ghPackageDir(spec) {
|
|
32365
|
-
return
|
|
32649
|
+
return join18(ghCacheRoot(), spec.id);
|
|
32366
32650
|
}
|
|
32367
32651
|
function ghBinDir(spec) {
|
|
32368
|
-
return
|
|
32652
|
+
return join18(ghPackageDir(spec), "bin");
|
|
32369
32653
|
}
|
|
32370
32654
|
function ghExtractDir(spec) {
|
|
32371
|
-
return
|
|
32655
|
+
return join18(ghPackageDir(spec), "extracted");
|
|
32372
32656
|
}
|
|
32373
32657
|
var INSTALLED_META_FILE2 = ".aft-installed";
|
|
32374
32658
|
function ghBinaryPath(spec, platform3) {
|
|
32375
32659
|
const ext = platform3 === "win32" ? ".exe" : "";
|
|
32376
|
-
return
|
|
32660
|
+
return join18(ghBinDir(spec), `${spec.binary}${ext}`);
|
|
32377
32661
|
}
|
|
32378
32662
|
function isGithubInstalled(spec, platform3) {
|
|
32379
32663
|
for (const candidate of ghBinaryCandidates(spec, platform3)) {
|
|
32380
32664
|
try {
|
|
32381
|
-
if (statSync7(
|
|
32665
|
+
if (statSync7(join18(ghBinDir(spec), candidate)).isFile())
|
|
32382
32666
|
return true;
|
|
32383
32667
|
} catch {}
|
|
32384
32668
|
}
|
|
@@ -32391,10 +32675,10 @@ function ghBinaryCandidates(spec, platform3) {
|
|
|
32391
32675
|
}
|
|
32392
32676
|
function readGithubInstalledMetaIn(installDir) {
|
|
32393
32677
|
try {
|
|
32394
|
-
const
|
|
32395
|
-
if (!statSync7(
|
|
32678
|
+
const path3 = join18(installDir, INSTALLED_META_FILE2);
|
|
32679
|
+
if (!statSync7(path3).isFile())
|
|
32396
32680
|
return null;
|
|
32397
|
-
const parsed = JSON.parse(readFileSync12(
|
|
32681
|
+
const parsed = JSON.parse(readFileSync12(path3, "utf8"));
|
|
32398
32682
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
32399
32683
|
return null;
|
|
32400
32684
|
return {
|
|
@@ -32418,24 +32702,24 @@ function writeGithubInstalledMetaIn(installDir, version2, binarySha256, archiveS
|
|
|
32418
32702
|
binarySha256,
|
|
32419
32703
|
...archiveSha256 ? { archiveSha256 } : {}
|
|
32420
32704
|
};
|
|
32421
|
-
writeFileSync9(
|
|
32705
|
+
writeFileSync9(join18(installDir, INSTALLED_META_FILE2), JSON.stringify(meta3), "utf8");
|
|
32422
32706
|
} catch (err) {
|
|
32423
32707
|
warn2(`[lsp] failed to write github installed metadata in ${installDir}: ${err}`);
|
|
32424
32708
|
}
|
|
32425
32709
|
}
|
|
32426
32710
|
var MAX_DOWNLOAD_BYTES3 = 256 * 1024 * 1024;
|
|
32427
32711
|
var MAX_EXTRACT_BYTES2 = 1024 * 1024 * 1024;
|
|
32428
|
-
function sha256OfFile(
|
|
32429
|
-
return new Promise((
|
|
32712
|
+
function sha256OfFile(path3) {
|
|
32713
|
+
return new Promise((resolve5, reject) => {
|
|
32430
32714
|
const hash2 = createHash5("sha256");
|
|
32431
|
-
const stream = createReadStream2(
|
|
32715
|
+
const stream = createReadStream2(path3);
|
|
32432
32716
|
stream.on("error", reject);
|
|
32433
32717
|
stream.on("data", (chunk) => hash2.update(chunk));
|
|
32434
|
-
stream.on("end", () =>
|
|
32718
|
+
stream.on("end", () => resolve5(hash2.digest("hex")));
|
|
32435
32719
|
});
|
|
32436
32720
|
}
|
|
32437
|
-
function sha256OfFileSync2(
|
|
32438
|
-
return createHash5("sha256").update(readFileSync12(
|
|
32721
|
+
function sha256OfFileSync2(path3) {
|
|
32722
|
+
return createHash5("sha256").update(readFileSync12(path3)).digest("hex");
|
|
32439
32723
|
}
|
|
32440
32724
|
async function fetchReleaseByTag(githubRepo, tag, fetchImpl, signal) {
|
|
32441
32725
|
const candidates = [];
|
|
@@ -32667,7 +32951,7 @@ function validateExtraction(stagingRoot) {
|
|
|
32667
32951
|
throw new Error(`failed to read staging dir ${dir}: ${err}`);
|
|
32668
32952
|
}
|
|
32669
32953
|
for (const entry of entries) {
|
|
32670
|
-
const full =
|
|
32954
|
+
const full = join18(dir, entry);
|
|
32671
32955
|
let lst;
|
|
32672
32956
|
try {
|
|
32673
32957
|
lst = lstatSync2(full);
|
|
@@ -32679,7 +32963,7 @@ function validateExtraction(stagingRoot) {
|
|
|
32679
32963
|
try {
|
|
32680
32964
|
target = readlinkSync2(full);
|
|
32681
32965
|
} catch {}
|
|
32682
|
-
throw new Error(`archive contains symlink ${
|
|
32966
|
+
throw new Error(`archive contains symlink ${relative3(realStagingRoot, full)} → ${target}; rejecting (zip-slip defense)`);
|
|
32683
32967
|
}
|
|
32684
32968
|
let realFull;
|
|
32685
32969
|
try {
|
|
@@ -32687,8 +32971,8 @@ function validateExtraction(stagingRoot) {
|
|
|
32687
32971
|
} catch (err) {
|
|
32688
32972
|
throw new Error(`failed to realpath ${full}: ${err}`);
|
|
32689
32973
|
}
|
|
32690
|
-
const rel =
|
|
32691
|
-
if (rel.startsWith("..") ||
|
|
32974
|
+
const rel = relative3(realStagingRoot, realFull);
|
|
32975
|
+
if (rel.startsWith("..") || resolve4(realStagingRoot, rel) !== realFull) {
|
|
32692
32976
|
throw new Error(`archive entry escapes staging root: ${full} → ${realFull} (zip-slip defense)`);
|
|
32693
32977
|
}
|
|
32694
32978
|
if (lst.isDirectory()) {
|
|
@@ -32755,7 +33039,7 @@ function extractArchiveSafely(archivePath, destDir, archiveType) {
|
|
|
32755
33039
|
}
|
|
32756
33040
|
function quarantineCachedGithubInstall(spec, reason) {
|
|
32757
33041
|
const packageDir = ghPackageDir(spec);
|
|
32758
|
-
const dest =
|
|
33042
|
+
const dest = join18(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
|
|
32759
33043
|
warn2(`[lsp] tofu_mismatch ${spec.id}: ${reason}; quarantining ${packageDir} -> ${dest}`);
|
|
32760
33044
|
try {
|
|
32761
33045
|
mkdirSync9(dirname8(dest), { recursive: true });
|
|
@@ -32768,7 +33052,7 @@ function quarantineCachedGithubInstall(spec, reason) {
|
|
|
32768
33052
|
function validateCachedGithubInstall(spec, platform3) {
|
|
32769
33053
|
const packageDir = ghPackageDir(spec);
|
|
32770
33054
|
const meta3 = readGithubInstalledMetaIn(packageDir);
|
|
32771
|
-
const binaryPath = ghBinaryCandidates(spec, platform3).map((candidate) =>
|
|
33055
|
+
const binaryPath = ghBinaryCandidates(spec, platform3).map((candidate) => join18(ghBinDir(spec), candidate)).find((candidate) => {
|
|
32772
33056
|
try {
|
|
32773
33057
|
return statSync7(candidate).isFile();
|
|
32774
33058
|
} catch {
|
|
@@ -32846,7 +33130,7 @@ async function downloadAndInstall(spec, tag, assets, platform3, arch, fetchImpl,
|
|
|
32846
33130
|
}
|
|
32847
33131
|
const pkgDir = ghPackageDir(spec);
|
|
32848
33132
|
const extractDir = ghExtractDir(spec);
|
|
32849
|
-
const archivePath =
|
|
33133
|
+
const archivePath = join18(pkgDir, expected.name);
|
|
32850
33134
|
log2(`[lsp] downloading ${spec.id} ${tag} → ${matchingAsset.url}`);
|
|
32851
33135
|
try {
|
|
32852
33136
|
await downloadFile(matchingAsset.url, archivePath, fetchImpl, matchingAsset.size, signal);
|
|
@@ -32886,7 +33170,7 @@ async function downloadAndInstall(spec, tag, assets, platform3, arch, fetchImpl,
|
|
|
32886
33170
|
unlinkSync6(archivePath);
|
|
32887
33171
|
} catch {}
|
|
32888
33172
|
}
|
|
32889
|
-
const innerBinaryPath =
|
|
33173
|
+
const innerBinaryPath = join18(extractDir, spec.binaryPathInArchive(platform3, arch, version2));
|
|
32890
33174
|
if (!existsSync13(innerBinaryPath)) {
|
|
32891
33175
|
error2(`[lsp] ${spec.id}: extracted binary not found at ${innerBinaryPath}`);
|
|
32892
33176
|
return null;
|
|
@@ -33181,7 +33465,7 @@ function renderScreen(state, rows = state.rows, cols = state.cols) {
|
|
|
33181
33465
|
`);
|
|
33182
33466
|
}
|
|
33183
33467
|
function writeTerminal(terminal, data) {
|
|
33184
|
-
return new Promise((
|
|
33468
|
+
return new Promise((resolve5) => terminal.write(data, resolve5));
|
|
33185
33469
|
}
|
|
33186
33470
|
|
|
33187
33471
|
// src/shared/rpc-server.ts
|
|
@@ -33196,18 +33480,18 @@ import {
|
|
|
33196
33480
|
writeFileSync as writeFileSync10
|
|
33197
33481
|
} from "node:fs";
|
|
33198
33482
|
import { createServer } from "node:http";
|
|
33199
|
-
import { dirname as dirname9, join as
|
|
33483
|
+
import { dirname as dirname9, join as join20 } from "node:path";
|
|
33200
33484
|
|
|
33201
33485
|
// src/shared/rpc-utils.ts
|
|
33202
33486
|
import { createHash as createHash6 } from "node:crypto";
|
|
33203
|
-
import { join as
|
|
33487
|
+
import { join as join19 } from "node:path";
|
|
33204
33488
|
function projectHash(directory) {
|
|
33205
33489
|
const normalized = directory.replace(/\/+$/, "");
|
|
33206
33490
|
return createHash6("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
33207
33491
|
}
|
|
33208
33492
|
function rpcPortFileDir(storageDir, directory) {
|
|
33209
33493
|
const hash2 = projectHash(directory);
|
|
33210
|
-
return
|
|
33494
|
+
return join19(storageDir, "rpc", hash2, "ports");
|
|
33211
33495
|
}
|
|
33212
33496
|
function isPidAlive(pid) {
|
|
33213
33497
|
if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0)
|
|
@@ -33260,13 +33544,13 @@ class AftRpcServer {
|
|
|
33260
33544
|
constructor(storageDir, directory) {
|
|
33261
33545
|
this.portsDir = rpcPortFileDir(storageDir, directory);
|
|
33262
33546
|
this.instanceId = randomBytes2(8).toString("hex");
|
|
33263
|
-
this.portFilePath =
|
|
33547
|
+
this.portFilePath = join20(this.portsDir, `${this.instanceId}.json`);
|
|
33264
33548
|
}
|
|
33265
33549
|
handle(method, handler) {
|
|
33266
33550
|
this.handlers.set(method, handler);
|
|
33267
33551
|
}
|
|
33268
33552
|
async start() {
|
|
33269
|
-
return new Promise((
|
|
33553
|
+
return new Promise((resolve5, reject) => {
|
|
33270
33554
|
const server = createServer((req, res) => this.dispatch(req, res));
|
|
33271
33555
|
server.on("error", (err) => {
|
|
33272
33556
|
warn2(`RPC server error: ${err.message}`);
|
|
@@ -33299,7 +33583,7 @@ class AftRpcServer {
|
|
|
33299
33583
|
} catch (err) {
|
|
33300
33584
|
warn2(`Failed to write RPC port file: ${err}`);
|
|
33301
33585
|
}
|
|
33302
|
-
|
|
33586
|
+
resolve5(this.port);
|
|
33303
33587
|
});
|
|
33304
33588
|
server.unref();
|
|
33305
33589
|
});
|
|
@@ -33314,7 +33598,7 @@ class AftRpcServer {
|
|
|
33314
33598
|
for (const entry of entries) {
|
|
33315
33599
|
if (!entry.endsWith(".json"))
|
|
33316
33600
|
continue;
|
|
33317
|
-
const filePath =
|
|
33601
|
+
const filePath = join20(this.portsDir, entry);
|
|
33318
33602
|
if (filePath === this.portFilePath)
|
|
33319
33603
|
continue;
|
|
33320
33604
|
try {
|
|
@@ -33719,20 +34003,20 @@ function formatStatusMarkdown(status) {
|
|
|
33719
34003
|
// src/shared/tui-config.ts
|
|
33720
34004
|
var import_comment_json4 = __toESM(require_src2(), 1);
|
|
33721
34005
|
import { existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "node:fs";
|
|
33722
|
-
import { dirname as dirname10, join as
|
|
34006
|
+
import { dirname as dirname10, join as join22 } from "node:path";
|
|
33723
34007
|
|
|
33724
34008
|
// src/shared/opencode-config-dir.ts
|
|
33725
|
-
import { homedir as
|
|
33726
|
-
import { join as
|
|
34009
|
+
import { homedir as homedir12 } from "node:os";
|
|
34010
|
+
import { join as join21, resolve as resolve5 } from "node:path";
|
|
33727
34011
|
function getCliConfigDir() {
|
|
33728
34012
|
const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
33729
34013
|
if (envConfigDir) {
|
|
33730
|
-
return
|
|
34014
|
+
return resolve5(envConfigDir);
|
|
33731
34015
|
}
|
|
33732
34016
|
if (process.platform === "win32") {
|
|
33733
|
-
return
|
|
34017
|
+
return join21(homedir12(), ".config", "opencode");
|
|
33734
34018
|
}
|
|
33735
|
-
return
|
|
34019
|
+
return join21(process.env.XDG_CONFIG_HOME || join21(homedir12(), ".config"), "opencode");
|
|
33736
34020
|
}
|
|
33737
34021
|
function getOpenCodeConfigDir2(_options) {
|
|
33738
34022
|
return getCliConfigDir();
|
|
@@ -33741,10 +34025,10 @@ function getOpenCodeConfigPaths(options) {
|
|
|
33741
34025
|
const configDir = getOpenCodeConfigDir2(options);
|
|
33742
34026
|
return {
|
|
33743
34027
|
configDir,
|
|
33744
|
-
configJson:
|
|
33745
|
-
configJsonc:
|
|
33746
|
-
packageJson:
|
|
33747
|
-
omoConfig:
|
|
34028
|
+
configJson: join21(configDir, "opencode.json"),
|
|
34029
|
+
configJsonc: join21(configDir, "opencode.jsonc"),
|
|
34030
|
+
packageJson: join21(configDir, "package.json"),
|
|
34031
|
+
omoConfig: join21(configDir, "magic-context.jsonc")
|
|
33748
34032
|
};
|
|
33749
34033
|
}
|
|
33750
34034
|
|
|
@@ -33753,8 +34037,8 @@ var PLUGIN_NAME = "@cortexkit/aft-opencode";
|
|
|
33753
34037
|
var PLUGIN_ENTRY = `${PLUGIN_NAME}@latest`;
|
|
33754
34038
|
function resolveTuiConfigPath() {
|
|
33755
34039
|
const configDir = getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
|
|
33756
|
-
const jsoncPath =
|
|
33757
|
-
const jsonPath =
|
|
34040
|
+
const jsoncPath = join22(configDir, "tui.jsonc");
|
|
34041
|
+
const jsonPath = join22(configDir, "tui.json");
|
|
33758
34042
|
if (existsSync15(jsoncPath))
|
|
33759
34043
|
return jsoncPath;
|
|
33760
34044
|
if (existsSync15(jsonPath))
|
|
@@ -33843,8 +34127,8 @@ function installProcessHandlers() {
|
|
|
33843
34127
|
}
|
|
33844
34128
|
signalShutdownStarted = true;
|
|
33845
34129
|
process.exitCode = SIGNAL_EXIT_CODES[sig];
|
|
33846
|
-
const timeout = new Promise((
|
|
33847
|
-
setTimeout(
|
|
34130
|
+
const timeout = new Promise((resolve6) => {
|
|
34131
|
+
setTimeout(resolve6, SIGNAL_CLEANUP_TIMEOUT_MS);
|
|
33848
34132
|
});
|
|
33849
34133
|
Promise.race([runCleanups(sig), timeout]).finally(() => {
|
|
33850
34134
|
process.exit(SIGNAL_EXIT_CODES[sig]);
|
|
@@ -33956,99 +34240,18 @@ import { tool as tool3 } from "@opencode-ai/plugin";
|
|
|
33956
34240
|
|
|
33957
34241
|
// src/tools/_shared.ts
|
|
33958
34242
|
import * as fs3 from "node:fs";
|
|
33959
|
-
import * as
|
|
33960
|
-
import * as
|
|
34243
|
+
import * as os3 from "node:os";
|
|
34244
|
+
import * as path3 from "node:path";
|
|
33961
34245
|
import { tool as tool2 } from "@opencode-ai/plugin";
|
|
33962
34246
|
var z2 = tool2.schema;
|
|
33963
34247
|
var optionalInt = (min, max) => z2.number().int().min(min).max(max).optional();
|
|
33964
|
-
function isEmptyParam(value) {
|
|
33965
|
-
if (value === undefined || value === null)
|
|
33966
|
-
return true;
|
|
33967
|
-
if (typeof value === "string")
|
|
33968
|
-
return value.length === 0;
|
|
33969
|
-
if (Array.isArray(value))
|
|
33970
|
-
return value.length === 0;
|
|
33971
|
-
if (typeof value === "object")
|
|
33972
|
-
return Object.keys(value).length === 0;
|
|
33973
|
-
return false;
|
|
33974
|
-
}
|
|
33975
34248
|
var BASH_TRANSPORT_TIMEOUT_MS = 30000;
|
|
33976
|
-
function asPlainObject(value) {
|
|
33977
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
33978
|
-
return;
|
|
33979
|
-
return value;
|
|
33980
|
-
}
|
|
33981
|
-
function candidateLocation(candidate) {
|
|
33982
|
-
const file2 = typeof candidate.file === "string" && candidate.file.length > 0 ? candidate.file : undefined;
|
|
33983
|
-
if (!file2)
|
|
33984
|
-
return;
|
|
33985
|
-
const line = typeof candidate.line === "number" && Number.isFinite(candidate.line) ? candidate.line : undefined;
|
|
33986
|
-
return line === undefined ? file2 : `${file2}:${line}`;
|
|
33987
|
-
}
|
|
33988
|
-
function stringifyData(data) {
|
|
33989
|
-
if (data === undefined)
|
|
33990
|
-
return;
|
|
33991
|
-
try {
|
|
33992
|
-
return JSON.stringify(data, null, 2);
|
|
33993
|
-
} catch {
|
|
33994
|
-
return String(data);
|
|
33995
|
-
}
|
|
33996
|
-
}
|
|
33997
|
-
function formatBridgeErrorMessage(command, response, params = {}) {
|
|
33998
|
-
const code = typeof response.code === "string" && response.code.length > 0 ? response.code : undefined;
|
|
33999
|
-
const message = typeof response.message === "string" && response.message.length > 0 ? response.message : `${command} failed`;
|
|
34000
|
-
const data = asPlainObject(response.data);
|
|
34001
|
-
const rawCandidates = Array.isArray(response.candidates) ? response.candidates : Array.isArray(data?.candidates) ? data.candidates : undefined;
|
|
34002
|
-
const rawSymbol = typeof response.symbol === "string" && response.symbol.length > 0 ? response.symbol : typeof data?.symbol === "string" && data.symbol.length > 0 ? data.symbol : undefined;
|
|
34003
|
-
if (code === "ambiguous_target" || code === "target_symbol_not_in_file") {
|
|
34004
|
-
const candidates = (rawCandidates ?? []).map(asPlainObject).filter((candidate) => candidate !== undefined).map(candidateLocation).filter((candidate) => candidate !== undefined);
|
|
34005
|
-
if (candidates.length > 0) {
|
|
34006
|
-
const symbol2 = typeof params.toSymbol === "string" && params.toSymbol.length > 0 ? params.toSymbol : rawSymbol;
|
|
34007
|
-
const target = symbol2 ? `multiple symbols named "${symbol2}"` : message.replace(/[.!?]+$/, "");
|
|
34008
|
-
const action = code === "ambiguous_target" ? "Pass toFile to disambiguate" : "Try one of these files for toFile";
|
|
34009
|
-
return `${command}: ${code} — ${target}. ${action}:
|
|
34010
|
-
${candidates.map((candidate) => ` - ${candidate}`).join(`
|
|
34011
|
-
`)}`;
|
|
34012
|
-
}
|
|
34013
|
-
}
|
|
34014
|
-
if (!code)
|
|
34015
|
-
return message;
|
|
34016
|
-
const lines = [`${command}: ${code} — ${message}`];
|
|
34017
|
-
const extras = collectStructuredExtras(response);
|
|
34018
|
-
if (extras)
|
|
34019
|
-
lines.push(`data: ${extras}`);
|
|
34020
|
-
return lines.join(`
|
|
34021
|
-
`);
|
|
34022
|
-
}
|
|
34023
|
-
function collectStructuredExtras(response) {
|
|
34024
|
-
const reserved = new Set([
|
|
34025
|
-
"id",
|
|
34026
|
-
"success",
|
|
34027
|
-
"code",
|
|
34028
|
-
"message",
|
|
34029
|
-
"data",
|
|
34030
|
-
"status_bar",
|
|
34031
|
-
"bg_completions"
|
|
34032
|
-
]);
|
|
34033
|
-
const extras = {};
|
|
34034
|
-
for (const [key, value] of Object.entries(response)) {
|
|
34035
|
-
if (reserved.has(key))
|
|
34036
|
-
continue;
|
|
34037
|
-
extras[key] = value;
|
|
34038
|
-
}
|
|
34039
|
-
if (Object.keys(extras).length === 0) {
|
|
34040
|
-
return stringifyData(response.data);
|
|
34041
|
-
}
|
|
34042
|
-
if (response.data !== undefined)
|
|
34043
|
-
extras.data = response.data;
|
|
34044
|
-
return stringifyData(extras);
|
|
34045
|
-
}
|
|
34046
34249
|
function canonicalizeDirectory(dir) {
|
|
34047
34250
|
const trimmed = dir.replace(/[/\\]+$/, "");
|
|
34048
34251
|
try {
|
|
34049
34252
|
return fs3.realpathSync(trimmed);
|
|
34050
34253
|
} catch {
|
|
34051
|
-
return
|
|
34254
|
+
return path3.resolve(trimmed);
|
|
34052
34255
|
}
|
|
34053
34256
|
}
|
|
34054
34257
|
function projectRootFor(runtime) {
|
|
@@ -34065,19 +34268,19 @@ async function resolveProjectRoot(ctx, runtime) {
|
|
|
34065
34268
|
}
|
|
34066
34269
|
return projectRootFor(runtime);
|
|
34067
34270
|
}
|
|
34068
|
-
function
|
|
34271
|
+
function expandTilde2(input) {
|
|
34069
34272
|
if (!input || !input.startsWith("~"))
|
|
34070
34273
|
return input;
|
|
34071
34274
|
if (input === "~")
|
|
34072
|
-
return
|
|
34073
|
-
if (input.startsWith("~/") || input.startsWith(`~${
|
|
34074
|
-
return
|
|
34275
|
+
return os3.homedir();
|
|
34276
|
+
if (input.startsWith("~/") || input.startsWith(`~${path3.sep}`)) {
|
|
34277
|
+
return path3.resolve(os3.homedir(), input.slice(2));
|
|
34075
34278
|
}
|
|
34076
34279
|
return input;
|
|
34077
34280
|
}
|
|
34078
34281
|
function resolvePathFromProjectRoot(projectRoot, target) {
|
|
34079
|
-
const expanded =
|
|
34080
|
-
return
|
|
34282
|
+
const expanded = expandTilde2(target);
|
|
34283
|
+
return path3.isAbsolute(expanded) ? expanded : path3.resolve(projectRoot, expanded);
|
|
34081
34284
|
}
|
|
34082
34285
|
async function resolvePathArg(ctx, runtime, target) {
|
|
34083
34286
|
return resolvePathFromProjectRoot(await resolveProjectRoot(ctx, runtime), target);
|
|
@@ -34119,19 +34322,19 @@ async function callBashBridge(ctx, runtime, command, params = {}, options) {
|
|
|
34119
34322
|
|
|
34120
34323
|
// src/tools/permissions.ts
|
|
34121
34324
|
import * as fs4 from "node:fs";
|
|
34122
|
-
import * as
|
|
34325
|
+
import * as path4 from "node:path";
|
|
34123
34326
|
var UNSUPPORTED_ASK_HOST = "AFT requires OpenCode 1.15.5 or newer for permission asks; please upgrade OpenCode";
|
|
34124
34327
|
async function runAsk(maybe) {
|
|
34125
34328
|
await maybe;
|
|
34126
34329
|
}
|
|
34127
34330
|
function resolveAbsolutePath(context, target) {
|
|
34128
|
-
return
|
|
34331
|
+
return path4.isAbsolute(target) ? target : path4.resolve(projectRootFor(context), target);
|
|
34129
34332
|
}
|
|
34130
34333
|
function resolveRelativePattern(context, target) {
|
|
34131
|
-
return
|
|
34334
|
+
return path4.relative(projectRootFor(context), resolveAbsolutePath(context, target)) || ".";
|
|
34132
34335
|
}
|
|
34133
34336
|
function resolveRelativePatternFromAbsolute(context, absolutePath) {
|
|
34134
|
-
return
|
|
34337
|
+
return path4.relative(projectRootFor(context), absolutePath) || ".";
|
|
34135
34338
|
}
|
|
34136
34339
|
function resolveRelativePatterns(context, targets) {
|
|
34137
34340
|
const seen = new Set;
|
|
@@ -34171,8 +34374,8 @@ async function askEditPermission(context, patterns, metadata = {}) {
|
|
|
34171
34374
|
function containsPath(parent, child) {
|
|
34172
34375
|
if (!parent)
|
|
34173
34376
|
return false;
|
|
34174
|
-
const rel =
|
|
34175
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
34377
|
+
const rel = path4.relative(parent, child);
|
|
34378
|
+
return rel === "" || !rel.startsWith("..") && !path4.isAbsolute(rel);
|
|
34176
34379
|
}
|
|
34177
34380
|
function windowsPath(p) {
|
|
34178
34381
|
if (process.platform !== "win32")
|
|
@@ -34182,7 +34385,7 @@ function windowsPath(p) {
|
|
|
34182
34385
|
function normalizePath(p) {
|
|
34183
34386
|
if (process.platform !== "win32")
|
|
34184
34387
|
return p;
|
|
34185
|
-
const resolved =
|
|
34388
|
+
const resolved = path4.resolve(windowsPath(p));
|
|
34186
34389
|
try {
|
|
34187
34390
|
return fs4.realpathSync.native(resolved);
|
|
34188
34391
|
} catch {
|
|
@@ -34198,7 +34401,7 @@ function normalizePathPattern(p) {
|
|
|
34198
34401
|
if (!match)
|
|
34199
34402
|
return normalizePath(p);
|
|
34200
34403
|
const dir = /^[A-Za-z]:$/.test(match[1]) ? `${match[1]}\\` : match[1];
|
|
34201
|
-
return
|
|
34404
|
+
return path4.join(normalizePath(dir), match[2]);
|
|
34202
34405
|
}
|
|
34203
34406
|
async function assertExternalDirectoryPermission(context, target, options) {
|
|
34204
34407
|
if (!target)
|
|
@@ -34217,8 +34420,8 @@ async function assertExternalDirectoryPermission(context, target, options) {
|
|
|
34217
34420
|
return;
|
|
34218
34421
|
}
|
|
34219
34422
|
const kind = options?.kind ?? "file";
|
|
34220
|
-
const parentDir = kind === "directory" ? absoluteTarget :
|
|
34221
|
-
const rawGlob = process.platform === "win32" ? normalizePathPattern(
|
|
34423
|
+
const parentDir = kind === "directory" ? absoluteTarget : path4.dirname(absoluteTarget);
|
|
34424
|
+
const rawGlob = process.platform === "win32" ? normalizePathPattern(path4.join(parentDir, "*")) : path4.join(parentDir, "*").replaceAll("\\", "/");
|
|
34222
34425
|
try {
|
|
34223
34426
|
await runAsk(context.ask({
|
|
34224
34427
|
permission: "external_directory",
|
|
@@ -34292,6 +34495,20 @@ function extractHint(response) {
|
|
|
34292
34495
|
const hint = response.hint;
|
|
34293
34496
|
return typeof hint === "string" && hint.length > 0 ? hint : null;
|
|
34294
34497
|
}
|
|
34498
|
+
function appendSkippedFiles(output, skippedFiles) {
|
|
34499
|
+
if (!skippedFiles || skippedFiles.length === 0)
|
|
34500
|
+
return output;
|
|
34501
|
+
const lines = skippedFiles.map((skipped) => {
|
|
34502
|
+
const file2 = skipped.file ?? "unknown";
|
|
34503
|
+
const reason = skipped.reason ?? "unknown reason";
|
|
34504
|
+
return ` ${file2}: ${reason}`;
|
|
34505
|
+
});
|
|
34506
|
+
return `${output}
|
|
34507
|
+
|
|
34508
|
+
Incomplete: skipped ${skippedFiles.length} file(s)
|
|
34509
|
+
${lines.join(`
|
|
34510
|
+
`)}`;
|
|
34511
|
+
}
|
|
34295
34512
|
async function resolveAstPaths(ctx, context, paths) {
|
|
34296
34513
|
if (isEmptyParam(paths) || !Array.isArray(paths))
|
|
34297
34514
|
return;
|
|
@@ -34316,17 +34533,18 @@ var SUPPORTED_LANGS = [
|
|
|
34316
34533
|
"python",
|
|
34317
34534
|
"rust",
|
|
34318
34535
|
"go",
|
|
34319
|
-
"pascal"
|
|
34536
|
+
"pascal",
|
|
34537
|
+
"r"
|
|
34320
34538
|
];
|
|
34321
34539
|
function astTools(ctx) {
|
|
34322
34540
|
const searchTool = {
|
|
34323
|
-
description: `Search code patterns across filesystem using AST-aware matching. Supports
|
|
34541
|
+
description: `Search code patterns across filesystem using AST-aware matching. Supports 8 languages.
|
|
34324
34542
|
|
|
34325
34543
|
` + `Use meta-variables: $VAR matches a single AST node, $$$ matches multiple nodes (variadic).
|
|
34326
34544
|
` + `IMPORTANT: Patterns must be complete AST nodes (valid code fragments).
|
|
34327
34545
|
` + `For functions, include params and body: 'export async function $NAME($$$) { $$$ }' not just 'export async function $NAME'.
|
|
34328
34546
|
|
|
34329
|
-
` + "Examples: pattern='console.log($MSG)' lang='typescript', pattern='async function $NAME($$$) { $$$ }' lang='javascript', pattern='def $FUNC($$$): $$$' lang='python', pattern='Writeln($MSG);' lang='pascal'",
|
|
34547
|
+
` + "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'",
|
|
34330
34548
|
args: {
|
|
34331
34549
|
pattern: z3.string().describe("AST pattern with meta-variables ($VAR, $$$). Must be complete AST node."),
|
|
34332
34550
|
lang: z3.enum(SUPPORTED_LANGS).describe("Target language"),
|
|
@@ -34407,6 +34625,9 @@ ${hint}`;
|
|
|
34407
34625
|
}
|
|
34408
34626
|
}
|
|
34409
34627
|
}
|
|
34628
|
+
if (data.complete === false || (data.skipped_files?.length ?? 0) > 0) {
|
|
34629
|
+
output = appendSkippedFiles(output, data.skipped_files);
|
|
34630
|
+
}
|
|
34410
34631
|
showOutputToUser(context, output);
|
|
34411
34632
|
return output;
|
|
34412
34633
|
}
|
|
@@ -34750,7 +34971,7 @@ function createBashTool(ctx, aftSearchRegisteredOverride) {
|
|
|
34750
34971
|
throw new Error(status.message ?? "bash_status failed");
|
|
34751
34972
|
}
|
|
34752
34973
|
if (isTerminalStatus(status.status)) {
|
|
34753
|
-
const rendered2 = maybeAppendGrepSearchHint(appendPipeStripNote(formatForegroundResult(status), pipeStrip.note), command, aftSearchRegistered);
|
|
34974
|
+
const rendered2 = maybeAppendGrepSearchHint(appendPipeStripNote(formatForegroundResult(status), pipeStrip.note), command, aftSearchRegistered, projectRootFor(context));
|
|
34754
34975
|
const metadataPayload2 = foregroundMetadata(description, status, rendered2);
|
|
34755
34976
|
metadata?.(metadataPayload2);
|
|
34756
34977
|
return { output: rendered2, title: uiTitle, metadata: metadataPayload2 };
|
|
@@ -34814,11 +35035,6 @@ function createBashTool(ctx, aftSearchRegisteredOverride) {
|
|
|
34814
35035
|
}
|
|
34815
35036
|
};
|
|
34816
35037
|
}
|
|
34817
|
-
function appendPipeStripNote(output, note) {
|
|
34818
|
-
return note ? `${output}
|
|
34819
|
-
|
|
34820
|
-
${note}` : output;
|
|
34821
|
-
}
|
|
34822
35038
|
function createBashStatusTool(ctx) {
|
|
34823
35039
|
return {
|
|
34824
35040
|
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.",
|
|
@@ -34923,9 +35139,6 @@ function ptyCacheKey(runtime, taskId) {
|
|
|
34923
35139
|
function preview(output) {
|
|
34924
35140
|
return output.length <= METADATA_PREVIEW_LIMIT ? output : output.slice(-METADATA_PREVIEW_LIMIT);
|
|
34925
35141
|
}
|
|
34926
|
-
function isTerminalStatus(status) {
|
|
34927
|
-
return status === "completed" || status === "failed" || status === "killed" || status === "timed_out";
|
|
34928
|
-
}
|
|
34929
35142
|
function subagentGuidance(taskId) {
|
|
34930
35143
|
return `
|
|
34931
35144
|
|
|
@@ -34941,30 +35154,6 @@ function formatPromotionMessage(taskId, timeout, waitWindowMs) {
|
|
|
34941
35154
|
const waited = timeout !== undefined ? Math.min(timeout, waitWindowMs) : waitWindowMs;
|
|
34942
35155
|
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.`;
|
|
34943
35156
|
}
|
|
34944
|
-
function formatSeconds(ms) {
|
|
34945
|
-
return `${Number((ms / 1000).toFixed(1))}s`;
|
|
34946
|
-
}
|
|
34947
|
-
function formatForegroundResult(data) {
|
|
34948
|
-
const output = data.output_preview ?? "";
|
|
34949
|
-
const outputPath = data.output_path;
|
|
34950
|
-
const truncated = data.output_truncated === true;
|
|
34951
|
-
const status = data.status;
|
|
34952
|
-
const exit = data.exit_code;
|
|
34953
|
-
let rendered = output;
|
|
34954
|
-
if (truncated && outputPath) {
|
|
34955
|
-
rendered += `
|
|
34956
|
-
[output truncated; full output at ${outputPath}]`;
|
|
34957
|
-
}
|
|
34958
|
-
if (status === "timed_out") {
|
|
34959
|
-
rendered += `
|
|
34960
|
-
[command timed out]`;
|
|
34961
|
-
}
|
|
34962
|
-
if (typeof exit === "number" && exit !== 0) {
|
|
34963
|
-
rendered += `
|
|
34964
|
-
[exit code: ${exit}]`;
|
|
34965
|
-
}
|
|
34966
|
-
return rendered;
|
|
34967
|
-
}
|
|
34968
35157
|
function foregroundMetadata(description, data, rendered) {
|
|
34969
35158
|
const outputPath = data.output_path;
|
|
34970
35159
|
return {
|
|
@@ -34975,9 +35164,6 @@ function foregroundMetadata(description, data, rendered) {
|
|
|
34975
35164
|
...outputPath ? { outputPath } : {}
|
|
34976
35165
|
};
|
|
34977
35166
|
}
|
|
34978
|
-
function sleep(ms) {
|
|
34979
|
-
return new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
34980
|
-
}
|
|
34981
35167
|
function getCallID(ctx) {
|
|
34982
35168
|
const c = ctx;
|
|
34983
35169
|
return c.callID ?? c.callId ?? c.call_id;
|
|
@@ -35000,7 +35186,7 @@ function conflictTools(ctx) {
|
|
|
35000
35186
|
execute: async (args, context) => {
|
|
35001
35187
|
const params = {};
|
|
35002
35188
|
if (!isEmptyParam(args?.path)) {
|
|
35003
|
-
const expanded =
|
|
35189
|
+
const expanded = expandTilde2(String(args.path));
|
|
35004
35190
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
35005
35191
|
const resolved = resolvePathFromProjectRoot(projectRoot, expanded);
|
|
35006
35192
|
const denied = await assertExternalDirectoryPermission(context, resolved, {
|
|
@@ -35022,7 +35208,7 @@ function conflictTools(ctx) {
|
|
|
35022
35208
|
|
|
35023
35209
|
// src/tools/hoisted.ts
|
|
35024
35210
|
import * as fs6 from "node:fs";
|
|
35025
|
-
import * as
|
|
35211
|
+
import * as path5 from "node:path";
|
|
35026
35212
|
import { tool as tool8 } from "@opencode-ai/plugin";
|
|
35027
35213
|
|
|
35028
35214
|
// src/patch-parser.ts
|
|
@@ -35462,13 +35648,16 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
|
|
|
35462
35648
|
let scanText = "";
|
|
35463
35649
|
let scanBaseOffset = 0;
|
|
35464
35650
|
const bridgeOptions = {};
|
|
35651
|
+
if (waitFor?.kind === "regex") {
|
|
35652
|
+
await validateWaitRegex(ctx, runtime, waitFor);
|
|
35653
|
+
}
|
|
35465
35654
|
clearSyncWatchAbort(runtime.sessionID);
|
|
35466
35655
|
markTaskWaiting(runtime.sessionID, taskId);
|
|
35467
35656
|
let sawTerminal = false;
|
|
35468
35657
|
try {
|
|
35469
35658
|
while (true) {
|
|
35470
35659
|
const data = await bashStatusSnapshot2(ctx, runtime, taskId, outputMode, bridgeOptions);
|
|
35471
|
-
const terminal =
|
|
35660
|
+
const terminal = isTerminalStatus(data.status);
|
|
35472
35661
|
if (waitFor) {
|
|
35473
35662
|
const scan = await readNewTaskOutput(runtime, taskId, data, spillCursor);
|
|
35474
35663
|
if (scan) {
|
|
@@ -35476,7 +35665,12 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
|
|
|
35476
35665
|
if (scanText.length === 0)
|
|
35477
35666
|
scanBaseOffset = scan.baseOffset;
|
|
35478
35667
|
scanText += scan.text;
|
|
35479
|
-
|
|
35668
|
+
if (waitFor.kind === "regex") {
|
|
35669
|
+
const trimmed = trimWaitScanBuffer(scanText, scanBaseOffset, waitFor);
|
|
35670
|
+
scanText = trimmed.text;
|
|
35671
|
+
scanBaseOffset = trimmed.baseOffset;
|
|
35672
|
+
}
|
|
35673
|
+
const match = await findWaitMatch(ctx, runtime, scanText, waitFor);
|
|
35480
35674
|
if (match) {
|
|
35481
35675
|
if (terminal) {
|
|
35482
35676
|
sawTerminal = true;
|
|
@@ -35487,12 +35681,14 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
|
|
|
35487
35681
|
reason: "matched",
|
|
35488
35682
|
elapsed_ms: Date.now() - startedAt,
|
|
35489
35683
|
match: match.text,
|
|
35490
|
-
match_offset: scanBaseOffset +
|
|
35684
|
+
match_offset: scanBaseOffset + match.byteOffset
|
|
35491
35685
|
});
|
|
35492
35686
|
}
|
|
35493
|
-
|
|
35494
|
-
|
|
35495
|
-
|
|
35687
|
+
if (waitFor.kind === "substring") {
|
|
35688
|
+
const trimmed = trimWaitScanBuffer(scanText, scanBaseOffset, waitFor);
|
|
35689
|
+
scanText = trimmed.text;
|
|
35690
|
+
scanBaseOffset = trimmed.baseOffset;
|
|
35691
|
+
}
|
|
35496
35692
|
}
|
|
35497
35693
|
}
|
|
35498
35694
|
if (terminal) {
|
|
@@ -35507,7 +35703,7 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
|
|
|
35507
35703
|
if (Date.now() >= deadline) {
|
|
35508
35704
|
return withWaited(data, { reason: "timeout", elapsed_ms: Date.now() - startedAt });
|
|
35509
35705
|
}
|
|
35510
|
-
await
|
|
35706
|
+
await sleep(Math.min(BASH_WAIT_POLL_INTERVAL_MS, Math.max(0, deadline - Date.now())));
|
|
35511
35707
|
}
|
|
35512
35708
|
} finally {
|
|
35513
35709
|
if (!sawTerminal)
|
|
@@ -35573,20 +35769,41 @@ function parseWaitPattern(value) {
|
|
|
35573
35769
|
if (typeof value === "string")
|
|
35574
35770
|
return { kind: "substring", value };
|
|
35575
35771
|
if (isRegexWaitObject(value))
|
|
35576
|
-
return { kind: "regex",
|
|
35772
|
+
return { kind: "regex", source: value.regex };
|
|
35577
35773
|
return;
|
|
35578
35774
|
}
|
|
35579
35775
|
function isRegexWaitObject(value) {
|
|
35580
35776
|
return typeof value === "object" && value !== null && "regex" in value && typeof value.regex === "string";
|
|
35581
35777
|
}
|
|
35582
|
-
function
|
|
35778
|
+
async function validateWaitRegex(ctx, runtime, pattern) {
|
|
35779
|
+
await matchRegexWithBridge(ctx, runtime, pattern.source, "");
|
|
35780
|
+
}
|
|
35781
|
+
async function findWaitMatch(ctx, runtime, text, pattern) {
|
|
35583
35782
|
if (pattern.kind === "substring") {
|
|
35584
35783
|
const index = text.indexOf(pattern.value);
|
|
35585
|
-
return index >= 0 ? { text: pattern.value, index } : undefined;
|
|
35784
|
+
return index >= 0 ? { text: pattern.value, byteOffset: Buffer.byteLength(text.slice(0, index), "utf8") } : undefined;
|
|
35586
35785
|
}
|
|
35587
|
-
pattern.
|
|
35588
|
-
|
|
35589
|
-
|
|
35786
|
+
return await matchRegexWithBridge(ctx, runtime, pattern.source, text);
|
|
35787
|
+
}
|
|
35788
|
+
async function matchRegexWithBridge(ctx, runtime, pattern, text) {
|
|
35789
|
+
const result = await callBashBridge(ctx, runtime, "bash_regex_match", { pattern, text });
|
|
35790
|
+
if (result.success === false) {
|
|
35791
|
+
const code = String(result.code ?? "invalid_request");
|
|
35792
|
+
const message = String(result.message ?? "bash_regex_match failed");
|
|
35793
|
+
if (code === "invalid_regex")
|
|
35794
|
+
throw new Error(`invalid_request: invalid_regex: ${message}`);
|
|
35795
|
+
throw new Error(`${code}: ${message}`);
|
|
35796
|
+
}
|
|
35797
|
+
if (result.matched !== true)
|
|
35798
|
+
return;
|
|
35799
|
+
return {
|
|
35800
|
+
text: typeof result.match_text === "string" ? result.match_text : "",
|
|
35801
|
+
byteOffset: coerceMatchOffset(result.match_offset)
|
|
35802
|
+
};
|
|
35803
|
+
}
|
|
35804
|
+
function coerceMatchOffset(value) {
|
|
35805
|
+
const offset = typeof value === "number" ? value : Number(value ?? 0);
|
|
35806
|
+
return Number.isFinite(offset) && offset >= 0 ? offset : 0;
|
|
35590
35807
|
}
|
|
35591
35808
|
function trimWaitScanBuffer(text, baseOffset, pattern) {
|
|
35592
35809
|
const keepFrom = pattern.kind === "substring" ? substringKeepStart(text, pattern.value) : regexKeepStart(text, REGEX_WAIT_SCAN_WINDOW_BYTES);
|
|
@@ -35619,18 +35836,12 @@ function regexKeepStart(text, maxBytes) {
|
|
|
35619
35836
|
function withWaited(data, waited) {
|
|
35620
35837
|
return { ...data, waited };
|
|
35621
35838
|
}
|
|
35622
|
-
function isTerminalStatus2(status) {
|
|
35623
|
-
return status === "completed" || status === "failed" || status === "killed" || status === "timed_out";
|
|
35624
|
-
}
|
|
35625
35839
|
function ptyCacheKey2(runtime, taskId) {
|
|
35626
35840
|
return `${projectRootFor(runtime)}::${runtime.sessionID ?? "__default__"}::${taskId}`;
|
|
35627
35841
|
}
|
|
35628
35842
|
function watchPtyCacheKey(runtime, taskId) {
|
|
35629
35843
|
return `${ptyCacheKey2(runtime, taskId)}::watch`;
|
|
35630
35844
|
}
|
|
35631
|
-
function sleep2(ms) {
|
|
35632
|
-
return new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
35633
|
-
}
|
|
35634
35845
|
|
|
35635
35846
|
// src/tools/bash_write.ts
|
|
35636
35847
|
import { tool as tool7 } from "@opencode-ai/plugin";
|
|
@@ -35665,21 +35876,10 @@ function createBashWriteTool(ctx) {
|
|
|
35665
35876
|
|
|
35666
35877
|
// src/tools/hoisted.ts
|
|
35667
35878
|
function relativeToWorktree(fp, worktree) {
|
|
35668
|
-
return
|
|
35879
|
+
return path5.relative(worktree, fp);
|
|
35669
35880
|
}
|
|
35670
|
-
function
|
|
35671
|
-
|
|
35672
|
-
return "";
|
|
35673
|
-
if (!data.truncated)
|
|
35674
|
-
return "";
|
|
35675
|
-
const startLine = data.start_line;
|
|
35676
|
-
const endLine = data.end_line;
|
|
35677
|
-
const totalLines = data.total_lines;
|
|
35678
|
-
if (startLine === undefined || endLine === undefined || totalLines === undefined) {
|
|
35679
|
-
return "";
|
|
35680
|
-
}
|
|
35681
|
-
return `
|
|
35682
|
-
(Showing lines ${startLine}-${endLine} of ${totalLines}. Use startLine/endLine to read other sections.)`;
|
|
35881
|
+
function formatReadFooter2(agentSpecifiedRange, data) {
|
|
35882
|
+
return formatReadFooter(agentSpecifiedRange, data, { rangeHint: "startLine/endLine" });
|
|
35683
35883
|
}
|
|
35684
35884
|
function buildUnifiedDiff(fp, before, after) {
|
|
35685
35885
|
const beforeLines = before.split(`
|
|
@@ -35872,6 +36072,91 @@ var z8 = tool8.schema;
|
|
|
35872
36072
|
function diagnosticsOnEditDefault(ctx) {
|
|
35873
36073
|
return ctx.config.lsp?.diagnostics_on_edit ?? false;
|
|
35874
36074
|
}
|
|
36075
|
+
async function readCurrentFileForPreview(filePath) {
|
|
36076
|
+
try {
|
|
36077
|
+
return await fs6.promises.readFile(filePath, "utf-8");
|
|
36078
|
+
} catch (error50) {
|
|
36079
|
+
if (error50 && typeof error50 === "object" && "code" in error50 && error50.code === "ENOENT") {
|
|
36080
|
+
return "";
|
|
36081
|
+
}
|
|
36082
|
+
throw error50;
|
|
36083
|
+
}
|
|
36084
|
+
}
|
|
36085
|
+
function previewDiffFromResponse(data, filePath) {
|
|
36086
|
+
const previewDiff = data.preview_diff;
|
|
36087
|
+
if (typeof previewDiff === "string")
|
|
36088
|
+
return previewDiff;
|
|
36089
|
+
const diff = data.diff;
|
|
36090
|
+
if (typeof diff?.before === "string" && typeof diff.after === "string") {
|
|
36091
|
+
return buildUnifiedDiff(filePath, diff.before, diff.after);
|
|
36092
|
+
}
|
|
36093
|
+
return "";
|
|
36094
|
+
}
|
|
36095
|
+
function virtualPatchContent(virtualFiles, filePath) {
|
|
36096
|
+
return virtualFiles.has(filePath) ? virtualFiles.get(filePath) ?? null : undefined;
|
|
36097
|
+
}
|
|
36098
|
+
async function readPatchPreviewContent(virtualFiles, filePath, action, patchPath) {
|
|
36099
|
+
const virtualContent = virtualPatchContent(virtualFiles, filePath);
|
|
36100
|
+
if (virtualContent !== undefined) {
|
|
36101
|
+
if (virtualContent === null) {
|
|
36102
|
+
throw new Error(`Failed to ${action} ${patchPath}: file not found: ${filePath}`);
|
|
36103
|
+
}
|
|
36104
|
+
return virtualContent;
|
|
36105
|
+
}
|
|
36106
|
+
try {
|
|
36107
|
+
return await fs6.promises.readFile(filePath, "utf-8");
|
|
36108
|
+
} catch (error50) {
|
|
36109
|
+
throw new Error(`Failed to ${action} ${patchPath}: ${formatError2(error50)}`);
|
|
36110
|
+
}
|
|
36111
|
+
}
|
|
36112
|
+
async function buildApplyPatchPreview(hunks, projectRoot) {
|
|
36113
|
+
const virtualFiles = new Map;
|
|
36114
|
+
const patches = [];
|
|
36115
|
+
let firstFilePath = "";
|
|
36116
|
+
for (const hunk of hunks) {
|
|
36117
|
+
const filePath = resolvePathFromProjectRoot(projectRoot, hunk.path);
|
|
36118
|
+
if (!firstFilePath)
|
|
36119
|
+
firstFilePath = filePath;
|
|
36120
|
+
switch (hunk.type) {
|
|
36121
|
+
case "add": {
|
|
36122
|
+
const virtualContent = virtualPatchContent(virtualFiles, filePath);
|
|
36123
|
+
const exists = virtualContent !== undefined ? virtualContent !== null : fs6.existsSync(filePath);
|
|
36124
|
+
if (exists) {
|
|
36125
|
+
throw new Error(`Failed to create ${hunk.path}: file already exists. Use *** Update File: to modify, or *** Delete File: first if you want to replace it entirely.`);
|
|
36126
|
+
}
|
|
36127
|
+
const after = hunk.contents.endsWith(`
|
|
36128
|
+
`) ? hunk.contents : `${hunk.contents}
|
|
36129
|
+
`;
|
|
36130
|
+
patches.push(buildUnifiedDiff(filePath, "", after));
|
|
36131
|
+
virtualFiles.set(filePath, after);
|
|
36132
|
+
break;
|
|
36133
|
+
}
|
|
36134
|
+
case "delete": {
|
|
36135
|
+
const before = await readPatchPreviewContent(virtualFiles, filePath, "delete", hunk.path);
|
|
36136
|
+
patches.push(buildUnifiedDiff(filePath, before, ""));
|
|
36137
|
+
virtualFiles.set(filePath, null);
|
|
36138
|
+
break;
|
|
36139
|
+
}
|
|
36140
|
+
case "update": {
|
|
36141
|
+
const before = await readPatchPreviewContent(virtualFiles, filePath, "update", hunk.path);
|
|
36142
|
+
let after;
|
|
36143
|
+
try {
|
|
36144
|
+
after = applyUpdateChunks(before, filePath, hunk.chunks);
|
|
36145
|
+
} catch (error50) {
|
|
36146
|
+
throw new Error(`Failed to update ${hunk.path}: ${formatError2(error50)}`);
|
|
36147
|
+
}
|
|
36148
|
+
const targetPath = hunk.move_path ? resolvePathFromProjectRoot(projectRoot, hunk.move_path) : filePath;
|
|
36149
|
+
patches.push(buildUnifiedDiff(targetPath, before, after));
|
|
36150
|
+
if (hunk.move_path)
|
|
36151
|
+
virtualFiles.set(filePath, null);
|
|
36152
|
+
virtualFiles.set(targetPath, after);
|
|
36153
|
+
break;
|
|
36154
|
+
}
|
|
36155
|
+
}
|
|
36156
|
+
}
|
|
36157
|
+
return { filepath: firstFilePath || projectRoot, diff: patches.join(`
|
|
36158
|
+
`) };
|
|
36159
|
+
}
|
|
35875
36160
|
var READ_DESCRIPTION = `Read file contents or list directory entries.
|
|
35876
36161
|
|
|
35877
36162
|
Use either startLine/endLine OR offset/limit to read a section of a file.
|
|
@@ -35921,7 +36206,7 @@ function createReadTool(ctx) {
|
|
|
35921
36206
|
return permissionDeniedResponse(error50.message);
|
|
35922
36207
|
return permissionDeniedResponse("Permission denied.");
|
|
35923
36208
|
}
|
|
35924
|
-
const ext =
|
|
36209
|
+
const ext = path5.extname(filePath).toLowerCase();
|
|
35925
36210
|
const mimeMap = {
|
|
35926
36211
|
".png": "image/png",
|
|
35927
36212
|
".jpg": "image/jpeg",
|
|
@@ -35950,7 +36235,7 @@ function createReadTool(ctx) {
|
|
|
35950
36235
|
const msg = `${label} read successfully`;
|
|
35951
36236
|
return {
|
|
35952
36237
|
output: `${msg} (${ext.slice(1).toUpperCase()}, ${sizeStr}). File: ${filePath}`,
|
|
35953
|
-
title:
|
|
36238
|
+
title: path5.relative(projectRoot, filePath),
|
|
35954
36239
|
metadata: {
|
|
35955
36240
|
preview: msg,
|
|
35956
36241
|
filepath: filePath,
|
|
@@ -35992,7 +36277,7 @@ function createReadTool(ctx) {
|
|
|
35992
36277
|
}
|
|
35993
36278
|
let output = data.content;
|
|
35994
36279
|
const agentSpecifiedRange = args.startLine !== undefined || args.endLine !== undefined || args.offset !== undefined || args.limit !== undefined;
|
|
35995
|
-
const footer =
|
|
36280
|
+
const footer = formatReadFooter2(agentSpecifiedRange, data);
|
|
35996
36281
|
if (footer)
|
|
35997
36282
|
output += footer;
|
|
35998
36283
|
return { output, title: dp, metadata: { title: dp } };
|
|
@@ -36014,18 +36299,20 @@ function createWriteTool(ctx, editToolName = "edit") {
|
|
|
36014
36299
|
const content = args.content;
|
|
36015
36300
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
36016
36301
|
const filePath = resolvePathFromProjectRoot(projectRoot, file2);
|
|
36017
|
-
const relPath =
|
|
36302
|
+
const relPath = path5.relative(projectRoot, filePath);
|
|
36018
36303
|
{
|
|
36019
|
-
const
|
|
36020
|
-
if (
|
|
36021
|
-
return permissionDeniedResponse(
|
|
36022
|
-
}
|
|
36023
|
-
await
|
|
36024
|
-
|
|
36025
|
-
|
|
36026
|
-
|
|
36027
|
-
|
|
36028
|
-
})
|
|
36304
|
+
const denial2 = await assertExternalDirectoryPermission(context, filePath);
|
|
36305
|
+
if (denial2)
|
|
36306
|
+
return permissionDeniedResponse(denial2);
|
|
36307
|
+
}
|
|
36308
|
+
const currentContent = await readCurrentFileForPreview(filePath);
|
|
36309
|
+
const previewDiff = buildUnifiedDiff(filePath, currentContent, content);
|
|
36310
|
+
const denial = await askEditPermission(context, [relPath], {
|
|
36311
|
+
filepath: filePath,
|
|
36312
|
+
diff: previewDiff
|
|
36313
|
+
});
|
|
36314
|
+
if (denial)
|
|
36315
|
+
return permissionDeniedResponse(denial);
|
|
36029
36316
|
const data = await callBridge(ctx, context, "write", {
|
|
36030
36317
|
file: filePath,
|
|
36031
36318
|
content,
|
|
@@ -36163,18 +36450,12 @@ function createEditTool(ctx, writeToolName = "write") {
|
|
|
36163
36450
|
throw new Error("'filePath' parameter is required");
|
|
36164
36451
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
36165
36452
|
const filePath = resolvePathFromProjectRoot(projectRoot, file2);
|
|
36166
|
-
const relPath =
|
|
36453
|
+
const relPath = path5.relative(projectRoot, filePath);
|
|
36167
36454
|
{
|
|
36168
|
-
const
|
|
36169
|
-
if (
|
|
36170
|
-
return permissionDeniedResponse(
|
|
36455
|
+
const denial2 = await assertExternalDirectoryPermission(context, filePath);
|
|
36456
|
+
if (denial2)
|
|
36457
|
+
return permissionDeniedResponse(denial2);
|
|
36171
36458
|
}
|
|
36172
|
-
await runAsk(context.ask({
|
|
36173
|
-
permission: "edit",
|
|
36174
|
-
patterns: [relPath],
|
|
36175
|
-
always: ["*"],
|
|
36176
|
-
metadata: { filepath: filePath }
|
|
36177
|
-
}));
|
|
36178
36459
|
const params = { file: filePath };
|
|
36179
36460
|
let command;
|
|
36180
36461
|
if (typeof args.appendContent === "string") {
|
|
@@ -36217,6 +36498,21 @@ function createEditTool(ctx, writeToolName = "write") {
|
|
|
36217
36498
|
const hint = typeof args.content === "string" ? ` To write the whole file, use the '${writeToolName}' tool. To edit existing content, provide 'oldString' (and optionally 'newString'), 'symbol' + 'content', or an 'edits' array.` : " Provide 'oldString' (+ optional 'newString'), 'symbol' + 'content', or an 'edits' array.";
|
|
36218
36499
|
throw new Error(`edit: no edit mode resolved from arguments.${hint}`);
|
|
36219
36500
|
}
|
|
36501
|
+
const previewData = await callBridge(ctx, context, command, {
|
|
36502
|
+
...params,
|
|
36503
|
+
preview: true,
|
|
36504
|
+
include_diff_content: true
|
|
36505
|
+
});
|
|
36506
|
+
if (previewData.success === false) {
|
|
36507
|
+
throw new Error(previewData.message || "edit preview failed");
|
|
36508
|
+
}
|
|
36509
|
+
const previewDiff = previewDiffFromResponse(previewData, filePath);
|
|
36510
|
+
const denial = await askEditPermission(context, [relPath], {
|
|
36511
|
+
filepath: filePath,
|
|
36512
|
+
diff: previewDiff
|
|
36513
|
+
});
|
|
36514
|
+
if (denial)
|
|
36515
|
+
return permissionDeniedResponse(denial);
|
|
36220
36516
|
params.diagnostics = diagnosticsOnEditDefault(ctx);
|
|
36221
36517
|
params.include_diff_content = true;
|
|
36222
36518
|
const data = await callBridge(ctx, context, command, params);
|
|
@@ -36357,22 +36653,34 @@ function createApplyPatchTool(ctx) {
|
|
|
36357
36653
|
}
|
|
36358
36654
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
36359
36655
|
const affectedAbs = new Set;
|
|
36656
|
+
const initiallyExistsAbs = new Map;
|
|
36657
|
+
const rememberAffectedPath = (abs) => {
|
|
36658
|
+
affectedAbs.add(abs);
|
|
36659
|
+
if (!initiallyExistsAbs.has(abs)) {
|
|
36660
|
+
initiallyExistsAbs.set(abs, fs6.existsSync(abs));
|
|
36661
|
+
}
|
|
36662
|
+
};
|
|
36663
|
+
for (const h of hunks) {
|
|
36664
|
+
const srcAbs = resolvePathFromProjectRoot(projectRoot, h.path);
|
|
36665
|
+
rememberAffectedPath(srcAbs);
|
|
36666
|
+
if (h.type === "update" && h.move_path) {
|
|
36667
|
+
rememberAffectedPath(resolvePathFromProjectRoot(projectRoot, h.move_path));
|
|
36668
|
+
}
|
|
36669
|
+
}
|
|
36360
36670
|
const newlyCreatedAbs = new Set;
|
|
36361
36671
|
for (const h of hunks) {
|
|
36362
36672
|
const srcAbs = resolvePathFromProjectRoot(projectRoot, h.path);
|
|
36363
|
-
|
|
36364
|
-
if (h.type === "add") {
|
|
36673
|
+
if (h.type === "add" && initiallyExistsAbs.get(srcAbs) === false) {
|
|
36365
36674
|
newlyCreatedAbs.add(srcAbs);
|
|
36366
36675
|
}
|
|
36367
36676
|
if (h.type === "update" && h.move_path) {
|
|
36368
36677
|
const dstAbs = resolvePathFromProjectRoot(projectRoot, h.move_path);
|
|
36369
|
-
|
|
36370
|
-
if (!fs6.existsSync(dstAbs)) {
|
|
36678
|
+
if (initiallyExistsAbs.get(dstAbs) === false) {
|
|
36371
36679
|
newlyCreatedAbs.add(dstAbs);
|
|
36372
36680
|
}
|
|
36373
36681
|
}
|
|
36374
36682
|
}
|
|
36375
|
-
const relPaths = Array.from(affectedAbs).map((abs) =>
|
|
36683
|
+
const relPaths = Array.from(affectedAbs).map((abs) => path5.relative(projectRoot, abs));
|
|
36376
36684
|
const multiFileWritePaths = Array.from(affectedAbs);
|
|
36377
36685
|
{
|
|
36378
36686
|
const asked = new Set;
|
|
@@ -36380,17 +36688,18 @@ function createApplyPatchTool(ctx) {
|
|
|
36380
36688
|
if (asked.has(filePath))
|
|
36381
36689
|
continue;
|
|
36382
36690
|
asked.add(filePath);
|
|
36383
|
-
const
|
|
36384
|
-
if (
|
|
36385
|
-
return permissionDeniedResponse(
|
|
36691
|
+
const denial2 = await assertExternalDirectoryPermission(context, filePath);
|
|
36692
|
+
if (denial2)
|
|
36693
|
+
return permissionDeniedResponse(denial2);
|
|
36386
36694
|
}
|
|
36387
36695
|
}
|
|
36388
|
-
await
|
|
36389
|
-
|
|
36390
|
-
|
|
36391
|
-
|
|
36392
|
-
|
|
36393
|
-
|
|
36696
|
+
const preview2 = await buildApplyPatchPreview(hunks, projectRoot);
|
|
36697
|
+
const denial = await askEditPermission(context, relPaths, {
|
|
36698
|
+
filepath: preview2.filepath,
|
|
36699
|
+
diff: preview2.diff
|
|
36700
|
+
});
|
|
36701
|
+
if (denial)
|
|
36702
|
+
return permissionDeniedResponse(denial);
|
|
36394
36703
|
const checkpointPaths = Array.from(affectedAbs).filter((abs) => !newlyCreatedAbs.has(abs));
|
|
36395
36704
|
const checkpointName = `apply_patch_${Date.now()}`;
|
|
36396
36705
|
let checkpointCreated = false;
|
|
@@ -36405,15 +36714,15 @@ function createApplyPatchTool(ctx) {
|
|
|
36405
36714
|
}
|
|
36406
36715
|
const results = [];
|
|
36407
36716
|
const failures = [];
|
|
36408
|
-
const
|
|
36409
|
-
for (const hunk of hunks) {
|
|
36717
|
+
const appliedHunkResults = [];
|
|
36718
|
+
for (const [hunkIndex, hunk] of hunks.entries()) {
|
|
36410
36719
|
const filePath = resolvePathFromProjectRoot(projectRoot, hunk.path);
|
|
36411
36720
|
switch (hunk.type) {
|
|
36412
36721
|
case "add": {
|
|
36413
36722
|
if (fs6.existsSync(filePath)) {
|
|
36414
36723
|
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.`;
|
|
36415
36724
|
results.push(msg);
|
|
36416
|
-
failures.push(hunk.path);
|
|
36725
|
+
failures.push({ index: hunkIndex, path: hunk.path });
|
|
36417
36726
|
break;
|
|
36418
36727
|
}
|
|
36419
36728
|
try {
|
|
@@ -36435,10 +36744,13 @@ function createApplyPatchTool(ctx) {
|
|
|
36435
36744
|
throw new Error("produced invalid syntax (rolled back)");
|
|
36436
36745
|
}
|
|
36437
36746
|
const wrDiff = writeResult.diff;
|
|
36438
|
-
|
|
36747
|
+
appliedHunkResults.push({
|
|
36748
|
+
index: hunkIndex,
|
|
36749
|
+
hunk,
|
|
36439
36750
|
filePath,
|
|
36751
|
+
displayPath: filePath,
|
|
36440
36752
|
before: "",
|
|
36441
|
-
after:
|
|
36753
|
+
after: content,
|
|
36442
36754
|
additions: wrDiff?.additions ?? lineCount(content),
|
|
36443
36755
|
deletions: wrDiff?.deletions ?? 0
|
|
36444
36756
|
});
|
|
@@ -36446,7 +36758,7 @@ function createApplyPatchTool(ctx) {
|
|
|
36446
36758
|
} catch (e) {
|
|
36447
36759
|
const msg = `Failed to create ${hunk.path}: ${e instanceof Error ? e.message : e}`;
|
|
36448
36760
|
results.push(msg);
|
|
36449
|
-
failures.push(hunk.path);
|
|
36761
|
+
failures.push({ index: hunkIndex, path: hunk.path });
|
|
36450
36762
|
const filePath2 = resolvePathFromProjectRoot(projectRoot, hunk.path);
|
|
36451
36763
|
if (fs6.existsSync(filePath2)) {
|
|
36452
36764
|
try {
|
|
@@ -36465,8 +36777,11 @@ function createApplyPatchTool(ctx) {
|
|
|
36465
36777
|
if (deleteResult.success === false) {
|
|
36466
36778
|
throw new Error(deleteResult.message ?? "delete failed");
|
|
36467
36779
|
}
|
|
36468
|
-
|
|
36780
|
+
appliedHunkResults.push({
|
|
36781
|
+
index: hunkIndex,
|
|
36782
|
+
hunk,
|
|
36469
36783
|
filePath,
|
|
36784
|
+
displayPath: filePath,
|
|
36470
36785
|
before,
|
|
36471
36786
|
after: "",
|
|
36472
36787
|
additions: 0,
|
|
@@ -36475,7 +36790,7 @@ function createApplyPatchTool(ctx) {
|
|
|
36475
36790
|
results.push(`Deleted ${hunk.path}`);
|
|
36476
36791
|
} catch (e) {
|
|
36477
36792
|
results.push(`Failed to delete ${hunk.path}: ${e instanceof Error ? e.message : e}`);
|
|
36478
|
-
failures.push(hunk.path);
|
|
36793
|
+
failures.push({ index: hunkIndex, path: hunk.path });
|
|
36479
36794
|
}
|
|
36480
36795
|
break;
|
|
36481
36796
|
}
|
|
@@ -36502,7 +36817,7 @@ function createApplyPatchTool(ctx) {
|
|
|
36502
36817
|
if (diags && diags.length > 0) {
|
|
36503
36818
|
const errors3 = diags.filter((d) => d.severity === "error");
|
|
36504
36819
|
if (errors3.length > 0) {
|
|
36505
|
-
const relPath =
|
|
36820
|
+
const relPath = path5.relative(projectRoot, targetPath);
|
|
36506
36821
|
const diagLines = errors3.map((d) => ` Line ${d.line}: ${d.message}`).join(`
|
|
36507
36822
|
`);
|
|
36508
36823
|
results.push(`
|
|
@@ -36516,13 +36831,17 @@ ${diagLines}`);
|
|
|
36516
36831
|
additions: wrDiff.additions,
|
|
36517
36832
|
deletions: wrDiff.deletions
|
|
36518
36833
|
};
|
|
36519
|
-
|
|
36834
|
+
const appliedHunkResult = {
|
|
36835
|
+
index: hunkIndex,
|
|
36836
|
+
hunk,
|
|
36520
36837
|
filePath,
|
|
36838
|
+
displayPath: targetPath,
|
|
36839
|
+
...hunk.move_path ? { movePath: targetPath } : {},
|
|
36521
36840
|
before: original,
|
|
36522
36841
|
after: newContent,
|
|
36523
36842
|
additions,
|
|
36524
36843
|
deletions
|
|
36525
|
-
}
|
|
36844
|
+
};
|
|
36526
36845
|
if (hunk.move_path) {
|
|
36527
36846
|
try {
|
|
36528
36847
|
const deleteResult = await callBridge(ctx, context, "delete_file", {
|
|
@@ -36555,13 +36874,15 @@ ${diagLines}`);
|
|
|
36555
36874
|
}
|
|
36556
36875
|
throw new Error(`source delete failed after writing move destination; restored pre-patch checkpoint ${checkpointName}: ${formatError2(deleteError)}`);
|
|
36557
36876
|
}
|
|
36877
|
+
appliedHunkResults.push(appliedHunkResult);
|
|
36558
36878
|
results.push(`Updated and moved ${hunk.path} → ${hunk.move_path}`);
|
|
36559
36879
|
} else {
|
|
36880
|
+
appliedHunkResults.push(appliedHunkResult);
|
|
36560
36881
|
results.push(`Updated ${hunk.path}`);
|
|
36561
36882
|
}
|
|
36562
36883
|
} catch (e) {
|
|
36563
36884
|
results.push(`Failed to update ${hunk.path}: ${e instanceof Error ? e.message : e}`);
|
|
36564
|
-
failures.push(hunk.path);
|
|
36885
|
+
failures.push({ index: hunkIndex, path: hunk.path });
|
|
36565
36886
|
break;
|
|
36566
36887
|
}
|
|
36567
36888
|
break;
|
|
@@ -36570,7 +36891,8 @@ ${diagLines}`);
|
|
|
36570
36891
|
}
|
|
36571
36892
|
if (failures.length > 0) {
|
|
36572
36893
|
const partial2 = failures.length < hunks.length;
|
|
36573
|
-
const
|
|
36894
|
+
const failedList = failures.map((failure) => failure.path).join(", ");
|
|
36895
|
+
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}.`;
|
|
36574
36896
|
results.push(summary);
|
|
36575
36897
|
if (!partial2) {
|
|
36576
36898
|
throw new Error(results.join(`
|
|
@@ -36578,28 +36900,56 @@ ${diagLines}`);
|
|
|
36578
36900
|
}
|
|
36579
36901
|
}
|
|
36580
36902
|
{
|
|
36581
|
-
const
|
|
36582
|
-
const
|
|
36583
|
-
|
|
36584
|
-
|
|
36585
|
-
|
|
36586
|
-
|
|
36587
|
-
|
|
36588
|
-
|
|
36589
|
-
|
|
36590
|
-
|
|
36591
|
-
|
|
36592
|
-
|
|
36593
|
-
|
|
36594
|
-
|
|
36903
|
+
const diffByReportKey = new Map;
|
|
36904
|
+
for (const applied of appliedHunkResults) {
|
|
36905
|
+
const reportKey = applied.movePath ? `${applied.filePath}\x00${applied.displayPath}` : applied.filePath;
|
|
36906
|
+
const existing = diffByReportKey.get(reportKey);
|
|
36907
|
+
if (!existing) {
|
|
36908
|
+
diffByReportKey.set(reportKey, {
|
|
36909
|
+
filePath: applied.filePath,
|
|
36910
|
+
displayPath: applied.displayPath,
|
|
36911
|
+
...applied.movePath ? { movePath: applied.movePath } : {},
|
|
36912
|
+
lastHunk: applied.hunk,
|
|
36913
|
+
before: applied.before,
|
|
36914
|
+
after: applied.after,
|
|
36915
|
+
additions: applied.additions,
|
|
36916
|
+
deletions: applied.deletions,
|
|
36917
|
+
hunkCount: 1
|
|
36918
|
+
});
|
|
36919
|
+
continue;
|
|
36920
|
+
}
|
|
36921
|
+
existing.displayPath = applied.displayPath;
|
|
36922
|
+
existing.movePath = applied.movePath ?? existing.movePath;
|
|
36923
|
+
existing.lastHunk = applied.hunk;
|
|
36924
|
+
existing.after = applied.after;
|
|
36925
|
+
existing.hunkCount += 1;
|
|
36926
|
+
const netCounts = countDiffLines(existing.before, existing.after);
|
|
36927
|
+
existing.additions = netCounts.additions;
|
|
36928
|
+
existing.deletions = netCounts.deletions;
|
|
36929
|
+
}
|
|
36930
|
+
const files = Array.from(diffByReportKey.values()).map((entry) => {
|
|
36931
|
+
const relPath = path5.relative(projectRoot, entry.displayPath);
|
|
36932
|
+
const patch = buildUnifiedDiff(entry.displayPath, entry.before, entry.after);
|
|
36933
|
+
let uiType;
|
|
36934
|
+
if (entry.movePath) {
|
|
36935
|
+
uiType = "move";
|
|
36936
|
+
} else if (entry.hunkCount === 1) {
|
|
36937
|
+
uiType = entry.lastHunk.type;
|
|
36938
|
+
} else if (entry.before.length === 0 && entry.after.length > 0) {
|
|
36939
|
+
uiType = "add";
|
|
36940
|
+
} else if (entry.before.length > 0 && entry.after.length === 0) {
|
|
36941
|
+
uiType = "delete";
|
|
36942
|
+
} else {
|
|
36943
|
+
uiType = "update";
|
|
36944
|
+
}
|
|
36595
36945
|
return {
|
|
36596
|
-
filePath,
|
|
36946
|
+
filePath: entry.filePath,
|
|
36597
36947
|
relativePath: relPath,
|
|
36598
36948
|
type: uiType,
|
|
36599
36949
|
patch,
|
|
36600
|
-
additions,
|
|
36601
|
-
deletions,
|
|
36602
|
-
...movePath ? { movePath } : {}
|
|
36950
|
+
additions: entry.additions,
|
|
36951
|
+
deletions: entry.deletions,
|
|
36952
|
+
...entry.movePath ? { movePath: entry.movePath } : {}
|
|
36603
36953
|
};
|
|
36604
36954
|
});
|
|
36605
36955
|
const fileList = files.map((f) => {
|
|
@@ -36607,7 +36957,7 @@ ${diagLines}`);
|
|
|
36607
36957
|
return `${prefix} ${f.relativePath}`;
|
|
36608
36958
|
}).join(`
|
|
36609
36959
|
`);
|
|
36610
|
-
const title = failures.length > 0 ? `Partially applied (${
|
|
36960
|
+
const title = failures.length > 0 ? `Partially applied (${hunks.length - failures.length} of ${hunks.length}). Updated:
|
|
36611
36961
|
${fileList}` : `Success. Updated the following files:
|
|
36612
36962
|
${fileList}`;
|
|
36613
36963
|
const diffText = files.map((f) => f.patch).filter(Boolean).join(`
|
|
@@ -36760,18 +37110,20 @@ function aftPrefixedTools(ctx) {
|
|
|
36760
37110
|
const file2 = normalizedArgs.filePath;
|
|
36761
37111
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
36762
37112
|
const filePath = resolvePathFromProjectRoot(projectRoot, file2);
|
|
36763
|
-
const relPath =
|
|
37113
|
+
const relPath = path5.relative(projectRoot, filePath);
|
|
36764
37114
|
{
|
|
36765
|
-
const
|
|
36766
|
-
if (
|
|
36767
|
-
return permissionDeniedResponse(
|
|
37115
|
+
const denial2 = await assertExternalDirectoryPermission(context, filePath);
|
|
37116
|
+
if (denial2)
|
|
37117
|
+
return permissionDeniedResponse(denial2);
|
|
36768
37118
|
}
|
|
36769
|
-
await
|
|
36770
|
-
|
|
36771
|
-
|
|
36772
|
-
|
|
36773
|
-
|
|
36774
|
-
})
|
|
37119
|
+
const currentContent = await readCurrentFileForPreview(filePath);
|
|
37120
|
+
const previewDiff = buildUnifiedDiff(filePath, currentContent, normalizedArgs.content);
|
|
37121
|
+
const denial = await askEditPermission(context, [relPath], {
|
|
37122
|
+
filepath: filePath,
|
|
37123
|
+
diff: previewDiff
|
|
37124
|
+
});
|
|
37125
|
+
if (denial)
|
|
37126
|
+
return permissionDeniedResponse(denial);
|
|
36775
37127
|
const writeParams = {
|
|
36776
37128
|
file: filePath,
|
|
36777
37129
|
content: normalizedArgs.content,
|
|
@@ -37155,15 +37507,15 @@ function buildZoomTitle(args) {
|
|
|
37155
37507
|
}
|
|
37156
37508
|
return `${args.targets.filePath}#${args.targets.symbol}`;
|
|
37157
37509
|
}
|
|
37158
|
-
const
|
|
37510
|
+
const path6 = args.filePath ?? args.url ?? "";
|
|
37159
37511
|
if (typeof args.symbols === "string")
|
|
37160
|
-
return
|
|
37512
|
+
return path6 ? `${path6}#${args.symbols}` : args.symbols;
|
|
37161
37513
|
if (Array.isArray(args.symbols) && args.symbols.length > 0) {
|
|
37162
37514
|
if (args.symbols.length === 1)
|
|
37163
|
-
return
|
|
37164
|
-
return
|
|
37515
|
+
return path6 ? `${path6}#${args.symbols[0]}` : args.symbols[0];
|
|
37516
|
+
return path6 ? `${path6} (${args.symbols.length} symbols)` : `${args.symbols.length} symbols`;
|
|
37165
37517
|
}
|
|
37166
|
-
return
|
|
37518
|
+
return path6 || "(no target)";
|
|
37167
37519
|
}
|
|
37168
37520
|
function readingTools(ctx) {
|
|
37169
37521
|
return {
|
|
@@ -37396,6 +37748,11 @@ function readingTools(ctx) {
|
|
|
37396
37748
|
}));
|
|
37397
37749
|
if (symbolsArray.length === 1) {
|
|
37398
37750
|
const response = results[0] ?? { success: false, message: "missing zoom response" };
|
|
37751
|
+
const rustBatch = unwrapRustZoomBatchEnvelope(response);
|
|
37752
|
+
if (rustBatch) {
|
|
37753
|
+
const batch = formatZoomBatchResult(targetLabel, rustBatch.names, rustBatch.responses);
|
|
37754
|
+
return withMeta(batch.text);
|
|
37755
|
+
}
|
|
37399
37756
|
if (response.success === false) {
|
|
37400
37757
|
throw new Error(response.message || "zoom failed");
|
|
37401
37758
|
}
|
|
@@ -37664,11 +38021,11 @@ function refactoringTools(ctx) {
|
|
|
37664
38021
|
}
|
|
37665
38022
|
|
|
37666
38023
|
// src/tools/safety.ts
|
|
37667
|
-
import * as
|
|
38024
|
+
import * as path6 from "node:path";
|
|
37668
38025
|
import { tool as tool14 } from "@opencode-ai/plugin";
|
|
37669
38026
|
var z14 = tool14.schema;
|
|
37670
38027
|
function responsePaths(response) {
|
|
37671
|
-
return Array.isArray(response.paths) ? response.paths.filter((
|
|
38028
|
+
return Array.isArray(response.paths) ? response.paths.filter((path7) => typeof path7 === "string" && path7.length > 0) : [];
|
|
37672
38029
|
}
|
|
37673
38030
|
function bridgeErrorMessage(response, fallback) {
|
|
37674
38031
|
return typeof response.message === "string" && response.message.length > 0 ? response.message : fallback;
|
|
@@ -37745,9 +38102,9 @@ function safetyTools(ctx) {
|
|
|
37745
38102
|
for (const rawFile of checkpointFiles) {
|
|
37746
38103
|
if (typeof rawFile !== "string")
|
|
37747
38104
|
continue;
|
|
37748
|
-
const file2 =
|
|
37749
|
-
const abs =
|
|
37750
|
-
const parent =
|
|
38105
|
+
const file2 = expandTilde2(rawFile);
|
|
38106
|
+
const abs = path6.isAbsolute(file2) ? file2 : path6.resolve(projectRoot, file2);
|
|
38107
|
+
const parent = path6.dirname(abs);
|
|
37751
38108
|
if (uniqueParents.has(parent))
|
|
37752
38109
|
continue;
|
|
37753
38110
|
uniqueParents.add(parent);
|
|
@@ -37785,8 +38142,8 @@ function safetyTools(ctx) {
|
|
|
37785
38142
|
const params = {};
|
|
37786
38143
|
if (args.name !== undefined)
|
|
37787
38144
|
params.name = args.name;
|
|
37788
|
-
const payloadFiles = coerceStringArray(args.files).map(
|
|
37789
|
-
const filePathArg = typeof args.filePath === "string" ?
|
|
38145
|
+
const payloadFiles = coerceStringArray(args.files).map(expandTilde2);
|
|
38146
|
+
const filePathArg = typeof args.filePath === "string" ? expandTilde2(args.filePath) : undefined;
|
|
37790
38147
|
if (op === "checkpoint") {
|
|
37791
38148
|
if (payloadFiles.length > 0) {
|
|
37792
38149
|
params.files = payloadFiles;
|
|
@@ -37811,7 +38168,7 @@ function safetyTools(ctx) {
|
|
|
37811
38168
|
|
|
37812
38169
|
// src/tools/search.ts
|
|
37813
38170
|
import * as fs7 from "node:fs";
|
|
37814
|
-
import * as
|
|
38171
|
+
import * as path7 from "node:path";
|
|
37815
38172
|
function arg2(schema) {
|
|
37816
38173
|
return schema;
|
|
37817
38174
|
}
|
|
@@ -37843,7 +38200,7 @@ function normalizeGlob(pattern) {
|
|
|
37843
38200
|
return pattern;
|
|
37844
38201
|
}
|
|
37845
38202
|
function absoluteSearchPath(projectRoot, target) {
|
|
37846
|
-
return resolvePathFromProjectRoot(projectRoot,
|
|
38203
|
+
return resolvePathFromProjectRoot(projectRoot, expandTilde2(target));
|
|
37847
38204
|
}
|
|
37848
38205
|
function searchPathExists(projectRoot, target) {
|
|
37849
38206
|
return fs7.existsSync(absoluteSearchPath(projectRoot, target));
|
|
@@ -37920,7 +38277,7 @@ function searchTools(ctx) {
|
|
|
37920
38277
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
37921
38278
|
const pattern = String(args.pattern);
|
|
37922
38279
|
const includeArg = args.include ? String(args.include) : undefined;
|
|
37923
|
-
const pathArg = args.path ?
|
|
38280
|
+
const pathArg = args.path ? expandTilde2(String(args.path)) : undefined;
|
|
37924
38281
|
const bridgePath = pathArg ? absoluteSearchPath(projectRoot, pathArg) : undefined;
|
|
37925
38282
|
const grepDenied = await askGrepPermission(context, pattern, {
|
|
37926
38283
|
path: bridgePath,
|
|
@@ -37958,8 +38315,8 @@ function searchTools(ctx) {
|
|
|
37958
38315
|
},
|
|
37959
38316
|
execute: async (args, context) => {
|
|
37960
38317
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
37961
|
-
let globPattern =
|
|
37962
|
-
let globPath = args.path ?
|
|
38318
|
+
let globPattern = expandTilde2(String(args.pattern));
|
|
38319
|
+
let globPath = args.path ? expandTilde2(String(args.path)) : undefined;
|
|
37963
38320
|
if (!globPath && globPattern.startsWith("/")) {
|
|
37964
38321
|
const metaIdx = globPattern.search(/[*?{}[\]]/);
|
|
37965
38322
|
if (metaIdx > 0) {
|
|
@@ -37969,8 +38326,8 @@ function searchTools(ctx) {
|
|
|
37969
38326
|
globPattern = `**/${globPattern.slice(lastSlash + 1)}`;
|
|
37970
38327
|
}
|
|
37971
38328
|
} else if (metaIdx === -1) {
|
|
37972
|
-
globPath =
|
|
37973
|
-
globPattern =
|
|
38329
|
+
globPath = path7.dirname(globPattern);
|
|
38330
|
+
globPattern = path7.basename(globPattern);
|
|
37974
38331
|
}
|
|
37975
38332
|
}
|
|
37976
38333
|
const globDenied = await askGlobPermission(context, globPattern, { path: globPath });
|
|
@@ -38218,12 +38575,12 @@ var PLUGIN_VERSION = (() => {
|
|
|
38218
38575
|
return "0.0.0";
|
|
38219
38576
|
}
|
|
38220
38577
|
})();
|
|
38221
|
-
var ANNOUNCEMENT_VERSION = "0.
|
|
38578
|
+
var ANNOUNCEMENT_VERSION = "0.39.0";
|
|
38222
38579
|
var ANNOUNCEMENT_FEATURES = [
|
|
38223
|
-
"
|
|
38224
|
-
"
|
|
38225
|
-
"
|
|
38226
|
-
"
|
|
38580
|
+
"Accurate Rust dead code: constructors and associated functions reached through receiver-type inference are no longer mis-reported as dead.",
|
|
38581
|
+
"Code Health scans reparse only the file you changed instead of the whole project on every edit — a single-file edit dropped from ~3s of scan work to ~130ms on this repo, byte-identical results.",
|
|
38582
|
+
"R language support in outline, zoom, and the AST tools.",
|
|
38583
|
+
"Edit approval prompts now show the pending diff instead of 'No diff provided', so you can review a change before approving it."
|
|
38227
38584
|
];
|
|
38228
38585
|
var ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/DSa65w8wuf";
|
|
38229
38586
|
var plugin = async (input) => initializePluginForDirectory(input);
|
|
@@ -38335,13 +38692,13 @@ ${lines}
|
|
|
38335
38692
|
const upgradePromise = (async () => {
|
|
38336
38693
|
warn2(`WARNING: aft binary v${binaryVersion} is older than plugin v${minVersion}. ` + "Some features may not work. Attempting to download a compatible binary...");
|
|
38337
38694
|
try {
|
|
38338
|
-
const
|
|
38339
|
-
if (!
|
|
38695
|
+
const path8 = await ensureBinary(`v${minVersion}`);
|
|
38696
|
+
if (!path8) {
|
|
38340
38697
|
warn2(`Could not find or download v${minVersion}. Continuing with v${binaryVersion}.`);
|
|
38341
38698
|
return null;
|
|
38342
38699
|
}
|
|
38343
|
-
log2(`Found/downloaded compatible binary at ${
|
|
38344
|
-
const replaced = await pool.replaceBinary(
|
|
38700
|
+
log2(`Found/downloaded compatible binary at ${path8}. Replacing running bridges...`);
|
|
38701
|
+
const replaced = await pool.replaceBinary(path8);
|
|
38345
38702
|
log2("Binary replaced successfully. New bridges will use the updated binary.");
|
|
38346
38703
|
return replaced;
|
|
38347
38704
|
} catch (err) {
|