@cortexkit/aft 0.45.1 → 0.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/lsp.d.ts +2 -0
- package/dist/commands/lsp.d.ts.map +1 -1
- package/dist/index.js +1935 -722
- package/dist/lib/bridge-tool-failures.d.ts.map +1 -1
- package/dist/lib/diagnostics.d.ts +4 -0
- package/dist/lib/diagnostics.d.ts.map +1 -1
- package/dist/lib/legacy-storage.d.ts +12 -0
- package/dist/lib/legacy-storage.d.ts.map +1 -0
- package/dist/lib/onnx-fix.d.ts +9 -17
- package/dist/lib/onnx-fix.d.ts.map +1 -1
- package/dist/lib/onnx.d.ts +1 -0
- package/dist/lib/onnx.d.ts.map +1 -1
- package/dist/lib/paths.d.ts +0 -2
- package/dist/lib/paths.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1895,6 +1895,21 @@ function isEmptyParam(value) {
|
|
|
1895
1895
|
return false;
|
|
1896
1896
|
}
|
|
1897
1897
|
|
|
1898
|
+
// ../aft-bridge/dist/config-keys.js
|
|
1899
|
+
function stripHarnessSpecificConfigKeys(value, keys) {
|
|
1900
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
1901
|
+
return value;
|
|
1902
|
+
const stripped = { ...value };
|
|
1903
|
+
for (const key of keys)
|
|
1904
|
+
delete stripped[key];
|
|
1905
|
+
return stripped;
|
|
1906
|
+
}
|
|
1907
|
+
var OPENCODE_ONLY_KEYS, PI_ONLY_KEYS;
|
|
1908
|
+
var init_config_keys = __esm(() => {
|
|
1909
|
+
OPENCODE_ONLY_KEYS = ["hoist_builtin_tools", "auto_update"];
|
|
1910
|
+
PI_ONLY_KEYS = [];
|
|
1911
|
+
});
|
|
1912
|
+
|
|
1898
1913
|
// ../aft-bridge/dist/config-tiers.js
|
|
1899
1914
|
import { existsSync, readFileSync as readFileSync2 } from "node:fs";
|
|
1900
1915
|
import { resolve as resolve2 } from "node:path";
|
|
@@ -2223,6 +2238,120 @@ var init_downloader = __esm(() => {
|
|
|
2223
2238
|
DOWNLOAD_LOCK_STALE_MS = 10 * 60000;
|
|
2224
2239
|
});
|
|
2225
2240
|
|
|
2241
|
+
// ../aft-bridge/dist/durable-log.js
|
|
2242
|
+
import { appendFile, mkdir, rename, rm, stat } from "node:fs/promises";
|
|
2243
|
+
import { homedir as homedir5 } from "node:os";
|
|
2244
|
+
import { dirname, join as join4 } from "node:path";
|
|
2245
|
+
function homeDir() {
|
|
2246
|
+
if (process.platform === "win32")
|
|
2247
|
+
return process.env.USERPROFILE || process.env.HOME || homedir5();
|
|
2248
|
+
return process.env.HOME || homedir5();
|
|
2249
|
+
}
|
|
2250
|
+
function dataHome() {
|
|
2251
|
+
if (process.env.XDG_DATA_HOME)
|
|
2252
|
+
return process.env.XDG_DATA_HOME;
|
|
2253
|
+
if (process.platform === "win32") {
|
|
2254
|
+
return process.env.LOCALAPPDATA || process.env.APPDATA || join4(homeDir(), "AppData", "Local");
|
|
2255
|
+
}
|
|
2256
|
+
return join4(homeDir(), ".local", "share");
|
|
2257
|
+
}
|
|
2258
|
+
function resolveAftStorageRoot(configuredRoot) {
|
|
2259
|
+
if (configuredRoot)
|
|
2260
|
+
return configuredRoot;
|
|
2261
|
+
if (process.env.AFT_CACHE_DIR)
|
|
2262
|
+
return join4(process.env.AFT_CACHE_DIR, "aft");
|
|
2263
|
+
return join4(dataHome(), "cortexkit", "aft");
|
|
2264
|
+
}
|
|
2265
|
+
function resolveAftLogPath(filename, configuredRoot) {
|
|
2266
|
+
return join4(resolveAftStorageRoot(configuredRoot), "logs", filename);
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
class RotatingLogSink {
|
|
2270
|
+
path;
|
|
2271
|
+
maxBytes;
|
|
2272
|
+
generations;
|
|
2273
|
+
estimatedBytes = null;
|
|
2274
|
+
queue = Promise.resolve();
|
|
2275
|
+
disabled = false;
|
|
2276
|
+
failureReported = false;
|
|
2277
|
+
constructor(path2, options = {}) {
|
|
2278
|
+
this.path = path2;
|
|
2279
|
+
this.maxBytes = options.maxBytes ?? DEFAULT_LOG_BYTES;
|
|
2280
|
+
this.generations = options.generations ?? DEFAULT_LOG_GENERATIONS;
|
|
2281
|
+
}
|
|
2282
|
+
append(data) {
|
|
2283
|
+
if (this.disabled || data.length === 0)
|
|
2284
|
+
return;
|
|
2285
|
+
this.queue = this.queue.then(() => this.write(data)).catch((error2) => {
|
|
2286
|
+
this.disabled = true;
|
|
2287
|
+
if (!this.failureReported) {
|
|
2288
|
+
this.failureReported = true;
|
|
2289
|
+
try {
|
|
2290
|
+
process.stderr.write(`[aft-plugin] durable log disabled for ${this.path}: ${error2 instanceof Error ? error2.message : String(error2)}
|
|
2291
|
+
`);
|
|
2292
|
+
} catch {}
|
|
2293
|
+
}
|
|
2294
|
+
});
|
|
2295
|
+
}
|
|
2296
|
+
async drain() {
|
|
2297
|
+
await this.queue;
|
|
2298
|
+
}
|
|
2299
|
+
async write(data) {
|
|
2300
|
+
await mkdir(dirname(this.path), { recursive: true });
|
|
2301
|
+
if (this.estimatedBytes === null) {
|
|
2302
|
+
try {
|
|
2303
|
+
this.estimatedBytes = (await stat(this.path)).size;
|
|
2304
|
+
} catch (error2) {
|
|
2305
|
+
if (!isMissing(error2))
|
|
2306
|
+
throw error2;
|
|
2307
|
+
this.estimatedBytes = 0;
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2310
|
+
const bytes = Buffer.byteLength(data);
|
|
2311
|
+
if (this.estimatedBytes > 0 && this.estimatedBytes + bytes > this.maxBytes) {
|
|
2312
|
+
await this.rotate();
|
|
2313
|
+
}
|
|
2314
|
+
await appendFile(this.path, data, "utf8");
|
|
2315
|
+
this.estimatedBytes = (this.estimatedBytes ?? 0) + bytes;
|
|
2316
|
+
}
|
|
2317
|
+
async rotate() {
|
|
2318
|
+
if (this.generations <= 0) {
|
|
2319
|
+
await removeIfPresent(this.path);
|
|
2320
|
+
this.estimatedBytes = 0;
|
|
2321
|
+
return;
|
|
2322
|
+
}
|
|
2323
|
+
await removeIfPresent(`${this.path}.${this.generations}`);
|
|
2324
|
+
for (let generation = this.generations - 1;generation >= 1; generation -= 1) {
|
|
2325
|
+
await renameIfPresent(`${this.path}.${generation}`, `${this.path}.${generation + 1}`);
|
|
2326
|
+
}
|
|
2327
|
+
await renameIfPresent(this.path, `${this.path}.1`);
|
|
2328
|
+
this.estimatedBytes = 0;
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
function isMissing(error2) {
|
|
2332
|
+
return typeof error2 === "object" && error2 !== null && "code" in error2 && error2.code === "ENOENT";
|
|
2333
|
+
}
|
|
2334
|
+
async function removeIfPresent(path2) {
|
|
2335
|
+
try {
|
|
2336
|
+
await rm(path2, { force: true });
|
|
2337
|
+
} catch (error2) {
|
|
2338
|
+
if (!isMissing(error2))
|
|
2339
|
+
throw error2;
|
|
2340
|
+
}
|
|
2341
|
+
}
|
|
2342
|
+
async function renameIfPresent(from, to) {
|
|
2343
|
+
try {
|
|
2344
|
+
await rename(from, to);
|
|
2345
|
+
} catch (error2) {
|
|
2346
|
+
if (!isMissing(error2))
|
|
2347
|
+
throw error2;
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
var DEFAULT_LOG_BYTES, DEFAULT_LOG_GENERATIONS = 5;
|
|
2351
|
+
var init_durable_log = __esm(() => {
|
|
2352
|
+
DEFAULT_LOG_BYTES = 20 * 1024 * 1024;
|
|
2353
|
+
});
|
|
2354
|
+
|
|
2226
2355
|
// ../aft-bridge/dist/edit-summary.js
|
|
2227
2356
|
function formatEditSummary(data) {
|
|
2228
2357
|
if (data.rolled_back === true) {
|
|
@@ -2308,27 +2437,27 @@ function stripJsoncSymbols(value) {
|
|
|
2308
2437
|
|
|
2309
2438
|
// ../aft-bridge/dist/paths.js
|
|
2310
2439
|
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync } from "node:fs";
|
|
2311
|
-
import { homedir as
|
|
2312
|
-
import { dirname, isAbsolute as isAbsolute2, join as
|
|
2313
|
-
function
|
|
2440
|
+
import { homedir as homedir6 } from "node:os";
|
|
2441
|
+
import { dirname as dirname2, isAbsolute as isAbsolute2, join as join5, resolve as resolve3 } from "node:path";
|
|
2442
|
+
function homeDir2() {
|
|
2314
2443
|
if (process.platform === "win32")
|
|
2315
|
-
return process.env.USERPROFILE || process.env.HOME ||
|
|
2316
|
-
return process.env.HOME ||
|
|
2444
|
+
return process.env.USERPROFILE || process.env.HOME || homedir6();
|
|
2445
|
+
return process.env.HOME || homedir6();
|
|
2317
2446
|
}
|
|
2318
2447
|
function configHome() {
|
|
2319
2448
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
2320
2449
|
if (xdg && isAbsolute2(xdg))
|
|
2321
2450
|
return xdg;
|
|
2322
|
-
return
|
|
2451
|
+
return join5(homeDir2(), ".config");
|
|
2323
2452
|
}
|
|
2324
2453
|
function legacyOpenCodeConfigDir() {
|
|
2325
2454
|
const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
2326
2455
|
if (envDir)
|
|
2327
2456
|
return resolve3(envDir);
|
|
2328
|
-
return
|
|
2457
|
+
return join5(configHome(), "opencode");
|
|
2329
2458
|
}
|
|
2330
2459
|
function legacyPiAgentDir() {
|
|
2331
|
-
return
|
|
2460
|
+
return join5(homeDir2(), ".pi", "agent");
|
|
2332
2461
|
}
|
|
2333
2462
|
function legacySources(basePath, label, harness) {
|
|
2334
2463
|
return [
|
|
@@ -2337,10 +2466,10 @@ function legacySources(basePath, label, harness) {
|
|
|
2337
2466
|
];
|
|
2338
2467
|
}
|
|
2339
2468
|
function resolveCortexKitUserConfigPath() {
|
|
2340
|
-
return
|
|
2469
|
+
return join5(configHome(), "cortexkit", "aft.jsonc");
|
|
2341
2470
|
}
|
|
2342
2471
|
function resolveCortexKitProjectConfigPath(projectDirectory) {
|
|
2343
|
-
return
|
|
2472
|
+
return join5(projectDirectory, ".cortexkit", "aft.jsonc");
|
|
2344
2473
|
}
|
|
2345
2474
|
function resolveCortexKitConfigPaths(projectDirectory) {
|
|
2346
2475
|
return {
|
|
@@ -2351,25 +2480,25 @@ function resolveCortexKitConfigPaths(projectDirectory) {
|
|
|
2351
2480
|
function resolveLegacyAftConfigSources(projectDirectory) {
|
|
2352
2481
|
return {
|
|
2353
2482
|
user: [
|
|
2354
|
-
...legacySources(
|
|
2355
|
-
...legacySources(
|
|
2483
|
+
...legacySources(join5(legacyOpenCodeConfigDir(), "aft"), "OpenCode user", "opencode"),
|
|
2484
|
+
...legacySources(join5(legacyPiAgentDir(), "aft"), "Pi user", "pi")
|
|
2356
2485
|
],
|
|
2357
2486
|
project: [
|
|
2358
|
-
...legacySources(
|
|
2359
|
-
...legacySources(
|
|
2487
|
+
...legacySources(join5(projectDirectory, ".opencode", "aft"), "OpenCode project", "opencode"),
|
|
2488
|
+
...legacySources(join5(projectDirectory, ".pi", "aft"), "Pi project", "pi")
|
|
2360
2489
|
]
|
|
2361
2490
|
};
|
|
2362
2491
|
}
|
|
2363
2492
|
function resolveHarnessStoragePath(storageRoot, harness, ...segments) {
|
|
2364
|
-
return
|
|
2493
|
+
return join5(storageRoot, harness, ...segments);
|
|
2365
2494
|
}
|
|
2366
2495
|
function repairRootScopedStorageFile(storageRoot, harness, fileName) {
|
|
2367
2496
|
const harnessPath = resolveHarnessStoragePath(storageRoot, harness, fileName);
|
|
2368
|
-
const rootPath =
|
|
2497
|
+
const rootPath = join5(storageRoot, fileName);
|
|
2369
2498
|
if (existsSync3(harnessPath) || !existsSync3(rootPath))
|
|
2370
2499
|
return harnessPath;
|
|
2371
2500
|
try {
|
|
2372
|
-
mkdirSync2(
|
|
2501
|
+
mkdirSync2(dirname2(harnessPath), { recursive: true });
|
|
2373
2502
|
renameSync2(rootPath, harnessPath);
|
|
2374
2503
|
} catch {}
|
|
2375
2504
|
return harnessPath;
|
|
@@ -2390,7 +2519,7 @@ function shouldShowAnnouncement(storageRoot, harness, currentVersion) {
|
|
|
2390
2519
|
return false;
|
|
2391
2520
|
if (!lastVersion) {
|
|
2392
2521
|
try {
|
|
2393
|
-
mkdirSync2(
|
|
2522
|
+
mkdirSync2(dirname2(versionFile), { recursive: true });
|
|
2394
2523
|
writeFileSync(versionFile, currentVersion);
|
|
2395
2524
|
} catch {}
|
|
2396
2525
|
return false;
|
|
@@ -2402,7 +2531,7 @@ function markAnnouncementSeen(storageRoot, harness, currentVersion) {
|
|
|
2402
2531
|
return;
|
|
2403
2532
|
const versionFile = repairRootScopedStorageFile(storageRoot, harness, "last_announced_version");
|
|
2404
2533
|
try {
|
|
2405
|
-
mkdirSync2(
|
|
2534
|
+
mkdirSync2(dirname2(versionFile), { recursive: true });
|
|
2406
2535
|
writeFileSync(versionFile, currentVersion);
|
|
2407
2536
|
} catch {}
|
|
2408
2537
|
}
|
|
@@ -2412,8 +2541,8 @@ var init_paths = () => {};
|
|
|
2412
2541
|
import { execSync } from "node:child_process";
|
|
2413
2542
|
import { chmodSync as chmodSync2, closeSync as closeSync2, copyFileSync as copyFileSync2, existsSync as existsSync4, mkdirSync as mkdirSync3, openSync as openSync2, readSync, renameSync as renameSync3, unlinkSync as unlinkSync2 } from "node:fs";
|
|
2414
2543
|
import { createRequire } from "node:module";
|
|
2415
|
-
import { homedir as
|
|
2416
|
-
import { join as
|
|
2544
|
+
import { homedir as homedir7 } from "node:os";
|
|
2545
|
+
import { join as join6 } from "node:path";
|
|
2417
2546
|
function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
2418
2547
|
try {
|
|
2419
2548
|
const version = knownVersion ?? readBinaryVersion(npmBinaryPath);
|
|
@@ -2421,9 +2550,9 @@ function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
|
2421
2550
|
return null;
|
|
2422
2551
|
const tag = version.startsWith("v") ? version : `v${version}`;
|
|
2423
2552
|
const cacheDir = getCacheDir();
|
|
2424
|
-
const versionedDir =
|
|
2553
|
+
const versionedDir = join6(cacheDir, tag);
|
|
2425
2554
|
const ext = process.platform === "win32" ? ".exe" : "";
|
|
2426
|
-
const cachedPath =
|
|
2555
|
+
const cachedPath = join6(versionedDir, `aft${ext}`);
|
|
2427
2556
|
if (existsSync4(cachedPath)) {
|
|
2428
2557
|
const cachedVersion = readBinaryVersion(cachedPath);
|
|
2429
2558
|
if (cachedVersion === version)
|
|
@@ -2453,18 +2582,18 @@ function normalizeBareVersion(version) {
|
|
|
2453
2582
|
return version.startsWith("v") ? version.slice(1) : version;
|
|
2454
2583
|
}
|
|
2455
2584
|
function homeDirFromEnv(env) {
|
|
2456
|
-
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) ||
|
|
2585
|
+
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir7();
|
|
2457
2586
|
}
|
|
2458
2587
|
function cacheDirFromEnv(env) {
|
|
2459
2588
|
if (process.platform === "win32") {
|
|
2460
|
-
const base2 = env.LOCALAPPDATA || env.APPDATA ||
|
|
2461
|
-
return
|
|
2589
|
+
const base2 = env.LOCALAPPDATA || env.APPDATA || join6(homeDirFromEnv(env), "AppData", "Local");
|
|
2590
|
+
return join6(base2, "aft", "bin");
|
|
2462
2591
|
}
|
|
2463
|
-
const base = env.XDG_CACHE_HOME ||
|
|
2464
|
-
return
|
|
2592
|
+
const base = env.XDG_CACHE_HOME || join6(homeDirFromEnv(env), ".cache");
|
|
2593
|
+
return join6(base, "aft", "bin");
|
|
2465
2594
|
}
|
|
2466
2595
|
function cachedBinaryPathFromEnv(version, env, ext) {
|
|
2467
|
-
const binaryPath =
|
|
2596
|
+
const binaryPath = join6(cacheDirFromEnv(env), version, `aft${ext}`);
|
|
2468
2597
|
return existsSync4(binaryPath) ? binaryPath : null;
|
|
2469
2598
|
}
|
|
2470
2599
|
function isExpectedCachedBinary2(binaryPath, expectedVersion) {
|
|
@@ -2583,7 +2712,7 @@ function findBinarySync(expectedVersion) {
|
|
|
2583
2712
|
return usable;
|
|
2584
2713
|
}
|
|
2585
2714
|
} catch {}
|
|
2586
|
-
const cargoPath =
|
|
2715
|
+
const cargoPath = join6(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
|
|
2587
2716
|
if (existsSync4(cargoPath)) {
|
|
2588
2717
|
const usable = probeBinaryCandidate(cargoPath, "cargo", expectedVersion);
|
|
2589
2718
|
if (usable)
|
|
@@ -2631,28 +2760,28 @@ var init_resolver = __esm(() => {
|
|
|
2631
2760
|
// ../aft-bridge/dist/migration.js
|
|
2632
2761
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
2633
2762
|
import { closeSync as closeSync3, existsSync as existsSync5, mkdirSync as mkdirSync4, openSync as openSync3, readFileSync as readFileSync5, renameSync as renameSync4, rmSync as rmSync2, statSync as statSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "node:fs";
|
|
2634
|
-
import { homedir as
|
|
2635
|
-
import { basename, dirname as
|
|
2636
|
-
function
|
|
2763
|
+
import { homedir as homedir8, tmpdir } from "node:os";
|
|
2764
|
+
import { basename, dirname as dirname3, join as join7, resolve as resolve4 } from "node:path";
|
|
2765
|
+
function dataHome2() {
|
|
2637
2766
|
if (process.env.XDG_DATA_HOME)
|
|
2638
2767
|
return process.env.XDG_DATA_HOME;
|
|
2639
2768
|
if (process.platform === "win32") {
|
|
2640
|
-
return process.env.LOCALAPPDATA || process.env.APPDATA ||
|
|
2769
|
+
return process.env.LOCALAPPDATA || process.env.APPDATA || join7(homeDir3(), "AppData", "Local");
|
|
2641
2770
|
}
|
|
2642
|
-
return
|
|
2771
|
+
return join7(homeDir3(), ".local", "share");
|
|
2643
2772
|
}
|
|
2644
|
-
function
|
|
2773
|
+
function homeDir3() {
|
|
2645
2774
|
if (process.platform === "win32")
|
|
2646
|
-
return process.env.USERPROFILE || process.env.HOME ||
|
|
2647
|
-
return process.env.HOME ||
|
|
2775
|
+
return process.env.USERPROFILE || process.env.HOME || homedir8();
|
|
2776
|
+
return process.env.HOME || homedir8();
|
|
2648
2777
|
}
|
|
2649
2778
|
function resolveLegacyStorageRoot(harness) {
|
|
2650
2779
|
if (harness === "pi")
|
|
2651
|
-
return
|
|
2652
|
-
return
|
|
2780
|
+
return join7(homeDir3(), ".pi", "agent", "aft");
|
|
2781
|
+
return join7(dataHome2(), "opencode", "storage", "plugin", "aft");
|
|
2653
2782
|
}
|
|
2654
2783
|
function resolveCortexKitStorageRoot() {
|
|
2655
|
-
return
|
|
2784
|
+
return join7(dataHome2(), "cortexkit", "aft");
|
|
2656
2785
|
}
|
|
2657
2786
|
function stripJsoncForParse(input) {
|
|
2658
2787
|
let out = "";
|
|
@@ -2781,8 +2910,8 @@ function acquireConfigMigrationLock(lockDir) {
|
|
|
2781
2910
|
}
|
|
2782
2911
|
}
|
|
2783
2912
|
function atomicCopyConfigFile(sourcePath, targetPath) {
|
|
2784
|
-
mkdirSync4(
|
|
2785
|
-
const tmpPath =
|
|
2913
|
+
mkdirSync4(dirname3(targetPath), { recursive: true });
|
|
2914
|
+
const tmpPath = join7(dirname3(targetPath), `.${basename(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
|
|
2786
2915
|
let fd = null;
|
|
2787
2916
|
try {
|
|
2788
2917
|
fd = openSync3(tmpPath, "wx", 384);
|
|
@@ -2803,8 +2932,8 @@ function atomicCopyConfigFile(sourcePath, targetPath) {
|
|
|
2803
2932
|
}
|
|
2804
2933
|
}
|
|
2805
2934
|
function atomicWriteConfigFile(targetPath, content) {
|
|
2806
|
-
mkdirSync4(
|
|
2807
|
-
const tmpPath =
|
|
2935
|
+
mkdirSync4(dirname3(targetPath), { recursive: true });
|
|
2936
|
+
const tmpPath = join7(dirname3(targetPath), `.${basename(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
|
|
2808
2937
|
let fd = null;
|
|
2809
2938
|
try {
|
|
2810
2939
|
fd = openSync3(tmpPath, "wx", 384);
|
|
@@ -2927,7 +3056,7 @@ function migrateAftConfigFile(opts) {
|
|
|
2927
3056
|
if (existingSources.length === 0) {
|
|
2928
3057
|
return { migrated: false, conflict: false, targetPath: opts.targetPath, warnings };
|
|
2929
3058
|
}
|
|
2930
|
-
mkdirSync4(
|
|
3059
|
+
mkdirSync4(dirname3(opts.targetPath), { recursive: true });
|
|
2931
3060
|
const release = acquireConfigMigrationLock(`${opts.targetPath}.lock`);
|
|
2932
3061
|
try {
|
|
2933
3062
|
const sources = existingSources.map((source) => ({
|
|
@@ -2984,13 +3113,13 @@ function spawnErrorLabel(error2) {
|
|
|
2984
3113
|
return [code, error2.message].filter(Boolean).join(": ");
|
|
2985
3114
|
}
|
|
2986
3115
|
function migrationLogPath(newRoot, harness, logger) {
|
|
2987
|
-
const desired =
|
|
3116
|
+
const desired = join7(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
|
|
2988
3117
|
try {
|
|
2989
|
-
mkdirSync4(
|
|
3118
|
+
mkdirSync4(dirname3(desired), { recursive: true });
|
|
2990
3119
|
return desired;
|
|
2991
3120
|
} catch (err) {
|
|
2992
|
-
const fallback =
|
|
2993
|
-
logger?.warn?.(`Failed to create AFT migration log directory ${
|
|
3121
|
+
const fallback = join7(tmpdir(), `aft-migration-${harness}-${Date.now()}.jsonl`);
|
|
3122
|
+
logger?.warn?.(`Failed to create AFT migration log directory ${dirname3(desired)}: ${err instanceof Error ? err.message : String(err)}. ` + `Using fallback log path ${fallback}.`);
|
|
2994
3123
|
return fallback;
|
|
2995
3124
|
}
|
|
2996
3125
|
}
|
|
@@ -3091,13 +3220,13 @@ var init_migration = __esm(() => {
|
|
|
3091
3220
|
// ../aft-bridge/dist/npm-resolver.js
|
|
3092
3221
|
import { execFileSync } from "node:child_process";
|
|
3093
3222
|
import { readdirSync, statSync as statSync3 } from "node:fs";
|
|
3094
|
-
import { homedir as
|
|
3095
|
-
import { delimiter, dirname as
|
|
3223
|
+
import { homedir as homedir9 } from "node:os";
|
|
3224
|
+
import { delimiter, dirname as dirname4, isAbsolute as isAbsolute3, join as join8 } from "node:path";
|
|
3096
3225
|
function defaultDeps() {
|
|
3097
3226
|
return {
|
|
3098
3227
|
platform: process.platform,
|
|
3099
3228
|
env: process.env,
|
|
3100
|
-
home:
|
|
3229
|
+
home: homedir9(),
|
|
3101
3230
|
execPath: process.execPath
|
|
3102
3231
|
};
|
|
3103
3232
|
}
|
|
@@ -3118,14 +3247,14 @@ function npmFromPath(deps) {
|
|
|
3118
3247
|
const dir = entry.trim().replace(/^"|"$/g, "");
|
|
3119
3248
|
if (!dir || !isAbsolute3(dir))
|
|
3120
3249
|
continue;
|
|
3121
|
-
if (isFile(
|
|
3250
|
+
if (isFile(join8(dir, name)))
|
|
3122
3251
|
return dir;
|
|
3123
3252
|
}
|
|
3124
3253
|
return null;
|
|
3125
3254
|
}
|
|
3126
3255
|
function npmAdjacentToNode(deps) {
|
|
3127
|
-
const dir =
|
|
3128
|
-
return isFile(
|
|
3256
|
+
const dir = dirname4(deps.execPath);
|
|
3257
|
+
return isFile(join8(dir, npmBinaryName(deps.platform))) ? dir : null;
|
|
3129
3258
|
}
|
|
3130
3259
|
function highestVersionedNodeBin(installsDir, name) {
|
|
3131
3260
|
let entries;
|
|
@@ -3134,8 +3263,8 @@ function highestVersionedNodeBin(installsDir, name) {
|
|
|
3134
3263
|
} catch {
|
|
3135
3264
|
return null;
|
|
3136
3265
|
}
|
|
3137
|
-
const candidates = entries.filter((v) => isFile(
|
|
3138
|
-
return candidates.length > 0 ?
|
|
3266
|
+
const candidates = entries.filter((v) => isFile(join8(installsDir, v, "bin", name))).sort((a, b) => compareVersionsDesc(a, b));
|
|
3267
|
+
return candidates.length > 0 ? join8(installsDir, candidates[0], "bin") : null;
|
|
3139
3268
|
}
|
|
3140
3269
|
function compareVersionsDesc(a, b) {
|
|
3141
3270
|
const pa = a.replace(/^v/, "").split(".").map((n) => Number.parseInt(n, 10));
|
|
@@ -3160,22 +3289,22 @@ function wellKnownNpmDirs(deps) {
|
|
|
3160
3289
|
const programFiles = env.ProgramFiles || "C:\\Program Files";
|
|
3161
3290
|
const appData = env.APPDATA;
|
|
3162
3291
|
const localAppData = env.LOCALAPPDATA;
|
|
3163
|
-
push(
|
|
3292
|
+
push(join8(programFiles, "nodejs"));
|
|
3164
3293
|
if (appData)
|
|
3165
|
-
push(
|
|
3294
|
+
push(join8(appData, "npm"));
|
|
3166
3295
|
if (localAppData)
|
|
3167
|
-
push(
|
|
3296
|
+
push(join8(localAppData, "Volta", "bin"));
|
|
3168
3297
|
if (env.NVM_SYMLINK)
|
|
3169
3298
|
push(env.NVM_SYMLINK);
|
|
3170
3299
|
} else {
|
|
3171
3300
|
if (env.NVM_BIN)
|
|
3172
3301
|
push(env.NVM_BIN);
|
|
3173
|
-
push(highestVersionedNodeBin(
|
|
3174
|
-
push(highestVersionedNodeBin(
|
|
3175
|
-
push(highestVersionedNodeBin(
|
|
3176
|
-
push(
|
|
3177
|
-
push(
|
|
3178
|
-
const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin",
|
|
3302
|
+
push(highestVersionedNodeBin(join8(home, ".nvm", "versions", "node"), name));
|
|
3303
|
+
push(highestVersionedNodeBin(join8(home, ".local", "share", "mise", "installs", "node"), name));
|
|
3304
|
+
push(highestVersionedNodeBin(join8(home, ".asdf", "installs", "nodejs"), name));
|
|
3305
|
+
push(join8(home, ".volta", "bin"));
|
|
3306
|
+
push(join8(home, ".asdf", "shims"));
|
|
3307
|
+
const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin", join8(home, ".local", "bin")]);
|
|
3179
3308
|
for (const dir of systemDirs)
|
|
3180
3309
|
push(dir);
|
|
3181
3310
|
}
|
|
@@ -3185,12 +3314,12 @@ function resolveNpm(deps = defaultDeps()) {
|
|
|
3185
3314
|
const name = npmBinaryName(deps.platform);
|
|
3186
3315
|
const onPath = npmFromPath(deps);
|
|
3187
3316
|
if (onPath)
|
|
3188
|
-
return { command:
|
|
3317
|
+
return { command: join8(onPath, name), binDir: onPath };
|
|
3189
3318
|
const adjacent = npmAdjacentToNode(deps);
|
|
3190
3319
|
if (adjacent)
|
|
3191
|
-
return { command:
|
|
3320
|
+
return { command: join8(adjacent, name), binDir: adjacent };
|
|
3192
3321
|
for (const dir of wellKnownNpmDirs(deps)) {
|
|
3193
|
-
const candidate =
|
|
3322
|
+
const candidate = join8(dir, name);
|
|
3194
3323
|
if (isFile(candidate))
|
|
3195
3324
|
return { command: candidate, binDir: dir };
|
|
3196
3325
|
}
|
|
@@ -3226,7 +3355,7 @@ var init_npm_resolver = () => {};
|
|
|
3226
3355
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
3227
3356
|
import { createHash as createHash3 } from "node:crypto";
|
|
3228
3357
|
import { chmodSync as chmodSync3, closeSync as closeSync4, copyFileSync as copyFileSync3, createWriteStream as createWriteStream2, existsSync as existsSync6, lstatSync, mkdirSync as mkdirSync5, openSync as openSync4, readdirSync as readdirSync2, readFileSync as readFileSync6, readlinkSync, realpathSync, rmSync as rmSync3, statSync as statSync4, symlinkSync, unlinkSync as unlinkSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
3229
|
-
import { basename as basename2, dirname as
|
|
3358
|
+
import { basename as basename2, dirname as dirname5, isAbsolute as isAbsolute4, join as join9, relative as relative2, resolve as resolve5, win32 } from "node:path";
|
|
3230
3359
|
import { Readable as Readable2 } from "node:stream";
|
|
3231
3360
|
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
3232
3361
|
function getPlatformInfo() {
|
|
@@ -3252,10 +3381,10 @@ function getManualInstallHint() {
|
|
|
3252
3381
|
}
|
|
3253
3382
|
async function ensureOnnxRuntime(storageDir) {
|
|
3254
3383
|
const info = getPlatformInfo();
|
|
3255
|
-
const ortVersionDir =
|
|
3384
|
+
const ortVersionDir = join9(storageDir, "onnxruntime", ORT_VERSION);
|
|
3256
3385
|
const libName = info?.libName ?? "libonnxruntime.dylib";
|
|
3257
3386
|
const resolvedOrtDir = resolveCachedOnnxRuntimeDir(ortVersionDir, libName);
|
|
3258
|
-
const libPath =
|
|
3387
|
+
const libPath = join9(resolvedOrtDir, libName);
|
|
3259
3388
|
if (existsSync6(libPath)) {
|
|
3260
3389
|
const meta = readOnnxInstalledMeta(ortVersionDir);
|
|
3261
3390
|
if (meta?.sha256) {
|
|
@@ -3285,9 +3414,9 @@ async function ensureOnnxRuntime(storageDir) {
|
|
|
3285
3414
|
warn(`ONNX Runtime auto-download not available for ${process.platform}/${process.arch}. Install manually: ${getManualInstallHint()}`);
|
|
3286
3415
|
return null;
|
|
3287
3416
|
}
|
|
3288
|
-
const onnxBaseDir =
|
|
3417
|
+
const onnxBaseDir = join9(storageDir, "onnxruntime");
|
|
3289
3418
|
mkdirSync5(onnxBaseDir, { recursive: true });
|
|
3290
|
-
const lockPath =
|
|
3419
|
+
const lockPath = join9(onnxBaseDir, ONNX_LOCK_FILE);
|
|
3291
3420
|
cleanupAbandonedStagingDirs(onnxBaseDir);
|
|
3292
3421
|
if (!acquireLock(lockPath)) {
|
|
3293
3422
|
warn(`ONNX Runtime install already in progress in another process (lock: ${lockPath}). Skipping.`);
|
|
@@ -3306,7 +3435,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
3306
3435
|
for (const entry of entries) {
|
|
3307
3436
|
if (!entry.startsWith(`${ORT_VERSION}.tmp.`))
|
|
3308
3437
|
continue;
|
|
3309
|
-
const stagingDir =
|
|
3438
|
+
const stagingDir = join9(onnxBaseDir, entry);
|
|
3310
3439
|
const parts = entry.split(".");
|
|
3311
3440
|
const pidStr = parts[parts.length - 2];
|
|
3312
3441
|
const pid = pidStr ? Number.parseInt(pidStr, 10) : NaN;
|
|
@@ -3343,7 +3472,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
3343
3472
|
}
|
|
3344
3473
|
function cleanupIncompleteTargetIfUnowned(ortDir) {
|
|
3345
3474
|
try {
|
|
3346
|
-
if (existsSync6(ortDir) && !existsSync6(
|
|
3475
|
+
if (existsSync6(ortDir) && !existsSync6(join9(ortDir, ONNX_INSTALLED_META_FILE))) {
|
|
3347
3476
|
log(`[onnx] removing half-populated install dir ${ortDir} (no meta file)`);
|
|
3348
3477
|
rmSync3(ortDir, { recursive: true, force: true });
|
|
3349
3478
|
}
|
|
@@ -3388,7 +3517,7 @@ function detectOnnxVersion(libDir, libName) {
|
|
|
3388
3517
|
if (version)
|
|
3389
3518
|
return version;
|
|
3390
3519
|
}
|
|
3391
|
-
const base =
|
|
3520
|
+
const base = join9(libDir, libName);
|
|
3392
3521
|
if (existsSync6(base)) {
|
|
3393
3522
|
try {
|
|
3394
3523
|
const real = realpathSync(base);
|
|
@@ -3427,6 +3556,17 @@ function pathEntriesForPlatform() {
|
|
|
3427
3556
|
return isAbsolute4(entry) || win32.isAbsolute(entry);
|
|
3428
3557
|
});
|
|
3429
3558
|
}
|
|
3559
|
+
function isWindowsSystem32Directory(dir) {
|
|
3560
|
+
if (process.platform !== "win32")
|
|
3561
|
+
return false;
|
|
3562
|
+
const normalizedDir = win32.resolve(dir).replace(/[\\/]+$/, "").toLowerCase();
|
|
3563
|
+
const windowsRoots = [process.env.SystemRoot, process.env.windir, "C:\\Windows"];
|
|
3564
|
+
return windowsRoots.some((root) => {
|
|
3565
|
+
if (!root)
|
|
3566
|
+
return false;
|
|
3567
|
+
return normalizedDir === win32.resolve(root, "System32").replace(/[\\/]+$/, "").toLowerCase();
|
|
3568
|
+
});
|
|
3569
|
+
}
|
|
3430
3570
|
function directoryContainsLibrary(dir, libName) {
|
|
3431
3571
|
try {
|
|
3432
3572
|
const entries = readdirSync2(dir);
|
|
@@ -3440,10 +3580,10 @@ function directoryContainsLibrary(dir, libName) {
|
|
|
3440
3580
|
}
|
|
3441
3581
|
}
|
|
3442
3582
|
function resolveCachedOnnxRuntimeDir(ortVersionDir, libName) {
|
|
3443
|
-
if (existsSync6(
|
|
3583
|
+
if (existsSync6(join9(ortVersionDir, libName)))
|
|
3444
3584
|
return ortVersionDir;
|
|
3445
|
-
const libSubdir =
|
|
3446
|
-
if (existsSync6(
|
|
3585
|
+
const libSubdir = join9(ortVersionDir, "lib");
|
|
3586
|
+
if (existsSync6(join9(libSubdir, libName)))
|
|
3447
3587
|
return libSubdir;
|
|
3448
3588
|
return ortVersionDir;
|
|
3449
3589
|
}
|
|
@@ -3458,12 +3598,12 @@ function findSystemOnnxRuntime(libName) {
|
|
|
3458
3598
|
} else if (process.platform === "win32") {
|
|
3459
3599
|
const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
|
|
3460
3600
|
const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
|
|
3461
|
-
searchPaths.push(
|
|
3601
|
+
searchPaths.push(join9(programFiles, "onnxruntime", "lib"), join9(programFiles, "Microsoft ONNX Runtime", "lib"), join9(programFiles, "Microsoft Machine Learning", "lib"), join9(programFilesX86, "onnxruntime", "lib"), ...(() => {
|
|
3462
3602
|
const nugetPaths = [];
|
|
3463
3603
|
const userProfile = process.env.USERPROFILE ?? "";
|
|
3464
3604
|
if (!userProfile)
|
|
3465
3605
|
return nugetPaths;
|
|
3466
|
-
const nugetPackageDir =
|
|
3606
|
+
const nugetPackageDir = join9(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
|
|
3467
3607
|
if (!existsSync6(nugetPackageDir))
|
|
3468
3608
|
return nugetPaths;
|
|
3469
3609
|
try {
|
|
@@ -3472,7 +3612,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
3472
3612
|
continue;
|
|
3473
3613
|
if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
|
|
3474
3614
|
continue;
|
|
3475
|
-
nugetPaths.push(
|
|
3615
|
+
nugetPaths.push(join9(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join9(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
|
|
3476
3616
|
}
|
|
3477
3617
|
} catch (err) {
|
|
3478
3618
|
warn(`Failed to scan NuGet ONNX Runtime cache ${nugetPackageDir}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -3494,7 +3634,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
3494
3634
|
});
|
|
3495
3635
|
const unknownVersionPaths = [];
|
|
3496
3636
|
for (const dir of uniquePaths) {
|
|
3497
|
-
const libPath =
|
|
3637
|
+
const libPath = join9(dir, libName);
|
|
3498
3638
|
if (process.platform === "win32") {
|
|
3499
3639
|
if (!directoryContainsLibrary(dir, libName))
|
|
3500
3640
|
continue;
|
|
@@ -3503,6 +3643,10 @@ function findSystemOnnxRuntime(libName) {
|
|
|
3503
3643
|
}
|
|
3504
3644
|
const version = detectOnnxVersion(dir, libName);
|
|
3505
3645
|
if (!version) {
|
|
3646
|
+
if (isWindowsSystem32Directory(dir)) {
|
|
3647
|
+
warn(`Skipping unversioned Windows system ONNX Runtime at ${dir}; falling through to AFT-managed download.`);
|
|
3648
|
+
continue;
|
|
3649
|
+
}
|
|
3506
3650
|
unknownVersionPaths.push(dir);
|
|
3507
3651
|
continue;
|
|
3508
3652
|
}
|
|
@@ -3530,7 +3674,7 @@ async function downloadFileWithCap(url, destPath) {
|
|
|
3530
3674
|
if (Number.isFinite(advertised) && advertised > MAX_DOWNLOAD_BYTES2) {
|
|
3531
3675
|
throw new Error(`Content-Length ${advertised} exceeds max ${MAX_DOWNLOAD_BYTES2}`);
|
|
3532
3676
|
}
|
|
3533
|
-
mkdirSync5(
|
|
3677
|
+
mkdirSync5(dirname5(destPath), { recursive: true });
|
|
3534
3678
|
let bytesWritten = 0;
|
|
3535
3679
|
const guard = new TransformStream({
|
|
3536
3680
|
transform(chunk, transformController) {
|
|
@@ -3560,11 +3704,11 @@ function validateExtractedTree(stagingRoot) {
|
|
|
3560
3704
|
const walk = (dir) => {
|
|
3561
3705
|
const entries = readdirSync2(dir);
|
|
3562
3706
|
for (const entry of entries) {
|
|
3563
|
-
const fullPath =
|
|
3707
|
+
const fullPath = join9(dir, entry);
|
|
3564
3708
|
const lst = lstatSync(fullPath);
|
|
3565
3709
|
if (lst.isSymbolicLink()) {
|
|
3566
3710
|
const linkTarget = readlinkSync(fullPath);
|
|
3567
|
-
const resolvedTarget = resolve5(
|
|
3711
|
+
const resolvedTarget = resolve5(dirname5(fullPath), linkTarget);
|
|
3568
3712
|
const rel2 = relative2(realRoot, resolvedTarget);
|
|
3569
3713
|
if (rel2.startsWith("..") || isAbsolute4(rel2) || win32.isAbsolute(rel2)) {
|
|
3570
3714
|
throw new Error(`extracted symlink ${fullPath} points outside staging root: ${linkTarget}`);
|
|
@@ -3595,7 +3739,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
3595
3739
|
const tmpDir = `${targetDir}.tmp.${process.pid}.${Date.now().toString(36)}`;
|
|
3596
3740
|
try {
|
|
3597
3741
|
mkdirSync5(tmpDir, { recursive: true });
|
|
3598
|
-
const archivePath =
|
|
3742
|
+
const archivePath = join9(tmpDir, `onnxruntime.${info.archiveType}`);
|
|
3599
3743
|
await downloadFileWithCap(url, archivePath);
|
|
3600
3744
|
const archiveSha256 = sha256File(archivePath);
|
|
3601
3745
|
log(`ONNX Runtime archive sha256=${archiveSha256}`);
|
|
@@ -3611,7 +3755,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
3611
3755
|
unlinkSync4(archivePath);
|
|
3612
3756
|
} catch {}
|
|
3613
3757
|
validateExtractedTree(tmpDir);
|
|
3614
|
-
const extractedDir =
|
|
3758
|
+
const extractedDir = join9(tmpDir, info.assetName, "lib");
|
|
3615
3759
|
if (!existsSync6(extractedDir)) {
|
|
3616
3760
|
throw new Error(`Expected directory not found: ${extractedDir}`);
|
|
3617
3761
|
}
|
|
@@ -3620,11 +3764,11 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
3620
3764
|
const realFiles = [];
|
|
3621
3765
|
const symlinks = [];
|
|
3622
3766
|
for (const libFile of libFiles) {
|
|
3623
|
-
const src =
|
|
3767
|
+
const src = join9(extractedDir, libFile);
|
|
3624
3768
|
try {
|
|
3625
|
-
const
|
|
3626
|
-
log(`ORT extract: ${libFile} — isSymlink=${
|
|
3627
|
-
if (
|
|
3769
|
+
const stat2 = lstatSync(src);
|
|
3770
|
+
log(`ORT extract: ${libFile} — isSymlink=${stat2.isSymbolicLink()}, isFile=${stat2.isFile()}, size=${stat2.size}`);
|
|
3771
|
+
if (stat2.isSymbolicLink()) {
|
|
3628
3772
|
symlinks.push({ name: libFile, target: readlinkSync(src) });
|
|
3629
3773
|
} else {
|
|
3630
3774
|
realFiles.push(libFile);
|
|
@@ -3635,7 +3779,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
3635
3779
|
}
|
|
3636
3780
|
}
|
|
3637
3781
|
copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks);
|
|
3638
|
-
const libPath =
|
|
3782
|
+
const libPath = join9(targetDir, info.libName);
|
|
3639
3783
|
let libHash = null;
|
|
3640
3784
|
try {
|
|
3641
3785
|
libHash = sha256File(libPath);
|
|
@@ -3660,8 +3804,8 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
3660
3804
|
function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, copyFile = copyFileSync3) {
|
|
3661
3805
|
const requiredLibs = new Set([info.libName]);
|
|
3662
3806
|
for (const libFile of realFiles) {
|
|
3663
|
-
const src =
|
|
3664
|
-
const dst =
|
|
3807
|
+
const src = join9(extractedDir, libFile);
|
|
3808
|
+
const dst = join9(targetDir, libFile);
|
|
3665
3809
|
try {
|
|
3666
3810
|
copyFile(src, dst);
|
|
3667
3811
|
if (process.platform !== "win32") {
|
|
@@ -3677,12 +3821,12 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
3677
3821
|
}
|
|
3678
3822
|
const targetRoot = realpathSync(targetDir);
|
|
3679
3823
|
for (const link of symlinks) {
|
|
3680
|
-
const dst =
|
|
3824
|
+
const dst = join9(targetDir, link.name);
|
|
3681
3825
|
try {
|
|
3682
3826
|
unlinkSync4(dst);
|
|
3683
3827
|
} catch {}
|
|
3684
|
-
const dstForContainment =
|
|
3685
|
-
const resolvedTarget = resolve5(
|
|
3828
|
+
const dstForContainment = join9(targetRoot, link.name);
|
|
3829
|
+
const resolvedTarget = resolve5(dirname5(dstForContainment), link.target);
|
|
3686
3830
|
if (!isPathInsideRoot(targetRoot, resolvedTarget)) {
|
|
3687
3831
|
const message = `ONNX Runtime symlink ${link.name} points outside install dir: ${link.target}`;
|
|
3688
3832
|
if (requiredLibs.has(link.name)) {
|
|
@@ -3702,7 +3846,7 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
3702
3846
|
log(`ORT extract: failed to symlink optional ${link.name}: ${symlinkErr}`);
|
|
3703
3847
|
}
|
|
3704
3848
|
}
|
|
3705
|
-
const requiredPath =
|
|
3849
|
+
const requiredPath = join9(targetDir, info.libName);
|
|
3706
3850
|
if (!existsSync6(requiredPath)) {
|
|
3707
3851
|
rmSync3(targetDir, { recursive: true, force: true });
|
|
3708
3852
|
throw new Error(`Required ONNX Runtime library missing after install: ${requiredPath}`);
|
|
@@ -3729,13 +3873,13 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
|
|
|
3729
3873
|
...sha256 ? { sha256 } : {},
|
|
3730
3874
|
archiveSha256
|
|
3731
3875
|
};
|
|
3732
|
-
writeFileSync3(
|
|
3876
|
+
writeFileSync3(join9(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
|
|
3733
3877
|
} catch (err) {
|
|
3734
3878
|
log(`[onnx] failed to write installed-meta in ${installDir}: ${err}`);
|
|
3735
3879
|
}
|
|
3736
3880
|
}
|
|
3737
3881
|
function readOnnxInstalledMeta(installDir) {
|
|
3738
|
-
const path2 =
|
|
3882
|
+
const path2 = join9(installDir, ONNX_INSTALLED_META_FILE);
|
|
3739
3883
|
try {
|
|
3740
3884
|
if (!statSync4(path2).isFile())
|
|
3741
3885
|
return null;
|
|
@@ -3873,7 +4017,7 @@ function isProcessAlive(pid) {
|
|
|
3873
4017
|
}
|
|
3874
4018
|
function cleanupOnnxRuntime(storageDir) {
|
|
3875
4019
|
try {
|
|
3876
|
-
const ortBase =
|
|
4020
|
+
const ortBase = join9(storageDir, "onnxruntime");
|
|
3877
4021
|
if (existsSync6(ortBase)) {
|
|
3878
4022
|
rmSync3(ortBase, { recursive: true, force: true });
|
|
3879
4023
|
}
|
|
@@ -3975,10 +4119,10 @@ function projectRootKeyHash(dir) {
|
|
|
3975
4119
|
var init_project_identity = () => {};
|
|
3976
4120
|
|
|
3977
4121
|
// ../aft-bridge/dist/pool.js
|
|
3978
|
-
import { homedir as
|
|
4122
|
+
import { homedir as homedir10 } from "node:os";
|
|
3979
4123
|
function canonicalHomeDir() {
|
|
3980
4124
|
try {
|
|
3981
|
-
const home =
|
|
4125
|
+
const home = homedir10();
|
|
3982
4126
|
if (!home)
|
|
3983
4127
|
return null;
|
|
3984
4128
|
return canonicalizeProjectRoot(home);
|
|
@@ -4004,6 +4148,7 @@ class BridgePool {
|
|
|
4004
4148
|
projectConfigLoader;
|
|
4005
4149
|
logger;
|
|
4006
4150
|
cleanupTimer = null;
|
|
4151
|
+
shutdownCalled = false;
|
|
4007
4152
|
constructor(binaryPath, options = {}, configOverrides = {}) {
|
|
4008
4153
|
this.binaryPath = binaryPath;
|
|
4009
4154
|
this.maxPoolSize = options.maxPoolSize ?? DEFAULT_MAX_POOL_SIZE;
|
|
@@ -4025,12 +4170,11 @@ class BridgePool {
|
|
|
4025
4170
|
childEnv: options.childEnv
|
|
4026
4171
|
};
|
|
4027
4172
|
this.configOverrides = configOverrides;
|
|
4028
|
-
|
|
4029
|
-
this.cleanupTimer = setInterval(() => this.cleanup(), CLEANUP_INTERVAL_MS);
|
|
4030
|
-
this.cleanupTimer.unref();
|
|
4031
|
-
}
|
|
4173
|
+
this.startCleanupTimer();
|
|
4032
4174
|
}
|
|
4033
4175
|
getActiveBridgeForRoot(projectRoot) {
|
|
4176
|
+
if (this.shutdownCalled)
|
|
4177
|
+
return null;
|
|
4034
4178
|
const key = normalizeKey(projectRoot);
|
|
4035
4179
|
const entry = this.bridges.get(key);
|
|
4036
4180
|
if (!entry?.bridge.isAlive())
|
|
@@ -4038,7 +4182,21 @@ class BridgePool {
|
|
|
4038
4182
|
entry.lastUsed = Date.now();
|
|
4039
4183
|
return entry.bridge;
|
|
4040
4184
|
}
|
|
4185
|
+
activeBridges() {
|
|
4186
|
+
if (this.shutdownCalled)
|
|
4187
|
+
return [];
|
|
4188
|
+
const alive = [];
|
|
4189
|
+
for (const entry of this.bridges.values()) {
|
|
4190
|
+
if (entry.bridge.isAlive())
|
|
4191
|
+
alive.push(entry.bridge);
|
|
4192
|
+
}
|
|
4193
|
+
return alive;
|
|
4194
|
+
}
|
|
4041
4195
|
getBridge(projectRoot) {
|
|
4196
|
+
if (this.shutdownCalled) {
|
|
4197
|
+
this.shutdownCalled = false;
|
|
4198
|
+
this.startCleanupTimer();
|
|
4199
|
+
}
|
|
4042
4200
|
const key = normalizeKey(projectRoot);
|
|
4043
4201
|
const existing = this.bridges.get(key);
|
|
4044
4202
|
if (existing) {
|
|
@@ -4048,15 +4206,7 @@ class BridgePool {
|
|
|
4048
4206
|
if (this.bridges.size >= this.maxPoolSize) {
|
|
4049
4207
|
this.evictLRU();
|
|
4050
4208
|
}
|
|
4051
|
-
|
|
4052
|
-
if (this.projectConfigLoader) {
|
|
4053
|
-
try {
|
|
4054
|
-
projectOverrides = this.projectConfigLoader(key) ?? {};
|
|
4055
|
-
} catch (err) {
|
|
4056
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
4057
|
-
this.error(`projectConfigLoader failed; using global overrides only: ${message}`);
|
|
4058
|
-
}
|
|
4059
|
-
}
|
|
4209
|
+
const projectOverrides = this.loadProjectOverrides(key);
|
|
4060
4210
|
const mergedOverrides = { ...this.configOverrides, ...projectOverrides };
|
|
4061
4211
|
const bridge = new BinaryBridge(this.binaryPath, key, this.bridgeOptions, mergedOverrides);
|
|
4062
4212
|
this.bridges.set(key, { bridge, lastUsed: Date.now() });
|
|
@@ -4106,6 +4256,7 @@ class BridgePool {
|
|
|
4106
4256
|
}
|
|
4107
4257
|
async closeSession(_projectRoot, _session) {}
|
|
4108
4258
|
async shutdown() {
|
|
4259
|
+
this.shutdownCalled = true;
|
|
4109
4260
|
if (this.cleanupTimer) {
|
|
4110
4261
|
clearInterval(this.cleanupTimer);
|
|
4111
4262
|
this.cleanupTimer = null;
|
|
@@ -4118,6 +4269,9 @@ class BridgePool {
|
|
|
4118
4269
|
this.staleBridges.clear();
|
|
4119
4270
|
await Promise.allSettled(shutdowns);
|
|
4120
4271
|
}
|
|
4272
|
+
isShutdown() {
|
|
4273
|
+
return this.shutdownCalled;
|
|
4274
|
+
}
|
|
4121
4275
|
async replaceBinary(newPath) {
|
|
4122
4276
|
this.binaryPath = newPath;
|
|
4123
4277
|
for (const entry of this.bridges.values()) {
|
|
@@ -4127,6 +4281,12 @@ class BridgePool {
|
|
|
4127
4281
|
this.log(`Binary path updated to ${newPath}. Active bridges marked stale — next calls will use the new binary.`);
|
|
4128
4282
|
return newPath;
|
|
4129
4283
|
}
|
|
4284
|
+
startCleanupTimer() {
|
|
4285
|
+
if (!Number.isFinite(this.idleTimeoutMs) || this.cleanupTimer)
|
|
4286
|
+
return;
|
|
4287
|
+
this.cleanupTimer = setInterval(() => this.cleanup(), CLEANUP_INTERVAL_MS);
|
|
4288
|
+
this.cleanupTimer.unref();
|
|
4289
|
+
}
|
|
4130
4290
|
log(message, meta) {
|
|
4131
4291
|
const logger = this.logger ?? getActiveLogger();
|
|
4132
4292
|
if (logger) {
|
|
@@ -4158,6 +4318,36 @@ class BridgePool {
|
|
|
4158
4318
|
this.configOverrides[key] = value;
|
|
4159
4319
|
}
|
|
4160
4320
|
}
|
|
4321
|
+
async reconfigure(projectRoot, overrides) {
|
|
4322
|
+
const key = normalizeKey(projectRoot);
|
|
4323
|
+
for (const [name, value] of Object.entries(overrides)) {
|
|
4324
|
+
this.setConfigureOverride(name, value);
|
|
4325
|
+
}
|
|
4326
|
+
const bridge = this.getActiveBridgeForRoot(key);
|
|
4327
|
+
if (!bridge)
|
|
4328
|
+
return;
|
|
4329
|
+
const projectOverrides = this.loadProjectOverrides(key);
|
|
4330
|
+
const response = await bridge.send("configure", {
|
|
4331
|
+
project_root: key,
|
|
4332
|
+
...this.configOverrides,
|
|
4333
|
+
...projectOverrides,
|
|
4334
|
+
...overrides
|
|
4335
|
+
});
|
|
4336
|
+
if (response.success === false) {
|
|
4337
|
+
throw new Error(`configure refresh failed for ${key}: ${String(response.message ?? "unknown error")}`);
|
|
4338
|
+
}
|
|
4339
|
+
}
|
|
4340
|
+
loadProjectOverrides(key) {
|
|
4341
|
+
if (!this.projectConfigLoader)
|
|
4342
|
+
return {};
|
|
4343
|
+
try {
|
|
4344
|
+
return this.projectConfigLoader(key) ?? {};
|
|
4345
|
+
} catch (err) {
|
|
4346
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4347
|
+
this.error(`projectConfigLoader failed; using global overrides only: ${message}`);
|
|
4348
|
+
return {};
|
|
4349
|
+
}
|
|
4350
|
+
}
|
|
4161
4351
|
get size() {
|
|
4162
4352
|
return this.bridges.size;
|
|
4163
4353
|
}
|
|
@@ -4188,7 +4378,186 @@ var init_pool = __esm(() => {
|
|
|
4188
4378
|
};
|
|
4189
4379
|
});
|
|
4190
4380
|
|
|
4191
|
-
//
|
|
4381
|
+
// ../aft-bridge/dist/revivable-transport.js
|
|
4382
|
+
class RevivableTransportPool {
|
|
4383
|
+
createPool;
|
|
4384
|
+
onBinaryReplaced;
|
|
4385
|
+
activePool;
|
|
4386
|
+
revival = null;
|
|
4387
|
+
transports = new Map;
|
|
4388
|
+
configureOverrides = new Map;
|
|
4389
|
+
constructor(initialPool, createPool, onBinaryReplaced) {
|
|
4390
|
+
this.createPool = createPool;
|
|
4391
|
+
this.onBinaryReplaced = onBinaryReplaced;
|
|
4392
|
+
this.activePool = initialPool;
|
|
4393
|
+
}
|
|
4394
|
+
getBridge(projectRoot) {
|
|
4395
|
+
const key = canonicalizeProjectRoot(projectRoot);
|
|
4396
|
+
let transport = this.transports.get(key);
|
|
4397
|
+
if (!transport) {
|
|
4398
|
+
transport = new RevivableProjectTransport(this, key);
|
|
4399
|
+
this.transports.set(key, transport);
|
|
4400
|
+
}
|
|
4401
|
+
return transport;
|
|
4402
|
+
}
|
|
4403
|
+
activeBridges() {
|
|
4404
|
+
return this.activePool.activeBridges();
|
|
4405
|
+
}
|
|
4406
|
+
getActiveBridgeForRoot(projectRoot) {
|
|
4407
|
+
const key = canonicalizeProjectRoot(projectRoot);
|
|
4408
|
+
const bridge = this.currentBridge(key);
|
|
4409
|
+
if (!bridge)
|
|
4410
|
+
return null;
|
|
4411
|
+
const transport = this.getBridge(key);
|
|
4412
|
+
transport.refreshStatusSubscription(bridge);
|
|
4413
|
+
return transport;
|
|
4414
|
+
}
|
|
4415
|
+
async toolCall(projectRoot, runtime, name, rawArgs = {}, options) {
|
|
4416
|
+
return this.getBridge(projectRoot).toolCall(runtime.sessionID, name, rawArgs, options);
|
|
4417
|
+
}
|
|
4418
|
+
setConfigureOverride(key, value) {
|
|
4419
|
+
if (value === undefined)
|
|
4420
|
+
this.configureOverrides.delete(key);
|
|
4421
|
+
else
|
|
4422
|
+
this.configureOverrides.set(key, value);
|
|
4423
|
+
this.activePool.setConfigureOverride(key, value);
|
|
4424
|
+
}
|
|
4425
|
+
async reconfigure(projectRoot, overrides) {
|
|
4426
|
+
for (const [key, value] of Object.entries(overrides)) {
|
|
4427
|
+
if (value === undefined)
|
|
4428
|
+
this.configureOverrides.delete(key);
|
|
4429
|
+
else
|
|
4430
|
+
this.configureOverrides.set(key, value);
|
|
4431
|
+
}
|
|
4432
|
+
const pool = await this.ensureActivePool();
|
|
4433
|
+
await pool.reconfigure(projectRoot, overrides);
|
|
4434
|
+
}
|
|
4435
|
+
async replaceBinary(path2) {
|
|
4436
|
+
const replaced = await this.activePool.replaceBinary(path2);
|
|
4437
|
+
this.onBinaryReplaced?.(replaced);
|
|
4438
|
+
return replaced;
|
|
4439
|
+
}
|
|
4440
|
+
closeSession(projectRoot, session) {
|
|
4441
|
+
return this.activePool.closeSession(projectRoot, session);
|
|
4442
|
+
}
|
|
4443
|
+
async shutdown() {
|
|
4444
|
+
const revival = this.revival;
|
|
4445
|
+
if (revival) {
|
|
4446
|
+
await Promise.allSettled([revival]);
|
|
4447
|
+
}
|
|
4448
|
+
await this.activePool.shutdown();
|
|
4449
|
+
for (const transport of this.transports.values()) {
|
|
4450
|
+
transport.refreshStatusSubscription(null);
|
|
4451
|
+
}
|
|
4452
|
+
}
|
|
4453
|
+
isShutdown() {
|
|
4454
|
+
return this.activePool.isShutdown();
|
|
4455
|
+
}
|
|
4456
|
+
async ensureActivePool() {
|
|
4457
|
+
if (!this.activePool.isShutdown())
|
|
4458
|
+
return this.activePool;
|
|
4459
|
+
if (this.revival)
|
|
4460
|
+
return this.revival;
|
|
4461
|
+
warn("transport was shut down but new demand arrived — reviving (host quit hook fired without process exit?)");
|
|
4462
|
+
const revival = this.createPool().then((pool) => {
|
|
4463
|
+
for (const [key, value] of this.configureOverrides) {
|
|
4464
|
+
pool.setConfigureOverride(key, value);
|
|
4465
|
+
}
|
|
4466
|
+
this.activePool = pool;
|
|
4467
|
+
for (const [root, transport] of this.transports) {
|
|
4468
|
+
transport.refreshStatusSubscription(pool.getActiveBridgeForRoot(root));
|
|
4469
|
+
}
|
|
4470
|
+
return pool;
|
|
4471
|
+
});
|
|
4472
|
+
this.revival = revival;
|
|
4473
|
+
revival.then(() => {
|
|
4474
|
+
if (this.revival === revival)
|
|
4475
|
+
this.revival = null;
|
|
4476
|
+
}, () => {
|
|
4477
|
+
if (this.revival === revival)
|
|
4478
|
+
this.revival = null;
|
|
4479
|
+
});
|
|
4480
|
+
return revival;
|
|
4481
|
+
}
|
|
4482
|
+
currentBridge(projectRoot) {
|
|
4483
|
+
return this.activePool.getActiveBridgeForRoot(projectRoot);
|
|
4484
|
+
}
|
|
4485
|
+
async send(projectRoot, command, params, options) {
|
|
4486
|
+
const pool = await this.ensureActivePool();
|
|
4487
|
+
const bridge = pool.getBridge(projectRoot);
|
|
4488
|
+
this.getBridge(projectRoot).refreshStatusSubscription(bridge);
|
|
4489
|
+
return bridge.send(command, params, options);
|
|
4490
|
+
}
|
|
4491
|
+
async toolCallOnProject(projectRoot, sessionId, name, rawArgs, options) {
|
|
4492
|
+
const pool = await this.ensureActivePool();
|
|
4493
|
+
const bridge = pool.getBridge(projectRoot);
|
|
4494
|
+
this.getBridge(projectRoot).refreshStatusSubscription(bridge);
|
|
4495
|
+
return bridge.toolCall(sessionId, name, rawArgs, options);
|
|
4496
|
+
}
|
|
4497
|
+
}
|
|
4498
|
+
|
|
4499
|
+
class RevivableProjectTransport {
|
|
4500
|
+
owner;
|
|
4501
|
+
projectRoot;
|
|
4502
|
+
statusListeners = new Map;
|
|
4503
|
+
statusBridges = new Map;
|
|
4504
|
+
constructor(owner, projectRoot) {
|
|
4505
|
+
this.owner = owner;
|
|
4506
|
+
this.projectRoot = projectRoot;
|
|
4507
|
+
}
|
|
4508
|
+
getCwd() {
|
|
4509
|
+
return this.projectRoot;
|
|
4510
|
+
}
|
|
4511
|
+
getStatusBar() {
|
|
4512
|
+
return this.owner.currentBridge(this.projectRoot)?.getStatusBar();
|
|
4513
|
+
}
|
|
4514
|
+
getCachedStatus() {
|
|
4515
|
+
return this.owner.currentBridge(this.projectRoot)?.getCachedStatus() ?? null;
|
|
4516
|
+
}
|
|
4517
|
+
cacheStatusSnapshot(snapshot) {
|
|
4518
|
+
this.owner.currentBridge(this.projectRoot)?.cacheStatusSnapshot(snapshot);
|
|
4519
|
+
}
|
|
4520
|
+
send(command, params, options) {
|
|
4521
|
+
return this.owner.send(this.projectRoot, command, params, options);
|
|
4522
|
+
}
|
|
4523
|
+
toolCall(sessionId, name, rawArgs, options) {
|
|
4524
|
+
return this.owner.toolCallOnProject(this.projectRoot, sessionId, name, rawArgs, options);
|
|
4525
|
+
}
|
|
4526
|
+
subscribeStatus(listener) {
|
|
4527
|
+
if (this.statusListeners.has(listener))
|
|
4528
|
+
return () => this.removeStatusListener(listener);
|
|
4529
|
+
this.statusListeners.set(listener, () => {});
|
|
4530
|
+
this.bindStatusListener(listener, this.owner.currentBridge(this.projectRoot));
|
|
4531
|
+
return () => this.removeStatusListener(listener);
|
|
4532
|
+
}
|
|
4533
|
+
refreshStatusSubscription(bridge) {
|
|
4534
|
+
for (const listener of this.statusListeners.keys()) {
|
|
4535
|
+
this.bindStatusListener(listener, bridge);
|
|
4536
|
+
}
|
|
4537
|
+
}
|
|
4538
|
+
bindStatusListener(listener, bridge) {
|
|
4539
|
+
if (this.statusBridges.get(listener) === bridge)
|
|
4540
|
+
return;
|
|
4541
|
+
const previousUnsubscribe = this.statusListeners.get(listener);
|
|
4542
|
+
previousUnsubscribe?.();
|
|
4543
|
+
const maybe = bridge;
|
|
4544
|
+
const unsubscribe = maybe && typeof maybe.subscribeStatus === "function" ? maybe.subscribeStatus(listener) : () => {};
|
|
4545
|
+
this.statusListeners.set(listener, unsubscribe);
|
|
4546
|
+
this.statusBridges.set(listener, bridge);
|
|
4547
|
+
}
|
|
4548
|
+
removeStatusListener(listener) {
|
|
4549
|
+
const unsubscribe = this.statusListeners.get(listener);
|
|
4550
|
+
this.statusListeners.delete(listener);
|
|
4551
|
+
this.statusBridges.delete(listener);
|
|
4552
|
+
unsubscribe?.();
|
|
4553
|
+
}
|
|
4554
|
+
}
|
|
4555
|
+
var init_revivable_transport = __esm(() => {
|
|
4556
|
+
init_active_logger();
|
|
4557
|
+
init_project_identity();
|
|
4558
|
+
});
|
|
4559
|
+
|
|
4560
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.5.0/node_modules/@cortexkit/subc-client/dist/auth.js
|
|
4192
4561
|
import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
|
|
4193
4562
|
function computeProof(key, domain, clientNonce, serverNonce, daemonId) {
|
|
4194
4563
|
const mac = createHmac("sha256", Buffer.from(key));
|
|
@@ -4249,7 +4618,132 @@ var init_auth = __esm(() => {
|
|
|
4249
4618
|
};
|
|
4250
4619
|
});
|
|
4251
4620
|
|
|
4252
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
4621
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.5.0/node_modules/@cortexkit/subc-client/dist/envelope.js
|
|
4622
|
+
function isPureHeader(ty) {
|
|
4623
|
+
return ty === FrameType.Cancel || ty === FrameType.Ping || ty === FrameType.Pong || ty === FrameType.Goodbye;
|
|
4624
|
+
}
|
|
4625
|
+
function buildFlags(binary, priority, last, admissionClass = AdmissionClass.Normal) {
|
|
4626
|
+
let flags = 0;
|
|
4627
|
+
if (binary)
|
|
4628
|
+
flags |= FLAG_BINARY;
|
|
4629
|
+
flags |= priority << FLAG_PRIORITY_SHIFT;
|
|
4630
|
+
if (last)
|
|
4631
|
+
flags |= FLAG_LAST;
|
|
4632
|
+
flags |= admissionClass << FLAG_ADMISSION_SHIFT;
|
|
4633
|
+
return flags;
|
|
4634
|
+
}
|
|
4635
|
+
function encodeHeader(header) {
|
|
4636
|
+
const buffer = new Uint8Array(HEADER_LEN);
|
|
4637
|
+
const view = new DataView(buffer.buffer);
|
|
4638
|
+
view.setUint32(0, header.len, true);
|
|
4639
|
+
buffer[4] = header.ver;
|
|
4640
|
+
buffer[5] = header.ty;
|
|
4641
|
+
buffer[6] = header.flags;
|
|
4642
|
+
view.setUint16(7, header.channel, true);
|
|
4643
|
+
view.setUint32(9, header.epoch, true);
|
|
4644
|
+
view.setBigUint64(13, header.corr, true);
|
|
4645
|
+
return buffer;
|
|
4646
|
+
}
|
|
4647
|
+
function decodeHeader(bytes) {
|
|
4648
|
+
if (bytes.length < FROZEN_PREFIX_LEN) {
|
|
4649
|
+
throw new DecodeError(`header shorter than frozen prefix: have ${bytes.length} bytes`, "too_short_for_prefix");
|
|
4650
|
+
}
|
|
4651
|
+
const ver = bytes[4];
|
|
4652
|
+
if (ver !== PROTOCOL_VERSION)
|
|
4653
|
+
throw new DecodeError(`unsupported envelope version ${ver}`, "unsupported_version");
|
|
4654
|
+
if (bytes.length < HEADER_LEN) {
|
|
4655
|
+
throw new DecodeError(`header too short for version: have ${bytes.length} bytes, need ${HEADER_LEN}`, "too_short_for_header");
|
|
4656
|
+
}
|
|
4657
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
4658
|
+
const len = view.getUint32(0, true);
|
|
4659
|
+
const typeByte = bytes[5];
|
|
4660
|
+
if (typeByte > FRAME_TYPE_MAX)
|
|
4661
|
+
throw new DecodeError(`unknown frame type byte ${typeByte}`, "unknown_frame_type");
|
|
4662
|
+
const ty = typeByte;
|
|
4663
|
+
const flags = bytes[6];
|
|
4664
|
+
if ((flags & FLAG_RESERVED_MASK) !== 0) {
|
|
4665
|
+
throw new DecodeError(`reserved flag bits set in flags 0b${flags.toString(2).padStart(8, "0")}`, "reserved_flag_bits");
|
|
4666
|
+
}
|
|
4667
|
+
if ((flags & FLAG_PRIORITY_MASK) >> FLAG_PRIORITY_SHIFT === 3) {
|
|
4668
|
+
throw new DecodeError(`reserved priority bits set in flags 0b${flags.toString(2).padStart(8, "0")}`, "reserved_priority_bits");
|
|
4669
|
+
}
|
|
4670
|
+
const admission = (flags & FLAG_ADMISSION_MASK) >> FLAG_ADMISSION_SHIFT;
|
|
4671
|
+
if (admission === 3) {
|
|
4672
|
+
throw new DecodeError(`reserved admission class set in flags 0b${flags.toString(2).padStart(8, "0")}`, "reserved_admission_class");
|
|
4673
|
+
}
|
|
4674
|
+
if (admission === AdmissionClass.Sheddable && ty !== FrameType.Push && ty !== FrameType.StreamData) {
|
|
4675
|
+
throw new DecodeError(`SHEDDABLE admission class is illegal on ${FrameType[ty]} in flags 0b${flags.toString(2).padStart(8, "0")}`, "sheddable_illegal_frame_type");
|
|
4676
|
+
}
|
|
4677
|
+
const channel = view.getUint16(7, true);
|
|
4678
|
+
const epoch = view.getUint32(9, true);
|
|
4679
|
+
if (channel === 0 && epoch !== 0) {
|
|
4680
|
+
throw new DecodeError(`control channel carried nonzero epoch ${epoch}`, "nonzero_epoch_on_control_channel");
|
|
4681
|
+
}
|
|
4682
|
+
if (isPureHeader(ty) && len !== 0) {
|
|
4683
|
+
throw new DecodeError(`pure-header frame ${FrameType[ty]} declared non-zero body length ${len}`, "pure_header_frame_with_body");
|
|
4684
|
+
}
|
|
4685
|
+
return { len, ver, ty, flags, channel, epoch, corr: view.getBigUint64(13, true) };
|
|
4686
|
+
}
|
|
4687
|
+
function buildFrame(ty, flags, channel, epoch, corr, body) {
|
|
4688
|
+
return buildFrameWithVersion(PROTOCOL_VERSION, ty, flags, channel, epoch, corr, body);
|
|
4689
|
+
}
|
|
4690
|
+
function buildFrameWithVersion(ver, ty, flags, channel, epoch, corr, body) {
|
|
4691
|
+
if (body.length > MAX_FRAME_BODY_LEN) {
|
|
4692
|
+
throw new DecodeError(`frame body ${body.length} exceeds max ${MAX_FRAME_BODY_LEN}`, "frame_body_too_large");
|
|
4693
|
+
}
|
|
4694
|
+
const header = { len: body.length, ver, ty, flags, channel, epoch, corr };
|
|
4695
|
+
decodeHeader(encodeHeader(header));
|
|
4696
|
+
return { header, body };
|
|
4697
|
+
}
|
|
4698
|
+
function encodeFrame(frame) {
|
|
4699
|
+
if (frame.header.len !== frame.body.length) {
|
|
4700
|
+
throw new DecodeError(`frame header length ${frame.header.len} does not match body length ${frame.body.length}`, "frame_length_mismatch");
|
|
4701
|
+
}
|
|
4702
|
+
const header = encodeHeader(frame.header);
|
|
4703
|
+
const output = new Uint8Array(header.length + frame.body.length);
|
|
4704
|
+
output.set(header, 0);
|
|
4705
|
+
output.set(frame.body, header.length);
|
|
4706
|
+
return output;
|
|
4707
|
+
}
|
|
4708
|
+
var PROTOCOL_VERSION = 2, HEADER_LEN = 21, FROZEN_PREFIX_LEN = 5, MAX_FRAME_BODY_LEN, FrameType, FRAME_TYPE_MAX, Priority, AdmissionClass, FLAG_BINARY = 1, FLAG_PRIORITY_MASK = 6, FLAG_PRIORITY_SHIFT = 1, FLAG_LAST = 8, FLAG_ADMISSION_MASK = 48, FLAG_ADMISSION_SHIFT = 4, FLAG_RESERVED_MASK = 192, DecodeError;
|
|
4709
|
+
var init_envelope = __esm(() => {
|
|
4710
|
+
MAX_FRAME_BODY_LEN = 64 * 1024 * 1024;
|
|
4711
|
+
(function(FrameType2) {
|
|
4712
|
+
FrameType2[FrameType2["Request"] = 0] = "Request";
|
|
4713
|
+
FrameType2[FrameType2["Response"] = 1] = "Response";
|
|
4714
|
+
FrameType2[FrameType2["Push"] = 2] = "Push";
|
|
4715
|
+
FrameType2[FrameType2["StreamData"] = 3] = "StreamData";
|
|
4716
|
+
FrameType2[FrameType2["StreamEnd"] = 4] = "StreamEnd";
|
|
4717
|
+
FrameType2[FrameType2["Error"] = 5] = "Error";
|
|
4718
|
+
FrameType2[FrameType2["Cancel"] = 6] = "Cancel";
|
|
4719
|
+
FrameType2[FrameType2["Ping"] = 7] = "Ping";
|
|
4720
|
+
FrameType2[FrameType2["Pong"] = 8] = "Pong";
|
|
4721
|
+
FrameType2[FrameType2["Hello"] = 9] = "Hello";
|
|
4722
|
+
FrameType2[FrameType2["HelloAck"] = 10] = "HelloAck";
|
|
4723
|
+
FrameType2[FrameType2["Goodbye"] = 11] = "Goodbye";
|
|
4724
|
+
})(FrameType || (FrameType = {}));
|
|
4725
|
+
FRAME_TYPE_MAX = FrameType.Goodbye;
|
|
4726
|
+
(function(Priority2) {
|
|
4727
|
+
Priority2[Priority2["Passive"] = 0] = "Passive";
|
|
4728
|
+
Priority2[Priority2["Interactive"] = 1] = "Interactive";
|
|
4729
|
+
Priority2[Priority2["Background"] = 2] = "Background";
|
|
4730
|
+
})(Priority || (Priority = {}));
|
|
4731
|
+
(function(AdmissionClass2) {
|
|
4732
|
+
AdmissionClass2[AdmissionClass2["Normal"] = 0] = "Normal";
|
|
4733
|
+
AdmissionClass2[AdmissionClass2["Expedite"] = 1] = "Expedite";
|
|
4734
|
+
AdmissionClass2[AdmissionClass2["Sheddable"] = 2] = "Sheddable";
|
|
4735
|
+
})(AdmissionClass || (AdmissionClass = {}));
|
|
4736
|
+
DecodeError = class DecodeError extends Error {
|
|
4737
|
+
code;
|
|
4738
|
+
constructor(message, code) {
|
|
4739
|
+
super(message);
|
|
4740
|
+
this.code = code;
|
|
4741
|
+
this.name = "DecodeError";
|
|
4742
|
+
}
|
|
4743
|
+
};
|
|
4744
|
+
});
|
|
4745
|
+
|
|
4746
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.5.0/node_modules/@cortexkit/subc-client/dist/connection-file.js
|
|
4253
4747
|
import { promises as fs } from "node:fs";
|
|
4254
4748
|
function toBytes(value, field) {
|
|
4255
4749
|
if (!Array.isArray(value) || value.some((n) => typeof n !== "number")) {
|
|
@@ -4274,8 +4768,8 @@ function validate(info) {
|
|
|
4274
4768
|
async function verifyOwnerOnly(path2) {
|
|
4275
4769
|
if (process.platform === "win32")
|
|
4276
4770
|
return;
|
|
4277
|
-
const
|
|
4278
|
-
const mode =
|
|
4771
|
+
const stat2 = await fs.stat(path2);
|
|
4772
|
+
const mode = stat2.mode & 511;
|
|
4279
4773
|
if ((mode & 63) !== 0) {
|
|
4280
4774
|
throw new ConnectionFileError(`connection file ${path2} has insecure permissions 0o${mode.toString(8)}; expected owner-only 0600`);
|
|
4281
4775
|
}
|
|
@@ -4289,6 +4783,10 @@ async function readConnectionFile(path2) {
|
|
|
4289
4783
|
} catch (err) {
|
|
4290
4784
|
throw new ConnectionFileError(`connection file JSON read failed for ${path2}: ${String(err)}`);
|
|
4291
4785
|
}
|
|
4786
|
+
const wireVersion = parsed.wire_version;
|
|
4787
|
+
if (wireVersion !== undefined && wireVersion !== PROTOCOL_VERSION) {
|
|
4788
|
+
throw new ConnectionFileError(`connection file wire_version ${String(wireVersion)} but this client speaks ${PROTOCOL_VERSION}; the client library must be upgraded`);
|
|
4789
|
+
}
|
|
4292
4790
|
const endpointsRaw = parsed.endpoints;
|
|
4293
4791
|
if (!Array.isArray(endpointsRaw)) {
|
|
4294
4792
|
throw new ConnectionFileError("connection file 'endpoints' must be an array");
|
|
@@ -4313,110 +4811,59 @@ async function readConnectionFile(path2) {
|
|
|
4313
4811
|
}
|
|
4314
4812
|
var SCHEMA_VERSION = 1, MIN_KEY_LEN = 32, DAEMON_ID_LEN = 16, ConnectionFileError;
|
|
4315
4813
|
var init_connection_file = __esm(() => {
|
|
4814
|
+
init_envelope();
|
|
4316
4815
|
ConnectionFileError = class ConnectionFileError extends Error {
|
|
4317
4816
|
};
|
|
4318
4817
|
});
|
|
4319
4818
|
|
|
4320
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
return
|
|
4343
|
-
}
|
|
4344
|
-
function
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
throw new DecodeError(`reserved flag bits set in flags 0b${flags.toString(2)}`);
|
|
4365
|
-
}
|
|
4366
|
-
if ((flags & FLAG_PRIORITY_MASK) >> FLAG_PRIORITY_SHIFT === 3) {
|
|
4367
|
-
throw new DecodeError(`reserved priority bits set in flags 0b${flags.toString(2)}`);
|
|
4368
|
-
}
|
|
4369
|
-
if (isPureHeader(ty) && len !== 0) {
|
|
4370
|
-
throw new DecodeError(`pure-header frame ${FrameType[ty]} declared non-zero body length ${len}`);
|
|
4371
|
-
}
|
|
4372
|
-
const channel = view.getUint16(7, true);
|
|
4373
|
-
const corr = view.getBigUint64(9, true);
|
|
4374
|
-
return { len, ver, ty, flags, channel, corr };
|
|
4375
|
-
}
|
|
4376
|
-
function buildFrame(ty, flags, channel, corr, body) {
|
|
4377
|
-
return buildFrameWithVersion(PROTOCOL_VERSION, ty, flags, channel, corr, body);
|
|
4378
|
-
}
|
|
4379
|
-
function buildFrameWithVersion(ver, ty, flags, channel, corr, body) {
|
|
4380
|
-
if (body.length > MAX_FRAME_BODY_LEN) {
|
|
4381
|
-
throw new DecodeError(`frame body ${body.length} exceeds max ${MAX_FRAME_BODY_LEN}`);
|
|
4382
|
-
}
|
|
4383
|
-
if (isPureHeader(ty) && body.length !== 0) {
|
|
4384
|
-
throw new DecodeError(`pure-header frame ${FrameType[ty]} cannot carry a body`);
|
|
4385
|
-
}
|
|
4386
|
-
return {
|
|
4387
|
-
header: { len: body.length, ver, ty, flags, channel, corr },
|
|
4388
|
-
body
|
|
4389
|
-
};
|
|
4390
|
-
}
|
|
4391
|
-
function encodeFrame(frame) {
|
|
4392
|
-
const header = encodeHeader(frame.header);
|
|
4393
|
-
const out = new Uint8Array(header.length + frame.body.length);
|
|
4394
|
-
out.set(header, 0);
|
|
4395
|
-
out.set(frame.body, header.length);
|
|
4396
|
-
return out;
|
|
4397
|
-
}
|
|
4398
|
-
var PROTOCOL_VERSION = 1, HEADER_LEN = 17, FROZEN_PREFIX_LEN = 5, MAX_FRAME_BODY_LEN, FrameType, FRAME_TYPE_MAX = 11 /* Goodbye */, FLAG_BINARY = 1, FLAG_PRIORITY_MASK = 6, FLAG_PRIORITY_SHIFT = 1, FLAG_LAST = 8, FLAG_RESERVED_MASK = 240, DecodeError;
|
|
4399
|
-
var init_envelope = __esm(() => {
|
|
4400
|
-
MAX_FRAME_BODY_LEN = 64 * 1024 * 1024;
|
|
4401
|
-
((FrameType2) => {
|
|
4402
|
-
FrameType2[FrameType2["Request"] = 0] = "Request";
|
|
4403
|
-
FrameType2[FrameType2["Response"] = 1] = "Response";
|
|
4404
|
-
FrameType2[FrameType2["Push"] = 2] = "Push";
|
|
4405
|
-
FrameType2[FrameType2["StreamData"] = 3] = "StreamData";
|
|
4406
|
-
FrameType2[FrameType2["StreamEnd"] = 4] = "StreamEnd";
|
|
4407
|
-
FrameType2[FrameType2["Error"] = 5] = "Error";
|
|
4408
|
-
FrameType2[FrameType2["Cancel"] = 6] = "Cancel";
|
|
4409
|
-
FrameType2[FrameType2["Ping"] = 7] = "Ping";
|
|
4410
|
-
FrameType2[FrameType2["Pong"] = 8] = "Pong";
|
|
4411
|
-
FrameType2[FrameType2["Hello"] = 9] = "Hello";
|
|
4412
|
-
FrameType2[FrameType2["HelloAck"] = 10] = "HelloAck";
|
|
4413
|
-
FrameType2[FrameType2["Goodbye"] = 11] = "Goodbye";
|
|
4414
|
-
})(FrameType ||= {});
|
|
4415
|
-
DecodeError = class DecodeError extends Error {
|
|
4819
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.5.0/node_modules/@cortexkit/subc-client/dist/route-handle.js
|
|
4820
|
+
class RouteHandle {
|
|
4821
|
+
channel;
|
|
4822
|
+
epoch;
|
|
4823
|
+
constructor(channel, epoch, token) {
|
|
4824
|
+
if (!Number.isInteger(channel) || channel <= 0 || channel > 65535) {
|
|
4825
|
+
throw new RangeError(`route channel must be an integer in 1..65535, got ${channel}`);
|
|
4826
|
+
}
|
|
4827
|
+
if (!Number.isInteger(epoch) || epoch <= 0 || epoch > 4294967295) {
|
|
4828
|
+
throw new RangeError(`route epoch must be an integer in 1..4294967295, got ${epoch}`);
|
|
4829
|
+
}
|
|
4830
|
+
this.channel = channel;
|
|
4831
|
+
this.epoch = epoch;
|
|
4832
|
+
connectionToken.set(this, token);
|
|
4833
|
+
Object.freeze(this);
|
|
4834
|
+
}
|
|
4835
|
+
static create(channel, epoch, token) {
|
|
4836
|
+
return new RouteHandle(channel, epoch, token);
|
|
4837
|
+
}
|
|
4838
|
+
}
|
|
4839
|
+
function createRouteHandle(channel, epoch, token) {
|
|
4840
|
+
const factory = RouteHandle;
|
|
4841
|
+
return factory.create(channel, epoch, token);
|
|
4842
|
+
}
|
|
4843
|
+
function newConnectionToken() {
|
|
4844
|
+
return Object.freeze({});
|
|
4845
|
+
}
|
|
4846
|
+
function belongsToConnection(handle, token) {
|
|
4847
|
+
return connectionToken.get(handle) === token;
|
|
4848
|
+
}
|
|
4849
|
+
function sameRouteHandle(left, right) {
|
|
4850
|
+
return left === right;
|
|
4851
|
+
}
|
|
4852
|
+
var connectionToken, StaleRouteHandleError;
|
|
4853
|
+
var init_route_handle = __esm(() => {
|
|
4854
|
+
connectionToken = new WeakMap;
|
|
4855
|
+
StaleRouteHandleError = class StaleRouteHandleError extends Error {
|
|
4856
|
+
handle;
|
|
4857
|
+
code = "stale_route_handle";
|
|
4858
|
+
constructor(handle) {
|
|
4859
|
+
super(`route handle (${handle.channel}, ${handle.epoch}) is not live on the current connection`);
|
|
4860
|
+
this.handle = handle;
|
|
4861
|
+
this.name = "StaleRouteHandleError";
|
|
4862
|
+
}
|
|
4416
4863
|
};
|
|
4417
4864
|
});
|
|
4418
4865
|
|
|
4419
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
4866
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.5.0/node_modules/@cortexkit/subc-client/dist/socket.js
|
|
4420
4867
|
import net from "node:net";
|
|
4421
4868
|
|
|
4422
4869
|
class SubcSocket {
|
|
@@ -4465,6 +4912,24 @@ class SubcSocket {
|
|
|
4465
4912
|
});
|
|
4466
4913
|
});
|
|
4467
4914
|
}
|
|
4915
|
+
async readFrame(headerDeadlineMs, bodyDeadline, onHeader) {
|
|
4916
|
+
const prefix = await this.readExact(FROZEN_PREFIX_LEN, headerDeadlineMs);
|
|
4917
|
+
const version = prefix[4];
|
|
4918
|
+
if (version !== PROTOCOL_VERSION)
|
|
4919
|
+
throw new DecodeError(`unsupported envelope version ${version}`, "unsupported_version");
|
|
4920
|
+
const remainder = await this.readExact(HEADER_LEN - FROZEN_PREFIX_LEN, headerDeadlineMs);
|
|
4921
|
+
const headerBytes = new Uint8Array(HEADER_LEN);
|
|
4922
|
+
headerBytes.set(prefix);
|
|
4923
|
+
headerBytes.set(remainder, FROZEN_PREFIX_LEN);
|
|
4924
|
+
const header = decodeHeader(headerBytes);
|
|
4925
|
+
if (header.len > MAX_FRAME_BODY_LEN) {
|
|
4926
|
+
throw new DecodeError(`frame body ${header.len} exceeds max ${MAX_FRAME_BODY_LEN}`, "frame_body_too_large");
|
|
4927
|
+
}
|
|
4928
|
+
onHeader?.();
|
|
4929
|
+
const bodyDeadlineMs = typeof bodyDeadline === "number" ? bodyDeadline : Date.now() + bodyDeadline.afterHeaderMs;
|
|
4930
|
+
const body = header.len === 0 ? new Uint8Array(0) : await this.readExact(header.len, bodyDeadlineMs);
|
|
4931
|
+
return { header, body };
|
|
4932
|
+
}
|
|
4468
4933
|
readExact(n, deadlineMs) {
|
|
4469
4934
|
if (this.waiter) {
|
|
4470
4935
|
return Promise.reject(new Error("concurrent readExact is not supported"));
|
|
@@ -4587,6 +5052,7 @@ class SubcSocket {
|
|
|
4587
5052
|
}
|
|
4588
5053
|
var SocketClosedError, SocketTimeoutError, SocketWriteNotQueuedError, SocketWriteQueuedError;
|
|
4589
5054
|
var init_socket = __esm(() => {
|
|
5055
|
+
init_envelope();
|
|
4590
5056
|
SocketClosedError = class SocketClosedError extends Error {
|
|
4591
5057
|
};
|
|
4592
5058
|
SocketTimeoutError = class SocketTimeoutError extends Error {
|
|
@@ -4607,7 +5073,7 @@ var init_socket = __esm(() => {
|
|
|
4607
5073
|
};
|
|
4608
5074
|
});
|
|
4609
5075
|
|
|
4610
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
5076
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.5.0/node_modules/@cortexkit/subc-client/dist/client.js
|
|
4611
5077
|
import { promises as fs2 } from "node:fs";
|
|
4612
5078
|
import { debuglog } from "node:util";
|
|
4613
5079
|
|
|
@@ -4617,7 +5083,11 @@ class SubcClient {
|
|
|
4617
5083
|
opts;
|
|
4618
5084
|
nextCorr = 1n;
|
|
4619
5085
|
pending = new Map;
|
|
5086
|
+
lateResponses = new Map;
|
|
4620
5087
|
routes = new Map;
|
|
5088
|
+
liveRoutes = new Map;
|
|
5089
|
+
connectionToken = newConnectionToken();
|
|
5090
|
+
ingressEpochDropCount = 0;
|
|
4621
5091
|
closedErr = null;
|
|
4622
5092
|
closeStarted = false;
|
|
4623
5093
|
reconnecting = null;
|
|
@@ -4645,34 +5115,71 @@ class SubcClient {
|
|
|
4645
5115
|
}
|
|
4646
5116
|
async routeOpen(target, identity, opts = {}) {
|
|
4647
5117
|
const consumerIdentity = routeOpenConsumerIdentity(opts);
|
|
5118
|
+
const consumerCapabilities = opts.consumerCapabilities;
|
|
4648
5119
|
const body = this.encode({
|
|
4649
5120
|
op: "route.open",
|
|
4650
5121
|
target,
|
|
4651
5122
|
identity,
|
|
4652
|
-
...consumerIdentity ? { consumer_identity: consumerIdentity } : {}
|
|
5123
|
+
...consumerIdentity ? { consumer_identity: consumerIdentity } : {},
|
|
5124
|
+
...consumerCapabilities !== undefined ? { consumer_capabilities: consumerCapabilities } : {}
|
|
4653
5125
|
});
|
|
4654
|
-
|
|
4655
|
-
const
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
|
|
5126
|
+
let installed = null;
|
|
5127
|
+
const install = (frame) => {
|
|
5128
|
+
if (frame.header.ty !== FrameType.Response)
|
|
5129
|
+
return true;
|
|
5130
|
+
const parsed = this.parseJson(frame);
|
|
5131
|
+
if (typeof parsed.route_channel !== "number" || typeof parsed.route_epoch !== "number") {
|
|
5132
|
+
throw new SubcError(`route.open returned no route handle: ${JSON.stringify(parsed)}`);
|
|
5133
|
+
}
|
|
5134
|
+
installed = this.installRoute(parsed.route_channel, parsed.route_epoch);
|
|
5135
|
+
return true;
|
|
5136
|
+
};
|
|
5137
|
+
const closeLateRoute = (frame) => {
|
|
5138
|
+
if (frame.header.ty !== FrameType.Response)
|
|
5139
|
+
return;
|
|
5140
|
+
try {
|
|
5141
|
+
const parsed = this.parseJson(frame);
|
|
5142
|
+
if (typeof parsed.route_channel !== "number" || typeof parsed.route_epoch !== "number")
|
|
5143
|
+
return;
|
|
5144
|
+
const lateHandle = this.installRoute(parsed.route_channel, parsed.route_epoch);
|
|
5145
|
+
this.failHandle(lateHandle, new SubcError("late route.open was closed", "route_closed"));
|
|
5146
|
+
this.liveRoutes.delete(lateHandle.channel);
|
|
5147
|
+
this.sendRouteGoodbye(lateHandle, true);
|
|
5148
|
+
} catch {
|
|
5149
|
+
this.closeConnectionAfterCleanupFailure();
|
|
5150
|
+
}
|
|
5151
|
+
};
|
|
5152
|
+
await this.controlRpc(body, install, closeLateRoute);
|
|
5153
|
+
if (!installed)
|
|
5154
|
+
throw new SubcError("route.open response was not installed");
|
|
5155
|
+
return installed;
|
|
4660
5156
|
}
|
|
4661
|
-
async request(
|
|
5157
|
+
async request(handle, body, opts = {}) {
|
|
5158
|
+
this.assertLiveHandle(handle);
|
|
4662
5159
|
const bytes = body instanceof Uint8Array ? body : this.encode(body);
|
|
4663
|
-
const priority = opts.priority ??
|
|
4664
|
-
const
|
|
5160
|
+
const priority = opts.priority ?? Priority.Interactive;
|
|
5161
|
+
const admission = opts.admissionClass ?? AdmissionClass.Normal;
|
|
5162
|
+
const reply = await this.send(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress);
|
|
4665
5163
|
return this.parseJson(reply);
|
|
4666
5164
|
}
|
|
4667
5165
|
async call(moduleId, method, params, opts = {}) {
|
|
4668
5166
|
const body = params === undefined ? { method } : { method, params };
|
|
5167
|
+
let retriedUnknownChannel = false;
|
|
4669
5168
|
for (;; ) {
|
|
4670
|
-
const
|
|
5169
|
+
const routeHandle = await this.cachedRouteHandle(moduleId, opts);
|
|
4671
5170
|
try {
|
|
4672
|
-
return await this.managedRequest(
|
|
5171
|
+
return await this.managedRequest(routeHandle, body, opts);
|
|
4673
5172
|
} catch (err) {
|
|
4674
5173
|
if (!(err instanceof SubcCallError))
|
|
4675
5174
|
throw this.terminalCallError("managed call failed", err);
|
|
5175
|
+
if (err.code === "unknown_channel" && !retriedUnknownChannel && !this.closeStarted) {
|
|
5176
|
+
retriedUnknownChannel = true;
|
|
5177
|
+
this.evictRouteHandle(routeHandle);
|
|
5178
|
+
continue;
|
|
5179
|
+
}
|
|
5180
|
+
if (err.code === "unknown_channel" && retriedUnknownChannel) {
|
|
5181
|
+
this.evictRouteHandle(routeHandle);
|
|
5182
|
+
}
|
|
4676
5183
|
if (err.kind === "not_sent") {
|
|
4677
5184
|
try {
|
|
4678
5185
|
await this.reconnectAfterDrop(err);
|
|
@@ -4688,29 +5195,31 @@ class SubcClient {
|
|
|
4688
5195
|
}
|
|
4689
5196
|
}
|
|
4690
5197
|
}
|
|
4691
|
-
subscribe(
|
|
5198
|
+
subscribe(handle, body, onEvent, opts = {}) {
|
|
5199
|
+
this.assertLiveHandle(handle);
|
|
4692
5200
|
const bytes = body instanceof Uint8Array ? body : this.encode(body);
|
|
4693
|
-
const priority = opts.priority ??
|
|
4694
|
-
const
|
|
4695
|
-
const
|
|
5201
|
+
const priority = opts.priority ?? Priority.Interactive;
|
|
5202
|
+
const admission = opts.admissionClass ?? AdmissionClass.Normal;
|
|
5203
|
+
const corr = this.allocateCorr();
|
|
5204
|
+
const key = pendingKey(handle, corr);
|
|
4696
5205
|
const closed = new Promise((resolve7, reject) => {
|
|
4697
5206
|
if (this.closedErr) {
|
|
4698
5207
|
reject(this.closedErr);
|
|
4699
5208
|
return;
|
|
4700
5209
|
}
|
|
4701
5210
|
this.pending.set(key, {
|
|
4702
|
-
|
|
5211
|
+
handle,
|
|
4703
5212
|
resolve: () => resolve7(),
|
|
4704
5213
|
reject,
|
|
4705
5214
|
onProgress: onEvent,
|
|
4706
5215
|
timer: null,
|
|
4707
5216
|
subscription: true
|
|
4708
5217
|
});
|
|
4709
|
-
const frame = buildFrame(
|
|
5218
|
+
const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), handle.channel, handle.epoch, corr, bytes);
|
|
4710
5219
|
this.sock.write(encodeFrame(frame), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS).catch((err) => {
|
|
4711
|
-
const
|
|
4712
|
-
if (
|
|
4713
|
-
this.rejectPending(key,
|
|
5220
|
+
const pending = this.pending.get(key);
|
|
5221
|
+
if (pending)
|
|
5222
|
+
this.rejectPending(key, pending, err instanceof Error ? err : new SubcError(String(err)));
|
|
4714
5223
|
});
|
|
4715
5224
|
});
|
|
4716
5225
|
let cancelled = false;
|
|
@@ -4718,45 +5227,77 @@ class SubcClient {
|
|
|
4718
5227
|
if (cancelled)
|
|
4719
5228
|
return;
|
|
4720
5229
|
cancelled = true;
|
|
4721
|
-
|
|
4722
|
-
this.sock.write(encodeFrame(cancel), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS).catch(() => {});
|
|
5230
|
+
this.cancel(handle, corr, priority);
|
|
4723
5231
|
};
|
|
4724
5232
|
return { unsubscribe, closed };
|
|
4725
5233
|
}
|
|
4726
|
-
|
|
5234
|
+
cancel(handle, corr, priority = Priority.Interactive) {
|
|
5235
|
+
this.assertLiveHandle(handle);
|
|
5236
|
+
const cancel = buildFrame(FrameType.Cancel, buildFlags(false, priority, false), handle.channel, handle.epoch, corr, EMPTY_BODY);
|
|
5237
|
+
this.sock.write(encodeFrame(cancel), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS).catch(() => {
|
|
5238
|
+
return;
|
|
5239
|
+
});
|
|
5240
|
+
}
|
|
5241
|
+
async routePoll(handle, kind) {
|
|
5242
|
+
this.assertLiveHandle(handle);
|
|
5243
|
+
const body = this.encode({
|
|
5244
|
+
op: "route.poll",
|
|
5245
|
+
route_channel: handle.channel,
|
|
5246
|
+
route_epoch: handle.epoch,
|
|
5247
|
+
kind
|
|
5248
|
+
});
|
|
5249
|
+
const reply = await this.controlRpc(body, (frame) => {
|
|
5250
|
+
if (frame.header.ty !== FrameType.Response)
|
|
5251
|
+
return true;
|
|
5252
|
+
const parsed = this.parseJson(frame);
|
|
5253
|
+
return parsed.route_channel === handle.channel && parsed.route_epoch === handle.epoch;
|
|
5254
|
+
});
|
|
5255
|
+
return this.parseJson(reply);
|
|
5256
|
+
}
|
|
5257
|
+
async closeRoute(handle, opts = {}) {
|
|
5258
|
+
this.assertLiveHandle(handle);
|
|
5259
|
+
for (const [key, cached] of this.routes) {
|
|
5260
|
+
if (cached.handle && sameRouteHandle(cached.handle, handle)) {
|
|
5261
|
+
cached.closed = true;
|
|
5262
|
+
cached.handle = null;
|
|
5263
|
+
this.routes.delete(key);
|
|
5264
|
+
}
|
|
5265
|
+
}
|
|
5266
|
+
if (opts.drain)
|
|
5267
|
+
await this.drainUnaryOnHandle(handle);
|
|
5268
|
+
this.failHandle(handle, new SubcError("route closed by closeRoute", "route_closed"));
|
|
5269
|
+
if (this.liveRoutes.get(handle.channel) === handle)
|
|
5270
|
+
this.liveRoutes.delete(handle.channel);
|
|
5271
|
+
this.sendRouteGoodbye(handle);
|
|
5272
|
+
}
|
|
5273
|
+
async closeManagedRoute(target, identity, opts = {}) {
|
|
4727
5274
|
const key = routeCacheKey(target, identity, routeOpenConsumerIdentity(opts));
|
|
4728
5275
|
const cached = this.routes.get(key);
|
|
4729
5276
|
if (!cached)
|
|
4730
5277
|
return;
|
|
4731
5278
|
cached.closed = true;
|
|
4732
5279
|
this.routes.delete(key);
|
|
4733
|
-
const
|
|
4734
|
-
cached.
|
|
4735
|
-
if (
|
|
4736
|
-
await this.
|
|
5280
|
+
const handle = cached.handle;
|
|
5281
|
+
cached.handle = null;
|
|
5282
|
+
if (handle)
|
|
5283
|
+
await this.closeRoute(handle, opts);
|
|
4737
5284
|
}
|
|
4738
|
-
async closeRouteChannel(
|
|
4739
|
-
|
|
4740
|
-
return;
|
|
4741
|
-
if (opts.drain) {
|
|
4742
|
-
await this.drainUnaryOnChannel(channel);
|
|
4743
|
-
}
|
|
4744
|
-
this.failChannel(channel, new SubcError("route closed by closeRoute", "route_closed"));
|
|
4745
|
-
this.sendRouteGoodbye(channel);
|
|
5285
|
+
async closeRouteChannel(handle, opts = {}) {
|
|
5286
|
+
await this.closeRoute(handle, opts);
|
|
4746
5287
|
}
|
|
4747
5288
|
close() {
|
|
4748
5289
|
this.closeStarted = true;
|
|
4749
5290
|
this.fail(new SubcError("client closed"));
|
|
4750
5291
|
this.sock.close();
|
|
4751
5292
|
}
|
|
4752
|
-
|
|
5293
|
+
drainUnaryOnHandle(handle) {
|
|
4753
5294
|
const waiters = [];
|
|
4754
5295
|
for (const pending of this.pending.values()) {
|
|
4755
|
-
if (pending.
|
|
5296
|
+
if (pending.handle === handle && !pending.subscription) {
|
|
4756
5297
|
waiters.push(new Promise((resolve7) => {
|
|
4757
|
-
const
|
|
5298
|
+
const previous = pending.onSettle;
|
|
4758
5299
|
pending.onSettle = () => {
|
|
4759
|
-
|
|
5300
|
+
previous?.();
|
|
4760
5301
|
resolve7();
|
|
4761
5302
|
};
|
|
4762
5303
|
}));
|
|
@@ -4766,11 +5307,21 @@ class SubcClient {
|
|
|
4766
5307
|
return;
|
|
4767
5308
|
});
|
|
4768
5309
|
}
|
|
4769
|
-
sendRouteGoodbye(
|
|
4770
|
-
|
|
5310
|
+
sendRouteGoodbye(handle, closeOnQueueFailure = false) {
|
|
5311
|
+
this.assertLiveConnection(handle);
|
|
5312
|
+
if (this.closedErr) {
|
|
5313
|
+
if (closeOnQueueFailure)
|
|
5314
|
+
this.closeConnectionAfterCleanupFailure();
|
|
4771
5315
|
return;
|
|
4772
|
-
|
|
4773
|
-
|
|
5316
|
+
}
|
|
5317
|
+
const goodbye = buildFrame(FrameType.Goodbye, buildFlags(false, Priority.Interactive, false), handle.channel, handle.epoch, 0n, EMPTY_BODY);
|
|
5318
|
+
const write = this.sock.writeTracked(encodeFrame(goodbye), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS);
|
|
5319
|
+
if (!write.queued && closeOnQueueFailure)
|
|
5320
|
+
this.closeConnectionAfterCleanupFailure();
|
|
5321
|
+
write.completed.catch(() => {
|
|
5322
|
+
if (closeOnQueueFailure && !write.queued)
|
|
5323
|
+
this.closeConnectionAfterCleanupFailure();
|
|
5324
|
+
});
|
|
4774
5325
|
}
|
|
4775
5326
|
static async openConnection(opts) {
|
|
4776
5327
|
const conn = await readConnectionFile(opts.connectionFile);
|
|
@@ -4785,37 +5336,48 @@ class SubcClient {
|
|
|
4785
5336
|
}
|
|
4786
5337
|
return { sock, conn };
|
|
4787
5338
|
}
|
|
4788
|
-
async controlRpc(body) {
|
|
4789
|
-
return this.send(
|
|
5339
|
+
async controlRpc(body, acceptFrame, onLateResponse) {
|
|
5340
|
+
return this.send(null, body, Priority.Interactive, AdmissionClass.Normal, undefined, undefined, acceptFrame, onLateResponse);
|
|
4790
5341
|
}
|
|
4791
|
-
send(
|
|
5342
|
+
send(handle, body, priority, admission, timeoutMs, onProgress, acceptFrame, onLateResponse) {
|
|
5343
|
+
if (handle)
|
|
5344
|
+
this.assertLiveHandle(handle);
|
|
4792
5345
|
if (this.closedErr)
|
|
4793
5346
|
return Promise.reject(this.closedErr);
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
5347
|
+
let corr;
|
|
5348
|
+
try {
|
|
5349
|
+
corr = this.allocateCorr();
|
|
5350
|
+
} catch (error2) {
|
|
5351
|
+
return Promise.reject(error2);
|
|
5352
|
+
}
|
|
5353
|
+
const key = pendingKey(handle, corr);
|
|
5354
|
+
const channel = handle?.channel ?? 0;
|
|
5355
|
+
const epoch = handle?.epoch ?? 0;
|
|
5356
|
+
const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), channel, epoch, corr, body);
|
|
4797
5357
|
return new Promise((resolve7, reject) => {
|
|
4798
5358
|
const ms = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
4799
5359
|
const pending = {
|
|
4800
|
-
|
|
5360
|
+
handle,
|
|
4801
5361
|
resolve: resolve7,
|
|
4802
5362
|
reject,
|
|
4803
5363
|
onProgress,
|
|
4804
|
-
timer: null
|
|
5364
|
+
timer: null,
|
|
5365
|
+
acceptFrame,
|
|
5366
|
+
onLateResponse
|
|
4805
5367
|
};
|
|
4806
|
-
pending.timer = setTimeout(() =>
|
|
4807
|
-
this.arbitrateTimeout(key, pending, channel, corr, ms);
|
|
4808
|
-
}, ms);
|
|
5368
|
+
pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, channel, corr, ms), ms);
|
|
4809
5369
|
this.pending.set(key, pending);
|
|
4810
|
-
this.sock.write(encodeFrame(frame), Date.now() + ms).catch((
|
|
4811
|
-
const
|
|
4812
|
-
if (
|
|
4813
|
-
this.rejectPending(key,
|
|
5370
|
+
this.sock.write(encodeFrame(frame), Date.now() + ms).catch((error2) => {
|
|
5371
|
+
const current = this.pending.get(key);
|
|
5372
|
+
if (current)
|
|
5373
|
+
this.rejectPending(key, current, error2 instanceof Error ? error2 : new SubcError(String(error2)));
|
|
4814
5374
|
});
|
|
4815
5375
|
});
|
|
4816
5376
|
}
|
|
4817
5377
|
arbitrateTimeout(key, pending, channel, corr, ms) {
|
|
4818
5378
|
const settleAsTimeout = () => {
|
|
5379
|
+
if (pending.onLateResponse)
|
|
5380
|
+
this.lateResponses.set(key, pending.onLateResponse);
|
|
4819
5381
|
this.rejectPending(key, pending, new SubcError(this.timeoutMessage(channel, corr, ms), REQUEST_DEADLINE_MARKER));
|
|
4820
5382
|
};
|
|
4821
5383
|
const graceDeadline = Date.now() + this.opts.timeoutArbitrationGraceMs;
|
|
@@ -4831,59 +5393,67 @@ class SubcClient {
|
|
|
4831
5393
|
};
|
|
4832
5394
|
setImmediate(arbitrate);
|
|
4833
5395
|
}
|
|
4834
|
-
async managedRequest(
|
|
5396
|
+
async managedRequest(handle, body, opts) {
|
|
4835
5397
|
const bytes = body instanceof Uint8Array ? body : this.encode(body);
|
|
4836
|
-
const priority = opts.priority ??
|
|
5398
|
+
const priority = opts.priority ?? Priority.Interactive;
|
|
5399
|
+
const admission = opts.admissionClass ?? AdmissionClass.Normal;
|
|
4837
5400
|
try {
|
|
4838
|
-
const reply = await this.sendManaged(
|
|
5401
|
+
const reply = await this.sendManaged(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress);
|
|
4839
5402
|
return this.parseJson(reply);
|
|
4840
|
-
} catch (
|
|
4841
|
-
if (
|
|
4842
|
-
throw
|
|
4843
|
-
throw this.terminalCallError("managed call failed",
|
|
5403
|
+
} catch (error2) {
|
|
5404
|
+
if (error2 instanceof SubcCallError)
|
|
5405
|
+
throw error2;
|
|
5406
|
+
throw this.terminalCallError("managed call failed", error2);
|
|
4844
5407
|
}
|
|
4845
5408
|
}
|
|
4846
|
-
sendManaged(
|
|
5409
|
+
sendManaged(handle, body, priority, admission, timeoutMs, onProgress) {
|
|
5410
|
+
try {
|
|
5411
|
+
this.assertLiveHandle(handle);
|
|
5412
|
+
} catch (error2) {
|
|
5413
|
+
return Promise.reject(this.notSentCallError("request used a stale route handle", error2));
|
|
5414
|
+
}
|
|
4847
5415
|
if (this.closedErr) {
|
|
4848
5416
|
return Promise.reject(this.notSentCallError("request was not sent because the subc connection was already closed", this.closedErr));
|
|
4849
5417
|
}
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
5418
|
+
let corr;
|
|
5419
|
+
try {
|
|
5420
|
+
corr = this.allocateCorr();
|
|
5421
|
+
} catch (error2) {
|
|
5422
|
+
return Promise.reject(this.notSentCallError("request correlation allocator was exhausted", error2));
|
|
5423
|
+
}
|
|
5424
|
+
const key = pendingKey(handle, corr);
|
|
5425
|
+
const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), handle.channel, handle.epoch, corr, body);
|
|
4853
5426
|
let handedToSocket = false;
|
|
4854
|
-
const classifyFailure = (
|
|
4855
|
-
if (!handedToSocket)
|
|
4856
|
-
return this.notSentCallError("request bytes were not queued to the subc socket",
|
|
5427
|
+
const classifyFailure = (error2) => {
|
|
5428
|
+
if (!handedToSocket)
|
|
5429
|
+
return this.notSentCallError("request bytes were not queued to the subc socket", error2);
|
|
5430
|
+
if (error2 instanceof SubcError && error2.code === REQUEST_DEADLINE_MARKER) {
|
|
5431
|
+
return new SubcCallError("outcome_unknown", `managed call deadline exceeded after request bytes were queued to the local socket; no terminal response was observed; outcome unknown${causeMessage(error2)}`, DEADLINE_NO_DROP_CODE, error2);
|
|
4857
5432
|
}
|
|
4858
|
-
|
|
4859
|
-
return new SubcCallError("outcome_unknown", `managed call deadline exceeded after request bytes were queued to the local socket; no terminal response was observed; outcome unknown${causeMessage(err)}`, DEADLINE_NO_DROP_CODE, err);
|
|
4860
|
-
}
|
|
4861
|
-
return this.outcomeUnknownCallError("connection dropped before the managed call returned a response", err);
|
|
5433
|
+
return this.outcomeUnknownCallError("connection dropped before the managed call returned a response", error2);
|
|
4862
5434
|
};
|
|
4863
5435
|
return new Promise((resolve7, reject) => {
|
|
4864
5436
|
const ms = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
4865
5437
|
const pending = {
|
|
4866
|
-
|
|
5438
|
+
handle,
|
|
4867
5439
|
resolve: resolve7,
|
|
4868
5440
|
reject,
|
|
4869
5441
|
onProgress,
|
|
4870
5442
|
timer: null,
|
|
4871
5443
|
classifyFailure
|
|
4872
5444
|
};
|
|
4873
|
-
pending.timer = setTimeout(() =>
|
|
4874
|
-
this.arbitrateTimeout(key, pending, channel, corr, ms);
|
|
4875
|
-
}, ms);
|
|
5445
|
+
pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, handle.channel, corr, ms), ms);
|
|
4876
5446
|
this.pending.set(key, pending);
|
|
4877
5447
|
const write = this.sock.writeTracked(encodeFrame(frame), Date.now() + ms);
|
|
4878
5448
|
handedToSocket = write.queued;
|
|
4879
|
-
write.completed.catch((
|
|
4880
|
-
const
|
|
4881
|
-
if (
|
|
4882
|
-
this.rejectPending(key,
|
|
5449
|
+
write.completed.catch((error2) => {
|
|
5450
|
+
const current = this.pending.get(key);
|
|
5451
|
+
if (current)
|
|
5452
|
+
this.rejectPending(key, current, error2 instanceof Error ? error2 : new SubcError(String(error2)));
|
|
4883
5453
|
});
|
|
4884
5454
|
});
|
|
4885
5455
|
}
|
|
4886
|
-
async
|
|
5456
|
+
async cachedRouteHandle(moduleId, opts) {
|
|
4887
5457
|
const identity = opts.identity ?? this.opts.identity;
|
|
4888
5458
|
if (!identity) {
|
|
4889
5459
|
throw new SubcCallError("terminal", "managed call requires a BindIdentity in SubcClient.connect({ identity }) or call(..., { identity })", "missing_identity");
|
|
@@ -4899,15 +5469,13 @@ class SubcClient {
|
|
|
4899
5469
|
target,
|
|
4900
5470
|
identity,
|
|
4901
5471
|
consumerIdentity,
|
|
4902
|
-
|
|
4903
|
-
generation: 0,
|
|
5472
|
+
handle: null,
|
|
4904
5473
|
opening: null
|
|
4905
5474
|
};
|
|
4906
5475
|
this.routes.set(key, cached);
|
|
4907
5476
|
}
|
|
4908
|
-
if (cached.
|
|
4909
|
-
return cached.
|
|
4910
|
-
}
|
|
5477
|
+
if (cached.handle && this.isLiveHandle(cached.handle))
|
|
5478
|
+
return cached.handle;
|
|
4911
5479
|
if (!cached.opening) {
|
|
4912
5480
|
cached.opening = this.openCachedRoute(cached).finally(() => {
|
|
4913
5481
|
cached.opening = null;
|
|
@@ -4924,44 +5492,43 @@ class SubcClient {
|
|
|
4924
5492
|
throw this.routeClosedDuringOpen();
|
|
4925
5493
|
try {
|
|
4926
5494
|
await this.ensureConnectedForManaged();
|
|
4927
|
-
} catch (
|
|
4928
|
-
throw this.notSentRecoveryError("route.open could not run because reconnect failed",
|
|
4929
|
-
}
|
|
4930
|
-
if (cached.channel !== null && cached.generation === this.generation && !this.closedErr) {
|
|
4931
|
-
return cached.channel;
|
|
5495
|
+
} catch (error2) {
|
|
5496
|
+
throw this.notSentRecoveryError("route.open could not run because reconnect failed", error2);
|
|
4932
5497
|
}
|
|
5498
|
+
if (cached.handle && this.isLiveHandle(cached.handle))
|
|
5499
|
+
return cached.handle;
|
|
4933
5500
|
try {
|
|
4934
|
-
const
|
|
5501
|
+
const handle = await this.routeOpen(cached.target, cached.identity, {
|
|
4935
5502
|
consumerIdentity: cached.consumerIdentity ?? null
|
|
4936
5503
|
});
|
|
4937
5504
|
if (cached.closed) {
|
|
4938
|
-
this.
|
|
5505
|
+
this.liveRoutes.delete(handle.channel);
|
|
5506
|
+
this.sendRouteGoodbye(handle);
|
|
4939
5507
|
throw this.routeClosedDuringOpen();
|
|
4940
5508
|
}
|
|
4941
|
-
cached.
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
if (!this.closeStarted && isConsumerReconnectTransient(err)) {
|
|
5509
|
+
cached.handle = handle;
|
|
5510
|
+
return handle;
|
|
5511
|
+
} catch (error2) {
|
|
5512
|
+
if (error2 instanceof SubcCallError && error2.code === "route_closed")
|
|
5513
|
+
throw error2;
|
|
5514
|
+
if (!this.closeStarted && isConsumerReconnectTransient(error2)) {
|
|
4948
5515
|
try {
|
|
4949
|
-
await this.reconnectAfterDrop(
|
|
4950
|
-
} catch (
|
|
4951
|
-
throw this.notSentRecoveryError("route.open was not sent and reconnect failed",
|
|
5516
|
+
await this.reconnectAfterDrop(error2);
|
|
5517
|
+
} catch (reconnectError) {
|
|
5518
|
+
throw this.notSentRecoveryError("route.open was not sent and reconnect failed", reconnectError);
|
|
4952
5519
|
}
|
|
4953
5520
|
continue;
|
|
4954
5521
|
}
|
|
4955
|
-
if (!this.closeStarted &&
|
|
5522
|
+
if (!this.closeStarted && error2 instanceof SubcError && isRetryableRouteOpenCode(error2.code)) {
|
|
4956
5523
|
routeRetryAttempt += 1;
|
|
4957
5524
|
if (routeRetryAttempt < this.opts.reconnectBackoff.maxAttempts && Date.now() < routeRetryDeadline) {
|
|
4958
5525
|
await this.opts.sleep(routeRetryDelay);
|
|
4959
5526
|
routeRetryDelay = Math.min(routeRetryDelay * 2, this.opts.reconnectBackoff.capMs);
|
|
4960
5527
|
continue;
|
|
4961
5528
|
}
|
|
4962
|
-
throw this.notSentCallError(`route.open failed for module ${cached.moduleId}: ${
|
|
5529
|
+
throw this.notSentCallError(`route.open failed for module ${cached.moduleId}: ${error2.code} (retry budget exhausted)`, error2);
|
|
4963
5530
|
}
|
|
4964
|
-
throw this.terminalCallError(`route.open failed for module ${cached.moduleId}`,
|
|
5531
|
+
throw this.terminalCallError(`route.open failed for module ${cached.moduleId}`, error2);
|
|
4965
5532
|
}
|
|
4966
5533
|
}
|
|
4967
5534
|
}
|
|
@@ -5008,6 +5575,9 @@ class SubcClient {
|
|
|
5008
5575
|
return;
|
|
5009
5576
|
} catch (err) {
|
|
5010
5577
|
if (!isConsumerReconnectTransient(err) || attempt >= this.opts.reconnectBackoff.maxAttempts) {
|
|
5578
|
+
if (err instanceof AuthError && attempt > 1) {
|
|
5579
|
+
throw new AuthError(`reconnect gave up after ${attempt} attempts: ${err.message} — the connection file and the daemon's key disagree persistently ` + `(daemon restarting in a loop, split connection-file paths, or a genuinely foreign daemon on this port); ` + `check the daemon, then restart this host app`);
|
|
5580
|
+
}
|
|
5011
5581
|
throw err;
|
|
5012
5582
|
}
|
|
5013
5583
|
await this.opts.sleep(delay);
|
|
@@ -5021,25 +5591,27 @@ class SubcClient {
|
|
|
5021
5591
|
this.currentConn = opened.conn;
|
|
5022
5592
|
this.closedErr = null;
|
|
5023
5593
|
this.generation += 1;
|
|
5594
|
+
this.connectionToken = newConnectionToken();
|
|
5595
|
+
this.liveRoutes.clear();
|
|
5596
|
+
this.lateResponses.clear();
|
|
5597
|
+
this.nextCorr = 1n;
|
|
5024
5598
|
this.readLoop(opened.sock, this.generation);
|
|
5025
5599
|
}
|
|
5026
5600
|
async reopenCachedRoutes() {
|
|
5027
|
-
for (const cached of this.routes.values())
|
|
5028
|
-
cached.
|
|
5029
|
-
cached.generation = 0;
|
|
5030
|
-
}
|
|
5601
|
+
for (const cached of this.routes.values())
|
|
5602
|
+
cached.handle = null;
|
|
5031
5603
|
for (const cached of this.routes.values()) {
|
|
5032
5604
|
if (cached.closed)
|
|
5033
5605
|
continue;
|
|
5034
|
-
const
|
|
5606
|
+
const handle = await this.routeOpen(cached.target, cached.identity, {
|
|
5035
5607
|
consumerIdentity: cached.consumerIdentity ?? null
|
|
5036
5608
|
});
|
|
5037
5609
|
if (cached.closed) {
|
|
5038
|
-
this.
|
|
5610
|
+
this.liveRoutes.delete(handle.channel);
|
|
5611
|
+
this.sendRouteGoodbye(handle);
|
|
5039
5612
|
continue;
|
|
5040
5613
|
}
|
|
5041
|
-
cached.
|
|
5042
|
-
cached.generation = this.generation;
|
|
5614
|
+
cached.handle = handle;
|
|
5043
5615
|
}
|
|
5044
5616
|
}
|
|
5045
5617
|
timeoutMessage(channel, corr, ms) {
|
|
@@ -5053,52 +5625,69 @@ class SubcClient {
|
|
|
5053
5625
|
async readLoop(sock, generation) {
|
|
5054
5626
|
try {
|
|
5055
5627
|
for (;; ) {
|
|
5056
|
-
|
|
5057
|
-
|
|
5628
|
+
this.readerActive = false;
|
|
5629
|
+
const frame = await sock.readFrame(Number.POSITIVE_INFINITY, { afterHeaderMs: BODY_READ_TIMEOUT_MS }, () => {
|
|
5630
|
+
this.readerActive = true;
|
|
5631
|
+
});
|
|
5058
5632
|
try {
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
if (this.sock === sock && this.generation === generation) {
|
|
5062
|
-
this.dispatch({ header, body });
|
|
5063
|
-
}
|
|
5633
|
+
if (this.sock === sock && this.generation === generation)
|
|
5634
|
+
this.dispatch(frame);
|
|
5064
5635
|
} finally {
|
|
5065
5636
|
this.readerActive = false;
|
|
5066
5637
|
}
|
|
5067
5638
|
}
|
|
5068
|
-
} catch (
|
|
5639
|
+
} catch (error2) {
|
|
5069
5640
|
if (this.sock === sock && this.generation === generation) {
|
|
5070
|
-
this.fail(
|
|
5641
|
+
this.fail(error2 instanceof Error ? error2 : new SubcError(String(error2)));
|
|
5071
5642
|
}
|
|
5072
5643
|
}
|
|
5073
5644
|
}
|
|
5074
5645
|
dispatch(frame) {
|
|
5075
|
-
|
|
5646
|
+
let handle = null;
|
|
5647
|
+
if (frame.header.channel !== 0) {
|
|
5648
|
+
handle = this.liveRoutes.get(frame.header.channel) ?? null;
|
|
5649
|
+
if (!handle || handle.epoch !== frame.header.epoch) {
|
|
5650
|
+
this.ingressEpochDropCount += 1;
|
|
5651
|
+
return;
|
|
5652
|
+
}
|
|
5653
|
+
}
|
|
5654
|
+
const key = pendingKey(handle, frame.header.corr);
|
|
5076
5655
|
const pending = this.pending.get(key);
|
|
5077
5656
|
if (pending) {
|
|
5657
|
+
if (pending.acceptFrame && !pending.acceptFrame(frame))
|
|
5658
|
+
return;
|
|
5078
5659
|
switch (frame.header.ty) {
|
|
5079
|
-
case
|
|
5080
|
-
case
|
|
5660
|
+
case FrameType.Push:
|
|
5661
|
+
case FrameType.StreamData:
|
|
5081
5662
|
pending.onProgress?.(frame.body);
|
|
5082
5663
|
return;
|
|
5083
|
-
case
|
|
5084
|
-
case
|
|
5664
|
+
case FrameType.Response:
|
|
5665
|
+
case FrameType.StreamEnd:
|
|
5085
5666
|
this.settle(key, pending, () => pending.resolve(frame));
|
|
5086
5667
|
return;
|
|
5087
|
-
case
|
|
5668
|
+
case FrameType.Error:
|
|
5088
5669
|
this.settle(key, pending, () => pending.reject(this.errorFromFrame(frame)));
|
|
5089
5670
|
return;
|
|
5090
5671
|
default:
|
|
5091
5672
|
return;
|
|
5092
5673
|
}
|
|
5093
5674
|
}
|
|
5094
|
-
|
|
5095
|
-
|
|
5675
|
+
const late = this.lateResponses.get(key);
|
|
5676
|
+
if (late && (frame.header.ty === FrameType.Response || frame.header.ty === FrameType.Error)) {
|
|
5677
|
+
this.lateResponses.delete(key);
|
|
5678
|
+
late(frame);
|
|
5096
5679
|
return;
|
|
5097
5680
|
}
|
|
5098
|
-
if (frame.header.ty ===
|
|
5099
|
-
|
|
5681
|
+
if (frame.header.ty === FrameType.Goodbye && handle) {
|
|
5682
|
+
this.failHandle(handle, new SubcError("route closed by subc (GOODBYE)"));
|
|
5683
|
+
if (this.liveRoutes.get(handle.channel) === handle)
|
|
5684
|
+
this.liveRoutes.delete(handle.channel);
|
|
5685
|
+
this.evictRouteHandle(handle);
|
|
5100
5686
|
return;
|
|
5101
5687
|
}
|
|
5688
|
+
if (frame.header.ty === FrameType.Response || frame.header.ty === FrameType.Error || frame.header.ty === FrameType.StreamEnd) {
|
|
5689
|
+
debug("dropped terminal frame with no waiter: type=%d channel=%d epoch=%d corr=%s port=%s", frame.header.ty, frame.header.channel, frame.header.epoch, frame.header.corr, this.sock.localPort() ?? "?");
|
|
5690
|
+
}
|
|
5102
5691
|
}
|
|
5103
5692
|
settle(key, pending, run) {
|
|
5104
5693
|
if (this.pending.get(key) !== pending)
|
|
@@ -5121,11 +5710,16 @@ class SubcClient {
|
|
|
5121
5710
|
return new SubcError(Buffer.from(frame.body).toString("utf8") || "subc error");
|
|
5122
5711
|
}
|
|
5123
5712
|
}
|
|
5124
|
-
|
|
5713
|
+
evictRouteHandle(handle) {
|
|
5714
|
+
for (const cached of this.routes.values()) {
|
|
5715
|
+
if (cached.handle && sameRouteHandle(cached.handle, handle))
|
|
5716
|
+
cached.handle = null;
|
|
5717
|
+
}
|
|
5718
|
+
}
|
|
5719
|
+
failHandle(handle, error2) {
|
|
5125
5720
|
for (const [key, pending] of this.pending) {
|
|
5126
|
-
if (pending.
|
|
5127
|
-
this.rejectPending(key, pending,
|
|
5128
|
-
}
|
|
5721
|
+
if (pending.handle && sameRouteHandle(pending.handle, handle))
|
|
5722
|
+
this.rejectPending(key, pending, error2);
|
|
5129
5723
|
}
|
|
5130
5724
|
}
|
|
5131
5725
|
fail(err) {
|
|
@@ -5153,6 +5747,44 @@ class SubcClient {
|
|
|
5153
5747
|
return this.notSentCallError(message, cause);
|
|
5154
5748
|
return this.terminalCallError(message, cause);
|
|
5155
5749
|
}
|
|
5750
|
+
get droppedIngressFrames() {
|
|
5751
|
+
return this.ingressEpochDropCount;
|
|
5752
|
+
}
|
|
5753
|
+
installRoute(channel, epoch) {
|
|
5754
|
+
const handle = createRouteHandle(channel, epoch, this.connectionToken);
|
|
5755
|
+
this.liveRoutes.set(channel, handle);
|
|
5756
|
+
return handle;
|
|
5757
|
+
}
|
|
5758
|
+
isLiveHandle(handle) {
|
|
5759
|
+
return belongsToConnection(handle, this.connectionToken) && this.liveRoutes.get(handle.channel) === handle;
|
|
5760
|
+
}
|
|
5761
|
+
assertLiveConnection(handle) {
|
|
5762
|
+
if (!belongsToConnection(handle, this.connectionToken))
|
|
5763
|
+
throw new StaleRouteHandleError(handle);
|
|
5764
|
+
}
|
|
5765
|
+
assertLiveHandle(handle) {
|
|
5766
|
+
if (!this.isLiveHandle(handle))
|
|
5767
|
+
throw new StaleRouteHandleError(handle);
|
|
5768
|
+
}
|
|
5769
|
+
allocateCorr() {
|
|
5770
|
+
const maximum = 0xffffffffffffffffn;
|
|
5771
|
+
if (this.nextCorr > maximum) {
|
|
5772
|
+
const error2 = new SubcError("channel-0 correlation id allocator exhausted", "corr_exhausted");
|
|
5773
|
+
this.fail(error2);
|
|
5774
|
+
this.sock.close();
|
|
5775
|
+
this.scheduleReconnectAfterDrop(error2);
|
|
5776
|
+
throw error2;
|
|
5777
|
+
}
|
|
5778
|
+
const corr = this.nextCorr;
|
|
5779
|
+
this.nextCorr += 1n;
|
|
5780
|
+
return corr;
|
|
5781
|
+
}
|
|
5782
|
+
closeConnectionAfterCleanupFailure() {
|
|
5783
|
+
const error2 = new SubcError("late route cleanup could not be queued", "late_route_cleanup_failed");
|
|
5784
|
+
this.fail(error2);
|
|
5785
|
+
this.sock.close();
|
|
5786
|
+
this.scheduleReconnectAfterDrop(error2);
|
|
5787
|
+
}
|
|
5156
5788
|
encode(value) {
|
|
5157
5789
|
return new Uint8Array(Buffer.from(JSON.stringify(value), "utf8"));
|
|
5158
5790
|
}
|
|
@@ -5167,7 +5799,9 @@ function isConsumerReconnectTransient(err) {
|
|
|
5167
5799
|
return true;
|
|
5168
5800
|
if (err instanceof SubcCallError)
|
|
5169
5801
|
return err.kind === "not_sent" || err.kind === "outcome_unknown";
|
|
5170
|
-
if (err instanceof
|
|
5802
|
+
if (err instanceof AuthError)
|
|
5803
|
+
return true;
|
|
5804
|
+
if (err instanceof SubcError || err instanceof ConnectionFileError)
|
|
5171
5805
|
return false;
|
|
5172
5806
|
const code = errorCode(err);
|
|
5173
5807
|
return code === "ECONNREFUSED" || code === "ECONNRESET" || code === "EPIPE" || code === "ETIMEDOUT" || code === "ENOENT";
|
|
@@ -5220,11 +5854,15 @@ function causeMessage(cause) {
|
|
|
5220
5854
|
return "";
|
|
5221
5855
|
return `: ${cause instanceof Error ? cause.message : String(cause)}`;
|
|
5222
5856
|
}
|
|
5223
|
-
|
|
5857
|
+
function pendingKey(handle, corr) {
|
|
5858
|
+
return handle ? `${handle.channel}:${handle.epoch}:${corr}` : `0:0:${corr}`;
|
|
5859
|
+
}
|
|
5860
|
+
var debug, DEFAULT_HANDSHAKE_TIMEOUT_MS = 1e4, DEFAULT_REQUEST_TIMEOUT_MS = 30000, TIMEOUT_ARBITRATION_GRACE_MS = 50, REQUEST_DEADLINE_MARKER = "request_deadline", DEADLINE_NO_DROP_CODE = "deadline_exceeded_no_drop_observed", ROUTE_OPEN_RETRY_DEADLINE_MS = 30000, BODY_READ_TIMEOUT_MS = 30000, EMPTY_BODY, DEFAULT_MANAGED_TARGET_KIND = "management_surface", SUBC_MODULE_ID_ENV = "SUBC_MODULE_ID", SUBC_LAUNCH_NONCE_ENV = "SUBC_LAUNCH_NONCE", DEFAULT_RECONNECT_BACKOFF, SubcCallError, SubcError;
|
|
5224
5861
|
var init_client = __esm(() => {
|
|
5225
5862
|
init_auth();
|
|
5226
5863
|
init_connection_file();
|
|
5227
5864
|
init_envelope();
|
|
5865
|
+
init_route_handle();
|
|
5228
5866
|
init_socket();
|
|
5229
5867
|
debug = debuglog("subc-client");
|
|
5230
5868
|
EMPTY_BODY = new Uint8Array(0);
|
|
@@ -5254,9 +5892,44 @@ var init_client = __esm(() => {
|
|
|
5254
5892
|
};
|
|
5255
5893
|
});
|
|
5256
5894
|
|
|
5257
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
5895
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.5.0/node_modules/@cortexkit/subc-client/dist/provider.js
|
|
5258
5896
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
5259
5897
|
|
|
5898
|
+
class AsyncPermitPool {
|
|
5899
|
+
available;
|
|
5900
|
+
waiters = [];
|
|
5901
|
+
constructor(capacity) {
|
|
5902
|
+
if (!Number.isInteger(capacity) || capacity <= 0) {
|
|
5903
|
+
throw new SubcProviderError("provider handler capacity must be a positive integer", "invalid_handler_capacity");
|
|
5904
|
+
}
|
|
5905
|
+
this.available = capacity;
|
|
5906
|
+
}
|
|
5907
|
+
async acquire() {
|
|
5908
|
+
if (this.available > 0) {
|
|
5909
|
+
this.available -= 1;
|
|
5910
|
+
return this.releaseOnce();
|
|
5911
|
+
}
|
|
5912
|
+
await new Promise((resolve7) => {
|
|
5913
|
+
this.waiters.push(resolve7);
|
|
5914
|
+
});
|
|
5915
|
+
return this.releaseOnce();
|
|
5916
|
+
}
|
|
5917
|
+
releaseOnce() {
|
|
5918
|
+
let released = false;
|
|
5919
|
+
return () => {
|
|
5920
|
+
if (released)
|
|
5921
|
+
return;
|
|
5922
|
+
released = true;
|
|
5923
|
+
const next = this.waiters.shift();
|
|
5924
|
+
if (next) {
|
|
5925
|
+
next();
|
|
5926
|
+
} else {
|
|
5927
|
+
this.available += 1;
|
|
5928
|
+
}
|
|
5929
|
+
};
|
|
5930
|
+
}
|
|
5931
|
+
}
|
|
5932
|
+
|
|
5260
5933
|
class SubcProvider {
|
|
5261
5934
|
sock;
|
|
5262
5935
|
currentConn;
|
|
@@ -5268,6 +5941,12 @@ class SubcProvider {
|
|
|
5268
5941
|
closeStarted = false;
|
|
5269
5942
|
closedErr = null;
|
|
5270
5943
|
inflight = new Map;
|
|
5944
|
+
pending = new Map;
|
|
5945
|
+
liveRoutes = new Map;
|
|
5946
|
+
connectionToken = newConnectionToken();
|
|
5947
|
+
nextCorr = 1n;
|
|
5948
|
+
ingressEpochDropCount = 0;
|
|
5949
|
+
requestGate = new AsyncPermitPool(DEFAULT_PROVIDER_HANDLER_CAPACITY);
|
|
5271
5950
|
reconnecting = null;
|
|
5272
5951
|
generation = 1;
|
|
5273
5952
|
connectionEpoch = 1;
|
|
@@ -5286,12 +5965,55 @@ class SubcProvider {
|
|
|
5286
5965
|
this.readLoop(sock, this.generation);
|
|
5287
5966
|
this.enqueueConnectionState({ state: "connected", epoch: this.connectionEpoch });
|
|
5288
5967
|
}
|
|
5968
|
+
get droppedIngressFrames() {
|
|
5969
|
+
return this.ingressEpochDropCount;
|
|
5970
|
+
}
|
|
5289
5971
|
get conn() {
|
|
5290
5972
|
return this.currentConn;
|
|
5291
5973
|
}
|
|
5292
5974
|
currentEpoch() {
|
|
5293
5975
|
return this.connectionEpoch;
|
|
5294
5976
|
}
|
|
5977
|
+
async request(handle, body, opts = {}) {
|
|
5978
|
+
this.assertLiveHandle(handle);
|
|
5979
|
+
const corr = this.allocateCorr();
|
|
5980
|
+
const key = routeKey(handle, corr);
|
|
5981
|
+
const timeoutMs = opts.timeoutMs ?? WRITE_TIMEOUT_MS;
|
|
5982
|
+
const frame = buildFrame(FrameType.Request, buildFlags(false, opts.priority ?? Priority.Interactive, false, opts.admissionClass ?? AdmissionClass.Normal), handle.channel, handle.epoch, corr, body);
|
|
5983
|
+
return await new Promise((resolve7, reject) => {
|
|
5984
|
+
const timer = setTimeout(() => {
|
|
5985
|
+
if (this.pending.delete(key))
|
|
5986
|
+
reject(new SubcProviderError("reverse request timed out", "request_timeout"));
|
|
5987
|
+
}, timeoutMs);
|
|
5988
|
+
this.pending.set(key, {
|
|
5989
|
+
resolve: (response) => resolve7(response.body),
|
|
5990
|
+
reject,
|
|
5991
|
+
timer
|
|
5992
|
+
});
|
|
5993
|
+
this.sendOn(this.sock, this.generation, frame).catch((error2) => {
|
|
5994
|
+
const pending = this.pending.get(key);
|
|
5995
|
+
if (!pending)
|
|
5996
|
+
return;
|
|
5997
|
+
this.pending.delete(key);
|
|
5998
|
+
clearTimeout(pending.timer);
|
|
5999
|
+
reject(error2 instanceof Error ? error2 : new SubcProviderError(String(error2)));
|
|
6000
|
+
});
|
|
6001
|
+
});
|
|
6002
|
+
}
|
|
6003
|
+
async push(handle, body, opts = {}) {
|
|
6004
|
+
this.assertLiveHandle(handle);
|
|
6005
|
+
await this.sendOn(this.sock, this.generation, buildFrame(FrameType.Push, buildFlags(false, opts.priority ?? Priority.Interactive, false, opts.admissionClass ?? AdmissionClass.Normal), handle.channel, handle.epoch, 0n, body));
|
|
6006
|
+
}
|
|
6007
|
+
cancel(handle, corr) {
|
|
6008
|
+
this.assertLiveHandle(handle);
|
|
6009
|
+
this.sendOn(this.sock, this.generation, buildFrame(FrameType.Cancel, controlFlags(), handle.channel, handle.epoch, corr, new Uint8Array(0)));
|
|
6010
|
+
}
|
|
6011
|
+
closeRoute(handle) {
|
|
6012
|
+
this.assertLiveHandle(handle);
|
|
6013
|
+
this.liveRoutes.delete(handle.channel);
|
|
6014
|
+
this.abortHandle(handle);
|
|
6015
|
+
this.sendOn(this.sock, this.generation, buildFrame(FrameType.Goodbye, controlFlags(), handle.channel, handle.epoch, 0n, new Uint8Array(0)));
|
|
6016
|
+
}
|
|
5295
6017
|
static async connect(opts) {
|
|
5296
6018
|
if (opts.manifest.protocol_ver !== PROTOCOL_VERSION) {
|
|
5297
6019
|
throw new SubcProviderError(`manifest protocol_ver ${opts.manifest.protocol_ver} does not match client protocol ${PROTOCOL_VERSION}`, "invalid_manifest");
|
|
@@ -5306,7 +6028,7 @@ class SubcProvider {
|
|
|
5306
6028
|
this.cancelRestoredDebounce();
|
|
5307
6029
|
const sock = this.sock;
|
|
5308
6030
|
try {
|
|
5309
|
-
await sendFrame(sock, buildFrame(
|
|
6031
|
+
await sendFrame(sock, buildFrame(FrameType.Goodbye, controlFlags(), 0, 0, 0n, new Uint8Array(0)));
|
|
5310
6032
|
} catch {} finally {
|
|
5311
6033
|
sock.close();
|
|
5312
6034
|
this.finishClosed();
|
|
@@ -5314,12 +6036,13 @@ class SubcProvider {
|
|
|
5314
6036
|
}
|
|
5315
6037
|
await this.closed;
|
|
5316
6038
|
}
|
|
5317
|
-
static async openConnection(opts) {
|
|
6039
|
+
static async openConnection(opts, onSocket) {
|
|
5318
6040
|
const conn = await readConnectionFile(opts.connectionFile);
|
|
5319
6041
|
const deadline = Date.now() + (opts.handshakeTimeoutMs ?? DEFAULT_HANDSHAKE_TIMEOUT_MS2);
|
|
5320
6042
|
const endpoint = conn.endpoints[0];
|
|
5321
6043
|
const sock = await SubcSocket.connect(endpoint.host, endpoint.port, deadline);
|
|
5322
6044
|
try {
|
|
6045
|
+
onSocket?.(sock);
|
|
5323
6046
|
await authenticateClient(sock, conn, deadline);
|
|
5324
6047
|
await sendFrame(sock, buildHelloFrame(opts));
|
|
5325
6048
|
const ack = await expectHelloAck(sock, deadline);
|
|
@@ -5332,19 +6055,17 @@ class SubcProvider {
|
|
|
5332
6055
|
async readLoop(sock, generation) {
|
|
5333
6056
|
try {
|
|
5334
6057
|
for (;; ) {
|
|
5335
|
-
const
|
|
5336
|
-
const
|
|
5337
|
-
const body = header.len === 0 ? new Uint8Array(0) : await sock.readExact(header.len, Date.now() + BODY_READ_TIMEOUT_MS2);
|
|
5338
|
-
const keepGoing = await this.dispatch({ header, body }, sock, generation);
|
|
6058
|
+
const frame = await sock.readFrame(Number.POSITIVE_INFINITY, { afterHeaderMs: BODY_READ_TIMEOUT_MS2 });
|
|
6059
|
+
const keepGoing = await this.dispatch(frame, sock, generation);
|
|
5339
6060
|
if (!keepGoing) {
|
|
5340
6061
|
if (this.sock === sock && this.generation === generation)
|
|
5341
6062
|
this.closeStarted = true;
|
|
5342
6063
|
break;
|
|
5343
6064
|
}
|
|
5344
6065
|
}
|
|
5345
|
-
} catch (
|
|
6066
|
+
} catch (error2) {
|
|
5346
6067
|
if (this.sock === sock && this.generation === generation && !this.closeStarted) {
|
|
5347
|
-
this.handleUnexpectedDrop(sock, generation,
|
|
6068
|
+
this.handleUnexpectedDrop(sock, generation, error2 instanceof Error ? error2 : new SubcProviderError(String(error2)));
|
|
5348
6069
|
return;
|
|
5349
6070
|
}
|
|
5350
6071
|
} finally {
|
|
@@ -5356,28 +6077,58 @@ class SubcProvider {
|
|
|
5356
6077
|
}
|
|
5357
6078
|
}
|
|
5358
6079
|
async dispatch(frame, sock, generation) {
|
|
6080
|
+
let handle = null;
|
|
6081
|
+
if (frame.header.channel !== 0) {
|
|
6082
|
+
handle = this.liveRoutes.get(frame.header.channel) ?? null;
|
|
6083
|
+
if (!handle || handle.epoch !== frame.header.epoch) {
|
|
6084
|
+
this.ingressEpochDropCount += 1;
|
|
6085
|
+
return true;
|
|
6086
|
+
}
|
|
6087
|
+
}
|
|
6088
|
+
if (handle) {
|
|
6089
|
+
const pendingKey2 = routeKey(handle, frame.header.corr);
|
|
6090
|
+
const pending = this.pending.get(pendingKey2);
|
|
6091
|
+
if (pending) {
|
|
6092
|
+
if (frame.header.ty === FrameType.Push || frame.header.ty === FrameType.StreamData)
|
|
6093
|
+
return true;
|
|
6094
|
+
if (frame.header.ty === FrameType.Response || frame.header.ty === FrameType.StreamEnd) {
|
|
6095
|
+
this.pending.delete(pendingKey2);
|
|
6096
|
+
clearTimeout(pending.timer);
|
|
6097
|
+
pending.resolve(frame);
|
|
6098
|
+
return true;
|
|
6099
|
+
}
|
|
6100
|
+
if (frame.header.ty === FrameType.Error) {
|
|
6101
|
+
this.pending.delete(pendingKey2);
|
|
6102
|
+
clearTimeout(pending.timer);
|
|
6103
|
+
pending.reject(providerErrorFromFrame(frame));
|
|
6104
|
+
return true;
|
|
6105
|
+
}
|
|
6106
|
+
}
|
|
6107
|
+
}
|
|
5359
6108
|
switch (frame.header.ty) {
|
|
5360
|
-
case
|
|
6109
|
+
case FrameType.Ping:
|
|
5361
6110
|
if (frame.header.channel === 0) {
|
|
5362
|
-
await this.sendOn(sock, generation, buildFrameWithVersion(frame.header.ver,
|
|
6111
|
+
await this.sendOn(sock, generation, buildFrameWithVersion(frame.header.ver, FrameType.Pong, frame.header.flags, 0, 0, frame.header.corr, new Uint8Array(0)));
|
|
5363
6112
|
}
|
|
5364
6113
|
return true;
|
|
5365
|
-
case
|
|
5366
|
-
if (
|
|
6114
|
+
case FrameType.Goodbye:
|
|
6115
|
+
if (!handle)
|
|
5367
6116
|
return false;
|
|
5368
|
-
this.
|
|
5369
|
-
|
|
6117
|
+
this.liveRoutes.delete(handle.channel);
|
|
6118
|
+
this.abortHandle(handle);
|
|
6119
|
+
await this.opts.onRouteGone?.(handle);
|
|
5370
6120
|
return true;
|
|
5371
|
-
case
|
|
5372
|
-
|
|
6121
|
+
case FrameType.Cancel:
|
|
6122
|
+
if (handle)
|
|
6123
|
+
this.inflight.get(routeKey(handle, frame.header.corr))?.abort();
|
|
5373
6124
|
return true;
|
|
5374
|
-
case
|
|
6125
|
+
case FrameType.Request:
|
|
5375
6126
|
if (frame.header.channel === 0) {
|
|
5376
6127
|
await this.handleControlRequest(frame, sock, generation);
|
|
5377
|
-
} else {
|
|
5378
|
-
this.handleDataRequest(frame, sock, generation).catch((
|
|
6128
|
+
} else if (handle) {
|
|
6129
|
+
this.handleDataRequest(frame, handle, sock, generation).catch((error2) => {
|
|
5379
6130
|
if (!this.closeStarted && this.sock === sock && this.generation === generation) {
|
|
5380
|
-
console.warn("SubcProvider handler failed after its request was dispatched",
|
|
6131
|
+
console.warn("SubcProvider handler failed after its request was dispatched", error2);
|
|
5381
6132
|
}
|
|
5382
6133
|
});
|
|
5383
6134
|
}
|
|
@@ -5386,19 +6137,28 @@ class SubcProvider {
|
|
|
5386
6137
|
return true;
|
|
5387
6138
|
}
|
|
5388
6139
|
}
|
|
5389
|
-
|
|
5390
|
-
const prefix = `${
|
|
6140
|
+
abortHandle(handle) {
|
|
6141
|
+
const prefix = `${handle.channel}:${handle.epoch}:`;
|
|
5391
6142
|
for (const [key, controller] of this.inflight) {
|
|
5392
6143
|
if (key.startsWith(prefix))
|
|
5393
6144
|
controller.abort();
|
|
5394
6145
|
}
|
|
6146
|
+
for (const [key, pending] of this.pending) {
|
|
6147
|
+
if (!key.startsWith(prefix))
|
|
6148
|
+
continue;
|
|
6149
|
+
this.pending.delete(key);
|
|
6150
|
+
clearTimeout(pending.timer);
|
|
6151
|
+
pending.reject(new StaleRouteHandleError(handle));
|
|
6152
|
+
}
|
|
5395
6153
|
}
|
|
5396
|
-
abortGeneration(
|
|
5397
|
-
|
|
5398
|
-
for (const [key,
|
|
5399
|
-
|
|
5400
|
-
|
|
6154
|
+
abortGeneration(_generation) {
|
|
6155
|
+
this.abortAllInflight();
|
|
6156
|
+
for (const [key, pending] of this.pending) {
|
|
6157
|
+
this.pending.delete(key);
|
|
6158
|
+
clearTimeout(pending.timer);
|
|
6159
|
+
pending.reject(new SubcProviderError("provider connection dropped", "connection_dropped"));
|
|
5401
6160
|
}
|
|
6161
|
+
this.liveRoutes.clear();
|
|
5402
6162
|
}
|
|
5403
6163
|
abortAllInflight() {
|
|
5404
6164
|
for (const controller of this.inflight.values())
|
|
@@ -5406,56 +6166,136 @@ class SubcProvider {
|
|
|
5406
6166
|
}
|
|
5407
6167
|
async handleControlRequest(frame, sock, generation) {
|
|
5408
6168
|
const request = parseJson(frame.body);
|
|
6169
|
+
if (request.op === HEALTH_CHECK_OP) {
|
|
6170
|
+
this.handleHealthRequest(frame, sock, generation).catch((error2) => {
|
|
6171
|
+
if (!this.closeStarted && this.sock === sock && this.generation === generation) {
|
|
6172
|
+
console.warn("SubcProvider health handler failed after its request was dispatched", error2);
|
|
6173
|
+
}
|
|
6174
|
+
});
|
|
6175
|
+
return;
|
|
6176
|
+
}
|
|
5409
6177
|
if (request.op !== "route.bind") {
|
|
5410
6178
|
throw new SubcProviderError(`unsupported module control request ${request.op ?? "<missing op>"}`);
|
|
5411
6179
|
}
|
|
6180
|
+
const boundChannel = numberField(request.route_channel, "route_channel");
|
|
6181
|
+
const boundEpoch = numberField(request.epoch, "epoch");
|
|
6182
|
+
const stale = this.liveRoutes.get(boundChannel);
|
|
6183
|
+
if (stale) {
|
|
6184
|
+
if (boundEpoch <= stale.epoch) {
|
|
6185
|
+
await this.sendError(frame, "route_rejected", `route.bind epoch ${boundEpoch} does not supersede installed epoch ${stale.epoch} on channel ${boundChannel}`, controlFlags(), sock, generation);
|
|
6186
|
+
return;
|
|
6187
|
+
}
|
|
6188
|
+
this.liveRoutes.delete(stale.channel);
|
|
6189
|
+
this.abortHandle(stale);
|
|
6190
|
+
await this.opts.onRouteGone?.(stale);
|
|
6191
|
+
}
|
|
6192
|
+
const tentative = createRouteHandle(boundChannel, boundEpoch, this.connectionToken);
|
|
5412
6193
|
const bindRequest = {
|
|
5413
|
-
|
|
6194
|
+
handle: tentative,
|
|
5414
6195
|
target: request.target,
|
|
5415
6196
|
identity: request.identity,
|
|
5416
|
-
principal: request.principal
|
|
6197
|
+
principal: request.principal,
|
|
6198
|
+
consumer_capabilities: request.consumer_capabilities
|
|
5417
6199
|
};
|
|
5418
|
-
|
|
6200
|
+
let decision;
|
|
6201
|
+
try {
|
|
6202
|
+
decision = await this.opts.onBind?.(bindRequest);
|
|
6203
|
+
} catch (error2) {
|
|
6204
|
+
try {
|
|
6205
|
+
await this.sendError(frame, "route_rejected", error2 instanceof Error ? error2.message : String(error2), controlFlags(), sock, generation);
|
|
6206
|
+
} finally {
|
|
6207
|
+
await this.opts.onRouteGone?.(tentative);
|
|
6208
|
+
}
|
|
6209
|
+
return;
|
|
6210
|
+
}
|
|
5419
6211
|
const rejection = bindRejection(decision);
|
|
5420
6212
|
if (rejection) {
|
|
5421
|
-
|
|
6213
|
+
try {
|
|
6214
|
+
await this.sendError(frame, rejection.code, rejection.message, controlFlags(), sock, generation);
|
|
6215
|
+
} finally {
|
|
6216
|
+
await this.opts.onRouteGone?.(tentative);
|
|
6217
|
+
}
|
|
5422
6218
|
return;
|
|
5423
6219
|
}
|
|
5424
|
-
|
|
6220
|
+
try {
|
|
6221
|
+
await this.sendOn(sock, generation, buildFrameWithVersion(frame.header.ver, FrameType.Response, controlFlags(), 0, 0, frame.header.corr, encodeJson({ op: "route.bind" })));
|
|
6222
|
+
} catch (error2) {
|
|
6223
|
+
await this.opts.onRouteGone?.(tentative);
|
|
6224
|
+
throw error2;
|
|
6225
|
+
}
|
|
6226
|
+
if (this.sock !== sock || this.generation !== generation || this.closeStarted || this.closedErr) {
|
|
6227
|
+
await this.opts.onRouteGone?.(tentative);
|
|
6228
|
+
return;
|
|
6229
|
+
}
|
|
6230
|
+
this.liveRoutes.set(tentative.channel, tentative);
|
|
6231
|
+
await this.opts.onBound?.(tentative);
|
|
5425
6232
|
}
|
|
5426
|
-
async handleDataRequest(frame, sock, generation) {
|
|
5427
|
-
const {
|
|
5428
|
-
const key = routeKey(
|
|
6233
|
+
async handleDataRequest(frame, handle, sock, generation) {
|
|
6234
|
+
const { corr, ver } = frame.header;
|
|
6235
|
+
const key = routeKey(handle, corr);
|
|
5429
6236
|
const controller = new AbortController;
|
|
5430
6237
|
this.inflight.set(key, controller);
|
|
5431
|
-
const
|
|
5432
|
-
|
|
6238
|
+
const context = {
|
|
6239
|
+
handle,
|
|
5433
6240
|
signal: controller.signal,
|
|
5434
6241
|
currentEpoch: () => this.connectionEpoch,
|
|
5435
|
-
emit: async (eventBody) => {
|
|
6242
|
+
emit: async (eventBody, options = {}) => {
|
|
6243
|
+
this.assertLiveHandle(handle);
|
|
5436
6244
|
if (controller.signal.aborted)
|
|
5437
6245
|
return;
|
|
5438
|
-
await this.sendOn(sock, generation, buildFrameWithVersion(ver,
|
|
6246
|
+
await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.StreamData, buildFlags(false, options.priority ?? Priority.Interactive, false, options.admissionClass ?? AdmissionClass.Normal), handle.channel, handle.epoch, corr, eventBody));
|
|
5439
6247
|
}
|
|
5440
6248
|
};
|
|
6249
|
+
const releasePermit = await (this.requestGate ?? new AsyncPermitPool(DEFAULT_PROVIDER_HANDLER_CAPACITY)).acquire();
|
|
6250
|
+
const dataFlags = buildFlags(false, Priority.Interactive, false);
|
|
5441
6251
|
try {
|
|
5442
|
-
const body = await this.opts.handler(
|
|
6252
|
+
const body = await this.opts.handler(handle, frame.body, context);
|
|
6253
|
+
if (controller.signal.aborted)
|
|
6254
|
+
return;
|
|
6255
|
+
this.assertLiveHandle(handle);
|
|
5443
6256
|
if (body === undefined) {
|
|
5444
|
-
await this.sendOn(sock, generation, buildFrameWithVersion(ver,
|
|
6257
|
+
await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.StreamEnd, dataFlags, handle.channel, handle.epoch, corr, new Uint8Array(0)));
|
|
5445
6258
|
} else if (body instanceof Uint8Array) {
|
|
5446
|
-
await this.sendOn(sock, generation, buildFrameWithVersion(ver,
|
|
6259
|
+
await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.Response, dataFlags, handle.channel, handle.epoch, corr, body));
|
|
5447
6260
|
} else {
|
|
5448
6261
|
throw new SubcProviderError("provider handler must return a Uint8Array or void", "invalid_handler_response");
|
|
5449
6262
|
}
|
|
5450
|
-
} catch (
|
|
5451
|
-
|
|
6263
|
+
} catch (error2) {
|
|
6264
|
+
if (error2 instanceof StaleRouteHandleError || controller.signal.aborted)
|
|
6265
|
+
return;
|
|
6266
|
+
await this.sendError(frame, error2 instanceof SubcProviderError && error2.code ? error2.code : "handler_error", error2 instanceof Error ? error2.message : String(error2), dataFlags, sock, generation);
|
|
6267
|
+
} finally {
|
|
6268
|
+
releasePermit();
|
|
6269
|
+
if (this.inflight.get(key) === controller)
|
|
6270
|
+
this.inflight.delete(key);
|
|
6271
|
+
}
|
|
6272
|
+
}
|
|
6273
|
+
async handleHealthRequest(frame, sock, generation) {
|
|
6274
|
+
const { corr, ver } = frame.header;
|
|
6275
|
+
const key = `control:${generation}:${corr}`;
|
|
6276
|
+
const controller = new AbortController;
|
|
6277
|
+
this.inflight.set(key, controller);
|
|
6278
|
+
const releasePermit = await (this.requestGate ?? new AsyncPermitPool(DEFAULT_PROVIDER_HANDLER_CAPACITY)).acquire();
|
|
6279
|
+
try {
|
|
6280
|
+
if (controller.signal.aborted)
|
|
6281
|
+
return;
|
|
6282
|
+
const report = await this.opts.health();
|
|
6283
|
+
await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.Response, controlFlags(), 0, 0, corr, encodeJson({
|
|
6284
|
+
op: HEALTH_CHECK_OP,
|
|
6285
|
+
status: report.status,
|
|
6286
|
+
...report.detail === undefined ? {} : { detail: report.detail },
|
|
6287
|
+
...report.metrics === undefined ? {} : { metrics: report.metrics }
|
|
6288
|
+
})));
|
|
6289
|
+
} catch (error2) {
|
|
6290
|
+
await this.sendError(frame, error2 instanceof SubcProviderError && error2.code ? error2.code : "health_error", error2 instanceof Error ? error2.message : String(error2), controlFlags(), sock, generation);
|
|
5452
6291
|
} finally {
|
|
6292
|
+
releasePermit();
|
|
5453
6293
|
if (this.inflight.get(key) === controller)
|
|
5454
6294
|
this.inflight.delete(key);
|
|
5455
6295
|
}
|
|
5456
6296
|
}
|
|
5457
6297
|
async sendError(frame, code, message, flags, sock, generation) {
|
|
5458
|
-
await this.sendOn(sock, generation, buildFrameWithVersion(frame.header.ver,
|
|
6298
|
+
await this.sendOn(sock, generation, buildFrameWithVersion(frame.header.ver, FrameType.Error, flags, frame.header.channel, frame.header.epoch, frame.header.corr, encodeJson({ code, message })));
|
|
5459
6299
|
}
|
|
5460
6300
|
async sendOn(sock, generation, frame) {
|
|
5461
6301
|
if (this.sock !== sock || this.generation !== generation || this.closeStarted || this.closedErr)
|
|
@@ -5463,42 +6303,79 @@ class SubcProvider {
|
|
|
5463
6303
|
await sendFrame(sock, frame);
|
|
5464
6304
|
}
|
|
5465
6305
|
handleUnexpectedDrop(sock, generation, cause) {
|
|
6306
|
+
if (this.closeStarted || this.sock !== sock || this.generation !== generation)
|
|
6307
|
+
return;
|
|
5466
6308
|
this.cancelRestoredDebounce();
|
|
5467
6309
|
this.abortGeneration(generation);
|
|
5468
6310
|
this.generation += 1;
|
|
5469
6311
|
sock.close();
|
|
5470
|
-
this.
|
|
5471
|
-
this.scheduleReconnectAfterDrop(cause);
|
|
6312
|
+
this.scheduleReconnectAfterDrop(cause, this.generation, sock);
|
|
5472
6313
|
}
|
|
5473
|
-
scheduleReconnectAfterDrop(
|
|
5474
|
-
if (this.closeStarted
|
|
6314
|
+
scheduleReconnectAfterDrop(cause, generation, droppedSocket) {
|
|
6315
|
+
if (this.closeStarted)
|
|
5475
6316
|
return;
|
|
5476
|
-
const
|
|
5477
|
-
|
|
6317
|
+
const previous = this.reconnecting;
|
|
6318
|
+
if (previous) {
|
|
6319
|
+
if (!this.shouldSupersedeReconnect(previous, generation, droppedSocket))
|
|
6320
|
+
return;
|
|
6321
|
+
previous.superseded = true;
|
|
6322
|
+
previous.socket?.close();
|
|
6323
|
+
}
|
|
6324
|
+
const cycle = {
|
|
6325
|
+
generation,
|
|
6326
|
+
socket: null,
|
|
6327
|
+
socketDied: false,
|
|
6328
|
+
superseded: false
|
|
6329
|
+
};
|
|
6330
|
+
this.reconnecting = cycle;
|
|
6331
|
+
this.enqueueConnectionState({ state: "down", cause });
|
|
6332
|
+
this.reconnectWithRetry(cycle).catch((err) => {
|
|
6333
|
+
if (this.isCurrentReconnect(cycle) && !this.closeStarted) {
|
|
5478
6334
|
this.failFatal(err instanceof Error ? err : new SubcProviderError(String(err)));
|
|
6335
|
+
}
|
|
5479
6336
|
}).finally(() => {
|
|
5480
|
-
if (this.
|
|
6337
|
+
if (this.isCurrentReconnect(cycle))
|
|
5481
6338
|
this.reconnecting = null;
|
|
5482
6339
|
});
|
|
5483
|
-
this.reconnecting = promise;
|
|
5484
6340
|
}
|
|
5485
|
-
async reconnectWithRetry(
|
|
6341
|
+
async reconnectWithRetry(cycle) {
|
|
5486
6342
|
let attempt = 0;
|
|
5487
6343
|
let delay = this.opts.reconnectBackoff.baseMs;
|
|
5488
6344
|
for (;; ) {
|
|
6345
|
+
if (!this.isCurrentReconnect(cycle))
|
|
6346
|
+
return;
|
|
5489
6347
|
if (this.closeStarted)
|
|
5490
6348
|
throw new SubcProviderError("provider closed");
|
|
6349
|
+
cycle.socket = null;
|
|
6350
|
+
cycle.socketDied = false;
|
|
5491
6351
|
attempt += 1;
|
|
5492
|
-
this.
|
|
6352
|
+
this.enqueueReconnectState(cycle, attempt);
|
|
5493
6353
|
try {
|
|
5494
|
-
const opened = await SubcProvider.openConnection(this.opts)
|
|
5495
|
-
|
|
6354
|
+
const opened = await SubcProvider.openConnection(this.opts, (sock) => {
|
|
6355
|
+
if (!this.isCurrentReconnect(cycle)) {
|
|
6356
|
+
sock.close();
|
|
6357
|
+
return;
|
|
6358
|
+
}
|
|
6359
|
+
cycle.socket = sock;
|
|
6360
|
+
});
|
|
6361
|
+
if (!this.isCurrentReconnect(cycle) || this.closeStarted) {
|
|
5496
6362
|
opened.sock.close();
|
|
5497
|
-
|
|
6363
|
+
if (this.closeStarted)
|
|
6364
|
+
throw new SubcProviderError("provider closed");
|
|
6365
|
+
return;
|
|
5498
6366
|
}
|
|
5499
|
-
this.replaceConnection(opened);
|
|
6367
|
+
const epoch = this.replaceConnection(opened, cycle.generation);
|
|
6368
|
+
this.reconnecting = null;
|
|
6369
|
+
if (this.reconnecting !== null) {
|
|
6370
|
+
throw new SubcProviderError("reconnect state must clear before restored", "reconnect_state");
|
|
6371
|
+
}
|
|
6372
|
+
this.scheduleRestored(cycle.generation, epoch);
|
|
5500
6373
|
return;
|
|
5501
6374
|
} catch (err) {
|
|
6375
|
+
if (!this.isCurrentReconnect(cycle))
|
|
6376
|
+
return;
|
|
6377
|
+
if (cycle.socket)
|
|
6378
|
+
cycle.socketDied = true;
|
|
5502
6379
|
if (this.closeStarted)
|
|
5503
6380
|
throw err;
|
|
5504
6381
|
if (!isProviderReconnectTransient(err))
|
|
@@ -5508,16 +6385,29 @@ class SubcProvider {
|
|
|
5508
6385
|
}
|
|
5509
6386
|
}
|
|
5510
6387
|
}
|
|
5511
|
-
|
|
6388
|
+
isCurrentReconnect(cycle) {
|
|
6389
|
+
return !cycle.superseded && this.reconnecting === cycle && this.generation === cycle.generation;
|
|
6390
|
+
}
|
|
6391
|
+
shouldSupersedeReconnect(cycle, generation, droppedSocket) {
|
|
6392
|
+
return cycle.generation < generation || cycle.socketDied || cycle.socket === droppedSocket;
|
|
6393
|
+
}
|
|
6394
|
+
enqueueReconnectState(cycle, attempt) {
|
|
6395
|
+
if (!this.isCurrentReconnect(cycle))
|
|
6396
|
+
return;
|
|
6397
|
+
this.enqueueConnectionState({ state: "reconnecting", attempt }, cycle.generation, cycle);
|
|
6398
|
+
}
|
|
6399
|
+
replaceConnection(opened, generation) {
|
|
5512
6400
|
this.sock.close();
|
|
5513
6401
|
this.sock = opened.sock;
|
|
5514
6402
|
this.currentConn = opened.conn;
|
|
5515
6403
|
this.storage = opened.ack.storage;
|
|
5516
6404
|
this.closedErr = null;
|
|
5517
6405
|
this.connectionEpoch += 1;
|
|
5518
|
-
|
|
6406
|
+
this.connectionToken = newConnectionToken();
|
|
6407
|
+
this.liveRoutes.clear();
|
|
6408
|
+
this.nextCorr = 1n;
|
|
5519
6409
|
this.readLoop(opened.sock, generation);
|
|
5520
|
-
|
|
6410
|
+
return this.connectionEpoch;
|
|
5521
6411
|
}
|
|
5522
6412
|
scheduleRestored(generation, epoch) {
|
|
5523
6413
|
if (!this.opts.onConnectionState)
|
|
@@ -5525,7 +6415,7 @@ class SubcProvider {
|
|
|
5525
6415
|
const token = ++this.restoredDebounceToken;
|
|
5526
6416
|
this.opts.sleep(this.opts.restoredDebounceMs).then(() => {
|
|
5527
6417
|
if (token === this.restoredDebounceToken && !this.closeStarted && this.sock && this.generation === generation && this.connectionEpoch === epoch) {
|
|
5528
|
-
this.enqueueConnectionState({ state: "restored", epoch });
|
|
6418
|
+
this.enqueueConnectionState({ state: "restored", epoch }, generation);
|
|
5529
6419
|
}
|
|
5530
6420
|
}).catch((err) => {
|
|
5531
6421
|
if (token === this.restoredDebounceToken && !this.closeStarted) {
|
|
@@ -5536,10 +6426,10 @@ class SubcProvider {
|
|
|
5536
6426
|
cancelRestoredDebounce() {
|
|
5537
6427
|
this.restoredDebounceToken += 1;
|
|
5538
6428
|
}
|
|
5539
|
-
enqueueConnectionState(event) {
|
|
6429
|
+
enqueueConnectionState(event, generation, reconnect) {
|
|
5540
6430
|
if (!this.opts.onConnectionState)
|
|
5541
6431
|
return;
|
|
5542
|
-
this.stateQueue.push(event);
|
|
6432
|
+
this.stateQueue.push({ event, generation, reconnect });
|
|
5543
6433
|
if (!this.drainingStateQueue)
|
|
5544
6434
|
this.drainConnectionStateQueue();
|
|
5545
6435
|
}
|
|
@@ -5549,7 +6439,12 @@ class SubcProvider {
|
|
|
5549
6439
|
this.drainingStateQueue = true;
|
|
5550
6440
|
try {
|
|
5551
6441
|
while (this.stateQueue.length > 0) {
|
|
5552
|
-
const
|
|
6442
|
+
const queued = this.stateQueue[0];
|
|
6443
|
+
if (this.closeStarted || queued.generation !== undefined && queued.generation !== this.generation || queued.reconnect?.superseded) {
|
|
6444
|
+
this.stateQueue.shift();
|
|
6445
|
+
continue;
|
|
6446
|
+
}
|
|
6447
|
+
const { event } = queued;
|
|
5553
6448
|
try {
|
|
5554
6449
|
await this.opts.onConnectionState?.(event);
|
|
5555
6450
|
this.stateQueue.shift();
|
|
@@ -5569,6 +6464,24 @@ class SubcProvider {
|
|
|
5569
6464
|
this.drainConnectionStateQueue();
|
|
5570
6465
|
}
|
|
5571
6466
|
}
|
|
6467
|
+
isLiveHandle(handle) {
|
|
6468
|
+
return belongsToConnection(handle, this.connectionToken) && this.liveRoutes.get(handle.channel) === handle;
|
|
6469
|
+
}
|
|
6470
|
+
assertLiveHandle(handle) {
|
|
6471
|
+
if (!this.isLiveHandle(handle))
|
|
6472
|
+
throw new StaleRouteHandleError(handle);
|
|
6473
|
+
}
|
|
6474
|
+
allocateCorr() {
|
|
6475
|
+
const maximum = 0xffffffffffffffffn;
|
|
6476
|
+
if (this.nextCorr > maximum) {
|
|
6477
|
+
const error2 = new SubcProviderError("channel-0 correlation id allocator exhausted", "corr_exhausted");
|
|
6478
|
+
this.handleUnexpectedDrop(this.sock, this.generation, error2);
|
|
6479
|
+
throw error2;
|
|
6480
|
+
}
|
|
6481
|
+
const corr = this.nextCorr;
|
|
6482
|
+
this.nextCorr += 1n;
|
|
6483
|
+
return corr;
|
|
6484
|
+
}
|
|
5572
6485
|
failFatal(err) {
|
|
5573
6486
|
if (!this.closedErr)
|
|
5574
6487
|
this.closedErr = err;
|
|
@@ -5582,8 +6495,16 @@ class SubcProvider {
|
|
|
5582
6495
|
this.resolveClosed();
|
|
5583
6496
|
}
|
|
5584
6497
|
}
|
|
5585
|
-
function routeKey(
|
|
5586
|
-
return `${
|
|
6498
|
+
function routeKey(handle, corr) {
|
|
6499
|
+
return `${handle.channel}:${handle.epoch}:${corr}`;
|
|
6500
|
+
}
|
|
6501
|
+
function providerErrorFromFrame(frame) {
|
|
6502
|
+
try {
|
|
6503
|
+
const body = parseJson(frame.body);
|
|
6504
|
+
return new SubcProviderError(body.message ?? "subc error", body.code);
|
|
6505
|
+
} catch {
|
|
6506
|
+
return new SubcProviderError(Buffer2.from(frame.body).toString("utf8") || "subc error");
|
|
6507
|
+
}
|
|
5587
6508
|
}
|
|
5588
6509
|
function launchNonce(opts) {
|
|
5589
6510
|
const nonce = opts.launchNonce ?? process.env[SUBC_LAUNCH_NONCE_ENV2];
|
|
@@ -5594,9 +6515,11 @@ function normalizeProviderConnectOptions(opts) {
|
|
|
5594
6515
|
connectionFile: opts.connectionFile,
|
|
5595
6516
|
manifest: opts.manifest,
|
|
5596
6517
|
handler: opts.handler,
|
|
6518
|
+
health: opts.health ?? (() => ({ status: "ok" })),
|
|
5597
6519
|
handshakeTimeoutMs: opts.handshakeTimeoutMs,
|
|
5598
6520
|
controlOps: opts.controlOps,
|
|
5599
6521
|
onBind: opts.onBind,
|
|
6522
|
+
onBound: opts.onBound,
|
|
5600
6523
|
onRouteGone: opts.onRouteGone,
|
|
5601
6524
|
reconnectBackoff: opts.reconnectBackoff ?? DEFAULT_RECONNECT_BACKOFF,
|
|
5602
6525
|
sleep: opts.sleep ?? ((ms) => new Promise((resolve7) => setTimeout(resolve7, ms))),
|
|
@@ -5605,12 +6528,19 @@ function normalizeProviderConnectOptions(opts) {
|
|
|
5605
6528
|
launchNonce: opts.launchNonce
|
|
5606
6529
|
};
|
|
5607
6530
|
}
|
|
6531
|
+
function normalizedControlOps(controlOps) {
|
|
6532
|
+
if (controlOps === null)
|
|
6533
|
+
return null;
|
|
6534
|
+
const merged = new Set(controlOps ?? []);
|
|
6535
|
+
merged.add(HEALTH_CHECK_OP);
|
|
6536
|
+
return [...merged];
|
|
6537
|
+
}
|
|
5608
6538
|
function buildHelloFrame(opts) {
|
|
5609
6539
|
const nonce = launchNonce(opts);
|
|
5610
|
-
return buildFrame(
|
|
6540
|
+
return buildFrame(FrameType.Hello, controlFlags(), 0, 0, HELLO_CORR, encodeJson({
|
|
5611
6541
|
manifest: normalizeManifest(opts.manifest),
|
|
5612
6542
|
protocol_ver: PROTOCOL_VERSION,
|
|
5613
|
-
control_ops: opts.controlOps
|
|
6543
|
+
control_ops: normalizedControlOps(opts.controlOps),
|
|
5614
6544
|
...nonce ? { launch_nonce: nonce } : {}
|
|
5615
6545
|
}));
|
|
5616
6546
|
}
|
|
@@ -5621,7 +6551,9 @@ function isProviderReconnectTransient(err) {
|
|
|
5621
6551
|
return true;
|
|
5622
6552
|
if (err instanceof SocketWriteNotQueuedError || err instanceof SocketWriteQueuedError)
|
|
5623
6553
|
return true;
|
|
5624
|
-
if (err instanceof
|
|
6554
|
+
if (err instanceof AuthError)
|
|
6555
|
+
return true;
|
|
6556
|
+
if (err instanceof ConnectionFileError)
|
|
5625
6557
|
return false;
|
|
5626
6558
|
const code = errorCode2(err);
|
|
5627
6559
|
return code === "ECONNREFUSED" || code === "ECONNRESET" || code === "EPIPE" || code === "ETIMEDOUT" || code === "ENOENT";
|
|
@@ -5638,20 +6570,23 @@ async function pauseBeforeStateRetry() {
|
|
|
5638
6570
|
await new Promise((resolve7) => setTimeout(resolve7, 0));
|
|
5639
6571
|
}
|
|
5640
6572
|
function controlFlags() {
|
|
5641
|
-
return buildFlags(false,
|
|
6573
|
+
return buildFlags(false, Priority.Passive, false);
|
|
5642
6574
|
}
|
|
5643
6575
|
async function sendFrame(sock, frame) {
|
|
5644
6576
|
await sock.write(encodeFrame(frame), Date.now() + WRITE_TIMEOUT_MS);
|
|
5645
6577
|
}
|
|
5646
6578
|
async function expectHelloAck(sock, deadline) {
|
|
5647
|
-
const
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
6579
|
+
const frame = await sock.readFrame(deadline, deadline);
|
|
6580
|
+
switch (frame.header.ty) {
|
|
6581
|
+
case FrameType.HelloAck: {
|
|
6582
|
+
const ack = parseJson(frame.body);
|
|
6583
|
+
if (ack.negotiated_ver !== PROTOCOL_VERSION) {
|
|
6584
|
+
throw new SubcProviderError(`subc negotiated protocol ${ack.negotiated_ver}; expected exactly ${PROTOCOL_VERSION}`, "unsupported_version");
|
|
6585
|
+
}
|
|
6586
|
+
return ack;
|
|
6587
|
+
}
|
|
6588
|
+
case FrameType.Error: {
|
|
6589
|
+
const error2 = parseJson(frame.body);
|
|
5655
6590
|
throw new SubcProviderError(`subc rejected HELLO: ${error2.code ?? "unknown"} — ${error2.message ?? "subc error"}`, error2.code);
|
|
5656
6591
|
}
|
|
5657
6592
|
default:
|
|
@@ -5716,6 +6651,7 @@ function normalizeProviderRole(role) {
|
|
|
5716
6651
|
role: "tool_provider",
|
|
5717
6652
|
tools: role.tools.map((tool) => ({
|
|
5718
6653
|
name: tool.name,
|
|
6654
|
+
...tool.description === undefined ? {} : { description: tool.description },
|
|
5719
6655
|
execution_mode: tool.execution_mode,
|
|
5720
6656
|
schema: tool.schema
|
|
5721
6657
|
})),
|
|
@@ -5791,12 +6727,13 @@ function normalizeScheduledTask(task) {
|
|
|
5791
6727
|
}
|
|
5792
6728
|
};
|
|
5793
6729
|
}
|
|
5794
|
-
var DEFAULT_HANDSHAKE_TIMEOUT_MS2 = 1e4, BODY_READ_TIMEOUT_MS2 = 30000, WRITE_TIMEOUT_MS = 30000, DEFAULT_RESTORED_DEBOUNCE_MS = 250, HELLO_CORR = 1n, SubcProviderError, SUBC_LAUNCH_NONCE_ENV2 = "SUBC_LAUNCH_NONCE";
|
|
6730
|
+
var DEFAULT_HANDSHAKE_TIMEOUT_MS2 = 1e4, BODY_READ_TIMEOUT_MS2 = 30000, WRITE_TIMEOUT_MS = 30000, DEFAULT_RESTORED_DEBOUNCE_MS = 250, DEFAULT_PROVIDER_HANDLER_CAPACITY = 64, HEALTH_CHECK_OP = "health.check", HELLO_CORR = 1n, SubcProviderError, SUBC_LAUNCH_NONCE_ENV2 = "SUBC_LAUNCH_NONCE";
|
|
5795
6731
|
var init_provider = __esm(() => {
|
|
5796
6732
|
init_auth();
|
|
5797
6733
|
init_client();
|
|
5798
6734
|
init_connection_file();
|
|
5799
6735
|
init_envelope();
|
|
6736
|
+
init_route_handle();
|
|
5800
6737
|
init_socket();
|
|
5801
6738
|
SubcProviderError = class SubcProviderError extends Error {
|
|
5802
6739
|
code;
|
|
@@ -5807,9 +6744,10 @@ var init_provider = __esm(() => {
|
|
|
5807
6744
|
};
|
|
5808
6745
|
});
|
|
5809
6746
|
|
|
5810
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
5811
|
-
var
|
|
6747
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.5.0/node_modules/@cortexkit/subc-client/dist/index.js
|
|
6748
|
+
var init_dist = __esm(() => {
|
|
5812
6749
|
init_client();
|
|
6750
|
+
init_route_handle();
|
|
5813
6751
|
init_connection_file();
|
|
5814
6752
|
init_envelope();
|
|
5815
6753
|
init_auth();
|
|
@@ -5826,15 +6764,17 @@ class BgSubscription {
|
|
|
5826
6764
|
identity;
|
|
5827
6765
|
acquireClient;
|
|
5828
6766
|
dropClient;
|
|
6767
|
+
consumerIdentity;
|
|
5829
6768
|
onNudge;
|
|
5830
6769
|
sleep;
|
|
5831
6770
|
stopped = false;
|
|
5832
6771
|
current = null;
|
|
5833
6772
|
loop;
|
|
5834
|
-
constructor(identity, acquireClient, dropClient, onNudge, sleep2) {
|
|
6773
|
+
constructor(identity, acquireClient, dropClient, consumerIdentity, onNudge, sleep2) {
|
|
5835
6774
|
this.identity = identity;
|
|
5836
6775
|
this.acquireClient = acquireClient;
|
|
5837
6776
|
this.dropClient = dropClient;
|
|
6777
|
+
this.consumerIdentity = consumerIdentity;
|
|
5838
6778
|
this.onNudge = onNudge;
|
|
5839
6779
|
this.sleep = sleep2;
|
|
5840
6780
|
this.loop = this.run();
|
|
@@ -5863,9 +6803,9 @@ class BgSubscription {
|
|
|
5863
6803
|
}
|
|
5864
6804
|
if (this.stopped)
|
|
5865
6805
|
return;
|
|
5866
|
-
let
|
|
6806
|
+
let route;
|
|
5867
6807
|
try {
|
|
5868
|
-
|
|
6808
|
+
route = await client.routeOpen({ kind: "tool_provider", module_id: AFT_MODULE_ID }, this.identity, { consumerIdentity: this.consumerIdentity });
|
|
5869
6809
|
} catch (err) {
|
|
5870
6810
|
if (isConsumerReconnectTransient(err))
|
|
5871
6811
|
this.dropClient(client);
|
|
@@ -5873,12 +6813,12 @@ class BgSubscription {
|
|
|
5873
6813
|
continue;
|
|
5874
6814
|
}
|
|
5875
6815
|
if (this.stopped) {
|
|
5876
|
-
safeCloseRoute(client,
|
|
6816
|
+
safeCloseRoute(client, route);
|
|
5877
6817
|
return;
|
|
5878
6818
|
}
|
|
5879
6819
|
const subscribedAt = Date.now();
|
|
5880
6820
|
try {
|
|
5881
|
-
const sub = client.subscribe(
|
|
6821
|
+
const sub = client.subscribe(route, { op: "bg_events" }, () => {
|
|
5882
6822
|
if (!this.stopped)
|
|
5883
6823
|
this.onNudge();
|
|
5884
6824
|
});
|
|
@@ -5898,7 +6838,7 @@ class BgSubscription {
|
|
|
5898
6838
|
attempt = 0;
|
|
5899
6839
|
} finally {
|
|
5900
6840
|
this.current = null;
|
|
5901
|
-
safeCloseRoute(client,
|
|
6841
|
+
safeCloseRoute(client, route);
|
|
5902
6842
|
}
|
|
5903
6843
|
await this.backoff(attempt++);
|
|
5904
6844
|
}
|
|
@@ -5911,9 +6851,12 @@ class BgSubscription {
|
|
|
5911
6851
|
function isRecord(value) {
|
|
5912
6852
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5913
6853
|
}
|
|
5914
|
-
function
|
|
6854
|
+
function isRouteProvenAbsentError(err) {
|
|
6855
|
+
return err instanceof SubcError && err.code === "unknown_channel" || err instanceof StaleRouteHandleError;
|
|
6856
|
+
}
|
|
6857
|
+
function safeCloseRoute(client, route) {
|
|
5915
6858
|
try {
|
|
5916
|
-
client.closeRouteChannel(
|
|
6859
|
+
client.closeRouteChannel(route).catch(() => {
|
|
5917
6860
|
return;
|
|
5918
6861
|
});
|
|
5919
6862
|
} catch {}
|
|
@@ -5987,7 +6930,7 @@ class SubcTransport {
|
|
|
5987
6930
|
if (!options)
|
|
5988
6931
|
return {};
|
|
5989
6932
|
const preview = options.preview;
|
|
5990
|
-
const timeoutMs = options.timeoutMs;
|
|
6933
|
+
const timeoutMs = options.transportTimeoutMs ?? options.timeoutMs;
|
|
5991
6934
|
const onProgress = options.onProgress;
|
|
5992
6935
|
return { preview, timeoutMs, onProgress };
|
|
5993
6936
|
}
|
|
@@ -5997,6 +6940,7 @@ class SubcTransportPool {
|
|
|
5997
6940
|
harness;
|
|
5998
6941
|
connectionFile;
|
|
5999
6942
|
handshakeTimeoutMs;
|
|
6943
|
+
consumerIdentity;
|
|
6000
6944
|
connectFn;
|
|
6001
6945
|
onBgEventsNudge;
|
|
6002
6946
|
bgBackoffSleep;
|
|
@@ -6010,6 +6954,7 @@ class SubcTransportPool {
|
|
|
6010
6954
|
this.connectionFile = options.connectionFile;
|
|
6011
6955
|
this.harness = options.harness;
|
|
6012
6956
|
this.handshakeTimeoutMs = options.handshakeTimeoutMs;
|
|
6957
|
+
this.consumerIdentity = options.consumerIdentity;
|
|
6013
6958
|
this.connectFn = options.connect ?? ((opts) => SubcClient.connect(opts));
|
|
6014
6959
|
this.onBgEventsNudge = options.onBgEventsNudge;
|
|
6015
6960
|
this.bgBackoffSleep = options.bgBackoffSleep ?? ((ms) => new Promise((resolve7) => setTimeout(resolve7, ms)));
|
|
@@ -6032,6 +6977,11 @@ class SubcTransportPool {
|
|
|
6032
6977
|
return null;
|
|
6033
6978
|
return this.transports.get(key) ?? null;
|
|
6034
6979
|
}
|
|
6980
|
+
activeBridges() {
|
|
6981
|
+
if (!this.client || this.shuttingDown)
|
|
6982
|
+
return [];
|
|
6983
|
+
return [...this.transports.values()];
|
|
6984
|
+
}
|
|
6035
6985
|
async toolCall(projectRoot, runtime, name, rawArgs = {}, options) {
|
|
6036
6986
|
return this.getBridge(projectRoot).toolCall(runtime.sessionID, name, rawArgs, options);
|
|
6037
6987
|
}
|
|
@@ -6057,45 +7007,66 @@ class SubcTransportPool {
|
|
|
6057
7007
|
record.inflight += 1;
|
|
6058
7008
|
try {
|
|
6059
7009
|
const client = await this.ensureClient();
|
|
6060
|
-
|
|
6061
|
-
throw new RouteTornDownError("subc session closed");
|
|
6062
|
-
}
|
|
6063
|
-
let channel;
|
|
6064
|
-
let entry;
|
|
6065
|
-
try {
|
|
6066
|
-
({ channel, entry } = await this.routeChannel(client, identity, record));
|
|
7010
|
+
const openRoute = async () => {
|
|
6067
7011
|
if (!this.isCurrentSession(key, record)) {
|
|
6068
7012
|
throw new RouteTornDownError("subc session closed");
|
|
6069
7013
|
}
|
|
6070
|
-
|
|
6071
|
-
|
|
7014
|
+
try {
|
|
7015
|
+
const opened = await this.routeHandle(client, identity, record);
|
|
7016
|
+
if (!this.isCurrentSession(key, record)) {
|
|
7017
|
+
throw new RouteTornDownError("subc session closed");
|
|
7018
|
+
}
|
|
7019
|
+
return opened;
|
|
7020
|
+
} catch (err) {
|
|
7021
|
+
if (err instanceof RouteTornDownError)
|
|
7022
|
+
throw err;
|
|
7023
|
+
if (isConsumerReconnectTransient(err) && this.isCurrentSession(key, record) && this.client === client) {
|
|
7024
|
+
this.dropClient(client);
|
|
7025
|
+
}
|
|
6072
7026
|
throw err;
|
|
6073
|
-
if (isConsumerReconnectTransient(err) && this.isCurrentSession(key, record) && this.client === client) {
|
|
6074
|
-
this.dropClient(client);
|
|
6075
|
-
}
|
|
6076
|
-
throw err;
|
|
6077
|
-
}
|
|
6078
|
-
try {
|
|
6079
|
-
const reply = await client.request(channel, body, { timeoutMs, onProgress });
|
|
6080
|
-
if (this.isCurrentSession(key, record) && this.client === client) {
|
|
6081
|
-
this.transportFailures = 0;
|
|
6082
7027
|
}
|
|
6083
|
-
|
|
6084
|
-
|
|
6085
|
-
|
|
6086
|
-
|
|
6087
|
-
entry.closed = true;
|
|
7028
|
+
};
|
|
7029
|
+
const clearRouteEntry = (entry2) => {
|
|
7030
|
+
if (record.routeEntry === entry2) {
|
|
7031
|
+
entry2.closed = true;
|
|
6088
7032
|
record.routeEntry = null;
|
|
6089
7033
|
}
|
|
7034
|
+
};
|
|
7035
|
+
const handleRequestFailure = (err, entry2) => {
|
|
7036
|
+
clearRouteEntry(entry2);
|
|
6090
7037
|
if (this.isCurrentSession(key, record) && this.client === client) {
|
|
6091
7038
|
if (isConsumerReconnectTransient(err)) {
|
|
6092
7039
|
this.transportFailures = 0;
|
|
6093
7040
|
this.dropClient(client);
|
|
6094
|
-
} else if (++this.transportFailures >= MAX_CONSECUTIVE_TRANSPORT_FAILURES) {
|
|
7041
|
+
} else if (!isRouteProvenAbsentError(err) && ++this.transportFailures >= MAX_CONSECUTIVE_TRANSPORT_FAILURES) {
|
|
6095
7042
|
this.transportFailures = 0;
|
|
6096
7043
|
this.dropClient(client);
|
|
6097
7044
|
}
|
|
6098
7045
|
}
|
|
7046
|
+
};
|
|
7047
|
+
const requestOnRoute = async (route2) => {
|
|
7048
|
+
const reply = await client.request(route2, body, { timeoutMs, onProgress });
|
|
7049
|
+
if (this.isCurrentSession(key, record) && this.client === client) {
|
|
7050
|
+
this.transportFailures = 0;
|
|
7051
|
+
}
|
|
7052
|
+
this.ensureBgSubscription(identity, record);
|
|
7053
|
+
return reply;
|
|
7054
|
+
};
|
|
7055
|
+
let { route, entry } = await openRoute();
|
|
7056
|
+
try {
|
|
7057
|
+
return await requestOnRoute(route);
|
|
7058
|
+
} catch (err) {
|
|
7059
|
+
if (isRouteProvenAbsentError(err) && this.isCurrentSession(key, record) && this.client === client) {
|
|
7060
|
+
clearRouteEntry(entry);
|
|
7061
|
+
({ route, entry } = await openRoute());
|
|
7062
|
+
try {
|
|
7063
|
+
return await requestOnRoute(route);
|
|
7064
|
+
} catch (retryErr) {
|
|
7065
|
+
handleRequestFailure(retryErr, entry);
|
|
7066
|
+
throw retryErr;
|
|
7067
|
+
}
|
|
7068
|
+
}
|
|
7069
|
+
handleRequestFailure(err, entry);
|
|
6099
7070
|
throw err;
|
|
6100
7071
|
}
|
|
6101
7072
|
} finally {
|
|
@@ -6131,24 +7102,26 @@ class SubcTransportPool {
|
|
|
6131
7102
|
});
|
|
6132
7103
|
return this.connecting;
|
|
6133
7104
|
}
|
|
6134
|
-
async
|
|
7105
|
+
async routeHandle(client, identity, record) {
|
|
6135
7106
|
const key = identityKey(identity);
|
|
6136
7107
|
const existing = record.routeEntry;
|
|
6137
|
-
if (existing?.
|
|
6138
|
-
return {
|
|
7108
|
+
if (existing?.handle != null)
|
|
7109
|
+
return { route: existing.handle, entry: existing };
|
|
6139
7110
|
if (existing?.opening)
|
|
6140
|
-
return {
|
|
6141
|
-
const entry = { client, opening: null,
|
|
6142
|
-
const opening = client.routeOpen({ kind: "tool_provider", module_id: AFT_MODULE_ID }, identity
|
|
7111
|
+
return { route: await existing.opening, entry: existing };
|
|
7112
|
+
const entry = { client, opening: null, handle: null, closed: false };
|
|
7113
|
+
const opening = client.routeOpen({ kind: "tool_provider", module_id: AFT_MODULE_ID }, identity, {
|
|
7114
|
+
consumerIdentity: this.consumerIdentity
|
|
7115
|
+
}).then((route) => {
|
|
6143
7116
|
if (!this.isCurrentSession(key, record) || record.routeEntry !== entry || entry.closed || this.client !== client) {
|
|
6144
|
-
safeCloseRoute(client,
|
|
7117
|
+
safeCloseRoute(client, route);
|
|
6145
7118
|
if (record.routeEntry === entry)
|
|
6146
7119
|
record.routeEntry = null;
|
|
6147
7120
|
throw new RouteTornDownError("subc route opened after teardown");
|
|
6148
7121
|
}
|
|
6149
|
-
entry.
|
|
7122
|
+
entry.handle = route;
|
|
6150
7123
|
entry.opening = null;
|
|
6151
|
-
return
|
|
7124
|
+
return route;
|
|
6152
7125
|
}).catch((err) => {
|
|
6153
7126
|
const current = this.isCurrentSession(key, record);
|
|
6154
7127
|
if (record.routeEntry === entry) {
|
|
@@ -6162,7 +7135,7 @@ class SubcTransportPool {
|
|
|
6162
7135
|
});
|
|
6163
7136
|
entry.opening = opening;
|
|
6164
7137
|
record.routeEntry = entry;
|
|
6165
|
-
return {
|
|
7138
|
+
return { route: await opening, entry };
|
|
6166
7139
|
}
|
|
6167
7140
|
ensureBgSubscription(identity, record) {
|
|
6168
7141
|
if (this.shuttingDown || !this.onBgEventsNudge)
|
|
@@ -6173,7 +7146,7 @@ class SubcTransportPool {
|
|
|
6173
7146
|
if (record.bgSub)
|
|
6174
7147
|
return;
|
|
6175
7148
|
const onNudge = () => this.onBgEventsNudge?.(identity.project_root, identity.session);
|
|
6176
|
-
const sub = new BgSubscription(identity, () => this.ensureClient(), (client) => this.dropClient(client), onNudge, this.bgBackoffSleep);
|
|
7149
|
+
const sub = new BgSubscription(identity, () => this.ensureClient(), (client) => this.dropClient(client), this.consumerIdentity, onNudge, this.bgBackoffSleep);
|
|
6177
7150
|
record.bgSub = sub;
|
|
6178
7151
|
}
|
|
6179
7152
|
dropClient(client) {
|
|
@@ -6194,9 +7167,13 @@ class SubcTransportPool {
|
|
|
6194
7167
|
}
|
|
6195
7168
|
}
|
|
6196
7169
|
setConfigureOverride(_key, _value) {}
|
|
7170
|
+
async reconfigure(_projectRoot, _overrides) {}
|
|
6197
7171
|
async replaceBinary(path2) {
|
|
6198
7172
|
return path2;
|
|
6199
7173
|
}
|
|
7174
|
+
isShutdown() {
|
|
7175
|
+
return this.shuttingDown;
|
|
7176
|
+
}
|
|
6200
7177
|
async shutdown() {
|
|
6201
7178
|
this.shuttingDown = true;
|
|
6202
7179
|
const subs = [];
|
|
@@ -6220,10 +7197,10 @@ class SubcTransportPool {
|
|
|
6220
7197
|
this.transports.clear();
|
|
6221
7198
|
await Promise.allSettled(subs.map((sub) => sub.stop()));
|
|
6222
7199
|
await Promise.allSettled(entries.map(async (entry) => {
|
|
6223
|
-
if (entry.
|
|
7200
|
+
if (entry.handle == null)
|
|
6224
7201
|
return;
|
|
6225
7202
|
try {
|
|
6226
|
-
await entry.client.closeRouteChannel(entry.
|
|
7203
|
+
await entry.client.closeRouteChannel(entry.handle);
|
|
6227
7204
|
} catch {}
|
|
6228
7205
|
}));
|
|
6229
7206
|
if (client) {
|
|
@@ -6252,16 +7229,16 @@ class SubcTransportPool {
|
|
|
6252
7229
|
entry.closed = true;
|
|
6253
7230
|
if (sub)
|
|
6254
7231
|
await sub.stop();
|
|
6255
|
-
if (entry?.
|
|
7232
|
+
if (entry?.handle != null) {
|
|
6256
7233
|
try {
|
|
6257
|
-
await entry.client.closeRouteChannel(entry.
|
|
7234
|
+
await entry.client.closeRouteChannel(entry.handle);
|
|
6258
7235
|
} catch {}
|
|
6259
7236
|
}
|
|
6260
7237
|
}
|
|
6261
7238
|
}
|
|
6262
7239
|
var AFT_MODULE_ID = "aft", MAX_CONSECUTIVE_TRANSPORT_FAILURES = 3, BG_STABLE_MS = 5000, DEFAULT_SESSION_ID = "__default__", LOCALLY_SATISFIED_COMMANDS, RouteTornDownError;
|
|
6263
7240
|
var init_subc_transport = __esm(() => {
|
|
6264
|
-
|
|
7241
|
+
init_dist();
|
|
6265
7242
|
init_project_identity();
|
|
6266
7243
|
LOCALLY_SATISFIED_COMMANDS = new Set(["configure"]);
|
|
6267
7244
|
RouteTornDownError = class RouteTornDownError extends Error {
|
|
@@ -6355,18 +7332,25 @@ function formatReadFooter(agentSpecifiedRange, data, options) {
|
|
|
6355
7332
|
}
|
|
6356
7333
|
|
|
6357
7334
|
// ../aft-bridge/dist/transport-factory.js
|
|
6358
|
-
import { homedir as
|
|
6359
|
-
import { isAbsolute as isAbsolute5, join as
|
|
7335
|
+
import { homedir as homedir11 } from "node:os";
|
|
7336
|
+
import { isAbsolute as isAbsolute5, join as join10 } from "node:path";
|
|
6360
7337
|
function resolveConnectionFilePath(raw) {
|
|
6361
7338
|
const trimmed = raw.trim();
|
|
6362
7339
|
if (trimmed.startsWith("~")) {
|
|
6363
|
-
return
|
|
7340
|
+
return join10(homedir11(), trimmed.slice(1).replace(/^[/\\]/, ""));
|
|
6364
7341
|
}
|
|
6365
7342
|
if (isAbsolute5(trimmed))
|
|
6366
7343
|
return trimmed;
|
|
6367
|
-
return
|
|
7344
|
+
return join10(homedir11(), trimmed);
|
|
6368
7345
|
}
|
|
6369
7346
|
async function createAftTransportPool(opts) {
|
|
7347
|
+
let binaryPath = opts.binaryPath;
|
|
7348
|
+
const createPool = () => createConcreteAftTransportPool({ ...opts, binaryPath });
|
|
7349
|
+
return new RevivableTransportPool(await createPool(), createPool, (path2) => {
|
|
7350
|
+
binaryPath = path2;
|
|
7351
|
+
});
|
|
7352
|
+
}
|
|
7353
|
+
async function createConcreteAftTransportPool(opts) {
|
|
6370
7354
|
const raw = opts.subcConnectionFile?.trim();
|
|
6371
7355
|
if (raw && raw.length > 0) {
|
|
6372
7356
|
const connectionFile = resolveConnectionFilePath(raw);
|
|
@@ -6377,6 +7361,7 @@ async function createAftTransportPool(opts) {
|
|
|
6377
7361
|
return new SubcTransportPool({
|
|
6378
7362
|
connectionFile,
|
|
6379
7363
|
harness: opts.harness,
|
|
7364
|
+
consumerIdentity: opts.subcConsumerIdentity,
|
|
6380
7365
|
onBgEventsNudge: opts.onBgEventsNudge
|
|
6381
7366
|
});
|
|
6382
7367
|
}
|
|
@@ -6384,6 +7369,7 @@ async function createAftTransportPool(opts) {
|
|
|
6384
7369
|
}
|
|
6385
7370
|
var init_transport_factory = __esm(() => {
|
|
6386
7371
|
init_pool();
|
|
7372
|
+
init_revivable_transport();
|
|
6387
7373
|
init_subc_transport();
|
|
6388
7374
|
});
|
|
6389
7375
|
|
|
@@ -6501,6 +7487,7 @@ __export(exports_dist, {
|
|
|
6501
7487
|
timeoutForCommand: () => timeoutForCommand,
|
|
6502
7488
|
tagStderrLine: () => tagStderrLine,
|
|
6503
7489
|
stripJsoncSymbols: () => stripJsoncSymbols,
|
|
7490
|
+
stripHarnessSpecificConfigKeys: () => stripHarnessSpecificConfigKeys,
|
|
6504
7491
|
statusBarLine: () => statusBarLine,
|
|
6505
7492
|
sleep: () => sleep,
|
|
6506
7493
|
shouldShowAnnouncement: () => shouldShowAnnouncement,
|
|
@@ -6515,6 +7502,8 @@ __export(exports_dist, {
|
|
|
6515
7502
|
resolveCortexKitProjectConfigPath: () => resolveCortexKitProjectConfigPath,
|
|
6516
7503
|
resolveCortexKitConfigPaths: () => resolveCortexKitConfigPaths,
|
|
6517
7504
|
resolveBashKillTimeout: () => resolveBashKillTimeout,
|
|
7505
|
+
resolveAftStorageRoot: () => resolveAftStorageRoot,
|
|
7506
|
+
resolveAftLogPath: () => resolveAftLogPath,
|
|
6518
7507
|
repairRootScopedStorageFile: () => repairRootScopedStorageFile,
|
|
6519
7508
|
readConfigTiers: () => readConfigTiers,
|
|
6520
7509
|
projectRootKeyHash: () => projectRootKeyHash,
|
|
@@ -6572,23 +7561,31 @@ __export(exports_dist, {
|
|
|
6572
7561
|
__onnxTest__: () => __test__,
|
|
6573
7562
|
SubcTransportPool: () => SubcTransportPool,
|
|
6574
7563
|
STATUS_BAR_HEARTBEAT_CALLS: () => STATUS_BAR_HEARTBEAT_CALLS,
|
|
7564
|
+
RotatingLogSink: () => RotatingLogSink,
|
|
7565
|
+
RevivableTransportPool: () => RevivableTransportPool,
|
|
6575
7566
|
PLATFORM_ASSET_MAP: () => PLATFORM_ASSET_MAP,
|
|
6576
7567
|
PLATFORM_ARCH_MAP: () => PLATFORM_ARCH_MAP,
|
|
6577
7568
|
PLAIN_CALLGRAPH_THEME: () => PLAIN_CALLGRAPH_THEME,
|
|
7569
|
+
PI_ONLY_KEYS: () => PI_ONLY_KEYS,
|
|
7570
|
+
OPENCODE_ONLY_KEYS: () => OPENCODE_ONLY_KEYS,
|
|
6578
7571
|
LONG_RUNNING_COMMAND_TIMEOUT_MS: () => LONG_RUNNING_COMMAND_TIMEOUT_MS,
|
|
6579
7572
|
HomeProjectRootError: () => HomeProjectRootError,
|
|
7573
|
+
DEFAULT_LOG_GENERATIONS: () => DEFAULT_LOG_GENERATIONS,
|
|
7574
|
+
DEFAULT_LOG_BYTES: () => DEFAULT_LOG_BYTES,
|
|
6580
7575
|
BridgeTransportTimeoutError: () => BridgeTransportTimeoutError,
|
|
6581
7576
|
BridgePool: () => BridgePool,
|
|
6582
7577
|
BinaryBridge: () => BinaryBridge
|
|
6583
7578
|
});
|
|
6584
|
-
var
|
|
7579
|
+
var init_dist2 = __esm(() => {
|
|
6585
7580
|
init_active_logger();
|
|
6586
7581
|
init_bash_hints();
|
|
6587
7582
|
init_bridge();
|
|
6588
7583
|
init_callgraph_format();
|
|
6589
7584
|
init_command_timeouts();
|
|
7585
|
+
init_config_keys();
|
|
6590
7586
|
init_config_tiers();
|
|
6591
7587
|
init_downloader();
|
|
7588
|
+
init_durable_log();
|
|
6592
7589
|
init_migration();
|
|
6593
7590
|
init_npm_resolver();
|
|
6594
7591
|
init_onnx_runtime();
|
|
@@ -6597,70 +7594,70 @@ var init_dist = __esm(() => {
|
|
|
6597
7594
|
init_pool();
|
|
6598
7595
|
init_project_identity();
|
|
6599
7596
|
init_resolver();
|
|
7597
|
+
init_revivable_transport();
|
|
6600
7598
|
init_subc_transport();
|
|
6601
7599
|
init_transport_factory();
|
|
6602
7600
|
});
|
|
6603
7601
|
|
|
6604
7602
|
// src/lib/paths.ts
|
|
6605
|
-
import { homedir as
|
|
6606
|
-
import { join as
|
|
7603
|
+
import { homedir as homedir12 } from "node:os";
|
|
7604
|
+
import { join as join11 } from "node:path";
|
|
6607
7605
|
function getAftBinaryCacheDir() {
|
|
6608
7606
|
if (process.env.AFT_CACHE_DIR) {
|
|
6609
|
-
return
|
|
7607
|
+
return join11(process.env.AFT_CACHE_DIR, "bin");
|
|
6610
7608
|
}
|
|
6611
7609
|
if (process.platform === "win32") {
|
|
6612
7610
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
6613
|
-
const base2 = localAppData ||
|
|
6614
|
-
return
|
|
7611
|
+
const base2 = localAppData || join11(homedir12(), "AppData", "Local");
|
|
7612
|
+
return join11(base2, "aft", "bin");
|
|
6615
7613
|
}
|
|
6616
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
6617
|
-
return
|
|
7614
|
+
const base = process.env.XDG_CACHE_HOME || join11(homedir12(), ".cache");
|
|
7615
|
+
return join11(base, "aft", "bin");
|
|
6618
7616
|
}
|
|
6619
7617
|
function getAftBinaryName() {
|
|
6620
7618
|
return process.platform === "win32" ? "aft.exe" : "aft";
|
|
6621
7619
|
}
|
|
6622
7620
|
function getAftLspPackagesDir() {
|
|
6623
7621
|
if (process.env.AFT_CACHE_DIR) {
|
|
6624
|
-
return
|
|
7622
|
+
return join11(process.env.AFT_CACHE_DIR, "lsp-packages");
|
|
6625
7623
|
}
|
|
6626
7624
|
if (process.platform === "win32") {
|
|
6627
7625
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
6628
|
-
const base2 = localAppData ||
|
|
6629
|
-
return
|
|
7626
|
+
const base2 = localAppData || join11(homedir12(), "AppData", "Local");
|
|
7627
|
+
return join11(base2, "aft", "lsp-packages");
|
|
6630
7628
|
}
|
|
6631
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
6632
|
-
return
|
|
7629
|
+
const base = process.env.XDG_CACHE_HOME || join11(homedir12(), ".cache");
|
|
7630
|
+
return join11(base, "aft", "lsp-packages");
|
|
6633
7631
|
}
|
|
6634
7632
|
function getAftLspBinariesDir() {
|
|
6635
7633
|
if (process.env.AFT_CACHE_DIR) {
|
|
6636
|
-
return
|
|
7634
|
+
return join11(process.env.AFT_CACHE_DIR, "lsp-binaries");
|
|
6637
7635
|
}
|
|
6638
7636
|
if (process.platform === "win32") {
|
|
6639
7637
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
6640
|
-
const base2 = localAppData ||
|
|
6641
|
-
return
|
|
7638
|
+
const base2 = localAppData || join11(homedir12(), "AppData", "Local");
|
|
7639
|
+
return join11(base2, "aft", "lsp-binaries");
|
|
6642
7640
|
}
|
|
6643
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
6644
|
-
return
|
|
7641
|
+
const base = process.env.XDG_CACHE_HOME || join11(homedir12(), ".cache");
|
|
7642
|
+
return join11(base, "aft", "lsp-binaries");
|
|
6645
7643
|
}
|
|
6646
|
-
function
|
|
7644
|
+
function homeDir4() {
|
|
6647
7645
|
if (process.platform === "win32")
|
|
6648
|
-
return process.env.USERPROFILE || process.env.HOME ||
|
|
6649
|
-
return process.env.HOME ||
|
|
7646
|
+
return process.env.USERPROFILE || process.env.HOME || homedir12();
|
|
7647
|
+
return process.env.HOME || homedir12();
|
|
6650
7648
|
}
|
|
6651
|
-
function
|
|
7649
|
+
function dataHome3() {
|
|
6652
7650
|
if (process.env.XDG_DATA_HOME)
|
|
6653
7651
|
return process.env.XDG_DATA_HOME;
|
|
6654
7652
|
if (process.platform === "win32") {
|
|
6655
|
-
return process.env.LOCALAPPDATA || process.env.APPDATA ||
|
|
7653
|
+
return process.env.LOCALAPPDATA || process.env.APPDATA || join11(homeDir4(), "AppData", "Local");
|
|
6656
7654
|
}
|
|
6657
|
-
return
|
|
7655
|
+
return join11(homeDir4(), ".local", "share");
|
|
6658
7656
|
}
|
|
6659
7657
|
function getCortexKitStorageRoot() {
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
return join10(tmpdir2(), filename);
|
|
7658
|
+
if (process.env.AFT_CACHE_DIR)
|
|
7659
|
+
return join11(process.env.AFT_CACHE_DIR, "aft");
|
|
7660
|
+
return join11(dataHome3(), "cortexkit", "aft");
|
|
6664
7661
|
}
|
|
6665
7662
|
var init_paths2 = () => {};
|
|
6666
7663
|
|
|
@@ -6668,11 +7665,11 @@ var init_paths2 = () => {};
|
|
|
6668
7665
|
import { execSync as execSync2, spawnSync as spawnSync3 } from "node:child_process";
|
|
6669
7666
|
import { existsSync as existsSync7 } from "node:fs";
|
|
6670
7667
|
import { createRequire as createRequire2 } from "node:module";
|
|
6671
|
-
import { homedir as
|
|
6672
|
-
import { join as
|
|
7668
|
+
import { homedir as homedir13 } from "node:os";
|
|
7669
|
+
import { join as join12 } from "node:path";
|
|
6673
7670
|
async function loadPluginVersion() {
|
|
6674
7671
|
try {
|
|
6675
|
-
const bridge = await Promise.resolve().then(() => (
|
|
7672
|
+
const bridge = await Promise.resolve().then(() => (init_dist2(), exports_dist));
|
|
6676
7673
|
if (typeof bridge.PLUGIN_VERSION === "string" && bridge.PLUGIN_VERSION.length > 0) {
|
|
6677
7674
|
return bridge.PLUGIN_VERSION;
|
|
6678
7675
|
}
|
|
@@ -6791,7 +7788,7 @@ function aftBinaryCandidates(preferredVersion) {
|
|
|
6791
7788
|
const candidates = [];
|
|
6792
7789
|
if (preferredVersion) {
|
|
6793
7790
|
const tag = preferredVersion.startsWith("v") ? preferredVersion : `v${preferredVersion}`;
|
|
6794
|
-
pushCandidate(candidates,
|
|
7791
|
+
pushCandidate(candidates, join12(getAftBinaryCacheDir(), tag, getAftBinaryName()));
|
|
6795
7792
|
}
|
|
6796
7793
|
const key = platformKey2();
|
|
6797
7794
|
if (key) {
|
|
@@ -6814,7 +7811,7 @@ function aftBinaryCandidates(preferredVersion) {
|
|
|
6814
7811
|
}
|
|
6815
7812
|
}
|
|
6816
7813
|
} catch {}
|
|
6817
|
-
pushCandidate(candidates,
|
|
7814
|
+
pushCandidate(candidates, join12(homedir13(), ".cargo", "bin", getAftBinaryName()));
|
|
6818
7815
|
return candidates;
|
|
6819
7816
|
}
|
|
6820
7817
|
function findAftBinary(preferredVersion) {
|
|
@@ -6822,7 +7819,7 @@ function findAftBinary(preferredVersion) {
|
|
|
6822
7819
|
}
|
|
6823
7820
|
var PLUGIN_VERSION, VERSION_LINE;
|
|
6824
7821
|
var init_binary_probe = __esm(async () => {
|
|
6825
|
-
|
|
7822
|
+
init_dist2();
|
|
6826
7823
|
init_paths2();
|
|
6827
7824
|
PLUGIN_VERSION = await loadPluginVersion();
|
|
6828
7825
|
VERSION_LINE = /^(?:aft\s+)?v?(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)$/i;
|
|
@@ -6830,21 +7827,21 @@ var init_binary_probe = __esm(async () => {
|
|
|
6830
7827
|
|
|
6831
7828
|
// src/lib/fs-util.ts
|
|
6832
7829
|
import { existsSync as existsSync8, readdirSync as readdirSync3, statSync as statSync5 } from "node:fs";
|
|
6833
|
-
import { join as
|
|
7830
|
+
import { join as join13 } from "node:path";
|
|
6834
7831
|
function dirSize(path2) {
|
|
6835
7832
|
if (!existsSync8(path2)) {
|
|
6836
7833
|
return 0;
|
|
6837
7834
|
}
|
|
6838
|
-
const
|
|
6839
|
-
if (
|
|
6840
|
-
return
|
|
7835
|
+
const stat2 = statSync5(path2);
|
|
7836
|
+
if (stat2.isFile()) {
|
|
7837
|
+
return stat2.size;
|
|
6841
7838
|
}
|
|
6842
|
-
if (!
|
|
7839
|
+
if (!stat2.isDirectory()) {
|
|
6843
7840
|
return 0;
|
|
6844
7841
|
}
|
|
6845
7842
|
let total = 0;
|
|
6846
7843
|
for (const entry of readdirSync3(path2)) {
|
|
6847
|
-
total += dirSize(
|
|
7844
|
+
total += dirSize(join13(path2, entry));
|
|
6848
7845
|
}
|
|
6849
7846
|
return total;
|
|
6850
7847
|
}
|
|
@@ -14467,10 +15464,10 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
14467
15464
|
replacer = null;
|
|
14468
15465
|
indent = EMPTY;
|
|
14469
15466
|
};
|
|
14470
|
-
var
|
|
15467
|
+
var join14 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(one, gap)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two, gap)), gap) : EMPTY;
|
|
14471
15468
|
var join_content = (inside, value, gap) => {
|
|
14472
15469
|
const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
|
|
14473
|
-
return
|
|
15470
|
+
return join14(comment, inside, gap);
|
|
14474
15471
|
};
|
|
14475
15472
|
var stringify_string = (holder, key, value) => {
|
|
14476
15473
|
const raw = get_raw_string_literal(holder, key);
|
|
@@ -14492,13 +15489,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
14492
15489
|
if (i !== 0) {
|
|
14493
15490
|
inside += COMMA;
|
|
14494
15491
|
}
|
|
14495
|
-
const before =
|
|
15492
|
+
const before = join14(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
|
|
14496
15493
|
inside += before || LF + deeper_gap;
|
|
14497
15494
|
inside += stringify(i, value, deeper_gap) || STR_NULL;
|
|
14498
15495
|
inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
|
|
14499
15496
|
after_comma = process_comments(value, AFTER(i), deeper_gap);
|
|
14500
15497
|
}
|
|
14501
|
-
inside +=
|
|
15498
|
+
inside += join14(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
14502
15499
|
return BRACKET_OPEN + join_content(inside, value, gap) + BRACKET_CLOSE;
|
|
14503
15500
|
};
|
|
14504
15501
|
var object_stringify = (value, gap) => {
|
|
@@ -14519,13 +15516,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
14519
15516
|
inside += COMMA;
|
|
14520
15517
|
}
|
|
14521
15518
|
first = false;
|
|
14522
|
-
const before =
|
|
15519
|
+
const before = join14(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
|
|
14523
15520
|
inside += before || LF + deeper_gap;
|
|
14524
15521
|
inside += quote(key) + process_comments(value, AFTER_PROP(key), deeper_gap) + COLON + process_comments(value, AFTER_COLON(key), deeper_gap) + SPACE + sv + process_comments(value, AFTER_VALUE(key), deeper_gap);
|
|
14525
15522
|
after_comma = process_comments(value, AFTER(key), deeper_gap);
|
|
14526
15523
|
};
|
|
14527
15524
|
keys.forEach(iteratee);
|
|
14528
|
-
inside +=
|
|
15525
|
+
inside += join14(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
14529
15526
|
return CURLY_BRACKET_OPEN + join_content(inside, value, gap) + CURLY_BRACKET_CLOSE;
|
|
14530
15527
|
};
|
|
14531
15528
|
function stringify(key, holder, gap) {
|
|
@@ -14619,7 +15616,7 @@ var require_src2 = __commonJS((exports, module) => {
|
|
|
14619
15616
|
|
|
14620
15617
|
// src/lib/jsonc.ts
|
|
14621
15618
|
import { existsSync as existsSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "node:fs";
|
|
14622
|
-
import { dirname as
|
|
15619
|
+
import { dirname as dirname6 } from "node:path";
|
|
14623
15620
|
function detectJsoncFile(configDir, baseName) {
|
|
14624
15621
|
const jsoncPath = `${configDir}/${baseName}.jsonc`;
|
|
14625
15622
|
const jsonPath = `${configDir}/${baseName}.json`;
|
|
@@ -14647,7 +15644,7 @@ function readJsoncFile(path2) {
|
|
|
14647
15644
|
}
|
|
14648
15645
|
}
|
|
14649
15646
|
function writeJsoncFile(path2, value, format = "json") {
|
|
14650
|
-
mkdirSync6(
|
|
15647
|
+
mkdirSync6(dirname6(path2), { recursive: true });
|
|
14651
15648
|
const serialized = format === "jsonc" ? import_comment_json.stringify(value, null, 2) : JSON.stringify(value, null, 2);
|
|
14652
15649
|
writeFileSync4(path2, `${serialized}
|
|
14653
15650
|
`);
|
|
@@ -14707,25 +15704,25 @@ var init_self_version = () => {};
|
|
|
14707
15704
|
// src/adapters/opencode.ts
|
|
14708
15705
|
import { execSync as execSync3 } from "node:child_process";
|
|
14709
15706
|
import { existsSync as existsSync10, readFileSync as readFileSync8, rmSync as rmSync4, statSync as statSync6 } from "node:fs";
|
|
14710
|
-
import { homedir as
|
|
14711
|
-
import { dirname as
|
|
15707
|
+
import { homedir as homedir14 } from "node:os";
|
|
15708
|
+
import { dirname as dirname7, join as join14, parse, resolve as resolve7 } from "node:path";
|
|
14712
15709
|
import { fileURLToPath } from "node:url";
|
|
14713
15710
|
function getOpenCodeConfigDir() {
|
|
14714
15711
|
const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
14715
15712
|
if (envDir)
|
|
14716
15713
|
return resolve7(envDir);
|
|
14717
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
14718
|
-
return
|
|
15714
|
+
const xdg = process.env.XDG_CONFIG_HOME || join14(homedir14(), ".config");
|
|
15715
|
+
return join14(xdg, "opencode");
|
|
14719
15716
|
}
|
|
14720
15717
|
function getOpenCodeCacheDir() {
|
|
14721
15718
|
const xdg = process.env.XDG_CACHE_HOME;
|
|
14722
15719
|
if (xdg)
|
|
14723
|
-
return
|
|
15720
|
+
return join14(xdg, "opencode");
|
|
14724
15721
|
if (process.platform === "win32") {
|
|
14725
|
-
const localAppData = process.env.LOCALAPPDATA ??
|
|
14726
|
-
return
|
|
15722
|
+
const localAppData = process.env.LOCALAPPDATA ?? join14(homedir14(), "AppData", "Local");
|
|
15723
|
+
return join14(localAppData, "opencode");
|
|
14727
15724
|
}
|
|
14728
|
-
return
|
|
15725
|
+
return join14(homedir14(), ".cache", "opencode");
|
|
14729
15726
|
}
|
|
14730
15727
|
function hasOpenCodeCli() {
|
|
14731
15728
|
try {
|
|
@@ -14738,12 +15735,12 @@ function hasOpenCodeCli() {
|
|
|
14738
15735
|
function openCodeDesktopAppExists() {
|
|
14739
15736
|
const candidates = [];
|
|
14740
15737
|
if (process.platform === "darwin") {
|
|
14741
|
-
candidates.push("/Applications/OpenCode.app", "/Applications/OpenCode Beta.app",
|
|
15738
|
+
candidates.push("/Applications/OpenCode.app", "/Applications/OpenCode Beta.app", join14(homedir14(), "Applications", "OpenCode.app"), join14(homedir14(), "Applications", "OpenCode Beta.app"));
|
|
14742
15739
|
} else if (process.platform === "win32") {
|
|
14743
|
-
const localAppData = process.env.LOCALAPPDATA ??
|
|
14744
|
-
candidates.push(
|
|
15740
|
+
const localAppData = process.env.LOCALAPPDATA ?? join14(homedir14(), "AppData", "Local");
|
|
15741
|
+
candidates.push(join14(localAppData, "Programs", "opencode"), join14(localAppData, "opencode"));
|
|
14745
15742
|
} else {
|
|
14746
|
-
candidates.push("/opt/OpenCode", "/usr/lib/opencode",
|
|
15743
|
+
candidates.push("/opt/OpenCode", "/usr/lib/opencode", join14(homedir14(), ".local", "share", "applications", "opencode.desktop"));
|
|
14747
15744
|
}
|
|
14748
15745
|
return candidates.some((p) => {
|
|
14749
15746
|
try {
|
|
@@ -14772,15 +15769,15 @@ function pathPointsToOurPlugin(entry) {
|
|
|
14772
15769
|
try {
|
|
14773
15770
|
if (!existsSync10(fsPath))
|
|
14774
15771
|
return false;
|
|
14775
|
-
let searchDir = statSync6(fsPath).isDirectory() ? fsPath :
|
|
15772
|
+
let searchDir = statSync6(fsPath).isDirectory() ? fsPath : dirname7(fsPath);
|
|
14776
15773
|
let pkgJsonPath = null;
|
|
14777
15774
|
while (true) {
|
|
14778
|
-
const candidate =
|
|
15775
|
+
const candidate = join14(searchDir, "package.json");
|
|
14779
15776
|
if (existsSync10(candidate)) {
|
|
14780
15777
|
pkgJsonPath = candidate;
|
|
14781
15778
|
break;
|
|
14782
15779
|
}
|
|
14783
|
-
const parent =
|
|
15780
|
+
const parent = dirname7(searchDir);
|
|
14784
15781
|
if (parent === searchDir || searchDir === parse(searchDir).root)
|
|
14785
15782
|
break;
|
|
14786
15783
|
searchDir = parent;
|
|
@@ -14946,10 +15943,10 @@ class OpenCodeAdapter {
|
|
|
14946
15943
|
};
|
|
14947
15944
|
}
|
|
14948
15945
|
getPluginCacheInfo() {
|
|
14949
|
-
const path2 =
|
|
15946
|
+
const path2 = join14(getOpenCodeCacheDir(), "packages", PLUGIN_ENTRY);
|
|
14950
15947
|
let cached;
|
|
14951
15948
|
try {
|
|
14952
|
-
const installedPkgPath =
|
|
15949
|
+
const installedPkgPath = join14(path2, "node_modules", "@cortexkit", "aft-opencode", "package.json");
|
|
14953
15950
|
if (existsSync10(installedPkgPath)) {
|
|
14954
15951
|
const pkg = JSON.parse(readFileSync8(installedPkgPath, "utf-8"));
|
|
14955
15952
|
cached = typeof pkg.version === "string" ? pkg.version : undefined;
|
|
@@ -14968,7 +15965,7 @@ class OpenCodeAdapter {
|
|
|
14968
15965
|
return getCortexKitStorageRoot();
|
|
14969
15966
|
}
|
|
14970
15967
|
getLogFile() {
|
|
14971
|
-
return
|
|
15968
|
+
return resolveAftLogPath("aft-plugin.log");
|
|
14972
15969
|
}
|
|
14973
15970
|
getInstallHint() {
|
|
14974
15971
|
return "Install OpenCode: https://opencode.ai/docs/install";
|
|
@@ -15010,17 +16007,17 @@ class OpenCodeAdapter {
|
|
|
15010
16007
|
describeStorageSubtrees() {
|
|
15011
16008
|
const storage = this.getStorageDir();
|
|
15012
16009
|
return {
|
|
15013
|
-
index: dirSize(
|
|
15014
|
-
semantic: dirSize(
|
|
15015
|
-
backups: dirSize(
|
|
15016
|
-
url_cache: dirSize(
|
|
15017
|
-
onnxruntime: dirSize(
|
|
16010
|
+
index: dirSize(join14(storage, "index")),
|
|
16011
|
+
semantic: dirSize(join14(storage, "semantic")),
|
|
16012
|
+
backups: dirSize(join14(storage, "backups")),
|
|
16013
|
+
url_cache: dirSize(join14(storage, "url_cache")),
|
|
16014
|
+
onnxruntime: dirSize(join14(storage, "onnxruntime"))
|
|
15018
16015
|
};
|
|
15019
16016
|
}
|
|
15020
16017
|
}
|
|
15021
16018
|
var PLUGIN_NAME = "@cortexkit/aft-opencode", PLUGIN_ENTRY;
|
|
15022
16019
|
var init_opencode = __esm(() => {
|
|
15023
|
-
|
|
16020
|
+
init_dist2();
|
|
15024
16021
|
init_fs_util();
|
|
15025
16022
|
init_jsonc();
|
|
15026
16023
|
init_paths2();
|
|
@@ -15031,15 +16028,15 @@ var init_opencode = __esm(() => {
|
|
|
15031
16028
|
// src/adapters/pi.ts
|
|
15032
16029
|
import { execSync as execSync4, spawnSync as spawnSync4 } from "node:child_process";
|
|
15033
16030
|
import { existsSync as existsSync11, readFileSync as readFileSync9 } from "node:fs";
|
|
15034
|
-
import { homedir as
|
|
15035
|
-
import { join as
|
|
16031
|
+
import { homedir as homedir15 } from "node:os";
|
|
16032
|
+
import { join as join15 } from "node:path";
|
|
15036
16033
|
function getPiAgentDir() {
|
|
15037
16034
|
const envHome = process.platform === "win32" ? process.env.USERPROFILE : process.env.HOME;
|
|
15038
|
-
const home = envHome && envHome.length > 0 ? envHome :
|
|
15039
|
-
return
|
|
16035
|
+
const home = envHome && envHome.length > 0 ? envHome : homedir15();
|
|
16036
|
+
return join15(home, ".pi", "agent");
|
|
15040
16037
|
}
|
|
15041
16038
|
function readPiExtensionIndex() {
|
|
15042
|
-
const settingsPath =
|
|
16039
|
+
const settingsPath = join15(getPiAgentDir(), "settings.json");
|
|
15043
16040
|
if (existsSync11(settingsPath)) {
|
|
15044
16041
|
try {
|
|
15045
16042
|
const raw = readFileSync9(settingsPath, "utf-8");
|
|
@@ -15053,10 +16050,10 @@ function readPiExtensionIndex() {
|
|
|
15053
16050
|
} catch {}
|
|
15054
16051
|
}
|
|
15055
16052
|
const candidates = [
|
|
15056
|
-
|
|
15057
|
-
|
|
15058
|
-
|
|
15059
|
-
|
|
16053
|
+
join15(getPiAgentDir(), "extensions.json"),
|
|
16054
|
+
join15(getPiAgentDir(), "extensions.jsonc"),
|
|
16055
|
+
join15(getPiAgentDir(), "config.json"),
|
|
16056
|
+
join15(getPiAgentDir(), "config.jsonc")
|
|
15060
16057
|
];
|
|
15061
16058
|
for (const path2 of candidates) {
|
|
15062
16059
|
if (!existsSync11(path2))
|
|
@@ -15092,14 +16089,14 @@ function piEntryMatchesAft(entry) {
|
|
|
15092
16089
|
} else if (entry.startsWith("/")) {
|
|
15093
16090
|
resolved = entry;
|
|
15094
16091
|
} else if (entry.length > 0) {
|
|
15095
|
-
resolved =
|
|
16092
|
+
resolved = join15(getPiAgentDir(), entry);
|
|
15096
16093
|
}
|
|
15097
16094
|
if (!resolved)
|
|
15098
16095
|
return false;
|
|
15099
16096
|
try {
|
|
15100
16097
|
if (!existsSync11(resolved))
|
|
15101
16098
|
return false;
|
|
15102
|
-
const pkgPath =
|
|
16099
|
+
const pkgPath = join15(resolved, "package.json");
|
|
15103
16100
|
if (!existsSync11(pkgPath))
|
|
15104
16101
|
return false;
|
|
15105
16102
|
const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
|
|
@@ -15151,7 +16148,7 @@ class PiAdapter {
|
|
|
15151
16148
|
const aftConfigExists = existsSync11(aftConfigPath);
|
|
15152
16149
|
return {
|
|
15153
16150
|
configDir,
|
|
15154
|
-
harnessConfig: index.path ??
|
|
16151
|
+
harnessConfig: index.path ?? join15(configDir, "extensions.json"),
|
|
15155
16152
|
harnessConfigFormat: index.path ? "json" : "none",
|
|
15156
16153
|
aftConfig: aftConfigPath,
|
|
15157
16154
|
aftConfigFormat: aftConfigExists ? "jsonc" : "none"
|
|
@@ -15196,8 +16193,8 @@ class PiAdapter {
|
|
|
15196
16193
|
}
|
|
15197
16194
|
getPluginCacheInfo() {
|
|
15198
16195
|
const candidates = [
|
|
15199
|
-
|
|
15200
|
-
|
|
16196
|
+
join15(getPiAgentDir(), "node_modules", "@cortexkit", "aft-pi", "package.json"),
|
|
16197
|
+
join15(getPiAgentDir(), "extensions", "node_modules", "@cortexkit", "aft-pi", "package.json")
|
|
15201
16198
|
];
|
|
15202
16199
|
for (const candidate of candidates) {
|
|
15203
16200
|
if (!existsSync11(candidate))
|
|
@@ -15214,7 +16211,7 @@ class PiAdapter {
|
|
|
15214
16211
|
} catch {}
|
|
15215
16212
|
}
|
|
15216
16213
|
return {
|
|
15217
|
-
path:
|
|
16214
|
+
path: join15(getPiAgentDir(), "extensions"),
|
|
15218
16215
|
exists: false
|
|
15219
16216
|
};
|
|
15220
16217
|
}
|
|
@@ -15222,7 +16219,7 @@ class PiAdapter {
|
|
|
15222
16219
|
return getCortexKitStorageRoot();
|
|
15223
16220
|
}
|
|
15224
16221
|
getLogFile() {
|
|
15225
|
-
return
|
|
16222
|
+
return resolveAftLogPath("aft-plugin.log");
|
|
15226
16223
|
}
|
|
15227
16224
|
getInstallHint() {
|
|
15228
16225
|
return "Install Pi: https://github.com/badlogic/pi-mono";
|
|
@@ -15236,17 +16233,17 @@ class PiAdapter {
|
|
|
15236
16233
|
describeStorageSubtrees() {
|
|
15237
16234
|
const storage = this.getStorageDir();
|
|
15238
16235
|
return {
|
|
15239
|
-
index: dirSize(
|
|
15240
|
-
semantic: dirSize(
|
|
15241
|
-
backups: dirSize(
|
|
15242
|
-
url_cache: dirSize(
|
|
15243
|
-
onnxruntime: dirSize(
|
|
16236
|
+
index: dirSize(join15(storage, "index")),
|
|
16237
|
+
semantic: dirSize(join15(storage, "semantic")),
|
|
16238
|
+
backups: dirSize(join15(storage, "backups")),
|
|
16239
|
+
url_cache: dirSize(join15(storage, "url_cache")),
|
|
16240
|
+
onnxruntime: dirSize(join15(storage, "onnxruntime"))
|
|
15244
16241
|
};
|
|
15245
16242
|
}
|
|
15246
16243
|
}
|
|
15247
16244
|
var PLUGIN_NAME2 = "@cortexkit/aft-pi", PLUGIN_ENTRY2;
|
|
15248
16245
|
var init_pi = __esm(() => {
|
|
15249
|
-
|
|
16246
|
+
init_dist2();
|
|
15250
16247
|
init_fs_util();
|
|
15251
16248
|
init_jsonc();
|
|
15252
16249
|
init_paths2();
|
|
@@ -15382,7 +16379,7 @@ var ANSI_RE, CONTROL_RE, CJKT_WIDE_RE, TAB_RE, EMOJI_RE, LATIN_RE, MODIFIER_RE,
|
|
|
15382
16379
|
ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
|
|
15383
16380
|
};
|
|
15384
16381
|
}, dist_default;
|
|
15385
|
-
var
|
|
16382
|
+
var init_dist3 = __esm(() => {
|
|
15386
16383
|
init_utils();
|
|
15387
16384
|
ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
|
|
15388
16385
|
CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
|
|
@@ -15399,8 +16396,8 @@ var init_dist2 = __esm(() => {
|
|
|
15399
16396
|
var NO_TRUNCATION2, fastStringWidth = (input, options = {}) => {
|
|
15400
16397
|
return dist_default(input, NO_TRUNCATION2, options).width;
|
|
15401
16398
|
}, dist_default2;
|
|
15402
|
-
var
|
|
15403
|
-
|
|
16399
|
+
var init_dist4 = __esm(() => {
|
|
16400
|
+
init_dist3();
|
|
15404
16401
|
NO_TRUNCATION2 = {
|
|
15405
16402
|
limit: Infinity,
|
|
15406
16403
|
ellipsis: "",
|
|
@@ -15606,7 +16603,7 @@ var ESC = "\x1B", CSI = "", END_CODE = 39, ANSI_ESCAPE_BELL = "\x07", ANSI_CSI
|
|
|
15606
16603
|
return returnValue;
|
|
15607
16604
|
}, CRLF_OR_LF;
|
|
15608
16605
|
var init_main = __esm(() => {
|
|
15609
|
-
|
|
16606
|
+
init_dist4();
|
|
15610
16607
|
ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
|
|
15611
16608
|
GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
|
|
15612
16609
|
CRLF_OR_LF = /\r?\n/;
|
|
@@ -15961,7 +16958,7 @@ function T2(r2, t2, i, s) {
|
|
|
15961
16958
|
};
|
|
15962
16959
|
}
|
|
15963
16960
|
var import_sisteransi, a$2, t, settings, R, CANCEL_SYMBOL, getColumns = (e) => ("columns" in e) && typeof e.columns == "number" ? e.columns : 80, getRows = (e) => ("rows" in e) && typeof e.rows == "number" ? e.rows : 20, T$1, r, _, U, u$1, o$1, h, a$1, a2, n;
|
|
15964
|
-
var
|
|
16961
|
+
var init_dist5 = __esm(() => {
|
|
15965
16962
|
init_main();
|
|
15966
16963
|
import_sisteransi = __toESM(require_src3(), 1);
|
|
15967
16964
|
a$2 = ["up", "down", "left", "right", "space", "enter", "cancel"];
|
|
@@ -16813,11 +17810,11 @@ ${r2}
|
|
|
16813
17810
|
}
|
|
16814
17811
|
}
|
|
16815
17812
|
}).prompt();
|
|
16816
|
-
var
|
|
16817
|
-
|
|
16818
|
-
|
|
17813
|
+
var init_dist6 = __esm(() => {
|
|
17814
|
+
init_dist5();
|
|
17815
|
+
init_dist5();
|
|
16819
17816
|
init_main();
|
|
16820
|
-
|
|
17817
|
+
init_dist4();
|
|
16821
17818
|
import_sisteransi2 = __toESM(require_src3(), 1);
|
|
16822
17819
|
unicode = isUnicodeSupported();
|
|
16823
17820
|
S_STEP_ACTIVE = unicodeOr("◆", "*");
|
|
@@ -16954,7 +17951,7 @@ async function text2(message, options = {}) {
|
|
|
16954
17951
|
return result;
|
|
16955
17952
|
}
|
|
16956
17953
|
var init_prompts = __esm(() => {
|
|
16957
|
-
|
|
17954
|
+
init_dist6();
|
|
16958
17955
|
});
|
|
16959
17956
|
|
|
16960
17957
|
// src/lib/harness-select.ts
|
|
@@ -17264,28 +18261,30 @@ var init_aft_bridge = () => {};
|
|
|
17264
18261
|
// src/commands/lsp.ts
|
|
17265
18262
|
var exports_lsp = {};
|
|
17266
18263
|
__export(exports_lsp, {
|
|
18264
|
+
typescriptPackageWarning: () => typescriptPackageWarning,
|
|
17267
18265
|
runLspDoctor: () => runLspDoctor,
|
|
17268
18266
|
renderLspInspection: () => renderLspInspection,
|
|
17269
18267
|
printLspDoctorHelp: () => printLspDoctorHelp,
|
|
17270
18268
|
findProjectRootForFile: () => findProjectRootForFile
|
|
17271
18269
|
});
|
|
17272
18270
|
import { existsSync as existsSync12, readdirSync as readdirSync4, statSync as statSync7 } from "node:fs";
|
|
17273
|
-
import {
|
|
18271
|
+
import { createRequire as createRequire4 } from "node:module";
|
|
18272
|
+
import { dirname as dirname8, join as join16, resolve as resolve8 } from "node:path";
|
|
17274
18273
|
function findProjectRootForFile(filePath, fallbackCwd = process.cwd()) {
|
|
17275
18274
|
const resolvedFile = resolve8(fallbackCwd, filePath);
|
|
17276
|
-
let dir =
|
|
18275
|
+
let dir = dirname8(resolvedFile);
|
|
17277
18276
|
try {
|
|
17278
18277
|
if (existsSync12(resolvedFile) && statSync7(resolvedFile).isDirectory()) {
|
|
17279
18278
|
dir = resolvedFile;
|
|
17280
18279
|
}
|
|
17281
18280
|
} catch {
|
|
17282
|
-
dir =
|
|
18281
|
+
dir = dirname8(resolvedFile);
|
|
17283
18282
|
}
|
|
17284
18283
|
while (true) {
|
|
17285
|
-
if (PROJECT_ROOT_MARKERS.some((marker) => existsSync12(
|
|
18284
|
+
if (PROJECT_ROOT_MARKERS.some((marker) => existsSync12(join16(dir, marker)))) {
|
|
17286
18285
|
return dir;
|
|
17287
18286
|
}
|
|
17288
|
-
const parent =
|
|
18287
|
+
const parent = dirname8(dir);
|
|
17289
18288
|
if (parent === dir)
|
|
17290
18289
|
return resolve8(fallbackCwd);
|
|
17291
18290
|
dir = parent;
|
|
@@ -17341,7 +18340,12 @@ async function runLspDoctor(options) {
|
|
|
17341
18340
|
log2.error(inspect.message ?? inspect.code ?? "lsp_inspect failed");
|
|
17342
18341
|
return 1;
|
|
17343
18342
|
}
|
|
17344
|
-
|
|
18343
|
+
const inspection = inspect;
|
|
18344
|
+
const typescriptWarning = typescriptPackageWarning(inspection);
|
|
18345
|
+
console.log(renderLspInspection(file, {
|
|
18346
|
+
...inspection,
|
|
18347
|
+
...typescriptWarning ? { typescript_package_warning: typescriptWarning } : {}
|
|
18348
|
+
}));
|
|
17345
18349
|
return 0;
|
|
17346
18350
|
}
|
|
17347
18351
|
function renderLspInspection(inputFile, response) {
|
|
@@ -17377,6 +18381,10 @@ function renderLspInspection(inputFile, response) {
|
|
|
17377
18381
|
lines.push(` Action: ${installHint(server.binary_name)}`);
|
|
17378
18382
|
}
|
|
17379
18383
|
}
|
|
18384
|
+
if (response.typescript_package_warning) {
|
|
18385
|
+
lines.push("");
|
|
18386
|
+
lines.push(`Warning: ${response.typescript_package_warning}`);
|
|
18387
|
+
}
|
|
17380
18388
|
const diagnostics = response.diagnostics ?? [];
|
|
17381
18389
|
lines.push("");
|
|
17382
18390
|
lines.push(`Diagnostics (${response.diagnostics_count ?? diagnostics.length} found):`);
|
|
@@ -17405,8 +18413,8 @@ function parseFileArg(argv) {
|
|
|
17405
18413
|
function buildConfigureParams(adapter, projectRoot) {
|
|
17406
18414
|
const userConfigPath = adapter.detectConfigPaths().aftConfig;
|
|
17407
18415
|
const dir = adapter.kind === "pi" ? ".pi" : ".opencode";
|
|
17408
|
-
const projectJsonc =
|
|
17409
|
-
const projectJson =
|
|
18416
|
+
const projectJsonc = join16(projectRoot, dir, "aft.jsonc");
|
|
18417
|
+
const projectJson = join16(projectRoot, dir, "aft.json");
|
|
17410
18418
|
const projectConfigPath = existsSync12(projectJsonc) ? projectJsonc : projectJson;
|
|
17411
18419
|
return {
|
|
17412
18420
|
id: "doctor-lsp-configure",
|
|
@@ -17420,10 +18428,10 @@ function buildConfigureParams(adapter, projectRoot) {
|
|
|
17420
18428
|
function inferLspPathsExtra(_lsp) {
|
|
17421
18429
|
const paths = new Set;
|
|
17422
18430
|
for (const entry of childDirs(getAftLspPackagesDir())) {
|
|
17423
|
-
paths.add(
|
|
18431
|
+
paths.add(join16(entry, "node_modules", ".bin"));
|
|
17424
18432
|
}
|
|
17425
18433
|
for (const entry of childDirs(getAftLspBinariesDir())) {
|
|
17426
|
-
paths.add(
|
|
18434
|
+
paths.add(join16(entry, "bin"));
|
|
17427
18435
|
}
|
|
17428
18436
|
return [...paths];
|
|
17429
18437
|
}
|
|
@@ -17431,7 +18439,7 @@ function childDirs(path2) {
|
|
|
17431
18439
|
if (!existsSync12(path2))
|
|
17432
18440
|
return [];
|
|
17433
18441
|
try {
|
|
17434
|
-
return readdirSync4(path2).map((entry) =>
|
|
18442
|
+
return readdirSync4(path2).map((entry) => join16(path2, entry)).filter((entry) => {
|
|
17435
18443
|
try {
|
|
17436
18444
|
return statSync7(entry).isDirectory();
|
|
17437
18445
|
} catch {
|
|
@@ -17466,6 +18474,18 @@ function formatSpawnStatus(server) {
|
|
|
17466
18474
|
function formatList(values) {
|
|
17467
18475
|
return values.length === 0 ? "(none)" : values.join(", ");
|
|
17468
18476
|
}
|
|
18477
|
+
function typescriptPackageWarning(response) {
|
|
18478
|
+
const typescriptServerSpawned = response.matching_servers?.some((server) => server.id === "typescript" && server.spawn_status === "ok");
|
|
18479
|
+
const diagnosticsCount = response.diagnostics_count ?? response.diagnostics?.length ?? 0;
|
|
18480
|
+
if (!typescriptServerSpawned || !response.project_root || diagnosticsCount > 0)
|
|
18481
|
+
return null;
|
|
18482
|
+
try {
|
|
18483
|
+
createRequire4(join16(response.project_root, "package.json")).resolve("typescript");
|
|
18484
|
+
return null;
|
|
18485
|
+
} catch {
|
|
18486
|
+
return "typescript package not resolvable from project — server will produce no diagnostics";
|
|
18487
|
+
}
|
|
18488
|
+
}
|
|
17469
18489
|
function installHint(binaryName) {
|
|
17470
18490
|
if (binaryName === "ty")
|
|
17471
18491
|
return "Install with `uv tool install ty` or `pip install ty`.";
|
|
@@ -17475,7 +18495,7 @@ function installHint(binaryName) {
|
|
|
17475
18495
|
}
|
|
17476
18496
|
var PROJECT_ROOT_MARKERS;
|
|
17477
18497
|
var init_lsp = __esm(async () => {
|
|
17478
|
-
|
|
18498
|
+
init_dist2();
|
|
17479
18499
|
init_aft_bridge();
|
|
17480
18500
|
init_harness_select();
|
|
17481
18501
|
init_paths2();
|
|
@@ -17509,7 +18529,7 @@ __export(exports_doctor_filters, {
|
|
|
17509
18529
|
printDoctorFiltersHelp: () => printDoctorFiltersHelp
|
|
17510
18530
|
});
|
|
17511
18531
|
import { existsSync as existsSync13 } from "node:fs";
|
|
17512
|
-
import { homedir as
|
|
18532
|
+
import { homedir as homedir16 } from "node:os";
|
|
17513
18533
|
import { relative as relative3, resolve as resolve9 } from "node:path";
|
|
17514
18534
|
function printDoctorFiltersHelp() {
|
|
17515
18535
|
console.log("Usage: aft doctor filters [--show <name>] [trust|untrust]");
|
|
@@ -17727,7 +18747,7 @@ function truncate(value) {
|
|
|
17727
18747
|
return value.length <= 80 ? value : `${value.slice(0, 77)}…`;
|
|
17728
18748
|
}
|
|
17729
18749
|
function formatHome(path2) {
|
|
17730
|
-
const home =
|
|
18750
|
+
const home = homedir16();
|
|
17731
18751
|
return path2.startsWith(home) ? `~${path2.slice(home.length)}` : path2;
|
|
17732
18752
|
}
|
|
17733
18753
|
function formatProjectPath(path2, projectRoot) {
|
|
@@ -17751,7 +18771,7 @@ var init_doctor_filters = __esm(async () => {
|
|
|
17751
18771
|
|
|
17752
18772
|
// src/lib/binary-cache.ts
|
|
17753
18773
|
import { existsSync as existsSync14, readdirSync as readdirSync5, statSync as statSync8 } from "node:fs";
|
|
17754
|
-
import { join as
|
|
18774
|
+
import { join as join17 } from "node:path";
|
|
17755
18775
|
function getBinaryCacheInfo(activeVersion) {
|
|
17756
18776
|
const path2 = getAftBinaryCacheDir();
|
|
17757
18777
|
if (!existsSync14(path2)) {
|
|
@@ -17764,7 +18784,7 @@ function getBinaryCacheInfo(activeVersion) {
|
|
|
17764
18784
|
}
|
|
17765
18785
|
const versions = readdirSync5(path2).filter((entry) => {
|
|
17766
18786
|
try {
|
|
17767
|
-
return statSync8(
|
|
18787
|
+
return statSync8(join17(path2, entry)).isDirectory();
|
|
17768
18788
|
} catch {
|
|
17769
18789
|
return false;
|
|
17770
18790
|
}
|
|
@@ -17785,7 +18805,7 @@ var init_binary_cache = __esm(() => {
|
|
|
17785
18805
|
|
|
17786
18806
|
// src/lib/sanitize.ts
|
|
17787
18807
|
import { realpathSync as realpathSync3 } from "node:fs";
|
|
17788
|
-
import { homedir as
|
|
18808
|
+
import { homedir as homedir17, userInfo } from "node:os";
|
|
17789
18809
|
function escapeRegex(value) {
|
|
17790
18810
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
17791
18811
|
}
|
|
@@ -17816,7 +18836,7 @@ function redactSecrets(content) {
|
|
|
17816
18836
|
}
|
|
17817
18837
|
function sanitizeContent(content) {
|
|
17818
18838
|
const username = userInfo().username;
|
|
17819
|
-
const home =
|
|
18839
|
+
const home = homedir17();
|
|
17820
18840
|
let sanitized = redactSecrets(content);
|
|
17821
18841
|
const cwd = process.cwd();
|
|
17822
18842
|
for (const candidate of new Set([cwd, safeRealpath(cwd)])) {
|
|
@@ -17863,11 +18883,9 @@ var init_sanitize = __esm(() => {
|
|
|
17863
18883
|
|
|
17864
18884
|
// src/lib/bridge-tool-failures.ts
|
|
17865
18885
|
import { closeSync as closeSync5, existsSync as existsSync15, openSync as openSync5, readSync as readSync2, statSync as statSync9 } from "node:fs";
|
|
17866
|
-
import { tmpdir as tmpdir3 } from "node:os";
|
|
17867
|
-
import { join as join17 } from "node:path";
|
|
17868
18886
|
function resolveBridgePluginLogPath() {
|
|
17869
18887
|
const isTestEnv = process.env.BUN_TEST === "1" || false;
|
|
17870
|
-
return
|
|
18888
|
+
return resolveAftLogPath(isTestEnv ? "aft-plugin-test.log" : "aft-plugin.log");
|
|
17871
18889
|
}
|
|
17872
18890
|
function tailLogFileBytes(path2, maxBytes) {
|
|
17873
18891
|
if (!existsSync15(path2) || maxBytes <= 0)
|
|
@@ -17998,31 +19016,156 @@ function buildRecentAftToolFailuresSectionFromLog(logPath = resolveBridgePluginL
|
|
|
17998
19016
|
}
|
|
17999
19017
|
var BRIDGE_LOG_TAIL_BYTES, MAX_TOOL_FAILURE_CLASSES = 30, SESSION_TAG_PATTERN, STRUCTURED_CODE_PATTERN;
|
|
18000
19018
|
var init_bridge_tool_failures = __esm(() => {
|
|
19019
|
+
init_dist2();
|
|
18001
19020
|
init_sanitize();
|
|
18002
19021
|
BRIDGE_LOG_TAIL_BYTES = 2 * 1024 * 1024;
|
|
18003
19022
|
SESSION_TAG_PATTERN = /\[ses_[^\]\s]+\]|\[[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\]/g;
|
|
18004
19023
|
STRUCTURED_CODE_PATTERN = /"code"\s*:\s*"([^"]+)"/;
|
|
18005
19024
|
});
|
|
18006
19025
|
|
|
18007
|
-
// src/lib/
|
|
18008
|
-
import { existsSync as existsSync16, readdirSync as readdirSync6,
|
|
19026
|
+
// src/lib/legacy-storage.ts
|
|
19027
|
+
import { existsSync as existsSync16, readdirSync as readdirSync6, statSync as statSync10 } from "node:fs";
|
|
18009
19028
|
import { join as join18 } from "node:path";
|
|
19029
|
+
function summarizeLegacyPartitionDuplication(storageRoot) {
|
|
19030
|
+
if (!existsSync16(storageRoot)) {
|
|
19031
|
+
return { totalPartitions: 0, totalBytes: 0, byHarness: [] };
|
|
19032
|
+
}
|
|
19033
|
+
const byHarness = [];
|
|
19034
|
+
for (const harness of safeReadDir(storageRoot)) {
|
|
19035
|
+
const harnessPath = join18(storageRoot, harness);
|
|
19036
|
+
if (!isDirectory(harnessPath))
|
|
19037
|
+
continue;
|
|
19038
|
+
const partitions = new Map;
|
|
19039
|
+
collectCallgraphPartitions(join18(harnessPath, "callgraph"), partitions);
|
|
19040
|
+
collectInspectPartitions(join18(harnessPath, "inspect"), partitions);
|
|
19041
|
+
if (partitions.size === 0)
|
|
19042
|
+
continue;
|
|
19043
|
+
let bytes = 0;
|
|
19044
|
+
for (const size of partitions.values())
|
|
19045
|
+
bytes += size;
|
|
19046
|
+
byHarness.push({ harness, partitions: partitions.size, bytes });
|
|
19047
|
+
}
|
|
19048
|
+
byHarness.sort((left, right) => left.harness.localeCompare(right.harness));
|
|
19049
|
+
return {
|
|
19050
|
+
totalPartitions: byHarness.reduce((sum, item) => sum + item.partitions, 0),
|
|
19051
|
+
totalBytes: byHarness.reduce((sum, item) => sum + item.bytes, 0),
|
|
19052
|
+
byHarness
|
|
19053
|
+
};
|
|
19054
|
+
}
|
|
19055
|
+
function collectCallgraphPartitions(domainPath, partitions) {
|
|
19056
|
+
if (!isDirectory(domainPath))
|
|
19057
|
+
return;
|
|
19058
|
+
for (const name of safeReadDir(domainPath)) {
|
|
19059
|
+
const path2 = join18(domainPath, name);
|
|
19060
|
+
if (isDirectory(path2)) {
|
|
19061
|
+
if (!looksLikePartitionKey(name))
|
|
19062
|
+
continue;
|
|
19063
|
+
addPartitionBytes(partitions, `callgraph:${name}`, dirSize(path2));
|
|
19064
|
+
continue;
|
|
19065
|
+
}
|
|
19066
|
+
const key = callgraphPartitionKeyFromName(name);
|
|
19067
|
+
if (!key)
|
|
19068
|
+
continue;
|
|
19069
|
+
addPartitionBytes(partitions, `callgraph:${key}`, safeFileSize(path2));
|
|
19070
|
+
}
|
|
19071
|
+
}
|
|
19072
|
+
function collectInspectPartitions(domainPath, partitions) {
|
|
19073
|
+
if (!isDirectory(domainPath))
|
|
19074
|
+
return;
|
|
19075
|
+
for (const name of safeReadDir(domainPath)) {
|
|
19076
|
+
const path2 = join18(domainPath, name);
|
|
19077
|
+
if (isDirectory(path2)) {
|
|
19078
|
+
if (!looksLikePartitionKey(name))
|
|
19079
|
+
continue;
|
|
19080
|
+
addPartitionBytes(partitions, `inspect:${name}`, dirSize(path2));
|
|
19081
|
+
continue;
|
|
19082
|
+
}
|
|
19083
|
+
const key = inspectPartitionKeyFromName(name);
|
|
19084
|
+
if (!key)
|
|
19085
|
+
continue;
|
|
19086
|
+
addPartitionBytes(partitions, `inspect:${key}`, safeFileSize(path2));
|
|
19087
|
+
}
|
|
19088
|
+
}
|
|
19089
|
+
function addPartitionBytes(partitions, key, bytes) {
|
|
19090
|
+
partitions.set(key, (partitions.get(key) ?? 0) + bytes);
|
|
19091
|
+
}
|
|
19092
|
+
function callgraphPartitionKeyFromName(name) {
|
|
19093
|
+
if (name.includes(".tmp."))
|
|
19094
|
+
return null;
|
|
19095
|
+
if (name.endsWith(".current")) {
|
|
19096
|
+
const key2 = name.slice(0, -".current".length);
|
|
19097
|
+
return looksLikePartitionKey(key2) ? key2 : null;
|
|
19098
|
+
}
|
|
19099
|
+
const base = sqliteishBaseName(name);
|
|
19100
|
+
if (!base)
|
|
19101
|
+
return null;
|
|
19102
|
+
const split = base.indexOf(".g");
|
|
19103
|
+
const key = split === -1 ? base : base.slice(0, split);
|
|
19104
|
+
return looksLikePartitionKey(key) ? key : null;
|
|
19105
|
+
}
|
|
19106
|
+
function inspectPartitionKeyFromName(name) {
|
|
19107
|
+
if (name.includes(".tmp."))
|
|
19108
|
+
return null;
|
|
19109
|
+
const base = sqliteishBaseName(name);
|
|
19110
|
+
return base && looksLikePartitionKey(base) ? base : null;
|
|
19111
|
+
}
|
|
19112
|
+
function sqliteishBaseName(name) {
|
|
19113
|
+
for (const suffix of SQLITE_SUFFIXES) {
|
|
19114
|
+
if (name.endsWith(suffix)) {
|
|
19115
|
+
return name.slice(0, -suffix.length);
|
|
19116
|
+
}
|
|
19117
|
+
}
|
|
19118
|
+
return null;
|
|
19119
|
+
}
|
|
19120
|
+
function looksLikePartitionKey(value) {
|
|
19121
|
+
return /^[0-9a-fA-F]{16}$/.test(value);
|
|
19122
|
+
}
|
|
19123
|
+
function safeReadDir(path2) {
|
|
19124
|
+
try {
|
|
19125
|
+
return readdirSync6(path2).sort((left, right) => left.localeCompare(right));
|
|
19126
|
+
} catch {
|
|
19127
|
+
return [];
|
|
19128
|
+
}
|
|
19129
|
+
}
|
|
19130
|
+
function isDirectory(path2) {
|
|
19131
|
+
try {
|
|
19132
|
+
return statSync10(path2).isDirectory();
|
|
19133
|
+
} catch {
|
|
19134
|
+
return false;
|
|
19135
|
+
}
|
|
19136
|
+
}
|
|
19137
|
+
function safeFileSize(path2) {
|
|
19138
|
+
try {
|
|
19139
|
+
return statSync10(path2).isFile() ? statSync10(path2).size : 0;
|
|
19140
|
+
} catch {
|
|
19141
|
+
return 0;
|
|
19142
|
+
}
|
|
19143
|
+
}
|
|
19144
|
+
var SQLITE_SUFFIXES;
|
|
19145
|
+
var init_legacy_storage = __esm(() => {
|
|
19146
|
+
init_fs_util();
|
|
19147
|
+
SQLITE_SUFFIXES = [".sqlite-wal", ".sqlite-shm", ".sqlite-journal", ".sqlite"];
|
|
19148
|
+
});
|
|
19149
|
+
|
|
19150
|
+
// src/lib/lsp-cache.ts
|
|
19151
|
+
import { existsSync as existsSync17, readdirSync as readdirSync7, rmSync as rmSync5, statSync as statSync11 } from "node:fs";
|
|
19152
|
+
import { join as join19 } from "node:path";
|
|
18010
19153
|
function inspectDir(path2) {
|
|
18011
|
-
if (!
|
|
19154
|
+
if (!existsSync17(path2)) {
|
|
18012
19155
|
return { entries: [], totalSize: 0 };
|
|
18013
19156
|
}
|
|
18014
19157
|
const entries = [];
|
|
18015
19158
|
let totalSize = 0;
|
|
18016
19159
|
let names;
|
|
18017
19160
|
try {
|
|
18018
|
-
names =
|
|
19161
|
+
names = readdirSync7(path2);
|
|
18019
19162
|
} catch {
|
|
18020
19163
|
return { entries: [], totalSize: 0 };
|
|
18021
19164
|
}
|
|
18022
19165
|
for (const name of names) {
|
|
18023
|
-
const full =
|
|
19166
|
+
const full = join19(path2, name);
|
|
18024
19167
|
try {
|
|
18025
|
-
if (!
|
|
19168
|
+
if (!statSync11(full).isDirectory())
|
|
18026
19169
|
continue;
|
|
18027
19170
|
const size = dirSize(full);
|
|
18028
19171
|
entries.push({
|
|
@@ -18078,8 +19221,8 @@ var init_lsp_cache = __esm(() => {
|
|
|
18078
19221
|
});
|
|
18079
19222
|
|
|
18080
19223
|
// src/lib/onnx.ts
|
|
18081
|
-
import { existsSync as
|
|
18082
|
-
import { basename as basename3, isAbsolute as isAbsolute6, join as
|
|
19224
|
+
import { existsSync as existsSync18, readdirSync as readdirSync8, readlinkSync as readlinkSync2, realpathSync as realpathSync4 } from "node:fs";
|
|
19225
|
+
import { basename as basename3, isAbsolute as isAbsolute6, join as join20, resolve as resolve10, win32 as win322 } from "node:path";
|
|
18083
19226
|
function getOnnxLibraryName() {
|
|
18084
19227
|
if (process.platform === "darwin")
|
|
18085
19228
|
return "libonnxruntime.dylib";
|
|
@@ -18119,9 +19262,20 @@ function pathEntriesForPlatform2() {
|
|
|
18119
19262
|
return isAbsolute6(entry) || win322.isAbsolute(entry);
|
|
18120
19263
|
});
|
|
18121
19264
|
}
|
|
19265
|
+
function isWindowsSystem32Directory2(dir) {
|
|
19266
|
+
if (process.platform !== "win32")
|
|
19267
|
+
return false;
|
|
19268
|
+
const normalizedDir = win322.resolve(dir).replace(/[\\/]+$/, "").toLowerCase();
|
|
19269
|
+
const windowsRoots = [process.env.SystemRoot, process.env.windir, "C:\\Windows"];
|
|
19270
|
+
return windowsRoots.some((root) => {
|
|
19271
|
+
if (!root)
|
|
19272
|
+
return false;
|
|
19273
|
+
return normalizedDir === win322.resolve(root, "System32").replace(/[\\/]+$/, "").toLowerCase();
|
|
19274
|
+
});
|
|
19275
|
+
}
|
|
18122
19276
|
function directoryContainsLibrary2(dir, libName) {
|
|
18123
19277
|
try {
|
|
18124
|
-
const entries =
|
|
19278
|
+
const entries = readdirSync8(dir);
|
|
18125
19279
|
if (process.platform === "win32") {
|
|
18126
19280
|
const expected = libName.toLowerCase();
|
|
18127
19281
|
return entries.some((entry) => entry.toLowerCase() === expected);
|
|
@@ -18131,6 +19285,24 @@ function directoryContainsLibrary2(dir, libName) {
|
|
|
18131
19285
|
return false;
|
|
18132
19286
|
}
|
|
18133
19287
|
}
|
|
19288
|
+
function findIgnoredWindowsSystemOnnxRuntime() {
|
|
19289
|
+
if (process.platform !== "win32")
|
|
19290
|
+
return null;
|
|
19291
|
+
const windowsRoots = [process.env.SystemRoot, process.env.windir, "C:\\Windows"];
|
|
19292
|
+
const seen = new Set;
|
|
19293
|
+
for (const root of windowsRoots) {
|
|
19294
|
+
if (!root)
|
|
19295
|
+
continue;
|
|
19296
|
+
const systemDir = join20(root, "System32");
|
|
19297
|
+
const key = win322.resolve(systemDir).toLowerCase();
|
|
19298
|
+
if (seen.has(key))
|
|
19299
|
+
continue;
|
|
19300
|
+
seen.add(key);
|
|
19301
|
+
if (directoryContainsLibrary2(systemDir, getOnnxLibraryName()))
|
|
19302
|
+
return systemDir;
|
|
19303
|
+
}
|
|
19304
|
+
return null;
|
|
19305
|
+
}
|
|
18134
19306
|
function findSystemOnnxRuntime2() {
|
|
18135
19307
|
const libName = getOnnxLibraryName();
|
|
18136
19308
|
const searchPaths = [];
|
|
@@ -18142,21 +19314,21 @@ function findSystemOnnxRuntime2() {
|
|
|
18142
19314
|
searchPaths.push(...pathEntriesForPlatform2());
|
|
18143
19315
|
const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
|
|
18144
19316
|
const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
|
|
18145
|
-
searchPaths.push(
|
|
19317
|
+
searchPaths.push(join20(programFiles, "onnxruntime", "lib"), join20(programFiles, "Microsoft ONNX Runtime", "lib"), join20(programFiles, "Microsoft Machine Learning", "lib"), join20(programFilesX86, "onnxruntime", "lib"), ...(() => {
|
|
18146
19318
|
const nugetPaths = [];
|
|
18147
19319
|
const userProfile = process.env.USERPROFILE ?? "";
|
|
18148
19320
|
if (!userProfile)
|
|
18149
19321
|
return nugetPaths;
|
|
18150
|
-
const nugetPackageDir =
|
|
18151
|
-
if (!
|
|
19322
|
+
const nugetPackageDir = join20(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
|
|
19323
|
+
if (!existsSync18(nugetPackageDir))
|
|
18152
19324
|
return nugetPaths;
|
|
18153
19325
|
try {
|
|
18154
|
-
for (const entry of
|
|
19326
|
+
for (const entry of readdirSync8(nugetPackageDir, { withFileTypes: true })) {
|
|
18155
19327
|
if (!entry.isDirectory())
|
|
18156
19328
|
continue;
|
|
18157
19329
|
if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
|
|
18158
19330
|
continue;
|
|
18159
|
-
nugetPaths.push(
|
|
19331
|
+
nugetPaths.push(join20(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join20(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
|
|
18160
19332
|
}
|
|
18161
19333
|
} catch {}
|
|
18162
19334
|
return nugetPaths;
|
|
@@ -18176,6 +19348,8 @@ function findSystemOnnxRuntime2() {
|
|
|
18176
19348
|
continue;
|
|
18177
19349
|
const version = detectOrtVersion(dir);
|
|
18178
19350
|
if (!version) {
|
|
19351
|
+
if (isWindowsSystem32Directory2(dir))
|
|
19352
|
+
continue;
|
|
18179
19353
|
unknownVersionPaths.push(dir);
|
|
18180
19354
|
continue;
|
|
18181
19355
|
}
|
|
@@ -18186,12 +19360,12 @@ function findSystemOnnxRuntime2() {
|
|
|
18186
19360
|
return unknownVersionPaths[0] ?? null;
|
|
18187
19361
|
}
|
|
18188
19362
|
function findCachedOnnxRuntime(storageDir) {
|
|
18189
|
-
const ortDir =
|
|
19363
|
+
const ortDir = join20(storageDir, "onnxruntime", ONNX_RUNTIME_VERSION);
|
|
18190
19364
|
const libName = getOnnxLibraryName();
|
|
18191
|
-
if (
|
|
19365
|
+
if (existsSync18(join20(ortDir, libName)))
|
|
18192
19366
|
return ortDir;
|
|
18193
|
-
const libSubdir =
|
|
18194
|
-
if (
|
|
19367
|
+
const libSubdir = join20(ortDir, "lib");
|
|
19368
|
+
if (existsSync18(join20(libSubdir, libName)))
|
|
18195
19369
|
return libSubdir;
|
|
18196
19370
|
return null;
|
|
18197
19371
|
}
|
|
@@ -18212,11 +19386,11 @@ function parseOrtVersionFromDirectoryPath(value) {
|
|
|
18212
19386
|
return null;
|
|
18213
19387
|
}
|
|
18214
19388
|
function detectOrtVersion(libDir) {
|
|
18215
|
-
if (!
|
|
19389
|
+
if (!existsSync18(libDir))
|
|
18216
19390
|
return null;
|
|
18217
19391
|
const libName = getOnnxLibraryName();
|
|
18218
19392
|
try {
|
|
18219
|
-
const entries =
|
|
19393
|
+
const entries = readdirSync8(libDir);
|
|
18220
19394
|
const barePrefix = libName.replace(/\.(so|dylib|dll)$/, "");
|
|
18221
19395
|
const expectedPrefix = process.platform === "win32" ? barePrefix.toLowerCase() : barePrefix;
|
|
18222
19396
|
for (const entry of entries) {
|
|
@@ -18227,8 +19401,8 @@ function detectOrtVersion(libDir) {
|
|
|
18227
19401
|
if (version)
|
|
18228
19402
|
return version;
|
|
18229
19403
|
}
|
|
18230
|
-
const base =
|
|
18231
|
-
if (
|
|
19404
|
+
const base = join20(libDir, libName);
|
|
19405
|
+
if (existsSync18(base)) {
|
|
18232
19406
|
try {
|
|
18233
19407
|
const real = realpathSync4(base);
|
|
18234
19408
|
const version = parseOrtVersionFromPath(real) ?? parseOrtVersionFromDirectoryPath(real);
|
|
@@ -18263,10 +19437,10 @@ import {
|
|
|
18263
19437
|
accessSync,
|
|
18264
19438
|
closeSync as closeSync6,
|
|
18265
19439
|
constants,
|
|
18266
|
-
existsSync as
|
|
19440
|
+
existsSync as existsSync19,
|
|
18267
19441
|
openSync as openSync6,
|
|
18268
19442
|
readSync as readSync3,
|
|
18269
|
-
statSync as
|
|
19443
|
+
statSync as statSync12
|
|
18270
19444
|
} from "node:fs";
|
|
18271
19445
|
async function collectDiagnostics(adapters) {
|
|
18272
19446
|
const cliVersion = getSelfVersion();
|
|
@@ -18301,7 +19475,7 @@ async function diagnoseHarness(adapter) {
|
|
|
18301
19475
|
const logPath = adapter.getLogFile();
|
|
18302
19476
|
const pluginCache = adapter.getPluginCacheInfo();
|
|
18303
19477
|
const storageAccessible = (() => {
|
|
18304
|
-
if (!
|
|
19478
|
+
if (!existsSync19(storage))
|
|
18305
19479
|
return false;
|
|
18306
19480
|
try {
|
|
18307
19481
|
accessSync(storage, constants.R_OK | constants.W_OK);
|
|
@@ -18311,8 +19485,10 @@ async function diagnoseHarness(adapter) {
|
|
|
18311
19485
|
}
|
|
18312
19486
|
})();
|
|
18313
19487
|
const describeStorage = "describeStorageSubtrees" in adapter && typeof adapter.describeStorageSubtrees === "function" ? adapter.describeStorageSubtrees() : {};
|
|
19488
|
+
const legacyDuplication = summarizeLegacyPartitionDuplication(storage);
|
|
18314
19489
|
const semanticEnabled = aftEnabled && (aftConfigRead.value?.semantic_search === true || aftConfigRead.value?.experimental_semantic_search === true);
|
|
18315
19490
|
const systemOrtDir = findSystemOnnxRuntime2();
|
|
19491
|
+
const ignoredSystemOrtDir = systemOrtDir ? null : findIgnoredWindowsSystemOnnxRuntime();
|
|
18316
19492
|
const cachedOrtDir = findCachedOnnxRuntime(storage);
|
|
18317
19493
|
const systemVersion = systemOrtDir ? detectOrtVersion(systemOrtDir) : null;
|
|
18318
19494
|
const cachedVersion = cachedOrtDir ? detectOrtVersion(cachedOrtDir) : null;
|
|
@@ -18324,7 +19500,7 @@ async function diagnoseHarness(adapter) {
|
|
|
18324
19500
|
pluginRegistered: adapter.hasPluginEntry(),
|
|
18325
19501
|
configPaths,
|
|
18326
19502
|
aftConfig: {
|
|
18327
|
-
exists:
|
|
19503
|
+
exists: existsSync19(configPaths.aftConfig),
|
|
18328
19504
|
...aftConfigRead.error ? { parseError: aftConfigRead.error } : {},
|
|
18329
19505
|
enabled: aftEnabled,
|
|
18330
19506
|
...aftEnabledSource ? { enabledSource: aftEnabledSource } : {},
|
|
@@ -18333,15 +19509,18 @@ async function diagnoseHarness(adapter) {
|
|
|
18333
19509
|
pluginCache,
|
|
18334
19510
|
storageDir: {
|
|
18335
19511
|
path: storage,
|
|
18336
|
-
exists:
|
|
19512
|
+
exists: existsSync19(storage),
|
|
18337
19513
|
accessible: storageAccessible,
|
|
18338
|
-
sizesByKey: describeStorage
|
|
19514
|
+
sizesByKey: describeStorage,
|
|
19515
|
+
...legacyDuplication.totalPartitions > 0 ? { legacyDuplication } : {}
|
|
18339
19516
|
},
|
|
18340
19517
|
onnxRuntime: {
|
|
18341
19518
|
required: semanticEnabled,
|
|
18342
19519
|
systemPath: systemOrtDir,
|
|
18343
19520
|
systemVersion,
|
|
18344
19521
|
systemCompatible: systemVersion ? isOrtVersionCompatible(systemVersion) : null,
|
|
19522
|
+
ignoredSystemPath: ignoredSystemOrtDir,
|
|
19523
|
+
ignoredSystemReason: ignoredSystemOrtDir ? "version unreadable (Windows system copy) — ignored" : null,
|
|
18345
19524
|
cachedPath: cachedOrtDir,
|
|
18346
19525
|
cachedVersion,
|
|
18347
19526
|
cachedCompatible: cachedVersion ? isOrtVersionCompatible(cachedVersion) : null,
|
|
@@ -18351,8 +19530,8 @@ async function diagnoseHarness(adapter) {
|
|
|
18351
19530
|
},
|
|
18352
19531
|
logFile: {
|
|
18353
19532
|
path: logPath,
|
|
18354
|
-
exists:
|
|
18355
|
-
sizeKb:
|
|
19533
|
+
exists: existsSync19(logPath),
|
|
19534
|
+
sizeKb: existsSync19(logPath) ? Math.round(statSync12(logPath).size / 1024) : 0
|
|
18356
19535
|
}
|
|
18357
19536
|
};
|
|
18358
19537
|
}
|
|
@@ -18507,7 +19686,7 @@ function collectDiagnosticIssues(report) {
|
|
|
18507
19686
|
code: "onnx_missing",
|
|
18508
19687
|
severity: "medium",
|
|
18509
19688
|
scope: h2.displayName,
|
|
18510
|
-
message: "ONNX Runtime is required for semantic search but was not detected.",
|
|
19689
|
+
message: h2.onnxRuntime.ignoredSystemPath ? `ONNX Runtime at ${h2.onnxRuntime.ignoredSystemPath} has a ${h2.onnxRuntime.ignoredSystemReason}; no compatible runtime was detected.` : "ONNX Runtime is required for semantic search but was not detected.",
|
|
18511
19690
|
remediation: `Run \`aft doctor --fix\` or install ONNX Runtime manually (${h2.onnxRuntime.installHint}).`
|
|
18512
19691
|
});
|
|
18513
19692
|
}
|
|
@@ -18548,14 +19727,14 @@ function formatDiagnosticIssuesSection(report) {
|
|
|
18548
19727
|
return lines;
|
|
18549
19728
|
}
|
|
18550
19729
|
function tailLogFile(path2, lines) {
|
|
18551
|
-
if (!
|
|
19730
|
+
if (!existsSync19(path2))
|
|
18552
19731
|
return "";
|
|
18553
19732
|
if (lines <= 0)
|
|
18554
19733
|
return "";
|
|
18555
19734
|
const chunkSize = 64 * 1024;
|
|
18556
19735
|
let fd = null;
|
|
18557
19736
|
try {
|
|
18558
|
-
const size =
|
|
19737
|
+
const size = statSync12(path2).size;
|
|
18559
19738
|
fd = openSync6(path2, "r");
|
|
18560
19739
|
const chunks = [];
|
|
18561
19740
|
let position = size;
|
|
@@ -18585,9 +19764,10 @@ function tailLogFile(path2, lines) {
|
|
|
18585
19764
|
}
|
|
18586
19765
|
}
|
|
18587
19766
|
var init_diagnostics = __esm(async () => {
|
|
18588
|
-
|
|
19767
|
+
init_dist2();
|
|
18589
19768
|
init_binary_cache();
|
|
18590
19769
|
init_jsonc();
|
|
19770
|
+
init_legacy_storage();
|
|
18591
19771
|
init_lsp_cache();
|
|
18592
19772
|
init_onnx();
|
|
18593
19773
|
init_sanitize();
|
|
@@ -18735,34 +19915,42 @@ var init_issue_body = __esm(() => {
|
|
|
18735
19915
|
});
|
|
18736
19916
|
|
|
18737
19917
|
// src/lib/onnx-fix.ts
|
|
18738
|
-
import { existsSync as
|
|
18739
|
-
import { join as
|
|
19918
|
+
import { existsSync as existsSync20, rmSync as rmSync6 } from "node:fs";
|
|
19919
|
+
import { join as join21 } from "node:path";
|
|
18740
19920
|
function findOnnxFixCandidates(report) {
|
|
18741
19921
|
const candidates = [];
|
|
18742
19922
|
for (const harness of report.harnesses) {
|
|
18743
19923
|
if (!harness.onnxRuntime.required)
|
|
18744
19924
|
continue;
|
|
18745
|
-
|
|
18746
|
-
continue;
|
|
18747
|
-
const storageOnnxDir = join20(harness.storageDir.path, "onnxruntime");
|
|
19925
|
+
const storageOnnxDir = join21(harness.storageDir.path, "onnxruntime");
|
|
18748
19926
|
const systemTooOld = harness.onnxRuntime.systemPath !== null && harness.onnxRuntime.systemCompatible === false;
|
|
18749
19927
|
const cachedTooOld = harness.onnxRuntime.cachedPath !== null && harness.onnxRuntime.cachedCompatible === false;
|
|
18750
19928
|
const hasCompatibleCached = harness.onnxRuntime.cachedCompatible === true;
|
|
18751
19929
|
if (cachedTooOld) {
|
|
18752
19930
|
candidates.push({
|
|
18753
19931
|
harness,
|
|
18754
|
-
reason: `cached ONNX Runtime at ${harness.onnxRuntime.cachedPath} is v${harness.onnxRuntime.cachedVersion}, but AFT requires ${harness.onnxRuntime.requirement}. Clearing
|
|
19932
|
+
reason: `cached ONNX Runtime at ${harness.onnxRuntime.cachedPath} is v${harness.onnxRuntime.cachedVersion}, but AFT requires ${harness.onnxRuntime.requirement}. Clearing it allows an immediate managed download.`,
|
|
18755
19933
|
storageOnnxDir,
|
|
18756
|
-
storageOnnxBytes:
|
|
19934
|
+
storageOnnxBytes: existsSync20(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
|
|
18757
19935
|
});
|
|
18758
19936
|
continue;
|
|
18759
19937
|
}
|
|
18760
19938
|
if (systemTooOld && !hasCompatibleCached) {
|
|
18761
19939
|
candidates.push({
|
|
18762
19940
|
harness,
|
|
18763
|
-
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
|
|
19941
|
+
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.`,
|
|
19942
|
+
storageOnnxDir,
|
|
19943
|
+
storageOnnxBytes: existsSync20(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
|
|
19944
|
+
});
|
|
19945
|
+
continue;
|
|
19946
|
+
}
|
|
19947
|
+
if (!harness.onnxRuntime.systemPath && !harness.onnxRuntime.cachedPath) {
|
|
19948
|
+
const ignoredCopy = harness.onnxRuntime.ignoredSystemPath ? ` The Windows system copy at ${harness.onnxRuntime.ignoredSystemPath} was ignored because its version is unreadable.` : "";
|
|
19949
|
+
candidates.push({
|
|
19950
|
+
harness,
|
|
19951
|
+
reason: `no compatible ONNX Runtime is installed.${ignoredCopy} AFT will download v1.24 into managed storage.`,
|
|
18764
19952
|
storageOnnxDir,
|
|
18765
|
-
storageOnnxBytes:
|
|
19953
|
+
storageOnnxBytes: existsSync20(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
|
|
18766
19954
|
});
|
|
18767
19955
|
}
|
|
18768
19956
|
}
|
|
@@ -18770,58 +19958,74 @@ function findOnnxFixCandidates(report) {
|
|
|
18770
19958
|
}
|
|
18771
19959
|
async function runOnnxFix(adapters, report, options = {}) {
|
|
18772
19960
|
const candidates = findOnnxFixCandidates(report);
|
|
18773
|
-
if (candidates.length === 0)
|
|
19961
|
+
if (candidates.length === 0)
|
|
18774
19962
|
return null;
|
|
18775
|
-
}
|
|
18776
|
-
|
|
18777
|
-
|
|
18778
|
-
|
|
18779
|
-
|
|
18780
|
-
log2.info(` will delete: ${c3.storageOnnxDir} (${formatBytes(c3.storageOnnxBytes)})`);
|
|
19963
|
+
log2.warn(`Found ${candidates.length} ONNX Runtime issue(s) that --fix can repair with an AFT-managed runtime:`);
|
|
19964
|
+
for (const candidate of candidates) {
|
|
19965
|
+
log2.info(` • ${candidate.harness.displayName}: ${candidate.reason}`);
|
|
19966
|
+
if (candidate.storageOnnxBytes > 0) {
|
|
19967
|
+
log2.info(` will delete: ${candidate.storageOnnxDir} (${formatBytes(candidate.storageOnnxBytes)})`);
|
|
18781
19968
|
} else {
|
|
18782
|
-
log2.info(
|
|
19969
|
+
log2.info(" no AFT-managed ONNX cache to delete");
|
|
18783
19970
|
}
|
|
18784
19971
|
}
|
|
18785
|
-
note("This NEVER touches system paths like /usr/lib. It only
|
|
19972
|
+
note("This NEVER touches system paths like /usr/lib or C:\\Windows\\System32. It only replaces AFT's own ONNX cache, then downloads the compatible managed runtime.", "Safe operation");
|
|
18786
19973
|
const confirmFn = options.confirmFn ?? confirm2;
|
|
18787
19974
|
const proceed = options.yes ? true : await confirmFn("Proceed with the fixes above?", true);
|
|
18788
19975
|
if (!proceed) {
|
|
18789
19976
|
log2.info("Skipped — no changes made.");
|
|
18790
19977
|
return null;
|
|
18791
19978
|
}
|
|
18792
|
-
const result = { cleared: 0, bytesReclaimed: 0, errors: [] };
|
|
19979
|
+
const result = { cleared: 0, installed: 0, bytesReclaimed: 0, errors: [] };
|
|
18793
19980
|
const rmFn = options.rmFn ?? rmSync6;
|
|
18794
|
-
|
|
18795
|
-
|
|
18796
|
-
|
|
18797
|
-
|
|
19981
|
+
const ensureFn = options.ensureFn ?? ensureOnnxRuntime;
|
|
19982
|
+
for (const candidate of candidates) {
|
|
19983
|
+
if (existsSync20(candidate.storageOnnxDir)) {
|
|
19984
|
+
try {
|
|
19985
|
+
rmFn(candidate.storageOnnxDir, { recursive: true, force: true });
|
|
19986
|
+
result.cleared += 1;
|
|
19987
|
+
result.bytesReclaimed += candidate.storageOnnxBytes;
|
|
19988
|
+
log2.success(`${candidate.harness.displayName}: cleared ${candidate.storageOnnxDir} (reclaimed ${formatBytes(candidate.storageOnnxBytes)})`);
|
|
19989
|
+
} catch (err) {
|
|
19990
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
19991
|
+
log2.error(`${candidate.harness.displayName}: failed to clear ${candidate.storageOnnxDir}: ${message}`);
|
|
19992
|
+
result.errors.push({ path: candidate.storageOnnxDir, error: message });
|
|
19993
|
+
continue;
|
|
19994
|
+
}
|
|
18798
19995
|
}
|
|
18799
19996
|
try {
|
|
18800
|
-
|
|
18801
|
-
|
|
18802
|
-
|
|
18803
|
-
|
|
19997
|
+
log2.info(`${candidate.harness.displayName}: downloading managed ONNX Runtime…`);
|
|
19998
|
+
const installedPath = await ensureFn(candidate.harness.storageDir.path);
|
|
19999
|
+
if (!installedPath) {
|
|
20000
|
+
const message = "managed ONNX Runtime download was unavailable";
|
|
20001
|
+
log2.error(`${candidate.harness.displayName}: ${message}`);
|
|
20002
|
+
result.errors.push({ path: candidate.storageOnnxDir, error: message });
|
|
20003
|
+
continue;
|
|
20004
|
+
}
|
|
20005
|
+
result.installed += 1;
|
|
20006
|
+
log2.success(`${candidate.harness.displayName}: ONNX Runtime installed at ${installedPath}`);
|
|
18804
20007
|
} catch (err) {
|
|
18805
|
-
const message = err.message
|
|
18806
|
-
log2.error(`${
|
|
18807
|
-
result.errors.push({ path:
|
|
20008
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
20009
|
+
log2.error(`${candidate.harness.displayName}: ONNX Runtime download failed: ${message}`);
|
|
20010
|
+
result.errors.push({ path: candidate.storageOnnxDir, error: message });
|
|
18808
20011
|
}
|
|
18809
20012
|
}
|
|
18810
|
-
if (result.
|
|
18811
|
-
note("Restart your AFT-using harness (OpenCode / Pi)
|
|
20013
|
+
if (result.installed > 0) {
|
|
20014
|
+
note("Restart your AFT-using harness (OpenCode / Pi) so semantic indexing uses the newly installed managed runtime.", "Next step");
|
|
18812
20015
|
}
|
|
18813
20016
|
return result;
|
|
18814
20017
|
}
|
|
18815
20018
|
var init_onnx_fix = __esm(() => {
|
|
20019
|
+
init_dist2();
|
|
18816
20020
|
init_fs_util();
|
|
18817
20021
|
init_prompts();
|
|
18818
20022
|
});
|
|
18819
20023
|
|
|
18820
20024
|
// src/lib/sessions.ts
|
|
18821
|
-
import { existsSync as
|
|
18822
|
-
import { createRequire as
|
|
18823
|
-
import { homedir as
|
|
18824
|
-
import { basename as basename4, join as
|
|
20025
|
+
import { existsSync as existsSync21, readdirSync as readdirSync9, readFileSync as readFileSync10, statSync as statSync13 } from "node:fs";
|
|
20026
|
+
import { createRequire as createRequire5 } from "node:module";
|
|
20027
|
+
import { homedir as homedir18 } from "node:os";
|
|
20028
|
+
import { basename as basename4, join as join22 } from "node:path";
|
|
18825
20029
|
function listRecentSessions(adapter) {
|
|
18826
20030
|
try {
|
|
18827
20031
|
if (adapter.kind === "opencode")
|
|
@@ -18850,12 +20054,12 @@ function mapOpenCodeSessionRows(rows) {
|
|
|
18850
20054
|
}).filter((session) => session !== null).sort((a3, b2) => b2.lastActivity - a3.lastActivity).slice(0, MAX_RECENT_SESSIONS);
|
|
18851
20055
|
}
|
|
18852
20056
|
function listRecentOpenCodeSessions() {
|
|
18853
|
-
const dbPath =
|
|
18854
|
-
if (!
|
|
20057
|
+
const dbPath = join22(getXdgDataHome(), "opencode", "opencode.db");
|
|
20058
|
+
if (!existsSync21(dbPath))
|
|
18855
20059
|
return [];
|
|
18856
20060
|
let db = null;
|
|
18857
20061
|
try {
|
|
18858
|
-
const require2 =
|
|
20062
|
+
const require2 = createRequire5(import.meta.url);
|
|
18859
20063
|
const sqlite = require2("node:sqlite");
|
|
18860
20064
|
db = new sqlite.DatabaseSync(dbPath, { readOnly: true });
|
|
18861
20065
|
const rows = db.prepare("SELECT id, title, time_updated FROM session ORDER BY time_updated DESC LIMIT 5").all();
|
|
@@ -18870,22 +20074,22 @@ function listRecentOpenCodeSessions() {
|
|
|
18870
20074
|
}
|
|
18871
20075
|
function getXdgDataHome() {
|
|
18872
20076
|
const xdgDataHome = process.env.XDG_DATA_HOME;
|
|
18873
|
-
return xdgDataHome && xdgDataHome.length > 0 ? xdgDataHome :
|
|
20077
|
+
return xdgDataHome && xdgDataHome.length > 0 ? xdgDataHome : join22(homedir18(), ".local", "share");
|
|
18874
20078
|
}
|
|
18875
20079
|
function listRecentPiSessions() {
|
|
18876
|
-
return listPiSessionsFromDir(
|
|
20080
|
+
return listPiSessionsFromDir(join22(getHomeDir(), ".pi", "agent", "sessions"));
|
|
18877
20081
|
}
|
|
18878
20082
|
function getHomeDir() {
|
|
18879
20083
|
const envHome = process.platform === "win32" ? process.env.USERPROFILE : process.env.HOME;
|
|
18880
|
-
return envHome && envHome.length > 0 ? envHome :
|
|
20084
|
+
return envHome && envHome.length > 0 ? envHome : homedir18();
|
|
18881
20085
|
}
|
|
18882
20086
|
function listPiSessionsFromDir(sessionsDir) {
|
|
18883
20087
|
try {
|
|
18884
|
-
if (!
|
|
20088
|
+
if (!existsSync21(sessionsDir))
|
|
18885
20089
|
return [];
|
|
18886
20090
|
const files = collectJsonlFiles(sessionsDir).map((filePath) => {
|
|
18887
20091
|
try {
|
|
18888
|
-
const stats =
|
|
20092
|
+
const stats = statSync13(filePath);
|
|
18889
20093
|
return { filePath, mtimeMs: stats.mtimeMs };
|
|
18890
20094
|
} catch {
|
|
18891
20095
|
return null;
|
|
@@ -18914,12 +20118,12 @@ function collectJsonlFiles(root) {
|
|
|
18914
20118
|
continue;
|
|
18915
20119
|
let entries;
|
|
18916
20120
|
try {
|
|
18917
|
-
entries =
|
|
20121
|
+
entries = readdirSync9(dir, { withFileTypes: true });
|
|
18918
20122
|
} catch {
|
|
18919
20123
|
continue;
|
|
18920
20124
|
}
|
|
18921
20125
|
for (const entry of entries) {
|
|
18922
|
-
const path2 =
|
|
20126
|
+
const path2 = join22(dir, entry.name);
|
|
18923
20127
|
if (entry.isDirectory()) {
|
|
18924
20128
|
stack.push(path2);
|
|
18925
20129
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
@@ -19019,17 +20223,17 @@ __export(exports_doctor, {
|
|
|
19019
20223
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
19020
20224
|
import {
|
|
19021
20225
|
chmodSync as chmodSync4,
|
|
19022
|
-
existsSync as
|
|
20226
|
+
existsSync as existsSync22,
|
|
19023
20227
|
mkdirSync as mkdirSync7,
|
|
19024
20228
|
mkdtempSync,
|
|
19025
20229
|
readFileSync as readFileSync11,
|
|
19026
20230
|
realpathSync as realpathSync5,
|
|
19027
20231
|
rmSync as rmSync7,
|
|
19028
|
-
statSync as
|
|
20232
|
+
statSync as statSync14,
|
|
19029
20233
|
writeFileSync as writeFileSync5
|
|
19030
20234
|
} from "node:fs";
|
|
19031
|
-
import { tmpdir as
|
|
19032
|
-
import { join as
|
|
20235
|
+
import { tmpdir as tmpdir2 } from "node:os";
|
|
20236
|
+
import { join as join23 } from "node:path";
|
|
19033
20237
|
async function runDoctor(options) {
|
|
19034
20238
|
if (options.issue) {
|
|
19035
20239
|
return runIssueFlow(options.argv);
|
|
@@ -19098,6 +20302,8 @@ async function runDoctor(options) {
|
|
|
19098
20302
|
}
|
|
19099
20303
|
if (h2.onnxRuntime.systemPath) {
|
|
19100
20304
|
parts.push(`system: ${h2.onnxRuntime.systemVersion ?? "unknown"}${h2.onnxRuntime.systemCompatible === false ? " (incompatible)" : ""}`);
|
|
20305
|
+
} else if (h2.onnxRuntime.ignoredSystemPath) {
|
|
20306
|
+
parts.push(`system: ${h2.onnxRuntime.ignoredSystemReason} at ${h2.onnxRuntime.ignoredSystemPath}`);
|
|
19101
20307
|
}
|
|
19102
20308
|
if (!h2.onnxRuntime.cachedPath && !h2.onnxRuntime.systemPath) {
|
|
19103
20309
|
parts.push(`not installed — ${h2.onnxRuntime.installHint}`);
|
|
@@ -19194,7 +20400,7 @@ function clearOldBinaries() {
|
|
|
19194
20400
|
errors: [],
|
|
19195
20401
|
keptVersion: keepTag
|
|
19196
20402
|
};
|
|
19197
|
-
if (!
|
|
20403
|
+
if (!existsSync22(info.path)) {
|
|
19198
20404
|
log2.info(`Binary cache: nothing to clear at ${info.path}`);
|
|
19199
20405
|
return result;
|
|
19200
20406
|
}
|
|
@@ -19204,10 +20410,10 @@ function clearOldBinaries() {
|
|
|
19204
20410
|
return result;
|
|
19205
20411
|
}
|
|
19206
20412
|
for (const version of stale) {
|
|
19207
|
-
const dir =
|
|
20413
|
+
const dir = join23(info.path, version);
|
|
19208
20414
|
let bytes = 0;
|
|
19209
20415
|
try {
|
|
19210
|
-
bytes =
|
|
20416
|
+
bytes = statSync14(dir).isDirectory() ? dirSize(dir) : 0;
|
|
19211
20417
|
} catch {
|
|
19212
20418
|
bytes = 0;
|
|
19213
20419
|
}
|
|
@@ -19381,12 +20587,12 @@ function buildDoctorFixPlan(adapters, report) {
|
|
|
19381
20587
|
if (candidate.storageOnnxBytes > 0) {
|
|
19382
20588
|
items.push({
|
|
19383
20589
|
kind: "onnx",
|
|
19384
|
-
message: `Will
|
|
20590
|
+
message: `Will replace AFT-managed ONNX cache at ${candidate.storageOnnxDir} (${formatBytes(candidate.storageOnnxBytes)}) and download a compatible runtime`
|
|
19385
20591
|
});
|
|
19386
20592
|
} else {
|
|
19387
20593
|
items.push({
|
|
19388
20594
|
kind: "onnx",
|
|
19389
|
-
message: `Will leave system ONNX untouched and
|
|
20595
|
+
message: `Will leave system ONNX untouched and download a compatible AFT-managed runtime for ${candidate.harness.displayName}`
|
|
19390
20596
|
});
|
|
19391
20597
|
}
|
|
19392
20598
|
}
|
|
@@ -19468,7 +20674,7 @@ async function runFixFlow(argv) {
|
|
|
19468
20674
|
} else {
|
|
19469
20675
|
log2.info("AFT binary not found. Downloading…");
|
|
19470
20676
|
try {
|
|
19471
|
-
const { ensureBinary: ensureBinary2 } = await Promise.resolve().then(() => (
|
|
20677
|
+
const { ensureBinary: ensureBinary2 } = await Promise.resolve().then(() => (init_dist2(), exports_dist));
|
|
19472
20678
|
const path2 = await ensureBinary2(`v${report.cliVersion}`);
|
|
19473
20679
|
if (path2) {
|
|
19474
20680
|
log2.success(`AFT binary installed at ${path2}`);
|
|
@@ -19518,7 +20724,8 @@ function logDoctorIssues(report) {
|
|
|
19518
20724
|
}
|
|
19519
20725
|
function formatDoctorStorageStatus(h2) {
|
|
19520
20726
|
const state = h2.storageDir.exists ? h2.storageDir.path : `${h2.storageDir.path} (${h2.pluginRegistered ? "not yet created (lazy — created on first tool call)" : "not created"})`;
|
|
19521
|
-
|
|
20727
|
+
const legacyDuplication = formatLegacyDuplication(h2.storageDir.legacyDuplication);
|
|
20728
|
+
return `${state} (${[formatStorageSizes(h2.storageDir.sizesByKey), legacyDuplication].filter((part) => Boolean(part)).join("; ")})`;
|
|
19522
20729
|
}
|
|
19523
20730
|
async function confirmBinaryDownloadDespitePluginSkew(report, argv) {
|
|
19524
20731
|
const skews = findPluginCliVersionSkews(report);
|
|
@@ -19548,7 +20755,7 @@ function ensureStorageDirsForRegisteredPlugins(adapters) {
|
|
|
19548
20755
|
if (!adapter.isInstalled() || !adapter.hasPluginEntry())
|
|
19549
20756
|
continue;
|
|
19550
20757
|
const storageDir = adapter.getStorageDir();
|
|
19551
|
-
if (
|
|
20758
|
+
if (existsSync22(storageDir))
|
|
19552
20759
|
continue;
|
|
19553
20760
|
mkdirSync7(storageDir, { recursive: true });
|
|
19554
20761
|
summary.created += 1;
|
|
@@ -19630,6 +20837,12 @@ function formatStorageSizes(sizes) {
|
|
|
19630
20837
|
const parts = Object.entries(sizes).filter(([, size]) => size > 0).map(([key, size]) => `${key}: ${formatBytes(size)}`);
|
|
19631
20838
|
return parts.length > 0 ? parts.join(", ") : "empty";
|
|
19632
20839
|
}
|
|
20840
|
+
function formatLegacyDuplication(summary) {
|
|
20841
|
+
if (!summary || summary.totalPartitions === 0)
|
|
20842
|
+
return null;
|
|
20843
|
+
const byHarness = summary.byHarness.map((entry) => `${entry.harness}: ${entry.partitions} partition(s) / ${formatBytes(entry.bytes)}`).join("; ");
|
|
20844
|
+
return `legacy duplication: ${summary.totalPartitions} partition(s), ${formatBytes(summary.totalBytes)} total [${byHarness}]`;
|
|
20845
|
+
}
|
|
19633
20846
|
function isInteractiveTerminal() {
|
|
19634
20847
|
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
19635
20848
|
}
|
|
@@ -19661,11 +20874,11 @@ function deriveIssueTitleFromBody(body) {
|
|
|
19661
20874
|
function writeIssueReviewFile(body) {
|
|
19662
20875
|
let reviewDir = null;
|
|
19663
20876
|
try {
|
|
19664
|
-
reviewDir = mkdtempSync(
|
|
20877
|
+
reviewDir = mkdtempSync(join23(tmpdir2(), "aft-issue-"));
|
|
19665
20878
|
if (process.platform !== "win32") {
|
|
19666
20879
|
chmodSync4(reviewDir, 448);
|
|
19667
20880
|
}
|
|
19668
|
-
const outPath =
|
|
20881
|
+
const outPath = join23(reviewDir, "issue.md");
|
|
19669
20882
|
writeFileSync5(outPath, `${body}
|
|
19670
20883
|
`, { encoding: "utf8", mode: 384, flag: "wx" });
|
|
19671
20884
|
return { path: outPath, realPath: realpathSync5(outPath) };
|
|
@@ -19826,7 +21039,7 @@ https://github.com/cortexkit/aft/issues/new and paste the contents of ${outPath}
|
|
|
19826
21039
|
}
|
|
19827
21040
|
var DOCTOR_CLEAR_TARGET_OPTIONS, DOCTOR_FORCE_CLEAR_TARGETS;
|
|
19828
21041
|
var init_doctor = __esm(async () => {
|
|
19829
|
-
|
|
21042
|
+
init_dist2();
|
|
19830
21043
|
init_binary_cache();
|
|
19831
21044
|
init_bridge_tool_failures();
|
|
19832
21045
|
init_fs_util();
|