@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/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 (!existsSync(path)) {
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(join(path, entry));
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(error) {
4620
- this.errors.push(error);
6014
+ ErrorHandler2.prototype.recordError = function(error2) {
6015
+ this.errors.push(error2);
4621
6016
  };
4622
- ErrorHandler2.prototype.tolerate = function(error) {
6017
+ ErrorHandler2.prototype.tolerate = function(error2) {
4623
6018
  if (this.tolerant) {
4624
- this.recordError(error);
6019
+ this.recordError(error2);
4625
6020
  } else {
4626
- throw error;
6021
+ throw error2;
4627
6022
  }
4628
6023
  };
4629
6024
  ErrorHandler2.prototype.constructError = function(msg, column) {
4630
- var error = new Error(msg);
6025
+ var error2 = new Error(msg);
4631
6026
  try {
4632
- throw error;
6027
+ throw error2;
4633
6028
  } catch (base) {
4634
6029
  if (Object.create && Object.defineProperty) {
4635
- error = Object.create(base);
4636
- Object.defineProperty(error, "column", { value: column });
6030
+ error2 = Object.create(base);
6031
+ Object.defineProperty(error2, "column", { value: column });
4637
6032
  }
4638
6033
  }
4639
- return error;
6034
+ return error2;
4640
6035
  };
4641
6036
  ErrorHandler2.prototype.createError = function(index, line, col, description) {
4642
6037
  var msg = "Line " + line + ": " + description;
4643
- var error = this.constructError(msg, col);
4644
- error.index = index;
4645
- error.lineNumber = line;
4646
- error.description = description;
4647
- return error;
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 error = this.createError(index, line, col, description);
6048
+ var error2 = this.createError(index, line, col, description);
4654
6049
  if (this.tolerant) {
4655
- this.recordError(error);
6050
+ this.recordError(error2);
4656
6051
  } else {
4657
- throw error;
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 error = new SyntaxError(`Unexpected token '${current.value.slice(0, 1)}', "${current_code}" is not valid JSON`);
7328
- Object.assign(error, current.loc.start);
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 error;
8725
+ throw error2;
7331
8726
  };
7332
8727
  var unexpected_end = () => {
7333
- const error = new SyntaxError("Unexpected end of JSON input");
7334
- Object.assign(error, last ? last.loc.end : {
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 error;
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 join2 = (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;
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 join2(comment, inside, gap);
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 = join2(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
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 += join2(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
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 = join2(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
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 += join2(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
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 existsSync2, mkdirSync, readFileSync, writeFileSync } from "node:fs";
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 (existsSync2(jsoncPath)) {
9239
+ if (existsSync4(jsoncPath)) {
7845
9240
  return { path: jsoncPath, format: "jsonc" };
7846
9241
  }
7847
- if (existsSync2(jsonPath)) {
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 (!existsSync2(path)) {
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 (error) {
9255
+ } catch (error2) {
7861
9256
  return {
7862
9257
  value: null,
7863
- error: error instanceof Error ? error.message : String(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
- mkdirSync(dirname(path), { recursive: true });
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 = existsSync2(path);
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(error ? `failed to parse ${path}: ${error}` : `failed to parse ${path}`);
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 = createRequire(import.meta.url);
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 existsSync3, readFileSync as readFileSync2, rmSync, statSync as statSync2 } from "node:fs";
7991
- import { homedir as homedir2 } from "node:os";
7992
- import { dirname as dirname2, join as join3, parse, resolve } from "node:path";
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 || join3(homedir2(), ".config");
7999
- return join3(xdg, "opencode");
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 join3(xdg, "opencode");
9336
+ return join5(xdg, "opencode");
8005
9337
  if (process.platform === "win32") {
8006
- const localAppData = process.env.LOCALAPPDATA ?? join3(homedir2(), "AppData", "Local");
8007
- return join3(localAppData, "opencode");
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 join3(homedir2(), ".cache", "opencode");
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 (!existsSync3(fsPath))
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 = join3(searchDir, "package.json");
8034
- if (existsSync3(candidate)) {
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
- try {
8066
- execSync("opencode --version", { stdio: "ignore" });
9423
+ if (existsSync5(getOpenCodeConfigDir()))
8067
9424
  return true;
8068
- } catch {
8069
- return false;
8070
- }
9425
+ if (openCodeDesktopAppExists())
9426
+ return true;
9427
+ return hasOpenCodeCli();
8071
9428
  }
8072
9429
  getHostVersion() {
8073
9430
  try {
8074
- return execSync("opencode --version", { encoding: "utf-8", stdio: "pipe" }).trim();
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 (error || !value) {
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}: ${error ?? "unknown error"}`,
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 = join3(getOpenCodeCacheDir(), "packages", PLUGIN_ENTRY);
9504
+ const path = join5(getOpenCodeCacheDir(), "packages", PLUGIN_ENTRY);
8144
9505
  let cached;
8145
9506
  try {
8146
- const installedPkgPath = join3(path, "node_modules", "@cortexkit", "aft-opencode", "package.json");
8147
- if (existsSync3(installedPkgPath)) {
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: existsSync3(path)
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 (error) {
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: error instanceof Error ? error.message : String(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(join3(storage, "index")),
8208
- semantic: dirSize(join3(storage, "semantic")),
8209
- backups: dirSize(join3(storage, "backups")),
8210
- url_cache: dirSize(join3(storage, "url_cache")),
8211
- onnxruntime: dirSize(join3(storage, "onnxruntime"))
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
- init_paths();
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 execSync2, spawnSync } from "node:child_process";
8226
- import { existsSync as existsSync4, readFileSync as readFileSync3 } from "node:fs";
8227
- import { homedir as homedir3 } from "node:os";
8228
- import { join as join4 } from "node:path";
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 : homedir3();
8232
- return join4(home, ".pi", "agent");
9592
+ const home = envHome && envHome.length > 0 ? envHome : homedir5();
9593
+ return join6(home, ".pi", "agent");
8233
9594
  }
8234
9595
  function readPiExtensionIndex() {
8235
- const settingsPath = join4(getPiAgentDir(), "settings.json");
8236
- if (existsSync4(settingsPath)) {
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
- join4(getPiAgentDir(), "extensions.json"),
8250
- join4(getPiAgentDir(), "extensions.jsonc"),
8251
- join4(getPiAgentDir(), "config.json"),
8252
- join4(getPiAgentDir(), "config.jsonc")
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 (!existsSync4(path))
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 = join4(getPiAgentDir(), entry);
9649
+ resolved = join6(getPiAgentDir(), entry);
8289
9650
  }
8290
9651
  if (!resolved)
8291
9652
  return false;
8292
9653
  try {
8293
- if (!existsSync4(resolved))
9654
+ if (!existsSync6(resolved))
8294
9655
  return false;
8295
- const pkgPath = join4(resolved, "package.json");
8296
- if (!existsSync4(pkgPath))
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
- execSync2("pi --version", { stdio: "ignore" });
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 = spawnSync("pi", ["--version"], {
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 ?? join4(configDir, "extensions.json"),
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
- execSync2(`pi install ${PLUGIN_ENTRY2}`, { stdio: "inherit" });
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 (error) {
9741
+ } catch (error2) {
8380
9742
  return {
8381
9743
  ok: false,
8382
9744
  action: "error",
8383
- message: `Failed to run \`pi install ${PLUGIN_ENTRY2}\`: ${error instanceof Error ? error.message : String(error)}`,
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
- join4(getPiAgentDir(), "node_modules", "@cortexkit", "aft-pi", "package.json"),
8391
- join4(getPiAgentDir(), "extensions", "node_modules", "@cortexkit", "aft-pi", "package.json")
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 (!existsSync4(candidate))
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: join4(getPiAgentDir(), "extensions"),
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(join4(storage, "index")),
8431
- semantic: dirSize(join4(storage, "semantic")),
8432
- backups: dirSize(join4(storage, "backups")),
8433
- url_cache: dirSize(join4(storage, "url_cache")),
8434
- onnxruntime: dirSize(join4(storage, "onnxruntime"))
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
- init_paths();
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 init_dist = __esm(() => {
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 init_dist2 = __esm(() => {
8634
- init_dist();
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
- init_dist2();
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 init_dist3 = __esm(() => {
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 init_dist4 = __esm(() => {
9740
- init_dist3();
9741
- init_dist3();
11104
+ var init_dist5 = __esm(() => {
11105
+ init_dist4();
11106
+ init_dist4();
9742
11107
  init_main();
9743
- init_dist2();
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
- init_dist4();
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 (error) {
9954
- O2.warn(`${adapter.displayName}: could not set $schema on aft.jsonc: ${error instanceof Error ? error.message : String(error)}`);
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 = spawn(binaryPath, [], {
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", (error) => {
10060
- finish(() => reject(error));
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 existsSync6, readdirSync as readdirSync2, statSync as statSync3 } from "node:fs";
10274
- import { dirname as dirname3, join as join6, resolve as resolve2 } from "node:path";
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 (existsSync6(resolvedFile) && statSync3(resolvedFile).isDirectory()) {
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) => existsSync6(join6(dir, 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 findBinary = options.findBinary ?? findAftBinary;
10317
- const binary = findBinary(getSelfVersion());
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 = join6(projectRoot, dir, "aft.jsonc");
10425
- const json = join6(projectRoot, dir, "aft.json");
10426
- if (existsSync6(jsonc))
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 (existsSync6(json))
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(join6(entry, "node_modules", ".bin"));
11743
+ paths.add(join7(entry, "node_modules", ".bin"));
10492
11744
  }
10493
11745
  for (const entry of childDirs(getAftLspBinariesDir())) {
10494
- paths.add(join6(entry, "bin"));
11746
+ paths.add(join7(entry, "bin"));
10495
11747
  }
10496
11748
  return [...paths];
10497
11749
  }
10498
11750
  function childDirs(path) {
10499
- if (!existsSync6(path))
11751
+ if (!existsSync7(path))
10500
11752
  return [];
10501
11753
  try {
10502
- return readdirSync2(path).map((entry) => join6(path, entry)).filter((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
- init_paths();
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 existsSync7 } from "node:fs";
10583
- import { homedir as homedir5 } from "node:os";
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 findBinary = options.findBinary ?? findAftBinary;
10614
- const binary = findBinary(getSelfVersion());
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 ? existsSync7(list.project_dir) : false;
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 = homedir5();
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 existsSync8, readdirSync as readdirSync3, statSync as statSync4 } from "node:fs";
10825
- import { join as join7 } from "node:path";
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 (!existsSync8(path)) {
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(join7(path, entry)).isDirectory();
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
- init_paths();
12106
+ init_paths2();
10855
12107
  });
10856
12108
 
10857
12109
  // src/lib/lsp-cache.ts
10858
- import { existsSync as existsSync9, readdirSync as readdirSync4, rmSync as rmSync2, statSync as statSync5 } from "node:fs";
10859
- import { join as join8 } from "node:path";
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 (!existsSync9(path)) {
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 = join8(path, name);
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
- init_paths();
12179
+ init_paths2();
10928
12180
  });
10929
12181
 
10930
12182
  // src/lib/onnx.ts
10931
- import { existsSync as existsSync10, readdirSync as readdirSync5, readlinkSync, realpathSync, statSync as statSync6 } from "node:fs";
10932
- import { basename, isAbsolute, join as join9, resolve as resolve4, win32 } from "node:path";
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 getManualInstallHint() {
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(join9(programFiles, "onnxruntime", "lib"), join9(programFiles, "Microsoft ONNX Runtime", "lib"), join9(programFiles, "Microsoft Machine Learning", "lib"), join9(programFilesX86, "onnxruntime", "lib"), ...(() => {
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 = join9(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
11001
- if (!existsSync10(nugetPackageDir))
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(join9(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join9(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
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 = join9(storageDir, "onnxruntime", ONNX_RUNTIME_VERSION);
12291
+ const ortDir = join10(storageDir, "onnxruntime", ONNX_RUNTIME_VERSION);
11040
12292
  const libName = getOnnxLibraryName();
11041
- if (existsSync10(join9(ortDir, libName)))
12293
+ if (existsSync11(join10(ortDir, libName)))
11042
12294
  return ortDir;
11043
- const libSubdir = join9(ortDir, "lib");
11044
- if (existsSync10(join9(libSubdir, libName)))
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 (!existsSync10(libDir))
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 = join9(libDir, libName);
11081
- if (existsSync10(base)) {
12332
+ const base = join10(libDir, libName);
12333
+ if (existsSync11(base)) {
11082
12334
  try {
11083
- const real = realpathSync(base);
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 realpathSync2 } from "node:fs";
11113
- import { homedir as homedir6, userInfo } from "node:os";
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 realpathSync2(p2);
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 = homedir6();
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 existsSync11,
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 (!existsSync11(storage))
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: existsSync11(configPaths.aftConfig),
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: existsSync11(storage),
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: getManualInstallHint(),
12520
+ installHint: getManualInstallHint2(),
11269
12521
  requirement: `>=${REQUIRED_ORT_MAJOR}.${REQUIRED_ORT_MIN_MINOR}`
11270
12522
  },
11271
12523
  logFile: {
11272
12524
  path: logPath,
11273
- exists: existsSync11(logPath),
11274
- sizeKb: existsSync11(logPath) ? Math.round(statSync7(logPath).size / 1024) : 0
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 (!existsSync11(path))
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 = openSync(path, "r");
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 = readSync(fd, buffer, 0, readLength, position);
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
- closeSync(fd);
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 log = body.slice(logBlockStart, logBlockEnd);
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 = log.split(`
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 existsSync12, rmSync as rmSync3 } from "node:fs";
11648
- import { join as join10 } from "node:path";
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 = join10(harness.storageDir.path, "onnxruntime");
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: existsSync12(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
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: existsSync12(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
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 (!existsSync12(c2.storageOnnxDir)) {
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 existsSync13,
11748
- mkdirSync as mkdirSync2,
13188
+ chmodSync as chmodSync2,
13189
+ existsSync as existsSync15,
13190
+ mkdirSync as mkdirSync3,
11749
13191
  mkdtempSync,
11750
- readFileSync as readFileSync4,
11751
- realpathSync as realpathSync3,
13192
+ readFileSync as readFileSync5,
13193
+ realpathSync as realpathSync4,
11752
13194
  rmSync as rmSync4,
11753
- statSync as statSync8,
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 join11 } from "node:path";
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: true,
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 (!existsSync13(info.path)) {
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 = join11(info.path, version);
13363
+ const dir = join13(info.path, version);
11918
13364
  let bytes = 0;
11919
13365
  try {
11920
- bytes = statSync8(dir).isDirectory() ? dirSize(dir) : 0;
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: true,
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 ensureBinary(`v${report.cliVersion}`);
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 (existsSync13(storageDir))
13627
+ if (existsSync15(storageDir))
12139
13628
  continue;
12140
- mkdirSync2(storageDir, { recursive: true });
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(join11(tmpdir2(), "aft-issue-"));
13730
+ reviewDir = mkdtempSync(join13(tmpdir2(), "aft-issue-"));
12242
13731
  if (process.platform !== "win32") {
12243
- chmodSync(reviewDir, 448);
13732
+ chmodSync2(reviewDir, 448);
12244
13733
  }
12245
- const outPath = join11(reviewDir, "issue.md");
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: realpathSync3(outPath) };
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 = realpathSync3(reviewFile.path);
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 readFileSync4(reviewFile.path, "utf8");
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: true,
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
- ${tail || "<no log output>"}
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
- return sanitizeContent(tailLogFile(path, 4000));
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);