@cortexkit/aft 0.34.0 → 0.35.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/adapters/opencode.d.ts.map +1 -1
- package/dist/adapters/pi.d.ts.map +1 -1
- package/dist/adapters/types.d.ts +6 -1
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/commands/doctor.d.ts +1 -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 +1977 -454
- package/dist/lib/binary-probe.d.ts.map +1 -1
- package/dist/lib/issue-body.d.ts +1 -0
- package/dist/lib/issue-body.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 +2 -2
package/dist/index.js
CHANGED
|
@@ -46,11 +46,1406 @@ 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
|
+
// ../aft-bridge/dist/active-logger.js
|
|
50
|
+
function loggerGlobal() {
|
|
51
|
+
return globalThis;
|
|
52
|
+
}
|
|
53
|
+
function getActiveLogger() {
|
|
54
|
+
return loggerGlobal()[ACTIVE_LOGGER_SYMBOL];
|
|
55
|
+
}
|
|
56
|
+
function getLogFilePath() {
|
|
57
|
+
try {
|
|
58
|
+
return getActiveLogger()?.getLogFilePath?.();
|
|
59
|
+
} catch (err) {
|
|
60
|
+
console.error(`[aft-bridge] ERROR: active logger getLogFilePath threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function log(message, meta) {
|
|
65
|
+
const active = getActiveLogger();
|
|
66
|
+
if (active) {
|
|
67
|
+
try {
|
|
68
|
+
active.log(message, meta);
|
|
69
|
+
} catch (err) {
|
|
70
|
+
console.error(`[aft-bridge] ERROR: active logger log threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
71
|
+
console.error(`[aft-bridge] ${message}`);
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
console.error(`[aft-bridge] ${message}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function warn(message, meta) {
|
|
78
|
+
const active = getActiveLogger();
|
|
79
|
+
if (active) {
|
|
80
|
+
try {
|
|
81
|
+
active.warn(message, meta);
|
|
82
|
+
} catch (err) {
|
|
83
|
+
console.error(`[aft-bridge] ERROR: active logger warn threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
84
|
+
console.error(`[aft-bridge] WARN: ${message}`);
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
console.error(`[aft-bridge] WARN: ${message}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function error(message, meta) {
|
|
91
|
+
const active = getActiveLogger();
|
|
92
|
+
if (active) {
|
|
93
|
+
try {
|
|
94
|
+
active.error(message, meta);
|
|
95
|
+
} catch (err) {
|
|
96
|
+
console.error(`[aft-bridge] ERROR: active logger error threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
97
|
+
console.error(`[aft-bridge] ERROR: ${message}`);
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
console.error(`[aft-bridge] ERROR: ${message}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
var ACTIVE_LOGGER_SYMBOL;
|
|
104
|
+
var init_active_logger = __esm(() => {
|
|
105
|
+
ACTIVE_LOGGER_SYMBOL = Symbol.for("aft-bridge-active-logger");
|
|
106
|
+
});
|
|
107
|
+
// ../aft-bridge/dist/status-bar.js
|
|
108
|
+
function parseStatusBarCounts(value) {
|
|
109
|
+
if (!value || typeof value !== "object")
|
|
110
|
+
return;
|
|
111
|
+
const record = value;
|
|
112
|
+
const num = (key) => {
|
|
113
|
+
const raw = record[key];
|
|
114
|
+
return typeof raw === "number" && Number.isFinite(raw) ? raw : 0;
|
|
115
|
+
};
|
|
116
|
+
return {
|
|
117
|
+
errors: num("errors"),
|
|
118
|
+
warnings: num("warnings"),
|
|
119
|
+
dead_code: num("dead_code"),
|
|
120
|
+
unused_exports: num("unused_exports"),
|
|
121
|
+
duplicates: num("duplicates"),
|
|
122
|
+
todos: num("todos"),
|
|
123
|
+
tier2_stale: record.tier2_stale === true
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ../aft-bridge/dist/bridge.js
|
|
128
|
+
import { spawn } from "node:child_process";
|
|
129
|
+
import { homedir } from "node:os";
|
|
130
|
+
import { join } from "node:path";
|
|
131
|
+
import { StringDecoder } from "node:string_decoder";
|
|
132
|
+
function tagStderrLine(line) {
|
|
133
|
+
return /^\[aft(-\w+)?\] /.test(line) ? line : `[aft] ${line}`;
|
|
134
|
+
}
|
|
135
|
+
function compareSemver(a, b) {
|
|
136
|
+
const [aMain, aPre] = a.split("-", 2);
|
|
137
|
+
const [bMain, bPre] = b.split("-", 2);
|
|
138
|
+
const aParts = aMain.split(".").map(Number);
|
|
139
|
+
const bParts = bMain.split(".").map(Number);
|
|
140
|
+
for (let i = 0;i < 3; i++) {
|
|
141
|
+
if (aParts[i] !== bParts[i])
|
|
142
|
+
return (aParts[i] ?? 0) - (bParts[i] ?? 0);
|
|
143
|
+
}
|
|
144
|
+
if (!aPre && !bPre)
|
|
145
|
+
return 0;
|
|
146
|
+
if (!aPre)
|
|
147
|
+
return 1;
|
|
148
|
+
if (!bPre)
|
|
149
|
+
return -1;
|
|
150
|
+
const aIds = aPre.split(".");
|
|
151
|
+
const bIds = bPre.split(".");
|
|
152
|
+
for (let i = 0;i < Math.max(aIds.length, bIds.length); i++) {
|
|
153
|
+
const ai = aIds[i];
|
|
154
|
+
const bi = bIds[i];
|
|
155
|
+
if (ai === undefined)
|
|
156
|
+
return -1;
|
|
157
|
+
if (bi === undefined)
|
|
158
|
+
return 1;
|
|
159
|
+
const aNum = /^\d+$/.test(ai);
|
|
160
|
+
const bNum = /^\d+$/.test(bi);
|
|
161
|
+
if (aNum && bNum) {
|
|
162
|
+
const diff = Number.parseInt(ai, 10) - Number.parseInt(bi, 10);
|
|
163
|
+
if (diff !== 0)
|
|
164
|
+
return diff;
|
|
165
|
+
} else if (aNum) {
|
|
166
|
+
return -1;
|
|
167
|
+
} else if (bNum) {
|
|
168
|
+
return 1;
|
|
169
|
+
} else {
|
|
170
|
+
const cmp = ai.localeCompare(bi);
|
|
171
|
+
if (cmp !== 0)
|
|
172
|
+
return cmp;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return 0;
|
|
176
|
+
}
|
|
177
|
+
function clampSemanticTimeout(configOverrides, bridgeTimeoutMs) {
|
|
178
|
+
const semantic = configOverrides.semantic;
|
|
179
|
+
if (!semantic || typeof semantic !== "object" || Array.isArray(semantic)) {
|
|
180
|
+
return configOverrides;
|
|
181
|
+
}
|
|
182
|
+
const timeoutMs = semantic.timeout_ms;
|
|
183
|
+
if (typeof timeoutMs !== "number" || !Number.isFinite(timeoutMs)) {
|
|
184
|
+
return configOverrides;
|
|
185
|
+
}
|
|
186
|
+
const maxSemanticTimeoutMs = bridgeTimeoutMs > SEMANTIC_TIMEOUT_SAFETY_MARGIN_MS ? bridgeTimeoutMs - SEMANTIC_TIMEOUT_SAFETY_MARGIN_MS : Math.max(1, bridgeTimeoutMs - 1);
|
|
187
|
+
if (timeoutMs <= maxSemanticTimeoutMs) {
|
|
188
|
+
return configOverrides;
|
|
189
|
+
}
|
|
190
|
+
warn(`semantic.timeout_ms=${timeoutMs} exceeds bridge timeout budget; clamping to ${maxSemanticTimeoutMs}ms (bridge timeout: ${bridgeTimeoutMs}ms)`);
|
|
191
|
+
return {
|
|
192
|
+
...configOverrides,
|
|
193
|
+
semantic: {
|
|
194
|
+
...semantic,
|
|
195
|
+
timeout_ms: maxSemanticTimeoutMs
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
var DEFAULT_BRIDGE_TIMEOUT_MS = 30000, BRIDGE_HANG_TIMEOUT_THRESHOLD = 2, SEMANTIC_TIMEOUT_SAFETY_MARGIN_MS = 5000, MAX_STDOUT_BUFFER, BridgeReplacedDuringVersionCheck, BinaryBridge;
|
|
200
|
+
var init_bridge = __esm(() => {
|
|
201
|
+
init_active_logger();
|
|
202
|
+
MAX_STDOUT_BUFFER = 64 * 1024 * 1024;
|
|
203
|
+
BridgeReplacedDuringVersionCheck = class BridgeReplacedDuringVersionCheck extends Error {
|
|
204
|
+
newBinaryPath;
|
|
205
|
+
constructor(newBinaryPath) {
|
|
206
|
+
super(`Bridge binary replaced during version check: ${newBinaryPath}`);
|
|
207
|
+
this.newBinaryPath = newBinaryPath;
|
|
208
|
+
this.name = "BridgeReplacedDuringVersionCheck";
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
BinaryBridge = class BinaryBridge {
|
|
212
|
+
static RESTART_RESET_MS = 5 * 60 * 1000;
|
|
213
|
+
static STDERR_TAIL_MAX = 20;
|
|
214
|
+
binaryPath;
|
|
215
|
+
cwd;
|
|
216
|
+
process = null;
|
|
217
|
+
pending = new Map;
|
|
218
|
+
nextId = 1;
|
|
219
|
+
stdoutBuffer = "";
|
|
220
|
+
stderrBuffer = "";
|
|
221
|
+
stderrTail = [];
|
|
222
|
+
_restartCount = 0;
|
|
223
|
+
_shuttingDown = false;
|
|
224
|
+
timeoutMs;
|
|
225
|
+
maxRestarts;
|
|
226
|
+
configured = false;
|
|
227
|
+
_configurePromise = null;
|
|
228
|
+
configOverrides;
|
|
229
|
+
minVersion;
|
|
230
|
+
onVersionMismatch;
|
|
231
|
+
onConfigureWarnings;
|
|
232
|
+
onBashCompletion;
|
|
233
|
+
onBashLongRunning;
|
|
234
|
+
onBashPatternMatch;
|
|
235
|
+
cachedStatus = null;
|
|
236
|
+
statusListeners = new Set;
|
|
237
|
+
configureWarningClients = new Map;
|
|
238
|
+
restartResetTimer = null;
|
|
239
|
+
lastChildActivityAt = 0;
|
|
240
|
+
lastStatusBar;
|
|
241
|
+
consecutiveRequestTimeouts = 0;
|
|
242
|
+
errorPrefix;
|
|
243
|
+
logger;
|
|
244
|
+
childEnv;
|
|
245
|
+
constructor(binaryPath, cwd, options, configOverrides) {
|
|
246
|
+
this.binaryPath = binaryPath;
|
|
247
|
+
this.cwd = cwd;
|
|
248
|
+
this.timeoutMs = options?.timeoutMs ?? DEFAULT_BRIDGE_TIMEOUT_MS;
|
|
249
|
+
this.maxRestarts = options?.maxRestarts ?? 3;
|
|
250
|
+
this.configOverrides = clampSemanticTimeout(configOverrides ?? {}, this.timeoutMs);
|
|
251
|
+
this.minVersion = options?.minVersion;
|
|
252
|
+
this.onVersionMismatch = options?.onVersionMismatch;
|
|
253
|
+
this.onConfigureWarnings = options?.onConfigureWarnings;
|
|
254
|
+
this.onBashCompletion = options?.onBashCompletion;
|
|
255
|
+
this.onBashLongRunning = options?.onBashLongRunning;
|
|
256
|
+
this.onBashPatternMatch = options?.onBashPatternMatch;
|
|
257
|
+
this.errorPrefix = options?.errorPrefix ?? "[aft-bridge]";
|
|
258
|
+
this.logger = options?.logger;
|
|
259
|
+
this.childEnv = options?.childEnv;
|
|
260
|
+
}
|
|
261
|
+
logVia(message, meta) {
|
|
262
|
+
const logger = this.logger ?? getActiveLogger();
|
|
263
|
+
if (logger) {
|
|
264
|
+
try {
|
|
265
|
+
logger.log(message, meta);
|
|
266
|
+
} catch (err) {
|
|
267
|
+
console.error(`[aft-bridge] ERROR: logger log threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
268
|
+
console.error(`[aft-bridge] ${message}`);
|
|
269
|
+
}
|
|
270
|
+
} else {
|
|
271
|
+
log(message, meta);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
warnVia(message, meta) {
|
|
275
|
+
const logger = this.logger ?? getActiveLogger();
|
|
276
|
+
if (logger) {
|
|
277
|
+
try {
|
|
278
|
+
logger.warn(message, meta);
|
|
279
|
+
} catch (err) {
|
|
280
|
+
console.error(`[aft-bridge] ERROR: logger warn threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
281
|
+
console.error(`[aft-bridge] WARN: ${message}`);
|
|
282
|
+
}
|
|
283
|
+
} else {
|
|
284
|
+
warn(message, meta);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
errorVia(message, meta) {
|
|
288
|
+
const logger = this.logger ?? getActiveLogger();
|
|
289
|
+
if (logger) {
|
|
290
|
+
try {
|
|
291
|
+
logger.error(message, meta);
|
|
292
|
+
} catch (err) {
|
|
293
|
+
console.error(`[aft-bridge] ERROR: logger error threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
294
|
+
console.error(`[aft-bridge] ERROR: ${message}`);
|
|
295
|
+
}
|
|
296
|
+
} else {
|
|
297
|
+
error(message, meta);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
getLogFilePathVia() {
|
|
301
|
+
if (this.logger?.getLogFilePath) {
|
|
302
|
+
try {
|
|
303
|
+
return this.logger.getLogFilePath();
|
|
304
|
+
} catch (err) {
|
|
305
|
+
console.error(`[aft-bridge] ERROR: logger getLogFilePath threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return getLogFilePath();
|
|
310
|
+
}
|
|
311
|
+
sessionLogVia(sessionId, message) {
|
|
312
|
+
this.logVia(message, sessionId ? { sessionId } : undefined);
|
|
313
|
+
}
|
|
314
|
+
sessionWarnVia(sessionId, message) {
|
|
315
|
+
this.warnVia(message, sessionId ? { sessionId } : undefined);
|
|
316
|
+
}
|
|
317
|
+
sessionErrorVia(sessionId, message) {
|
|
318
|
+
this.errorVia(message, sessionId ? { sessionId } : undefined);
|
|
319
|
+
}
|
|
320
|
+
get restartCount() {
|
|
321
|
+
return this._restartCount;
|
|
322
|
+
}
|
|
323
|
+
isAlive() {
|
|
324
|
+
return this.process !== null && this.process.exitCode === null && !this.process.killed;
|
|
325
|
+
}
|
|
326
|
+
hasPendingRequests() {
|
|
327
|
+
return this.pending.size > 0;
|
|
328
|
+
}
|
|
329
|
+
getCachedStatus() {
|
|
330
|
+
return this.cachedStatus;
|
|
331
|
+
}
|
|
332
|
+
subscribeStatus(listener) {
|
|
333
|
+
this.statusListeners.add(listener);
|
|
334
|
+
if (this.cachedStatus !== null) {
|
|
335
|
+
this.deliverStatusSnapshot(listener, this.cachedStatus);
|
|
336
|
+
}
|
|
337
|
+
return () => {
|
|
338
|
+
this.statusListeners.delete(listener);
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
cacheStatusSnapshot(snapshot) {
|
|
342
|
+
this.cachedStatus = snapshot;
|
|
343
|
+
}
|
|
344
|
+
async send(command, params = {}, options) {
|
|
345
|
+
return this.sendWithVersionMismatchRetry(command, params, options, true);
|
|
346
|
+
}
|
|
347
|
+
async sendWithVersionMismatchRetry(command, params, options, canRetryAfterVersionSwap) {
|
|
348
|
+
try {
|
|
349
|
+
if (this._shuttingDown) {
|
|
350
|
+
throw new Error(`${this.errorPrefix} Bridge is shutting down, cannot send "${command}"`);
|
|
351
|
+
}
|
|
352
|
+
if (Object.hasOwn(params, "id")) {
|
|
353
|
+
throw new Error("params cannot contain reserved key 'id'");
|
|
354
|
+
}
|
|
355
|
+
const requestSessionId = typeof params.session_id === "string" && params.session_id.length > 0 ? params.session_id : undefined;
|
|
356
|
+
this.ensureSpawned(requestSessionId);
|
|
357
|
+
if (requestSessionId && options?.configureWarningClient !== undefined) {
|
|
358
|
+
this.configureWarningClients.set(requestSessionId, options.configureWarningClient);
|
|
359
|
+
}
|
|
360
|
+
const effectiveTimeoutMs = options?.transportTimeoutMs ?? options?.timeoutMs ?? this.timeoutMs;
|
|
361
|
+
const implicitTransportOptions = {
|
|
362
|
+
...options?.transportTimeoutMs !== undefined || options?.timeoutMs !== undefined ? { transportTimeoutMs: effectiveTimeoutMs } : {},
|
|
363
|
+
markConfiguredOnSuccess: false
|
|
364
|
+
};
|
|
365
|
+
if (!this.configured) {
|
|
366
|
+
if (command !== "configure" && command !== "version") {
|
|
367
|
+
if (!this._configurePromise) {
|
|
368
|
+
const sessionIdForConfigure = typeof params.session_id === "string" ? params.session_id : undefined;
|
|
369
|
+
this._configurePromise = (async () => {
|
|
370
|
+
try {
|
|
371
|
+
const configResult = await this.send("configure", {
|
|
372
|
+
project_root: this.cwd,
|
|
373
|
+
...this.configOverrides,
|
|
374
|
+
...sessionIdForConfigure ? { session_id: sessionIdForConfigure } : {}
|
|
375
|
+
}, implicitTransportOptions);
|
|
376
|
+
if (configResult.success === false) {
|
|
377
|
+
throw new Error(`${this.errorPrefix} Configure failed: ${configResult.message ?? "unknown error"}`);
|
|
378
|
+
}
|
|
379
|
+
await this.deliverConfigureWarnings(configResult, params, options);
|
|
380
|
+
await this.checkVersion(implicitTransportOptions);
|
|
381
|
+
if (!this.isAlive()) {
|
|
382
|
+
throw new Error(`${this.errorPrefix} Bridge died during version check. Check logs: ${this.getLogFilePathVia()}`);
|
|
383
|
+
}
|
|
384
|
+
this.configured = true;
|
|
385
|
+
} finally {
|
|
386
|
+
this._configurePromise = null;
|
|
387
|
+
}
|
|
388
|
+
})();
|
|
389
|
+
}
|
|
390
|
+
await this._configurePromise;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
const id = String(this.nextId++);
|
|
394
|
+
let request;
|
|
395
|
+
if (Object.hasOwn(params, "command") || Object.hasOwn(params, "method")) {
|
|
396
|
+
const nested = { ...params };
|
|
397
|
+
const reserved = {};
|
|
398
|
+
for (const key of ["session_id", "lsp_hints"]) {
|
|
399
|
+
if (Object.hasOwn(nested, key)) {
|
|
400
|
+
reserved[key] = nested[key];
|
|
401
|
+
delete nested[key];
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
request = { id, command, ...reserved, params: nested };
|
|
405
|
+
} else {
|
|
406
|
+
request = { id, command, ...params };
|
|
407
|
+
}
|
|
408
|
+
const line = `${JSON.stringify(request)}
|
|
409
|
+
`;
|
|
410
|
+
const keepBridgeOnTimeout = options?.keepBridgeOnTimeout === true;
|
|
411
|
+
let requestSentAt = Date.now();
|
|
412
|
+
const response = await new Promise((resolve, reject) => {
|
|
413
|
+
const timer = setTimeout(() => {
|
|
414
|
+
const entry = this.pending.get(id);
|
|
415
|
+
if (!entry)
|
|
416
|
+
return;
|
|
417
|
+
this.pending.delete(id);
|
|
418
|
+
clearTimeout(entry.timer);
|
|
419
|
+
if (keepBridgeOnTimeout) {
|
|
420
|
+
const timeoutMsg2 = `Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`;
|
|
421
|
+
if (requestSessionId) {
|
|
422
|
+
this.sessionWarnVia(requestSessionId, timeoutMsg2);
|
|
423
|
+
} else {
|
|
424
|
+
this.warnVia(timeoutMsg2);
|
|
425
|
+
}
|
|
426
|
+
entry.reject(new Error(`${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`));
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
const childActiveSinceRequest = this.lastChildActivityAt > requestSentAt;
|
|
430
|
+
const consecutiveTimeouts = this.consecutiveRequestTimeouts + 1;
|
|
431
|
+
this.consecutiveRequestTimeouts = consecutiveTimeouts;
|
|
432
|
+
const keepWarm = childActiveSinceRequest || consecutiveTimeouts < BRIDGE_HANG_TIMEOUT_THRESHOLD;
|
|
433
|
+
const restartSuffix = keepWarm ? " — bridge kept warm" : " — restarting bridge";
|
|
434
|
+
const timeoutMsg = `Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms${restartSuffix}`;
|
|
435
|
+
if (requestSessionId) {
|
|
436
|
+
this.sessionWarnVia(requestSessionId, timeoutMsg);
|
|
437
|
+
} else {
|
|
438
|
+
this.warnVia(timeoutMsg);
|
|
439
|
+
}
|
|
440
|
+
if (keepWarm) {
|
|
441
|
+
entry.reject(new Error(`${this.errorPrefix} request "${command}" timed out after ${effectiveTimeoutMs}ms (bridge busy/under load); bridge kept warm — retry`));
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
entry.reject(new Error(`${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`));
|
|
445
|
+
this.handleTimeout(requestSessionId);
|
|
446
|
+
}, effectiveTimeoutMs);
|
|
447
|
+
this.pending.set(id, { resolve, reject, timer, onProgress: options?.onProgress });
|
|
448
|
+
if (!this.process?.stdin?.writable) {
|
|
449
|
+
this.pending.delete(id);
|
|
450
|
+
clearTimeout(timer);
|
|
451
|
+
reject(new Error(`${this.errorPrefix} stdin not writable for command "${command}"`));
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
requestSentAt = Date.now();
|
|
455
|
+
this.process.stdin.write(line, (err) => {
|
|
456
|
+
if (err) {
|
|
457
|
+
const entry = this.pending.get(id);
|
|
458
|
+
if (entry) {
|
|
459
|
+
this.pending.delete(id);
|
|
460
|
+
clearTimeout(entry.timer);
|
|
461
|
+
entry.reject(new Error(`${this.errorPrefix} Failed to write to stdin: ${err.message}`));
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
});
|
|
466
|
+
if (command === "configure" && response.success === true && options?.markConfiguredOnSuccess !== false) {
|
|
467
|
+
this.configured = true;
|
|
468
|
+
}
|
|
469
|
+
return response;
|
|
470
|
+
} catch (err) {
|
|
471
|
+
if (err instanceof BridgeReplacedDuringVersionCheck && canRetryAfterVersionSwap && command !== "configure" && command !== "version") {
|
|
472
|
+
this.logVia(`Retrying request "${command}" once after coordinated binary replacement: ${err.newBinaryPath}`);
|
|
473
|
+
return this.sendWithVersionMismatchRetry(command, params, options, false);
|
|
474
|
+
}
|
|
475
|
+
throw err;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
async deliverConfigureWarnings(configResult, params, options) {
|
|
479
|
+
if (!this.onConfigureWarnings || !Array.isArray(configResult.warnings))
|
|
480
|
+
return;
|
|
481
|
+
if (configResult.warnings.length === 0)
|
|
482
|
+
return;
|
|
483
|
+
const sessionId = typeof params.session_id === "string" ? params.session_id : undefined;
|
|
484
|
+
try {
|
|
485
|
+
await this.onConfigureWarnings({
|
|
486
|
+
projectRoot: this.cwd,
|
|
487
|
+
sessionId,
|
|
488
|
+
client: options?.configureWarningClient ?? (sessionId ? this.configureWarningClients.get(sessionId) : undefined),
|
|
489
|
+
warnings: configResult.warnings
|
|
490
|
+
});
|
|
491
|
+
} catch (err) {
|
|
492
|
+
this.warnVia(`configure warning delivery failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
493
|
+
} finally {
|
|
494
|
+
if (sessionId) {
|
|
495
|
+
this.configureWarningClients.delete(sessionId);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
async handleConfigureWarningsFrame(frame) {
|
|
500
|
+
if (!this.onConfigureWarnings)
|
|
501
|
+
return;
|
|
502
|
+
const warnings = frame.warnings;
|
|
503
|
+
if (!Array.isArray(warnings) || warnings.length === 0)
|
|
504
|
+
return;
|
|
505
|
+
const projectRoot = typeof frame.project_root === "string" ? frame.project_root : this.cwd;
|
|
506
|
+
const rawSessionId = frame.session_id;
|
|
507
|
+
const sessionId = typeof rawSessionId === "string" && rawSessionId.length > 0 ? rawSessionId : null;
|
|
508
|
+
try {
|
|
509
|
+
await this.onConfigureWarnings({
|
|
510
|
+
projectRoot,
|
|
511
|
+
sessionId,
|
|
512
|
+
client: sessionId ? this.configureWarningClients.get(sessionId) : undefined,
|
|
513
|
+
warnings
|
|
514
|
+
});
|
|
515
|
+
} finally {
|
|
516
|
+
if (sessionId) {
|
|
517
|
+
this.configureWarningClients.delete(sessionId);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
handleStatusChangedFrame(frame) {
|
|
522
|
+
const snapshot = frame.snapshot;
|
|
523
|
+
if (!snapshot || typeof snapshot !== "object" || Array.isArray(snapshot))
|
|
524
|
+
return;
|
|
525
|
+
this.cachedStatus = snapshot;
|
|
526
|
+
this.logVia("Received status_changed push frame; cached AFT status snapshot");
|
|
527
|
+
for (const listener of this.statusListeners) {
|
|
528
|
+
this.deliverStatusSnapshot(listener, this.cachedStatus);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
deliverStatusSnapshot(listener, snapshot) {
|
|
532
|
+
try {
|
|
533
|
+
listener(snapshot);
|
|
534
|
+
} catch (err) {
|
|
535
|
+
this.warnVia(`status listener threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
async shutdown() {
|
|
539
|
+
this._shuttingDown = true;
|
|
540
|
+
this.clearRestartResetTimer();
|
|
541
|
+
this.configureWarningClients.clear();
|
|
542
|
+
this.rejectAllPending(new Error(`${this.errorPrefix} Bridge shutting down`));
|
|
543
|
+
if (this.process) {
|
|
544
|
+
const proc = this.process;
|
|
545
|
+
this.process = null;
|
|
546
|
+
return new Promise((resolve) => {
|
|
547
|
+
const forceKillTimer = setTimeout(() => {
|
|
548
|
+
proc.kill("SIGKILL");
|
|
549
|
+
resolve();
|
|
550
|
+
}, 5000);
|
|
551
|
+
proc.once("exit", () => {
|
|
552
|
+
clearTimeout(forceKillTimer);
|
|
553
|
+
this.logVia("Process exited during shutdown");
|
|
554
|
+
resolve();
|
|
555
|
+
});
|
|
556
|
+
proc.kill("SIGTERM");
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
async checkVersion(options) {
|
|
561
|
+
if (!this.minVersion)
|
|
562
|
+
return;
|
|
563
|
+
try {
|
|
564
|
+
const resp = await this.send("version", {}, options);
|
|
565
|
+
if (resp.success === false) {
|
|
566
|
+
throw new Error(`Binary version check failed: ${String(resp.code ?? "unknown")} — likely too old`);
|
|
567
|
+
}
|
|
568
|
+
const binaryVersion = resp.version;
|
|
569
|
+
if (typeof binaryVersion !== "string") {
|
|
570
|
+
throw new Error(`Binary did not report a version — likely too old (minVersion: ${this.minVersion})`);
|
|
571
|
+
}
|
|
572
|
+
this.logVia(`Binary version: ${binaryVersion}`);
|
|
573
|
+
if (compareSemver(binaryVersion, this.minVersion) < 0) {
|
|
574
|
+
this.warnVia(`Binary version ${binaryVersion} is older than required ${this.minVersion}`);
|
|
575
|
+
const replacementPath = await this.onVersionMismatch?.(binaryVersion, this.minVersion);
|
|
576
|
+
if (replacementPath === undefined) {
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
if (replacementPath === null || replacementPath.length === 0) {
|
|
580
|
+
throw new Error(`Binary version ${binaryVersion} is older than required ${this.minVersion}; no compatible replacement binary was provided`);
|
|
581
|
+
}
|
|
582
|
+
await this.replaceCurrentBinary(replacementPath);
|
|
583
|
+
throw new BridgeReplacedDuringVersionCheck(replacementPath);
|
|
584
|
+
}
|
|
585
|
+
} catch (err) {
|
|
586
|
+
this.warnVia(`Version check failed: ${err.message}`);
|
|
587
|
+
throw err;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
async replaceCurrentBinary(newBinaryPath) {
|
|
591
|
+
this.binaryPath = newBinaryPath;
|
|
592
|
+
this.configured = false;
|
|
593
|
+
this.clearRestartResetTimer();
|
|
594
|
+
this.rejectAllPending(new Error(`${this.errorPrefix} Bridge restarting with updated binary: ${newBinaryPath}`));
|
|
595
|
+
if (!this.process)
|
|
596
|
+
return;
|
|
597
|
+
const proc = this.process;
|
|
598
|
+
this.process = null;
|
|
599
|
+
await new Promise((resolve) => {
|
|
600
|
+
const forceKillTimer = setTimeout(() => {
|
|
601
|
+
proc.kill("SIGKILL");
|
|
602
|
+
resolve();
|
|
603
|
+
}, 5000);
|
|
604
|
+
proc.once("exit", () => {
|
|
605
|
+
clearTimeout(forceKillTimer);
|
|
606
|
+
this.logVia("Process exited during coordinated binary replacement");
|
|
607
|
+
resolve();
|
|
608
|
+
});
|
|
609
|
+
proc.kill("SIGTERM");
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
ensureSpawned(triggeringSessionId) {
|
|
613
|
+
if (this.isAlive())
|
|
614
|
+
return;
|
|
615
|
+
this.spawnProcess(triggeringSessionId);
|
|
616
|
+
}
|
|
617
|
+
spawnProcess(triggeringSessionId) {
|
|
618
|
+
this.lastStatusBar = undefined;
|
|
619
|
+
if (triggeringSessionId) {
|
|
620
|
+
this.sessionLogVia(triggeringSessionId, `Spawning binary: ${this.binaryPath} (cwd: ${this.cwd})`);
|
|
621
|
+
} else {
|
|
622
|
+
this.logVia(`Spawning binary: ${this.binaryPath} (cwd: ${this.cwd})`);
|
|
623
|
+
}
|
|
624
|
+
const semantic = this.configOverrides.semantic;
|
|
625
|
+
const semanticBackend = (() => {
|
|
626
|
+
if (semantic && typeof semantic === "object" && !Array.isArray(semantic)) {
|
|
627
|
+
const candidate = semantic.backend;
|
|
628
|
+
return typeof candidate === "string" ? candidate : undefined;
|
|
629
|
+
}
|
|
630
|
+
return;
|
|
631
|
+
})();
|
|
632
|
+
const useFastembedBackend = semanticBackend === undefined || semanticBackend === "fastembed" || semanticBackend === "";
|
|
633
|
+
const ortDir = typeof this.configOverrides._ort_dylib_dir === "string" && useFastembedBackend ? this.configOverrides._ort_dylib_dir : null;
|
|
634
|
+
const ortLibraryPath = ortDir == null ? null : join(ortDir, process.platform === "win32" ? "onnxruntime.dll" : process.platform === "darwin" ? "libonnxruntime.dylib" : "libonnxruntime.so");
|
|
635
|
+
const envPath = process.platform === "win32" && ortDir ? `${ortDir};${process.env.PATH ?? ""}` : process.env.PATH;
|
|
636
|
+
const env = {
|
|
637
|
+
...process.env,
|
|
638
|
+
...envPath ? { PATH: envPath } : {}
|
|
639
|
+
};
|
|
640
|
+
this.logVia(`bridge.spawnProcess: useFastembedBackend=${useFastembedBackend}, ` + `parentORT=${process.env.ORT_DYLIB_PATH ?? "(unset)"}, ` + `ortLibraryPath=${ortLibraryPath ?? "(none)"}`);
|
|
641
|
+
if (useFastembedBackend) {
|
|
642
|
+
env.FASTEMBED_CACHE_DIR = process.env.FASTEMBED_CACHE_DIR || (typeof this.configOverrides.storage_dir === "string" ? join(this.configOverrides.storage_dir, "semantic", "models") : join(homedir() || "", ".cache", "fastembed"));
|
|
643
|
+
if (process.env.ORT_DYLIB_PATH) {
|
|
644
|
+
this.logVia(`ORT_DYLIB_PATH inherited from parent env: ${process.env.ORT_DYLIB_PATH}`);
|
|
645
|
+
} else if (ortLibraryPath) {
|
|
646
|
+
env.ORT_DYLIB_PATH = ortLibraryPath;
|
|
647
|
+
this.logVia(`ORT_DYLIB_PATH set from managed ONNX Runtime: ${ortLibraryPath}`);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
if (this.childEnv) {
|
|
651
|
+
for (const [key, value] of Object.entries(this.childEnv)) {
|
|
652
|
+
if (value === undefined) {
|
|
653
|
+
delete env[key];
|
|
654
|
+
} else {
|
|
655
|
+
env[key] = value;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
const child = spawn(this.binaryPath, [], {
|
|
660
|
+
cwd: this.cwd,
|
|
661
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
662
|
+
env
|
|
663
|
+
});
|
|
664
|
+
const currentChild = child;
|
|
665
|
+
const stdoutDecoder = new StringDecoder("utf8");
|
|
666
|
+
child.stdout?.on("data", (chunk) => {
|
|
667
|
+
this.onStdoutData(stdoutDecoder.write(chunk));
|
|
668
|
+
});
|
|
669
|
+
child.stdout?.on("end", () => {
|
|
670
|
+
const remaining = stdoutDecoder.end();
|
|
671
|
+
if (remaining)
|
|
672
|
+
this.onStdoutData(remaining);
|
|
673
|
+
});
|
|
674
|
+
const stderrDecoder = new StringDecoder("utf8");
|
|
675
|
+
child.stderr?.on("data", (chunk) => {
|
|
676
|
+
this.onStderrData(stderrDecoder.write(chunk));
|
|
677
|
+
});
|
|
678
|
+
child.stderr?.on("end", () => {
|
|
679
|
+
const remaining = stderrDecoder.end();
|
|
680
|
+
if (remaining)
|
|
681
|
+
this.onStderrData(remaining);
|
|
682
|
+
this.flushStderrBuffer();
|
|
683
|
+
});
|
|
684
|
+
child.on("error", (err) => {
|
|
685
|
+
if (this.process !== currentChild)
|
|
686
|
+
return;
|
|
687
|
+
this.errorVia(`Process error: ${err.message}${this.formatStderrTail()}`);
|
|
688
|
+
this.handleCrash();
|
|
689
|
+
});
|
|
690
|
+
child.on("exit", (code, signal) => {
|
|
691
|
+
if (this.process !== currentChild)
|
|
692
|
+
return;
|
|
693
|
+
if (this._shuttingDown)
|
|
694
|
+
return;
|
|
695
|
+
this.logVia(`Process exited: code=${code}, signal=${signal}`);
|
|
696
|
+
if (signal === "SIGTERM" || signal === "SIGKILL" || signal === "SIGHUP" || signal === "SIGINT") {
|
|
697
|
+
this.process = null;
|
|
698
|
+
this.configured = false;
|
|
699
|
+
this.clearRestartResetTimer();
|
|
700
|
+
this.rejectAllPending(new Error(`${this.errorPrefix} Binary killed by ${signal}`));
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
this.handleCrash();
|
|
704
|
+
});
|
|
705
|
+
this.process = child;
|
|
706
|
+
this.stdoutBuffer = "";
|
|
707
|
+
this.stderrBuffer = "";
|
|
708
|
+
this.lastChildActivityAt = 0;
|
|
709
|
+
this.consecutiveRequestTimeouts = 0;
|
|
710
|
+
this.stderrTail = [];
|
|
711
|
+
}
|
|
712
|
+
pushStderrLine(line) {
|
|
713
|
+
this.stderrTail.push(line);
|
|
714
|
+
if (this.stderrTail.length > BinaryBridge.STDERR_TAIL_MAX) {
|
|
715
|
+
this.stderrTail.shift();
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
onStderrData(data) {
|
|
719
|
+
this.stderrBuffer += data;
|
|
720
|
+
let newlineIdx;
|
|
721
|
+
while ((newlineIdx = this.stderrBuffer.indexOf(`
|
|
722
|
+
`)) !== -1) {
|
|
723
|
+
const line = this.stderrBuffer.slice(0, newlineIdx).replace(/\r$/, "");
|
|
724
|
+
this.stderrBuffer = this.stderrBuffer.slice(newlineIdx + 1);
|
|
725
|
+
if (!line)
|
|
726
|
+
continue;
|
|
727
|
+
const tagged = tagStderrLine(line);
|
|
728
|
+
this.logVia(tagged);
|
|
729
|
+
this.pushStderrLine(tagged);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
flushStderrBuffer() {
|
|
733
|
+
const line = this.stderrBuffer.replace(/\r$/, "");
|
|
734
|
+
this.stderrBuffer = "";
|
|
735
|
+
if (!line)
|
|
736
|
+
return;
|
|
737
|
+
const tagged = tagStderrLine(line);
|
|
738
|
+
this.logVia(tagged);
|
|
739
|
+
this.pushStderrLine(tagged);
|
|
740
|
+
}
|
|
741
|
+
formatStderrTail() {
|
|
742
|
+
if (this.stderrTail.length === 0)
|
|
743
|
+
return "";
|
|
744
|
+
const tail = this.stderrTail.join(`
|
|
745
|
+
`);
|
|
746
|
+
return `
|
|
747
|
+
--- last ${this.stderrTail.length} stderr lines ---
|
|
748
|
+
${tail}`;
|
|
749
|
+
}
|
|
750
|
+
onStdoutData(data) {
|
|
751
|
+
this.stdoutBuffer += data;
|
|
752
|
+
if (this.stdoutBuffer.length > MAX_STDOUT_BUFFER) {
|
|
753
|
+
this.handleCrash(new Error(`aft bridge stdout buffer exceeded ${MAX_STDOUT_BUFFER} bytes — killing bridge`));
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
let newlineIdx;
|
|
757
|
+
while ((newlineIdx = this.stdoutBuffer.indexOf(`
|
|
758
|
+
`)) !== -1) {
|
|
759
|
+
const line = this.stdoutBuffer.slice(0, newlineIdx).trim();
|
|
760
|
+
this.stdoutBuffer = this.stdoutBuffer.slice(newlineIdx + 1);
|
|
761
|
+
if (!line)
|
|
762
|
+
continue;
|
|
763
|
+
try {
|
|
764
|
+
const response = JSON.parse(line);
|
|
765
|
+
this.lastChildActivityAt = Date.now();
|
|
766
|
+
if (response.type === "progress") {
|
|
767
|
+
const requestId = response.request_id;
|
|
768
|
+
const entry = requestId ? this.pending.get(requestId) : undefined;
|
|
769
|
+
const kind = response.kind === "stderr" ? "stderr" : "stdout";
|
|
770
|
+
const text = typeof response.chunk === "string" ? response.chunk : "";
|
|
771
|
+
entry?.onProgress?.({ kind, text });
|
|
772
|
+
continue;
|
|
773
|
+
}
|
|
774
|
+
if (response.type === "permission_ask") {
|
|
775
|
+
const requestId = response.request_id;
|
|
776
|
+
const entry = requestId ? this.pending.get(requestId) : undefined;
|
|
777
|
+
if (requestId && entry) {
|
|
778
|
+
this.pending.delete(requestId);
|
|
779
|
+
clearTimeout(entry.timer);
|
|
780
|
+
entry.resolve({
|
|
781
|
+
success: false,
|
|
782
|
+
code: "permission_required",
|
|
783
|
+
message: "bash command requires permission",
|
|
784
|
+
asks: response.asks
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
continue;
|
|
788
|
+
}
|
|
789
|
+
if (response.type === "bash_completed") {
|
|
790
|
+
this.onBashCompletion?.(response, this);
|
|
791
|
+
continue;
|
|
792
|
+
}
|
|
793
|
+
if (response.type === "bash_long_running") {
|
|
794
|
+
this.onBashLongRunning?.(response, this);
|
|
795
|
+
continue;
|
|
796
|
+
}
|
|
797
|
+
if (response.type === "bash_pattern_match") {
|
|
798
|
+
this.onBashPatternMatch?.(response, this);
|
|
799
|
+
continue;
|
|
800
|
+
}
|
|
801
|
+
if (response.type === "configure_warnings") {
|
|
802
|
+
this.handleConfigureWarningsFrame(response).catch((err) => {
|
|
803
|
+
this.warnVia(`configure warning delivery failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
804
|
+
});
|
|
805
|
+
continue;
|
|
806
|
+
}
|
|
807
|
+
if (response.type === "status_changed") {
|
|
808
|
+
this.handleStatusChangedFrame(response);
|
|
809
|
+
continue;
|
|
810
|
+
}
|
|
811
|
+
const id = response.id;
|
|
812
|
+
if (id && this.pending.has(id)) {
|
|
813
|
+
const entry = this.pending.get(id);
|
|
814
|
+
if (!entry)
|
|
815
|
+
continue;
|
|
816
|
+
this.pending.delete(id);
|
|
817
|
+
clearTimeout(entry.timer);
|
|
818
|
+
this.consecutiveRequestTimeouts = 0;
|
|
819
|
+
this.scheduleRestartCountReset();
|
|
820
|
+
this.captureStatusBar(response);
|
|
821
|
+
entry.resolve(response);
|
|
822
|
+
} else if (typeof response.type === "string") {
|
|
823
|
+
this.logVia(`Ignoring unknown stdout push frame type: ${response.type}`);
|
|
824
|
+
}
|
|
825
|
+
} catch (_err) {
|
|
826
|
+
this.warnVia(`Failed to parse stdout line: ${line}`);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
captureStatusBar(response) {
|
|
831
|
+
const parsed = parseStatusBarCounts(response.status_bar);
|
|
832
|
+
if (parsed)
|
|
833
|
+
this.lastStatusBar = parsed;
|
|
834
|
+
}
|
|
835
|
+
getStatusBar() {
|
|
836
|
+
return this.lastStatusBar;
|
|
837
|
+
}
|
|
838
|
+
handleTimeout(triggeringSessionId) {
|
|
839
|
+
this.consecutiveRequestTimeouts = 0;
|
|
840
|
+
this.rejectAllPending(new Error(`${this.errorPrefix} bridge killed during sibling timeout — request aborted`));
|
|
841
|
+
if (this.process) {
|
|
842
|
+
this.process.kill("SIGKILL");
|
|
843
|
+
this.process = null;
|
|
844
|
+
}
|
|
845
|
+
this.clearRestartResetTimer();
|
|
846
|
+
this.configured = false;
|
|
847
|
+
const tail = this.formatStderrTail();
|
|
848
|
+
this.stderrTail = [];
|
|
849
|
+
const killedMsg = tail ? `Bridge killed after timeout.${tail}` : `Bridge killed after timeout (see ${this.getLogFilePathVia()})`;
|
|
850
|
+
if (tail) {
|
|
851
|
+
if (triggeringSessionId) {
|
|
852
|
+
this.sessionErrorVia(triggeringSessionId, killedMsg);
|
|
853
|
+
} else {
|
|
854
|
+
this.errorVia(killedMsg);
|
|
855
|
+
}
|
|
856
|
+
} else if (triggeringSessionId) {
|
|
857
|
+
this.sessionWarnVia(triggeringSessionId, killedMsg);
|
|
858
|
+
} else {
|
|
859
|
+
this.warnVia(killedMsg);
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
handleCrash(cause) {
|
|
863
|
+
const proc = this.process;
|
|
864
|
+
this.process = null;
|
|
865
|
+
if (proc && proc.exitCode === null && !proc.killed) {
|
|
866
|
+
proc.kill("SIGKILL");
|
|
867
|
+
}
|
|
868
|
+
this.clearRestartResetTimer();
|
|
869
|
+
this.configured = false;
|
|
870
|
+
const tail = this.formatStderrTail();
|
|
871
|
+
if (tail) {
|
|
872
|
+
this.errorVia(`Binary crashed (restarts: ${this._restartCount})${cause ? `: ${cause.message}` : ""}.${tail}`);
|
|
873
|
+
}
|
|
874
|
+
this.rejectAllPending(new Error(`${this.errorPrefix} Binary crashed (restarts: ${this._restartCount})${cause ? `: ${cause.message}` : ""} (see ${this.getLogFilePathVia()})`));
|
|
875
|
+
if (this._restartCount < this.maxRestarts) {
|
|
876
|
+
const delay = 100 * 2 ** this._restartCount;
|
|
877
|
+
this._restartCount++;
|
|
878
|
+
this.logVia(`Auto-restart #${this._restartCount} in ${delay}ms`);
|
|
879
|
+
setTimeout(() => {
|
|
880
|
+
if (!this._shuttingDown && !this.isAlive()) {
|
|
881
|
+
try {
|
|
882
|
+
this.spawnProcess();
|
|
883
|
+
} catch (err) {
|
|
884
|
+
this.errorVia(`Failed to restart: ${err.message}`);
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
}, delay);
|
|
888
|
+
this.scheduleRestartCountReset();
|
|
889
|
+
} else {
|
|
890
|
+
this.errorVia(`Max restarts (${this.maxRestarts}) reached, giving up. Logs: ${this.getLogFilePathVia()}${tail}`);
|
|
891
|
+
this.scheduleRestartCountReset();
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
rejectAllPending(error2) {
|
|
895
|
+
for (const [_id, entry] of this.pending) {
|
|
896
|
+
clearTimeout(entry.timer);
|
|
897
|
+
entry.reject(error2);
|
|
898
|
+
}
|
|
899
|
+
this.pending.clear();
|
|
900
|
+
}
|
|
901
|
+
scheduleRestartCountReset() {
|
|
902
|
+
this.clearRestartResetTimer();
|
|
903
|
+
this.restartResetTimer = setTimeout(() => {
|
|
904
|
+
this._restartCount = 0;
|
|
905
|
+
this.restartResetTimer = null;
|
|
906
|
+
}, BinaryBridge.RESTART_RESET_MS);
|
|
907
|
+
}
|
|
908
|
+
clearRestartResetTimer() {
|
|
909
|
+
if (this.restartResetTimer) {
|
|
910
|
+
clearTimeout(this.restartResetTimer);
|
|
911
|
+
this.restartResetTimer = null;
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
};
|
|
915
|
+
});
|
|
916
|
+
|
|
917
|
+
// ../aft-bridge/dist/platform.js
|
|
918
|
+
var init_platform = () => {};
|
|
919
|
+
|
|
920
|
+
// ../aft-bridge/dist/downloader.js
|
|
921
|
+
var MAX_DOWNLOAD_BYTES, DOWNLOAD_LOCK_STALE_MS;
|
|
922
|
+
var init_downloader = __esm(() => {
|
|
923
|
+
init_active_logger();
|
|
924
|
+
init_platform();
|
|
925
|
+
MAX_DOWNLOAD_BYTES = 200 * 1024 * 1024;
|
|
926
|
+
DOWNLOAD_LOCK_STALE_MS = 10 * 60000;
|
|
927
|
+
});
|
|
928
|
+
// ../aft-bridge/dist/paths.js
|
|
929
|
+
var init_paths = () => {};
|
|
930
|
+
|
|
931
|
+
// ../aft-bridge/dist/resolver.js
|
|
932
|
+
import { chmodSync, closeSync, copyFileSync, existsSync, mkdirSync, openSync, readSync, renameSync, unlinkSync } from "node:fs";
|
|
933
|
+
function isNativeExecutable(binaryPath) {
|
|
934
|
+
let fd = null;
|
|
935
|
+
try {
|
|
936
|
+
fd = openSync(binaryPath, "r");
|
|
937
|
+
const buf = Buffer.alloc(4);
|
|
938
|
+
const read = readSync(fd, buf, 0, 4, 0);
|
|
939
|
+
if (read < 2)
|
|
940
|
+
return false;
|
|
941
|
+
const b0 = buf[0];
|
|
942
|
+
const b1 = buf[1];
|
|
943
|
+
if (b0 === 35 && b1 === 33)
|
|
944
|
+
return false;
|
|
945
|
+
const m32 = buf.readUInt32BE(0);
|
|
946
|
+
const machO = new Set([4277009102, 4277009103, 3472551422, 3489328638, 3405691582]);
|
|
947
|
+
if (read >= 4 && machO.has(m32))
|
|
948
|
+
return true;
|
|
949
|
+
if (read >= 4 && m32 === 2135247942)
|
|
950
|
+
return true;
|
|
951
|
+
if (b0 === 77 && b1 === 90)
|
|
952
|
+
return true;
|
|
953
|
+
return false;
|
|
954
|
+
} catch {
|
|
955
|
+
return false;
|
|
956
|
+
} finally {
|
|
957
|
+
if (fd !== null) {
|
|
958
|
+
try {
|
|
959
|
+
closeSync(fd);
|
|
960
|
+
} catch {}
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
var init_resolver = __esm(() => {
|
|
965
|
+
init_active_logger();
|
|
966
|
+
init_downloader();
|
|
967
|
+
init_platform();
|
|
968
|
+
});
|
|
969
|
+
|
|
970
|
+
// ../aft-bridge/dist/migration.js
|
|
971
|
+
var DEFAULT_TIMEOUT_MS;
|
|
972
|
+
var init_migration = __esm(() => {
|
|
973
|
+
init_paths();
|
|
974
|
+
init_resolver();
|
|
975
|
+
DEFAULT_TIMEOUT_MS = 30 * 60 * 1000;
|
|
976
|
+
});
|
|
977
|
+
|
|
978
|
+
// ../aft-bridge/dist/onnx-runtime.js
|
|
979
|
+
var ORT_VERSION = "1.24.4", MAX_DOWNLOAD_BYTES2, MAX_EXTRACT_BYTES, STALE_LOCK_MS, ORT_PLATFORM_MAP;
|
|
980
|
+
var init_onnx_runtime = __esm(() => {
|
|
981
|
+
init_active_logger();
|
|
982
|
+
init_platform();
|
|
983
|
+
MAX_DOWNLOAD_BYTES2 = 256 * 1024 * 1024;
|
|
984
|
+
MAX_EXTRACT_BYTES = 1 * 1024 * 1024 * 1024;
|
|
985
|
+
STALE_LOCK_MS = 5 * 60 * 1000;
|
|
986
|
+
ORT_PLATFORM_MAP = {
|
|
987
|
+
darwin: {
|
|
988
|
+
arm64: {
|
|
989
|
+
assetName: `onnxruntime-osx-arm64-${ORT_VERSION}`,
|
|
990
|
+
libName: "libonnxruntime.dylib",
|
|
991
|
+
archiveType: "tgz"
|
|
992
|
+
}
|
|
993
|
+
},
|
|
994
|
+
linux: {
|
|
995
|
+
x64: {
|
|
996
|
+
assetName: `onnxruntime-linux-x64-${ORT_VERSION}`,
|
|
997
|
+
libName: "libonnxruntime.so",
|
|
998
|
+
archiveType: "tgz"
|
|
999
|
+
},
|
|
1000
|
+
arm64: {
|
|
1001
|
+
assetName: `onnxruntime-linux-aarch64-${ORT_VERSION}`,
|
|
1002
|
+
libName: "libonnxruntime.so",
|
|
1003
|
+
archiveType: "tgz"
|
|
1004
|
+
}
|
|
1005
|
+
},
|
|
1006
|
+
win32: {
|
|
1007
|
+
x64: {
|
|
1008
|
+
assetName: `onnxruntime-win-x64-${ORT_VERSION}`,
|
|
1009
|
+
libName: "onnxruntime.dll",
|
|
1010
|
+
archiveType: "zip"
|
|
1011
|
+
},
|
|
1012
|
+
arm64: {
|
|
1013
|
+
assetName: `onnxruntime-win-arm64-${ORT_VERSION}`,
|
|
1014
|
+
libName: "onnxruntime.dll",
|
|
1015
|
+
archiveType: "zip"
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
};
|
|
1019
|
+
});
|
|
1020
|
+
|
|
1021
|
+
// ../aft-bridge/dist/pool.js
|
|
1022
|
+
import { realpathSync } from "node:fs";
|
|
1023
|
+
|
|
1024
|
+
class BridgePool {
|
|
1025
|
+
bridges = new Map;
|
|
1026
|
+
staleBridges = new Set;
|
|
1027
|
+
binaryPath;
|
|
1028
|
+
maxPoolSize;
|
|
1029
|
+
idleTimeoutMs;
|
|
1030
|
+
bridgeOptions;
|
|
1031
|
+
configOverrides;
|
|
1032
|
+
projectConfigLoader;
|
|
1033
|
+
logger;
|
|
1034
|
+
cleanupTimer = null;
|
|
1035
|
+
constructor(binaryPath, options = {}, configOverrides = {}) {
|
|
1036
|
+
this.binaryPath = binaryPath;
|
|
1037
|
+
this.maxPoolSize = options.maxPoolSize ?? DEFAULT_MAX_POOL_SIZE;
|
|
1038
|
+
this.idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
|
|
1039
|
+
this.logger = options.logger;
|
|
1040
|
+
this.projectConfigLoader = options.projectConfigLoader;
|
|
1041
|
+
this.bridgeOptions = {
|
|
1042
|
+
timeoutMs: options.timeoutMs,
|
|
1043
|
+
maxRestarts: options.maxRestarts,
|
|
1044
|
+
minVersion: options.minVersion,
|
|
1045
|
+
onVersionMismatch: options.onVersionMismatch,
|
|
1046
|
+
onConfigureWarnings: options.onConfigureWarnings,
|
|
1047
|
+
onBashCompletion: options.onBashCompletion,
|
|
1048
|
+
onBashLongRunning: options.onBashLongRunning,
|
|
1049
|
+
onBashPatternMatch: options.onBashPatternMatch,
|
|
1050
|
+
errorPrefix: options.errorPrefix,
|
|
1051
|
+
logger: options.logger,
|
|
1052
|
+
childEnv: options.childEnv
|
|
1053
|
+
};
|
|
1054
|
+
this.configOverrides = configOverrides;
|
|
1055
|
+
if (Number.isFinite(this.idleTimeoutMs)) {
|
|
1056
|
+
this.cleanupTimer = setInterval(() => this.cleanup(), CLEANUP_INTERVAL_MS);
|
|
1057
|
+
this.cleanupTimer.unref();
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
getActiveBridgeForRoot(projectRoot) {
|
|
1061
|
+
const key = normalizeKey(projectRoot);
|
|
1062
|
+
const entry = this.bridges.get(key);
|
|
1063
|
+
if (!entry?.bridge.isAlive())
|
|
1064
|
+
return null;
|
|
1065
|
+
entry.lastUsed = Date.now();
|
|
1066
|
+
return entry.bridge;
|
|
1067
|
+
}
|
|
1068
|
+
getBridge(projectRoot) {
|
|
1069
|
+
const key = normalizeKey(projectRoot);
|
|
1070
|
+
const existing = this.bridges.get(key);
|
|
1071
|
+
if (existing) {
|
|
1072
|
+
existing.lastUsed = Date.now();
|
|
1073
|
+
return existing.bridge;
|
|
1074
|
+
}
|
|
1075
|
+
if (this.bridges.size >= this.maxPoolSize) {
|
|
1076
|
+
this.evictLRU();
|
|
1077
|
+
}
|
|
1078
|
+
let projectOverrides = {};
|
|
1079
|
+
if (this.projectConfigLoader) {
|
|
1080
|
+
try {
|
|
1081
|
+
projectOverrides = this.projectConfigLoader(key) ?? {};
|
|
1082
|
+
} catch (err) {
|
|
1083
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1084
|
+
this.error(`projectConfigLoader failed; using global overrides only: ${message}`);
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
const mergedOverrides = { ...this.configOverrides, ...projectOverrides };
|
|
1088
|
+
const bridge = new BinaryBridge(this.binaryPath, key, this.bridgeOptions, mergedOverrides);
|
|
1089
|
+
this.bridges.set(key, { bridge, lastUsed: Date.now() });
|
|
1090
|
+
return bridge;
|
|
1091
|
+
}
|
|
1092
|
+
cleanup() {
|
|
1093
|
+
const now = Date.now();
|
|
1094
|
+
for (const [dir, entry] of this.bridges) {
|
|
1095
|
+
if (entry.bridge.hasPendingRequests())
|
|
1096
|
+
continue;
|
|
1097
|
+
if (now - entry.lastUsed > this.idleTimeoutMs) {
|
|
1098
|
+
entry.bridge.shutdown().catch((err) => this.error("cleanup shutdown failed:", err));
|
|
1099
|
+
this.bridges.delete(dir);
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
for (const bridge of this.staleBridges) {
|
|
1103
|
+
if (bridge.hasPendingRequests())
|
|
1104
|
+
continue;
|
|
1105
|
+
bridge.shutdown().catch((err) => this.error("stale cleanup shutdown failed:", err));
|
|
1106
|
+
this.staleBridges.delete(bridge);
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
evictLRU() {
|
|
1110
|
+
let oldestDir = null;
|
|
1111
|
+
let oldestTime = Infinity;
|
|
1112
|
+
for (const [dir, entry] of this.bridges) {
|
|
1113
|
+
if (entry.bridge.hasPendingRequests())
|
|
1114
|
+
continue;
|
|
1115
|
+
if (entry.lastUsed < oldestTime) {
|
|
1116
|
+
oldestTime = entry.lastUsed;
|
|
1117
|
+
oldestDir = dir;
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
if (oldestDir) {
|
|
1121
|
+
const entry = this.bridges.get(oldestDir);
|
|
1122
|
+
entry?.bridge.shutdown().catch((err) => this.error("eviction shutdown failed:", err));
|
|
1123
|
+
this.bridges.delete(oldestDir);
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
async shutdown() {
|
|
1127
|
+
if (this.cleanupTimer) {
|
|
1128
|
+
clearInterval(this.cleanupTimer);
|
|
1129
|
+
this.cleanupTimer = null;
|
|
1130
|
+
}
|
|
1131
|
+
const shutdowns = [
|
|
1132
|
+
...Array.from(this.bridges.values(), (e) => e.bridge.shutdown()),
|
|
1133
|
+
...Array.from(this.staleBridges.values(), (bridge) => bridge.shutdown())
|
|
1134
|
+
];
|
|
1135
|
+
this.bridges.clear();
|
|
1136
|
+
this.staleBridges.clear();
|
|
1137
|
+
await Promise.allSettled(shutdowns);
|
|
1138
|
+
}
|
|
1139
|
+
async replaceBinary(newPath) {
|
|
1140
|
+
this.binaryPath = newPath;
|
|
1141
|
+
for (const entry of this.bridges.values()) {
|
|
1142
|
+
this.staleBridges.add(entry.bridge);
|
|
1143
|
+
}
|
|
1144
|
+
this.bridges.clear();
|
|
1145
|
+
this.log(`Binary path updated to ${newPath}. Active bridges marked stale — next calls will use the new binary.`);
|
|
1146
|
+
return newPath;
|
|
1147
|
+
}
|
|
1148
|
+
log(message, meta) {
|
|
1149
|
+
const logger = this.logger ?? getActiveLogger();
|
|
1150
|
+
if (logger) {
|
|
1151
|
+
try {
|
|
1152
|
+
logger.log(message, meta);
|
|
1153
|
+
} catch (err) {
|
|
1154
|
+
console.error(`[aft-bridge] ERROR: pool logger log threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
1155
|
+
console.error(`[aft-bridge] ${message}`);
|
|
1156
|
+
}
|
|
1157
|
+
} else
|
|
1158
|
+
log(message, meta);
|
|
1159
|
+
}
|
|
1160
|
+
error(message, meta) {
|
|
1161
|
+
const logger = this.logger ?? getActiveLogger();
|
|
1162
|
+
if (logger) {
|
|
1163
|
+
try {
|
|
1164
|
+
logger.error(message, meta);
|
|
1165
|
+
} catch (err) {
|
|
1166
|
+
console.error(`[aft-bridge] ERROR: pool logger error threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
1167
|
+
console.error(`[aft-bridge] ERROR: ${message}`);
|
|
1168
|
+
}
|
|
1169
|
+
} else
|
|
1170
|
+
error(message, meta);
|
|
1171
|
+
}
|
|
1172
|
+
setConfigureOverride(key, value) {
|
|
1173
|
+
if (value === undefined) {
|
|
1174
|
+
delete this.configOverrides[key];
|
|
1175
|
+
} else {
|
|
1176
|
+
this.configOverrides[key] = value;
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
get size() {
|
|
1180
|
+
return this.bridges.size;
|
|
1181
|
+
}
|
|
1182
|
+
_testGetConfigOverrides() {
|
|
1183
|
+
return { ...this.configOverrides };
|
|
1184
|
+
}
|
|
1185
|
+
_testGetBridgeOptions() {
|
|
1186
|
+
return { ...this.bridgeOptions };
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
function normalizeKey(projectRoot) {
|
|
1190
|
+
const stripped = projectRoot.replace(/[/\\]+$/, "");
|
|
1191
|
+
try {
|
|
1192
|
+
return realpathSync(stripped);
|
|
1193
|
+
} catch {
|
|
1194
|
+
return stripped;
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
var DEFAULT_IDLE_TIMEOUT_MS = Infinity, DEFAULT_MAX_POOL_SIZE = 8, CLEANUP_INTERVAL_MS;
|
|
1198
|
+
var init_pool = __esm(() => {
|
|
1199
|
+
init_active_logger();
|
|
1200
|
+
init_bridge();
|
|
1201
|
+
CLEANUP_INTERVAL_MS = 60 * 1000;
|
|
1202
|
+
});
|
|
1203
|
+
// ../aft-bridge/dist/index.js
|
|
1204
|
+
var init_dist = __esm(() => {
|
|
1205
|
+
init_active_logger();
|
|
1206
|
+
init_bridge();
|
|
1207
|
+
init_downloader();
|
|
1208
|
+
init_migration();
|
|
1209
|
+
init_onnx_runtime();
|
|
1210
|
+
init_paths();
|
|
1211
|
+
init_platform();
|
|
1212
|
+
init_pool();
|
|
1213
|
+
init_resolver();
|
|
1214
|
+
});
|
|
1215
|
+
|
|
1216
|
+
// src/lib/paths.ts
|
|
1217
|
+
import { homedir as homedir2, tmpdir } from "node:os";
|
|
1218
|
+
import { join as join2 } from "node:path";
|
|
1219
|
+
function getAftBinaryCacheDir() {
|
|
1220
|
+
if (process.env.AFT_CACHE_DIR) {
|
|
1221
|
+
return join2(process.env.AFT_CACHE_DIR, "bin");
|
|
1222
|
+
}
|
|
1223
|
+
if (process.platform === "win32") {
|
|
1224
|
+
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
1225
|
+
const base2 = localAppData || join2(homedir2(), "AppData", "Local");
|
|
1226
|
+
return join2(base2, "aft", "bin");
|
|
1227
|
+
}
|
|
1228
|
+
const base = process.env.XDG_CACHE_HOME || join2(homedir2(), ".cache");
|
|
1229
|
+
return join2(base, "aft", "bin");
|
|
1230
|
+
}
|
|
1231
|
+
function getAftBinaryName() {
|
|
1232
|
+
return process.platform === "win32" ? "aft.exe" : "aft";
|
|
1233
|
+
}
|
|
1234
|
+
function getAftLspPackagesDir() {
|
|
1235
|
+
if (process.env.AFT_CACHE_DIR) {
|
|
1236
|
+
return join2(process.env.AFT_CACHE_DIR, "lsp-packages");
|
|
1237
|
+
}
|
|
1238
|
+
if (process.platform === "win32") {
|
|
1239
|
+
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
1240
|
+
const base2 = localAppData || join2(homedir2(), "AppData", "Local");
|
|
1241
|
+
return join2(base2, "aft", "lsp-packages");
|
|
1242
|
+
}
|
|
1243
|
+
const base = process.env.XDG_CACHE_HOME || join2(homedir2(), ".cache");
|
|
1244
|
+
return join2(base, "aft", "lsp-packages");
|
|
1245
|
+
}
|
|
1246
|
+
function getAftLspBinariesDir() {
|
|
1247
|
+
if (process.env.AFT_CACHE_DIR) {
|
|
1248
|
+
return join2(process.env.AFT_CACHE_DIR, "lsp-binaries");
|
|
1249
|
+
}
|
|
1250
|
+
if (process.platform === "win32") {
|
|
1251
|
+
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
1252
|
+
const base2 = localAppData || join2(homedir2(), "AppData", "Local");
|
|
1253
|
+
return join2(base2, "aft", "lsp-binaries");
|
|
1254
|
+
}
|
|
1255
|
+
const base = process.env.XDG_CACHE_HOME || join2(homedir2(), ".cache");
|
|
1256
|
+
return join2(base, "aft", "lsp-binaries");
|
|
1257
|
+
}
|
|
1258
|
+
function homeDir() {
|
|
1259
|
+
if (process.platform === "win32")
|
|
1260
|
+
return process.env.USERPROFILE || process.env.HOME || homedir2();
|
|
1261
|
+
return process.env.HOME || homedir2();
|
|
1262
|
+
}
|
|
1263
|
+
function dataHome() {
|
|
1264
|
+
if (process.env.XDG_DATA_HOME)
|
|
1265
|
+
return process.env.XDG_DATA_HOME;
|
|
1266
|
+
if (process.platform === "win32") {
|
|
1267
|
+
return process.env.LOCALAPPDATA || process.env.APPDATA || join2(homeDir(), "AppData", "Local");
|
|
1268
|
+
}
|
|
1269
|
+
return join2(homeDir(), ".local", "share");
|
|
1270
|
+
}
|
|
1271
|
+
function getCortexKitStorageRoot() {
|
|
1272
|
+
return join2(dataHome(), "cortexkit", "aft");
|
|
1273
|
+
}
|
|
1274
|
+
function getTmpLogPath(filename) {
|
|
1275
|
+
return join2(tmpdir(), filename);
|
|
1276
|
+
}
|
|
1277
|
+
var init_paths2 = () => {};
|
|
1278
|
+
|
|
1279
|
+
// src/lib/binary-probe.ts
|
|
1280
|
+
import { execSync, spawnSync } from "node:child_process";
|
|
1281
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
1282
|
+
import { createRequire } from "node:module";
|
|
1283
|
+
import { homedir as homedir3 } from "node:os";
|
|
1284
|
+
import { join as join3 } from "node:path";
|
|
1285
|
+
async function loadPluginVersion() {
|
|
1286
|
+
try {
|
|
1287
|
+
const bridgePackageName = "@cortexkit/aft-bridge";
|
|
1288
|
+
const bridge = await import(bridgePackageName);
|
|
1289
|
+
if (typeof bridge.PLUGIN_VERSION === "string" && bridge.PLUGIN_VERSION.length > 0) {
|
|
1290
|
+
return bridge.PLUGIN_VERSION;
|
|
1291
|
+
}
|
|
1292
|
+
} catch {}
|
|
1293
|
+
const require2 = createRequire(import.meta.url);
|
|
1294
|
+
for (const relPath of [
|
|
1295
|
+
"../../../aft-bridge/package.json",
|
|
1296
|
+
"../../package.json",
|
|
1297
|
+
"../package.json"
|
|
1298
|
+
]) {
|
|
1299
|
+
try {
|
|
1300
|
+
const pkg = require2(relPath);
|
|
1301
|
+
if (typeof pkg.version === "string" && pkg.version.length > 0)
|
|
1302
|
+
return pkg.version;
|
|
1303
|
+
} catch {}
|
|
1304
|
+
}
|
|
1305
|
+
return "unknown";
|
|
1306
|
+
}
|
|
1307
|
+
function parseVersionOutput(output) {
|
|
1308
|
+
for (const line of output.split(/\r?\n/)) {
|
|
1309
|
+
const match = line.trim().match(VERSION_LINE);
|
|
1310
|
+
if (match?.[1])
|
|
1311
|
+
return match[1];
|
|
1312
|
+
}
|
|
1313
|
+
return null;
|
|
1314
|
+
}
|
|
1315
|
+
function majorMinor(version) {
|
|
1316
|
+
if (!version)
|
|
1317
|
+
return null;
|
|
1318
|
+
const match = version.trim().match(/^v?(\d+)\.(\d+)\.\d+(?:[-+][0-9A-Za-z.-]+)?$/);
|
|
1319
|
+
if (!match)
|
|
1320
|
+
return null;
|
|
1321
|
+
return `${match[1]}.${match[2]}`;
|
|
1322
|
+
}
|
|
1323
|
+
function versionMatchesExpected(candidate, expectedVersion) {
|
|
1324
|
+
const candidateMajorMinor = majorMinor(candidate);
|
|
1325
|
+
const expectedMajorMinor = majorMinor(expectedVersion);
|
|
1326
|
+
return candidateMajorMinor !== null && candidateMajorMinor === expectedMajorMinor;
|
|
1327
|
+
}
|
|
1328
|
+
function probeBinaryVersion(preferredVersion) {
|
|
1329
|
+
return probeAftBinary(preferredVersion).version;
|
|
1330
|
+
}
|
|
1331
|
+
function probeAftBinary(preferredVersion) {
|
|
1332
|
+
const expectedVersion = preferredVersion ?? PLUGIN_VERSION;
|
|
1333
|
+
const expectedMajorMinor = majorMinor(expectedVersion);
|
|
1334
|
+
const candidates = [];
|
|
1335
|
+
for (const candidate of aftBinaryCandidates(preferredVersion)) {
|
|
1336
|
+
try {
|
|
1337
|
+
if (!existsSync2(candidate))
|
|
1338
|
+
continue;
|
|
1339
|
+
const result = spawnSync(candidate, ["--version"], {
|
|
1340
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1341
|
+
encoding: "utf-8",
|
|
1342
|
+
timeout: 5000,
|
|
1343
|
+
env: process.env
|
|
1344
|
+
});
|
|
1345
|
+
const output = `${result.stdout ?? ""}
|
|
1346
|
+
${result.stderr ?? ""}`.trim();
|
|
1347
|
+
if (result.error || result.status !== 0) {
|
|
1348
|
+
candidates.push({
|
|
1349
|
+
path: candidate,
|
|
1350
|
+
status: "error",
|
|
1351
|
+
version: null,
|
|
1352
|
+
...output ? { output } : {},
|
|
1353
|
+
error: result.error?.message ?? `exit status ${result.status ?? "unknown"}`
|
|
1354
|
+
});
|
|
1355
|
+
continue;
|
|
1356
|
+
}
|
|
1357
|
+
const version = parseVersionOutput(output);
|
|
1358
|
+
if (!version) {
|
|
1359
|
+
candidates.push({ path: candidate, status: "invalid", version: null, output });
|
|
1360
|
+
continue;
|
|
1361
|
+
}
|
|
1362
|
+
if (!versionMatchesExpected(version, expectedVersion)) {
|
|
1363
|
+
candidates.push({ path: candidate, status: "unmatched", version, output });
|
|
1364
|
+
continue;
|
|
1365
|
+
}
|
|
1366
|
+
candidates.push({ path: candidate, status: "matched", version, output });
|
|
1367
|
+
return { version, path: candidate, expectedVersion, expectedMajorMinor, candidates };
|
|
1368
|
+
} catch (error2) {
|
|
1369
|
+
candidates.push({
|
|
1370
|
+
path: candidate,
|
|
1371
|
+
status: "error",
|
|
1372
|
+
version: null,
|
|
1373
|
+
error: error2 instanceof Error ? error2.message : String(error2)
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
return { version: null, path: null, expectedVersion, expectedMajorMinor, candidates };
|
|
1378
|
+
}
|
|
1379
|
+
function pushCandidate(candidates, candidate) {
|
|
1380
|
+
if (!candidate)
|
|
1381
|
+
return;
|
|
1382
|
+
if (!candidates.includes(candidate))
|
|
1383
|
+
candidates.push(candidate);
|
|
1384
|
+
}
|
|
1385
|
+
function firstExisting(candidates) {
|
|
1386
|
+
for (const candidate of candidates) {
|
|
1387
|
+
try {
|
|
1388
|
+
if (!existsSync2(candidate))
|
|
1389
|
+
continue;
|
|
1390
|
+
return candidate;
|
|
1391
|
+
} catch {}
|
|
1392
|
+
}
|
|
1393
|
+
return null;
|
|
1394
|
+
}
|
|
1395
|
+
function platformKey2(platform = process.platform, arch = process.arch) {
|
|
1396
|
+
const table = {
|
|
1397
|
+
darwin: { arm64: "darwin-arm64", x64: "darwin-x64" },
|
|
1398
|
+
linux: { arm64: "linux-arm64", x64: "linux-x64" },
|
|
1399
|
+
win32: { x64: "win32-x64" }
|
|
1400
|
+
};
|
|
1401
|
+
return table[platform]?.[arch] ?? null;
|
|
1402
|
+
}
|
|
1403
|
+
function aftBinaryCandidates(preferredVersion) {
|
|
1404
|
+
const candidates = [];
|
|
1405
|
+
if (preferredVersion) {
|
|
1406
|
+
const tag = preferredVersion.startsWith("v") ? preferredVersion : `v${preferredVersion}`;
|
|
1407
|
+
pushCandidate(candidates, join3(getAftBinaryCacheDir(), tag, getAftBinaryName()));
|
|
1408
|
+
}
|
|
1409
|
+
const key = platformKey2();
|
|
1410
|
+
if (key) {
|
|
1411
|
+
try {
|
|
1412
|
+
const require2 = createRequire(import.meta.url);
|
|
1413
|
+
pushCandidate(candidates, require2.resolve(`@cortexkit/aft-${key}/bin/${getAftBinaryName()}`));
|
|
1414
|
+
} catch {}
|
|
1415
|
+
}
|
|
1416
|
+
try {
|
|
1417
|
+
const lookup = process.platform === "win32" ? "where aft" : "which aft";
|
|
1418
|
+
const resolved = execSync(lookup, {
|
|
1419
|
+
stdio: "pipe",
|
|
1420
|
+
encoding: "utf-8",
|
|
1421
|
+
env: process.env
|
|
1422
|
+
}).trim();
|
|
1423
|
+
for (const line of resolved.split(/\r?\n/)) {
|
|
1424
|
+
const candidate = line.trim();
|
|
1425
|
+
if (candidate && isNativeExecutable(candidate)) {
|
|
1426
|
+
pushCandidate(candidates, candidate);
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
} catch {}
|
|
1430
|
+
pushCandidate(candidates, join3(homedir3(), ".cargo", "bin", getAftBinaryName()));
|
|
1431
|
+
return candidates;
|
|
1432
|
+
}
|
|
1433
|
+
function findAftBinary(preferredVersion) {
|
|
1434
|
+
return firstExisting(aftBinaryCandidates(preferredVersion));
|
|
1435
|
+
}
|
|
1436
|
+
var PLUGIN_VERSION, VERSION_LINE;
|
|
1437
|
+
var init_binary_probe = __esm(async () => {
|
|
1438
|
+
init_dist();
|
|
1439
|
+
init_paths2();
|
|
1440
|
+
PLUGIN_VERSION = await loadPluginVersion();
|
|
1441
|
+
VERSION_LINE = /^(?:aft\s+)?v?(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)$/i;
|
|
1442
|
+
});
|
|
1443
|
+
|
|
49
1444
|
// src/lib/fs-util.ts
|
|
50
|
-
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
51
|
-
import { join } from "node:path";
|
|
1445
|
+
import { existsSync as existsSync3, readdirSync, statSync } from "node:fs";
|
|
1446
|
+
import { join as join4 } from "node:path";
|
|
52
1447
|
function dirSize(path) {
|
|
53
|
-
if (!
|
|
1448
|
+
if (!existsSync3(path)) {
|
|
54
1449
|
return 0;
|
|
55
1450
|
}
|
|
56
1451
|
const stat = statSync(path);
|
|
@@ -62,7 +1457,7 @@ function dirSize(path) {
|
|
|
62
1457
|
}
|
|
63
1458
|
let total = 0;
|
|
64
1459
|
for (const entry of readdirSync(path)) {
|
|
65
|
-
total += dirSize(
|
|
1460
|
+
total += dirSize(join4(path, entry));
|
|
66
1461
|
}
|
|
67
1462
|
return total;
|
|
68
1463
|
}
|
|
@@ -4616,45 +6011,45 @@ var require_esprima = __commonJS((exports, module) => {
|
|
|
4616
6011
|
this.errors = [];
|
|
4617
6012
|
this.tolerant = false;
|
|
4618
6013
|
}
|
|
4619
|
-
ErrorHandler2.prototype.recordError = function(
|
|
4620
|
-
this.errors.push(
|
|
6014
|
+
ErrorHandler2.prototype.recordError = function(error2) {
|
|
6015
|
+
this.errors.push(error2);
|
|
4621
6016
|
};
|
|
4622
|
-
ErrorHandler2.prototype.tolerate = function(
|
|
6017
|
+
ErrorHandler2.prototype.tolerate = function(error2) {
|
|
4623
6018
|
if (this.tolerant) {
|
|
4624
|
-
this.recordError(
|
|
6019
|
+
this.recordError(error2);
|
|
4625
6020
|
} else {
|
|
4626
|
-
throw
|
|
6021
|
+
throw error2;
|
|
4627
6022
|
}
|
|
4628
6023
|
};
|
|
4629
6024
|
ErrorHandler2.prototype.constructError = function(msg, column) {
|
|
4630
|
-
var
|
|
6025
|
+
var error2 = new Error(msg);
|
|
4631
6026
|
try {
|
|
4632
|
-
throw
|
|
6027
|
+
throw error2;
|
|
4633
6028
|
} catch (base) {
|
|
4634
6029
|
if (Object.create && Object.defineProperty) {
|
|
4635
|
-
|
|
4636
|
-
Object.defineProperty(
|
|
6030
|
+
error2 = Object.create(base);
|
|
6031
|
+
Object.defineProperty(error2, "column", { value: column });
|
|
4637
6032
|
}
|
|
4638
6033
|
}
|
|
4639
|
-
return
|
|
6034
|
+
return error2;
|
|
4640
6035
|
};
|
|
4641
6036
|
ErrorHandler2.prototype.createError = function(index, line, col, description) {
|
|
4642
6037
|
var msg = "Line " + line + ": " + description;
|
|
4643
|
-
var
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
return
|
|
6038
|
+
var error2 = this.constructError(msg, col);
|
|
6039
|
+
error2.index = index;
|
|
6040
|
+
error2.lineNumber = line;
|
|
6041
|
+
error2.description = description;
|
|
6042
|
+
return error2;
|
|
4648
6043
|
};
|
|
4649
6044
|
ErrorHandler2.prototype.throwError = function(index, line, col, description) {
|
|
4650
6045
|
throw this.createError(index, line, col, description);
|
|
4651
6046
|
};
|
|
4652
6047
|
ErrorHandler2.prototype.tolerateError = function(index, line, col, description) {
|
|
4653
|
-
var
|
|
6048
|
+
var error2 = this.createError(index, line, col, description);
|
|
4654
6049
|
if (this.tolerant) {
|
|
4655
|
-
this.recordError(
|
|
6050
|
+
this.recordError(error2);
|
|
4656
6051
|
} else {
|
|
4657
|
-
throw
|
|
6052
|
+
throw error2;
|
|
4658
6053
|
}
|
|
4659
6054
|
};
|
|
4660
6055
|
return ErrorHandler2;
|
|
@@ -7324,19 +8719,19 @@ var require_parse = __commonJS((exports, module) => {
|
|
|
7324
8719
|
var symbolFor = (prefix) => Symbol.for(last_prop !== UNDEFINED ? prefix + COLON + last_prop : prefix);
|
|
7325
8720
|
var transform = (k, { value, context = {} }) => reviver ? reviver(k, value, context) : value;
|
|
7326
8721
|
var unexpected = () => {
|
|
7327
|
-
const
|
|
7328
|
-
Object.assign(
|
|
8722
|
+
const error2 = new SyntaxError(`Unexpected token '${current.value.slice(0, 1)}', "${current_code}" is not valid JSON`);
|
|
8723
|
+
Object.assign(error2, current.loc.start);
|
|
7329
8724
|
free();
|
|
7330
|
-
throw
|
|
8725
|
+
throw error2;
|
|
7331
8726
|
};
|
|
7332
8727
|
var unexpected_end = () => {
|
|
7333
|
-
const
|
|
7334
|
-
Object.assign(
|
|
8728
|
+
const error2 = new SyntaxError("Unexpected end of JSON input");
|
|
8729
|
+
Object.assign(error2, last ? last.loc.end : {
|
|
7335
8730
|
line: 1,
|
|
7336
8731
|
column: 0
|
|
7337
8732
|
});
|
|
7338
8733
|
free();
|
|
7339
|
-
throw
|
|
8734
|
+
throw error2;
|
|
7340
8735
|
};
|
|
7341
8736
|
var next = () => {
|
|
7342
8737
|
const new_token = tokens[++index];
|
|
@@ -7685,10 +9080,10 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
7685
9080
|
replacer = null;
|
|
7686
9081
|
indent = EMPTY;
|
|
7687
9082
|
};
|
|
7688
|
-
var
|
|
9083
|
+
var join5 = (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
9084
|
var join_content = (inside, value, gap) => {
|
|
7690
9085
|
const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
|
|
7691
|
-
return
|
|
9086
|
+
return join5(comment, inside, gap);
|
|
7692
9087
|
};
|
|
7693
9088
|
var stringify_string = (holder, key, value) => {
|
|
7694
9089
|
const raw = get_raw_string_literal(holder, key);
|
|
@@ -7710,13 +9105,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
7710
9105
|
if (i !== 0) {
|
|
7711
9106
|
inside += COMMA;
|
|
7712
9107
|
}
|
|
7713
|
-
const before =
|
|
9108
|
+
const before = join5(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
|
|
7714
9109
|
inside += before || LF + deeper_gap;
|
|
7715
9110
|
inside += stringify(i, value, deeper_gap) || STR_NULL;
|
|
7716
9111
|
inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
|
|
7717
9112
|
after_comma = process_comments(value, AFTER(i), deeper_gap);
|
|
7718
9113
|
}
|
|
7719
|
-
inside +=
|
|
9114
|
+
inside += join5(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
7720
9115
|
return BRACKET_OPEN + join_content(inside, value, gap) + BRACKET_CLOSE;
|
|
7721
9116
|
};
|
|
7722
9117
|
var object_stringify = (value, gap) => {
|
|
@@ -7737,13 +9132,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
7737
9132
|
inside += COMMA;
|
|
7738
9133
|
}
|
|
7739
9134
|
first = false;
|
|
7740
|
-
const before =
|
|
9135
|
+
const before = join5(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
|
|
7741
9136
|
inside += before || LF + deeper_gap;
|
|
7742
9137
|
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
9138
|
after_comma = process_comments(value, AFTER(key), deeper_gap);
|
|
7744
9139
|
};
|
|
7745
9140
|
keys.forEach(iteratee);
|
|
7746
|
-
inside +=
|
|
9141
|
+
inside += join5(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
7747
9142
|
return CURLY_BRACKET_OPEN + join_content(inside, value, gap) + CURLY_BRACKET_CLOSE;
|
|
7748
9143
|
};
|
|
7749
9144
|
function stringify(key, holder, gap) {
|
|
@@ -7836,42 +9231,42 @@ var require_src2 = __commonJS((exports, module) => {
|
|
|
7836
9231
|
});
|
|
7837
9232
|
|
|
7838
9233
|
// src/lib/jsonc.ts
|
|
7839
|
-
import { existsSync as
|
|
9234
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync, writeFileSync } from "node:fs";
|
|
7840
9235
|
import { dirname } from "node:path";
|
|
7841
9236
|
function detectJsoncFile(configDir, baseName) {
|
|
7842
9237
|
const jsoncPath = `${configDir}/${baseName}.jsonc`;
|
|
7843
9238
|
const jsonPath = `${configDir}/${baseName}.json`;
|
|
7844
|
-
if (
|
|
9239
|
+
if (existsSync4(jsoncPath)) {
|
|
7845
9240
|
return { path: jsoncPath, format: "jsonc" };
|
|
7846
9241
|
}
|
|
7847
|
-
if (
|
|
9242
|
+
if (existsSync4(jsonPath)) {
|
|
7848
9243
|
return { path: jsonPath, format: "json" };
|
|
7849
9244
|
}
|
|
7850
9245
|
return { path: jsonPath, format: "none" };
|
|
7851
9246
|
}
|
|
7852
9247
|
function readJsoncFile(path) {
|
|
7853
|
-
if (!
|
|
9248
|
+
if (!existsSync4(path)) {
|
|
7854
9249
|
return { value: null };
|
|
7855
9250
|
}
|
|
7856
9251
|
try {
|
|
7857
9252
|
const raw = readFileSync(path, "utf-8");
|
|
7858
9253
|
const value = import_comment_json.parse(raw);
|
|
7859
9254
|
return { value };
|
|
7860
|
-
} catch (
|
|
9255
|
+
} catch (error2) {
|
|
7861
9256
|
return {
|
|
7862
9257
|
value: null,
|
|
7863
|
-
error:
|
|
9258
|
+
error: error2 instanceof Error ? error2.message : String(error2)
|
|
7864
9259
|
};
|
|
7865
9260
|
}
|
|
7866
9261
|
}
|
|
7867
9262
|
function writeJsoncFile(path, value, format = "json") {
|
|
7868
|
-
|
|
9263
|
+
mkdirSync2(dirname(path), { recursive: true });
|
|
7869
9264
|
const serialized = format === "jsonc" ? import_comment_json.stringify(value, null, 2) : JSON.stringify(value, null, 2);
|
|
7870
9265
|
writeFileSync(path, `${serialized}
|
|
7871
9266
|
`);
|
|
7872
9267
|
}
|
|
7873
9268
|
function ensureAftSchemaUrl(path, format) {
|
|
7874
|
-
const existed =
|
|
9269
|
+
const existed = existsSync4(path);
|
|
7875
9270
|
if (!existed) {
|
|
7876
9271
|
const writeFormat = format === "jsonc" ? "jsonc" : "json";
|
|
7877
9272
|
writeJsoncFile(path, { $schema: AFT_SCHEMA_URL }, writeFormat);
|
|
@@ -7880,9 +9275,9 @@ function ensureAftSchemaUrl(path, format) {
|
|
|
7880
9275
|
message: `created ${path} with $schema URL for editor autocomplete`
|
|
7881
9276
|
};
|
|
7882
9277
|
}
|
|
7883
|
-
const { value, error } = readJsoncFile(path);
|
|
9278
|
+
const { value, error: error2 } = readJsoncFile(path);
|
|
7884
9279
|
if (!value) {
|
|
7885
|
-
throw new Error(
|
|
9280
|
+
throw new Error(error2 ? `failed to parse ${path}: ${error2}` : `failed to parse ${path}`);
|
|
7886
9281
|
}
|
|
7887
9282
|
const previous = value.$schema;
|
|
7888
9283
|
if (previous === AFT_SCHEMA_URL) {
|
|
@@ -7906,73 +9301,10 @@ var init_jsonc = __esm(() => {
|
|
|
7906
9301
|
import_comment_json = __toESM(require_src2(), 1);
|
|
7907
9302
|
});
|
|
7908
9303
|
|
|
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
9304
|
// src/lib/self-version.ts
|
|
7973
|
-
import { createRequire } from "node:module";
|
|
9305
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
7974
9306
|
function getSelfVersion() {
|
|
7975
|
-
const require2 =
|
|
9307
|
+
const require2 = createRequire2(import.meta.url);
|
|
7976
9308
|
for (const relPath of ["../../package.json", "../package.json"]) {
|
|
7977
9309
|
try {
|
|
7978
9310
|
const version = require2(relPath).version;
|
|
@@ -7986,27 +9318,53 @@ function getSelfVersion() {
|
|
|
7986
9318
|
var init_self_version = () => {};
|
|
7987
9319
|
|
|
7988
9320
|
// 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
|
|
9321
|
+
import { execSync as execSync2 } from "node:child_process";
|
|
9322
|
+
import { existsSync as existsSync5, readFileSync as readFileSync2, rmSync, statSync as statSync2 } from "node:fs";
|
|
9323
|
+
import { homedir as homedir4 } from "node:os";
|
|
9324
|
+
import { dirname as dirname2, join as join5, parse, resolve } from "node:path";
|
|
7993
9325
|
import { fileURLToPath } from "node:url";
|
|
7994
9326
|
function getOpenCodeConfigDir() {
|
|
7995
9327
|
const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
7996
9328
|
if (envDir)
|
|
7997
9329
|
return resolve(envDir);
|
|
7998
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
7999
|
-
return
|
|
9330
|
+
const xdg = process.env.XDG_CONFIG_HOME || join5(homedir4(), ".config");
|
|
9331
|
+
return join5(xdg, "opencode");
|
|
8000
9332
|
}
|
|
8001
9333
|
function getOpenCodeCacheDir() {
|
|
8002
9334
|
const xdg = process.env.XDG_CACHE_HOME;
|
|
8003
9335
|
if (xdg)
|
|
8004
|
-
return
|
|
9336
|
+
return join5(xdg, "opencode");
|
|
8005
9337
|
if (process.platform === "win32") {
|
|
8006
|
-
const localAppData = process.env.LOCALAPPDATA ??
|
|
8007
|
-
return
|
|
9338
|
+
const localAppData = process.env.LOCALAPPDATA ?? join5(homedir4(), "AppData", "Local");
|
|
9339
|
+
return join5(localAppData, "opencode");
|
|
9340
|
+
}
|
|
9341
|
+
return join5(homedir4(), ".cache", "opencode");
|
|
9342
|
+
}
|
|
9343
|
+
function hasOpenCodeCli() {
|
|
9344
|
+
try {
|
|
9345
|
+
execSync2("opencode --version", { stdio: "ignore", timeout: 5000 });
|
|
9346
|
+
return true;
|
|
9347
|
+
} catch {
|
|
9348
|
+
return false;
|
|
9349
|
+
}
|
|
9350
|
+
}
|
|
9351
|
+
function openCodeDesktopAppExists() {
|
|
9352
|
+
const candidates = [];
|
|
9353
|
+
if (process.platform === "darwin") {
|
|
9354
|
+
candidates.push("/Applications/OpenCode.app", "/Applications/OpenCode Beta.app", join5(homedir4(), "Applications", "OpenCode.app"), join5(homedir4(), "Applications", "OpenCode Beta.app"));
|
|
9355
|
+
} else if (process.platform === "win32") {
|
|
9356
|
+
const localAppData = process.env.LOCALAPPDATA ?? join5(homedir4(), "AppData", "Local");
|
|
9357
|
+
candidates.push(join5(localAppData, "Programs", "opencode"), join5(localAppData, "opencode"));
|
|
9358
|
+
} else {
|
|
9359
|
+
candidates.push("/opt/OpenCode", "/usr/lib/opencode", join5(homedir4(), ".local", "share", "applications", "opencode.desktop"));
|
|
8008
9360
|
}
|
|
8009
|
-
return
|
|
9361
|
+
return candidates.some((p) => {
|
|
9362
|
+
try {
|
|
9363
|
+
return existsSync5(p);
|
|
9364
|
+
} catch {
|
|
9365
|
+
return false;
|
|
9366
|
+
}
|
|
9367
|
+
});
|
|
8010
9368
|
}
|
|
8011
9369
|
function pathFromEntry(entry) {
|
|
8012
9370
|
if (entry.startsWith("file://")) {
|
|
@@ -8025,13 +9383,13 @@ function pathPointsToOurPlugin(entry) {
|
|
|
8025
9383
|
if (!fsPath)
|
|
8026
9384
|
return false;
|
|
8027
9385
|
try {
|
|
8028
|
-
if (!
|
|
9386
|
+
if (!existsSync5(fsPath))
|
|
8029
9387
|
return false;
|
|
8030
9388
|
let searchDir = statSync2(fsPath).isDirectory() ? fsPath : dirname2(fsPath);
|
|
8031
9389
|
let pkgJsonPath = null;
|
|
8032
9390
|
while (true) {
|
|
8033
|
-
const candidate =
|
|
8034
|
-
if (
|
|
9391
|
+
const candidate = join5(searchDir, "package.json");
|
|
9392
|
+
if (existsSync5(candidate)) {
|
|
8035
9393
|
pkgJsonPath = candidate;
|
|
8036
9394
|
break;
|
|
8037
9395
|
}
|
|
@@ -8062,16 +9420,19 @@ class OpenCodeAdapter {
|
|
|
8062
9420
|
pluginPackageName = PLUGIN_NAME;
|
|
8063
9421
|
pluginEntryWithVersion = PLUGIN_ENTRY;
|
|
8064
9422
|
isInstalled() {
|
|
8065
|
-
|
|
8066
|
-
execSync("opencode --version", { stdio: "ignore" });
|
|
9423
|
+
if (existsSync5(getOpenCodeConfigDir()))
|
|
8067
9424
|
return true;
|
|
8068
|
-
|
|
8069
|
-
return
|
|
8070
|
-
|
|
9425
|
+
if (openCodeDesktopAppExists())
|
|
9426
|
+
return true;
|
|
9427
|
+
return hasOpenCodeCli();
|
|
8071
9428
|
}
|
|
8072
9429
|
getHostVersion() {
|
|
8073
9430
|
try {
|
|
8074
|
-
return
|
|
9431
|
+
return execSync2("opencode --version", {
|
|
9432
|
+
encoding: "utf-8",
|
|
9433
|
+
stdio: "pipe",
|
|
9434
|
+
timeout: 5000
|
|
9435
|
+
}).trim();
|
|
8075
9436
|
} catch {
|
|
8076
9437
|
return null;
|
|
8077
9438
|
}
|
|
@@ -8110,12 +9471,12 @@ class OpenCodeAdapter {
|
|
|
8110
9471
|
configPath
|
|
8111
9472
|
};
|
|
8112
9473
|
}
|
|
8113
|
-
const { value, error } = readJsoncFile(configPath);
|
|
8114
|
-
if (
|
|
9474
|
+
const { value, error: error2 } = readJsoncFile(configPath);
|
|
9475
|
+
if (error2 || !value) {
|
|
8115
9476
|
return {
|
|
8116
9477
|
ok: false,
|
|
8117
9478
|
action: "error",
|
|
8118
|
-
message: `Could not parse ${configPath}: ${
|
|
9479
|
+
message: `Could not parse ${configPath}: ${error2 ?? "unknown error"}`,
|
|
8119
9480
|
configPath
|
|
8120
9481
|
};
|
|
8121
9482
|
}
|
|
@@ -8140,11 +9501,11 @@ class OpenCodeAdapter {
|
|
|
8140
9501
|
};
|
|
8141
9502
|
}
|
|
8142
9503
|
getPluginCacheInfo() {
|
|
8143
|
-
const path =
|
|
9504
|
+
const path = join5(getOpenCodeCacheDir(), "packages", PLUGIN_ENTRY);
|
|
8144
9505
|
let cached;
|
|
8145
9506
|
try {
|
|
8146
|
-
const installedPkgPath =
|
|
8147
|
-
if (
|
|
9507
|
+
const installedPkgPath = join5(path, "node_modules", "@cortexkit", "aft-opencode", "package.json");
|
|
9508
|
+
if (existsSync5(installedPkgPath)) {
|
|
8148
9509
|
const pkg = JSON.parse(readFileSync2(installedPkgPath, "utf-8"));
|
|
8149
9510
|
cached = typeof pkg.version === "string" ? pkg.version : undefined;
|
|
8150
9511
|
}
|
|
@@ -8155,7 +9516,7 @@ class OpenCodeAdapter {
|
|
|
8155
9516
|
path,
|
|
8156
9517
|
cached,
|
|
8157
9518
|
latest: getSelfVersion(),
|
|
8158
|
-
exists:
|
|
9519
|
+
exists: existsSync5(path)
|
|
8159
9520
|
};
|
|
8160
9521
|
}
|
|
8161
9522
|
getStorageDir() {
|
|
@@ -8188,13 +9549,13 @@ class OpenCodeAdapter {
|
|
|
8188
9549
|
cached: info.cached,
|
|
8189
9550
|
latest: info.latest
|
|
8190
9551
|
};
|
|
8191
|
-
} catch (
|
|
9552
|
+
} catch (error2) {
|
|
8192
9553
|
return {
|
|
8193
9554
|
action: "error",
|
|
8194
9555
|
path: info.path,
|
|
8195
9556
|
cached: info.cached,
|
|
8196
9557
|
latest: info.latest,
|
|
8197
|
-
error:
|
|
9558
|
+
error: error2 instanceof Error ? error2.message : String(error2)
|
|
8198
9559
|
};
|
|
8199
9560
|
}
|
|
8200
9561
|
}
|
|
@@ -8204,11 +9565,11 @@ class OpenCodeAdapter {
|
|
|
8204
9565
|
describeStorageSubtrees() {
|
|
8205
9566
|
const storage = this.getStorageDir();
|
|
8206
9567
|
return {
|
|
8207
|
-
index: dirSize(
|
|
8208
|
-
semantic: dirSize(
|
|
8209
|
-
backups: dirSize(
|
|
8210
|
-
url_cache: dirSize(
|
|
8211
|
-
onnxruntime: dirSize(
|
|
9568
|
+
index: dirSize(join5(storage, "index")),
|
|
9569
|
+
semantic: dirSize(join5(storage, "semantic")),
|
|
9570
|
+
backups: dirSize(join5(storage, "backups")),
|
|
9571
|
+
url_cache: dirSize(join5(storage, "url_cache")),
|
|
9572
|
+
onnxruntime: dirSize(join5(storage, "onnxruntime"))
|
|
8212
9573
|
};
|
|
8213
9574
|
}
|
|
8214
9575
|
}
|
|
@@ -8216,24 +9577,24 @@ var PLUGIN_NAME = "@cortexkit/aft-opencode", PLUGIN_ENTRY;
|
|
|
8216
9577
|
var init_opencode = __esm(() => {
|
|
8217
9578
|
init_fs_util();
|
|
8218
9579
|
init_jsonc();
|
|
8219
|
-
|
|
9580
|
+
init_paths2();
|
|
8220
9581
|
init_self_version();
|
|
8221
9582
|
PLUGIN_ENTRY = `${PLUGIN_NAME}@latest`;
|
|
8222
9583
|
});
|
|
8223
9584
|
|
|
8224
9585
|
// src/adapters/pi.ts
|
|
8225
|
-
import { execSync as
|
|
8226
|
-
import { existsSync as
|
|
8227
|
-
import { homedir as
|
|
8228
|
-
import { join as
|
|
9586
|
+
import { execSync as execSync3, spawnSync as spawnSync2 } from "node:child_process";
|
|
9587
|
+
import { existsSync as existsSync6, readFileSync as readFileSync3 } from "node:fs";
|
|
9588
|
+
import { homedir as homedir5 } from "node:os";
|
|
9589
|
+
import { join as join6 } from "node:path";
|
|
8229
9590
|
function getPiAgentDir() {
|
|
8230
9591
|
const envHome = process.platform === "win32" ? process.env.USERPROFILE : process.env.HOME;
|
|
8231
|
-
const home = envHome && envHome.length > 0 ? envHome :
|
|
8232
|
-
return
|
|
9592
|
+
const home = envHome && envHome.length > 0 ? envHome : homedir5();
|
|
9593
|
+
return join6(home, ".pi", "agent");
|
|
8233
9594
|
}
|
|
8234
9595
|
function readPiExtensionIndex() {
|
|
8235
|
-
const settingsPath =
|
|
8236
|
-
if (
|
|
9596
|
+
const settingsPath = join6(getPiAgentDir(), "settings.json");
|
|
9597
|
+
if (existsSync6(settingsPath)) {
|
|
8237
9598
|
try {
|
|
8238
9599
|
const raw = readFileSync3(settingsPath, "utf-8");
|
|
8239
9600
|
const trimmed = raw.replace(/^\uFEFF/, "");
|
|
@@ -8246,13 +9607,13 @@ function readPiExtensionIndex() {
|
|
|
8246
9607
|
} catch {}
|
|
8247
9608
|
}
|
|
8248
9609
|
const candidates = [
|
|
8249
|
-
|
|
8250
|
-
|
|
8251
|
-
|
|
8252
|
-
|
|
9610
|
+
join6(getPiAgentDir(), "extensions.json"),
|
|
9611
|
+
join6(getPiAgentDir(), "extensions.jsonc"),
|
|
9612
|
+
join6(getPiAgentDir(), "config.json"),
|
|
9613
|
+
join6(getPiAgentDir(), "config.jsonc")
|
|
8253
9614
|
];
|
|
8254
9615
|
for (const path of candidates) {
|
|
8255
|
-
if (!
|
|
9616
|
+
if (!existsSync6(path))
|
|
8256
9617
|
continue;
|
|
8257
9618
|
try {
|
|
8258
9619
|
const { value } = readJsoncFile(path);
|
|
@@ -8285,15 +9646,15 @@ function piEntryMatchesAft(entry) {
|
|
|
8285
9646
|
} else if (entry.startsWith("/")) {
|
|
8286
9647
|
resolved = entry;
|
|
8287
9648
|
} else if (entry.length > 0) {
|
|
8288
|
-
resolved =
|
|
9649
|
+
resolved = join6(getPiAgentDir(), entry);
|
|
8289
9650
|
}
|
|
8290
9651
|
if (!resolved)
|
|
8291
9652
|
return false;
|
|
8292
9653
|
try {
|
|
8293
|
-
if (!
|
|
9654
|
+
if (!existsSync6(resolved))
|
|
8294
9655
|
return false;
|
|
8295
|
-
const pkgPath =
|
|
8296
|
-
if (!
|
|
9656
|
+
const pkgPath = join6(resolved, "package.json");
|
|
9657
|
+
if (!existsSync6(pkgPath))
|
|
8297
9658
|
return false;
|
|
8298
9659
|
const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
|
|
8299
9660
|
return pkg.name === PLUGIN_NAME2;
|
|
@@ -8313,7 +9674,7 @@ class PiAdapter {
|
|
|
8313
9674
|
pluginEntryWithVersion = PLUGIN_ENTRY2;
|
|
8314
9675
|
isInstalled() {
|
|
8315
9676
|
try {
|
|
8316
|
-
|
|
9677
|
+
execSync3("pi --version", { stdio: "ignore", timeout: 5000 });
|
|
8317
9678
|
return true;
|
|
8318
9679
|
} catch {
|
|
8319
9680
|
return false;
|
|
@@ -8321,9 +9682,10 @@ class PiAdapter {
|
|
|
8321
9682
|
}
|
|
8322
9683
|
getHostVersion() {
|
|
8323
9684
|
try {
|
|
8324
|
-
const result =
|
|
9685
|
+
const result = spawnSync2("pi", ["--version"], {
|
|
8325
9686
|
stdio: ["ignore", "pipe", "pipe"],
|
|
8326
|
-
encoding: "utf-8"
|
|
9687
|
+
encoding: "utf-8",
|
|
9688
|
+
timeout: 5000
|
|
8327
9689
|
});
|
|
8328
9690
|
if (result.status !== 0)
|
|
8329
9691
|
return null;
|
|
@@ -8342,7 +9704,7 @@ class PiAdapter {
|
|
|
8342
9704
|
const aft = detectJsoncFile(configDir, "aft");
|
|
8343
9705
|
return {
|
|
8344
9706
|
configDir,
|
|
8345
|
-
harnessConfig: index.path ??
|
|
9707
|
+
harnessConfig: index.path ?? join6(configDir, "extensions.json"),
|
|
8346
9708
|
harnessConfigFormat: index.path ? "json" : "none",
|
|
8347
9709
|
aftConfig: aft.path,
|
|
8348
9710
|
aftConfigFormat: aft.format
|
|
@@ -8369,29 +9731,29 @@ class PiAdapter {
|
|
|
8369
9731
|
};
|
|
8370
9732
|
}
|
|
8371
9733
|
try {
|
|
8372
|
-
|
|
9734
|
+
execSync3(`pi install ${PLUGIN_ENTRY2}`, { stdio: "inherit" });
|
|
8373
9735
|
return {
|
|
8374
9736
|
ok: true,
|
|
8375
9737
|
action: "added",
|
|
8376
9738
|
message: `Installed ${PLUGIN_ENTRY2} via \`pi install\``,
|
|
8377
9739
|
configPath: this.detectConfigPaths().harnessConfig
|
|
8378
9740
|
};
|
|
8379
|
-
} catch (
|
|
9741
|
+
} catch (error2) {
|
|
8380
9742
|
return {
|
|
8381
9743
|
ok: false,
|
|
8382
9744
|
action: "error",
|
|
8383
|
-
message: `Failed to run \`pi install ${PLUGIN_ENTRY2}\`: ${
|
|
9745
|
+
message: `Failed to run \`pi install ${PLUGIN_ENTRY2}\`: ${error2 instanceof Error ? error2.message : String(error2)}`,
|
|
8384
9746
|
configPath: this.detectConfigPaths().harnessConfig
|
|
8385
9747
|
};
|
|
8386
9748
|
}
|
|
8387
9749
|
}
|
|
8388
9750
|
getPluginCacheInfo() {
|
|
8389
9751
|
const candidates = [
|
|
8390
|
-
|
|
8391
|
-
|
|
9752
|
+
join6(getPiAgentDir(), "node_modules", "@cortexkit", "aft-pi", "package.json"),
|
|
9753
|
+
join6(getPiAgentDir(), "extensions", "node_modules", "@cortexkit", "aft-pi", "package.json")
|
|
8392
9754
|
];
|
|
8393
9755
|
for (const candidate of candidates) {
|
|
8394
|
-
if (!
|
|
9756
|
+
if (!existsSync6(candidate))
|
|
8395
9757
|
continue;
|
|
8396
9758
|
try {
|
|
8397
9759
|
const pkg = JSON.parse(readFileSync3(candidate, "utf-8"));
|
|
@@ -8405,7 +9767,7 @@ class PiAdapter {
|
|
|
8405
9767
|
} catch {}
|
|
8406
9768
|
}
|
|
8407
9769
|
return {
|
|
8408
|
-
path:
|
|
9770
|
+
path: join6(getPiAgentDir(), "extensions"),
|
|
8409
9771
|
exists: false
|
|
8410
9772
|
};
|
|
8411
9773
|
}
|
|
@@ -8427,11 +9789,11 @@ class PiAdapter {
|
|
|
8427
9789
|
describeStorageSubtrees() {
|
|
8428
9790
|
const storage = this.getStorageDir();
|
|
8429
9791
|
return {
|
|
8430
|
-
index: dirSize(
|
|
8431
|
-
semantic: dirSize(
|
|
8432
|
-
backups: dirSize(
|
|
8433
|
-
url_cache: dirSize(
|
|
8434
|
-
onnxruntime: dirSize(
|
|
9792
|
+
index: dirSize(join6(storage, "index")),
|
|
9793
|
+
semantic: dirSize(join6(storage, "semantic")),
|
|
9794
|
+
backups: dirSize(join6(storage, "backups")),
|
|
9795
|
+
url_cache: dirSize(join6(storage, "url_cache")),
|
|
9796
|
+
onnxruntime: dirSize(join6(storage, "onnxruntime"))
|
|
8435
9797
|
};
|
|
8436
9798
|
}
|
|
8437
9799
|
}
|
|
@@ -8439,11 +9801,14 @@ var PLUGIN_NAME2 = "@cortexkit/aft-pi", PLUGIN_ENTRY2;
|
|
|
8439
9801
|
var init_pi = __esm(() => {
|
|
8440
9802
|
init_fs_util();
|
|
8441
9803
|
init_jsonc();
|
|
8442
|
-
|
|
9804
|
+
init_paths2();
|
|
8443
9805
|
PLUGIN_ENTRY2 = `npm:${PLUGIN_NAME2}`;
|
|
8444
9806
|
});
|
|
8445
9807
|
|
|
8446
9808
|
// src/adapters/index.ts
|
|
9809
|
+
function getAllAdapters() {
|
|
9810
|
+
return ALL;
|
|
9811
|
+
}
|
|
8447
9812
|
function getAdapter(kind) {
|
|
8448
9813
|
const found = ALL.find((a) => a.kind === kind);
|
|
8449
9814
|
if (!found)
|
|
@@ -8614,7 +9979,7 @@ var ANSI_RE, CONTROL_RE, TAB_RE, EMOJI_RE, LATIN_RE, MODIFIER_RE, NO_TRUNCATION,
|
|
|
8614
9979
|
ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
|
|
8615
9980
|
};
|
|
8616
9981
|
}, dist_default;
|
|
8617
|
-
var
|
|
9982
|
+
var init_dist2 = __esm(() => {
|
|
8618
9983
|
init_utils();
|
|
8619
9984
|
ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/y;
|
|
8620
9985
|
CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
|
|
@@ -8630,8 +9995,8 @@ var init_dist = __esm(() => {
|
|
|
8630
9995
|
var NO_TRUNCATION2, fastStringWidth = (input, options = {}) => {
|
|
8631
9996
|
return dist_default(input, NO_TRUNCATION2, options).width;
|
|
8632
9997
|
}, dist_default2;
|
|
8633
|
-
var
|
|
8634
|
-
|
|
9998
|
+
var init_dist3 = __esm(() => {
|
|
9999
|
+
init_dist2();
|
|
8635
10000
|
NO_TRUNCATION2 = {
|
|
8636
10001
|
limit: Infinity,
|
|
8637
10002
|
ellipsis: "",
|
|
@@ -8834,7 +10199,7 @@ var ESC = "\x1B", CSI = "", END_CODE = 39, ANSI_ESCAPE_BELL = "\x07", ANSI_CSI
|
|
|
8834
10199
|
return returnValue;
|
|
8835
10200
|
}, CRLF_OR_LF;
|
|
8836
10201
|
var init_main = __esm(() => {
|
|
8837
|
-
|
|
10202
|
+
init_dist3();
|
|
8838
10203
|
ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
|
|
8839
10204
|
GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
|
|
8840
10205
|
CRLF_OR_LF = /\r?\n/;
|
|
@@ -9114,7 +10479,7 @@ var import_sisteransi, E, G, u, Y, C, O = (r) => ("columns" in r) && typeof r.co
|
|
|
9114
10479
|
}
|
|
9115
10480
|
}
|
|
9116
10481
|
}, H, Q, X, et, st, it, nt, at;
|
|
9117
|
-
var
|
|
10482
|
+
var init_dist4 = __esm(() => {
|
|
9118
10483
|
init_main();
|
|
9119
10484
|
import_sisteransi = __toESM(require_src3(), 1);
|
|
9120
10485
|
E = ["up", "down", "left", "right", "space", "enter", "cancel"];
|
|
@@ -9736,11 +11101,11 @@ ${c2}
|
|
|
9736
11101
|
}
|
|
9737
11102
|
}
|
|
9738
11103
|
} }).prompt();
|
|
9739
|
-
var
|
|
9740
|
-
|
|
9741
|
-
|
|
11104
|
+
var init_dist5 = __esm(() => {
|
|
11105
|
+
init_dist4();
|
|
11106
|
+
init_dist4();
|
|
9742
11107
|
init_main();
|
|
9743
|
-
|
|
11108
|
+
init_dist3();
|
|
9744
11109
|
import_sisteransi2 = __toESM(require_src3(), 1);
|
|
9745
11110
|
ee = Ze();
|
|
9746
11111
|
_e = w2("◆", "*");
|
|
@@ -9850,7 +11215,7 @@ async function text(message, options = {}) {
|
|
|
9850
11215
|
return result;
|
|
9851
11216
|
}
|
|
9852
11217
|
var init_prompts = __esm(() => {
|
|
9853
|
-
|
|
11218
|
+
init_dist5();
|
|
9854
11219
|
});
|
|
9855
11220
|
|
|
9856
11221
|
// src/lib/harness-select.ts
|
|
@@ -9903,11 +11268,59 @@ async function resolveAdaptersForCommand(argv, options) {
|
|
|
9903
11268
|
})), installed.map((a) => a.kind));
|
|
9904
11269
|
return picks.map((kind) => getAdapter(kind));
|
|
9905
11270
|
}
|
|
11271
|
+
function getAllRegistryAdapters() {
|
|
11272
|
+
return getAllAdapters();
|
|
11273
|
+
}
|
|
9906
11274
|
var init_harness_select = __esm(() => {
|
|
9907
11275
|
init_adapters();
|
|
9908
11276
|
init_prompts();
|
|
9909
11277
|
});
|
|
9910
11278
|
|
|
11279
|
+
// src/commands/version.ts
|
|
11280
|
+
var exports_version = {};
|
|
11281
|
+
__export(exports_version, {
|
|
11282
|
+
runVersion: () => runVersion
|
|
11283
|
+
});
|
|
11284
|
+
function runVersion() {
|
|
11285
|
+
const cliVersion = getSelfVersion();
|
|
11286
|
+
const binaryVersion = probeBinaryVersion();
|
|
11287
|
+
const lines = [];
|
|
11288
|
+
lines.push("");
|
|
11289
|
+
lines.push(" AFT versions");
|
|
11290
|
+
lines.push("");
|
|
11291
|
+
lines.push(` @cortexkit/aft (this CLI) v${cliVersion}`);
|
|
11292
|
+
lines.push(` aft binary ${binaryVersion ?? "not installed"}`);
|
|
11293
|
+
lines.push("");
|
|
11294
|
+
const adapters = getAllRegistryAdapters();
|
|
11295
|
+
const labelWidth = Math.max(...adapters.map((adapter) => adapter.displayName.length));
|
|
11296
|
+
for (const adapter of adapters) {
|
|
11297
|
+
const label = adapter.displayName.padEnd(labelWidth);
|
|
11298
|
+
if (!adapter.isInstalled()) {
|
|
11299
|
+
lines.push(` ${label} host not installed`);
|
|
11300
|
+
continue;
|
|
11301
|
+
}
|
|
11302
|
+
const host = adapter.getHostVersion() ?? "unknown";
|
|
11303
|
+
const registered = adapter.hasPluginEntry();
|
|
11304
|
+
let pluginPart;
|
|
11305
|
+
if (!registered) {
|
|
11306
|
+
pluginPart = "plugin not registered";
|
|
11307
|
+
} else {
|
|
11308
|
+
const cached = adapter.getPluginCacheInfo().cached;
|
|
11309
|
+
pluginPart = cached ? `plugin ${cached}` : "plugin registered (version unknown)";
|
|
11310
|
+
}
|
|
11311
|
+
lines.push(` ${label} host ${host} · ${pluginPart}`);
|
|
11312
|
+
}
|
|
11313
|
+
lines.push("");
|
|
11314
|
+
console.log(lines.join(`
|
|
11315
|
+
`));
|
|
11316
|
+
return 0;
|
|
11317
|
+
}
|
|
11318
|
+
var init_version = __esm(async () => {
|
|
11319
|
+
init_harness_select();
|
|
11320
|
+
init_self_version();
|
|
11321
|
+
await init_binary_probe();
|
|
11322
|
+
});
|
|
11323
|
+
|
|
9911
11324
|
// src/commands/setup.ts
|
|
9912
11325
|
var exports_setup = {};
|
|
9913
11326
|
__export(exports_setup, {
|
|
@@ -9950,8 +11363,8 @@ async function runSetup(argv) {
|
|
|
9950
11363
|
if (schemaResult.action === "added" || schemaResult.action === "updated") {
|
|
9951
11364
|
O2.success(`${adapter.displayName}: ${schemaResult.message}`);
|
|
9952
11365
|
}
|
|
9953
|
-
} catch (
|
|
9954
|
-
O2.warn(`${adapter.displayName}: could not set $schema on aft.jsonc: ${
|
|
11366
|
+
} catch (error2) {
|
|
11367
|
+
O2.warn(`${adapter.displayName}: could not set $schema on aft.jsonc: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
9955
11368
|
}
|
|
9956
11369
|
printNextSteps(adapter);
|
|
9957
11370
|
}
|
|
@@ -9986,7 +11399,7 @@ var init_setup = __esm(() => {
|
|
|
9986
11399
|
});
|
|
9987
11400
|
|
|
9988
11401
|
// src/lib/aft-bridge.ts
|
|
9989
|
-
import { spawn } from "node:child_process";
|
|
11402
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
9990
11403
|
function isResponseForRequest(parsed, expectedIds) {
|
|
9991
11404
|
if (!parsed || typeof parsed !== "object")
|
|
9992
11405
|
return false;
|
|
@@ -9998,7 +11411,7 @@ function isResponseForRequest(parsed, expectedIds) {
|
|
|
9998
11411
|
}
|
|
9999
11412
|
async function sendAftRequests(binaryPath, requests) {
|
|
10000
11413
|
return new Promise((resolve2, reject) => {
|
|
10001
|
-
const child =
|
|
11414
|
+
const child = spawn2(binaryPath, [], {
|
|
10002
11415
|
stdio: ["pipe", "pipe", "pipe"]
|
|
10003
11416
|
});
|
|
10004
11417
|
const responses = [];
|
|
@@ -10056,8 +11469,8 @@ async function sendAftRequests(binaryPath, requests) {
|
|
|
10056
11469
|
child.stderr.on("data", (chunk) => {
|
|
10057
11470
|
stderr += chunk;
|
|
10058
11471
|
});
|
|
10059
|
-
child.on("error", (
|
|
10060
|
-
finish(() => reject(
|
|
11472
|
+
child.on("error", (error2) => {
|
|
11473
|
+
finish(() => reject(error2));
|
|
10061
11474
|
});
|
|
10062
11475
|
child.on("close", (code) => {
|
|
10063
11476
|
if (settled)
|
|
@@ -10101,167 +11514,6 @@ ${stderrTrimmed}`);
|
|
|
10101
11514
|
var MAX_NOISE_LINES_IN_ERROR = 5;
|
|
10102
11515
|
var init_aft_bridge = () => {};
|
|
10103
11516
|
|
|
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
11517
|
// src/commands/lsp.ts
|
|
10266
11518
|
var exports_lsp = {};
|
|
10267
11519
|
__export(exports_lsp, {
|
|
@@ -10270,20 +11522,20 @@ __export(exports_lsp, {
|
|
|
10270
11522
|
printLspDoctorHelp: () => printLspDoctorHelp,
|
|
10271
11523
|
findProjectRootForFile: () => findProjectRootForFile
|
|
10272
11524
|
});
|
|
10273
|
-
import { existsSync as
|
|
10274
|
-
import { dirname as dirname3, join as
|
|
11525
|
+
import { existsSync as existsSync7, readdirSync as readdirSync2, statSync as statSync3 } from "node:fs";
|
|
11526
|
+
import { dirname as dirname3, join as join7, resolve as resolve2 } from "node:path";
|
|
10275
11527
|
function findProjectRootForFile(filePath, fallbackCwd = process.cwd()) {
|
|
10276
11528
|
const resolvedFile = resolve2(fallbackCwd, filePath);
|
|
10277
11529
|
let dir = dirname3(resolvedFile);
|
|
10278
11530
|
try {
|
|
10279
|
-
if (
|
|
11531
|
+
if (existsSync7(resolvedFile) && statSync3(resolvedFile).isDirectory()) {
|
|
10280
11532
|
dir = resolvedFile;
|
|
10281
11533
|
}
|
|
10282
11534
|
} catch {
|
|
10283
11535
|
dir = dirname3(resolvedFile);
|
|
10284
11536
|
}
|
|
10285
11537
|
while (true) {
|
|
10286
|
-
if (PROJECT_ROOT_MARKERS.some((marker) =>
|
|
11538
|
+
if (PROJECT_ROOT_MARKERS.some((marker) => existsSync7(join7(dir, marker)))) {
|
|
10287
11539
|
return dir;
|
|
10288
11540
|
}
|
|
10289
11541
|
const parent = dirname3(dir);
|
|
@@ -10313,8 +11565,8 @@ async function runLspDoctor(options) {
|
|
|
10313
11565
|
O2.error("No harness selected.");
|
|
10314
11566
|
return 1;
|
|
10315
11567
|
}
|
|
10316
|
-
const
|
|
10317
|
-
const binary =
|
|
11568
|
+
const findBinary2 = options.findBinary ?? findAftBinary;
|
|
11569
|
+
const binary = findBinary2(getSelfVersion());
|
|
10318
11570
|
if (!binary) {
|
|
10319
11571
|
O2.error("Could not find the aft binary in the cache, platform package, PATH, or ~/.cargo/bin.");
|
|
10320
11572
|
return 1;
|
|
@@ -10421,11 +11673,11 @@ function buildConfigureParams(adapter, projectRoot) {
|
|
|
10421
11673
|
}
|
|
10422
11674
|
function readProjectConfig(kind, projectRoot) {
|
|
10423
11675
|
const dir = kind === "pi" ? ".pi" : ".opencode";
|
|
10424
|
-
const jsonc =
|
|
10425
|
-
const json =
|
|
10426
|
-
if (
|
|
11676
|
+
const jsonc = join7(projectRoot, dir, "aft.jsonc");
|
|
11677
|
+
const json = join7(projectRoot, dir, "aft.json");
|
|
11678
|
+
if (existsSync7(jsonc))
|
|
10427
11679
|
return readJsoncFile(jsonc).value ?? {};
|
|
10428
|
-
if (
|
|
11680
|
+
if (existsSync7(json))
|
|
10429
11681
|
return readJsoncFile(json).value ?? {};
|
|
10430
11682
|
return {};
|
|
10431
11683
|
}
|
|
@@ -10488,18 +11740,18 @@ function resolveCustomServers(servers) {
|
|
|
10488
11740
|
function inferLspPathsExtra(_lsp) {
|
|
10489
11741
|
const paths = new Set;
|
|
10490
11742
|
for (const entry of childDirs(getAftLspPackagesDir())) {
|
|
10491
|
-
paths.add(
|
|
11743
|
+
paths.add(join7(entry, "node_modules", ".bin"));
|
|
10492
11744
|
}
|
|
10493
11745
|
for (const entry of childDirs(getAftLspBinariesDir())) {
|
|
10494
|
-
paths.add(
|
|
11746
|
+
paths.add(join7(entry, "bin"));
|
|
10495
11747
|
}
|
|
10496
11748
|
return [...paths];
|
|
10497
11749
|
}
|
|
10498
11750
|
function childDirs(path) {
|
|
10499
|
-
if (!
|
|
11751
|
+
if (!existsSync7(path))
|
|
10500
11752
|
return [];
|
|
10501
11753
|
try {
|
|
10502
|
-
return readdirSync2(path).map((entry) =>
|
|
11754
|
+
return readdirSync2(path).map((entry) => join7(path, entry)).filter((entry) => {
|
|
10503
11755
|
try {
|
|
10504
11756
|
return statSync3(entry).isDirectory();
|
|
10505
11757
|
} catch {
|
|
@@ -10549,7 +11801,7 @@ var init_lsp = __esm(async () => {
|
|
|
10549
11801
|
init_aft_bridge();
|
|
10550
11802
|
init_harness_select();
|
|
10551
11803
|
init_jsonc();
|
|
10552
|
-
|
|
11804
|
+
init_paths2();
|
|
10553
11805
|
init_prompts();
|
|
10554
11806
|
init_self_version();
|
|
10555
11807
|
await init_binary_probe();
|
|
@@ -10579,8 +11831,8 @@ __export(exports_doctor_filters, {
|
|
|
10579
11831
|
renderFilterList: () => renderFilterList,
|
|
10580
11832
|
printDoctorFiltersHelp: () => printDoctorFiltersHelp
|
|
10581
11833
|
});
|
|
10582
|
-
import { existsSync as
|
|
10583
|
-
import { homedir as
|
|
11834
|
+
import { existsSync as existsSync8 } from "node:fs";
|
|
11835
|
+
import { homedir as homedir6 } from "node:os";
|
|
10584
11836
|
import { relative, resolve as resolve3 } from "node:path";
|
|
10585
11837
|
function printDoctorFiltersHelp() {
|
|
10586
11838
|
console.log("Usage: aft doctor filters [--show <name>] [trust|untrust]");
|
|
@@ -10610,8 +11862,8 @@ async function runDoctorFilters(options) {
|
|
|
10610
11862
|
O2.error("No harness selected.");
|
|
10611
11863
|
return 1;
|
|
10612
11864
|
}
|
|
10613
|
-
const
|
|
10614
|
-
const binary =
|
|
11865
|
+
const findBinary2 = options.findBinary ?? findAftBinary;
|
|
11866
|
+
const binary = findBinary2(getSelfVersion());
|
|
10615
11867
|
if (!binary) {
|
|
10616
11868
|
O2.error("Could not find the aft binary in the cache, platform package, PATH, or ~/.cargo/bin.");
|
|
10617
11869
|
return 1;
|
|
@@ -10622,7 +11874,7 @@ async function runDoctorFilters(options) {
|
|
|
10622
11874
|
O2.error(list.message ?? list.code ?? "list_filters failed");
|
|
10623
11875
|
return 1;
|
|
10624
11876
|
}
|
|
10625
|
-
list.project_dir_exists = list.project_dir ?
|
|
11877
|
+
list.project_dir_exists = list.project_dir ? existsSync8(list.project_dir) : false;
|
|
10626
11878
|
if (mode.kind === "list") {
|
|
10627
11879
|
console.log(renderFilterList(list, projectRoot));
|
|
10628
11880
|
return 0;
|
|
@@ -10798,7 +12050,7 @@ function truncate(value) {
|
|
|
10798
12050
|
return value.length <= 80 ? value : `${value.slice(0, 77)}…`;
|
|
10799
12051
|
}
|
|
10800
12052
|
function formatHome(path) {
|
|
10801
|
-
const home =
|
|
12053
|
+
const home = homedir6();
|
|
10802
12054
|
return path.startsWith(home) ? `~${path.slice(home.length)}` : path;
|
|
10803
12055
|
}
|
|
10804
12056
|
function formatProjectPath(path, projectRoot) {
|
|
@@ -10821,11 +12073,11 @@ var init_doctor_filters = __esm(async () => {
|
|
|
10821
12073
|
});
|
|
10822
12074
|
|
|
10823
12075
|
// src/lib/binary-cache.ts
|
|
10824
|
-
import { existsSync as
|
|
10825
|
-
import { join as
|
|
12076
|
+
import { existsSync as existsSync9, readdirSync as readdirSync3, statSync as statSync4 } from "node:fs";
|
|
12077
|
+
import { join as join8 } from "node:path";
|
|
10826
12078
|
function getBinaryCacheInfo(activeVersion) {
|
|
10827
12079
|
const path = getAftBinaryCacheDir();
|
|
10828
|
-
if (!
|
|
12080
|
+
if (!existsSync9(path)) {
|
|
10829
12081
|
return {
|
|
10830
12082
|
versions: [],
|
|
10831
12083
|
activeVersion: null,
|
|
@@ -10835,7 +12087,7 @@ function getBinaryCacheInfo(activeVersion) {
|
|
|
10835
12087
|
}
|
|
10836
12088
|
const versions = readdirSync3(path).filter((entry) => {
|
|
10837
12089
|
try {
|
|
10838
|
-
return statSync4(
|
|
12090
|
+
return statSync4(join8(path, entry)).isDirectory();
|
|
10839
12091
|
} catch {
|
|
10840
12092
|
return false;
|
|
10841
12093
|
}
|
|
@@ -10851,14 +12103,14 @@ function getBinaryCacheInfo(activeVersion) {
|
|
|
10851
12103
|
}
|
|
10852
12104
|
var init_binary_cache = __esm(() => {
|
|
10853
12105
|
init_fs_util();
|
|
10854
|
-
|
|
12106
|
+
init_paths2();
|
|
10855
12107
|
});
|
|
10856
12108
|
|
|
10857
12109
|
// src/lib/lsp-cache.ts
|
|
10858
|
-
import { existsSync as
|
|
10859
|
-
import { join as
|
|
12110
|
+
import { existsSync as existsSync10, readdirSync as readdirSync4, rmSync as rmSync2, statSync as statSync5 } from "node:fs";
|
|
12111
|
+
import { join as join9 } from "node:path";
|
|
10860
12112
|
function inspectDir(path) {
|
|
10861
|
-
if (!
|
|
12113
|
+
if (!existsSync10(path)) {
|
|
10862
12114
|
return { entries: [], totalSize: 0 };
|
|
10863
12115
|
}
|
|
10864
12116
|
const entries = [];
|
|
@@ -10870,7 +12122,7 @@ function inspectDir(path) {
|
|
|
10870
12122
|
return { entries: [], totalSize: 0 };
|
|
10871
12123
|
}
|
|
10872
12124
|
for (const name of names) {
|
|
10873
|
-
const full =
|
|
12125
|
+
const full = join9(path, name);
|
|
10874
12126
|
try {
|
|
10875
12127
|
if (!statSync5(full).isDirectory())
|
|
10876
12128
|
continue;
|
|
@@ -10924,12 +12176,12 @@ function clearLspCaches() {
|
|
|
10924
12176
|
}
|
|
10925
12177
|
var init_lsp_cache = __esm(() => {
|
|
10926
12178
|
init_fs_util();
|
|
10927
|
-
|
|
12179
|
+
init_paths2();
|
|
10928
12180
|
});
|
|
10929
12181
|
|
|
10930
12182
|
// src/lib/onnx.ts
|
|
10931
|
-
import { existsSync as
|
|
10932
|
-
import { basename, isAbsolute, join as
|
|
12183
|
+
import { existsSync as existsSync11, readdirSync as readdirSync5, readlinkSync, realpathSync as realpathSync2, statSync as statSync6 } from "node:fs";
|
|
12184
|
+
import { basename, isAbsolute, join as join10, resolve as resolve4, win32 } from "node:path";
|
|
10933
12185
|
function getOnnxLibraryName() {
|
|
10934
12186
|
if (process.platform === "darwin")
|
|
10935
12187
|
return "libonnxruntime.dylib";
|
|
@@ -10937,7 +12189,7 @@ function getOnnxLibraryName() {
|
|
|
10937
12189
|
return "onnxruntime.dll";
|
|
10938
12190
|
return "libonnxruntime.so";
|
|
10939
12191
|
}
|
|
10940
|
-
function
|
|
12192
|
+
function getManualInstallHint2() {
|
|
10941
12193
|
const p2 = process.platform;
|
|
10942
12194
|
const a = process.arch;
|
|
10943
12195
|
if (p2 === "darwin") {
|
|
@@ -10992,13 +12244,13 @@ function findSystemOnnxRuntime() {
|
|
|
10992
12244
|
searchPaths.push(...pathEntriesForPlatform());
|
|
10993
12245
|
const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
|
|
10994
12246
|
const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
|
|
10995
|
-
searchPaths.push(
|
|
12247
|
+
searchPaths.push(join10(programFiles, "onnxruntime", "lib"), join10(programFiles, "Microsoft ONNX Runtime", "lib"), join10(programFiles, "Microsoft Machine Learning", "lib"), join10(programFilesX86, "onnxruntime", "lib"), ...(() => {
|
|
10996
12248
|
const nugetPaths = [];
|
|
10997
12249
|
const userProfile = process.env.USERPROFILE ?? "";
|
|
10998
12250
|
if (!userProfile)
|
|
10999
12251
|
return nugetPaths;
|
|
11000
|
-
const nugetPackageDir =
|
|
11001
|
-
if (!
|
|
12252
|
+
const nugetPackageDir = join10(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
|
|
12253
|
+
if (!existsSync11(nugetPackageDir))
|
|
11002
12254
|
return nugetPaths;
|
|
11003
12255
|
try {
|
|
11004
12256
|
for (const entry of readdirSync5(nugetPackageDir, { withFileTypes: true })) {
|
|
@@ -11006,7 +12258,7 @@ function findSystemOnnxRuntime() {
|
|
|
11006
12258
|
continue;
|
|
11007
12259
|
if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
|
|
11008
12260
|
continue;
|
|
11009
|
-
nugetPaths.push(
|
|
12261
|
+
nugetPaths.push(join10(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join10(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
|
|
11010
12262
|
}
|
|
11011
12263
|
} catch {}
|
|
11012
12264
|
return nugetPaths;
|
|
@@ -11036,12 +12288,12 @@ function findSystemOnnxRuntime() {
|
|
|
11036
12288
|
return unknownVersionPaths[0] ?? null;
|
|
11037
12289
|
}
|
|
11038
12290
|
function findCachedOnnxRuntime(storageDir) {
|
|
11039
|
-
const ortDir =
|
|
12291
|
+
const ortDir = join10(storageDir, "onnxruntime", ONNX_RUNTIME_VERSION);
|
|
11040
12292
|
const libName = getOnnxLibraryName();
|
|
11041
|
-
if (
|
|
12293
|
+
if (existsSync11(join10(ortDir, libName)))
|
|
11042
12294
|
return ortDir;
|
|
11043
|
-
const libSubdir =
|
|
11044
|
-
if (
|
|
12295
|
+
const libSubdir = join10(ortDir, "lib");
|
|
12296
|
+
if (existsSync11(join10(libSubdir, libName)))
|
|
11045
12297
|
return libSubdir;
|
|
11046
12298
|
return null;
|
|
11047
12299
|
}
|
|
@@ -11062,7 +12314,7 @@ function parseOrtVersionFromDirectoryPath(value) {
|
|
|
11062
12314
|
return null;
|
|
11063
12315
|
}
|
|
11064
12316
|
function detectOrtVersion(libDir) {
|
|
11065
|
-
if (!
|
|
12317
|
+
if (!existsSync11(libDir))
|
|
11066
12318
|
return null;
|
|
11067
12319
|
const libName = getOnnxLibraryName();
|
|
11068
12320
|
try {
|
|
@@ -11077,10 +12329,10 @@ function detectOrtVersion(libDir) {
|
|
|
11077
12329
|
if (version)
|
|
11078
12330
|
return version;
|
|
11079
12331
|
}
|
|
11080
|
-
const base =
|
|
11081
|
-
if (
|
|
12332
|
+
const base = join10(libDir, libName);
|
|
12333
|
+
if (existsSync11(base)) {
|
|
11082
12334
|
try {
|
|
11083
|
-
const real =
|
|
12335
|
+
const real = realpathSync2(base);
|
|
11084
12336
|
const version = parseOrtVersionFromPath(real) ?? parseOrtVersionFromDirectoryPath(real);
|
|
11085
12337
|
if (version)
|
|
11086
12338
|
return version;
|
|
@@ -11109,14 +12361,14 @@ var ONNX_RUNTIME_VERSION = "1.24.4", INVALID_ORT_VERSION = "<invalid>", REQUIRED
|
|
|
11109
12361
|
var init_onnx = () => {};
|
|
11110
12362
|
|
|
11111
12363
|
// src/lib/sanitize.ts
|
|
11112
|
-
import { realpathSync as
|
|
11113
|
-
import { homedir as
|
|
12364
|
+
import { realpathSync as realpathSync3 } from "node:fs";
|
|
12365
|
+
import { homedir as homedir7, userInfo } from "node:os";
|
|
11114
12366
|
function escapeRegex(value) {
|
|
11115
12367
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
11116
12368
|
}
|
|
11117
12369
|
function safeRealpath(p2) {
|
|
11118
12370
|
try {
|
|
11119
|
-
return
|
|
12371
|
+
return realpathSync3(p2);
|
|
11120
12372
|
} catch {
|
|
11121
12373
|
return null;
|
|
11122
12374
|
}
|
|
@@ -11141,7 +12393,7 @@ function redactSecrets(content) {
|
|
|
11141
12393
|
}
|
|
11142
12394
|
function sanitizeContent(content) {
|
|
11143
12395
|
const username = userInfo().username;
|
|
11144
|
-
const home =
|
|
12396
|
+
const home = homedir7();
|
|
11145
12397
|
let sanitized = redactSecrets(content);
|
|
11146
12398
|
const cwd = process.cwd();
|
|
11147
12399
|
for (const candidate of new Set([cwd, safeRealpath(cwd)])) {
|
|
@@ -11188,11 +12440,11 @@ var init_sanitize = __esm(() => {
|
|
|
11188
12440
|
// src/lib/diagnostics.ts
|
|
11189
12441
|
import {
|
|
11190
12442
|
accessSync,
|
|
11191
|
-
closeSync,
|
|
12443
|
+
closeSync as closeSync2,
|
|
11192
12444
|
constants,
|
|
11193
|
-
existsSync as
|
|
11194
|
-
openSync,
|
|
11195
|
-
readSync,
|
|
12445
|
+
existsSync as existsSync12,
|
|
12446
|
+
openSync as openSync2,
|
|
12447
|
+
readSync as readSync2,
|
|
11196
12448
|
statSync as statSync7
|
|
11197
12449
|
} from "node:fs";
|
|
11198
12450
|
async function collectDiagnostics(adapters) {
|
|
@@ -11222,7 +12474,7 @@ async function diagnoseHarness(adapter) {
|
|
|
11222
12474
|
const logPath = adapter.getLogFile();
|
|
11223
12475
|
const pluginCache = adapter.getPluginCacheInfo();
|
|
11224
12476
|
const storageAccessible = (() => {
|
|
11225
|
-
if (!
|
|
12477
|
+
if (!existsSync12(storage))
|
|
11226
12478
|
return false;
|
|
11227
12479
|
try {
|
|
11228
12480
|
accessSync(storage, constants.R_OK | constants.W_OK);
|
|
@@ -11245,14 +12497,14 @@ async function diagnoseHarness(adapter) {
|
|
|
11245
12497
|
pluginRegistered: adapter.hasPluginEntry(),
|
|
11246
12498
|
configPaths,
|
|
11247
12499
|
aftConfig: {
|
|
11248
|
-
exists:
|
|
12500
|
+
exists: existsSync12(configPaths.aftConfig),
|
|
11249
12501
|
...aftConfigRead.error ? { parseError: aftConfigRead.error } : {},
|
|
11250
12502
|
flags: aftFlags
|
|
11251
12503
|
},
|
|
11252
12504
|
pluginCache,
|
|
11253
12505
|
storageDir: {
|
|
11254
12506
|
path: storage,
|
|
11255
|
-
exists:
|
|
12507
|
+
exists: existsSync12(storage),
|
|
11256
12508
|
accessible: storageAccessible,
|
|
11257
12509
|
sizesByKey: describeStorage
|
|
11258
12510
|
},
|
|
@@ -11265,13 +12517,13 @@ async function diagnoseHarness(adapter) {
|
|
|
11265
12517
|
cachedVersion,
|
|
11266
12518
|
cachedCompatible: cachedVersion ? isOrtVersionCompatible(cachedVersion) : null,
|
|
11267
12519
|
platform: `${process.platform}-${process.arch}`,
|
|
11268
|
-
installHint:
|
|
12520
|
+
installHint: getManualInstallHint2(),
|
|
11269
12521
|
requirement: `>=${REQUIRED_ORT_MAJOR}.${REQUIRED_ORT_MIN_MINOR}`
|
|
11270
12522
|
},
|
|
11271
12523
|
logFile: {
|
|
11272
12524
|
path: logPath,
|
|
11273
|
-
exists:
|
|
11274
|
-
sizeKb:
|
|
12525
|
+
exists: existsSync12(logPath),
|
|
12526
|
+
sizeKb: existsSync12(logPath) ? Math.round(statSync7(logPath).size / 1024) : 0
|
|
11275
12527
|
}
|
|
11276
12528
|
};
|
|
11277
12529
|
}
|
|
@@ -11465,7 +12717,7 @@ function formatDiagnosticIssuesSection(report) {
|
|
|
11465
12717
|
return lines;
|
|
11466
12718
|
}
|
|
11467
12719
|
function tailLogFile(path, lines) {
|
|
11468
|
-
if (!
|
|
12720
|
+
if (!existsSync12(path))
|
|
11469
12721
|
return "";
|
|
11470
12722
|
if (lines <= 0)
|
|
11471
12723
|
return "";
|
|
@@ -11473,7 +12725,7 @@ function tailLogFile(path, lines) {
|
|
|
11473
12725
|
let fd = null;
|
|
11474
12726
|
try {
|
|
11475
12727
|
const size = statSync7(path).size;
|
|
11476
|
-
fd =
|
|
12728
|
+
fd = openSync2(path, "r");
|
|
11477
12729
|
const chunks = [];
|
|
11478
12730
|
let position = size;
|
|
11479
12731
|
let newlineCount = 0;
|
|
@@ -11481,7 +12733,7 @@ function tailLogFile(path, lines) {
|
|
|
11481
12733
|
const readLength = Math.min(chunkSize, position);
|
|
11482
12734
|
position -= readLength;
|
|
11483
12735
|
const buffer = Buffer.allocUnsafe(readLength);
|
|
11484
|
-
const bytesRead =
|
|
12736
|
+
const bytesRead = readSync2(fd, buffer, 0, readLength, position);
|
|
11485
12737
|
const chunk = bytesRead === readLength ? buffer : buffer.subarray(0, bytesRead);
|
|
11486
12738
|
chunks.unshift(chunk);
|
|
11487
12739
|
for (let i = chunk.length - 1;i >= 0; i -= 1) {
|
|
@@ -11496,7 +12748,7 @@ function tailLogFile(path, lines) {
|
|
|
11496
12748
|
} finally {
|
|
11497
12749
|
if (fd !== null) {
|
|
11498
12750
|
try {
|
|
11499
|
-
|
|
12751
|
+
closeSync2(fd);
|
|
11500
12752
|
} catch {}
|
|
11501
12753
|
}
|
|
11502
12754
|
}
|
|
@@ -11552,6 +12804,12 @@ function createGitHubIssue(repo, title, body) {
|
|
|
11552
12804
|
var init_github = () => {};
|
|
11553
12805
|
|
|
11554
12806
|
// src/lib/issue-body.ts
|
|
12807
|
+
function filterLogToSession(logText, sessionId) {
|
|
12808
|
+
const bareId = sessionId.replace(/^ses_/, "");
|
|
12809
|
+
const keepTokens = [`[ses_${bareId}]`, `[${bareId}]`];
|
|
12810
|
+
return logText.split(/\r?\n/).filter((line) => !SESSION_TAG_PATTERN.test(line) || keepTokens.some((token) => line.includes(token))).join(`
|
|
12811
|
+
`);
|
|
12812
|
+
}
|
|
11555
12813
|
function isErrorLogLine(line) {
|
|
11556
12814
|
return ERROR_LOG_PATTERNS.some((rx) => rx.test(line));
|
|
11557
12815
|
}
|
|
@@ -11586,7 +12844,7 @@ function capBodyToGithubLimit(body, maxBytes = MAX_GITHUB_BODY_BYTES) {
|
|
|
11586
12844
|
const logBlockStart = headingEol + 1;
|
|
11587
12845
|
const logBlockEnd = nextSectionIdx === -1 ? body.length : nextSectionIdx;
|
|
11588
12846
|
const head = body.slice(0, logBlockStart);
|
|
11589
|
-
const
|
|
12847
|
+
const log2 = body.slice(logBlockStart, logBlockEnd);
|
|
11590
12848
|
const tail = body.slice(logBlockEnd);
|
|
11591
12849
|
const overheadBytes = Buffer.byteLength(head, "utf8") + Buffer.byteLength(tail, "utf8");
|
|
11592
12850
|
const truncationMarker = `[truncated for GitHub 64KB limit — older log lines dropped]
|
|
@@ -11596,7 +12854,7 @@ function capBodyToGithubLimit(body, maxBytes = MAX_GITHUB_BODY_BYTES) {
|
|
|
11596
12854
|
if (logBudget <= 0) {
|
|
11597
12855
|
return `${head}${truncationMarker}${tail}`;
|
|
11598
12856
|
}
|
|
11599
|
-
const lines =
|
|
12857
|
+
const lines = log2.split(`
|
|
11600
12858
|
`);
|
|
11601
12859
|
let keepLines = lines;
|
|
11602
12860
|
let kept = keepLines.join(`
|
|
@@ -11629,8 +12887,9 @@ function truncateToByteBudget(input, maxBytes) {
|
|
|
11629
12887
|
}
|
|
11630
12888
|
return buf.subarray(0, end).toString("utf8");
|
|
11631
12889
|
}
|
|
11632
|
-
var MAX_GITHUB_BODY_BYTES = 60000, ERROR_LOG_PATTERNS;
|
|
12890
|
+
var MAX_GITHUB_BODY_BYTES = 60000, SESSION_TAG_PATTERN, ERROR_LOG_PATTERNS;
|
|
11633
12891
|
var init_issue_body = __esm(() => {
|
|
12892
|
+
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}\]/;
|
|
11634
12893
|
ERROR_LOG_PATTERNS = [
|
|
11635
12894
|
/\bcrashed:/i,
|
|
11636
12895
|
/\bfailed:/i,
|
|
@@ -11644,8 +12903,8 @@ var init_issue_body = __esm(() => {
|
|
|
11644
12903
|
});
|
|
11645
12904
|
|
|
11646
12905
|
// src/lib/onnx-fix.ts
|
|
11647
|
-
import { existsSync as
|
|
11648
|
-
import { join as
|
|
12906
|
+
import { existsSync as existsSync13, rmSync as rmSync3 } from "node:fs";
|
|
12907
|
+
import { join as join11 } from "node:path";
|
|
11649
12908
|
function findOnnxFixCandidates(report) {
|
|
11650
12909
|
const candidates = [];
|
|
11651
12910
|
for (const harness of report.harnesses) {
|
|
@@ -11653,7 +12912,7 @@ function findOnnxFixCandidates(report) {
|
|
|
11653
12912
|
continue;
|
|
11654
12913
|
if (!harness.storageDir.exists)
|
|
11655
12914
|
continue;
|
|
11656
|
-
const storageOnnxDir =
|
|
12915
|
+
const storageOnnxDir = join11(harness.storageDir.path, "onnxruntime");
|
|
11657
12916
|
const systemTooOld = harness.onnxRuntime.systemPath !== null && harness.onnxRuntime.systemCompatible === false;
|
|
11658
12917
|
const cachedTooOld = harness.onnxRuntime.cachedPath !== null && harness.onnxRuntime.cachedCompatible === false;
|
|
11659
12918
|
const hasCompatibleCached = harness.onnxRuntime.cachedCompatible === true;
|
|
@@ -11662,7 +12921,7 @@ function findOnnxFixCandidates(report) {
|
|
|
11662
12921
|
harness,
|
|
11663
12922
|
reason: `cached ONNX Runtime at ${harness.onnxRuntime.cachedPath} is v${harness.onnxRuntime.cachedVersion}, but AFT requires ${harness.onnxRuntime.requirement}. Clearing forces a fresh download on next start.`,
|
|
11664
12923
|
storageOnnxDir,
|
|
11665
|
-
storageOnnxBytes:
|
|
12924
|
+
storageOnnxBytes: existsSync13(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
|
|
11666
12925
|
});
|
|
11667
12926
|
continue;
|
|
11668
12927
|
}
|
|
@@ -11671,7 +12930,7 @@ function findOnnxFixCandidates(report) {
|
|
|
11671
12930
|
harness,
|
|
11672
12931
|
reason: `system ONNX Runtime at ${harness.onnxRuntime.systemPath} is v${harness.onnxRuntime.systemVersion}, but AFT requires ${harness.onnxRuntime.requirement}, and no AFT-managed install is present. AFT v0.19.5+ skips incompatible system installs and auto-downloads v1.24 on next start; clearing any stale state here ensures a clean slate.`,
|
|
11673
12932
|
storageOnnxDir,
|
|
11674
|
-
storageOnnxBytes:
|
|
12933
|
+
storageOnnxBytes: existsSync13(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
|
|
11675
12934
|
});
|
|
11676
12935
|
}
|
|
11677
12936
|
}
|
|
@@ -11701,7 +12960,7 @@ async function runOnnxFix(adapters, report, options = {}) {
|
|
|
11701
12960
|
const result = { cleared: 0, bytesReclaimed: 0, errors: [] };
|
|
11702
12961
|
const rmFn = options.rmFn ?? rmSync3;
|
|
11703
12962
|
for (const c2 of candidates) {
|
|
11704
|
-
if (!
|
|
12963
|
+
if (!existsSync13(c2.storageOnnxDir)) {
|
|
11705
12964
|
O2.success(`${c2.harness.displayName}: no cached state to clear; restart your harness to trigger a fresh ONNX download`);
|
|
11706
12965
|
continue;
|
|
11707
12966
|
}
|
|
@@ -11726,6 +12985,189 @@ var init_onnx_fix = __esm(() => {
|
|
|
11726
12985
|
init_prompts();
|
|
11727
12986
|
});
|
|
11728
12987
|
|
|
12988
|
+
// src/lib/sessions.ts
|
|
12989
|
+
import { existsSync as existsSync14, readdirSync as readdirSync6, readFileSync as readFileSync4, statSync as statSync8 } from "node:fs";
|
|
12990
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
12991
|
+
import { homedir as homedir8 } from "node:os";
|
|
12992
|
+
import { basename as basename2, join as join12 } from "node:path";
|
|
12993
|
+
function listRecentSessions(adapter) {
|
|
12994
|
+
try {
|
|
12995
|
+
if (adapter.kind === "opencode")
|
|
12996
|
+
return listRecentOpenCodeSessions();
|
|
12997
|
+
if (adapter.kind === "pi")
|
|
12998
|
+
return listRecentPiSessions();
|
|
12999
|
+
return [];
|
|
13000
|
+
} catch {
|
|
13001
|
+
return [];
|
|
13002
|
+
}
|
|
13003
|
+
}
|
|
13004
|
+
function mapOpenCodeSessionRows(rows) {
|
|
13005
|
+
return rows.map((row) => {
|
|
13006
|
+
if (typeof row.id !== "string" || row.id.length === 0)
|
|
13007
|
+
return null;
|
|
13008
|
+
if (typeof row.title !== "string" || row.title.length === 0)
|
|
13009
|
+
return null;
|
|
13010
|
+
const lastActivity = typeof row.time_updated === "number" ? row.time_updated : Number(row.time_updated);
|
|
13011
|
+
if (!Number.isFinite(lastActivity))
|
|
13012
|
+
return null;
|
|
13013
|
+
return {
|
|
13014
|
+
id: row.id,
|
|
13015
|
+
title: row.title,
|
|
13016
|
+
lastActivity
|
|
13017
|
+
};
|
|
13018
|
+
}).filter((session) => session !== null).sort((a, b) => b.lastActivity - a.lastActivity).slice(0, MAX_RECENT_SESSIONS);
|
|
13019
|
+
}
|
|
13020
|
+
function listRecentOpenCodeSessions() {
|
|
13021
|
+
const dbPath = join12(getXdgDataHome(), "opencode", "opencode.db");
|
|
13022
|
+
if (!existsSync14(dbPath))
|
|
13023
|
+
return [];
|
|
13024
|
+
let db = null;
|
|
13025
|
+
try {
|
|
13026
|
+
const require2 = createRequire3(import.meta.url);
|
|
13027
|
+
const sqlite = require2("node:sqlite");
|
|
13028
|
+
db = new sqlite.DatabaseSync(dbPath, { readOnly: true });
|
|
13029
|
+
const rows = db.prepare("SELECT id, title, time_updated FROM session ORDER BY time_updated DESC LIMIT 5").all();
|
|
13030
|
+
return mapOpenCodeSessionRows(rows);
|
|
13031
|
+
} catch {
|
|
13032
|
+
return [];
|
|
13033
|
+
} finally {
|
|
13034
|
+
try {
|
|
13035
|
+
db?.close();
|
|
13036
|
+
} catch {}
|
|
13037
|
+
}
|
|
13038
|
+
}
|
|
13039
|
+
function getXdgDataHome() {
|
|
13040
|
+
const xdgDataHome = process.env.XDG_DATA_HOME;
|
|
13041
|
+
return xdgDataHome && xdgDataHome.length > 0 ? xdgDataHome : join12(homedir8(), ".local", "share");
|
|
13042
|
+
}
|
|
13043
|
+
function listRecentPiSessions() {
|
|
13044
|
+
return listPiSessionsFromDir(join12(getHomeDir(), ".pi", "agent", "sessions"));
|
|
13045
|
+
}
|
|
13046
|
+
function getHomeDir() {
|
|
13047
|
+
const envHome = process.platform === "win32" ? process.env.USERPROFILE : process.env.HOME;
|
|
13048
|
+
return envHome && envHome.length > 0 ? envHome : homedir8();
|
|
13049
|
+
}
|
|
13050
|
+
function listPiSessionsFromDir(sessionsDir) {
|
|
13051
|
+
try {
|
|
13052
|
+
if (!existsSync14(sessionsDir))
|
|
13053
|
+
return [];
|
|
13054
|
+
const files = collectJsonlFiles(sessionsDir).map((filePath) => {
|
|
13055
|
+
try {
|
|
13056
|
+
const stats = statSync8(filePath);
|
|
13057
|
+
return { filePath, mtimeMs: stats.mtimeMs };
|
|
13058
|
+
} catch {
|
|
13059
|
+
return null;
|
|
13060
|
+
}
|
|
13061
|
+
}).filter((entry) => entry !== null).sort((a, b) => b.mtimeMs - a.mtimeMs).slice(0, MAX_RECENT_SESSIONS * 4);
|
|
13062
|
+
const sessions = [];
|
|
13063
|
+
for (const file of files) {
|
|
13064
|
+
const parsed = parsePiSessionJsonl(readFileSync4(file.filePath, "utf8"), basename2(file.filePath));
|
|
13065
|
+
if (!parsed)
|
|
13066
|
+
continue;
|
|
13067
|
+
sessions.push({ ...parsed, lastActivity: file.mtimeMs });
|
|
13068
|
+
if (sessions.length >= MAX_RECENT_SESSIONS)
|
|
13069
|
+
break;
|
|
13070
|
+
}
|
|
13071
|
+
return sessions;
|
|
13072
|
+
} catch {
|
|
13073
|
+
return [];
|
|
13074
|
+
}
|
|
13075
|
+
}
|
|
13076
|
+
function collectJsonlFiles(root) {
|
|
13077
|
+
const files = [];
|
|
13078
|
+
const stack = [root];
|
|
13079
|
+
while (stack.length > 0) {
|
|
13080
|
+
const dir = stack.pop();
|
|
13081
|
+
if (!dir)
|
|
13082
|
+
continue;
|
|
13083
|
+
let entries;
|
|
13084
|
+
try {
|
|
13085
|
+
entries = readdirSync6(dir, { withFileTypes: true });
|
|
13086
|
+
} catch {
|
|
13087
|
+
continue;
|
|
13088
|
+
}
|
|
13089
|
+
for (const entry of entries) {
|
|
13090
|
+
const path = join12(dir, entry.name);
|
|
13091
|
+
if (entry.isDirectory()) {
|
|
13092
|
+
stack.push(path);
|
|
13093
|
+
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
13094
|
+
files.push(path);
|
|
13095
|
+
}
|
|
13096
|
+
}
|
|
13097
|
+
}
|
|
13098
|
+
return files;
|
|
13099
|
+
}
|
|
13100
|
+
function parsePiSessionJsonl(jsonl, fallbackFilename = "") {
|
|
13101
|
+
let id = extractUuidFromFilename(fallbackFilename);
|
|
13102
|
+
let title = null;
|
|
13103
|
+
for (const line of jsonl.split(/\r?\n/)) {
|
|
13104
|
+
const trimmed = line.trim();
|
|
13105
|
+
if (trimmed.length === 0)
|
|
13106
|
+
continue;
|
|
13107
|
+
let value;
|
|
13108
|
+
try {
|
|
13109
|
+
value = JSON.parse(trimmed);
|
|
13110
|
+
} catch {
|
|
13111
|
+
continue;
|
|
13112
|
+
}
|
|
13113
|
+
if (!value || typeof value !== "object")
|
|
13114
|
+
continue;
|
|
13115
|
+
const record = value;
|
|
13116
|
+
if (record.type === "session" && typeof record.id === "string" && record.id.length > 0) {
|
|
13117
|
+
id = record.id;
|
|
13118
|
+
}
|
|
13119
|
+
if (title === null) {
|
|
13120
|
+
const maybeTitle = extractPiUserMessageText(record);
|
|
13121
|
+
if (maybeTitle)
|
|
13122
|
+
title = truncateTitle(maybeTitle);
|
|
13123
|
+
}
|
|
13124
|
+
if (id && title)
|
|
13125
|
+
break;
|
|
13126
|
+
}
|
|
13127
|
+
if (!id)
|
|
13128
|
+
return null;
|
|
13129
|
+
return { id, title: title ?? id };
|
|
13130
|
+
}
|
|
13131
|
+
function extractPiUserMessageText(record) {
|
|
13132
|
+
if (record.type !== "message")
|
|
13133
|
+
return null;
|
|
13134
|
+
const message = record.message;
|
|
13135
|
+
if (!message || typeof message !== "object")
|
|
13136
|
+
return null;
|
|
13137
|
+
const messageRecord = message;
|
|
13138
|
+
if (messageRecord.role !== "user")
|
|
13139
|
+
return null;
|
|
13140
|
+
return extractTextFromContent(messageRecord.content);
|
|
13141
|
+
}
|
|
13142
|
+
function extractTextFromContent(content) {
|
|
13143
|
+
if (typeof content === "string")
|
|
13144
|
+
return content.trim() || null;
|
|
13145
|
+
if (!Array.isArray(content))
|
|
13146
|
+
return null;
|
|
13147
|
+
const parts = content.map((part) => {
|
|
13148
|
+
if (typeof part === "string")
|
|
13149
|
+
return part;
|
|
13150
|
+
if (!part || typeof part !== "object")
|
|
13151
|
+
return "";
|
|
13152
|
+
const partRecord = part;
|
|
13153
|
+
return partRecord.type === "text" && typeof partRecord.text === "string" ? partRecord.text : "";
|
|
13154
|
+
}).filter((text2) => text2.trim().length > 0);
|
|
13155
|
+
const joined = parts.join(" ").trim();
|
|
13156
|
+
return joined.length > 0 ? joined : null;
|
|
13157
|
+
}
|
|
13158
|
+
function extractUuidFromFilename(filename) {
|
|
13159
|
+
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);
|
|
13160
|
+
return match?.[1] ?? null;
|
|
13161
|
+
}
|
|
13162
|
+
function truncateTitle(title, maxLength = 60) {
|
|
13163
|
+
const normalized = title.replace(/\s+/g, " ").trim();
|
|
13164
|
+
if (normalized.length <= maxLength)
|
|
13165
|
+
return normalized;
|
|
13166
|
+
return `${normalized.slice(0, Math.max(0, maxLength - 1))}…`;
|
|
13167
|
+
}
|
|
13168
|
+
var MAX_RECENT_SESSIONS = 5;
|
|
13169
|
+
var init_sessions = () => {};
|
|
13170
|
+
|
|
11729
13171
|
// src/commands/doctor.ts
|
|
11730
13172
|
var exports_doctor = {};
|
|
11731
13173
|
__export(exports_doctor, {
|
|
@@ -11743,18 +13185,18 @@ __export(exports_doctor, {
|
|
|
11743
13185
|
DOCTOR_CLEAR_TARGET_OPTIONS: () => DOCTOR_CLEAR_TARGET_OPTIONS
|
|
11744
13186
|
});
|
|
11745
13187
|
import {
|
|
11746
|
-
chmodSync,
|
|
11747
|
-
existsSync as
|
|
11748
|
-
mkdirSync as
|
|
13188
|
+
chmodSync as chmodSync2,
|
|
13189
|
+
existsSync as existsSync15,
|
|
13190
|
+
mkdirSync as mkdirSync3,
|
|
11749
13191
|
mkdtempSync,
|
|
11750
|
-
readFileSync as
|
|
11751
|
-
realpathSync as
|
|
13192
|
+
readFileSync as readFileSync5,
|
|
13193
|
+
realpathSync as realpathSync4,
|
|
11752
13194
|
rmSync as rmSync4,
|
|
11753
|
-
statSync as
|
|
13195
|
+
statSync as statSync9,
|
|
11754
13196
|
writeFileSync as writeFileSync2
|
|
11755
13197
|
} from "node:fs";
|
|
11756
13198
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
11757
|
-
import { join as
|
|
13199
|
+
import { join as join13 } from "node:path";
|
|
11758
13200
|
async function runDoctor(options) {
|
|
11759
13201
|
if (options.issue) {
|
|
11760
13202
|
return runIssueFlow(options.argv);
|
|
@@ -11767,7 +13209,7 @@ async function runDoctor(options) {
|
|
|
11767
13209
|
return runClearFlow(options.argv);
|
|
11768
13210
|
}
|
|
11769
13211
|
const adapters = await resolveAdaptersForCommand(options.argv, {
|
|
11770
|
-
allowMulti:
|
|
13212
|
+
allowMulti: false,
|
|
11771
13213
|
verb: "diagnose"
|
|
11772
13214
|
});
|
|
11773
13215
|
const report = await collectDiagnostics(adapters);
|
|
@@ -11798,6 +13240,10 @@ async function runDoctor(options) {
|
|
|
11798
13240
|
O2.info(` aft config: ${h.aftConfig.exists ? h.configPaths.aftConfig : "(not set)"}`);
|
|
11799
13241
|
if (h.aftConfig.parseError) {
|
|
11800
13242
|
O2.error(` aft config parse error: ${h.aftConfig.parseError}`);
|
|
13243
|
+
} else if (h.aftConfig.exists) {
|
|
13244
|
+
const { value } = readJsoncFile(h.configPaths.aftConfig);
|
|
13245
|
+
const schemaSet = value?.$schema === AFT_SCHEMA_URL;
|
|
13246
|
+
O2.info(` aft config $schema: ${schemaSet ? "set" : "not set — run `aft doctor --fix` for editor autocomplete"}`);
|
|
11801
13247
|
}
|
|
11802
13248
|
O2.info(` storage: ${formatDoctorStorageStatus(h)}`);
|
|
11803
13249
|
if (h.onnxRuntime.required) {
|
|
@@ -11904,7 +13350,7 @@ function clearOldBinaries() {
|
|
|
11904
13350
|
errors: [],
|
|
11905
13351
|
keptVersion: keepTag
|
|
11906
13352
|
};
|
|
11907
|
-
if (!
|
|
13353
|
+
if (!existsSync15(info.path)) {
|
|
11908
13354
|
O2.info(`Binary cache: nothing to clear at ${info.path}`);
|
|
11909
13355
|
return result;
|
|
11910
13356
|
}
|
|
@@ -11914,10 +13360,10 @@ function clearOldBinaries() {
|
|
|
11914
13360
|
return result;
|
|
11915
13361
|
}
|
|
11916
13362
|
for (const version of stale) {
|
|
11917
|
-
const dir =
|
|
13363
|
+
const dir = join13(info.path, version);
|
|
11918
13364
|
let bytes = 0;
|
|
11919
13365
|
try {
|
|
11920
|
-
bytes =
|
|
13366
|
+
bytes = statSync9(dir).isDirectory() ? dirSize(dir) : 0;
|
|
11921
13367
|
} catch {
|
|
11922
13368
|
bytes = 0;
|
|
11923
13369
|
}
|
|
@@ -11937,6 +13383,42 @@ function clearOldBinaries() {
|
|
|
11937
13383
|
}
|
|
11938
13384
|
return result;
|
|
11939
13385
|
}
|
|
13386
|
+
function findSchemaFixTargets(adapters) {
|
|
13387
|
+
const targets = [];
|
|
13388
|
+
for (const adapter of adapters) {
|
|
13389
|
+
if (!adapter.isInstalled())
|
|
13390
|
+
continue;
|
|
13391
|
+
let aftConfig;
|
|
13392
|
+
let aftConfigFormat;
|
|
13393
|
+
try {
|
|
13394
|
+
({ aftConfig, aftConfigFormat } = adapter.detectConfigPaths());
|
|
13395
|
+
} catch {
|
|
13396
|
+
continue;
|
|
13397
|
+
}
|
|
13398
|
+
const { value } = readJsoncFile(aftConfig);
|
|
13399
|
+
if (value?.$schema === AFT_SCHEMA_URL)
|
|
13400
|
+
continue;
|
|
13401
|
+
targets.push({ adapter, aftConfig, aftConfigFormat });
|
|
13402
|
+
}
|
|
13403
|
+
return targets;
|
|
13404
|
+
}
|
|
13405
|
+
function applySchemaFixes(targets) {
|
|
13406
|
+
let changed = 0;
|
|
13407
|
+
let errors = 0;
|
|
13408
|
+
for (const target of targets) {
|
|
13409
|
+
try {
|
|
13410
|
+
const result = ensureAftSchemaUrl(target.aftConfig, target.aftConfigFormat);
|
|
13411
|
+
if (result.action === "added" || result.action === "updated") {
|
|
13412
|
+
changed += 1;
|
|
13413
|
+
O2.success(`${target.adapter.displayName}: ${result.message}`);
|
|
13414
|
+
}
|
|
13415
|
+
} catch (error2) {
|
|
13416
|
+
errors += 1;
|
|
13417
|
+
O2.warn(`${target.adapter.displayName}: could not set $schema on ${target.aftConfig}: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
13418
|
+
}
|
|
13419
|
+
}
|
|
13420
|
+
return { changed, errors };
|
|
13421
|
+
}
|
|
11940
13422
|
function buildDoctorFixPlan(adapters, report) {
|
|
11941
13423
|
const items = [];
|
|
11942
13424
|
const adaptersByKind = new Map(adapters.map((adapter) => [adapter.kind, adapter]));
|
|
@@ -11984,6 +13466,12 @@ function buildDoctorFixPlan(adapters, report) {
|
|
|
11984
13466
|
});
|
|
11985
13467
|
}
|
|
11986
13468
|
}
|
|
13469
|
+
for (const target of findSchemaFixTargets(adapters)) {
|
|
13470
|
+
items.push({
|
|
13471
|
+
kind: "schema",
|
|
13472
|
+
message: `Will add the AFT config $schema URL to ${target.aftConfig} (editor autocomplete + validation)`
|
|
13473
|
+
});
|
|
13474
|
+
}
|
|
11987
13475
|
return items;
|
|
11988
13476
|
}
|
|
11989
13477
|
function shouldSkipDoctorFixConfirmation(argv) {
|
|
@@ -12022,7 +13510,7 @@ function logUnmatchedBinaryCandidates(expectedVersion) {
|
|
|
12022
13510
|
}
|
|
12023
13511
|
async function runFixFlow(argv) {
|
|
12024
13512
|
const adapters = await resolveAdaptersForCommand(argv, {
|
|
12025
|
-
allowMulti:
|
|
13513
|
+
allowMulti: false,
|
|
12026
13514
|
verb: "auto-fix issues for"
|
|
12027
13515
|
});
|
|
12028
13516
|
O2.info("Running diagnostics to identify auto-fixable issues…");
|
|
@@ -12044,6 +13532,7 @@ async function runFixFlow(argv) {
|
|
|
12044
13532
|
}
|
|
12045
13533
|
await fixPluginEntries(adapters);
|
|
12046
13534
|
const storageSummary = ensureStorageDirsForRegisteredPlugins(adapters);
|
|
13535
|
+
const schemaSummary = applySchemaFixes(findSchemaFixTargets(adapters));
|
|
12047
13536
|
let binaryDownloaded = false;
|
|
12048
13537
|
let binaryDownloadSkipped = false;
|
|
12049
13538
|
let binaryDownloadError = null;
|
|
@@ -12055,8 +13544,8 @@ async function runFixFlow(argv) {
|
|
|
12055
13544
|
O2.info("AFT binary not found. Downloading…");
|
|
12056
13545
|
try {
|
|
12057
13546
|
const bridgePackageName = "@cortexkit/aft-bridge";
|
|
12058
|
-
const { ensureBinary } = await import(bridgePackageName);
|
|
12059
|
-
const path = await
|
|
13547
|
+
const { ensureBinary: ensureBinary2 } = await import(bridgePackageName);
|
|
13548
|
+
const path = await ensureBinary2(`v${report.cliVersion}`);
|
|
12060
13549
|
if (path) {
|
|
12061
13550
|
O2.success(`AFT binary installed at ${path}`);
|
|
12062
13551
|
binaryDownloaded = true;
|
|
@@ -12072,7 +13561,7 @@ async function runFixFlow(argv) {
|
|
|
12072
13561
|
}
|
|
12073
13562
|
}
|
|
12074
13563
|
const onnxResult = await runOnnxFix(adapters, report, { yes: true });
|
|
12075
|
-
if (onnxResult === null && !binaryDownloaded && !binaryDownloadSkipped && !binaryDownloadError && storageSummary.created === 0 && storageSummary.errors === 0) {
|
|
13564
|
+
if (onnxResult === null && !binaryDownloaded && !binaryDownloadSkipped && !binaryDownloadError && storageSummary.created === 0 && storageSummary.errors === 0 && schemaSummary.changed === 0 && schemaSummary.errors === 0) {
|
|
12076
13565
|
O2.info("No auto-fixable issues detected.");
|
|
12077
13566
|
wt("If you're still seeing 'Semantic Index: failed' in the TUI sidebar, run `aft doctor` (without --fix) for a full diagnostic dump.", "Tip");
|
|
12078
13567
|
const afterReport2 = await collectDiagnostics(adapters);
|
|
@@ -12080,7 +13569,7 @@ async function runFixFlow(argv) {
|
|
|
12080
13569
|
gt(stillHasProblems2 ? "Done — some issues remain." : "Done.");
|
|
12081
13570
|
return stillHasProblems2 ? 1 : 0;
|
|
12082
13571
|
}
|
|
12083
|
-
const hadErrors = (onnxResult?.errors.length ?? 0) > 0 || binaryDownloadError !== null || storageSummary.errors > 0;
|
|
13572
|
+
const hadErrors = (onnxResult?.errors.length ?? 0) > 0 || binaryDownloadError !== null || storageSummary.errors > 0 || schemaSummary.errors > 0;
|
|
12084
13573
|
const afterReport = await collectDiagnostics(adapters);
|
|
12085
13574
|
const stillHasProblems = hasDoctorProblems(afterReport);
|
|
12086
13575
|
gt(hadErrors ? "Done — some fixes failed." : stillHasProblems ? "Done — some issues remain." : "Done.");
|
|
@@ -12135,9 +13624,9 @@ function ensureStorageDirsForRegisteredPlugins(adapters) {
|
|
|
12135
13624
|
if (!adapter.isInstalled() || !adapter.hasPluginEntry())
|
|
12136
13625
|
continue;
|
|
12137
13626
|
const storageDir = adapter.getStorageDir();
|
|
12138
|
-
if (
|
|
13627
|
+
if (existsSync15(storageDir))
|
|
12139
13628
|
continue;
|
|
12140
|
-
|
|
13629
|
+
mkdirSync3(storageDir, { recursive: true });
|
|
12141
13630
|
summary.created += 1;
|
|
12142
13631
|
O2.success(`${adapter.displayName}: created AFT storage directory at ${storageDir}`);
|
|
12143
13632
|
} catch (err) {
|
|
@@ -12238,14 +13727,14 @@ function deriveIssueTitleFromBody(body) {
|
|
|
12238
13727
|
function writeIssueReviewFile(body) {
|
|
12239
13728
|
let reviewDir = null;
|
|
12240
13729
|
try {
|
|
12241
|
-
reviewDir = mkdtempSync(
|
|
13730
|
+
reviewDir = mkdtempSync(join13(tmpdir2(), "aft-issue-"));
|
|
12242
13731
|
if (process.platform !== "win32") {
|
|
12243
|
-
|
|
13732
|
+
chmodSync2(reviewDir, 448);
|
|
12244
13733
|
}
|
|
12245
|
-
const outPath =
|
|
13734
|
+
const outPath = join13(reviewDir, "issue.md");
|
|
12246
13735
|
writeFileSync2(outPath, `${body}
|
|
12247
13736
|
`, { encoding: "utf8", mode: 384, flag: "wx" });
|
|
12248
|
-
return { path: outPath, realPath:
|
|
13737
|
+
return { path: outPath, realPath: realpathSync4(outPath) };
|
|
12249
13738
|
} catch (err) {
|
|
12250
13739
|
if (reviewDir) {
|
|
12251
13740
|
try {
|
|
@@ -12258,17 +13747,38 @@ function writeIssueReviewFile(body) {
|
|
|
12258
13747
|
}
|
|
12259
13748
|
function readReviewedIssueFile(reviewFile) {
|
|
12260
13749
|
try {
|
|
12261
|
-
const realPath =
|
|
13750
|
+
const realPath = realpathSync4(reviewFile.path);
|
|
12262
13751
|
if (realPath !== reviewFile.realPath) {
|
|
12263
13752
|
O2.error(`Review file path changed before filing; refusing to read ${reviewFile.path}.`);
|
|
12264
13753
|
return null;
|
|
12265
13754
|
}
|
|
12266
|
-
return
|
|
13755
|
+
return readFileSync5(reviewFile.path, "utf8");
|
|
12267
13756
|
} catch (err) {
|
|
12268
13757
|
O2.error(`Failed to read reviewed issue report: ${err instanceof Error ? err.message : String(err)}`);
|
|
12269
13758
|
return null;
|
|
12270
13759
|
}
|
|
12271
13760
|
}
|
|
13761
|
+
async function promptForIssueSession(adapter) {
|
|
13762
|
+
const sessions = listRecentSessions(adapter);
|
|
13763
|
+
if (sessions.length === 0)
|
|
13764
|
+
return null;
|
|
13765
|
+
const allLogsValue = "__all__";
|
|
13766
|
+
const selected = await selectOne("Is this issue about a specific session?", [
|
|
13767
|
+
{ label: "General — not session-specific (include all logs)", value: allLogsValue },
|
|
13768
|
+
...sessions.map((session) => ({
|
|
13769
|
+
label: truncateTitle(session.title),
|
|
13770
|
+
value: session.id,
|
|
13771
|
+
hint: shortSessionId(session.id)
|
|
13772
|
+
}))
|
|
13773
|
+
]);
|
|
13774
|
+
if (selected === allLogsValue)
|
|
13775
|
+
return null;
|
|
13776
|
+
return sessions.find((session) => session.id === selected) ?? null;
|
|
13777
|
+
}
|
|
13778
|
+
function shortSessionId(id) {
|
|
13779
|
+
const bareId = id.replace(/^ses_/, "");
|
|
13780
|
+
return bareId.length <= 12 ? bareId : bareId.slice(0, 12);
|
|
13781
|
+
}
|
|
12272
13782
|
async function runIssueFlow(argv) {
|
|
12273
13783
|
mt("AFT doctor --issue");
|
|
12274
13784
|
if (!isInteractiveTerminal()) {
|
|
@@ -12277,28 +13787,33 @@ async function runIssueFlow(argv) {
|
|
|
12277
13787
|
return 0;
|
|
12278
13788
|
}
|
|
12279
13789
|
const adapters = await resolveAdaptersForCommand(argv, {
|
|
12280
|
-
allowMulti:
|
|
13790
|
+
allowMulti: false,
|
|
12281
13791
|
verb: "include in the issue"
|
|
12282
13792
|
});
|
|
12283
13793
|
const description = await text("Describe the problem you're running into:", {
|
|
12284
13794
|
placeholder: "What happened? What did you expect? Steps to reproduce…",
|
|
12285
13795
|
validate: (value) => value.trim().length === 0 ? "Please enter a short description." : undefined
|
|
12286
13796
|
});
|
|
13797
|
+
const selectedSession = await promptForIssueSession(adapters[0]);
|
|
13798
|
+
const selectedBareSessionId = selectedSession?.id.replace(/^ses_/, "") ?? null;
|
|
12287
13799
|
const report = await collectDiagnostics(adapters);
|
|
12288
13800
|
const logSections = adapters.map((adapter) => {
|
|
12289
13801
|
const path = adapter.getLogFile();
|
|
12290
13802
|
const tail = tailLogFile(path, 200);
|
|
13803
|
+
const scopedTail = selectedBareSessionId ? filterLogToSession(tail, selectedBareSessionId) : tail;
|
|
12291
13804
|
return `#### ${adapter.displayName} log (${path})
|
|
12292
13805
|
|
|
12293
13806
|
\`\`\`
|
|
12294
|
-
${
|
|
13807
|
+
${scopedTail || "<no log output>"}
|
|
12295
13808
|
\`\`\`
|
|
12296
13809
|
`;
|
|
12297
13810
|
}).join(`
|
|
12298
13811
|
`);
|
|
12299
13812
|
const errorScanWindow = adapters.map((adapter) => {
|
|
12300
13813
|
const path = adapter.getLogFile();
|
|
12301
|
-
|
|
13814
|
+
const tail = tailLogFile(path, 4000);
|
|
13815
|
+
const scopedTail = selectedBareSessionId ? filterLogToSession(tail, selectedBareSessionId) : tail;
|
|
13816
|
+
return sanitizeContent(scopedTail);
|
|
12302
13817
|
}).join(`
|
|
12303
13818
|
`);
|
|
12304
13819
|
const recentErrorLines = extractRecentErrors(errorScanWindow, 20);
|
|
@@ -12314,6 +13829,7 @@ ${tail || "<no log output>"}
|
|
|
12314
13829
|
`- AFT binary: ${report.binaryVersion ?? "unknown"}`,
|
|
12315
13830
|
`- OS: ${report.platform} ${report.arch}`,
|
|
12316
13831
|
`- Node: ${report.nodeVersion}`,
|
|
13832
|
+
...selectedSession ? [`- Session: ses_${selectedBareSessionId} (${truncateTitle(selectedSession.title)})`] : [],
|
|
12317
13833
|
"",
|
|
12318
13834
|
"## Diagnostics",
|
|
12319
13835
|
renderDiagnosticsMarkdown(report),
|
|
@@ -12378,11 +13894,13 @@ var init_doctor = __esm(async () => {
|
|
|
12378
13894
|
init_github();
|
|
12379
13895
|
init_harness_select();
|
|
12380
13896
|
init_issue_body();
|
|
13897
|
+
init_jsonc();
|
|
12381
13898
|
init_lsp_cache();
|
|
12382
13899
|
init_onnx_fix();
|
|
12383
13900
|
init_prompts();
|
|
12384
13901
|
init_sanitize();
|
|
12385
13902
|
init_self_version();
|
|
13903
|
+
init_sessions();
|
|
12386
13904
|
await __promiseAll([
|
|
12387
13905
|
init_binary_probe(),
|
|
12388
13906
|
init_diagnostics()
|
|
@@ -12413,6 +13931,7 @@ function printHelp() {
|
|
|
12413
13931
|
console.log(" -------");
|
|
12414
13932
|
console.log("");
|
|
12415
13933
|
console.log(" Commands:");
|
|
13934
|
+
console.log(" --version Show CLI, binary, and per-harness plugin versions");
|
|
12416
13935
|
console.log(" setup Interactive setup wizard");
|
|
12417
13936
|
console.log(" doctor Check and fix configuration issues");
|
|
12418
13937
|
console.log(" doctor lsp <file> Inspect LSP setup for one file");
|
|
@@ -12434,6 +13953,10 @@ function printHelp() {
|
|
|
12434
13953
|
console.log("");
|
|
12435
13954
|
}
|
|
12436
13955
|
async function main() {
|
|
13956
|
+
if (command === "--version" || command === "-v" || command === "-V" || command === "version") {
|
|
13957
|
+
const { runVersion: runVersion2 } = await init_version().then(() => exports_version);
|
|
13958
|
+
return runVersion2();
|
|
13959
|
+
}
|
|
12437
13960
|
if (command === "setup") {
|
|
12438
13961
|
const { runSetup: runSetup2 } = await Promise.resolve().then(() => (init_setup(), exports_setup));
|
|
12439
13962
|
return runSetup2(args);
|