@cortexkit/aft-opencode 0.39.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 +706 -506
- 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.`;
|
|
@@ -11623,18 +11661,87 @@ function commandInvokesCodeSearch(command) {
|
|
|
11623
11661
|
}
|
|
11624
11662
|
return false;
|
|
11625
11663
|
}
|
|
11626
|
-
function maybeAppendGrepSearchHint(output, command, aftSearchRegistered) {
|
|
11664
|
+
function maybeAppendGrepSearchHint(output, command, aftSearchRegistered, projectRoot) {
|
|
11627
11665
|
if (output === "")
|
|
11628
11666
|
return output;
|
|
11629
11667
|
if (!commandInvokesCodeSearch(command))
|
|
11630
11668
|
return output;
|
|
11631
11669
|
if (output.includes(GREP_SEARCH_HINT_PREFIX))
|
|
11632
11670
|
return output;
|
|
11671
|
+
if (shouldSuppressGrepSearchHint(command, projectRoot))
|
|
11672
|
+
return output;
|
|
11633
11673
|
const hint = aftSearchRegistered ? GREP_SEARCH_AFT_SEARCH_HINT : GREP_SEARCH_GREP_HINT;
|
|
11634
11674
|
return `${output}
|
|
11635
11675
|
|
|
11636
11676
|
${hint}`;
|
|
11637
11677
|
}
|
|
11678
|
+
function shouldSuppressGrepSearchHint(command, projectRoot) {
|
|
11679
|
+
const root = projectRoot?.trim();
|
|
11680
|
+
if (!root)
|
|
11681
|
+
return false;
|
|
11682
|
+
const statements = splitTopLevelStatements(command);
|
|
11683
|
+
if (statements === null)
|
|
11684
|
+
return false;
|
|
11685
|
+
let sawCodeSearchStatement = false;
|
|
11686
|
+
for (const statement of statements) {
|
|
11687
|
+
const firstStage = firstPipelineStage(statement);
|
|
11688
|
+
if (firstStage === null)
|
|
11689
|
+
continue;
|
|
11690
|
+
const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0));
|
|
11691
|
+
if (firstToken === null)
|
|
11692
|
+
continue;
|
|
11693
|
+
if (firstToken.token !== "grep" && firstToken.token !== "rg")
|
|
11694
|
+
continue;
|
|
11695
|
+
sawCodeSearchStatement = true;
|
|
11696
|
+
const operands = collectPathOperands(firstStage, firstToken.end);
|
|
11697
|
+
if (operands.length === 0)
|
|
11698
|
+
return false;
|
|
11699
|
+
for (const operand of operands) {
|
|
11700
|
+
if (isPathInsideProject(root, operand))
|
|
11701
|
+
return false;
|
|
11702
|
+
}
|
|
11703
|
+
}
|
|
11704
|
+
return sawCodeSearchStatement;
|
|
11705
|
+
}
|
|
11706
|
+
function collectPathOperands(firstStage, startAfterCommand) {
|
|
11707
|
+
const operands = [];
|
|
11708
|
+
let index = skipSpaces(firstStage, startAfterCommand);
|
|
11709
|
+
while (index < firstStage.length) {
|
|
11710
|
+
const tokenResult = readShellToken(firstStage, index);
|
|
11711
|
+
if (tokenResult === null)
|
|
11712
|
+
break;
|
|
11713
|
+
const { token, end } = tokenResult;
|
|
11714
|
+
if (end <= index)
|
|
11715
|
+
break;
|
|
11716
|
+
index = skipSpaces(firstStage, end);
|
|
11717
|
+
if (token.startsWith("-"))
|
|
11718
|
+
continue;
|
|
11719
|
+
if (looksLikePathOperand(token))
|
|
11720
|
+
operands.push(token);
|
|
11721
|
+
}
|
|
11722
|
+
return operands;
|
|
11723
|
+
}
|
|
11724
|
+
function looksLikePathOperand(token) {
|
|
11725
|
+
return token.includes("/") || token.startsWith("~") || token.startsWith("./") || token.startsWith("../");
|
|
11726
|
+
}
|
|
11727
|
+
function expandTilde(target) {
|
|
11728
|
+
if (!target.startsWith("~"))
|
|
11729
|
+
return target;
|
|
11730
|
+
if (target === "~" || target.startsWith("~/")) {
|
|
11731
|
+
return path.join(os.homedir(), target.slice(1));
|
|
11732
|
+
}
|
|
11733
|
+
return target;
|
|
11734
|
+
}
|
|
11735
|
+
function resolvePathOperand(projectRoot, operand) {
|
|
11736
|
+
const expanded = expandTilde(operand);
|
|
11737
|
+
return path.isAbsolute(expanded) ? path.resolve(expanded) : path.resolve(projectRoot, expanded);
|
|
11738
|
+
}
|
|
11739
|
+
function isPathInsideProject(projectRoot, operand) {
|
|
11740
|
+
const root = path.resolve(projectRoot);
|
|
11741
|
+
const resolved = resolvePathOperand(root, operand);
|
|
11742
|
+
const rel = path.relative(root, resolved);
|
|
11743
|
+
return rel === "" || !rel.startsWith("..") && !path.isAbsolute(rel);
|
|
11744
|
+
}
|
|
11638
11745
|
function splitTopLevelStatements(command) {
|
|
11639
11746
|
const statements = [];
|
|
11640
11747
|
let start = 0;
|
|
@@ -11814,8 +11921,8 @@ function resolveBashKillTimeout(modelTimeout, foregroundWaitMs) {
|
|
|
11814
11921
|
}
|
|
11815
11922
|
// ../aft-bridge/dist/bridge.js
|
|
11816
11923
|
import { spawn } from "node:child_process";
|
|
11817
|
-
import { homedir } from "node:os";
|
|
11818
|
-
import { join } from "node:path";
|
|
11924
|
+
import { homedir as homedir2 } from "node:os";
|
|
11925
|
+
import { join as join2 } from "node:path";
|
|
11819
11926
|
import { StringDecoder } from "node:string_decoder";
|
|
11820
11927
|
|
|
11821
11928
|
// ../aft-bridge/dist/command-timeouts.js
|
|
@@ -12193,7 +12300,7 @@ class BinaryBridge {
|
|
|
12193
12300
|
`;
|
|
12194
12301
|
const keepBridgeOnTimeout = options?.keepBridgeOnTimeout === true;
|
|
12195
12302
|
let requestSentAt = Date.now();
|
|
12196
|
-
const response = await new Promise((
|
|
12303
|
+
const response = await new Promise((resolve2, reject) => {
|
|
12197
12304
|
const timer = setTimeout(() => {
|
|
12198
12305
|
const entry = this.pending.get(id);
|
|
12199
12306
|
if (!entry)
|
|
@@ -12228,7 +12335,7 @@ class BinaryBridge {
|
|
|
12228
12335
|
entry.reject(new Error(`${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`));
|
|
12229
12336
|
this.handleTimeout(requestSessionId);
|
|
12230
12337
|
}, effectiveTimeoutMs);
|
|
12231
|
-
this.pending.set(id, { resolve, reject, timer, onProgress: options?.onProgress, command });
|
|
12338
|
+
this.pending.set(id, { resolve: resolve2, reject, timer, onProgress: options?.onProgress, command });
|
|
12232
12339
|
if (!this.process?.stdin?.writable) {
|
|
12233
12340
|
this.pending.delete(id);
|
|
12234
12341
|
clearTimeout(timer);
|
|
@@ -12326,15 +12433,15 @@ class BinaryBridge {
|
|
|
12326
12433
|
if (this.process) {
|
|
12327
12434
|
const proc = this.process;
|
|
12328
12435
|
this.process = null;
|
|
12329
|
-
return new Promise((
|
|
12436
|
+
return new Promise((resolve2) => {
|
|
12330
12437
|
const forceKillTimer = setTimeout(() => {
|
|
12331
12438
|
proc.kill("SIGKILL");
|
|
12332
|
-
|
|
12439
|
+
resolve2();
|
|
12333
12440
|
}, 5000);
|
|
12334
12441
|
proc.once("exit", () => {
|
|
12335
12442
|
clearTimeout(forceKillTimer);
|
|
12336
12443
|
this.logVia("Process exited during shutdown");
|
|
12337
|
-
|
|
12444
|
+
resolve2();
|
|
12338
12445
|
});
|
|
12339
12446
|
proc.kill("SIGTERM");
|
|
12340
12447
|
});
|
|
@@ -12379,15 +12486,15 @@ class BinaryBridge {
|
|
|
12379
12486
|
return;
|
|
12380
12487
|
const proc = this.process;
|
|
12381
12488
|
this.process = null;
|
|
12382
|
-
await new Promise((
|
|
12489
|
+
await new Promise((resolve2) => {
|
|
12383
12490
|
const forceKillTimer = setTimeout(() => {
|
|
12384
12491
|
proc.kill("SIGKILL");
|
|
12385
|
-
|
|
12492
|
+
resolve2();
|
|
12386
12493
|
}, 5000);
|
|
12387
12494
|
proc.once("exit", () => {
|
|
12388
12495
|
clearTimeout(forceKillTimer);
|
|
12389
12496
|
this.logVia("Process exited during coordinated binary replacement");
|
|
12390
|
-
|
|
12497
|
+
resolve2();
|
|
12391
12498
|
});
|
|
12392
12499
|
proc.kill("SIGTERM");
|
|
12393
12500
|
});
|
|
@@ -12414,7 +12521,7 @@ class BinaryBridge {
|
|
|
12414
12521
|
})();
|
|
12415
12522
|
const useFastembedBackend = semanticBackend === undefined || semanticBackend === "fastembed" || semanticBackend === "";
|
|
12416
12523
|
const ortDir = typeof this.configOverrides._ort_dylib_dir === "string" && useFastembedBackend ? this.configOverrides._ort_dylib_dir : null;
|
|
12417
|
-
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");
|
|
12418
12525
|
const envPath = process.platform === "win32" && ortDir ? `${ortDir};${process.env.PATH ?? ""}` : process.env.PATH;
|
|
12419
12526
|
const env = {
|
|
12420
12527
|
...process.env,
|
|
@@ -12422,7 +12529,7 @@ class BinaryBridge {
|
|
|
12422
12529
|
};
|
|
12423
12530
|
this.logVia(`bridge.spawnProcess: useFastembedBackend=${useFastembedBackend}, ` + `parentORT=${process.env.ORT_DYLIB_PATH ?? "(unset)"}, ` + `ortLibraryPath=${ortLibraryPath ?? "(none)"}`);
|
|
12424
12531
|
if (useFastembedBackend) {
|
|
12425
|
-
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"));
|
|
12426
12533
|
if (process.env.ORT_DYLIB_PATH) {
|
|
12427
12534
|
this.logVia(`ORT_DYLIB_PATH inherited from parent env: ${process.env.ORT_DYLIB_PATH}`);
|
|
12428
12535
|
} else if (ortLibraryPath) {
|
|
@@ -12764,12 +12871,23 @@ function coerceStringArray(value) {
|
|
|
12764
12871
|
}
|
|
12765
12872
|
return [];
|
|
12766
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
|
+
}
|
|
12767
12885
|
// ../aft-bridge/dist/downloader.js
|
|
12768
12886
|
import { spawnSync } from "node:child_process";
|
|
12769
12887
|
import { createHash, randomUUID } from "node:crypto";
|
|
12770
12888
|
import { chmodSync, closeSync, copyFileSync, createWriteStream, existsSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, unlinkSync, writeSync } from "node:fs";
|
|
12771
|
-
import { homedir as
|
|
12772
|
-
import { join as
|
|
12889
|
+
import { homedir as homedir3 } from "node:os";
|
|
12890
|
+
import { join as join3 } from "node:path";
|
|
12773
12891
|
import { Readable } from "node:stream";
|
|
12774
12892
|
import { pipeline } from "node:stream/promises";
|
|
12775
12893
|
|
|
@@ -12826,11 +12944,11 @@ function isExpectedCachedBinary(binaryPath, tag) {
|
|
|
12826
12944
|
function getCacheDir() {
|
|
12827
12945
|
if (process.platform === "win32") {
|
|
12828
12946
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
12829
|
-
const base2 = localAppData ||
|
|
12830
|
-
return
|
|
12947
|
+
const base2 = localAppData || join3(homedir3(), "AppData", "Local");
|
|
12948
|
+
return join3(base2, "aft", "bin");
|
|
12831
12949
|
}
|
|
12832
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
12833
|
-
return
|
|
12950
|
+
const base = process.env.XDG_CACHE_HOME || join3(homedir3(), ".cache");
|
|
12951
|
+
return join3(base, "aft", "bin");
|
|
12834
12952
|
}
|
|
12835
12953
|
function getBinaryName() {
|
|
12836
12954
|
return process.platform === "win32" ? "aft.exe" : "aft";
|
|
@@ -12838,7 +12956,7 @@ function getBinaryName() {
|
|
|
12838
12956
|
function getCachedBinaryPath(version) {
|
|
12839
12957
|
if (!version)
|
|
12840
12958
|
return null;
|
|
12841
|
-
const binaryPath =
|
|
12959
|
+
const binaryPath = join3(getCacheDir(), version, getBinaryName());
|
|
12842
12960
|
return existsSync(binaryPath) ? binaryPath : null;
|
|
12843
12961
|
}
|
|
12844
12962
|
async function downloadBinary(version) {
|
|
@@ -12855,16 +12973,16 @@ async function downloadBinary(version) {
|
|
|
12855
12973
|
return null;
|
|
12856
12974
|
}
|
|
12857
12975
|
const tag = rawTag.startsWith("v") ? rawTag : `v${rawTag}`;
|
|
12858
|
-
const versionedCacheDir =
|
|
12976
|
+
const versionedCacheDir = join3(getCacheDir(), tag);
|
|
12859
12977
|
const binaryName = getBinaryName();
|
|
12860
|
-
const binaryPath =
|
|
12978
|
+
const binaryPath = join3(versionedCacheDir, binaryName);
|
|
12861
12979
|
if (existsSync(binaryPath) && isExpectedCachedBinary(binaryPath, tag)) {
|
|
12862
12980
|
return binaryPath;
|
|
12863
12981
|
}
|
|
12864
12982
|
const downloadUrl = `https://github.com/${REPO}/releases/download/${tag}/${assetName}`;
|
|
12865
12983
|
const checksumUrl = `https://github.com/${REPO}/releases/download/${tag}/checksums.sha256`;
|
|
12866
12984
|
log(`Downloading AFT binary (${tag}) for ${platformKey}...`);
|
|
12867
|
-
const lockPath =
|
|
12985
|
+
const lockPath = join3(versionedCacheDir, ".download.lock");
|
|
12868
12986
|
let releaseLock = null;
|
|
12869
12987
|
let binaryController = null;
|
|
12870
12988
|
let checksumController = null;
|
|
@@ -13016,7 +13134,7 @@ async function acquireDownloadLock(lockPath) {
|
|
|
13016
13134
|
if (Date.now() - startedAt > DOWNLOAD_LOCK_TIMEOUT_MS) {
|
|
13017
13135
|
throw new Error(`Timed out waiting for download lock: ${lockPath}`);
|
|
13018
13136
|
}
|
|
13019
|
-
await new Promise((
|
|
13137
|
+
await new Promise((resolve2) => setTimeout(resolve2, 100));
|
|
13020
13138
|
}
|
|
13021
13139
|
}
|
|
13022
13140
|
}
|
|
@@ -13102,18 +13220,18 @@ function stripJsoncSymbols(value) {
|
|
|
13102
13220
|
// ../aft-bridge/dist/migration.js
|
|
13103
13221
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
13104
13222
|
import { existsSync as existsSync4, mkdirSync as mkdirSync4 } from "node:fs";
|
|
13105
|
-
import { homedir as
|
|
13106
|
-
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";
|
|
13107
13225
|
|
|
13108
13226
|
// ../aft-bridge/dist/paths.js
|
|
13109
13227
|
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync as renameSync2, writeFileSync } from "node:fs";
|
|
13110
|
-
import { dirname, join as
|
|
13228
|
+
import { dirname, join as join4 } from "node:path";
|
|
13111
13229
|
function resolveHarnessStoragePath(storageRoot, harness, ...segments) {
|
|
13112
|
-
return
|
|
13230
|
+
return join4(storageRoot, harness, ...segments);
|
|
13113
13231
|
}
|
|
13114
13232
|
function repairRootScopedStorageFile(storageRoot, harness, fileName) {
|
|
13115
13233
|
const harnessPath = resolveHarnessStoragePath(storageRoot, harness, fileName);
|
|
13116
|
-
const rootPath =
|
|
13234
|
+
const rootPath = join4(storageRoot, fileName);
|
|
13117
13235
|
if (existsSync2(harnessPath) || !existsSync2(rootPath))
|
|
13118
13236
|
return harnessPath;
|
|
13119
13237
|
try {
|
|
@@ -13159,8 +13277,8 @@ function markAnnouncementSeen(storageRoot, harness, currentVersion) {
|
|
|
13159
13277
|
import { execSync } from "node:child_process";
|
|
13160
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";
|
|
13161
13279
|
import { createRequire as createRequire2 } from "node:module";
|
|
13162
|
-
import { homedir as
|
|
13163
|
-
import { join as
|
|
13280
|
+
import { homedir as homedir4 } from "node:os";
|
|
13281
|
+
import { join as join5 } from "node:path";
|
|
13164
13282
|
var ensureBinaryForResolver = ensureBinary;
|
|
13165
13283
|
function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
13166
13284
|
try {
|
|
@@ -13169,9 +13287,9 @@ function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
|
13169
13287
|
return null;
|
|
13170
13288
|
const tag = version.startsWith("v") ? version : `v${version}`;
|
|
13171
13289
|
const cacheDir = getCacheDir();
|
|
13172
|
-
const versionedDir =
|
|
13290
|
+
const versionedDir = join5(cacheDir, tag);
|
|
13173
13291
|
const ext = process.platform === "win32" ? ".exe" : "";
|
|
13174
|
-
const cachedPath =
|
|
13292
|
+
const cachedPath = join5(versionedDir, `aft${ext}`);
|
|
13175
13293
|
if (existsSync3(cachedPath)) {
|
|
13176
13294
|
const cachedVersion = readBinaryVersion(cachedPath);
|
|
13177
13295
|
if (cachedVersion === version)
|
|
@@ -13201,18 +13319,18 @@ function normalizeBareVersion(version) {
|
|
|
13201
13319
|
return version.startsWith("v") ? version.slice(1) : version;
|
|
13202
13320
|
}
|
|
13203
13321
|
function homeDirFromEnv(env) {
|
|
13204
|
-
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) ||
|
|
13322
|
+
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir4();
|
|
13205
13323
|
}
|
|
13206
13324
|
function cacheDirFromEnv(env) {
|
|
13207
13325
|
if (process.platform === "win32") {
|
|
13208
|
-
const base2 = env.LOCALAPPDATA || env.APPDATA ||
|
|
13209
|
-
return
|
|
13326
|
+
const base2 = env.LOCALAPPDATA || env.APPDATA || join5(homeDirFromEnv(env), "AppData", "Local");
|
|
13327
|
+
return join5(base2, "aft", "bin");
|
|
13210
13328
|
}
|
|
13211
|
-
const base = env.XDG_CACHE_HOME ||
|
|
13212
|
-
return
|
|
13329
|
+
const base = env.XDG_CACHE_HOME || join5(homeDirFromEnv(env), ".cache");
|
|
13330
|
+
return join5(base, "aft", "bin");
|
|
13213
13331
|
}
|
|
13214
13332
|
function cachedBinaryPathFromEnv(version, env, ext) {
|
|
13215
|
-
const binaryPath =
|
|
13333
|
+
const binaryPath = join5(cacheDirFromEnv(env), version, `aft${ext}`);
|
|
13216
13334
|
return existsSync3(binaryPath) ? binaryPath : null;
|
|
13217
13335
|
}
|
|
13218
13336
|
function isExpectedCachedBinary2(binaryPath, expectedVersion) {
|
|
@@ -13331,7 +13449,7 @@ function findBinarySync(expectedVersion) {
|
|
|
13331
13449
|
return usable;
|
|
13332
13450
|
}
|
|
13333
13451
|
} catch {}
|
|
13334
|
-
const cargoPath =
|
|
13452
|
+
const cargoPath = join5(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
|
|
13335
13453
|
if (existsSync3(cargoPath)) {
|
|
13336
13454
|
const usable = probeBinaryCandidate(cargoPath, "cargo", expectedVersion);
|
|
13337
13455
|
if (usable)
|
|
@@ -13377,22 +13495,22 @@ function dataHome() {
|
|
|
13377
13495
|
if (process.env.XDG_DATA_HOME)
|
|
13378
13496
|
return process.env.XDG_DATA_HOME;
|
|
13379
13497
|
if (process.platform === "win32") {
|
|
13380
|
-
return process.env.LOCALAPPDATA || process.env.APPDATA ||
|
|
13498
|
+
return process.env.LOCALAPPDATA || process.env.APPDATA || join6(homeDir(), "AppData", "Local");
|
|
13381
13499
|
}
|
|
13382
|
-
return
|
|
13500
|
+
return join6(homeDir(), ".local", "share");
|
|
13383
13501
|
}
|
|
13384
13502
|
function homeDir() {
|
|
13385
13503
|
if (process.platform === "win32")
|
|
13386
|
-
return process.env.USERPROFILE || process.env.HOME ||
|
|
13387
|
-
return process.env.HOME ||
|
|
13504
|
+
return process.env.USERPROFILE || process.env.HOME || homedir5();
|
|
13505
|
+
return process.env.HOME || homedir5();
|
|
13388
13506
|
}
|
|
13389
13507
|
function resolveLegacyStorageRoot(harness) {
|
|
13390
13508
|
if (harness === "pi")
|
|
13391
|
-
return
|
|
13392
|
-
return
|
|
13509
|
+
return join6(homeDir(), ".pi", "agent", "aft");
|
|
13510
|
+
return join6(dataHome(), "opencode", "storage", "plugin", "aft");
|
|
13393
13511
|
}
|
|
13394
13512
|
function resolveCortexKitStorageRoot() {
|
|
13395
|
-
return
|
|
13513
|
+
return join6(dataHome(), "cortexkit", "aft");
|
|
13396
13514
|
}
|
|
13397
13515
|
function tail(value) {
|
|
13398
13516
|
if (!value)
|
|
@@ -13406,12 +13524,12 @@ function spawnErrorLabel(error2) {
|
|
|
13406
13524
|
return [code, error2.message].filter(Boolean).join(": ");
|
|
13407
13525
|
}
|
|
13408
13526
|
function migrationLogPath(newRoot, harness, logger) {
|
|
13409
|
-
const desired =
|
|
13527
|
+
const desired = join6(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
|
|
13410
13528
|
try {
|
|
13411
13529
|
mkdirSync4(dirname2(desired), { recursive: true });
|
|
13412
13530
|
return desired;
|
|
13413
13531
|
} catch (err) {
|
|
13414
|
-
const fallback =
|
|
13532
|
+
const fallback = join6(tmpdir(), `aft-migration-${harness}-${Date.now()}.jsonl`);
|
|
13415
13533
|
logger?.warn?.(`Failed to create AFT migration log directory ${dirname2(desired)}: ${err instanceof Error ? err.message : String(err)}. ` + `Using fallback log path ${fallback}.`);
|
|
13416
13534
|
return fallback;
|
|
13417
13535
|
}
|
|
@@ -13474,13 +13592,13 @@ async function ensureStorageMigrated(opts) {
|
|
|
13474
13592
|
}
|
|
13475
13593
|
// ../aft-bridge/dist/npm-resolver.js
|
|
13476
13594
|
import { readdirSync, statSync as statSync2 } from "node:fs";
|
|
13477
|
-
import { homedir as
|
|
13478
|
-
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";
|
|
13479
13597
|
function defaultDeps() {
|
|
13480
13598
|
return {
|
|
13481
13599
|
platform: process.platform,
|
|
13482
13600
|
env: process.env,
|
|
13483
|
-
home:
|
|
13601
|
+
home: homedir6(),
|
|
13484
13602
|
execPath: process.execPath
|
|
13485
13603
|
};
|
|
13486
13604
|
}
|
|
@@ -13499,16 +13617,16 @@ function npmFromPath(deps) {
|
|
|
13499
13617
|
const raw = deps.env.PATH ?? deps.env.Path ?? "";
|
|
13500
13618
|
for (const entry of raw.split(delimiter)) {
|
|
13501
13619
|
const dir = entry.trim().replace(/^"|"$/g, "");
|
|
13502
|
-
if (!dir || !
|
|
13620
|
+
if (!dir || !isAbsolute2(dir))
|
|
13503
13621
|
continue;
|
|
13504
|
-
if (isFile(
|
|
13622
|
+
if (isFile(join7(dir, name)))
|
|
13505
13623
|
return dir;
|
|
13506
13624
|
}
|
|
13507
13625
|
return null;
|
|
13508
13626
|
}
|
|
13509
13627
|
function npmAdjacentToNode(deps) {
|
|
13510
13628
|
const dir = dirname3(deps.execPath);
|
|
13511
|
-
return isFile(
|
|
13629
|
+
return isFile(join7(dir, npmBinaryName(deps.platform))) ? dir : null;
|
|
13512
13630
|
}
|
|
13513
13631
|
function highestVersionedNodeBin(installsDir, name) {
|
|
13514
13632
|
let entries;
|
|
@@ -13517,8 +13635,8 @@ function highestVersionedNodeBin(installsDir, name) {
|
|
|
13517
13635
|
} catch {
|
|
13518
13636
|
return null;
|
|
13519
13637
|
}
|
|
13520
|
-
const candidates = entries.filter((v) => isFile(
|
|
13521
|
-
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;
|
|
13522
13640
|
}
|
|
13523
13641
|
function compareVersionsDesc(a, b) {
|
|
13524
13642
|
const pa = a.replace(/^v/, "").split(".").map((n) => Number.parseInt(n, 10));
|
|
@@ -13543,22 +13661,22 @@ function wellKnownNpmDirs(deps) {
|
|
|
13543
13661
|
const programFiles = env.ProgramFiles || "C:\\Program Files";
|
|
13544
13662
|
const appData = env.APPDATA;
|
|
13545
13663
|
const localAppData = env.LOCALAPPDATA;
|
|
13546
|
-
push(
|
|
13664
|
+
push(join7(programFiles, "nodejs"));
|
|
13547
13665
|
if (appData)
|
|
13548
|
-
push(
|
|
13666
|
+
push(join7(appData, "npm"));
|
|
13549
13667
|
if (localAppData)
|
|
13550
|
-
push(
|
|
13668
|
+
push(join7(localAppData, "Volta", "bin"));
|
|
13551
13669
|
if (env.NVM_SYMLINK)
|
|
13552
13670
|
push(env.NVM_SYMLINK);
|
|
13553
13671
|
} else {
|
|
13554
13672
|
if (env.NVM_BIN)
|
|
13555
13673
|
push(env.NVM_BIN);
|
|
13556
|
-
push(highestVersionedNodeBin(
|
|
13557
|
-
push(highestVersionedNodeBin(
|
|
13558
|
-
push(highestVersionedNodeBin(
|
|
13559
|
-
push(
|
|
13560
|
-
push(
|
|
13561
|
-
const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin",
|
|
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")]);
|
|
13562
13680
|
for (const dir of systemDirs)
|
|
13563
13681
|
push(dir);
|
|
13564
13682
|
}
|
|
@@ -13568,12 +13686,12 @@ function resolveNpm(deps = defaultDeps()) {
|
|
|
13568
13686
|
const name = npmBinaryName(deps.platform);
|
|
13569
13687
|
const onPath = npmFromPath(deps);
|
|
13570
13688
|
if (onPath)
|
|
13571
|
-
return { command:
|
|
13689
|
+
return { command: join7(onPath, name), binDir: onPath };
|
|
13572
13690
|
const adjacent = npmAdjacentToNode(deps);
|
|
13573
13691
|
if (adjacent)
|
|
13574
|
-
return { command:
|
|
13692
|
+
return { command: join7(adjacent, name), binDir: adjacent };
|
|
13575
13693
|
for (const dir of wellKnownNpmDirs(deps)) {
|
|
13576
|
-
const candidate =
|
|
13694
|
+
const candidate = join7(dir, name);
|
|
13577
13695
|
if (isFile(candidate))
|
|
13578
13696
|
return { command: candidate, binDir: dir };
|
|
13579
13697
|
}
|
|
@@ -13593,7 +13711,7 @@ function isNpmAvailable(deps = defaultDeps()) {
|
|
|
13593
13711
|
import { execFileSync } from "node:child_process";
|
|
13594
13712
|
import { createHash as createHash2 } from "node:crypto";
|
|
13595
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";
|
|
13596
|
-
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";
|
|
13597
13715
|
import { Readable as Readable2 } from "node:stream";
|
|
13598
13716
|
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
13599
13717
|
var ORT_VERSION = "1.24.4";
|
|
@@ -13659,10 +13777,10 @@ function getManualInstallHint() {
|
|
|
13659
13777
|
}
|
|
13660
13778
|
async function ensureOnnxRuntime(storageDir) {
|
|
13661
13779
|
const info = getPlatformInfo();
|
|
13662
|
-
const ortVersionDir =
|
|
13780
|
+
const ortVersionDir = join8(storageDir, "onnxruntime", ORT_VERSION);
|
|
13663
13781
|
const libName = info?.libName ?? "libonnxruntime.dylib";
|
|
13664
13782
|
const resolvedOrtDir = resolveCachedOnnxRuntimeDir(ortVersionDir, libName);
|
|
13665
|
-
const libPath =
|
|
13783
|
+
const libPath = join8(resolvedOrtDir, libName);
|
|
13666
13784
|
if (existsSync5(libPath)) {
|
|
13667
13785
|
const meta = readOnnxInstalledMeta(ortVersionDir);
|
|
13668
13786
|
if (meta?.sha256) {
|
|
@@ -13692,9 +13810,9 @@ async function ensureOnnxRuntime(storageDir) {
|
|
|
13692
13810
|
warn(`ONNX Runtime auto-download not available for ${process.platform}/${process.arch}. Install manually: ${getManualInstallHint()}`);
|
|
13693
13811
|
return null;
|
|
13694
13812
|
}
|
|
13695
|
-
const onnxBaseDir =
|
|
13813
|
+
const onnxBaseDir = join8(storageDir, "onnxruntime");
|
|
13696
13814
|
mkdirSync5(onnxBaseDir, { recursive: true });
|
|
13697
|
-
const lockPath =
|
|
13815
|
+
const lockPath = join8(onnxBaseDir, ONNX_LOCK_FILE);
|
|
13698
13816
|
cleanupAbandonedStagingDirs(onnxBaseDir);
|
|
13699
13817
|
if (!acquireLock(lockPath)) {
|
|
13700
13818
|
warn(`ONNX Runtime install already in progress in another process (lock: ${lockPath}). Skipping.`);
|
|
@@ -13713,7 +13831,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
13713
13831
|
for (const entry of entries) {
|
|
13714
13832
|
if (!entry.startsWith(`${ORT_VERSION}.tmp.`))
|
|
13715
13833
|
continue;
|
|
13716
|
-
const stagingDir =
|
|
13834
|
+
const stagingDir = join8(onnxBaseDir, entry);
|
|
13717
13835
|
const parts = entry.split(".");
|
|
13718
13836
|
const pidStr = parts[parts.length - 2];
|
|
13719
13837
|
const pid = pidStr ? Number.parseInt(pidStr, 10) : NaN;
|
|
@@ -13750,7 +13868,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
13750
13868
|
}
|
|
13751
13869
|
function cleanupIncompleteTargetIfUnowned(ortDir) {
|
|
13752
13870
|
try {
|
|
13753
|
-
if (existsSync5(ortDir) && !existsSync5(
|
|
13871
|
+
if (existsSync5(ortDir) && !existsSync5(join8(ortDir, ONNX_INSTALLED_META_FILE))) {
|
|
13754
13872
|
log(`[onnx] removing half-populated install dir ${ortDir} (no meta file)`);
|
|
13755
13873
|
rmSync2(ortDir, { recursive: true, force: true });
|
|
13756
13874
|
}
|
|
@@ -13778,8 +13896,8 @@ function parseOnnxVersionFromDirectoryPath(value) {
|
|
|
13778
13896
|
return null;
|
|
13779
13897
|
}
|
|
13780
13898
|
function isPathInsideRoot(root, candidate) {
|
|
13781
|
-
const rel =
|
|
13782
|
-
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);
|
|
13783
13901
|
}
|
|
13784
13902
|
function detectOnnxVersion(libDir, libName) {
|
|
13785
13903
|
try {
|
|
@@ -13794,7 +13912,7 @@ function detectOnnxVersion(libDir, libName) {
|
|
|
13794
13912
|
if (version)
|
|
13795
13913
|
return version;
|
|
13796
13914
|
}
|
|
13797
|
-
const base =
|
|
13915
|
+
const base = join8(libDir, libName);
|
|
13798
13916
|
if (existsSync5(base)) {
|
|
13799
13917
|
try {
|
|
13800
13918
|
const real = realpathSync(base);
|
|
@@ -13830,7 +13948,7 @@ function pathEntriesForPlatform() {
|
|
|
13830
13948
|
return pathEnvValue().split(delimiter2).map((entry) => entry.trim().replace(/^"|"$/g, "")).filter((entry) => {
|
|
13831
13949
|
if (!entry || entry === "." || entry.includes("\x00"))
|
|
13832
13950
|
return false;
|
|
13833
|
-
return
|
|
13951
|
+
return isAbsolute3(entry) || win32.isAbsolute(entry);
|
|
13834
13952
|
});
|
|
13835
13953
|
}
|
|
13836
13954
|
function directoryContainsLibrary(dir, libName) {
|
|
@@ -13846,10 +13964,10 @@ function directoryContainsLibrary(dir, libName) {
|
|
|
13846
13964
|
}
|
|
13847
13965
|
}
|
|
13848
13966
|
function resolveCachedOnnxRuntimeDir(ortVersionDir, libName) {
|
|
13849
|
-
if (existsSync5(
|
|
13967
|
+
if (existsSync5(join8(ortVersionDir, libName)))
|
|
13850
13968
|
return ortVersionDir;
|
|
13851
|
-
const libSubdir =
|
|
13852
|
-
if (existsSync5(
|
|
13969
|
+
const libSubdir = join8(ortVersionDir, "lib");
|
|
13970
|
+
if (existsSync5(join8(libSubdir, libName)))
|
|
13853
13971
|
return libSubdir;
|
|
13854
13972
|
return ortVersionDir;
|
|
13855
13973
|
}
|
|
@@ -13864,12 +13982,12 @@ function findSystemOnnxRuntime(libName) {
|
|
|
13864
13982
|
} else if (process.platform === "win32") {
|
|
13865
13983
|
const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
|
|
13866
13984
|
const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
|
|
13867
|
-
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"), ...(() => {
|
|
13868
13986
|
const nugetPaths = [];
|
|
13869
13987
|
const userProfile = process.env.USERPROFILE ?? "";
|
|
13870
13988
|
if (!userProfile)
|
|
13871
13989
|
return nugetPaths;
|
|
13872
|
-
const nugetPackageDir =
|
|
13990
|
+
const nugetPackageDir = join8(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
|
|
13873
13991
|
if (!existsSync5(nugetPackageDir))
|
|
13874
13992
|
return nugetPaths;
|
|
13875
13993
|
try {
|
|
@@ -13878,7 +13996,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
13878
13996
|
continue;
|
|
13879
13997
|
if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
|
|
13880
13998
|
continue;
|
|
13881
|
-
nugetPaths.push(
|
|
13999
|
+
nugetPaths.push(join8(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join8(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
|
|
13882
14000
|
}
|
|
13883
14001
|
} catch (err) {
|
|
13884
14002
|
warn(`Failed to scan NuGet ONNX Runtime cache ${nugetPackageDir}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -13890,7 +14008,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
13890
14008
|
const normalizeCase = process.platform === "win32" || process.platform === "darwin";
|
|
13891
14009
|
const seen = new Set;
|
|
13892
14010
|
const uniquePaths = searchPaths.filter((p) => {
|
|
13893
|
-
let key =
|
|
14011
|
+
let key = resolve2(p).replace(/[/\\]+$/, "");
|
|
13894
14012
|
if (normalizeCase)
|
|
13895
14013
|
key = key.toLowerCase();
|
|
13896
14014
|
if (seen.has(key))
|
|
@@ -13900,7 +14018,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
13900
14018
|
});
|
|
13901
14019
|
const unknownVersionPaths = [];
|
|
13902
14020
|
for (const dir of uniquePaths) {
|
|
13903
|
-
const libPath =
|
|
14021
|
+
const libPath = join8(dir, libName);
|
|
13904
14022
|
if (process.platform === "win32") {
|
|
13905
14023
|
if (!directoryContainsLibrary(dir, libName))
|
|
13906
14024
|
continue;
|
|
@@ -13966,19 +14084,19 @@ function validateExtractedTree(stagingRoot) {
|
|
|
13966
14084
|
const walk = (dir) => {
|
|
13967
14085
|
const entries = readdirSync2(dir);
|
|
13968
14086
|
for (const entry of entries) {
|
|
13969
|
-
const fullPath =
|
|
14087
|
+
const fullPath = join8(dir, entry);
|
|
13970
14088
|
const lst = lstatSync(fullPath);
|
|
13971
14089
|
if (lst.isSymbolicLink()) {
|
|
13972
14090
|
const linkTarget = readlinkSync(fullPath);
|
|
13973
|
-
const resolvedTarget =
|
|
13974
|
-
const rel2 =
|
|
13975
|
-
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)) {
|
|
13976
14094
|
throw new Error(`extracted symlink ${fullPath} points outside staging root: ${linkTarget}`);
|
|
13977
14095
|
}
|
|
13978
14096
|
continue;
|
|
13979
14097
|
}
|
|
13980
|
-
const rel =
|
|
13981
|
-
if (rel.startsWith("..") ||
|
|
14098
|
+
const rel = relative2(realRoot, fullPath);
|
|
14099
|
+
if (rel.startsWith("..") || isAbsolute3(rel) || win32.isAbsolute(rel)) {
|
|
13982
14100
|
throw new Error(`extracted entry ${fullPath} escapes staging root`);
|
|
13983
14101
|
}
|
|
13984
14102
|
if (lst.isDirectory()) {
|
|
@@ -14001,7 +14119,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
14001
14119
|
const tmpDir = `${targetDir}.tmp.${process.pid}.${Date.now().toString(36)}`;
|
|
14002
14120
|
try {
|
|
14003
14121
|
mkdirSync5(tmpDir, { recursive: true });
|
|
14004
|
-
const archivePath =
|
|
14122
|
+
const archivePath = join8(tmpDir, `onnxruntime.${info.archiveType}`);
|
|
14005
14123
|
await downloadFileWithCap(url, archivePath);
|
|
14006
14124
|
const archiveSha256 = sha256File(archivePath);
|
|
14007
14125
|
log(`ONNX Runtime archive sha256=${archiveSha256}`);
|
|
@@ -14017,7 +14135,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
14017
14135
|
unlinkSync3(archivePath);
|
|
14018
14136
|
} catch {}
|
|
14019
14137
|
validateExtractedTree(tmpDir);
|
|
14020
|
-
const extractedDir =
|
|
14138
|
+
const extractedDir = join8(tmpDir, info.assetName, "lib");
|
|
14021
14139
|
if (!existsSync5(extractedDir)) {
|
|
14022
14140
|
throw new Error(`Expected directory not found: ${extractedDir}`);
|
|
14023
14141
|
}
|
|
@@ -14026,7 +14144,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
14026
14144
|
const realFiles = [];
|
|
14027
14145
|
const symlinks = [];
|
|
14028
14146
|
for (const libFile of libFiles) {
|
|
14029
|
-
const src =
|
|
14147
|
+
const src = join8(extractedDir, libFile);
|
|
14030
14148
|
try {
|
|
14031
14149
|
const stat = lstatSync(src);
|
|
14032
14150
|
log(`ORT extract: ${libFile} — isSymlink=${stat.isSymbolicLink()}, isFile=${stat.isFile()}, size=${stat.size}`);
|
|
@@ -14041,7 +14159,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
14041
14159
|
}
|
|
14042
14160
|
}
|
|
14043
14161
|
copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks);
|
|
14044
|
-
const libPath =
|
|
14162
|
+
const libPath = join8(targetDir, info.libName);
|
|
14045
14163
|
let libHash = null;
|
|
14046
14164
|
try {
|
|
14047
14165
|
libHash = sha256File(libPath);
|
|
@@ -14066,8 +14184,8 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
14066
14184
|
function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, copyFile = copyFileSync3) {
|
|
14067
14185
|
const requiredLibs = new Set([info.libName]);
|
|
14068
14186
|
for (const libFile of realFiles) {
|
|
14069
|
-
const src =
|
|
14070
|
-
const dst =
|
|
14187
|
+
const src = join8(extractedDir, libFile);
|
|
14188
|
+
const dst = join8(targetDir, libFile);
|
|
14071
14189
|
try {
|
|
14072
14190
|
copyFile(src, dst);
|
|
14073
14191
|
if (process.platform !== "win32") {
|
|
@@ -14083,12 +14201,12 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
14083
14201
|
}
|
|
14084
14202
|
const targetRoot = realpathSync(targetDir);
|
|
14085
14203
|
for (const link of symlinks) {
|
|
14086
|
-
const dst =
|
|
14204
|
+
const dst = join8(targetDir, link.name);
|
|
14087
14205
|
try {
|
|
14088
14206
|
unlinkSync3(dst);
|
|
14089
14207
|
} catch {}
|
|
14090
|
-
const dstForContainment =
|
|
14091
|
-
const resolvedTarget =
|
|
14208
|
+
const dstForContainment = join8(targetRoot, link.name);
|
|
14209
|
+
const resolvedTarget = resolve2(dirname4(dstForContainment), link.target);
|
|
14092
14210
|
if (!isPathInsideRoot(targetRoot, resolvedTarget)) {
|
|
14093
14211
|
const message = `ONNX Runtime symlink ${link.name} points outside install dir: ${link.target}`;
|
|
14094
14212
|
if (requiredLibs.has(link.name)) {
|
|
@@ -14108,7 +14226,7 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
14108
14226
|
log(`ORT extract: failed to symlink optional ${link.name}: ${symlinkErr}`);
|
|
14109
14227
|
}
|
|
14110
14228
|
}
|
|
14111
|
-
const requiredPath =
|
|
14229
|
+
const requiredPath = join8(targetDir, info.libName);
|
|
14112
14230
|
if (!existsSync5(requiredPath)) {
|
|
14113
14231
|
rmSync2(targetDir, { recursive: true, force: true });
|
|
14114
14232
|
throw new Error(`Required ONNX Runtime library missing after install: ${requiredPath}`);
|
|
@@ -14135,17 +14253,17 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
|
|
|
14135
14253
|
...sha256 ? { sha256 } : {},
|
|
14136
14254
|
archiveSha256
|
|
14137
14255
|
};
|
|
14138
|
-
writeFileSync2(
|
|
14256
|
+
writeFileSync2(join8(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
|
|
14139
14257
|
} catch (err) {
|
|
14140
14258
|
log(`[onnx] failed to write installed-meta in ${installDir}: ${err}`);
|
|
14141
14259
|
}
|
|
14142
14260
|
}
|
|
14143
14261
|
function readOnnxInstalledMeta(installDir) {
|
|
14144
|
-
const
|
|
14262
|
+
const path2 = join8(installDir, ONNX_INSTALLED_META_FILE);
|
|
14145
14263
|
try {
|
|
14146
|
-
if (!statSync3(
|
|
14264
|
+
if (!statSync3(path2).isFile())
|
|
14147
14265
|
return null;
|
|
14148
|
-
const raw = readFileSync3(
|
|
14266
|
+
const raw = readFileSync3(path2, "utf8");
|
|
14149
14267
|
const parsed = JSON.parse(raw);
|
|
14150
14268
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
14151
14269
|
return null;
|
|
@@ -14159,9 +14277,9 @@ function readOnnxInstalledMeta(installDir) {
|
|
|
14159
14277
|
return null;
|
|
14160
14278
|
}
|
|
14161
14279
|
}
|
|
14162
|
-
function sha256File(
|
|
14280
|
+
function sha256File(path2) {
|
|
14163
14281
|
const hash = createHash2("sha256");
|
|
14164
|
-
hash.update(readFileSync3(
|
|
14282
|
+
hash.update(readFileSync3(path2));
|
|
14165
14283
|
return hash.digest("hex");
|
|
14166
14284
|
}
|
|
14167
14285
|
function acquireLock(lockPath) {
|
|
@@ -14997,6 +15115,91 @@ function normalizeKey(projectRoot) {
|
|
|
14997
15115
|
return stripped;
|
|
14998
15116
|
}
|
|
14999
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
|
+
}
|
|
15000
15203
|
// ../aft-bridge/dist/zoom-format.js
|
|
15001
15204
|
function formatZoomText(targetLabel, response) {
|
|
15002
15205
|
const range = response.range;
|
|
@@ -15077,16 +15280,39 @@ function formatZoomMultiTargetResult(entries) {
|
|
|
15077
15280
|
|
|
15078
15281
|
`) };
|
|
15079
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
|
+
}
|
|
15080
15306
|
// src/bg-notifications.ts
|
|
15081
15307
|
import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypto";
|
|
15082
15308
|
|
|
15083
15309
|
// src/logger.ts
|
|
15084
15310
|
import * as fs from "node:fs";
|
|
15085
|
-
import * as
|
|
15086
|
-
import * as
|
|
15311
|
+
import * as os2 from "node:os";
|
|
15312
|
+
import * as path2 from "node:path";
|
|
15087
15313
|
var TAG = "[aft-plugin]";
|
|
15088
15314
|
var isTestEnv = process.env.BUN_TEST === "1" || false;
|
|
15089
|
-
var logFile =
|
|
15315
|
+
var logFile = path2.join(os2.tmpdir(), isTestEnv ? "aft-plugin-test.log" : "aft-plugin.log");
|
|
15090
15316
|
var useStderr = process.env.AFT_LOG_STDERR === "1";
|
|
15091
15317
|
var buffer = [];
|
|
15092
15318
|
var flushTimer = null;
|
|
@@ -16030,8 +16256,8 @@ function formatDuration(completion) {
|
|
|
16030
16256
|
|
|
16031
16257
|
// src/config.ts
|
|
16032
16258
|
import { existsSync as existsSync6, readFileSync as readFileSync4, renameSync as renameSync4, unlinkSync as unlinkSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
16033
|
-
import { homedir as
|
|
16034
|
-
import { join as
|
|
16259
|
+
import { homedir as homedir7 } from "node:os";
|
|
16260
|
+
import { join as join10 } from "node:path";
|
|
16035
16261
|
var import_comment_json = __toESM(require_src2(), 1);
|
|
16036
16262
|
|
|
16037
16263
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
|
|
@@ -16799,10 +17025,10 @@ function mergeDefs(...defs) {
|
|
|
16799
17025
|
function cloneDef(schema) {
|
|
16800
17026
|
return mergeDefs(schema._zod.def);
|
|
16801
17027
|
}
|
|
16802
|
-
function getElementAtPath(obj,
|
|
16803
|
-
if (!
|
|
17028
|
+
function getElementAtPath(obj, path3) {
|
|
17029
|
+
if (!path3)
|
|
16804
17030
|
return obj;
|
|
16805
|
-
return
|
|
17031
|
+
return path3.reduce((acc, key) => acc?.[key], obj);
|
|
16806
17032
|
}
|
|
16807
17033
|
function promiseAllObject(promisesObj) {
|
|
16808
17034
|
const keys = Object.keys(promisesObj);
|
|
@@ -17183,11 +17409,11 @@ function aborted(x, startIndex = 0) {
|
|
|
17183
17409
|
}
|
|
17184
17410
|
return false;
|
|
17185
17411
|
}
|
|
17186
|
-
function prefixIssues(
|
|
17412
|
+
function prefixIssues(path3, issues) {
|
|
17187
17413
|
return issues.map((iss) => {
|
|
17188
17414
|
var _a;
|
|
17189
17415
|
(_a = iss).path ?? (_a.path = []);
|
|
17190
|
-
iss.path.unshift(
|
|
17416
|
+
iss.path.unshift(path3);
|
|
17191
17417
|
return iss;
|
|
17192
17418
|
});
|
|
17193
17419
|
}
|
|
@@ -17370,7 +17596,7 @@ function formatError(error3, mapper = (issue2) => issue2.message) {
|
|
|
17370
17596
|
}
|
|
17371
17597
|
function treeifyError(error3, mapper = (issue2) => issue2.message) {
|
|
17372
17598
|
const result = { errors: [] };
|
|
17373
|
-
const processError = (error4,
|
|
17599
|
+
const processError = (error4, path3 = []) => {
|
|
17374
17600
|
var _a, _b;
|
|
17375
17601
|
for (const issue2 of error4.issues) {
|
|
17376
17602
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -17380,7 +17606,7 @@ function treeifyError(error3, mapper = (issue2) => issue2.message) {
|
|
|
17380
17606
|
} else if (issue2.code === "invalid_element") {
|
|
17381
17607
|
processError({ issues: issue2.issues }, issue2.path);
|
|
17382
17608
|
} else {
|
|
17383
|
-
const fullpath = [...
|
|
17609
|
+
const fullpath = [...path3, ...issue2.path];
|
|
17384
17610
|
if (fullpath.length === 0) {
|
|
17385
17611
|
result.errors.push(mapper(issue2));
|
|
17386
17612
|
continue;
|
|
@@ -17412,8 +17638,8 @@ function treeifyError(error3, mapper = (issue2) => issue2.message) {
|
|
|
17412
17638
|
}
|
|
17413
17639
|
function toDotPath(_path) {
|
|
17414
17640
|
const segs = [];
|
|
17415
|
-
const
|
|
17416
|
-
for (const seg of
|
|
17641
|
+
const path3 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
17642
|
+
for (const seg of path3) {
|
|
17417
17643
|
if (typeof seg === "number")
|
|
17418
17644
|
segs.push(`[${seg}]`);
|
|
17419
17645
|
else if (typeof seg === "symbol")
|
|
@@ -29160,13 +29386,13 @@ function resolveRef(ref, ctx) {
|
|
|
29160
29386
|
if (!ref.startsWith("#")) {
|
|
29161
29387
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
29162
29388
|
}
|
|
29163
|
-
const
|
|
29164
|
-
if (
|
|
29389
|
+
const path3 = ref.slice(1).split("/").filter(Boolean);
|
|
29390
|
+
if (path3.length === 0) {
|
|
29165
29391
|
return ctx.rootSchema;
|
|
29166
29392
|
}
|
|
29167
29393
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
29168
|
-
if (
|
|
29169
|
-
const key =
|
|
29394
|
+
if (path3[0] === defsKey) {
|
|
29395
|
+
const key = path3[1];
|
|
29170
29396
|
if (!key || !ctx.defs[key]) {
|
|
29171
29397
|
throw new Error(`Reference not found: ${ref}`);
|
|
29172
29398
|
}
|
|
@@ -29864,9 +30090,9 @@ function extractCommentsForPreservation(content) {
|
|
|
29864
30090
|
}
|
|
29865
30091
|
return comments;
|
|
29866
30092
|
}
|
|
29867
|
-
function ensureRecordAtPath(root,
|
|
30093
|
+
function ensureRecordAtPath(root, path3) {
|
|
29868
30094
|
let current = root;
|
|
29869
|
-
for (const segment of
|
|
30095
|
+
for (const segment of path3) {
|
|
29870
30096
|
const existing = current[segment];
|
|
29871
30097
|
if (!existing || typeof existing !== "object" || Array.isArray(existing)) {
|
|
29872
30098
|
current[segment] = {};
|
|
@@ -29875,9 +30101,9 @@ function ensureRecordAtPath(root, path2) {
|
|
|
29875
30101
|
}
|
|
29876
30102
|
return current;
|
|
29877
30103
|
}
|
|
29878
|
-
function hasPath(root,
|
|
30104
|
+
function hasPath(root, path3) {
|
|
29879
30105
|
let current = root;
|
|
29880
|
-
for (const segment of
|
|
30106
|
+
for (const segment of path3) {
|
|
29881
30107
|
if (!current || typeof current !== "object" || Array.isArray(current))
|
|
29882
30108
|
return false;
|
|
29883
30109
|
const record2 = current;
|
|
@@ -29887,9 +30113,9 @@ function hasPath(root, path2) {
|
|
|
29887
30113
|
}
|
|
29888
30114
|
return true;
|
|
29889
30115
|
}
|
|
29890
|
-
function setPath(root,
|
|
29891
|
-
const parent = ensureRecordAtPath(root,
|
|
29892
|
-
parent[
|
|
30116
|
+
function setPath(root, path3, value) {
|
|
30117
|
+
const parent = ensureRecordAtPath(root, path3.slice(0, -1));
|
|
30118
|
+
parent[path3[path3.length - 1]] = value;
|
|
29893
30119
|
}
|
|
29894
30120
|
function migrateRawConfig(rawConfig, configPath, logger) {
|
|
29895
30121
|
const oldKeys = [];
|
|
@@ -30226,17 +30452,17 @@ function getOpenCodeConfigDir() {
|
|
|
30226
30452
|
if (envDir) {
|
|
30227
30453
|
return envDir;
|
|
30228
30454
|
}
|
|
30229
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME ||
|
|
30230
|
-
return
|
|
30455
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME || join10(homedir7(), ".config");
|
|
30456
|
+
return join10(xdgConfig, "opencode");
|
|
30231
30457
|
}
|
|
30232
30458
|
function loadAftConfig(projectDirectory) {
|
|
30233
30459
|
const configDir = getOpenCodeConfigDir();
|
|
30234
|
-
const userBasePath =
|
|
30460
|
+
const userBasePath = join10(configDir, "aft");
|
|
30235
30461
|
migrateAftConfigFile(`${userBasePath}.jsonc`);
|
|
30236
30462
|
migrateAftConfigFile(`${userBasePath}.json`);
|
|
30237
30463
|
const userDetected = detectConfigFile(userBasePath);
|
|
30238
30464
|
const userConfigPath = userDetected.format !== "none" ? userDetected.path : `${userBasePath}.json`;
|
|
30239
|
-
const projectBasePath =
|
|
30465
|
+
const projectBasePath = join10(projectDirectory, ".opencode", "aft");
|
|
30240
30466
|
migrateAftConfigFile(`${projectBasePath}.jsonc`);
|
|
30241
30467
|
migrateAftConfigFile(`${projectBasePath}.json`);
|
|
30242
30468
|
const projectDetected = detectConfigFile(projectBasePath);
|
|
@@ -30262,8 +30488,8 @@ function loadAftConfig(projectDirectory) {
|
|
|
30262
30488
|
|
|
30263
30489
|
// src/notifications.ts
|
|
30264
30490
|
import { existsSync as existsSync7, readFileSync as readFileSync5 } from "node:fs";
|
|
30265
|
-
import { homedir as
|
|
30266
|
-
import { join as
|
|
30491
|
+
import { homedir as homedir8, platform } from "node:os";
|
|
30492
|
+
import { join as join11 } from "node:path";
|
|
30267
30493
|
function isTuiMode() {
|
|
30268
30494
|
return process.env.OPENCODE_CLIENT === "cli";
|
|
30269
30495
|
}
|
|
@@ -30283,18 +30509,18 @@ var FEATURE_MARKER = `${AFT_MARKER} New in`;
|
|
|
30283
30509
|
var WARNING_MARKER = `${AFT_MARKER} ⚠️`;
|
|
30284
30510
|
var STATUS_MARKER = `${AFT_MARKER} ✅`;
|
|
30285
30511
|
function getDesktopStatePath() {
|
|
30286
|
-
const
|
|
30287
|
-
const home =
|
|
30288
|
-
if (
|
|
30289
|
-
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");
|
|
30290
30516
|
}
|
|
30291
|
-
if (
|
|
30292
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME ||
|
|
30293
|
-
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");
|
|
30294
30520
|
}
|
|
30295
|
-
if (
|
|
30296
|
-
const appData = process.env.APPDATA ||
|
|
30297
|
-
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");
|
|
30298
30524
|
}
|
|
30299
30525
|
return null;
|
|
30300
30526
|
}
|
|
@@ -30764,37 +30990,37 @@ import { dirname as dirname7 } from "node:path";
|
|
|
30764
30990
|
import { spawn as spawn2 } from "node:child_process";
|
|
30765
30991
|
import { cpSync, existsSync as existsSync9, mkdtempSync, readFileSync as readFileSync7, rmSync as rmSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
30766
30992
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
30767
|
-
import { basename as basename2, dirname as dirname6, join as
|
|
30993
|
+
import { basename as basename2, dirname as dirname6, join as join14 } from "node:path";
|
|
30768
30994
|
var import_comment_json3 = __toESM(require_src2(), 1);
|
|
30769
30995
|
|
|
30770
30996
|
// src/hooks/auto-update-checker/checker.ts
|
|
30771
30997
|
var import_comment_json2 = __toESM(require_src2(), 1);
|
|
30772
30998
|
import { existsSync as existsSync8, readFileSync as readFileSync6, statSync as statSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
30773
|
-
import { homedir as
|
|
30774
|
-
import { dirname as dirname5, isAbsolute as
|
|
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";
|
|
30775
31001
|
import { fileURLToPath } from "node:url";
|
|
30776
31002
|
|
|
30777
31003
|
// src/hooks/auto-update-checker/constants.ts
|
|
30778
|
-
import { homedir as
|
|
30779
|
-
import { join as
|
|
31004
|
+
import { homedir as homedir9, platform as platform2 } from "node:os";
|
|
31005
|
+
import { join as join12 } from "node:path";
|
|
30780
31006
|
var PACKAGE_NAME = "@cortexkit/aft-opencode";
|
|
30781
31007
|
var NPM_REGISTRY_URL = "https://registry.npmjs.org";
|
|
30782
31008
|
var NPM_FETCH_TIMEOUT = 1e4;
|
|
30783
31009
|
function getOpenCodeCacheRoot() {
|
|
30784
31010
|
if (platform2() === "win32") {
|
|
30785
|
-
return
|
|
31011
|
+
return join12(process.env.LOCALAPPDATA ?? homedir9(), "opencode");
|
|
30786
31012
|
}
|
|
30787
|
-
return
|
|
31013
|
+
return join12(homedir9(), ".cache", "opencode");
|
|
30788
31014
|
}
|
|
30789
31015
|
function getOpenCodeConfigRoot() {
|
|
30790
31016
|
if (platform2() === "win32") {
|
|
30791
|
-
return
|
|
31017
|
+
return join12(process.env.APPDATA ?? join12(homedir9(), "AppData", "Roaming"), "opencode");
|
|
30792
31018
|
}
|
|
30793
|
-
return
|
|
31019
|
+
return join12(process.env.XDG_CONFIG_HOME ?? join12(homedir9(), ".config"), "opencode");
|
|
30794
31020
|
}
|
|
30795
|
-
var CACHE_DIR =
|
|
30796
|
-
var USER_OPENCODE_CONFIG =
|
|
30797
|
-
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");
|
|
30798
31024
|
|
|
30799
31025
|
// src/hooks/auto-update-checker/types.ts
|
|
30800
31026
|
var NpmPackageEnvelopeSchema = exports_external.object({
|
|
@@ -30852,8 +31078,8 @@ function extractChannel(version2) {
|
|
|
30852
31078
|
}
|
|
30853
31079
|
function getConfigPaths(directory) {
|
|
30854
31080
|
return [
|
|
30855
|
-
|
|
30856
|
-
|
|
31081
|
+
join13(directory, ".opencode", "opencode.json"),
|
|
31082
|
+
join13(directory, ".opencode", "opencode.jsonc"),
|
|
30857
31083
|
USER_OPENCODE_CONFIG,
|
|
30858
31084
|
USER_OPENCODE_CONFIG_JSONC
|
|
30859
31085
|
];
|
|
@@ -30866,9 +31092,9 @@ function resolvePathPluginSpec(spec, configPath) {
|
|
|
30866
31092
|
return spec.replace(/^file:\/\//, "");
|
|
30867
31093
|
}
|
|
30868
31094
|
}
|
|
30869
|
-
if (
|
|
31095
|
+
if (isAbsolute4(spec) || /^[A-Za-z]:[\\/]/.test(spec))
|
|
30870
31096
|
return spec;
|
|
30871
|
-
return
|
|
31097
|
+
return resolve3(dirname5(configPath), spec);
|
|
30872
31098
|
}
|
|
30873
31099
|
function getLocalDevPath(directory) {
|
|
30874
31100
|
for (const configPath of getConfigPaths(directory)) {
|
|
@@ -30880,7 +31106,7 @@ function getLocalDevPath(directory) {
|
|
|
30880
31106
|
for (const entry of plugins) {
|
|
30881
31107
|
if (entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`))
|
|
30882
31108
|
continue;
|
|
30883
|
-
if (entry.startsWith("file://") || entry.startsWith(".") ||
|
|
31109
|
+
if (entry.startsWith("file://") || entry.startsWith(".") || isAbsolute4(entry)) {
|
|
30884
31110
|
const localPath = resolvePathPluginSpec(entry, configPath);
|
|
30885
31111
|
const pkgPath = findPackageJsonUp(localPath);
|
|
30886
31112
|
if (!pkgPath)
|
|
@@ -30899,7 +31125,7 @@ function findPackageJsonUp(startPath) {
|
|
|
30899
31125
|
const stat = statSync4(startPath);
|
|
30900
31126
|
let dir = stat.isDirectory() ? startPath : dirname5(startPath);
|
|
30901
31127
|
for (let i = 0;i < 10; i++) {
|
|
30902
|
-
const pkgPath =
|
|
31128
|
+
const pkgPath = join13(dir, "package.json");
|
|
30903
31129
|
if (existsSync8(pkgPath)) {
|
|
30904
31130
|
try {
|
|
30905
31131
|
const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync6(pkgPath, "utf-8")));
|
|
@@ -30960,7 +31186,7 @@ function findPluginEntry(directory) {
|
|
|
30960
31186
|
}
|
|
30961
31187
|
var cachedPackageVersion = null;
|
|
30962
31188
|
function getSpecCachePackageJsonPath(spec) {
|
|
30963
|
-
return
|
|
31189
|
+
return join13(CACHE_DIR, spec, "node_modules", PACKAGE_NAME, "package.json");
|
|
30964
31190
|
}
|
|
30965
31191
|
function getCachedVersion(spec) {
|
|
30966
31192
|
if (!spec && cachedPackageVersion)
|
|
@@ -30969,7 +31195,7 @@ function getCachedVersion(spec) {
|
|
|
30969
31195
|
getCurrentRuntimePackageJsonPath(),
|
|
30970
31196
|
spec ? getSpecCachePackageJsonPath(spec) : null,
|
|
30971
31197
|
getSpecCachePackageJsonPath(`${PACKAGE_NAME}@latest`),
|
|
30972
|
-
|
|
31198
|
+
join13(homedir10(), ".cache", "opencode", "node_modules", PACKAGE_NAME, "package.json")
|
|
30973
31199
|
].filter(isString);
|
|
30974
31200
|
for (const packageJsonPath of candidates) {
|
|
30975
31201
|
try {
|
|
@@ -31017,10 +31243,10 @@ async function getLatestVersion(channel = "latest", options = {}) {
|
|
|
31017
31243
|
// src/hooks/auto-update-checker/cache.ts
|
|
31018
31244
|
var pendingSnapshots = new Map;
|
|
31019
31245
|
function createAutoUpdateSnapshot(installDir, packageJsonPath, packageName) {
|
|
31020
|
-
const packageDir =
|
|
31021
|
-
const lockfilePath =
|
|
31022
|
-
const tempDir = mkdtempSync(
|
|
31023
|
-
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;
|
|
31024
31250
|
if (stagedPackageDir)
|
|
31025
31251
|
cpSync(packageDir, stagedPackageDir, { recursive: true });
|
|
31026
31252
|
return {
|
|
@@ -31061,7 +31287,7 @@ function stripPackageNameFromPath(pathValue, packageName) {
|
|
|
31061
31287
|
return current;
|
|
31062
31288
|
}
|
|
31063
31289
|
function removeFromPackageLock(installDir, packageName) {
|
|
31064
|
-
const lockPath =
|
|
31290
|
+
const lockPath = join14(installDir, "package-lock.json");
|
|
31065
31291
|
if (!existsSync9(lockPath))
|
|
31066
31292
|
return false;
|
|
31067
31293
|
try {
|
|
@@ -31110,7 +31336,7 @@ function ensureDependencyVersion(packageJsonPath, packageName, version2) {
|
|
|
31110
31336
|
}
|
|
31111
31337
|
}
|
|
31112
31338
|
function removeInstalledPackage(installDir, packageName) {
|
|
31113
|
-
const packageDir =
|
|
31339
|
+
const packageDir = join14(installDir, "node_modules", packageName);
|
|
31114
31340
|
if (!existsSync9(packageDir))
|
|
31115
31341
|
return false;
|
|
31116
31342
|
rmSync3(packageDir, { recursive: true, force: true });
|
|
@@ -31123,13 +31349,13 @@ function resolveInstallContext(runtimePackageJsonPath = getCurrentRuntimePackage
|
|
|
31123
31349
|
const nodeModulesDir = stripPackageNameFromPath(packageDir, PACKAGE_NAME);
|
|
31124
31350
|
if (nodeModulesDir && basename2(nodeModulesDir) === "node_modules") {
|
|
31125
31351
|
const installDir = dirname6(nodeModulesDir);
|
|
31126
|
-
const packageJsonPath =
|
|
31352
|
+
const packageJsonPath = join14(installDir, "package.json");
|
|
31127
31353
|
if (existsSync9(packageJsonPath))
|
|
31128
31354
|
return { installDir, packageJsonPath };
|
|
31129
31355
|
}
|
|
31130
31356
|
return null;
|
|
31131
31357
|
}
|
|
31132
|
-
const legacyPackageJsonPath =
|
|
31358
|
+
const legacyPackageJsonPath = join14(dirname6(CACHE_DIR), "package.json");
|
|
31133
31359
|
if (existsSync9(legacyPackageJsonPath)) {
|
|
31134
31360
|
return { installDir: dirname6(CACHE_DIR), packageJsonPath: legacyPackageJsonPath };
|
|
31135
31361
|
}
|
|
@@ -31460,7 +31686,7 @@ import {
|
|
|
31460
31686
|
statSync as statSync6,
|
|
31461
31687
|
writeFileSync as writeFileSync8
|
|
31462
31688
|
} from "node:fs";
|
|
31463
|
-
import { join as
|
|
31689
|
+
import { join as join17 } from "node:path";
|
|
31464
31690
|
|
|
31465
31691
|
// src/lsp-cache.ts
|
|
31466
31692
|
import {
|
|
@@ -31472,36 +31698,36 @@ import {
|
|
|
31472
31698
|
unlinkSync as unlinkSync5,
|
|
31473
31699
|
writeFileSync as writeFileSync7
|
|
31474
31700
|
} from "node:fs";
|
|
31475
|
-
import { homedir as
|
|
31476
|
-
import { join as
|
|
31701
|
+
import { homedir as homedir11 } from "node:os";
|
|
31702
|
+
import { join as join15 } from "node:path";
|
|
31477
31703
|
function aftCacheBase() {
|
|
31478
31704
|
const override = process.env.AFT_CACHE_DIR;
|
|
31479
31705
|
if (override && override.length > 0)
|
|
31480
31706
|
return override;
|
|
31481
31707
|
if (process.platform === "win32") {
|
|
31482
31708
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
31483
|
-
const base2 = localAppData ||
|
|
31484
|
-
return
|
|
31709
|
+
const base2 = localAppData || join15(homedir11(), "AppData", "Local");
|
|
31710
|
+
return join15(base2, "aft");
|
|
31485
31711
|
}
|
|
31486
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
31487
|
-
return
|
|
31712
|
+
const base = process.env.XDG_CACHE_HOME || join15(homedir11(), ".cache");
|
|
31713
|
+
return join15(base, "aft");
|
|
31488
31714
|
}
|
|
31489
31715
|
function lspCacheRoot() {
|
|
31490
|
-
return
|
|
31716
|
+
return join15(aftCacheBase(), "lsp-packages");
|
|
31491
31717
|
}
|
|
31492
31718
|
function lspPackageDir(npmPackage) {
|
|
31493
|
-
return
|
|
31719
|
+
return join15(lspCacheRoot(), encodeURIComponent(npmPackage));
|
|
31494
31720
|
}
|
|
31495
31721
|
function lspBinaryPath(npmPackage, binary) {
|
|
31496
|
-
return
|
|
31722
|
+
return join15(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
|
|
31497
31723
|
}
|
|
31498
31724
|
function lspBinDir(npmPackage) {
|
|
31499
|
-
return
|
|
31725
|
+
return join15(lspPackageDir(npmPackage), "node_modules", ".bin");
|
|
31500
31726
|
}
|
|
31501
31727
|
function isInstalled(npmPackage, binary) {
|
|
31502
31728
|
for (const candidate of lspBinaryCandidates(binary)) {
|
|
31503
31729
|
try {
|
|
31504
|
-
if (statSync5(
|
|
31730
|
+
if (statSync5(join15(lspBinDir(npmPackage), candidate)).isFile())
|
|
31505
31731
|
return true;
|
|
31506
31732
|
} catch {}
|
|
31507
31733
|
}
|
|
@@ -31521,17 +31747,17 @@ function writeInstalledMetaIn(installDir, version2, sha256) {
|
|
|
31521
31747
|
installedAt: new Date().toISOString(),
|
|
31522
31748
|
...sha256 ? { sha256 } : {}
|
|
31523
31749
|
};
|
|
31524
|
-
writeFileSync7(
|
|
31750
|
+
writeFileSync7(join15(installDir, INSTALLED_META_FILE), JSON.stringify(meta3), "utf8");
|
|
31525
31751
|
} catch (err) {
|
|
31526
31752
|
log2(`[lsp-cache] failed to write installed-meta in ${installDir}: ${err}`);
|
|
31527
31753
|
}
|
|
31528
31754
|
}
|
|
31529
31755
|
function readInstalledMetaIn(installDir) {
|
|
31530
|
-
const
|
|
31756
|
+
const path3 = join15(installDir, INSTALLED_META_FILE);
|
|
31531
31757
|
try {
|
|
31532
|
-
if (!statSync5(
|
|
31758
|
+
if (!statSync5(path3).isFile())
|
|
31533
31759
|
return null;
|
|
31534
|
-
const raw = readFileSync9(
|
|
31760
|
+
const raw = readFileSync9(path3, "utf8");
|
|
31535
31761
|
const parsed = JSON.parse(raw);
|
|
31536
31762
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
31537
31763
|
return null;
|
|
@@ -31551,7 +31777,7 @@ function readInstalledMeta(packageKey) {
|
|
|
31551
31777
|
return readInstalledMetaIn(lspPackageDir(packageKey));
|
|
31552
31778
|
}
|
|
31553
31779
|
function lockPath(npmPackage) {
|
|
31554
|
-
return
|
|
31780
|
+
return join15(lspPackageDir(npmPackage), ".aft-installing");
|
|
31555
31781
|
}
|
|
31556
31782
|
var STALE_LOCK_MS2 = 30 * 60 * 1000;
|
|
31557
31783
|
function acquireInstallLock(lockKey) {
|
|
@@ -31658,7 +31884,7 @@ async function withInstallLock(lockKey, task) {
|
|
|
31658
31884
|
}
|
|
31659
31885
|
var VERSION_CHECK_FILE = ".aft-version-check";
|
|
31660
31886
|
function readVersionCheck(npmPackage) {
|
|
31661
|
-
const file2 =
|
|
31887
|
+
const file2 = join15(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
|
|
31662
31888
|
try {
|
|
31663
31889
|
const raw = readFileSync9(file2, "utf8");
|
|
31664
31890
|
const parsed = JSON.parse(raw);
|
|
@@ -31675,7 +31901,7 @@ function readVersionCheck(npmPackage) {
|
|
|
31675
31901
|
}
|
|
31676
31902
|
function writeVersionCheck(npmPackage, latest) {
|
|
31677
31903
|
mkdirSync7(lspPackageDir(npmPackage), { recursive: true });
|
|
31678
|
-
const file2 =
|
|
31904
|
+
const file2 = join15(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
|
|
31679
31905
|
const record2 = {
|
|
31680
31906
|
last_checked: new Date().toISOString(),
|
|
31681
31907
|
latest_eligible: latest
|
|
@@ -31838,7 +32064,7 @@ var NPM_LSP_TABLE = [
|
|
|
31838
32064
|
|
|
31839
32065
|
// src/lsp-project-relevance.ts
|
|
31840
32066
|
import { existsSync as existsSync11, readdirSync as readdirSync3, readFileSync as readFileSync10 } from "node:fs";
|
|
31841
|
-
import { join as
|
|
32067
|
+
import { join as join16 } from "node:path";
|
|
31842
32068
|
var MAX_WALK_DIRS = 200;
|
|
31843
32069
|
var MAX_WALK_DEPTH = 4;
|
|
31844
32070
|
var NOISE_DIRS = new Set([
|
|
@@ -31855,7 +32081,7 @@ function hasRootMarker(projectRoot, rootMarkers) {
|
|
|
31855
32081
|
if (!rootMarkers)
|
|
31856
32082
|
return false;
|
|
31857
32083
|
for (const marker of rootMarkers) {
|
|
31858
|
-
if (existsSync11(
|
|
32084
|
+
if (existsSync11(join16(projectRoot, marker)))
|
|
31859
32085
|
return true;
|
|
31860
32086
|
}
|
|
31861
32087
|
return false;
|
|
@@ -31879,7 +32105,7 @@ function hasPackageJsonDep(projectRoot, depNames) {
|
|
|
31879
32105
|
}
|
|
31880
32106
|
function readPackageJson(projectRoot) {
|
|
31881
32107
|
try {
|
|
31882
|
-
const raw = readFileSync10(
|
|
32108
|
+
const raw = readFileSync10(join16(projectRoot, "package.json"), "utf8");
|
|
31883
32109
|
const parsed = JSON.parse(raw);
|
|
31884
32110
|
if (typeof parsed !== "object" || parsed === null)
|
|
31885
32111
|
return null;
|
|
@@ -31909,7 +32135,7 @@ function relevantExtensionsInProject(projectRoot, extToServer) {
|
|
|
31909
32135
|
for (const entry of entries) {
|
|
31910
32136
|
if (entry.isDirectory()) {
|
|
31911
32137
|
if (current.depth < MAX_WALK_DEPTH && !NOISE_DIRS.has(entry.name.toLowerCase())) {
|
|
31912
|
-
queue.push({ dir:
|
|
32138
|
+
queue.push({ dir: join16(current.dir, entry.name), depth: current.depth + 1 });
|
|
31913
32139
|
}
|
|
31914
32140
|
continue;
|
|
31915
32141
|
}
|
|
@@ -32036,7 +32262,7 @@ async function resolveTargetVersion(spec, config2, fetchImpl = fetch) {
|
|
|
32036
32262
|
}
|
|
32037
32263
|
function ensureInstallAnchor(cwd) {
|
|
32038
32264
|
try {
|
|
32039
|
-
const stub =
|
|
32265
|
+
const stub = join17(cwd, "package.json");
|
|
32040
32266
|
if (!existsSync12(stub)) {
|
|
32041
32267
|
writeFileSync8(stub, `${JSON.stringify({ name: "aft-lsp-cache", version: "0.0.0", private: true })}
|
|
32042
32268
|
`);
|
|
@@ -32046,18 +32272,18 @@ function ensureInstallAnchor(cwd) {
|
|
|
32046
32272
|
}
|
|
32047
32273
|
}
|
|
32048
32274
|
function runInstall(spec, version2, cwd, signal) {
|
|
32049
|
-
return new Promise((
|
|
32275
|
+
return new Promise((resolve4) => {
|
|
32050
32276
|
const target = `${spec.npm}@${version2}`;
|
|
32051
32277
|
log2(`[lsp] installing ${target} to ${cwd}`);
|
|
32052
32278
|
if (signal?.aborted) {
|
|
32053
32279
|
warn2(`[lsp] install ${target} aborted before spawn`);
|
|
32054
|
-
|
|
32280
|
+
resolve4(false);
|
|
32055
32281
|
return;
|
|
32056
32282
|
}
|
|
32057
32283
|
const npm = resolveNpm();
|
|
32058
32284
|
if (!npm) {
|
|
32059
32285
|
warn2(`[lsp] npm not found on PATH or known locations; cannot install ${target}`);
|
|
32060
|
-
|
|
32286
|
+
resolve4(false);
|
|
32061
32287
|
return;
|
|
32062
32288
|
}
|
|
32063
32289
|
ensureInstallAnchor(cwd);
|
|
@@ -32080,7 +32306,7 @@ function runInstall(spec, version2, cwd, signal) {
|
|
|
32080
32306
|
return;
|
|
32081
32307
|
settled = true;
|
|
32082
32308
|
cleanup();
|
|
32083
|
-
|
|
32309
|
+
resolve4(ok);
|
|
32084
32310
|
};
|
|
32085
32311
|
const onAbort = () => {
|
|
32086
32312
|
warn2(`[lsp] install ${target} aborted during shutdown`);
|
|
@@ -32181,7 +32407,7 @@ function cachedPackageDir(npmPackage) {
|
|
|
32181
32407
|
return lspBinDir(npmPackage).replace(/[\\/]node_modules[\\/]\.bin[\\/]?$/, "");
|
|
32182
32408
|
}
|
|
32183
32409
|
function hashInstalledBinary(spec) {
|
|
32184
|
-
return new Promise((
|
|
32410
|
+
return new Promise((resolve4, reject) => {
|
|
32185
32411
|
const candidates = process.platform === "win32" ? [
|
|
32186
32412
|
lspBinaryPath(spec.npm, spec.binary),
|
|
32187
32413
|
lspBinaryPath(spec.npm, `${spec.binary}.cmd`),
|
|
@@ -32205,7 +32431,7 @@ function hashInstalledBinary(spec) {
|
|
|
32205
32431
|
const stream = createReadStream(pathToHash);
|
|
32206
32432
|
stream.on("error", reject);
|
|
32207
32433
|
stream.on("data", (chunk) => hash2.update(chunk));
|
|
32208
|
-
stream.on("end", () =>
|
|
32434
|
+
stream.on("end", () => resolve4(hash2.digest("hex")));
|
|
32209
32435
|
});
|
|
32210
32436
|
}
|
|
32211
32437
|
function installedBinaryPath(spec) {
|
|
@@ -32223,15 +32449,15 @@ function installedBinaryPath(spec) {
|
|
|
32223
32449
|
}
|
|
32224
32450
|
return null;
|
|
32225
32451
|
}
|
|
32226
|
-
function sha256OfFileSync(
|
|
32227
|
-
return createHash4("sha256").update(readFileSync11(
|
|
32452
|
+
function sha256OfFileSync(path3) {
|
|
32453
|
+
return createHash4("sha256").update(readFileSync11(path3)).digest("hex");
|
|
32228
32454
|
}
|
|
32229
32455
|
function quarantineCachedNpmInstall(spec, reason) {
|
|
32230
32456
|
const packageDir = lspPackageDir(spec.npm);
|
|
32231
|
-
const dest =
|
|
32457
|
+
const dest = join17(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
|
|
32232
32458
|
warn2(`[lsp] tofu_mismatch ${spec.npm}: ${reason}; quarantining ${packageDir} -> ${dest}`);
|
|
32233
32459
|
try {
|
|
32234
|
-
mkdirSync8(
|
|
32460
|
+
mkdirSync8(join17(dest, ".."), { recursive: true });
|
|
32235
32461
|
rmSync5(dest, { recursive: true, force: true });
|
|
32236
32462
|
renameSync6(packageDir, dest);
|
|
32237
32463
|
} catch (err) {
|
|
@@ -32327,7 +32553,7 @@ import {
|
|
|
32327
32553
|
unlinkSync as unlinkSync6,
|
|
32328
32554
|
writeFileSync as writeFileSync9
|
|
32329
32555
|
} from "node:fs";
|
|
32330
|
-
import { dirname as dirname8, join as
|
|
32556
|
+
import { dirname as dirname8, join as join18, relative as relative3, resolve as resolve4 } from "node:path";
|
|
32331
32557
|
import { Readable as Readable3 } from "node:stream";
|
|
32332
32558
|
import { pipeline as pipeline3 } from "node:stream/promises";
|
|
32333
32559
|
|
|
@@ -32417,26 +32643,26 @@ function detectHostPlatform() {
|
|
|
32417
32643
|
|
|
32418
32644
|
// src/lsp-github-install.ts
|
|
32419
32645
|
function ghCacheRoot() {
|
|
32420
|
-
return
|
|
32646
|
+
return join18(aftCacheBase(), "lsp-binaries");
|
|
32421
32647
|
}
|
|
32422
32648
|
function ghPackageDir(spec) {
|
|
32423
|
-
return
|
|
32649
|
+
return join18(ghCacheRoot(), spec.id);
|
|
32424
32650
|
}
|
|
32425
32651
|
function ghBinDir(spec) {
|
|
32426
|
-
return
|
|
32652
|
+
return join18(ghPackageDir(spec), "bin");
|
|
32427
32653
|
}
|
|
32428
32654
|
function ghExtractDir(spec) {
|
|
32429
|
-
return
|
|
32655
|
+
return join18(ghPackageDir(spec), "extracted");
|
|
32430
32656
|
}
|
|
32431
32657
|
var INSTALLED_META_FILE2 = ".aft-installed";
|
|
32432
32658
|
function ghBinaryPath(spec, platform3) {
|
|
32433
32659
|
const ext = platform3 === "win32" ? ".exe" : "";
|
|
32434
|
-
return
|
|
32660
|
+
return join18(ghBinDir(spec), `${spec.binary}${ext}`);
|
|
32435
32661
|
}
|
|
32436
32662
|
function isGithubInstalled(spec, platform3) {
|
|
32437
32663
|
for (const candidate of ghBinaryCandidates(spec, platform3)) {
|
|
32438
32664
|
try {
|
|
32439
|
-
if (statSync7(
|
|
32665
|
+
if (statSync7(join18(ghBinDir(spec), candidate)).isFile())
|
|
32440
32666
|
return true;
|
|
32441
32667
|
} catch {}
|
|
32442
32668
|
}
|
|
@@ -32449,10 +32675,10 @@ function ghBinaryCandidates(spec, platform3) {
|
|
|
32449
32675
|
}
|
|
32450
32676
|
function readGithubInstalledMetaIn(installDir) {
|
|
32451
32677
|
try {
|
|
32452
|
-
const
|
|
32453
|
-
if (!statSync7(
|
|
32678
|
+
const path3 = join18(installDir, INSTALLED_META_FILE2);
|
|
32679
|
+
if (!statSync7(path3).isFile())
|
|
32454
32680
|
return null;
|
|
32455
|
-
const parsed = JSON.parse(readFileSync12(
|
|
32681
|
+
const parsed = JSON.parse(readFileSync12(path3, "utf8"));
|
|
32456
32682
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
32457
32683
|
return null;
|
|
32458
32684
|
return {
|
|
@@ -32476,24 +32702,24 @@ function writeGithubInstalledMetaIn(installDir, version2, binarySha256, archiveS
|
|
|
32476
32702
|
binarySha256,
|
|
32477
32703
|
...archiveSha256 ? { archiveSha256 } : {}
|
|
32478
32704
|
};
|
|
32479
|
-
writeFileSync9(
|
|
32705
|
+
writeFileSync9(join18(installDir, INSTALLED_META_FILE2), JSON.stringify(meta3), "utf8");
|
|
32480
32706
|
} catch (err) {
|
|
32481
32707
|
warn2(`[lsp] failed to write github installed metadata in ${installDir}: ${err}`);
|
|
32482
32708
|
}
|
|
32483
32709
|
}
|
|
32484
32710
|
var MAX_DOWNLOAD_BYTES3 = 256 * 1024 * 1024;
|
|
32485
32711
|
var MAX_EXTRACT_BYTES2 = 1024 * 1024 * 1024;
|
|
32486
|
-
function sha256OfFile(
|
|
32487
|
-
return new Promise((
|
|
32712
|
+
function sha256OfFile(path3) {
|
|
32713
|
+
return new Promise((resolve5, reject) => {
|
|
32488
32714
|
const hash2 = createHash5("sha256");
|
|
32489
|
-
const stream = createReadStream2(
|
|
32715
|
+
const stream = createReadStream2(path3);
|
|
32490
32716
|
stream.on("error", reject);
|
|
32491
32717
|
stream.on("data", (chunk) => hash2.update(chunk));
|
|
32492
|
-
stream.on("end", () =>
|
|
32718
|
+
stream.on("end", () => resolve5(hash2.digest("hex")));
|
|
32493
32719
|
});
|
|
32494
32720
|
}
|
|
32495
|
-
function sha256OfFileSync2(
|
|
32496
|
-
return createHash5("sha256").update(readFileSync12(
|
|
32721
|
+
function sha256OfFileSync2(path3) {
|
|
32722
|
+
return createHash5("sha256").update(readFileSync12(path3)).digest("hex");
|
|
32497
32723
|
}
|
|
32498
32724
|
async function fetchReleaseByTag(githubRepo, tag, fetchImpl, signal) {
|
|
32499
32725
|
const candidates = [];
|
|
@@ -32725,7 +32951,7 @@ function validateExtraction(stagingRoot) {
|
|
|
32725
32951
|
throw new Error(`failed to read staging dir ${dir}: ${err}`);
|
|
32726
32952
|
}
|
|
32727
32953
|
for (const entry of entries) {
|
|
32728
|
-
const full =
|
|
32954
|
+
const full = join18(dir, entry);
|
|
32729
32955
|
let lst;
|
|
32730
32956
|
try {
|
|
32731
32957
|
lst = lstatSync2(full);
|
|
@@ -32737,7 +32963,7 @@ function validateExtraction(stagingRoot) {
|
|
|
32737
32963
|
try {
|
|
32738
32964
|
target = readlinkSync2(full);
|
|
32739
32965
|
} catch {}
|
|
32740
|
-
throw new Error(`archive contains symlink ${
|
|
32966
|
+
throw new Error(`archive contains symlink ${relative3(realStagingRoot, full)} → ${target}; rejecting (zip-slip defense)`);
|
|
32741
32967
|
}
|
|
32742
32968
|
let realFull;
|
|
32743
32969
|
try {
|
|
@@ -32745,8 +32971,8 @@ function validateExtraction(stagingRoot) {
|
|
|
32745
32971
|
} catch (err) {
|
|
32746
32972
|
throw new Error(`failed to realpath ${full}: ${err}`);
|
|
32747
32973
|
}
|
|
32748
|
-
const rel =
|
|
32749
|
-
if (rel.startsWith("..") ||
|
|
32974
|
+
const rel = relative3(realStagingRoot, realFull);
|
|
32975
|
+
if (rel.startsWith("..") || resolve4(realStagingRoot, rel) !== realFull) {
|
|
32750
32976
|
throw new Error(`archive entry escapes staging root: ${full} → ${realFull} (zip-slip defense)`);
|
|
32751
32977
|
}
|
|
32752
32978
|
if (lst.isDirectory()) {
|
|
@@ -32813,7 +33039,7 @@ function extractArchiveSafely(archivePath, destDir, archiveType) {
|
|
|
32813
33039
|
}
|
|
32814
33040
|
function quarantineCachedGithubInstall(spec, reason) {
|
|
32815
33041
|
const packageDir = ghPackageDir(spec);
|
|
32816
|
-
const dest =
|
|
33042
|
+
const dest = join18(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
|
|
32817
33043
|
warn2(`[lsp] tofu_mismatch ${spec.id}: ${reason}; quarantining ${packageDir} -> ${dest}`);
|
|
32818
33044
|
try {
|
|
32819
33045
|
mkdirSync9(dirname8(dest), { recursive: true });
|
|
@@ -32826,7 +33052,7 @@ function quarantineCachedGithubInstall(spec, reason) {
|
|
|
32826
33052
|
function validateCachedGithubInstall(spec, platform3) {
|
|
32827
33053
|
const packageDir = ghPackageDir(spec);
|
|
32828
33054
|
const meta3 = readGithubInstalledMetaIn(packageDir);
|
|
32829
|
-
const binaryPath = ghBinaryCandidates(spec, platform3).map((candidate) =>
|
|
33055
|
+
const binaryPath = ghBinaryCandidates(spec, platform3).map((candidate) => join18(ghBinDir(spec), candidate)).find((candidate) => {
|
|
32830
33056
|
try {
|
|
32831
33057
|
return statSync7(candidate).isFile();
|
|
32832
33058
|
} catch {
|
|
@@ -32904,7 +33130,7 @@ async function downloadAndInstall(spec, tag, assets, platform3, arch, fetchImpl,
|
|
|
32904
33130
|
}
|
|
32905
33131
|
const pkgDir = ghPackageDir(spec);
|
|
32906
33132
|
const extractDir = ghExtractDir(spec);
|
|
32907
|
-
const archivePath =
|
|
33133
|
+
const archivePath = join18(pkgDir, expected.name);
|
|
32908
33134
|
log2(`[lsp] downloading ${spec.id} ${tag} → ${matchingAsset.url}`);
|
|
32909
33135
|
try {
|
|
32910
33136
|
await downloadFile(matchingAsset.url, archivePath, fetchImpl, matchingAsset.size, signal);
|
|
@@ -32944,7 +33170,7 @@ async function downloadAndInstall(spec, tag, assets, platform3, arch, fetchImpl,
|
|
|
32944
33170
|
unlinkSync6(archivePath);
|
|
32945
33171
|
} catch {}
|
|
32946
33172
|
}
|
|
32947
|
-
const innerBinaryPath =
|
|
33173
|
+
const innerBinaryPath = join18(extractDir, spec.binaryPathInArchive(platform3, arch, version2));
|
|
32948
33174
|
if (!existsSync13(innerBinaryPath)) {
|
|
32949
33175
|
error2(`[lsp] ${spec.id}: extracted binary not found at ${innerBinaryPath}`);
|
|
32950
33176
|
return null;
|
|
@@ -33239,7 +33465,7 @@ function renderScreen(state, rows = state.rows, cols = state.cols) {
|
|
|
33239
33465
|
`);
|
|
33240
33466
|
}
|
|
33241
33467
|
function writeTerminal(terminal, data) {
|
|
33242
|
-
return new Promise((
|
|
33468
|
+
return new Promise((resolve5) => terminal.write(data, resolve5));
|
|
33243
33469
|
}
|
|
33244
33470
|
|
|
33245
33471
|
// src/shared/rpc-server.ts
|
|
@@ -33254,18 +33480,18 @@ import {
|
|
|
33254
33480
|
writeFileSync as writeFileSync10
|
|
33255
33481
|
} from "node:fs";
|
|
33256
33482
|
import { createServer } from "node:http";
|
|
33257
|
-
import { dirname as dirname9, join as
|
|
33483
|
+
import { dirname as dirname9, join as join20 } from "node:path";
|
|
33258
33484
|
|
|
33259
33485
|
// src/shared/rpc-utils.ts
|
|
33260
33486
|
import { createHash as createHash6 } from "node:crypto";
|
|
33261
|
-
import { join as
|
|
33487
|
+
import { join as join19 } from "node:path";
|
|
33262
33488
|
function projectHash(directory) {
|
|
33263
33489
|
const normalized = directory.replace(/\/+$/, "");
|
|
33264
33490
|
return createHash6("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
33265
33491
|
}
|
|
33266
33492
|
function rpcPortFileDir(storageDir, directory) {
|
|
33267
33493
|
const hash2 = projectHash(directory);
|
|
33268
|
-
return
|
|
33494
|
+
return join19(storageDir, "rpc", hash2, "ports");
|
|
33269
33495
|
}
|
|
33270
33496
|
function isPidAlive(pid) {
|
|
33271
33497
|
if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0)
|
|
@@ -33318,13 +33544,13 @@ class AftRpcServer {
|
|
|
33318
33544
|
constructor(storageDir, directory) {
|
|
33319
33545
|
this.portsDir = rpcPortFileDir(storageDir, directory);
|
|
33320
33546
|
this.instanceId = randomBytes2(8).toString("hex");
|
|
33321
|
-
this.portFilePath =
|
|
33547
|
+
this.portFilePath = join20(this.portsDir, `${this.instanceId}.json`);
|
|
33322
33548
|
}
|
|
33323
33549
|
handle(method, handler) {
|
|
33324
33550
|
this.handlers.set(method, handler);
|
|
33325
33551
|
}
|
|
33326
33552
|
async start() {
|
|
33327
|
-
return new Promise((
|
|
33553
|
+
return new Promise((resolve5, reject) => {
|
|
33328
33554
|
const server = createServer((req, res) => this.dispatch(req, res));
|
|
33329
33555
|
server.on("error", (err) => {
|
|
33330
33556
|
warn2(`RPC server error: ${err.message}`);
|
|
@@ -33357,7 +33583,7 @@ class AftRpcServer {
|
|
|
33357
33583
|
} catch (err) {
|
|
33358
33584
|
warn2(`Failed to write RPC port file: ${err}`);
|
|
33359
33585
|
}
|
|
33360
|
-
|
|
33586
|
+
resolve5(this.port);
|
|
33361
33587
|
});
|
|
33362
33588
|
server.unref();
|
|
33363
33589
|
});
|
|
@@ -33372,7 +33598,7 @@ class AftRpcServer {
|
|
|
33372
33598
|
for (const entry of entries) {
|
|
33373
33599
|
if (!entry.endsWith(".json"))
|
|
33374
33600
|
continue;
|
|
33375
|
-
const filePath =
|
|
33601
|
+
const filePath = join20(this.portsDir, entry);
|
|
33376
33602
|
if (filePath === this.portFilePath)
|
|
33377
33603
|
continue;
|
|
33378
33604
|
try {
|
|
@@ -33777,20 +34003,20 @@ function formatStatusMarkdown(status) {
|
|
|
33777
34003
|
// src/shared/tui-config.ts
|
|
33778
34004
|
var import_comment_json4 = __toESM(require_src2(), 1);
|
|
33779
34005
|
import { existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "node:fs";
|
|
33780
|
-
import { dirname as dirname10, join as
|
|
34006
|
+
import { dirname as dirname10, join as join22 } from "node:path";
|
|
33781
34007
|
|
|
33782
34008
|
// src/shared/opencode-config-dir.ts
|
|
33783
|
-
import { homedir as
|
|
33784
|
-
import { join as
|
|
34009
|
+
import { homedir as homedir12 } from "node:os";
|
|
34010
|
+
import { join as join21, resolve as resolve5 } from "node:path";
|
|
33785
34011
|
function getCliConfigDir() {
|
|
33786
34012
|
const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
33787
34013
|
if (envConfigDir) {
|
|
33788
|
-
return
|
|
34014
|
+
return resolve5(envConfigDir);
|
|
33789
34015
|
}
|
|
33790
34016
|
if (process.platform === "win32") {
|
|
33791
|
-
return
|
|
34017
|
+
return join21(homedir12(), ".config", "opencode");
|
|
33792
34018
|
}
|
|
33793
|
-
return
|
|
34019
|
+
return join21(process.env.XDG_CONFIG_HOME || join21(homedir12(), ".config"), "opencode");
|
|
33794
34020
|
}
|
|
33795
34021
|
function getOpenCodeConfigDir2(_options) {
|
|
33796
34022
|
return getCliConfigDir();
|
|
@@ -33799,10 +34025,10 @@ function getOpenCodeConfigPaths(options) {
|
|
|
33799
34025
|
const configDir = getOpenCodeConfigDir2(options);
|
|
33800
34026
|
return {
|
|
33801
34027
|
configDir,
|
|
33802
|
-
configJson:
|
|
33803
|
-
configJsonc:
|
|
33804
|
-
packageJson:
|
|
33805
|
-
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")
|
|
33806
34032
|
};
|
|
33807
34033
|
}
|
|
33808
34034
|
|
|
@@ -33811,8 +34037,8 @@ var PLUGIN_NAME = "@cortexkit/aft-opencode";
|
|
|
33811
34037
|
var PLUGIN_ENTRY = `${PLUGIN_NAME}@latest`;
|
|
33812
34038
|
function resolveTuiConfigPath() {
|
|
33813
34039
|
const configDir = getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
|
|
33814
|
-
const jsoncPath =
|
|
33815
|
-
const jsonPath =
|
|
34040
|
+
const jsoncPath = join22(configDir, "tui.jsonc");
|
|
34041
|
+
const jsonPath = join22(configDir, "tui.json");
|
|
33816
34042
|
if (existsSync15(jsoncPath))
|
|
33817
34043
|
return jsoncPath;
|
|
33818
34044
|
if (existsSync15(jsonPath))
|
|
@@ -33901,8 +34127,8 @@ function installProcessHandlers() {
|
|
|
33901
34127
|
}
|
|
33902
34128
|
signalShutdownStarted = true;
|
|
33903
34129
|
process.exitCode = SIGNAL_EXIT_CODES[sig];
|
|
33904
|
-
const timeout = new Promise((
|
|
33905
|
-
setTimeout(
|
|
34130
|
+
const timeout = new Promise((resolve6) => {
|
|
34131
|
+
setTimeout(resolve6, SIGNAL_CLEANUP_TIMEOUT_MS);
|
|
33906
34132
|
});
|
|
33907
34133
|
Promise.race([runCleanups(sig), timeout]).finally(() => {
|
|
33908
34134
|
process.exit(SIGNAL_EXIT_CODES[sig]);
|
|
@@ -34014,99 +34240,18 @@ import { tool as tool3 } from "@opencode-ai/plugin";
|
|
|
34014
34240
|
|
|
34015
34241
|
// src/tools/_shared.ts
|
|
34016
34242
|
import * as fs3 from "node:fs";
|
|
34017
|
-
import * as
|
|
34018
|
-
import * as
|
|
34243
|
+
import * as os3 from "node:os";
|
|
34244
|
+
import * as path3 from "node:path";
|
|
34019
34245
|
import { tool as tool2 } from "@opencode-ai/plugin";
|
|
34020
34246
|
var z2 = tool2.schema;
|
|
34021
34247
|
var optionalInt = (min, max) => z2.number().int().min(min).max(max).optional();
|
|
34022
|
-
function isEmptyParam(value) {
|
|
34023
|
-
if (value === undefined || value === null)
|
|
34024
|
-
return true;
|
|
34025
|
-
if (typeof value === "string")
|
|
34026
|
-
return value.length === 0;
|
|
34027
|
-
if (Array.isArray(value))
|
|
34028
|
-
return value.length === 0;
|
|
34029
|
-
if (typeof value === "object")
|
|
34030
|
-
return Object.keys(value).length === 0;
|
|
34031
|
-
return false;
|
|
34032
|
-
}
|
|
34033
34248
|
var BASH_TRANSPORT_TIMEOUT_MS = 30000;
|
|
34034
|
-
function asPlainObject(value) {
|
|
34035
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
34036
|
-
return;
|
|
34037
|
-
return value;
|
|
34038
|
-
}
|
|
34039
|
-
function candidateLocation(candidate) {
|
|
34040
|
-
const file2 = typeof candidate.file === "string" && candidate.file.length > 0 ? candidate.file : undefined;
|
|
34041
|
-
if (!file2)
|
|
34042
|
-
return;
|
|
34043
|
-
const line = typeof candidate.line === "number" && Number.isFinite(candidate.line) ? candidate.line : undefined;
|
|
34044
|
-
return line === undefined ? file2 : `${file2}:${line}`;
|
|
34045
|
-
}
|
|
34046
|
-
function stringifyData(data) {
|
|
34047
|
-
if (data === undefined)
|
|
34048
|
-
return;
|
|
34049
|
-
try {
|
|
34050
|
-
return JSON.stringify(data, null, 2);
|
|
34051
|
-
} catch {
|
|
34052
|
-
return String(data);
|
|
34053
|
-
}
|
|
34054
|
-
}
|
|
34055
|
-
function formatBridgeErrorMessage(command, response, params = {}) {
|
|
34056
|
-
const code = typeof response.code === "string" && response.code.length > 0 ? response.code : undefined;
|
|
34057
|
-
const message = typeof response.message === "string" && response.message.length > 0 ? response.message : `${command} failed`;
|
|
34058
|
-
const data = asPlainObject(response.data);
|
|
34059
|
-
const rawCandidates = Array.isArray(response.candidates) ? response.candidates : Array.isArray(data?.candidates) ? data.candidates : undefined;
|
|
34060
|
-
const rawSymbol = typeof response.symbol === "string" && response.symbol.length > 0 ? response.symbol : typeof data?.symbol === "string" && data.symbol.length > 0 ? data.symbol : undefined;
|
|
34061
|
-
if (code === "ambiguous_target" || code === "target_symbol_not_in_file") {
|
|
34062
|
-
const candidates = (rawCandidates ?? []).map(asPlainObject).filter((candidate) => candidate !== undefined).map(candidateLocation).filter((candidate) => candidate !== undefined);
|
|
34063
|
-
if (candidates.length > 0) {
|
|
34064
|
-
const symbol2 = typeof params.toSymbol === "string" && params.toSymbol.length > 0 ? params.toSymbol : rawSymbol;
|
|
34065
|
-
const target = symbol2 ? `multiple symbols named "${symbol2}"` : message.replace(/[.!?]+$/, "");
|
|
34066
|
-
const action = code === "ambiguous_target" ? "Pass toFile to disambiguate" : "Try one of these files for toFile";
|
|
34067
|
-
return `${command}: ${code} — ${target}. ${action}:
|
|
34068
|
-
${candidates.map((candidate) => ` - ${candidate}`).join(`
|
|
34069
|
-
`)}`;
|
|
34070
|
-
}
|
|
34071
|
-
}
|
|
34072
|
-
if (!code)
|
|
34073
|
-
return message;
|
|
34074
|
-
const lines = [`${command}: ${code} — ${message}`];
|
|
34075
|
-
const extras = collectStructuredExtras(response);
|
|
34076
|
-
if (extras)
|
|
34077
|
-
lines.push(`data: ${extras}`);
|
|
34078
|
-
return lines.join(`
|
|
34079
|
-
`);
|
|
34080
|
-
}
|
|
34081
|
-
function collectStructuredExtras(response) {
|
|
34082
|
-
const reserved = new Set([
|
|
34083
|
-
"id",
|
|
34084
|
-
"success",
|
|
34085
|
-
"code",
|
|
34086
|
-
"message",
|
|
34087
|
-
"data",
|
|
34088
|
-
"status_bar",
|
|
34089
|
-
"bg_completions"
|
|
34090
|
-
]);
|
|
34091
|
-
const extras = {};
|
|
34092
|
-
for (const [key, value] of Object.entries(response)) {
|
|
34093
|
-
if (reserved.has(key))
|
|
34094
|
-
continue;
|
|
34095
|
-
extras[key] = value;
|
|
34096
|
-
}
|
|
34097
|
-
if (Object.keys(extras).length === 0) {
|
|
34098
|
-
return stringifyData(response.data);
|
|
34099
|
-
}
|
|
34100
|
-
if (response.data !== undefined)
|
|
34101
|
-
extras.data = response.data;
|
|
34102
|
-
return stringifyData(extras);
|
|
34103
|
-
}
|
|
34104
34249
|
function canonicalizeDirectory(dir) {
|
|
34105
34250
|
const trimmed = dir.replace(/[/\\]+$/, "");
|
|
34106
34251
|
try {
|
|
34107
34252
|
return fs3.realpathSync(trimmed);
|
|
34108
34253
|
} catch {
|
|
34109
|
-
return
|
|
34254
|
+
return path3.resolve(trimmed);
|
|
34110
34255
|
}
|
|
34111
34256
|
}
|
|
34112
34257
|
function projectRootFor(runtime) {
|
|
@@ -34123,19 +34268,19 @@ async function resolveProjectRoot(ctx, runtime) {
|
|
|
34123
34268
|
}
|
|
34124
34269
|
return projectRootFor(runtime);
|
|
34125
34270
|
}
|
|
34126
|
-
function
|
|
34271
|
+
function expandTilde2(input) {
|
|
34127
34272
|
if (!input || !input.startsWith("~"))
|
|
34128
34273
|
return input;
|
|
34129
34274
|
if (input === "~")
|
|
34130
|
-
return
|
|
34131
|
-
if (input.startsWith("~/") || input.startsWith(`~${
|
|
34132
|
-
return
|
|
34275
|
+
return os3.homedir();
|
|
34276
|
+
if (input.startsWith("~/") || input.startsWith(`~${path3.sep}`)) {
|
|
34277
|
+
return path3.resolve(os3.homedir(), input.slice(2));
|
|
34133
34278
|
}
|
|
34134
34279
|
return input;
|
|
34135
34280
|
}
|
|
34136
34281
|
function resolvePathFromProjectRoot(projectRoot, target) {
|
|
34137
|
-
const expanded =
|
|
34138
|
-
return
|
|
34282
|
+
const expanded = expandTilde2(target);
|
|
34283
|
+
return path3.isAbsolute(expanded) ? expanded : path3.resolve(projectRoot, expanded);
|
|
34139
34284
|
}
|
|
34140
34285
|
async function resolvePathArg(ctx, runtime, target) {
|
|
34141
34286
|
return resolvePathFromProjectRoot(await resolveProjectRoot(ctx, runtime), target);
|
|
@@ -34177,19 +34322,19 @@ async function callBashBridge(ctx, runtime, command, params = {}, options) {
|
|
|
34177
34322
|
|
|
34178
34323
|
// src/tools/permissions.ts
|
|
34179
34324
|
import * as fs4 from "node:fs";
|
|
34180
|
-
import * as
|
|
34325
|
+
import * as path4 from "node:path";
|
|
34181
34326
|
var UNSUPPORTED_ASK_HOST = "AFT requires OpenCode 1.15.5 or newer for permission asks; please upgrade OpenCode";
|
|
34182
34327
|
async function runAsk(maybe) {
|
|
34183
34328
|
await maybe;
|
|
34184
34329
|
}
|
|
34185
34330
|
function resolveAbsolutePath(context, target) {
|
|
34186
|
-
return
|
|
34331
|
+
return path4.isAbsolute(target) ? target : path4.resolve(projectRootFor(context), target);
|
|
34187
34332
|
}
|
|
34188
34333
|
function resolveRelativePattern(context, target) {
|
|
34189
|
-
return
|
|
34334
|
+
return path4.relative(projectRootFor(context), resolveAbsolutePath(context, target)) || ".";
|
|
34190
34335
|
}
|
|
34191
34336
|
function resolveRelativePatternFromAbsolute(context, absolutePath) {
|
|
34192
|
-
return
|
|
34337
|
+
return path4.relative(projectRootFor(context), absolutePath) || ".";
|
|
34193
34338
|
}
|
|
34194
34339
|
function resolveRelativePatterns(context, targets) {
|
|
34195
34340
|
const seen = new Set;
|
|
@@ -34229,8 +34374,8 @@ async function askEditPermission(context, patterns, metadata = {}) {
|
|
|
34229
34374
|
function containsPath(parent, child) {
|
|
34230
34375
|
if (!parent)
|
|
34231
34376
|
return false;
|
|
34232
|
-
const rel =
|
|
34233
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
34377
|
+
const rel = path4.relative(parent, child);
|
|
34378
|
+
return rel === "" || !rel.startsWith("..") && !path4.isAbsolute(rel);
|
|
34234
34379
|
}
|
|
34235
34380
|
function windowsPath(p) {
|
|
34236
34381
|
if (process.platform !== "win32")
|
|
@@ -34240,7 +34385,7 @@ function windowsPath(p) {
|
|
|
34240
34385
|
function normalizePath(p) {
|
|
34241
34386
|
if (process.platform !== "win32")
|
|
34242
34387
|
return p;
|
|
34243
|
-
const resolved =
|
|
34388
|
+
const resolved = path4.resolve(windowsPath(p));
|
|
34244
34389
|
try {
|
|
34245
34390
|
return fs4.realpathSync.native(resolved);
|
|
34246
34391
|
} catch {
|
|
@@ -34256,7 +34401,7 @@ function normalizePathPattern(p) {
|
|
|
34256
34401
|
if (!match)
|
|
34257
34402
|
return normalizePath(p);
|
|
34258
34403
|
const dir = /^[A-Za-z]:$/.test(match[1]) ? `${match[1]}\\` : match[1];
|
|
34259
|
-
return
|
|
34404
|
+
return path4.join(normalizePath(dir), match[2]);
|
|
34260
34405
|
}
|
|
34261
34406
|
async function assertExternalDirectoryPermission(context, target, options) {
|
|
34262
34407
|
if (!target)
|
|
@@ -34275,8 +34420,8 @@ async function assertExternalDirectoryPermission(context, target, options) {
|
|
|
34275
34420
|
return;
|
|
34276
34421
|
}
|
|
34277
34422
|
const kind = options?.kind ?? "file";
|
|
34278
|
-
const parentDir = kind === "directory" ? absoluteTarget :
|
|
34279
|
-
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("\\", "/");
|
|
34280
34425
|
try {
|
|
34281
34426
|
await runAsk(context.ask({
|
|
34282
34427
|
permission: "external_directory",
|
|
@@ -34350,6 +34495,20 @@ function extractHint(response) {
|
|
|
34350
34495
|
const hint = response.hint;
|
|
34351
34496
|
return typeof hint === "string" && hint.length > 0 ? hint : null;
|
|
34352
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
|
+
}
|
|
34353
34512
|
async function resolveAstPaths(ctx, context, paths) {
|
|
34354
34513
|
if (isEmptyParam(paths) || !Array.isArray(paths))
|
|
34355
34514
|
return;
|
|
@@ -34374,17 +34533,18 @@ var SUPPORTED_LANGS = [
|
|
|
34374
34533
|
"python",
|
|
34375
34534
|
"rust",
|
|
34376
34535
|
"go",
|
|
34377
|
-
"pascal"
|
|
34536
|
+
"pascal",
|
|
34537
|
+
"r"
|
|
34378
34538
|
];
|
|
34379
34539
|
function astTools(ctx) {
|
|
34380
34540
|
const searchTool = {
|
|
34381
|
-
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.
|
|
34382
34542
|
|
|
34383
34543
|
` + `Use meta-variables: $VAR matches a single AST node, $$$ matches multiple nodes (variadic).
|
|
34384
34544
|
` + `IMPORTANT: Patterns must be complete AST nodes (valid code fragments).
|
|
34385
34545
|
` + `For functions, include params and body: 'export async function $NAME($$$) { $$$ }' not just 'export async function $NAME'.
|
|
34386
34546
|
|
|
34387
|
-
` + "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'",
|
|
34388
34548
|
args: {
|
|
34389
34549
|
pattern: z3.string().describe("AST pattern with meta-variables ($VAR, $$$). Must be complete AST node."),
|
|
34390
34550
|
lang: z3.enum(SUPPORTED_LANGS).describe("Target language"),
|
|
@@ -34465,6 +34625,9 @@ ${hint}`;
|
|
|
34465
34625
|
}
|
|
34466
34626
|
}
|
|
34467
34627
|
}
|
|
34628
|
+
if (data.complete === false || (data.skipped_files?.length ?? 0) > 0) {
|
|
34629
|
+
output = appendSkippedFiles(output, data.skipped_files);
|
|
34630
|
+
}
|
|
34468
34631
|
showOutputToUser(context, output);
|
|
34469
34632
|
return output;
|
|
34470
34633
|
}
|
|
@@ -34808,7 +34971,7 @@ function createBashTool(ctx, aftSearchRegisteredOverride) {
|
|
|
34808
34971
|
throw new Error(status.message ?? "bash_status failed");
|
|
34809
34972
|
}
|
|
34810
34973
|
if (isTerminalStatus(status.status)) {
|
|
34811
|
-
const rendered2 = maybeAppendGrepSearchHint(appendPipeStripNote(formatForegroundResult(status), pipeStrip.note), command, aftSearchRegistered);
|
|
34974
|
+
const rendered2 = maybeAppendGrepSearchHint(appendPipeStripNote(formatForegroundResult(status), pipeStrip.note), command, aftSearchRegistered, projectRootFor(context));
|
|
34812
34975
|
const metadataPayload2 = foregroundMetadata(description, status, rendered2);
|
|
34813
34976
|
metadata?.(metadataPayload2);
|
|
34814
34977
|
return { output: rendered2, title: uiTitle, metadata: metadataPayload2 };
|
|
@@ -34872,11 +35035,6 @@ function createBashTool(ctx, aftSearchRegisteredOverride) {
|
|
|
34872
35035
|
}
|
|
34873
35036
|
};
|
|
34874
35037
|
}
|
|
34875
|
-
function appendPipeStripNote(output, note) {
|
|
34876
|
-
return note ? `${output}
|
|
34877
|
-
|
|
34878
|
-
${note}` : output;
|
|
34879
|
-
}
|
|
34880
35038
|
function createBashStatusTool(ctx) {
|
|
34881
35039
|
return {
|
|
34882
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.",
|
|
@@ -34981,9 +35139,6 @@ function ptyCacheKey(runtime, taskId) {
|
|
|
34981
35139
|
function preview(output) {
|
|
34982
35140
|
return output.length <= METADATA_PREVIEW_LIMIT ? output : output.slice(-METADATA_PREVIEW_LIMIT);
|
|
34983
35141
|
}
|
|
34984
|
-
function isTerminalStatus(status) {
|
|
34985
|
-
return status === "completed" || status === "failed" || status === "killed" || status === "timed_out";
|
|
34986
|
-
}
|
|
34987
35142
|
function subagentGuidance(taskId) {
|
|
34988
35143
|
return `
|
|
34989
35144
|
|
|
@@ -34999,30 +35154,6 @@ function formatPromotionMessage(taskId, timeout, waitWindowMs) {
|
|
|
34999
35154
|
const waited = timeout !== undefined ? Math.min(timeout, waitWindowMs) : waitWindowMs;
|
|
35000
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.`;
|
|
35001
35156
|
}
|
|
35002
|
-
function formatSeconds(ms) {
|
|
35003
|
-
return `${Number((ms / 1000).toFixed(1))}s`;
|
|
35004
|
-
}
|
|
35005
|
-
function formatForegroundResult(data) {
|
|
35006
|
-
const output = data.output_preview ?? "";
|
|
35007
|
-
const outputPath = data.output_path;
|
|
35008
|
-
const truncated = data.output_truncated === true;
|
|
35009
|
-
const status = data.status;
|
|
35010
|
-
const exit = data.exit_code;
|
|
35011
|
-
let rendered = output;
|
|
35012
|
-
if (truncated && outputPath) {
|
|
35013
|
-
rendered += `
|
|
35014
|
-
[output truncated; full output at ${outputPath}]`;
|
|
35015
|
-
}
|
|
35016
|
-
if (status === "timed_out") {
|
|
35017
|
-
rendered += `
|
|
35018
|
-
[command timed out]`;
|
|
35019
|
-
}
|
|
35020
|
-
if (typeof exit === "number" && exit !== 0) {
|
|
35021
|
-
rendered += `
|
|
35022
|
-
[exit code: ${exit}]`;
|
|
35023
|
-
}
|
|
35024
|
-
return rendered;
|
|
35025
|
-
}
|
|
35026
35157
|
function foregroundMetadata(description, data, rendered) {
|
|
35027
35158
|
const outputPath = data.output_path;
|
|
35028
35159
|
return {
|
|
@@ -35033,9 +35164,6 @@ function foregroundMetadata(description, data, rendered) {
|
|
|
35033
35164
|
...outputPath ? { outputPath } : {}
|
|
35034
35165
|
};
|
|
35035
35166
|
}
|
|
35036
|
-
function sleep(ms) {
|
|
35037
|
-
return new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
35038
|
-
}
|
|
35039
35167
|
function getCallID(ctx) {
|
|
35040
35168
|
const c = ctx;
|
|
35041
35169
|
return c.callID ?? c.callId ?? c.call_id;
|
|
@@ -35058,7 +35186,7 @@ function conflictTools(ctx) {
|
|
|
35058
35186
|
execute: async (args, context) => {
|
|
35059
35187
|
const params = {};
|
|
35060
35188
|
if (!isEmptyParam(args?.path)) {
|
|
35061
|
-
const expanded =
|
|
35189
|
+
const expanded = expandTilde2(String(args.path));
|
|
35062
35190
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
35063
35191
|
const resolved = resolvePathFromProjectRoot(projectRoot, expanded);
|
|
35064
35192
|
const denied = await assertExternalDirectoryPermission(context, resolved, {
|
|
@@ -35080,7 +35208,7 @@ function conflictTools(ctx) {
|
|
|
35080
35208
|
|
|
35081
35209
|
// src/tools/hoisted.ts
|
|
35082
35210
|
import * as fs6 from "node:fs";
|
|
35083
|
-
import * as
|
|
35211
|
+
import * as path5 from "node:path";
|
|
35084
35212
|
import { tool as tool8 } from "@opencode-ai/plugin";
|
|
35085
35213
|
|
|
35086
35214
|
// src/patch-parser.ts
|
|
@@ -35520,13 +35648,16 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
|
|
|
35520
35648
|
let scanText = "";
|
|
35521
35649
|
let scanBaseOffset = 0;
|
|
35522
35650
|
const bridgeOptions = {};
|
|
35651
|
+
if (waitFor?.kind === "regex") {
|
|
35652
|
+
await validateWaitRegex(ctx, runtime, waitFor);
|
|
35653
|
+
}
|
|
35523
35654
|
clearSyncWatchAbort(runtime.sessionID);
|
|
35524
35655
|
markTaskWaiting(runtime.sessionID, taskId);
|
|
35525
35656
|
let sawTerminal = false;
|
|
35526
35657
|
try {
|
|
35527
35658
|
while (true) {
|
|
35528
35659
|
const data = await bashStatusSnapshot2(ctx, runtime, taskId, outputMode, bridgeOptions);
|
|
35529
|
-
const terminal =
|
|
35660
|
+
const terminal = isTerminalStatus(data.status);
|
|
35530
35661
|
if (waitFor) {
|
|
35531
35662
|
const scan = await readNewTaskOutput(runtime, taskId, data, spillCursor);
|
|
35532
35663
|
if (scan) {
|
|
@@ -35534,7 +35665,12 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
|
|
|
35534
35665
|
if (scanText.length === 0)
|
|
35535
35666
|
scanBaseOffset = scan.baseOffset;
|
|
35536
35667
|
scanText += scan.text;
|
|
35537
|
-
|
|
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);
|
|
35538
35674
|
if (match) {
|
|
35539
35675
|
if (terminal) {
|
|
35540
35676
|
sawTerminal = true;
|
|
@@ -35545,12 +35681,14 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
|
|
|
35545
35681
|
reason: "matched",
|
|
35546
35682
|
elapsed_ms: Date.now() - startedAt,
|
|
35547
35683
|
match: match.text,
|
|
35548
|
-
match_offset: scanBaseOffset +
|
|
35684
|
+
match_offset: scanBaseOffset + match.byteOffset
|
|
35549
35685
|
});
|
|
35550
35686
|
}
|
|
35551
|
-
|
|
35552
|
-
|
|
35553
|
-
|
|
35687
|
+
if (waitFor.kind === "substring") {
|
|
35688
|
+
const trimmed = trimWaitScanBuffer(scanText, scanBaseOffset, waitFor);
|
|
35689
|
+
scanText = trimmed.text;
|
|
35690
|
+
scanBaseOffset = trimmed.baseOffset;
|
|
35691
|
+
}
|
|
35554
35692
|
}
|
|
35555
35693
|
}
|
|
35556
35694
|
if (terminal) {
|
|
@@ -35565,7 +35703,7 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
|
|
|
35565
35703
|
if (Date.now() >= deadline) {
|
|
35566
35704
|
return withWaited(data, { reason: "timeout", elapsed_ms: Date.now() - startedAt });
|
|
35567
35705
|
}
|
|
35568
|
-
await
|
|
35706
|
+
await sleep(Math.min(BASH_WAIT_POLL_INTERVAL_MS, Math.max(0, deadline - Date.now())));
|
|
35569
35707
|
}
|
|
35570
35708
|
} finally {
|
|
35571
35709
|
if (!sawTerminal)
|
|
@@ -35631,20 +35769,41 @@ function parseWaitPattern(value) {
|
|
|
35631
35769
|
if (typeof value === "string")
|
|
35632
35770
|
return { kind: "substring", value };
|
|
35633
35771
|
if (isRegexWaitObject(value))
|
|
35634
|
-
return { kind: "regex",
|
|
35772
|
+
return { kind: "regex", source: value.regex };
|
|
35635
35773
|
return;
|
|
35636
35774
|
}
|
|
35637
35775
|
function isRegexWaitObject(value) {
|
|
35638
35776
|
return typeof value === "object" && value !== null && "regex" in value && typeof value.regex === "string";
|
|
35639
35777
|
}
|
|
35640
|
-
function
|
|
35778
|
+
async function validateWaitRegex(ctx, runtime, pattern) {
|
|
35779
|
+
await matchRegexWithBridge(ctx, runtime, pattern.source, "");
|
|
35780
|
+
}
|
|
35781
|
+
async function findWaitMatch(ctx, runtime, text, pattern) {
|
|
35641
35782
|
if (pattern.kind === "substring") {
|
|
35642
35783
|
const index = text.indexOf(pattern.value);
|
|
35643
|
-
return index >= 0 ? { text: pattern.value, index } : undefined;
|
|
35784
|
+
return index >= 0 ? { text: pattern.value, byteOffset: Buffer.byteLength(text.slice(0, index), "utf8") } : undefined;
|
|
35644
35785
|
}
|
|
35645
|
-
pattern.
|
|
35646
|
-
|
|
35647
|
-
|
|
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;
|
|
35648
35807
|
}
|
|
35649
35808
|
function trimWaitScanBuffer(text, baseOffset, pattern) {
|
|
35650
35809
|
const keepFrom = pattern.kind === "substring" ? substringKeepStart(text, pattern.value) : regexKeepStart(text, REGEX_WAIT_SCAN_WINDOW_BYTES);
|
|
@@ -35677,18 +35836,12 @@ function regexKeepStart(text, maxBytes) {
|
|
|
35677
35836
|
function withWaited(data, waited) {
|
|
35678
35837
|
return { ...data, waited };
|
|
35679
35838
|
}
|
|
35680
|
-
function isTerminalStatus2(status) {
|
|
35681
|
-
return status === "completed" || status === "failed" || status === "killed" || status === "timed_out";
|
|
35682
|
-
}
|
|
35683
35839
|
function ptyCacheKey2(runtime, taskId) {
|
|
35684
35840
|
return `${projectRootFor(runtime)}::${runtime.sessionID ?? "__default__"}::${taskId}`;
|
|
35685
35841
|
}
|
|
35686
35842
|
function watchPtyCacheKey(runtime, taskId) {
|
|
35687
35843
|
return `${ptyCacheKey2(runtime, taskId)}::watch`;
|
|
35688
35844
|
}
|
|
35689
|
-
function sleep2(ms) {
|
|
35690
|
-
return new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
35691
|
-
}
|
|
35692
35845
|
|
|
35693
35846
|
// src/tools/bash_write.ts
|
|
35694
35847
|
import { tool as tool7 } from "@opencode-ai/plugin";
|
|
@@ -35723,21 +35876,10 @@ function createBashWriteTool(ctx) {
|
|
|
35723
35876
|
|
|
35724
35877
|
// src/tools/hoisted.ts
|
|
35725
35878
|
function relativeToWorktree(fp, worktree) {
|
|
35726
|
-
return
|
|
35879
|
+
return path5.relative(worktree, fp);
|
|
35727
35880
|
}
|
|
35728
|
-
function
|
|
35729
|
-
|
|
35730
|
-
return "";
|
|
35731
|
-
if (!data.truncated)
|
|
35732
|
-
return "";
|
|
35733
|
-
const startLine = data.start_line;
|
|
35734
|
-
const endLine = data.end_line;
|
|
35735
|
-
const totalLines = data.total_lines;
|
|
35736
|
-
if (startLine === undefined || endLine === undefined || totalLines === undefined) {
|
|
35737
|
-
return "";
|
|
35738
|
-
}
|
|
35739
|
-
return `
|
|
35740
|
-
(Showing lines ${startLine}-${endLine} of ${totalLines}. Use startLine/endLine to read other sections.)`;
|
|
35881
|
+
function formatReadFooter2(agentSpecifiedRange, data) {
|
|
35882
|
+
return formatReadFooter(agentSpecifiedRange, data, { rangeHint: "startLine/endLine" });
|
|
35741
35883
|
}
|
|
35742
35884
|
function buildUnifiedDiff(fp, before, after) {
|
|
35743
35885
|
const beforeLines = before.split(`
|
|
@@ -36064,7 +36206,7 @@ function createReadTool(ctx) {
|
|
|
36064
36206
|
return permissionDeniedResponse(error50.message);
|
|
36065
36207
|
return permissionDeniedResponse("Permission denied.");
|
|
36066
36208
|
}
|
|
36067
|
-
const ext =
|
|
36209
|
+
const ext = path5.extname(filePath).toLowerCase();
|
|
36068
36210
|
const mimeMap = {
|
|
36069
36211
|
".png": "image/png",
|
|
36070
36212
|
".jpg": "image/jpeg",
|
|
@@ -36093,7 +36235,7 @@ function createReadTool(ctx) {
|
|
|
36093
36235
|
const msg = `${label} read successfully`;
|
|
36094
36236
|
return {
|
|
36095
36237
|
output: `${msg} (${ext.slice(1).toUpperCase()}, ${sizeStr}). File: ${filePath}`,
|
|
36096
|
-
title:
|
|
36238
|
+
title: path5.relative(projectRoot, filePath),
|
|
36097
36239
|
metadata: {
|
|
36098
36240
|
preview: msg,
|
|
36099
36241
|
filepath: filePath,
|
|
@@ -36135,7 +36277,7 @@ function createReadTool(ctx) {
|
|
|
36135
36277
|
}
|
|
36136
36278
|
let output = data.content;
|
|
36137
36279
|
const agentSpecifiedRange = args.startLine !== undefined || args.endLine !== undefined || args.offset !== undefined || args.limit !== undefined;
|
|
36138
|
-
const footer =
|
|
36280
|
+
const footer = formatReadFooter2(agentSpecifiedRange, data);
|
|
36139
36281
|
if (footer)
|
|
36140
36282
|
output += footer;
|
|
36141
36283
|
return { output, title: dp, metadata: { title: dp } };
|
|
@@ -36157,7 +36299,7 @@ function createWriteTool(ctx, editToolName = "edit") {
|
|
|
36157
36299
|
const content = args.content;
|
|
36158
36300
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
36159
36301
|
const filePath = resolvePathFromProjectRoot(projectRoot, file2);
|
|
36160
|
-
const relPath =
|
|
36302
|
+
const relPath = path5.relative(projectRoot, filePath);
|
|
36161
36303
|
{
|
|
36162
36304
|
const denial2 = await assertExternalDirectoryPermission(context, filePath);
|
|
36163
36305
|
if (denial2)
|
|
@@ -36308,7 +36450,7 @@ function createEditTool(ctx, writeToolName = "write") {
|
|
|
36308
36450
|
throw new Error("'filePath' parameter is required");
|
|
36309
36451
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
36310
36452
|
const filePath = resolvePathFromProjectRoot(projectRoot, file2);
|
|
36311
|
-
const relPath =
|
|
36453
|
+
const relPath = path5.relative(projectRoot, filePath);
|
|
36312
36454
|
{
|
|
36313
36455
|
const denial2 = await assertExternalDirectoryPermission(context, filePath);
|
|
36314
36456
|
if (denial2)
|
|
@@ -36511,22 +36653,34 @@ function createApplyPatchTool(ctx) {
|
|
|
36511
36653
|
}
|
|
36512
36654
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
36513
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
|
+
}
|
|
36514
36670
|
const newlyCreatedAbs = new Set;
|
|
36515
36671
|
for (const h of hunks) {
|
|
36516
36672
|
const srcAbs = resolvePathFromProjectRoot(projectRoot, h.path);
|
|
36517
|
-
|
|
36518
|
-
if (h.type === "add") {
|
|
36673
|
+
if (h.type === "add" && initiallyExistsAbs.get(srcAbs) === false) {
|
|
36519
36674
|
newlyCreatedAbs.add(srcAbs);
|
|
36520
36675
|
}
|
|
36521
36676
|
if (h.type === "update" && h.move_path) {
|
|
36522
36677
|
const dstAbs = resolvePathFromProjectRoot(projectRoot, h.move_path);
|
|
36523
|
-
|
|
36524
|
-
if (!fs6.existsSync(dstAbs)) {
|
|
36678
|
+
if (initiallyExistsAbs.get(dstAbs) === false) {
|
|
36525
36679
|
newlyCreatedAbs.add(dstAbs);
|
|
36526
36680
|
}
|
|
36527
36681
|
}
|
|
36528
36682
|
}
|
|
36529
|
-
const relPaths = Array.from(affectedAbs).map((abs) =>
|
|
36683
|
+
const relPaths = Array.from(affectedAbs).map((abs) => path5.relative(projectRoot, abs));
|
|
36530
36684
|
const multiFileWritePaths = Array.from(affectedAbs);
|
|
36531
36685
|
{
|
|
36532
36686
|
const asked = new Set;
|
|
@@ -36560,15 +36714,15 @@ function createApplyPatchTool(ctx) {
|
|
|
36560
36714
|
}
|
|
36561
36715
|
const results = [];
|
|
36562
36716
|
const failures = [];
|
|
36563
|
-
const
|
|
36564
|
-
for (const hunk of hunks) {
|
|
36717
|
+
const appliedHunkResults = [];
|
|
36718
|
+
for (const [hunkIndex, hunk] of hunks.entries()) {
|
|
36565
36719
|
const filePath = resolvePathFromProjectRoot(projectRoot, hunk.path);
|
|
36566
36720
|
switch (hunk.type) {
|
|
36567
36721
|
case "add": {
|
|
36568
36722
|
if (fs6.existsSync(filePath)) {
|
|
36569
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.`;
|
|
36570
36724
|
results.push(msg);
|
|
36571
|
-
failures.push(hunk.path);
|
|
36725
|
+
failures.push({ index: hunkIndex, path: hunk.path });
|
|
36572
36726
|
break;
|
|
36573
36727
|
}
|
|
36574
36728
|
try {
|
|
@@ -36590,10 +36744,13 @@ function createApplyPatchTool(ctx) {
|
|
|
36590
36744
|
throw new Error("produced invalid syntax (rolled back)");
|
|
36591
36745
|
}
|
|
36592
36746
|
const wrDiff = writeResult.diff;
|
|
36593
|
-
|
|
36747
|
+
appliedHunkResults.push({
|
|
36748
|
+
index: hunkIndex,
|
|
36749
|
+
hunk,
|
|
36594
36750
|
filePath,
|
|
36751
|
+
displayPath: filePath,
|
|
36595
36752
|
before: "",
|
|
36596
|
-
after:
|
|
36753
|
+
after: content,
|
|
36597
36754
|
additions: wrDiff?.additions ?? lineCount(content),
|
|
36598
36755
|
deletions: wrDiff?.deletions ?? 0
|
|
36599
36756
|
});
|
|
@@ -36601,7 +36758,7 @@ function createApplyPatchTool(ctx) {
|
|
|
36601
36758
|
} catch (e) {
|
|
36602
36759
|
const msg = `Failed to create ${hunk.path}: ${e instanceof Error ? e.message : e}`;
|
|
36603
36760
|
results.push(msg);
|
|
36604
|
-
failures.push(hunk.path);
|
|
36761
|
+
failures.push({ index: hunkIndex, path: hunk.path });
|
|
36605
36762
|
const filePath2 = resolvePathFromProjectRoot(projectRoot, hunk.path);
|
|
36606
36763
|
if (fs6.existsSync(filePath2)) {
|
|
36607
36764
|
try {
|
|
@@ -36620,8 +36777,11 @@ function createApplyPatchTool(ctx) {
|
|
|
36620
36777
|
if (deleteResult.success === false) {
|
|
36621
36778
|
throw new Error(deleteResult.message ?? "delete failed");
|
|
36622
36779
|
}
|
|
36623
|
-
|
|
36780
|
+
appliedHunkResults.push({
|
|
36781
|
+
index: hunkIndex,
|
|
36782
|
+
hunk,
|
|
36624
36783
|
filePath,
|
|
36784
|
+
displayPath: filePath,
|
|
36625
36785
|
before,
|
|
36626
36786
|
after: "",
|
|
36627
36787
|
additions: 0,
|
|
@@ -36630,7 +36790,7 @@ function createApplyPatchTool(ctx) {
|
|
|
36630
36790
|
results.push(`Deleted ${hunk.path}`);
|
|
36631
36791
|
} catch (e) {
|
|
36632
36792
|
results.push(`Failed to delete ${hunk.path}: ${e instanceof Error ? e.message : e}`);
|
|
36633
|
-
failures.push(hunk.path);
|
|
36793
|
+
failures.push({ index: hunkIndex, path: hunk.path });
|
|
36634
36794
|
}
|
|
36635
36795
|
break;
|
|
36636
36796
|
}
|
|
@@ -36657,7 +36817,7 @@ function createApplyPatchTool(ctx) {
|
|
|
36657
36817
|
if (diags && diags.length > 0) {
|
|
36658
36818
|
const errors3 = diags.filter((d) => d.severity === "error");
|
|
36659
36819
|
if (errors3.length > 0) {
|
|
36660
|
-
const relPath =
|
|
36820
|
+
const relPath = path5.relative(projectRoot, targetPath);
|
|
36661
36821
|
const diagLines = errors3.map((d) => ` Line ${d.line}: ${d.message}`).join(`
|
|
36662
36822
|
`);
|
|
36663
36823
|
results.push(`
|
|
@@ -36671,13 +36831,17 @@ ${diagLines}`);
|
|
|
36671
36831
|
additions: wrDiff.additions,
|
|
36672
36832
|
deletions: wrDiff.deletions
|
|
36673
36833
|
};
|
|
36674
|
-
|
|
36834
|
+
const appliedHunkResult = {
|
|
36835
|
+
index: hunkIndex,
|
|
36836
|
+
hunk,
|
|
36675
36837
|
filePath,
|
|
36838
|
+
displayPath: targetPath,
|
|
36839
|
+
...hunk.move_path ? { movePath: targetPath } : {},
|
|
36676
36840
|
before: original,
|
|
36677
36841
|
after: newContent,
|
|
36678
36842
|
additions,
|
|
36679
36843
|
deletions
|
|
36680
|
-
}
|
|
36844
|
+
};
|
|
36681
36845
|
if (hunk.move_path) {
|
|
36682
36846
|
try {
|
|
36683
36847
|
const deleteResult = await callBridge(ctx, context, "delete_file", {
|
|
@@ -36710,13 +36874,15 @@ ${diagLines}`);
|
|
|
36710
36874
|
}
|
|
36711
36875
|
throw new Error(`source delete failed after writing move destination; restored pre-patch checkpoint ${checkpointName}: ${formatError2(deleteError)}`);
|
|
36712
36876
|
}
|
|
36877
|
+
appliedHunkResults.push(appliedHunkResult);
|
|
36713
36878
|
results.push(`Updated and moved ${hunk.path} → ${hunk.move_path}`);
|
|
36714
36879
|
} else {
|
|
36880
|
+
appliedHunkResults.push(appliedHunkResult);
|
|
36715
36881
|
results.push(`Updated ${hunk.path}`);
|
|
36716
36882
|
}
|
|
36717
36883
|
} catch (e) {
|
|
36718
36884
|
results.push(`Failed to update ${hunk.path}: ${e instanceof Error ? e.message : e}`);
|
|
36719
|
-
failures.push(hunk.path);
|
|
36885
|
+
failures.push({ index: hunkIndex, path: hunk.path });
|
|
36720
36886
|
break;
|
|
36721
36887
|
}
|
|
36722
36888
|
break;
|
|
@@ -36725,7 +36891,8 @@ ${diagLines}`);
|
|
|
36725
36891
|
}
|
|
36726
36892
|
if (failures.length > 0) {
|
|
36727
36893
|
const partial2 = failures.length < hunks.length;
|
|
36728
|
-
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}.`;
|
|
36729
36896
|
results.push(summary);
|
|
36730
36897
|
if (!partial2) {
|
|
36731
36898
|
throw new Error(results.join(`
|
|
@@ -36733,28 +36900,56 @@ ${diagLines}`);
|
|
|
36733
36900
|
}
|
|
36734
36901
|
}
|
|
36735
36902
|
{
|
|
36736
|
-
const
|
|
36737
|
-
const
|
|
36738
|
-
|
|
36739
|
-
|
|
36740
|
-
|
|
36741
|
-
|
|
36742
|
-
|
|
36743
|
-
|
|
36744
|
-
|
|
36745
|
-
|
|
36746
|
-
|
|
36747
|
-
|
|
36748
|
-
|
|
36749
|
-
|
|
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
|
+
}
|
|
36750
36945
|
return {
|
|
36751
|
-
filePath,
|
|
36946
|
+
filePath: entry.filePath,
|
|
36752
36947
|
relativePath: relPath,
|
|
36753
36948
|
type: uiType,
|
|
36754
36949
|
patch,
|
|
36755
|
-
additions,
|
|
36756
|
-
deletions,
|
|
36757
|
-
...movePath ? { movePath } : {}
|
|
36950
|
+
additions: entry.additions,
|
|
36951
|
+
deletions: entry.deletions,
|
|
36952
|
+
...entry.movePath ? { movePath: entry.movePath } : {}
|
|
36758
36953
|
};
|
|
36759
36954
|
});
|
|
36760
36955
|
const fileList = files.map((f) => {
|
|
@@ -36762,7 +36957,7 @@ ${diagLines}`);
|
|
|
36762
36957
|
return `${prefix} ${f.relativePath}`;
|
|
36763
36958
|
}).join(`
|
|
36764
36959
|
`);
|
|
36765
|
-
const title = failures.length > 0 ? `Partially applied (${
|
|
36960
|
+
const title = failures.length > 0 ? `Partially applied (${hunks.length - failures.length} of ${hunks.length}). Updated:
|
|
36766
36961
|
${fileList}` : `Success. Updated the following files:
|
|
36767
36962
|
${fileList}`;
|
|
36768
36963
|
const diffText = files.map((f) => f.patch).filter(Boolean).join(`
|
|
@@ -36915,7 +37110,7 @@ function aftPrefixedTools(ctx) {
|
|
|
36915
37110
|
const file2 = normalizedArgs.filePath;
|
|
36916
37111
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
36917
37112
|
const filePath = resolvePathFromProjectRoot(projectRoot, file2);
|
|
36918
|
-
const relPath =
|
|
37113
|
+
const relPath = path5.relative(projectRoot, filePath);
|
|
36919
37114
|
{
|
|
36920
37115
|
const denial2 = await assertExternalDirectoryPermission(context, filePath);
|
|
36921
37116
|
if (denial2)
|
|
@@ -37312,15 +37507,15 @@ function buildZoomTitle(args) {
|
|
|
37312
37507
|
}
|
|
37313
37508
|
return `${args.targets.filePath}#${args.targets.symbol}`;
|
|
37314
37509
|
}
|
|
37315
|
-
const
|
|
37510
|
+
const path6 = args.filePath ?? args.url ?? "";
|
|
37316
37511
|
if (typeof args.symbols === "string")
|
|
37317
|
-
return
|
|
37512
|
+
return path6 ? `${path6}#${args.symbols}` : args.symbols;
|
|
37318
37513
|
if (Array.isArray(args.symbols) && args.symbols.length > 0) {
|
|
37319
37514
|
if (args.symbols.length === 1)
|
|
37320
|
-
return
|
|
37321
|
-
return
|
|
37515
|
+
return path6 ? `${path6}#${args.symbols[0]}` : args.symbols[0];
|
|
37516
|
+
return path6 ? `${path6} (${args.symbols.length} symbols)` : `${args.symbols.length} symbols`;
|
|
37322
37517
|
}
|
|
37323
|
-
return
|
|
37518
|
+
return path6 || "(no target)";
|
|
37324
37519
|
}
|
|
37325
37520
|
function readingTools(ctx) {
|
|
37326
37521
|
return {
|
|
@@ -37553,6 +37748,11 @@ function readingTools(ctx) {
|
|
|
37553
37748
|
}));
|
|
37554
37749
|
if (symbolsArray.length === 1) {
|
|
37555
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
|
+
}
|
|
37556
37756
|
if (response.success === false) {
|
|
37557
37757
|
throw new Error(response.message || "zoom failed");
|
|
37558
37758
|
}
|
|
@@ -37821,11 +38021,11 @@ function refactoringTools(ctx) {
|
|
|
37821
38021
|
}
|
|
37822
38022
|
|
|
37823
38023
|
// src/tools/safety.ts
|
|
37824
|
-
import * as
|
|
38024
|
+
import * as path6 from "node:path";
|
|
37825
38025
|
import { tool as tool14 } from "@opencode-ai/plugin";
|
|
37826
38026
|
var z14 = tool14.schema;
|
|
37827
38027
|
function responsePaths(response) {
|
|
37828
|
-
return Array.isArray(response.paths) ? response.paths.filter((
|
|
38028
|
+
return Array.isArray(response.paths) ? response.paths.filter((path7) => typeof path7 === "string" && path7.length > 0) : [];
|
|
37829
38029
|
}
|
|
37830
38030
|
function bridgeErrorMessage(response, fallback) {
|
|
37831
38031
|
return typeof response.message === "string" && response.message.length > 0 ? response.message : fallback;
|
|
@@ -37902,9 +38102,9 @@ function safetyTools(ctx) {
|
|
|
37902
38102
|
for (const rawFile of checkpointFiles) {
|
|
37903
38103
|
if (typeof rawFile !== "string")
|
|
37904
38104
|
continue;
|
|
37905
|
-
const file2 =
|
|
37906
|
-
const abs =
|
|
37907
|
-
const parent =
|
|
38105
|
+
const file2 = expandTilde2(rawFile);
|
|
38106
|
+
const abs = path6.isAbsolute(file2) ? file2 : path6.resolve(projectRoot, file2);
|
|
38107
|
+
const parent = path6.dirname(abs);
|
|
37908
38108
|
if (uniqueParents.has(parent))
|
|
37909
38109
|
continue;
|
|
37910
38110
|
uniqueParents.add(parent);
|
|
@@ -37942,8 +38142,8 @@ function safetyTools(ctx) {
|
|
|
37942
38142
|
const params = {};
|
|
37943
38143
|
if (args.name !== undefined)
|
|
37944
38144
|
params.name = args.name;
|
|
37945
|
-
const payloadFiles = coerceStringArray(args.files).map(
|
|
37946
|
-
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;
|
|
37947
38147
|
if (op === "checkpoint") {
|
|
37948
38148
|
if (payloadFiles.length > 0) {
|
|
37949
38149
|
params.files = payloadFiles;
|
|
@@ -37968,7 +38168,7 @@ function safetyTools(ctx) {
|
|
|
37968
38168
|
|
|
37969
38169
|
// src/tools/search.ts
|
|
37970
38170
|
import * as fs7 from "node:fs";
|
|
37971
|
-
import * as
|
|
38171
|
+
import * as path7 from "node:path";
|
|
37972
38172
|
function arg2(schema) {
|
|
37973
38173
|
return schema;
|
|
37974
38174
|
}
|
|
@@ -38000,7 +38200,7 @@ function normalizeGlob(pattern) {
|
|
|
38000
38200
|
return pattern;
|
|
38001
38201
|
}
|
|
38002
38202
|
function absoluteSearchPath(projectRoot, target) {
|
|
38003
|
-
return resolvePathFromProjectRoot(projectRoot,
|
|
38203
|
+
return resolvePathFromProjectRoot(projectRoot, expandTilde2(target));
|
|
38004
38204
|
}
|
|
38005
38205
|
function searchPathExists(projectRoot, target) {
|
|
38006
38206
|
return fs7.existsSync(absoluteSearchPath(projectRoot, target));
|
|
@@ -38077,7 +38277,7 @@ function searchTools(ctx) {
|
|
|
38077
38277
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
38078
38278
|
const pattern = String(args.pattern);
|
|
38079
38279
|
const includeArg = args.include ? String(args.include) : undefined;
|
|
38080
|
-
const pathArg = args.path ?
|
|
38280
|
+
const pathArg = args.path ? expandTilde2(String(args.path)) : undefined;
|
|
38081
38281
|
const bridgePath = pathArg ? absoluteSearchPath(projectRoot, pathArg) : undefined;
|
|
38082
38282
|
const grepDenied = await askGrepPermission(context, pattern, {
|
|
38083
38283
|
path: bridgePath,
|
|
@@ -38115,8 +38315,8 @@ function searchTools(ctx) {
|
|
|
38115
38315
|
},
|
|
38116
38316
|
execute: async (args, context) => {
|
|
38117
38317
|
const projectRoot = await resolveProjectRoot(ctx, context);
|
|
38118
|
-
let globPattern =
|
|
38119
|
-
let globPath = args.path ?
|
|
38318
|
+
let globPattern = expandTilde2(String(args.pattern));
|
|
38319
|
+
let globPath = args.path ? expandTilde2(String(args.path)) : undefined;
|
|
38120
38320
|
if (!globPath && globPattern.startsWith("/")) {
|
|
38121
38321
|
const metaIdx = globPattern.search(/[*?{}[\]]/);
|
|
38122
38322
|
if (metaIdx > 0) {
|
|
@@ -38126,8 +38326,8 @@ function searchTools(ctx) {
|
|
|
38126
38326
|
globPattern = `**/${globPattern.slice(lastSlash + 1)}`;
|
|
38127
38327
|
}
|
|
38128
38328
|
} else if (metaIdx === -1) {
|
|
38129
|
-
globPath =
|
|
38130
|
-
globPattern =
|
|
38329
|
+
globPath = path7.dirname(globPattern);
|
|
38330
|
+
globPattern = path7.basename(globPattern);
|
|
38131
38331
|
}
|
|
38132
38332
|
}
|
|
38133
38333
|
const globDenied = await askGlobPermission(context, globPattern, { path: globPath });
|
|
@@ -38492,13 +38692,13 @@ ${lines}
|
|
|
38492
38692
|
const upgradePromise = (async () => {
|
|
38493
38693
|
warn2(`WARNING: aft binary v${binaryVersion} is older than plugin v${minVersion}. ` + "Some features may not work. Attempting to download a compatible binary...");
|
|
38494
38694
|
try {
|
|
38495
|
-
const
|
|
38496
|
-
if (!
|
|
38695
|
+
const path8 = await ensureBinary(`v${minVersion}`);
|
|
38696
|
+
if (!path8) {
|
|
38497
38697
|
warn2(`Could not find or download v${minVersion}. Continuing with v${binaryVersion}.`);
|
|
38498
38698
|
return null;
|
|
38499
38699
|
}
|
|
38500
|
-
log2(`Found/downloaded compatible binary at ${
|
|
38501
|
-
const replaced = await pool.replaceBinary(
|
|
38700
|
+
log2(`Found/downloaded compatible binary at ${path8}. Replacing running bridges...`);
|
|
38701
|
+
const replaced = await pool.replaceBinary(path8);
|
|
38502
38702
|
log2("Binary replaced successfully. New bridges will use the updated binary.");
|
|
38503
38703
|
return replaced;
|
|
38504
38704
|
} catch (err) {
|