@cortexkit/aft 0.63.5 → 0.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/adapters/opencode.d.ts +7 -5
- package/dist/adapters/opencode.d.ts.map +1 -1
- package/dist/adapters/types.d.ts +12 -2
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/commands/cache.d.ts +2 -2
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/doctor/opencode.d.ts +1 -0
- package/dist/doctor/opencode.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +911 -363
- package/dist/lib/config-migration.d.ts +5 -1
- package/dist/lib/config-migration.d.ts.map +1 -1
- package/dist/lib/diagnostics.d.ts +1 -0
- package/dist/lib/diagnostics.d.ts.map +1 -1
- package/dist/lib/doctor-labels.d.ts +4 -0
- package/dist/lib/doctor-labels.d.ts.map +1 -0
- package/dist/lib/opencode-plugin-cache.d.ts +9 -0
- package/dist/lib/opencode-plugin-cache.d.ts.map +1 -0
- package/dist/lib/sanitize.d.ts +12 -6
- package/dist/lib/sanitize.d.ts.map +1 -1
- package/dist/lib/semver.d.ts +3 -0
- package/dist/lib/semver.d.ts.map +1 -0
- package/dist/setup/opencode-config.d.ts +12 -4
- package/dist/setup/opencode-config.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -263,10 +263,87 @@ function relativePathEscapesRoot(rel, platform = process.platform) {
|
|
|
263
263
|
}
|
|
264
264
|
var init_path_display = () => {};
|
|
265
265
|
|
|
266
|
+
// ../aft-bridge/dist/wait-clock.js
|
|
267
|
+
class WaitClock {
|
|
268
|
+
wallNow;
|
|
269
|
+
awakeNow;
|
|
270
|
+
wall;
|
|
271
|
+
awake;
|
|
272
|
+
skew = 0;
|
|
273
|
+
elapsed;
|
|
274
|
+
suspendCount = 0;
|
|
275
|
+
lastSuspendEnd = Number.NEGATIVE_INFINITY;
|
|
276
|
+
constructor(wallNow = Date.now, awakeNow = () => performance.now()) {
|
|
277
|
+
this.wallNow = wallNow;
|
|
278
|
+
this.awakeNow = awakeNow;
|
|
279
|
+
this.wall = wallNow();
|
|
280
|
+
this.awake = awakeNow();
|
|
281
|
+
this.elapsed = this.awake;
|
|
282
|
+
}
|
|
283
|
+
now() {
|
|
284
|
+
const wall = this.wallNow();
|
|
285
|
+
const awake = this.awakeNow();
|
|
286
|
+
const active = Math.max(0, awake - this.awake);
|
|
287
|
+
this.skew = Math.max(0, this.skew + wall - this.wall - active);
|
|
288
|
+
this.elapsed += active;
|
|
289
|
+
if (this.skew >= SUSPEND_SKEW_MS) {
|
|
290
|
+
this.elapsed += this.skew;
|
|
291
|
+
this.lastSuspendEnd = this.elapsed;
|
|
292
|
+
this.skew = 0;
|
|
293
|
+
this.suspendCount++;
|
|
294
|
+
}
|
|
295
|
+
this.wall = wall;
|
|
296
|
+
this.awake = awake;
|
|
297
|
+
return this.elapsed;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
class RequestDeadline {
|
|
302
|
+
clock;
|
|
303
|
+
allowResume;
|
|
304
|
+
deadline;
|
|
305
|
+
suspendCount;
|
|
306
|
+
resumed = false;
|
|
307
|
+
constructor(clock, timeoutMs, allowResume = true) {
|
|
308
|
+
this.clock = clock;
|
|
309
|
+
this.allowResume = allowResume;
|
|
310
|
+
this.deadline = clock.now() + timeoutMs;
|
|
311
|
+
this.suspendCount = clock.suspendCount;
|
|
312
|
+
}
|
|
313
|
+
remaining() {
|
|
314
|
+
const now = this.clock.now();
|
|
315
|
+
if (now >= this.deadline && this.allowResume && !this.resumed && this.clock.suspendCount > this.suspendCount && this.clock.lastSuspendEnd >= this.deadline) {
|
|
316
|
+
this.resumed = true;
|
|
317
|
+
this.deadline = now + RESUME_ALLOWANCE_MS;
|
|
318
|
+
}
|
|
319
|
+
return Math.max(0, this.deadline - now);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
var SUSPEND_SKEW_MS = 1000, RESUME_ALLOWANCE_MS = 1e4, DEADLINE_POLL_MS = 250;
|
|
323
|
+
|
|
266
324
|
// ../aft-bridge/dist/bash-hints.js
|
|
325
|
+
function abortableSleep(ms, signal) {
|
|
326
|
+
if (signal?.aborted)
|
|
327
|
+
return Promise.resolve();
|
|
328
|
+
return new Promise((resolve) => {
|
|
329
|
+
const done = () => {
|
|
330
|
+
clearTimeout(timer);
|
|
331
|
+
signal?.removeEventListener("abort", done);
|
|
332
|
+
resolve();
|
|
333
|
+
};
|
|
334
|
+
const timer = setTimeout(done, ms);
|
|
335
|
+
signal?.addEventListener("abort", done, { once: true });
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
var watchClock;
|
|
267
339
|
var init_bash_hints = __esm(() => {
|
|
268
340
|
init_bash_format();
|
|
269
341
|
init_path_display();
|
|
342
|
+
watchClock = {
|
|
343
|
+
source: new WaitClock,
|
|
344
|
+
now: () => watchClock.source.now(),
|
|
345
|
+
sleep: abortableSleep
|
|
346
|
+
};
|
|
270
347
|
});
|
|
271
348
|
|
|
272
349
|
// ../aft-bridge/dist/test-child-environment.js
|
|
@@ -498,12 +575,13 @@ function resolvePluginLogPath(context = {}) {
|
|
|
498
575
|
var init_storage_paths = () => {};
|
|
499
576
|
|
|
500
577
|
// ../aft-bridge/dist/bash-host-fallback.js
|
|
501
|
-
var BASH_HOST_FALLBACK_MAX_OUTPUT_BYTES, BASH_HOST_FALLBACK_MAX_TIMEOUT_MS;
|
|
578
|
+
var BASH_HOST_FALLBACK_MAX_OUTPUT_BYTES, BASH_HOST_FALLBACK_MAX_TIMEOUT_MS, BASH_RUNON_MEMORY_DESCRIPTION = "On Linux, add `,Ngb` to ask for N GiB of memory, for example `linux,2c,16gb` for a Rust build.", BASH_RUNON_DESCRIPTION;
|
|
502
579
|
var init_bash_host_fallback = __esm(() => {
|
|
503
580
|
init_child_process();
|
|
504
581
|
init_storage_paths();
|
|
505
582
|
BASH_HOST_FALLBACK_MAX_OUTPUT_BYTES = 100 * 1024;
|
|
506
583
|
BASH_HOST_FALLBACK_MAX_TIMEOUT_MS = 10 * 60 * 1000;
|
|
584
|
+
BASH_RUNON_DESCRIPTION = 'Run on a remote build server: `linux` (2 vCPUs), or `linux,Nc` for N vCPUs such as `linux,8c`; add ",net" for outbound internet (offline by default). `windows` runs the command in Git Bash on a Windows build machine (no vCPU or network options). `macos` sends the command to a macOS machine for builds and tests that need macOS (no vCPU or network options).' + ` ${BASH_RUNON_MEMORY_DESCRIPTION}`;
|
|
507
585
|
});
|
|
508
586
|
// ../aft-bridge/dist/bash-permissions.js
|
|
509
587
|
var init_bash_permissions = __esm(() => {
|
|
@@ -881,6 +959,7 @@ var init_bridge = __esm(() => {
|
|
|
881
959
|
binaryFingerprintAsyncReader = binaryContentHash;
|
|
882
960
|
SYSTEM_CLOCK = {
|
|
883
961
|
now: () => Date.now(),
|
|
962
|
+
awakeNow: () => performance.now(),
|
|
884
963
|
setTimeout: (callback, ms) => setTimeout(callback, ms),
|
|
885
964
|
clearTimeout: (timer) => clearTimeout(timer)
|
|
886
965
|
};
|
|
@@ -960,6 +1039,7 @@ var init_bridge = __esm(() => {
|
|
|
960
1039
|
hangWindowMinMs;
|
|
961
1040
|
hangProbeTimeoutMs;
|
|
962
1041
|
clock;
|
|
1042
|
+
waitClock;
|
|
963
1043
|
lateShellReplyGraceMs;
|
|
964
1044
|
maxRestarts;
|
|
965
1045
|
configured = false;
|
|
@@ -996,6 +1076,7 @@ var init_bridge = __esm(() => {
|
|
|
996
1076
|
this.hangWindowMinMs = options?.hangWindowMinMs ?? DEFAULT_MIN_HANG_WINDOW_MS;
|
|
997
1077
|
this.hangProbeTimeoutMs = options?.hangProbeTimeoutMs ?? DEFAULT_HANG_PROBE_TIMEOUT_MS;
|
|
998
1078
|
this.clock = options?.clock ?? SYSTEM_CLOCK;
|
|
1079
|
+
this.waitClock = new WaitClock(() => this.clock.now(), () => this.clock.awakeNow?.() ?? this.clock.now());
|
|
999
1080
|
this.lateShellReplyGraceMs = options?.lateShellReplyGraceMs ?? DEFAULT_LATE_SHELL_REPLY_GRACE_MS;
|
|
1000
1081
|
this.maxRestarts = options?.maxRestarts ?? 3;
|
|
1001
1082
|
this.errorPrefix = options?.errorPrefix ?? "[aft-bridge]";
|
|
@@ -1362,11 +1443,17 @@ var init_bridge = __esm(() => {
|
|
|
1362
1443
|
const keepBridgeOnTimeout = passive || command === "bash_drain_completions" || options?.keepBridgeOnTimeout === true;
|
|
1363
1444
|
const child = this.process;
|
|
1364
1445
|
const response = await new Promise((resolve, reject) => {
|
|
1365
|
-
const
|
|
1446
|
+
const deadline = new RequestDeadline(this.waitClock, effectiveTimeoutMs);
|
|
1447
|
+
const expire = () => {
|
|
1366
1448
|
const entry = this.pending.get(id);
|
|
1367
1449
|
if (!entry)
|
|
1368
1450
|
return;
|
|
1369
|
-
|
|
1451
|
+
const remaining = deadline.remaining();
|
|
1452
|
+
if (remaining > 0) {
|
|
1453
|
+
entry.timer = this.clock.setTimeout(expire, Math.min(remaining, DEADLINE_POLL_MS));
|
|
1454
|
+
return;
|
|
1455
|
+
}
|
|
1456
|
+
if (keepBridgeOnTimeout && !deadline.resumed && this.holdForLateShellReply(id, entry, effectiveTimeoutMs, requestSessionId)) {
|
|
1370
1457
|
return;
|
|
1371
1458
|
}
|
|
1372
1459
|
this.pending.delete(id);
|
|
@@ -1379,11 +1466,12 @@ var init_bridge = __esm(() => {
|
|
|
1379
1466
|
this.warnVia(timeoutMsg);
|
|
1380
1467
|
}
|
|
1381
1468
|
if (keepBridgeOnTimeout) {
|
|
1382
|
-
entry.reject(new BridgeTransportTimeoutError(command, effectiveTimeoutMs, `${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms
|
|
1469
|
+
entry.reject(new BridgeTransportTimeoutError(command, effectiveTimeoutMs, `${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`, deadline.resumed && SHELL_TASK_COMMANDS.has(command) ? { kind: "unknown" } : undefined));
|
|
1383
1470
|
return;
|
|
1384
1471
|
}
|
|
1385
1472
|
entry.reject(new Error(`${this.errorPrefix} request "${command}" timed out after ${effectiveTimeoutMs}ms (bridge busy/under load); bridge kept warm — retry. A timed-out mutation may still complete; inspect before repeating it.`));
|
|
1386
|
-
}
|
|
1473
|
+
};
|
|
1474
|
+
const timer = this.clock.setTimeout(expire, Math.min(effectiveTimeoutMs, DEADLINE_POLL_MS));
|
|
1387
1475
|
const entry = {
|
|
1388
1476
|
resolve,
|
|
1389
1477
|
reject,
|
|
@@ -1939,14 +2027,21 @@ var init_bridge = __esm(() => {
|
|
|
1939
2027
|
};
|
|
1940
2028
|
entry.resolve = (response) => settle(shellOutcomeFromLateReply(response));
|
|
1941
2029
|
this.clock.clearTimeout(entry.timer);
|
|
1942
|
-
|
|
2030
|
+
const deadline = new RequestDeadline(this.waitClock, graceMs, false);
|
|
2031
|
+
const expire = () => {
|
|
1943
2032
|
if (this.pending.get(id) !== entry)
|
|
1944
2033
|
return;
|
|
2034
|
+
const remaining = deadline.remaining();
|
|
2035
|
+
if (remaining > 0) {
|
|
2036
|
+
entry.timer = this.clock.setTimeout(expire, Math.min(remaining, DEADLINE_POLL_MS));
|
|
2037
|
+
return;
|
|
2038
|
+
}
|
|
1945
2039
|
this.pending.delete(id);
|
|
1946
2040
|
entry.onSettled?.();
|
|
1947
2041
|
this.warnVia(`Request "${entry.command}" (id=${id}) got no reply within ${graceMs}ms after its deadline`);
|
|
1948
2042
|
settle({ kind: "unknown" });
|
|
1949
|
-
}
|
|
2043
|
+
};
|
|
2044
|
+
entry.timer = this.clock.setTimeout(expire, Math.min(graceMs, DEADLINE_POLL_MS));
|
|
1950
2045
|
return true;
|
|
1951
2046
|
}
|
|
1952
2047
|
accountForBashTaskResponse(command, response) {
|
|
@@ -2289,7 +2384,10 @@ function readConfigTiers(opts) {
|
|
|
2289
2384
|
var init_config_tiers = () => {};
|
|
2290
2385
|
|
|
2291
2386
|
// ../aft-bridge/dist/config-watch.js
|
|
2292
|
-
var
|
|
2387
|
+
var CONFIG_READ_LIMIT;
|
|
2388
|
+
var init_config_watch = __esm(() => {
|
|
2389
|
+
CONFIG_READ_LIMIT = 1024 * 1024;
|
|
2390
|
+
});
|
|
2293
2391
|
|
|
2294
2392
|
// ../aft-bridge/dist/platform.js
|
|
2295
2393
|
var PLATFORM_ARCH_MAP, PLATFORM_ASSET_MAP;
|
|
@@ -2836,10 +2934,11 @@ var init_durable_log = __esm(() => {
|
|
|
2836
2934
|
init_storage_paths();
|
|
2837
2935
|
DEFAULT_LOG_BYTES = 32 * 1024 * 1024;
|
|
2838
2936
|
});
|
|
2839
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
2840
|
-
var MAX_FRAME_BODY_LEN, FrameType, FRAME_TYPE_MAX, Priority, AdmissionClass;
|
|
2937
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/envelope.js
|
|
2938
|
+
var MAX_FRAME_BODY_LEN, MAX_DELIVERED_FRAME_LEN, FrameType, FRAME_TYPE_MAX, Priority, AdmissionClass;
|
|
2841
2939
|
var init_envelope = __esm(() => {
|
|
2842
2940
|
MAX_FRAME_BODY_LEN = 64 * 1024 * 1024;
|
|
2941
|
+
MAX_DELIVERED_FRAME_LEN = 4 * 1024 * 1024;
|
|
2843
2942
|
(function(FrameType) {
|
|
2844
2943
|
FrameType[FrameType["Request"] = 0] = "Request";
|
|
2845
2944
|
FrameType[FrameType["Response"] = 1] = "Response";
|
|
@@ -2867,7 +2966,7 @@ var init_envelope = __esm(() => {
|
|
|
2867
2966
|
})(AdmissionClass || (AdmissionClass = {}));
|
|
2868
2967
|
});
|
|
2869
2968
|
|
|
2870
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
2969
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/socket.js
|
|
2871
2970
|
var WRITE_BORROWED, WRITE_TRACKED_BORROWED;
|
|
2872
2971
|
var init_socket = __esm(() => {
|
|
2873
2972
|
init_envelope();
|
|
@@ -2875,17 +2974,17 @@ var init_socket = __esm(() => {
|
|
|
2875
2974
|
WRITE_TRACKED_BORROWED = Symbol("subc.socket.writeTrackedBorrowed");
|
|
2876
2975
|
});
|
|
2877
2976
|
|
|
2878
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
2977
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/auth.js
|
|
2879
2978
|
var init_auth = __esm(() => {
|
|
2880
2979
|
init_socket();
|
|
2881
2980
|
});
|
|
2882
2981
|
|
|
2883
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
2982
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/connection-file.js
|
|
2884
2983
|
var init_connection_file = __esm(() => {
|
|
2885
2984
|
init_envelope();
|
|
2886
2985
|
});
|
|
2887
2986
|
|
|
2888
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
2987
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/launch-nonce.js
|
|
2889
2988
|
var PROCESS_CELL_KEY, U64_MAX, I32_MAX, RedactedLaunchNonce;
|
|
2890
2989
|
var init_launch_nonce = __esm(() => {
|
|
2891
2990
|
PROCESS_CELL_KEY = Symbol.for("@cortexkit/subc-client/launch-nonce/v1");
|
|
@@ -2910,15 +3009,14 @@ var init_launch_nonce = __esm(() => {
|
|
|
2910
3009
|
}
|
|
2911
3010
|
};
|
|
2912
3011
|
});
|
|
2913
|
-
|
|
2914
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.21.2/node_modules/@cortexkit/subc-client/dist/route-handle.js
|
|
3012
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/route-handle.js
|
|
2915
3013
|
var connectionToken, reverseRequests;
|
|
2916
3014
|
var init_route_handle = __esm(() => {
|
|
2917
3015
|
connectionToken = new WeakMap;
|
|
2918
3016
|
reverseRequests = new WeakMap;
|
|
2919
3017
|
});
|
|
2920
3018
|
|
|
2921
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
3019
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/client.js
|
|
2922
3020
|
import { debuglog } from "node:util";
|
|
2923
3021
|
var debug, EMPTY_BODY, errorFrameFlags, SCOPE_ROUTE_CLOSE_REASONS, ROUTE_OPEN_ADMISSION_PRESSURE_REASONS;
|
|
2924
3022
|
var init_client = __esm(() => {
|
|
@@ -2940,8 +3038,7 @@ var init_client = __esm(() => {
|
|
|
2940
3038
|
]);
|
|
2941
3039
|
ROUTE_OPEN_ADMISSION_PRESSURE_REASONS = new Set(["open_admission_full", "target_binds_full"]);
|
|
2942
3040
|
});
|
|
2943
|
-
|
|
2944
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.21.2/node_modules/@cortexkit/subc-client/dist/provider.js
|
|
3041
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/provider.js
|
|
2945
3042
|
var init_provider = __esm(() => {
|
|
2946
3043
|
init_auth();
|
|
2947
3044
|
init_client();
|
|
@@ -2952,7 +3049,7 @@ var init_provider = __esm(() => {
|
|
|
2952
3049
|
init_socket();
|
|
2953
3050
|
});
|
|
2954
3051
|
|
|
2955
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
3052
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/index.js
|
|
2956
3053
|
var init_dist = __esm(() => {
|
|
2957
3054
|
init_client();
|
|
2958
3055
|
init_route_handle();
|
|
@@ -3539,6 +3636,45 @@ function dropNoEffectPaths(map, prefix, out) {
|
|
|
3539
3636
|
}
|
|
3540
3637
|
}
|
|
3541
3638
|
}
|
|
3639
|
+
function retiredIdleCheckoutHours(value) {
|
|
3640
|
+
const raw = typeof value === "number" && Number.isSafeInteger(value) ? value : IDLE_CHECKOUT_HOURS_DEFAULT;
|
|
3641
|
+
return Math.min(IDLE_CHECKOUT_HOURS_MAX, Math.max(IDLE_CHECKOUT_HOURS_MIN, raw));
|
|
3642
|
+
}
|
|
3643
|
+
function translateDataLayerPaths(map, prefix, out) {
|
|
3644
|
+
const [retired, replacement] = RETIRED_IDLE_CHECKOUT_HOURS;
|
|
3645
|
+
const hours = takeNested(map, "views", "idle_checkout_hours");
|
|
3646
|
+
if (hours.found) {
|
|
3647
|
+
recordRetired(out, prefix, retired);
|
|
3648
|
+
if (isRecord(map.idle) && map.idle.checkout_hours !== undefined) {
|
|
3649
|
+
superseded(out, `${prefix}${retired}`, `${retired} is ignored because ${replacement} is set`);
|
|
3650
|
+
} else {
|
|
3651
|
+
if (!Object.hasOwn(map, "idle"))
|
|
3652
|
+
map.idle = {};
|
|
3653
|
+
if (isRecord(map.idle))
|
|
3654
|
+
map.idle.checkout_hours = retiredIdleCheckoutHours(hours.value);
|
|
3655
|
+
}
|
|
3656
|
+
}
|
|
3657
|
+
for (const path of REMOVED_DATA_LAYER_PATHS) {
|
|
3658
|
+
const [container, leaf] = path.split(".");
|
|
3659
|
+
if (container && leaf && takeNested(map, container, leaf).found)
|
|
3660
|
+
recordRetired(out, prefix, path);
|
|
3661
|
+
}
|
|
3662
|
+
}
|
|
3663
|
+
function dropRemovedDataLayerKeys(map) {
|
|
3664
|
+
const blocks = [map];
|
|
3665
|
+
if (isRecord(map.harnesses)) {
|
|
3666
|
+
for (const block of Object.values(map.harnesses))
|
|
3667
|
+
if (isRecord(block))
|
|
3668
|
+
blocks.push(block);
|
|
3669
|
+
}
|
|
3670
|
+
for (const block of blocks) {
|
|
3671
|
+
for (const path of REMOVED_DATA_LAYER_PATHS) {
|
|
3672
|
+
const [container, leaf] = path.split(".");
|
|
3673
|
+
if (container && leaf)
|
|
3674
|
+
takeNested(block, container, leaf);
|
|
3675
|
+
}
|
|
3676
|
+
}
|
|
3677
|
+
}
|
|
3542
3678
|
function translateExperimentalPaths(map, prefix, out) {
|
|
3543
3679
|
for (const [oldKey, leaf] of [
|
|
3544
3680
|
["experimental_lsp_ty", "lsp_ty"],
|
|
@@ -3571,23 +3707,25 @@ function translateExperimentalPaths(map, prefix, out) {
|
|
|
3571
3707
|
const experimental = map.experimental;
|
|
3572
3708
|
const legacy = experimental.bash;
|
|
3573
3709
|
if (isRecord(legacy)) {
|
|
3574
|
-
if (
|
|
3575
|
-
|
|
3710
|
+
if (Object.keys(legacy).length === 0)
|
|
3711
|
+
recordRetired(out, prefix, "experimental.bash");
|
|
3576
3712
|
for (const leaf of Object.keys(legacy))
|
|
3577
3713
|
recordRetired(out, prefix, `experimental.bash.${leaf}`);
|
|
3578
3714
|
if (Object.hasOwn(map, "bash")) {
|
|
3579
3715
|
superseded(out, "experimental.bash", 'experimental.bash is ignored because top-level "bash" is already set');
|
|
3580
3716
|
} else {
|
|
3581
|
-
const bash = {
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3717
|
+
const bash = {};
|
|
3718
|
+
if (["rewrite", "compress", "background"].some((leaf) => Object.hasOwn(legacy, leaf))) {
|
|
3719
|
+
bash.rewrite = legacy.rewrite === true;
|
|
3720
|
+
bash.compress = legacy.compress === true;
|
|
3721
|
+
bash.background = legacy.background === true;
|
|
3722
|
+
}
|
|
3586
3723
|
for (const leaf of ["long_running_reminder_enabled", "long_running_reminder_interval_ms"]) {
|
|
3587
3724
|
if (Object.hasOwn(legacy, leaf))
|
|
3588
3725
|
bash[leaf] = legacy[leaf];
|
|
3589
3726
|
}
|
|
3590
|
-
|
|
3727
|
+
if (Object.keys(bash).length > 0)
|
|
3728
|
+
map.bash = bash;
|
|
3591
3729
|
}
|
|
3592
3730
|
} else {
|
|
3593
3731
|
recordRetired(out, prefix, "experimental.bash");
|
|
@@ -3600,6 +3738,7 @@ function translateBlock(map, userBase, blockLabel, out) {
|
|
|
3600
3738
|
const prefix = blockLabel === "base" ? "" : `${blockLabel}.`;
|
|
3601
3739
|
translateGithubAliases(map, prefix, out);
|
|
3602
3740
|
translateInspectLspPaths(map, prefix, out);
|
|
3741
|
+
translateDataLayerPaths(map, prefix, out);
|
|
3603
3742
|
dropNoEffectPaths(map, prefix, out);
|
|
3604
3743
|
translateExperimentalPaths(map, prefix, out);
|
|
3605
3744
|
if (isRecord(map.sandbox) && Object.hasOwn(map.sandbox, "enabled")) {
|
|
@@ -3638,8 +3777,6 @@ function translateBlock(map, userBase, blockLabel, out) {
|
|
|
3638
3777
|
});
|
|
3639
3778
|
}
|
|
3640
3779
|
for (const [path] of RETIRED_PATHS) {
|
|
3641
|
-
if (path === "experimental.bash")
|
|
3642
|
-
continue;
|
|
3643
3780
|
if (hasPath(map, path))
|
|
3644
3781
|
recordRetired(out, prefix, path);
|
|
3645
3782
|
}
|
|
@@ -3808,7 +3945,7 @@ function mergeIndexes(base, override, restricted) {
|
|
|
3808
3945
|
}
|
|
3809
3946
|
return merged;
|
|
3810
3947
|
}
|
|
3811
|
-
var CANONICAL_TOOLS, HOST_TOOL_NAMES, DEFAULT_DISABLED_TOOLS, LEGACY_TOOL_ALIASES, RETIRED_PATHS, INDEX_INPUTS, LSP_IDLE_MINUTES_DEFAULT = 60, LSP_IDLE_MINUTES_MIN = 5, LSP_IDLE_MINUTES_MAX = 1440, REMOVED_NO_EFFECT_PATHS, RETIRED_ENABLED_FALSE_INDEXES_NOTE = "enabled: false no longer turns AFT off: it is translated to disabling every tool, but the trigram, semantic and callgraph indexes still build. To keep AFT from indexing this repository, also set indexes.trigram, indexes.semantic and indexes.callgraph to false.", SEMANTIC_COST_NOTICE_DIGEST, SECURITY_CONFIG_SECTIONS;
|
|
3948
|
+
var CANONICAL_TOOLS, HOST_TOOL_NAMES, DEFAULT_DISABLED_TOOLS, LEGACY_TOOL_ALIASES, REMOVED_DATA_LAYER_PATHS, RETIRED_IDLE_CHECKOUT_HOURS, IDLE_CHECKOUT_HOURS_DEFAULT = 168, IDLE_CHECKOUT_HOURS_MIN = 1, IDLE_CHECKOUT_HOURS_MAX, AFT_PACKAGE_NAMES, RETIRED_PATHS, INDEX_INPUTS, LSP_IDLE_MINUTES_DEFAULT = 60, LSP_IDLE_MINUTES_MIN = 5, LSP_IDLE_MINUTES_MAX = 1440, REMOVED_NO_EFFECT_PATHS, RETIRED_ENABLED_FALSE_INDEXES_NOTE = "enabled: false no longer turns AFT off: it is translated to disabling every tool, but the trigram, semantic and callgraph indexes still build. To keep AFT from indexing this repository, also set indexes.trigram, indexes.semantic and indexes.callgraph to false.", SEMANTIC_COST_NOTICE_DIGEST, SECURITY_CONFIG_SECTIONS;
|
|
3812
3949
|
var init_feature_config = __esm(() => {
|
|
3813
3950
|
CANONICAL_TOOLS = [
|
|
3814
3951
|
"aft_callgraph",
|
|
@@ -3854,6 +3991,22 @@ var init_feature_config = __esm(() => {
|
|
|
3854
3991
|
aft_glob: "glob",
|
|
3855
3992
|
aft_bash: "bash"
|
|
3856
3993
|
};
|
|
3994
|
+
REMOVED_DATA_LAYER_PATHS = [
|
|
3995
|
+
"views.callgraph_copies",
|
|
3996
|
+
"views.enabled",
|
|
3997
|
+
"worktree.ram_overlay"
|
|
3998
|
+
];
|
|
3999
|
+
RETIRED_IDLE_CHECKOUT_HOURS = [
|
|
4000
|
+
"views.idle_checkout_hours",
|
|
4001
|
+
"idle.checkout_hours"
|
|
4002
|
+
];
|
|
4003
|
+
IDLE_CHECKOUT_HOURS_MAX = 24 * 365;
|
|
4004
|
+
AFT_PACKAGE_NAMES = new Set([
|
|
4005
|
+
"@cortexkit/aft-bridge",
|
|
4006
|
+
"@cortexkit/aft-opencode",
|
|
4007
|
+
"@cortexkit/aft-pi",
|
|
4008
|
+
"@cortexkit/aft"
|
|
4009
|
+
]);
|
|
3857
4010
|
RETIRED_PATHS = [
|
|
3858
4011
|
["sandbox.enabled", "sandbox.profile"],
|
|
3859
4012
|
["tool_surface", "disabled_tools"],
|
|
@@ -3876,7 +4029,10 @@ var init_feature_config = __esm(() => {
|
|
|
3876
4029
|
["semantic", "semantic_search", "experimental_semantic_search"],
|
|
3877
4030
|
["callgraph", "callgraph_store", undefined]
|
|
3878
4031
|
];
|
|
3879
|
-
REMOVED_NO_EFFECT_PATHS = [
|
|
4032
|
+
REMOVED_NO_EFFECT_PATHS = [
|
|
4033
|
+
"bridge.hang_threshold",
|
|
4034
|
+
"inspect.tier2_idle_minutes"
|
|
4035
|
+
];
|
|
3880
4036
|
SEMANTIC_COST_NOTICE_DIGEST = noticeDigest({ notice: "semantic_default_cost_v1" });
|
|
3881
4037
|
SECURITY_CONFIG_SECTIONS = new Set([
|
|
3882
4038
|
"restrict_to_project_root",
|
|
@@ -4127,6 +4283,8 @@ function quoteCmdArgument(value) {
|
|
|
4127
4283
|
return `"${value}"`;
|
|
4128
4284
|
}
|
|
4129
4285
|
function npmInvocation(resolved, npmArgs, platform = process.platform, env = process.env) {
|
|
4286
|
+
if (resolved.cliPath)
|
|
4287
|
+
return { command: resolved.command, args: [resolved.cliPath, ...npmArgs] };
|
|
4130
4288
|
if (platform !== "win32" || !/\.(?:cmd|bat)$/i.test(resolved.command)) {
|
|
4131
4289
|
return { command: resolved.command, args: [...npmArgs] };
|
|
4132
4290
|
}
|
|
@@ -4319,6 +4477,12 @@ var init_lsp_npm_policy = __esm(() => {
|
|
|
4319
4477
|
NPM_PROBE_RETRY_MS = 5 * 60000;
|
|
4320
4478
|
});
|
|
4321
4479
|
|
|
4480
|
+
// ../aft-bridge/dist/lsp-npm-selection.js
|
|
4481
|
+
var init_lsp_npm_selection = __esm(() => {
|
|
4482
|
+
init_lsp_npm_policy();
|
|
4483
|
+
init_npm_resolver();
|
|
4484
|
+
});
|
|
4485
|
+
|
|
4322
4486
|
// ../aft-bridge/dist/message-detach.js
|
|
4323
4487
|
var BASH_WAIT_DETACH_MAGIC_KEYWORD = "&detach", STANDALONE_DETACH_KEYWORD_SOURCE, STANDALONE_DETACH_KEYWORD_PATTERN, STANDALONE_DETACH_KEYWORDS_PATTERN;
|
|
4324
4488
|
var init_message_detach = __esm(() => {
|
|
@@ -5489,6 +5653,7 @@ var init_dist2 = __esm(() => {
|
|
|
5489
5653
|
init_lsp_github_probe();
|
|
5490
5654
|
init_lsp_github_table();
|
|
5491
5655
|
init_lsp_npm_policy();
|
|
5656
|
+
init_lsp_npm_selection();
|
|
5492
5657
|
init_message_detach();
|
|
5493
5658
|
init_migration();
|
|
5494
5659
|
init_migration_notices();
|
|
@@ -14177,27 +14342,54 @@ var init_jsonc = __esm(() => {
|
|
|
14177
14342
|
import_comment_json = __toESM(require_src2(), 1);
|
|
14178
14343
|
});
|
|
14179
14344
|
|
|
14180
|
-
// src/lib/self-version.ts
|
|
14181
|
-
import { createRequire as createRequire2 } from "node:module";
|
|
14182
|
-
function getSelfVersion() {
|
|
14183
|
-
const require2 = createRequire2(import.meta.url);
|
|
14184
|
-
for (const relPath of ["../../package.json", "../package.json"]) {
|
|
14185
|
-
try {
|
|
14186
|
-
const version = require2(relPath).version;
|
|
14187
|
-
if (typeof version === "string" && version.length > 0) {
|
|
14188
|
-
return version;
|
|
14189
|
-
}
|
|
14190
|
-
} catch {}
|
|
14191
|
-
}
|
|
14192
|
-
return "unknown";
|
|
14193
|
-
}
|
|
14194
|
-
var init_self_version = () => {};
|
|
14195
|
-
|
|
14196
14345
|
// ../../.github/opencode-version.txt
|
|
14197
14346
|
var opencode_version_default = `1.19.3
|
|
14198
14347
|
`;
|
|
14199
14348
|
var init_opencode_version = () => {};
|
|
14200
14349
|
|
|
14350
|
+
// src/lib/semver.ts
|
|
14351
|
+
function parse2(version) {
|
|
14352
|
+
const match = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/.exec(version);
|
|
14353
|
+
if (!match)
|
|
14354
|
+
return;
|
|
14355
|
+
const prerelease = match[4]?.split(".") ?? [];
|
|
14356
|
+
if (prerelease.some((part) => /^\d+$/.test(part) && part.length > 1 && part[0] === "0")) {
|
|
14357
|
+
return;
|
|
14358
|
+
}
|
|
14359
|
+
return { core: match.slice(1, 4).map(BigInt), prerelease };
|
|
14360
|
+
}
|
|
14361
|
+
function compareSemver2(left, right) {
|
|
14362
|
+
const a = parse2(left);
|
|
14363
|
+
const b = parse2(right);
|
|
14364
|
+
if (!a || !b)
|
|
14365
|
+
return;
|
|
14366
|
+
for (let i = 0;i < 3; i++) {
|
|
14367
|
+
if (a.core[i] !== b.core[i])
|
|
14368
|
+
return a.core[i] > b.core[i] ? 1 : -1;
|
|
14369
|
+
}
|
|
14370
|
+
if (!a.prerelease.length || !b.prerelease.length) {
|
|
14371
|
+
return a.prerelease.length === b.prerelease.length ? 0 : a.prerelease.length ? -1 : 1;
|
|
14372
|
+
}
|
|
14373
|
+
for (let i = 0;i < Math.max(a.prerelease.length, b.prerelease.length); i++) {
|
|
14374
|
+
const x = a.prerelease[i];
|
|
14375
|
+
const y = b.prerelease[i];
|
|
14376
|
+
if (x === y)
|
|
14377
|
+
continue;
|
|
14378
|
+
if (x === undefined)
|
|
14379
|
+
return -1;
|
|
14380
|
+
if (y === undefined)
|
|
14381
|
+
return 1;
|
|
14382
|
+
const xn = /^\d+$/.test(x);
|
|
14383
|
+
const yn = /^\d+$/.test(y);
|
|
14384
|
+
if (xn && yn)
|
|
14385
|
+
return BigInt(x) > BigInt(y) ? 1 : -1;
|
|
14386
|
+
if (xn !== yn)
|
|
14387
|
+
return xn ? -1 : 1;
|
|
14388
|
+
return x > y ? 1 : -1;
|
|
14389
|
+
}
|
|
14390
|
+
return 0;
|
|
14391
|
+
}
|
|
14392
|
+
|
|
14201
14393
|
// src/setup/opencode-config.ts
|
|
14202
14394
|
function openCodePluginKey(generation) {
|
|
14203
14395
|
return generation === "v2" ? "plugins" : "plugin";
|
|
@@ -14215,6 +14407,24 @@ function openCodePluginReadKeys(generation) {
|
|
|
14215
14407
|
function pinnedPluginEntry(version) {
|
|
14216
14408
|
return `${AFT_OPENCODE_PACKAGE}@${version}`;
|
|
14217
14409
|
}
|
|
14410
|
+
function preserveDoctorPluginEntry(cli, entry, installed) {
|
|
14411
|
+
const configured = entry ? exactPinnedVersion(entry) : null;
|
|
14412
|
+
const configuredOrder = configured ? compareSemver2(configured, cli) : undefined;
|
|
14413
|
+
const installedOrder = installed ? compareSemver2(installed, cli) : undefined;
|
|
14414
|
+
if (installed && (installedOrder === undefined || installedOrder > 0))
|
|
14415
|
+
return true;
|
|
14416
|
+
if (configured && (configuredOrder === undefined || configuredOrder > 0))
|
|
14417
|
+
return true;
|
|
14418
|
+
if (entry === AFT_OPENCODE_PACKAGE)
|
|
14419
|
+
return false;
|
|
14420
|
+
return Boolean(entry && configuredOrder === undefined && installedOrder === undefined);
|
|
14421
|
+
}
|
|
14422
|
+
function doctorNoDowngradeMessage(cli, entry, installed) {
|
|
14423
|
+
const configured = entry ? exactPinnedVersion(entry) : null;
|
|
14424
|
+
const newerInstalled = installed && (compareSemver2(installed, cli) ?? 1) > 0;
|
|
14425
|
+
const plugin = newerInstalled ? installed : (configured ?? entry?.slice(AFT_OPENCODE_PACKAGE.length + 1)) || "unknown";
|
|
14426
|
+
return DOCTOR_NO_DOWNGRADE.replace("<cli>", cli).replace("<plugin>", plugin);
|
|
14427
|
+
}
|
|
14218
14428
|
function describePluginEntry(entry) {
|
|
14219
14429
|
if (entry === AFT_OPENCODE_PACKAGE) {
|
|
14220
14430
|
return "has no version, so OpenCode may load any release of the plugin";
|
|
@@ -14287,8 +14497,8 @@ function findLocalAftEntry(list, hasLocalAftEntry) {
|
|
|
14287
14497
|
}
|
|
14288
14498
|
return null;
|
|
14289
14499
|
}
|
|
14290
|
-
function ensurePinnedPluginConfig(value, version, hasLocalAftEntry = () => false, generation = "unknown") {
|
|
14291
|
-
const entry = pinnedPluginEntry(version);
|
|
14500
|
+
function ensurePinnedPluginConfig(value, version, hasLocalAftEntry = () => false, generation = "unknown", policy = {}) {
|
|
14501
|
+
const entry = policy.fallbackEntry ?? pinnedPluginEntry(version);
|
|
14292
14502
|
const key = openCodePluginKey(generation);
|
|
14293
14503
|
const hadKey = Array.isArray(value[key]);
|
|
14294
14504
|
const list = hadKey ? value[key] : [];
|
|
@@ -14302,6 +14512,21 @@ function ensurePinnedPluginConfig(value, version, hasLocalAftEntry = () => false
|
|
|
14302
14512
|
}
|
|
14303
14513
|
if (npmIndexes.length > 0) {
|
|
14304
14514
|
const firstIndex = npmIndexes[0];
|
|
14515
|
+
if (policy.doctor && npmIndexes.some((index) => preserveDoctorPluginEntry(version, pluginEntryPackage(list[index]) ?? undefined, policy.installedVersion))) {
|
|
14516
|
+
let changed = false;
|
|
14517
|
+
for (const index of npmIndexes) {
|
|
14518
|
+
const spec = pluginEntryPackage(list[index]);
|
|
14519
|
+
const shaped = shapePluginEntry(key, spec, pluginEntryOptions(list[index]));
|
|
14520
|
+
changed ||= !sameEntry(list[index], shaped);
|
|
14521
|
+
list[index] = shaped;
|
|
14522
|
+
}
|
|
14523
|
+
return {
|
|
14524
|
+
action: changed ? "updated" : "already_present",
|
|
14525
|
+
changed,
|
|
14526
|
+
entry: pluginEntryPackage(list[firstIndex]),
|
|
14527
|
+
key
|
|
14528
|
+
};
|
|
14529
|
+
}
|
|
14305
14530
|
const shaped = shapePluginEntry(key, entry, pluginEntryOptions(list[firstIndex]));
|
|
14306
14531
|
const wasExact = sameEntry(list[firstIndex], shaped);
|
|
14307
14532
|
list[firstIndex] = shaped;
|
|
@@ -14320,13 +14545,24 @@ function ensurePinnedPluginConfig(value, version, hasLocalAftEntry = () => false
|
|
|
14320
14545
|
}
|
|
14321
14546
|
const sibling = value[otherOpenCodePluginKey(key)];
|
|
14322
14547
|
const siblingList = Array.isArray(sibling) ? sibling : null;
|
|
14548
|
+
if (policy.doctor && siblingList) {
|
|
14549
|
+
const preserved = siblingList.find((candidate) => {
|
|
14550
|
+
const spec = pluginEntryPackage(candidate);
|
|
14551
|
+
return spec !== null && isAftNpmEntry(spec) && preserveDoctorPluginEntry(version, spec, policy.installedVersion);
|
|
14552
|
+
});
|
|
14553
|
+
const spec = pluginEntryPackage(preserved);
|
|
14554
|
+
if (spec) {
|
|
14555
|
+
list.push(shapePluginEntry(key, spec, pluginEntryOptions(preserved)));
|
|
14556
|
+
return { action: "added", changed: true, entry: spec, key };
|
|
14557
|
+
}
|
|
14558
|
+
}
|
|
14323
14559
|
const carried = siblingList ? findLocalAftEntry(siblingList, hasLocalAftEntry) : null;
|
|
14324
14560
|
list.push(carried ? shapePluginEntry(key, carried.packageSpec, carried.options) : entry);
|
|
14325
14561
|
if (carried && siblingList)
|
|
14326
14562
|
siblingList.splice(carried.index, 1);
|
|
14327
14563
|
return { action: "added", changed: true, entry, key };
|
|
14328
14564
|
}
|
|
14329
|
-
function pluginConfigNeedsUpdate(value, version, hasLocalAftEntry = () => false, generation = "unknown") {
|
|
14565
|
+
function pluginConfigNeedsUpdate(value, version, hasLocalAftEntry = () => false, generation = "unknown", policy = {}) {
|
|
14330
14566
|
const key = openCodePluginKey(generation);
|
|
14331
14567
|
const list = value[key];
|
|
14332
14568
|
if (!Array.isArray(list))
|
|
@@ -14336,7 +14572,9 @@ function pluginConfigNeedsUpdate(value, version, hasLocalAftEntry = () => false,
|
|
|
14336
14572
|
return packageSpec !== null && isAftNpmEntry(packageSpec);
|
|
14337
14573
|
});
|
|
14338
14574
|
if (npmEntries.length > 0) {
|
|
14339
|
-
|
|
14575
|
+
if (policy.doctor && npmEntries.some((candidate) => preserveDoctorPluginEntry(version, pluginEntryPackage(candidate) ?? undefined, policy.installedVersion)))
|
|
14576
|
+
return npmEntries.some((candidate) => !pluginEntryFitsKey(candidate, key));
|
|
14577
|
+
return npmEntries.length !== 1 || pluginEntryPackage(npmEntries[0]) !== (policy.fallbackEntry ?? pinnedPluginEntry(version)) || !pluginEntryFitsKey(npmEntries[0], key);
|
|
14340
14578
|
}
|
|
14341
14579
|
const local = findLocalAftEntry(list, hasLocalAftEntry);
|
|
14342
14580
|
if (local)
|
|
@@ -14386,7 +14624,7 @@ function aftHostReplacementEnabled(userConfig, hostTool) {
|
|
|
14386
14624
|
}
|
|
14387
14625
|
return true;
|
|
14388
14626
|
}
|
|
14389
|
-
var AFT_OPENCODE_PACKAGE = "@cortexkit/aft-opencode", MODERN_V1_VERSION, EXACT_VERSION, OPENCODE_HOST_SHELL_DISABLE_ENTRY = "-opencode.tool.shell", OPENCODE_HOST_PATCH_DISABLE_ENTRY = "-opencode.tool.patch", OPENCODE_HOST_TOOLS, OPENCODE_HOST_TOOL_NAMES;
|
|
14627
|
+
var AFT_OPENCODE_PACKAGE = "@cortexkit/aft-opencode", MODERN_V1_VERSION, DOCTOR_NO_DOWNGRADE = "This doctor is AFT <cli>; OpenCode is configured for AFT plugin <plugin>. Doctor will not downgrade that entry. Run doctor with a matching or newer CLI.", EXACT_VERSION, OPENCODE_HOST_SHELL_DISABLE_ENTRY = "-opencode.tool.shell", OPENCODE_HOST_PATCH_DISABLE_ENTRY = "-opencode.tool.patch", OPENCODE_HOST_TOOLS, OPENCODE_HOST_TOOL_NAMES;
|
|
14390
14628
|
var init_opencode_config = __esm(() => {
|
|
14391
14629
|
init_opencode_version();
|
|
14392
14630
|
MODERN_V1_VERSION = opencode_version_default.trim();
|
|
@@ -14398,29 +14636,138 @@ var init_opencode_config = __esm(() => {
|
|
|
14398
14636
|
OPENCODE_HOST_TOOL_NAMES = Object.keys(OPENCODE_HOST_TOOLS);
|
|
14399
14637
|
});
|
|
14400
14638
|
|
|
14639
|
+
// src/lib/opencode-plugin-cache.ts
|
|
14640
|
+
import { existsSync as existsSync14, readdirSync as readdirSync6, readFileSync as readFileSync10 } from "node:fs";
|
|
14641
|
+
import { dirname as dirname8, join as join18 } from "node:path";
|
|
14642
|
+
function discoverLocalOpenCodePlugin(path, cliVersion) {
|
|
14643
|
+
let current = path;
|
|
14644
|
+
for (;; ) {
|
|
14645
|
+
const manifestPath = join18(current, "package.json");
|
|
14646
|
+
try {
|
|
14647
|
+
const pkg = JSON.parse(readFileSync10(manifestPath, "utf8"));
|
|
14648
|
+
if (pkg.name === AFT_OPENCODE_PACKAGE && typeof pkg.version === "string") {
|
|
14649
|
+
return {
|
|
14650
|
+
path: current,
|
|
14651
|
+
manifestPath,
|
|
14652
|
+
cached: pkg.version,
|
|
14653
|
+
version: pkg.version,
|
|
14654
|
+
versionSource: "installed",
|
|
14655
|
+
exists: true,
|
|
14656
|
+
cliVersion,
|
|
14657
|
+
local: true
|
|
14658
|
+
};
|
|
14659
|
+
}
|
|
14660
|
+
} catch {}
|
|
14661
|
+
const parent = dirname8(current);
|
|
14662
|
+
if (parent === current)
|
|
14663
|
+
return;
|
|
14664
|
+
current = parent;
|
|
14665
|
+
}
|
|
14666
|
+
}
|
|
14667
|
+
function discoverOpenCodePluginCache(root, entry, generation, cliVersion, configuredEntry) {
|
|
14668
|
+
const v1 = join18(root, "packages", entry);
|
|
14669
|
+
const v2 = join18(root, "npm", entry === AFT_OPENCODE_PACKAGE ? `${entry}@latest` : entry);
|
|
14670
|
+
const paths = [];
|
|
14671
|
+
if (generation !== "v1") {
|
|
14672
|
+
try {
|
|
14673
|
+
const timestamps = readdirSync6(v2).filter((name) => /^\d+$/.test(name));
|
|
14674
|
+
timestamps.sort((a, b) => BigInt(a) > BigInt(b) ? -1 : BigInt(a) < BigInt(b) ? 1 : 0);
|
|
14675
|
+
if (timestamps[0])
|
|
14676
|
+
paths.push(join18(v2, timestamps[0]));
|
|
14677
|
+
} catch {}
|
|
14678
|
+
}
|
|
14679
|
+
if (generation === "v1" || generation !== "v2" && paths.length === 0)
|
|
14680
|
+
paths.push(v1);
|
|
14681
|
+
let readError;
|
|
14682
|
+
for (const path of paths) {
|
|
14683
|
+
const manifestPath = join18(path, "node_modules", AFT_OPENCODE_PACKAGE, "package.json");
|
|
14684
|
+
try {
|
|
14685
|
+
const pkg = JSON.parse(readFileSync10(manifestPath, "utf8"));
|
|
14686
|
+
if (pkg.name !== AFT_OPENCODE_PACKAGE || typeof pkg.version !== "string" || compareSemver2(pkg.version, pkg.version) !== 0) {
|
|
14687
|
+
readError = `Invalid plugin identity or version at ${manifestPath}`;
|
|
14688
|
+
continue;
|
|
14689
|
+
}
|
|
14690
|
+
if (typeof pkg.main === "string" && !existsSync14(join18(path, "node_modules", AFT_OPENCODE_PACKAGE, pkg.main))) {
|
|
14691
|
+
readError = `Incomplete plugin installation at ${manifestPath}`;
|
|
14692
|
+
continue;
|
|
14693
|
+
}
|
|
14694
|
+
return {
|
|
14695
|
+
path,
|
|
14696
|
+
manifestPath,
|
|
14697
|
+
cached: pkg.version,
|
|
14698
|
+
version: pkg.version,
|
|
14699
|
+
versionSource: "installed",
|
|
14700
|
+
configuredEntry,
|
|
14701
|
+
exists: true,
|
|
14702
|
+
cliVersion
|
|
14703
|
+
};
|
|
14704
|
+
} catch (error) {
|
|
14705
|
+
if (error.code !== "ENOENT" || existsSync14(path))
|
|
14706
|
+
readError = String(error);
|
|
14707
|
+
}
|
|
14708
|
+
}
|
|
14709
|
+
return {
|
|
14710
|
+
path: paths[0] ?? (generation === "v2" ? v2 : v1),
|
|
14711
|
+
cached: undefined,
|
|
14712
|
+
version: configuredEntry ? exactPinnedVersion(configuredEntry) ?? undefined : undefined,
|
|
14713
|
+
versionSource: configuredEntry && exactPinnedVersion(configuredEntry) ? "configured" : "unknown",
|
|
14714
|
+
readError,
|
|
14715
|
+
exists: false,
|
|
14716
|
+
configuredEntry,
|
|
14717
|
+
cliVersion
|
|
14718
|
+
};
|
|
14719
|
+
}
|
|
14720
|
+
function doctorInstalledVersion(cache) {
|
|
14721
|
+
return cache.cached ?? (cache.readError ? "unknown" : undefined);
|
|
14722
|
+
}
|
|
14723
|
+
function describePluginVersion(cache) {
|
|
14724
|
+
const version = cache.version ?? cache.cached;
|
|
14725
|
+
const source = cache.versionSource ?? (cache.cached ? "installed" : "unknown");
|
|
14726
|
+
return `${version ?? "unknown"} (${source}${cache.manifestPath ? `: ${cache.manifestPath}` : source === "configured" && cache.configuredEntry ? `: ${cache.configuredEntry}` : ""})`;
|
|
14727
|
+
}
|
|
14728
|
+
var init_opencode_plugin_cache = __esm(() => {
|
|
14729
|
+
init_opencode_config();
|
|
14730
|
+
});
|
|
14731
|
+
|
|
14732
|
+
// src/lib/self-version.ts
|
|
14733
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
14734
|
+
function getSelfVersion() {
|
|
14735
|
+
const require2 = createRequire2(import.meta.url);
|
|
14736
|
+
for (const relPath of ["../../package.json", "../package.json"]) {
|
|
14737
|
+
try {
|
|
14738
|
+
const version = require2(relPath).version;
|
|
14739
|
+
if (typeof version === "string" && version.length > 0) {
|
|
14740
|
+
return version;
|
|
14741
|
+
}
|
|
14742
|
+
} catch {}
|
|
14743
|
+
}
|
|
14744
|
+
return "unknown";
|
|
14745
|
+
}
|
|
14746
|
+
var init_self_version = () => {};
|
|
14747
|
+
|
|
14401
14748
|
// src/setup/host-generation.ts
|
|
14402
14749
|
import { createHash as createHash4 } from "node:crypto";
|
|
14403
14750
|
import {
|
|
14404
14751
|
closeSync as closeSync7,
|
|
14405
|
-
existsSync as
|
|
14752
|
+
existsSync as existsSync15,
|
|
14406
14753
|
mkdirSync as mkdirSync5,
|
|
14407
14754
|
mkdtempSync,
|
|
14408
14755
|
openSync as openSync7,
|
|
14409
|
-
readdirSync as
|
|
14410
|
-
readFileSync as
|
|
14756
|
+
readdirSync as readdirSync7,
|
|
14757
|
+
readFileSync as readFileSync11,
|
|
14411
14758
|
readSync as readSync5,
|
|
14412
14759
|
realpathSync as realpathSync5,
|
|
14413
14760
|
rmSync as rmSync4,
|
|
14414
14761
|
statSync as statSync10
|
|
14415
14762
|
} from "node:fs";
|
|
14416
14763
|
import { homedir as homedir14, tmpdir as tmpdir3 } from "node:os";
|
|
14417
|
-
import { dirname as
|
|
14764
|
+
import { dirname as dirname9, join as join19, parse as parse3 } from "node:path";
|
|
14418
14765
|
function findExecutableOnPath2(name, pathValue = process.env.PATH ?? "", platform = process.platform) {
|
|
14419
14766
|
return findExecutableOnPath(name, { pathValue, platform });
|
|
14420
14767
|
}
|
|
14421
14768
|
function packageMetadataAt(path, expectedName) {
|
|
14422
14769
|
try {
|
|
14423
|
-
const metadata = JSON.parse(
|
|
14770
|
+
const metadata = JSON.parse(readFileSync11(path, "utf8"));
|
|
14424
14771
|
return metadata.name === expectedName ? metadata : null;
|
|
14425
14772
|
} catch {
|
|
14426
14773
|
return null;
|
|
@@ -14429,16 +14776,16 @@ function packageMetadataAt(path, expectedName) {
|
|
|
14429
14776
|
function packageMetadataNearExecutable(executable, expectedName) {
|
|
14430
14777
|
let current;
|
|
14431
14778
|
try {
|
|
14432
|
-
current =
|
|
14779
|
+
current = dirname9(realpathSync5(executable));
|
|
14433
14780
|
} catch {
|
|
14434
|
-
current =
|
|
14781
|
+
current = dirname9(executable);
|
|
14435
14782
|
}
|
|
14436
14783
|
while (true) {
|
|
14437
|
-
const direct = packageMetadataAt(
|
|
14784
|
+
const direct = packageMetadataAt(join19(current, "package.json"), expectedName);
|
|
14438
14785
|
if (direct)
|
|
14439
14786
|
return direct;
|
|
14440
|
-
const parent =
|
|
14441
|
-
if (parent === current || current ===
|
|
14787
|
+
const parent = dirname9(current);
|
|
14788
|
+
if (parent === current || current === parse3(current).root)
|
|
14442
14789
|
return null;
|
|
14443
14790
|
current = parent;
|
|
14444
14791
|
}
|
|
@@ -14448,7 +14795,7 @@ function npmLauncherTarget(launcher) {
|
|
|
14448
14795
|
try {
|
|
14449
14796
|
if (statSync10(launcher).size > LAUNCHER_MAX_BYTES)
|
|
14450
14797
|
return null;
|
|
14451
|
-
source =
|
|
14798
|
+
source = readFileSync11(launcher, "utf8");
|
|
14452
14799
|
} catch {
|
|
14453
14800
|
return null;
|
|
14454
14801
|
}
|
|
@@ -14458,7 +14805,7 @@ function npmLauncherTarget(launcher) {
|
|
|
14458
14805
|
const relativeTarget = operands.at(-1)?.[1];
|
|
14459
14806
|
if (!relativeTarget)
|
|
14460
14807
|
return null;
|
|
14461
|
-
const target =
|
|
14808
|
+
const target = join19(dirname9(launcher), ...relativeTarget.split(/[\\/]+/).filter(Boolean));
|
|
14462
14809
|
try {
|
|
14463
14810
|
return statSync10(target).isFile() ? target : null;
|
|
14464
14811
|
} catch {
|
|
@@ -14504,7 +14851,7 @@ function hashFileBytes(hash, path, size) {
|
|
|
14504
14851
|
}
|
|
14505
14852
|
}
|
|
14506
14853
|
function snapshotTree(path) {
|
|
14507
|
-
if (!
|
|
14854
|
+
if (!existsSync15(path))
|
|
14508
14855
|
return "missing";
|
|
14509
14856
|
const hash = createHash4("sha256");
|
|
14510
14857
|
const visit = (current, relativePath) => {
|
|
@@ -14517,8 +14864,8 @@ function snapshotTree(path) {
|
|
|
14517
14864
|
}
|
|
14518
14865
|
hash.update(`${relativePath}\x00${info.mode}\x00${info.size}\x00${info.mtimeMs}\x00`);
|
|
14519
14866
|
if (info.isDirectory()) {
|
|
14520
|
-
for (const entry of
|
|
14521
|
-
visit(
|
|
14867
|
+
for (const entry of readdirSync7(current).sort()) {
|
|
14868
|
+
visit(join19(current, entry), join19(relativePath, entry));
|
|
14522
14869
|
}
|
|
14523
14870
|
return;
|
|
14524
14871
|
}
|
|
@@ -14534,19 +14881,19 @@ function snapshotTree(path) {
|
|
|
14534
14881
|
return hash.digest("hex");
|
|
14535
14882
|
}
|
|
14536
14883
|
function snapshotOperatorState(operatorHome) {
|
|
14537
|
-
const database =
|
|
14884
|
+
const database = join19(operatorHome, ".local", "share", "opencode", "opencode.db");
|
|
14538
14885
|
return JSON.stringify({
|
|
14539
14886
|
database: snapshotTree(database),
|
|
14540
14887
|
databaseWal: snapshotTree(`${database}-wal`),
|
|
14541
14888
|
databaseShm: snapshotTree(`${database}-shm`),
|
|
14542
|
-
logs: snapshotTree(
|
|
14889
|
+
logs: snapshotTree(join19(operatorHome, ".local", "share", "opencode", "log"))
|
|
14543
14890
|
});
|
|
14544
14891
|
}
|
|
14545
14892
|
function probeCreatedIsolatedState(dataRoot, stateRoot) {
|
|
14546
14893
|
return [dataRoot, stateRoot].some((root) => {
|
|
14547
|
-
const opencodeRoot =
|
|
14548
|
-
const database =
|
|
14549
|
-
return [database, `${database}-wal`, `${database}-shm`,
|
|
14894
|
+
const opencodeRoot = join19(root, "opencode");
|
|
14895
|
+
const database = join19(opencodeRoot, "opencode.db");
|
|
14896
|
+
return [database, `${database}-wal`, `${database}-shm`, join19(opencodeRoot, "log")].some(existsSync15);
|
|
14550
14897
|
});
|
|
14551
14898
|
}
|
|
14552
14899
|
function probeOpenCodeV1Version(executable, options = {}) {
|
|
@@ -14555,13 +14902,13 @@ function probeOpenCodeV1Version(executable, options = {}) {
|
|
|
14555
14902
|
return null;
|
|
14556
14903
|
const operatorHome = options.operatorHome ?? homedir14();
|
|
14557
14904
|
const before = snapshotOperatorState(operatorHome);
|
|
14558
|
-
const root = mkdtempSync(
|
|
14559
|
-
const home =
|
|
14560
|
-
const config =
|
|
14561
|
-
const data =
|
|
14562
|
-
const state =
|
|
14563
|
-
const cache =
|
|
14564
|
-
const project =
|
|
14905
|
+
const root = mkdtempSync(join19(options.tempParent ?? tmpdir3(), "aft-opencode-probe-"));
|
|
14906
|
+
const home = join19(root, "home");
|
|
14907
|
+
const config = join19(root, "config");
|
|
14908
|
+
const data = join19(root, "data");
|
|
14909
|
+
const state = join19(root, "state");
|
|
14910
|
+
const cache = join19(root, "cache");
|
|
14911
|
+
const project = join19(root, "project");
|
|
14565
14912
|
for (const directory of [home, config, data, state, cache, project]) {
|
|
14566
14913
|
mkdirSync5(directory, { recursive: true });
|
|
14567
14914
|
}
|
|
@@ -14572,7 +14919,7 @@ function probeOpenCodeV1Version(executable, options = {}) {
|
|
|
14572
14919
|
XDG_DATA_HOME: data,
|
|
14573
14920
|
XDG_STATE_HOME: state,
|
|
14574
14921
|
XDG_CACHE_HOME: cache,
|
|
14575
|
-
TMPDIR:
|
|
14922
|
+
TMPDIR: join19(root, "tmp")
|
|
14576
14923
|
};
|
|
14577
14924
|
mkdirSync5(env.TMPDIR, { recursive: true });
|
|
14578
14925
|
delete env.OPENCODE_CONFIG;
|
|
@@ -14713,9 +15060,9 @@ var init_host_generation = __esm(() => {
|
|
|
14713
15060
|
});
|
|
14714
15061
|
|
|
14715
15062
|
// src/adapters/opencode.ts
|
|
14716
|
-
import { existsSync as
|
|
15063
|
+
import { existsSync as existsSync16, readFileSync as readFileSync12, rmSync as rmSync5, statSync as statSync11 } from "node:fs";
|
|
14717
15064
|
import { homedir as homedir15 } from "node:os";
|
|
14718
|
-
import { dirname as
|
|
15065
|
+
import { dirname as dirname10, join as join20, parse as parse4, resolve as resolve12 } from "node:path";
|
|
14719
15066
|
import { fileURLToPath } from "node:url";
|
|
14720
15067
|
function getOpenCodeConfigDir() {
|
|
14721
15068
|
const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
@@ -14726,13 +15073,13 @@ function getOpenCodeConfigDir() {
|
|
|
14726
15073
|
function getLegacyOpenCodePluginCachePath(primaryPath) {
|
|
14727
15074
|
if (process.platform !== "win32")
|
|
14728
15075
|
return null;
|
|
14729
|
-
const localAppData = process.env.LOCALAPPDATA ??
|
|
14730
|
-
const legacyPath =
|
|
15076
|
+
const localAppData = process.env.LOCALAPPDATA ?? join20(homedir15(), "AppData", "Local");
|
|
15077
|
+
const legacyPath = join20(localAppData, "opencode", "packages", LEGACY_PLUGIN_ENTRY);
|
|
14731
15078
|
return resolve12(legacyPath) === resolve12(primaryPath) ? null : legacyPath;
|
|
14732
15079
|
}
|
|
14733
15080
|
function clearLegacyOpenCodePluginCache(primaryPath) {
|
|
14734
15081
|
const legacyPath = getLegacyOpenCodePluginCachePath(primaryPath);
|
|
14735
|
-
if (!legacyPath || !
|
|
15082
|
+
if (!legacyPath || !existsSync16(legacyPath))
|
|
14736
15083
|
return { clearedPath: null };
|
|
14737
15084
|
try {
|
|
14738
15085
|
rmSync5(legacyPath, { recursive: true, force: true });
|
|
@@ -14750,16 +15097,16 @@ function hasOpenCodeCli() {
|
|
|
14750
15097
|
function openCodeDesktopAppExists() {
|
|
14751
15098
|
const candidates = [];
|
|
14752
15099
|
if (process.platform === "darwin") {
|
|
14753
|
-
candidates.push("/Applications/OpenCode.app", "/Applications/OpenCode Beta.app",
|
|
15100
|
+
candidates.push("/Applications/OpenCode.app", "/Applications/OpenCode Beta.app", join20(homedir15(), "Applications", "OpenCode.app"), join20(homedir15(), "Applications", "OpenCode Beta.app"));
|
|
14754
15101
|
} else if (process.platform === "win32") {
|
|
14755
|
-
const localAppData = process.env.LOCALAPPDATA ??
|
|
14756
|
-
candidates.push(
|
|
15102
|
+
const localAppData = process.env.LOCALAPPDATA ?? join20(homedir15(), "AppData", "Local");
|
|
15103
|
+
candidates.push(join20(localAppData, "Programs", "opencode"), join20(localAppData, "opencode"));
|
|
14757
15104
|
} else {
|
|
14758
|
-
candidates.push("/opt/OpenCode", "/usr/lib/opencode",
|
|
15105
|
+
candidates.push("/opt/OpenCode", "/usr/lib/opencode", join20(homedir15(), ".local", "share", "applications", "opencode.desktop"));
|
|
14759
15106
|
}
|
|
14760
15107
|
return candidates.some((p) => {
|
|
14761
15108
|
try {
|
|
14762
|
-
return
|
|
15109
|
+
return existsSync16(p);
|
|
14763
15110
|
} catch {
|
|
14764
15111
|
return false;
|
|
14765
15112
|
}
|
|
@@ -14782,24 +15129,24 @@ function pathPointsToOurPlugin(entry) {
|
|
|
14782
15129
|
if (!fsPath)
|
|
14783
15130
|
return false;
|
|
14784
15131
|
try {
|
|
14785
|
-
if (!
|
|
15132
|
+
if (!existsSync16(fsPath))
|
|
14786
15133
|
return false;
|
|
14787
|
-
let searchDir = statSync11(fsPath).isDirectory() ? fsPath :
|
|
15134
|
+
let searchDir = statSync11(fsPath).isDirectory() ? fsPath : dirname10(fsPath);
|
|
14788
15135
|
let pkgJsonPath = null;
|
|
14789
15136
|
while (true) {
|
|
14790
|
-
const candidate =
|
|
14791
|
-
if (
|
|
15137
|
+
const candidate = join20(searchDir, "package.json");
|
|
15138
|
+
if (existsSync16(candidate)) {
|
|
14792
15139
|
pkgJsonPath = candidate;
|
|
14793
15140
|
break;
|
|
14794
15141
|
}
|
|
14795
|
-
const parent =
|
|
14796
|
-
if (parent === searchDir || searchDir ===
|
|
15142
|
+
const parent = dirname10(searchDir);
|
|
15143
|
+
if (parent === searchDir || searchDir === parse4(searchDir).root)
|
|
14797
15144
|
break;
|
|
14798
15145
|
searchDir = parent;
|
|
14799
15146
|
}
|
|
14800
15147
|
if (!pkgJsonPath)
|
|
14801
15148
|
return false;
|
|
14802
|
-
const parsed = JSON.parse(
|
|
15149
|
+
const parsed = JSON.parse(readFileSync12(pkgJsonPath, "utf-8"));
|
|
14803
15150
|
return parsed.name === PLUGIN_NAME;
|
|
14804
15151
|
} catch {
|
|
14805
15152
|
return false;
|
|
@@ -14833,7 +15180,7 @@ class OpenCodeAdapter {
|
|
|
14833
15180
|
pluginEntryWithVersion = PLUGIN_ENTRY;
|
|
14834
15181
|
hostDetection;
|
|
14835
15182
|
isInstalled() {
|
|
14836
|
-
if (
|
|
15183
|
+
if (existsSync16(getOpenCodeConfigDir()))
|
|
14837
15184
|
return true;
|
|
14838
15185
|
if (openCodeDesktopAppExists())
|
|
14839
15186
|
return true;
|
|
@@ -14857,7 +15204,7 @@ class OpenCodeAdapter {
|
|
|
14857
15204
|
const configDir = getOpenCodeConfigDir();
|
|
14858
15205
|
const harness = detectJsoncFile(configDir, "opencode");
|
|
14859
15206
|
const aftConfigPath = resolveCortexKitUserConfigPath();
|
|
14860
|
-
const aftConfigExists =
|
|
15207
|
+
const aftConfigExists = existsSync16(aftConfigPath);
|
|
14861
15208
|
const tui = detectJsoncFile(configDir, "tui");
|
|
14862
15209
|
return {
|
|
14863
15210
|
configDir,
|
|
@@ -14874,13 +15221,32 @@ class OpenCodeAdapter {
|
|
|
14874
15221
|
const { value } = readJsoncFile(paths.harnessConfig);
|
|
14875
15222
|
return configRegistersAft(value, this.configGeneration());
|
|
14876
15223
|
}
|
|
14877
|
-
async ensurePluginEntry() {
|
|
15224
|
+
async ensurePluginEntry(options = {}) {
|
|
15225
|
+
const paths = this.detectConfigPaths();
|
|
15226
|
+
return this.ensureConfigEntry(paths.harnessConfig, paths.harnessConfigFormat, "server config", options);
|
|
15227
|
+
}
|
|
15228
|
+
needsPluginEntryUpdate(options = {}) {
|
|
14878
15229
|
const paths = this.detectConfigPaths();
|
|
14879
|
-
return this.
|
|
15230
|
+
return this.configEntryNeedsUpdate(paths.harnessConfig, paths.harnessConfigFormat, options);
|
|
14880
15231
|
}
|
|
14881
|
-
|
|
15232
|
+
doctorPluginEntry(tui = false) {
|
|
14882
15233
|
const paths = this.detectConfigPaths();
|
|
14883
|
-
|
|
15234
|
+
const path = tui ? paths.tuiConfig : paths.harnessConfig;
|
|
15235
|
+
const value = path ? readJsoncFile(path).value : null;
|
|
15236
|
+
const policy = this.doctorVersionPolicy({ doctor: true });
|
|
15237
|
+
if (!value)
|
|
15238
|
+
return policy.fallbackEntry ?? PLUGIN_ENTRY;
|
|
15239
|
+
return ensurePinnedPluginConfig(JSON.parse(JSON.stringify(value)), getSelfVersion(), pathPointsToOurPlugin, this.configGeneration(), policy).entry;
|
|
15240
|
+
}
|
|
15241
|
+
doctorVersionPolicy(policy) {
|
|
15242
|
+
if (!policy.doctor)
|
|
15243
|
+
return policy;
|
|
15244
|
+
const cache = this.getPluginCacheInfo();
|
|
15245
|
+
const installedVersion = doctorInstalledVersion(cache);
|
|
15246
|
+
const configuredVersion = cache.configuredEntry ? exactPinnedVersion(cache.configuredEntry) : null;
|
|
15247
|
+
const newer = configuredVersion && (compareSemver2(configuredVersion, getSelfVersion()) ?? 0) > 0 || cache.cached && (compareSemver2(cache.cached, getSelfVersion()) ?? 0) > 0;
|
|
15248
|
+
const fallbackEntry = newer ? cache.configuredEntry ?? (cache.cached ? pinnedPluginEntry(cache.cached) : undefined) : undefined;
|
|
15249
|
+
return { ...policy, installedVersion, fallbackEntry };
|
|
14884
15250
|
}
|
|
14885
15251
|
hasTuiPluginEntry() {
|
|
14886
15252
|
const paths = this.detectConfigPaths();
|
|
@@ -14889,7 +15255,7 @@ class OpenCodeAdapter {
|
|
|
14889
15255
|
const { value } = readJsoncFile(paths.tuiConfig);
|
|
14890
15256
|
return configRegistersAft(value, this.configGeneration());
|
|
14891
15257
|
}
|
|
14892
|
-
async ensureTuiPluginEntry() {
|
|
15258
|
+
async ensureTuiPluginEntry(options = {}) {
|
|
14893
15259
|
const paths = this.detectConfigPaths();
|
|
14894
15260
|
if (this.configGeneration() === "v2") {
|
|
14895
15261
|
return {
|
|
@@ -14907,28 +15273,30 @@ class OpenCodeAdapter {
|
|
|
14907
15273
|
configPath: paths.configDir
|
|
14908
15274
|
};
|
|
14909
15275
|
}
|
|
14910
|
-
return this.ensureConfigEntry(paths.tuiConfig, paths.tuiConfigFormat ?? "none", "TUI config");
|
|
15276
|
+
return this.ensureConfigEntry(paths.tuiConfig, paths.tuiConfigFormat ?? "none", "TUI config", options);
|
|
14911
15277
|
}
|
|
14912
15278
|
tuiPluginEntryApplies() {
|
|
14913
15279
|
return this.configGeneration() !== "v2";
|
|
14914
15280
|
}
|
|
14915
|
-
needsTuiPluginEntryUpdate() {
|
|
15281
|
+
needsTuiPluginEntryUpdate(options = {}) {
|
|
14916
15282
|
if (this.configGeneration() === "v2")
|
|
14917
15283
|
return false;
|
|
14918
15284
|
const paths = this.detectConfigPaths();
|
|
14919
|
-
return paths.tuiConfig ? this.configEntryNeedsUpdate(paths.tuiConfig, paths.tuiConfigFormat ?? "none") : true;
|
|
15285
|
+
return paths.tuiConfig ? this.configEntryNeedsUpdate(paths.tuiConfig, paths.tuiConfigFormat ?? "none", options) : true;
|
|
14920
15286
|
}
|
|
14921
|
-
ensureConfigEntry(configPath, format, label) {
|
|
15287
|
+
ensureConfigEntry(configPath, format, label, policy = {}) {
|
|
14922
15288
|
const generation = this.configGeneration();
|
|
14923
15289
|
const key = openCodePluginKey(generation);
|
|
15290
|
+
policy = this.doctorVersionPolicy(policy);
|
|
15291
|
+
const initialEntry = policy.fallbackEntry ?? PLUGIN_ENTRY;
|
|
14924
15292
|
if (format === "none") {
|
|
14925
|
-
const failed = this.tryWrite(configPath, () => writeJsoncFile(configPath, { [key]: [
|
|
15293
|
+
const failed = this.tryWrite(configPath, () => writeJsoncFile(configPath, { [key]: [initialEntry] }, "json"));
|
|
14926
15294
|
if (failed)
|
|
14927
15295
|
return failed;
|
|
14928
15296
|
return {
|
|
14929
15297
|
ok: true,
|
|
14930
15298
|
action: "added",
|
|
14931
|
-
message: `Created ${configPath} and added ${
|
|
15299
|
+
message: `Created ${configPath} and added ${initialEntry} under \`${key}\` (${label})`,
|
|
14932
15300
|
configPath
|
|
14933
15301
|
};
|
|
14934
15302
|
}
|
|
@@ -14941,12 +15309,14 @@ class OpenCodeAdapter {
|
|
|
14941
15309
|
configPath
|
|
14942
15310
|
};
|
|
14943
15311
|
}
|
|
14944
|
-
const update = ensurePinnedPluginConfig(value, getSelfVersion(), pathPointsToOurPlugin, generation);
|
|
15312
|
+
const update = ensurePinnedPluginConfig(value, getSelfVersion(), pathPointsToOurPlugin, generation, policy);
|
|
15313
|
+
const preserved = policy.doctor && preserveDoctorPluginEntry(getSelfVersion(), update.entry, doctorInstalledVersion(this.getPluginCacheInfo()));
|
|
15314
|
+
const notice = preserved ? doctorNoDowngradeMessage(getSelfVersion(), update.entry, doctorInstalledVersion(this.getPluginCacheInfo())) : "";
|
|
14945
15315
|
if (!update.changed) {
|
|
14946
15316
|
return {
|
|
14947
15317
|
ok: true,
|
|
14948
15318
|
action: "already_present",
|
|
14949
|
-
message: `${
|
|
15319
|
+
message: notice || `${update.entry} is already registered under \`${update.key}\` in ${configPath}`,
|
|
14950
15320
|
configPath
|
|
14951
15321
|
};
|
|
14952
15322
|
}
|
|
@@ -14956,7 +15326,7 @@ class OpenCodeAdapter {
|
|
|
14956
15326
|
return {
|
|
14957
15327
|
ok: true,
|
|
14958
15328
|
action: update.action,
|
|
14959
|
-
message: `${update.action === "added" ? "Added" : "Updated"} ${
|
|
15329
|
+
message: `${update.action === "added" ? "Added" : "Updated"} ${update.entry} under \`${update.key}\` in ${configPath} (${label})${notice ? `. ${notice}` : ""}`,
|
|
14960
15330
|
configPath
|
|
14961
15331
|
};
|
|
14962
15332
|
}
|
|
@@ -15041,38 +15411,27 @@ class OpenCodeAdapter {
|
|
|
15041
15411
|
return { ok: false, action: "error", message: formatFsError(error, configPath), configPath };
|
|
15042
15412
|
}
|
|
15043
15413
|
}
|
|
15044
|
-
configEntryNeedsUpdate(configPath, format) {
|
|
15414
|
+
configEntryNeedsUpdate(configPath, format, policy = {}) {
|
|
15045
15415
|
if (format === "none")
|
|
15046
15416
|
return true;
|
|
15047
15417
|
const { value, error } = readJsoncFile(configPath);
|
|
15048
15418
|
if (error || !value)
|
|
15049
15419
|
return false;
|
|
15050
|
-
return pluginConfigNeedsUpdate(value, getSelfVersion(), pathPointsToOurPlugin, this.configGeneration());
|
|
15420
|
+
return pluginConfigNeedsUpdate(value, getSelfVersion(), pathPointsToOurPlugin, this.configGeneration(), this.doctorVersionPolicy(policy));
|
|
15051
15421
|
}
|
|
15052
15422
|
getPluginCacheInfo() {
|
|
15053
15423
|
const configPath = this.detectConfigPaths().harnessConfig;
|
|
15054
15424
|
const { value } = readJsoncFile(configPath);
|
|
15055
|
-
const
|
|
15056
|
-
const
|
|
15057
|
-
|
|
15058
|
-
|
|
15059
|
-
|
|
15060
|
-
const
|
|
15061
|
-
|
|
15062
|
-
|
|
15063
|
-
} catch (error) {
|
|
15064
|
-
if (error.code !== "ENOENT") {
|
|
15065
|
-
readError = error instanceof Error ? error.message : String(error);
|
|
15066
|
-
}
|
|
15425
|
+
const entries = openCodePluginReadKeys(this.configGeneration()).flatMap((key) => Array.isArray(value?.[key]) ? value[key] : []).map(pluginEntryPackage);
|
|
15426
|
+
const configuredEntry = entries.find(isAftNpmEntry);
|
|
15427
|
+
if (!configuredEntry) {
|
|
15428
|
+
const localEntry = entries.find((entry) => entry !== null && pathPointsToOurPlugin(entry));
|
|
15429
|
+
const localPath = localEntry ? pathFromEntry(localEntry) : null;
|
|
15430
|
+
const local = localPath ? discoverLocalOpenCodePlugin(localPath, getSelfVersion()) : undefined;
|
|
15431
|
+
if (local)
|
|
15432
|
+
return local;
|
|
15067
15433
|
}
|
|
15068
|
-
return
|
|
15069
|
-
path,
|
|
15070
|
-
cached,
|
|
15071
|
-
readError,
|
|
15072
|
-
latest: getSelfVersion(),
|
|
15073
|
-
exists: existsSync15(path),
|
|
15074
|
-
configuredEntry
|
|
15075
|
-
};
|
|
15434
|
+
return discoverOpenCodePluginCache(getOpenCodeCacheDir(), configuredEntry ?? PLUGIN_ENTRY, this.configGeneration(), getSelfVersion(), configuredEntry);
|
|
15076
15435
|
}
|
|
15077
15436
|
getStorageDir() {
|
|
15078
15437
|
return getCortexKitStorageRoot();
|
|
@@ -15085,6 +15444,8 @@ class OpenCodeAdapter {
|
|
|
15085
15444
|
}
|
|
15086
15445
|
async clearPluginCache(force) {
|
|
15087
15446
|
const info = this.getPluginCacheInfo();
|
|
15447
|
+
if (info.local)
|
|
15448
|
+
return { action: "not_applicable", path: info.path };
|
|
15088
15449
|
const clearLegacy = force ? clearLegacyOpenCodePluginCache(info.path) : { clearedPath: null };
|
|
15089
15450
|
if (clearLegacy.error) {
|
|
15090
15451
|
return {
|
|
@@ -15101,12 +15462,12 @@ class OpenCodeAdapter {
|
|
|
15101
15462
|
legacy_path_cleared: clearLegacy.clearedPath
|
|
15102
15463
|
} : { action: "not_found", path: info.path };
|
|
15103
15464
|
}
|
|
15104
|
-
if (!force && info.cached && info.cached === info.
|
|
15465
|
+
if (!force && info.cached && info.cached === info.cliVersion) {
|
|
15105
15466
|
return {
|
|
15106
15467
|
action: "up_to_date",
|
|
15107
15468
|
path: info.path,
|
|
15108
15469
|
cached: info.cached,
|
|
15109
|
-
latest: info.
|
|
15470
|
+
latest: info.cliVersion
|
|
15110
15471
|
};
|
|
15111
15472
|
}
|
|
15112
15473
|
try {
|
|
@@ -15115,7 +15476,7 @@ class OpenCodeAdapter {
|
|
|
15115
15476
|
action: "cleared",
|
|
15116
15477
|
path: info.path,
|
|
15117
15478
|
cached: info.cached,
|
|
15118
|
-
latest: info.
|
|
15479
|
+
latest: info.cliVersion,
|
|
15119
15480
|
...clearLegacy.clearedPath ? { legacy_path_cleared: clearLegacy.clearedPath } : {}
|
|
15120
15481
|
};
|
|
15121
15482
|
} catch (error) {
|
|
@@ -15123,7 +15484,7 @@ class OpenCodeAdapter {
|
|
|
15123
15484
|
action: "error",
|
|
15124
15485
|
path: info.path,
|
|
15125
15486
|
cached: info.cached,
|
|
15126
|
-
latest: info.
|
|
15487
|
+
latest: info.cliVersion,
|
|
15127
15488
|
error: error instanceof Error ? error.message : String(error)
|
|
15128
15489
|
};
|
|
15129
15490
|
}
|
|
@@ -15134,12 +15495,12 @@ class OpenCodeAdapter {
|
|
|
15134
15495
|
describeStorageSubtrees() {
|
|
15135
15496
|
const storage = this.getStorageDir();
|
|
15136
15497
|
return {
|
|
15137
|
-
index: dirSize(
|
|
15138
|
-
semantic: dirSize(
|
|
15139
|
-
backups: dirSize(
|
|
15140
|
-
url_cache: dirSize(
|
|
15141
|
-
onnxruntime: dirSize(
|
|
15142
|
-
logs: dirSize(
|
|
15498
|
+
index: dirSize(join20(storage, "index")),
|
|
15499
|
+
semantic: dirSize(join20(storage, "semantic")),
|
|
15500
|
+
backups: dirSize(join20(storage, "backups")),
|
|
15501
|
+
url_cache: dirSize(join20(storage, "url_cache")),
|
|
15502
|
+
onnxruntime: dirSize(join20(storage, "onnxruntime")),
|
|
15503
|
+
logs: dirSize(join20(storage, "logs"))
|
|
15143
15504
|
};
|
|
15144
15505
|
}
|
|
15145
15506
|
}
|
|
@@ -15149,6 +15510,7 @@ var init_opencode = __esm(() => {
|
|
|
15149
15510
|
init_fs_errors();
|
|
15150
15511
|
init_fs_util();
|
|
15151
15512
|
init_jsonc();
|
|
15513
|
+
init_opencode_plugin_cache();
|
|
15152
15514
|
init_paths2();
|
|
15153
15515
|
init_self_version();
|
|
15154
15516
|
init_host_generation();
|
|
@@ -15159,9 +15521,9 @@ var init_opencode = __esm(() => {
|
|
|
15159
15521
|
});
|
|
15160
15522
|
|
|
15161
15523
|
// src/adapters/pi.ts
|
|
15162
|
-
import { existsSync as
|
|
15524
|
+
import { existsSync as existsSync17, readFileSync as readFileSync13 } from "node:fs";
|
|
15163
15525
|
import { homedir as homedir16 } from "node:os";
|
|
15164
|
-
import { isAbsolute as isAbsolute7, join as
|
|
15526
|
+
import { isAbsolute as isAbsolute7, join as join21, resolve as resolve13 } from "node:path";
|
|
15165
15527
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
15166
15528
|
function getPiAgentDir() {
|
|
15167
15529
|
const configuredDir = process.env.PI_CODING_AGENT_DIR?.trim();
|
|
@@ -15169,13 +15531,13 @@ function getPiAgentDir() {
|
|
|
15169
15531
|
return resolve13(configuredDir);
|
|
15170
15532
|
const envHome = process.platform === "win32" ? process.env.USERPROFILE : process.env.HOME;
|
|
15171
15533
|
const home = envHome && envHome.length > 0 ? envHome : homedir16();
|
|
15172
|
-
return
|
|
15534
|
+
return join21(home, ".pi", "agent");
|
|
15173
15535
|
}
|
|
15174
15536
|
function readPiExtensionIndex() {
|
|
15175
|
-
const settingsPath =
|
|
15176
|
-
if (
|
|
15537
|
+
const settingsPath = join21(getPiAgentDir(), "settings.json");
|
|
15538
|
+
if (existsSync17(settingsPath)) {
|
|
15177
15539
|
try {
|
|
15178
|
-
const raw =
|
|
15540
|
+
const raw = readFileSync13(settingsPath, "utf-8");
|
|
15179
15541
|
const trimmed = raw.replace(/^\uFEFF/, "");
|
|
15180
15542
|
const value = JSON.parse(trimmed);
|
|
15181
15543
|
const packages = value.packages;
|
|
@@ -15193,13 +15555,13 @@ function readPiExtensionIndex() {
|
|
|
15193
15555
|
} catch {}
|
|
15194
15556
|
}
|
|
15195
15557
|
const candidates = [
|
|
15196
|
-
|
|
15197
|
-
|
|
15198
|
-
|
|
15199
|
-
|
|
15558
|
+
join21(getPiAgentDir(), "extensions.json"),
|
|
15559
|
+
join21(getPiAgentDir(), "extensions.jsonc"),
|
|
15560
|
+
join21(getPiAgentDir(), "config.json"),
|
|
15561
|
+
join21(getPiAgentDir(), "config.jsonc")
|
|
15200
15562
|
];
|
|
15201
15563
|
for (const path of candidates) {
|
|
15202
|
-
if (!
|
|
15564
|
+
if (!existsSync17(path))
|
|
15203
15565
|
continue;
|
|
15204
15566
|
try {
|
|
15205
15567
|
const { value } = readJsoncFile(path);
|
|
@@ -15231,17 +15593,17 @@ function piEntryMatchesAft(entry) {
|
|
|
15231
15593
|
} else if (isAbsolute7(entry)) {
|
|
15232
15594
|
resolved = entry;
|
|
15233
15595
|
} else if (entry.length > 0) {
|
|
15234
|
-
resolved =
|
|
15596
|
+
resolved = join21(getPiAgentDir(), entry);
|
|
15235
15597
|
}
|
|
15236
15598
|
if (!resolved)
|
|
15237
15599
|
return false;
|
|
15238
15600
|
try {
|
|
15239
|
-
if (!
|
|
15601
|
+
if (!existsSync17(resolved))
|
|
15240
15602
|
return false;
|
|
15241
|
-
const pkgPath =
|
|
15242
|
-
if (!
|
|
15603
|
+
const pkgPath = join21(resolved, "package.json");
|
|
15604
|
+
if (!existsSync17(pkgPath))
|
|
15243
15605
|
return false;
|
|
15244
|
-
const pkg = JSON.parse(
|
|
15606
|
+
const pkg = JSON.parse(readFileSync13(pkgPath, "utf-8"));
|
|
15245
15607
|
return pkg.name === PLUGIN_NAME2;
|
|
15246
15608
|
} catch {
|
|
15247
15609
|
return false;
|
|
@@ -15287,10 +15649,10 @@ class PiAdapter {
|
|
|
15287
15649
|
const configDir = getPiAgentDir();
|
|
15288
15650
|
const index = readPiExtensionIndex();
|
|
15289
15651
|
const aftConfigPath = resolveCortexKitUserConfigPath();
|
|
15290
|
-
const aftConfigExists =
|
|
15652
|
+
const aftConfigExists = existsSync17(aftConfigPath);
|
|
15291
15653
|
return {
|
|
15292
15654
|
configDir,
|
|
15293
|
-
harnessConfig: index.path ??
|
|
15655
|
+
harnessConfig: index.path ?? join21(configDir, "extensions.json"),
|
|
15294
15656
|
harnessConfigFormat: index.path ? "json" : "none",
|
|
15295
15657
|
aftConfig: aftConfigPath,
|
|
15296
15658
|
aftConfigFormat: aftConfigExists ? "jsonc" : "none"
|
|
@@ -15338,14 +15700,14 @@ class PiAdapter {
|
|
|
15338
15700
|
}
|
|
15339
15701
|
getPluginCacheInfo() {
|
|
15340
15702
|
const candidates = [
|
|
15341
|
-
|
|
15342
|
-
|
|
15343
|
-
|
|
15703
|
+
join21(getPiAgentDir(), "npm", "node_modules", "@cortexkit", "aft-pi", "package.json"),
|
|
15704
|
+
join21(getPiAgentDir(), "node_modules", "@cortexkit", "aft-pi", "package.json"),
|
|
15705
|
+
join21(getPiAgentDir(), "extensions", "node_modules", "@cortexkit", "aft-pi", "package.json")
|
|
15344
15706
|
];
|
|
15345
15707
|
let readError;
|
|
15346
15708
|
for (const candidate of candidates) {
|
|
15347
15709
|
try {
|
|
15348
|
-
const pkg = JSON.parse(
|
|
15710
|
+
const pkg = JSON.parse(readFileSync13(candidate, "utf-8"));
|
|
15349
15711
|
const cached = typeof pkg.version === "string" ? pkg.version : undefined;
|
|
15350
15712
|
return {
|
|
15351
15713
|
path: candidate,
|
|
@@ -15361,7 +15723,7 @@ class PiAdapter {
|
|
|
15361
15723
|
}
|
|
15362
15724
|
}
|
|
15363
15725
|
return {
|
|
15364
|
-
path:
|
|
15726
|
+
path: join21(getPiAgentDir(), "npm", "node_modules", "@cortexkit", "aft-pi", "package.json"),
|
|
15365
15727
|
exists: readError !== undefined,
|
|
15366
15728
|
readError
|
|
15367
15729
|
};
|
|
@@ -15384,12 +15746,12 @@ class PiAdapter {
|
|
|
15384
15746
|
describeStorageSubtrees() {
|
|
15385
15747
|
const storage = this.getStorageDir();
|
|
15386
15748
|
return {
|
|
15387
|
-
index: dirSize(
|
|
15388
|
-
semantic: dirSize(
|
|
15389
|
-
backups: dirSize(
|
|
15390
|
-
url_cache: dirSize(
|
|
15391
|
-
onnxruntime: dirSize(
|
|
15392
|
-
logs: dirSize(
|
|
15749
|
+
index: dirSize(join21(storage, "index")),
|
|
15750
|
+
semantic: dirSize(join21(storage, "semantic")),
|
|
15751
|
+
backups: dirSize(join21(storage, "backups")),
|
|
15752
|
+
url_cache: dirSize(join21(storage, "url_cache")),
|
|
15753
|
+
onnxruntime: dirSize(join21(storage, "onnxruntime")),
|
|
15754
|
+
logs: dirSize(join21(storage, "logs"))
|
|
15393
15755
|
};
|
|
15394
15756
|
}
|
|
15395
15757
|
}
|
|
@@ -16811,10 +17173,10 @@ var init_version = __esm(async () => {
|
|
|
16811
17173
|
// src/lib/cli-logger.ts
|
|
16812
17174
|
import { appendFileSync, mkdirSync as mkdirSync6 } from "node:fs";
|
|
16813
17175
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
16814
|
-
import { dirname as
|
|
17176
|
+
import { dirname as dirname11, join as join22 } from "node:path";
|
|
16815
17177
|
function cliLogPath() {
|
|
16816
17178
|
if (isTestEnvironment())
|
|
16817
|
-
return
|
|
17179
|
+
return join22(tmpdir4(), "aft-cli-test.log");
|
|
16818
17180
|
return resolveAftLogPath("aft-cli.log");
|
|
16819
17181
|
}
|
|
16820
17182
|
function write(level, message) {
|
|
@@ -16829,7 +17191,7 @@ function write(level, message) {
|
|
|
16829
17191
|
}
|
|
16830
17192
|
try {
|
|
16831
17193
|
const path = cliLogPath();
|
|
16832
|
-
mkdirSync6(
|
|
17194
|
+
mkdirSync6(dirname11(path), { recursive: true });
|
|
16833
17195
|
appendFileSync(path, `${new Date().toISOString()} ${level.toUpperCase()} ${message}
|
|
16834
17196
|
`);
|
|
16835
17197
|
} catch {}
|
|
@@ -16866,13 +17228,13 @@ var init_cli_logger = __esm(() => {
|
|
|
16866
17228
|
});
|
|
16867
17229
|
|
|
16868
17230
|
// src/lib/binary-install.ts
|
|
16869
|
-
import { existsSync as
|
|
16870
|
-
import { join as
|
|
17231
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
17232
|
+
import { join as join23 } from "node:path";
|
|
16871
17233
|
function cachedBinaryFor(version) {
|
|
16872
17234
|
const tag = version.startsWith("v") ? version : `v${version}`;
|
|
16873
|
-
const path =
|
|
17235
|
+
const path = join23(getAftBinaryCacheDir(), tag, getAftBinaryName());
|
|
16874
17236
|
try {
|
|
16875
|
-
return
|
|
17237
|
+
return existsSync18(path) ? path : null;
|
|
16876
17238
|
} catch {
|
|
16877
17239
|
return null;
|
|
16878
17240
|
}
|
|
@@ -17818,8 +18180,8 @@ var init_features = __esm(() => {
|
|
|
17818
18180
|
});
|
|
17819
18181
|
|
|
17820
18182
|
// src/doctor/opencode.ts
|
|
17821
|
-
import { existsSync as
|
|
17822
|
-
import { dirname as
|
|
18183
|
+
import { existsSync as existsSync19, readFileSync as readFileSync14 } from "node:fs";
|
|
18184
|
+
import { dirname as dirname12, join as join24 } from "node:path";
|
|
17823
18185
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
17824
18186
|
function isLoadPath(value) {
|
|
17825
18187
|
return OPENCODE_LOAD_PATHS.includes(value);
|
|
@@ -17882,7 +18244,7 @@ function configuredVersion(entry) {
|
|
|
17882
18244
|
}
|
|
17883
18245
|
function readManifest(path) {
|
|
17884
18246
|
try {
|
|
17885
|
-
const parsed = JSON.parse(
|
|
18247
|
+
const parsed = JSON.parse(readFileSync14(path, "utf8"));
|
|
17886
18248
|
return parsed.name === AFT_OPENCODE_PACKAGE ? parsed : null;
|
|
17887
18249
|
} catch {
|
|
17888
18250
|
return null;
|
|
@@ -17890,13 +18252,13 @@ function readManifest(path) {
|
|
|
17890
18252
|
}
|
|
17891
18253
|
function manifestFromLocalPath(path) {
|
|
17892
18254
|
let current = path;
|
|
17893
|
-
if (!
|
|
17894
|
-
current =
|
|
18255
|
+
if (!existsSync19(join24(current, "package.json")))
|
|
18256
|
+
current = dirname12(current);
|
|
17895
18257
|
while (true) {
|
|
17896
|
-
const manifest = readManifest(
|
|
18258
|
+
const manifest = readManifest(join24(current, "package.json"));
|
|
17897
18259
|
if (manifest)
|
|
17898
18260
|
return manifest;
|
|
17899
|
-
const parent =
|
|
18261
|
+
const parent = dirname12(current);
|
|
17900
18262
|
if (parent === current)
|
|
17901
18263
|
return null;
|
|
17902
18264
|
current = parent;
|
|
@@ -17906,16 +18268,16 @@ function pluginManifest(entry, cachePath) {
|
|
|
17906
18268
|
const localRoot = localPluginRoot(entry);
|
|
17907
18269
|
if (localRoot)
|
|
17908
18270
|
return manifestFromLocalPath(localRoot);
|
|
17909
|
-
return readManifest(
|
|
18271
|
+
return readManifest(join24(cachePath, "node_modules", "@cortexkit", "aft-opencode", "package.json"));
|
|
17910
18272
|
}
|
|
17911
18273
|
function pinProblem(entry, pinned) {
|
|
17912
18274
|
return `the plugin entry ${entry} ${describePluginEntry(entry)}; run \`${CLI} doctor --fix\` to pin it to ${pinned}`;
|
|
17913
18275
|
}
|
|
17914
18276
|
function latestLoggedLoadPath(logPath) {
|
|
17915
|
-
if (!
|
|
18277
|
+
if (!existsSync19(logPath))
|
|
17916
18278
|
return null;
|
|
17917
18279
|
try {
|
|
17918
|
-
const text =
|
|
18280
|
+
const text = readFileSync14(logPath, "utf8");
|
|
17919
18281
|
const pattern = /(?:load path|load_path)\s*[:=]\s*(root-default|export-server-effect-bun|export-server-effect-node)/gi;
|
|
17920
18282
|
let latest = null;
|
|
17921
18283
|
for (const match of text.matchAll(pattern)) {
|
|
@@ -17955,7 +18317,12 @@ function diagnoseOpenCodeLoad(input) {
|
|
|
17955
18317
|
const pluginVersion = (typeof manifest?.version === "string" ? manifest.version : null) ?? input.cachedPluginVersion ?? configuredVersion(entry) ?? null;
|
|
17956
18318
|
const problems = [...describePluginKeyProblems(config, generation)];
|
|
17957
18319
|
let entryPinProblem = null;
|
|
17958
|
-
|
|
18320
|
+
let versionNotice;
|
|
18321
|
+
const cli = input.expectedPluginEntry ? exactPinnedVersion(input.expectedPluginEntry) : null;
|
|
18322
|
+
const installed = input.cachedPluginVersion ?? (typeof manifest?.version === "string" ? manifest.version : undefined);
|
|
18323
|
+
if (cli && entry && isAftNpmEntry(entry) && preserveDoctorPluginEntry(cli, entry, installed)) {
|
|
18324
|
+
versionNotice = doctorNoDowngradeMessage(cli, entry, installed);
|
|
18325
|
+
} else if (entry && isAftNpmEntry(entry) && input.expectedPluginEntry && entry !== input.expectedPluginEntry && !(input.acceptExplicitPluginVersion && acceptV1Entry(entry))) {
|
|
17959
18326
|
entryPinProblem = pinProblem(entry, input.expectedPluginEntry);
|
|
17960
18327
|
problems.push(entryPinProblem);
|
|
17961
18328
|
}
|
|
@@ -17967,7 +18334,14 @@ function diagnoseOpenCodeLoad(input) {
|
|
|
17967
18334
|
if (expectedLoadPath && takenLoadPath && expectedLoadPath !== takenLoadPath) {
|
|
17968
18335
|
problems.push(`load path ${takenLoadPath} does not match ${expectedLoadPath} expected for the detected host`);
|
|
17969
18336
|
}
|
|
17970
|
-
return {
|
|
18337
|
+
return {
|
|
18338
|
+
expectedLoadPath,
|
|
18339
|
+
takenLoadPath,
|
|
18340
|
+
pluginVersion,
|
|
18341
|
+
problems,
|
|
18342
|
+
pinProblem: entryPinProblem,
|
|
18343
|
+
versionNotice
|
|
18344
|
+
};
|
|
17971
18345
|
}
|
|
17972
18346
|
function describePluginKeyProblems(config, generation) {
|
|
17973
18347
|
if (!config || generation === "ambiguous" || generation === "unknown")
|
|
@@ -18167,11 +18541,11 @@ var init_aft_bridge = __esm(() => {
|
|
|
18167
18541
|
});
|
|
18168
18542
|
|
|
18169
18543
|
// src/lib/binary-cache.ts
|
|
18170
|
-
import { existsSync as
|
|
18171
|
-
import { join as
|
|
18544
|
+
import { existsSync as existsSync20, readdirSync as readdirSync8, statSync as statSync12 } from "node:fs";
|
|
18545
|
+
import { join as join25 } from "node:path";
|
|
18172
18546
|
function getBinaryCacheInfo(activeVersion) {
|
|
18173
18547
|
const path = getAftBinaryCacheDir();
|
|
18174
|
-
if (!
|
|
18548
|
+
if (!existsSync20(path)) {
|
|
18175
18549
|
return {
|
|
18176
18550
|
versions: [],
|
|
18177
18551
|
activeVersion: null,
|
|
@@ -18179,9 +18553,9 @@ function getBinaryCacheInfo(activeVersion) {
|
|
|
18179
18553
|
path
|
|
18180
18554
|
};
|
|
18181
18555
|
}
|
|
18182
|
-
const versions =
|
|
18556
|
+
const versions = readdirSync8(path).filter((entry) => {
|
|
18183
18557
|
try {
|
|
18184
|
-
return statSync12(
|
|
18558
|
+
return statSync12(join25(path, entry)).isDirectory();
|
|
18185
18559
|
} catch {
|
|
18186
18560
|
return false;
|
|
18187
18561
|
}
|
|
@@ -18216,8 +18590,22 @@ function safeRealpath(p) {
|
|
|
18216
18590
|
function looksLikeSecret(value) {
|
|
18217
18591
|
return value.length >= 16 && /^[A-Za-z0-9_\-.~+/=]+$/.test(value) && /[0-9]/.test(value) && /[A-Z]/.test(value) && /[a-z]/.test(value);
|
|
18218
18592
|
}
|
|
18593
|
+
function looksLikeAssignmentSecret(value) {
|
|
18594
|
+
return !["/", "~/", "./", "../"].some((prefix) => value.startsWith(prefix)) && !value.includes("://") && looksLikeSecret(value);
|
|
18595
|
+
}
|
|
18219
18596
|
function isSensitiveKeyName(keyName) {
|
|
18220
|
-
return SENSITIVE_KEY_WORD.test(keyName) || SEGMENTED_KEY_WORD.test(keyName) || CAMEL_CASE_KEY_WORD.test(keyName);
|
|
18597
|
+
return keyName !== "PWD" && (SENSITIVE_KEY_WORD.test(keyName) || SEGMENTED_KEY_WORD.test(keyName) || CAMEL_CASE_KEY_WORD.test(keyName) || SHORT_PASSWORD_NAME.test(keyName));
|
|
18598
|
+
}
|
|
18599
|
+
function shouldRedactAssignment(prefix, keyName, value, offset, content, commandContext) {
|
|
18600
|
+
if (keyName.toLowerCase() === "key" && /[?&]/.test(content[offset - 1] ?? "")) {
|
|
18601
|
+
return false;
|
|
18602
|
+
}
|
|
18603
|
+
return isSensitiveKeyName(keyName) || commandContext && prefix.trimEnd().endsWith("=") && looksLikeAssignmentSecret(value);
|
|
18604
|
+
}
|
|
18605
|
+
function redactAssignments(content, commandContext) {
|
|
18606
|
+
let sanitized = content.replace(unquotedSensitiveKeyValuePattern, (match, prefix, keyName, valueQuote, value, offset, input) => shouldRedactAssignment(prefix, keyName, value, offset, input, commandContext) ? `${prefix}${valueQuote}${SECRET_PLACEHOLDER}${valueQuote}` : match);
|
|
18607
|
+
sanitized = sanitized.replace(bareSensitiveKeyValuePattern, (match, prefix, keyName, value, offset, input) => shouldRedactAssignment(prefix, keyName, value, offset, input, commandContext) ? `${prefix}${SECRET_PLACEHOLDER}` : match);
|
|
18608
|
+
return sanitized;
|
|
18221
18609
|
}
|
|
18222
18610
|
function redactSecrets(content) {
|
|
18223
18611
|
let sanitized = content;
|
|
@@ -18230,73 +18618,188 @@ function redactSecrets(content) {
|
|
|
18230
18618
|
sanitized = sanitized.replace(CREDENTIAL_QUERY_PATTERN, `$1${SECRET_PLACEHOLDER}`);
|
|
18231
18619
|
sanitized = sanitized.replace(KEY_QUERY_PATTERN, (match, prefix, value) => looksLikeSecret(value) ? `${prefix}${SECRET_PLACEHOLDER}` : match);
|
|
18232
18620
|
sanitized = sanitized.replace(quotedSensitiveKeyValuePattern, (match, prefix, _keyQuote, keyName, valueQuote) => isSensitiveKeyName(keyName) ? `${prefix}${valueQuote}${SECRET_PLACEHOLDER}${valueQuote}` : match);
|
|
18233
|
-
sanitized = sanitized
|
|
18234
|
-
sanitized = sanitized.replace(bareSensitiveKeyValuePattern, (match, prefix, keyName) => isSensitiveKeyName(keyName) ? `${prefix}${SECRET_PLACEHOLDER}` : match);
|
|
18621
|
+
sanitized = redactAssignments(sanitized, false);
|
|
18235
18622
|
sanitized = sanitized.replace(/\b([a-z][a-z0-9+.-]*:\/\/)[^@\s/?#]+@/gi, `$1${URL_CREDENTIAL_PLACEHOLDER}@`);
|
|
18236
18623
|
sanitized = sanitized.replace(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi, "<EMAIL>");
|
|
18624
|
+
sanitized = sanitized.replace(/^([^\r\n]*\bbash spawned task=[^\r\n]*? cmd=)([^\r\n]*)/gm, (_match, prefix, command) => `${prefix}${redactAssignments(command, true)}`);
|
|
18237
18625
|
return sanitized;
|
|
18238
18626
|
}
|
|
18239
|
-
function sanitizeContent(content) {
|
|
18240
|
-
const username = userInfo().username;
|
|
18241
|
-
const home = homedir17();
|
|
18627
|
+
function sanitizeContent(content, context = {}) {
|
|
18628
|
+
const username = context.username ?? userInfo().username;
|
|
18629
|
+
const home = context.home ?? homedir17();
|
|
18242
18630
|
let sanitized = redactSecrets(content);
|
|
18243
18631
|
const cwd = process.cwd();
|
|
18244
|
-
|
|
18245
|
-
|
|
18246
|
-
|
|
18632
|
+
const roots = new Set([
|
|
18633
|
+
cwd,
|
|
18634
|
+
safeRealpath(cwd),
|
|
18635
|
+
...(context.projectRoots ?? []).flatMap((root) => root.startsWith("~/") ? [root, home + root.slice(1)] : [root]),
|
|
18636
|
+
...reportProjectRoots(decodedView(content).text)
|
|
18637
|
+
]);
|
|
18638
|
+
const candidates = [...roots].filter((root) => Boolean(root));
|
|
18639
|
+
for (const root of candidates) {
|
|
18640
|
+
const real = safeRealpath(root);
|
|
18641
|
+
if (real)
|
|
18642
|
+
roots.add(real);
|
|
18643
|
+
}
|
|
18644
|
+
for (const root of [...roots].filter((root) => Boolean(root)).sort((a, b) => b.length - a.length)) {
|
|
18645
|
+
if (/^(?:\/|[A-Za-z]:[/\\]|~\/)/.test(root) && root !== home && !/^(?:[/\\]|[A-Za-z]:[/\\])$/.test(root)) {
|
|
18646
|
+
sanitized = replacePath(sanitized, root, "<PROJECT>");
|
|
18647
|
+
}
|
|
18648
|
+
}
|
|
18649
|
+
if (home && home !== "/")
|
|
18650
|
+
sanitized = replacePath(sanitized, home, "~");
|
|
18651
|
+
sanitized = replaceDecoded(sanitized, /(?:(?<![\p{L}\p{N}_/.-])|(?<=file:\/\/)|(?<=file:\/\/\/))(?:\/(?:home|Users)\/|[A-Za-z]:\/Users\/)([^/\s"'<>`,;:?#&()[\]{}=]+)/gu, (match) => ({ offset: match[0].length - match[1].length, value: "<USER>" }));
|
|
18652
|
+
return redactUsername(sanitized, username);
|
|
18653
|
+
}
|
|
18654
|
+
function decodedView(content) {
|
|
18655
|
+
let units = Array.from({ length: content.length }, (_, i) => ({
|
|
18656
|
+
char: content[i],
|
|
18657
|
+
start: i,
|
|
18658
|
+
end: i + 1
|
|
18659
|
+
}));
|
|
18660
|
+
const decoded = [];
|
|
18661
|
+
for (let i = 0;i < units.length; ) {
|
|
18662
|
+
const byte = content.slice(i, i + 3);
|
|
18663
|
+
const first = /^%[\da-f]{2}$/i.test(byte) ? Number.parseInt(byte.slice(1), 16) : -1;
|
|
18664
|
+
const width = first < 128 ? 1 : first >= 194 && first <= 223 ? 2 : first <= 239 ? 3 : 4;
|
|
18665
|
+
const spelling = content.slice(i, i + width * 3);
|
|
18666
|
+
if (first >= 0 && /^(?:%[\da-f]{2})+$/i.test(spelling)) {
|
|
18667
|
+
try {
|
|
18668
|
+
const value = decodeURIComponent(spelling);
|
|
18669
|
+
for (const char of value.split(""))
|
|
18670
|
+
decoded.push({ char, start: i, end: i + spelling.length });
|
|
18671
|
+
i += spelling.length;
|
|
18672
|
+
continue;
|
|
18673
|
+
} catch {}
|
|
18247
18674
|
}
|
|
18675
|
+
decoded.push(units[i++]);
|
|
18248
18676
|
}
|
|
18249
|
-
|
|
18250
|
-
|
|
18677
|
+
units = [];
|
|
18678
|
+
for (let i = 0;i < decoded.length; i++) {
|
|
18679
|
+
const unit = decoded[i];
|
|
18680
|
+
const next = decoded[i + 1];
|
|
18681
|
+
if (unit.char === "\\" && next && (next.char === "/" || next.char === "\\")) {
|
|
18682
|
+
units.push({ char: "/", start: unit.start, end: next.end });
|
|
18683
|
+
i++;
|
|
18684
|
+
} else
|
|
18685
|
+
units.push({ ...unit, char: unit.char === "\\" ? "/" : unit.char });
|
|
18251
18686
|
}
|
|
18252
|
-
|
|
18253
|
-
|
|
18254
|
-
|
|
18255
|
-
|
|
18256
|
-
|
|
18257
|
-
|
|
18258
|
-
|
|
18687
|
+
return { text: units.map((unit) => unit.char).join(""), units };
|
|
18688
|
+
}
|
|
18689
|
+
function replaceDecoded(content, pattern, replacement) {
|
|
18690
|
+
const view = decodedView(content);
|
|
18691
|
+
let result = "";
|
|
18692
|
+
let cursor = 0;
|
|
18693
|
+
for (const match of view.text.matchAll(pattern)) {
|
|
18694
|
+
const change = replacement(match);
|
|
18695
|
+
if (!change)
|
|
18696
|
+
continue;
|
|
18697
|
+
const { offset, value } = change;
|
|
18698
|
+
const start = view.units[match.index + offset].start;
|
|
18699
|
+
const end = view.units[match.index + match[0].length - 1].end;
|
|
18700
|
+
result += content.slice(cursor, start) + value;
|
|
18701
|
+
cursor = end;
|
|
18259
18702
|
}
|
|
18260
|
-
return
|
|
18703
|
+
return result + content.slice(cursor);
|
|
18704
|
+
}
|
|
18705
|
+
function replacePath(content, path, value) {
|
|
18706
|
+
const normalized = path.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
18707
|
+
if (!normalized)
|
|
18708
|
+
return content;
|
|
18709
|
+
const pattern = new RegExp(`(?:(?<![\\p{L}\\p{N}_/.-])|(?<=file://)|(?<=file:///))${escapeRegex(normalized)}(?=$|[/\\s"'<>\`,;:)\\]?#&])`, /^[A-Za-z]:/.test(path) ? "giu" : "gu");
|
|
18710
|
+
return replaceDecoded(content, pattern, () => ({ offset: 0, value }));
|
|
18711
|
+
}
|
|
18712
|
+
function reportProjectRoots(content) {
|
|
18713
|
+
return [
|
|
18714
|
+
...content.matchAll(/(?:project root set: |watcher started: )([^\r\n]+)/g),
|
|
18715
|
+
...content.matchAll(/(?:\broot=|"(?:projectRoot|project_root|canonical_root)"\s*:\s*)("[^"]+"|'[^']+'|[^\s"'<>`,;]+)/g)
|
|
18716
|
+
].map((match) => match[1].trim().replace(/^["']|["']$/g, "")).filter((root) => /^(?:\/|[A-Za-z]:\/)/.test(root));
|
|
18717
|
+
}
|
|
18718
|
+
function sanitizeValue(value, context = {}) {
|
|
18719
|
+
const scoped = {
|
|
18720
|
+
...context,
|
|
18721
|
+
projectRoots: [...context.projectRoots ?? [], ...projectRootsFromValue(value)]
|
|
18722
|
+
};
|
|
18723
|
+
return sanitizeNestedValue(value, scoped);
|
|
18261
18724
|
}
|
|
18262
|
-
function
|
|
18725
|
+
function sanitizeNestedValue(value, context) {
|
|
18263
18726
|
if (typeof value === "string") {
|
|
18264
|
-
return sanitizeContent(value);
|
|
18727
|
+
return sanitizeContent(value, context);
|
|
18265
18728
|
}
|
|
18266
18729
|
if (Array.isArray(value)) {
|
|
18267
|
-
return value.map((entry) =>
|
|
18730
|
+
return value.map((entry) => sanitizeNestedValue(entry, context));
|
|
18268
18731
|
}
|
|
18269
18732
|
if (value && typeof value === "object") {
|
|
18270
|
-
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key,
|
|
18733
|
+
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, sanitizeNestedValue(entry, context)]));
|
|
18271
18734
|
}
|
|
18272
18735
|
return value;
|
|
18273
18736
|
}
|
|
18737
|
+
function projectRootsFromValue(value) {
|
|
18738
|
+
if (!value || typeof value !== "object")
|
|
18739
|
+
return [];
|
|
18740
|
+
if (Array.isArray(value))
|
|
18741
|
+
return value.flatMap(projectRootsFromValue);
|
|
18742
|
+
const object = value;
|
|
18743
|
+
const roots = [object.projectRoot, object.project_root, object.canonical_root].filter((root) => typeof root === "string");
|
|
18744
|
+
const index = object.index;
|
|
18745
|
+
if (index && Array.isArray(index.roots)) {
|
|
18746
|
+
for (const root of index.roots)
|
|
18747
|
+
if (root && typeof root.path === "string")
|
|
18748
|
+
roots.push(root.path);
|
|
18749
|
+
}
|
|
18750
|
+
return [...roots, ...Object.values(object).flatMap(projectRootsFromValue)];
|
|
18751
|
+
}
|
|
18274
18752
|
function redactUsername(content, username) {
|
|
18275
18753
|
if (!username)
|
|
18276
18754
|
return content;
|
|
18277
|
-
|
|
18755
|
+
if (!COMMON_ACCOUNT_NAMES.has(username.toLowerCase())) {
|
|
18756
|
+
return replaceDecoded(content, new RegExp(`(?<![\\p{L}\\p{N}_])${escapeRegex(username)}(?![\\p{L}\\p{N}_])`, "gu"), () => ({ offset: 0, value: "<USER>" }));
|
|
18757
|
+
}
|
|
18758
|
+
return replaceDecoded(content, new RegExp(`(?<![\\p{L}\\p{N}_/.-])~${escapeRegex(username)}(?![\\p{L}\\p{N}_])|(?<![\\p{L}\\p{N}_/.-])${escapeRegex(username)}(?=@[\\p{L}\\p{N}])`, "gu"), (match) => ({ offset: match[0].startsWith("~") ? 1 : 0, value: "<USER>" }));
|
|
18278
18759
|
}
|
|
18279
|
-
var SECRET_PLACEHOLDER = "<REDACTED_SECRET>", URL_CREDENTIAL_PLACEHOLDER = "***", KEY_NAME = "[A-Za-z_][A-Za-z0-9_.-]*", SENSITIVE_KEY_WORD, SEGMENTED_KEY_WORD, CAMEL_CASE_KEY_WORD, JWT_PATTERN, AWS_ACCESS_KEY_ID_PATTERN, CREDENTIAL_QUERY_PATTERN, KEY_QUERY_PATTERN, quotedSensitiveKeyValuePattern, unquotedSensitiveKeyValuePattern, bareSensitiveKeyValuePattern;
|
|
18760
|
+
var SECRET_PLACEHOLDER = "<REDACTED_SECRET>", URL_CREDENTIAL_PLACEHOLDER = "***", KEY_NAME = "[A-Za-z_][A-Za-z0-9_.-]*", SENSITIVE_KEY_WORD, SEGMENTED_KEY_WORD, CAMEL_CASE_KEY_WORD, SHORT_PASSWORD_NAME, JWT_PATTERN, AWS_ACCESS_KEY_ID_PATTERN, CREDENTIAL_QUERY_PATTERN, KEY_QUERY_PATTERN, quotedSensitiveKeyValuePattern, unquotedSensitiveKeyValuePattern, bareSensitiveKeyValuePattern, COMMON_ACCOUNT_NAMES;
|
|
18280
18761
|
var init_sanitize = __esm(() => {
|
|
18281
18762
|
SENSITIVE_KEY_WORD = /(?:token|password|secret|api[_-]?key|passwd|pwd|credential)/i;
|
|
18282
18763
|
SEGMENTED_KEY_WORD = /(?:^|[_.-])key(?:$|[_.-])/i;
|
|
18283
18764
|
CAMEL_CASE_KEY_WORD = /[a-z0-9]Key(?:$|[A-Z_.-])/;
|
|
18765
|
+
SHORT_PASSWORD_NAME = /(?:^|_)(?:pw|pass)$/i;
|
|
18284
18766
|
JWT_PATTERN = /\beyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g;
|
|
18285
18767
|
AWS_ACCESS_KEY_ID_PATTERN = /\b(?:AKIA|ASIA|AGPA|AIDA|AROA)[A-Z0-9]{16}\b/g;
|
|
18286
18768
|
CREDENTIAL_QUERY_PATTERN = /([?&](?:[a-z0-9_-]*token|api[_-]?key|apikey|[a-z0-9_-]*secret|password|passwd|pwd)=)[^&\s#"'<>]+/gi;
|
|
18287
18769
|
KEY_QUERY_PATTERN = /([?&]key=)([^&\s#"'<>]+)/gi;
|
|
18288
18770
|
quotedSensitiveKeyValuePattern = new RegExp(String.raw`((['"])(${KEY_NAME})\2[^\S\r\n]*:[^\S\r\n]*)(['"])([^'"\r\n]+)\4`, "gi");
|
|
18289
18771
|
unquotedSensitiveKeyValuePattern = new RegExp(String.raw`\b((${KEY_NAME})[^\S\r\n]*[=:][^\S\r\n]*)(['"])([^'"\r\n]+)\3`, "gi");
|
|
18290
|
-
bareSensitiveKeyValuePattern = new RegExp(String.raw`\b((${KEY_NAME})[^\S\r\n]*[=:][^\S\r\n]*)([^\s
|
|
18772
|
+
bareSensitiveKeyValuePattern = new RegExp(String.raw`\b((${KEY_NAME})[^\S\r\n]*[=:][^\S\r\n]*)([^\s,;&|<>()'"]+)`, "gi");
|
|
18773
|
+
COMMON_ACCOUNT_NAMES = new Set([
|
|
18774
|
+
"root",
|
|
18775
|
+
"admin",
|
|
18776
|
+
"administrator",
|
|
18777
|
+
"user",
|
|
18778
|
+
"dev",
|
|
18779
|
+
"developer",
|
|
18780
|
+
"test",
|
|
18781
|
+
"guest",
|
|
18782
|
+
"ubuntu",
|
|
18783
|
+
"debian",
|
|
18784
|
+
"pi",
|
|
18785
|
+
"runner",
|
|
18786
|
+
"vagrant",
|
|
18787
|
+
"ec2-user",
|
|
18788
|
+
"centos",
|
|
18789
|
+
"git",
|
|
18790
|
+
"docker",
|
|
18791
|
+
"build",
|
|
18792
|
+
"ci"
|
|
18793
|
+
]);
|
|
18291
18794
|
});
|
|
18292
18795
|
|
|
18293
18796
|
// src/lib/bridge-tool-failures.ts
|
|
18294
|
-
import { closeSync as closeSync8, existsSync as
|
|
18797
|
+
import { closeSync as closeSync8, existsSync as existsSync21, openSync as openSync8, readSync as readSync6, statSync as statSync13 } from "node:fs";
|
|
18295
18798
|
function resolveBridgePluginLogPath() {
|
|
18296
18799
|
return resolvePluginLogPath();
|
|
18297
18800
|
}
|
|
18298
18801
|
function tailLogFileBytes(path, maxBytes) {
|
|
18299
|
-
if (!
|
|
18802
|
+
if (!existsSync21(path) || maxBytes <= 0)
|
|
18300
18803
|
return "";
|
|
18301
18804
|
let fd = null;
|
|
18302
18805
|
try {
|
|
@@ -18432,9 +18935,9 @@ var init_bridge_tool_failures = __esm(() => {
|
|
|
18432
18935
|
});
|
|
18433
18936
|
|
|
18434
18937
|
// src/lib/build-breaker.ts
|
|
18435
|
-
import { existsSync as
|
|
18938
|
+
import { existsSync as existsSync22, readdirSync as readdirSync9 } from "node:fs";
|
|
18436
18939
|
import { createRequire as createRequire3 } from "node:module";
|
|
18437
|
-
import { join as
|
|
18940
|
+
import { join as join26 } from "node:path";
|
|
18438
18941
|
function loadDatabaseSync() {
|
|
18439
18942
|
const require2 = createRequire3(import.meta.url);
|
|
18440
18943
|
try {
|
|
@@ -18448,11 +18951,11 @@ function loadDatabaseSync() {
|
|
|
18448
18951
|
}
|
|
18449
18952
|
}
|
|
18450
18953
|
function buildBreakerDatabases(storageRoot) {
|
|
18451
|
-
const callgraphRoot =
|
|
18452
|
-
if (!
|
|
18954
|
+
const callgraphRoot = join26(storageRoot, "callgraph");
|
|
18955
|
+
if (!existsSync22(callgraphRoot))
|
|
18453
18956
|
return [];
|
|
18454
18957
|
try {
|
|
18455
|
-
return
|
|
18958
|
+
return readdirSync9(callgraphRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join26(callgraphRoot, entry.name, "build-breaker.sqlite")).filter((path) => existsSync22(path));
|
|
18456
18959
|
} catch {
|
|
18457
18960
|
return [];
|
|
18458
18961
|
}
|
|
@@ -18528,15 +19031,15 @@ var init_build_breaker = __esm(() => {
|
|
|
18528
19031
|
});
|
|
18529
19032
|
|
|
18530
19033
|
// src/lib/config-migration.ts
|
|
18531
|
-
import { existsSync as
|
|
19034
|
+
import { existsSync as existsSync23, readFileSync as readFileSync15 } from "node:fs";
|
|
18532
19035
|
function isRecord2(value) {
|
|
18533
19036
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18534
19037
|
}
|
|
18535
19038
|
function readPlainConfig(path) {
|
|
18536
|
-
if (!
|
|
19039
|
+
if (!existsSync23(path))
|
|
18537
19040
|
return null;
|
|
18538
19041
|
try {
|
|
18539
|
-
const plain = JSON.parse(JSON.stringify(import_comment_json2.parse(
|
|
19042
|
+
const plain = JSON.parse(JSON.stringify(import_comment_json2.parse(readFileSync15(path, "utf8"))));
|
|
18540
19043
|
return isRecord2(plain) ? plain : null;
|
|
18541
19044
|
} catch {
|
|
18542
19045
|
return null;
|
|
@@ -18544,10 +19047,10 @@ function readPlainConfig(path) {
|
|
|
18544
19047
|
}
|
|
18545
19048
|
function configMigrationTargets(userConfigPath, cwd = process.cwd()) {
|
|
18546
19049
|
const targets = [];
|
|
18547
|
-
if (
|
|
19050
|
+
if (existsSync23(userConfigPath))
|
|
18548
19051
|
targets.push({ path: userConfigPath, tier: "user" });
|
|
18549
19052
|
const project = resolveCortexKitProjectConfigPath(cwd);
|
|
18550
|
-
if (project !== userConfigPath &&
|
|
19053
|
+
if (project !== userConfigPath && existsSync23(project)) {
|
|
18551
19054
|
targets.push({ path: project, tier: "project" });
|
|
18552
19055
|
}
|
|
18553
19056
|
return targets;
|
|
@@ -18591,6 +19094,7 @@ function previewConfigMigration(targets) {
|
|
|
18591
19094
|
const translation = translateConfigDocument(translated, target.tier);
|
|
18592
19095
|
if (!translation.legacyInput)
|
|
18593
19096
|
continue;
|
|
19097
|
+
dropRemovedDataLayerKeys(translated);
|
|
18594
19098
|
const changes = diffConfig(raw, translated);
|
|
18595
19099
|
previews.push({ ...target, changes });
|
|
18596
19100
|
}
|
|
@@ -18612,21 +19116,27 @@ var init_config_migration = __esm(() => {
|
|
|
18612
19116
|
import_comment_json2 = __toESM(require_src2(), 1);
|
|
18613
19117
|
});
|
|
18614
19118
|
|
|
19119
|
+
// src/lib/doctor-labels.ts
|
|
19120
|
+
function describeCliBinary(version, path) {
|
|
19121
|
+
return CLI_BINARY_LABEL.replace("<version>", version ?? "unknown").replace("<path>", path ?? "unknown");
|
|
19122
|
+
}
|
|
19123
|
+
var CLI_BINARY_LABEL = "AFT binary this CLI found: <version> at <path> (the plugin may run a different one)", CLI_VERSION_CACHED_LABEL = "Cached binary for this CLI";
|
|
19124
|
+
|
|
18615
19125
|
// src/lib/legacy-storage.ts
|
|
18616
|
-
import { existsSync as
|
|
18617
|
-
import { join as
|
|
19126
|
+
import { existsSync as existsSync24, readdirSync as readdirSync10, statSync as statSync14 } from "node:fs";
|
|
19127
|
+
import { join as join27 } from "node:path";
|
|
18618
19128
|
function summarizeLegacyPartitionDuplication(storageRoot) {
|
|
18619
|
-
if (!
|
|
19129
|
+
if (!existsSync24(storageRoot)) {
|
|
18620
19130
|
return { totalPartitions: 0, totalBytes: 0, byHarness: [] };
|
|
18621
19131
|
}
|
|
18622
19132
|
const byHarness = [];
|
|
18623
19133
|
for (const harness of safeReadDir(storageRoot)) {
|
|
18624
|
-
const harnessPath =
|
|
19134
|
+
const harnessPath = join27(storageRoot, harness);
|
|
18625
19135
|
if (!isDirectory(harnessPath))
|
|
18626
19136
|
continue;
|
|
18627
19137
|
const partitions = new Map;
|
|
18628
|
-
collectCallgraphPartitions(
|
|
18629
|
-
collectInspectPartitions(
|
|
19138
|
+
collectCallgraphPartitions(join27(harnessPath, "callgraph"), partitions);
|
|
19139
|
+
collectInspectPartitions(join27(harnessPath, "inspect"), partitions);
|
|
18630
19140
|
if (partitions.size === 0)
|
|
18631
19141
|
continue;
|
|
18632
19142
|
let bytes = 0;
|
|
@@ -18645,7 +19155,7 @@ function collectCallgraphPartitions(domainPath, partitions) {
|
|
|
18645
19155
|
if (!isDirectory(domainPath))
|
|
18646
19156
|
return;
|
|
18647
19157
|
for (const name of safeReadDir(domainPath)) {
|
|
18648
|
-
const path =
|
|
19158
|
+
const path = join27(domainPath, name);
|
|
18649
19159
|
if (isDirectory(path)) {
|
|
18650
19160
|
if (!looksLikePartitionKey(name))
|
|
18651
19161
|
continue;
|
|
@@ -18662,7 +19172,7 @@ function collectInspectPartitions(domainPath, partitions) {
|
|
|
18662
19172
|
if (!isDirectory(domainPath))
|
|
18663
19173
|
return;
|
|
18664
19174
|
for (const name of safeReadDir(domainPath)) {
|
|
18665
|
-
const path =
|
|
19175
|
+
const path = join27(domainPath, name);
|
|
18666
19176
|
if (isDirectory(path)) {
|
|
18667
19177
|
if (!looksLikePartitionKey(name))
|
|
18668
19178
|
continue;
|
|
@@ -18711,7 +19221,7 @@ function looksLikePartitionKey(value) {
|
|
|
18711
19221
|
}
|
|
18712
19222
|
function safeReadDir(path) {
|
|
18713
19223
|
try {
|
|
18714
|
-
return
|
|
19224
|
+
return readdirSync10(path).sort((left, right) => left.localeCompare(right));
|
|
18715
19225
|
} catch {
|
|
18716
19226
|
return [];
|
|
18717
19227
|
}
|
|
@@ -18737,22 +19247,22 @@ var init_legacy_storage = __esm(() => {
|
|
|
18737
19247
|
});
|
|
18738
19248
|
|
|
18739
19249
|
// src/lib/lsp-cache.ts
|
|
18740
|
-
import { existsSync as
|
|
18741
|
-
import { join as
|
|
19250
|
+
import { existsSync as existsSync25, readdirSync as readdirSync11, rmSync as rmSync6, statSync as statSync15 } from "node:fs";
|
|
19251
|
+
import { join as join28 } from "node:path";
|
|
18742
19252
|
function inspectDir(path) {
|
|
18743
|
-
if (!
|
|
19253
|
+
if (!existsSync25(path)) {
|
|
18744
19254
|
return { entries: [], totalSize: 0 };
|
|
18745
19255
|
}
|
|
18746
19256
|
const entries = [];
|
|
18747
19257
|
let totalSize = 0;
|
|
18748
19258
|
let names;
|
|
18749
19259
|
try {
|
|
18750
|
-
names =
|
|
19260
|
+
names = readdirSync11(path);
|
|
18751
19261
|
} catch {
|
|
18752
19262
|
return { entries: [], totalSize: 0 };
|
|
18753
19263
|
}
|
|
18754
19264
|
for (const name of names) {
|
|
18755
|
-
const full =
|
|
19265
|
+
const full = join28(path, name);
|
|
18756
19266
|
try {
|
|
18757
19267
|
if (!statSync15(full).isDirectory())
|
|
18758
19268
|
continue;
|
|
@@ -18814,8 +19324,8 @@ var init_lsp_cache = __esm(() => {
|
|
|
18814
19324
|
});
|
|
18815
19325
|
|
|
18816
19326
|
// src/lib/onnx.ts
|
|
18817
|
-
import { existsSync as
|
|
18818
|
-
import { basename as basename2, isAbsolute as isAbsolute8, join as
|
|
19327
|
+
import { existsSync as existsSync26, readdirSync as readdirSync12, readlinkSync as readlinkSync2, realpathSync as realpathSync7 } from "node:fs";
|
|
19328
|
+
import { basename as basename2, isAbsolute as isAbsolute8, join as join29, resolve as resolve14, win32 as win323 } from "node:path";
|
|
18819
19329
|
function getOnnxLibraryName() {
|
|
18820
19330
|
if (process.platform === "darwin")
|
|
18821
19331
|
return "libonnxruntime.dylib";
|
|
@@ -18867,7 +19377,7 @@ function isWindowsSystem32Directory2(dir) {
|
|
|
18867
19377
|
}
|
|
18868
19378
|
function directoryContainsLibrary2(dir, libName) {
|
|
18869
19379
|
try {
|
|
18870
|
-
const entries =
|
|
19380
|
+
const entries = readdirSync12(dir);
|
|
18871
19381
|
if (process.platform === "win32") {
|
|
18872
19382
|
const expected = libName.toLowerCase();
|
|
18873
19383
|
return entries.some((entry) => entry.toLowerCase() === expected);
|
|
@@ -18885,7 +19395,7 @@ function findIgnoredWindowsSystemOnnxRuntime() {
|
|
|
18885
19395
|
for (const root of windowsRoots) {
|
|
18886
19396
|
if (!root)
|
|
18887
19397
|
continue;
|
|
18888
|
-
const systemDir =
|
|
19398
|
+
const systemDir = join29(root, "System32");
|
|
18889
19399
|
const key = win323.resolve(systemDir).toLowerCase();
|
|
18890
19400
|
if (seen.has(key))
|
|
18891
19401
|
continue;
|
|
@@ -18907,21 +19417,21 @@ function inspectSystemOnnxRuntime(searchPathsOverride) {
|
|
|
18907
19417
|
searchPaths.push(...pathEntriesForPlatform2());
|
|
18908
19418
|
const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
|
|
18909
19419
|
const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
|
|
18910
|
-
searchPaths.push(
|
|
19420
|
+
searchPaths.push(join29(programFiles, "onnxruntime", "lib"), join29(programFiles, "Microsoft ONNX Runtime", "lib"), join29(programFiles, "Microsoft Machine Learning", "lib"), join29(programFilesX86, "onnxruntime", "lib"), ...(() => {
|
|
18911
19421
|
const nugetPaths = [];
|
|
18912
19422
|
const userProfile = process.env.USERPROFILE ?? "";
|
|
18913
19423
|
if (!userProfile)
|
|
18914
19424
|
return nugetPaths;
|
|
18915
|
-
const nugetPackageDir =
|
|
18916
|
-
if (!
|
|
19425
|
+
const nugetPackageDir = join29(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
|
|
19426
|
+
if (!existsSync26(nugetPackageDir))
|
|
18917
19427
|
return nugetPaths;
|
|
18918
19428
|
try {
|
|
18919
|
-
for (const entry of
|
|
19429
|
+
for (const entry of readdirSync12(nugetPackageDir, { withFileTypes: true })) {
|
|
18920
19430
|
if (!entry.isDirectory())
|
|
18921
19431
|
continue;
|
|
18922
19432
|
if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
|
|
18923
19433
|
continue;
|
|
18924
|
-
nugetPaths.push(
|
|
19434
|
+
nugetPaths.push(join29(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join29(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
|
|
18925
19435
|
}
|
|
18926
19436
|
} catch {}
|
|
18927
19437
|
return nugetPaths;
|
|
@@ -18940,7 +19450,7 @@ function inspectSystemOnnxRuntime(searchPathsOverride) {
|
|
|
18940
19450
|
if (!directoryContainsLibrary2(dir, libName))
|
|
18941
19451
|
continue;
|
|
18942
19452
|
if (process.platform !== "win32") {
|
|
18943
|
-
const probe = probeOnnxRuntimeLoadable(
|
|
19453
|
+
const probe = probeOnnxRuntimeLoadable(join29(dir, libName));
|
|
18944
19454
|
if (!probe.loadable) {
|
|
18945
19455
|
ignored ??= { path: dir, reason: `unloadable: ${probe.reason} — ignored` };
|
|
18946
19456
|
continue;
|
|
@@ -18960,12 +19470,12 @@ function inspectSystemOnnxRuntime(searchPathsOverride) {
|
|
|
18960
19470
|
return { path: unknownVersionPaths[0] ?? null, ignored };
|
|
18961
19471
|
}
|
|
18962
19472
|
function findCachedOnnxRuntime2(storageDir) {
|
|
18963
|
-
const ortDir =
|
|
19473
|
+
const ortDir = join29(storageDir, "onnxruntime", ONNX_RUNTIME_VERSION);
|
|
18964
19474
|
const libName = getOnnxLibraryName();
|
|
18965
|
-
if (
|
|
19475
|
+
if (existsSync26(join29(ortDir, libName)))
|
|
18966
19476
|
return ortDir;
|
|
18967
|
-
const libSubdir =
|
|
18968
|
-
if (
|
|
19477
|
+
const libSubdir = join29(ortDir, "lib");
|
|
19478
|
+
if (existsSync26(join29(libSubdir, libName)))
|
|
18969
19479
|
return libSubdir;
|
|
18970
19480
|
return null;
|
|
18971
19481
|
}
|
|
@@ -18986,16 +19496,16 @@ function parseOrtVersionFromDirectoryPath(value) {
|
|
|
18986
19496
|
return null;
|
|
18987
19497
|
}
|
|
18988
19498
|
function detectOrtVersion(libDir) {
|
|
18989
|
-
if (!
|
|
19499
|
+
if (!existsSync26(libDir))
|
|
18990
19500
|
return null;
|
|
18991
19501
|
const libName = getOnnxLibraryName();
|
|
18992
19502
|
try {
|
|
18993
|
-
const resolved = parseOrtVersionFromPath(realpathSync7(
|
|
19503
|
+
const resolved = parseOrtVersionFromPath(realpathSync7(join29(libDir, libName)));
|
|
18994
19504
|
if (resolved && resolved !== INVALID_ORT_VERSION2)
|
|
18995
19505
|
return resolved;
|
|
18996
19506
|
} catch {}
|
|
18997
19507
|
try {
|
|
18998
|
-
const entries =
|
|
19508
|
+
const entries = readdirSync12(libDir);
|
|
18999
19509
|
const barePrefix = libName.replace(/\.(so|dylib|dll)$/, "");
|
|
19000
19510
|
const expectedPrefix = process.platform === "win32" ? barePrefix.toLowerCase() : barePrefix;
|
|
19001
19511
|
for (const entry of entries) {
|
|
@@ -19006,8 +19516,8 @@ function detectOrtVersion(libDir) {
|
|
|
19006
19516
|
if (version)
|
|
19007
19517
|
return version;
|
|
19008
19518
|
}
|
|
19009
|
-
const base =
|
|
19010
|
-
if (
|
|
19519
|
+
const base = join29(libDir, libName);
|
|
19520
|
+
if (existsSync26(base)) {
|
|
19011
19521
|
try {
|
|
19012
19522
|
const real = realpathSync7(base);
|
|
19013
19523
|
const version = parseOrtVersionFromPath(real) ?? parseOrtVersionFromDirectoryPath(real);
|
|
@@ -19040,17 +19550,17 @@ var init_onnx = __esm(() => {
|
|
|
19040
19550
|
});
|
|
19041
19551
|
|
|
19042
19552
|
// src/lib/plugin-load.ts
|
|
19043
|
-
import { existsSync as
|
|
19553
|
+
import { existsSync as existsSync27, readFileSync as readFileSync16 } from "node:fs";
|
|
19044
19554
|
import { homedir as homedir18 } from "node:os";
|
|
19045
|
-
import { isAbsolute as isAbsolute9, join as
|
|
19555
|
+
import { isAbsolute as isAbsolute9, join as join30, normalize } from "node:path";
|
|
19046
19556
|
function isRecord3(value) {
|
|
19047
19557
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19048
19558
|
}
|
|
19049
19559
|
function readConfig(path) {
|
|
19050
|
-
if (!
|
|
19560
|
+
if (!existsSync27(path))
|
|
19051
19561
|
return { value: null, error: null };
|
|
19052
19562
|
try {
|
|
19053
|
-
const parsed = import_comment_json3.parse(
|
|
19563
|
+
const parsed = import_comment_json3.parse(readFileSync16(path, "utf8"));
|
|
19054
19564
|
const plain = JSON.parse(JSON.stringify(parsed));
|
|
19055
19565
|
return isRecord3(plain) ? { value: plain, error: null } : { value: null, error: "the file is not a JSON object" };
|
|
19056
19566
|
} catch (error) {
|
|
@@ -19106,7 +19616,7 @@ function evaluatePluginLoad(input) {
|
|
|
19106
19616
|
const raw = typeof subc?.connection_file === "string" ? subc.connection_file.trim() : "";
|
|
19107
19617
|
if (raw.length > 0) {
|
|
19108
19618
|
const resolved = resolveSubcConnectionPath(raw, input.home);
|
|
19109
|
-
if (!
|
|
19619
|
+
if (!existsSync27(resolved)) {
|
|
19110
19620
|
const toolCallError = formatConfigErrorMessage(formatSubcConnectionMissingMessage(raw, resolved));
|
|
19111
19621
|
blockers.push({
|
|
19112
19622
|
code: "subc_connection_missing",
|
|
@@ -19125,7 +19635,7 @@ function evaluatePluginLoad(input) {
|
|
|
19125
19635
|
const storage = loaded.user && isRecord3(loaded.user.storage) ? loaded.user.storage : null;
|
|
19126
19636
|
const requested = typeof storage?.cache_dir === "string" ? storage.cache_dir : "";
|
|
19127
19637
|
const home = input.home ?? homedir18();
|
|
19128
|
-
const expanded = requested === "~" ? home : requested.startsWith("~/") || requested.startsWith("~\\") ?
|
|
19638
|
+
const expanded = requested === "~" ? home : requested.startsWith("~/") || requested.startsWith("~\\") ? join30(home, requested.slice(2)) : requested;
|
|
19129
19639
|
return {
|
|
19130
19640
|
...isAbsolute9(expanded) ? { cacheDir: normalize(expanded) } : {},
|
|
19131
19641
|
blockers,
|
|
@@ -19145,15 +19655,16 @@ import {
|
|
|
19145
19655
|
accessSync as accessSync3,
|
|
19146
19656
|
closeSync as closeSync9,
|
|
19147
19657
|
constants as constants5,
|
|
19148
|
-
existsSync as
|
|
19658
|
+
existsSync as existsSync28,
|
|
19149
19659
|
openSync as openSync9,
|
|
19150
19660
|
readSync as readSync7,
|
|
19151
19661
|
statSync as statSync16
|
|
19152
19662
|
} from "node:fs";
|
|
19153
|
-
import { join as
|
|
19663
|
+
import { join as join31 } from "node:path";
|
|
19154
19664
|
async function collectDiagnostics(adapters) {
|
|
19155
19665
|
const cliVersion = getSelfVersion();
|
|
19156
|
-
const
|
|
19666
|
+
const binaryProbe = probeAftBinary(cliVersion);
|
|
19667
|
+
const binaryVersion = binaryProbe.version;
|
|
19157
19668
|
const harnesses = [];
|
|
19158
19669
|
for (const adapter of adapters) {
|
|
19159
19670
|
harnesses.push(await diagnoseHarness(adapter));
|
|
@@ -19165,6 +19676,7 @@ async function collectDiagnostics(adapters) {
|
|
|
19165
19676
|
nodeVersion: process.version,
|
|
19166
19677
|
cliVersion,
|
|
19167
19678
|
binaryVersion,
|
|
19679
|
+
binaryPath: binaryProbe.path,
|
|
19168
19680
|
harnesses,
|
|
19169
19681
|
binaryCache: getBinaryCacheInfo(cliVersion),
|
|
19170
19682
|
lspCache: getLspCacheReport(),
|
|
@@ -19185,7 +19697,7 @@ async function diagnoseHarness(adapter) {
|
|
|
19185
19697
|
const logPath = adapter.getLogFile();
|
|
19186
19698
|
const pluginCache = adapter.getPluginCacheInfo();
|
|
19187
19699
|
const storageAccessible = (() => {
|
|
19188
|
-
if (!
|
|
19700
|
+
if (!existsSync28(storage))
|
|
19189
19701
|
return false;
|
|
19190
19702
|
try {
|
|
19191
19703
|
accessSync3(storage, constants5.R_OK | constants5.W_OK);
|
|
@@ -19220,7 +19732,7 @@ async function diagnoseHarness(adapter) {
|
|
|
19220
19732
|
pluginRegistered: adapter.hasPluginEntry(),
|
|
19221
19733
|
configPaths,
|
|
19222
19734
|
aftConfig: {
|
|
19223
|
-
exists:
|
|
19735
|
+
exists: existsSync28(configPaths.aftConfig),
|
|
19224
19736
|
...aftConfigRead.error ? { parseError: aftConfigRead.error } : {},
|
|
19225
19737
|
enabled: aftEnabled,
|
|
19226
19738
|
...aftEnabledSource ? { enabledSource: aftEnabledSource } : {},
|
|
@@ -19229,10 +19741,10 @@ async function diagnoseHarness(adapter) {
|
|
|
19229
19741
|
pluginCache,
|
|
19230
19742
|
storageDir: {
|
|
19231
19743
|
path: storage,
|
|
19232
|
-
exists:
|
|
19744
|
+
exists: existsSync28(storage),
|
|
19233
19745
|
accessible: storageAccessible,
|
|
19234
19746
|
sizesByKey: describeStorage,
|
|
19235
|
-
...pluginLoad.cacheDir ? { cacheRoot:
|
|
19747
|
+
...pluginLoad.cacheDir ? { cacheRoot: join31(pluginLoad.cacheDir, "aft") } : {},
|
|
19236
19748
|
...legacyDuplication.totalPartitions > 0 ? { legacyDuplication } : {}
|
|
19237
19749
|
},
|
|
19238
19750
|
onnxRuntime: {
|
|
@@ -19252,8 +19764,8 @@ async function diagnoseHarness(adapter) {
|
|
|
19252
19764
|
},
|
|
19253
19765
|
logFile: {
|
|
19254
19766
|
path: logPath,
|
|
19255
|
-
exists:
|
|
19256
|
-
sizeKb:
|
|
19767
|
+
exists: existsSync28(logPath),
|
|
19768
|
+
sizeKb: existsSync28(logPath) ? Math.round(statSync16(logPath).size / 1024) : 0
|
|
19257
19769
|
},
|
|
19258
19770
|
pluginLoad
|
|
19259
19771
|
};
|
|
@@ -19262,7 +19774,7 @@ function renderDiagnosticsMarkdown(report) {
|
|
|
19262
19774
|
const lines = [];
|
|
19263
19775
|
lines.push(`- Timestamp: ${report.timestamp}`);
|
|
19264
19776
|
lines.push(`- AFT CLI: v${report.cliVersion}`);
|
|
19265
|
-
lines.push(`-
|
|
19777
|
+
lines.push(`- ${describeCliBinary(report.binaryVersion, report.binaryPath)}`);
|
|
19266
19778
|
lines.push(`- OS: ${report.platform} ${report.arch}`);
|
|
19267
19779
|
lines.push(`- Node: ${report.nodeVersion}`);
|
|
19268
19780
|
const issues = collectDiagnosticIssues(report);
|
|
@@ -19279,7 +19791,7 @@ function renderDiagnosticsMarkdown(report) {
|
|
|
19279
19791
|
lines.push(`- Host installed: ${h.hostInstalled}`);
|
|
19280
19792
|
lines.push(`- Host version: ${h.hostVersion ?? "unknown"}`);
|
|
19281
19793
|
lines.push(`- Plugin registered: ${h.pluginRegistered}`);
|
|
19282
|
-
lines.push(`- Plugin version: ${h.pluginCache
|
|
19794
|
+
lines.push(`- Plugin version: ${describePluginVersion(h.pluginCache)}`);
|
|
19283
19795
|
lines.push(`- AFT enabled: ${h.aftConfig.enabled}${h.aftConfig.enabledSource ? ` (from ${h.aftConfig.enabledSource})` : ""}`);
|
|
19284
19796
|
lines.push(`- AFT config parse error: ${h.aftConfig.parseError ?? "none"}`);
|
|
19285
19797
|
lines.push("");
|
|
@@ -19314,7 +19826,8 @@ function renderDiagnosticsMarkdown(report) {
|
|
|
19314
19826
|
lines.push("");
|
|
19315
19827
|
lines.push("### Binary cache");
|
|
19316
19828
|
lines.push("```json");
|
|
19317
|
-
|
|
19829
|
+
const { activeVersion, ...cacheInventory } = report.binaryCache;
|
|
19830
|
+
lines.push(JSON.stringify({ ...cacheInventory, [CLI_VERSION_CACHED_LABEL]: activeVersion }, null, 2));
|
|
19318
19831
|
lines.push("```");
|
|
19319
19832
|
lines.push("");
|
|
19320
19833
|
lines.push("### LSP cache");
|
|
@@ -19347,6 +19860,8 @@ function openCodeEntryToPin(harness, cliVersion) {
|
|
|
19347
19860
|
if (harness.kind !== "opencode")
|
|
19348
19861
|
return null;
|
|
19349
19862
|
const entry = harness.pluginCache.configuredEntry;
|
|
19863
|
+
if (preserveDoctorPluginEntry(normalizeVersion(cliVersion), entry, doctorInstalledVersion(harness.pluginCache)))
|
|
19864
|
+
return null;
|
|
19350
19865
|
return entry && entry !== pinnedPluginEntry(normalizeVersion(cliVersion)) ? entry : null;
|
|
19351
19866
|
}
|
|
19352
19867
|
function pluginVersionSkewRemediation(harness, cliVersion, older) {
|
|
@@ -19362,12 +19877,23 @@ function pluginVersionSkewRemediation(harness, cliVersion, older) {
|
|
|
19362
19877
|
return entry ? `Run \`${CLI} doctor --fix\` to pin the plugin entry to ${pinnedPluginEntry(version)} and ${change}.` : `Run \`${CLI} doctor --fix\` to ${change}.`;
|
|
19363
19878
|
}
|
|
19364
19879
|
function pluginVersionSkewIssue(harness, cliVersion) {
|
|
19880
|
+
if (harness.pluginCache.local)
|
|
19881
|
+
return null;
|
|
19882
|
+
if (harness.kind === "opencode" && preserveDoctorPluginEntry(normalizeVersion(cliVersion), harness.pluginCache.configuredEntry, doctorInstalledVersion(harness.pluginCache))) {
|
|
19883
|
+
return {
|
|
19884
|
+
code: "plugin_cli_version_skew",
|
|
19885
|
+
severity: "info",
|
|
19886
|
+
scope: harness.displayName,
|
|
19887
|
+
message: doctorNoDowngradeMessage(normalizeVersion(cliVersion), harness.pluginCache.configuredEntry, doctorInstalledVersion(harness.pluginCache)),
|
|
19888
|
+
remediation: ""
|
|
19889
|
+
};
|
|
19890
|
+
}
|
|
19365
19891
|
const pluginVersion = harness.pluginCache.cached;
|
|
19366
19892
|
if (!pluginVersion)
|
|
19367
19893
|
return null;
|
|
19368
19894
|
if (normalizeVersion(pluginVersion) === normalizeVersion(cliVersion))
|
|
19369
19895
|
return null;
|
|
19370
|
-
const older = compareLooseSemver(pluginVersion, cliVersion) < 0;
|
|
19896
|
+
const older = (compareSemver2(normalizeVersion(pluginVersion), normalizeVersion(cliVersion)) ?? compareLooseSemver(pluginVersion, cliVersion)) < 0;
|
|
19371
19897
|
const skew = older ? `Plugin version (${pluginVersion}) is older than CLI (${cliVersion}). New binary cache won't be used until you update the plugin.` : `Plugin version (${pluginVersion}) does not match CLI (${cliVersion}). New binary cache may not be used until the plugin and CLI match.`;
|
|
19372
19898
|
const entry = openCodeEntryToPin(harness, cliVersion);
|
|
19373
19899
|
return {
|
|
@@ -19484,7 +20010,7 @@ function formatDiagnosticIssuesSection(report) {
|
|
|
19484
20010
|
return lines;
|
|
19485
20011
|
}
|
|
19486
20012
|
function tailLogFile(path, lines) {
|
|
19487
|
-
if (!
|
|
20013
|
+
if (!existsSync28(path))
|
|
19488
20014
|
return "";
|
|
19489
20015
|
if (lines <= 0)
|
|
19490
20016
|
return "";
|
|
@@ -19529,6 +20055,7 @@ var init_diagnostics = __esm(async () => {
|
|
|
19529
20055
|
init_legacy_storage();
|
|
19530
20056
|
init_lsp_cache();
|
|
19531
20057
|
init_onnx();
|
|
20058
|
+
init_opencode_plugin_cache();
|
|
19532
20059
|
init_plugin_load();
|
|
19533
20060
|
init_sanitize();
|
|
19534
20061
|
init_self_version();
|
|
@@ -19684,14 +20211,14 @@ var init_issue_body = __esm(() => {
|
|
|
19684
20211
|
|
|
19685
20212
|
// src/lib/onnx-fix.ts
|
|
19686
20213
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
19687
|
-
import { existsSync as
|
|
19688
|
-
import { isAbsolute as isAbsolute10, join as
|
|
20214
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync7, renameSync as renameSync6, rmSync as rmSync7 } from "node:fs";
|
|
20215
|
+
import { isAbsolute as isAbsolute10, join as join32, relative as relative4 } from "node:path";
|
|
19689
20216
|
function findOnnxFixCandidates(report) {
|
|
19690
20217
|
const candidates = [];
|
|
19691
20218
|
for (const harness of report.harnesses) {
|
|
19692
20219
|
if (!harness.onnxRuntime.required)
|
|
19693
20220
|
continue;
|
|
19694
|
-
const storageOnnxDir =
|
|
20221
|
+
const storageOnnxDir = join32(harness.storageDir.path, "onnxruntime");
|
|
19695
20222
|
const systemTooOld = harness.onnxRuntime.systemPath !== null && harness.onnxRuntime.systemCompatible === false;
|
|
19696
20223
|
const cachedTooOld = harness.onnxRuntime.cachedPath !== null && harness.onnxRuntime.cachedCompatible === false;
|
|
19697
20224
|
const hasCompatibleCached = harness.onnxRuntime.cachedCompatible === true;
|
|
@@ -19700,7 +20227,7 @@ function findOnnxFixCandidates(report) {
|
|
|
19700
20227
|
harness,
|
|
19701
20228
|
reason: `cached ONNX Runtime at ${harness.onnxRuntime.cachedPath} is v${harness.onnxRuntime.cachedVersion}, but AFT requires ${harness.onnxRuntime.requirement}. AFT will stage and verify a managed replacement before removing it.`,
|
|
19702
20229
|
storageOnnxDir,
|
|
19703
|
-
storageOnnxBytes:
|
|
20230
|
+
storageOnnxBytes: existsSync29(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
|
|
19704
20231
|
});
|
|
19705
20232
|
continue;
|
|
19706
20233
|
}
|
|
@@ -19709,7 +20236,7 @@ function findOnnxFixCandidates(report) {
|
|
|
19709
20236
|
harness,
|
|
19710
20237
|
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 will leave the system copy untouched and download v1.24 into managed storage.`,
|
|
19711
20238
|
storageOnnxDir,
|
|
19712
|
-
storageOnnxBytes:
|
|
20239
|
+
storageOnnxBytes: existsSync29(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
|
|
19713
20240
|
});
|
|
19714
20241
|
continue;
|
|
19715
20242
|
}
|
|
@@ -19721,7 +20248,7 @@ function findOnnxFixCandidates(report) {
|
|
|
19721
20248
|
harness,
|
|
19722
20249
|
reason: `no compatible ONNX Runtime is installed.${ignoredCopy} AFT will download v1.24 into managed storage.`,
|
|
19723
20250
|
storageOnnxDir,
|
|
19724
|
-
storageOnnxBytes:
|
|
20251
|
+
storageOnnxBytes: existsSync29(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
|
|
19725
20252
|
});
|
|
19726
20253
|
}
|
|
19727
20254
|
}
|
|
@@ -19730,11 +20257,11 @@ function findOnnxFixCandidates(report) {
|
|
|
19730
20257
|
async function installManagedReplacement(candidate, ensureFn, rmFn) {
|
|
19731
20258
|
const suffix = `${process.pid}.${Date.now().toString(36)}.${randomBytes2(6).toString("hex")}`;
|
|
19732
20259
|
const stagingStorageDir = `${candidate.harness.storageDir.path}.onnx-fix.tmp.${suffix}`;
|
|
19733
|
-
const stagedOnnxDir =
|
|
20260
|
+
const stagedOnnxDir = join32(stagingStorageDir, "onnxruntime");
|
|
19734
20261
|
const backupDir = `${candidate.storageOnnxDir}.backup.${suffix}`;
|
|
19735
20262
|
try {
|
|
19736
20263
|
const stagedInstalledPath = await ensureFn(stagingStorageDir);
|
|
19737
|
-
if (!stagedInstalledPath || !
|
|
20264
|
+
if (!stagedInstalledPath || !existsSync29(stagedInstalledPath)) {
|
|
19738
20265
|
throw new Error("managed ONNX Runtime download was unavailable");
|
|
19739
20266
|
}
|
|
19740
20267
|
const installedRelativePath = relative4(stagedOnnxDir, stagedInstalledPath);
|
|
@@ -19742,7 +20269,7 @@ async function installManagedReplacement(candidate, ensureFn, rmFn) {
|
|
|
19742
20269
|
throw new Error(`managed ONNX Runtime was installed outside staging: ${stagedInstalledPath}`);
|
|
19743
20270
|
}
|
|
19744
20271
|
mkdirSync7(candidate.harness.storageDir.path, { recursive: true });
|
|
19745
|
-
const hadPrevious =
|
|
20272
|
+
const hadPrevious = existsSync29(candidate.storageOnnxDir);
|
|
19746
20273
|
if (hadPrevious)
|
|
19747
20274
|
renameSync6(candidate.storageOnnxDir, backupDir);
|
|
19748
20275
|
try {
|
|
@@ -19766,7 +20293,7 @@ async function installManagedReplacement(candidate, ensureFn, rmFn) {
|
|
|
19766
20293
|
}
|
|
19767
20294
|
}
|
|
19768
20295
|
return {
|
|
19769
|
-
installedPath:
|
|
20296
|
+
installedPath: join32(candidate.storageOnnxDir, installedRelativePath),
|
|
19770
20297
|
clearedPrevious: hadPrevious && cleanupError === undefined,
|
|
19771
20298
|
cleanupError
|
|
19772
20299
|
};
|
|
@@ -19915,10 +20442,10 @@ var init_session_log = __esm(() => {
|
|
|
19915
20442
|
});
|
|
19916
20443
|
|
|
19917
20444
|
// src/lib/sessions.ts
|
|
19918
|
-
import { existsSync as
|
|
20445
|
+
import { existsSync as existsSync30, readdirSync as readdirSync13, readFileSync as readFileSync17, statSync as statSync18 } from "node:fs";
|
|
19919
20446
|
import { createRequire as createRequire4 } from "node:module";
|
|
19920
20447
|
import { homedir as homedir19 } from "node:os";
|
|
19921
|
-
import { basename as basename3, join as
|
|
20448
|
+
import { basename as basename3, join as join33 } from "node:path";
|
|
19922
20449
|
function listRecentSessions(adapter) {
|
|
19923
20450
|
try {
|
|
19924
20451
|
if (adapter.kind === "opencode")
|
|
@@ -19952,8 +20479,8 @@ function mapOpenCodeSessionRows(rows) {
|
|
|
19952
20479
|
}).filter((session) => session !== null).sort((a, b) => b.lastActivity - a.lastActivity).slice(0, MAX_RECENT_SESSIONS);
|
|
19953
20480
|
}
|
|
19954
20481
|
function listRecentOpenCodeSessions() {
|
|
19955
|
-
const dbPath =
|
|
19956
|
-
if (!
|
|
20482
|
+
const dbPath = join33(getXdgDataHome(), "opencode", "opencode.db");
|
|
20483
|
+
if (!existsSync30(dbPath))
|
|
19957
20484
|
return [];
|
|
19958
20485
|
let db = null;
|
|
19959
20486
|
try {
|
|
@@ -19972,10 +20499,10 @@ function listRecentOpenCodeSessions() {
|
|
|
19972
20499
|
}
|
|
19973
20500
|
function getXdgDataHome() {
|
|
19974
20501
|
const xdgDataHome = process.env.XDG_DATA_HOME;
|
|
19975
|
-
return xdgDataHome && xdgDataHome.length > 0 ? xdgDataHome :
|
|
20502
|
+
return xdgDataHome && xdgDataHome.length > 0 ? xdgDataHome : join33(homedir19(), ".local", "share");
|
|
19976
20503
|
}
|
|
19977
20504
|
function listRecentPiSessions() {
|
|
19978
|
-
return listPiSessionsFromDir(
|
|
20505
|
+
return listPiSessionsFromDir(join33(getHomeDir(), ".pi", "agent", "sessions"));
|
|
19979
20506
|
}
|
|
19980
20507
|
function getHomeDir() {
|
|
19981
20508
|
const envHome = process.platform === "win32" ? process.env.USERPROFILE : process.env.HOME;
|
|
@@ -19983,7 +20510,7 @@ function getHomeDir() {
|
|
|
19983
20510
|
}
|
|
19984
20511
|
function listPiSessionsFromDir(sessionsDir) {
|
|
19985
20512
|
try {
|
|
19986
|
-
if (!
|
|
20513
|
+
if (!existsSync30(sessionsDir))
|
|
19987
20514
|
return [];
|
|
19988
20515
|
const files = collectJsonlFiles(sessionsDir).map((filePath) => {
|
|
19989
20516
|
try {
|
|
@@ -19995,7 +20522,7 @@ function listPiSessionsFromDir(sessionsDir) {
|
|
|
19995
20522
|
}).filter((entry) => entry !== null).sort((a, b) => b.mtimeMs - a.mtimeMs).slice(0, MAX_RECENT_SESSIONS * 4);
|
|
19996
20523
|
const sessions = [];
|
|
19997
20524
|
for (const file of files) {
|
|
19998
|
-
const parsed = parsePiSessionJsonl(
|
|
20525
|
+
const parsed = parsePiSessionJsonl(readFileSync17(file.filePath, "utf8"), basename3(file.filePath));
|
|
19999
20526
|
if (!parsed)
|
|
20000
20527
|
continue;
|
|
20001
20528
|
sessions.push({ ...parsed, lastActivity: file.mtimeMs });
|
|
@@ -20016,12 +20543,12 @@ function collectJsonlFiles(root) {
|
|
|
20016
20543
|
continue;
|
|
20017
20544
|
let entries;
|
|
20018
20545
|
try {
|
|
20019
|
-
entries =
|
|
20546
|
+
entries = readdirSync13(dir, { withFileTypes: true });
|
|
20020
20547
|
} catch {
|
|
20021
20548
|
continue;
|
|
20022
20549
|
}
|
|
20023
20550
|
for (const entry of entries) {
|
|
20024
|
-
const path =
|
|
20551
|
+
const path = join33(dir, entry.name);
|
|
20025
20552
|
if (entry.isDirectory()) {
|
|
20026
20553
|
stack.push(path);
|
|
20027
20554
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
@@ -20122,19 +20649,19 @@ var init_sessions = __esm(() => {
|
|
|
20122
20649
|
// src/commands/doctor.ts
|
|
20123
20650
|
import {
|
|
20124
20651
|
chmodSync as chmodSync4,
|
|
20125
|
-
existsSync as
|
|
20652
|
+
existsSync as existsSync31,
|
|
20126
20653
|
lstatSync as lstatSync5,
|
|
20127
20654
|
mkdirSync as mkdirSync8,
|
|
20128
20655
|
mkdtempSync as mkdtempSync2,
|
|
20129
|
-
readdirSync as
|
|
20130
|
-
readFileSync as
|
|
20656
|
+
readdirSync as readdirSync14,
|
|
20657
|
+
readFileSync as readFileSync18,
|
|
20131
20658
|
realpathSync as realpathSync8,
|
|
20132
20659
|
rmSync as rmSync8,
|
|
20133
20660
|
statSync as statSync19,
|
|
20134
20661
|
writeFileSync as writeFileSync5
|
|
20135
20662
|
} from "node:fs";
|
|
20136
20663
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
20137
|
-
import { dirname as
|
|
20664
|
+
import { dirname as dirname13, join as join34 } from "node:path";
|
|
20138
20665
|
function openCodeAdapter(adapters) {
|
|
20139
20666
|
return adapters.find((adapter) => adapter.kind === "opencode");
|
|
20140
20667
|
}
|
|
@@ -20157,7 +20684,7 @@ function refuseAmbiguousOpenCodeWrites(detection) {
|
|
|
20157
20684
|
function adapterConfigNeedsUpdate(adapter, tui = false) {
|
|
20158
20685
|
const method = tui ? "needsTuiPluginEntryUpdate" : "needsPluginEntryUpdate";
|
|
20159
20686
|
const candidate = adapter;
|
|
20160
|
-
return candidate[method]?.() ?? false;
|
|
20687
|
+
return candidate[method]?.({ doctor: true }) ?? false;
|
|
20161
20688
|
}
|
|
20162
20689
|
function buildDoctorProfileArgs(argv) {
|
|
20163
20690
|
const profileIndex = argv.indexOf("--profile");
|
|
@@ -20214,12 +20741,12 @@ async function runDoctor(options) {
|
|
|
20214
20741
|
configPath: opencodeHarness.configPaths.harnessConfig,
|
|
20215
20742
|
logPath: opencodeHarness.logFile.path,
|
|
20216
20743
|
pluginCachePath: opencodeHarness.pluginCache.path,
|
|
20217
|
-
cachedPluginVersion: opencodeHarness.pluginCache
|
|
20744
|
+
cachedPluginVersion: doctorInstalledVersion(opencodeHarness.pluginCache),
|
|
20218
20745
|
expectedPluginEntry: opencodeAdapter.pluginEntryWithVersion,
|
|
20219
20746
|
acceptExplicitPluginVersion: hostDetection.status === "v1"
|
|
20220
20747
|
}) : null;
|
|
20221
20748
|
const opencodeSkew = opencodeHarness ? pluginVersionSkewFor(report, opencodeHarness) : null;
|
|
20222
|
-
log2.info(`AFT CLI v${report.cliVersion},
|
|
20749
|
+
log2.info(`AFT CLI v${report.cliVersion}, ${describeCliBinary(report.binaryVersion, report.binaryPath)}`);
|
|
20223
20750
|
if (!report.binaryVersion) {
|
|
20224
20751
|
const hasEnabledRegisteredHarness = report.harnesses.some((h) => h.pluginRegistered && h.aftConfig.enabled);
|
|
20225
20752
|
const hasRegisteredHarness = report.harnesses.some((h) => h.pluginRegistered);
|
|
@@ -20235,7 +20762,7 @@ async function runDoctor(options) {
|
|
|
20235
20762
|
}
|
|
20236
20763
|
logUnmatchedBinaryCandidates(report.cliVersion);
|
|
20237
20764
|
}
|
|
20238
|
-
log2.info(`Binary cache: ${report.binaryCache.versions.length} version(s), ${formatBytes(report.binaryCache.totalSize)} at ${report.binaryCache.path}`);
|
|
20765
|
+
log2.info(`Binary cache: ${report.binaryCache.versions.length} version(s), ${formatBytes(report.binaryCache.totalSize)} at ${report.binaryCache.path}; ${CLI_VERSION_CACHED_LABEL}: ${report.binaryCache.activeVersion ?? "no"}`);
|
|
20239
20766
|
logBuildBreakerSuspensions(report);
|
|
20240
20767
|
const features = logFeatureStatus(options.argv, options.runNative, {
|
|
20241
20768
|
checkGh: options.checkGh ?? checkGhStatus,
|
|
@@ -20274,6 +20801,8 @@ async function runDoctor(options) {
|
|
|
20274
20801
|
}
|
|
20275
20802
|
if (opencodeSkew)
|
|
20276
20803
|
log2.error(` ${opencodeSkew.message} ${opencodeSkew.remediation}`);
|
|
20804
|
+
else if (opencodeDoctor?.versionNotice)
|
|
20805
|
+
log2.info(` ${opencodeDoctor.versionNotice}`);
|
|
20277
20806
|
for (const hostTool of OPENCODE_HOST_TOOL_NAMES) {
|
|
20278
20807
|
const line = hostToolDoctorLine(opencodeAdapter, hostTool);
|
|
20279
20808
|
if (line)
|
|
@@ -20286,7 +20815,7 @@ async function runDoctor(options) {
|
|
|
20286
20815
|
} else {
|
|
20287
20816
|
log2.info(` plugin registered: ${h.pluginRegistered ? "yes" : "no"}`);
|
|
20288
20817
|
}
|
|
20289
|
-
log2.info(` plugin version: ${h.
|
|
20818
|
+
log2.info(` plugin version: ${describePluginVersion(h.pluginCache)}`);
|
|
20290
20819
|
if (!h.aftConfig.enabled) {
|
|
20291
20820
|
log2.info(` AFT disabled by config${h.aftConfig.enabledSource ? ` (${h.aftConfig.enabledSource})` : ""}; plugin will stay inert`);
|
|
20292
20821
|
}
|
|
@@ -20545,7 +21074,7 @@ function clearOldBinaries(cliVersion = getSelfVersion(), plugins = getAllAdapter
|
|
|
20545
21074
|
errors: [],
|
|
20546
21075
|
keptVersion: keepTag
|
|
20547
21076
|
};
|
|
20548
|
-
if (!
|
|
21077
|
+
if (!existsSync31(info.path)) {
|
|
20549
21078
|
log2.info(`Binary cache: nothing to clear at ${info.path}`);
|
|
20550
21079
|
return result;
|
|
20551
21080
|
}
|
|
@@ -20576,7 +21105,7 @@ function clearOldBinaries(cliVersion = getSelfVersion(), plugins = getAllAdapter
|
|
|
20576
21105
|
return result;
|
|
20577
21106
|
}
|
|
20578
21107
|
for (const version of stale) {
|
|
20579
|
-
const dir =
|
|
21108
|
+
const dir = join34(info.path, version);
|
|
20580
21109
|
let bytes = 0;
|
|
20581
21110
|
try {
|
|
20582
21111
|
bytes = statSync19(dir).isDirectory() ? dirSize(dir) : 0;
|
|
@@ -20640,9 +21169,14 @@ function findPluginUpdateTargets(adapters, report) {
|
|
|
20640
21169
|
if (!harness.hostInstalled || !harness.pluginRegistered)
|
|
20641
21170
|
continue;
|
|
20642
21171
|
const cache = harness.pluginCache;
|
|
20643
|
-
if (
|
|
21172
|
+
if (cache.local)
|
|
21173
|
+
continue;
|
|
21174
|
+
const cliVersion = cache.cliVersion ?? cache.latest ?? report.cliVersion;
|
|
21175
|
+
if (!cache?.exists || !cache.cached)
|
|
20644
21176
|
continue;
|
|
20645
|
-
if (cache.
|
|
21177
|
+
if (preserveDoctorPluginEntry(cliVersion, cache.configuredEntry, doctorInstalledVersion(cache)))
|
|
21178
|
+
continue;
|
|
21179
|
+
if ((compareSemver2(cache.cached, cliVersion) ?? 0) >= 0)
|
|
20646
21180
|
continue;
|
|
20647
21181
|
const adapter = adaptersByKind.get(harness.kind);
|
|
20648
21182
|
if (!adapter)
|
|
@@ -20652,8 +21186,8 @@ function findPluginUpdateTargets(adapters, report) {
|
|
|
20652
21186
|
adapter,
|
|
20653
21187
|
installDir: cache.path,
|
|
20654
21188
|
cached: cache.cached,
|
|
20655
|
-
latest:
|
|
20656
|
-
oldPin: pin !== null && pin !==
|
|
21189
|
+
latest: cliVersion,
|
|
21190
|
+
oldPin: pin !== null && pin !== cliVersion ? pin : null
|
|
20657
21191
|
});
|
|
20658
21192
|
}
|
|
20659
21193
|
return targets;
|
|
@@ -20736,9 +21270,9 @@ async function runDoctorNpmInstall(npm, installDir) {
|
|
|
20736
21270
|
});
|
|
20737
21271
|
}
|
|
20738
21272
|
function installedPluginVersion(installDir) {
|
|
20739
|
-
const manifest =
|
|
21273
|
+
const manifest = join34(installDir, "node_modules", ...AFT_OPENCODE_PACKAGE.split("/"), "package.json");
|
|
20740
21274
|
try {
|
|
20741
|
-
const pkg = JSON.parse(
|
|
21275
|
+
const pkg = JSON.parse(readFileSync18(manifest, "utf-8"));
|
|
20742
21276
|
return typeof pkg.version === "string" ? pkg.version : null;
|
|
20743
21277
|
} catch {
|
|
20744
21278
|
return null;
|
|
@@ -20838,7 +21372,7 @@ function buildDoctorFixPlan(adapters, report) {
|
|
|
20838
21372
|
} else {
|
|
20839
21373
|
items.push({
|
|
20840
21374
|
kind: "plugin",
|
|
20841
|
-
message: `Will ${harness.pluginRegistered ? "update" : "add"} ${adapter.pluginEntryWithVersion} ${harness.pluginRegistered ? "in" : "to"} ${harness.configPaths.harnessConfig}`
|
|
21375
|
+
message: `Will ${harness.pluginRegistered ? "update" : "add"} ${adapter instanceof OpenCodeAdapter ? adapter.doctorPluginEntry() : adapter.pluginEntryWithVersion} ${harness.pluginRegistered ? "in" : "to"} ${harness.configPaths.harnessConfig}`
|
|
20842
21376
|
});
|
|
20843
21377
|
}
|
|
20844
21378
|
}
|
|
@@ -20855,7 +21389,7 @@ function buildDoctorFixPlan(adapters, report) {
|
|
|
20855
21389
|
continue;
|
|
20856
21390
|
items.push({
|
|
20857
21391
|
kind: "plugin",
|
|
20858
|
-
message: `Will ${hasTuiEntry ? "update" : "add"} ${adapter.pluginEntryWithVersion} ${hasTuiEntry ? "in" : "to"} ${harness.configPaths.tuiConfig} (TUI sidebar)`
|
|
21392
|
+
message: `Will ${hasTuiEntry ? "update" : "add"} ${adapter instanceof OpenCodeAdapter ? adapter.doctorPluginEntry(true) : adapter.pluginEntryWithVersion} ${hasTuiEntry ? "in" : "to"} ${harness.configPaths.tuiConfig} (TUI sidebar)`
|
|
20859
21393
|
});
|
|
20860
21394
|
}
|
|
20861
21395
|
for (const { adapter, hostTool } of hostToolFixTargets(adapters)) {
|
|
@@ -20994,6 +21528,12 @@ async function runFixFlow(argv, detectOpenCodeHost, resolveAdapters = resolveAda
|
|
|
20994
21528
|
}
|
|
20995
21529
|
log2.info("Running diagnostics to identify auto-fixable issues…");
|
|
20996
21530
|
const report = await collect(adapters);
|
|
21531
|
+
for (const harness of report.harnesses) {
|
|
21532
|
+
const cache = harness.pluginCache;
|
|
21533
|
+
if (harness.kind === "opencode" && preserveDoctorPluginEntry(report.cliVersion, cache.configuredEntry, doctorInstalledVersion(cache))) {
|
|
21534
|
+
log2.info(doctorNoDowngradeMessage(report.cliVersion, cache.configuredEntry, doctorInstalledVersion(cache)));
|
|
21535
|
+
}
|
|
21536
|
+
}
|
|
20997
21537
|
if (!report.binaryVersion) {
|
|
20998
21538
|
logUnmatchedBinaryCandidates(report.cliVersion);
|
|
20999
21539
|
}
|
|
@@ -21197,14 +21737,14 @@ function formatDoctorStorageStatus(h) {
|
|
|
21197
21737
|
let cacheWarning = "";
|
|
21198
21738
|
if (h.storageDir.cacheRoot) {
|
|
21199
21739
|
try {
|
|
21200
|
-
const parent = realpathSync8(
|
|
21740
|
+
const parent = realpathSync8(dirname13(h.storageDir.cacheRoot));
|
|
21201
21741
|
let durable = h.storageDir.path;
|
|
21202
|
-
while (!
|
|
21203
|
-
durable =
|
|
21742
|
+
while (!existsSync31(durable) && dirname13(durable) !== durable)
|
|
21743
|
+
durable = dirname13(durable);
|
|
21204
21744
|
let registered = false;
|
|
21205
|
-
const history =
|
|
21206
|
-
if (
|
|
21207
|
-
const saved = JSON.parse(
|
|
21745
|
+
const history = join34(h.storageDir.path, "retention/cache-parents.json");
|
|
21746
|
+
if (existsSync31(history)) {
|
|
21747
|
+
const saved = JSON.parse(readFileSync18(history, "utf8"));
|
|
21208
21748
|
registered = saved.parents?.some((entry) => entry.path === parent) === true;
|
|
21209
21749
|
}
|
|
21210
21750
|
if (!registered && statSync19(parent).dev === statSync19(durable).dev) {
|
|
@@ -21246,7 +21786,7 @@ function ensureStorageDirsForRegisteredPlugins(adapters) {
|
|
|
21246
21786
|
if (!adapter.isInstalled() || !adapter.hasPluginEntry())
|
|
21247
21787
|
continue;
|
|
21248
21788
|
storageDir = adapter.getStorageDir();
|
|
21249
|
-
if (
|
|
21789
|
+
if (existsSync31(storageDir))
|
|
21250
21790
|
continue;
|
|
21251
21791
|
mkdirSync8(storageDir, { recursive: true });
|
|
21252
21792
|
summary.created += 1;
|
|
@@ -21309,7 +21849,7 @@ async function maybeFixPlugin(adapter) {
|
|
|
21309
21849
|
return summary;
|
|
21310
21850
|
if (!adapter.hasPluginEntry() || adapterConfigNeedsUpdate(adapter)) {
|
|
21311
21851
|
log2.info(`${adapter.displayName}: attempting to register or update plugin config…`);
|
|
21312
|
-
const result = await adapter.ensurePluginEntry();
|
|
21852
|
+
const result = await adapter.ensurePluginEntry({ doctor: true });
|
|
21313
21853
|
if (result.ok) {
|
|
21314
21854
|
if (result.action === "added" || result.action === "updated")
|
|
21315
21855
|
summary.changed += 1;
|
|
@@ -21322,7 +21862,7 @@ async function maybeFixPlugin(adapter) {
|
|
|
21322
21862
|
if (adapter.ensureTuiPluginEntry && adapter.hasTuiPluginEntry && adapter.tuiPluginEntryApplies?.() !== false) {
|
|
21323
21863
|
const hasTuiEntry = adapter.hasTuiPluginEntry();
|
|
21324
21864
|
if (!hasTuiEntry || adapterConfigNeedsUpdate(adapter, true)) {
|
|
21325
|
-
const result = await adapter.ensureTuiPluginEntry();
|
|
21865
|
+
const result = await adapter.ensureTuiPluginEntry({ doctor: true });
|
|
21326
21866
|
if (result.ok && (result.action === "added" || result.action === "updated")) {
|
|
21327
21867
|
summary.changed += 1;
|
|
21328
21868
|
log2.success(`${adapter.displayName}: ${result.message}`);
|
|
@@ -21407,11 +21947,11 @@ function deriveIssueTitleFromBody(body) {
|
|
|
21407
21947
|
function writeIssueReviewFile(body) {
|
|
21408
21948
|
let reviewDir = null;
|
|
21409
21949
|
try {
|
|
21410
|
-
reviewDir = mkdtempSync2(
|
|
21950
|
+
reviewDir = mkdtempSync2(join34(tmpdir5(), "aft-issue-"));
|
|
21411
21951
|
if (process.platform !== "win32") {
|
|
21412
21952
|
chmodSync4(reviewDir, 448);
|
|
21413
21953
|
}
|
|
21414
|
-
const outPath =
|
|
21954
|
+
const outPath = join34(reviewDir, "issue.md");
|
|
21415
21955
|
writeFileSync5(outPath, `${body}
|
|
21416
21956
|
`, { encoding: "utf8", mode: 384, flag: "wx" });
|
|
21417
21957
|
return { path: outPath, realPath: realpathSync8(outPath) };
|
|
@@ -21432,7 +21972,7 @@ function readReviewedIssueFile(reviewFile) {
|
|
|
21432
21972
|
log2.error(`Review file path changed before filing; refusing to read ${reviewFile.path}.`);
|
|
21433
21973
|
return null;
|
|
21434
21974
|
}
|
|
21435
|
-
return
|
|
21975
|
+
return readFileSync18(reviewFile.path, "utf8");
|
|
21436
21976
|
} catch (err) {
|
|
21437
21977
|
log2.error(`Failed to read reviewed issue report: ${err instanceof Error ? err.message : String(err)}`);
|
|
21438
21978
|
return null;
|
|
@@ -21477,14 +22017,14 @@ function collectIssueLog(path, selectedSession) {
|
|
|
21477
22017
|
};
|
|
21478
22018
|
}
|
|
21479
22019
|
function collectIssueEngineLog(path, selectedSession) {
|
|
21480
|
-
const directory =
|
|
22020
|
+
const directory = dirname13(path);
|
|
21481
22021
|
const files = [];
|
|
21482
22022
|
try {
|
|
21483
|
-
for (const name of
|
|
22023
|
+
for (const name of readdirSync14(directory)) {
|
|
21484
22024
|
if (!/^aft-\d+\.log(?:\.1)?$/.test(name))
|
|
21485
22025
|
continue;
|
|
21486
22026
|
try {
|
|
21487
|
-
const candidate =
|
|
22027
|
+
const candidate = join34(directory, name);
|
|
21488
22028
|
const stat = lstatSync5(candidate);
|
|
21489
22029
|
if (stat.isFile())
|
|
21490
22030
|
files.push({ path: candidate, modified: stat.mtimeMs });
|
|
@@ -21519,6 +22059,13 @@ async function runIssueFlow(argv) {
|
|
|
21519
22059
|
const selectedSession = await promptForIssueSession(adapters[0]);
|
|
21520
22060
|
const selectedBareSessionId = selectedSession?.id.replace(/^ses_/, "") ?? null;
|
|
21521
22061
|
const report = await collectDiagnostics(adapters);
|
|
22062
|
+
const sanitizeContext = {
|
|
22063
|
+
projectRoots: [
|
|
22064
|
+
...adapters.flatMap((adapter) => projectRootsFromValue(readJsoncFile(adapter.detectConfigPaths().aftConfig).value)),
|
|
22065
|
+
...adapters.flatMap((adapter) => projectRootsFromValue(listRecentSessions(adapter))),
|
|
22066
|
+
...projectRootsFromValue(report)
|
|
22067
|
+
]
|
|
22068
|
+
};
|
|
21522
22069
|
const logResults = adapters.flatMap((adapter) => {
|
|
21523
22070
|
const path = adapter.getLogFile();
|
|
21524
22071
|
const { logText, errors, notice } = collectIssueLog(path, selectedSession);
|
|
@@ -21535,7 +22082,7 @@ ${logText || "<no log output>"}
|
|
|
21535
22082
|
errors
|
|
21536
22083
|
},
|
|
21537
22084
|
{
|
|
21538
|
-
section: `#### Engine logs (${
|
|
22085
|
+
section: `#### Engine logs (${dirname13(path)})
|
|
21539
22086
|
|
|
21540
22087
|
${engine.notice}
|
|
21541
22088
|
\`\`\`
|
|
@@ -21548,7 +22095,7 @@ ${engine.logText || "<no log output>"}
|
|
|
21548
22095
|
});
|
|
21549
22096
|
const logSections = logResults.map((result) => result.section).join(`
|
|
21550
22097
|
`);
|
|
21551
|
-
const recentErrorLines = extractRecentErrors(logResults.map((result) => sanitizeContent(result.errors)).join(`
|
|
22098
|
+
const recentErrorLines = extractRecentErrors(logResults.map((result) => sanitizeContent(result.errors, sanitizeContext)).join(`
|
|
21552
22099
|
`), 20);
|
|
21553
22100
|
const recentErrorsSection = recentErrorLines.length === 0 ? "_No error-shaped log lines found in recent history._" : ["```", recentErrorLines.join(`
|
|
21554
22101
|
`), "```"].join(`
|
|
@@ -21578,7 +22125,7 @@ ${engine.logText || "<no log output>"}
|
|
|
21578
22125
|
"_Usernames and home paths have been stripped from this report._"
|
|
21579
22126
|
].join(`
|
|
21580
22127
|
`);
|
|
21581
|
-
const body = capBodyToGithubLimit(sanitizeContent(rawBody));
|
|
22128
|
+
const body = capBodyToGithubLimit(sanitizeContent(rawBody, sanitizeContext));
|
|
21582
22129
|
const reviewFile = writeIssueReviewFile(body);
|
|
21583
22130
|
if (!reviewFile) {
|
|
21584
22131
|
outro("Done — could not write the issue report.");
|
|
@@ -21603,7 +22150,7 @@ https://github.com/cortexkit/aft/issues/new and paste the contents of ${outPath}
|
|
|
21603
22150
|
outro("Done.");
|
|
21604
22151
|
return 1;
|
|
21605
22152
|
}
|
|
21606
|
-
const finalBody = capBodyToGithubLimit(sanitizeContent(reviewedBody));
|
|
22153
|
+
const finalBody = capBodyToGithubLimit(sanitizeContent(reviewedBody, sanitizeContext));
|
|
21607
22154
|
const finalTitle = deriveIssueTitleFromBody(finalBody);
|
|
21608
22155
|
if (isGhInstalled()) {
|
|
21609
22156
|
log2.info("Opening GitHub issue via `gh`…");
|
|
@@ -21645,6 +22192,7 @@ var init_doctor = __esm(async () => {
|
|
|
21645
22192
|
init_jsonc();
|
|
21646
22193
|
init_lsp_cache();
|
|
21647
22194
|
init_onnx_fix();
|
|
22195
|
+
init_opencode_plugin_cache();
|
|
21648
22196
|
init_paths2();
|
|
21649
22197
|
init_prompts();
|
|
21650
22198
|
init_sanitize();
|
|
@@ -21677,24 +22225,24 @@ var init_doctor = __esm(async () => {
|
|
|
21677
22225
|
});
|
|
21678
22226
|
|
|
21679
22227
|
// src/commands/lsp.ts
|
|
21680
|
-
import { existsSync as
|
|
22228
|
+
import { existsSync as existsSync32, readdirSync as readdirSync15, statSync as statSync20 } from "node:fs";
|
|
21681
22229
|
import { createRequire as createRequire5 } from "node:module";
|
|
21682
|
-
import { dirname as
|
|
22230
|
+
import { dirname as dirname14, join as join35, resolve as resolve15 } from "node:path";
|
|
21683
22231
|
function findProjectRootForFile(filePath, fallbackCwd = process.cwd()) {
|
|
21684
22232
|
const resolvedFile = resolve15(fallbackCwd, filePath);
|
|
21685
|
-
let dir =
|
|
22233
|
+
let dir = dirname14(resolvedFile);
|
|
21686
22234
|
try {
|
|
21687
|
-
if (
|
|
22235
|
+
if (existsSync32(resolvedFile) && statSync20(resolvedFile).isDirectory()) {
|
|
21688
22236
|
dir = resolvedFile;
|
|
21689
22237
|
}
|
|
21690
22238
|
} catch {
|
|
21691
|
-
dir =
|
|
22239
|
+
dir = dirname14(resolvedFile);
|
|
21692
22240
|
}
|
|
21693
22241
|
while (true) {
|
|
21694
|
-
if (PROJECT_ROOT_MARKERS.some((marker) =>
|
|
22242
|
+
if (PROJECT_ROOT_MARKERS.some((marker) => existsSync32(join35(dir, marker)))) {
|
|
21695
22243
|
return dir;
|
|
21696
22244
|
}
|
|
21697
|
-
const parent =
|
|
22245
|
+
const parent = dirname14(dir);
|
|
21698
22246
|
if (parent === dir)
|
|
21699
22247
|
return resolve15(fallbackCwd);
|
|
21700
22248
|
dir = parent;
|
|
@@ -21840,18 +22388,18 @@ function buildConfigureParams(adapter, projectRoot) {
|
|
|
21840
22388
|
function inferLspPathsExtra(_lsp) {
|
|
21841
22389
|
const paths = new Set;
|
|
21842
22390
|
for (const entry of childDirs(getAftLspPackagesDir())) {
|
|
21843
|
-
paths.add(
|
|
22391
|
+
paths.add(join35(entry, "node_modules", ".bin"));
|
|
21844
22392
|
}
|
|
21845
22393
|
for (const entry of childDirs(getAftLspBinariesDir())) {
|
|
21846
|
-
paths.add(
|
|
22394
|
+
paths.add(join35(entry, "bin"));
|
|
21847
22395
|
}
|
|
21848
22396
|
return [...paths];
|
|
21849
22397
|
}
|
|
21850
22398
|
function childDirs(path) {
|
|
21851
|
-
if (!
|
|
22399
|
+
if (!existsSync32(path))
|
|
21852
22400
|
return [];
|
|
21853
22401
|
try {
|
|
21854
|
-
return
|
|
22402
|
+
return readdirSync15(path).map((entry) => join35(path, entry)).filter((entry) => {
|
|
21855
22403
|
try {
|
|
21856
22404
|
return statSync20(entry).isDirectory();
|
|
21857
22405
|
} catch {
|
|
@@ -21895,7 +22443,7 @@ function typescriptPackageWarning(response) {
|
|
|
21895
22443
|
if (!typescriptServerSpawned || !response.project_root || diagnosticsCount > 0)
|
|
21896
22444
|
return null;
|
|
21897
22445
|
try {
|
|
21898
|
-
createRequire5(
|
|
22446
|
+
createRequire5(join35(response.project_root, "package.json")).resolve("typescript");
|
|
21899
22447
|
return null;
|
|
21900
22448
|
} catch {
|
|
21901
22449
|
return "typescript package not resolvable from project — server will produce no diagnostics";
|
|
@@ -21935,7 +22483,7 @@ var init_lsp = __esm(async () => {
|
|
|
21935
22483
|
});
|
|
21936
22484
|
|
|
21937
22485
|
// src/commands/doctor-filters.ts
|
|
21938
|
-
import { existsSync as
|
|
22486
|
+
import { existsSync as existsSync33 } from "node:fs";
|
|
21939
22487
|
import { relative as relative5, resolve as resolve16 } from "node:path";
|
|
21940
22488
|
function printDoctorFiltersHelp() {
|
|
21941
22489
|
console.log(`Usage: ${CLI} doctor filters [--show <name>] [trust|untrust]`);
|
|
@@ -21977,7 +22525,7 @@ async function runDoctorFilters(options) {
|
|
|
21977
22525
|
log2.error(list.message ?? list.code ?? "list_filters failed");
|
|
21978
22526
|
return 1;
|
|
21979
22527
|
}
|
|
21980
|
-
list.project_dir_exists = list.project_dir ?
|
|
22528
|
+
list.project_dir_exists = list.project_dir ? existsSync33(list.project_dir) : false;
|
|
21981
22529
|
if (mode.kind === "list") {
|
|
21982
22530
|
console.log(renderFilterList(list, projectRoot));
|
|
21983
22531
|
return 0;
|
|
@@ -22191,7 +22739,7 @@ function printHelp() {
|
|
|
22191
22739
|
console.log(" setup --answers <file> Save feature choices from an answers file");
|
|
22192
22740
|
console.log(" index Build one configured index snapshot (no scheduler)");
|
|
22193
22741
|
console.log(" backups purge Remove undo backups by --path and/or --session (dry run unless --yes)");
|
|
22194
|
-
console.log(" cache prune-legacy Delete
|
|
22742
|
+
console.log(" cache prune-legacy Delete the index folders AFT used before 0.64 (dry run unless --yes)");
|
|
22195
22743
|
console.log(" doctor Check and fix configuration issues");
|
|
22196
22744
|
console.log(" doctor --profile [seconds] Profile a running AFT daemon");
|
|
22197
22745
|
console.log(" doctor lsp <file> Inspect LSP setup for one file");
|