@cortexkit/aft-opencode 0.26.4 → 0.27.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/bg-notifications.d.ts +3 -0
- package/dist/bg-notifications.d.ts.map +1 -1
- package/dist/config.d.ts +20 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/configure-warnings.d.ts +2 -0
- package/dist/configure-warnings.d.ts.map +1 -1
- package/dist/hooks/auto-update-checker/index.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +639 -500
- package/dist/lsp-auto-install.d.ts +1 -1
- package/dist/lsp-auto-install.d.ts.map +1 -1
- package/dist/notifications.d.ts +2 -0
- package/dist/notifications.d.ts.map +1 -1
- package/dist/shared/status.d.ts +12 -0
- package/dist/shared/status.d.ts.map +1 -1
- package/dist/tools/hoisted.d.ts.map +1 -1
- package/dist/tui.js +94 -10
- package/package.json +8 -7
- package/src/shared/status.ts +34 -0
- package/src/tui/index.tsx +35 -2
- package/src/tui/sidebar.tsx +66 -2
package/dist/index.js
CHANGED
|
@@ -1607,10 +1607,10 @@ var require_esprima = __commonJS((exports, module) => {
|
|
|
1607
1607
|
}();
|
|
1608
1608
|
exports2.TaggedTemplateExpression = TaggedTemplateExpression;
|
|
1609
1609
|
var TemplateElement = function() {
|
|
1610
|
-
function TemplateElement2(value,
|
|
1610
|
+
function TemplateElement2(value, tail2) {
|
|
1611
1611
|
this.type = syntax_1.Syntax.TemplateElement;
|
|
1612
1612
|
this.value = value;
|
|
1613
|
-
this.tail =
|
|
1613
|
+
this.tail = tail2;
|
|
1614
1614
|
}
|
|
1615
1615
|
return TemplateElement2;
|
|
1616
1616
|
}();
|
|
@@ -5450,14 +5450,14 @@ var require_esprima = __commonJS((exports, module) => {
|
|
|
5450
5450
|
var terminated = false;
|
|
5451
5451
|
var start = this.index;
|
|
5452
5452
|
var head = this.source[start] === "`";
|
|
5453
|
-
var
|
|
5453
|
+
var tail2 = false;
|
|
5454
5454
|
var rawOffset = 2;
|
|
5455
5455
|
++this.index;
|
|
5456
5456
|
while (!this.eof()) {
|
|
5457
5457
|
var ch = this.source[this.index++];
|
|
5458
5458
|
if (ch === "`") {
|
|
5459
5459
|
rawOffset = 1;
|
|
5460
|
-
|
|
5460
|
+
tail2 = true;
|
|
5461
5461
|
terminated = true;
|
|
5462
5462
|
break;
|
|
5463
5463
|
} else if (ch === "$") {
|
|
@@ -5558,7 +5558,7 @@ var require_esprima = __commonJS((exports, module) => {
|
|
|
5558
5558
|
value: this.source.slice(start + 1, this.index - rawOffset),
|
|
5559
5559
|
cooked,
|
|
5560
5560
|
head,
|
|
5561
|
-
tail,
|
|
5561
|
+
tail: tail2,
|
|
5562
5562
|
lineNumber: this.lineNumber,
|
|
5563
5563
|
lineStart: this.lineStart,
|
|
5564
5564
|
start,
|
|
@@ -7652,10 +7652,10 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
7652
7652
|
replacer = null;
|
|
7653
7653
|
indent = EMPTY;
|
|
7654
7654
|
};
|
|
7655
|
-
var
|
|
7655
|
+
var join8 = (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 join8(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 = join8(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 += join8(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 = join8(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 += join8(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) {
|
|
@@ -7803,10 +7803,9 @@ var require_src2 = __commonJS((exports, module) => {
|
|
|
7803
7803
|
});
|
|
7804
7804
|
|
|
7805
7805
|
// src/index.ts
|
|
7806
|
-
import { existsSync as
|
|
7806
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync13, readFileSync as readFileSync12, writeFileSync as writeFileSync12 } from "fs";
|
|
7807
7807
|
import { createRequire as createRequire2 } from "module";
|
|
7808
|
-
import {
|
|
7809
|
-
import { join as join21 } from "path";
|
|
7808
|
+
import { join as join22 } from "path";
|
|
7810
7809
|
|
|
7811
7810
|
// ../aft-bridge/dist/active-logger.js
|
|
7812
7811
|
var ACTIVE_LOGGER_SYMBOL = Symbol.for("aft-bridge-active-logger");
|
|
@@ -8831,11 +8830,288 @@ async function fetchLatestTag() {
|
|
|
8831
8830
|
clearTimeout(timeout);
|
|
8832
8831
|
}
|
|
8833
8832
|
}
|
|
8833
|
+
// ../aft-bridge/dist/migration.js
|
|
8834
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
8835
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3 } from "fs";
|
|
8836
|
+
import { homedir as homedir4, tmpdir } from "os";
|
|
8837
|
+
import { dirname, join as join4 } from "path";
|
|
8838
|
+
|
|
8839
|
+
// ../aft-bridge/dist/resolver.js
|
|
8840
|
+
import { execSync, spawnSync } from "child_process";
|
|
8841
|
+
import { chmodSync as chmodSync2, copyFileSync, existsSync as existsSync2, mkdirSync as mkdirSync2, renameSync as renameSync2 } from "fs";
|
|
8842
|
+
import { createRequire } from "module";
|
|
8843
|
+
import { homedir as homedir3 } from "os";
|
|
8844
|
+
import { join as join3 } from "path";
|
|
8845
|
+
function readBinaryVersion(binaryPath) {
|
|
8846
|
+
try {
|
|
8847
|
+
const result = spawnSync(binaryPath, ["--version"], {
|
|
8848
|
+
encoding: "utf-8",
|
|
8849
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
8850
|
+
timeout: 5000
|
|
8851
|
+
});
|
|
8852
|
+
const stdoutVersion = result.stdout?.trim();
|
|
8853
|
+
const stderrVersion = result.stderr?.trim();
|
|
8854
|
+
const rawVersion = stdoutVersion || stderrVersion;
|
|
8855
|
+
if (!rawVersion)
|
|
8856
|
+
return null;
|
|
8857
|
+
return rawVersion.replace(/^aft\s+/, "");
|
|
8858
|
+
} catch {
|
|
8859
|
+
return null;
|
|
8860
|
+
}
|
|
8861
|
+
}
|
|
8862
|
+
function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
8863
|
+
try {
|
|
8864
|
+
const version = knownVersion ?? readBinaryVersion(npmBinaryPath);
|
|
8865
|
+
if (!version)
|
|
8866
|
+
return null;
|
|
8867
|
+
const tag = version.startsWith("v") ? version : `v${version}`;
|
|
8868
|
+
const cacheDir = getCacheDir();
|
|
8869
|
+
const versionedDir = join3(cacheDir, tag);
|
|
8870
|
+
const ext = process.platform === "win32" ? ".exe" : "";
|
|
8871
|
+
const cachedPath = join3(versionedDir, `aft${ext}`);
|
|
8872
|
+
if (existsSync2(cachedPath)) {
|
|
8873
|
+
const cachedVersion = readBinaryVersion(cachedPath);
|
|
8874
|
+
if (cachedVersion === version)
|
|
8875
|
+
return cachedPath;
|
|
8876
|
+
warn(`Cached binary at ${cachedPath} reports ${cachedVersion ?? "no version"}, expected ${version}; refreshing from npm package`);
|
|
8877
|
+
}
|
|
8878
|
+
mkdirSync2(versionedDir, { recursive: true });
|
|
8879
|
+
const tmpPath = `${cachedPath}.${process.pid}.${Date.now()}.tmp`;
|
|
8880
|
+
copyFileSync(npmBinaryPath, tmpPath);
|
|
8881
|
+
if (process.platform !== "win32") {
|
|
8882
|
+
chmodSync2(tmpPath, 493);
|
|
8883
|
+
}
|
|
8884
|
+
renameSync2(tmpPath, cachedPath);
|
|
8885
|
+
log(`Copied npm binary to versioned cache: ${cachedPath}`);
|
|
8886
|
+
return cachedPath;
|
|
8887
|
+
} catch (err) {
|
|
8888
|
+
warn(`Failed to copy binary to cache: ${err instanceof Error ? err.message : String(err)}`);
|
|
8889
|
+
return null;
|
|
8890
|
+
}
|
|
8891
|
+
}
|
|
8892
|
+
function normalizeBareVersion(version) {
|
|
8893
|
+
return version.startsWith("v") ? version.slice(1) : version;
|
|
8894
|
+
}
|
|
8895
|
+
function homeDirFromEnv(env) {
|
|
8896
|
+
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir3();
|
|
8897
|
+
}
|
|
8898
|
+
function cacheDirFromEnv(env) {
|
|
8899
|
+
if (process.platform === "win32") {
|
|
8900
|
+
const base2 = env.LOCALAPPDATA || env.APPDATA || join3(homeDirFromEnv(env), "AppData", "Local");
|
|
8901
|
+
return join3(base2, "aft", "bin");
|
|
8902
|
+
}
|
|
8903
|
+
const base = env.XDG_CACHE_HOME || join3(homeDirFromEnv(env), ".cache");
|
|
8904
|
+
return join3(base, "aft", "bin");
|
|
8905
|
+
}
|
|
8906
|
+
function cachedBinaryPathFromEnv(version, env, ext) {
|
|
8907
|
+
const binaryPath = join3(cacheDirFromEnv(env), version, `aft${ext}`);
|
|
8908
|
+
return existsSync2(binaryPath) ? binaryPath : null;
|
|
8909
|
+
}
|
|
8910
|
+
function isExpectedCachedBinary(binaryPath, expectedVersion) {
|
|
8911
|
+
const expected = normalizeBareVersion(expectedVersion);
|
|
8912
|
+
const actual = readBinaryVersion(binaryPath);
|
|
8913
|
+
if (actual === expected)
|
|
8914
|
+
return true;
|
|
8915
|
+
warn(`Cached binary at ${binaryPath} reports ${actual ?? "no version"}, expected ${expected}; skipping cache candidate`);
|
|
8916
|
+
return false;
|
|
8917
|
+
}
|
|
8918
|
+
function platformKey(platform = process.platform, arch = process.arch) {
|
|
8919
|
+
const archMap = PLATFORM_ARCH_MAP[platform];
|
|
8920
|
+
if (!archMap) {
|
|
8921
|
+
throw new Error(`Unsupported platform: ${platform} (arch: ${arch}). ` + `Supported platforms: ${Object.keys(PLATFORM_ARCH_MAP).join(", ")}`);
|
|
8922
|
+
}
|
|
8923
|
+
const key = archMap[arch];
|
|
8924
|
+
if (!key) {
|
|
8925
|
+
throw new Error(`Unsupported architecture: ${arch} on platform ${platform}. ` + `Supported architectures for ${platform}: ${Object.keys(archMap).join(", ")}`);
|
|
8926
|
+
}
|
|
8927
|
+
return key;
|
|
8928
|
+
}
|
|
8929
|
+
function findBinarySync(expectedVersion) {
|
|
8930
|
+
const ext = process.platform === "win32" ? ".exe" : "";
|
|
8931
|
+
const env = { ...process.env };
|
|
8932
|
+
const pluginVersion = expectedVersion ?? (() => {
|
|
8933
|
+
try {
|
|
8934
|
+
const req = createRequire(import.meta.url);
|
|
8935
|
+
return req("../package.json").version;
|
|
8936
|
+
} catch {
|
|
8937
|
+
return null;
|
|
8938
|
+
}
|
|
8939
|
+
})();
|
|
8940
|
+
if (pluginVersion) {
|
|
8941
|
+
const tag = pluginVersion.startsWith("v") ? pluginVersion : `v${pluginVersion}`;
|
|
8942
|
+
const versionCached = cachedBinaryPathFromEnv(tag, env, ext);
|
|
8943
|
+
if (versionCached && isExpectedCachedBinary(versionCached, pluginVersion))
|
|
8944
|
+
return versionCached;
|
|
8945
|
+
}
|
|
8946
|
+
try {
|
|
8947
|
+
const key = platformKey();
|
|
8948
|
+
const packageBin = `@cortexkit/aft-${key}/bin/aft${ext}`;
|
|
8949
|
+
const req = createRequire(import.meta.url);
|
|
8950
|
+
const resolved = req.resolve(packageBin);
|
|
8951
|
+
if (existsSync2(resolved)) {
|
|
8952
|
+
const npmVersion = readBinaryVersion(resolved);
|
|
8953
|
+
if (npmVersion === null) {
|
|
8954
|
+
warn(`npm platform package binary at ${resolved} did not report a version; skipping (continuing to PATH lookup)`);
|
|
8955
|
+
} else if (pluginVersion && npmVersion !== normalizeBareVersion(pluginVersion)) {
|
|
8956
|
+
warn(`npm platform package binary v${npmVersion} does not match plugin v${pluginVersion}; skipping (continuing to PATH lookup)`);
|
|
8957
|
+
} else {
|
|
8958
|
+
const copied = copyToVersionedCache(resolved, npmVersion);
|
|
8959
|
+
return copied ?? resolved;
|
|
8960
|
+
}
|
|
8961
|
+
}
|
|
8962
|
+
} catch {}
|
|
8963
|
+
try {
|
|
8964
|
+
const whichCmd = process.platform === "win32" ? "where aft" : "which aft";
|
|
8965
|
+
const result = execSync(whichCmd, {
|
|
8966
|
+
encoding: "utf-8",
|
|
8967
|
+
env,
|
|
8968
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
8969
|
+
}).trim();
|
|
8970
|
+
if (result)
|
|
8971
|
+
return result;
|
|
8972
|
+
} catch {}
|
|
8973
|
+
const cargoPath = join3(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
|
|
8974
|
+
if (existsSync2(cargoPath))
|
|
8975
|
+
return cargoPath;
|
|
8976
|
+
return null;
|
|
8977
|
+
}
|
|
8978
|
+
async function findBinary(expectedVersion) {
|
|
8979
|
+
const syncResult = findBinarySync(expectedVersion);
|
|
8980
|
+
if (syncResult) {
|
|
8981
|
+
log(`Resolved binary: ${syncResult}`);
|
|
8982
|
+
return syncResult;
|
|
8983
|
+
}
|
|
8984
|
+
log("Binary not found locally, attempting auto-download...");
|
|
8985
|
+
const downloaded = await ensureBinary(expectedVersion);
|
|
8986
|
+
if (downloaded)
|
|
8987
|
+
return downloaded;
|
|
8988
|
+
throw new Error([
|
|
8989
|
+
"Could not find the `aft` binary.",
|
|
8990
|
+
"",
|
|
8991
|
+
"Attempted sources:",
|
|
8992
|
+
" - Cache directory (~/.cache/aft/bin/)",
|
|
8993
|
+
" - npm platform package (@cortexkit/aft-<platform>)",
|
|
8994
|
+
" - PATH lookup (which aft)",
|
|
8995
|
+
" - ~/.cargo/bin/aft",
|
|
8996
|
+
" - Auto-download from GitHub releases (failed)",
|
|
8997
|
+
"",
|
|
8998
|
+
"Install it using one of these methods:",
|
|
8999
|
+
" npm install @cortexkit/aft-opencode # installs platform-specific binary via npm",
|
|
9000
|
+
" cargo install agent-file-tools # from crates.io",
|
|
9001
|
+
" cargo build --release # from source (binary at target/release/aft)",
|
|
9002
|
+
"",
|
|
9003
|
+
"Or add the aft directory to your PATH."
|
|
9004
|
+
].join(`
|
|
9005
|
+
`));
|
|
9006
|
+
}
|
|
9007
|
+
|
|
9008
|
+
// ../aft-bridge/dist/migration.js
|
|
9009
|
+
var TARGET_MARKER = ".migrated_from_legacy";
|
|
9010
|
+
var DEFAULT_TIMEOUT_MS = 30 * 60 * 1000;
|
|
9011
|
+
function dataHome() {
|
|
9012
|
+
if (process.env.XDG_DATA_HOME)
|
|
9013
|
+
return process.env.XDG_DATA_HOME;
|
|
9014
|
+
if (process.platform === "win32") {
|
|
9015
|
+
return process.env.LOCALAPPDATA || process.env.APPDATA || join4(homeDir(), "AppData", "Local");
|
|
9016
|
+
}
|
|
9017
|
+
return join4(homeDir(), ".local", "share");
|
|
9018
|
+
}
|
|
9019
|
+
function homeDir() {
|
|
9020
|
+
if (process.platform === "win32")
|
|
9021
|
+
return process.env.USERPROFILE || process.env.HOME || homedir4();
|
|
9022
|
+
return process.env.HOME || homedir4();
|
|
9023
|
+
}
|
|
9024
|
+
function resolveLegacyStorageRoot(harness) {
|
|
9025
|
+
if (harness === "pi")
|
|
9026
|
+
return join4(homeDir(), ".pi", "agent", "aft");
|
|
9027
|
+
return join4(dataHome(), "opencode", "storage", "plugin", "aft");
|
|
9028
|
+
}
|
|
9029
|
+
function resolveCortexKitStorageRoot() {
|
|
9030
|
+
return join4(dataHome(), "cortexkit", "aft");
|
|
9031
|
+
}
|
|
9032
|
+
function tail(value) {
|
|
9033
|
+
if (!value)
|
|
9034
|
+
return "";
|
|
9035
|
+
return value.split(`
|
|
9036
|
+
`).slice(-20).join(`
|
|
9037
|
+
`).trim();
|
|
9038
|
+
}
|
|
9039
|
+
function spawnErrorLabel(error2) {
|
|
9040
|
+
const code = "code" in error2 ? String(error2.code ?? "") : "";
|
|
9041
|
+
return [code, error2.message].filter(Boolean).join(": ");
|
|
9042
|
+
}
|
|
9043
|
+
function migrationLogPath(newRoot, harness, logger) {
|
|
9044
|
+
const desired = join4(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
|
|
9045
|
+
try {
|
|
9046
|
+
mkdirSync3(dirname(desired), { recursive: true });
|
|
9047
|
+
return desired;
|
|
9048
|
+
} catch (err) {
|
|
9049
|
+
const fallback = join4(tmpdir(), `aft-migration-${harness}-${Date.now()}.jsonl`);
|
|
9050
|
+
logger?.warn?.(`Failed to create AFT migration log directory ${dirname(desired)}: ${err instanceof Error ? err.message : String(err)}. ` + `Using fallback log path ${fallback}.`);
|
|
9051
|
+
return fallback;
|
|
9052
|
+
}
|
|
9053
|
+
}
|
|
9054
|
+
async function ensureStorageMigrated(opts) {
|
|
9055
|
+
const legacyRoot = resolveLegacyStorageRoot(opts.harness);
|
|
9056
|
+
const newRoot = resolveCortexKitStorageRoot();
|
|
9057
|
+
const targetMarker = join4(newRoot, opts.harness, TARGET_MARKER);
|
|
9058
|
+
const info = opts.logger?.info ?? opts.logger?.log;
|
|
9059
|
+
if (existsSync3(targetMarker)) {
|
|
9060
|
+
info?.(`AFT storage already migrated for ${opts.harness}; using ${newRoot}`);
|
|
9061
|
+
return;
|
|
9062
|
+
}
|
|
9063
|
+
if (!existsSync3(legacyRoot)) {
|
|
9064
|
+
info?.(`AFT storage migration skipped for ${opts.harness}: no legacy data at ${legacyRoot}; ` + `using ${newRoot} for fresh install`);
|
|
9065
|
+
return;
|
|
9066
|
+
}
|
|
9067
|
+
const logPath = migrationLogPath(newRoot, opts.harness, opts.logger);
|
|
9068
|
+
const binaryPath = opts.binaryPath ?? await findBinary();
|
|
9069
|
+
const startMs = Date.now();
|
|
9070
|
+
info?.(`AFT storage migration starting for ${opts.harness}: ${legacyRoot} -> ${newRoot} ` + `(binary=${binaryPath}, log=${logPath})`);
|
|
9071
|
+
try {
|
|
9072
|
+
process.stderr.write(`
|
|
9073
|
+
[AFT] Migrating ${opts.harness} storage to ${newRoot}.
|
|
9074
|
+
` + `[AFT] This may take several minutes for large indexes \u2014 please do not close ${opts.harness === "pi" ? "Pi" : "OpenCode"}.
|
|
9075
|
+
` + `[AFT] Source: ${legacyRoot}
|
|
9076
|
+
` + `[AFT] Log: ${logPath}
|
|
9077
|
+
|
|
9078
|
+
`);
|
|
9079
|
+
} catch {}
|
|
9080
|
+
const result = spawnSync2(binaryPath, [
|
|
9081
|
+
"migrate-storage",
|
|
9082
|
+
"--from",
|
|
9083
|
+
legacyRoot,
|
|
9084
|
+
"--to",
|
|
9085
|
+
newRoot,
|
|
9086
|
+
"--harness",
|
|
9087
|
+
opts.harness,
|
|
9088
|
+
"--log",
|
|
9089
|
+
logPath
|
|
9090
|
+
], {
|
|
9091
|
+
encoding: "utf8",
|
|
9092
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
9093
|
+
timeout: opts.timeoutMs ?? DEFAULT_TIMEOUT_MS
|
|
9094
|
+
});
|
|
9095
|
+
if (!result.error && result.status === 0) {
|
|
9096
|
+
const elapsedMs = Date.now() - startMs;
|
|
9097
|
+
info?.(`AFT storage migration completed for ${opts.harness} in ${elapsedMs}ms (log=${logPath})`);
|
|
9098
|
+
try {
|
|
9099
|
+
process.stderr.write(`[AFT] Migration complete (${(elapsedMs / 1000).toFixed(1)}s).
|
|
9100
|
+
|
|
9101
|
+
`);
|
|
9102
|
+
} catch {}
|
|
9103
|
+
return;
|
|
9104
|
+
}
|
|
9105
|
+
const detail = result.error ? `spawn error ${spawnErrorLabel(result.error)}` : result.status === null ? `terminated by signal ${result.signal ?? "unknown"}` : `exit ${result.status}`;
|
|
9106
|
+
const stderrTail = tail(result.stderr);
|
|
9107
|
+
const stdoutTail = tail(result.stdout);
|
|
9108
|
+
throw new Error(`AFT storage migration failed (${detail}). ` + `Harness: ${opts.harness}. Legacy: ${legacyRoot}. Target: ${newRoot}. ` + `See log: ${logPath}. ` + `Plugin load aborted to prevent legacy/new state divergence.` + (stderrTail ? ` Stderr tail: ${stderrTail}` : "") + (stdoutTail ? ` Stdout tail: ${stdoutTail}` : ""));
|
|
9109
|
+
}
|
|
8834
9110
|
// ../aft-bridge/dist/onnx-runtime.js
|
|
8835
9111
|
import { execFileSync } from "child_process";
|
|
8836
9112
|
import { createHash as createHash2 } from "crypto";
|
|
8837
|
-
import { chmodSync as
|
|
8838
|
-
import { dirname, join as
|
|
9113
|
+
import { chmodSync as chmodSync3, closeSync as closeSync2, copyFileSync as copyFileSync2, createWriteStream as createWriteStream2, existsSync as existsSync4, lstatSync, mkdirSync as mkdirSync4, openSync as openSync2, readdirSync, readFileSync, readlinkSync, realpathSync, rmSync as rmSync2, statSync as statSync2, symlinkSync, unlinkSync as unlinkSync2, writeFileSync } from "fs";
|
|
9114
|
+
import { dirname as dirname2, join as join5, relative, resolve } from "path";
|
|
8839
9115
|
import { Readable as Readable2 } from "stream";
|
|
8840
9116
|
import { pipeline as pipeline2 } from "stream/promises";
|
|
8841
9117
|
var ORT_VERSION = "1.24.4";
|
|
@@ -8883,8 +9159,8 @@ function getPlatformInfo() {
|
|
|
8883
9159
|
if (!platformMap)
|
|
8884
9160
|
return null;
|
|
8885
9161
|
const archMap = PLATFORM_ARCH_MAP[process.platform] ?? {};
|
|
8886
|
-
const
|
|
8887
|
-
const ortArch =
|
|
9162
|
+
const platformKey2 = archMap[process.arch];
|
|
9163
|
+
const ortArch = platformKey2 ? platformKey2.split("-")[1] : process.arch;
|
|
8888
9164
|
return platformMap[ortArch] || null;
|
|
8889
9165
|
}
|
|
8890
9166
|
function isOrtAutoDownloadSupported() {
|
|
@@ -8901,9 +9177,9 @@ function getManualInstallHint() {
|
|
|
8901
9177
|
}
|
|
8902
9178
|
async function ensureOnnxRuntime(storageDir) {
|
|
8903
9179
|
const info = getPlatformInfo();
|
|
8904
|
-
const ortDir =
|
|
8905
|
-
const libPath =
|
|
8906
|
-
if (
|
|
9180
|
+
const ortDir = join5(storageDir, "onnxruntime", ORT_VERSION);
|
|
9181
|
+
const libPath = join5(ortDir, info?.libName ?? "libonnxruntime.dylib");
|
|
9182
|
+
if (existsSync4(libPath)) {
|
|
8907
9183
|
const meta = readOnnxInstalledMeta(ortDir);
|
|
8908
9184
|
if (meta?.sha256) {
|
|
8909
9185
|
try {
|
|
@@ -8932,9 +9208,9 @@ async function ensureOnnxRuntime(storageDir) {
|
|
|
8932
9208
|
warn(`ONNX Runtime auto-download not available for ${process.platform}/${process.arch}. Install manually: ${getManualInstallHint()}`);
|
|
8933
9209
|
return null;
|
|
8934
9210
|
}
|
|
8935
|
-
const onnxBaseDir =
|
|
8936
|
-
|
|
8937
|
-
const lockPath =
|
|
9211
|
+
const onnxBaseDir = join5(storageDir, "onnxruntime");
|
|
9212
|
+
mkdirSync4(onnxBaseDir, { recursive: true });
|
|
9213
|
+
const lockPath = join5(onnxBaseDir, ONNX_LOCK_FILE);
|
|
8938
9214
|
cleanupAbandonedStagingDirs(onnxBaseDir);
|
|
8939
9215
|
if (!acquireLock(lockPath)) {
|
|
8940
9216
|
warn(`ONNX Runtime install already in progress in another process (lock: ${lockPath}). Skipping.`);
|
|
@@ -8953,7 +9229,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
8953
9229
|
for (const entry of entries) {
|
|
8954
9230
|
if (!entry.startsWith(`${ORT_VERSION}.tmp.`))
|
|
8955
9231
|
continue;
|
|
8956
|
-
const stagingDir =
|
|
9232
|
+
const stagingDir = join5(onnxBaseDir, entry);
|
|
8957
9233
|
const parts = entry.split(".");
|
|
8958
9234
|
const pidStr = parts[parts.length - 2];
|
|
8959
9235
|
const pid = pidStr ? Number.parseInt(pidStr, 10) : NaN;
|
|
@@ -8985,7 +9261,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
8985
9261
|
}
|
|
8986
9262
|
function cleanupIncompleteTargetIfUnowned(ortDir) {
|
|
8987
9263
|
try {
|
|
8988
|
-
if (
|
|
9264
|
+
if (existsSync4(ortDir) && !existsSync4(join5(ortDir, ONNX_INSTALLED_META_FILE))) {
|
|
8989
9265
|
log(`[onnx] removing half-populated install dir ${ortDir} (no meta file)`);
|
|
8990
9266
|
rmSync2(ortDir, { recursive: true, force: true });
|
|
8991
9267
|
}
|
|
@@ -9006,8 +9282,8 @@ function detectOnnxVersion(libDir, libName) {
|
|
|
9006
9282
|
if (match)
|
|
9007
9283
|
return match[1];
|
|
9008
9284
|
}
|
|
9009
|
-
const base =
|
|
9010
|
-
if (
|
|
9285
|
+
const base = join5(libDir, libName);
|
|
9286
|
+
if (existsSync4(base)) {
|
|
9011
9287
|
try {
|
|
9012
9288
|
const real = realpathSync(base);
|
|
9013
9289
|
const m = real.match(/\.(\d+\.\d+\.\d+)(?:\.dylib)?$/);
|
|
@@ -9043,7 +9319,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
9043
9319
|
searchPaths.push("/usr/lib", "/usr/lib/x86_64-linux-gnu", "/usr/lib/aarch64-linux-gnu", "/usr/local/lib");
|
|
9044
9320
|
}
|
|
9045
9321
|
for (const dir of searchPaths) {
|
|
9046
|
-
if (!
|
|
9322
|
+
if (!existsSync4(join5(dir, libName)))
|
|
9047
9323
|
continue;
|
|
9048
9324
|
const version = detectOnnxVersion(dir, libName);
|
|
9049
9325
|
if (version && !isOnnxVersionCompatible(version)) {
|
|
@@ -9070,7 +9346,7 @@ async function downloadFileWithCap(url, destPath) {
|
|
|
9070
9346
|
if (Number.isFinite(advertised) && advertised > MAX_DOWNLOAD_BYTES2) {
|
|
9071
9347
|
throw new Error(`Content-Length ${advertised} exceeds max ${MAX_DOWNLOAD_BYTES2}`);
|
|
9072
9348
|
}
|
|
9073
|
-
|
|
9349
|
+
mkdirSync4(dirname2(destPath), { recursive: true });
|
|
9074
9350
|
let bytesWritten = 0;
|
|
9075
9351
|
const guard = new TransformStream({
|
|
9076
9352
|
transform(chunk, transformController) {
|
|
@@ -9100,11 +9376,11 @@ function validateExtractedTree(stagingRoot) {
|
|
|
9100
9376
|
const walk = (dir) => {
|
|
9101
9377
|
const entries = readdirSync(dir);
|
|
9102
9378
|
for (const entry of entries) {
|
|
9103
|
-
const fullPath =
|
|
9379
|
+
const fullPath = join5(dir, entry);
|
|
9104
9380
|
const lst = lstatSync(fullPath);
|
|
9105
9381
|
if (lst.isSymbolicLink()) {
|
|
9106
9382
|
const linkTarget = readlinkSync(fullPath);
|
|
9107
|
-
const resolvedTarget = resolve(
|
|
9383
|
+
const resolvedTarget = resolve(dirname2(fullPath), linkTarget);
|
|
9108
9384
|
const rel2 = relative(realRoot, resolvedTarget);
|
|
9109
9385
|
if (rel2.startsWith("..") || process.platform !== "win32" && rel2.startsWith("/")) {
|
|
9110
9386
|
throw new Error(`extracted symlink ${fullPath} points outside staging root: ${linkTarget}`);
|
|
@@ -9134,8 +9410,8 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
9134
9410
|
log(`Downloading ONNX Runtime v${ORT_VERSION} for ${process.platform}/${process.arch}...`);
|
|
9135
9411
|
const tmpDir = `${targetDir}.tmp.${process.pid}.${Date.now().toString(36)}`;
|
|
9136
9412
|
try {
|
|
9137
|
-
|
|
9138
|
-
const archivePath =
|
|
9413
|
+
mkdirSync4(tmpDir, { recursive: true });
|
|
9414
|
+
const archivePath = join5(tmpDir, `onnxruntime.${info.archiveType}`);
|
|
9139
9415
|
await downloadFileWithCap(url, archivePath);
|
|
9140
9416
|
const archiveSha256 = sha256File(archivePath);
|
|
9141
9417
|
log(`ONNX Runtime archive sha256=${archiveSha256}`);
|
|
@@ -9151,16 +9427,16 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
9151
9427
|
unlinkSync2(archivePath);
|
|
9152
9428
|
} catch {}
|
|
9153
9429
|
validateExtractedTree(tmpDir);
|
|
9154
|
-
const extractedDir =
|
|
9155
|
-
if (!
|
|
9430
|
+
const extractedDir = join5(tmpDir, info.assetName, "lib");
|
|
9431
|
+
if (!existsSync4(extractedDir)) {
|
|
9156
9432
|
throw new Error(`Expected directory not found: ${extractedDir}`);
|
|
9157
9433
|
}
|
|
9158
|
-
|
|
9434
|
+
mkdirSync4(targetDir, { recursive: true });
|
|
9159
9435
|
const libFiles = readdirSync(extractedDir).filter((f) => f.startsWith("libonnxruntime") || f.startsWith("onnxruntime"));
|
|
9160
9436
|
const realFiles = [];
|
|
9161
9437
|
const symlinks = [];
|
|
9162
9438
|
for (const libFile of libFiles) {
|
|
9163
|
-
const src =
|
|
9439
|
+
const src = join5(extractedDir, libFile);
|
|
9164
9440
|
try {
|
|
9165
9441
|
const stat = lstatSync(src);
|
|
9166
9442
|
log(`ORT extract: ${libFile} \u2014 isSymlink=${stat.isSymbolicLink()}, isFile=${stat.isFile()}, size=${stat.size}`);
|
|
@@ -9175,7 +9451,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
9175
9451
|
}
|
|
9176
9452
|
}
|
|
9177
9453
|
copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks);
|
|
9178
|
-
const libPath =
|
|
9454
|
+
const libPath = join5(targetDir, info.libName);
|
|
9179
9455
|
let libHash = null;
|
|
9180
9456
|
try {
|
|
9181
9457
|
libHash = sha256File(libPath);
|
|
@@ -9197,15 +9473,15 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
9197
9473
|
return null;
|
|
9198
9474
|
}
|
|
9199
9475
|
}
|
|
9200
|
-
function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, copyFile =
|
|
9476
|
+
function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, copyFile = copyFileSync2) {
|
|
9201
9477
|
const requiredLibs = new Set([info.libName]);
|
|
9202
9478
|
for (const libFile of realFiles) {
|
|
9203
|
-
const src =
|
|
9204
|
-
const dst =
|
|
9479
|
+
const src = join5(extractedDir, libFile);
|
|
9480
|
+
const dst = join5(targetDir, libFile);
|
|
9205
9481
|
try {
|
|
9206
9482
|
copyFile(src, dst);
|
|
9207
9483
|
if (process.platform !== "win32") {
|
|
9208
|
-
|
|
9484
|
+
chmodSync3(dst, 493);
|
|
9209
9485
|
}
|
|
9210
9486
|
} catch (copyErr) {
|
|
9211
9487
|
if (requiredLibs.has(libFile)) {
|
|
@@ -9216,7 +9492,7 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
9216
9492
|
}
|
|
9217
9493
|
}
|
|
9218
9494
|
for (const link of symlinks) {
|
|
9219
|
-
const dst =
|
|
9495
|
+
const dst = join5(targetDir, link.name);
|
|
9220
9496
|
try {
|
|
9221
9497
|
unlinkSync2(dst);
|
|
9222
9498
|
} catch {}
|
|
@@ -9230,8 +9506,8 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
9230
9506
|
log(`ORT extract: failed to symlink optional ${link.name}: ${symlinkErr}`);
|
|
9231
9507
|
}
|
|
9232
9508
|
}
|
|
9233
|
-
const requiredPath =
|
|
9234
|
-
if (!
|
|
9509
|
+
const requiredPath = join5(targetDir, info.libName);
|
|
9510
|
+
if (!existsSync4(requiredPath)) {
|
|
9235
9511
|
rmSync2(targetDir, { recursive: true, force: true });
|
|
9236
9512
|
throw new Error(`Required ONNX Runtime library missing after install: ${requiredPath}`);
|
|
9237
9513
|
}
|
|
@@ -9257,13 +9533,13 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
|
|
|
9257
9533
|
...sha256 ? { sha256 } : {},
|
|
9258
9534
|
archiveSha256
|
|
9259
9535
|
};
|
|
9260
|
-
writeFileSync(
|
|
9536
|
+
writeFileSync(join5(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
|
|
9261
9537
|
} catch (err) {
|
|
9262
9538
|
log(`[onnx] failed to write installed-meta in ${installDir}: ${err}`);
|
|
9263
9539
|
}
|
|
9264
9540
|
}
|
|
9265
9541
|
function readOnnxInstalledMeta(installDir) {
|
|
9266
|
-
const path =
|
|
9542
|
+
const path = join5(installDir, ONNX_INSTALLED_META_FILE);
|
|
9267
9543
|
try {
|
|
9268
9544
|
if (!statSync2(path).isFile())
|
|
9269
9545
|
return null;
|
|
@@ -9388,6 +9664,7 @@ class BridgePool {
|
|
|
9388
9664
|
idleTimeoutMs;
|
|
9389
9665
|
bridgeOptions;
|
|
9390
9666
|
configOverrides;
|
|
9667
|
+
projectConfigLoader;
|
|
9391
9668
|
logger;
|
|
9392
9669
|
cleanupTimer = null;
|
|
9393
9670
|
constructor(binaryPath, options = {}, configOverrides = {}) {
|
|
@@ -9395,6 +9672,7 @@ class BridgePool {
|
|
|
9395
9672
|
this.maxPoolSize = options.maxPoolSize ?? DEFAULT_MAX_POOL_SIZE;
|
|
9396
9673
|
this.idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
|
|
9397
9674
|
this.logger = options.logger;
|
|
9675
|
+
this.projectConfigLoader = options.projectConfigLoader;
|
|
9398
9676
|
this.bridgeOptions = {
|
|
9399
9677
|
timeoutMs: options.timeoutMs,
|
|
9400
9678
|
maxRestarts: options.maxRestarts,
|
|
@@ -9430,7 +9708,17 @@ class BridgePool {
|
|
|
9430
9708
|
if (this.bridges.size >= this.maxPoolSize) {
|
|
9431
9709
|
this.evictLRU();
|
|
9432
9710
|
}
|
|
9433
|
-
|
|
9711
|
+
let projectOverrides = {};
|
|
9712
|
+
if (this.projectConfigLoader) {
|
|
9713
|
+
try {
|
|
9714
|
+
projectOverrides = this.projectConfigLoader(key) ?? {};
|
|
9715
|
+
} catch (err) {
|
|
9716
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
9717
|
+
this.error(`projectConfigLoader failed; using global overrides only: ${message}`);
|
|
9718
|
+
}
|
|
9719
|
+
}
|
|
9720
|
+
const mergedOverrides = { ...this.configOverrides, ...projectOverrides };
|
|
9721
|
+
const bridge = new BinaryBridge(this.binaryPath, key, this.bridgeOptions, mergedOverrides);
|
|
9434
9722
|
this.bridges.set(key, { bridge, lastUsed: Date.now() });
|
|
9435
9723
|
return bridge;
|
|
9436
9724
|
}
|
|
@@ -9523,196 +9811,28 @@ function normalizeKey(projectRoot) {
|
|
|
9523
9811
|
return stripped;
|
|
9524
9812
|
}
|
|
9525
9813
|
}
|
|
9526
|
-
// ../aft-bridge/dist/resolver.js
|
|
9527
|
-
import { execSync, spawnSync } from "child_process";
|
|
9528
|
-
import { chmodSync as chmodSync3, copyFileSync as copyFileSync2, existsSync as existsSync3, mkdirSync as mkdirSync3, renameSync as renameSync2 } from "fs";
|
|
9529
|
-
import { createRequire } from "module";
|
|
9530
|
-
import { homedir as homedir3 } from "os";
|
|
9531
|
-
import { join as join4 } from "path";
|
|
9532
|
-
function readBinaryVersion(binaryPath) {
|
|
9533
|
-
try {
|
|
9534
|
-
const result = spawnSync(binaryPath, ["--version"], {
|
|
9535
|
-
encoding: "utf-8",
|
|
9536
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
9537
|
-
timeout: 5000
|
|
9538
|
-
});
|
|
9539
|
-
const stdoutVersion = result.stdout?.trim();
|
|
9540
|
-
const stderrVersion = result.stderr?.trim();
|
|
9541
|
-
const rawVersion = stdoutVersion || stderrVersion;
|
|
9542
|
-
if (!rawVersion)
|
|
9543
|
-
return null;
|
|
9544
|
-
return rawVersion.replace(/^aft\s+/, "");
|
|
9545
|
-
} catch {
|
|
9546
|
-
return null;
|
|
9547
|
-
}
|
|
9548
|
-
}
|
|
9549
|
-
function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
9550
|
-
try {
|
|
9551
|
-
const version = knownVersion ?? readBinaryVersion(npmBinaryPath);
|
|
9552
|
-
if (!version)
|
|
9553
|
-
return null;
|
|
9554
|
-
const tag = version.startsWith("v") ? version : `v${version}`;
|
|
9555
|
-
const cacheDir = getCacheDir();
|
|
9556
|
-
const versionedDir = join4(cacheDir, tag);
|
|
9557
|
-
const ext = process.platform === "win32" ? ".exe" : "";
|
|
9558
|
-
const cachedPath = join4(versionedDir, `aft${ext}`);
|
|
9559
|
-
if (existsSync3(cachedPath)) {
|
|
9560
|
-
const cachedVersion = readBinaryVersion(cachedPath);
|
|
9561
|
-
if (cachedVersion === version)
|
|
9562
|
-
return cachedPath;
|
|
9563
|
-
warn(`Cached binary at ${cachedPath} reports ${cachedVersion ?? "no version"}, expected ${version}; refreshing from npm package`);
|
|
9564
|
-
}
|
|
9565
|
-
mkdirSync3(versionedDir, { recursive: true });
|
|
9566
|
-
const tmpPath = `${cachedPath}.${process.pid}.${Date.now()}.tmp`;
|
|
9567
|
-
copyFileSync2(npmBinaryPath, tmpPath);
|
|
9568
|
-
if (process.platform !== "win32") {
|
|
9569
|
-
chmodSync3(tmpPath, 493);
|
|
9570
|
-
}
|
|
9571
|
-
renameSync2(tmpPath, cachedPath);
|
|
9572
|
-
log(`Copied npm binary to versioned cache: ${cachedPath}`);
|
|
9573
|
-
return cachedPath;
|
|
9574
|
-
} catch (err) {
|
|
9575
|
-
warn(`Failed to copy binary to cache: ${err instanceof Error ? err.message : String(err)}`);
|
|
9576
|
-
return null;
|
|
9577
|
-
}
|
|
9578
|
-
}
|
|
9579
|
-
function normalizeBareVersion(version) {
|
|
9580
|
-
return version.startsWith("v") ? version.slice(1) : version;
|
|
9581
|
-
}
|
|
9582
|
-
function homeDirFromEnv(env) {
|
|
9583
|
-
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir3();
|
|
9584
|
-
}
|
|
9585
|
-
function cacheDirFromEnv(env) {
|
|
9586
|
-
if (process.platform === "win32") {
|
|
9587
|
-
const base2 = env.LOCALAPPDATA || env.APPDATA || join4(homeDirFromEnv(env), "AppData", "Local");
|
|
9588
|
-
return join4(base2, "aft", "bin");
|
|
9589
|
-
}
|
|
9590
|
-
const base = env.XDG_CACHE_HOME || join4(homeDirFromEnv(env), ".cache");
|
|
9591
|
-
return join4(base, "aft", "bin");
|
|
9592
|
-
}
|
|
9593
|
-
function cachedBinaryPathFromEnv(version, env, ext) {
|
|
9594
|
-
const binaryPath = join4(cacheDirFromEnv(env), version, `aft${ext}`);
|
|
9595
|
-
return existsSync3(binaryPath) ? binaryPath : null;
|
|
9596
|
-
}
|
|
9597
|
-
function isExpectedCachedBinary(binaryPath, expectedVersion) {
|
|
9598
|
-
const expected = normalizeBareVersion(expectedVersion);
|
|
9599
|
-
const actual = readBinaryVersion(binaryPath);
|
|
9600
|
-
if (actual === expected)
|
|
9601
|
-
return true;
|
|
9602
|
-
warn(`Cached binary at ${binaryPath} reports ${actual ?? "no version"}, expected ${expected}; skipping cache candidate`);
|
|
9603
|
-
return false;
|
|
9604
|
-
}
|
|
9605
|
-
function platformKey(platform = process.platform, arch = process.arch) {
|
|
9606
|
-
const archMap = PLATFORM_ARCH_MAP[platform];
|
|
9607
|
-
if (!archMap) {
|
|
9608
|
-
throw new Error(`Unsupported platform: ${platform} (arch: ${arch}). ` + `Supported platforms: ${Object.keys(PLATFORM_ARCH_MAP).join(", ")}`);
|
|
9609
|
-
}
|
|
9610
|
-
const key = archMap[arch];
|
|
9611
|
-
if (!key) {
|
|
9612
|
-
throw new Error(`Unsupported architecture: ${arch} on platform ${platform}. ` + `Supported architectures for ${platform}: ${Object.keys(archMap).join(", ")}`);
|
|
9613
|
-
}
|
|
9614
|
-
return key;
|
|
9615
|
-
}
|
|
9616
|
-
function findBinarySync(expectedVersion) {
|
|
9617
|
-
const ext = process.platform === "win32" ? ".exe" : "";
|
|
9618
|
-
const env = { ...process.env };
|
|
9619
|
-
const pluginVersion = expectedVersion ?? (() => {
|
|
9620
|
-
try {
|
|
9621
|
-
const req = createRequire(import.meta.url);
|
|
9622
|
-
return req("../package.json").version;
|
|
9623
|
-
} catch {
|
|
9624
|
-
return null;
|
|
9625
|
-
}
|
|
9626
|
-
})();
|
|
9627
|
-
if (pluginVersion) {
|
|
9628
|
-
const tag = pluginVersion.startsWith("v") ? pluginVersion : `v${pluginVersion}`;
|
|
9629
|
-
const versionCached = cachedBinaryPathFromEnv(tag, env, ext);
|
|
9630
|
-
if (versionCached && isExpectedCachedBinary(versionCached, pluginVersion))
|
|
9631
|
-
return versionCached;
|
|
9632
|
-
}
|
|
9633
|
-
try {
|
|
9634
|
-
const key = platformKey();
|
|
9635
|
-
const packageBin = `@cortexkit/aft-${key}/bin/aft${ext}`;
|
|
9636
|
-
const req = createRequire(import.meta.url);
|
|
9637
|
-
const resolved = req.resolve(packageBin);
|
|
9638
|
-
if (existsSync3(resolved)) {
|
|
9639
|
-
const npmVersion = readBinaryVersion(resolved);
|
|
9640
|
-
if (npmVersion === null) {
|
|
9641
|
-
warn(`npm platform package binary at ${resolved} did not report a version; skipping (continuing to PATH lookup)`);
|
|
9642
|
-
} else if (pluginVersion && npmVersion !== normalizeBareVersion(pluginVersion)) {
|
|
9643
|
-
warn(`npm platform package binary v${npmVersion} does not match plugin v${pluginVersion}; skipping (continuing to PATH lookup)`);
|
|
9644
|
-
} else {
|
|
9645
|
-
const copied = copyToVersionedCache(resolved, npmVersion);
|
|
9646
|
-
return copied ?? resolved;
|
|
9647
|
-
}
|
|
9648
|
-
}
|
|
9649
|
-
} catch {}
|
|
9650
|
-
try {
|
|
9651
|
-
const whichCmd = process.platform === "win32" ? "where aft" : "which aft";
|
|
9652
|
-
const result = execSync(whichCmd, {
|
|
9653
|
-
encoding: "utf-8",
|
|
9654
|
-
env,
|
|
9655
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
9656
|
-
}).trim();
|
|
9657
|
-
if (result)
|
|
9658
|
-
return result;
|
|
9659
|
-
} catch {}
|
|
9660
|
-
const cargoPath = join4(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
|
|
9661
|
-
if (existsSync3(cargoPath))
|
|
9662
|
-
return cargoPath;
|
|
9663
|
-
return null;
|
|
9664
|
-
}
|
|
9665
|
-
async function findBinary(expectedVersion) {
|
|
9666
|
-
const syncResult = findBinarySync(expectedVersion);
|
|
9667
|
-
if (syncResult) {
|
|
9668
|
-
log(`Resolved binary: ${syncResult}`);
|
|
9669
|
-
return syncResult;
|
|
9670
|
-
}
|
|
9671
|
-
log("Binary not found locally, attempting auto-download...");
|
|
9672
|
-
const downloaded = await ensureBinary(expectedVersion);
|
|
9673
|
-
if (downloaded)
|
|
9674
|
-
return downloaded;
|
|
9675
|
-
throw new Error([
|
|
9676
|
-
"Could not find the `aft` binary.",
|
|
9677
|
-
"",
|
|
9678
|
-
"Attempted sources:",
|
|
9679
|
-
" - Cache directory (~/.cache/aft/bin/)",
|
|
9680
|
-
" - npm platform package (@cortexkit/aft-<platform>)",
|
|
9681
|
-
" - PATH lookup (which aft)",
|
|
9682
|
-
" - ~/.cargo/bin/aft",
|
|
9683
|
-
" - Auto-download from GitHub releases (failed)",
|
|
9684
|
-
"",
|
|
9685
|
-
"Install it using one of these methods:",
|
|
9686
|
-
" npm install @cortexkit/aft-opencode # installs platform-specific binary via npm",
|
|
9687
|
-
" cargo install agent-file-tools # from crates.io",
|
|
9688
|
-
" cargo build --release # from source (binary at target/release/aft)",
|
|
9689
|
-
"",
|
|
9690
|
-
"Or add the aft directory to your PATH."
|
|
9691
|
-
].join(`
|
|
9692
|
-
`));
|
|
9693
|
-
}
|
|
9694
9814
|
// ../aft-bridge/dist/url-fetch.js
|
|
9695
9815
|
import { createHash as createHash3 } from "crypto";
|
|
9696
9816
|
import { lookup } from "dns/promises";
|
|
9697
|
-
import { existsSync as
|
|
9817
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync5, readdirSync as readdirSync2, readFileSync as readFileSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
9698
9818
|
import { isIP } from "net";
|
|
9699
|
-
import { join as
|
|
9819
|
+
import { join as join6 } from "path";
|
|
9700
9820
|
import { Agent, fetch as undiciFetch } from "undici";
|
|
9701
9821
|
var MAX_RESPONSE_BYTES = 10 * 1024 * 1024;
|
|
9702
9822
|
var CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
9703
9823
|
var FETCH_TIMEOUT_MS = 30000;
|
|
9704
9824
|
var MAX_REDIRECTS = 5;
|
|
9705
9825
|
function cacheDir(storageDir) {
|
|
9706
|
-
return
|
|
9826
|
+
return join6(storageDir, "url_cache");
|
|
9707
9827
|
}
|
|
9708
9828
|
function hashUrl(url) {
|
|
9709
9829
|
return createHash3("sha256").update(url).digest("hex").slice(0, 16);
|
|
9710
9830
|
}
|
|
9711
9831
|
function metaPath(storageDir, hash) {
|
|
9712
|
-
return
|
|
9832
|
+
return join6(cacheDir(storageDir), `${hash}.meta.json`);
|
|
9713
9833
|
}
|
|
9714
9834
|
function contentPath(storageDir, hash, extension) {
|
|
9715
|
-
return
|
|
9835
|
+
return join6(cacheDir(storageDir), `${hash}${extension}`);
|
|
9716
9836
|
}
|
|
9717
9837
|
function _isPrivateIpv4(address) {
|
|
9718
9838
|
const parts = address.split(".").map((part) => Number.parseInt(part, 10));
|
|
@@ -9730,9 +9850,9 @@ function expandIpv6(addr) {
|
|
|
9730
9850
|
let normalized = addr;
|
|
9731
9851
|
const lastColon = normalized.lastIndexOf(":");
|
|
9732
9852
|
if (lastColon !== -1) {
|
|
9733
|
-
const
|
|
9734
|
-
if (
|
|
9735
|
-
const octets =
|
|
9853
|
+
const tail2 = normalized.slice(lastColon + 1);
|
|
9854
|
+
if (tail2.includes(".")) {
|
|
9855
|
+
const octets = tail2.split(".").map((p) => Number.parseInt(p, 10));
|
|
9736
9856
|
if (octets.length !== 4 || octets.some((o) => Number.isNaN(o) || o < 0 || o > 255)) {
|
|
9737
9857
|
return null;
|
|
9738
9858
|
}
|
|
@@ -9910,15 +10030,15 @@ async function fetchUrlToTempFile(url, storageDir, options = {}) {
|
|
|
9910
10030
|
const allowPrivate = options.allowPrivate === true;
|
|
9911
10031
|
await assertPublicUrl(parsed, allowPrivate, options.lookup);
|
|
9912
10032
|
const dir = cacheDir(storageDir);
|
|
9913
|
-
|
|
10033
|
+
mkdirSync5(dir, { recursive: true });
|
|
9914
10034
|
const hash = hashUrl(url);
|
|
9915
10035
|
const metaFile = metaPath(storageDir, hash);
|
|
9916
|
-
if (
|
|
10036
|
+
if (existsSync5(metaFile)) {
|
|
9917
10037
|
try {
|
|
9918
10038
|
const meta2 = JSON.parse(readFileSync2(metaFile, "utf8"));
|
|
9919
10039
|
const age = Date.now() - meta2.fetchedAt;
|
|
9920
10040
|
const cached = contentPath(storageDir, hash, meta2.extension);
|
|
9921
|
-
if (age < CACHE_TTL_MS &&
|
|
10041
|
+
if (age < CACHE_TTL_MS && existsSync5(cached)) {
|
|
9922
10042
|
log(`URL cache hit: ${url} (${Math.round(age / 1000)}s old)`);
|
|
9923
10043
|
return cached;
|
|
9924
10044
|
}
|
|
@@ -9980,21 +10100,21 @@ async function fetchUrlToTempFile(url, storageDir, options = {}) {
|
|
|
9980
10100
|
}
|
|
9981
10101
|
function cleanupUrlCache(storageDir) {
|
|
9982
10102
|
const dir = cacheDir(storageDir);
|
|
9983
|
-
if (!
|
|
10103
|
+
if (!existsSync5(dir))
|
|
9984
10104
|
return;
|
|
9985
10105
|
let removed = 0;
|
|
9986
10106
|
try {
|
|
9987
10107
|
for (const entry of readdirSync2(dir)) {
|
|
9988
10108
|
if (!entry.endsWith(".meta.json"))
|
|
9989
10109
|
continue;
|
|
9990
|
-
const metaFile =
|
|
10110
|
+
const metaFile = join6(dir, entry);
|
|
9991
10111
|
try {
|
|
9992
10112
|
const meta = JSON.parse(readFileSync2(metaFile, "utf8"));
|
|
9993
10113
|
const age = Date.now() - meta.fetchedAt;
|
|
9994
10114
|
if (age > CACHE_TTL_MS) {
|
|
9995
10115
|
const hash = entry.slice(0, -".meta.json".length);
|
|
9996
10116
|
const content = contentPath(storageDir, hash, meta.extension);
|
|
9997
|
-
if (
|
|
10117
|
+
if (existsSync5(content))
|
|
9998
10118
|
unlinkSync3(content);
|
|
9999
10119
|
unlinkSync3(metaFile);
|
|
10000
10120
|
removed++;
|
|
@@ -10366,12 +10486,12 @@ function formatSystemReminder(completions) {
|
|
|
10366
10486
|
const bullets = completions.map((completion) => formatCompletion(completion)).join(`
|
|
10367
10487
|
`);
|
|
10368
10488
|
const anyTruncated = completions.some((c) => c.output_truncated === true);
|
|
10369
|
-
const
|
|
10489
|
+
const tail2 = anyTruncated ? `
|
|
10370
10490
|
|
|
10371
10491
|
For truncated tasks, use bash_status({ taskId: "..." }) to retrieve full output.` : "";
|
|
10372
10492
|
return `<system-reminder>
|
|
10373
10493
|
[BACKGROUND BASH COMPLETED]
|
|
10374
|
-
${bullets}${
|
|
10494
|
+
${bullets}${tail2}
|
|
10375
10495
|
</system-reminder>`;
|
|
10376
10496
|
}
|
|
10377
10497
|
function formatLongRunningReminder(reminders) {
|
|
@@ -10626,9 +10746,9 @@ function formatDuration(completion) {
|
|
|
10626
10746
|
|
|
10627
10747
|
// src/config.ts
|
|
10628
10748
|
var import_comment_json = __toESM(require_src2(), 1);
|
|
10629
|
-
import { existsSync as
|
|
10630
|
-
import { homedir as
|
|
10631
|
-
import { join as
|
|
10749
|
+
import { existsSync as existsSync6, readFileSync as readFileSync3, renameSync as renameSync3, unlinkSync as unlinkSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
10750
|
+
import { homedir as homedir5 } from "os";
|
|
10751
|
+
import { join as join8 } from "path";
|
|
10632
10752
|
|
|
10633
10753
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
|
|
10634
10754
|
var exports_external = {};
|
|
@@ -24227,6 +24347,7 @@ var ExperimentalConfigSchema = exports_external.object({
|
|
|
24227
24347
|
lsp_ty: exports_external.boolean().optional()
|
|
24228
24348
|
});
|
|
24229
24349
|
var AftConfigSchema = exports_external.object({
|
|
24350
|
+
$schema: exports_external.string().optional(),
|
|
24230
24351
|
format_on_edit: exports_external.boolean().optional(),
|
|
24231
24352
|
formatter_timeout_secs: exports_external.number().int().min(1).max(600).optional(),
|
|
24232
24353
|
validate_on_edit: exports_external.enum(["syntax", "full"]).optional(),
|
|
@@ -24292,6 +24413,31 @@ function resolveLspConfigForConfigure(config2) {
|
|
|
24292
24413
|
}
|
|
24293
24414
|
return overrides;
|
|
24294
24415
|
}
|
|
24416
|
+
function resolveProjectOverridesForConfigure(config2) {
|
|
24417
|
+
const overrides = {};
|
|
24418
|
+
if (config2.format_on_edit !== undefined)
|
|
24419
|
+
overrides.format_on_edit = config2.format_on_edit;
|
|
24420
|
+
if (config2.formatter_timeout_secs !== undefined)
|
|
24421
|
+
overrides.formatter_timeout_secs = config2.formatter_timeout_secs;
|
|
24422
|
+
if (config2.validate_on_edit !== undefined)
|
|
24423
|
+
overrides.validate_on_edit = config2.validate_on_edit;
|
|
24424
|
+
if (config2.formatter !== undefined)
|
|
24425
|
+
overrides.formatter = config2.formatter;
|
|
24426
|
+
if (config2.checker !== undefined)
|
|
24427
|
+
overrides.checker = config2.checker;
|
|
24428
|
+
overrides.restrict_to_project_root = config2.restrict_to_project_root ?? false;
|
|
24429
|
+
if (config2.search_index !== undefined)
|
|
24430
|
+
overrides.search_index = config2.search_index;
|
|
24431
|
+
if (config2.semantic_search !== undefined)
|
|
24432
|
+
overrides.semantic_search = config2.semantic_search;
|
|
24433
|
+
Object.assign(overrides, resolveExperimentalConfigForConfigure(config2));
|
|
24434
|
+
Object.assign(overrides, resolveLspConfigForConfigure(config2));
|
|
24435
|
+
if (config2.semantic !== undefined)
|
|
24436
|
+
overrides.semantic = config2.semantic;
|
|
24437
|
+
if (config2.max_callgraph_files !== undefined)
|
|
24438
|
+
overrides.max_callgraph_files = config2.max_callgraph_files;
|
|
24439
|
+
return overrides;
|
|
24440
|
+
}
|
|
24295
24441
|
function resolveExperimentalConfigForConfigure(config2) {
|
|
24296
24442
|
const overrides = {};
|
|
24297
24443
|
if (config2.experimental?.bash?.rewrite !== undefined) {
|
|
@@ -24381,7 +24527,7 @@ function migrateRawConfig(rawConfig, configPath, logger) {
|
|
|
24381
24527
|
return oldKeys;
|
|
24382
24528
|
}
|
|
24383
24529
|
function migrateAftConfigFile(configPath, logger = { log: log2, warn: warn2 }) {
|
|
24384
|
-
if (!
|
|
24530
|
+
if (!existsSync6(configPath)) {
|
|
24385
24531
|
return { migrated: false, oldKeys: [] };
|
|
24386
24532
|
}
|
|
24387
24533
|
let tmpPath = null;
|
|
@@ -24425,10 +24571,10 @@ ${serialized}` : serialized;
|
|
|
24425
24571
|
function detectConfigFile(basePath) {
|
|
24426
24572
|
const jsoncPath = `${basePath}.jsonc`;
|
|
24427
24573
|
const jsonPath = `${basePath}.json`;
|
|
24428
|
-
if (
|
|
24574
|
+
if (existsSync6(jsoncPath)) {
|
|
24429
24575
|
return { format: "jsonc", path: jsoncPath };
|
|
24430
24576
|
}
|
|
24431
|
-
if (
|
|
24577
|
+
if (existsSync6(jsonPath)) {
|
|
24432
24578
|
return { format: "json", path: jsonPath };
|
|
24433
24579
|
}
|
|
24434
24580
|
return { format: "none", path: jsonPath };
|
|
@@ -24461,7 +24607,7 @@ function parseConfigPartially(rawConfig) {
|
|
|
24461
24607
|
}
|
|
24462
24608
|
function loadConfigFromPath(configPath) {
|
|
24463
24609
|
try {
|
|
24464
|
-
if (!
|
|
24610
|
+
if (!existsSync6(configPath)) {
|
|
24465
24611
|
return null;
|
|
24466
24612
|
}
|
|
24467
24613
|
const content = readFileSync3(configPath, "utf-8");
|
|
@@ -24605,17 +24751,17 @@ function getOpenCodeConfigDir() {
|
|
|
24605
24751
|
if (envDir) {
|
|
24606
24752
|
return envDir;
|
|
24607
24753
|
}
|
|
24608
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME ||
|
|
24609
|
-
return
|
|
24754
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME || join8(homedir5(), ".config");
|
|
24755
|
+
return join8(xdgConfig, "opencode");
|
|
24610
24756
|
}
|
|
24611
24757
|
function loadAftConfig(projectDirectory) {
|
|
24612
24758
|
const configDir = getOpenCodeConfigDir();
|
|
24613
|
-
const userBasePath =
|
|
24759
|
+
const userBasePath = join8(configDir, "aft");
|
|
24614
24760
|
migrateAftConfigFile(`${userBasePath}.jsonc`);
|
|
24615
24761
|
migrateAftConfigFile(`${userBasePath}.json`);
|
|
24616
24762
|
const userDetected = detectConfigFile(userBasePath);
|
|
24617
24763
|
const userConfigPath = userDetected.format !== "none" ? userDetected.path : `${userBasePath}.json`;
|
|
24618
|
-
const projectBasePath =
|
|
24764
|
+
const projectBasePath = join8(projectDirectory, ".opencode", "aft");
|
|
24619
24765
|
migrateAftConfigFile(`${projectBasePath}.jsonc`);
|
|
24620
24766
|
migrateAftConfigFile(`${projectBasePath}.json`);
|
|
24621
24767
|
const projectDetected = detectConfigFile(projectBasePath);
|
|
@@ -24640,44 +24786,44 @@ function loadAftConfig(projectDirectory) {
|
|
|
24640
24786
|
}
|
|
24641
24787
|
|
|
24642
24788
|
// src/hooks/auto-update-checker/index.ts
|
|
24643
|
-
import { existsSync as
|
|
24644
|
-
import { dirname as
|
|
24789
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync6, renameSync as renameSync4, writeFileSync as writeFileSync6 } from "fs";
|
|
24790
|
+
import { dirname as dirname5, join as join12 } from "path";
|
|
24645
24791
|
|
|
24646
24792
|
// src/hooks/auto-update-checker/cache.ts
|
|
24647
24793
|
var import_comment_json3 = __toESM(require_src2(), 1);
|
|
24648
24794
|
import { spawn as spawn2 } from "child_process";
|
|
24649
|
-
import { cpSync, existsSync as
|
|
24650
|
-
import { tmpdir as
|
|
24651
|
-
import { basename, dirname as
|
|
24795
|
+
import { cpSync, existsSync as existsSync8, mkdtempSync, readFileSync as readFileSync5, rmSync as rmSync3, writeFileSync as writeFileSync5 } from "fs";
|
|
24796
|
+
import { tmpdir as tmpdir3 } from "os";
|
|
24797
|
+
import { basename, dirname as dirname4, join as join11 } from "path";
|
|
24652
24798
|
|
|
24653
24799
|
// src/hooks/auto-update-checker/checker.ts
|
|
24654
24800
|
var import_comment_json2 = __toESM(require_src2(), 1);
|
|
24655
|
-
import { existsSync as
|
|
24656
|
-
import { homedir as
|
|
24657
|
-
import { dirname as
|
|
24801
|
+
import { existsSync as existsSync7, readFileSync as readFileSync4, statSync as statSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
24802
|
+
import { homedir as homedir7 } from "os";
|
|
24803
|
+
import { dirname as dirname3, isAbsolute, join as join10, resolve as resolve2 } from "path";
|
|
24658
24804
|
import { fileURLToPath } from "url";
|
|
24659
24805
|
|
|
24660
24806
|
// src/hooks/auto-update-checker/constants.ts
|
|
24661
|
-
import { homedir as
|
|
24662
|
-
import { join as
|
|
24807
|
+
import { homedir as homedir6, platform } from "os";
|
|
24808
|
+
import { join as join9 } from "path";
|
|
24663
24809
|
var PACKAGE_NAME = "@cortexkit/aft-opencode";
|
|
24664
24810
|
var NPM_REGISTRY_URL = "https://registry.npmjs.org";
|
|
24665
24811
|
var NPM_FETCH_TIMEOUT = 1e4;
|
|
24666
24812
|
function getOpenCodeCacheRoot() {
|
|
24667
24813
|
if (platform() === "win32") {
|
|
24668
|
-
return
|
|
24814
|
+
return join9(process.env.LOCALAPPDATA ?? homedir6(), "opencode");
|
|
24669
24815
|
}
|
|
24670
|
-
return
|
|
24816
|
+
return join9(homedir6(), ".cache", "opencode");
|
|
24671
24817
|
}
|
|
24672
24818
|
function getOpenCodeConfigRoot() {
|
|
24673
24819
|
if (platform() === "win32") {
|
|
24674
|
-
return
|
|
24820
|
+
return join9(process.env.APPDATA ?? join9(homedir6(), "AppData", "Roaming"), "opencode");
|
|
24675
24821
|
}
|
|
24676
|
-
return
|
|
24822
|
+
return join9(process.env.XDG_CONFIG_HOME ?? join9(homedir6(), ".config"), "opencode");
|
|
24677
24823
|
}
|
|
24678
|
-
var CACHE_DIR =
|
|
24679
|
-
var USER_OPENCODE_CONFIG =
|
|
24680
|
-
var USER_OPENCODE_CONFIG_JSONC =
|
|
24824
|
+
var CACHE_DIR = join9(getOpenCodeCacheRoot(), "packages");
|
|
24825
|
+
var USER_OPENCODE_CONFIG = join9(getOpenCodeConfigRoot(), "opencode.json");
|
|
24826
|
+
var USER_OPENCODE_CONFIG_JSONC = join9(getOpenCodeConfigRoot(), "opencode.jsonc");
|
|
24681
24827
|
|
|
24682
24828
|
// src/hooks/auto-update-checker/types.ts
|
|
24683
24829
|
var NpmPackageEnvelopeSchema = exports_external.object({
|
|
@@ -24735,8 +24881,8 @@ function extractChannel(version2) {
|
|
|
24735
24881
|
}
|
|
24736
24882
|
function getConfigPaths(directory) {
|
|
24737
24883
|
return [
|
|
24738
|
-
|
|
24739
|
-
|
|
24884
|
+
join10(directory, ".opencode", "opencode.json"),
|
|
24885
|
+
join10(directory, ".opencode", "opencode.jsonc"),
|
|
24740
24886
|
USER_OPENCODE_CONFIG,
|
|
24741
24887
|
USER_OPENCODE_CONFIG_JSONC
|
|
24742
24888
|
];
|
|
@@ -24751,12 +24897,12 @@ function resolvePathPluginSpec(spec, configPath) {
|
|
|
24751
24897
|
}
|
|
24752
24898
|
if (isAbsolute(spec) || /^[A-Za-z]:[\\/]/.test(spec))
|
|
24753
24899
|
return spec;
|
|
24754
|
-
return resolve2(
|
|
24900
|
+
return resolve2(dirname3(configPath), spec);
|
|
24755
24901
|
}
|
|
24756
24902
|
function getLocalDevPath(directory) {
|
|
24757
24903
|
for (const configPath of getConfigPaths(directory)) {
|
|
24758
24904
|
try {
|
|
24759
|
-
if (!
|
|
24905
|
+
if (!existsSync7(configPath))
|
|
24760
24906
|
continue;
|
|
24761
24907
|
const rawConfig = parseJsonConfig(readFileSync4(configPath, "utf-8"));
|
|
24762
24908
|
const plugins = getPluginEntries(rawConfig);
|
|
@@ -24780,17 +24926,17 @@ function getLocalDevPath(directory) {
|
|
|
24780
24926
|
function findPackageJsonUp(startPath) {
|
|
24781
24927
|
try {
|
|
24782
24928
|
const stat = statSync3(startPath);
|
|
24783
|
-
let dir = stat.isDirectory() ? startPath :
|
|
24929
|
+
let dir = stat.isDirectory() ? startPath : dirname3(startPath);
|
|
24784
24930
|
for (let i = 0;i < 10; i++) {
|
|
24785
|
-
const pkgPath =
|
|
24786
|
-
if (
|
|
24931
|
+
const pkgPath = join10(dir, "package.json");
|
|
24932
|
+
if (existsSync7(pkgPath)) {
|
|
24787
24933
|
try {
|
|
24788
24934
|
const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync4(pkgPath, "utf-8")));
|
|
24789
24935
|
if (pkg.success && pkg.data.name === PACKAGE_NAME)
|
|
24790
24936
|
return pkgPath;
|
|
24791
24937
|
} catch {}
|
|
24792
24938
|
}
|
|
24793
|
-
const parent =
|
|
24939
|
+
const parent = dirname3(dir);
|
|
24794
24940
|
if (parent === dir)
|
|
24795
24941
|
break;
|
|
24796
24942
|
dir = parent;
|
|
@@ -24814,7 +24960,7 @@ function getLocalDevVersion(directory) {
|
|
|
24814
24960
|
}
|
|
24815
24961
|
function getCurrentRuntimePackageJsonPath(currentModuleUrl = import.meta.url) {
|
|
24816
24962
|
try {
|
|
24817
|
-
return findPackageJsonUp(
|
|
24963
|
+
return findPackageJsonUp(dirname3(fileURLToPath(currentModuleUrl)));
|
|
24818
24964
|
} catch (err) {
|
|
24819
24965
|
warn2(`[auto-update-checker] Failed to resolve runtime package path: ${String(err)}`);
|
|
24820
24966
|
return null;
|
|
@@ -24823,7 +24969,7 @@ function getCurrentRuntimePackageJsonPath(currentModuleUrl = import.meta.url) {
|
|
|
24823
24969
|
function findPluginEntry(directory) {
|
|
24824
24970
|
for (const configPath of getConfigPaths(directory)) {
|
|
24825
24971
|
try {
|
|
24826
|
-
if (!
|
|
24972
|
+
if (!existsSync7(configPath))
|
|
24827
24973
|
continue;
|
|
24828
24974
|
const rawConfig = parseJsonConfig(readFileSync4(configPath, "utf-8"));
|
|
24829
24975
|
const plugins = getPluginEntries(rawConfig);
|
|
@@ -24843,7 +24989,7 @@ function findPluginEntry(directory) {
|
|
|
24843
24989
|
}
|
|
24844
24990
|
var cachedPackageVersion = null;
|
|
24845
24991
|
function getSpecCachePackageJsonPath(spec) {
|
|
24846
|
-
return
|
|
24992
|
+
return join10(CACHE_DIR, spec, "node_modules", PACKAGE_NAME, "package.json");
|
|
24847
24993
|
}
|
|
24848
24994
|
function getCachedVersion(spec) {
|
|
24849
24995
|
if (!spec && cachedPackageVersion)
|
|
@@ -24852,11 +24998,11 @@ function getCachedVersion(spec) {
|
|
|
24852
24998
|
getCurrentRuntimePackageJsonPath(),
|
|
24853
24999
|
spec ? getSpecCachePackageJsonPath(spec) : null,
|
|
24854
25000
|
getSpecCachePackageJsonPath(`${PACKAGE_NAME}@latest`),
|
|
24855
|
-
|
|
25001
|
+
join10(homedir7(), ".cache", "opencode", "node_modules", PACKAGE_NAME, "package.json")
|
|
24856
25002
|
].filter(isString);
|
|
24857
25003
|
for (const packageJsonPath of candidates) {
|
|
24858
25004
|
try {
|
|
24859
|
-
if (!
|
|
25005
|
+
if (!existsSync7(packageJsonPath))
|
|
24860
25006
|
continue;
|
|
24861
25007
|
const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync4(packageJsonPath, "utf-8")));
|
|
24862
25008
|
if (pkg.success && pkg.data.version) {
|
|
@@ -24900,17 +25046,17 @@ async function getLatestVersion(channel = "latest", options = {}) {
|
|
|
24900
25046
|
// src/hooks/auto-update-checker/cache.ts
|
|
24901
25047
|
var pendingSnapshots = new Map;
|
|
24902
25048
|
function createAutoUpdateSnapshot(installDir, packageJsonPath, packageName) {
|
|
24903
|
-
const packageDir =
|
|
24904
|
-
const lockfilePath =
|
|
24905
|
-
const tempDir = mkdtempSync(
|
|
24906
|
-
const stagedPackageDir =
|
|
25049
|
+
const packageDir = join11(installDir, "node_modules", packageName);
|
|
25050
|
+
const lockfilePath = join11(installDir, "package-lock.json");
|
|
25051
|
+
const tempDir = mkdtempSync(join11(tmpdir3(), "aft-auto-update-"));
|
|
25052
|
+
const stagedPackageDir = existsSync8(packageDir) ? join11(tempDir, "package") : null;
|
|
24907
25053
|
if (stagedPackageDir)
|
|
24908
25054
|
cpSync(packageDir, stagedPackageDir, { recursive: true });
|
|
24909
25055
|
return {
|
|
24910
25056
|
packageJsonPath,
|
|
24911
|
-
packageJson:
|
|
25057
|
+
packageJson: existsSync8(packageJsonPath) ? readFileSync5(packageJsonPath, "utf-8") : null,
|
|
24912
25058
|
lockfilePath,
|
|
24913
|
-
lockfile:
|
|
25059
|
+
lockfile: existsSync8(lockfilePath) ? readFileSync5(lockfilePath, "utf-8") : null,
|
|
24914
25060
|
packageDir,
|
|
24915
25061
|
stagedPackageDir,
|
|
24916
25062
|
tempDir
|
|
@@ -24939,13 +25085,13 @@ function stripPackageNameFromPath(pathValue, packageName) {
|
|
|
24939
25085
|
for (const segment of [...packageName.split("/")].reverse()) {
|
|
24940
25086
|
if (basename(current) !== segment)
|
|
24941
25087
|
return null;
|
|
24942
|
-
current =
|
|
25088
|
+
current = dirname4(current);
|
|
24943
25089
|
}
|
|
24944
25090
|
return current;
|
|
24945
25091
|
}
|
|
24946
25092
|
function removeFromPackageLock(installDir, packageName) {
|
|
24947
|
-
const lockPath =
|
|
24948
|
-
if (!
|
|
25093
|
+
const lockPath = join11(installDir, "package-lock.json");
|
|
25094
|
+
if (!existsSync8(lockPath))
|
|
24949
25095
|
return false;
|
|
24950
25096
|
try {
|
|
24951
25097
|
const lock = import_comment_json3.parse(readFileSync5(lockPath, "utf-8"));
|
|
@@ -24971,7 +25117,7 @@ function removeFromPackageLock(installDir, packageName) {
|
|
|
24971
25117
|
}
|
|
24972
25118
|
}
|
|
24973
25119
|
function ensureDependencyVersion(packageJsonPath, packageName, version2) {
|
|
24974
|
-
if (!
|
|
25120
|
+
if (!existsSync8(packageJsonPath))
|
|
24975
25121
|
return false;
|
|
24976
25122
|
try {
|
|
24977
25123
|
const raw = import_comment_json3.parse(readFileSync5(packageJsonPath, "utf-8"));
|
|
@@ -24993,8 +25139,8 @@ function ensureDependencyVersion(packageJsonPath, packageName, version2) {
|
|
|
24993
25139
|
}
|
|
24994
25140
|
}
|
|
24995
25141
|
function removeInstalledPackage(installDir, packageName) {
|
|
24996
|
-
const packageDir =
|
|
24997
|
-
if (!
|
|
25142
|
+
const packageDir = join11(installDir, "node_modules", packageName);
|
|
25143
|
+
if (!existsSync8(packageDir))
|
|
24998
25144
|
return false;
|
|
24999
25145
|
rmSync3(packageDir, { recursive: true, force: true });
|
|
25000
25146
|
log2(`[auto-update-checker] Package removed: ${packageDir}`);
|
|
@@ -25002,19 +25148,19 @@ function removeInstalledPackage(installDir, packageName) {
|
|
|
25002
25148
|
}
|
|
25003
25149
|
function resolveInstallContext(runtimePackageJsonPath = getCurrentRuntimePackageJsonPath()) {
|
|
25004
25150
|
if (runtimePackageJsonPath) {
|
|
25005
|
-
const packageDir =
|
|
25151
|
+
const packageDir = dirname4(runtimePackageJsonPath);
|
|
25006
25152
|
const nodeModulesDir = stripPackageNameFromPath(packageDir, PACKAGE_NAME);
|
|
25007
25153
|
if (nodeModulesDir && basename(nodeModulesDir) === "node_modules") {
|
|
25008
|
-
const installDir =
|
|
25009
|
-
const packageJsonPath =
|
|
25010
|
-
if (
|
|
25154
|
+
const installDir = dirname4(nodeModulesDir);
|
|
25155
|
+
const packageJsonPath = join11(installDir, "package.json");
|
|
25156
|
+
if (existsSync8(packageJsonPath))
|
|
25011
25157
|
return { installDir, packageJsonPath };
|
|
25012
25158
|
}
|
|
25013
25159
|
return null;
|
|
25014
25160
|
}
|
|
25015
|
-
const legacyPackageJsonPath =
|
|
25016
|
-
if (
|
|
25017
|
-
return { installDir:
|
|
25161
|
+
const legacyPackageJsonPath = join11(dirname4(CACHE_DIR), "package.json");
|
|
25162
|
+
if (existsSync8(legacyPackageJsonPath)) {
|
|
25163
|
+
return { installDir: dirname4(CACHE_DIR), packageJsonPath: legacyPackageJsonPath };
|
|
25018
25164
|
}
|
|
25019
25165
|
return null;
|
|
25020
25166
|
}
|
|
@@ -25152,8 +25298,8 @@ function claimCheckSlot(storageDir, intervalMs) {
|
|
|
25152
25298
|
if (!storageDir)
|
|
25153
25299
|
return true;
|
|
25154
25300
|
try {
|
|
25155
|
-
const file2 =
|
|
25156
|
-
if (
|
|
25301
|
+
const file2 = join12(storageDir, TIMESTAMP_FILENAME);
|
|
25302
|
+
if (existsSync9(file2)) {
|
|
25157
25303
|
try {
|
|
25158
25304
|
const raw = JSON.parse(readFileSync6(file2, "utf-8"));
|
|
25159
25305
|
const last = typeof raw.lastCheckedMs === "number" ? raw.lastCheckedMs : 0;
|
|
@@ -25162,7 +25308,7 @@ function claimCheckSlot(storageDir, intervalMs) {
|
|
|
25162
25308
|
}
|
|
25163
25309
|
} catch {}
|
|
25164
25310
|
}
|
|
25165
|
-
|
|
25311
|
+
mkdirSync6(dirname5(file2), { recursive: true });
|
|
25166
25312
|
const tmp = `${file2}.tmp.${process.pid}`;
|
|
25167
25313
|
writeFileSync6(tmp, JSON.stringify({ lastCheckedMs: Date.now() }), "utf-8");
|
|
25168
25314
|
renameSync4(tmp, file2);
|
|
@@ -25253,49 +25399,49 @@ function showToast(ctx, title, message, variant = "info", duration3 = 3000) {
|
|
|
25253
25399
|
// src/lsp-auto-install.ts
|
|
25254
25400
|
import { spawn as spawn3 } from "child_process";
|
|
25255
25401
|
import { createHash as createHash4 } from "crypto";
|
|
25256
|
-
import { createReadStream, mkdirSync as
|
|
25257
|
-
import { join as
|
|
25402
|
+
import { createReadStream, mkdirSync as mkdirSync8, readFileSync as readFileSync8, renameSync as renameSync5, rmSync as rmSync4, statSync as statSync5 } from "fs";
|
|
25403
|
+
import { join as join15 } from "path";
|
|
25258
25404
|
|
|
25259
25405
|
// src/lsp-cache.ts
|
|
25260
25406
|
import {
|
|
25261
25407
|
closeSync as closeSync3,
|
|
25262
|
-
mkdirSync as
|
|
25408
|
+
mkdirSync as mkdirSync7,
|
|
25263
25409
|
openSync as openSync3,
|
|
25264
25410
|
readFileSync as readFileSync7,
|
|
25265
25411
|
statSync as statSync4,
|
|
25266
25412
|
unlinkSync as unlinkSync5,
|
|
25267
25413
|
writeFileSync as writeFileSync7
|
|
25268
25414
|
} from "fs";
|
|
25269
|
-
import { homedir as
|
|
25270
|
-
import { join as
|
|
25415
|
+
import { homedir as homedir8 } from "os";
|
|
25416
|
+
import { join as join13 } from "path";
|
|
25271
25417
|
function aftCacheBase() {
|
|
25272
25418
|
const override = process.env.AFT_CACHE_DIR;
|
|
25273
25419
|
if (override && override.length > 0)
|
|
25274
25420
|
return override;
|
|
25275
25421
|
if (process.platform === "win32") {
|
|
25276
25422
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
25277
|
-
const base2 = localAppData ||
|
|
25278
|
-
return
|
|
25423
|
+
const base2 = localAppData || join13(homedir8(), "AppData", "Local");
|
|
25424
|
+
return join13(base2, "aft");
|
|
25279
25425
|
}
|
|
25280
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
25281
|
-
return
|
|
25426
|
+
const base = process.env.XDG_CACHE_HOME || join13(homedir8(), ".cache");
|
|
25427
|
+
return join13(base, "aft");
|
|
25282
25428
|
}
|
|
25283
25429
|
function lspCacheRoot() {
|
|
25284
|
-
return
|
|
25430
|
+
return join13(aftCacheBase(), "lsp-packages");
|
|
25285
25431
|
}
|
|
25286
25432
|
function lspPackageDir(npmPackage) {
|
|
25287
|
-
return
|
|
25433
|
+
return join13(lspCacheRoot(), encodeURIComponent(npmPackage));
|
|
25288
25434
|
}
|
|
25289
25435
|
function lspBinaryPath(npmPackage, binary) {
|
|
25290
|
-
return
|
|
25436
|
+
return join13(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
|
|
25291
25437
|
}
|
|
25292
25438
|
function lspBinDir(npmPackage) {
|
|
25293
|
-
return
|
|
25439
|
+
return join13(lspPackageDir(npmPackage), "node_modules", ".bin");
|
|
25294
25440
|
}
|
|
25295
25441
|
function isInstalled(npmPackage, binary) {
|
|
25296
25442
|
for (const candidate of lspBinaryCandidates(binary)) {
|
|
25297
25443
|
try {
|
|
25298
|
-
if (statSync4(
|
|
25444
|
+
if (statSync4(join13(lspBinDir(npmPackage), candidate)).isFile())
|
|
25299
25445
|
return true;
|
|
25300
25446
|
} catch {}
|
|
25301
25447
|
}
|
|
@@ -25309,19 +25455,19 @@ function lspBinaryCandidates(binary) {
|
|
|
25309
25455
|
var INSTALLED_META_FILE = ".aft-installed";
|
|
25310
25456
|
function writeInstalledMetaIn(installDir, version2, sha256) {
|
|
25311
25457
|
try {
|
|
25312
|
-
|
|
25458
|
+
mkdirSync7(installDir, { recursive: true });
|
|
25313
25459
|
const meta3 = {
|
|
25314
25460
|
version: version2,
|
|
25315
25461
|
installedAt: new Date().toISOString(),
|
|
25316
25462
|
...sha256 ? { sha256 } : {}
|
|
25317
25463
|
};
|
|
25318
|
-
writeFileSync7(
|
|
25464
|
+
writeFileSync7(join13(installDir, INSTALLED_META_FILE), JSON.stringify(meta3), "utf8");
|
|
25319
25465
|
} catch (err) {
|
|
25320
25466
|
log2(`[lsp-cache] failed to write installed-meta in ${installDir}: ${err}`);
|
|
25321
25467
|
}
|
|
25322
25468
|
}
|
|
25323
25469
|
function readInstalledMetaIn(installDir) {
|
|
25324
|
-
const path2 =
|
|
25470
|
+
const path2 = join13(installDir, INSTALLED_META_FILE);
|
|
25325
25471
|
try {
|
|
25326
25472
|
if (!statSync4(path2).isFile())
|
|
25327
25473
|
return null;
|
|
@@ -25345,11 +25491,11 @@ function readInstalledMeta(packageKey) {
|
|
|
25345
25491
|
return readInstalledMetaIn(lspPackageDir(packageKey));
|
|
25346
25492
|
}
|
|
25347
25493
|
function lockPath(npmPackage) {
|
|
25348
|
-
return
|
|
25494
|
+
return join13(lspPackageDir(npmPackage), ".aft-installing");
|
|
25349
25495
|
}
|
|
25350
25496
|
var STALE_LOCK_MS2 = 30 * 60 * 1000;
|
|
25351
25497
|
function acquireInstallLock(lockKey) {
|
|
25352
|
-
|
|
25498
|
+
mkdirSync7(lspPackageDir(lockKey), { recursive: true });
|
|
25353
25499
|
const lock = lockPath(lockKey);
|
|
25354
25500
|
const tryClaim = () => {
|
|
25355
25501
|
try {
|
|
@@ -25452,7 +25598,7 @@ async function withInstallLock(lockKey, task) {
|
|
|
25452
25598
|
}
|
|
25453
25599
|
var VERSION_CHECK_FILE = ".aft-version-check";
|
|
25454
25600
|
function readVersionCheck(npmPackage) {
|
|
25455
|
-
const file2 =
|
|
25601
|
+
const file2 = join13(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
|
|
25456
25602
|
try {
|
|
25457
25603
|
const raw = readFileSync7(file2, "utf8");
|
|
25458
25604
|
const parsed = JSON.parse(raw);
|
|
@@ -25468,8 +25614,8 @@ function readVersionCheck(npmPackage) {
|
|
|
25468
25614
|
}
|
|
25469
25615
|
}
|
|
25470
25616
|
function writeVersionCheck(npmPackage, latest) {
|
|
25471
|
-
|
|
25472
|
-
const file2 =
|
|
25617
|
+
mkdirSync7(lspPackageDir(npmPackage), { recursive: true });
|
|
25618
|
+
const file2 = join13(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
|
|
25473
25619
|
const record2 = {
|
|
25474
25620
|
last_checked: new Date().toISOString(),
|
|
25475
25621
|
latest_eligible: latest
|
|
@@ -25617,8 +25763,8 @@ var NPM_LSP_TABLE = [
|
|
|
25617
25763
|
];
|
|
25618
25764
|
|
|
25619
25765
|
// src/lsp-project-relevance.ts
|
|
25620
|
-
import { existsSync as
|
|
25621
|
-
import { join as
|
|
25766
|
+
import { existsSync as existsSync10, readdirSync as readdirSync3 } from "fs";
|
|
25767
|
+
import { join as join14 } from "path";
|
|
25622
25768
|
var MAX_WALK_DIRS = 200;
|
|
25623
25769
|
var MAX_WALK_DEPTH = 4;
|
|
25624
25770
|
var NOISE_DIRS = new Set([
|
|
@@ -25635,7 +25781,7 @@ function hasRootMarker(projectRoot, rootMarkers) {
|
|
|
25635
25781
|
if (!rootMarkers)
|
|
25636
25782
|
return false;
|
|
25637
25783
|
for (const marker of rootMarkers) {
|
|
25638
|
-
if (
|
|
25784
|
+
if (existsSync10(join14(projectRoot, marker)))
|
|
25639
25785
|
return true;
|
|
25640
25786
|
}
|
|
25641
25787
|
return false;
|
|
@@ -25661,7 +25807,7 @@ function relevantExtensionsInProject(projectRoot, extToServer) {
|
|
|
25661
25807
|
for (const entry of entries) {
|
|
25662
25808
|
if (entry.isDirectory()) {
|
|
25663
25809
|
if (current.depth < MAX_WALK_DEPTH && !NOISE_DIRS.has(entry.name.toLowerCase())) {
|
|
25664
|
-
queue.push({ dir:
|
|
25810
|
+
queue.push({ dir: join14(current.dir, entry.name), depth: current.depth + 1 });
|
|
25665
25811
|
}
|
|
25666
25812
|
continue;
|
|
25667
25813
|
}
|
|
@@ -25793,8 +25939,9 @@ function runInstall(spec, version2, cwd, signal) {
|
|
|
25793
25939
|
resolve3(false);
|
|
25794
25940
|
return;
|
|
25795
25941
|
}
|
|
25796
|
-
const child = spawn3("
|
|
25797
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
25942
|
+
const child = spawn3("npm", ["install", "--no-save", "--ignore-scripts", "--silent", target], {
|
|
25943
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
25944
|
+
cwd
|
|
25798
25945
|
});
|
|
25799
25946
|
child.unref();
|
|
25800
25947
|
let stderrBuf = "";
|
|
@@ -25958,10 +26105,10 @@ function sha256OfFileSync(path2) {
|
|
|
25958
26105
|
}
|
|
25959
26106
|
function quarantineCachedNpmInstall(spec, reason) {
|
|
25960
26107
|
const packageDir = lspPackageDir(spec.npm);
|
|
25961
|
-
const dest =
|
|
26108
|
+
const dest = join15(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
|
|
25962
26109
|
warn2(`[lsp] tofu_mismatch ${spec.npm}: ${reason}; quarantining ${packageDir} -> ${dest}`);
|
|
25963
26110
|
try {
|
|
25964
|
-
|
|
26111
|
+
mkdirSync8(join15(dest, ".."), { recursive: true });
|
|
25965
26112
|
rmSync4(dest, { recursive: true, force: true });
|
|
25966
26113
|
renameSync5(packageDir, dest);
|
|
25967
26114
|
} catch (err) {
|
|
@@ -26044,9 +26191,9 @@ import {
|
|
|
26044
26191
|
copyFileSync as copyFileSync3,
|
|
26045
26192
|
createReadStream as createReadStream2,
|
|
26046
26193
|
createWriteStream as createWriteStream3,
|
|
26047
|
-
existsSync as
|
|
26194
|
+
existsSync as existsSync11,
|
|
26048
26195
|
lstatSync as lstatSync2,
|
|
26049
|
-
mkdirSync as
|
|
26196
|
+
mkdirSync as mkdirSync9,
|
|
26050
26197
|
readdirSync as readdirSync4,
|
|
26051
26198
|
readFileSync as readFileSync9,
|
|
26052
26199
|
readlinkSync as readlinkSync2,
|
|
@@ -26057,7 +26204,7 @@ import {
|
|
|
26057
26204
|
unlinkSync as unlinkSync6,
|
|
26058
26205
|
writeFileSync as writeFileSync8
|
|
26059
26206
|
} from "fs";
|
|
26060
|
-
import { dirname as
|
|
26207
|
+
import { dirname as dirname6, join as join16, relative as relative2, resolve as resolve3 } from "path";
|
|
26061
26208
|
import { Readable as Readable3 } from "stream";
|
|
26062
26209
|
import { pipeline as pipeline3 } from "stream/promises";
|
|
26063
26210
|
|
|
@@ -26147,26 +26294,26 @@ function detectHostPlatform() {
|
|
|
26147
26294
|
|
|
26148
26295
|
// src/lsp-github-install.ts
|
|
26149
26296
|
function ghCacheRoot() {
|
|
26150
|
-
return
|
|
26297
|
+
return join16(aftCacheBase(), "lsp-binaries");
|
|
26151
26298
|
}
|
|
26152
26299
|
function ghPackageDir(spec) {
|
|
26153
|
-
return
|
|
26300
|
+
return join16(ghCacheRoot(), spec.id);
|
|
26154
26301
|
}
|
|
26155
26302
|
function ghBinDir(spec) {
|
|
26156
|
-
return
|
|
26303
|
+
return join16(ghPackageDir(spec), "bin");
|
|
26157
26304
|
}
|
|
26158
26305
|
function ghExtractDir(spec) {
|
|
26159
|
-
return
|
|
26306
|
+
return join16(ghPackageDir(spec), "extracted");
|
|
26160
26307
|
}
|
|
26161
26308
|
var INSTALLED_META_FILE2 = ".aft-installed";
|
|
26162
26309
|
function ghBinaryPath(spec, platform2) {
|
|
26163
26310
|
const ext = platform2 === "win32" ? ".exe" : "";
|
|
26164
|
-
return
|
|
26311
|
+
return join16(ghBinDir(spec), `${spec.binary}${ext}`);
|
|
26165
26312
|
}
|
|
26166
26313
|
function isGithubInstalled(spec, platform2) {
|
|
26167
26314
|
for (const candidate of ghBinaryCandidates(spec, platform2)) {
|
|
26168
26315
|
try {
|
|
26169
|
-
if (statSync6(
|
|
26316
|
+
if (statSync6(join16(ghBinDir(spec), candidate)).isFile())
|
|
26170
26317
|
return true;
|
|
26171
26318
|
} catch {}
|
|
26172
26319
|
}
|
|
@@ -26179,7 +26326,7 @@ function ghBinaryCandidates(spec, platform2) {
|
|
|
26179
26326
|
}
|
|
26180
26327
|
function readGithubInstalledMetaIn(installDir) {
|
|
26181
26328
|
try {
|
|
26182
|
-
const path2 =
|
|
26329
|
+
const path2 = join16(installDir, INSTALLED_META_FILE2);
|
|
26183
26330
|
if (!statSync6(path2).isFile())
|
|
26184
26331
|
return null;
|
|
26185
26332
|
const parsed = JSON.parse(readFileSync9(path2, "utf8"));
|
|
@@ -26198,7 +26345,7 @@ function readGithubInstalledMetaIn(installDir) {
|
|
|
26198
26345
|
}
|
|
26199
26346
|
function writeGithubInstalledMetaIn(installDir, version2, binarySha256, archiveSha256) {
|
|
26200
26347
|
try {
|
|
26201
|
-
|
|
26348
|
+
mkdirSync9(installDir, { recursive: true });
|
|
26202
26349
|
const meta3 = {
|
|
26203
26350
|
version: version2,
|
|
26204
26351
|
installedAt: new Date().toISOString(),
|
|
@@ -26206,7 +26353,7 @@ function writeGithubInstalledMetaIn(installDir, version2, binarySha256, archiveS
|
|
|
26206
26353
|
binarySha256,
|
|
26207
26354
|
...archiveSha256 ? { archiveSha256 } : {}
|
|
26208
26355
|
};
|
|
26209
|
-
writeFileSync8(
|
|
26356
|
+
writeFileSync8(join16(installDir, INSTALLED_META_FILE2), JSON.stringify(meta3), "utf8");
|
|
26210
26357
|
} catch (err) {
|
|
26211
26358
|
warn2(`[lsp] failed to write github installed metadata in ${installDir}: ${err}`);
|
|
26212
26359
|
}
|
|
@@ -26399,7 +26546,7 @@ async function downloadFile(url2, destPath, fetchImpl, assetSize, signal) {
|
|
|
26399
26546
|
if (Number.isFinite(advertised) && advertised > MAX_DOWNLOAD_BYTES3) {
|
|
26400
26547
|
throw new Error(`Content-Length ${advertised} exceeds max ${MAX_DOWNLOAD_BYTES3}`);
|
|
26401
26548
|
}
|
|
26402
|
-
|
|
26549
|
+
mkdirSync9(dirname6(destPath), { recursive: true });
|
|
26403
26550
|
let bytesWritten = 0;
|
|
26404
26551
|
const guard = new TransformStream({
|
|
26405
26552
|
transform(chunk, controller) {
|
|
@@ -26455,7 +26602,7 @@ function validateExtraction(stagingRoot) {
|
|
|
26455
26602
|
throw new Error(`failed to read staging dir ${dir}: ${err}`);
|
|
26456
26603
|
}
|
|
26457
26604
|
for (const entry of entries) {
|
|
26458
|
-
const full =
|
|
26605
|
+
const full = join16(dir, entry);
|
|
26459
26606
|
let lst;
|
|
26460
26607
|
try {
|
|
26461
26608
|
lst = lstatSync2(full);
|
|
@@ -26525,7 +26672,7 @@ function extractArchiveSafely(archivePath, destDir, archiveType) {
|
|
|
26525
26672
|
try {
|
|
26526
26673
|
rmSync5(stagingDir, { recursive: true, force: true });
|
|
26527
26674
|
} catch {}
|
|
26528
|
-
|
|
26675
|
+
mkdirSync9(stagingDir, { recursive: true });
|
|
26529
26676
|
try {
|
|
26530
26677
|
precheckArchiveContents(archivePath, archiveType);
|
|
26531
26678
|
runPlatformExtractor(archivePath, stagingDir, archiveType);
|
|
@@ -26543,10 +26690,10 @@ function extractArchiveSafely(archivePath, destDir, archiveType) {
|
|
|
26543
26690
|
}
|
|
26544
26691
|
function quarantineCachedGithubInstall(spec, reason) {
|
|
26545
26692
|
const packageDir = ghPackageDir(spec);
|
|
26546
|
-
const dest =
|
|
26693
|
+
const dest = join16(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
|
|
26547
26694
|
warn2(`[lsp] tofu_mismatch ${spec.id}: ${reason}; quarantining ${packageDir} -> ${dest}`);
|
|
26548
26695
|
try {
|
|
26549
|
-
|
|
26696
|
+
mkdirSync9(dirname6(dest), { recursive: true });
|
|
26550
26697
|
rmSync5(dest, { recursive: true, force: true });
|
|
26551
26698
|
renameSync6(packageDir, dest);
|
|
26552
26699
|
} catch (err) {
|
|
@@ -26556,7 +26703,7 @@ function quarantineCachedGithubInstall(spec, reason) {
|
|
|
26556
26703
|
function validateCachedGithubInstall(spec, platform2) {
|
|
26557
26704
|
const packageDir = ghPackageDir(spec);
|
|
26558
26705
|
const meta3 = readGithubInstalledMetaIn(packageDir);
|
|
26559
|
-
const binaryPath = ghBinaryCandidates(spec, platform2).map((candidate) =>
|
|
26706
|
+
const binaryPath = ghBinaryCandidates(spec, platform2).map((candidate) => join16(ghBinDir(spec), candidate)).find((candidate) => {
|
|
26560
26707
|
try {
|
|
26561
26708
|
return statSync6(candidate).isFile();
|
|
26562
26709
|
} catch {
|
|
@@ -26634,7 +26781,7 @@ async function downloadAndInstall(spec, tag, assets, platform2, arch, fetchImpl,
|
|
|
26634
26781
|
}
|
|
26635
26782
|
const pkgDir = ghPackageDir(spec);
|
|
26636
26783
|
const extractDir = ghExtractDir(spec);
|
|
26637
|
-
const archivePath =
|
|
26784
|
+
const archivePath = join16(pkgDir, expected.name);
|
|
26638
26785
|
log2(`[lsp] downloading ${spec.id} ${tag} \u2192 ${matchingAsset.url}`);
|
|
26639
26786
|
try {
|
|
26640
26787
|
await downloadFile(matchingAsset.url, archivePath, fetchImpl, matchingAsset.size, signal);
|
|
@@ -26674,13 +26821,13 @@ async function downloadAndInstall(spec, tag, assets, platform2, arch, fetchImpl,
|
|
|
26674
26821
|
unlinkSync6(archivePath);
|
|
26675
26822
|
} catch {}
|
|
26676
26823
|
}
|
|
26677
|
-
const innerBinaryPath =
|
|
26678
|
-
if (!
|
|
26824
|
+
const innerBinaryPath = join16(extractDir, spec.binaryPathInArchive(platform2, arch, version2));
|
|
26825
|
+
if (!existsSync11(innerBinaryPath)) {
|
|
26679
26826
|
error2(`[lsp] ${spec.id}: extracted binary not found at ${innerBinaryPath}`);
|
|
26680
26827
|
return null;
|
|
26681
26828
|
}
|
|
26682
26829
|
const targetBinary = ghBinaryPath(spec, platform2);
|
|
26683
|
-
|
|
26830
|
+
mkdirSync9(dirname6(targetBinary), { recursive: true });
|
|
26684
26831
|
try {
|
|
26685
26832
|
copyFileSync3(innerBinaryPath, targetBinary);
|
|
26686
26833
|
if (platform2 !== "win32") {
|
|
@@ -26759,7 +26906,7 @@ function runGithubAutoInstall(relevantServers, config2, fetchImpl = fetch) {
|
|
|
26759
26906
|
if (!host) {
|
|
26760
26907
|
for (const spec of GITHUB_LSP_TABLE) {
|
|
26761
26908
|
try {
|
|
26762
|
-
if (
|
|
26909
|
+
if (existsSync11(ghBinDir(spec))) {
|
|
26763
26910
|
cachedBinDirs.push(ghBinDir(spec));
|
|
26764
26911
|
}
|
|
26765
26912
|
} catch {}
|
|
@@ -26922,9 +27069,9 @@ function normalizeToolMap(tools) {
|
|
|
26922
27069
|
}
|
|
26923
27070
|
|
|
26924
27071
|
// src/notifications.ts
|
|
26925
|
-
import { existsSync as
|
|
26926
|
-
import { homedir as
|
|
26927
|
-
import { join as
|
|
27072
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync10, readFileSync as readFileSync10, writeFileSync as writeFileSync9 } from "fs";
|
|
27073
|
+
import { homedir as homedir9, platform as platform2 } from "os";
|
|
27074
|
+
import { join as join17 } from "path";
|
|
26928
27075
|
function isTuiMode() {
|
|
26929
27076
|
return process.env.OPENCODE_CLIENT === "cli";
|
|
26930
27077
|
}
|
|
@@ -26943,26 +27090,25 @@ var AFT_MARKER = "\uD83D\uDD27 AFT:";
|
|
|
26943
27090
|
var FEATURE_MARKER = `${AFT_MARKER} New in`;
|
|
26944
27091
|
var WARNING_MARKER = `${AFT_MARKER} \u26A0\uFE0F`;
|
|
26945
27092
|
var STATUS_MARKER = `${AFT_MARKER} \u2705`;
|
|
26946
|
-
var WARNED_TOOLS_FILE = "warned_tools.json";
|
|
26947
27093
|
function getDesktopStatePath() {
|
|
26948
27094
|
const os2 = platform2();
|
|
26949
|
-
const home =
|
|
27095
|
+
const home = homedir9();
|
|
26950
27096
|
if (os2 === "darwin") {
|
|
26951
|
-
return
|
|
27097
|
+
return join17(home, "Library", "Application Support", "ai.opencode.desktop", "opencode.global.dat");
|
|
26952
27098
|
}
|
|
26953
27099
|
if (os2 === "linux") {
|
|
26954
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME ||
|
|
26955
|
-
return
|
|
27100
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME || join17(home, ".config");
|
|
27101
|
+
return join17(xdgConfig, "ai.opencode.desktop", "opencode.global.dat");
|
|
26956
27102
|
}
|
|
26957
27103
|
if (os2 === "win32") {
|
|
26958
|
-
const appData = process.env.APPDATA ||
|
|
26959
|
-
return
|
|
27104
|
+
const appData = process.env.APPDATA || join17(home, "AppData", "Roaming");
|
|
27105
|
+
return join17(appData, "ai.opencode.desktop", "opencode.global.dat");
|
|
26960
27106
|
}
|
|
26961
27107
|
return null;
|
|
26962
27108
|
}
|
|
26963
27109
|
function readDesktopState(directory) {
|
|
26964
27110
|
const statePath = getDesktopStatePath();
|
|
26965
|
-
if (!statePath || !
|
|
27111
|
+
if (!statePath || !existsSync12(statePath)) {
|
|
26966
27112
|
return { sessionId: null, serverUrl: null };
|
|
26967
27113
|
}
|
|
26968
27114
|
try {
|
|
@@ -27064,9 +27210,9 @@ async function sendWarning(opts, message) {
|
|
|
27064
27210
|
}
|
|
27065
27211
|
async function sendFeatureAnnouncement(opts, version2, features, storageDir) {
|
|
27066
27212
|
if (storageDir) {
|
|
27067
|
-
const versionFile =
|
|
27213
|
+
const versionFile = join17(storageDir, "last_announced_version");
|
|
27068
27214
|
try {
|
|
27069
|
-
if (
|
|
27215
|
+
if (existsSync12(versionFile)) {
|
|
27070
27216
|
const lastVersion = readFileSync10(versionFile, "utf-8").trim();
|
|
27071
27217
|
if (lastVersion === version2)
|
|
27072
27218
|
return;
|
|
@@ -27087,60 +27233,41 @@ async function sendFeatureAnnouncement(opts, version2, features, storageDir) {
|
|
|
27087
27233
|
}
|
|
27088
27234
|
if (storageDir) {
|
|
27089
27235
|
try {
|
|
27090
|
-
|
|
27091
|
-
writeFileSync9(
|
|
27236
|
+
mkdirSync10(storageDir, { recursive: true });
|
|
27237
|
+
writeFileSync9(join17(storageDir, "last_announced_version"), version2);
|
|
27092
27238
|
} catch {}
|
|
27093
27239
|
}
|
|
27094
27240
|
}
|
|
27095
|
-
function readWarnedTools(
|
|
27241
|
+
async function readWarnedTools(bridge) {
|
|
27096
27242
|
try {
|
|
27097
|
-
const
|
|
27098
|
-
if (
|
|
27243
|
+
const resp = await bridge.send("db_get_state", { key: "warned_tools" });
|
|
27244
|
+
if (resp.success === false)
|
|
27245
|
+
return {};
|
|
27246
|
+
const value = resp.data?.value;
|
|
27247
|
+
if (typeof value !== "string")
|
|
27099
27248
|
return {};
|
|
27100
|
-
const parsed = JSON.parse(
|
|
27249
|
+
const parsed = JSON.parse(value);
|
|
27101
27250
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
27102
27251
|
return {};
|
|
27103
|
-
|
|
27104
|
-
for (const [key, version2] of Object.entries(parsed)) {
|
|
27105
|
-
if (typeof version2 === "string") {
|
|
27106
|
-
warned[key] = version2;
|
|
27107
|
-
}
|
|
27108
|
-
}
|
|
27109
|
-
return warned;
|
|
27252
|
+
return parsed;
|
|
27110
27253
|
} catch {
|
|
27111
27254
|
return {};
|
|
27112
27255
|
}
|
|
27113
27256
|
}
|
|
27114
|
-
function
|
|
27257
|
+
async function hasWarnedFor(bridge, key) {
|
|
27258
|
+
const warned = await readWarnedTools(bridge);
|
|
27259
|
+
return warned[key] === true || typeof warned[key] === "string";
|
|
27260
|
+
}
|
|
27261
|
+
async function recordWarning(bridge, key) {
|
|
27262
|
+
const warned = await readWarnedTools(bridge);
|
|
27263
|
+
warned[key] = true;
|
|
27115
27264
|
try {
|
|
27116
|
-
|
|
27117
|
-
|
|
27118
|
-
|
|
27119
|
-
|
|
27120
|
-
`);
|
|
27121
|
-
renameSync7(tmpPath, warnedToolsPath);
|
|
27265
|
+
await bridge.send("db_set_state", {
|
|
27266
|
+
key: "warned_tools",
|
|
27267
|
+
value: JSON.stringify(warned)
|
|
27268
|
+
});
|
|
27122
27269
|
} catch {}
|
|
27123
27270
|
}
|
|
27124
|
-
async function withWarnedToolsLock(storageDir, fn) {
|
|
27125
|
-
const lockDir = join16(storageDir, "warned_tools.lock");
|
|
27126
|
-
for (let attempt = 0;attempt < 5; attempt++) {
|
|
27127
|
-
try {
|
|
27128
|
-
mkdirSync9(storageDir, { recursive: true });
|
|
27129
|
-
mkdirSync9(lockDir, { mode: 448 });
|
|
27130
|
-
try {
|
|
27131
|
-
return await fn();
|
|
27132
|
-
} finally {
|
|
27133
|
-
rmSync6(lockDir, { recursive: true, force: true });
|
|
27134
|
-
}
|
|
27135
|
-
} catch (err) {
|
|
27136
|
-
const code = err.code;
|
|
27137
|
-
if (code !== "EEXIST")
|
|
27138
|
-
return null;
|
|
27139
|
-
await new Promise((resolve4) => setTimeout(resolve4, 10 * (attempt + 1)));
|
|
27140
|
-
}
|
|
27141
|
-
}
|
|
27142
|
-
return null;
|
|
27143
|
-
}
|
|
27144
27271
|
function warningKey(warning, projectRoot) {
|
|
27145
27272
|
const scope = warning.kind === "lsp_binary_missing" ? "_" : projectRoot ?? "_";
|
|
27146
27273
|
return [
|
|
@@ -27179,29 +27306,14 @@ ${warning.hint}`;
|
|
|
27179
27306
|
async function deliverConfigureWarnings(opts, warnings) {
|
|
27180
27307
|
if (warnings.length === 0)
|
|
27181
27308
|
return;
|
|
27182
|
-
const deliveredWithLock = await withWarnedToolsLock(opts.storageDir, async () => {
|
|
27183
|
-
const warned = readWarnedTools(opts.storageDir);
|
|
27184
|
-
let changed = false;
|
|
27185
|
-
for (const warning of warnings) {
|
|
27186
|
-
const key = warningKey(warning, opts.projectRoot);
|
|
27187
|
-
if (Object.hasOwn(warned, key))
|
|
27188
|
-
continue;
|
|
27189
|
-
const delivered = await sendIgnoredMessage(opts.client, opts.sessionId, formatConfigureWarning(warning));
|
|
27190
|
-
if (!delivered)
|
|
27191
|
-
continue;
|
|
27192
|
-
warned[key] = opts.pluginVersion;
|
|
27193
|
-
changed = true;
|
|
27194
|
-
}
|
|
27195
|
-
if (changed) {
|
|
27196
|
-
const merged = { ...readWarnedTools(opts.storageDir), ...warned };
|
|
27197
|
-
writeWarnedTools(opts.storageDir, merged);
|
|
27198
|
-
}
|
|
27199
|
-
return true;
|
|
27200
|
-
});
|
|
27201
|
-
if (deliveredWithLock)
|
|
27202
|
-
return;
|
|
27203
27309
|
for (const warning of warnings) {
|
|
27204
|
-
|
|
27310
|
+
const key = warningKey(warning, opts.projectRoot);
|
|
27311
|
+
if (await hasWarnedFor(opts.bridge, key))
|
|
27312
|
+
continue;
|
|
27313
|
+
const delivered = await sendIgnoredMessage(opts.client, opts.sessionId, formatConfigureWarning(warning));
|
|
27314
|
+
if (!delivered)
|
|
27315
|
+
continue;
|
|
27316
|
+
await recordWarning(opts.bridge, key);
|
|
27205
27317
|
}
|
|
27206
27318
|
}
|
|
27207
27319
|
async function cleanupWarnings(opts) {
|
|
@@ -27239,20 +27351,20 @@ async function cleanupWarnings(opts) {
|
|
|
27239
27351
|
|
|
27240
27352
|
// src/shared/rpc-server.ts
|
|
27241
27353
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
27242
|
-
import { mkdirSync as
|
|
27354
|
+
import { mkdirSync as mkdirSync11, renameSync as renameSync7, unlinkSync as unlinkSync7, writeFileSync as writeFileSync10 } from "fs";
|
|
27243
27355
|
import { createServer } from "http";
|
|
27244
|
-
import { dirname as
|
|
27356
|
+
import { dirname as dirname7 } from "path";
|
|
27245
27357
|
|
|
27246
27358
|
// src/shared/rpc-utils.ts
|
|
27247
27359
|
import { createHash as createHash6 } from "crypto";
|
|
27248
|
-
import { join as
|
|
27360
|
+
import { join as join18 } from "path";
|
|
27249
27361
|
function projectHash(directory) {
|
|
27250
27362
|
const normalized = directory.replace(/\/+$/, "");
|
|
27251
27363
|
return createHash6("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
27252
27364
|
}
|
|
27253
27365
|
function rpcPortFilePath(storageDir, directory) {
|
|
27254
27366
|
const hash2 = projectHash(directory);
|
|
27255
|
-
return
|
|
27367
|
+
return join18(storageDir, "rpc", hash2, "port");
|
|
27256
27368
|
}
|
|
27257
27369
|
|
|
27258
27370
|
// src/shared/rpc-server.ts
|
|
@@ -27285,14 +27397,14 @@ class AftRpcServer {
|
|
|
27285
27397
|
this.token = randomBytes2(32).toString("hex");
|
|
27286
27398
|
this.server = server;
|
|
27287
27399
|
try {
|
|
27288
|
-
const dir =
|
|
27289
|
-
|
|
27400
|
+
const dir = dirname7(this.portFilePath);
|
|
27401
|
+
mkdirSync11(dir, { recursive: true, mode: 448 });
|
|
27290
27402
|
const tmpPath = `${this.portFilePath}.tmp`;
|
|
27291
27403
|
writeFileSync10(tmpPath, JSON.stringify({ port: this.port, token: this.token }), {
|
|
27292
27404
|
encoding: "utf-8",
|
|
27293
27405
|
mode: 384
|
|
27294
27406
|
});
|
|
27295
|
-
|
|
27407
|
+
renameSync7(tmpPath, this.portFilePath);
|
|
27296
27408
|
log2(`RPC server listening on 127.0.0.1:${this.port}`);
|
|
27297
27409
|
} catch (err) {
|
|
27298
27410
|
warn2(`Failed to write RPC port file: ${err}`);
|
|
@@ -27446,6 +27558,24 @@ function readNumber(value, fallback = 0) {
|
|
|
27446
27558
|
function readOptionalNumber(value) {
|
|
27447
27559
|
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
27448
27560
|
}
|
|
27561
|
+
function readCompressionAggregate(value) {
|
|
27562
|
+
const aggregate = asRecord(value);
|
|
27563
|
+
return {
|
|
27564
|
+
events: readNumber(aggregate.events),
|
|
27565
|
+
original_tokens: readNumber(aggregate.original_tokens),
|
|
27566
|
+
compressed_tokens: readNumber(aggregate.compressed_tokens),
|
|
27567
|
+
savings_tokens: readNumber(aggregate.savings_tokens)
|
|
27568
|
+
};
|
|
27569
|
+
}
|
|
27570
|
+
function readCompression(value) {
|
|
27571
|
+
if (typeof value !== "object" || value === null)
|
|
27572
|
+
return;
|
|
27573
|
+
const compression = asRecord(value);
|
|
27574
|
+
return {
|
|
27575
|
+
project: readCompressionAggregate(compression.project),
|
|
27576
|
+
session: readCompressionAggregate(compression.session)
|
|
27577
|
+
};
|
|
27578
|
+
}
|
|
27449
27579
|
function formatFlag(enabled) {
|
|
27450
27580
|
return enabled ? "enabled" : "disabled";
|
|
27451
27581
|
}
|
|
@@ -27524,6 +27654,7 @@ function coerceAftStatus(response) {
|
|
|
27524
27654
|
tracked_files: readNumber(session.tracked_files),
|
|
27525
27655
|
checkpoints: readNumber(session.checkpoints)
|
|
27526
27656
|
},
|
|
27657
|
+
compression: readCompression(response.compression),
|
|
27527
27658
|
message: readString(response.message, "")
|
|
27528
27659
|
};
|
|
27529
27660
|
}
|
|
@@ -27582,21 +27713,21 @@ function formatStatusMarkdown(status) {
|
|
|
27582
27713
|
|
|
27583
27714
|
// src/shared/tui-config.ts
|
|
27584
27715
|
var import_comment_json4 = __toESM(require_src2(), 1);
|
|
27585
|
-
import { existsSync as
|
|
27586
|
-
import { dirname as
|
|
27716
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync12, readFileSync as readFileSync11, writeFileSync as writeFileSync11 } from "fs";
|
|
27717
|
+
import { dirname as dirname8, join as join20 } from "path";
|
|
27587
27718
|
|
|
27588
27719
|
// src/shared/opencode-config-dir.ts
|
|
27589
|
-
import { homedir as
|
|
27590
|
-
import { join as
|
|
27720
|
+
import { homedir as homedir10 } from "os";
|
|
27721
|
+
import { join as join19, resolve as resolve4 } from "path";
|
|
27591
27722
|
function getCliConfigDir() {
|
|
27592
27723
|
const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
27593
27724
|
if (envConfigDir) {
|
|
27594
27725
|
return resolve4(envConfigDir);
|
|
27595
27726
|
}
|
|
27596
27727
|
if (process.platform === "win32") {
|
|
27597
|
-
return
|
|
27728
|
+
return join19(homedir10(), ".config", "opencode");
|
|
27598
27729
|
}
|
|
27599
|
-
return
|
|
27730
|
+
return join19(process.env.XDG_CONFIG_HOME || join19(homedir10(), ".config"), "opencode");
|
|
27600
27731
|
}
|
|
27601
27732
|
function getOpenCodeConfigDir2(_options) {
|
|
27602
27733
|
return getCliConfigDir();
|
|
@@ -27605,10 +27736,10 @@ function getOpenCodeConfigPaths(options) {
|
|
|
27605
27736
|
const configDir = getOpenCodeConfigDir2(options);
|
|
27606
27737
|
return {
|
|
27607
27738
|
configDir,
|
|
27608
|
-
configJson:
|
|
27609
|
-
configJsonc:
|
|
27610
|
-
packageJson:
|
|
27611
|
-
omoConfig:
|
|
27739
|
+
configJson: join19(configDir, "opencode.json"),
|
|
27740
|
+
configJsonc: join19(configDir, "opencode.jsonc"),
|
|
27741
|
+
packageJson: join19(configDir, "package.json"),
|
|
27742
|
+
omoConfig: join19(configDir, "magic-context.jsonc")
|
|
27612
27743
|
};
|
|
27613
27744
|
}
|
|
27614
27745
|
|
|
@@ -27617,11 +27748,11 @@ var PLUGIN_NAME = "@cortexkit/aft-opencode";
|
|
|
27617
27748
|
var PLUGIN_ENTRY = `${PLUGIN_NAME}@latest`;
|
|
27618
27749
|
function resolveTuiConfigPath() {
|
|
27619
27750
|
const configDir = getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
|
|
27620
|
-
const jsoncPath =
|
|
27621
|
-
const jsonPath =
|
|
27622
|
-
if (
|
|
27751
|
+
const jsoncPath = join20(configDir, "tui.jsonc");
|
|
27752
|
+
const jsonPath = join20(configDir, "tui.json");
|
|
27753
|
+
if (existsSync13(jsoncPath))
|
|
27623
27754
|
return jsoncPath;
|
|
27624
|
-
if (
|
|
27755
|
+
if (existsSync13(jsonPath))
|
|
27625
27756
|
return jsonPath;
|
|
27626
27757
|
return jsonPath;
|
|
27627
27758
|
}
|
|
@@ -27629,7 +27760,7 @@ function ensureTuiPluginEntry() {
|
|
|
27629
27760
|
try {
|
|
27630
27761
|
const configPath = resolveTuiConfigPath();
|
|
27631
27762
|
let config2 = {};
|
|
27632
|
-
if (
|
|
27763
|
+
if (existsSync13(configPath)) {
|
|
27633
27764
|
config2 = import_comment_json4.parse(readFileSync11(configPath, "utf-8")) ?? {};
|
|
27634
27765
|
}
|
|
27635
27766
|
const plugins = Array.isArray(config2.plugin) ? config2.plugin.filter((value) => typeof value === "string") : [];
|
|
@@ -27638,7 +27769,7 @@ function ensureTuiPluginEntry() {
|
|
|
27638
27769
|
}
|
|
27639
27770
|
plugins.push(PLUGIN_ENTRY);
|
|
27640
27771
|
config2.plugin = plugins;
|
|
27641
|
-
|
|
27772
|
+
mkdirSync12(dirname8(configPath), { recursive: true });
|
|
27642
27773
|
writeFileSync11(configPath, `${import_comment_json4.stringify(config2, null, 2)}
|
|
27643
27774
|
`);
|
|
27644
27775
|
log2(`[aft-plugin] added TUI plugin entry to ${configPath}`);
|
|
@@ -29235,6 +29366,9 @@ function createWriteTool(ctx, editToolName = "edit") {
|
|
|
29235
29366
|
let output = data.created ? "Created new file." : "File updated.";
|
|
29236
29367
|
if (data.formatted)
|
|
29237
29368
|
output += " Auto-formatted.";
|
|
29369
|
+
if (data.no_op === true) {
|
|
29370
|
+
output += " No net change \u2014 the written content is byte-identical to what was already on disk.";
|
|
29371
|
+
}
|
|
29238
29372
|
const diags = data.lsp_diagnostics;
|
|
29239
29373
|
if (diags && diags.length > 0) {
|
|
29240
29374
|
const errors3 = diags.filter((d) => d.severity === "error");
|
|
@@ -29483,6 +29617,11 @@ function createEditTool(ctx, writeToolName = "write") {
|
|
|
29483
29617
|
result += `
|
|
29484
29618
|
|
|
29485
29619
|
${globSkipNote}`;
|
|
29620
|
+
if (data.no_op === true) {
|
|
29621
|
+
result += `
|
|
29622
|
+
|
|
29623
|
+
Note: no net file change \u2014 the match was found and applied, but the file content is byte-identical to before. Likely causes: oldString and newString are identical, or a formatter normalized the change away.`;
|
|
29624
|
+
}
|
|
29486
29625
|
const diags = data.lsp_diagnostics;
|
|
29487
29626
|
if (diags && diags.length > 0) {
|
|
29488
29627
|
const errors3 = diags.filter((d) => d.severity === "error");
|
|
@@ -30662,9 +30801,9 @@ function splitIncludeArg(raw) {
|
|
|
30662
30801
|
}
|
|
30663
30802
|
buf += ch;
|
|
30664
30803
|
}
|
|
30665
|
-
const
|
|
30666
|
-
if (
|
|
30667
|
-
out.push(
|
|
30804
|
+
const tail2 = buf.trim();
|
|
30805
|
+
if (tail2.length > 0)
|
|
30806
|
+
out.push(tail2);
|
|
30668
30807
|
return out;
|
|
30669
30808
|
}
|
|
30670
30809
|
function searchTools(ctx) {
|
|
@@ -31024,6 +31163,7 @@ async function handleConfigureWarningsForSession(context) {
|
|
|
31024
31163
|
await deliverConfigureWarnings({
|
|
31025
31164
|
client: context.client ?? context.fallbackClient,
|
|
31026
31165
|
sessionId: context.sessionId,
|
|
31166
|
+
bridge: context.bridge,
|
|
31027
31167
|
storageDir: context.storageDir,
|
|
31028
31168
|
pluginVersion: context.pluginVersion,
|
|
31029
31169
|
projectRoot: context.projectRoot
|
|
@@ -31065,47 +31205,25 @@ var PLUGIN_VERSION = (() => {
|
|
|
31065
31205
|
return "0.0.0";
|
|
31066
31206
|
}
|
|
31067
31207
|
})();
|
|
31068
|
-
var ANNOUNCEMENT_VERSION = "0.
|
|
31208
|
+
var ANNOUNCEMENT_VERSION = "0.27.0";
|
|
31069
31209
|
var ANNOUNCEMENT_FEATURES = [
|
|
31070
|
-
|
|
31071
|
-
|
|
31072
|
-
|
|
31073
|
-
|
|
31074
|
-
Check GitHub for how to enable.`,
|
|
31075
|
-
"Trigram grep/glob and semantic search (aft_search) graduated out of experimental.",
|
|
31076
|
-
"Lots of bugfixes and new end-to-end test coverage."
|
|
31210
|
+
"Storage moved to ~/.local/share/cortexkit/aft (~/Library/Application Support/cortexkit/aft on macOS, %APPDATA%/cortexkit/aft on Windows). Your existing data migrated automatically on first launch.",
|
|
31211
|
+
"Bash output compression now reports token savings \u2014 visible in /aft-status and the TUI sidebar (Session + Project totals).",
|
|
31212
|
+
"Seven new languages supported by aft_outline / aft_zoom / aft_search / ast_grep: Java, Ruby, Kotlin, Swift, PHP, Lua, Perl.",
|
|
31213
|
+
"Join us on Discord: https://discord.gg/F2uWxjGnU"
|
|
31077
31214
|
];
|
|
31078
31215
|
var plugin = async (input) => initializePluginForDirectory(input);
|
|
31079
31216
|
async function initializePluginForDirectory(input) {
|
|
31080
31217
|
const binaryPath = await findBinary(PLUGIN_VERSION);
|
|
31218
|
+
await ensureStorageMigrated({ harness: "opencode", binaryPath, logger: bridgeLogger });
|
|
31081
31219
|
const aftConfig = loadAftConfig(input.directory);
|
|
31082
31220
|
const autoUpdateAbort = new AbortController;
|
|
31083
|
-
const configOverrides = {
|
|
31084
|
-
|
|
31085
|
-
|
|
31086
|
-
|
|
31087
|
-
configOverrides.formatter_timeout_secs = aftConfig.formatter_timeout_secs;
|
|
31088
|
-
if (aftConfig.validate_on_edit !== undefined)
|
|
31089
|
-
configOverrides.validate_on_edit = aftConfig.validate_on_edit;
|
|
31090
|
-
if (aftConfig.formatter !== undefined)
|
|
31091
|
-
configOverrides.formatter = aftConfig.formatter;
|
|
31092
|
-
if (aftConfig.checker !== undefined)
|
|
31093
|
-
configOverrides.checker = aftConfig.checker;
|
|
31094
|
-
configOverrides.restrict_to_project_root = aftConfig.restrict_to_project_root ?? false;
|
|
31095
|
-
configOverrides.bash_permissions = true;
|
|
31096
|
-
if (aftConfig.search_index !== undefined)
|
|
31097
|
-
configOverrides.search_index = aftConfig.search_index;
|
|
31098
|
-
if (aftConfig.semantic_search !== undefined)
|
|
31099
|
-
configOverrides.semantic_search = aftConfig.semantic_search;
|
|
31100
|
-
Object.assign(configOverrides, resolveExperimentalConfigForConfigure(aftConfig));
|
|
31101
|
-
Object.assign(configOverrides, resolveLspConfigForConfigure(aftConfig));
|
|
31102
|
-
if (aftConfig.semantic !== undefined)
|
|
31103
|
-
configOverrides.semantic = aftConfig.semantic;
|
|
31104
|
-
if (aftConfig.max_callgraph_files !== undefined)
|
|
31105
|
-
configOverrides.max_callgraph_files = aftConfig.max_callgraph_files;
|
|
31221
|
+
const configOverrides = {
|
|
31222
|
+
...resolveProjectOverridesForConfigure(aftConfig),
|
|
31223
|
+
bash_permissions: true
|
|
31224
|
+
};
|
|
31106
31225
|
const isFastembedSemanticBackend = (aftConfig.semantic?.backend ?? "fastembed") === "fastembed";
|
|
31107
|
-
|
|
31108
|
-
configOverrides.storage_dir = join21(dataHome, "opencode", "storage", "plugin", "aft");
|
|
31226
|
+
configOverrides.storage_dir = resolveCortexKitStorageRoot();
|
|
31109
31227
|
let onnxRuntimePromise = null;
|
|
31110
31228
|
if (aftConfig.semantic_search && isFastembedSemanticBackend) {
|
|
31111
31229
|
const storageDir2 = configOverrides.storage_dir;
|
|
@@ -31184,6 +31302,15 @@ ${lines}
|
|
|
31184
31302
|
const poolOptions = {
|
|
31185
31303
|
errorPrefix: "[aft-plugin]",
|
|
31186
31304
|
minVersion: PLUGIN_VERSION,
|
|
31305
|
+
projectConfigLoader: (projectRoot) => {
|
|
31306
|
+
try {
|
|
31307
|
+
const projectConfig = loadAftConfig(projectRoot);
|
|
31308
|
+
return resolveProjectOverridesForConfigure(projectConfig);
|
|
31309
|
+
} catch (err) {
|
|
31310
|
+
warn2(`loadAftConfig(${projectRoot}) failed; falling back to plugin-init config: ${err instanceof Error ? err.message : String(err)}`);
|
|
31311
|
+
return {};
|
|
31312
|
+
}
|
|
31313
|
+
},
|
|
31187
31314
|
onVersionMismatch: async (binaryVersion, minVersion) => {
|
|
31188
31315
|
const existing = versionUpgradePromises.get(minVersion);
|
|
31189
31316
|
if (existing) {
|
|
@@ -31212,17 +31339,23 @@ ${lines}
|
|
|
31212
31339
|
versionUpgradePromises.set(minVersion, upgradePromise);
|
|
31213
31340
|
return upgradePromise;
|
|
31214
31341
|
},
|
|
31215
|
-
onConfigureWarnings:
|
|
31342
|
+
onConfigureWarnings: ({ projectRoot, sessionId, client, warnings }) => {
|
|
31343
|
+
const bridge = pool.getActiveBridgeForRoot(projectRoot);
|
|
31344
|
+
if (!bridge)
|
|
31345
|
+
return;
|
|
31216
31346
|
const pendingWarnings = sessionId ? drainPendingEagerWarnings(projectRoot) : [];
|
|
31217
|
-
|
|
31218
|
-
|
|
31219
|
-
|
|
31220
|
-
|
|
31221
|
-
|
|
31222
|
-
|
|
31223
|
-
|
|
31224
|
-
|
|
31225
|
-
|
|
31347
|
+
setTimeout(() => {
|
|
31348
|
+
handleConfigureWarningsForSession({
|
|
31349
|
+
projectRoot,
|
|
31350
|
+
sessionId,
|
|
31351
|
+
client,
|
|
31352
|
+
bridge,
|
|
31353
|
+
warnings: [...pendingWarnings, ...warnings],
|
|
31354
|
+
fallbackClient: input.client,
|
|
31355
|
+
storageDir: configOverrides.storage_dir,
|
|
31356
|
+
pluginVersion: PLUGIN_VERSION
|
|
31357
|
+
});
|
|
31358
|
+
}, 0);
|
|
31226
31359
|
},
|
|
31227
31360
|
onBashCompletion: (completion) => {
|
|
31228
31361
|
const sessionDir = getSessionDirectoryCached(completion.session_id) ?? input.directory;
|
|
@@ -31244,6 +31377,7 @@ ${lines}
|
|
|
31244
31377
|
}
|
|
31245
31378
|
};
|
|
31246
31379
|
const pool = new BridgePool(binaryPath, poolOptions, configOverrides);
|
|
31380
|
+
pool.setConfigureOverride("harness", "opencode");
|
|
31247
31381
|
const ctx = {
|
|
31248
31382
|
pool,
|
|
31249
31383
|
client: input.client,
|
|
@@ -31293,7 +31427,9 @@ ${lines}
|
|
|
31293
31427
|
};
|
|
31294
31428
|
}
|
|
31295
31429
|
const cached2 = bridge.getCachedStatus();
|
|
31296
|
-
|
|
31430
|
+
const cachedSessionId = cached2?.session;
|
|
31431
|
+
const cachedId = cachedSessionId?.id;
|
|
31432
|
+
if (cached2 !== null && cachedId === sessionID) {
|
|
31297
31433
|
return { success: true, ...cached2 };
|
|
31298
31434
|
}
|
|
31299
31435
|
const response = await bridge.send("status", { session_id: sessionID });
|
|
@@ -31308,9 +31444,9 @@ ${lines}
|
|
|
31308
31444
|
return { show: false };
|
|
31309
31445
|
}
|
|
31310
31446
|
if (storageDir) {
|
|
31311
|
-
const versionFile =
|
|
31447
|
+
const versionFile = join22(storageDir, "last_announced_version");
|
|
31312
31448
|
try {
|
|
31313
|
-
if (
|
|
31449
|
+
if (existsSync15(versionFile)) {
|
|
31314
31450
|
const lastVersion = readFileSync12(versionFile, "utf-8").trim();
|
|
31315
31451
|
if (lastVersion === ANNOUNCEMENT_VERSION)
|
|
31316
31452
|
return { show: false };
|
|
@@ -31322,8 +31458,8 @@ ${lines}
|
|
|
31322
31458
|
rpcServer.handle("mark-announced", async () => {
|
|
31323
31459
|
if (storageDir && ANNOUNCEMENT_VERSION) {
|
|
31324
31460
|
try {
|
|
31325
|
-
|
|
31326
|
-
writeFileSync12(
|
|
31461
|
+
mkdirSync13(storageDir, { recursive: true });
|
|
31462
|
+
writeFileSync12(join22(storageDir, "last_announced_version"), ANNOUNCEMENT_VERSION);
|
|
31327
31463
|
} catch {}
|
|
31328
31464
|
}
|
|
31329
31465
|
return { success: true };
|
|
@@ -31464,8 +31600,11 @@ Install: ${getManualInstallHint()}`).catch(() => {});
|
|
|
31464
31600
|
const sessionDir = await getSessionDirectory(input.client, commandInput.sessionID, input.directory) ?? input.directory;
|
|
31465
31601
|
const bridge = ctx.pool.getActiveBridgeForRoot(sessionDir) ?? ctx.pool.getBridge(sessionDir);
|
|
31466
31602
|
const cached2 = bridge.getCachedStatus();
|
|
31467
|
-
const
|
|
31468
|
-
|
|
31603
|
+
const cachedSessionId = cached2?.session;
|
|
31604
|
+
const cachedId = cachedSessionId?.id;
|
|
31605
|
+
const cacheUsable = cached2 !== null && cachedId === commandInput.sessionID;
|
|
31606
|
+
const response = cacheUsable ? { success: true, ...cached2 } : await bridge.send("status", { session_id: commandInput.sessionID });
|
|
31607
|
+
if (!cacheUsable && response.success !== false) {
|
|
31469
31608
|
bridge.cacheStatusSnapshot(response);
|
|
31470
31609
|
}
|
|
31471
31610
|
if (response.success === false) {
|