@cortexkit/aft 0.33.0 → 0.35.0
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/commands/doctor.d.ts +2 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/version.d.ts +7 -0
- package/dist/commands/version.d.ts.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +852 -335
- package/dist/lib/issue-body.d.ts +1 -0
- package/dist/lib/issue-body.d.ts.map +1 -1
- package/dist/lib/onnx.d.ts.map +1 -1
- package/dist/lib/sanitize.d.ts.map +1 -1
- package/dist/lib/sessions.d.ts +18 -0
- package/dist/lib/sessions.d.ts.map +1 -0
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -46,11 +46,235 @@ var __export = (target, all) => {
|
|
|
46
46
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
47
47
|
var __promiseAll = (args) => Promise.all(args);
|
|
48
48
|
|
|
49
|
-
// src/lib/
|
|
50
|
-
import {
|
|
49
|
+
// src/lib/paths.ts
|
|
50
|
+
import { homedir, tmpdir } from "node:os";
|
|
51
51
|
import { join } from "node:path";
|
|
52
|
+
function getAftBinaryCacheDir() {
|
|
53
|
+
if (process.env.AFT_CACHE_DIR) {
|
|
54
|
+
return join(process.env.AFT_CACHE_DIR, "bin");
|
|
55
|
+
}
|
|
56
|
+
if (process.platform === "win32") {
|
|
57
|
+
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
58
|
+
const base2 = localAppData || join(homedir(), "AppData", "Local");
|
|
59
|
+
return join(base2, "aft", "bin");
|
|
60
|
+
}
|
|
61
|
+
const base = process.env.XDG_CACHE_HOME || join(homedir(), ".cache");
|
|
62
|
+
return join(base, "aft", "bin");
|
|
63
|
+
}
|
|
64
|
+
function getAftBinaryName() {
|
|
65
|
+
return process.platform === "win32" ? "aft.exe" : "aft";
|
|
66
|
+
}
|
|
67
|
+
function getAftLspPackagesDir() {
|
|
68
|
+
if (process.env.AFT_CACHE_DIR) {
|
|
69
|
+
return join(process.env.AFT_CACHE_DIR, "lsp-packages");
|
|
70
|
+
}
|
|
71
|
+
if (process.platform === "win32") {
|
|
72
|
+
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
73
|
+
const base2 = localAppData || join(homedir(), "AppData", "Local");
|
|
74
|
+
return join(base2, "aft", "lsp-packages");
|
|
75
|
+
}
|
|
76
|
+
const base = process.env.XDG_CACHE_HOME || join(homedir(), ".cache");
|
|
77
|
+
return join(base, "aft", "lsp-packages");
|
|
78
|
+
}
|
|
79
|
+
function getAftLspBinariesDir() {
|
|
80
|
+
if (process.env.AFT_CACHE_DIR) {
|
|
81
|
+
return join(process.env.AFT_CACHE_DIR, "lsp-binaries");
|
|
82
|
+
}
|
|
83
|
+
if (process.platform === "win32") {
|
|
84
|
+
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
85
|
+
const base2 = localAppData || join(homedir(), "AppData", "Local");
|
|
86
|
+
return join(base2, "aft", "lsp-binaries");
|
|
87
|
+
}
|
|
88
|
+
const base = process.env.XDG_CACHE_HOME || join(homedir(), ".cache");
|
|
89
|
+
return join(base, "aft", "lsp-binaries");
|
|
90
|
+
}
|
|
91
|
+
function homeDir() {
|
|
92
|
+
if (process.platform === "win32")
|
|
93
|
+
return process.env.USERPROFILE || process.env.HOME || homedir();
|
|
94
|
+
return process.env.HOME || homedir();
|
|
95
|
+
}
|
|
96
|
+
function dataHome() {
|
|
97
|
+
if (process.env.XDG_DATA_HOME)
|
|
98
|
+
return process.env.XDG_DATA_HOME;
|
|
99
|
+
if (process.platform === "win32") {
|
|
100
|
+
return process.env.LOCALAPPDATA || process.env.APPDATA || join(homeDir(), "AppData", "Local");
|
|
101
|
+
}
|
|
102
|
+
return join(homeDir(), ".local", "share");
|
|
103
|
+
}
|
|
104
|
+
function getCortexKitStorageRoot() {
|
|
105
|
+
return join(dataHome(), "cortexkit", "aft");
|
|
106
|
+
}
|
|
107
|
+
function getTmpLogPath(filename) {
|
|
108
|
+
return join(tmpdir(), filename);
|
|
109
|
+
}
|
|
110
|
+
var init_paths = () => {};
|
|
111
|
+
|
|
112
|
+
// src/lib/binary-probe.ts
|
|
113
|
+
import { execSync, spawnSync } from "node:child_process";
|
|
114
|
+
import { existsSync } from "node:fs";
|
|
115
|
+
import { createRequire } from "node:module";
|
|
116
|
+
import { homedir as homedir2 } from "node:os";
|
|
117
|
+
import { join as join2 } from "node:path";
|
|
118
|
+
async function loadPluginVersion() {
|
|
119
|
+
try {
|
|
120
|
+
const bridgePackageName = "@cortexkit/aft-bridge";
|
|
121
|
+
const bridge = await import(bridgePackageName);
|
|
122
|
+
if (typeof bridge.PLUGIN_VERSION === "string" && bridge.PLUGIN_VERSION.length > 0) {
|
|
123
|
+
return bridge.PLUGIN_VERSION;
|
|
124
|
+
}
|
|
125
|
+
} catch {}
|
|
126
|
+
const require2 = createRequire(import.meta.url);
|
|
127
|
+
for (const relPath of [
|
|
128
|
+
"../../../aft-bridge/package.json",
|
|
129
|
+
"../../package.json",
|
|
130
|
+
"../package.json"
|
|
131
|
+
]) {
|
|
132
|
+
try {
|
|
133
|
+
const pkg = require2(relPath);
|
|
134
|
+
if (typeof pkg.version === "string" && pkg.version.length > 0)
|
|
135
|
+
return pkg.version;
|
|
136
|
+
} catch {}
|
|
137
|
+
}
|
|
138
|
+
return "unknown";
|
|
139
|
+
}
|
|
140
|
+
function parseVersionOutput(output) {
|
|
141
|
+
for (const line of output.split(/\r?\n/)) {
|
|
142
|
+
const match = line.trim().match(VERSION_LINE);
|
|
143
|
+
if (match?.[1])
|
|
144
|
+
return match[1];
|
|
145
|
+
}
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
function majorMinor(version) {
|
|
149
|
+
if (!version)
|
|
150
|
+
return null;
|
|
151
|
+
const match = version.trim().match(/^v?(\d+)\.(\d+)\.\d+(?:[-+][0-9A-Za-z.-]+)?$/);
|
|
152
|
+
if (!match)
|
|
153
|
+
return null;
|
|
154
|
+
return `${match[1]}.${match[2]}`;
|
|
155
|
+
}
|
|
156
|
+
function versionMatchesExpected(candidate, expectedVersion) {
|
|
157
|
+
const candidateMajorMinor = majorMinor(candidate);
|
|
158
|
+
const expectedMajorMinor = majorMinor(expectedVersion);
|
|
159
|
+
return candidateMajorMinor !== null && candidateMajorMinor === expectedMajorMinor;
|
|
160
|
+
}
|
|
161
|
+
function probeBinaryVersion(preferredVersion) {
|
|
162
|
+
return probeAftBinary(preferredVersion).version;
|
|
163
|
+
}
|
|
164
|
+
function probeAftBinary(preferredVersion) {
|
|
165
|
+
const expectedVersion = preferredVersion ?? PLUGIN_VERSION;
|
|
166
|
+
const expectedMajorMinor = majorMinor(expectedVersion);
|
|
167
|
+
const candidates = [];
|
|
168
|
+
for (const candidate of aftBinaryCandidates(preferredVersion)) {
|
|
169
|
+
try {
|
|
170
|
+
if (!existsSync(candidate))
|
|
171
|
+
continue;
|
|
172
|
+
const result = spawnSync(candidate, ["--version"], {
|
|
173
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
174
|
+
encoding: "utf-8",
|
|
175
|
+
timeout: 5000,
|
|
176
|
+
env: process.env
|
|
177
|
+
});
|
|
178
|
+
const output = `${result.stdout ?? ""}
|
|
179
|
+
${result.stderr ?? ""}`.trim();
|
|
180
|
+
if (result.error || result.status !== 0) {
|
|
181
|
+
candidates.push({
|
|
182
|
+
path: candidate,
|
|
183
|
+
status: "error",
|
|
184
|
+
version: null,
|
|
185
|
+
...output ? { output } : {},
|
|
186
|
+
error: result.error?.message ?? `exit status ${result.status ?? "unknown"}`
|
|
187
|
+
});
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
const version = parseVersionOutput(output);
|
|
191
|
+
if (!version) {
|
|
192
|
+
candidates.push({ path: candidate, status: "invalid", version: null, output });
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
if (!versionMatchesExpected(version, expectedVersion)) {
|
|
196
|
+
candidates.push({ path: candidate, status: "unmatched", version, output });
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
candidates.push({ path: candidate, status: "matched", version, output });
|
|
200
|
+
return { version, path: candidate, expectedVersion, expectedMajorMinor, candidates };
|
|
201
|
+
} catch (error) {
|
|
202
|
+
candidates.push({
|
|
203
|
+
path: candidate,
|
|
204
|
+
status: "error",
|
|
205
|
+
version: null,
|
|
206
|
+
error: error instanceof Error ? error.message : String(error)
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return { version: null, path: null, expectedVersion, expectedMajorMinor, candidates };
|
|
211
|
+
}
|
|
212
|
+
function pushCandidate(candidates, candidate) {
|
|
213
|
+
if (!candidate)
|
|
214
|
+
return;
|
|
215
|
+
if (!candidates.includes(candidate))
|
|
216
|
+
candidates.push(candidate);
|
|
217
|
+
}
|
|
218
|
+
function firstExisting(candidates) {
|
|
219
|
+
for (const candidate of candidates) {
|
|
220
|
+
try {
|
|
221
|
+
if (!existsSync(candidate))
|
|
222
|
+
continue;
|
|
223
|
+
return candidate;
|
|
224
|
+
} catch {}
|
|
225
|
+
}
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
function platformKey(platform = process.platform, arch = process.arch) {
|
|
229
|
+
const table = {
|
|
230
|
+
darwin: { arm64: "darwin-arm64", x64: "darwin-x64" },
|
|
231
|
+
linux: { arm64: "linux-arm64", x64: "linux-x64" },
|
|
232
|
+
win32: { x64: "win32-x64" }
|
|
233
|
+
};
|
|
234
|
+
return table[platform]?.[arch] ?? null;
|
|
235
|
+
}
|
|
236
|
+
function aftBinaryCandidates(preferredVersion) {
|
|
237
|
+
const candidates = [];
|
|
238
|
+
if (preferredVersion) {
|
|
239
|
+
const tag = preferredVersion.startsWith("v") ? preferredVersion : `v${preferredVersion}`;
|
|
240
|
+
pushCandidate(candidates, join2(getAftBinaryCacheDir(), tag, getAftBinaryName()));
|
|
241
|
+
}
|
|
242
|
+
const key = platformKey();
|
|
243
|
+
if (key) {
|
|
244
|
+
try {
|
|
245
|
+
const require2 = createRequire(import.meta.url);
|
|
246
|
+
pushCandidate(candidates, require2.resolve(`@cortexkit/aft-${key}/bin/${getAftBinaryName()}`));
|
|
247
|
+
} catch {}
|
|
248
|
+
}
|
|
249
|
+
try {
|
|
250
|
+
const lookup = process.platform === "win32" ? "where aft" : "which aft";
|
|
251
|
+
const resolved = execSync(lookup, {
|
|
252
|
+
stdio: "pipe",
|
|
253
|
+
encoding: "utf-8",
|
|
254
|
+
env: process.env
|
|
255
|
+
}).trim();
|
|
256
|
+
if (resolved) {
|
|
257
|
+
pushCandidate(candidates, resolved.split(/\r?\n/)[0]);
|
|
258
|
+
}
|
|
259
|
+
} catch {}
|
|
260
|
+
pushCandidate(candidates, join2(homedir2(), ".cargo", "bin", getAftBinaryName()));
|
|
261
|
+
return candidates;
|
|
262
|
+
}
|
|
263
|
+
function findAftBinary(preferredVersion) {
|
|
264
|
+
return firstExisting(aftBinaryCandidates(preferredVersion));
|
|
265
|
+
}
|
|
266
|
+
var PLUGIN_VERSION, VERSION_LINE;
|
|
267
|
+
var init_binary_probe = __esm(async () => {
|
|
268
|
+
init_paths();
|
|
269
|
+
PLUGIN_VERSION = await loadPluginVersion();
|
|
270
|
+
VERSION_LINE = /^(?:aft\s+)?v?(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)$/i;
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
// src/lib/fs-util.ts
|
|
274
|
+
import { existsSync as existsSync2, readdirSync, statSync } from "node:fs";
|
|
275
|
+
import { join as join3 } from "node:path";
|
|
52
276
|
function dirSize(path) {
|
|
53
|
-
if (!
|
|
277
|
+
if (!existsSync2(path)) {
|
|
54
278
|
return 0;
|
|
55
279
|
}
|
|
56
280
|
const stat = statSync(path);
|
|
@@ -62,7 +286,7 @@ function dirSize(path) {
|
|
|
62
286
|
}
|
|
63
287
|
let total = 0;
|
|
64
288
|
for (const entry of readdirSync(path)) {
|
|
65
|
-
total += dirSize(
|
|
289
|
+
total += dirSize(join3(path, entry));
|
|
66
290
|
}
|
|
67
291
|
return total;
|
|
68
292
|
}
|
|
@@ -7685,10 +7909,10 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
7685
7909
|
replacer = null;
|
|
7686
7910
|
indent = EMPTY;
|
|
7687
7911
|
};
|
|
7688
|
-
var
|
|
7912
|
+
var join4 = (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;
|
|
7689
7913
|
var join_content = (inside, value, gap) => {
|
|
7690
7914
|
const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
|
|
7691
|
-
return
|
|
7915
|
+
return join4(comment, inside, gap);
|
|
7692
7916
|
};
|
|
7693
7917
|
var stringify_string = (holder, key, value) => {
|
|
7694
7918
|
const raw = get_raw_string_literal(holder, key);
|
|
@@ -7710,13 +7934,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
7710
7934
|
if (i !== 0) {
|
|
7711
7935
|
inside += COMMA;
|
|
7712
7936
|
}
|
|
7713
|
-
const before =
|
|
7937
|
+
const before = join4(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
|
|
7714
7938
|
inside += before || LF + deeper_gap;
|
|
7715
7939
|
inside += stringify(i, value, deeper_gap) || STR_NULL;
|
|
7716
7940
|
inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
|
|
7717
7941
|
after_comma = process_comments(value, AFTER(i), deeper_gap);
|
|
7718
7942
|
}
|
|
7719
|
-
inside +=
|
|
7943
|
+
inside += join4(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
7720
7944
|
return BRACKET_OPEN + join_content(inside, value, gap) + BRACKET_CLOSE;
|
|
7721
7945
|
};
|
|
7722
7946
|
var object_stringify = (value, gap) => {
|
|
@@ -7737,13 +7961,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
7737
7961
|
inside += COMMA;
|
|
7738
7962
|
}
|
|
7739
7963
|
first = false;
|
|
7740
|
-
const before =
|
|
7964
|
+
const before = join4(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
|
|
7741
7965
|
inside += before || LF + deeper_gap;
|
|
7742
7966
|
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);
|
|
7743
7967
|
after_comma = process_comments(value, AFTER(key), deeper_gap);
|
|
7744
7968
|
};
|
|
7745
7969
|
keys.forEach(iteratee);
|
|
7746
|
-
inside +=
|
|
7970
|
+
inside += join4(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
7747
7971
|
return CURLY_BRACKET_OPEN + join_content(inside, value, gap) + CURLY_BRACKET_CLOSE;
|
|
7748
7972
|
};
|
|
7749
7973
|
function stringify(key, holder, gap) {
|
|
@@ -7836,21 +8060,21 @@ var require_src2 = __commonJS((exports, module) => {
|
|
|
7836
8060
|
});
|
|
7837
8061
|
|
|
7838
8062
|
// src/lib/jsonc.ts
|
|
7839
|
-
import { existsSync as
|
|
8063
|
+
import { existsSync as existsSync3, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
7840
8064
|
import { dirname } from "node:path";
|
|
7841
8065
|
function detectJsoncFile(configDir, baseName) {
|
|
7842
8066
|
const jsoncPath = `${configDir}/${baseName}.jsonc`;
|
|
7843
8067
|
const jsonPath = `${configDir}/${baseName}.json`;
|
|
7844
|
-
if (
|
|
8068
|
+
if (existsSync3(jsoncPath)) {
|
|
7845
8069
|
return { path: jsoncPath, format: "jsonc" };
|
|
7846
8070
|
}
|
|
7847
|
-
if (
|
|
8071
|
+
if (existsSync3(jsonPath)) {
|
|
7848
8072
|
return { path: jsonPath, format: "json" };
|
|
7849
8073
|
}
|
|
7850
8074
|
return { path: jsonPath, format: "none" };
|
|
7851
8075
|
}
|
|
7852
8076
|
function readJsoncFile(path) {
|
|
7853
|
-
if (!
|
|
8077
|
+
if (!existsSync3(path)) {
|
|
7854
8078
|
return { value: null };
|
|
7855
8079
|
}
|
|
7856
8080
|
try {
|
|
@@ -7871,7 +8095,7 @@ function writeJsoncFile(path, value, format = "json") {
|
|
|
7871
8095
|
`);
|
|
7872
8096
|
}
|
|
7873
8097
|
function ensureAftSchemaUrl(path, format) {
|
|
7874
|
-
const existed =
|
|
8098
|
+
const existed = existsSync3(path);
|
|
7875
8099
|
if (!existed) {
|
|
7876
8100
|
const writeFormat = format === "jsonc" ? "jsonc" : "json";
|
|
7877
8101
|
writeJsoncFile(path, { $schema: AFT_SCHEMA_URL }, writeFormat);
|
|
@@ -7906,73 +8130,10 @@ var init_jsonc = __esm(() => {
|
|
|
7906
8130
|
import_comment_json = __toESM(require_src2(), 1);
|
|
7907
8131
|
});
|
|
7908
8132
|
|
|
7909
|
-
// src/lib/paths.ts
|
|
7910
|
-
import { homedir, tmpdir } from "node:os";
|
|
7911
|
-
import { join as join2 } from "node:path";
|
|
7912
|
-
function getAftBinaryCacheDir() {
|
|
7913
|
-
if (process.env.AFT_CACHE_DIR) {
|
|
7914
|
-
return join2(process.env.AFT_CACHE_DIR, "bin");
|
|
7915
|
-
}
|
|
7916
|
-
if (process.platform === "win32") {
|
|
7917
|
-
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
7918
|
-
const base2 = localAppData || join2(homedir(), "AppData", "Local");
|
|
7919
|
-
return join2(base2, "aft", "bin");
|
|
7920
|
-
}
|
|
7921
|
-
const base = process.env.XDG_CACHE_HOME || join2(homedir(), ".cache");
|
|
7922
|
-
return join2(base, "aft", "bin");
|
|
7923
|
-
}
|
|
7924
|
-
function getAftBinaryName() {
|
|
7925
|
-
return process.platform === "win32" ? "aft.exe" : "aft";
|
|
7926
|
-
}
|
|
7927
|
-
function getAftLspPackagesDir() {
|
|
7928
|
-
if (process.env.AFT_CACHE_DIR) {
|
|
7929
|
-
return join2(process.env.AFT_CACHE_DIR, "lsp-packages");
|
|
7930
|
-
}
|
|
7931
|
-
if (process.platform === "win32") {
|
|
7932
|
-
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
7933
|
-
const base2 = localAppData || join2(homedir(), "AppData", "Local");
|
|
7934
|
-
return join2(base2, "aft", "lsp-packages");
|
|
7935
|
-
}
|
|
7936
|
-
const base = process.env.XDG_CACHE_HOME || join2(homedir(), ".cache");
|
|
7937
|
-
return join2(base, "aft", "lsp-packages");
|
|
7938
|
-
}
|
|
7939
|
-
function getAftLspBinariesDir() {
|
|
7940
|
-
if (process.env.AFT_CACHE_DIR) {
|
|
7941
|
-
return join2(process.env.AFT_CACHE_DIR, "lsp-binaries");
|
|
7942
|
-
}
|
|
7943
|
-
if (process.platform === "win32") {
|
|
7944
|
-
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
7945
|
-
const base2 = localAppData || join2(homedir(), "AppData", "Local");
|
|
7946
|
-
return join2(base2, "aft", "lsp-binaries");
|
|
7947
|
-
}
|
|
7948
|
-
const base = process.env.XDG_CACHE_HOME || join2(homedir(), ".cache");
|
|
7949
|
-
return join2(base, "aft", "lsp-binaries");
|
|
7950
|
-
}
|
|
7951
|
-
function homeDir() {
|
|
7952
|
-
if (process.platform === "win32")
|
|
7953
|
-
return process.env.USERPROFILE || process.env.HOME || homedir();
|
|
7954
|
-
return process.env.HOME || homedir();
|
|
7955
|
-
}
|
|
7956
|
-
function dataHome() {
|
|
7957
|
-
if (process.env.XDG_DATA_HOME)
|
|
7958
|
-
return process.env.XDG_DATA_HOME;
|
|
7959
|
-
if (process.platform === "win32") {
|
|
7960
|
-
return process.env.LOCALAPPDATA || process.env.APPDATA || join2(homeDir(), "AppData", "Local");
|
|
7961
|
-
}
|
|
7962
|
-
return join2(homeDir(), ".local", "share");
|
|
7963
|
-
}
|
|
7964
|
-
function getCortexKitStorageRoot() {
|
|
7965
|
-
return join2(dataHome(), "cortexkit", "aft");
|
|
7966
|
-
}
|
|
7967
|
-
function getTmpLogPath(filename) {
|
|
7968
|
-
return join2(tmpdir(), filename);
|
|
7969
|
-
}
|
|
7970
|
-
var init_paths = () => {};
|
|
7971
|
-
|
|
7972
8133
|
// src/lib/self-version.ts
|
|
7973
|
-
import { createRequire } from "node:module";
|
|
8134
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
7974
8135
|
function getSelfVersion() {
|
|
7975
|
-
const require2 =
|
|
8136
|
+
const require2 = createRequire2(import.meta.url);
|
|
7976
8137
|
for (const relPath of ["../../package.json", "../package.json"]) {
|
|
7977
8138
|
try {
|
|
7978
8139
|
const version = require2(relPath).version;
|
|
@@ -7986,27 +8147,27 @@ function getSelfVersion() {
|
|
|
7986
8147
|
var init_self_version = () => {};
|
|
7987
8148
|
|
|
7988
8149
|
// src/adapters/opencode.ts
|
|
7989
|
-
import { execSync } from "node:child_process";
|
|
7990
|
-
import { existsSync as
|
|
7991
|
-
import { homedir as
|
|
7992
|
-
import { dirname as dirname2, join as
|
|
8150
|
+
import { execSync as execSync2 } from "node:child_process";
|
|
8151
|
+
import { existsSync as existsSync4, readFileSync as readFileSync2, rmSync, statSync as statSync2 } from "node:fs";
|
|
8152
|
+
import { homedir as homedir3 } from "node:os";
|
|
8153
|
+
import { dirname as dirname2, join as join4, parse, resolve } from "node:path";
|
|
7993
8154
|
import { fileURLToPath } from "node:url";
|
|
7994
8155
|
function getOpenCodeConfigDir() {
|
|
7995
8156
|
const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
7996
8157
|
if (envDir)
|
|
7997
8158
|
return resolve(envDir);
|
|
7998
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
7999
|
-
return
|
|
8159
|
+
const xdg = process.env.XDG_CONFIG_HOME || join4(homedir3(), ".config");
|
|
8160
|
+
return join4(xdg, "opencode");
|
|
8000
8161
|
}
|
|
8001
8162
|
function getOpenCodeCacheDir() {
|
|
8002
8163
|
const xdg = process.env.XDG_CACHE_HOME;
|
|
8003
8164
|
if (xdg)
|
|
8004
|
-
return
|
|
8165
|
+
return join4(xdg, "opencode");
|
|
8005
8166
|
if (process.platform === "win32") {
|
|
8006
|
-
const localAppData = process.env.LOCALAPPDATA ??
|
|
8007
|
-
return
|
|
8167
|
+
const localAppData = process.env.LOCALAPPDATA ?? join4(homedir3(), "AppData", "Local");
|
|
8168
|
+
return join4(localAppData, "opencode");
|
|
8008
8169
|
}
|
|
8009
|
-
return
|
|
8170
|
+
return join4(homedir3(), ".cache", "opencode");
|
|
8010
8171
|
}
|
|
8011
8172
|
function pathFromEntry(entry) {
|
|
8012
8173
|
if (entry.startsWith("file://")) {
|
|
@@ -8025,13 +8186,13 @@ function pathPointsToOurPlugin(entry) {
|
|
|
8025
8186
|
if (!fsPath)
|
|
8026
8187
|
return false;
|
|
8027
8188
|
try {
|
|
8028
|
-
if (!
|
|
8189
|
+
if (!existsSync4(fsPath))
|
|
8029
8190
|
return false;
|
|
8030
8191
|
let searchDir = statSync2(fsPath).isDirectory() ? fsPath : dirname2(fsPath);
|
|
8031
8192
|
let pkgJsonPath = null;
|
|
8032
8193
|
while (true) {
|
|
8033
|
-
const candidate =
|
|
8034
|
-
if (
|
|
8194
|
+
const candidate = join4(searchDir, "package.json");
|
|
8195
|
+
if (existsSync4(candidate)) {
|
|
8035
8196
|
pkgJsonPath = candidate;
|
|
8036
8197
|
break;
|
|
8037
8198
|
}
|
|
@@ -8063,7 +8224,7 @@ class OpenCodeAdapter {
|
|
|
8063
8224
|
pluginEntryWithVersion = PLUGIN_ENTRY;
|
|
8064
8225
|
isInstalled() {
|
|
8065
8226
|
try {
|
|
8066
|
-
|
|
8227
|
+
execSync2("opencode --version", { stdio: "ignore" });
|
|
8067
8228
|
return true;
|
|
8068
8229
|
} catch {
|
|
8069
8230
|
return false;
|
|
@@ -8071,7 +8232,7 @@ class OpenCodeAdapter {
|
|
|
8071
8232
|
}
|
|
8072
8233
|
getHostVersion() {
|
|
8073
8234
|
try {
|
|
8074
|
-
return
|
|
8235
|
+
return execSync2("opencode --version", { encoding: "utf-8", stdio: "pipe" }).trim();
|
|
8075
8236
|
} catch {
|
|
8076
8237
|
return null;
|
|
8077
8238
|
}
|
|
@@ -8140,11 +8301,11 @@ class OpenCodeAdapter {
|
|
|
8140
8301
|
};
|
|
8141
8302
|
}
|
|
8142
8303
|
getPluginCacheInfo() {
|
|
8143
|
-
const path =
|
|
8304
|
+
const path = join4(getOpenCodeCacheDir(), "packages", PLUGIN_ENTRY);
|
|
8144
8305
|
let cached;
|
|
8145
8306
|
try {
|
|
8146
|
-
const installedPkgPath =
|
|
8147
|
-
if (
|
|
8307
|
+
const installedPkgPath = join4(path, "node_modules", "@cortexkit", "aft-opencode", "package.json");
|
|
8308
|
+
if (existsSync4(installedPkgPath)) {
|
|
8148
8309
|
const pkg = JSON.parse(readFileSync2(installedPkgPath, "utf-8"));
|
|
8149
8310
|
cached = typeof pkg.version === "string" ? pkg.version : undefined;
|
|
8150
8311
|
}
|
|
@@ -8155,7 +8316,7 @@ class OpenCodeAdapter {
|
|
|
8155
8316
|
path,
|
|
8156
8317
|
cached,
|
|
8157
8318
|
latest: getSelfVersion(),
|
|
8158
|
-
exists:
|
|
8319
|
+
exists: existsSync4(path)
|
|
8159
8320
|
};
|
|
8160
8321
|
}
|
|
8161
8322
|
getStorageDir() {
|
|
@@ -8204,11 +8365,11 @@ class OpenCodeAdapter {
|
|
|
8204
8365
|
describeStorageSubtrees() {
|
|
8205
8366
|
const storage = this.getStorageDir();
|
|
8206
8367
|
return {
|
|
8207
|
-
index: dirSize(
|
|
8208
|
-
semantic: dirSize(
|
|
8209
|
-
backups: dirSize(
|
|
8210
|
-
url_cache: dirSize(
|
|
8211
|
-
onnxruntime: dirSize(
|
|
8368
|
+
index: dirSize(join4(storage, "index")),
|
|
8369
|
+
semantic: dirSize(join4(storage, "semantic")),
|
|
8370
|
+
backups: dirSize(join4(storage, "backups")),
|
|
8371
|
+
url_cache: dirSize(join4(storage, "url_cache")),
|
|
8372
|
+
onnxruntime: dirSize(join4(storage, "onnxruntime"))
|
|
8212
8373
|
};
|
|
8213
8374
|
}
|
|
8214
8375
|
}
|
|
@@ -8222,18 +8383,18 @@ var init_opencode = __esm(() => {
|
|
|
8222
8383
|
});
|
|
8223
8384
|
|
|
8224
8385
|
// src/adapters/pi.ts
|
|
8225
|
-
import { execSync as
|
|
8226
|
-
import { existsSync as
|
|
8227
|
-
import { homedir as
|
|
8228
|
-
import { join as
|
|
8229
|
-
function getPiAgentDir() {
|
|
8386
|
+
import { execSync as execSync3, spawnSync as spawnSync2 } from "node:child_process";
|
|
8387
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "node:fs";
|
|
8388
|
+
import { homedir as homedir4 } from "node:os";
|
|
8389
|
+
import { join as join5 } from "node:path";
|
|
8390
|
+
function getPiAgentDir() {
|
|
8230
8391
|
const envHome = process.platform === "win32" ? process.env.USERPROFILE : process.env.HOME;
|
|
8231
|
-
const home = envHome && envHome.length > 0 ? envHome :
|
|
8232
|
-
return
|
|
8392
|
+
const home = envHome && envHome.length > 0 ? envHome : homedir4();
|
|
8393
|
+
return join5(home, ".pi", "agent");
|
|
8233
8394
|
}
|
|
8234
8395
|
function readPiExtensionIndex() {
|
|
8235
|
-
const settingsPath =
|
|
8236
|
-
if (
|
|
8396
|
+
const settingsPath = join5(getPiAgentDir(), "settings.json");
|
|
8397
|
+
if (existsSync5(settingsPath)) {
|
|
8237
8398
|
try {
|
|
8238
8399
|
const raw = readFileSync3(settingsPath, "utf-8");
|
|
8239
8400
|
const trimmed = raw.replace(/^\uFEFF/, "");
|
|
@@ -8246,13 +8407,13 @@ function readPiExtensionIndex() {
|
|
|
8246
8407
|
} catch {}
|
|
8247
8408
|
}
|
|
8248
8409
|
const candidates = [
|
|
8249
|
-
|
|
8250
|
-
|
|
8251
|
-
|
|
8252
|
-
|
|
8410
|
+
join5(getPiAgentDir(), "extensions.json"),
|
|
8411
|
+
join5(getPiAgentDir(), "extensions.jsonc"),
|
|
8412
|
+
join5(getPiAgentDir(), "config.json"),
|
|
8413
|
+
join5(getPiAgentDir(), "config.jsonc")
|
|
8253
8414
|
];
|
|
8254
8415
|
for (const path of candidates) {
|
|
8255
|
-
if (!
|
|
8416
|
+
if (!existsSync5(path))
|
|
8256
8417
|
continue;
|
|
8257
8418
|
try {
|
|
8258
8419
|
const { value } = readJsoncFile(path);
|
|
@@ -8285,15 +8446,15 @@ function piEntryMatchesAft(entry) {
|
|
|
8285
8446
|
} else if (entry.startsWith("/")) {
|
|
8286
8447
|
resolved = entry;
|
|
8287
8448
|
} else if (entry.length > 0) {
|
|
8288
|
-
resolved =
|
|
8449
|
+
resolved = join5(getPiAgentDir(), entry);
|
|
8289
8450
|
}
|
|
8290
8451
|
if (!resolved)
|
|
8291
8452
|
return false;
|
|
8292
8453
|
try {
|
|
8293
|
-
if (!
|
|
8454
|
+
if (!existsSync5(resolved))
|
|
8294
8455
|
return false;
|
|
8295
|
-
const pkgPath =
|
|
8296
|
-
if (!
|
|
8456
|
+
const pkgPath = join5(resolved, "package.json");
|
|
8457
|
+
if (!existsSync5(pkgPath))
|
|
8297
8458
|
return false;
|
|
8298
8459
|
const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
|
|
8299
8460
|
return pkg.name === PLUGIN_NAME2;
|
|
@@ -8313,7 +8474,7 @@ class PiAdapter {
|
|
|
8313
8474
|
pluginEntryWithVersion = PLUGIN_ENTRY2;
|
|
8314
8475
|
isInstalled() {
|
|
8315
8476
|
try {
|
|
8316
|
-
|
|
8477
|
+
execSync3("pi --version", { stdio: "ignore" });
|
|
8317
8478
|
return true;
|
|
8318
8479
|
} catch {
|
|
8319
8480
|
return false;
|
|
@@ -8321,7 +8482,7 @@ class PiAdapter {
|
|
|
8321
8482
|
}
|
|
8322
8483
|
getHostVersion() {
|
|
8323
8484
|
try {
|
|
8324
|
-
const result =
|
|
8485
|
+
const result = spawnSync2("pi", ["--version"], {
|
|
8325
8486
|
stdio: ["ignore", "pipe", "pipe"],
|
|
8326
8487
|
encoding: "utf-8"
|
|
8327
8488
|
});
|
|
@@ -8342,7 +8503,7 @@ class PiAdapter {
|
|
|
8342
8503
|
const aft = detectJsoncFile(configDir, "aft");
|
|
8343
8504
|
return {
|
|
8344
8505
|
configDir,
|
|
8345
|
-
harnessConfig: index.path ??
|
|
8506
|
+
harnessConfig: index.path ?? join5(configDir, "extensions.json"),
|
|
8346
8507
|
harnessConfigFormat: index.path ? "json" : "none",
|
|
8347
8508
|
aftConfig: aft.path,
|
|
8348
8509
|
aftConfigFormat: aft.format
|
|
@@ -8369,7 +8530,7 @@ class PiAdapter {
|
|
|
8369
8530
|
};
|
|
8370
8531
|
}
|
|
8371
8532
|
try {
|
|
8372
|
-
|
|
8533
|
+
execSync3(`pi install ${PLUGIN_ENTRY2}`, { stdio: "inherit" });
|
|
8373
8534
|
return {
|
|
8374
8535
|
ok: true,
|
|
8375
8536
|
action: "added",
|
|
@@ -8387,11 +8548,11 @@ class PiAdapter {
|
|
|
8387
8548
|
}
|
|
8388
8549
|
getPluginCacheInfo() {
|
|
8389
8550
|
const candidates = [
|
|
8390
|
-
|
|
8391
|
-
|
|
8551
|
+
join5(getPiAgentDir(), "node_modules", "@cortexkit", "aft-pi", "package.json"),
|
|
8552
|
+
join5(getPiAgentDir(), "extensions", "node_modules", "@cortexkit", "aft-pi", "package.json")
|
|
8392
8553
|
];
|
|
8393
8554
|
for (const candidate of candidates) {
|
|
8394
|
-
if (!
|
|
8555
|
+
if (!existsSync5(candidate))
|
|
8395
8556
|
continue;
|
|
8396
8557
|
try {
|
|
8397
8558
|
const pkg = JSON.parse(readFileSync3(candidate, "utf-8"));
|
|
@@ -8405,7 +8566,7 @@ class PiAdapter {
|
|
|
8405
8566
|
} catch {}
|
|
8406
8567
|
}
|
|
8407
8568
|
return {
|
|
8408
|
-
path:
|
|
8569
|
+
path: join5(getPiAgentDir(), "extensions"),
|
|
8409
8570
|
exists: false
|
|
8410
8571
|
};
|
|
8411
8572
|
}
|
|
@@ -8427,11 +8588,11 @@ class PiAdapter {
|
|
|
8427
8588
|
describeStorageSubtrees() {
|
|
8428
8589
|
const storage = this.getStorageDir();
|
|
8429
8590
|
return {
|
|
8430
|
-
index: dirSize(
|
|
8431
|
-
semantic: dirSize(
|
|
8432
|
-
backups: dirSize(
|
|
8433
|
-
url_cache: dirSize(
|
|
8434
|
-
onnxruntime: dirSize(
|
|
8591
|
+
index: dirSize(join5(storage, "index")),
|
|
8592
|
+
semantic: dirSize(join5(storage, "semantic")),
|
|
8593
|
+
backups: dirSize(join5(storage, "backups")),
|
|
8594
|
+
url_cache: dirSize(join5(storage, "url_cache")),
|
|
8595
|
+
onnxruntime: dirSize(join5(storage, "onnxruntime"))
|
|
8435
8596
|
};
|
|
8436
8597
|
}
|
|
8437
8598
|
}
|
|
@@ -8444,6 +8605,9 @@ var init_pi = __esm(() => {
|
|
|
8444
8605
|
});
|
|
8445
8606
|
|
|
8446
8607
|
// src/adapters/index.ts
|
|
8608
|
+
function getAllAdapters() {
|
|
8609
|
+
return ALL;
|
|
8610
|
+
}
|
|
8447
8611
|
function getAdapter(kind) {
|
|
8448
8612
|
const found = ALL.find((a) => a.kind === kind);
|
|
8449
8613
|
if (!found)
|
|
@@ -9903,11 +10067,59 @@ async function resolveAdaptersForCommand(argv, options) {
|
|
|
9903
10067
|
})), installed.map((a) => a.kind));
|
|
9904
10068
|
return picks.map((kind) => getAdapter(kind));
|
|
9905
10069
|
}
|
|
10070
|
+
function getAllRegistryAdapters() {
|
|
10071
|
+
return getAllAdapters();
|
|
10072
|
+
}
|
|
9906
10073
|
var init_harness_select = __esm(() => {
|
|
9907
10074
|
init_adapters();
|
|
9908
10075
|
init_prompts();
|
|
9909
10076
|
});
|
|
9910
10077
|
|
|
10078
|
+
// src/commands/version.ts
|
|
10079
|
+
var exports_version = {};
|
|
10080
|
+
__export(exports_version, {
|
|
10081
|
+
runVersion: () => runVersion
|
|
10082
|
+
});
|
|
10083
|
+
function runVersion() {
|
|
10084
|
+
const cliVersion = getSelfVersion();
|
|
10085
|
+
const binaryVersion = probeBinaryVersion();
|
|
10086
|
+
const lines = [];
|
|
10087
|
+
lines.push("");
|
|
10088
|
+
lines.push(" AFT versions");
|
|
10089
|
+
lines.push("");
|
|
10090
|
+
lines.push(` @cortexkit/aft (this CLI) v${cliVersion}`);
|
|
10091
|
+
lines.push(` aft binary ${binaryVersion ?? "not installed"}`);
|
|
10092
|
+
lines.push("");
|
|
10093
|
+
const adapters = getAllRegistryAdapters();
|
|
10094
|
+
const labelWidth = Math.max(...adapters.map((adapter) => adapter.displayName.length));
|
|
10095
|
+
for (const adapter of adapters) {
|
|
10096
|
+
const label = adapter.displayName.padEnd(labelWidth);
|
|
10097
|
+
if (!adapter.isInstalled()) {
|
|
10098
|
+
lines.push(` ${label} host not installed`);
|
|
10099
|
+
continue;
|
|
10100
|
+
}
|
|
10101
|
+
const host = adapter.getHostVersion() ?? "unknown";
|
|
10102
|
+
const registered = adapter.hasPluginEntry();
|
|
10103
|
+
let pluginPart;
|
|
10104
|
+
if (!registered) {
|
|
10105
|
+
pluginPart = "plugin not registered";
|
|
10106
|
+
} else {
|
|
10107
|
+
const cached = adapter.getPluginCacheInfo().cached;
|
|
10108
|
+
pluginPart = cached ? `plugin ${cached}` : "plugin registered (version unknown)";
|
|
10109
|
+
}
|
|
10110
|
+
lines.push(` ${label} host ${host} · ${pluginPart}`);
|
|
10111
|
+
}
|
|
10112
|
+
lines.push("");
|
|
10113
|
+
console.log(lines.join(`
|
|
10114
|
+
`));
|
|
10115
|
+
return 0;
|
|
10116
|
+
}
|
|
10117
|
+
var init_version = __esm(async () => {
|
|
10118
|
+
init_harness_select();
|
|
10119
|
+
init_self_version();
|
|
10120
|
+
await init_binary_probe();
|
|
10121
|
+
});
|
|
10122
|
+
|
|
9911
10123
|
// src/commands/setup.ts
|
|
9912
10124
|
var exports_setup = {};
|
|
9913
10125
|
__export(exports_setup, {
|
|
@@ -10101,167 +10313,6 @@ ${stderrTrimmed}`);
|
|
|
10101
10313
|
var MAX_NOISE_LINES_IN_ERROR = 5;
|
|
10102
10314
|
var init_aft_bridge = () => {};
|
|
10103
10315
|
|
|
10104
|
-
// src/lib/binary-probe.ts
|
|
10105
|
-
import { execSync as execSync3, spawnSync as spawnSync2 } from "node:child_process";
|
|
10106
|
-
import { existsSync as existsSync5 } from "node:fs";
|
|
10107
|
-
import { createRequire as createRequire2 } from "node:module";
|
|
10108
|
-
import { homedir as homedir4 } from "node:os";
|
|
10109
|
-
import { join as join5 } from "node:path";
|
|
10110
|
-
async function loadPluginVersion() {
|
|
10111
|
-
try {
|
|
10112
|
-
const bridgePackageName = "@cortexkit/aft-bridge";
|
|
10113
|
-
const bridge = await import(bridgePackageName);
|
|
10114
|
-
if (typeof bridge.PLUGIN_VERSION === "string" && bridge.PLUGIN_VERSION.length > 0) {
|
|
10115
|
-
return bridge.PLUGIN_VERSION;
|
|
10116
|
-
}
|
|
10117
|
-
} catch {}
|
|
10118
|
-
const require2 = createRequire2(import.meta.url);
|
|
10119
|
-
for (const relPath of [
|
|
10120
|
-
"../../../aft-bridge/package.json",
|
|
10121
|
-
"../../package.json",
|
|
10122
|
-
"../package.json"
|
|
10123
|
-
]) {
|
|
10124
|
-
try {
|
|
10125
|
-
const pkg = require2(relPath);
|
|
10126
|
-
if (typeof pkg.version === "string" && pkg.version.length > 0)
|
|
10127
|
-
return pkg.version;
|
|
10128
|
-
} catch {}
|
|
10129
|
-
}
|
|
10130
|
-
return "unknown";
|
|
10131
|
-
}
|
|
10132
|
-
function parseVersionOutput(output) {
|
|
10133
|
-
for (const line of output.split(/\r?\n/)) {
|
|
10134
|
-
const match = line.trim().match(VERSION_LINE);
|
|
10135
|
-
if (match?.[1])
|
|
10136
|
-
return match[1];
|
|
10137
|
-
}
|
|
10138
|
-
return null;
|
|
10139
|
-
}
|
|
10140
|
-
function majorMinor(version) {
|
|
10141
|
-
if (!version)
|
|
10142
|
-
return null;
|
|
10143
|
-
const match = version.trim().match(/^v?(\d+)\.(\d+)\.\d+(?:[-+][0-9A-Za-z.-]+)?$/);
|
|
10144
|
-
if (!match)
|
|
10145
|
-
return null;
|
|
10146
|
-
return `${match[1]}.${match[2]}`;
|
|
10147
|
-
}
|
|
10148
|
-
function versionMatchesExpected(candidate, expectedVersion) {
|
|
10149
|
-
const candidateMajorMinor = majorMinor(candidate);
|
|
10150
|
-
const expectedMajorMinor = majorMinor(expectedVersion);
|
|
10151
|
-
return candidateMajorMinor !== null && candidateMajorMinor === expectedMajorMinor;
|
|
10152
|
-
}
|
|
10153
|
-
function probeBinaryVersion(preferredVersion) {
|
|
10154
|
-
return probeAftBinary(preferredVersion).version;
|
|
10155
|
-
}
|
|
10156
|
-
function probeAftBinary(preferredVersion) {
|
|
10157
|
-
const expectedVersion = preferredVersion ?? PLUGIN_VERSION;
|
|
10158
|
-
const expectedMajorMinor = majorMinor(expectedVersion);
|
|
10159
|
-
const candidates = [];
|
|
10160
|
-
for (const candidate of aftBinaryCandidates(preferredVersion)) {
|
|
10161
|
-
try {
|
|
10162
|
-
if (!existsSync5(candidate))
|
|
10163
|
-
continue;
|
|
10164
|
-
const result = spawnSync2(candidate, ["--version"], {
|
|
10165
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
10166
|
-
encoding: "utf-8",
|
|
10167
|
-
timeout: 5000,
|
|
10168
|
-
env: process.env
|
|
10169
|
-
});
|
|
10170
|
-
const output = `${result.stdout ?? ""}
|
|
10171
|
-
${result.stderr ?? ""}`.trim();
|
|
10172
|
-
if (result.error || result.status !== 0) {
|
|
10173
|
-
candidates.push({
|
|
10174
|
-
path: candidate,
|
|
10175
|
-
status: "error",
|
|
10176
|
-
version: null,
|
|
10177
|
-
...output ? { output } : {},
|
|
10178
|
-
error: result.error?.message ?? `exit status ${result.status ?? "unknown"}`
|
|
10179
|
-
});
|
|
10180
|
-
continue;
|
|
10181
|
-
}
|
|
10182
|
-
const version = parseVersionOutput(output);
|
|
10183
|
-
if (!version) {
|
|
10184
|
-
candidates.push({ path: candidate, status: "invalid", version: null, output });
|
|
10185
|
-
continue;
|
|
10186
|
-
}
|
|
10187
|
-
if (!versionMatchesExpected(version, expectedVersion)) {
|
|
10188
|
-
candidates.push({ path: candidate, status: "unmatched", version, output });
|
|
10189
|
-
continue;
|
|
10190
|
-
}
|
|
10191
|
-
candidates.push({ path: candidate, status: "matched", version, output });
|
|
10192
|
-
return { version, path: candidate, expectedVersion, expectedMajorMinor, candidates };
|
|
10193
|
-
} catch (error) {
|
|
10194
|
-
candidates.push({
|
|
10195
|
-
path: candidate,
|
|
10196
|
-
status: "error",
|
|
10197
|
-
version: null,
|
|
10198
|
-
error: error instanceof Error ? error.message : String(error)
|
|
10199
|
-
});
|
|
10200
|
-
}
|
|
10201
|
-
}
|
|
10202
|
-
return { version: null, path: null, expectedVersion, expectedMajorMinor, candidates };
|
|
10203
|
-
}
|
|
10204
|
-
function pushCandidate(candidates, candidate) {
|
|
10205
|
-
if (!candidate)
|
|
10206
|
-
return;
|
|
10207
|
-
if (!candidates.includes(candidate))
|
|
10208
|
-
candidates.push(candidate);
|
|
10209
|
-
}
|
|
10210
|
-
function firstExisting(candidates) {
|
|
10211
|
-
for (const candidate of candidates) {
|
|
10212
|
-
try {
|
|
10213
|
-
if (!existsSync5(candidate))
|
|
10214
|
-
continue;
|
|
10215
|
-
return candidate;
|
|
10216
|
-
} catch {}
|
|
10217
|
-
}
|
|
10218
|
-
return null;
|
|
10219
|
-
}
|
|
10220
|
-
function platformKey(platform = process.platform, arch = process.arch) {
|
|
10221
|
-
const table = {
|
|
10222
|
-
darwin: { arm64: "darwin-arm64", x64: "darwin-x64" },
|
|
10223
|
-
linux: { arm64: "linux-arm64", x64: "linux-x64" },
|
|
10224
|
-
win32: { x64: "win32-x64" }
|
|
10225
|
-
};
|
|
10226
|
-
return table[platform]?.[arch] ?? null;
|
|
10227
|
-
}
|
|
10228
|
-
function aftBinaryCandidates(preferredVersion) {
|
|
10229
|
-
const candidates = [];
|
|
10230
|
-
if (preferredVersion) {
|
|
10231
|
-
const tag = preferredVersion.startsWith("v") ? preferredVersion : `v${preferredVersion}`;
|
|
10232
|
-
pushCandidate(candidates, join5(getAftBinaryCacheDir(), tag, getAftBinaryName()));
|
|
10233
|
-
}
|
|
10234
|
-
const key = platformKey();
|
|
10235
|
-
if (key) {
|
|
10236
|
-
try {
|
|
10237
|
-
const require2 = createRequire2(import.meta.url);
|
|
10238
|
-
pushCandidate(candidates, require2.resolve(`@cortexkit/aft-${key}/bin/${getAftBinaryName()}`));
|
|
10239
|
-
} catch {}
|
|
10240
|
-
}
|
|
10241
|
-
try {
|
|
10242
|
-
const lookup = process.platform === "win32" ? "where aft" : "which aft";
|
|
10243
|
-
const resolved = execSync3(lookup, {
|
|
10244
|
-
stdio: "pipe",
|
|
10245
|
-
encoding: "utf-8",
|
|
10246
|
-
env: process.env
|
|
10247
|
-
}).trim();
|
|
10248
|
-
if (resolved) {
|
|
10249
|
-
pushCandidate(candidates, resolved.split(/\r?\n/)[0]);
|
|
10250
|
-
}
|
|
10251
|
-
} catch {}
|
|
10252
|
-
pushCandidate(candidates, join5(homedir4(), ".cargo", "bin", getAftBinaryName()));
|
|
10253
|
-
return candidates;
|
|
10254
|
-
}
|
|
10255
|
-
function findAftBinary(preferredVersion) {
|
|
10256
|
-
return firstExisting(aftBinaryCandidates(preferredVersion));
|
|
10257
|
-
}
|
|
10258
|
-
var PLUGIN_VERSION, VERSION_LINE;
|
|
10259
|
-
var init_binary_probe = __esm(async () => {
|
|
10260
|
-
init_paths();
|
|
10261
|
-
PLUGIN_VERSION = await loadPluginVersion();
|
|
10262
|
-
VERSION_LINE = /^(?:aft\s+)?v?(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)$/i;
|
|
10263
|
-
});
|
|
10264
|
-
|
|
10265
10316
|
// src/commands/lsp.ts
|
|
10266
10317
|
var exports_lsp = {};
|
|
10267
10318
|
__export(exports_lsp, {
|
|
@@ -10929,7 +10980,7 @@ var init_lsp_cache = __esm(() => {
|
|
|
10929
10980
|
|
|
10930
10981
|
// src/lib/onnx.ts
|
|
10931
10982
|
import { existsSync as existsSync10, readdirSync as readdirSync5, readlinkSync, realpathSync, statSync as statSync6 } from "node:fs";
|
|
10932
|
-
import { isAbsolute, join as join9, resolve as resolve4, win32 } from "node:path";
|
|
10983
|
+
import { basename, isAbsolute, join as join9, resolve as resolve4, win32 } from "node:path";
|
|
10933
10984
|
function getOnnxLibraryName() {
|
|
10934
10985
|
if (process.platform === "darwin")
|
|
10935
10986
|
return "libonnxruntime.dylib";
|
|
@@ -10992,10 +11043,29 @@ function findSystemOnnxRuntime() {
|
|
|
10992
11043
|
searchPaths.push(...pathEntriesForPlatform());
|
|
10993
11044
|
const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
|
|
10994
11045
|
const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
|
|
10995
|
-
searchPaths.push(join9(programFiles, "onnxruntime", "lib"), join9(programFiles, "Microsoft ONNX Runtime", "lib"), join9(programFiles, "Microsoft Machine Learning", "lib"), join9(programFilesX86, "onnxruntime", "lib"))
|
|
11046
|
+
searchPaths.push(join9(programFiles, "onnxruntime", "lib"), join9(programFiles, "Microsoft ONNX Runtime", "lib"), join9(programFiles, "Microsoft Machine Learning", "lib"), join9(programFilesX86, "onnxruntime", "lib"), ...(() => {
|
|
11047
|
+
const nugetPaths = [];
|
|
11048
|
+
const userProfile = process.env.USERPROFILE ?? "";
|
|
11049
|
+
if (!userProfile)
|
|
11050
|
+
return nugetPaths;
|
|
11051
|
+
const nugetPackageDir = join9(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
|
|
11052
|
+
if (!existsSync10(nugetPackageDir))
|
|
11053
|
+
return nugetPaths;
|
|
11054
|
+
try {
|
|
11055
|
+
for (const entry of readdirSync5(nugetPackageDir, { withFileTypes: true })) {
|
|
11056
|
+
if (!entry.isDirectory())
|
|
11057
|
+
continue;
|
|
11058
|
+
if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
|
|
11059
|
+
continue;
|
|
11060
|
+
nugetPaths.push(join9(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join9(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
|
|
11061
|
+
}
|
|
11062
|
+
} catch {}
|
|
11063
|
+
return nugetPaths;
|
|
11064
|
+
})());
|
|
10996
11065
|
}
|
|
10997
11066
|
const normalizeCase = process.platform === "win32" || process.platform === "darwin";
|
|
10998
11067
|
const seen = new Set;
|
|
11068
|
+
const unknownVersionPaths = [];
|
|
10999
11069
|
for (const dir of searchPaths) {
|
|
11000
11070
|
let key = resolve4(dir).replace(/[/\\]+$/, "");
|
|
11001
11071
|
if (normalizeCase)
|
|
@@ -11003,14 +11073,44 @@ function findSystemOnnxRuntime() {
|
|
|
11003
11073
|
if (seen.has(key))
|
|
11004
11074
|
continue;
|
|
11005
11075
|
seen.add(key);
|
|
11006
|
-
if (directoryContainsLibrary(dir, libName))
|
|
11007
|
-
|
|
11076
|
+
if (!directoryContainsLibrary(dir, libName))
|
|
11077
|
+
continue;
|
|
11078
|
+
const version = detectOrtVersion(dir);
|
|
11079
|
+
if (!version) {
|
|
11080
|
+
unknownVersionPaths.push(dir);
|
|
11081
|
+
continue;
|
|
11082
|
+
}
|
|
11083
|
+
if (!isOrtVersionCompatible(version))
|
|
11084
|
+
continue;
|
|
11085
|
+
return dir;
|
|
11008
11086
|
}
|
|
11009
|
-
return null;
|
|
11087
|
+
return unknownVersionPaths[0] ?? null;
|
|
11010
11088
|
}
|
|
11011
11089
|
function findCachedOnnxRuntime(storageDir) {
|
|
11012
11090
|
const ortDir = join9(storageDir, "onnxruntime", ONNX_RUNTIME_VERSION);
|
|
11013
|
-
|
|
11091
|
+
const libName = getOnnxLibraryName();
|
|
11092
|
+
if (existsSync10(join9(ortDir, libName)))
|
|
11093
|
+
return ortDir;
|
|
11094
|
+
const libSubdir = join9(ortDir, "lib");
|
|
11095
|
+
if (existsSync10(join9(libSubdir, libName)))
|
|
11096
|
+
return libSubdir;
|
|
11097
|
+
return null;
|
|
11098
|
+
}
|
|
11099
|
+
function parseOrtVersionFromPath(value) {
|
|
11100
|
+
const name = basename(value);
|
|
11101
|
+
const semverish = name.match(/(?:^|[._-])(\d+\.\d+\.\d+(?:[-+][A-Za-z0-9.-]+)?)(?:\.(?:dylib|dll))?$/);
|
|
11102
|
+
if (semverish)
|
|
11103
|
+
return semverish[1].split(/[-+]/, 1)[0];
|
|
11104
|
+
return /\d+\.\d+\.\d+/.test(name) ? INVALID_ORT_VERSION : null;
|
|
11105
|
+
}
|
|
11106
|
+
function parseOrtVersionFromDirectoryPath(value) {
|
|
11107
|
+
const parts = value.split(/[\\/]+/).filter(Boolean).reverse();
|
|
11108
|
+
for (const part of parts) {
|
|
11109
|
+
const version = parseOrtVersionFromPath(part);
|
|
11110
|
+
if (version)
|
|
11111
|
+
return version;
|
|
11112
|
+
}
|
|
11113
|
+
return null;
|
|
11014
11114
|
}
|
|
11015
11115
|
function detectOrtVersion(libDir) {
|
|
11016
11116
|
if (!existsSync10(libDir))
|
|
@@ -11018,28 +11118,32 @@ function detectOrtVersion(libDir) {
|
|
|
11018
11118
|
const libName = getOnnxLibraryName();
|
|
11019
11119
|
try {
|
|
11020
11120
|
const entries = readdirSync5(libDir);
|
|
11121
|
+
const barePrefix = libName.replace(/\.(so|dylib|dll)$/, "");
|
|
11122
|
+
const expectedPrefix = process.platform === "win32" ? barePrefix.toLowerCase() : barePrefix;
|
|
11021
11123
|
for (const entry of entries) {
|
|
11022
|
-
|
|
11124
|
+
const comparable = process.platform === "win32" ? entry.toLowerCase() : entry;
|
|
11125
|
+
if (!comparable.startsWith(expectedPrefix))
|
|
11023
11126
|
continue;
|
|
11024
|
-
const
|
|
11025
|
-
if (
|
|
11026
|
-
return
|
|
11127
|
+
const version = parseOrtVersionFromPath(entry);
|
|
11128
|
+
if (version)
|
|
11129
|
+
return version;
|
|
11027
11130
|
}
|
|
11028
11131
|
const base = join9(libDir, libName);
|
|
11029
11132
|
if (existsSync10(base)) {
|
|
11030
11133
|
try {
|
|
11031
11134
|
const real = realpathSync(base);
|
|
11032
|
-
const
|
|
11033
|
-
if (
|
|
11034
|
-
return
|
|
11135
|
+
const version = parseOrtVersionFromPath(real) ?? parseOrtVersionFromDirectoryPath(real);
|
|
11136
|
+
if (version)
|
|
11137
|
+
return version;
|
|
11035
11138
|
} catch {}
|
|
11036
11139
|
try {
|
|
11037
11140
|
const target = readlinkSync(base);
|
|
11038
|
-
const
|
|
11039
|
-
if (
|
|
11040
|
-
return
|
|
11141
|
+
const version = parseOrtVersionFromPath(target);
|
|
11142
|
+
if (version)
|
|
11143
|
+
return version;
|
|
11041
11144
|
} catch {}
|
|
11042
11145
|
}
|
|
11146
|
+
return parseOrtVersionFromDirectoryPath(libDir);
|
|
11043
11147
|
} catch {}
|
|
11044
11148
|
return null;
|
|
11045
11149
|
}
|
|
@@ -11052,18 +11156,50 @@ function isOrtVersionCompatible(version) {
|
|
|
11052
11156
|
return false;
|
|
11053
11157
|
return minor >= REQUIRED_ORT_MIN_MINOR;
|
|
11054
11158
|
}
|
|
11055
|
-
var ONNX_RUNTIME_VERSION = "1.24.4", REQUIRED_ORT_MAJOR = 1, REQUIRED_ORT_MIN_MINOR = 20;
|
|
11159
|
+
var ONNX_RUNTIME_VERSION = "1.24.4", INVALID_ORT_VERSION = "<invalid>", REQUIRED_ORT_MAJOR = 1, REQUIRED_ORT_MIN_MINOR = 20;
|
|
11056
11160
|
var init_onnx = () => {};
|
|
11057
11161
|
|
|
11058
11162
|
// src/lib/sanitize.ts
|
|
11163
|
+
import { realpathSync as realpathSync2 } from "node:fs";
|
|
11059
11164
|
import { homedir as homedir6, userInfo } from "node:os";
|
|
11060
11165
|
function escapeRegex(value) {
|
|
11061
11166
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
11062
11167
|
}
|
|
11168
|
+
function safeRealpath(p2) {
|
|
11169
|
+
try {
|
|
11170
|
+
return realpathSync2(p2);
|
|
11171
|
+
} catch {
|
|
11172
|
+
return null;
|
|
11173
|
+
}
|
|
11174
|
+
}
|
|
11175
|
+
function isSensitiveKeyName(keyName) {
|
|
11176
|
+
return SENSITIVE_KEY_WORD.test(keyName) || SEGMENTED_KEY_WORD.test(keyName) || CAMEL_CASE_KEY_WORD.test(keyName);
|
|
11177
|
+
}
|
|
11178
|
+
function redactSecrets(content) {
|
|
11179
|
+
let sanitized = content;
|
|
11180
|
+
sanitized = sanitized.replace(/\b((?:Proxy-)?Authorization[^\S\r\n]*:[^\S\r\n]*(?:Bearer|Basic)[^\S\r\n]+)[A-Za-z0-9._~+/-]+=*/gi, `$1${SECRET_PLACEHOLDER}`);
|
|
11181
|
+
sanitized = sanitized.replace(/\bgithub_pat_[A-Za-z0-9_]+\b/g, SECRET_PLACEHOLDER);
|
|
11182
|
+
sanitized = sanitized.replace(/\bgh(?:p|o|s)_[A-Za-z0-9_]{16,}\b/g, SECRET_PLACEHOLDER);
|
|
11183
|
+
sanitized = sanitized.replace(/\bsk-(?:live-)?[A-Za-z0-9][A-Za-z0-9_-]{7,}\b/g, SECRET_PLACEHOLDER);
|
|
11184
|
+
sanitized = sanitized.replace(JWT_PATTERN, SECRET_PLACEHOLDER);
|
|
11185
|
+
sanitized = sanitized.replace(AWS_ACCESS_KEY_ID_PATTERN, SECRET_PLACEHOLDER);
|
|
11186
|
+
sanitized = sanitized.replace(quotedSensitiveKeyValuePattern, (match, prefix, _keyQuote, keyName, valueQuote) => isSensitiveKeyName(keyName) ? `${prefix}${valueQuote}${SECRET_PLACEHOLDER}${valueQuote}` : match);
|
|
11187
|
+
sanitized = sanitized.replace(unquotedSensitiveKeyValuePattern, (match, prefix, keyName, valueQuote) => isSensitiveKeyName(keyName) ? `${prefix}${valueQuote}${SECRET_PLACEHOLDER}${valueQuote}` : match);
|
|
11188
|
+
sanitized = sanitized.replace(bareSensitiveKeyValuePattern, (match, prefix, keyName) => isSensitiveKeyName(keyName) ? `${prefix}${SECRET_PLACEHOLDER}` : match);
|
|
11189
|
+
sanitized = sanitized.replace(/\b([a-z][a-z0-9+.-]*:\/\/)[^@\s/?#]+@/gi, `$1${URL_CREDENTIAL_PLACEHOLDER}@`);
|
|
11190
|
+
sanitized = sanitized.replace(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi, "<EMAIL>");
|
|
11191
|
+
return sanitized;
|
|
11192
|
+
}
|
|
11063
11193
|
function sanitizeContent(content) {
|
|
11064
11194
|
const username = userInfo().username;
|
|
11065
11195
|
const home = homedir6();
|
|
11066
|
-
let sanitized = content;
|
|
11196
|
+
let sanitized = redactSecrets(content);
|
|
11197
|
+
const cwd = process.cwd();
|
|
11198
|
+
for (const candidate of new Set([cwd, safeRealpath(cwd)])) {
|
|
11199
|
+
if (candidate && candidate !== "/" && candidate !== home) {
|
|
11200
|
+
sanitized = sanitized.replace(new RegExp(escapeRegex(candidate), "g"), "<PROJECT>");
|
|
11201
|
+
}
|
|
11202
|
+
}
|
|
11067
11203
|
if (home) {
|
|
11068
11204
|
sanitized = sanitized.replace(new RegExp(escapeRegex(home), "g"), "~");
|
|
11069
11205
|
}
|
|
@@ -11088,7 +11224,17 @@ function sanitizeValue(value) {
|
|
|
11088
11224
|
}
|
|
11089
11225
|
return value;
|
|
11090
11226
|
}
|
|
11091
|
-
var
|
|
11227
|
+
var SECRET_PLACEHOLDER = "<REDACTED_SECRET>", URL_CREDENTIAL_PLACEHOLDER = "***", KEY_NAME = "[A-Za-z_][A-Za-z0-9_.-]*", SENSITIVE_KEY_WORD, SEGMENTED_KEY_WORD, CAMEL_CASE_KEY_WORD, JWT_PATTERN, AWS_ACCESS_KEY_ID_PATTERN, quotedSensitiveKeyValuePattern, unquotedSensitiveKeyValuePattern, bareSensitiveKeyValuePattern;
|
|
11228
|
+
var init_sanitize = __esm(() => {
|
|
11229
|
+
SENSITIVE_KEY_WORD = /(?:token|password|secret|api[_-]?key|passwd|pwd|credential)/i;
|
|
11230
|
+
SEGMENTED_KEY_WORD = /(?:^|[_.-])key(?:$|[_.-])/i;
|
|
11231
|
+
CAMEL_CASE_KEY_WORD = /[a-z0-9]Key(?:$|[A-Z_.-])/;
|
|
11232
|
+
JWT_PATTERN = /\beyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g;
|
|
11233
|
+
AWS_ACCESS_KEY_ID_PATTERN = /\b(?:AKIA|ASIA|AGPA|AIDA|AROA)[A-Z0-9]{16}\b/g;
|
|
11234
|
+
quotedSensitiveKeyValuePattern = new RegExp(String.raw`((['"])(${KEY_NAME})\2[^\S\r\n]*:[^\S\r\n]*)(['"])([^'"\r\n]+)\4`, "gi");
|
|
11235
|
+
unquotedSensitiveKeyValuePattern = new RegExp(String.raw`\b((${KEY_NAME})[^\S\r\n]*[=:][^\S\r\n]*)(['"])([^'"\r\n]+)\3`, "gi");
|
|
11236
|
+
bareSensitiveKeyValuePattern = new RegExp(String.raw`\b((${KEY_NAME})[^\S\r\n]*[=:][^\S\r\n]*)([^\s,;&'"]+)`, "gi");
|
|
11237
|
+
});
|
|
11092
11238
|
|
|
11093
11239
|
// src/lib/diagnostics.ts
|
|
11094
11240
|
import {
|
|
@@ -11457,6 +11603,12 @@ function createGitHubIssue(repo, title, body) {
|
|
|
11457
11603
|
var init_github = () => {};
|
|
11458
11604
|
|
|
11459
11605
|
// src/lib/issue-body.ts
|
|
11606
|
+
function filterLogToSession(logText, sessionId) {
|
|
11607
|
+
const bareId = sessionId.replace(/^ses_/, "");
|
|
11608
|
+
const keepTokens = [`[ses_${bareId}]`, `[${bareId}]`];
|
|
11609
|
+
return logText.split(/\r?\n/).filter((line) => !SESSION_TAG_PATTERN.test(line) || keepTokens.some((token) => line.includes(token))).join(`
|
|
11610
|
+
`);
|
|
11611
|
+
}
|
|
11460
11612
|
function isErrorLogLine(line) {
|
|
11461
11613
|
return ERROR_LOG_PATTERNS.some((rx) => rx.test(line));
|
|
11462
11614
|
}
|
|
@@ -11534,8 +11686,9 @@ function truncateToByteBudget(input, maxBytes) {
|
|
|
11534
11686
|
}
|
|
11535
11687
|
return buf.subarray(0, end).toString("utf8");
|
|
11536
11688
|
}
|
|
11537
|
-
var MAX_GITHUB_BODY_BYTES = 60000, ERROR_LOG_PATTERNS;
|
|
11689
|
+
var MAX_GITHUB_BODY_BYTES = 60000, SESSION_TAG_PATTERN, ERROR_LOG_PATTERNS;
|
|
11538
11690
|
var init_issue_body = __esm(() => {
|
|
11691
|
+
SESSION_TAG_PATTERN = /\[ses_[^\]\s]+\]|\[[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\]/;
|
|
11539
11692
|
ERROR_LOG_PATTERNS = [
|
|
11540
11693
|
/\bcrashed:/i,
|
|
11541
11694
|
/\bfailed:/i,
|
|
@@ -11631,6 +11784,189 @@ var init_onnx_fix = __esm(() => {
|
|
|
11631
11784
|
init_prompts();
|
|
11632
11785
|
});
|
|
11633
11786
|
|
|
11787
|
+
// src/lib/sessions.ts
|
|
11788
|
+
import { existsSync as existsSync13, readdirSync as readdirSync6, readFileSync as readFileSync4, statSync as statSync8 } from "node:fs";
|
|
11789
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
11790
|
+
import { homedir as homedir7 } from "node:os";
|
|
11791
|
+
import { basename as basename2, join as join11 } from "node:path";
|
|
11792
|
+
function listRecentSessions(adapter) {
|
|
11793
|
+
try {
|
|
11794
|
+
if (adapter.kind === "opencode")
|
|
11795
|
+
return listRecentOpenCodeSessions();
|
|
11796
|
+
if (adapter.kind === "pi")
|
|
11797
|
+
return listRecentPiSessions();
|
|
11798
|
+
return [];
|
|
11799
|
+
} catch {
|
|
11800
|
+
return [];
|
|
11801
|
+
}
|
|
11802
|
+
}
|
|
11803
|
+
function mapOpenCodeSessionRows(rows) {
|
|
11804
|
+
return rows.map((row) => {
|
|
11805
|
+
if (typeof row.id !== "string" || row.id.length === 0)
|
|
11806
|
+
return null;
|
|
11807
|
+
if (typeof row.title !== "string" || row.title.length === 0)
|
|
11808
|
+
return null;
|
|
11809
|
+
const lastActivity = typeof row.time_updated === "number" ? row.time_updated : Number(row.time_updated);
|
|
11810
|
+
if (!Number.isFinite(lastActivity))
|
|
11811
|
+
return null;
|
|
11812
|
+
return {
|
|
11813
|
+
id: row.id,
|
|
11814
|
+
title: row.title,
|
|
11815
|
+
lastActivity
|
|
11816
|
+
};
|
|
11817
|
+
}).filter((session) => session !== null).sort((a, b) => b.lastActivity - a.lastActivity).slice(0, MAX_RECENT_SESSIONS);
|
|
11818
|
+
}
|
|
11819
|
+
function listRecentOpenCodeSessions() {
|
|
11820
|
+
const dbPath = join11(getXdgDataHome(), "opencode", "opencode.db");
|
|
11821
|
+
if (!existsSync13(dbPath))
|
|
11822
|
+
return [];
|
|
11823
|
+
let db = null;
|
|
11824
|
+
try {
|
|
11825
|
+
const require2 = createRequire3(import.meta.url);
|
|
11826
|
+
const sqlite = require2("node:sqlite");
|
|
11827
|
+
db = new sqlite.DatabaseSync(dbPath, { readOnly: true });
|
|
11828
|
+
const rows = db.prepare("SELECT id, title, time_updated FROM session ORDER BY time_updated DESC LIMIT 5").all();
|
|
11829
|
+
return mapOpenCodeSessionRows(rows);
|
|
11830
|
+
} catch {
|
|
11831
|
+
return [];
|
|
11832
|
+
} finally {
|
|
11833
|
+
try {
|
|
11834
|
+
db?.close();
|
|
11835
|
+
} catch {}
|
|
11836
|
+
}
|
|
11837
|
+
}
|
|
11838
|
+
function getXdgDataHome() {
|
|
11839
|
+
const xdgDataHome = process.env.XDG_DATA_HOME;
|
|
11840
|
+
return xdgDataHome && xdgDataHome.length > 0 ? xdgDataHome : join11(homedir7(), ".local", "share");
|
|
11841
|
+
}
|
|
11842
|
+
function listRecentPiSessions() {
|
|
11843
|
+
return listPiSessionsFromDir(join11(getHomeDir(), ".pi", "agent", "sessions"));
|
|
11844
|
+
}
|
|
11845
|
+
function getHomeDir() {
|
|
11846
|
+
const envHome = process.platform === "win32" ? process.env.USERPROFILE : process.env.HOME;
|
|
11847
|
+
return envHome && envHome.length > 0 ? envHome : homedir7();
|
|
11848
|
+
}
|
|
11849
|
+
function listPiSessionsFromDir(sessionsDir) {
|
|
11850
|
+
try {
|
|
11851
|
+
if (!existsSync13(sessionsDir))
|
|
11852
|
+
return [];
|
|
11853
|
+
const files = collectJsonlFiles(sessionsDir).map((filePath) => {
|
|
11854
|
+
try {
|
|
11855
|
+
const stats = statSync8(filePath);
|
|
11856
|
+
return { filePath, mtimeMs: stats.mtimeMs };
|
|
11857
|
+
} catch {
|
|
11858
|
+
return null;
|
|
11859
|
+
}
|
|
11860
|
+
}).filter((entry) => entry !== null).sort((a, b) => b.mtimeMs - a.mtimeMs).slice(0, MAX_RECENT_SESSIONS * 4);
|
|
11861
|
+
const sessions = [];
|
|
11862
|
+
for (const file of files) {
|
|
11863
|
+
const parsed = parsePiSessionJsonl(readFileSync4(file.filePath, "utf8"), basename2(file.filePath));
|
|
11864
|
+
if (!parsed)
|
|
11865
|
+
continue;
|
|
11866
|
+
sessions.push({ ...parsed, lastActivity: file.mtimeMs });
|
|
11867
|
+
if (sessions.length >= MAX_RECENT_SESSIONS)
|
|
11868
|
+
break;
|
|
11869
|
+
}
|
|
11870
|
+
return sessions;
|
|
11871
|
+
} catch {
|
|
11872
|
+
return [];
|
|
11873
|
+
}
|
|
11874
|
+
}
|
|
11875
|
+
function collectJsonlFiles(root) {
|
|
11876
|
+
const files = [];
|
|
11877
|
+
const stack = [root];
|
|
11878
|
+
while (stack.length > 0) {
|
|
11879
|
+
const dir = stack.pop();
|
|
11880
|
+
if (!dir)
|
|
11881
|
+
continue;
|
|
11882
|
+
let entries;
|
|
11883
|
+
try {
|
|
11884
|
+
entries = readdirSync6(dir, { withFileTypes: true });
|
|
11885
|
+
} catch {
|
|
11886
|
+
continue;
|
|
11887
|
+
}
|
|
11888
|
+
for (const entry of entries) {
|
|
11889
|
+
const path = join11(dir, entry.name);
|
|
11890
|
+
if (entry.isDirectory()) {
|
|
11891
|
+
stack.push(path);
|
|
11892
|
+
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
11893
|
+
files.push(path);
|
|
11894
|
+
}
|
|
11895
|
+
}
|
|
11896
|
+
}
|
|
11897
|
+
return files;
|
|
11898
|
+
}
|
|
11899
|
+
function parsePiSessionJsonl(jsonl, fallbackFilename = "") {
|
|
11900
|
+
let id = extractUuidFromFilename(fallbackFilename);
|
|
11901
|
+
let title = null;
|
|
11902
|
+
for (const line of jsonl.split(/\r?\n/)) {
|
|
11903
|
+
const trimmed = line.trim();
|
|
11904
|
+
if (trimmed.length === 0)
|
|
11905
|
+
continue;
|
|
11906
|
+
let value;
|
|
11907
|
+
try {
|
|
11908
|
+
value = JSON.parse(trimmed);
|
|
11909
|
+
} catch {
|
|
11910
|
+
continue;
|
|
11911
|
+
}
|
|
11912
|
+
if (!value || typeof value !== "object")
|
|
11913
|
+
continue;
|
|
11914
|
+
const record = value;
|
|
11915
|
+
if (record.type === "session" && typeof record.id === "string" && record.id.length > 0) {
|
|
11916
|
+
id = record.id;
|
|
11917
|
+
}
|
|
11918
|
+
if (title === null) {
|
|
11919
|
+
const maybeTitle = extractPiUserMessageText(record);
|
|
11920
|
+
if (maybeTitle)
|
|
11921
|
+
title = truncateTitle(maybeTitle);
|
|
11922
|
+
}
|
|
11923
|
+
if (id && title)
|
|
11924
|
+
break;
|
|
11925
|
+
}
|
|
11926
|
+
if (!id)
|
|
11927
|
+
return null;
|
|
11928
|
+
return { id, title: title ?? id };
|
|
11929
|
+
}
|
|
11930
|
+
function extractPiUserMessageText(record) {
|
|
11931
|
+
if (record.type !== "message")
|
|
11932
|
+
return null;
|
|
11933
|
+
const message = record.message;
|
|
11934
|
+
if (!message || typeof message !== "object")
|
|
11935
|
+
return null;
|
|
11936
|
+
const messageRecord = message;
|
|
11937
|
+
if (messageRecord.role !== "user")
|
|
11938
|
+
return null;
|
|
11939
|
+
return extractTextFromContent(messageRecord.content);
|
|
11940
|
+
}
|
|
11941
|
+
function extractTextFromContent(content) {
|
|
11942
|
+
if (typeof content === "string")
|
|
11943
|
+
return content.trim() || null;
|
|
11944
|
+
if (!Array.isArray(content))
|
|
11945
|
+
return null;
|
|
11946
|
+
const parts = content.map((part) => {
|
|
11947
|
+
if (typeof part === "string")
|
|
11948
|
+
return part;
|
|
11949
|
+
if (!part || typeof part !== "object")
|
|
11950
|
+
return "";
|
|
11951
|
+
const partRecord = part;
|
|
11952
|
+
return partRecord.type === "text" && typeof partRecord.text === "string" ? partRecord.text : "";
|
|
11953
|
+
}).filter((text2) => text2.trim().length > 0);
|
|
11954
|
+
const joined = parts.join(" ").trim();
|
|
11955
|
+
return joined.length > 0 ? joined : null;
|
|
11956
|
+
}
|
|
11957
|
+
function extractUuidFromFilename(filename) {
|
|
11958
|
+
const match = filename.match(/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/i);
|
|
11959
|
+
return match?.[1] ?? null;
|
|
11960
|
+
}
|
|
11961
|
+
function truncateTitle(title, maxLength = 60) {
|
|
11962
|
+
const normalized = title.replace(/\s+/g, " ").trim();
|
|
11963
|
+
if (normalized.length <= maxLength)
|
|
11964
|
+
return normalized;
|
|
11965
|
+
return `${normalized.slice(0, Math.max(0, maxLength - 1))}…`;
|
|
11966
|
+
}
|
|
11967
|
+
var MAX_RECENT_SESSIONS = 5;
|
|
11968
|
+
var init_sessions = () => {};
|
|
11969
|
+
|
|
11634
11970
|
// src/commands/doctor.ts
|
|
11635
11971
|
var exports_doctor = {};
|
|
11636
11972
|
__export(exports_doctor, {
|
|
@@ -11640,14 +11976,26 @@ __export(exports_doctor, {
|
|
|
11640
11976
|
formatDoctorStorageStatus: () => formatDoctorStorageStatus,
|
|
11641
11977
|
fixPluginEntries: () => fixPluginEntries,
|
|
11642
11978
|
doctorSkewBinaryDownloadDecision: () => doctorSkewBinaryDownloadDecision,
|
|
11979
|
+
deriveIssueTitleFromBody: () => deriveIssueTitleFromBody,
|
|
11643
11980
|
clearOldBinaries: () => clearOldBinaries,
|
|
11644
11981
|
clearDoctorCaches: () => clearDoctorCaches,
|
|
11645
11982
|
buildDoctorFixPlan: () => buildDoctorFixPlan,
|
|
11646
11983
|
DOCTOR_FORCE_CLEAR_TARGETS: () => DOCTOR_FORCE_CLEAR_TARGETS,
|
|
11647
11984
|
DOCTOR_CLEAR_TARGET_OPTIONS: () => DOCTOR_CLEAR_TARGET_OPTIONS
|
|
11648
11985
|
});
|
|
11649
|
-
import {
|
|
11650
|
-
|
|
11986
|
+
import {
|
|
11987
|
+
chmodSync,
|
|
11988
|
+
existsSync as existsSync14,
|
|
11989
|
+
mkdirSync as mkdirSync2,
|
|
11990
|
+
mkdtempSync,
|
|
11991
|
+
readFileSync as readFileSync5,
|
|
11992
|
+
realpathSync as realpathSync3,
|
|
11993
|
+
rmSync as rmSync4,
|
|
11994
|
+
statSync as statSync9,
|
|
11995
|
+
writeFileSync as writeFileSync2
|
|
11996
|
+
} from "node:fs";
|
|
11997
|
+
import { tmpdir as tmpdir2 } from "node:os";
|
|
11998
|
+
import { join as join12 } from "node:path";
|
|
11651
11999
|
async function runDoctor(options) {
|
|
11652
12000
|
if (options.issue) {
|
|
11653
12001
|
return runIssueFlow(options.argv);
|
|
@@ -11660,7 +12008,7 @@ async function runDoctor(options) {
|
|
|
11660
12008
|
return runClearFlow(options.argv);
|
|
11661
12009
|
}
|
|
11662
12010
|
const adapters = await resolveAdaptersForCommand(options.argv, {
|
|
11663
|
-
allowMulti:
|
|
12011
|
+
allowMulti: false,
|
|
11664
12012
|
verb: "diagnose"
|
|
11665
12013
|
});
|
|
11666
12014
|
const report = await collectDiagnostics(adapters);
|
|
@@ -11691,6 +12039,10 @@ async function runDoctor(options) {
|
|
|
11691
12039
|
O2.info(` aft config: ${h.aftConfig.exists ? h.configPaths.aftConfig : "(not set)"}`);
|
|
11692
12040
|
if (h.aftConfig.parseError) {
|
|
11693
12041
|
O2.error(` aft config parse error: ${h.aftConfig.parseError}`);
|
|
12042
|
+
} else if (h.aftConfig.exists) {
|
|
12043
|
+
const { value } = readJsoncFile(h.configPaths.aftConfig);
|
|
12044
|
+
const schemaSet = value?.$schema === AFT_SCHEMA_URL;
|
|
12045
|
+
O2.info(` aft config $schema: ${schemaSet ? "set" : "not set — run `aft doctor --fix` for editor autocomplete"}`);
|
|
11694
12046
|
}
|
|
11695
12047
|
O2.info(` storage: ${formatDoctorStorageStatus(h)}`);
|
|
11696
12048
|
if (h.onnxRuntime.required) {
|
|
@@ -11797,7 +12149,7 @@ function clearOldBinaries() {
|
|
|
11797
12149
|
errors: [],
|
|
11798
12150
|
keptVersion: keepTag
|
|
11799
12151
|
};
|
|
11800
|
-
if (!
|
|
12152
|
+
if (!existsSync14(info.path)) {
|
|
11801
12153
|
O2.info(`Binary cache: nothing to clear at ${info.path}`);
|
|
11802
12154
|
return result;
|
|
11803
12155
|
}
|
|
@@ -11807,10 +12159,10 @@ function clearOldBinaries() {
|
|
|
11807
12159
|
return result;
|
|
11808
12160
|
}
|
|
11809
12161
|
for (const version of stale) {
|
|
11810
|
-
const dir =
|
|
12162
|
+
const dir = join12(info.path, version);
|
|
11811
12163
|
let bytes = 0;
|
|
11812
12164
|
try {
|
|
11813
|
-
bytes =
|
|
12165
|
+
bytes = statSync9(dir).isDirectory() ? dirSize(dir) : 0;
|
|
11814
12166
|
} catch {
|
|
11815
12167
|
bytes = 0;
|
|
11816
12168
|
}
|
|
@@ -11830,6 +12182,42 @@ function clearOldBinaries() {
|
|
|
11830
12182
|
}
|
|
11831
12183
|
return result;
|
|
11832
12184
|
}
|
|
12185
|
+
function findSchemaFixTargets(adapters) {
|
|
12186
|
+
const targets = [];
|
|
12187
|
+
for (const adapter of adapters) {
|
|
12188
|
+
if (!adapter.isInstalled())
|
|
12189
|
+
continue;
|
|
12190
|
+
let aftConfig;
|
|
12191
|
+
let aftConfigFormat;
|
|
12192
|
+
try {
|
|
12193
|
+
({ aftConfig, aftConfigFormat } = adapter.detectConfigPaths());
|
|
12194
|
+
} catch {
|
|
12195
|
+
continue;
|
|
12196
|
+
}
|
|
12197
|
+
const { value } = readJsoncFile(aftConfig);
|
|
12198
|
+
if (value?.$schema === AFT_SCHEMA_URL)
|
|
12199
|
+
continue;
|
|
12200
|
+
targets.push({ adapter, aftConfig, aftConfigFormat });
|
|
12201
|
+
}
|
|
12202
|
+
return targets;
|
|
12203
|
+
}
|
|
12204
|
+
function applySchemaFixes(targets) {
|
|
12205
|
+
let changed = 0;
|
|
12206
|
+
let errors = 0;
|
|
12207
|
+
for (const target of targets) {
|
|
12208
|
+
try {
|
|
12209
|
+
const result = ensureAftSchemaUrl(target.aftConfig, target.aftConfigFormat);
|
|
12210
|
+
if (result.action === "added" || result.action === "updated") {
|
|
12211
|
+
changed += 1;
|
|
12212
|
+
O2.success(`${target.adapter.displayName}: ${result.message}`);
|
|
12213
|
+
}
|
|
12214
|
+
} catch (error) {
|
|
12215
|
+
errors += 1;
|
|
12216
|
+
O2.warn(`${target.adapter.displayName}: could not set $schema on ${target.aftConfig}: ${error instanceof Error ? error.message : String(error)}`);
|
|
12217
|
+
}
|
|
12218
|
+
}
|
|
12219
|
+
return { changed, errors };
|
|
12220
|
+
}
|
|
11833
12221
|
function buildDoctorFixPlan(adapters, report) {
|
|
11834
12222
|
const items = [];
|
|
11835
12223
|
const adaptersByKind = new Map(adapters.map((adapter) => [adapter.kind, adapter]));
|
|
@@ -11877,6 +12265,12 @@ function buildDoctorFixPlan(adapters, report) {
|
|
|
11877
12265
|
});
|
|
11878
12266
|
}
|
|
11879
12267
|
}
|
|
12268
|
+
for (const target of findSchemaFixTargets(adapters)) {
|
|
12269
|
+
items.push({
|
|
12270
|
+
kind: "schema",
|
|
12271
|
+
message: `Will add the AFT config $schema URL to ${target.aftConfig} (editor autocomplete + validation)`
|
|
12272
|
+
});
|
|
12273
|
+
}
|
|
11880
12274
|
return items;
|
|
11881
12275
|
}
|
|
11882
12276
|
function shouldSkipDoctorFixConfirmation(argv) {
|
|
@@ -11915,7 +12309,7 @@ function logUnmatchedBinaryCandidates(expectedVersion) {
|
|
|
11915
12309
|
}
|
|
11916
12310
|
async function runFixFlow(argv) {
|
|
11917
12311
|
const adapters = await resolveAdaptersForCommand(argv, {
|
|
11918
|
-
allowMulti:
|
|
12312
|
+
allowMulti: false,
|
|
11919
12313
|
verb: "auto-fix issues for"
|
|
11920
12314
|
});
|
|
11921
12315
|
O2.info("Running diagnostics to identify auto-fixable issues…");
|
|
@@ -11937,6 +12331,7 @@ async function runFixFlow(argv) {
|
|
|
11937
12331
|
}
|
|
11938
12332
|
await fixPluginEntries(adapters);
|
|
11939
12333
|
const storageSummary = ensureStorageDirsForRegisteredPlugins(adapters);
|
|
12334
|
+
const schemaSummary = applySchemaFixes(findSchemaFixTargets(adapters));
|
|
11940
12335
|
let binaryDownloaded = false;
|
|
11941
12336
|
let binaryDownloadSkipped = false;
|
|
11942
12337
|
let binaryDownloadError = null;
|
|
@@ -11965,7 +12360,7 @@ async function runFixFlow(argv) {
|
|
|
11965
12360
|
}
|
|
11966
12361
|
}
|
|
11967
12362
|
const onnxResult = await runOnnxFix(adapters, report, { yes: true });
|
|
11968
|
-
if (onnxResult === null && !binaryDownloaded && !binaryDownloadSkipped && !binaryDownloadError && storageSummary.created === 0 && storageSummary.errors === 0) {
|
|
12363
|
+
if (onnxResult === null && !binaryDownloaded && !binaryDownloadSkipped && !binaryDownloadError && storageSummary.created === 0 && storageSummary.errors === 0 && schemaSummary.changed === 0 && schemaSummary.errors === 0) {
|
|
11969
12364
|
O2.info("No auto-fixable issues detected.");
|
|
11970
12365
|
wt("If you're still seeing 'Semantic Index: failed' in the TUI sidebar, run `aft doctor` (without --fix) for a full diagnostic dump.", "Tip");
|
|
11971
12366
|
const afterReport2 = await collectDiagnostics(adapters);
|
|
@@ -11973,7 +12368,7 @@ async function runFixFlow(argv) {
|
|
|
11973
12368
|
gt(stillHasProblems2 ? "Done — some issues remain." : "Done.");
|
|
11974
12369
|
return stillHasProblems2 ? 1 : 0;
|
|
11975
12370
|
}
|
|
11976
|
-
const hadErrors = (onnxResult?.errors.length ?? 0) > 0 || binaryDownloadError !== null || storageSummary.errors > 0;
|
|
12371
|
+
const hadErrors = (onnxResult?.errors.length ?? 0) > 0 || binaryDownloadError !== null || storageSummary.errors > 0 || schemaSummary.errors > 0;
|
|
11977
12372
|
const afterReport = await collectDiagnostics(adapters);
|
|
11978
12373
|
const stillHasProblems = hasDoctorProblems(afterReport);
|
|
11979
12374
|
gt(hadErrors ? "Done — some fixes failed." : stillHasProblems ? "Done — some issues remain." : "Done.");
|
|
@@ -12028,7 +12423,7 @@ function ensureStorageDirsForRegisteredPlugins(adapters) {
|
|
|
12028
12423
|
if (!adapter.isInstalled() || !adapter.hasPluginEntry())
|
|
12029
12424
|
continue;
|
|
12030
12425
|
const storageDir = adapter.getStorageDir();
|
|
12031
|
-
if (
|
|
12426
|
+
if (existsSync14(storageDir))
|
|
12032
12427
|
continue;
|
|
12033
12428
|
mkdirSync2(storageDir, { recursive: true });
|
|
12034
12429
|
summary.created += 1;
|
|
@@ -12100,31 +12495,124 @@ function formatStorageSizes(sizes) {
|
|
|
12100
12495
|
const parts = Object.entries(sizes).filter(([, size]) => size > 0).map(([key, size]) => `${key}: ${formatBytes(size)}`);
|
|
12101
12496
|
return parts.length > 0 ? parts.join(", ") : "empty";
|
|
12102
12497
|
}
|
|
12498
|
+
function isInteractiveTerminal() {
|
|
12499
|
+
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
12500
|
+
}
|
|
12501
|
+
function issueDescriptionSummaryFromBody(body) {
|
|
12502
|
+
const lines = body.split(/\r?\n/);
|
|
12503
|
+
const descriptionStart = lines.findIndex((line) => line.trim() === "## Description");
|
|
12504
|
+
if (descriptionStart !== -1) {
|
|
12505
|
+
const parts = [];
|
|
12506
|
+
for (let i = descriptionStart + 1;i < lines.length; i += 1) {
|
|
12507
|
+
const trimmed = lines[i].trim();
|
|
12508
|
+
if (trimmed.startsWith("## "))
|
|
12509
|
+
break;
|
|
12510
|
+
if (!trimmed)
|
|
12511
|
+
continue;
|
|
12512
|
+
parts.push(trimmed);
|
|
12513
|
+
if (parts.join(" ").length >= 72)
|
|
12514
|
+
break;
|
|
12515
|
+
}
|
|
12516
|
+
const summary = parts.join(" ").replace(/\s+/g, " ").trim();
|
|
12517
|
+
if (summary)
|
|
12518
|
+
return summary;
|
|
12519
|
+
}
|
|
12520
|
+
return lines.map((line) => line.trim()).find((line) => line.length > 0 && !line.startsWith("#") && !line.startsWith("```")) ?? "diagnostic report";
|
|
12521
|
+
}
|
|
12522
|
+
function deriveIssueTitleFromBody(body) {
|
|
12523
|
+
const summary = issueDescriptionSummaryFromBody(sanitizeContent(body));
|
|
12524
|
+
return sanitizeContent(`AFT issue: ${summary.slice(0, 72)}`);
|
|
12525
|
+
}
|
|
12526
|
+
function writeIssueReviewFile(body) {
|
|
12527
|
+
let reviewDir = null;
|
|
12528
|
+
try {
|
|
12529
|
+
reviewDir = mkdtempSync(join12(tmpdir2(), "aft-issue-"));
|
|
12530
|
+
if (process.platform !== "win32") {
|
|
12531
|
+
chmodSync(reviewDir, 448);
|
|
12532
|
+
}
|
|
12533
|
+
const outPath = join12(reviewDir, "issue.md");
|
|
12534
|
+
writeFileSync2(outPath, `${body}
|
|
12535
|
+
`, { encoding: "utf8", mode: 384, flag: "wx" });
|
|
12536
|
+
return { path: outPath, realPath: realpathSync3(outPath) };
|
|
12537
|
+
} catch (err) {
|
|
12538
|
+
if (reviewDir) {
|
|
12539
|
+
try {
|
|
12540
|
+
rmSync4(reviewDir, { recursive: true, force: true });
|
|
12541
|
+
} catch {}
|
|
12542
|
+
}
|
|
12543
|
+
O2.error(`Failed to write sanitized issue report: ${err instanceof Error ? err.message : String(err)}`);
|
|
12544
|
+
return null;
|
|
12545
|
+
}
|
|
12546
|
+
}
|
|
12547
|
+
function readReviewedIssueFile(reviewFile) {
|
|
12548
|
+
try {
|
|
12549
|
+
const realPath = realpathSync3(reviewFile.path);
|
|
12550
|
+
if (realPath !== reviewFile.realPath) {
|
|
12551
|
+
O2.error(`Review file path changed before filing; refusing to read ${reviewFile.path}.`);
|
|
12552
|
+
return null;
|
|
12553
|
+
}
|
|
12554
|
+
return readFileSync5(reviewFile.path, "utf8");
|
|
12555
|
+
} catch (err) {
|
|
12556
|
+
O2.error(`Failed to read reviewed issue report: ${err instanceof Error ? err.message : String(err)}`);
|
|
12557
|
+
return null;
|
|
12558
|
+
}
|
|
12559
|
+
}
|
|
12560
|
+
async function promptForIssueSession(adapter) {
|
|
12561
|
+
const sessions = listRecentSessions(adapter);
|
|
12562
|
+
if (sessions.length === 0)
|
|
12563
|
+
return null;
|
|
12564
|
+
const allLogsValue = "__all__";
|
|
12565
|
+
const selected = await selectOne("Is this issue about a specific session?", [
|
|
12566
|
+
{ label: "General — not session-specific (include all logs)", value: allLogsValue },
|
|
12567
|
+
...sessions.map((session) => ({
|
|
12568
|
+
label: truncateTitle(session.title),
|
|
12569
|
+
value: session.id,
|
|
12570
|
+
hint: shortSessionId(session.id)
|
|
12571
|
+
}))
|
|
12572
|
+
]);
|
|
12573
|
+
if (selected === allLogsValue)
|
|
12574
|
+
return null;
|
|
12575
|
+
return sessions.find((session) => session.id === selected) ?? null;
|
|
12576
|
+
}
|
|
12577
|
+
function shortSessionId(id) {
|
|
12578
|
+
const bareId = id.replace(/^ses_/, "");
|
|
12579
|
+
return bareId.length <= 12 ? bareId : bareId.slice(0, 12);
|
|
12580
|
+
}
|
|
12103
12581
|
async function runIssueFlow(argv) {
|
|
12104
12582
|
mt("AFT doctor --issue");
|
|
12583
|
+
if (!isInteractiveTerminal()) {
|
|
12584
|
+
wt("Non-interactive terminal — not collecting or filing automatically. Run `aft doctor --issue` from an interactive terminal so you can describe and review the report before filing.", "Manual filing");
|
|
12585
|
+
gt("Done.");
|
|
12586
|
+
return 0;
|
|
12587
|
+
}
|
|
12105
12588
|
const adapters = await resolveAdaptersForCommand(argv, {
|
|
12106
|
-
allowMulti:
|
|
12589
|
+
allowMulti: false,
|
|
12107
12590
|
verb: "include in the issue"
|
|
12108
12591
|
});
|
|
12109
12592
|
const description = await text("Describe the problem you're running into:", {
|
|
12110
12593
|
placeholder: "What happened? What did you expect? Steps to reproduce…",
|
|
12111
12594
|
validate: (value) => value.trim().length === 0 ? "Please enter a short description." : undefined
|
|
12112
12595
|
});
|
|
12596
|
+
const selectedSession = await promptForIssueSession(adapters[0]);
|
|
12597
|
+
const selectedBareSessionId = selectedSession?.id.replace(/^ses_/, "") ?? null;
|
|
12113
12598
|
const report = await collectDiagnostics(adapters);
|
|
12114
12599
|
const logSections = adapters.map((adapter) => {
|
|
12115
12600
|
const path = adapter.getLogFile();
|
|
12116
12601
|
const tail = tailLogFile(path, 200);
|
|
12602
|
+
const scopedTail = selectedBareSessionId ? filterLogToSession(tail, selectedBareSessionId) : tail;
|
|
12117
12603
|
return `#### ${adapter.displayName} log (${path})
|
|
12118
12604
|
|
|
12119
12605
|
\`\`\`
|
|
12120
|
-
${
|
|
12606
|
+
${scopedTail || "<no log output>"}
|
|
12121
12607
|
\`\`\`
|
|
12122
12608
|
`;
|
|
12123
12609
|
}).join(`
|
|
12124
12610
|
`);
|
|
12125
12611
|
const errorScanWindow = adapters.map((adapter) => {
|
|
12126
12612
|
const path = adapter.getLogFile();
|
|
12127
|
-
|
|
12613
|
+
const tail = tailLogFile(path, 4000);
|
|
12614
|
+
const scopedTail = selectedBareSessionId ? filterLogToSession(tail, selectedBareSessionId) : tail;
|
|
12615
|
+
return sanitizeContent(scopedTail);
|
|
12128
12616
|
}).join(`
|
|
12129
12617
|
`);
|
|
12130
12618
|
const recentErrorLines = extractRecentErrors(errorScanWindow, 20);
|
|
@@ -12140,6 +12628,7 @@ ${tail || "<no log output>"}
|
|
|
12140
12628
|
`- AFT binary: ${report.binaryVersion ?? "unknown"}`,
|
|
12141
12629
|
`- OS: ${report.platform} ${report.arch}`,
|
|
12142
12630
|
`- Node: ${report.nodeVersion}`,
|
|
12631
|
+
...selectedSession ? [`- Session: ses_${selectedBareSessionId} (${truncateTitle(selectedSession.title)})`] : [],
|
|
12143
12632
|
"",
|
|
12144
12633
|
"## Diagnostics",
|
|
12145
12634
|
renderDiagnosticsMarkdown(report),
|
|
@@ -12153,14 +12642,35 @@ ${tail || "<no log output>"}
|
|
|
12153
12642
|
].join(`
|
|
12154
12643
|
`);
|
|
12155
12644
|
const body = capBodyToGithubLimit(sanitizeContent(rawBody));
|
|
12156
|
-
const
|
|
12157
|
-
|
|
12158
|
-
|
|
12159
|
-
|
|
12645
|
+
const reviewFile = writeIssueReviewFile(body);
|
|
12646
|
+
if (!reviewFile) {
|
|
12647
|
+
gt("Done — could not write the issue report.");
|
|
12648
|
+
return 1;
|
|
12649
|
+
}
|
|
12650
|
+
const outPath = reviewFile.path;
|
|
12160
12651
|
O2.success(`Wrote sanitized issue body to ${outPath}`);
|
|
12652
|
+
wt(`Open and review the report before filing:
|
|
12653
|
+
${outPath}
|
|
12654
|
+
|
|
12655
|
+
Home paths and your username have been stripped, but it still contains log lines and file paths from your project. Edit the file to remove anything you don't want public — your edits are used when you confirm below.`, "Review before filing");
|
|
12656
|
+
const proceed = await confirm("Have you reviewed the report above? File it as a GitHub issue now?", false);
|
|
12657
|
+
if (!proceed) {
|
|
12658
|
+
wt(`No issue filed. When ready, file manually at
|
|
12659
|
+
https://github.com/cortexkit/aft/issues/new and paste the contents of ${outPath}.`, "Skipped");
|
|
12660
|
+
gt("Done.");
|
|
12661
|
+
return 0;
|
|
12662
|
+
}
|
|
12663
|
+
const reviewedBody = readReviewedIssueFile(reviewFile);
|
|
12664
|
+
if (reviewedBody === null) {
|
|
12665
|
+
wt("No issue filed. Please review the report path above and file manually if needed.", "Skipped");
|
|
12666
|
+
gt("Done.");
|
|
12667
|
+
return 1;
|
|
12668
|
+
}
|
|
12669
|
+
const finalBody = capBodyToGithubLimit(sanitizeContent(reviewedBody));
|
|
12670
|
+
const finalTitle = deriveIssueTitleFromBody(finalBody);
|
|
12161
12671
|
if (isGhInstalled()) {
|
|
12162
12672
|
O2.info("Opening GitHub issue via `gh`…");
|
|
12163
|
-
const result = createGitHubIssue("cortexkit/aft",
|
|
12673
|
+
const result = createGitHubIssue("cortexkit/aft", finalTitle, finalBody);
|
|
12164
12674
|
if (result.url) {
|
|
12165
12675
|
O2.success(`Issue filed: ${result.url}`);
|
|
12166
12676
|
openBrowser(result.url);
|
|
@@ -12169,7 +12679,7 @@ ${tail || "<no log output>"}
|
|
|
12169
12679
|
}
|
|
12170
12680
|
O2.warn(`gh failed: ${result.stderr ?? "unknown error"}. Falling back to browser.`);
|
|
12171
12681
|
}
|
|
12172
|
-
const fallback = `https://github.com/cortexkit/aft/issues/new?title=${encodeURIComponent(
|
|
12682
|
+
const fallback = `https://github.com/cortexkit/aft/issues/new?title=${encodeURIComponent(finalTitle)}&body=${encodeURIComponent(finalBody)}`;
|
|
12173
12683
|
O2.info("Opening GitHub issue form in your browser…");
|
|
12174
12684
|
openBrowser(fallback);
|
|
12175
12685
|
wt(`If the browser didn't open, the sanitized body is at ${outPath}. Copy it into a new issue at https://github.com/cortexkit/aft/issues/new.`, "Fallback");
|
|
@@ -12183,11 +12693,13 @@ var init_doctor = __esm(async () => {
|
|
|
12183
12693
|
init_github();
|
|
12184
12694
|
init_harness_select();
|
|
12185
12695
|
init_issue_body();
|
|
12696
|
+
init_jsonc();
|
|
12186
12697
|
init_lsp_cache();
|
|
12187
12698
|
init_onnx_fix();
|
|
12188
12699
|
init_prompts();
|
|
12189
12700
|
init_sanitize();
|
|
12190
12701
|
init_self_version();
|
|
12702
|
+
init_sessions();
|
|
12191
12703
|
await __promiseAll([
|
|
12192
12704
|
init_binary_probe(),
|
|
12193
12705
|
init_diagnostics()
|
|
@@ -12218,6 +12730,7 @@ function printHelp() {
|
|
|
12218
12730
|
console.log(" -------");
|
|
12219
12731
|
console.log("");
|
|
12220
12732
|
console.log(" Commands:");
|
|
12733
|
+
console.log(" --version Show CLI, binary, and per-harness plugin versions");
|
|
12221
12734
|
console.log(" setup Interactive setup wizard");
|
|
12222
12735
|
console.log(" doctor Check and fix configuration issues");
|
|
12223
12736
|
console.log(" doctor lsp <file> Inspect LSP setup for one file");
|
|
@@ -12239,6 +12752,10 @@ function printHelp() {
|
|
|
12239
12752
|
console.log("");
|
|
12240
12753
|
}
|
|
12241
12754
|
async function main() {
|
|
12755
|
+
if (command === "--version" || command === "-v" || command === "-V" || command === "version") {
|
|
12756
|
+
const { runVersion: runVersion2 } = await init_version().then(() => exports_version);
|
|
12757
|
+
return runVersion2();
|
|
12758
|
+
}
|
|
12242
12759
|
if (command === "setup") {
|
|
12243
12760
|
const { runSetup: runSetup2 } = await Promise.resolve().then(() => (init_setup(), exports_setup));
|
|
12244
12761
|
return runSetup2(args);
|